Index: trunk/phase3/includes/db/DatabaseOracle.php |
— | — | @@ -44,10 +44,10 @@ |
45 | 45 | $array_out[] = $item; |
46 | 46 | } |
47 | 47 | } |
48 | | - |
| 48 | + |
49 | 49 | return $array_out; |
50 | 50 | } |
51 | | - |
| 51 | + |
52 | 52 | function __construct( &$db, $stmt, $unique = false ) { |
53 | 53 | $this->db =& $db; |
54 | 54 | |
— | — | @@ -132,7 +132,7 @@ |
133 | 133 | $this->is_key = ( $this->is_pk || $this->is_unique || $this->is_multiple ); |
134 | 134 | $this->type = $info['data_type']; |
135 | 135 | } |
136 | | - |
| 136 | + |
137 | 137 | function name() { |
138 | 138 | return $this->name; |
139 | 139 | } |
— | — | @@ -152,7 +152,7 @@ |
153 | 153 | function nullable() { |
154 | 154 | return $this->nullable; |
155 | 155 | } |
156 | | - |
| 156 | + |
157 | 157 | function isKey() { |
158 | 158 | return $this->is_key; |
159 | 159 | } |
— | — | @@ -182,6 +182,8 @@ |
183 | 183 | |
184 | 184 | var $defaultCharset = 'AL32UTF8'; |
185 | 185 | |
| 186 | + var $mFileInfoCache = array(); |
| 187 | + |
186 | 188 | function __construct( $server = false, $user = false, $password = false, $dbName = false, |
187 | 189 | $failFunction = false, $flags = 0, $tablePrefix = 'get from global' ) |
188 | 190 | { |
— | — | @@ -251,7 +253,7 @@ |
252 | 254 | } |
253 | 255 | |
254 | 256 | $this->mOpened = true; |
255 | | - |
| 257 | + |
256 | 258 | # removed putenv calls because they interfere with the system globaly |
257 | 259 | $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' ); |
258 | 260 | $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' ); |
— | — | @@ -296,10 +298,10 @@ |
297 | 299 | error_reporting( $olderr ); |
298 | 300 | |
299 | 301 | $sql = preg_replace( '/^EXPLAIN /', 'EXPLAIN PLAN SET STATEMENT_ID = \'' . $explain_id . '\' FOR', $sql, 1, $explain_count ); |
300 | | - |
301 | | - |
| 302 | + |
| 303 | + |
302 | 304 | $olderr = error_reporting( E_ERROR ); |
303 | | - |
| 305 | + |
304 | 306 | if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) { |
305 | 307 | $e = oci_error( $this->mConn ); |
306 | 308 | $this->reportQueryError( $e['message'], $e['code'], $sql, __FUNCTION__ ); |
— | — | @@ -465,7 +467,7 @@ |
466 | 468 | } else { |
467 | 469 | $sql .= $val !== null ? ', :' . $col : ', NULL'; |
468 | 470 | } |
469 | | - |
| 471 | + |
470 | 472 | $first = false; |
471 | 473 | } |
472 | 474 | $sql .= ')'; |
— | — | @@ -484,7 +486,7 @@ |
485 | 487 | if ( preg_match( '/^timestamp.*/i', $col_type ) == 1 && strtolower( $val ) == 'infinity' ) { |
486 | 488 | $val = '31-12-2030 12:00:00.000000'; |
487 | 489 | } |
488 | | - |
| 490 | + |
489 | 491 | $val = ( $wgLang != null ) ? $wgLang->checkTitleEncoding( $val ) : $val; |
490 | 492 | if ( oci_bind_by_name( $stmt, ":$col", $val ) === false ) { |
491 | 493 | $this->reportQueryError( $this->lastErrno(), $this->lastError(), $sql, __METHOD__ ); |
— | — | @@ -508,7 +510,7 @@ |
509 | 511 | $olderr = error_reporting( E_ERROR ); |
510 | 512 | if ( oci_execute( $stmt, OCI_DEFAULT ) === false ) { |
511 | 513 | $e = oci_error( $stmt ); |
512 | | - |
| 514 | + |
513 | 515 | if ( !$this->ignore_DUP_VAL_ON_INDEX || $e['code'] != '1' ) { |
514 | 516 | $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ ); |
515 | 517 | } else { |
— | — | @@ -518,13 +520,13 @@ |
519 | 521 | $this->mAffectedRows = oci_num_rows( $stmt ); |
520 | 522 | } |
521 | 523 | error_reporting( $olderr ); |
522 | | - |
| 524 | + |
523 | 525 | if ( isset( $lob ) ) { |
524 | 526 | foreach ( $lob as $lob_i => $lob_v ) { |
525 | 527 | $lob_v->free(); |
526 | 528 | } |
527 | 529 | } |
528 | | - |
| 530 | + |
529 | 531 | if ( !$this->mTrxLevel ) { |
530 | 532 | oci_commit( $this->mConn ); |
531 | 533 | } |
— | — | @@ -545,17 +547,17 @@ |
546 | 548 | } else { |
547 | 549 | $srcTable = $this->tableName( $srcTable ); |
548 | 550 | } |
549 | | - |
| 551 | + |
550 | 552 | if ( ( $sequenceData = $this->getSequenceData( $destTable ) ) !== false && |
551 | 553 | !isset( $varMap[$sequenceData['column']] ) ) |
552 | 554 | $varMap[$sequenceData['column']] = 'GET_SEQUENCE_VALUE(\'' . $sequenceData['sequence'] . '\')'; |
553 | | - |
| 555 | + |
554 | 556 | // count-alias subselect fields to avoid abigious definition errors |
555 | 557 | $i = 0; |
556 | 558 | foreach ( $varMap as $key => &$val ) { |
557 | 559 | $val = $val . ' field' . ( $i++ ); |
558 | 560 | } |
559 | | - |
| 561 | + |
560 | 562 | $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' . |
561 | 563 | " SELECT $startOpts " . implode( ',', $varMap ) . |
562 | 564 | " FROM $srcTable $useIndex "; |
— | — | @@ -563,13 +565,13 @@ |
564 | 566 | $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND ); |
565 | 567 | } |
566 | 568 | $sql .= " $tailOpts"; |
567 | | - |
| 569 | + |
568 | 570 | if ( in_array( 'IGNORE', $insertOptions ) ) { |
569 | 571 | $this->ignore_DUP_VAL_ON_INDEX = true; |
570 | 572 | } |
571 | | - |
| 573 | + |
572 | 574 | $retval = $this->query( $sql, $fname ); |
573 | | - |
| 575 | + |
574 | 576 | if ( in_array( 'IGNORE', $insertOptions ) ) { |
575 | 577 | $this->ignore_DUP_VAL_ON_INDEX = false; |
576 | 578 | } |
— | — | @@ -581,7 +583,7 @@ |
582 | 584 | global $wgSharedDB, $wgSharedPrefix, $wgSharedTables; |
583 | 585 | /* |
584 | 586 | Replace reserved words with better ones |
585 | | - Using uppercase because that's the only way Oracle can handle |
| 587 | + Using uppercase because that's the only way Oracle can handle |
586 | 588 | quoted tablenames |
587 | 589 | */ |
588 | 590 | switch( $name ) { |
— | — | @@ -612,7 +614,7 @@ |
613 | 615 | } |
614 | 616 | |
615 | 617 | $prefix = $this->mTablePrefix; |
616 | | - |
| 618 | + |
617 | 619 | if ( isset( $database ) ) { |
618 | 620 | $table = ( $table[0] == '`' ? $table : "`{$table}`" ); |
619 | 621 | } |
— | — | @@ -653,7 +655,7 @@ |
654 | 656 | function getSequenceData( $table ) { |
655 | 657 | if ( $this->sequenceData == null ) { |
656 | 658 | $result = $this->query( "SELECT lower(us.sequence_name), lower(utc.table_name), lower(utc.column_name) from user_sequences us, user_tab_columns utc where us.sequence_name = utc.table_name||'_'||utc.column_name||'_SEQ'" ); |
657 | | - |
| 659 | + |
658 | 660 | while ( ( $row = $result->fetchRow() ) !== false ) { |
659 | 661 | $this->sequenceData[$this->tableName( $row[1] )] = array( |
660 | 662 | 'sequence' => $row[0], |
— | — | @@ -664,7 +666,7 @@ |
665 | 667 | |
666 | 668 | return ( isset( $this->sequenceData[$table] ) ) ? $this->sequenceData[$table] : false; |
667 | 669 | } |
668 | | - |
| 670 | + |
669 | 671 | # REPLACE query wrapper |
670 | 672 | # Oracle simulates this with a DELETE followed by INSERT |
671 | 673 | # $row is the row to insert, an associative array |
— | — | @@ -851,7 +853,11 @@ |
852 | 854 | * based on prebuilt table to simulate MySQL field info and keep query speed minimal |
853 | 855 | */ |
854 | 856 | function fieldExists( $table, $field, $fname = 'DatabaseOracle::fieldExists' ) { |
855 | | - if ( !isset( $this->fieldInfo_stmt ) ) { |
| 857 | + $table = trim( $table, '"' ); |
| 858 | + |
| 859 | + if (isset($this->mFileInfoCache[$table.'.'.$field])) { |
| 860 | + return true; |
| 861 | + } elseif ( !isset( $this->fieldInfo_stmt ) ) { |
856 | 862 | $this->fieldInfo_stmt = oci_parse( $this->mConn, 'SELECT * FROM wiki_field_info_full WHERE table_name = upper(:tab) and column_name = UPPER(:col)' ); |
857 | 863 | } |
858 | 864 | |
— | — | @@ -864,15 +870,23 @@ |
865 | 871 | return false; |
866 | 872 | } |
867 | 873 | $res = new ORAResult( $this, $this->fieldInfo_stmt ); |
868 | | - return $res->numRows() != 0; |
| 874 | + if ($res->numRows() != 0) { |
| 875 | + $this->mFileInfoCache[$table.'.'.$field] = new ORAField( $res->fetchRow() ); |
| 876 | + return true; |
| 877 | + } else { |
| 878 | + return false; |
| 879 | + } |
869 | 880 | } |
870 | 881 | |
871 | 882 | function fieldInfo( $table, $field ) { |
872 | | - if ( !isset( $this->fieldInfo_stmt ) ) { |
| 883 | + $table = trim( $table, '"' ); |
| 884 | + |
| 885 | + if (isset($this->mFileInfoCache[$table.'.'.$field])) { |
| 886 | + return $this->mFileInfoCache[$table.'.'.$field]; |
| 887 | + } elseif ( !isset( $this->fieldInfo_stmt ) ) { |
873 | 888 | $this->fieldInfo_stmt = oci_parse( $this->mConn, 'SELECT * FROM wiki_field_info_full WHERE table_name = upper(:tab) and column_name = UPPER(:col)' ); |
874 | 889 | } |
875 | 890 | |
876 | | - $table = trim( $table, '"' ); |
877 | 891 | oci_bind_by_name( $this->fieldInfo_stmt, ':tab', $table ); |
878 | 892 | oci_bind_by_name( $this->fieldInfo_stmt, ':col', $field ); |
879 | 893 | |
— | — | @@ -882,7 +896,8 @@ |
883 | 897 | return false; |
884 | 898 | } |
885 | 899 | $res = new ORAResult( $this, $this->fieldInfo_stmt ); |
886 | | - return new ORAField( $res->fetchRow() ); |
| 900 | + $this->mFileInfoCache[$table.'.'.$field] = new ORAField( $res->fetchRow() ); |
| 901 | + return $this->mFileInfoCache[$table.'.'.$field]; |
887 | 902 | } |
888 | 903 | |
889 | 904 | function begin( $fname = '' ) { |
— | — | @@ -908,7 +923,7 @@ |
909 | 924 | $cmd = ''; |
910 | 925 | $done = false; |
911 | 926 | $dollarquote = false; |
912 | | - |
| 927 | + |
913 | 928 | $replacements = array(); |
914 | 929 | |
915 | 930 | while ( ! feof( $fp ) ) { |
— | — | @@ -1155,7 +1170,7 @@ |
1156 | 1171 | function getServer() { |
1157 | 1172 | return $this->mServer; |
1158 | 1173 | } |
1159 | | - |
| 1174 | + |
1160 | 1175 | public function replaceVars( $ins ) { |
1161 | 1176 | $varnames = array( 'wgDBprefix' ); |
1162 | 1177 | if ( $this->mFlags & DBO_SYSDBA ) { |