MDB
[ class tree: MDB ] [ index: MDB ] [ all elements ]

Source for file ibase.php

Documentation is available at ibase.php

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP Version 4                                                        |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  6. // | Stig. S. Bakken, Lukas Smith                                         |
  7. // | All rights reserved.                                                 |
  8. // +----------------------------------------------------------------------+
  9. // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  10. // | API as well as database abstraction for PHP applications.            |
  11. // | This LICENSE is in the BSD license style.                            |
  12. // |                                                                      |
  13. // | Redistribution and use in source and binary forms, with or without   |
  14. // | modification, are permitted provided that the following conditions   |
  15. // | are met:                                                             |
  16. // |                                                                      |
  17. // | Redistributions of source code must retain the above copyright       |
  18. // | notice, this list of conditions and the following disclaimer.        |
  19. // |                                                                      |
  20. // | Redistributions in binary form must reproduce the above copyright    |
  21. // | notice, this list of conditions and the following disclaimer in the  |
  22. // | documentation and/or other materials provided with the distribution. |
  23. // |                                                                      |
  24. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25. // | Lukas Smith nor the names of his contributors may be used to endorse |
  26. // | or promote products derived from this software without specific prior|
  27. // | written permission.                                                  |
  28. // |                                                                      |
  29. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41. // +----------------------------------------------------------------------+
  42. // | Author: Lorenzo Alberton <l.alberton@quipo.it>                       |
  43. // +----------------------------------------------------------------------+
  44. //
  45. // $Id: ibase.php,v 1.9.4.29 2004/03/31 20:00:55 quipo Exp $
  46.  
  47. require_once 'MDB/Common.php';
  48.  
  49. /**
  50.  * MDB FireBird/InterBase driver
  51.  *
  52.  * Notes:
  53.  * - when fetching in associative mode all keys are lowercased.
  54.  *
  55.  * - Currently, the driver relies on the Interbase server to use SQL dialect 3
  56.  *   that was introduced with Interbase 6. Some versions of Interbase server,
  57.  *   like the Super Server, do not seem to work by default with dialect 3.
  58.  *   This may lead to errors when trying to create tables using Interbase SQL
  59.  *   data types that are only available when using this dialect version.
  60.  *
  61.  * - Interbase does not support per field index sorting support. Indexes are
  62.  *   either ascending, descending or both even when they are defined from more
  63.  *   than one field. Currently Metabase Interbase driver uses the index sorting
  64.  *   type given by the first field of the index for which it is specified the
  65.  *   sorting type.
  66.  *
  67.  * - The numRows method is emulated by fetching all the rows into memory.
  68.  *   Avoid using it if for queries with large result sets.
  69.  *
  70.  * - Interbase does not provide direct support for returning result sets
  71.      restrictedto a given range. Such support is emulated in the MDB ibase driver.
  72.  *
  73.  * - Current Interbase versions do not support altering table field DEFAULT
  74.  *   values and NOT NULL constraint. Text fields' length may only be raised in
  75.  *   increments defined by Interbase, so the Metabase Interbase does not support
  76.  *   altering text field length yet.
  77.  *
  78.  * - createDatabase and dropDatabase are not supported
  79.  *
  80.  * - MDB creates Interbase blobs before executing a prepared queries to insert
  81.  *   or update large object fields. If such queries fail to execute, MDB
  82.  *   Interbase driver class is not able to reclaim the database space allocated
  83.  *   for the large object values because there is currently no PHP function to do so.
  84.  *
  85.  * @package MDB
  86.  * @category Database
  87.  * @author  Lorenzo Alberton <l.alberton@quipo.it>
  88.  */
  89.  
  90. class MDB_ibase extends MDB_Common
  91. {
  92.     var $connection = 0;
  93.     var $connected_host;
  94.     var $connected_port;
  95.     var $selected_database = '';
  96.     var $selected_database_file = '';
  97.     var $opened_persistent = '';
  98.     var $transaction_id = 0;
  99.  
  100.     var $escape_quotes = "'";
  101.     var $decimal_factor = 1.0;
  102.  
  103.     var $results = array();
  104.     var $current_row = array();
  105.     var $columns = array();
  106.     var $rows = array();
  107.     var $limits = array();
  108.     var $row_buffer = array();
  109.     var $highest_fetched_row = array();
  110.     var $query_parameters = array();
  111.     var $query_parameter_values = array();
  112.  
  113.     // }}}
  114.     // {{{ constructor
  115.  
  116.     /**
  117.      * Constructor
  118.      */
  119.     function MDB_ibase()
  120.     {
  121.         $this->MDB_Common();
  122.         $this->phptype  'ibase';
  123.         $this->dbsyntax 'ibase';
  124.  
  125.         $this->supported['Sequences'= 1;
  126.         $this->supported['Indexes'= 1;
  127.         $this->supported['SummaryFunctions'= 1;
  128.         $this->supported['OrderByText'= 1;
  129.         $this->supported['Transactions'= 1;
  130.         $this->supported['CurrId'= 0;
  131.         $this->supported['AffectedRows'= 0;
  132.         $this->supported['SelectRowRanges'= 1;
  133.         $this->supported['LOBs'= 1;
  134.         $this->supported['Replace'= 1;
  135.         $this->supported['SubSelects'= 1;
  136.  
  137.         $this->decimal_factor = pow(10.0$this->decimal_places);
  138.  
  139.         $this->options['DatabasePath''';
  140.         $this->options['DatabaseExtension''.gdb';
  141.         $this->options['DBAUser'= FALSE;
  142.         $this->options['DBAPassword'= FALSE;
  143.  
  144.         $this->errorcode_map = array(
  145.             -104 => MDB_ERROR_SYNTAX,
  146.             -150 => MDB_ERROR_ACCESS_VIOLATION,
  147.             -151 => MDB_ERROR_ACCESS_VIOLATION,
  148.             -155 => MDB_ERROR_NOSUCHTABLE,
  149.               88 => MDB_ERROR_NOSUCHTABLE,
  150.             -157 => MDB_ERROR_NOSUCHFIELD,
  151.             -158 => MDB_ERROR_VALUE_COUNT_ON_ROW,
  152.             -170 => MDB_ERROR_MISMATCH,
  153.             -171 => MDB_ERROR_MISMATCH,
  154.             -172 => MDB_ERROR_INVALID,
  155.             -204 => MDB_ERROR_INVALID,
  156.             -205 => MDB_ERROR_NOSUCHFIELD,
  157.             -206 => MDB_ERROR_NOSUCHFIELD,
  158.             -208 => MDB_ERROR_INVALID,
  159.             -219 => MDB_ERROR_NOSUCHTABLE,
  160.             -297 => MDB_ERROR_CONSTRAINT,
  161.             -530 => MDB_ERROR_CONSTRAINT,
  162.             -551 => MDB_ERROR_ACCESS_VIOLATION,
  163.             -552 => MDB_ERROR_ACCESS_VIOLATION,
  164.             -607 => MDB_ERROR_NOSUCHTABLE,
  165.             -803 => MDB_ERROR_CONSTRAINT,
  166.             -913 => MDB_ERROR_DEADLOCK,
  167.             -922 => MDB_ERROR_NOSUCHDB,
  168.             -923 => MDB_ERROR_CONNECT_FAILED,
  169.             -924 => MDB_ERROR_CONNECT_FAILED
  170.         );
  171.  
  172.     }
  173.  
  174.     // }}}
  175.     // {{{ errorCode()
  176.  
  177.     /**
  178.      * Map native error codes to DB's portable ones.  Requires that
  179.      * the DB implementation's constructor fills in the $errorcode_map
  180.      * property.
  181.      *
  182.      * @param $nativecode the native error code, as returned by the backend
  183.      *  database extension (string or integer)
  184.      * @return int a portable MDB error code, or FALSE if this DB
  185.      *  implementation has no mapping for the given error code.
  186.      */
  187.     function errorCode($errormsg)
  188.     {
  189.         // memo for the interbase php module hackers: we need something similar
  190.         // to mysql_errno() to retrieve error codes instead of this ugly hack
  191.         if (preg_match('/^([^0-9\-]+)([0-9\-]+)\s+(.*)$/'$errormsg$match)) {
  192.             $errno = (int)$match[2];
  193.         else {
  194.             $errno = NULL;
  195.         }
  196.         switch ($errno{
  197.             case -204:
  198.                 if (is_int(strpos($match[3]'Table unknown'))) {
  199.                     return MDB_ERROR_NOSUCHTABLE;
  200.                 }
  201.             break;
  202.             default:
  203.                 if (isset($this->errorcode_map[$errno])) {
  204.                     return($this->errorcode_map[$errno]);
  205.                 }
  206.                 static $error_regexps;
  207.                 if (empty($error_regexps)) {
  208.                     $error_regexps = array(
  209.                         '/[tT]able not found/' => MDB_ERROR_NOSUCHTABLE,
  210.                         '/[tT]able unknown/' => MDB_ERROR_NOSUCHTABLE,
  211.                         '/[tT]able .* already exists/' => MDB_ERROR_ALREADY_EXISTS,
  212.                         '/validation error for column .* value "\*\*\* null/' => MDB_ERROR_CONSTRAINT_NOT_NULL,
  213.                         '/violation of [\w ]+ constraint/' => MDB_ERROR_CONSTRAINT,
  214.                         '/conversion error from string/' => MDB_ERROR_INVALID_NUMBER,
  215.                         '/no permission for/' => MDB_ERROR_ACCESS_VIOLATION,
  216.                         '/arithmetic exception, numeric overflow, or string truncation/' => MDB_ERROR_DIVZERO,
  217.                         '/deadlock/' => MDB_ERROR_DEADLOCK,
  218.                         '/attempt to store duplicate value/' => MDB_ERROR_CONSTRAINT
  219.                     );
  220.                 }
  221.                 foreach ($error_regexps as $regexp => $code{
  222.                     if (preg_match($regexp$errormsg)) {
  223.                         return $code;
  224.                     }
  225.                 }
  226.         }
  227.         // Fall back to MDB_ERROR if there was no mapping.
  228.         return MDB_ERROR;
  229.     }
  230.  
  231.     // }}}
  232.     // {{{ ibaseRaiseError()
  233.  
  234.     /**
  235.      * This method is used to communicate an error and invoke error
  236.      * callbacks etc.  Basically a wrapper for MDB::raiseError
  237.      * that checks for native error msgs.
  238.      *
  239.      * @param integer $errno error code
  240.      * @param string  $message userinfo message
  241.      * @return object PEAR error object
  242.      * @access public
  243.      * @see PEAR_Error
  244.      */
  245.     function ibaseRaiseError($errno = NULL$message = NULL)
  246.     {
  247.         $error $this->errorNative();
  248.         return($this->raiseError($this->errorCode($error)NULLNULL,
  249.             $message$error));
  250.     }
  251.  
  252.     // }}}
  253.     // {{{ errorNative()
  254.  
  255.     /**
  256.      * Get the native error code of the last error (if any) that
  257.      * occured on the current connection.
  258.      *
  259.      * @access public
  260.      * @return int native ibase error code
  261.      */
  262.     function errorNative()
  263.     {
  264.         return @ibase_errmsg();
  265.     }
  266.  
  267.     // }}}
  268.     // {{{ autoCommit()
  269.  
  270.     /**
  271.      * Define whether database changes done on the database be automatically
  272.      * committed. This function may also implicitly start or end a transaction.
  273.      *
  274.      * @param boolean $auto_commit flag that indicates whether the database
  275.      *      changes should be committed right after executing every query
  276.      *      statement. If this argument is 0 a transaction implicitly started.
  277.      *      Otherwise, if a transaction is in progress it is ended by committing
  278.      *      any database changes that were pending.
  279.      * @return mixed MDB_OK on success, a MDB error on failure
  280.      * @access public
  281.      */
  282.     function autoCommit($auto_commit)
  283.     {
  284.         $this->debug('AutoCommit: '.($auto_commit 'On' 'Off'));
  285.         if ((!$this->auto_commit== (!$auto_commit)) {
  286.             return MDB_OK;
  287.         }
  288.         if ($this->connection && $auto_commit && MDB::isError($commit $this->commit())) {
  289.             return($commit);
  290.         }
  291.         $this->auto_commit $auto_commit;
  292.         $this->in_transaction !$auto_commit;
  293.         return MDB_OK;
  294.     }
  295.  
  296.     // }}}
  297.     // {{{ commit()
  298.  
  299.     /**
  300.      * Commit the database changes done during a transaction that is in
  301.      * progress. This function may only be called when auto-committing is
  302.      * disabled, otherwise it will fail. Therefore, a new transaction is
  303.      * implicitly started after committing the pending changes.
  304.      *
  305.      * @return mixed MDB_OK on success, a MDB error on failure
  306.      * @access public
  307.      */
  308.     function commit()
  309.     {
  310.         $this->debug('Commit Transaction');
  311.         if ($this->auto_commit{
  312.             return($this->raiseError(MDB_ERRORNULLNULL,
  313.                 'Commit: transaction changes are being auto commited'));
  314.         }
  315.         return @ibase_commit($this->connection);
  316.     }
  317.  
  318.     // }}}
  319.     // {{{ rollback()
  320.  
  321.     /**
  322.      * Cancel any database changes done during a transaction that is in
  323.      * progress. This function may only be called when auto-committing is
  324.      * disabled, otherwise it will fail. Therefore, a new transaction is
  325.      * implicitly started after canceling the pending changes.
  326.      *
  327.      * @return mixed MDB_OK on success, a MDB error on failure
  328.      * @access public
  329.      */
  330.     function rollback()
  331.     {
  332.         $this->debug('Rollback Transaction');
  333.         if ($this->auto_commit{
  334.             return($this->raiseError(MDB_ERRORNULLNULL,
  335.                 'Rollback: transactions can not be rolled back when changes are auto commited'));
  336.         }
  337.  
  338.         //return ibase_rollback($this->connection);
  339.  
  340.         if ($this->transaction_id && !@ibase_rollback($this->connection)) {
  341.             return($this->raiseError(MDB_ERRORNULLNULL,
  342.                 'Rollback: Could not rollback a pending transaction: '.@ibase_errmsg()));
  343.         }
  344.         if (!$this->transaction_id = @ibase_trans(IBASE_COMMITTED$this->connection)) {
  345.             return($this->raiseError(MDB_ERRORNULLNULL,
  346.                 'Rollback: Could not start a new transaction: '.@ibase_errmsg()));
  347.         }
  348.         return MDB_OK;
  349.     }
  350.  
  351.     // }}}
  352.     // {{{ getDatabaseFile()
  353.  
  354.     function getDatabaseFile($database_name)
  355.     {
  356.         if (isset($this->options['DatabasePath'])) {
  357.             $this->database_path $this->options['DatabasePath'];
  358.         }
  359.         if (isset($this->options['DatabaseExtension'])) {
  360.             $this->database_extension $this->options['DatabaseExtension'];
  361.         }
  362.         //$this->database_path = (isset($this->options['DatabasePath']) ? $this->options['DatabasePath'] : '');
  363.         //$this->database_extension = (isset($this->options['DatabaseExtension']) ? $this->options['DatabaseExtension'] : '.gdb');
  364.  
  365.         //$database_path = (isset($this->options['DatabasePath']) ? $this->options['DatabasePath'] : '');
  366.         //$database_extension = (isset($this->options['DatabaseExtension']) ? $this->options['DatabaseExtension'] : '.gdb');
  367.         return $this->database_path.$database_name.$this->database_extension;
  368.     }
  369.  
  370.     // }}}
  371.     // {{{ _doConnect()
  372.  
  373.     /**
  374.      * Does the grunt work of connecting to the database
  375.      *
  376.      * @return mixed connection resource on success, MDB_Error on failure
  377.      * @access private
  378.      ***/
  379.     function _doConnect($database_name$persistent)
  380.     {
  381.         $function ($persistent 'ibase_pconnect' 'ibase_connect');
  382.         if (!function_exists($function)) {
  383.             return($this->raiseError(MDB_ERROR_UNSUPPORTEDNULLNULL,
  384.                 'doConnect: FireBird/InterBase support is not available in this PHP configuration'));
  385.         }
  386.  
  387.         $dbhost $this->host ?
  388.                   ($this->host ':' $database_name:
  389.                   $database_name;
  390.  
  391.         $params = array();
  392.         $params[$dbhost;
  393.         $params[!empty($this->user$this->user : NULL;
  394.         $params[!empty($this->password$this->password : NULL;
  395.  
  396.         $connection @call_user_func_array($function$params);
  397.         if ($connection > 0{
  398.             @ibase_timefmt("%Y-%m-%d %H:%M:%S"IBASE_TIMESTAMP);
  399.             @ibase_timefmt("%Y-%m-%d"IBASE_DATE);
  400.             return $connection;
  401.         }
  402.         if (isset($php_errormsg)) {
  403.             $error_msg $php_errormsg;
  404.         else {
  405.             $error_msg 'Could not connect to FireBird/InterBase server';
  406.         }
  407.         return($this->raiseError(MDB_ERROR_CONNECT_FAILEDNULLNULL,
  408.             'doConnect: '.$error_msg));
  409.     }
  410.  
  411.     // }}}
  412.     // {{{ connect()
  413.  
  414.     /**
  415.      * Connect to the database
  416.      *
  417.      * @return TRUE on success, MDB_Error on failure
  418.      * @access public
  419.      ***/
  420.     function connect()
  421.     {
  422.         $port (isset($this->options['port']$this->options['port''');
  423.  
  424.         $database_file $this->getDatabaseFile($this->database_name);
  425.  
  426.         if ($this->connection != 0{
  427.             if (!strcmp($this->connected_host$this->host)
  428.                 && !strcmp($this->connected_port$port)
  429.                 && !strcmp($this->selected_database_file$database_file)
  430.                 && ($this->opened_persistent == $this->options['persistent']))
  431.             {
  432.                 return MDB_OK;
  433.             }
  434.             @ibase_close($this->connection);
  435.             $this->affected_rows = -1;
  436.             $this->connection = 0;
  437.         }
  438.         $connection $this->_doConnect($database_file$this->options['persistent']);
  439.         if (MDB::isError($connection)) {
  440.             return $connection;
  441.         }
  442.         $this->connection = $connection;
  443.  
  444.         //the if below was added after PEAR::DB. Review me!!
  445.         if ($this->dbsyntax == 'fbird'{
  446.             $this->supported['limit''alter';
  447.         }
  448.  
  449.         if (!$this->auto_commit && MDB::isError($trans_result $this->_doQuery('BEGIN'))) {
  450.             @ibase_close($this->connection);
  451.             $this->connection = 0;
  452.             $this->affected_rows = -1;
  453.             return $trans_result;
  454.         }
  455.         $this->connected_host = $this->host;
  456.         $this->connected_port = $port;
  457.         $this->selected_database_file = $database_file;
  458.         $this->opened_persistent = $this->options['persistent'];
  459.         return MDB_OK;
  460.     }
  461.  
  462.     // }}}
  463.     // {{{ _close()
  464.     /**
  465.      * Close the database connection
  466.      *
  467.      * @return boolean 
  468.      * @access private
  469.      ***/
  470.     function _close()
  471.     {
  472.         if ($this->connection != 0{
  473.             if (!$this->auto_commit{
  474.                 $this->_doQuery('END');
  475.             }
  476.             @ibase_close($this->connection);
  477.             $this->connection = 0;
  478.             $this->affected_rows = -1;
  479.  
  480.             unset($GLOBALS['_MDB_databases'][$this->database]);
  481.             return true;
  482.         }
  483.         return false;
  484.     }
  485.  
  486.     // }}}
  487.     // {{{ _doQuery()
  488.  
  489.     /**
  490.      * Execute a query
  491.      * @param string $query the SQL query
  492.      * @return mixed result identifier if query executed, else MDB_error
  493.      * @access private
  494.      ***/
  495.     function _doQuery($query$first=0$limit=0$prepared_query=0)  // function _doQuery($query)
  496.     {
  497.         $connection ($this->auto_commit $this->connection : $this->transaction_id);
  498.         if ($prepared_query
  499.             && isset($this->query_parameters[$prepared_query])
  500.             && count($this->query_parameters[$prepared_query]> 2)
  501.         {
  502.  
  503.             $this->query_parameters[$prepared_query][0$connection;
  504.             $this->query_parameters[$prepared_query][1$query;
  505.             $result @call_user_func_array("ibase_query"$this->query_parameters[$prepared_query]);
  506.         else {
  507.             //Not Prepared Query
  508.             $result @ibase_query($connection$query);
  509.             while (@ibase_errmsg(== 'Query argument missed'//ibase_errcode() only available in PHP5
  510.                 //connection lost, try again...
  511.                 $this->connect();
  512.                 //rollback the failed transaction to prevent deadlock and execute the query again
  513.                 if ($this->transaction_id{
  514.                     $this->rollback();
  515.                 }
  516.                 $result @ibase_query($this->connection$query);
  517.             }
  518.         }
  519.         if ($result{
  520.             if (!MDB::isManip($query)) {
  521.                 $result_value intval($result);
  522.                 $this->current_row[$result_value= -1;
  523.                 if ($limit > 0{
  524.                     $this->limits[$result_value= array($first$limit0);
  525.                 }
  526.                 $this->highest_fetched_row[$result_value= -1;
  527.             else {
  528.                 $this->affected_rows = -1;
  529.             }
  530.         else {
  531.             return ($this->raiseError(MDB_ERRORNULLNULL,
  532.                 '_doQuery: Could not execute query ("'.$query.'"): ' @ibase_errmsg()));
  533.         }
  534.         return $result;
  535.     }
  536.  
  537.     // }}}
  538.     // {{{ query()
  539.  
  540.     /**
  541.      * Send a query to the database and return any results
  542.      *
  543.      * @param string $query the SQL query
  544.      * @param array $types array that contains the types of the columns in
  545.      *                          the result set
  546.      * @return mixed result identifier if query executed, else MDB_error
  547.      * @access public
  548.      ***/
  549.     function query($query$types = NULL)
  550.     {
  551.         $this->debug('Query: '.$query);
  552.         $this->last_query $query;
  553.         $first $this->first_selected_row;
  554.         $limit $this->selected_row_limit;
  555.         $this->first_selected_row $this->selected_row_limit = 0;
  556.         $connected $this->connect();
  557.         if (MDB::isError($connected)) {
  558.             return $connected;
  559.         }
  560.  
  561.         if (!MDB::isError($result $this->_doQuery($query$first$limit0))) {
  562.             if ($types != NULL{
  563.                 if (!is_array($types)) {
  564.                     $types = array($types);
  565.                 }
  566.                 if (MDB::isError($err $this->setResultTypes($result$types))) {
  567.                     $this->freeResult($result);
  568.                     return $err;
  569.                 }
  570.             }
  571.             return $result;
  572.         }
  573.         return $this->ibaseRaiseError();
  574.  
  575.     }
  576.  
  577.     // }}}
  578.     // {{{ _executePreparedQuery()
  579.  
  580.     /**
  581.      * Execute a prepared query statement.
  582.      *
  583.      * @param int $prepared_query argument is a handle that was returned by
  584.      *        the function prepareQuery()
  585.      * @param string $query query to be executed
  586.      * @param array $types array that contains the types of the columns in
  587.      *        the result set
  588.      * @return mixed a result handle or MDB_OK on success, a MDB error on failure
  589.      * @access private
  590.      */
  591.     function _executePreparedQuery($prepared_query$query)
  592.     {
  593.         $first $this->first_selected_row;
  594.         $limit $this->selected_row_limit;
  595.         $this->first_selected_row $this->selected_row_limit = 0;
  596.         if (MDB::isError($connect $this->connect())) {
  597.             return $connect;
  598.         }
  599.         return($this->_doQuery($query$first$limit$prepared_query));
  600.     }
  601.  
  602.     // }}}
  603.     // {{{ _skipLimitOffset()
  604.  
  605.     /**
  606.      * Skip the first row of a result set.
  607.      *
  608.      * @param resource $result 
  609.      * @return mixed a result handle or MDB_OK on success, a MDB error on failure
  610.      * @access private
  611.      */
  612.     function _skipLimitOffset($result)
  613.     {
  614.         $result_value intval($result);
  615.         $first $this->limits[$result_value][0];
  616.         for ($this->limits[$result_value][2$first$this->limits[$result_value][2]++{
  617.             if (!is_array(@ibase_fetch_row($result))) {
  618.                 $this->limits[$result_value][2$first;
  619.                 return($this->raiseError(MDB_ERRORNULLNULL,
  620.                     'Skip first rows: could not skip a query result row'));
  621.             }
  622.         }
  623.         return MDB_OK;
  624.     }
  625.  
  626.     // }}}
  627.     // {{{ getColumnNames()
  628.  
  629.     /**
  630.      * Retrieve the names of columns returned by the DBMS in a query result.
  631.      *
  632.      * @param resource $result  result identifier
  633.      * @return mixed an associative array variable
  634.      *                                that will hold the names of columns.The
  635.      *                                indexes of the array are the column names
  636.      *                                mapped to lower case and the values are the
  637.      *                                respective numbers of the columns starting
  638.      *                                from 0. Some DBMS may not return any
  639.      *                                columns when the result set does not
  640.      *                                contain any rows.
  641.      *
  642.      *                                a MDB error on failure
  643.      * @access public
  644.      */
  645.     function getColumnNames($result)
  646.     {
  647.         $result_value intval($result);
  648.         if (!isset($this->highest_fetched_row[$result_value])) {
  649.             return($this->raiseError(MDB_ERRORNULLNULL,
  650.                 'Get column names: it was specified an inexisting result set'));
  651.         }
  652.         if (!isset($this->columns[$result_value])) {
  653.             $this->columns[$result_value= array();
  654.             $columns @ibase_num_fields($result);
  655.             for ($column=0; $column $columns$column++{
  656.                 $column_info @ibase_field_info($result$column);
  657.                 $field_name $column_info['name'];
  658.                 if ($this->options['optimize'== 'portability'{
  659.                     $field_name strtolower($field_name);
  660.                 }
  661.                 $this->columns[$result_value][$field_name$column;
  662.             }
  663.         }
  664.         return $this->columns[$result_value];
  665.     }
  666.  
  667.     // }}}
  668.     // {{{ numCols()
  669.  
  670.     /**
  671.      * Count the number of columns returned by the DBMS in a query result.
  672.      *
  673.      * @param resource $result result identifier
  674.      * @return mixed integer value with the number of columns, a MDB error
  675.      *       on failure
  676.      * @access public
  677.      */
  678.     function numCols($result)
  679.     {
  680.         if (!isset($this->highest_fetched_row[intval($result)])) {
  681.             return($this->raiseError(MDB_ERRORNULLNULL,
  682.                 'Number of columns: it was specified an inexisting result set'));
  683.         }
  684.         return @ibase_num_fields($result);
  685.     }
  686.  
  687.     // }}}
  688.     // {{{ endOfResult()
  689.  
  690.     /**
  691.      * check if the end of the result set has been reached
  692.      *
  693.      * @param resource    $result result identifier
  694.      * @return mixed TRUE or FALSE on sucess, a MDB error on failure
  695.      * @access public
  696.      */
  697.     function endOfResult($result)
  698.     {
  699.         $result_value intval($result);
  700.         if (!isset($this->current_row[$result_value])) {
  701.             return($this->raiseError(MDB_ERRORNULLNULL,
  702.                 'End of result: attempted to check the end of an unknown result'));
  703.         }
  704.         if (isset($this->results[$result_value]&& end($this->results[$result_value]=== false{
  705.             return(($this->highest_fetched_row[$result_value]-1<= $this->current_row[$result_value]);
  706.         }
  707.         if (isset($this->row_buffer[$result_value])) {
  708.             return(!$this->row_buffer[$result_value]);
  709.         }
  710.         if (isset($this->limits[$result_value])) {
  711.             if (MDB::isError($this->_skipLimitOffset($result))
  712.                 || ($this->current_row[$result_value]$this->limits[$result_value][1]
  713.             {
  714.                 return true;
  715.             }
  716.         }
  717.         if (is_array($this->row_buffer[$result_value@ibase_fetch_row($result))) {
  718.             return false;
  719.         }
  720.         $this->row_buffer[$result_value= false;
  721.         return true;
  722.     }
  723.  
  724.     // }}}
  725.     // {{{ fetch()
  726.  
  727.     /**
  728.      * fetch value from a result set
  729.      *
  730.      * @param resource $result result identifier
  731.      * @param int $rownum number of the row where the data can be found
  732.      * @param int $field field number where the data can be found
  733.      * @return mixed string on success, a MDB error on failure
  734.      * @access public
  735.      */
  736.     function fetch($result$rownum$field)
  737.     {
  738.         $fetchmode is_numeric($fieldMDB_FETCHMODE_ORDERED : MDB_FETCHMODE_ASSOC;
  739.         $row $this->fetchInto($result$fetchmode$rownum);
  740.         if (MDB::isError($row)) {
  741.             return $row;
  742.         }
  743.         if (!array_key_exists($field$row)) {
  744.             return null;
  745.         }
  746.         return $row[$field];
  747.     }
  748.  
  749.     // }}}
  750.     // {{{ fetchInto()
  751.  
  752.     /**
  753.      * Fetch a row and return data in an array.
  754.      *
  755.      * @param resource $result result identifier
  756.      * @param int $fetchmode how the array data should be indexed
  757.      * @param int $rownum the row number to fetch
  758.      * @return mixed data array or NULL on success, a MDB error on failure
  759.      * @access public
  760.      */
  761.     function fetchInto($result$fetchmode=MDB_FETCHMODE_DEFAULT$rownum=null)
  762.     {
  763.         $result_value intval($result);
  764.         if (!isset($this->current_row[$result_value])) {
  765.             return($this->raiseError(MDB_ERRORNULLNULL,
  766.                 'fetchInto: attemped to fetch on an unknown query result'));
  767.         }
  768.         if ($fetchmode == MDB_FETCHMODE_DEFAULT{
  769.             $fetchmode $this->fetchmode;
  770.         }
  771.         if (is_null($rownum)) {
  772.             $rownum $this->current_row[$result_value+ 1;
  773.         }
  774.         if (!isset($this->results[$result_value][$rownum])
  775.             && (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]])
  776.                 || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== false)
  777.         {
  778.             if (isset($this->limits[$result_value])) {
  779.                 //upper limit
  780.                 if ($rownum $this->limits[$result_value][1]{
  781.                     // are all previous rows fetched so that we can set the end
  782.                     // of the result set and not have any "holes" in between?
  783.                     if ($rownum == 0
  784.                         || (isset($this->results[$result_value])
  785.                             && count($this->results[$result_value]== $rownum)
  786.                     {
  787.                         $this->highest_fetched_row[$result_value$rownum;
  788.                         $this->current_row[$result_value$rownum;
  789.                         $this->results[$result_value][$rownum= false;
  790.                     }
  791.                     if ($this->options['autofree']{
  792.                         $this->freeResult($result);
  793.                     }
  794.                     return null;
  795.                 }
  796.                 // offset skipping
  797.                 if (MDB::isError($this->_skipLimitOffset($result))) {
  798.                     $this->current_row[$result_value= 0;
  799.                     $this->results[$result_value= array(false);
  800.                     if ($this->options['autofree']{
  801.                         $this->freeResult($result);
  802.                     }
  803.                     return null;
  804.                 }
  805.             }
  806.             if (isset($this->row_buffer[$result_value])) {
  807.                 ++$this->current_row[$result_value];
  808.                 $this->results[$result_value][$this->current_row[$result_value]] =
  809.                     $this->row_buffer[$result_value];
  810.                 unset($this->row_buffer[$result_value]);
  811.             }
  812.             if (!isset($this->results[$result_value][$rownum])
  813.                 && (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]])
  814.                     || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== false)
  815.             {
  816.                 while ($this->current_row[$result_value$rownum
  817.                     && is_array($buffer @ibase_fetch_row($result))
  818.                 {
  819.                     ++$this->current_row[$result_value];
  820.                     $this->results[$result_value][$this->current_row[$result_value]] $buffer;
  821.                 }
  822.                 // end of result set reached
  823.                 if ($this->current_row[$result_value$rownum{
  824.                     ++$this->current_row[$result_value];
  825.                     $this->results[$result_value][$this->current_row[$result_value]] = false;
  826.                 }
  827.             }
  828.             $this->highest_fetched_row[$result_value=
  829.                 max($this->highest_fetched_row[$result_value],
  830.                     $this->current_row[$result_value]);
  831.         else {
  832.             ++$this->current_row[$result_value];
  833.         }
  834.         if (isset($this->results[$result_value][$rownum])
  835.             && $this->results[$result_value][$rownum]
  836.         {
  837.             $row $this->results[$result_value][$rownum];
  838.         else {
  839.             if ($this->options['autofree']{
  840.                 $this->freeResult($result);
  841.             }
  842.             return null;
  843.         }
  844.         foreach ($row as $key => $value_with_space{
  845.             if (!is_null($value_with_space)) {
  846.                 $row[$keyrtrim($value_with_space' ');
  847.             }
  848.         }
  849.         if ($fetchmode MDB_FETCHMODE_ASSOC{
  850.             $column_names $this->getColumnNames($result);
  851.             foreach ($column_names as $name => $i{
  852.                 $column_names[$name$row[$i];
  853.             }
  854.             $row $column_names;
  855.         }
  856.         if (isset($this->result_types[$result_value])) {
  857.             $row $this->convertResultRow($result$row);
  858.         }
  859.         return $row;
  860.     }
  861.  
  862.     // }}}
  863.     // {{{ _retrieveLob()
  864.  
  865.     /**
  866.      * fetch a lob value from a result set
  867.      *
  868.      * @param int $lob handle to a lob created by the createLob() function
  869.      * @return mixed MDB_OK on success, a MDB error on failure
  870.      * @access private
  871.      */
  872.     function _retrieveLob($lob)
  873.     {
  874.         if (!isset($this->lobs[$lob])) {
  875.             return($this->raiseError(MDB_ERRORNULLNULL,
  876.                 'Retrieve LOB: it was not specified a valid lob'));
  877.         }
  878.  
  879.         if (!isset($this->lobs[$lob]['Value'])) {
  880.             $this->lobs[$lob]['Value'$this->fetch($this->lobs[$lob]['Result'],
  881.                                                       $this->lobs[$lob]['Row'],
  882.                                                       $this->lobs[$lob]['Field']);
  883.  
  884.             if (!$this->lobs[$lob]['Handle'@ibase_blob_open($this->lobs[$lob]['Value'])) {
  885.                 unset($this->lobs[$lob]['Value']);
  886.                 return($this->raiseError(MDB_ERRORNULLNULL,
  887.                     'Retrieve LOB: Could not open fetched large object field' @ibase_errmsg()));
  888.             }
  889.         }
  890.         return MDB_OK;
  891.     }
  892.  
  893.     // }}}
  894.     // {{{ endOfResultLob()
  895.  
  896.     /**
  897.      * Determine whether it was reached the end of the large object and
  898.      * therefore there is no more data to be read for the its input stream.
  899.      *
  900.      * @param int    $lob handle to a lob created by the createLob() function
  901.      * @return mixed TRUE or FALSE on success, a MDB error on failure
  902.      * @access public
  903.      */
  904.     function endOfResultLob($lob)
  905.     {
  906.         if (MDB::isError($lobresult $this->_retrieveLob($lob))) {
  907.             return($lobresult);
  908.         }
  909.         return(isset($this->lobs[$lob]['EndOfLOB']));
  910.     }
  911.  
  912.     // }}}
  913.     // {{{ _readResultLob()
  914.  
  915.     /**
  916.      * Read data from large object input stream.
  917.      *
  918.      * @param int $lob handle to a lob created by the createLob() function
  919.      * @param blob $data reference to a variable that will hold data to be
  920.      *       read from the large object input stream
  921.      * @param int $length integer value that indicates the largest ammount of
  922.      *       data to be read from the large object input stream.
  923.      * @return mixed length on success, a MDB error on failure
  924.      * @access private
  925.      */
  926.     function _readResultLob($lob&$data$length)
  927.     {
  928.         if (MDB::isError($lobresult $this->_retrieveLob($lob))) {
  929.             return $lobresult;
  930.         }
  931.         $data @ibase_blob_get($this->lobs[$lob]['Handle']$length);
  932.         if (!is_string($data)) {
  933.             $this->raiseError(MDB_ERRORNULLNULL,
  934.                 'Read Result LOB: ' @ibase_errmsg());
  935.         }
  936.         if (($length strlen($data)) == 0{
  937.             $this->lobs[$lob]['EndOfLOB'= 1;
  938.         }
  939.         return $length;
  940.     }
  941.  
  942.     // }}}
  943.     // {{{ _destroyResultLob()
  944.  
  945.     /**
  946.      * Free any resources allocated during the lifetime of the large object
  947.      * handler object.
  948.      *
  949.      * @param int $lob handle to a lob created by the createLob() function
  950.      * @access private
  951.      */
  952.     function _destroyResultLob($lob)
  953.     {
  954.         if (isset($this->lobs[$lob])) {
  955.             if (isset($this->lobs[$lob]['Value'])) {
  956.                @ibase_blob_close($this->lobs[$lob]['Handle']);
  957.             }
  958.             $this->lobs[$lob'';
  959.         }
  960.     }
  961.  
  962.     // }}}
  963.     // {{{ fetchClob()
  964.  
  965.     /**
  966.      * fetch a clob value from a result set
  967.      *
  968.      * @param resource $result result identifier
  969.      * @param int $row number of the row where the data can be found
  970.      * @param int $field field number where the data can be found
  971.      * @return mixed content of the specified data cell, a MDB error on failure,
  972.      *        a MDB error on failure
  973.      * @access public
  974.      */
  975.     function fetchClob($result$row$field)
  976.     {
  977.         return $this->fetchLob($result$row$field);
  978.     }
  979.  
  980.     // }}}
  981.     // {{{ fetchBlob()
  982.  
  983.     /**
  984.      * fetch a blob value from a result set
  985.      *
  986.      * @param resource $result result identifier
  987.      * @param int $row number of the row where the data can be found
  988.      * @param int $field field number where the data can be found
  989.      * @return mixed content of the specified data cell, a MDB error on failure
  990.      * @access public
  991.      */
  992.     function fetchBlob($result$row$field)
  993.     {
  994.         return $this->fetchLob($result$row$field);
  995.     }
  996.  
  997.     // }}}
  998.     // {{{ convertResult()
  999.  
  1000.     /**
  1001.      * convert a value to a RDBMS indepdenant MDB type
  1002.      *
  1003.      * @param mixed $value value to be converted
  1004.      * @param int $type constant that specifies which type to convert to
  1005.      * @return mixed converted value or a MDB error on failure
  1006.      * @access public
  1007.      */
  1008.     function convertResult($value$type)
  1009.     {
  1010.         switch ($type{
  1011.             case MDB_TYPE_DECIMAL:
  1012.                 return sprintf('%.'.$this->decimal_places.'f'doubleval($value)/$this->decimal_factor);
  1013.             case MDB_TYPE_TIMESTAMP:
  1014.                 return substr($value0strlen('YYYY-MM-DD HH:MM:SS'));
  1015.             default:
  1016.                 return $this->_baseConvertResult($value$type);
  1017.         }
  1018.     }
  1019.  
  1020.     // }}}
  1021.     // {{{ resultIsNull()
  1022.  
  1023.     /**
  1024.      * Determine whether the value of a query result located in given row and
  1025.      *    field is a NULL.
  1026.      *
  1027.      * @param resource $result result identifier
  1028.      * @param int $rownum number of the row where the data can be found
  1029.      * @param int $field field number where the data can be found
  1030.      * @return mixed TRUE or FALSE on success, a MDB error on failure
  1031.      * @access public
  1032.      */
  1033.     function resultIsNull($result$rownum$field)
  1034.     {
  1035.         $value $this->fetch($result$rownum$field);
  1036.         if (MDB::isError($value)) {
  1037.             return $value;
  1038.         }
  1039.         return(!isset($value));
  1040.     }
  1041.  
  1042.     // }}}
  1043.     // {{{ numRows()
  1044.  
  1045.     /**
  1046.      * returns the number of rows in a result object
  1047.      *
  1048.      * @param ressource $result a valid result ressouce pointer
  1049.      * @return mixed MDB_Error or the number of rows
  1050.      * @access public
  1051.      */
  1052.     function numRows($result)
  1053.     {
  1054.         $result_value intval($result);
  1055.         if (!isset($this->current_row[$result_value])) {
  1056.             return($this->raiseError(MDB_ERRORNULLNULL,
  1057.                 'Number of rows: attemped to obtain the number of rows contained in an unknown query result'));
  1058.         }
  1059.         if (!isset($this->rows[$result_value][$this->highest_fetched_row[$result_value]])
  1060.             || $this->rows[$result_value][$this->highest_fetched_row[$result_value]] !== false
  1061.         {
  1062.             if (isset($this->limits[$result_value])) {
  1063.                 if (MDB::isError($skipfirstrow $this->_skipLimitOffset($result))) {
  1064.                     //$this->rows[$result_value] = 0;
  1065.                     return $skipfirstrow;
  1066.                 }
  1067.             }
  1068.             if (isset($this->row_buffer[$result_value])) {
  1069.                 ++$this->highest_fetched_row[$result_value];
  1070.                 $this->results[$result_value][$this->highest_fetched_row[$result_value]]
  1071.                     = $this->row_buffer[$result_value];
  1072.                 unset($this->row_buffer[$result_value]);
  1073.             }
  1074.             if (!isset($this->results[$result_value][$this->highest_fetched_row[$result_value]])
  1075.                 || $this->results[$result_value][$this->highest_fetched_row[$result_value]] !== false
  1076.             {
  1077.                 while((!isset($this->limits[$result_value])
  1078.                     || ($this->highest_fetched_row[$result_value]+1$this->limits[$result_value][1]
  1079.                 )
  1080.                     && (is_array($buffer @ibase_fetch_row($result)))
  1081.                 {
  1082.                     ++$this->highest_fetched_row[$result_value];
  1083.                     $this->results[$result_value][$this->highest_fetched_row[$result_value]] $buffer;
  1084.                 }
  1085.                 ++$this->highest_fetched_row[$result_value];
  1086.                 $this->results[$result_value][$this->highest_fetched_row[$result_value]] = false;
  1087.             }
  1088.         }
  1089.         return(max(0$this->highest_fetched_row[$result_value]));
  1090.     }
  1091.  
  1092.     // }}}
  1093.     // {{{ freeResult()
  1094.  
  1095.     /**
  1096.      * Free the internal resources associated with $result.
  1097.      *
  1098.      * @param $result result identifier
  1099.      * @return boolean TRUE on success, FALSE if $result is invalid
  1100.      * @access public
  1101.      */
  1102.     function freeResult($result)
  1103.     {
  1104.         $result_value intval($result);
  1105.         if (!isset($this->current_row[$result_value])) {
  1106.            return($this->raiseError(MDB_ERRORNULLNULL,
  1107.                'Free result: attemped to free an unknown query result'));
  1108.         }
  1109.         if (isset($this->highest_fetched_row[$result_value])) {
  1110.             unset($this->highest_fetched_row[$result_value]);
  1111.         }
  1112.         if (isset($this->row_buffer[$result_value])) {
  1113.             unset($this->row_buffer[$result_value]);
  1114.         }
  1115.         if (isset($this->limits[$result_value])) {
  1116.             unset($this->limits[$result_value]);
  1117.         }
  1118.         if (isset($this->current_row[$result_value])) {
  1119.             unset($this->current_row[$result_value]);
  1120.         }
  1121.         if (isset($this->results[$result_value])) {
  1122.             unset($this->results[$result_value]);
  1123.         }
  1124.         if (isset($this->columns[$result_value])) {
  1125.             unset($this->columns[$result_value]);
  1126.         }
  1127.         if (isset($this->rows[$result_value])) {
  1128.             unset($this->rows[$result_value]);
  1129.         }
  1130.         if (isset($this->result_types[$result_value])) {
  1131.             unset($this->result_types[$result_value]);
  1132.         }
  1133.         if (is_resource($result)) {
  1134.             return @ibase_free_result($result);
  1135.         }
  1136.         return true;
  1137.     }
  1138.     // }}}
  1139.     // {{{ getTypeDeclaration()
  1140.  
  1141.     /**
  1142.      * Obtain DBMS specific SQL code portion needed to declare an text type
  1143.      * field to be used in statements like CREATE TABLE.
  1144.      *
  1145.      * @param string $field  associative array with the name of the properties
  1146.      *       of the field being declared as array indexes. Currently, the types
  1147.      *       of supported field properties are as follows:
  1148.      *
  1149.      *       length
  1150.      *           Integer value that determines the maximum length of the text
  1151.      *           field. If this argument is missing the field should be
  1152.      *           declared to have the longest length allowed by the DBMS.
  1153.      *
  1154.      *       default
  1155.      *           Text value to be used as default for this field.
  1156.      *
  1157.      *       notnull
  1158.      *           Boolean flag that indicates whether this field is constrained
  1159.      *           to not be set to null.
  1160.      * @return string  DBMS specific SQL code portion that should be used to
  1161.      *       declare the specified field.
  1162.      * @access public
  1163.      */
  1164.     function getTypeDeclaration($field)
  1165.     {
  1166.         switch($field['type'])
  1167.         {
  1168.             case 'text':
  1169.                 return('VARCHAR ('.(isset($field['length']$field['length'(isset($this->options['DefaultTextFieldLength']$this->options['DefaultTextFieldLength': 4000)).')');
  1170.             case 'clob':
  1171.                 return 'BLOB SUB_TYPE 1';
  1172.             case 'blob':
  1173.                 return 'BLOB SUB_TYPE 0';
  1174.             case 'integer':
  1175.                 return 'INTEGER';
  1176.             case 'boolean':
  1177.                 return 'CHAR (1)';
  1178.             case 'date':
  1179.                 return 'DATE';
  1180.             case 'time':
  1181.                 return 'TIME';
  1182.             case 'timestamp':
  1183.                 return 'TIMESTAMP';
  1184.             case 'float':
  1185.                 return 'DOUBLE PRECISION';
  1186.             case 'decimal':
  1187.                 return 'DECIMAL(18,'.$this->decimal_places.')';
  1188.         }
  1189.         return '';
  1190.     }
  1191.  
  1192.     // }}}
  1193.     // {{{ getTextDeclaration()
  1194.  
  1195.     /**
  1196.      * Obtain DBMS specific SQL code portion needed to declare an text type
  1197.      * field to be used in statements like CREATE TABLE.
  1198.      *
  1199.      * @param string $name   name the field to be declared.
  1200.      * @param string $field  associative array with the name of the properties
  1201.      *       of the field being declared as array indexes. Currently, the types
  1202.      *       of supported field properties are as follows:
  1203.      *
  1204.      *       length
  1205.      *           Integer value that determines the maximum length of the text
  1206.      *           field. If this argument is missing the field should be
  1207.      *           declared to have the longest length allowed by the DBMS.
  1208.      *
  1209.      *       default
  1210.      *           Text value to be used as default for this field.
  1211.      *
  1212.      *       notnull
  1213.      *           Boolean flag that indicates whether this field is constrained
  1214.      *           to not be set to NULL.
  1215.      * @return string  DBMS specific SQL code portion that should be used to
  1216.      *       declare the specified field.
  1217.      * @access public
  1218.      */
  1219.     function getTextDeclaration($name$field)
  1220.     {
  1221.         return($name.' '.$this->getTypeDeclaration($field).(isset($field['default']' DEFAULT '.$this->getTextValue($field['default']'').(IsSet($field['notnull']' NOT NULL' ''));
  1222.     }
  1223.  
  1224.     // }}}
  1225.     // {{{ getClobDeclaration()
  1226.  
  1227.     /**
  1228.      * Obtain DBMS specific SQL code portion needed to declare an character
  1229.      * large object type field to be used in statements like CREATE TABLE.
  1230.      *
  1231.      * @param string $name   name the field to be declared.
  1232.      * @param string $field  associative array with the name of the properties
  1233.      *       of the field being declared as array indexes. Currently, the types
  1234.      *       of supported field properties are as follows:
  1235.      *
  1236.      *       length
  1237.      *           Integer value that determines the maximum length of the large
  1238.      *           object field. If this argument is missing the field should be
  1239.      *           declared to have the longest length allowed by the DBMS.
  1240.      *
  1241.      *       notnull
  1242.      *           Boolean flag that indicates whether this field is constrained
  1243.      *           to not be set to NULL.
  1244.      * @return string  DBMS specific SQL code portion that should be used to
  1245.      *       declare the specified field.
  1246.      * @access public
  1247.      */
  1248.     function getClobDeclaration($name$field)
  1249.     {
  1250.         return($name.' '.$this->getTypeDeclaration($field).(isset($field['notnull']' NOT NULL' ''));
  1251.     }
  1252.  
  1253.     // }}}
  1254.     // {{{ getBlobDeclaration()
  1255.  
  1256.     /**
  1257.      * Obtain DBMS specific SQL code portion needed to declare an binary large
  1258.      * object type field to be used in statements like CREATE TABLE.
  1259.      *
  1260.      * @param string $name   name the field to be declared.
  1261.      * @param string $field  associative array with the name of the properties
  1262.      *       of the field being declared as array indexes. Currently, the types
  1263.      *       of supported field properties are as follows:
  1264.      *
  1265.      *       length
  1266.      *           Integer value that determines the maximum length of the large
  1267.      *           object field. If this argument is missing the field should be
  1268.      *           declared to have the longest length allowed by the DBMS.
  1269.      *
  1270.      *       notnull
  1271.      *           Boolean flag that indicates whether this field is constrained
  1272.      *           to not be set to NULL.
  1273.      * @return string  DBMS specific SQL code portion that should be used to
  1274.      *       declare the specified field.
  1275.      * @access public
  1276.      */
  1277.     function getBlobDeclaration($name$field)
  1278.     {
  1279.         return($name.' '.$this->getTypeDeclaration($field).(isset($field['notnull']' NOT NULL' ''));
  1280.     }
  1281.  
  1282.     // }}}
  1283.     // {{{ getDateDeclaration()
  1284.  
  1285.     /**
  1286.      * Obtain DBMS specific SQL code portion needed to declare a date type
  1287.      * field to be used in statements like CREATE TABLE.
  1288.      *
  1289.      * @param string $name   name the field to be declared.
  1290.      * @param string $field  associative array with the name of the properties
  1291.      *       of the field being declared as array indexes. Currently, the types
  1292.      *       of supported field properties are as follows:
  1293.      *
  1294.      *       default
  1295.      *           Date value to be used as default for this field.
  1296.      *
  1297.      *       notnull
  1298.      *           Boolean flag that indicates whether this field is constrained
  1299.      *           to not be set to NULL.
  1300.      * @return string  DBMS specific SQL code portion that should be used to
  1301.      *       declare the specified field.
  1302.      * @access public
  1303.      */
  1304.     function getDateDeclaration($name$field)
  1305.     {
  1306.         return($name.' '.$this->getTypeDeclaration($field).(isset($field['default']' DEFAULT "'.$field['default'].'"' '').(isset($field['notnull']' NOT NULL' ''));
  1307.     }
  1308.  
  1309.     // }}}
  1310.     // {{{ getTimeDeclaration()
  1311.  
  1312.     /**
  1313.      * Obtain DBMS specific SQL code portion needed to declare a time
  1314.      * field to be used in statements like CREATE TABLE.
  1315.      *
  1316.      * @param string $name   name the field to be declared.
  1317.      * @param string $field  associative array with the name of the properties
  1318.      *       of the field being declared as array indexes. Currently, the types
  1319.      *       of supported field properties are as follows:
  1320.      *
  1321.      *       default
  1322.      *           Time value to be used as default for this field.
  1323.      *
  1324.      *       notnull
  1325.      *           Boolean flag that indicates whether this field is constrained
  1326.      *           to not be set to NULL.
  1327.      * @return string  DBMS specific SQL code portion that should be used to
  1328.      *       declare the specified field.
  1329.      * @access public
  1330.      */
  1331.     function getTimeDeclaration($name$field)
  1332.     {
  1333.         return($name.' '.$this->getTypeDeclaration($field).(isset($field['default']' DEFAULT "'.$field['default'].'"' '').(isset($field['notnull']' NOT NULL' ''));
  1334.     }
  1335.  
  1336.     // }}}
  1337.     // {{{ getFloatDeclaration()
  1338.  
  1339.     /**
  1340.      * Obtain DBMS specific SQL code portion needed to declare a float type
  1341.      * field to be used in statements like CREATE TABLE.
  1342.      *
  1343.      * @param string $name   name the field to be declared.
  1344.      * @param string $field  associative array with the name of the properties
  1345.      *       of the field being declared as array indexes. Currently, the types
  1346.      *       of supported field properties are as follows:
  1347.      *
  1348.      *       default
  1349.      *           Float value to be used as default for this field.
  1350.      *
  1351.      *       notnull
  1352.      *           Boolean flag that indicates whether this field is constrained
  1353.      *           to not be set to NULL.
  1354.      * @return string  DBMS specific SQL code portion that should be used to
  1355.      *       declare the specified field.
  1356.      * @access public
  1357.      */
  1358.     function getFloatDeclaration($name$field)
  1359.     {
  1360.         return($name.' '.$this->getTypeDeclaration($field).(isset($field['default']' DEFAULT '.$this->getFloatValue($field['default']'').(isset($field['notnull']' NOT NULL' ''));
  1361.     }
  1362.  
  1363.     // }}}
  1364.     // {{{ getDecimalDeclaration()
  1365.  
  1366.     /**
  1367.      * Obtain DBMS specific SQL code portion needed to declare a decimal type
  1368.      * field to be used in statements like CREATE TABLE.
  1369.      *
  1370.      * @param string $name   name the field to be declared.
  1371.      * @param string $field  associative array with the name of the properties
  1372.      *       of the field being declared as array indexes. Currently, the types
  1373.      *       of supported field properties are as follows:
  1374.      *
  1375.      *       default
  1376.      *           Decimal value to be used as default for this field.
  1377.      *
  1378.      *       notnull
  1379.      *           Boolean flag that indicates whether this field is constrained
  1380.      *           to not be set to NULL.
  1381.      * @return string  DBMS specific SQL code portion that should be used to
  1382.      *       declare the specified field.
  1383.      * @access public
  1384.      */
  1385.     function getDecimalDeclaration($name$field)
  1386.     {
  1387.         return($name.' '.$this->getTypeDeclaration($field).(isset($field['default']' DEFAULT '.$this->getDecimalValue($field['default']'').(isset($field['notnull']' NOT NULL' ''));
  1388.     }
  1389.  
  1390.     // }}}
  1391.     // {{{ _getLobValue()
  1392.  
  1393.     /**
  1394.      * Convert a text value into a DBMS specific format that is suitable to
  1395.      * compose query statements.
  1396.      *
  1397.      * @param resource  $prepared_query query handle from prepare()
  1398.      * @param           $parameter 
  1399.      * @param           $lob 
  1400.      * @return string text string that represents the given argument value in
  1401.      *       a DBMS specific format.
  1402.      * @access private
  1403.      */
  1404.     function _getLobValue($prepared_query$parameter$lob)
  1405.     {
  1406.         if (MDB::isError($connect $this->connect())) {
  1407.             return $connect;
  1408.         }
  1409.         $value   '';  // DEAL WITH ME
  1410.         if (!$this->transaction_id = @ibase_trans(IBASE_COMMITTED$this->connection)) {
  1411.             return($this->raiseError(MDB_ERRORNULLNULL'_getLobValue: Could not start a new transaction: '.@ibase_errmsg()));
  1412.         }
  1413.  
  1414.         if (($lo @ibase_blob_create($this->auto_commit $this->connection : $this->transaction_id))) {
  1415.             while (!$this->endOfLob($lob)) {
  1416.                 if (MDB::isError($result $this->readLob($lob$data$this->options['lob_buffer_length']))) {
  1417.                     break;
  1418.                 }
  1419.                 if (@ibase_blob_add($lo$data=== false{
  1420.                     $result $this->raiseError(MDB_ERRORNULLNULL,
  1421.                         '_getLobValue - Could not add data to a large object: ' @ibase_errmsg());
  1422.                     break;
  1423.                 }
  1424.             }
  1425.             if (MDB::isError($result)) {
  1426.                 @ibase_blob_cancel($lo);
  1427.             else {
  1428.                 $value @ibase_blob_close($lo);
  1429.             }
  1430.         else {
  1431.             $result $this->raiseError(MDB_ERRORNULLNULL,
  1432.                 'Get LOB field value' @ibase_errmsg());
  1433.         }
  1434.         if (!isset($this->query_parameters[$prepared_query])) {
  1435.             $this->query_parameters[$prepared_query]       = array(0'');
  1436.             $this->query_parameter_values[$prepared_query= array();
  1437.         }
  1438.         $query_parameter count($this->query_parameters[$prepared_query]);
  1439.         $this->query_parameter_values[$prepared_query][$parameter$query_parameter;
  1440.         $this->query_parameters[$prepared_query][$query_parameter$value;
  1441.         $value '?';
  1442.  
  1443.         if (!$this->auto_commit{
  1444.             $this->commit();
  1445.         }
  1446.         return $value;
  1447.     }
  1448.  
  1449.     // }}}
  1450.     // {{{ getClobValue()
  1451.  
  1452.     /**
  1453.      * Convert a text value into a DBMS specific format that is suitable to
  1454.      * compose query statements.
  1455.      *
  1456.      * @param resource  $prepared_query query handle from prepare()
  1457.      * @param           $parameter 
  1458.      * @param           $clob 
  1459.      * @return string text string that represents the given argument value in
  1460.      *       a DBMS specific format.
  1461.      * @access public
  1462.      */
  1463.     function getClobValue($prepared_query$parameter$clob)
  1464.     {
  1465.         return $this->_getLobValue($prepared_query$parameter$clob);
  1466.     }
  1467.  
  1468.  
  1469.     // }}}
  1470.     // {{{ freeLobValue()
  1471.  
  1472.     /**
  1473.      * free a large object
  1474.      *
  1475.      * @param resource  $prepared_query query handle from prepare()
  1476.      * @param string    $lob 
  1477.      * @param string    $value 
  1478.      * @return MDB_OK 
  1479.      * @access public
  1480.      */
  1481.     function freeLobValue($prepared_query$lob&$value)
  1482.     {
  1483.         $query_parameter=$this->query_parameter_values[$prepared_query][$lob];
  1484.  
  1485.         unset($this->query_parameters[$prepared_query][$query_parameter]);
  1486.         unset($this->query_parameter_values[$prepared_query][$lob]);
  1487.         if (count($this->query_parameter_values[$prepared_query]== 0{
  1488.             unset($this->query_parameters[$prepared_query]);
  1489.             unset($this->query_parameter_values[$prepared_query]);
  1490.         }
  1491.         unset($value);
  1492.     }
  1493.  
  1494.     // }}}
  1495.     // {{{ freeClobValue()
  1496.  
  1497.     /**
  1498.      * free a character large object
  1499.      *
  1500.      * @param resource  $prepared_query query handle from prepare()
  1501.      * @param string    $clob 
  1502.      * @param string    $value 
  1503.      * @return MDB_OK 
  1504.      * @access public
  1505.      */
  1506.     function freeClobValue($prepared_query$clob&$value)
  1507.     {
  1508.         $this->freeLobValue($prepared_query$clob$value);
  1509.     }
  1510.  
  1511.     // }}}
  1512.     // {{{ getBlobValue()
  1513.  
  1514.     /**
  1515.      * Convert a text value into a DBMS specific format that is suitable to
  1516.      * compose query statements.
  1517.      *
  1518.      * @param resource  $prepared_query query handle from prepare()
  1519.      * @param           $parameter 
  1520.      * @param           $blob 
  1521.      * @return string text string that represents the given argument value in
  1522.      *       a DBMS specific format.
  1523.      * @access public
  1524.      */
  1525.     function getBlobValue($prepared_query$parameter$blob)
  1526.     {
  1527.         return $this->_getLobValue($prepared_query$parameter$blob);
  1528.     }
  1529.  
  1530.     // }}}
  1531.     // {{{ freeBlobValue()
  1532.  
  1533.     /**
  1534.      * free a binary large object
  1535.      *
  1536.      * @param resource  $prepared_query query handle from prepare()
  1537.      * @param string    $blob 
  1538.      * @param string    $value 
  1539.      * @return MDB_OK 
  1540.      * @access public
  1541.      */
  1542.     function freeBlobValue($prepared_query$blob&$value)
  1543.     {
  1544.         $this->freeLobValue($prepared_query$blob$value);
  1545.     }
  1546.  
  1547.     // }}}
  1548.     // {{{ getFloatValue()
  1549.  
  1550.     /**
  1551.      * Convert a text value into a DBMS specific format that is suitable to
  1552.      * compose query statements.
  1553.      *
  1554.      * @param string $value text string value that is intended to be converted.
  1555.      * @return string text string that represents the given argument value in
  1556.      *       a DBMS specific format.
  1557.      * @access public
  1558.      */
  1559.     function getFloatValue($value)
  1560.     {
  1561.         return (($value === null'NULL' $value);
  1562.     }
  1563.  
  1564.     // }}}
  1565.     // {{{ getDecimalValue()
  1566.  
  1567.     /**
  1568.      * Convert a text value into a DBMS specific format that is suitable to
  1569.      * compose query statements.
  1570.      *
  1571.      * @param string $value text string value that is intended to be converted.
  1572.      * @return string text string that represents the given argument value in
  1573.      *       a DBMS specific format.
  1574.      * @access public
  1575.      */
  1576.     function getDecimalValue($value)
  1577.     {
  1578.         return (($value === null'NULL' strval(round($value*$this->decimal_factor)));
  1579.     }
  1580.  
  1581.     // }}}
  1582.     // {{{ affectedRows()
  1583.  
  1584.     /**
  1585.      * returns the affected rows of a query
  1586.      *
  1587.      * @return mixed MDB Error Object or number of rows
  1588.      * @access public
  1589.      */
  1590.     function affectedRows()
  1591.     {
  1592.         if (function_exists('ibase_affected_rows')) //PHP5 only
  1593.             $affected_rows @ibase_affected_rows($this->connection);
  1594.             if ($affected_rows === false{
  1595.                 return $this->raiseError(MDB_ERROR_NEED_MORE_DATA);
  1596.             }
  1597.             return $affected_rows;
  1598.         }
  1599.         return parent::affectedRows();
  1600.     }
  1601.  
  1602.     // }}}
  1603.     // {{{ nextId()
  1604.  
  1605.     /**
  1606.      * returns the next free id of a sequence
  1607.      *
  1608.      * @param string  $seq_name name of the sequence
  1609.      * @param boolean $ondemand when TRUE the seqence is
  1610.      *                           automatic created, if it
  1611.      *                           not exists
  1612.      * @return mixed MDB_Error or id
  1613.      * @access public
  1614.      */
  1615.     function nextId($seq_name$ondemand = true)
  1616.     {
  1617.         if (MDB::isError($connect $this->connect())) {
  1618.             return $connect;
  1619.         }
  1620.         //$sequence_name = $this->getSequenceName($seq_name);
  1621.         $sequence_name strtoupper($this->getSequenceName($seq_name));
  1622.         $this->expectError(MDB_ERROR_NOSUCHTABLE);
  1623.         $query = "SELECT GEN_ID($sequence_name, 1) as the_value FROM RDB\$DATABASE";
  1624.         $result $this->_doQuery($query);
  1625.         $this->popExpect();
  1626.         if ($ondemand && MDB::isError($result)) {
  1627.             $result $this->createSequence($seq_name1);
  1628.             if (MDB::isError($result)) {
  1629.                 return $result;
  1630.             }
  1631.             return $this->nextId($seq_namefalse);
  1632.         }
  1633.         return $this->fetchOne($result);
  1634.     }
  1635.  
  1636.     // }}}
  1637.     // {{{ currId()
  1638.  
  1639.     /**
  1640.      * returns the current id of a sequence
  1641.      *
  1642.      * @param string  $seq_name name of the sequence
  1643.      * @return mixed MDB_Error or id
  1644.      * @access public
  1645.      */
  1646.     function currId($seq_name)
  1647.     {
  1648.         $sequence_name strtoupper($this->getSequenceName($seq_name));
  1649.         //$sequence_name = $this->getSequenceName($seq_name);
  1650.         $query = "SELECT RDB\$GENERATOR_ID FROM RDB\$GENERATORS WHERE RDB\$GENERATOR_NAME='$sequence_name'";
  1651.         if (MDB::isError($result $this->queryOne($query))) {
  1652.             return($this->raiseError(MDB_ERRORNULLNULL,
  1653.                 'currId: Unable to select from ' $seqname) );
  1654.         }
  1655.         if (!is_numeric($result)) {
  1656.             //var_dump($result); ==> null
  1657.             return($this->raiseError(MDB_ERRORNULLNULL,
  1658.                 'currId: could not find value in sequence table'));
  1659.         }
  1660.         return $result;
  1661.     }
  1662.  
  1663.     // }}}
  1664.     // {{{ nextResult()
  1665.  
  1666.     /**
  1667.      * Move the internal ibase result pointer to the next available result
  1668.      *
  1669.      * @param $result a valid ibase result resource
  1670.      * @return TRUE if a result is available otherwise return FALSE
  1671.      * @access public
  1672.      */
  1673.     function nextResult($result)
  1674.     {
  1675.         return false;
  1676.     }
  1677.  
  1678.     // }}}
  1679.     // {{{ tableInfo()
  1680.  
  1681.     /**
  1682.      * returns meta data about the result set
  1683.      *
  1684.      * @param  mixed $resource FireBird/InterBase result identifier or table name
  1685.      * @param mixed $mode depends on implementation
  1686.      * @return array an nested array, or a MDB error
  1687.      * @access public
  1688.      */
  1689.     function tableInfo($result$mode = NULL)
  1690.     {
  1691.         $count = 0;
  1692.         $id = 0;
  1693.         $res = array();
  1694.  
  1695.         /**
  1696.          * depending on $mode, metadata returns the following values:
  1697.          *
  1698.          * - mode is FALSE (default):
  1699.          * $result[]:
  1700.          *    [0]['table']  table name
  1701.          *    [0]['name']   field name
  1702.          *    [0]['type']   field type
  1703.          *    [0]['len']    field length
  1704.          *    [0]['flags']  field flags
  1705.          *
  1706.          * - mode is MDB_TABLEINFO_ORDER
  1707.          * $result[]:
  1708.          *    ['num_fields'] number of metadata records
  1709.          *    [0]['table']  table name
  1710.          *    [0]['name']   field name
  1711.          *    [0]['type']   field type
  1712.          *    [0]['len']    field length
  1713.          *    [0]['flags']  field flags
  1714.          *    ['order'][field name]  index of field named 'field name'
  1715.          *    The last one is used, if you have a field name, but no index.
  1716.          *    Test:  if (isset($result['meta']['myfield'])) { ...
  1717.          *
  1718.          * - mode is MDB_TABLEINFO_ORDERTABLE
  1719.          *     the same as above. but additionally
  1720.          *    ['ordertable'][table name][field name] index of field
  1721.          *       named 'field name'
  1722.          *
  1723.          *       this is, because if you have fields from different
  1724.          *       tables with the same field name * they override each
  1725.          *       other with MDB_TABLEINFO_ORDER
  1726.          *
  1727.          *       you can combine MDB_TABLEINFO_ORDER and
  1728.          *       MDB_TABLEINFO_ORDERTABLE with MDB_TABLEINFO_ORDER |
  1729.          *       MDB_TABLEINFO_ORDERTABLE * or with MDB_TABLEINFO_FULL
  1730.          **/
  1731.  
  1732.         // if $result is a string, then we want information about a
  1733.         // table without a resultset
  1734.         if (is_string($result)) {
  1735.             $id @ibase_query($this->connection,"SELECT * FROM $result");
  1736.             if (empty($id)) {
  1737.                 return $this->ibaseRaiseError();
  1738.             }
  1739.         else // else we want information about a resultset
  1740.             $id $result;
  1741.             if (empty($id)) {
  1742.                 return $this->ibaseRaiseError();
  1743.             }
  1744.         }
  1745.  
  1746.         $count @ibase_num_fields($id);
  1747.  
  1748.         // made this IF due to performance (one if is faster than $count if's)
  1749.         if (empty($mode)) {
  1750.             for ($i=0; $i<$count$i++{
  1751.                 $info @ibase_field_info($id$i);
  1752.                 //$res[$i]['table'] = (is_string($result)) ? $result : '';
  1753.                 $res[$i]['table'(is_string($result)) $result $info['relation'];
  1754.                 $res[$i]['name']  $info['name'];
  1755.                 $res[$i]['type']  $info['type'];
  1756.                 $res[$i]['len']   $info['length'];
  1757.                 //$res[$i]['flags'] = (is_string($result)) ? $this->_ibaseFieldFlags($info['name'], $result) : '';
  1758.                 $res[$i]['flags'(is_string($result)) $this->_ibaseFieldFlags($id$i$result'';
  1759.             }
  1760.         else // full
  1761.             $res['num_fields'$count;
  1762.  
  1763.             for ($i=0; $i<$count$i++{
  1764.                 $info @ibase_field_info($id$i);
  1765.                 //$res[$i]['table'] = (is_string($result)) ? $result : '';
  1766.                 $res[$i]['table'(is_string($result)) $result $info['relation'];
  1767.                 $res[$i]['name']  $info['name'];
  1768.                 $res[$i]['type']  $info['type'];
  1769.                 $res[$i]['len']   $info['length'];
  1770.                 //$res[$i]['flags'] = (is_string($result)) ? $this->_ibaseFieldFlags($info['name'], $result) : '';
  1771.                 $res[$i]['flags'(is_string($result)) $this->_ibaseFieldFlags($id$i$result'';
  1772.                 if ($mode MDB_TABLEINFO_ORDER{
  1773.                     $res['order'][$res[$i]['name']] $i;
  1774.                 }
  1775.                 if ($mode MDB_TABLEINFO_ORDERTABLE{
  1776.                     $res['ordertable'][$res[$i]['table']][$res[$i]['name']] $i;
  1777.                 }
  1778.             }
  1779.         }
  1780.  
  1781.         // free the result only if we were called on a table
  1782.         if (is_string($result&& is_resource($id)) {
  1783.             @ibase_free_result($id);
  1784.         }
  1785.         return $res;
  1786.     }
  1787.  
  1788.     // }}}
  1789.     // {{{ _ibaseFieldFlags()
  1790.  
  1791.     /**
  1792.      * get the Flags of a Field
  1793.      *
  1794.      * @param int $resource FireBird/InterBase result identifier
  1795.      * @param int $num_field the field number
  1796.      * @return string The flags of the field ('not_null', 'default_xx', 'primary_key',
  1797.      *                  'unique' and 'multiple_key' are supported)
  1798.      * @access private
  1799.      ***/
  1800.     function _ibaseFieldFlags($resource$num_field$table_name)
  1801.     {
  1802.         $field_name @ibase_field_info($resource$num_field);
  1803.         $field_name @$field_name['name'];
  1804.         $sql 'SELECT  R.RDB$CONSTRAINT_TYPE CTYPE'
  1805.                .' FROM  RDB$INDEX_SEGMENTS I'
  1806.                .' JOIN  RDB$RELATION_CONSTRAINTS R ON I.RDB$INDEX_NAME=R.RDB$INDEX_NAME'
  1807.               .' WHERE  I.RDB$FIELD_NAME=\''.$field_name.'\''
  1808.                  .' AND UPPER(R.RDB$RELATION_NAME)=\''.strtoupper($table_name).'\'';
  1809.         $result @ibase_query($this->connection$sql);
  1810.         if (empty($result)) {
  1811.             return $this->ibaseRaiseError();
  1812.         }
  1813.         $flags '';
  1814.         if ($obj @ibase_fetch_object($result)) {
  1815.             @ibase_free_result($result);
  1816.             if (isset($obj->CTYPE)  && trim($obj->CTYPE== 'PRIMARY KEY'{
  1817.                 $flags 'primary_key ';
  1818.             }
  1819.             if (isset($obj->CTYPE)  && trim($obj->CTYPE== 'UNIQUE'{
  1820.                 $flags .= 'unique_key ';
  1821.             }
  1822.         }
  1823.  
  1824.         $sql 'SELECT  R.RDB$NULL_FLAG AS NFLAG,'
  1825.                      .' R.RDB$DEFAULT_SOURCE AS DSOURCE,'
  1826.                      .' F.RDB$FIELD_TYPE AS FTYPE,'
  1827.                      .' F.RDB$COMPUTED_SOURCE AS CSOURCE'
  1828.                .' FROM  RDB$RELATION_FIELDS R '
  1829.                .' JOIN  RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME'
  1830.               .' WHERE  UPPER(R.RDB$RELATION_NAME)=\''.strtoupper($table_name).'\''
  1831.                 .' AND  R.RDB$FIELD_NAME=\''.$field_name.'\'';
  1832.         $result @ibase_query($this->connection$sql);
  1833.         if (empty($result)) {
  1834.             return $this->ibaseRaiseError();
  1835.         }
  1836.         if ($obj @ibase_fetch_object($result)) {
  1837.             @ibase_free_result($result);
  1838.             if (isset($obj->NFLAG)) {
  1839.                 $flags .= 'not_null ';
  1840.             }
  1841.             if (isset($obj->DSOURCE)) {
  1842.                 $flags .= 'default ';
  1843.             }
  1844.             if (isset($obj->CSOURCE)) {
  1845.                 $flags .= 'computed ';
  1846.             }
  1847.             if (isset($obj->FTYPE)  && $obj->FTYPE == 261{
  1848.                 $flags .= 'blob ';
  1849.             }
  1850.         }
  1851.  
  1852.          return trim($flags);
  1853.     }
  1854. }
  1855.  
  1856. ?>

Documentation generated on Mon, 11 Mar 2019 10:15:24 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.