MediaWiki  REL1_21
DatabaseOracle.php
Go to the documentation of this file.
00001 <?php
00030 class ORAResult {
00031         private $rows;
00032         private $cursor;
00033         private $nrows;
00034 
00035         private $columns = array();
00036 
00037         private function array_unique_md( $array_in ) {
00038                 $array_out = array();
00039                 $array_hashes = array();
00040 
00041                 foreach ( $array_in as $item ) {
00042                         $hash = md5( serialize( $item ) );
00043                         if ( !isset( $array_hashes[$hash] ) ) {
00044                                 $array_hashes[$hash] = $hash;
00045                                 $array_out[] = $item;
00046                         }
00047                 }
00048 
00049                 return $array_out;
00050         }
00051 
00057         function __construct( &$db, $stmt, $unique = false ) {
00058                 $this->db =& $db;
00059 
00060                 if ( ( $this->nrows = oci_fetch_all( $stmt, $this->rows, 0, - 1, OCI_FETCHSTATEMENT_BY_ROW | OCI_NUM ) ) === false ) {
00061                         $e = oci_error( $stmt );
00062                         $db->reportQueryError( $e['message'], $e['code'], '', __METHOD__ );
00063                         $this->free();
00064                         return;
00065                 }
00066 
00067                 if ( $unique ) {
00068                         $this->rows = $this->array_unique_md( $this->rows );
00069                         $this->nrows = count( $this->rows );
00070                 }
00071 
00072                 if ( $this->nrows > 0 ) {
00073                         foreach ( $this->rows[0] as $k => $v ) {
00074                                 $this->columns[$k] = strtolower( oci_field_name( $stmt, $k + 1 ) );
00075                         }
00076                 }
00077 
00078                 $this->cursor = 0;
00079                 oci_free_statement( $stmt );
00080         }
00081 
00082         public function free() {
00083                 unset( $this->db );
00084         }
00085 
00086         public function seek( $row ) {
00087                 $this->cursor = min( $row, $this->nrows );
00088         }
00089 
00090         public function numRows() {
00091                 return $this->nrows;
00092         }
00093 
00094         public function numFields() {
00095                 return count( $this->columns );
00096         }
00097 
00098         public function fetchObject() {
00099                 if ( $this->cursor >= $this->nrows ) {
00100                         return false;
00101                 }
00102                 $row = $this->rows[$this->cursor++];
00103                 $ret = new stdClass();
00104                 foreach ( $row as $k => $v ) {
00105                         $lc = $this->columns[$k];
00106                         $ret->$lc = $v;
00107                 }
00108 
00109                 return $ret;
00110         }
00111 
00112         public function fetchRow() {
00113                 if ( $this->cursor >= $this->nrows ) {
00114                         return false;
00115                 }
00116 
00117                 $row = $this->rows[$this->cursor++];
00118                 $ret = array();
00119                 foreach ( $row as $k => $v ) {
00120                         $lc = $this->columns[$k];
00121                         $ret[$lc] = $v;
00122                         $ret[$k] = $v;
00123                 }
00124                 return $ret;
00125         }
00126 }
00127 
00132 class ORAField implements Field {
00133         private $name, $tablename, $default, $max_length, $nullable,
00134                 $is_pk, $is_unique, $is_multiple, $is_key, $type;
00135 
00136         function __construct( $info ) {
00137                 $this->name = $info['column_name'];
00138                 $this->tablename = $info['table_name'];
00139                 $this->default = $info['data_default'];
00140                 $this->max_length = $info['data_length'];
00141                 $this->nullable = $info['not_null'];
00142                 $this->is_pk = isset( $info['prim'] ) && $info['prim'] == 1 ? 1 : 0;
00143                 $this->is_unique = isset( $info['uniq'] ) && $info['uniq'] == 1 ? 1 : 0;
00144                 $this->is_multiple = isset( $info['nonuniq'] ) && $info['nonuniq'] == 1 ? 1 : 0;
00145                 $this->is_key = ( $this->is_pk || $this->is_unique || $this->is_multiple );
00146                 $this->type = $info['data_type'];
00147         }
00148 
00149         function name() {
00150                 return $this->name;
00151         }
00152 
00153         function tableName() {
00154                 return $this->tablename;
00155         }
00156 
00157         function defaultValue() {
00158                 return $this->default;
00159         }
00160 
00161         function maxLength() {
00162                 return $this->max_length;
00163         }
00164 
00165         function isNullable() {
00166                 return $this->nullable;
00167         }
00168 
00169         function isKey() {
00170                 return $this->is_key;
00171         }
00172 
00173         function isMultipleKey() {
00174                 return $this->is_multiple;
00175         }
00176 
00177         function type() {
00178                 return $this->type;
00179         }
00180 }
00181 
00185 class DatabaseOracle extends DatabaseBase {
00186         var $mInsertId = null;
00187         var $mLastResult = null;
00188         var $lastResult = null;
00189         var $cursor = 0;
00190         var $mAffectedRows;
00191 
00192         var $ignore_DUP_VAL_ON_INDEX = false;
00193         var $sequenceData = null;
00194 
00195         var $defaultCharset = 'AL32UTF8';
00196 
00197         var $mFieldInfoCache = array();
00198 
00199         function __construct( $server = false, $user = false, $password = false, $dbName = false,
00200                 $flags = 0, $tablePrefix = 'get from global' )
00201         {
00202                 global $wgDBprefix;
00203                 $tablePrefix = $tablePrefix == 'get from global' ? strtoupper( $wgDBprefix ) : strtoupper( $tablePrefix );
00204                 parent::__construct( $server, $user, $password, $dbName, $flags, $tablePrefix );
00205                 wfRunHooks( 'DatabaseOraclePostInit', array( $this ) );
00206         }
00207 
00208         function __destruct() {
00209                 if ($this->mOpened) {
00210                         wfSuppressWarnings();
00211                         $this->close();
00212                         wfRestoreWarnings();
00213                 }
00214         }
00215 
00216         function getType() {
00217                 return 'oracle';
00218         }
00219 
00220         function cascadingDeletes() {
00221                 return true;
00222         }
00223         function cleanupTriggers() {
00224                 return true;
00225         }
00226         function strictIPs() {
00227                 return true;
00228         }
00229         function realTimestamps() {
00230                 return true;
00231         }
00232         function implicitGroupby() {
00233                 return false;
00234         }
00235         function implicitOrderby() {
00236                 return false;
00237         }
00238         function searchableIPs() {
00239                 return true;
00240         }
00241 
00251         function open( $server, $user, $password, $dbName ) {
00252                 if ( !function_exists( 'oci_connect' ) ) {
00253                         throw new DBConnectionError( $this, "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n (Note: if you recently installed PHP, you may need to restart your webserver and database)\n" );
00254                 }
00255 
00256                 $this->close();
00257                 $this->mUser = $user;
00258                 $this->mPassword = $password;
00259                 // changed internal variables functions
00260                 // mServer now holds the TNS endpoint
00261                 // mDBname is schema name if different from username
00262                 if ( !$server ) {
00263                         // backward compatibillity (server used to be null and TNS was supplied in dbname)
00264                         $this->mServer = $dbName;
00265                         $this->mDBname = $user;
00266                 } else {
00267                         $this->mServer = $server;
00268                         if ( !$dbName ) {
00269                                 $this->mDBname = $user;
00270                         } else {
00271                                 $this->mDBname = $dbName;
00272                         }
00273                 }
00274 
00275                 if ( !strlen( $user ) ) { # e.g. the class is being loaded
00276                         return;
00277                 }
00278 
00279                 $session_mode = $this->mFlags & DBO_SYSDBA ? OCI_SYSDBA : OCI_DEFAULT;
00280                 wfSuppressWarnings();
00281                 if ( $this->mFlags & DBO_DEFAULT ) {
00282                         $this->mConn = oci_new_connect( $this->mUser, $this->mPassword, $this->mServer, $this->defaultCharset, $session_mode );
00283                 } else {
00284                         $this->mConn = oci_connect( $this->mUser, $this->mPassword, $this->mServer, $this->defaultCharset, $session_mode );
00285                 }
00286                 wfRestoreWarnings();
00287 
00288                 if ( $this->mUser != $this->mDBname ) {
00289                         //change current schema in session
00290                         $this->selectDB( $this->mDBname );
00291                 }
00292 
00293                 if ( !$this->mConn ) {
00294                         throw new DBConnectionError( $this, $this->lastError() );
00295                 }
00296 
00297                 $this->mOpened = true;
00298 
00299                 # removed putenv calls because they interfere with the system globaly
00300                 $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
00301                 $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
00302                 $this->doQuery( 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=\'.,\'' );
00303                 return $this->mConn;
00304         }
00305 
00311         protected function closeConnection() {
00312                 return oci_close( $this->mConn );
00313         }
00314 
00315         function execFlags() {
00316                 return $this->mTrxLevel ? OCI_NO_AUTO_COMMIT : OCI_COMMIT_ON_SUCCESS;
00317         }
00318 
00319         protected function doQuery( $sql ) {
00320                 wfDebug( "SQL: [$sql]\n" );
00321                 if ( !StringUtils::isUtf8( $sql ) ) {
00322                         throw new MWException( "SQL encoding is invalid\n$sql" );
00323                 }
00324 
00325                 // handle some oracle specifics
00326                 // remove AS column/table/subquery namings
00327                 if( !$this->getFlag( DBO_DDLMODE ) ) {
00328                         $sql = preg_replace( '/ as /i', ' ', $sql );
00329                 }
00330 
00331                 // Oracle has issues with UNION clause if the statement includes LOB fields
00332                 // So we do a UNION ALL and then filter the results array with array_unique
00333                 $union_unique = ( preg_match( '/\/\* UNION_UNIQUE \*\/ /', $sql ) != 0 );
00334                 // EXPLAIN syntax in Oracle is EXPLAIN PLAN FOR and it return nothing
00335                 // you have to select data from plan table after explain
00336                 $explain_id = date( 'dmYHis' );
00337 
00338                 $sql = preg_replace( '/^EXPLAIN /', 'EXPLAIN PLAN SET STATEMENT_ID = \'' . $explain_id . '\' FOR', $sql, 1, $explain_count );
00339 
00340                 wfSuppressWarnings();
00341 
00342                 if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) {
00343                         $e = oci_error( $this->mConn );
00344                         $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
00345                         return false;
00346                 }
00347 
00348                 if ( !oci_execute( $stmt, $this->execFlags() ) ) {
00349                         $e = oci_error( $stmt );
00350                         if ( !$this->ignore_DUP_VAL_ON_INDEX || $e['code'] != '1' ) {
00351                                 $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
00352                                 return false;
00353                         }
00354                 }
00355 
00356                 wfRestoreWarnings();
00357 
00358                 if ( $explain_count > 0 ) {
00359                         return $this->doQuery( 'SELECT id, cardinality "ROWS" FROM plan_table WHERE statement_id = \'' . $explain_id . '\'' );
00360                 } elseif ( oci_statement_type( $stmt ) == 'SELECT' ) {
00361                         return new ORAResult( $this, $stmt, $union_unique );
00362                 } else {
00363                         $this->mAffectedRows = oci_num_rows( $stmt );
00364                         return true;
00365                 }
00366         }
00367 
00368         function queryIgnore( $sql, $fname = '' ) {
00369                 return $this->query( $sql, $fname, true );
00370         }
00371 
00372         function freeResult( $res ) {
00373                 if ( $res instanceof ResultWrapper ) {
00374                         $res = $res->result;
00375                 }
00376 
00377                 $res->free();
00378         }
00379 
00380         function fetchObject( $res ) {
00381                 if ( $res instanceof ResultWrapper ) {
00382                         $res = $res->result;
00383                 }
00384 
00385                 return $res->fetchObject();
00386         }
00387 
00388         function fetchRow( $res ) {
00389                 if ( $res instanceof ResultWrapper ) {
00390                         $res = $res->result;
00391                 }
00392 
00393                 return $res->fetchRow();
00394         }
00395 
00396         function numRows( $res ) {
00397                 if ( $res instanceof ResultWrapper ) {
00398                         $res = $res->result;
00399                 }
00400 
00401                 return $res->numRows();
00402         }
00403 
00404         function numFields( $res ) {
00405                 if ( $res instanceof ResultWrapper ) {
00406                         $res = $res->result;
00407                 }
00408 
00409                 return $res->numFields();
00410         }
00411 
00412         function fieldName( $stmt, $n ) {
00413                 return oci_field_name( $stmt, $n );
00414         }
00415 
00420         function insertId() {
00421                 return $this->mInsertId;
00422         }
00423 
00424         function dataSeek( $res, $row ) {
00425                 if ( $res instanceof ORAResult ) {
00426                         $res->seek( $row );
00427                 } else {
00428                         $res->result->seek( $row );
00429                 }
00430         }
00431 
00432         function lastError() {
00433                 if ( $this->mConn === false ) {
00434                         $e = oci_error();
00435                 } else {
00436                         $e = oci_error( $this->mConn );
00437                 }
00438                 return $e['message'];
00439         }
00440 
00441         function lastErrno() {
00442                 if ( $this->mConn === false ) {
00443                         $e = oci_error();
00444                 } else {
00445                         $e = oci_error( $this->mConn );
00446                 }
00447                 return $e['code'];
00448         }
00449 
00450         function affectedRows() {
00451                 return $this->mAffectedRows;
00452         }
00453 
00459         function indexInfo( $table, $index, $fname = 'DatabaseOracle::indexExists' ) {
00460                 return false;
00461         }
00462 
00463         function indexUnique( $table, $index, $fname = 'DatabaseOracle::indexUnique' ) {
00464                 return false;
00465         }
00466 
00467         function insert( $table, $a, $fname = 'DatabaseOracle::insert', $options = array() ) {
00468                 if ( !count( $a ) ) {
00469                         return true;
00470                 }
00471 
00472                 if ( !is_array( $options ) ) {
00473                         $options = array( $options );
00474                 }
00475 
00476                 if ( in_array( 'IGNORE', $options ) ) {
00477                         $this->ignore_DUP_VAL_ON_INDEX = true;
00478                 }
00479 
00480                 if ( !is_array( reset( $a ) ) ) {
00481                         $a = array( $a );
00482                 }
00483 
00484                 foreach ( $a as &$row ) {
00485                         $this->insertOneRow( $table, $row, $fname );
00486                 }
00487                 $retVal = true;
00488 
00489                 if ( in_array( 'IGNORE', $options ) ) {
00490                         $this->ignore_DUP_VAL_ON_INDEX = false;
00491                 }
00492 
00493                 return $retVal;
00494         }
00495 
00496         private function fieldBindStatement ( $table, $col, &$val, $includeCol = false ) {
00497                 $col_info = $this->fieldInfoMulti( $table, $col );
00498                 $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
00499 
00500                 $bind = '';
00501                 if ( is_numeric( $col ) ) {
00502                         $bind = $val;
00503                         $val = null;
00504                         return $bind;
00505                 } elseif ( $includeCol ) {
00506                         $bind = "$col = ";
00507                 }
00508 
00509                 if ( $val == '' && $val !== 0 && $col_type != 'BLOB' && $col_type != 'CLOB' ) {
00510                         $val = null;
00511                 }
00512 
00513                 if ( $val === 'NULL' ) {
00514                         $val = null;
00515                 }
00516 
00517                 if ( $val === null ) {
00518                         if ( $col_info != false && $col_info->isNullable() == 0 && $col_info->defaultValue() != null ) {
00519                                 $bind .= 'DEFAULT';
00520                         } else {
00521                                 $bind .= 'NULL';
00522                         }
00523                 } else {
00524                         $bind .= ':' . $col;
00525                 }
00526 
00527                 return $bind;
00528         }
00529 
00530         private function insertOneRow( $table, $row, $fname ) {
00531                 global $wgContLang;
00532 
00533                 $table = $this->tableName( $table );
00534                 // "INSERT INTO tables (a, b, c)"
00535                 $sql = "INSERT INTO " . $table . " (" . join( ',', array_keys( $row ) ) . ')';
00536                 $sql .= " VALUES (";
00537 
00538                 // for each value, append ":key"
00539                 $first = true;
00540                 foreach ( $row as $col => &$val ) {
00541                         if ( !$first ) {
00542                                 $sql .= ', ';
00543                         } else {
00544                                 $first = false;
00545                         }
00546 
00547                         $sql .= $this->fieldBindStatement( $table, $col, $val );
00548                 }
00549                 $sql .= ')';
00550 
00551                 if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) {
00552                         $e = oci_error( $this->mConn );
00553                         $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
00554                         return false;
00555                 }
00556                 foreach ( $row as $col => &$val ) {
00557                         $col_info = $this->fieldInfoMulti( $table, $col );
00558                         $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
00559 
00560                         if ( $val === null ) {
00561                                 // do nothing ... null was inserted in statement creation
00562                         } elseif ( $col_type != 'BLOB' && $col_type != 'CLOB' ) {
00563                                 if ( is_object( $val ) ) {
00564                                         $val = $val->fetch();
00565                                 }
00566 
00567                                 // backward compatibility
00568                                 if ( preg_match( '/^timestamp.*/i', $col_type ) == 1 && strtolower( $val ) == 'infinity' ) {
00569                                         $val = $this->getInfinity();
00570                                 }
00571 
00572                                 $val = ( $wgContLang != null ) ? $wgContLang->checkTitleEncoding( $val ) : $val;
00573                                 if ( oci_bind_by_name( $stmt, ":$col", $val, -1, SQLT_CHR ) === false ) {
00574                                         $e = oci_error( $stmt );
00575                                         $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
00576                                         return false;
00577                                 }
00578                         } else {
00579                                 if ( ( $lob[$col] = oci_new_descriptor( $this->mConn, OCI_D_LOB ) ) === false ) {
00580                                         $e = oci_error( $stmt );
00581                                         throw new DBUnexpectedError( $this, "Cannot create LOB descriptor: " . $e['message'] );
00582                                 }
00583 
00584                                 if ( is_object( $val ) ) {
00585                                         $val = $val->fetch();
00586                                 }
00587 
00588                                 if ( $col_type == 'BLOB' ) {
00589                                         $lob[$col]->writeTemporary( $val, OCI_TEMP_BLOB );
00590                                         oci_bind_by_name( $stmt, ":$col", $lob[$col], - 1, OCI_B_BLOB );
00591                                 } else {
00592                                         $lob[$col]->writeTemporary( $val, OCI_TEMP_CLOB );
00593                                         oci_bind_by_name( $stmt, ":$col", $lob[$col], - 1, OCI_B_CLOB );
00594                                 }
00595                         }
00596                 }
00597 
00598                 wfSuppressWarnings();
00599 
00600                 if ( oci_execute( $stmt, $this->execFlags() ) === false ) {
00601                         $e = oci_error( $stmt );
00602                         if ( !$this->ignore_DUP_VAL_ON_INDEX || $e['code'] != '1' ) {
00603                                 $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
00604                                 return false;
00605                         } else {
00606                                 $this->mAffectedRows = oci_num_rows( $stmt );
00607                         }
00608                 } else {
00609                         $this->mAffectedRows = oci_num_rows( $stmt );
00610                 }
00611 
00612                 wfRestoreWarnings();
00613 
00614                 if ( isset( $lob ) ) {
00615                         foreach ( $lob as $lob_v ) {
00616                                 $lob_v->free();
00617                         }
00618                 }
00619 
00620                 if ( !$this->mTrxLevel ) {
00621                         oci_commit( $this->mConn );
00622                 }
00623 
00624                 oci_free_statement( $stmt );
00625         }
00626 
00627         function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = 'DatabaseOracle::insertSelect',
00628                 $insertOptions = array(), $selectOptions = array() )
00629         {
00630                 $destTable = $this->tableName( $destTable );
00631                 if ( !is_array( $selectOptions ) ) {
00632                         $selectOptions = array( $selectOptions );
00633                 }
00634                 list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions );
00635                 if ( is_array( $srcTable ) ) {
00636                         $srcTable = implode( ',', array_map( array( &$this, 'tableName' ), $srcTable ) );
00637                 } else {
00638                         $srcTable = $this->tableName( $srcTable );
00639                 }
00640 
00641                 if ( ( $sequenceData = $this->getSequenceData( $destTable ) ) !== false &&
00642                                 !isset( $varMap[$sequenceData['column']] ) )
00643                 {
00644                         $varMap[$sequenceData['column']] = 'GET_SEQUENCE_VALUE(\'' . $sequenceData['sequence'] . '\')';
00645                 }
00646 
00647                 // count-alias subselect fields to avoid abigious definition errors
00648                 $i = 0;
00649                 foreach ( $varMap as &$val ) {
00650                         $val = $val . ' field' . ( $i++ );
00651                 }
00652 
00653                 $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
00654                         " SELECT $startOpts " . implode( ',', $varMap ) .
00655                         " FROM $srcTable $useIndex ";
00656                 if ( $conds != '*' ) {
00657                         $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
00658                 }
00659                 $sql .= " $tailOpts";
00660 
00661                 if ( in_array( 'IGNORE', $insertOptions ) ) {
00662                         $this->ignore_DUP_VAL_ON_INDEX = true;
00663                 }
00664 
00665                 $retval = $this->query( $sql, $fname );
00666 
00667                 if ( in_array( 'IGNORE', $insertOptions ) ) {
00668                         $this->ignore_DUP_VAL_ON_INDEX = false;
00669                 }
00670 
00671                 return $retval;
00672         }
00673 
00674         function tableName( $name, $format = 'quoted' ) {
00675                 /*
00676                 Replace reserved words with better ones
00677                 Using uppercase because that's the only way Oracle can handle
00678                 quoted tablenames
00679                 */
00680                 switch( $name ) {
00681                         case 'user':
00682                                 $name = 'MWUSER';
00683                                 break;
00684                         case 'text':
00685                                 $name = 'PAGECONTENT';
00686                                 break;
00687                 }
00688 
00689                 return parent::tableName( strtoupper( $name ), $format );
00690         }
00691 
00692         function tableNameInternal( $name ) {
00693                 $name = $this->tableName( $name );
00694                 return preg_replace( '/.*\.(.*)/', '$1', $name);
00695         }
00700         function nextSequenceValue( $seqName ) {
00701                 $res = $this->query( "SELECT $seqName.nextval FROM dual" );
00702                 $row = $this->fetchRow( $res );
00703                 $this->mInsertId = $row[0];
00704                 return $this->mInsertId;
00705         }
00706 
00711         private function getSequenceData( $table ) {
00712                 if ( $this->sequenceData == null ) {
00713                         $result = $this->doQuery( "SELECT lower(asq.sequence_name),
00714                                    lower(atc.table_name),
00715                                    lower(atc.column_name)
00716                           FROM all_sequences asq, all_tab_columns atc
00717                          WHERE decode(atc.table_name, '{$this->mTablePrefix}MWUSER', '{$this->mTablePrefix}USER', atc.table_name) || '_' ||
00718                                    atc.column_name || '_SEQ' = '{$this->mTablePrefix}' || asq.sequence_name
00719                            AND asq.sequence_owner = upper('{$this->mDBname}')
00720                            AND atc.owner = upper('{$this->mDBname}')" );
00721 
00722                         while ( ( $row = $result->fetchRow() ) !== false ) {
00723                                 $this->sequenceData[$row[1]] = array(
00724                                         'sequence' => $row[0],
00725                                         'column' => $row[2]
00726                                 );
00727                         }
00728                 }
00729                 $table = strtolower( $this->removeIdentifierQuotes( $this->tableName( $table ) ) );
00730                 return ( isset( $this->sequenceData[$table] ) ) ? $this->sequenceData[$table] : false;
00731         }
00732 
00733         # Returns the size of a text field, or -1 for "unlimited"
00734         function textFieldSize( $table, $field ) {
00735                 $fieldInfoData = $this->fieldInfo( $table, $field );
00736                 return $fieldInfoData->maxLength();
00737         }
00738 
00739         function limitResult( $sql, $limit, $offset = false ) {
00740                 if ( $offset === false ) {
00741                         $offset = 0;
00742                 }
00743                 return "SELECT * FROM ($sql) WHERE rownum >= (1 + $offset) AND rownum < (1 + $limit + $offset)";
00744         }
00745 
00746         function encodeBlob( $b ) {
00747                 return new Blob( $b );
00748         }
00749 
00750         function decodeBlob( $b ) {
00751                 if ( $b instanceof Blob ) {
00752                         $b = $b->fetch();
00753                 }
00754                 return $b;
00755         }
00756 
00757         function unionQueries( $sqls, $all ) {
00758                 $glue = ' UNION ALL ';
00759                 return 'SELECT * ' . ( $all ? '':'/* UNION_UNIQUE */ ' ) . 'FROM (' . implode( $glue, $sqls ) . ')';
00760         }
00761 
00762         function wasDeadlock() {
00763                 return $this->lastErrno() == 'OCI-00060';
00764         }
00765 
00766         function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = 'DatabaseOracle::duplicateTableStructure' ) {
00767                 $temporary = $temporary ? 'TRUE' : 'FALSE';
00768 
00769                 $newName = strtoupper( $newName );
00770                 $oldName = strtoupper( $oldName );
00771 
00772                 $tabName = substr( $newName, strlen( $this->mTablePrefix ) );
00773                 $oldPrefix = substr( $oldName, 0, strlen( $oldName ) - strlen( $tabName ) );
00774                 $newPrefix = strtoupper( $this->mTablePrefix );
00775 
00776                 return $this->doQuery( "BEGIN DUPLICATE_TABLE( '$tabName', '$oldPrefix', '$newPrefix', $temporary ); END;" );
00777         }
00778 
00779         function listTables( $prefix = null, $fname = 'DatabaseOracle::listTables' ) {
00780                 $listWhere = '';
00781                 if ( !empty( $prefix ) ) {
00782                         $listWhere = ' AND table_name LIKE \'' . strtoupper( $prefix ) . '%\'';
00783                 }
00784 
00785                 $owner = strtoupper( $this->mDBname );
00786                 $result = $this->doQuery( "SELECT table_name FROM all_tables WHERE owner='$owner' AND table_name NOT LIKE '%!_IDX\$_' ESCAPE '!' $listWhere" );
00787 
00788                 // dirty code ... i know
00789                 $endArray = array();
00790                 $endArray[] = strtoupper( $prefix . 'MWUSER' );
00791                 $endArray[] = strtoupper( $prefix . 'PAGE' );
00792                 $endArray[] = strtoupper( $prefix . 'IMAGE' );
00793                 $fixedOrderTabs = $endArray;
00794                 while ( ($row = $result->fetchRow()) !== false ) {
00795                         if ( !in_array( $row['table_name'], $fixedOrderTabs ) )
00796                                 $endArray[] = $row['table_name'];
00797                 }
00798 
00799                 return $endArray;
00800         }
00801 
00802         public function dropTable( $tableName, $fName = 'DatabaseOracle::dropTable' ) {
00803                 $tableName = $this->tableName( $tableName );
00804                 if( !$this->tableExists( $tableName ) ) {
00805                         return false;
00806                 }
00807 
00808                 return $this->doQuery( "DROP TABLE $tableName CASCADE CONSTRAINTS PURGE" );
00809         }
00810 
00811         function timestamp( $ts = 0 ) {
00812                 return wfTimestamp( TS_ORACLE, $ts );
00813         }
00814 
00818         public function aggregateValue( $valuedata, $valuename = 'value' ) {
00819                 return $valuedata;
00820         }
00821 
00822         function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
00823                 # Ignore errors during error handling to avoid infinite
00824                 # recursion
00825                 $ignore = $this->ignoreErrors( true );
00826                 ++$this->mErrorCount;
00827 
00828                 if ( $ignore || $tempIgnore ) {
00829                         wfDebug( "SQL ERROR (ignored): $error\n" );
00830                         $this->ignoreErrors( $ignore );
00831                 } else {
00832                         throw new DBQueryError( $this, $error, $errno, $sql, $fname );
00833                 }
00834         }
00835 
00839         public static function getSoftwareLink() {
00840                 return '[http://www.oracle.com/ Oracle]';
00841         }
00842 
00846         function getServerVersion() {
00847                 //better version number, fallback on driver
00848                 $rset = $this->doQuery( 'SELECT version FROM product_component_version WHERE UPPER(product) LIKE \'ORACLE DATABASE%\'' );
00849                 if ( !( $row = $rset->fetchRow() ) ) {
00850                         return oci_server_version( $this->mConn );
00851                 }
00852                 return $row['version'];
00853         }
00854 
00859         function indexExists( $table, $index, $fname = 'DatabaseOracle::indexExists' ) {
00860                 $table = $this->tableName( $table );
00861                 $table = strtoupper( $this->removeIdentifierQuotes( $table ) );
00862                 $index = strtoupper( $index );
00863                 $owner = strtoupper( $this->mDBname );
00864                 $SQL = "SELECT 1 FROM all_indexes WHERE owner='$owner' AND index_name='{$table}_{$index}'";
00865                 $res = $this->doQuery( $SQL );
00866                 if ( $res ) {
00867                         $count = $res->numRows();
00868                         $res->free();
00869                 } else {
00870                         $count = 0;
00871                 }
00872                 return $count != 0;
00873         }
00874 
00879         function tableExists( $table, $fname = __METHOD__ ) {
00880                 $table = $this->tableName( $table );
00881                 $table = $this->addQuotes( strtoupper( $this->removeIdentifierQuotes( $table ) ) );
00882                 $owner = $this->addQuotes( strtoupper( $this->mDBname ) );
00883                 $SQL = "SELECT 1 FROM all_tables WHERE owner=$owner AND table_name=$table";
00884                 $res = $this->doQuery( $SQL );
00885                 if ( $res ) {
00886                         $count = $res->numRows();
00887                         $res->free();
00888                 } else {
00889                         $count = 0;
00890                 }
00891                 return $count;
00892         }
00893 
00904         private function fieldInfoMulti( $table, $field ) {
00905                 $field = strtoupper( $field );
00906                 if ( is_array( $table ) ) {
00907                         $table = array_map( array( &$this, 'tableNameInternal' ), $table );
00908                         $tableWhere = 'IN (';
00909                         foreach( $table as &$singleTable ) {
00910                                 $singleTable = $this->removeIdentifierQuotes( $singleTable );
00911                                 if ( isset( $this->mFieldInfoCache["$singleTable.$field"] ) ) {
00912                                         return $this->mFieldInfoCache["$singleTable.$field"];
00913                                 }
00914                                 $tableWhere .= '\'' . $singleTable . '\',';
00915                         }
00916                         $tableWhere = rtrim( $tableWhere, ',' ) . ')';
00917                 } else {
00918                         $table = $this->removeIdentifierQuotes( $this->tableNameInternal( $table ) );
00919                         if ( isset( $this->mFieldInfoCache["$table.$field"] ) ) {
00920                                 return $this->mFieldInfoCache["$table.$field"];
00921                         }
00922                         $tableWhere = '= \''.$table.'\'';
00923                 }
00924 
00925                 $fieldInfoStmt = oci_parse( $this->mConn, 'SELECT * FROM wiki_field_info_full WHERE table_name ' . $tableWhere . ' and column_name = \'' . $field . '\'' );
00926                 if ( oci_execute( $fieldInfoStmt, $this->execFlags() ) === false ) {
00927                         $e = oci_error( $fieldInfoStmt );
00928                         $this->reportQueryError( $e['message'], $e['code'], 'fieldInfo QUERY', __METHOD__ );
00929                         return false;
00930                 }
00931                 $res = new ORAResult( $this, $fieldInfoStmt );
00932                 if ( $res->numRows() == 0 ) {
00933                         if ( is_array( $table ) ) {
00934                                 foreach( $table as &$singleTable ) {
00935                                         $this->mFieldInfoCache["$singleTable.$field"] = false;
00936                                 }
00937                         } else {
00938                                 $this->mFieldInfoCache["$table.$field"] = false;
00939                         }
00940                         $fieldInfoTemp = null;
00941                 } else {
00942                         $fieldInfoTemp = new ORAField( $res->fetchRow() );
00943                         $table = $fieldInfoTemp->tableName();
00944                         $this->mFieldInfoCache["$table.$field"] = $fieldInfoTemp;
00945                 }
00946                 $res->free();
00947                 return $fieldInfoTemp;
00948         }
00949 
00956         function fieldInfo( $table, $field ) {
00957                 if ( is_array( $table ) ) {
00958                         throw new DBUnexpectedError( $this, 'DatabaseOracle::fieldInfo called with table array!' );
00959                 }
00960                 return $this->fieldInfoMulti( $table, $field );
00961         }
00962 
00963         protected function doBegin( $fname = 'DatabaseOracle::begin' ) {
00964                 $this->mTrxLevel = 1;
00965                 $this->doQuery( 'SET CONSTRAINTS ALL DEFERRED' );
00966         }
00967 
00968         protected function doCommit( $fname = 'DatabaseOracle::commit' ) {
00969                 if ( $this->mTrxLevel ) {
00970                         $ret = oci_commit( $this->mConn );
00971                         if ( !$ret ) {
00972                                 throw new DBUnexpectedError( $this, $this->lastError() );
00973                         }
00974                         $this->mTrxLevel = 0;
00975                         $this->doQuery( 'SET CONSTRAINTS ALL IMMEDIATE' );
00976                 }
00977         }
00978 
00979         protected function doRollback( $fname = 'DatabaseOracle::rollback' ) {
00980                 if ( $this->mTrxLevel ) {
00981                         oci_rollback( $this->mConn );
00982                         $this->mTrxLevel = 0;
00983                         $this->doQuery( 'SET CONSTRAINTS ALL IMMEDIATE' );
00984                 }
00985         }
00986 
00987         /* defines must comply with ^define\s*([^\s=]*)\s*=\s?'\{\$([^\}]*)\}'; */
00988         function sourceStream( $fp, $lineCallback = false, $resultCallback = false,
00989                 $fname = 'DatabaseOracle::sourceStream', $inputCallback = false ) {
00990                 $cmd = '';
00991                 $done = false;
00992                 $dollarquote = false;
00993 
00994                 $replacements = array();
00995 
00996                 while ( ! feof( $fp ) ) {
00997                         if ( $lineCallback ) {
00998                                 call_user_func( $lineCallback );
00999                         }
01000                         $line = trim( fgets( $fp, 1024 ) );
01001                         $sl = strlen( $line ) - 1;
01002 
01003                         if ( $sl < 0 ) {
01004                                 continue;
01005                         }
01006                         if ( '-' == $line { 0 } && '-' == $line { 1 } ) {
01007                                 continue;
01008                         }
01009 
01010                         // Allow dollar quoting for function declarations
01011                         if ( substr( $line, 0, 8 ) == '/*$mw$*/' ) {
01012                                 if ( $dollarquote ) {
01013                                         $dollarquote = false;
01014                                         $line = str_replace( '/*$mw$*/', '', $line ); // remove dollarquotes
01015                                         $done = true;
01016                                 } else {
01017                                         $dollarquote = true;
01018                                 }
01019                         } elseif ( !$dollarquote ) {
01020                                 if ( ';' == $line { $sl } && ( $sl < 2 || ';' != $line { $sl - 1 } ) ) {
01021                                         $done = true;
01022                                         $line = substr( $line, 0, $sl );
01023                                 }
01024                         }
01025 
01026                         if ( $cmd != '' ) {
01027                                 $cmd .= ' ';
01028                         }
01029                         $cmd .= "$line\n";
01030 
01031                         if ( $done ) {
01032                                 $cmd = str_replace( ';;', ";", $cmd );
01033                                 if ( strtolower( substr( $cmd, 0, 6 ) ) == 'define' ) {
01034                                         if ( preg_match( '/^define\s*([^\s=]*)\s*=\s*\'\{\$([^\}]*)\}\'/', $cmd, $defines ) ) {
01035                                                 $replacements[$defines[2]] = $defines[1];
01036                                         }
01037                                 } else {
01038                                         foreach ( $replacements as $mwVar => $scVar ) {
01039                                                 $cmd = str_replace( '&' . $scVar . '.', '`{$' . $mwVar . '}`', $cmd );
01040                                         }
01041 
01042                                         $cmd = $this->replaceVars( $cmd );
01043                                         if ( $inputCallback ) {
01044                                                 call_user_func( $inputCallback, $cmd );
01045                                         }
01046                                         $res = $this->doQuery( $cmd );
01047                                         if ( $resultCallback ) {
01048                                                 call_user_func( $resultCallback, $res, $this );
01049                                         }
01050 
01051                                         if ( false === $res ) {
01052                                                 $err = $this->lastError();
01053                                                 return "Query \"{$cmd}\" failed with error code \"$err\".\n";
01054                                         }
01055                                 }
01056 
01057                                 $cmd = '';
01058                                 $done = false;
01059                         }
01060                 }
01061                 return true;
01062         }
01063 
01064         function selectDB( $db ) {
01065                 $this->mDBname = $db;
01066                 if ( $db == null || $db == $this->mUser ) {
01067                         return true;
01068                 }
01069                 $sql = 'ALTER SESSION SET CURRENT_SCHEMA=' . strtoupper( $db );
01070                 $stmt = oci_parse( $this->mConn, $sql );
01071                 wfSuppressWarnings();
01072                 $success = oci_execute( $stmt );
01073                 wfRestoreWarnings();
01074                 if ( !$success ) {
01075                         $e = oci_error( $stmt );
01076                         if ( $e['code'] != '1435' ) {
01077                                 $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
01078                         }
01079                         return false;
01080                 }
01081                 return true;
01082         }
01083 
01084         function strencode( $s ) {
01085                 return str_replace( "'", "''", $s );
01086         }
01087 
01088         function addQuotes( $s ) {
01089                 global $wgContLang;
01090                 if ( isset( $wgContLang->mLoaded ) && $wgContLang->mLoaded ) {
01091                         $s = $wgContLang->checkTitleEncoding( $s );
01092                 }
01093                 return "'" . $this->strencode( $s ) . "'";
01094         }
01095 
01096         public function addIdentifierQuotes( $s ) {
01097                 if ( !$this->getFlag( DBO_DDLMODE ) ) {
01098                         $s = '/*Q*/' . $s;
01099                 }
01100                 return $s;
01101         }
01102 
01103         public function removeIdentifierQuotes( $s ) {
01104                 return strpos( $s, '/*Q*/' ) === false ? $s : substr( $s, 5 );
01105         }
01106 
01107         public function isQuotedIdentifier( $s ) {
01108                 return strpos( $s, '/*Q*/' ) !== false;
01109         }
01110 
01111         private function wrapFieldForWhere( $table, &$col, &$val ) {
01112                 global $wgContLang;
01113 
01114                 $col_info = $this->fieldInfoMulti( $table, $col );
01115                 $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
01116                 if ( $col_type == 'CLOB' ) {
01117                         $col = 'TO_CHAR(' . $col . ')';
01118                         $val = $wgContLang->checkTitleEncoding( $val );
01119                 } elseif ( $col_type == 'VARCHAR2' ) {
01120                         $val = $wgContLang->checkTitleEncoding( $val );
01121                 }
01122         }
01123 
01124         private function wrapConditionsForWhere ( $table, $conds, $parentCol = null ) {
01125                 $conds2 = array();
01126                 foreach ( $conds as $col => $val ) {
01127                         if ( is_array( $val ) ) {
01128                                 $conds2[$col] = $this->wrapConditionsForWhere ( $table, $val, $col );
01129                         } else {
01130                                 if ( is_numeric( $col ) && $parentCol != null ) {
01131                                         $this->wrapFieldForWhere ( $table, $parentCol, $val );
01132                                 } else {
01133                                         $this->wrapFieldForWhere ( $table, $col, $val );
01134                                 }
01135                                 $conds2[$col] = $val;
01136                         }
01137                 }
01138                 return $conds2;
01139         }
01140 
01141         function selectRow( $table, $vars, $conds, $fname = 'DatabaseOracle::selectRow', $options = array(), $join_conds = array() ) {
01142                 if ( is_array( $conds ) ) {
01143                         $conds = $this->wrapConditionsForWhere( $table, $conds );
01144                 }
01145                 return parent::selectRow( $table, $vars, $conds, $fname, $options, $join_conds );
01146         }
01147 
01158         function makeSelectOptions( $options ) {
01159                 $preLimitTail = $postLimitTail = '';
01160                 $startOpts = '';
01161 
01162                 $noKeyOptions = array();
01163                 foreach ( $options as $key => $option ) {
01164                         if ( is_numeric( $key ) ) {
01165                                 $noKeyOptions[$option] = true;
01166                         }
01167                 }
01168 
01169                 $preLimitTail .= $this->makeGroupByWithHaving( $options );
01170 
01171                 $preLimitTail .= $this->makeOrderBy( $options );
01172 
01173                 if ( isset( $noKeyOptions['FOR UPDATE'] ) ) {
01174                         $postLimitTail .= ' FOR UPDATE';
01175                 }
01176 
01177                 if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) {
01178                         $startOpts .= 'DISTINCT';
01179                 }
01180 
01181                 if ( isset( $options['USE INDEX'] ) && ! is_array( $options['USE INDEX'] ) ) {
01182                         $useIndex = $this->useIndexClause( $options['USE INDEX'] );
01183                 } else {
01184                         $useIndex = '';
01185                 }
01186 
01187                 return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail );
01188         }
01189 
01190         public function delete( $table, $conds, $fname = 'DatabaseOracle::delete' ) {
01191                 if ( is_array( $conds ) ) {
01192                         $conds = $this->wrapConditionsForWhere( $table, $conds );
01193                 }
01194                 // a hack for deleting pages, users and images (which have non-nullable FKs)
01195                 // all deletions on these tables have transactions so final failure rollbacks these updates
01196                 $table = $this->tableName( $table );
01197                 if ( $table == $this->tableName( 'user' ) ) {
01198                                 $this->update( 'archive', array( 'ar_user' => 0 ), array( 'ar_user' => $conds['user_id'] ), $fname );
01199                                 $this->update( 'ipblocks', array( 'ipb_user' => 0 ), array( 'ipb_user' => $conds['user_id'] ), $fname );
01200                                 $this->update( 'image', array( 'img_user' => 0 ), array( 'img_user' => $conds['user_id'] ), $fname );
01201                                 $this->update( 'oldimage', array( 'oi_user' => 0 ), array( 'oi_user' => $conds['user_id'] ), $fname );
01202                                 $this->update( 'filearchive', array( 'fa_deleted_user' => 0 ), array( 'fa_deleted_user' => $conds['user_id'] ), $fname );
01203                                 $this->update( 'filearchive', array( 'fa_user' => 0 ), array( 'fa_user' => $conds['user_id'] ), $fname );
01204                                 $this->update( 'uploadstash', array( 'us_user' => 0 ), array( 'us_user' => $conds['user_id'] ), $fname );
01205                                 $this->update( 'recentchanges', array( 'rc_user' => 0 ), array( 'rc_user' => $conds['user_id'] ), $fname );
01206                                 $this->update( 'logging', array( 'log_user' => 0 ), array( 'log_user' => $conds['user_id'] ), $fname );
01207                 } elseif ( $table == $this->tableName( 'image' ) ) {
01208                                 $this->update( 'oldimage', array( 'oi_name' => 0 ), array( 'oi_name' => $conds['img_name'] ), $fname );
01209                 }
01210                 return parent::delete( $table, $conds, $fname );
01211         }
01212 
01213         function update( $table, $values, $conds, $fname = 'DatabaseOracle::update', $options = array() ) {
01214                 global $wgContLang;
01215 
01216                 $table = $this->tableName( $table );
01217                 $opts = $this->makeUpdateOptions( $options );
01218                 $sql = "UPDATE $opts $table SET ";
01219 
01220                 $first = true;
01221                 foreach ( $values as $col => &$val ) {
01222                         $sqlSet = $this->fieldBindStatement( $table, $col, $val, true );
01223 
01224                         if ( !$first ) {
01225                                 $sqlSet = ', ' . $sqlSet;
01226                         } else {
01227                                 $first = false;
01228                         }
01229                         $sql .= $sqlSet;
01230                 }
01231 
01232                 if ( $conds !== array() && $conds !== '*' ) {
01233                         $conds = $this->wrapConditionsForWhere( $table, $conds );
01234                         $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
01235                 }
01236 
01237                 if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) {
01238                         $e = oci_error( $this->mConn );
01239                         $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
01240                         return false;
01241                 }
01242                 foreach ( $values as $col => &$val ) {
01243                         $col_info = $this->fieldInfoMulti( $table, $col );
01244                         $col_type = $col_info != false ? $col_info->type() : 'CONSTANT';
01245 
01246                         if ( $val === null ) {
01247                                 // do nothing ... null was inserted in statement creation
01248                         } elseif ( $col_type != 'BLOB' && $col_type != 'CLOB' ) {
01249                                 if ( is_object( $val ) ) {
01250                                         $val = $val->getData();
01251                                 }
01252 
01253                                 if ( preg_match( '/^timestamp.*/i', $col_type ) == 1 && strtolower( $val ) == 'infinity' ) {
01254                                         $val = '31-12-2030 12:00:00.000000';
01255                                 }
01256 
01257                                 $val = ( $wgContLang != null ) ? $wgContLang->checkTitleEncoding( $val ) : $val;
01258                                 if ( oci_bind_by_name( $stmt, ":$col", $val ) === false ) {
01259                                         $e = oci_error( $stmt );
01260                                         $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
01261                                         return false;
01262                                 }
01263                         } else {
01264                                 if ( ( $lob[$col] = oci_new_descriptor( $this->mConn, OCI_D_LOB ) ) === false ) {
01265                                         $e = oci_error( $stmt );
01266                                         throw new DBUnexpectedError( $this, "Cannot create LOB descriptor: " . $e['message'] );
01267                                 }
01268 
01269                                 if ( $col_type == 'BLOB' ) {
01270                                         $lob[$col]->writeTemporary( $val );
01271                                         oci_bind_by_name( $stmt, ":$col", $lob[$col], - 1, SQLT_BLOB );
01272                                 } else {
01273                                         $lob[$col]->writeTemporary( $val );
01274                                         oci_bind_by_name( $stmt, ":$col", $lob[$col], - 1, OCI_B_CLOB );
01275                                 }
01276                         }
01277                 }
01278 
01279                 wfSuppressWarnings();
01280 
01281                 if ( oci_execute( $stmt, $this->execFlags() ) === false ) {
01282                         $e = oci_error( $stmt );
01283                         if ( !$this->ignore_DUP_VAL_ON_INDEX || $e['code'] != '1' ) {
01284                                 $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
01285                                 return false;
01286                         } else {
01287                                 $this->mAffectedRows = oci_num_rows( $stmt );
01288                         }
01289                 } else {
01290                         $this->mAffectedRows = oci_num_rows( $stmt );
01291                 }
01292 
01293                 wfRestoreWarnings();
01294 
01295                 if ( isset( $lob ) ) {
01296                         foreach ( $lob as $lob_v ) {
01297                                 $lob_v->free();
01298                         }
01299                 }
01300 
01301                 if ( !$this->mTrxLevel ) {
01302                         oci_commit( $this->mConn );
01303                 }
01304 
01305                 oci_free_statement( $stmt );
01306         }
01307 
01308         function bitNot( $field ) {
01309                 // expecting bit-fields smaller than 4bytes
01310                 return 'BITNOT(' . $field . ')';
01311         }
01312 
01313         function bitAnd( $fieldLeft, $fieldRight ) {
01314                 return 'BITAND(' . $fieldLeft . ', ' . $fieldRight . ')';
01315         }
01316 
01317         function bitOr( $fieldLeft, $fieldRight ) {
01318                 return 'BITOR(' . $fieldLeft . ', ' . $fieldRight . ')';
01319         }
01320 
01321         function setFakeMaster( $enabled = true ) {
01322         }
01323 
01324         function getDBname() {
01325                 return $this->mDBname;
01326         }
01327 
01328         function getServer() {
01329                 return $this->mServer;
01330         }
01331 
01332         public function getSearchEngine() {
01333                 return 'SearchOracle';
01334         }
01335 
01336         public function getInfinity() {
01337                 return '31-12-2030 12:00:00.000000';
01338         }
01339 
01340 } // end DatabaseOracle class