3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
6 * The PEAR DB driver for PHP's oci8 extension
7 * for interacting with Oracle databases
11 * LICENSE: This source file is subject to version 3.0 of the PHP license
12 * that is available through the world-wide-web at the following URI:
13 * http://www.php.net/license/3_0.txt. If you did not receive a copy of
14 * the PHP License and are unable to obtain it through the web, please
15 * send a note to license@php.net so we can mail you a copy immediately.
19 * @author James L. Pine <jlp@valinux.com>
20 * @author Daniel Convissor <danielc@php.net>
21 * @copyright 1997-2007 The PHP Group
22 * @license http://www.php.net/license/3_0.txt PHP License 3.0
24 * @link http://pear.php.net/package/DB
28 * Obtain the DB_common class so it can be extended from
30 //require_once 'DB/common.php';
31 require_once 'common.php';
34 * The methods PEAR DB uses to interact with PHP's oci8 extension
35 * for interacting with Oracle databases
37 * Definitely works with versions 8 and 9 of Oracle.
39 * These methods overload the ones declared in DB_common.
41 * Be aware... OCIError() only appears to return anything when given a
42 * statement, so functions return the generic DB_ERROR instead of more
43 * useful errors that have to do with feedback from the database.
47 * @author James L. Pine <jlp@valinux.com>
48 * @author Daniel Convissor <danielc@php.net>
49 * @copyright 1997-2007 The PHP Group
50 * @license http://www.php.net/license/3_0.txt PHP License 3.0
51 * @version Release: 1.9.2
52 * @link http://pear.php.net/package/DB
54 class DB_oci8 extends DB_common
59 * The DB driver type (mysql, oci8, odbc, etc.)
62 public $phptype = 'oci8';
65 * The database syntax variant to be used (db2, access, etc.), if any
68 public $dbsyntax = 'oci8';
71 * The capabilities of this DB implementation
73 * The 'new_link' element contains the PHP version that first provided
74 * new_link support for this DBMS. Contains false if it's unsupported.
76 * Meaning of the 'limit' element:
77 * + 'emulate' = emulate with fetch row by number
78 * + 'alter' = alter the query
83 public $features = array(
85 'new_link' => '5.0.0',
86 'numrows' => 'subquery',
90 'transactions' => true,
94 * A mapping of native error codes to DB error codes
97 public $errorcode_map = array(
98 1 => DB_ERROR_CONSTRAINT,
99 900 => DB_ERROR_SYNTAX,
100 904 => DB_ERROR_NOSUCHFIELD,
101 913 => DB_ERROR_VALUE_COUNT_ON_ROW,
102 921 => DB_ERROR_SYNTAX,
103 923 => DB_ERROR_SYNTAX,
104 942 => DB_ERROR_NOSUCHTABLE,
105 955 => DB_ERROR_ALREADY_EXISTS,
106 1400 => DB_ERROR_CONSTRAINT_NOT_NULL,
107 1401 => DB_ERROR_INVALID,
108 1407 => DB_ERROR_CONSTRAINT_NOT_NULL,
109 1418 => DB_ERROR_NOT_FOUND,
110 1476 => DB_ERROR_DIVZERO,
111 1722 => DB_ERROR_INVALID_NUMBER,
112 2289 => DB_ERROR_NOSUCHTABLE,
113 2291 => DB_ERROR_CONSTRAINT,
114 2292 => DB_ERROR_CONSTRAINT,
115 2449 => DB_ERROR_CONSTRAINT,
116 12899 => DB_ERROR_INVALID,
120 * The raw database connection created by PHP
126 * The DSN information for connecting to a database
129 public $dsn = array();
133 * Should data manipulation queries be committed automatically?
137 public $autocommit = true;
140 * Stores the $data passed to execute() in the oci8 driver
142 * Gets reset to array() when simpleQuery() is run.
144 * Needed in case user wants to call numRows() after prepare/execute
150 public $_data = array();
153 * The result or statement handle from the most recently executed query
159 * Is the given prepared statement a data manipulation query?
163 public $manip_query = array();
166 * Store of prepared SQL queries.
170 public $_prepared_queries = array();
177 * This constructor calls <kbd>parent::__construct()</kbd>
181 public function __construct()
183 parent::__construct();
190 * Connect to the database server, log in and open the database
192 * Don't call this method directly. Use DB::connect() instead.
194 * If PHP is at version 5.0.0 or greater:
195 * + Generally, oci_connect() or oci_pconnect() are used.
196 * + But if the new_link DSN option is set to true, oci_new_connect()
199 * When using PHP version 4.x, OCILogon() or OCIPLogon() are used.
201 * PEAR DB's oci8 driver supports the following extra DSN options:
202 * + charset The character set to be used on the connection.
203 * Only used if PHP is at version 5.0.0 or greater
204 * and the Oracle server is at 9.2 or greater.
205 * Available since PEAR DB 1.7.0.
206 * + new_link If set to true, causes subsequent calls to
207 * connect() to return a new connection link
208 * instead of the existing one. WARNING: this is
209 * not portable to other DBMS's.
210 * Available since PEAR DB 1.7.0.
212 * @param array $dsn the data source name
213 * @param bool $persistent should the connection be persistent?
217 public function connect($dsn, $persistent = false)
219 if (!PEAR::loadExtension('oci8')) {
220 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
224 if ($dsn['dbsyntax']) {
225 $this->dbsyntax = $dsn['dbsyntax'];
228 // Backwards compatibility with DB < 1.7.0
229 if (empty($dsn['database']) && !empty($dsn['hostspec'])) {
230 $db = $dsn['hostspec'];
232 $db = $dsn['database'];
235 if (function_exists('oci_connect')) {
236 if (isset($dsn['new_link'])
237 && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) {
238 $connect_function = 'oci_new_connect';
240 $connect_function = $persistent ? 'oci_pconnect'
243 if (isset($this->dsn['port']) && $this->dsn['port']) {
244 $db = '//' . $db . ':' . $this->dsn['port'];
247 $char = empty($dsn['charset']) ? null : $dsn['charset'];
248 $this->connection = @$connect_function(
255 if (!empty($error) && $error['code'] == 12541) {
256 // Couldn't find TNS listener. Try direct connection.
257 $this->connection = @$connect_function(
265 $connect_function = $persistent ? 'OCIPLogon' : 'OCILogon';
267 $this->connection = @$connect_function(
272 } elseif ($dsn['username'] || $dsn['password']) {
273 $this->connection = @$connect_function(
280 if (!$this->connection) {
282 $error = (is_array($error)) ? $error['message'] : null;
283 return $this->raiseError(
284 DB_ERROR_CONNECT_FAILED,
298 * Disconnects from the database server
300 * @return bool TRUE on success, FALSE on failure
302 public function disconnect()
304 if (function_exists('oci_close')) {
305 $ret = @oci_close($this->connection);
307 $ret = @OCILogOff($this->connection);
309 $this->connection = null;
317 * Sends a query to the database server
319 * To determine how many rows of a result set get buffered using
320 * ocisetprefetch(), see the "result_buffering" option in setOptions().
321 * This option was added in Release 1.7.0.
323 * @param string the SQL query string
325 * @return mixed + a PHP result resrouce for successful SELECT queries
326 * + the DB_OK constant for other successful queries
327 * + a DB_Error object on failure
329 public function simpleQuery($query)
331 $this->_data = array();
332 $this->last_parameters = array();
333 $this->last_query = $query;
334 $query = $this->modifyQuery($query);
335 $result = @OCIParse($this->connection, $query);
337 return $this->oci8RaiseError();
339 if ($this->autocommit) {
340 $success = @OCIExecute($result, OCI_COMMIT_ON_SUCCESS);
342 $success = @OCIExecute($result, OCI_DEFAULT);
345 return $this->oci8RaiseError($result);
347 $this->last_stmt = $result;
348 if ($this->_checkManip($query)) {
351 @ocisetprefetch($result, $this->options['result_buffering']);
360 * Changes a query string for various DBMS specific reasons
362 * "SELECT 2+2" must be "SELECT 2+2 FROM dual" in Oracle.
364 * @param string $query the query string to modify
366 * @return string the modified query string
370 public function modifyQuery($query)
372 if (preg_match('/^\s*SELECT/i', $query) &&
373 !preg_match('/\sFROM\s/i', $query)) {
374 $query .= ' FROM dual';
383 * Produces a DB_Error object regarding the current problem
385 * @param int $errno if the error is being manually raised pass a
386 * DB_ERROR* constant here. If this isn't passed
387 * the error information gathered from the DBMS.
389 * @return object the DB_Error object
391 * @see DB_common::raiseError(),
392 * DB_oci8::errorNative(), DB_oci8::errorCode()
394 public function oci8RaiseError($errno = null)
396 if ($errno === null) {
397 $error = @OCIError($this->connection);
398 return $this->raiseError(
399 $this->errorCode($error['code']),
405 } elseif (is_resource($errno)) {
406 $error = @OCIError($errno);
407 return $this->raiseError(
408 $this->errorCode($error['code']),
415 return $this->raiseError($this->errorCode($errno));
422 * Move the internal oracle result pointer to the next available result
424 * @param a valid oci8 result resource
428 * @return true if a result is available otherwise return false
430 public function nextResult($result)
436 * Places a row from the result set into the given array
438 * Formating of the array and the data therein are configurable.
439 * See DB_result::fetchInto() for more information.
441 * This method is not meant to be called directly. Use
442 * DB_result::fetchInto() instead. It can't be declared "protected"
443 * because DB_result is a separate object.
445 * @param resource $result the query result resource
446 * @param array $arr the referenced array to put the data in
447 * @param int $fetchmode how the resulting array should be indexed
448 * @param int $rownum the row number to fetch (0 = first row)
450 * @return mixed DB_OK on success, NULL when the end of a result set is
451 * reached or on failure
453 * @see DB_result::fetchInto()
455 public function fetchInto($result, &$arr, $fetchmode, $rownum = null)
457 if ($rownum !== null) {
458 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
460 if ($fetchmode & DB_FETCHMODE_ASSOC) {
461 $moredata = @OCIFetchInto($result, $arr, OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
462 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE &&
464 $arr = array_change_key_case($arr, CASE_LOWER);
467 $moredata = OCIFetchInto($result, $arr, OCI_RETURN_NULLS + OCI_RETURN_LOBS);
472 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
473 $this->_rtrimArrayValues($arr);
475 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
476 $this->_convertNullArrayValuesToEmpty($arr);
485 * Deletes the result set and frees the memory occupied by the result set
487 * This method is not meant to be called directly. Use
488 * DB_result::free() instead. It can't be declared "protected"
489 * because DB_result is a separate object.
491 * @param resource $result PHP's query result resource
493 * @return bool TRUE on success, FALSE if $result is invalid
495 * @see DB_result::free()
497 public function freeResult($result)
499 return is_resource($result) ? OCIFreeStatement($result) : false;
506 * Frees the internal resources associated with a prepared query
508 * @param resource $stmt the prepared statement's resource
509 * @param bool $free_resource should the PHP resource be freed too?
510 * Use false if you need to get data
511 * from the result set later.
513 * @return bool TRUE on success, FALSE if $result is invalid
515 * @see DB_oci8::prepare()
517 public function freePrepared($stmt, $free_resource = true)
519 if (!is_resource($stmt)) {
522 if ($free_resource) {
523 @ocifreestatement($stmt);
525 if (isset($this->prepare_types[(int)$stmt])) {
526 unset($this->prepare_types[(int)$stmt]);
527 unset($this->manip_query[(int)$stmt]);
528 unset($this->_prepared_queries[(int)$stmt]);
539 * Gets the number of rows in a result set
541 * Only works if the DB_PORTABILITY_NUMROWS portability option
544 * This method is not meant to be called directly. Use
545 * DB_result::numRows() instead. It can't be declared "protected"
546 * because DB_result is a separate object.
548 * @param resource $result PHP's query result resource
552 * @see DB_result::numRows(), DB_common::setOption()
554 public function numRows($result)
556 // emulate numRows for Oracle. yuck.
557 if ($this->options['portability'] & DB_PORTABILITY_NUMROWS &&
558 $result === $this->last_stmt) {
559 $countquery = 'SELECT COUNT(*) FROM (' . $this->last_query . ')';
560 $save_query = $this->last_query;
561 $save_stmt = $this->last_stmt;
563 $count = $this->query($countquery);
565 // Restore the last query and statement.
566 $this->last_query = $save_query;
567 $this->last_stmt = $save_stmt;
569 if (DB::isError($count) ||
570 DB::isError($row = $count->fetchRow(DB_FETCHMODE_ORDERED))) {
571 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
576 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
583 * Gets the number of columns in a result set
585 * This method is not meant to be called directly. Use
586 * DB_result::numCols() instead. It can't be declared "protected"
587 * because DB_result is a separate object.
589 * @param resource $result PHP's query result resource
593 * @see DB_result::numCols()
595 public function numCols($result)
597 $cols = @OCINumCols($result);
599 return $this->oci8RaiseError($result);
608 * Enables or disables automatic commits
610 * @param bool $onoff true turns it on, false turns it off
612 * @return int DB_OK on success. A DB_Error object if the driver
613 * doesn't support auto-committing transactions.
615 public function autoCommit($onoff = false)
617 $this->autocommit = (bool)$onoff;;
625 * Commits the current transaction
629 public function commit()
631 $result = @OCICommit($this->connection);
633 return $this->oci8RaiseError();
642 * Reverts the current transaction
646 public function rollback()
648 $result = @OCIRollback($this->connection);
650 return $this->oci8RaiseError();
656 // {{{ affectedRows()
659 * Determines the number of rows affected by a data maniuplation query
661 * 0 is returned for queries that don't manipulate data.
665 public function affectedRows()
667 if ($this->last_stmt === false) {
668 return $this->oci8RaiseError();
670 $result = @OCIRowCount($this->last_stmt);
671 if ($result === false) {
672 return $this->oci8RaiseError($this->last_stmt);
681 * Adds LIMIT clauses to a query string according to current DBMS standards
683 * @param string $query the query to modify
684 * @param int $from the row to start to fetching (0 = the first row)
685 * @param int $count the numbers of rows to fetch
686 * @param mixed $params array, string or numeric data to be used in
687 * execution of the statement. Quantity of items
688 * passed must match quantity of placeholders in
689 * query: meaning 1 placeholder for non-array
690 * parameters or 1 placeholder per array element.
692 * @return string the query string with LIMIT clauses added
696 public function modifyLimitQuery($query, $from, $count, $params = array())
698 // Let Oracle return the name of the columns instead of
699 // coding a "home" SQL parser
701 if (count($params)) {
702 $result = $this->prepare("SELECT * FROM ($query) "
703 . 'WHERE NULL = NULL');
704 $tmp = $this->execute($result, $params);
706 $q_fields = "SELECT * FROM ($query) WHERE NULL = NULL";
708 if (!$result = @OCIParse($this->connection, $q_fields)) {
709 $this->last_query = $q_fields;
710 return $this->oci8RaiseError();
712 if (!@OCIExecute($result, OCI_DEFAULT)) {
713 $this->last_query = $q_fields;
714 return $this->oci8RaiseError($result);
718 $ncols = OCINumCols($result);
720 for ($i = 1; $i <= $ncols; $i++) {
721 $cols[] = '"' . OCIColumnName($result, $i) . '"';
723 $fields = implode(', ', $cols);
724 // XXX Test that (tip by John Lim)
725 //if (preg_match('/^\s*SELECT\s+/is', $query, $match)) {
726 // // Introduce the FIRST_ROWS Oracle query optimizer
727 // $query = substr($query, strlen($match[0]), strlen($query));
728 // $query = "SELECT /* +FIRST_ROWS */ " . $query;
731 // Construct the query
732 // more at: http://marc.theaimsgroup.com/?l=php-db&m=99831958101212&w=2
733 // Perhaps this could be optimized with the use of Unions
734 $query = "SELECT $fields FROM" .
735 " (SELECT rownum as linenum, $fields FROM" .
737 ' WHERE rownum <= ' . ($from + $count) .
738 ') WHERE linenum >= ' . ++$from;
743 // {{{ modifyLimitQuery()
746 * Prepares a query for multiple execution with execute().
748 * With oci8, this is emulated.
750 * prepare() requires a generic query as string like <code>
751 * INSERT INTO numbers VALUES (?, ?, ?)
752 * </code>. The <kbd>?</kbd> characters are placeholders.
754 * Three types of placeholders can be used:
755 * + <kbd>?</kbd> a quoted scalar value, i.e. strings, integers
756 * + <kbd>!</kbd> value is inserted 'as is'
757 * + <kbd>&</kbd> requires a file name. The file's contents get
758 * inserted into the query (i.e. saving binary
761 * Use backslashes to escape placeholder characters if you don't want
762 * them to be interpreted as placeholders. Example: <code>
763 * "UPDATE foo SET col=? WHERE col='over \& under'"
766 * @param string $query the query to be prepared
768 * @return mixed DB statement resource on success. DB_Error on failure.
770 * @see DB_oci8::execute()
772 public function prepare($query)
774 $tokens = preg_split(
778 PREG_SPLIT_DELIM_CAPTURE
780 $binds = count($tokens) - 1;
785 foreach ($tokens as $key => $val) {
788 $types[$token++] = DB_PARAM_SCALAR;
789 unset($tokens[$key]);
792 $types[$token++] = DB_PARAM_OPAQUE;
793 unset($tokens[$key]);
796 $types[$token++] = DB_PARAM_MISC;
797 unset($tokens[$key]);
800 $tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val);
801 if ($key != $binds) {
802 $newquery .= $tokens[$key] . ':bind' . $token;
804 $newquery .= $tokens[$key];
809 $this->last_query = $query;
810 $newquery = $this->modifyQuery($newquery);
811 if (!$stmt = @OCIParse($this->connection, $newquery)) {
812 return $this->oci8RaiseError();
814 $this->prepare_types[(int)$stmt] = $types;
815 $this->manip_query[(int)$stmt] = DB::isManip($query);
816 $this->_prepared_queries[(int)$stmt] = $newquery;
824 * Executes a DB statement prepared with prepare().
826 * To determine how many rows of a result set get buffered using
827 * ocisetprefetch(), see the "result_buffering" option in setOptions().
828 * This option was added in Release 1.7.0.
830 * @param resource $stmt a DB statement resource returned from prepare()
831 * @param mixed $data array, string or numeric data to be used in
832 * execution of the statement. Quantity of items
833 * passed must match quantity of placeholders in
834 * query: meaning 1 for non-array items or the
835 * quantity of elements in the array.
837 * @return mixed returns an oic8 result resource for successful SELECT
838 * queries, DB_OK for other successful queries.
839 * A DB error object is returned on failure.
841 * @see DB_oci8::prepare()
843 public function &execute($stmt, $data = array())
845 $data = (array)$data;
846 $this->last_parameters = $data;
847 $this->last_query = $this->_prepared_queries[(int)$stmt];
848 $this->_data = $data;
850 $types = $this->prepare_types[(int)$stmt];
851 if (count($types) != count($data)) {
852 $tmp = $this->raiseError(DB_ERROR_MISMATCH);
857 foreach ($data as $key => $value) {
858 if ($types[$i] == DB_PARAM_MISC) {
860 * Oracle doesn't seem to have the ability to pass a
861 * parameter along unchanged, so strip off quotes from start
862 * and end, plus turn two single quotes to one single quote,
863 * in order to avoid the quotes getting escaped by
864 * Oracle and ending up in the database.
866 $data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]);
867 $data[$key] = str_replace("''", "'", $data[$key]);
868 } elseif ($types[$i] == DB_PARAM_OPAQUE) {
869 $fp = @fopen($data[$key], 'rb');
871 $tmp = $this->raiseError(DB_ERROR_ACCESS_VIOLATION);
874 $data[$key] = fread($fp, filesize($data[$key]));
876 } elseif ($types[$i] == DB_PARAM_SCALAR) {
877 // Floats have to be converted to a locale-neutral
879 if (is_float($data[$key])) {
880 $data[$key] = $this->quoteFloat($data[$key]);
883 if (!@OCIBindByName($stmt, ':bind' . $i, $data[$key], -1)) {
884 $tmp = $this->oci8RaiseError($stmt);
887 $this->last_query = preg_replace(
889 $this->quoteSmart($data[$key]),
895 if ($this->autocommit) {
896 $success = @OCIExecute($stmt, OCI_COMMIT_ON_SUCCESS);
898 $success = @OCIExecute($stmt, OCI_DEFAULT);
901 $tmp = $this->oci8RaiseError($stmt);
904 $this->last_stmt = $stmt;
905 if ($this->manip_query[(int)$stmt] || $this->_next_query_manip) {
906 $this->_last_query_manip = true;
907 $this->_next_query_manip = false;
910 $this->_last_query_manip = false;
911 @ocisetprefetch($stmt, $this->options['result_buffering']);
912 $tmp = new DB_result($this, $stmt);
918 * Formats a float value for use within a query in a locale-independent
921 * @param float the float value to be quoted.
922 * @return string the quoted string.
923 * @see DB_common::quoteSmart()
924 * @since Method available since release 1.7.8.
926 public function quoteFloat($float)
928 return $this->escapeSimple(str_replace(',', '.', strval(floatval($float))));
932 // {{{ dropSequence()
935 * Returns the next free id in a sequence
937 * @param string $seq_name name of the sequence
938 * @param boolean $ondemand when true, the seqence is automatically
939 * created if it does not exist
942 * A DB_Error object on failure.
944 * @see DB_common::nextID(), DB_common::getSequenceName(),
945 * DB_oci8::createSequence(), DB_oci8::dropSequence()
947 public function nextId($seq_name, $ondemand = true)
949 $seqname = $this->getSequenceName($seq_name);
952 $this->expectError(DB_ERROR_NOSUCHTABLE);
953 $result = $this->query("SELECT ${seqname}.nextval FROM dual");
955 if ($ondemand && DB::isError($result) &&
956 $result->getCode() == DB_ERROR_NOSUCHTABLE) {
958 $result = $this->createSequence($seq_name);
959 if (DB::isError($result)) {
960 return $this->raiseError($result);
966 if (DB::isError($result)) {
967 return $this->raiseError($result);
969 $arr = $result->fetchRow(DB_FETCHMODE_ORDERED);
974 // {{{ oci8RaiseError()
977 * Creates a new sequence
979 * @param string $seq_name name of the new sequence
981 * @return int DB_OK on success. A DB_Error object on failure.
983 * @see DB_common::createSequence(), DB_common::getSequenceName(),
984 * DB_oci8::nextID(), DB_oci8::dropSequence()
986 public function createSequence($seq_name)
988 return $this->query('CREATE SEQUENCE '
989 . $this->getSequenceName($seq_name));
998 * @param string $seq_name name of the sequence to be deleted
1000 * @return int DB_OK on success. A DB_Error object on failure.
1002 * @see DB_common::dropSequence(), DB_common::getSequenceName(),
1003 * DB_oci8::nextID(), DB_oci8::createSequence()
1005 public function dropSequence($seq_name)
1007 return $this->query('DROP SEQUENCE '
1008 . $this->getSequenceName($seq_name));
1015 * Gets the DBMS' native error code produced by the last query
1017 * @return int the DBMS' error code. FALSE if the code could not be
1020 public function errorNative()
1022 if (is_resource($this->last_stmt)) {
1023 $error = @OCIError($this->last_stmt);
1025 $error = @OCIError($this->connection);
1027 if (is_array($error)) {
1028 return $error['code'];
1034 // {{{ getSpecialQuery()
1037 * Returns information about a table or a result set
1039 * NOTE: only supports 'table' and 'flags' if <var>$result</var>
1042 * NOTE: flags won't contain index information.
1044 * @param object|string $result DB_result object from a query or a
1045 * string containing the name of a table.
1046 * While this also accepts a query result
1047 * resource identifier, this behavior is
1049 * @param int $mode a valid tableInfo mode
1051 * @return array|object
1052 * A DB_Error object on failure.
1054 * @see DB_common::tableInfo()
1056 public function tableInfo($result, $mode = null)
1058 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
1059 $case_func = 'strtolower';
1061 $case_func = 'strval';
1066 if (is_string($result)) {
1068 * Probably received a table name.
1069 * Create a result resource identifier.
1071 $result = strtoupper($result);
1072 $q_fields = 'SELECT column_name, data_type, data_length, '
1074 . 'FROM user_tab_columns '
1075 . "WHERE table_name='$result' ORDER BY column_id";
1077 $this->last_query = $q_fields;
1079 if (!$stmt = @OCIParse($this->connection, $q_fields)) {
1080 return $this->oci8RaiseError(DB_ERROR_NEED_MORE_DATA);
1082 if (!@OCIExecute($stmt, OCI_DEFAULT)) {
1083 return $this->oci8RaiseError($stmt);
1087 while (@OCIFetch($stmt)) {
1089 'table' => $case_func($result),
1090 'name' => $case_func(@OCIResult($stmt, 1)),
1091 'type' => @OCIResult($stmt, 2),
1092 'len' => @OCIResult($stmt, 3),
1093 'flags' => (@OCIResult($stmt, 4) == 'N') ? 'not_null' : '',
1095 if ($mode & DB_TABLEINFO_ORDER) {
1096 $res['order'][$res[$i]['name']] = $i;
1098 if ($mode & DB_TABLEINFO_ORDERTABLE) {
1099 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
1105 $res['num_fields'] = $i;
1107 @OCIFreeStatement($stmt);
1109 if (isset($result->result)) {
1111 * Probably received a result object.
1112 * Extract the result resource identifier.
1114 $result = $result->result;
1119 if ($result === $this->last_stmt) {
1120 $count = @OCINumCols($result);
1122 $res['num_fields'] = $count;
1124 for ($i = 0; $i < $count; $i++) {
1127 'name' => $case_func(@OCIColumnName($result, $i + 1)),
1128 'type' => @OCIColumnType($result, $i + 1),
1129 'len' => @OCIColumnSize($result, $i + 1),
1132 if ($mode & DB_TABLEINFO_ORDER) {
1133 $res['order'][$res[$i]['name']] = $i;
1135 if ($mode & DB_TABLEINFO_ORDERTABLE) {
1136 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
1140 return $this->raiseError(DB_ERROR_NOT_CAPABLE);
1150 * Obtains the query string needed for listing a given type of objects
1152 * @param string $type the kind of objects you want to retrieve
1154 * @return string the SQL query string or null if the driver doesn't
1155 * support the object type requested
1158 * @see DB_common::getListOf()
1160 public function getSpecialQuery($type)
1164 return 'SELECT table_name FROM user_tables';
1166 return 'SELECT synonym_name FROM user_synonyms';
1168 return 'SELECT view_name FROM user_views';