55 if ( $p[
'tablePrefix'] ==
'get from global' ) {
58 $p[
'tablePrefix'] = strtoupper( $p[
'tablePrefix'] );
59 parent::__construct( $p );
60 Hooks::run(
'DatabaseOraclePostInit', [ $this ] );
64 if ( $this->mOpened ) {
65 MediaWiki\suppressWarnings();
67 MediaWiki\restoreWarnings();
92 function open( $server, $user, $password, $dbName ) {
94 if ( !function_exists(
'oci_connect' ) ) {
97 "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n " .
98 "(Note: if you recently installed PHP, you may need to restart your webserver\n " .
103 $this->mUser =
$user;
104 $this->mPassword = $password;
110 $this->mServer = $dbName;
111 $this->mDBname =
$user;
113 $this->mServer = $server;
115 $this->mDBname =
$user;
117 $this->mDBname = $dbName;
121 if ( !strlen( $user ) ) { #
e.g. the
class is being loaded
129 $session_mode = $this->mFlags &
DBO_SYSDBA ? OCI_SYSDBA : OCI_DEFAULT;
131 MediaWiki\suppressWarnings();
133 $this->mConn = oci_pconnect(
137 $this->defaultCharset,
141 $this->mConn = oci_new_connect(
145 $this->defaultCharset,
149 $this->mConn = oci_connect(
153 $this->defaultCharset,
157 MediaWiki\restoreWarnings();
159 if ( $this->mUser != $this->mDBname ) {
164 if ( !$this->mConn ) {
168 $this->mOpened =
true;
170 # removed putenv calls because they interfere with the system globaly
171 $this->
doQuery(
'ALTER SESSION SET NLS_TIMESTAMP_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
172 $this->
doQuery(
'ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
173 $this->
doQuery(
'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=\'.,\'' );
184 return oci_close( $this->mConn );
188 return $this->mTrxLevel ? OCI_NO_AUTO_COMMIT : OCI_COMMIT_ON_SUCCESS;
194 throw new InvalidArgumentException(
"SQL encoding is invalid\n$sql" );
200 $sql = preg_replace(
'/ as /i',
' ', $sql );
205 $union_unique = ( preg_match(
'/\/\* UNION_UNIQUE \*\/ /', $sql ) != 0 );
212 'EXPLAIN PLAN SET STATEMENT_ID = \'' . $explain_id .
'\' FOR
',
218 MediaWiki\suppressWarnings();
220 $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql );
221 if ( $stmt === false ) {
222 $e = oci_error( $this->mConn );
223 $this->reportQueryError( $e['message
'], $e['code
'], $sql, __METHOD__ );
228 if ( !oci_execute( $stmt, $this->execFlags() ) ) {
229 $e = oci_error( $stmt );
230 if ( !$this->ignoreDupValOnIndex || $e['code
'] != '1
' ) {
231 $this->reportQueryError( $e['message
'], $e['code
'], $sql, __METHOD__ );
237 MediaWiki\restoreWarnings();
239 if ( $explain_count > 0 ) {
240 return $this->doQuery( 'SELECT
id, cardinality
"ROWS" FROM plan_table
' .
241 'WHERE statement_id = \
'' . $explain_id .
'\'' );
242 } elseif ( oci_statement_type( $stmt ) ==
'SELECT' ) {
243 return new ORAResult( $this, $stmt, $union_unique );
245 $this->mAffectedRows = oci_num_rows( $stmt );
276 return $res->fetchObject();
288 return $res->fetchRow();
300 return $res->numRows();
312 return $res->numFields();
316 return oci_field_name( $stmt, $n );
320 $res = $this->
query(
"SELECT lastval_pkg.getLastval FROM dual" );
321 $row = $this->fetchRow(
$res );
322 return is_null( $row[0] ) ? null : (int)$row[0];
333 $res->result->seek( $row );
338 if ( $this->mConn ===
false ) {
341 $e = oci_error( $this->mConn );
344 return $e[
'message'];
348 if ( $this->mConn ===
false ) {
351 $e = oci_error( $this->mConn );
358 return $this->mAffectedRows;
378 if ( !count( $a ) ) {
386 if ( in_array(
'IGNORE',
$options ) ) {
387 $this->ignoreDupValOnIndex =
true;
390 if ( !is_array( reset( $a ) ) ) {
394 foreach ( $a as &$row ) {
395 $this->insertOneRow( $table, $row,
$fname );
399 if ( in_array(
'IGNORE',
$options ) ) {
400 $this->ignoreDupValOnIndex =
false;
407 $col_info = $this->fieldInfoMulti( $table, $col );
408 $col_type = $col_info !=
false ? $col_info->type() :
'CONSTANT';
411 if ( is_numeric( $col ) ) {
416 } elseif ( $includeCol ) {
420 if ( $val ==
'' && $val !== 0 && $col_type !=
'BLOB' && $col_type !=
'CLOB' ) {
424 if ( $val ===
'NULL' ) {
428 if ( $val ===
null ) {
429 if ( $col_info !=
false && $col_info->isNullable() == 0 && $col_info->defaultValue() !=
null ) {
453 $sql =
"INSERT INTO " . $table .
" (" . implode(
',', array_keys( $row ) ) .
')';
458 foreach ( $row as $col => &$val ) {
464 if ( $this->isQuotedIdentifier( $val ) ) {
465 $sql .= $this->removeIdentifierQuotes( $val );
468 $sql .= $this->fieldBindStatement( $table, $col, $val );
473 $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql );
474 if ( $stmt ===
false ) {
475 $e = oci_error( $this->mConn );
476 $this->reportQueryError(
$e[
'message'],
$e[
'code'], $sql, __METHOD__ );
480 foreach ( $row as $col => &$val ) {
481 $col_info = $this->fieldInfoMulti( $table, $col );
482 $col_type = $col_info !=
false ? $col_info->type() :
'CONSTANT';
484 if ( $val ===
null ) {
486 } elseif ( $col_type !=
'BLOB' && $col_type !=
'CLOB' ) {
487 if ( is_object( $val ) ) {
488 $val = $val->fetch();
492 if ( preg_match(
'/^timestamp.*/i', $col_type ) == 1 && strtolower( $val ) ==
'infinity' ) {
493 $val = $this->getInfinity();
497 if ( oci_bind_by_name( $stmt,
":$col", $val, -1, SQLT_CHR ) ===
false ) {
498 $e = oci_error( $stmt );
499 $this->reportQueryError(
$e[
'message'],
$e[
'code'], $sql, __METHOD__ );
505 $lob[$col] = oci_new_descriptor( $this->mConn, OCI_D_LOB );
506 if ( $lob[$col] ===
false ) {
507 $e = oci_error( $stmt );
511 if ( is_object( $val ) ) {
512 $val = $val->fetch();
515 if ( $col_type ==
'BLOB' ) {
516 $lob[$col]->writeTemporary( $val, OCI_TEMP_BLOB );
517 oci_bind_by_name( $stmt,
":$col", $lob[$col], -1, OCI_B_BLOB );
519 $lob[$col]->writeTemporary( $val, OCI_TEMP_CLOB );
520 oci_bind_by_name( $stmt,
":$col", $lob[$col], -1, OCI_B_CLOB );
525 MediaWiki\suppressWarnings();
527 if ( oci_execute( $stmt, $this->execFlags() ) ===
false ) {
528 $e = oci_error( $stmt );
529 if ( !$this->ignoreDupValOnIndex ||
$e[
'code'] !=
'1' ) {
530 $this->reportQueryError(
$e[
'message'],
$e[
'code'], $sql, __METHOD__ );
534 $this->mAffectedRows = oci_num_rows( $stmt );
537 $this->mAffectedRows = oci_num_rows( $stmt );
540 MediaWiki\restoreWarnings();
542 if ( isset( $lob ) ) {
543 foreach ( $lob as $lob_v ) {
548 if ( !$this->mTrxLevel ) {
549 oci_commit( $this->mConn );
552 return oci_free_statement( $stmt );
556 $insertOptions = [], $selectOptions = [], $selectJoinConds = []
558 $destTable = $this->
tableName( $destTable );
560 $sequenceData = $this->getSequenceData( $destTable );
561 if ( $sequenceData !==
false &&
562 !isset( $varMap[$sequenceData[
'column']] )
564 $varMap[$sequenceData[
'column']] =
'GET_SEQUENCE_VALUE(\'' . $sequenceData[
'sequence'] .
'\')
';
567 // count-alias subselect fields to avoid abigious definition errors
569 foreach ( $varMap as &$val ) {
570 $val = $val . ' field
' . ( $i++ );
573 $selectSql = $this->selectSQLText(
575 array_values( $varMap ),
582 $sql = "INSERT INTO $destTable (" . implode( ',
', array_keys( $varMap ) ) . ')
' . $selectSql;
584 if ( in_array( 'IGNORE
', $insertOptions ) ) {
585 $this->ignoreDupValOnIndex = true;
588 $retval = $this->query( $sql, $fname );
590 if ( in_array( 'IGNORE
', $insertOptions ) ) {
591 $this->ignoreDupValOnIndex = false;
597 public function upsert( $table, array $rows, array $uniqueIndexes, array $set,
600 if ( !count( $rows ) ) {
601 return true; // nothing to do
604 if ( !is_array( reset( $rows ) ) ) {
608 $sequenceData = $this->getSequenceData( $table );
609 if ( $sequenceData !== false ) {
610 // add sequence column to each list of columns, when not set
611 foreach ( $rows as &$row ) {
612 if ( !isset( $row[$sequenceData['column']] ) ) {
613 $row[$sequenceData['column']] =
614 $this->addIdentifierQuotes( 'GET_SEQUENCE_VALUE(\
'' .
615 $sequenceData[
'sequence'] .
'\')
' );
620 return parent::upsert( $table, $rows, $uniqueIndexes, $set, $fname );
623 function tableName( $name, $format = 'quoted
' ) {
625 Replace reserved words with better ones
626 Using uppercase because that's the only
way Oracle can handle
634 $name =
'PAGECONTENT';
638 return strtoupper( parent::tableName( $name, $format ) );
644 return preg_replace(
'/.*\.(.*)/',
'$1', $name );
654 if ( $this->sequenceData ==
null ) {
655 $result = $this->doQuery(
"SELECT lower(asq.sequence_name),
656 lower(atc.table_name),
657 lower(atc.column_name)
658 FROM all_sequences asq, all_tab_columns atc
661 '{$this->mTablePrefix}MWUSER',
662 '{$this->mTablePrefix}USER',
665 atc.column_name || '_SEQ' = '{$this->mTablePrefix}' || asq.sequence_name
666 AND asq.sequence_owner = upper('{$this->mDBname}')
667 AND atc.owner = upper('{$this->mDBname}')" );
669 while ( ( $row = $result->fetchRow() ) !==
false ) {
670 $this->sequenceData[$row[1]] = [
671 'sequence' => $row[0],
676 $table = strtolower( $this->removeIdentifierQuotes( $this->
tableName( $table ) ) );
678 return ( isset( $this->sequenceData[$table] ) ) ? $this->sequenceData[$table] :
false;
689 $fieldInfoData = $this->fieldInfo( $table, $field );
691 return $fieldInfoData->maxLength();
695 if ( $offset ===
false ) {
699 return "SELECT * FROM ($sql) WHERE rownum >= (1 + $offset) AND rownum < (1 + $limit + $offset)";
703 return new Blob( $b );
707 if ( $b instanceof
Blob ) {
715 $glue =
' UNION ALL ';
717 return 'SELECT * ' . ( $all ?
'' :
'/* UNION_UNIQUE */ ' ) .
718 'FROM (' . implode( $glue, $sqls ) .
')';
722 return $this->lastErrno() ==
'OCI-00060';
728 $temporary = $temporary ?
'TRUE' :
'FALSE';
730 $newName = strtoupper( $newName );
731 $oldName = strtoupper( $oldName );
733 $tabName = substr( $newName, strlen( $this->mTablePrefix ) );
734 $oldPrefix = substr( $oldName, 0, strlen( $oldName ) - strlen( $tabName ) );
735 $newPrefix = strtoupper( $this->mTablePrefix );
737 return $this->doQuery(
"BEGIN DUPLICATE_TABLE( '$tabName', " .
738 "'$oldPrefix', '$newPrefix', $temporary ); END;" );
743 if ( !empty( $prefix ) ) {
744 $listWhere =
' AND table_name LIKE \'' . strtoupper( $prefix ) .
'%\'';
747 $owner = strtoupper( $this->mDBname );
748 $result = $this->doQuery(
"SELECT table_name FROM all_tables " .
749 "WHERE owner='$owner' AND table_name NOT LIKE '%!_IDX\$_' ESCAPE '!' $listWhere" );
753 $endArray[] = strtoupper( $prefix .
'MWUSER' );
754 $endArray[] = strtoupper( $prefix .
'PAGE' );
755 $endArray[] = strtoupper( $prefix .
'IMAGE' );
756 $fixedOrderTabs = $endArray;
757 while ( ( $row = $result->fetchRow() ) !==
false ) {
758 if ( !in_array( $row[
'table_name'], $fixedOrderTabs ) ) {
759 $endArray[] = $row[
'table_name'];
766 public function dropTable( $tableName, $fName = __METHOD__ ) {
767 $tableName = $this->
tableName( $tableName );
768 if ( !$this->tableExists( $tableName ) ) {
772 return $this->doQuery(
"DROP TABLE $tableName CASCADE CONSTRAINTS PURGE" );
794 return '[{{int:version-db-oracle-url}} Oracle]';
802 $rset = $this->doQuery(
803 'SELECT version FROM product_component_version ' .
804 'WHERE UPPER(product) LIKE \'ORACLE DATABASE%\''
806 $row = $rset->fetchRow();
808 return oci_server_version( $this->mConn );
811 return $row[
'version'];
823 $table = strtoupper( $this->removeIdentifierQuotes( $table ) );
824 $index = strtoupper( $index );
825 $owner = strtoupper( $this->mDBname );
826 $sql =
"SELECT 1 FROM all_indexes WHERE owner='$owner' AND index_name='{$table}_{$index}'";
827 $res = $this->doQuery( $sql );
829 $count =
$res->numRows();
846 $table = $this->addQuotes( strtoupper( $this->removeIdentifierQuotes( $table ) ) );
847 $owner = $this->addQuotes( strtoupper( $this->mDBname ) );
848 $sql =
"SELECT 1 FROM all_tables WHERE owner=$owner AND table_name=$table";
849 $res = $this->doQuery( $sql );
850 if (
$res &&
$res->numRows() > 0 ) {
872 $field = strtoupper( $field );
873 if ( is_array( $table ) ) {
874 $table = array_map( [ $this,
'tableNameInternal' ], $table );
875 $tableWhere =
'IN (';
876 foreach ( $table as &$singleTable ) {
877 $singleTable = $this->removeIdentifierQuotes( $singleTable );
878 if ( isset( $this->mFieldInfoCache[
"$singleTable.$field"] ) ) {
879 return $this->mFieldInfoCache[
"$singleTable.$field"];
881 $tableWhere .=
'\'' . $singleTable .
'\',
';
883 $tableWhere = rtrim( $tableWhere, ',
' ) . ')
';
885 $table = $this->removeIdentifierQuotes( $this->tableNameInternal( $table ) );
886 if ( isset( $this->mFieldInfoCache["$table.$field"] ) ) {
887 return $this->mFieldInfoCache["$table.$field"];
889 $tableWhere = '= \
'' . $table .
'\'';
892 $fieldInfoStmt = oci_parse(
894 'SELECT * FROM wiki_field_info_full WHERE table_name ' .
895 $tableWhere .
' and column_name = \'' . $field .
'\''
897 if ( oci_execute( $fieldInfoStmt, $this->execFlags() ) ===
false ) {
898 $e = oci_error( $fieldInfoStmt );
899 $this->reportQueryError(
$e[
'message'],
$e[
'code'],
'fieldInfo QUERY', __METHOD__ );
904 if (
$res->numRows() == 0 ) {
905 if ( is_array( $table ) ) {
906 foreach ( $table as &$singleTable ) {
907 $this->mFieldInfoCache[
"$singleTable.$field"] =
false;
910 $this->mFieldInfoCache[
"$table.$field"] =
false;
912 $fieldInfoTemp =
null;
915 $table = $fieldInfoTemp->tableName();
916 $this->mFieldInfoCache[
"$table.$field"] = $fieldInfoTemp;
920 return $fieldInfoTemp;
930 if ( is_array( $table ) ) {
931 throw new DBUnexpectedError( $this,
'DatabaseOracle::fieldInfo called with table array!' );
934 return $this->fieldInfoMulti( $table, $field );
938 $this->mTrxLevel = 1;
939 $this->doQuery(
'SET CONSTRAINTS ALL DEFERRED' );
943 if ( $this->mTrxLevel ) {
944 $ret = oci_commit( $this->mConn );
948 $this->mTrxLevel = 0;
949 $this->doQuery(
'SET CONSTRAINTS ALL IMMEDIATE' );
954 if ( $this->mTrxLevel ) {
955 oci_rollback( $this->mConn );
956 $this->mTrxLevel = 0;
957 $this->doQuery(
'SET CONSTRAINTS ALL IMMEDIATE' );
963 callable $lineCallback =
null,
964 callable $resultCallback =
null,
965 $fname = __METHOD__, callable $inputCallback =
null
969 $dollarquote =
false;
973 while ( !feof( $fp ) ) {
974 if ( $lineCallback ) {
975 call_user_func( $lineCallback );
977 $line = trim( fgets( $fp, 1024 ) );
978 $sl = strlen(
$line ) - 1;
988 if ( substr(
$line, 0, 8 ) ==
'/*$mw$*/' ) {
989 if ( $dollarquote ) {
990 $dollarquote =
false;
996 } elseif ( !$dollarquote ) {
997 if (
';' ==
$line[$sl] && ( $sl < 2 ||
';' !=
$line[$sl - 1] ) ) {
1009 $cmd = str_replace(
';;',
";", $cmd );
1010 if ( strtolower( substr( $cmd, 0, 6 ) ) ==
'define' ) {
1011 if ( preg_match(
'/^define\s*([^\s=]*)\s*=\s*\'\{\$([^\}]*)\}\'/', $cmd, $defines ) ) {
1012 $replacements[$defines[2]] = $defines[1];
1015 foreach ( $replacements as $mwVar => $scVar ) {
1016 $cmd = str_replace(
'&' . $scVar .
'.',
'`{$' . $mwVar .
'}`', $cmd );
1019 $cmd = $this->replaceVars( $cmd );
1020 if ( $inputCallback ) {
1021 call_user_func( $inputCallback, $cmd );
1023 $res = $this->doQuery( $cmd );
1024 if ( $resultCallback ) {
1025 call_user_func( $resultCallback,
$res, $this );
1028 if (
false ===
$res ) {
1029 $err = $this->lastError();
1031 return "Query \"{$cmd}\" failed with error code \"$err\".\n";
1044 $this->mDBname = $db;
1045 if ( $db ==
null || $db == $this->mUser ) {
1048 $sql =
'ALTER SESSION SET CURRENT_SCHEMA=' . strtoupper( $db );
1049 $stmt = oci_parse( $this->mConn, $sql );
1050 MediaWiki\suppressWarnings();
1052 MediaWiki\restoreWarnings();
1054 $e = oci_error( $stmt );
1055 if (
$e[
'code'] !=
'1435' ) {
1056 $this->reportQueryError(
$e[
'message'],
$e[
'code'], $sql, __METHOD__ );
1066 return str_replace(
"'",
"''",
$s );
1075 return "'" . $this->strencode(
$s ) .
"'";
1087 return strpos(
$s,
'/*Q*/' ) ===
false ?
$s : substr(
$s, 5 );
1091 return strpos(
$s,
'/*Q*/' ) !==
false;
1097 $col_info = $this->fieldInfoMulti( $table, $col );
1098 $col_type = $col_info !=
false ? $col_info->type() :
'CONSTANT';
1099 if ( $col_type ==
'CLOB' ) {
1100 $col =
'TO_CHAR(' . $col .
')';
1102 } elseif ( $col_type ==
'VARCHAR2' ) {
1109 foreach ( $conds as $col => $val ) {
1110 if ( is_array( $val ) ) {
1111 $conds2[$col] = $this->wrapConditionsForWhere( $table, $val, $col );
1113 if ( is_numeric( $col ) && $parentCol !=
null ) {
1114 $this->wrapFieldForWhere( $table, $parentCol, $val );
1116 $this->wrapFieldForWhere( $table, $col, $val );
1118 $conds2[$col] = $val;
1128 if ( is_array( $conds ) ) {
1129 $conds = $this->wrapConditionsForWhere( $table, $conds );
1144 $preLimitTail = $postLimitTail =
'';
1148 foreach (
$options as $key => $option ) {
1149 if ( is_numeric( $key ) ) {
1150 $noKeyOptions[$option] =
true;
1154 $preLimitTail .= $this->makeGroupByWithHaving(
$options );
1156 $preLimitTail .= $this->makeOrderBy(
$options );
1158 if ( isset( $noKeyOptions[
'FOR UPDATE'] ) ) {
1159 $postLimitTail .=
' FOR UPDATE';
1162 if ( isset( $noKeyOptions[
'DISTINCT'] ) || isset( $noKeyOptions[
'DISTINCTROW'] ) ) {
1163 $startOpts .=
'DISTINCT';
1166 if ( isset(
$options[
'USE INDEX'] ) && !is_array(
$options[
'USE INDEX'] ) ) {
1167 $useIndex = $this->useIndexClause(
$options[
'USE INDEX'] );
1172 if ( isset(
$options[
'IGNORE INDEX'] ) && !is_array(
$options[
'IGNORE INDEX'] ) ) {
1173 $ignoreIndex = $this->ignoreIndexClause(
$options[
'IGNORE INDEX'] );
1178 return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
1181 public function delete( $table, $conds,
$fname = __METHOD__ ) {
1182 if ( is_array( $conds ) ) {
1183 $conds = $this->wrapConditionsForWhere( $table, $conds );
1188 if ( $table == $this->
tableName(
'user' ) ) {
1189 $this->update(
'archive', [
'ar_user' => 0 ],
1190 [
'ar_user' => $conds[
'user_id'] ],
$fname );
1191 $this->update(
'ipblocks', [
'ipb_user' => 0 ],
1192 [
'ipb_user' => $conds[
'user_id'] ],
$fname );
1193 $this->update(
'image', [
'img_user' => 0 ],
1194 [
'img_user' => $conds[
'user_id'] ],
$fname );
1195 $this->update(
'oldimage', [
'oi_user' => 0 ],
1196 [
'oi_user' => $conds[
'user_id'] ],
$fname );
1197 $this->update(
'filearchive', [
'fa_deleted_user' => 0 ],
1198 [
'fa_deleted_user' => $conds[
'user_id'] ],
$fname );
1199 $this->update(
'filearchive', [
'fa_user' => 0 ],
1200 [
'fa_user' => $conds[
'user_id'] ],
$fname );
1201 $this->update(
'uploadstash', [
'us_user' => 0 ],
1202 [
'us_user' => $conds[
'user_id'] ],
$fname );
1203 $this->update(
'recentchanges', [
'rc_user' => 0 ],
1204 [
'rc_user' => $conds[
'user_id'] ],
$fname );
1205 $this->update(
'logging', [
'log_user' => 0 ],
1206 [
'log_user' => $conds[
'user_id'] ],
$fname );
1207 } elseif ( $table == $this->
tableName(
'image' ) ) {
1208 $this->update(
'oldimage', [
'oi_name' => 0 ],
1209 [
'oi_name' => $conds[
'img_name'] ],
$fname );
1212 return parent::delete( $table, $conds,
$fname );
1228 $opts = $this->makeUpdateOptions(
$options );
1229 $sql =
"UPDATE $opts $table SET ";
1232 foreach ( $values as $col => &$val ) {
1233 $sqlSet = $this->fieldBindStatement( $table, $col, $val,
true );
1236 $sqlSet =
', ' . $sqlSet;
1243 if ( $conds !== [] && $conds !==
'*' ) {
1244 $conds = $this->wrapConditionsForWhere( $table, $conds );
1245 $sql .=
' WHERE ' . $this->makeList( $conds,
LIST_AND );
1248 $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql );
1249 if ( $stmt ===
false ) {
1250 $e = oci_error( $this->mConn );
1251 $this->reportQueryError(
$e[
'message'],
$e[
'code'], $sql, __METHOD__ );
1255 foreach ( $values as $col => &$val ) {
1256 $col_info = $this->fieldInfoMulti( $table, $col );
1257 $col_type = $col_info !=
false ? $col_info->type() :
'CONSTANT';
1259 if ( $val ===
null ) {
1261 } elseif ( $col_type !=
'BLOB' && $col_type !=
'CLOB' ) {
1262 if ( is_object( $val ) ) {
1263 $val = $val->getData();
1266 if ( preg_match(
'/^timestamp.*/i', $col_type ) == 1 && strtolower( $val ) ==
'infinity' ) {
1267 $val =
'31-12-2030 12:00:00.000000';
1271 if ( oci_bind_by_name( $stmt,
":$col", $val ) ===
false ) {
1272 $e = oci_error( $stmt );
1273 $this->reportQueryError(
$e[
'message'],
$e[
'code'], $sql, __METHOD__ );
1279 $lob[$col] = oci_new_descriptor( $this->mConn, OCI_D_LOB );
1280 if ( $lob[$col] ===
false ) {
1281 $e = oci_error( $stmt );
1285 if ( is_object( $val ) ) {
1286 $val = $val->getData();
1289 if ( $col_type ==
'BLOB' ) {
1290 $lob[$col]->writeTemporary( $val );
1291 oci_bind_by_name( $stmt,
":$col", $lob[$col], -1, SQLT_BLOB );
1293 $lob[$col]->writeTemporary( $val );
1294 oci_bind_by_name( $stmt,
":$col", $lob[$col], -1, OCI_B_CLOB );
1299 MediaWiki\suppressWarnings();
1301 if ( oci_execute( $stmt, $this->execFlags() ) ===
false ) {
1302 $e = oci_error( $stmt );
1303 if ( !$this->ignoreDupValOnIndex ||
$e[
'code'] !=
'1' ) {
1304 $this->reportQueryError(
$e[
'message'],
$e[
'code'], $sql, __METHOD__ );
1308 $this->mAffectedRows = oci_num_rows( $stmt );
1311 $this->mAffectedRows = oci_num_rows( $stmt );
1314 MediaWiki\restoreWarnings();
1316 if ( isset( $lob ) ) {
1317 foreach ( $lob as $lob_v ) {
1322 if ( !$this->mTrxLevel ) {
1323 oci_commit( $this->mConn );
1326 return oci_free_statement( $stmt );
1331 return 'BITNOT(' . $field .
')';
1335 return 'BITAND(' . $fieldLeft .
', ' . $fieldRight .
')';
1338 function bitOr( $fieldLeft, $fieldRight ) {
1339 return 'BITOR(' . $fieldLeft .
', ' . $fieldRight .
')';
1343 return $this->mDBname;
1347 return $this->mServer;
1351 $delim, $table, $field, $conds =
'', $join_conds = []
1353 $fld =
"LISTAGG($field," . $this->addQuotes( $delim ) .
") WITHIN GROUP (ORDER BY $field)";
1355 return '(' . $this->selectSQLText( $table, $fld, $conds,
null, [], $join_conds ) .
')';
1364 return 'CAST ( ' . $field .
' AS VARCHAR2 )';
1368 return '31-12-2030 12:00:00.000000';
and give any other recipients of the Program a copy of this License along with the Program You may charge a fee for the physical act of transferring a and you may at your option offer warranty protection in exchange for a fee You may modify your copy or copies of the Program or any portion of thus forming a work based on the and copy and distribute such modifications or work under the terms of Section provided that you also meet all of these that in whole or in part contains or is derived from the Program or any part to be licensed as a whole at no charge to all third parties under the terms of this License c If the modified program normally reads commands interactively when you must cause when started running for such interactive use in the most ordinary way
$wgDBprefix
Table name prefix.
$wgDBOracleDRCP
Set true to enable Oracle DCRP (supported from 11gR1 onward)
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to and or sell copies of the and to permit persons to whom the Software is furnished to do subject to the following WITHOUT WARRANTY OF ANY EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR ARISING FROM
if(!defined( 'MEDIAWIKI')) $fname
This file is not a valid entry point, perform no further processing unless MEDIAWIKI is defined.
duplicateTableStructure( $oldName, $newName, $temporary=false, $fname=__METHOD__)
Creates a new table with structure copied from existing table.
removeIdentifierQuotes( $s)
doBegin( $fname=__METHOD__)
Issues the BEGIN command to the database server.
lastErrno()
Get the last error number.
addIdentifierQuotes( $s)
Quotes an identifier using backticks or "double quotes" depending on the database type.
bitAnd( $fieldLeft, $fieldRight)
wrapFieldForWhere( $table, &$col, &$val)
indexExists( $table, $index, $fname=__METHOD__)
Query whether a given index exists.
indexInfo( $table, $index, $fname=__METHOD__)
Returns information about an index If errors are explicitly ignored, returns NULL on failure.
bitOr( $fieldLeft, $fieldRight)
buildGroupConcatField( $delim, $table, $field, $conds='', $join_conds=[])
Build a GROUP_CONCAT or equivalent statement for a query.
getType()
Get the type of the DBMS, as it appears in $wgDBtype.
selectDB( $db)
Change the current database.
doRollback( $fname=__METHOD__)
Issues the ROLLBACK command to the database server.
strencode( $s)
Wrapper for addslashes()
affectedRows()
Get the number of rows affected by the last write query.
listTables( $prefix=null, $fname=__METHOD__)
List all tables on the database.
makeSelectOptions( $options)
Returns an optional USE INDEX clause to go after the table, and a string to go at the end of the quer...
fieldInfoMulti( $table, $field)
Function translates mysql_fetch_field() functionality on ORACLE.
fieldInfo( $table, $field)
textFieldSize( $table, $field)
Returns the size of a text field, or -1 for "unlimited".
implicitOrderby()
Returns true if this database does an implicit order by when the column has an index For example: SEL...
encodeBlob( $b)
Some DBMSs have a special format for inserting into blob fields, they don't allow simple quoted strin...
int $mAffectedRows
The number of rows affected as an integer.
addQuotes( $s)
Adds quotes and backslashes.
doCommit( $fname=__METHOD__)
Issues the COMMIT command to the database server.
queryIgnore( $sql, $fname='')
getSequenceData( $table)
Return sequence_name if table has a sequence.
lastError()
Get a description of the last error.
getDBname()
Get the current DB name.
decodeBlob( $b)
Some DBMSs return a special placeholder object representing blob fields in result objects.
insertOneRow( $table, $row, $fname)
string $defaultCharset
Character set for Oracle database.
__destruct()
Run a few simple sanity checks and close dangling connections.
dropTable( $tableName, $fName=__METHOD__)
Delete a table.
implicitGroupby()
Returns true if this database does an implicit sort when doing GROUP BY.
insertId()
Get the inserted value of an auto-increment row.
closeConnection()
Closes a database connection, if it is open Returns success, true if already closed.
bool $ignoreDupValOnIndex
limitResult( $sql, $limit, $offset=false)
Construct a LIMIT query with optional offset.
sourceStream( $fp, callable $lineCallback=null, callable $resultCallback=null, $fname=__METHOD__, callable $inputCallback=null)
Read and execute commands from an open file handle.
getServer()
Get the server hostname or IP address.
wasDeadlock()
Determines if the last failure was due to a deadlock.
tableExists( $table, $fname=__METHOD__)
Query whether a given table exists (in the given schema, or the default mw one if not given)
tableNameInternal( $name)
update( $table, $values, $conds, $fname=__METHOD__, $options=[])
indexUnique( $table, $index, $fname=__METHOD__)
fieldBindStatement( $table, $col, &$val, $includeCol=false)
insert( $table, $a, $fname=__METHOD__, $options=[])
INSERT wrapper, inserts an array into a table.
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
doQuery( $sql)
The DBMS-dependent part of query()
selectRow( $table, $vars, $conds, $fname=__METHOD__, $options=[], $join_conds=[])
Single row SELECT wrapper.
wrapConditionsForWhere( $table, $conds, $parentCol=null)
open( $server, $user, $password, $dbName)
Usually aborts on failure.
fieldName( $stmt, $n)
Get a field name in a result object.
freeResult( $res)
Frees resources associated with the LOB descriptor.
__construct(array $p)
Constructor and database handle and attempt to connect to the DB server.
unionQueries( $sqls, $all)
Construct a UNION query This is used for providing overload point for other DB abstractions not compa...
aggregateValue( $valuedata, $valuename='value')
Return aggregated value function call.
nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname=__METHOD__, $insertOptions=[], $selectOptions=[], $selectJoinConds=[])
Native server-side implementation of insertSelect() for situations where we don't want to select ever...
isQuotedIdentifier( $s)
Returns if the given identifier looks quoted or not according to the database convention for quoting ...
getInfinity()
Find out when 'infinity' is.
static getLocalInstance( $ts=false)
Get a timestamp instance in the server local timezone ($wgLocaltimezone)
The oci8 extension is fairly weak and doesn't support oci_num_rows, among other things.
static isUtf8( $value)
Test whether a string is valid UTF-8.
We use the convention $dbr for read and $dbw for write to help you keep track of whether the database object is a the world will explode Or to be a subsequent write query which succeeded on the master may fail when replicated to the slave due to a unique key collision Replication on the slave will stop and it may take hours to repair the database and get it back online Setting read_only in my cnf on the slave will avoid this but given the dire we prefer to have as many checks as possible We provide a but the wrapper functions like please read the documentation for tableName() and addQuotes(). You will need both of them. ------------------------------------------------------------------------ Basic query optimisation ------------------------------------------------------------------------ MediaWiki developers who need to write DB queries should have some understanding of databases and the performance issues associated with them. Patches containing unacceptably slow features will not be accepted. Unindexed queries are generally not welcome in MediaWiki
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang
static configuration should be added through ResourceLoaderGetConfigVars instead & $vars
in this case you re responsible for computing and outputting the entire conflict i e
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
processing should stop and the error should be shown to the user * false
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account $user
returning false will NOT prevent logging $e
This document describes the state of Postgres support in and is fairly well maintained The main code is very well while extensions are very hit and miss it is probably the most supported database after MySQL Much of the work in making MediaWiki database agnostic came about through the work of creating Postgres as and are nearing end of but without copying over all the usage comments General notes on the but these can almost always be programmed around *Although Postgres has a true BOOLEAN boolean columns are always mapped to as the code does not always treat the column as a and VARBINARY columns should simply be TEXT The only exception is when VARBINARY is used to store true binary such as the math_inputhash column