3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
6 * The PEAR DB driver for PHP's interbase extension
7 * for interacting with Interbase and Firebird databases
9 * While this class works with PHP 4, PHP's InterBase extension is
10 * unstable in PHP 4. Use PHP 5.
12 * PHP versions 4 and 5
14 * LICENSE: This source file is subject to version 3.0 of the PHP license
15 * that is available through the world-wide-web at the following URI:
16 * http://www.php.net/license/3_0.txt. If you did not receive a copy of
17 * the PHP License and are unable to obtain it through the web, please
18 * send a note to license@php.net so we can mail you a copy immediately.
22 * @author Sterling Hughes <sterling@php.net>
23 * @author Daniel Convissor <danielc@php.net>
24 * @copyright 1997-2007 The PHP Group
25 * @license http://www.php.net/license/3_0.txt PHP License 3.0
26 * @version CVS: $Id: ibase.php,v 1.116 2007/09/21 13:40:41 aharvey Exp $
27 * @link http://pear.php.net/package/DB
31 * Obtain the DB_common class so it can be extended from
33 require_once 'DB/common.php';
36 * The methods PEAR DB uses to interact with PHP's interbase extension
37 * for interacting with Interbase and Firebird databases
39 * These methods overload the ones declared in DB_common.
41 * While this class works with PHP 4, PHP's InterBase extension is
42 * unstable in PHP 4. Use PHP 5.
44 * NOTICE: limitQuery() only works for Firebird.
48 * @author Sterling Hughes <sterling@php.net>
49 * @author Daniel Convissor <danielc@php.net>
50 * @copyright 1997-2007 The PHP Group
51 * @license http://www.php.net/license/3_0.txt PHP License 3.0
52 * @version Release: 1.7.14RC1
53 * @link http://pear.php.net/package/DB
54 * @since Class became stable in Release 1.7.0
56 class DB_ibase extends DB_common
61 * The DB driver type (mysql, oci8, odbc, etc.)
64 var $phptype = 'ibase';
67 * The database syntax variant to be used (db2, access, etc.), if any
70 var $dbsyntax = 'ibase';
73 * The capabilities of this DB implementation
75 * The 'new_link' element contains the PHP version that first provided
76 * new_link support for this DBMS. Contains false if it's unsupported.
78 * Meaning of the 'limit' element:
79 * + 'emulate' = emulate with fetch row by number
80 * + 'alter' = alter the query
83 * NOTE: only firebird supports limit.
87 var $features = array(
90 'numrows' => 'emulate',
94 'transactions' => true,
98 * A mapping of native error codes to DB error codes
101 var $errorcode_map = array(
102 -104 => DB_ERROR_SYNTAX,
103 -150 => DB_ERROR_ACCESS_VIOLATION,
104 -151 => DB_ERROR_ACCESS_VIOLATION,
105 -155 => DB_ERROR_NOSUCHTABLE,
106 -157 => DB_ERROR_NOSUCHFIELD,
107 -158 => DB_ERROR_VALUE_COUNT_ON_ROW,
108 -170 => DB_ERROR_MISMATCH,
109 -171 => DB_ERROR_MISMATCH,
110 -172 => DB_ERROR_INVALID,
111 // -204 => // Covers too many errors, need to use regex on msg
112 -205 => DB_ERROR_NOSUCHFIELD,
113 -206 => DB_ERROR_NOSUCHFIELD,
114 -208 => DB_ERROR_INVALID,
115 -219 => DB_ERROR_NOSUCHTABLE,
116 -297 => DB_ERROR_CONSTRAINT,
117 -303 => DB_ERROR_INVALID,
118 -413 => DB_ERROR_INVALID_NUMBER,
119 -530 => DB_ERROR_CONSTRAINT,
120 -551 => DB_ERROR_ACCESS_VIOLATION,
121 -552 => DB_ERROR_ACCESS_VIOLATION,
122 // -607 => // Covers too many errors, need to use regex on msg
123 -625 => DB_ERROR_CONSTRAINT_NOT_NULL,
124 -803 => DB_ERROR_CONSTRAINT,
125 -804 => DB_ERROR_VALUE_COUNT_ON_ROW,
126 // -902 => // Covers too many errors, need to use regex on msg
127 -904 => DB_ERROR_CONNECT_FAILED,
128 -922 => DB_ERROR_NOSUCHDB,
129 -923 => DB_ERROR_CONNECT_FAILED,
130 -924 => DB_ERROR_CONNECT_FAILED
134 * The raw database connection created by PHP
140 * The DSN information for connecting to a database
147 * The number of rows affected by a data manipulation query
154 * Should data manipulation queries be committed automatically?
158 var $autocommit = true;
161 * The prepared statement handle from the most recently executed statement
163 * {@internal Mainly here because the InterBase/Firebird API is only
164 * able to retrieve data from result sets if the statemnt handle is
172 * Is the given prepared statement a data manipulation query?
176 var $manip_query = array();
183 * This constructor calls <kbd>$this->DB_common()</kbd>
196 * Connect to the database server, log in and open the database
198 * Don't call this method directly. Use DB::connect() instead.
200 * PEAR DB's ibase driver supports the following extra DSN options:
201 * + buffers The number of database buffers to allocate for the
203 * + charset The default character set for a database.
204 * + dialect The default SQL dialect for any statement
205 * executed within a connection. Defaults to the
206 * highest one supported by client libraries.
207 * Functional only with InterBase 6 and up.
208 * + role Functional only with InterBase 5 and up.
210 * @param array $dsn the data source name
211 * @param bool $persistent should the connection be persistent?
213 * @return int DB_OK on success. A DB_Error object on failure.
215 function connect($dsn, $persistent = false)
217 if (!PEAR::loadExtension('interbase')) {
218 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
222 if ($dsn['dbsyntax']) {
223 $this->dbsyntax = $dsn['dbsyntax'];
225 if ($this->dbsyntax == 'firebird') {
226 $this->features['limit'] = 'alter';
231 ? ($dsn['hostspec'] . ':' . $dsn['database'])
233 $dsn['username'] ? $dsn['username'] : null,
234 $dsn['password'] ? $dsn['password'] : null,
235 isset($dsn['charset']) ? $dsn['charset'] : null,
236 isset($dsn['buffers']) ? $dsn['buffers'] : null,
237 isset($dsn['dialect']) ? $dsn['dialect'] : null,
238 isset($dsn['role']) ? $dsn['role'] : null,
241 $connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect';
243 $this->connection = @call_user_func_array($connect_function, $params);
244 if (!$this->connection) {
245 return $this->ibaseRaiseError(DB_ERROR_CONNECT_FAILED);
254 * Disconnects from the database server
256 * @return bool TRUE on success, FALSE on failure
258 function disconnect()
260 $ret = @ibase_close($this->connection);
261 $this->connection = null;
269 * Sends a query to the database server
271 * @param string the SQL query string
273 * @return mixed + a PHP result resrouce for successful SELECT queries
274 * + the DB_OK constant for other successful queries
275 * + a DB_Error object on failure
277 function simpleQuery($query)
279 $ismanip = $this->_checkManip($query);
280 $this->last_query = $query;
281 $query = $this->modifyQuery($query);
282 $result = @ibase_query($this->connection, $query);
285 return $this->ibaseRaiseError();
287 if ($this->autocommit && $ismanip) {
288 @ibase_commit($this->connection);
291 $this->affected = $result;
300 // {{{ modifyLimitQuery()
303 * Adds LIMIT clauses to a query string according to current DBMS standards
305 * Only works with Firebird.
307 * @param string $query the query to modify
308 * @param int $from the row to start to fetching (0 = the first row)
309 * @param int $count the numbers of rows to fetch
310 * @param mixed $params array, string or numeric data to be used in
311 * execution of the statement. Quantity of items
312 * passed must match quantity of placeholders in
313 * query: meaning 1 placeholder for non-array
314 * parameters or 1 placeholder per array element.
316 * @return string the query string with LIMIT clauses added
320 function modifyLimitQuery($query, $from, $count, $params = array())
322 if ($this->dsn['dbsyntax'] == 'firebird') {
323 $query = preg_replace('/^([\s(])*SELECT/i',
324 "SELECT FIRST $count SKIP $from", $query);
333 * Move the internal ibase result pointer to the next available result
335 * @param a valid fbsql result resource
339 * @return true if a result is available otherwise return false
341 function nextResult($result)
350 * Places a row from the result set into the given array
352 * Formating of the array and the data therein are configurable.
353 * See DB_result::fetchInto() for more information.
355 * This method is not meant to be called directly. Use
356 * DB_result::fetchInto() instead. It can't be declared "protected"
357 * because DB_result is a separate object.
359 * @param resource $result the query result resource
360 * @param array $arr the referenced array to put the data in
361 * @param int $fetchmode how the resulting array should be indexed
362 * @param int $rownum the row number to fetch (0 = first row)
364 * @return mixed DB_OK on success, NULL when the end of a result set is
365 * reached or on failure
367 * @see DB_result::fetchInto()
369 function fetchInto($result, &$arr, $fetchmode, $rownum = null)
371 if ($rownum !== null) {
372 return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE);
374 if ($fetchmode & DB_FETCHMODE_ASSOC) {
375 if (function_exists('ibase_fetch_assoc')) {
376 $arr = @ibase_fetch_assoc($result);
378 $arr = get_object_vars(ibase_fetch_object($result));
380 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
381 $arr = array_change_key_case($arr, CASE_LOWER);
384 $arr = @ibase_fetch_row($result);
389 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
390 $this->_rtrimArrayValues($arr);
392 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
393 $this->_convertNullArrayValuesToEmpty($arr);
402 * Deletes the result set and frees the memory occupied by the result set
404 * This method is not meant to be called directly. Use
405 * DB_result::free() instead. It can't be declared "protected"
406 * because DB_result is a separate object.
408 * @param resource $result PHP's query result resource
410 * @return bool TRUE on success, FALSE if $result is invalid
412 * @see DB_result::free()
414 function freeResult($result)
416 return is_resource($result) ? ibase_free_result($result) : false;
422 function freeQuery($query)
424 return is_resource($query) ? ibase_free_query($query) : false;
428 // {{{ affectedRows()
431 * Determines the number of rows affected by a data maniuplation query
433 * 0 is returned for queries that don't manipulate data.
435 * @return int the number of rows. A DB_Error object on failure.
437 function affectedRows()
439 if (is_integer($this->affected)) {
440 return $this->affected;
442 return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE);
449 * Gets the number of columns in a result set
451 * This method is not meant to be called directly. Use
452 * DB_result::numCols() instead. It can't be declared "protected"
453 * because DB_result is a separate object.
455 * @param resource $result PHP's query result resource
457 * @return int the number of columns. A DB_Error object on failure.
459 * @see DB_result::numCols()
461 function numCols($result)
463 $cols = @ibase_num_fields($result);
465 return $this->ibaseRaiseError();
474 * Prepares a query for multiple execution with execute().
476 * prepare() requires a generic query as string like <code>
477 * INSERT INTO numbers VALUES (?, ?, ?)
478 * </code>. The <kbd>?</kbd> characters are placeholders.
480 * Three types of placeholders can be used:
481 * + <kbd>?</kbd> a quoted scalar value, i.e. strings, integers
482 * + <kbd>!</kbd> value is inserted 'as is'
483 * + <kbd>&</kbd> requires a file name. The file's contents get
484 * inserted into the query (i.e. saving binary
487 * Use backslashes to escape placeholder characters if you don't want
488 * them to be interpreted as placeholders. Example: <code>
489 * "UPDATE foo SET col=? WHERE col='over \& under'"
492 * @param string $query query to be prepared
493 * @return mixed DB statement resource on success. DB_Error on failure.
495 function prepare($query)
497 $tokens = preg_split('/((?<!\\\)[&?!])/', $query, -1,
498 PREG_SPLIT_DELIM_CAPTURE);
503 foreach ($tokens as $key => $val) {
506 $types[$token++] = DB_PARAM_SCALAR;
509 $types[$token++] = DB_PARAM_OPAQUE;
512 $types[$token++] = DB_PARAM_MISC;
515 $tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val);
516 $newquery .= $tokens[$key] . '?';
520 $newquery = substr($newquery, 0, -1);
521 $this->last_query = $query;
522 $newquery = $this->modifyQuery($newquery);
523 $stmt = @ibase_prepare($this->connection, $newquery);
525 if ($stmt === false) {
526 $stmt = $this->ibaseRaiseError();
528 $this->prepare_types[(int)$stmt] = $types;
529 $this->manip_query[(int)$stmt] = DB::isManip($query);
539 * Executes a DB statement prepared with prepare().
541 * @param resource $stmt a DB statement resource returned from prepare()
542 * @param mixed $data array, string or numeric data to be used in
543 * execution of the statement. Quantity of items
544 * passed must match quantity of placeholders in
545 * query: meaning 1 for non-array items or the
546 * quantity of elements in the array.
547 * @return object a new DB_Result or a DB_Error when fail
548 * @see DB_ibase::prepare()
551 function &execute($stmt, $data = array())
553 $data = (array)$data;
554 $this->last_parameters = $data;
556 $types = $this->prepare_types[(int)$stmt];
557 if (count($types) != count($data)) {
558 $tmp = $this->raiseError(DB_ERROR_MISMATCH);
563 foreach ($data as $key => $value) {
564 if ($types[$i] == DB_PARAM_MISC) {
566 * ibase doesn't seem to have the ability to pass a
567 * parameter along unchanged, so strip off quotes from start
568 * and end, plus turn two single quotes to one single quote,
569 * in order to avoid the quotes getting escaped by
570 * ibase and ending up in the database.
572 $data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]);
573 $data[$key] = str_replace("''", "'", $data[$key]);
574 } elseif ($types[$i] == DB_PARAM_OPAQUE) {
575 $fp = @fopen($data[$key], 'rb');
577 $tmp = $this->raiseError(DB_ERROR_ACCESS_VIOLATION);
580 $data[$key] = fread($fp, filesize($data[$key]));
586 array_unshift($data, $stmt);
588 $res = call_user_func_array('ibase_execute', $data);
590 $tmp = $this->ibaseRaiseError();
594 if ($this->autocommit && $this->manip_query[(int)$stmt]) {
595 @ibase_commit($this->connection);
597 $this->last_stmt = $stmt;
598 if ($this->manip_query[(int)$stmt] || $this->_next_query_manip) {
599 $this->_last_query_manip = true;
600 $this->_next_query_manip = false;
603 $this->_last_query_manip = false;
604 $tmp = new DB_result($this, $res);
610 * Frees the internal resources associated with a prepared query
612 * @param resource $stmt the prepared statement's PHP resource
613 * @param bool $free_resource should the PHP resource be freed too?
614 * Use false if you need to get data
615 * from the result set later.
617 * @return bool TRUE on success, FALSE if $result is invalid
619 * @see DB_ibase::prepare()
621 function freePrepared($stmt, $free_resource = true)
623 if (!is_resource($stmt)) {
626 if ($free_resource) {
627 @ibase_free_query($stmt);
629 unset($this->prepare_tokens[(int)$stmt]);
630 unset($this->prepare_types[(int)$stmt]);
631 unset($this->manip_query[(int)$stmt]);
639 * Enables or disables automatic commits
641 * @param bool $onoff true turns it on, false turns it off
643 * @return int DB_OK on success. A DB_Error object if the driver
644 * doesn't support auto-committing transactions.
646 function autoCommit($onoff = false)
648 $this->autocommit = $onoff ? 1 : 0;
656 * Commits the current transaction
658 * @return int DB_OK on success. A DB_Error object on failure.
662 return @ibase_commit($this->connection);
669 * Reverts the current transaction
671 * @return int DB_OK on success. A DB_Error object on failure.
675 return @ibase_rollback($this->connection);
679 // {{{ transactionInit()
681 function transactionInit($trans_args = 0)
684 ? @ibase_trans($trans_args, $this->connection)
692 * Returns the next free id in a sequence
694 * @param string $seq_name name of the sequence
695 * @param boolean $ondemand when true, the seqence is automatically
696 * created if it does not exist
698 * @return int the next id number in the sequence.
699 * A DB_Error object on failure.
701 * @see DB_common::nextID(), DB_common::getSequenceName(),
702 * DB_ibase::createSequence(), DB_ibase::dropSequence()
704 function nextId($seq_name, $ondemand = true)
706 $sqn = strtoupper($this->getSequenceName($seq_name));
709 $this->pushErrorHandling(PEAR_ERROR_RETURN);
710 $result = $this->query("SELECT GEN_ID(${sqn}, 1) "
711 . 'FROM RDB$GENERATORS '
712 . "WHERE RDB\$GENERATOR_NAME='${sqn}'");
713 $this->popErrorHandling();
714 if ($ondemand && DB::isError($result)) {
716 $result = $this->createSequence($seq_name);
717 if (DB::isError($result)) {
724 if (DB::isError($result)) {
725 return $this->raiseError($result);
727 $arr = $result->fetchRow(DB_FETCHMODE_ORDERED);
733 // {{{ createSequence()
736 * Creates a new sequence
738 * @param string $seq_name name of the new sequence
740 * @return int DB_OK on success. A DB_Error object on failure.
742 * @see DB_common::createSequence(), DB_common::getSequenceName(),
743 * DB_ibase::nextID(), DB_ibase::dropSequence()
745 function createSequence($seq_name)
747 $sqn = strtoupper($this->getSequenceName($seq_name));
748 $this->pushErrorHandling(PEAR_ERROR_RETURN);
749 $result = $this->query("CREATE GENERATOR ${sqn}");
750 $this->popErrorHandling();
756 // {{{ dropSequence()
761 * @param string $seq_name name of the sequence to be deleted
763 * @return int DB_OK on success. A DB_Error object on failure.
765 * @see DB_common::dropSequence(), DB_common::getSequenceName(),
766 * DB_ibase::nextID(), DB_ibase::createSequence()
768 function dropSequence($seq_name)
770 return $this->query('DELETE FROM RDB$GENERATORS '
771 . "WHERE RDB\$GENERATOR_NAME='"
772 . strtoupper($this->getSequenceName($seq_name))
777 // {{{ _ibaseFieldFlags()
780 * Get the column's flags
782 * Supports "primary_key", "unique_key", "not_null", "default",
783 * "computed" and "blob".
785 * @param string $field_name the name of the field
786 * @param string $table_name the name of the table
788 * @return string the flags
792 function _ibaseFieldFlags($field_name, $table_name)
794 $sql = 'SELECT R.RDB$CONSTRAINT_TYPE CTYPE'
795 .' FROM RDB$INDEX_SEGMENTS I'
796 .' JOIN RDB$RELATION_CONSTRAINTS R ON I.RDB$INDEX_NAME=R.RDB$INDEX_NAME'
797 .' WHERE I.RDB$FIELD_NAME=\'' . $field_name . '\''
798 .' AND UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\'';
800 $result = @ibase_query($this->connection, $sql);
802 return $this->ibaseRaiseError();
806 if ($obj = @ibase_fetch_object($result)) {
807 @ibase_free_result($result);
808 if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'PRIMARY KEY') {
809 $flags .= 'primary_key ';
811 if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'UNIQUE') {
812 $flags .= 'unique_key ';
816 $sql = 'SELECT R.RDB$NULL_FLAG AS NFLAG,'
817 .' R.RDB$DEFAULT_SOURCE AS DSOURCE,'
818 .' F.RDB$FIELD_TYPE AS FTYPE,'
819 .' F.RDB$COMPUTED_SOURCE AS CSOURCE'
820 .' FROM RDB$RELATION_FIELDS R '
821 .' JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME'
822 .' WHERE UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\''
823 .' AND R.RDB$FIELD_NAME=\'' . $field_name . '\'';
825 $result = @ibase_query($this->connection, $sql);
827 return $this->ibaseRaiseError();
829 if ($obj = @ibase_fetch_object($result)) {
830 @ibase_free_result($result);
831 if (isset($obj->NFLAG)) {
832 $flags .= 'not_null ';
834 if (isset($obj->DSOURCE)) {
835 $flags .= 'default ';
837 if (isset($obj->CSOURCE)) {
838 $flags .= 'computed ';
840 if (isset($obj->FTYPE) && $obj->FTYPE == 261) {
849 // {{{ ibaseRaiseError()
852 * Produces a DB_Error object regarding the current problem
854 * @param int $errno if the error is being manually raised pass a
855 * DB_ERROR* constant here. If this isn't passed
856 * the error information gathered from the DBMS.
858 * @return object the DB_Error object
860 * @see DB_common::raiseError(),
861 * DB_ibase::errorNative(), DB_ibase::errorCode()
863 function &ibaseRaiseError($errno = null)
865 if ($errno === null) {
866 $errno = $this->errorCode($this->errorNative());
868 $tmp = $this->raiseError($errno, null, null, null, @ibase_errmsg());
876 * Gets the DBMS' native error code produced by the last query
878 * @return int the DBMS' error code. NULL if there is no error code.
880 * @since Method available since Release 1.7.0
882 function errorNative()
884 if (function_exists('ibase_errcode')) {
885 return @ibase_errcode();
887 if (preg_match('/^Dynamic SQL Error SQL error code = ([0-9-]+)/i',
888 @ibase_errmsg(), $m)) {
898 * Maps native error codes to DB's portable ones
900 * @param int $nativecode the error code returned by the DBMS
902 * @return int the portable DB error code. Return DB_ERROR if the
903 * current driver doesn't have a mapping for the
904 * $nativecode submitted.
906 * @since Method available since Release 1.7.0
908 function errorCode($nativecode = null)
910 if (isset($this->errorcode_map[$nativecode])) {
911 return $this->errorcode_map[$nativecode];
914 static $error_regexps;
915 if (!isset($error_regexps)) {
916 $error_regexps = array(
917 '/generator .* is not defined/'
918 => DB_ERROR_SYNTAX, // for compat. w ibase_errcode()
919 '/table.*(not exist|not found|unknown)/i'
920 => DB_ERROR_NOSUCHTABLE,
921 '/table .* already exists/i'
922 => DB_ERROR_ALREADY_EXISTS,
923 '/unsuccessful metadata update .* failed attempt to store duplicate value/i'
924 => DB_ERROR_ALREADY_EXISTS,
925 '/unsuccessful metadata update .* not found/i'
926 => DB_ERROR_NOT_FOUND,
927 '/validation error for column .* value "\*\*\* null/i'
928 => DB_ERROR_CONSTRAINT_NOT_NULL,
929 '/violation of [\w ]+ constraint/i'
930 => DB_ERROR_CONSTRAINT,
931 '/conversion error from string/i'
932 => DB_ERROR_INVALID_NUMBER,
933 '/no permission for/i'
934 => DB_ERROR_ACCESS_VIOLATION,
935 '/arithmetic exception, numeric overflow, or string truncation/i'
937 '/feature is not supported/i'
938 => DB_ERROR_NOT_CAPABLE,
942 $errormsg = @ibase_errmsg();
943 foreach ($error_regexps as $regexp => $code) {
944 if (preg_match($regexp, $errormsg)) {
955 * Returns information about a table or a result set
957 * NOTE: only supports 'table' and 'flags' if <var>$result</var>
960 * @param object|string $result DB_result object from a query or a
961 * string containing the name of a table.
962 * While this also accepts a query result
963 * resource identifier, this behavior is
965 * @param int $mode a valid tableInfo mode
967 * @return array an associative array with the information requested.
968 * A DB_Error object on failure.
970 * @see DB_common::tableInfo()
972 function tableInfo($result, $mode = null)
974 if (is_string($result)) {
976 * Probably received a table name.
977 * Create a result resource identifier.
979 $id = @ibase_query($this->connection,
980 "SELECT * FROM $result WHERE 1=0");
982 } elseif (isset($result->result)) {
984 * Probably received a result object.
985 * Extract the result resource identifier.
987 $id = $result->result;
991 * Probably received a result resource identifier.
993 * Deprecated. Here for compatibility only.
999 if (!is_resource($id)) {
1000 return $this->ibaseRaiseError(DB_ERROR_NEED_MORE_DATA);
1003 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
1004 $case_func = 'strtolower';
1006 $case_func = 'strval';
1009 $count = @ibase_num_fields($id);
1013 $res['num_fields'] = $count;
1016 for ($i = 0; $i < $count; $i++) {
1017 $info = @ibase_field_info($id, $i);
1019 'table' => $got_string ? $case_func($result) : '',
1020 'name' => $case_func($info['name']),
1021 'type' => $info['type'],
1022 'len' => $info['length'],
1023 'flags' => ($got_string)
1024 ? $this->_ibaseFieldFlags($info['name'], $result)
1027 if ($mode & DB_TABLEINFO_ORDER) {
1028 $res['order'][$res[$i]['name']] = $i;
1030 if ($mode & DB_TABLEINFO_ORDERTABLE) {
1031 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
1035 // free the result only if we were called on a table
1037 @ibase_free_result($id);
1043 // {{{ getSpecialQuery()
1046 * Obtains the query string needed for listing a given type of objects
1048 * @param string $type the kind of objects you want to retrieve
1050 * @return string the SQL query string or null if the driver doesn't
1051 * support the object type requested
1054 * @see DB_common::getListOf()
1056 function getSpecialQuery($type)
1060 return 'SELECT DISTINCT R.RDB$RELATION_NAME FROM '
1061 . 'RDB$RELATION_FIELDS R WHERE R.RDB$SYSTEM_FLAG=0';
1063 return 'SELECT DISTINCT RDB$VIEW_NAME from RDB$VIEW_RELATIONS';
1065 return 'SELECT DISTINCT RDB$USER FROM RDB$USER_PRIVILEGES';