235 $server = $params[
'host'];
236 $user = $params[
'user'];
237 $password = $params[
'password'];
238 $dbName = $params[
'dbname'];
240 $this->mSchema = $params[
'schema'];
241 $this->mTablePrefix = $params[
'tablePrefix'];
243 $this->cliMode = $params[
'cliMode'];
245 $this->agent = str_replace(
'/',
'-', $params[
'agent'] );
247 $this->mFlags = $params[
'flags'];
249 if ( $this->cliMode ) {
256 $this->mSessionVars = $params[
'variables'];
258 $this->srvCache = isset( $params[
'srvCache'] )
259 ? $params[
'srvCache']
262 $this->profiler = $params[
'profiler'];
263 $this->trxProfiler = $params[
'trxProfiler'];
264 $this->connLogger = $params[
'connLogger'];
265 $this->queryLogger = $params[
'queryLogger'];
266 $this->errorLogger = $params[
'errorLogger'];
272 $this->
open( $server,
$user, $password, $dbName );
278 if ( $this->mDBname !=
'' ) {
280 $this->currentDomain =
new DatabaseDomain( $this->mDBname, null, $this->mTablePrefix );
325 final public static function factory( $dbType, $p = [] ) {
326 static $canonicalDBTypes = [
327 'mysql' => [
'mysqli',
'mysql' ],
335 $dbType = strtolower( $dbType );
336 if ( isset( $canonicalDBTypes[$dbType] ) && $canonicalDBTypes[$dbType] ) {
337 $possibleDrivers = $canonicalDBTypes[$dbType];
338 if ( !empty( $p[
'driver'] ) ) {
339 if ( in_array( $p[
'driver'], $possibleDrivers ) ) {
340 $driver = $p[
'driver'];
343 " type '$dbType' does not support driver '{$p['driver']}'" );
346 foreach ( $possibleDrivers
as $posDriver ) {
347 if ( extension_loaded( $posDriver ) ) {
348 $driver = $posDriver;
356 if ( $driver ===
false || $driver ===
'' ) {
358 " no viable database extension found for type '$dbType'" );
361 $class =
'Database' . ucfirst( $driver );
362 if ( class_exists( $class ) && is_subclass_of( $class,
'IDatabase' ) ) {
364 $p[
'host'] = isset( $p[
'host'] ) ? $p[
'host'] :
false;
365 $p[
'user'] = isset( $p[
'user'] ) ? $p[
'user'] :
false;
366 $p[
'password'] = isset( $p[
'password'] ) ? $p[
'password'] :
false;
367 $p[
'dbname'] = isset( $p[
'dbname'] ) ? $p[
'dbname'] :
false;
368 $p[
'flags'] = isset( $p[
'flags'] ) ? $p[
'flags'] : 0;
369 $p[
'variables'] = isset( $p[
'variables'] ) ? $p[
'variables'] : [];
370 $p[
'tablePrefix'] = isset( $p[
'tablePrefix'] ) ? $p[
'tablePrefix'] :
'';
371 $p[
'schema'] = isset( $p[
'schema'] ) ? $p[
'schema'] :
'';
372 $p[
'cliMode'] = isset( $p[
'cliMode'] ) ? $p[
'cliMode'] : ( PHP_SAPI ===
'cli' );
373 $p[
'agent'] = isset( $p[
'agent'] ) ? $p[
'agent'] :
'';
374 if ( !isset( $p[
'connLogger'] ) ) {
375 $p[
'connLogger'] = new \Psr\Log\NullLogger();
377 if ( !isset( $p[
'queryLogger'] ) ) {
378 $p[
'queryLogger'] = new \Psr\Log\NullLogger();
380 $p[
'profiler'] = isset( $p[
'profiler'] ) ? $p[
'profiler'] : null;
381 if ( !isset( $p[
'trxProfiler'] ) ) {
384 if ( !isset( $p[
'errorLogger'] ) ) {
386 trigger_error( get_class(
$e ) .
': ' .
$e->getMessage(), E_USER_WARNING );
390 $conn =
new $class( $p );
399 $this->queryLogger = $logger;
431 if ( $ignoreErrors !== null ) {
445 return $this->mTrxLevel ? $this->mTrxTimestamp : null;
450 if ( $prefix !== null ) {
451 $this->mTablePrefix = $prefix;
452 $this->currentDomain = ( $this->mDBname !=
'' )
462 if ( $schema !== null ) {
463 $this->mSchema = $schema;
470 if ( is_null(
$name ) ) {
473 if ( array_key_exists(
$name, $this->mLBInfo ) ) {
474 return $this->mLBInfo[
$name];
482 if ( is_null(
$value ) ) {
483 $this->mLBInfo =
$name;
490 $this->lazyMasterHandle = $conn;
519 return $this->mLastWriteTime ?:
false;
527 return $this->mTrxLevel && (
533 if ( !$this->mTrxLevel ) {
535 } elseif ( !$this->mTrxDoneWrites ) {
540 case self::ESTIMATE_DB_APPLY:
542 $rttAdjTotal = $this->mTrxWriteAdjQueryCount * $rtt;
543 $applyTime = max( $this->mTrxWriteAdjDuration - $rttAdjTotal, 0 );
546 $applyTime += self::TINY_WRITE_SEC * $omitted;
555 return $this->mTrxLevel ? $this->mTrxWriteCallers : [];
559 if ( !$this->mTrxLevel ) {
565 $this->mTrxIdleCallbacks,
566 $this->mTrxPreCommitCallbacks,
567 $this->mTrxEndCallbacks
569 foreach ( $callbacks
as $callback ) {
570 $fnames[] = $callback[1];
581 public function setFlag( $flag, $remember = self::REMEMBER_NOTHING ) {
582 if ( $remember === self::REMEMBER_PRIOR ) {
583 array_push( $this->priorFlags, $this->mFlags );
585 $this->mFlags |= $flag;
588 public function clearFlag( $flag, $remember = self::REMEMBER_NOTHING ) {
589 if ( $remember === self::REMEMBER_PRIOR ) {
590 array_push( $this->priorFlags, $this->mFlags );
592 $this->mFlags &= ~$flag;
596 if ( !$this->priorFlags ) {
600 if ( $state === self::RESTORE_INITIAL ) {
601 $this->mFlags = reset( $this->priorFlags );
602 $this->priorFlags = [];
604 $this->mFlags = array_pop( $this->priorFlags );
609 return !!( $this->mFlags & $flag );
622 return $this->currentDomain->getId();
647 $this->mPHPError =
false;
648 $this->htmlErrors = ini_set(
'html_errors',
'0' );
649 set_error_handler( [ $this,
'connectionErrorLogger' ] );
656 restore_error_handler();
657 if ( $this->htmlErrors !==
false ) {
658 ini_set(
'html_errors', $this->htmlErrors );
668 if ( $this->mPHPError ) {
669 $error = preg_replace(
'!\[<a.*</a>\]!',
'', $this->mPHPError );
670 $error = preg_replace(
'!^.*?:\s?(.*)$!',
'$1', $error );
685 $this->mPHPError = $errstr;
697 'db_server' => $this->mServer,
698 'db_name' => $this->mDBname,
699 'db_user' => $this->mUser,
706 if ( $this->mConn ) {
708 $this->
commit( __METHOD__, self::FLUSHING_INTERNAL );
712 $this->mConn =
false;
713 } elseif ( $this->mTrxIdleCallbacks || $this->mTrxEndCallbacks ) {
718 $this->mOpened =
false;
758 abstract protected function doQuery( $sql );
769 '/^(?:SELECT|BEGIN|ROLLBACK|COMMIT|SET|SHOW|EXPLAIN|\(SELECT)\b/i', $sql );
777 return preg_match(
'/^\s*([a-z]+)/i', $sql, $m ) ? strtoupper( $m[1] ) : null;
792 [
'BEGIN',
'COMMIT',
'ROLLBACK',
'SHOW',
'SET',
'CREATE',
'ALTER' ],
803 '/^CREATE\s+TEMPORARY\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?[`"\']?(\w+)[`"\']?/i',
807 $this->mSessionTempTables[
$matches[1]] = 1;
810 } elseif ( preg_match(
811 '/^DROP\s+(?:TEMPORARY\s+)?TABLE\s+(?:IF\s+EXISTS\s+)?[`"\']?(\w+)[`"\']?/i',
815 unset( $this->mSessionTempTables[
$matches[1]] );
818 } elseif ( preg_match(
819 '/^(?:INSERT\s+(?:\w+\s+)?INTO|UPDATE|DELETE\s+FROM)\s+[`"\']?(\w+)[`"\']?/i',
823 return isset( $this->mSessionTempTables[
$matches[1]] );
829 public function query( $sql,
$fname = __METHOD__, $tempIgnore =
false ) {
831 $this->mLastQuery = $sql;
836 if ( $reason !==
false ) {
839 # Set a flag indicating that writes have been done
840 $this->mLastWriteTime = microtime(
true );
845 $commentedSql = preg_replace(
'/\s|$/',
" /* $fname {$this->agent} */ ", $sql, 1 );
847 # Start implicit transactions that wrap the request if DBO_TRX is enabled
851 $this->
begin( __METHOD__ .
" ($fname)", self::TRANSACTION_INTERNAL );
852 $this->mTrxAutomatic =
true;
855 # Keep track of whether the transaction has write queries pending
856 if ( $this->mTrxLevel && !$this->mTrxDoneWrites && $isWrite ) {
857 $this->mTrxDoneWrites =
true;
858 $this->trxProfiler->transactionWritingIn(
859 $this->mServer, $this->mDBname, $this->mTrxShortId );
863 $this->queryLogger->debug(
"{$this->mDBname} {$commentedSql}" );
866 # Avoid fatals if close() was called
869 # Send the query to the server
872 # Try reconnecting if the connection was lost
875 # Stash the last error values before anything might clear them
878 # Update state tracking to reflect transaction loss due to disconnection
881 $msg = __METHOD__ .
": lost connection to {$this->getServer()}; reconnected";
882 $this->connLogger->warning( $msg );
883 $this->queryLogger->warning(
886 if ( !$recoverable ) {
887 # Callers may catch the exception and continue to use the DB
890 # Should be safe to silently retry the query
894 $msg = __METHOD__ .
": lost connection to {$this->getServer()} permanently";
895 $this->connLogger->error( $msg );
899 if (
false ===
$ret ) {
900 # Deadlocks cause the entire transaction to abort, not just the statement.
901 # http://dev.mysql.com/doc/refman/5.7/en/innodb-error-handling.html
902 # https://www.postgresql.org/docs/9.1/static/explicit-locking.html
907 # Update state tracking to reflect transaction loss
921 $isMaster = !is_null( $this->
getLBInfo(
'master' ) );
922 # generalizeSQL() will probably cut down the query to reasonable
923 # logging size most of the time. The substr is really just a sanity check.
925 $queryProf =
'query-m: ' . substr( self::generalizeSQL( $sql ), 0, 255 );
927 $queryProf =
'query: ' . substr( self::generalizeSQL( $sql ), 0, 255 );
930 # Include query transaction state
931 $queryProf .= $this->mTrxShortId ?
" [TRX#{$this->mTrxShortId}]" :
"";
933 $startTime = microtime(
true );
934 if ( $this->profiler ) {
935 call_user_func( [ $this->profiler,
'profileIn' ], $queryProf );
938 if ( $this->profiler ) {
939 call_user_func( [ $this->profiler,
'profileOut' ], $queryProf );
941 $queryRuntime = max( microtime(
true ) - $startTime, 0.0 );
943 unset( $queryProfSection );
945 if (
$ret !==
false ) {
946 $this->lastPing = $startTime;
947 if ( $isWrite && $this->mTrxLevel ) {
949 $this->mTrxWriteCallers[] =
$fname;
953 if ( $sql === self::PING_QUERY ) {
954 $this->mRTTEstimate = $queryRuntime;
957 $this->trxProfiler->recordQueryCompletion(
960 $this->queryLogger->debug( $sql, [
962 'master' => $isMaster,
963 'runtime' => $queryRuntime,
982 $indicativeOfReplicaRuntime =
true;
983 if ( $runtime > self::SLOW_WRITE_SEC ) {
986 if ( $verb ===
'INSERT' ) {
987 $indicativeOfReplicaRuntime = $this->
affectedRows() > self::SMALL_WRITE_ROWS;
988 } elseif ( $verb ===
'REPLACE' ) {
989 $indicativeOfReplicaRuntime = $this->
affectedRows() > self::SMALL_WRITE_ROWS / 2;
993 $this->mTrxWriteDuration += $runtime;
994 $this->mTrxWriteQueryCount += 1;
995 if ( $indicativeOfReplicaRuntime ) {
996 $this->mTrxWriteAdjDuration += $runtime;
997 $this->mTrxWriteAdjQueryCount += 1;
1002 # Transaction dropped; this can mean lost writes, or REPEATABLE-READ snapshots.
1003 # Dropped connections also mean that named locks are automatically released.
1004 # Only allow error suppression in autocommit mode or when the lost transaction
1005 # didn't matter anyway (aside from DBO_TRX snapshot loss).
1006 if ( $this->mNamedLocksHeld ) {
1008 } elseif ( $sql ===
'COMMIT' ) {
1009 return !$priorWritesPending;
1010 } elseif ( $sql ===
'ROLLBACK' ) {
1014 } elseif ( $priorWritesPending ) {
1022 $this->mTrxLevel = 0;
1023 $this->mTrxIdleCallbacks = [];
1024 $this->mTrxPreCommitCallbacks = [];
1025 $this->mSessionTempTables = [];
1026 $this->mNamedLocksHeld = [];
1040 $this->queryLogger->debug(
"SQL ERROR (ignored): $error\n" );
1042 $sql1line = mb_substr( str_replace(
"\n",
"\\n", $sql ), 0, 5 * 1024 );
1043 $this->queryLogger->error(
1044 "{fname}\t{db_server}\t{errno}\t{error}\t{sql1line}",
1046 'method' => __METHOD__,
1049 'sql1line' => $sql1line,
1053 $this->queryLogger->debug(
"SQL ERROR: " . $error .
"\n" );
1064 if ( $var ===
'*' ) {
1081 if ( $row !==
false ) {
1082 return reset( $row );
1089 $table, $var, $cond =
'',
$fname = __METHOD__,
$options = [], $join_conds = []
1091 if ( $var ===
'*' ) {
1093 } elseif ( !is_string( $var ) ) {
1102 if (
$res ===
false ) {
1107 foreach (
$res as $row ) {
1108 $values[] = $row->$var;
1124 $preLimitTail = $postLimitTail =
'';
1130 if ( is_numeric( $key ) ) {
1131 $noKeyOptions[$option] =
true;
1145 if ( isset( $noKeyOptions[
'FOR UPDATE'] ) ) {
1146 $postLimitTail .=
' FOR UPDATE';
1149 if ( isset( $noKeyOptions[
'LOCK IN SHARE MODE'] ) ) {
1150 $postLimitTail .=
' LOCK IN SHARE MODE';
1153 if ( isset( $noKeyOptions[
'DISTINCT'] ) || isset( $noKeyOptions[
'DISTINCTROW'] ) ) {
1154 $startOpts .=
'DISTINCT';
1157 # Various MySQL extensions
1158 if ( isset( $noKeyOptions[
'STRAIGHT_JOIN'] ) ) {
1159 $startOpts .=
' /*! STRAIGHT_JOIN */';
1162 if ( isset( $noKeyOptions[
'HIGH_PRIORITY'] ) ) {
1163 $startOpts .=
' HIGH_PRIORITY';
1166 if ( isset( $noKeyOptions[
'SQL_BIG_RESULT'] ) ) {
1167 $startOpts .=
' SQL_BIG_RESULT';
1170 if ( isset( $noKeyOptions[
'SQL_BUFFER_RESULT'] ) ) {
1171 $startOpts .=
' SQL_BUFFER_RESULT';
1174 if ( isset( $noKeyOptions[
'SQL_SMALL_RESULT'] ) ) {
1175 $startOpts .=
' SQL_SMALL_RESULT';
1178 if ( isset( $noKeyOptions[
'SQL_CALC_FOUND_ROWS'] ) ) {
1179 $startOpts .=
' SQL_CALC_FOUND_ROWS';
1182 if ( isset( $noKeyOptions[
'SQL_CACHE'] ) ) {
1183 $startOpts .=
' SQL_CACHE';
1186 if ( isset( $noKeyOptions[
'SQL_NO_CACHE'] ) ) {
1187 $startOpts .=
' SQL_NO_CACHE';
1190 if ( isset(
$options[
'USE INDEX'] ) && is_string(
$options[
'USE INDEX'] ) ) {
1195 if ( isset(
$options[
'IGNORE INDEX'] ) && is_string(
$options[
'IGNORE INDEX'] ) ) {
1201 return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
1214 if ( isset(
$options[
'GROUP BY'] ) ) {
1215 $gb = is_array(
$options[
'GROUP BY'] )
1216 ? implode(
',',
$options[
'GROUP BY'] )
1218 $sql .=
' GROUP BY ' . $gb;
1220 if ( isset(
$options[
'HAVING'] ) ) {
1221 $having = is_array(
$options[
'HAVING'] )
1224 $sql .=
' HAVING ' . $having;
1239 if ( isset(
$options[
'ORDER BY'] ) ) {
1240 $ob = is_array(
$options[
'ORDER BY'] )
1241 ? implode(
',',
$options[
'ORDER BY'] )
1244 return ' ORDER BY ' . $ob;
1251 $options = [], $join_conds = [] ) {
1260 if ( is_array(
$vars ) ) {
1265 $useIndexes = ( isset(
$options[
'USE INDEX'] ) && is_array(
$options[
'USE INDEX'] ) )
1269 isset(
$options[
'IGNORE INDEX'] ) &&
1270 is_array(
$options[
'IGNORE INDEX'] )
1275 if ( is_array( $table ) ) {
1278 $table, $useIndexes, $ignoreIndexes, $join_conds );
1279 } elseif ( $table !=
'' ) {
1280 if ( $table[0] ==
' ' ) {
1281 $from =
' FROM ' . $table;
1285 [ $table ], $useIndexes, $ignoreIndexes, [] );
1291 list( $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ) =
1294 if ( !empty( $conds ) ) {
1295 if ( is_array( $conds ) ) {
1298 $sql =
"SELECT $startOpts $vars $from $useIndex $ignoreIndex " .
1299 "WHERE $conds $preLimitTail";
1301 $sql =
"SELECT $startOpts $vars $from $useIndex $ignoreIndex $preLimitTail";
1304 if ( isset(
$options[
'LIMIT'] ) ) {
1308 $sql =
"$sql $postLimitTail";
1310 if ( isset(
$options[
'EXPLAIN'] ) ) {
1311 $sql =
'EXPLAIN ' . $sql;
1324 if (
$res ===
false ) {
1345 $rows = ( isset( $row[
'rowcount'] ) ) ? (
int)$row[
'rowcount'] : 0;
1356 $res = $this->
query(
"SELECT COUNT(*) AS rowcount FROM ($sql) tmp_count",
$fname );
1360 $rows = ( isset( $row[
'rowcount'] ) ) ? (
int)$row[
'rowcount'] : 0;
1375 # This does the same as the regexp below would do, but in such a way
1376 # as to avoid crashing php on some large strings.
1377 # $sql = preg_replace( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql );
1379 $sql = str_replace(
"\\\\",
'', $sql );
1380 $sql = str_replace(
"\\'",
'', $sql );
1381 $sql = str_replace(
"\\\"",
'', $sql );
1382 $sql = preg_replace(
"/'.*'/s",
"'X'", $sql );
1383 $sql = preg_replace(
'/".*"/s',
"'X'", $sql );
1385 # All newlines, tabs, etc replaced by single space
1386 $sql = preg_replace(
'/\s+/',
' ', $sql );
1389 # except the ones surrounded by characters, e.g. l10n
1390 $sql = preg_replace(
'/-?\d+(,-?\d+)+/s',
'N,...,N', $sql );
1391 $sql = preg_replace(
'/(?<![a-zA-Z])-?\d+(?![a-zA-Z])/s',
'N', $sql );
1397 $info = $this->
fieldInfo( $table, $field );
1408 if ( is_null( $info ) ) {
1411 return $info !==
false;
1416 $tableRaw = $this->
tableName( $table,
'raw' );
1417 if ( isset( $this->mSessionTempTables[$tableRaw] ) ) {
1430 $indexInfo = $this->
indexInfo( $table, $index );
1432 if ( !$indexInfo ) {
1436 return !$indexInfo[0]->Non_unique;
1450 # No rows to insert, easy just return now
1451 if ( !count( $a ) ) {
1462 if ( isset(
$options[
'fileHandle'] ) ) {
1467 if ( isset( $a[0] ) && is_array( $a[0] ) ) {
1469 $keys = array_keys( $a[0] );
1472 $keys = array_keys( $a );
1476 " INTO $table (" . implode(
',',
$keys ) .
') VALUES ';
1480 foreach ( $a
as $row ) {
1486 $sql .=
'(' . $this->
makeList( $row ) .
')';
1489 $sql .=
'(' . $this->
makeList( $a ) .
')';
1492 if ( $fh !== null &&
false === fwrite( $fh, $sql ) ) {
1494 } elseif ( $fh !== null ) {
1514 if ( in_array(
'IGNORE',
$options ) ) {
1530 return implode(
' ', $opts );
1538 if ( $conds !== [] && $conds !==
'*' ) {
1546 if ( !is_array( $a ) ) {
1547 throw new DBUnexpectedError( $this, __METHOD__ .
' called with incorrect parameters' );
1553 foreach ( $a
as $field =>
$value ) {
1567 $list .=
"($value)";
1574 $includeNull =
false;
1575 foreach ( array_keys(
$value, null,
true )
as $nullKey ) {
1576 $includeNull =
true;
1577 unset(
$value[$nullKey] );
1579 if ( count(
$value ) == 0 && !$includeNull ) {
1581 __METHOD__ .
": empty input for field $field" );
1582 } elseif ( count(
$value ) == 0 ) {
1584 $list .=
"$field IS NULL";
1587 if ( $includeNull ) {
1591 if ( count(
$value ) == 1 ) {
1601 if ( $includeNull ) {
1602 $list .=
" OR $field IS NULL)";
1605 } elseif (
$value === null ) {
1607 $list .=
"$field IS ";
1609 $list .=
"$field = ";
1616 $list .=
"$field = ";
1628 foreach ( $data
as $base => $sub ) {
1629 if ( count( $sub ) ) {
1631 [ $baseKey =>
$base, $subKey => array_keys( $sub ) ],
1652 public function bitAnd( $fieldLeft, $fieldRight ) {
1653 return "($fieldLeft & $fieldRight)";
1656 public function bitOr( $fieldLeft, $fieldRight ) {
1657 return "($fieldLeft | $fieldRight)";
1661 return 'CONCAT(' . implode(
',', $stringList ) .
')';
1665 $delim, $table, $field, $conds =
'', $join_conds = []
1667 $fld =
"GROUP_CONCAT($field SEPARATOR " . $this->
addQuotes( $delim ) .
')';
1669 return '(' . $this->
selectSQLText( $table, $fld, $conds, null, [], $join_conds ) .
')';
1677 # Stub. Shouldn't cause serious problems if it's not overridden, but
1678 # if your database engine supports a concept similar to MySQL's
1679 # databases you may as well.
1680 $this->mDBname = $db;
1694 # Skip the entire process when we have a string quoted on both ends.
1695 # Note that we check the end so that we will still quote any use of
1696 # use of `database`.table. But won't break things if someone wants
1697 # to query a database table with a dot in the name.
1702 # Lets test for any bits of text that should never show up in a table
1703 # name. Basically anything like JOIN or ON which are actually part of
1704 # SQL queries, but may end up inside of the table value to combine
1705 # sql. Such as how the API is doing.
1706 # Note that we use a whitespace test rather than a \b test to avoid
1707 # any remote case where a word like on may be inside of a table name
1708 # surrounded by symbols which may be considered word breaks.
1709 if ( preg_match(
'/(^|\s)(DISTINCT|JOIN|ON|AS)(\s|$)/i',
$name ) !== 0 ) {
1713 # Split database and table into proper variables.
1714 # We reverse the explode so that database.table and table both output
1715 # the correct table.
1716 $dbDetails = explode(
'.',
$name, 3 );
1717 if ( count( $dbDetails ) == 3 ) {
1718 list( $database, $schema, $table ) = $dbDetails;
1719 # We don't want any prefix added in this case
1721 } elseif ( count( $dbDetails ) == 2 ) {
1722 list( $database, $table ) = $dbDetails;
1723 # We don't want any prefix added in this case
1725 # In dbs that support it, $database may actually be the schema
1726 # but that doesn't affect any of the functionality here
1729 list( $table ) = $dbDetails;
1730 if ( isset( $this->tableAliases[$table] ) ) {
1731 $database = $this->tableAliases[$table][
'dbname'];
1732 $schema = is_string( $this->tableAliases[$table][
'schema'] )
1733 ? $this->tableAliases[$table][
'schema']
1735 $prefix = is_string( $this->tableAliases[$table][
'prefix'] )
1736 ? $this->tableAliases[$table][
'prefix']
1745 # Quote $table and apply the prefix if not quoted.
1746 # $tableName might be empty if this is called from Database::replaceVars()
1747 $tableName =
"{$prefix}{$table}";
1748 if ( $format ===
'quoted'
1750 && $tableName !==
''
1755 # Quote $schema and $database and merge them with the table name if needed
1769 if ( strlen( $namespace ) ) {
1773 $relation = $namespace .
'.' . $relation;
1780 $inArray = func_get_args();
1783 foreach ( $inArray
as $name ) {
1791 $inArray = func_get_args();
1794 foreach ( $inArray
as $name ) {
1810 if ( !$alias || $alias ==
$name ) {
1825 foreach (
$tables as $alias => $table ) {
1826 if ( is_numeric( $alias ) ) {
1844 if ( !$alias || (
string)$alias === (
string)
$name ) {
1859 foreach ( $fields
as $alias => $field ) {
1860 if ( is_numeric( $alias ) ) {
1880 $tables, $use_index = [], $ignore_index = [], $join_conds = []
1884 $use_index = (
array)$use_index;
1885 $ignore_index = (
array)$ignore_index;
1886 $join_conds = (
array)$join_conds;
1888 foreach (
$tables as $alias => $table ) {
1889 if ( !is_string( $alias ) ) {
1894 if ( isset( $join_conds[$alias] ) ) {
1895 list( $joinType, $conds ) = $join_conds[$alias];
1896 $tableClause = $joinType;
1898 if ( isset( $use_index[$alias] ) ) {
1901 $tableClause .=
' ' . $use;
1904 if ( isset( $ignore_index[$alias] ) ) {
1906 implode(
',', (
array)$ignore_index[$alias] ) );
1907 if ( $ignore !=
'' ) {
1908 $tableClause .=
' ' . $ignore;
1913 $tableClause .=
' ON (' . $on .
')';
1916 $retJOIN[] = $tableClause;
1917 } elseif ( isset( $use_index[$alias] ) ) {
1921 implode(
',', (
array)$use_index[$alias] )
1924 $ret[] = $tableClause;
1925 } elseif ( isset( $ignore_index[$alias] ) ) {
1929 implode(
',', (
array)$ignore_index[$alias] )
1932 $ret[] = $tableClause;
1936 $ret[] = $tableClause;
1941 $implicitJoins = !empty(
$ret ) ? implode(
',',
$ret ) :
"";
1942 $explicitJoins = !empty( $retJOIN ) ? implode(
' ', $retJOIN ) :
"";
1945 return implode(
' ', [ $implicitJoins, $explicitJoins ] );
1959 if (
$s instanceof
Blob ) {
1962 if (
$s === null ) {
1964 } elseif ( is_bool(
$s ) ) {
1967 # This will also quote numeric values. This should be harmless,
1968 # and protects against weird problems that occur when they really
1969 # _are_ strings such as article titles and string->number->string
1970 # conversion is not 1:1.
1985 return '"' . str_replace(
'"',
'""',
$s ) .
'"';
1998 return $name[0] ==
'"' && substr(
$name, -1, 1 ) ==
'"';
2006 return addcslashes(
$s,
'\%_' );
2020 $s .= $value->toString();
2026 return " LIKE {$this->addQuotes( $s )} ";
2070 $quotedTable = $this->
tableName( $table );
2072 if ( count( $rows ) == 0 ) {
2077 if ( !is_array( reset( $rows ) ) ) {
2082 foreach ( $rows
as $row ) {
2083 # Delete rows which collide
2084 if ( $uniqueIndexes ) {
2085 $sql =
"DELETE FROM $quotedTable WHERE ";
2087 foreach ( $uniqueIndexes
as $index ) {
2094 if ( is_array( $index ) ) {
2096 foreach ( $index
as $col ) {
2102 $sql .= $col .
'=' . $this->
addQuotes( $row[$col] );
2105 $sql .= $index .
'=' . $this->
addQuotes( $row[$index] );
2112 # Now insert the row
2131 if ( !is_array( reset( $rows ) ) ) {
2135 $sql =
"REPLACE INTO $table (" . implode(
',', array_keys( $rows[0] ) ) .
') VALUES ';
2138 foreach ( $rows
as $row ) {
2145 $sql .=
'(' . $this->
makeList( $row ) .
')';
2154 if ( !count( $rows ) ) {
2158 if ( !is_array( reset( $rows ) ) ) {
2162 if ( count( $uniqueIndexes ) ) {
2164 foreach ( $rows
as $row ) {
2165 foreach ( $uniqueIndexes
as $index ) {
2166 $index = is_array( $index ) ? $index : [ $index ];
2168 foreach ( $index
as $column ) {
2169 $rowKey[$column] = $row[$column];
2181 $this->
begin(
$fname, self::TRANSACTION_INTERNAL );
2184 # Update any existing conflicting row(s)
2185 if ( $where !==
false ) {
2190 # Now insert any non-conflicting row(s)
2191 $ok = $this->
insert( $table, $rows,
$fname, [
'IGNORE' ] ) && $ok;
2205 public function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds,
2212 $delTable = $this->
tableName( $delTable );
2213 $joinTable = $this->
tableName( $joinTable );
2214 $sql =
"DELETE FROM $delTable WHERE $delVar IN (SELECT $joinVar FROM $joinTable ";
2215 if ( $conds !=
'*' ) {
2225 $sql =
"SHOW COLUMNS FROM $table LIKE \"$field\";";
2226 $res = $this->
query( $sql, __METHOD__ );
2231 if ( preg_match(
'/\((.*)\)/', $row->Type, $m ) ) {
2240 public function delete( $table, $conds,
$fname = __METHOD__ ) {
2242 throw new DBUnexpectedError( $this, __METHOD__ .
' called with no conditions' );
2246 $sql =
"DELETE FROM $table";
2248 if ( $conds !=
'*' ) {
2249 if ( is_array( $conds ) ) {
2252 $sql .=
' WHERE ' . $conds;
2255 return $this->
query( $sql, $fname );
2259 $destTable, $srcTable, $varMap, $conds,
2260 $fname = __METHOD__, $insertOptions = [], $selectOptions = []
2262 if ( $this->cliMode ) {
2280 foreach ( $varMap
as $dstColumn => $sourceColumnOrSql ) {
2283 $selectOptions[] =
'FOR UPDATE';
2284 $res = $this->
select( $srcTable, implode(
',', $fields ), $conds, $fname, $selectOptions );
2290 foreach (
$res as $row ) {
2291 $rows[] = (
array)$row;
2294 return $this->
insert( $destTable, $rows, $fname, $insertOptions );
2298 $fname = __METHOD__,
2299 $insertOptions = [], $selectOptions = []
2301 $destTable = $this->
tableName( $destTable );
2303 if ( !is_array( $insertOptions ) ) {
2304 $insertOptions = [ $insertOptions ];
2309 if ( !is_array( $selectOptions ) ) {
2310 $selectOptions = [ $selectOptions ];
2316 if ( is_array( $srcTable ) ) {
2317 $srcTable = implode(
',', array_map( [ &$this,
'tableName' ], $srcTable ) );
2319 $srcTable = $this->
tableName( $srcTable );
2322 $sql =
"INSERT $insertOptions" .
2323 " INTO $destTable (" . implode(
',', array_keys( $varMap ) ) .
')' .
2324 " SELECT $startOpts " . implode(
',', $varMap ) .
2325 " FROM $srcTable $useIndex $ignoreIndex ";
2327 if ( $conds !=
'*' ) {
2328 if ( is_array( $conds ) ) {
2331 $sql .=
" WHERE $conds";
2334 $sql .=
" $tailOpts";
2336 return $this->
query( $sql, $fname );
2359 if ( !is_numeric(
$limit ) ) {
2361 "Invalid non-numeric limit passed to limitResult()\n" );
2364 return "$sql LIMIT "
2365 . ( ( is_numeric( $offset ) && $offset != 0 ) ?
"{$offset}," :
"" )
2374 $glue = $all ?
') UNION ALL (' :
') UNION (';
2376 return '(' . implode( $glue, $sqls ) .
')';
2380 if ( is_array( $cond ) ) {
2384 return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) ";
2388 return "REPLACE({$orig}, {$old}, {$new})";
2422 $args = func_get_args();
2423 $function = array_shift(
$args );
2424 $tries = self::DEADLOCK_TRIES;
2426 $this->
begin( __METHOD__ );
2433 $retVal = call_user_func_array( $function,
$args );
2438 usleep( mt_rand( self::DEADLOCK_DELAY_MIN, self::DEADLOCK_DELAY_MAX ) );
2444 }
while ( --$tries > 0 );
2446 if ( $tries <= 0 ) {
2451 $this->
commit( __METHOD__ );
2458 # Real waits are implemented in the subclass.
2477 if ( !$this->mTrxLevel ) {
2480 $this->mTrxEndCallbacks[] = [ $callback,
$fname ];
2484 $this->mTrxIdleCallbacks[] = [ $callback,
$fname ];
2485 if ( !$this->mTrxLevel ) {
2491 if ( $this->mTrxLevel ) {
2492 $this->mTrxPreCommitCallbacks[] = [ $callback,
$fname ];
2497 call_user_func( $callback );
2500 $this->
rollback( __METHOD__, self::FLUSHING_INTERNAL );
2508 $this->mTrxRecurringCallbacks[
$name] = $callback;
2510 unset( $this->mTrxRecurringCallbacks[
$name] );
2523 $this->mTrxEndCallbacksSuppressed = $suppress;
2536 if ( $this->mTrxEndCallbacksSuppressed ) {
2544 $callbacks = array_merge(
2545 $this->mTrxIdleCallbacks,
2546 $this->mTrxEndCallbacks
2548 $this->mTrxIdleCallbacks = [];
2549 $this->mTrxEndCallbacks = [];
2550 foreach ( $callbacks
as $callback ) {
2552 list( $phpCallback ) = $callback;
2554 call_user_func_array( $phpCallback, [ $trigger ] );
2561 call_user_func( $this->errorLogger, $ex );
2566 $this->
rollback( __METHOD__, self::FLUSHING_INTERNAL );
2570 }
while ( count( $this->mTrxIdleCallbacks ) );
2589 $this->mTrxPreCommitCallbacks = [];
2590 foreach ( $callbacks
as $callback ) {
2592 list( $phpCallback ) = $callback;
2593 call_user_func( $phpCallback );
2595 call_user_func( $this->errorLogger, $ex );
2599 }
while ( count( $this->mTrxPreCommitCallbacks ) );
2616 if ( $this->mTrxEndCallbacksSuppressed ) {
2623 foreach ( $this->mTrxRecurringCallbacks
as $phpCallback ) {
2625 $phpCallback( $trigger, $this );
2627 call_user_func( $this->errorLogger, $ex );
2638 if ( !$this->mTrxLevel ) {
2639 $this->
begin( $fname, self::TRANSACTION_INTERNAL );
2643 $this->mTrxAutomaticAtomic =
true;
2647 $this->mTrxAtomicLevels[] =
$fname;
2651 if ( !$this->mTrxLevel ) {
2652 throw new DBUnexpectedError( $this,
"No atomic transaction is open (got $fname)." );
2654 if ( !$this->mTrxAtomicLevels ||
2655 array_pop( $this->mTrxAtomicLevels ) !== $fname
2657 throw new DBUnexpectedError( $this,
"Invalid atomic section ended (got $fname)." );
2660 if ( !$this->mTrxAtomicLevels && $this->mTrxAutomaticAtomic ) {
2661 $this->
commit( $fname, self::FLUSHING_INTERNAL );
2668 $res = call_user_func_array( $callback, [ $this, $fname ] );
2670 $this->
rollback( $fname, self::FLUSHING_INTERNAL );
2678 final public function begin( $fname = __METHOD__, $mode = self::TRANSACTION_EXPLICIT ) {
2680 if ( $this->mTrxLevel ) {
2681 if ( $this->mTrxAtomicLevels ) {
2682 $levels = implode(
', ', $this->mTrxAtomicLevels );
2683 $msg =
"$fname: Got explicit BEGIN while atomic section(s) $levels are open.";
2685 } elseif ( !$this->mTrxAutomatic ) {
2686 $msg =
"$fname: Explicit transaction already active (from {$this->mTrxFname}).";
2690 $msg =
"$fname: Implicit transaction already active (from {$this->mTrxFname}).";
2691 $this->queryLogger->error( $msg );
2696 $msg =
"$fname: Implicit transaction expected (DBO_TRX set).";
2697 $this->queryLogger->error( $msg );
2705 $this->mTrxTimestamp = microtime(
true );
2706 $this->mTrxFname =
$fname;
2707 $this->mTrxDoneWrites =
false;
2708 $this->mTrxAutomaticAtomic =
false;
2709 $this->mTrxAtomicLevels = [];
2710 $this->mTrxShortId = sprintf(
'%06x', mt_rand( 0, 0xffffff ) );
2711 $this->mTrxWriteDuration = 0.0;
2712 $this->mTrxWriteQueryCount = 0;
2713 $this->mTrxWriteAdjDuration = 0.0;
2714 $this->mTrxWriteAdjQueryCount = 0;
2715 $this->mTrxWriteCallers = [];
2720 $this->mTrxReplicaLag =
$status[
'lag'] + ( microtime(
true ) -
$status[
'since'] );
2724 $this->mTrxAutomatic = ( $mode === self::TRANSACTION_INTERNAL );
2734 $this->
query(
'BEGIN', $fname );
2735 $this->mTrxLevel = 1;
2738 final public function commit( $fname = __METHOD__, $flush =
'' ) {
2739 if ( $this->mTrxLevel && $this->mTrxAtomicLevels ) {
2741 $levels = implode(
', ', $this->mTrxAtomicLevels );
2744 "$fname: Got COMMIT while atomic sections $levels are still open."
2748 if ( $flush === self::FLUSHING_INTERNAL || $flush === self::FLUSHING_ALL_PEERS ) {
2749 if ( !$this->mTrxLevel ) {
2751 } elseif ( !$this->mTrxAutomatic ) {
2754 "$fname: Flushing an explicit transaction, getting out of sync."
2758 if ( !$this->mTrxLevel ) {
2759 $this->queryLogger->error(
2760 "$fname: No transaction to commit, something got out of sync." );
2762 } elseif ( $this->mTrxAutomatic ) {
2764 $msg =
"$fname: Explicit commit of implicit transaction.";
2765 $this->queryLogger->error( $msg );
2776 if ( $this->mTrxDoneWrites ) {
2777 $this->mLastWriteTime = microtime(
true );
2778 $this->trxProfiler->transactionWritingOut(
2779 $this->mServer, $this->mDBname, $this->mTrxShortId, $writeTime );
2793 if ( $this->mTrxLevel ) {
2794 $this->
query(
'COMMIT', $fname );
2795 $this->mTrxLevel = 0;
2799 final public function rollback( $fname = __METHOD__, $flush =
'' ) {
2800 if ( $flush === self::FLUSHING_INTERNAL || $flush === self::FLUSHING_ALL_PEERS ) {
2801 if ( !$this->mTrxLevel ) {
2805 if ( !$this->mTrxLevel ) {
2806 $this->queryLogger->error(
2807 "$fname: No transaction to rollback, something got out of sync." );
2812 "$fname: Expected mass rollback of all peer databases (DBO_TRX set)."
2821 $this->mTrxAtomicLevels = [];
2822 if ( $this->mTrxDoneWrites ) {
2823 $this->trxProfiler->transactionWritingOut(
2824 $this->mServer, $this->mDBname, $this->mTrxShortId );
2827 $this->mTrxIdleCallbacks = [];
2828 $this->mTrxPreCommitCallbacks = [];
2840 if ( $this->mTrxLevel ) {
2841 # Disconnects cause rollback anyway, so ignore those errors
2842 $ignoreErrors =
true;
2843 $this->
query(
'ROLLBACK', $fname, $ignoreErrors );
2844 $this->mTrxLevel = 0;
2854 "$fname: Cannot flush snapshot because writes are pending ($fnames)."
2858 $this->
commit( $fname, self::FLUSHING_INTERNAL );
2883 throw new RuntimeException( __METHOD__ .
' is not implemented in descendant class' );
2886 public function listTables( $prefix = null, $fname = __METHOD__ ) {
2887 throw new RuntimeException( __METHOD__ .
' is not implemented in descendant class' );
2890 public function listViews( $prefix = null, $fname = __METHOD__ ) {
2891 throw new RuntimeException( __METHOD__ .
' is not implemented in descendant class' );
2897 return $t->getTimestamp(
TS_MW );
2901 if ( is_null( $ts ) ) {
2926 } elseif (
$result ===
true ) {
2930 return new ResultWrapper( $this,
$result );
2934 public function ping( &$rtt = null ) {
2936 if ( $this->
isOpen() && ( microtime(
true ) - $this->lastPing ) < self::PING_TTL ) {
2937 if ( !func_num_args() || $this->mRTTEstimate > 0 ) {
2945 $ok = ( $this->
query( self::PING_QUERY, __METHOD__,
true ) !==
false );
2960 $this->mOpened =
false;
2961 $this->mConn =
false;
2963 $this->
open( $this->mServer, $this->mUser, $this->mPassword, $this->mDBname );
2964 $this->lastPing = microtime(
true );
2989 return $this->mTrxLevel
3003 'since' => microtime(
true )
3026 $res = [
'lag' => 0,
'since' => INF,
'pending' =>
false ];
3027 foreach ( func_get_args()
as $db ) {
3029 $status = $db->getSessionLagStatus();
3030 if (
$status[
'lag'] ===
false ) {
3031 $res[
'lag'] =
false;
3032 } elseif (
$res[
'lag'] !==
false ) {
3036 $res[
'pending'] =
$res[
'pending'] ?: $db->writesPending();
3055 if ( $b instanceof
Blob ) {
3066 callable $lineCallback = null,
3067 callable $resultCallback = null,
3069 callable $inputCallback = null
3071 MediaWiki\suppressWarnings();
3072 $fp = fopen( $filename,
'r' );
3073 MediaWiki\restoreWarnings();
3075 if (
false === $fp ) {
3080 $fname = __METHOD__ .
"( $filename )";
3085 $fp, $lineCallback, $resultCallback, $fname, $inputCallback );
3097 $this->mSchemaVars =
$vars;
3102 callable $lineCallback = null,
3103 callable $resultCallback = null,
3104 $fname = __METHOD__,
3105 callable $inputCallback = null
3109 while ( !feof( $fp ) ) {
3110 if ( $lineCallback ) {
3111 call_user_func( $lineCallback );
3114 $line = trim( fgets( $fp ) );
3116 if (
$line ==
'' ) {
3132 if ( $done || feof( $fp ) ) {
3135 if ( !$inputCallback || call_user_func( $inputCallback, $cmd ) ) {
3138 if ( $resultCallback ) {
3139 call_user_func( $resultCallback,
$res, $this );
3142 if (
false ===
$res ) {
3145 return "Query \"{$cmd}\" failed with error code \"$err\".\n";
3163 if ( $this->delimiter ) {
3165 $newLine = preg_replace(
3166 '/' . preg_quote( $this->delimiter,
'/' ) .
'$/',
'', $newLine );
3167 if ( $newLine != $prev ) {
3197 return preg_replace_callback(
3199 /\* (\$wgDBprefix|[_i]) \*/ (\w*) | # 1-2. tableName, indexName
3200 \'\{\$ (\w+) }\' | # 3. addQuotes
3201 `\{\$ (\w+) }` | # 4. addIdentifierQuotes
3202 /\*\$ (\w+) \*/ # 5. leave unencoded
3207 if ( isset( $m[1] ) && $m[1] !==
'' ) {
3208 if ( $m[1] ===
'i' ) {
3213 } elseif ( isset( $m[3] ) && $m[3] !==
'' && array_key_exists( $m[3],
$vars ) ) {
3215 } elseif ( isset( $m[4] ) && $m[4] !==
'' && array_key_exists( $m[4],
$vars ) ) {
3217 } elseif ( isset( $m[5] ) && $m[5] !==
'' && array_key_exists( $m[5],
$vars ) ) {
3218 return $vars[$m[5]];
3234 if ( $this->mSchemaVars ) {
3257 public function lock( $lockName, $method, $timeout = 5 ) {
3258 $this->mNamedLocksHeld[$lockName] = 1;
3263 public function unlock( $lockName, $method ) {
3264 unset( $this->mNamedLocksHeld[$lockName] );
3275 "$fname: Cannot flush pre-lock snapshot because writes are pending ($fnames)."
3279 if ( !$this->
lock( $lockKey, $fname, $timeout ) ) {
3283 $unlocker =
new ScopedCallback(
function ()
use ( $lockKey, $fname ) {
3289 function ()
use ( $lockKey, $fname ) {
3290 $this->
unlock( $lockKey, $fname );
3295 $this->
unlock( $lockKey, $fname );
3299 $this->
commit( $fname, self::FLUSHING_INTERNAL );
3317 public function lockTables( $read, $write, $method, $lowPriority =
true ) {
3338 public function dropTable( $tableName, $fName = __METHOD__ ) {
3339 if ( !$this->
tableExists( $tableName, $fName ) ) {
3342 $sql =
"DROP TABLE " . $this->
tableName( $tableName ) .
" CASCADE";
3344 return $this->
query( $sql, $fName );
3352 return ( $expiry ==
'' || $expiry ==
'infinity' || $expiry == $this->
getInfinity() )
3358 if ( $expiry ==
'' || $expiry ==
'infinity' || $expiry == $this->
getInfinity() ) {
3377 $reason = $this->
getLBInfo(
'readOnlyReason' );
3379 return is_string( $reason ) ? $reason :
false;
3383 $this->tableAliases = $aliases;
3406 if ( !$this->mConn ) {
3409 'DB connection was already closed or the connection dropped.'
3429 $this->connLogger->warning(
3430 "Cloning " . get_class( $this ) .
" is not recomended; forking connection:\n" .
3436 $this->mOpened =
false;
3437 $this->mConn =
false;
3438 $this->mTrxEndCallbacks = [];
3440 $this->
open( $this->mServer, $this->mUser, $this->mPassword, $this->mDBname );
3441 $this->lastPing = microtime(
true );
3451 throw new RuntimeException(
'Database serialization may cause problems, since ' .
3452 'the connection is not restored on wakeup.' );
3459 if ( $this->mTrxLevel && $this->mTrxDoneWrites ) {
3460 trigger_error(
"Uncommitted DB writes (transaction from {$this->mTrxFname})." );
3464 if ( $danglingWriters ) {
3465 $fnames = implode(
', ', $danglingWriters );
3466 trigger_error(
"DB transaction writes or callbacks still pending ($fnames)." );
3469 if ( $this->mConn ) {
3472 \MediaWiki\suppressWarnings();
3474 \MediaWiki\restoreWarnings();
3475 $this->mConn =
false;
3476 $this->mOpened =
false;
3490 class_alias(
'Database',
'DatabaseBase' );
rollback($fname=__METHOD__, $flush= '')
Rollback a transaction previously started using begin().
isTransactableQuery($sql)
Determine whether a SQL statement is sensitive to isolation level.
Library for creating, parsing, and converting timestamps.
decodeExpiry($expiry, $format=TS_MW)
Decode an expiry time into a DBMS independent format.
masterPosWait(DBMasterPos $pos, $timeout)
Wait for the replica DB to catch up to a given master position.
commit($fname=__METHOD__, $flush= '')
Commits a transaction previously started using begin().
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
reportQueryError($error, $errno, $sql, $fname, $tempIgnore=false)
Report a query error.
getInfinity()
Find out when 'infinity' is.
canRecoverFromDisconnect($sql, $priorWritesPending)
string $agent
Agent name for query profiling.
__destruct()
Run a few simple sanity checks and close dangling connections.
tableExists($table, $fname=__METHOD__)
Query whether a given table exists.
float $mTrxWriteDuration
Seconds spent in write queries for the current transaction.
the array() calling protocol came about after MediaWiki 1.4rc1.
bool $cliMode
Whether this PHP instance is for a CLI script.
TransactionProfiler $trxProfiler
reportConnectionError($error= 'Unknown error')
array[] $mTrxEndCallbacks
List of (callable, method name)
select($table, $vars, $conds= '', $fname=__METHOD__, $options=[], $join_conds=[])
Execute a SELECT query constructed using the various parameters provided.
maxListLen()
Return the maximum number of items allowed in a list, or 0 for unlimited.
Utility classThis allows us to distinguish a blob from a normal string and an array of strings...
addIdentifierQuotes($s)
Quotes an identifier using backticks or "double quotes" depending on the database type...
writesOrCallbacksPending()
Returns true if there is a transaction open with possible write queries or transaction pre-commit/idl...
__sleep()
Called by serialize.
insert($table, $a, $fname=__METHOD__, $options=[])
INSERT wrapper, inserts an array into a table.
setLBInfo($name, $value=null)
Set the LB info array, or a member of it.
doCommit($fname)
Issues the COMMIT command to the database server.
static factory($dbType, $p=[])
Construct a Database subclass instance given a database type and parameters.
bufferResults($buffer=null)
Turns buffering of SQL result sets on (true) or off (false).
trxLevel()
Gets the current transaction level.
doneWrites()
Returns true if the connection may have been used for write queries.
setSessionOptions(array $options)
Override database's default behavior.
processing should stop and the error should be shown to the user * false
strencode($s)
Wrapper for addslashes()
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
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
wasReadOnlyError()
Determines if the last failure was due to the database being read-only.
tableNamesN()
Fetch a number of table names into an zero-indexed numerical array This is handy when you need to con...
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException'returning false will NOT prevent logging $e
buildConcat($stringList)
Build a concatenation list to feed into a SQL query.
static getCacheSetOptions(IDatabase $db1)
Merge the result of getSessionLagStatus() for several DBs using the most pessimistic values to estima...
float bool $mLastWriteTime
UNIX timestamp of last write query.
DatabaseDomain $currentDomain
float $lastPing
UNIX timestamp.
trxTimestamp()
Get the UNIX timestamp of the time that the transaction was established.
aggregateValue($valuedata, $valuename= 'value')
Return aggregated value alias.
setTableAliases(array $aliases)
Make certain table names use their own database, schema, and table prefix when passed into SQL querie...
doRollback($fname)
Issues the ROLLBACK command to the database server.
implicitGroupby()
Returns true if this database does an implicit sort when doing GROUP BY.
deadlockLoop()
Perform a deadlock-prone transaction.
runTransactionListenerCallbacks($trigger)
Actually run any "transaction listener" callbacks.
open($server, $user, $password, $dbName)
Open a connection to the database.
timestamp($ts=0)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
unlockTables($method)
Unlock specific tables.
BagOStuff $srvCache
APC cache.
freeResult($res)
Free a result object returned by query() or select().
getApproximateLagStatus()
Get a replica DB lag estimate for this server.
restoreFlags($state=self::RESTORE_PRIOR)
Restore the flags to their prior state before the last setFlag/clearFlag call.
selectRowCount($tables, $vars= '*', $conds= '', $fname=__METHOD__, $options=[], $join_conds=[])
Get the number of rows in dataset.
assertOpen()
Make sure isOpen() returns true as a sanity check.
getServerVersion()
A string describing the current software version, like from mysql_get_server_info().
update($table, $values, $conds, $fname=__METHOD__, $options=[])
UPDATE wrapper.
lastError()
Get a description of the last error.
__construct(array $params)
Constructor and database handle and attempt to connect to the DB server.
getServerInfo()
A string describing the current software version, and possibly other details in a user-friendly way...
pendingWriteAndCallbackCallers()
An object representing a master or replica DB position in a replicated setup.
tableNameWithAlias($name, $alias=false)
Get an aliased table name e.g.
makeUpdateOptionsArray($options)
Make UPDATE options array for Database::makeUpdateOptions.
array[] $mTrxIdleCallbacks
List of (callable, method name)
unionSupportsOrderAndLimit()
Returns true if current database backend supports ORDER BY or LIMIT for separate subqueries within th...
LoggerInterface $queryLogger
setFlag($flag, $remember=self::REMEMBER_NOTHING)
Set a flag for this connection.
callback $errorLogger
Error logging callback.
fieldInfo($table, $field)
mysql_fetch_field() wrapper Returns false if the field doesn't exist
integer $mTrxWriteAdjQueryCount
Number of write queries counted in mTrxWriteAdjDuration.
encodeBlob($b)
Some DBMSs have a special format for inserting into blob fields, they don't allow simple quoted strin...
tableName($name, $format= 'quoted')
Format a table name ready for use in constructing an SQL query.
bool $mTrxAutomatic
Record if the current transaction was started implicitly due to DBO_TRX being set.
tableNamesWithIndexClauseOrJOIN($tables, $use_index=[], $ignore_index=[], $join_conds=[])
Get the aliased table name clause for a FROM clause which might have a JOIN and/or USE INDEX or IGNOR...
anyChar()
Returns a token for buildLike() that denotes a '_' to be used in a LIKE query.
unionQueries($sqls, $all)
Construct a UNION query This is used for providing overload point for other DB abstractions not compa...
selectDB($db)
Change the current database.
lockIsFree($lockName, $method)
Check to see if a named lock is available (non-blocking)
fieldNameWithAlias($name, $alias=false)
Get an aliased field name e.g.
lastErrno()
Get the last error number.
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist & $tables
tableNames()
Fetch a number of table names into an array This is handy when you need to construct SQL for joins...
implicitOrderby()
Returns true if this database does an implicit order by when the column has an index For example: SEL...
selectRow($table, $vars, $conds, $fname=__METHOD__, $options=[], $join_conds=[])
Single row SELECT wrapper.
bool $mTrxEndCallbacksSuppressed
Whether to suppress triggering of transaction end callbacks.
makeOrderBy($options)
Returns an optional ORDER BY.
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message.Please note the header message cannot receive/use parameters. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item.Return false to stop further processing of the tag $reader:XMLReader object $logInfo:Array of information 'ImportHandlePageXMLTag':When parsing a XML tag in a page.Return false to stop further processing of the tag $reader:XMLReader object &$pageInfo:Array of information 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision.Return false to stop further processing of the tag $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information 'ImportHandleToplevelXMLTag':When parsing a top level XML tag.Return false to stop further processing of the tag $reader:XMLReader object 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload.Return false to stop further processing of the tag $reader:XMLReader object $revisionInfo:Array of information 'ImportLogInterwikiLink':Hook to change the interwiki link used in log entries and edit summaries for transwiki imports.&$fullInterwikiPrefix:Interwiki prefix, may contain colons.&$pageTitle:String that contains page title. 'ImportSources':Called when reading from the $wgImportSources configuration variable.Can be used to lazy-load the import sources list.&$importSources:The value of $wgImportSources.Modify as necessary.See the comment in DefaultSettings.php for the detail of how to structure this array. 'InfoAction':When building information to display on the action=info page.$context:IContextSource object &$pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect.&$title:Title object for the current page &$request:WebRequest &$ignoreRedirect:boolean to skip redirect check &$target:Title/string of redirect target &$article:Article object 'InternalParseBeforeLinks':during Parser's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings.&$parser:Parser object &$text:string containing partially parsed text &$stripState:Parser's internal StripState object 'InternalParseBeforeSanitize':during Parser's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings.Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments.&$parser:Parser object &$text:string containing partially parsed text &$stripState:Parser's internal StripState object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not.Return true without providing an interwiki to continue interwiki search.$prefix:interwiki prefix we are looking for.&$iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InvalidateEmailComplete':Called after a user's email has been invalidated successfully.$user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification.Callee may modify $url and $query, URL will be constructed as $url.$query &$url:URL to index.php &$query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) &$article:article(object) being checked 'IsTrustedProxy':Override the result of IP::isTrustedProxy() &$ip:IP being check &$result:Change this value to override the result of IP::isTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from &$allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of Sanitizer::validateEmail(), for instance to return false if the domain name doesn't match your organization.$addr:The e-mail address entered by the user &$result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user &$result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we're looking for a messages file for &$file:The messages file path, you can override this to change the location. 'LanguageGetMagic':DEPRECATED!Use $magicWords in a file listed in $wgExtensionMessagesFiles instead.Use this to define synonyms of magic words depending of the language &$magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces.Do not use this hook to add namespaces.Use CanonicalNamespaces for that.&$namespaces:Array of namespaces indexed by their numbers 'LanguageGetSpecialPageAliases':DEPRECATED!Use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead.Use to define aliases of special pages names depending of the language &$specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names.&$names:array of language code=> language name $code:language of the preferred translations 'LanguageLinks':Manipulate a page's language links.This is called in various places to allow extensions to define the effective language links for a page.$title:The page's Title.&$links:Associative array mapping language codes to prefixed links of the form"language:title".&$linkFlags:Associative array mapping prefixed links to arrays of flags.Currently unused, but planned to provide support for marking individual language links in the UI, e.g.for featured articles. 'LanguageSelector':Hook to change the language selector available on a page.$out:The output page.$cssClassName:CSS class name of the language selector. 'LinkBegin':DEPRECATED!Use HtmlPageLinkRendererBegin instead.Used when generating internal and interwiki links in Linker::link(), before processing starts.Return false to skip default processing and return $ret.See documentation for Linker::link() for details on the expected meanings of parameters.$skin:the Skin object $target:the Title that the link is pointing to &$html:the contents that the< a > tag should have(raw HTML) $result
affectedRows()
Get the number of rows affected by the last write query.
nativeReplace($table, $rows, $fname)
REPLACE query wrapper for MySQL and SQLite, which have a native REPLACE statement.
Class to handle database/prefix specification for IDatabase domains.
nextSequenceValue($seqName)
Returns an appropriately quoted sequence value for inserting a new row.
doProfiledQuery($sql, $commentedSql, $isWrite, $fname)
deleteJoin($delTable, $joinTable, $delVar, $joinVar, $conds, $fname=__METHOD__)
DELETE where the condition is a join.
indexName($index)
Get the name of an index in a given table.
timestampOrNull($ts=null)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
indexInfo($table, $index, $fname=__METHOD__)
Get information about an index into an object.
setLogger(LoggerInterface $logger)
setTransactionListener($name, callable $callback=null)
Run a callback each time any transaction commits or rolls back.
endAtomic($fname=__METHOD__)
Ends an atomic section of SQL statements.
updateTrxWriteQueryTime($sql, $runtime)
Update the estimated run-time of a query, not counting large row lock times.
startAtomic($fname=__METHOD__)
Begin an atomic section of statements.
begin($fname=__METHOD__, $mode=self::TRANSACTION_EXPLICIT)
Begin a transaction.
string $mLastQuery
SQL query.
makeGroupByWithHaving($options)
Returns an optional GROUP BY with an optional HAVING.
float $mRTTEstimate
RTT time estimate.
textFieldSize($table, $field)
Returns the size of a text field, or -1 for "unlimited".
onTransactionIdle(callable $callback, $fname=__METHOD__)
Run a callback as soon as there is no transaction pending.
getTransactionLagStatus()
Get the replica DB lag when the current transaction started.
object string $profiler
Class name or object With profileIn/profileOut methods.
close()
Closes a database connection.
Helper class that detects high-contention DB queries via profiling calls.
setLazyMasterHandle(IDatabase $conn)
Set a lazy-connecting DB handle to the master DB (for replication status purposes) ...
getLBInfo($name=null)
Get properties passed down from the server info array of the load balancer.
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
decodeBlob($b)
Some DBMSs return a special placeholder object representing blob fields in result objects...
lastDoneWrites()
Returns the last time the connection may have been used for write queries.
fetchObject($res)
Fetch the next row from the given result object, in object form.
dbSchema($schema=null)
Get/set the db schema.
ignoreIndexClause($index)
IGNORE INDEX clause.
doAtomicSection($fname, callable $callback)
Run a callback to do an atomic set of updates for this database.
const DEADLOCK_DELAY_MAX
Maximum time to wait before retry.
getFlag($flag)
Returns a boolean whether the flag $flag is set for this connection.
bitOr($fieldLeft, $fieldRight)
buildGroupConcatField($delim, $table, $field, $conds= '', $join_conds=[])
Build a GROUP_CONCAT or equivalent statement for a query.
sourceStream($fp, callable $lineCallback=null, callable $resultCallback=null, $fname=__METHOD__, callable $inputCallback=null)
Read and execute commands from an open file handle.
static generalizeSQL($sql)
Removes most variables from an SQL query and replaces them with X or N for numbers.
__clone()
Make sure that copies do not share the same client binding handle.
isOpen()
Is a connection to the database open?
makeList($a, $mode=self::LIST_COMMA)
Makes an encoded list of strings from an array.
string[] $mTrxWriteCallers
Track the write query callers of the current transaction.
clearFlag($flag, $remember=self::REMEMBER_NOTHING)
Clear a flag for this connection.
wfDeprecated($function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
const TS_MW
MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS)
insertSelect($destTable, $srcTable, $varMap, $conds, $fname=__METHOD__, $insertOptions=[], $selectOptions=[])
INSERT SELECT wrapper.
isQuotedIdentifier($name)
Returns if the given identifier looks quoted or not according to the database convention for quoting ...
wasConnectionError($errno)
Do not use this method outside of Database/DBError classes.
selectSQLText($table, $vars, $conds= '', $fname=__METHOD__, $options=[], $join_conds=[])
The equivalent of IDatabase::select() except that the constructed SQL is returned, instead of being immediately executed.
const DEADLOCK_DELAY_MIN
Minimum time to wait before retry, in microseconds.
int $mTrxLevel
Either 1 if a transaction is active or 0 otherwise.
getLogContext(array $extras=[])
Create a log context to pass to PSR-3 logger functions.
string $mTrxShortId
Either a short hexidecimal string if a transaction is active or "".
conditional($cond, $trueVal, $falseVal)
Returns an SQL expression for a simple conditional.
ping(&$rtt=null)
Ping the server and try to reconnect if it there is no connection.
array $mNamedLocksHeld
Map of (name => 1) for locks obtained via lock()
Used by Database::buildLike() to represent characters that have special meaning in SQL LIKE clauses a...
onTransactionPreCommitOrIdle(callable $callback, $fname=__METHOD__)
Run a callback before the current transaction commits or now if there is none.
wasErrorReissuable()
Determines if the last query error was due to a dropped connection and should be dealt with by pingin...
float $mTrxReplicaLag
Lag estimate at the time of BEGIN.
ignoreErrors($ignoreErrors=null)
Turns on (false) or off (true) the automatic generation and sending of a "we're sorry, but there has been a database error" page on database errors.
bitAnd($fieldLeft, $fieldRight)
makeSelectOptions($options)
Returns an optional USE INDEX clause to go after the table, and a string to go at the end of the quer...
getScopedLockAndFlush($lockKey, $fname, $timeout)
Acquire a named lock, flush any transaction, and return an RAII style unlocker object.
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
LoggerInterface $connLogger
closeConnection()
Closes underlying database connection.
const PING_TTL
How long before it is worth doing a dummy query to test the connection.
callable[] $mTrxRecurringCallbacks
Map of (name => callable)
bool $mTrxDoneWrites
Record if possible write queries were done in the last transaction started.
upsert($table, array $rows, array $uniqueIndexes, array $set, $fname=__METHOD__)
INSERT ON DUPLICATE KEY UPDATE wrapper, upserts an array into a table.
bool $mTrxAutomaticAtomic
Record if the current transaction was started implicitly by Database::startAtomic.
duplicateTableStructure($oldName, $newName, $temporary=false, $fname=__METHOD__)
Creates a new table with structure copied from existing table Note that unlike most database abstract...
fetchRow($res)
Fetch the next row from the given result object, in associative array form.
string $mTrxFname
Remembers the function name given for starting the most recent transaction via begin().
estimateRowCount($table, $vars= '*', $conds= '', $fname=__METHOD__, $options=[])
Estimate the number of rows in dataset.
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
sourceFile($filename, callable $lineCallback=null, callable $resultCallback=null, $fname=false, callable $inputCallback=null)
Read and execute SQL commands from a file.
integer $mTrxWriteQueryCount
Number of write queries for the current transaction.
setBigSelects($value=true)
Allow or deny "big selects" for this session only.
streamStatementEnd(&$sql, &$newLine)
Called by sourceStream() to check if we've reached a statement end.
numRows($res)
Get the number of rows in a result object.
buildLike()
LIKE statement wrapper, receives a variable-length argument list with parts of pattern to match conta...
getReplicaPos()
Get the replication position of this replica DB.
indexExists($table, $index, $fname=__METHOD__)
Determines whether an index exists Usually throws a DBQueryError on failure If errors are explicitly ...
unlock($lockName, $method)
Release a lock.
getBindingHandle()
Get the underlying binding handle, mConn.
wasLockTimeout()
Determines if the last failure was due to a lock timeout.
wasDeadlock()
Determines if the last failure was due to a deadlock.
runOnTransactionIdleCallbacks($trigger)
Actually run and consume any "on transaction idle/resolution" callbacks.
flushSnapshot($fname=__METHOD__)
Commit any transaction but error out if writes or callbacks are pending.
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
lockTables($read, $write, $method, $lowPriority=true)
Lock specific tables.
strreplace($orig, $old, $new)
Returns a comand for str_replace function in SQL query.
addQuotes($s)
Adds quotes and backslashes.
doBegin($fname)
Issues the BEGIN command to the database server.
getMasterPos()
Get the position of this master.
anyString()
Returns a token for buildLike() that denotes a '' to be used in a LIKE query.
float $mTrxWriteAdjDuration
Like mTrxWriteQueryCount but excludes lock-bound, easy to replicate, queries.
if(!defined( 'MEDIAWIKI')) $fname
This file is not a valid entry point, perform no further processing unless MEDIAWIKI is defined...
fieldNamesWithAlias($fields)
Gets an array of aliased field names.
getSessionLagStatus()
Get the replica DB lag when the current transaction started or a general lag estimate if not transact...
onTransactionResolution(callable $callback, $fname=__METHOD__)
Run a callback as soon as the current transaction commits or rolls back.
static getSearchEngineClass(IDatabase $db)
getDefaultSchemaVars()
Get schema variables to use if none have been set via setSchemaVars().
fieldExists($table, $field, $fname=__METHOD__)
Determines whether a field exists in a table.
listViews($prefix=null, $fname=__METHOD__)
Lists all the VIEWs in the database.
getServer()
Get the server hostname or IP address.
array[] $mTrxPreCommitCallbacks
List of (callable, method name)
int[] $priorFlags
Prior mFlags values.
indexUnique($table, $index)
Determines if a given index is unique.
makeWhereFrom2d($data, $baseKey, $subKey)
Build a partial where clause from a 2-d array such as used for LinkBatch.
array $mTrxAtomicLevels
Array of levels of atomicity within transactions.
pendingWriteQueryDuration($type=self::ESTIMATE_TOTAL)
Get the time spend running write queries for this transaction.
dropTable($tableName, $fName=__METHOD__)
Delete a table.
getServerUptime()
Determines how long the server has been up.
pendingWriteCallers()
Get the list of method names that did write queries for this transaction.
makeInsertOptions($options)
Helper for Database::insert().
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context the output can only depend on parameters provided to this hook not on global state indicating whether full HTML should be generated If generation of HTML may be but other information should still be present in the ParserOutput object to manipulate or replace but no entry for that model exists in $wgContentHandlers if desired whether it is OK to use $contentModel on $title Handler functions that modify $ok should generally return false to prevent further hooks from further modifying $ok inclusive $limit
setTrxEndCallbackSuppression($suppress)
Whether to disable running of post-COMMIT/ROLLBACK callbacks.
registerTempTableOperation($sql)
resource null $mConn
Database connection.
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set $status
getWikiID()
Alias for getDomainID()
static convert($style=TS_UNIX, $ts)
Convert a timestamp string to a given format.
useIndexClause($index)
USE INDEX clause.
Advanced database interface for IDatabase handles that include maintenance methods.
selectFieldValues($table, $var, $cond= '', $fname=__METHOD__, $options=[], $join_conds=[])
namedLocksEnqueue()
Check to see if a named lock used by lock() use blocking queues.
string bool null $htmlErrors
Stashed value of html_errors INI setting.
replace($table, $uniqueIndexes, $rows, $fname=__METHOD__)
REPLACE query wrapper.
selectField($table, $var, $cond= '', $fname=__METHOD__, $options=[])
A SELECT wrapper which returns a single field from a single result row.
float null $mTrxTimestamp
The UNIX time that the transaction started.
IDatabase null $lazyMasterHandle
Lazy handle to the master DB this server replicates from.
Result wrapper for grabbing data queried from an IDatabase object.
runOnTransactionPreCommitCallbacks()
Actually run and consume any "on transaction pre-commit" callbacks.
encodeExpiry($expiry)
Encode an expiry time into the DBMS dependent format.
connectionErrorLogger($errno, $errstr)
This method should not be used outside of Database classes.
nativeInsertSelect($destTable, $srcTable, $varMap, $conds, $fname=__METHOD__, $insertOptions=[], $selectOptions=[])
setSchemaVars($vars)
Set variables to be used in sourceFile/sourceStream, in preference to the ones in $GLOBALS...
bool null $mDefaultBigSelects
replaceVars($ins)
Database independent variable replacement.
tableNamesWithAlias($tables)
Gets an array of aliased table names.
array $mSessionTempTables
Map of (table name => 1) for TEMPORARY tables.
makeUpdateOptions($options)
Make UPDATE options for the Database::update function.
getLag()
Get replica DB lag.
limitResult($sql, $limit, $offset=false)
Construct a LIMIT query with optional offset.
getSchemaVars()
Get schema variables.
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 incomplete not yet checked for validity & $retval
static configuration should be added through ResourceLoaderGetConfigVars instead & $vars
doQuery($sql)
The DBMS-dependent part of query()
resultObject($result)
Take the result from a query, and wrap it in a ResultWrapper if necessary.
getDBname()
Get the current DB name.
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached one of or reset my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled allows for interception of redirect as a string mapping parameter names to values & $type
tablePrefix($prefix=null)
Get/set the table prefix.
listTables($prefix=null, $fname=__METHOD__)
List all tables on the database.
prependDatabaseOrSchema($namespace, $relation, $format)
Basic database interface for live and lazy-loaded relation database handles.
query($sql, $fname=__METHOD__, $tempIgnore=false)
Run an SQL query and return the result.
lock($lockName, $method, $timeout=5)
Acquire a named lock.
lastQuery()
Return the last query that went through IDatabase::query()
const DEADLOCK_TRIES
Number of times to re-try an operation in case of deadlock.
isWriteQuery($sql)
Determine whether a query writes to the DB.
Allows to change the fields on the form that will be generated $name