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;
1359 $res = $this->
query(
"SELECT COUNT(*) AS $rowCountCol FROM ($sql) $tableName",
$fname );
1363 $rows = ( isset( $row[
'rowcount'] ) ) ? (
int)$row[
'rowcount'] : 0;
1378 # This does the same as the regexp below would do, but in such a way
1379 # as to avoid crashing php on some large strings.
1380 # $sql = preg_replace( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql );
1382 $sql = str_replace(
"\\\\",
'', $sql );
1383 $sql = str_replace(
"\\'",
'', $sql );
1384 $sql = str_replace(
"\\\"",
'', $sql );
1385 $sql = preg_replace(
"/'.*'/s",
"'X'", $sql );
1386 $sql = preg_replace(
'/".*"/s',
"'X'", $sql );
1388 # All newlines, tabs, etc replaced by single space
1389 $sql = preg_replace(
'/\s+/',
' ', $sql );
1392 # except the ones surrounded by characters, e.g. l10n
1393 $sql = preg_replace(
'/-?\d+(,-?\d+)+/s',
'N,...,N', $sql );
1394 $sql = preg_replace(
'/(?<![a-zA-Z])-?\d+(?![a-zA-Z])/s',
'N', $sql );
1400 $info = $this->
fieldInfo( $table, $field );
1411 if ( is_null( $info ) ) {
1414 return $info !==
false;
1419 $tableRaw = $this->
tableName( $table,
'raw' );
1420 if ( isset( $this->mSessionTempTables[$tableRaw] ) ) {
1433 $indexInfo = $this->
indexInfo( $table, $index );
1435 if ( !$indexInfo ) {
1439 return !$indexInfo[0]->Non_unique;
1453 # No rows to insert, easy just return now
1454 if ( !count( $a ) ) {
1465 if ( isset(
$options[
'fileHandle'] ) ) {
1470 if ( isset( $a[0] ) && is_array( $a[0] ) ) {
1472 $keys = array_keys( $a[0] );
1475 $keys = array_keys( $a );
1479 " INTO $table (" . implode(
',',
$keys ) .
') VALUES ';
1483 foreach ( $a
as $row ) {
1489 $sql .=
'(' . $this->
makeList( $row ) .
')';
1492 $sql .=
'(' . $this->
makeList( $a ) .
')';
1495 if ( $fh !== null &&
false === fwrite( $fh, $sql ) ) {
1497 } elseif ( $fh !== null ) {
1517 if ( in_array(
'IGNORE',
$options ) ) {
1533 return implode(
' ', $opts );
1541 if ( $conds !== [] && $conds !==
'*' ) {
1549 if ( !is_array( $a ) ) {
1550 throw new DBUnexpectedError( $this, __METHOD__ .
' called with incorrect parameters' );
1556 foreach ( $a
as $field =>
$value ) {
1570 $list .=
"($value)";
1577 $includeNull =
false;
1578 foreach ( array_keys(
$value, null,
true )
as $nullKey ) {
1579 $includeNull =
true;
1580 unset(
$value[$nullKey] );
1582 if ( count(
$value ) == 0 && !$includeNull ) {
1584 __METHOD__ .
": empty input for field $field" );
1585 } elseif ( count(
$value ) == 0 ) {
1587 $list .=
"$field IS NULL";
1590 if ( $includeNull ) {
1594 if ( count(
$value ) == 1 ) {
1604 if ( $includeNull ) {
1605 $list .=
" OR $field IS NULL)";
1608 } elseif (
$value === null ) {
1610 $list .=
"$field IS ";
1612 $list .=
"$field = ";
1619 $list .=
"$field = ";
1631 foreach ( $data
as $base => $sub ) {
1632 if ( count( $sub ) ) {
1634 [ $baseKey =>
$base, $subKey => array_keys( $sub ) ],
1655 public function bitAnd( $fieldLeft, $fieldRight ) {
1656 return "($fieldLeft & $fieldRight)";
1659 public function bitOr( $fieldLeft, $fieldRight ) {
1660 return "($fieldLeft | $fieldRight)";
1664 return 'CONCAT(' . implode(
',', $stringList ) .
')';
1668 $delim, $table, $field, $conds =
'', $join_conds = []
1670 $fld =
"GROUP_CONCAT($field SEPARATOR " . $this->
addQuotes( $delim ) .
')';
1672 return '(' . $this->
selectSQLText( $table, $fld, $conds, null, [], $join_conds ) .
')';
1680 # Stub. Shouldn't cause serious problems if it's not overridden, but
1681 # if your database engine supports a concept similar to MySQL's
1682 # databases you may as well.
1683 $this->mDBname = $db;
1697 # Skip the entire process when we have a string quoted on both ends.
1698 # Note that we check the end so that we will still quote any use of
1699 # use of `database`.table. But won't break things if someone wants
1700 # to query a database table with a dot in the name.
1705 # Lets test for any bits of text that should never show up in a table
1706 # name. Basically anything like JOIN or ON which are actually part of
1707 # SQL queries, but may end up inside of the table value to combine
1708 # sql. Such as how the API is doing.
1709 # Note that we use a whitespace test rather than a \b test to avoid
1710 # any remote case where a word like on may be inside of a table name
1711 # surrounded by symbols which may be considered word breaks.
1712 if ( preg_match(
'/(^|\s)(DISTINCT|JOIN|ON|AS)(\s|$)/i',
$name ) !== 0 ) {
1716 # Split database and table into proper variables.
1717 # We reverse the explode so that database.table and table both output
1718 # the correct table.
1719 $dbDetails = explode(
'.',
$name, 3 );
1720 if ( count( $dbDetails ) == 3 ) {
1721 list( $database, $schema, $table ) = $dbDetails;
1722 # We don't want any prefix added in this case
1724 } elseif ( count( $dbDetails ) == 2 ) {
1725 list( $database, $table ) = $dbDetails;
1726 # We don't want any prefix added in this case
1728 # In dbs that support it, $database may actually be the schema
1729 # but that doesn't affect any of the functionality here
1732 list( $table ) = $dbDetails;
1733 if ( isset( $this->tableAliases[$table] ) ) {
1734 $database = $this->tableAliases[$table][
'dbname'];
1735 $schema = is_string( $this->tableAliases[$table][
'schema'] )
1736 ? $this->tableAliases[$table][
'schema']
1738 $prefix = is_string( $this->tableAliases[$table][
'prefix'] )
1739 ? $this->tableAliases[$table][
'prefix']
1748 # Quote $table and apply the prefix if not quoted.
1749 # $tableName might be empty if this is called from Database::replaceVars()
1750 $tableName =
"{$prefix}{$table}";
1751 if ( $format ===
'quoted'
1753 && $tableName !==
''
1758 # Quote $schema and $database and merge them with the table name if needed
1772 if ( strlen( $namespace ) ) {
1776 $relation = $namespace .
'.' . $relation;
1783 $inArray = func_get_args();
1786 foreach ( $inArray
as $name ) {
1794 $inArray = func_get_args();
1797 foreach ( $inArray
as $name ) {
1813 if ( !$alias || $alias ==
$name ) {
1828 foreach (
$tables as $alias => $table ) {
1829 if ( is_numeric( $alias ) ) {
1847 if ( !$alias || (
string)$alias === (
string)
$name ) {
1862 foreach ( $fields
as $alias => $field ) {
1863 if ( is_numeric( $alias ) ) {
1883 $tables, $use_index = [], $ignore_index = [], $join_conds = []
1887 $use_index = (
array)$use_index;
1888 $ignore_index = (
array)$ignore_index;
1889 $join_conds = (
array)$join_conds;
1891 foreach (
$tables as $alias => $table ) {
1892 if ( !is_string( $alias ) ) {
1897 if ( isset( $join_conds[$alias] ) ) {
1898 list( $joinType, $conds ) = $join_conds[$alias];
1899 $tableClause = $joinType;
1901 if ( isset( $use_index[$alias] ) ) {
1904 $tableClause .=
' ' . $use;
1907 if ( isset( $ignore_index[$alias] ) ) {
1909 implode(
',', (
array)$ignore_index[$alias] ) );
1910 if ( $ignore !=
'' ) {
1911 $tableClause .=
' ' . $ignore;
1916 $tableClause .=
' ON (' . $on .
')';
1919 $retJOIN[] = $tableClause;
1920 } elseif ( isset( $use_index[$alias] ) ) {
1924 implode(
',', (
array)$use_index[$alias] )
1927 $ret[] = $tableClause;
1928 } elseif ( isset( $ignore_index[$alias] ) ) {
1932 implode(
',', (
array)$ignore_index[$alias] )
1935 $ret[] = $tableClause;
1939 $ret[] = $tableClause;
1944 $implicitJoins = !empty(
$ret ) ? implode(
',',
$ret ) :
"";
1945 $explicitJoins = !empty( $retJOIN ) ? implode(
' ', $retJOIN ) :
"";
1948 return implode(
' ', [ $implicitJoins, $explicitJoins ] );
1960 'ar_usertext_timestamp' =>
'usertext_timestamp',
1961 'un_user_id' =>
'user_id',
1962 'un_user_ip' =>
'user_ip',
1965 if ( isset( $renamed[$index] ) ) {
1966 return $renamed[$index];
1973 if (
$s instanceof
Blob ) {
1976 if (
$s === null ) {
1978 } elseif ( is_bool(
$s ) ) {
1981 # This will also quote numeric values. This should be harmless,
1982 # and protects against weird problems that occur when they really
1983 # _are_ strings such as article titles and string->number->string
1984 # conversion is not 1:1.
1999 return '"' . str_replace(
'"',
'""',
$s ) .
'"';
2012 return $name[0] ==
'"' && substr(
$name, -1, 1 ) ==
'"';
2020 return addcslashes(
$s,
'\%_' );
2034 $s .= $value->toString();
2040 return " LIKE {$this->addQuotes( $s )} ";
2084 $quotedTable = $this->
tableName( $table );
2086 if ( count( $rows ) == 0 ) {
2091 if ( !is_array( reset( $rows ) ) ) {
2096 foreach ( $rows
as $row ) {
2097 # Delete rows which collide
2098 if ( $uniqueIndexes ) {
2099 $sql =
"DELETE FROM $quotedTable WHERE ";
2101 foreach ( $uniqueIndexes
as $index ) {
2108 if ( is_array( $index ) ) {
2110 foreach ( $index
as $col ) {
2116 $sql .= $col .
'=' . $this->
addQuotes( $row[$col] );
2119 $sql .= $index .
'=' . $this->
addQuotes( $row[$index] );
2126 # Now insert the row
2145 if ( !is_array( reset( $rows ) ) ) {
2149 $sql =
"REPLACE INTO $table (" . implode(
',', array_keys( $rows[0] ) ) .
') VALUES ';
2152 foreach ( $rows
as $row ) {
2159 $sql .=
'(' . $this->
makeList( $row ) .
')';
2168 if ( !count( $rows ) ) {
2172 if ( !is_array( reset( $rows ) ) ) {
2176 if ( count( $uniqueIndexes ) ) {
2178 foreach ( $rows
as $row ) {
2179 foreach ( $uniqueIndexes
as $index ) {
2180 $index = is_array( $index ) ? $index : [ $index ];
2182 foreach ( $index
as $column ) {
2183 $rowKey[$column] = $row[$column];
2195 $this->
begin(
$fname, self::TRANSACTION_INTERNAL );
2198 # Update any existing conflicting row(s)
2199 if ( $where !==
false ) {
2204 # Now insert any non-conflicting row(s)
2205 $ok = $this->
insert( $table, $rows,
$fname, [
'IGNORE' ] ) && $ok;
2219 public function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds,
2226 $delTable = $this->
tableName( $delTable );
2227 $joinTable = $this->
tableName( $joinTable );
2228 $sql =
"DELETE FROM $delTable WHERE $delVar IN (SELECT $joinVar FROM $joinTable ";
2229 if ( $conds !=
'*' ) {
2239 $sql =
"SHOW COLUMNS FROM $table LIKE \"$field\";";
2240 $res = $this->
query( $sql, __METHOD__ );
2245 if ( preg_match(
'/\((.*)\)/', $row->Type, $m ) ) {
2254 public function delete( $table, $conds,
$fname = __METHOD__ ) {
2256 throw new DBUnexpectedError( $this, __METHOD__ .
' called with no conditions' );
2260 $sql =
"DELETE FROM $table";
2262 if ( $conds !=
'*' ) {
2263 if ( is_array( $conds ) ) {
2266 $sql .=
' WHERE ' . $conds;
2269 return $this->
query( $sql, $fname );
2273 $destTable, $srcTable, $varMap, $conds,
2274 $fname = __METHOD__, $insertOptions = [], $selectOptions = []
2276 if ( $this->cliMode ) {
2294 foreach ( $varMap
as $dstColumn => $sourceColumnOrSql ) {
2297 $selectOptions[] =
'FOR UPDATE';
2298 $res = $this->
select( $srcTable, implode(
',', $fields ), $conds, $fname, $selectOptions );
2304 foreach (
$res as $row ) {
2305 $rows[] = (
array)$row;
2308 return $this->
insert( $destTable, $rows, $fname, $insertOptions );
2312 $fname = __METHOD__,
2313 $insertOptions = [], $selectOptions = []
2315 $destTable = $this->
tableName( $destTable );
2317 if ( !is_array( $insertOptions ) ) {
2318 $insertOptions = [ $insertOptions ];
2323 if ( !is_array( $selectOptions ) ) {
2324 $selectOptions = [ $selectOptions ];
2330 if ( is_array( $srcTable ) ) {
2331 $srcTable = implode(
',', array_map( [ $this,
'tableName' ], $srcTable ) );
2333 $srcTable = $this->
tableName( $srcTable );
2336 $sql =
"INSERT $insertOptions" .
2337 " INTO $destTable (" . implode(
',', array_keys( $varMap ) ) .
')' .
2338 " SELECT $startOpts " . implode(
',', $varMap ) .
2339 " FROM $srcTable $useIndex $ignoreIndex ";
2341 if ( $conds !=
'*' ) {
2342 if ( is_array( $conds ) ) {
2345 $sql .=
" WHERE $conds";
2348 $sql .=
" $tailOpts";
2350 return $this->
query( $sql, $fname );
2373 if ( !is_numeric(
$limit ) ) {
2375 "Invalid non-numeric limit passed to limitResult()\n" );
2378 return "$sql LIMIT "
2379 . ( ( is_numeric( $offset ) && $offset != 0 ) ?
"{$offset}," :
"" )
2388 $glue = $all ?
') UNION ALL (' :
') UNION (';
2390 return '(' . implode( $glue, $sqls ) .
')';
2394 if ( is_array( $cond ) ) {
2398 return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) ";
2402 return "REPLACE({$orig}, {$old}, {$new})";
2436 $args = func_get_args();
2437 $function = array_shift(
$args );
2438 $tries = self::DEADLOCK_TRIES;
2440 $this->
begin( __METHOD__ );
2447 $retVal = call_user_func_array( $function,
$args );
2452 usleep( mt_rand( self::DEADLOCK_DELAY_MIN, self::DEADLOCK_DELAY_MAX ) );
2458 }
while ( --$tries > 0 );
2460 if ( $tries <= 0 ) {
2465 $this->
commit( __METHOD__ );
2472 # Real waits are implemented in the subclass.
2491 if ( !$this->mTrxLevel ) {
2494 $this->mTrxEndCallbacks[] = [ $callback,
$fname ];
2498 $this->mTrxIdleCallbacks[] = [ $callback,
$fname ];
2499 if ( !$this->mTrxLevel ) {
2505 if ( $this->mTrxLevel ) {
2506 $this->mTrxPreCommitCallbacks[] = [ $callback,
$fname ];
2511 call_user_func( $callback );
2514 $this->
rollback( __METHOD__, self::FLUSHING_INTERNAL );
2522 $this->mTrxRecurringCallbacks[
$name] = $callback;
2524 unset( $this->mTrxRecurringCallbacks[
$name] );
2537 $this->mTrxEndCallbacksSuppressed = $suppress;
2550 if ( $this->mTrxEndCallbacksSuppressed ) {
2558 $callbacks = array_merge(
2559 $this->mTrxIdleCallbacks,
2560 $this->mTrxEndCallbacks
2562 $this->mTrxIdleCallbacks = [];
2563 $this->mTrxEndCallbacks = [];
2564 foreach ( $callbacks
as $callback ) {
2566 list( $phpCallback ) = $callback;
2568 call_user_func_array( $phpCallback, [ $trigger ] );
2575 call_user_func( $this->errorLogger, $ex );
2580 $this->
rollback( __METHOD__, self::FLUSHING_INTERNAL );
2584 }
while ( count( $this->mTrxIdleCallbacks ) );
2603 $this->mTrxPreCommitCallbacks = [];
2604 foreach ( $callbacks
as $callback ) {
2606 list( $phpCallback ) = $callback;
2607 call_user_func( $phpCallback );
2609 call_user_func( $this->errorLogger, $ex );
2613 }
while ( count( $this->mTrxPreCommitCallbacks ) );
2630 if ( $this->mTrxEndCallbacksSuppressed ) {
2637 foreach ( $this->mTrxRecurringCallbacks
as $phpCallback ) {
2639 $phpCallback( $trigger, $this );
2641 call_user_func( $this->errorLogger, $ex );
2652 if ( !$this->mTrxLevel ) {
2653 $this->
begin( $fname, self::TRANSACTION_INTERNAL );
2657 $this->mTrxAutomaticAtomic =
true;
2661 $this->mTrxAtomicLevels[] =
$fname;
2665 if ( !$this->mTrxLevel ) {
2666 throw new DBUnexpectedError( $this,
"No atomic transaction is open (got $fname)." );
2668 if ( !$this->mTrxAtomicLevels ||
2669 array_pop( $this->mTrxAtomicLevels ) !== $fname
2671 throw new DBUnexpectedError( $this,
"Invalid atomic section ended (got $fname)." );
2674 if ( !$this->mTrxAtomicLevels && $this->mTrxAutomaticAtomic ) {
2675 $this->
commit( $fname, self::FLUSHING_INTERNAL );
2682 $res = call_user_func_array( $callback, [ $this, $fname ] );
2684 $this->
rollback( $fname, self::FLUSHING_INTERNAL );
2692 final public function begin( $fname = __METHOD__, $mode = self::TRANSACTION_EXPLICIT ) {
2694 if ( $this->mTrxLevel ) {
2695 if ( $this->mTrxAtomicLevels ) {
2696 $levels = implode(
', ', $this->mTrxAtomicLevels );
2697 $msg =
"$fname: Got explicit BEGIN while atomic section(s) $levels are open.";
2699 } elseif ( !$this->mTrxAutomatic ) {
2700 $msg =
"$fname: Explicit transaction already active (from {$this->mTrxFname}).";
2704 $msg =
"$fname: Implicit transaction already active (from {$this->mTrxFname}).";
2705 $this->queryLogger->error( $msg );
2710 $msg =
"$fname: Implicit transaction expected (DBO_TRX set).";
2711 $this->queryLogger->error( $msg );
2719 $this->mTrxTimestamp = microtime(
true );
2720 $this->mTrxFname =
$fname;
2721 $this->mTrxDoneWrites =
false;
2722 $this->mTrxAutomaticAtomic =
false;
2723 $this->mTrxAtomicLevels = [];
2724 $this->mTrxShortId = sprintf(
'%06x', mt_rand( 0, 0xffffff ) );
2725 $this->mTrxWriteDuration = 0.0;
2726 $this->mTrxWriteQueryCount = 0;
2727 $this->mTrxWriteAdjDuration = 0.0;
2728 $this->mTrxWriteAdjQueryCount = 0;
2729 $this->mTrxWriteCallers = [];
2734 $this->mTrxReplicaLag =
$status[
'lag'] + ( microtime(
true ) -
$status[
'since'] );
2738 $this->mTrxAutomatic = ( $mode === self::TRANSACTION_INTERNAL );
2748 $this->
query(
'BEGIN', $fname );
2749 $this->mTrxLevel = 1;
2752 final public function commit( $fname = __METHOD__, $flush =
'' ) {
2753 if ( $this->mTrxLevel && $this->mTrxAtomicLevels ) {
2755 $levels = implode(
', ', $this->mTrxAtomicLevels );
2758 "$fname: Got COMMIT while atomic sections $levels are still open."
2762 if ( $flush === self::FLUSHING_INTERNAL || $flush === self::FLUSHING_ALL_PEERS ) {
2763 if ( !$this->mTrxLevel ) {
2765 } elseif ( !$this->mTrxAutomatic ) {
2768 "$fname: Flushing an explicit transaction, getting out of sync."
2772 if ( !$this->mTrxLevel ) {
2773 $this->queryLogger->error(
2774 "$fname: No transaction to commit, something got out of sync." );
2776 } elseif ( $this->mTrxAutomatic ) {
2778 $msg =
"$fname: Explicit commit of implicit transaction.";
2779 $this->queryLogger->error( $msg );
2790 if ( $this->mTrxDoneWrites ) {
2791 $this->mLastWriteTime = microtime(
true );
2792 $this->trxProfiler->transactionWritingOut(
2793 $this->mServer, $this->mDBname, $this->mTrxShortId, $writeTime );
2807 if ( $this->mTrxLevel ) {
2808 $this->
query(
'COMMIT', $fname );
2809 $this->mTrxLevel = 0;
2813 final public function rollback( $fname = __METHOD__, $flush =
'' ) {
2814 if ( $flush === self::FLUSHING_INTERNAL || $flush === self::FLUSHING_ALL_PEERS ) {
2815 if ( !$this->mTrxLevel ) {
2819 if ( !$this->mTrxLevel ) {
2820 $this->queryLogger->error(
2821 "$fname: No transaction to rollback, something got out of sync." );
2826 "$fname: Expected mass rollback of all peer databases (DBO_TRX set)."
2835 $this->mTrxAtomicLevels = [];
2836 if ( $this->mTrxDoneWrites ) {
2837 $this->trxProfiler->transactionWritingOut(
2838 $this->mServer, $this->mDBname, $this->mTrxShortId );
2841 $this->mTrxIdleCallbacks = [];
2842 $this->mTrxPreCommitCallbacks = [];
2854 if ( $this->mTrxLevel ) {
2855 # Disconnects cause rollback anyway, so ignore those errors
2856 $ignoreErrors =
true;
2857 $this->
query(
'ROLLBACK', $fname, $ignoreErrors );
2858 $this->mTrxLevel = 0;
2868 "$fname: Cannot flush snapshot because writes are pending ($fnames)."
2872 $this->
commit( $fname, self::FLUSHING_INTERNAL );
2897 throw new RuntimeException( __METHOD__ .
' is not implemented in descendant class' );
2900 public function listTables( $prefix = null, $fname = __METHOD__ ) {
2901 throw new RuntimeException( __METHOD__ .
' is not implemented in descendant class' );
2904 public function listViews( $prefix = null, $fname = __METHOD__ ) {
2905 throw new RuntimeException( __METHOD__ .
' is not implemented in descendant class' );
2911 return $t->getTimestamp(
TS_MW );
2915 if ( is_null( $ts ) ) {
2940 } elseif (
$result ===
true ) {
2944 return new ResultWrapper( $this,
$result );
2948 public function ping( &$rtt = null ) {
2950 if ( $this->
isOpen() && ( microtime(
true ) - $this->lastPing ) < self::PING_TTL ) {
2951 if ( !func_num_args() || $this->mRTTEstimate > 0 ) {
2959 $ok = ( $this->
query( self::PING_QUERY, __METHOD__,
true ) !==
false );
2974 $this->mOpened =
false;
2975 $this->mConn =
false;
2977 $this->
open( $this->mServer, $this->mUser, $this->mPassword, $this->mDBname );
2978 $this->lastPing = microtime(
true );
3003 return $this->mTrxLevel
3017 'since' => microtime(
true )
3040 $res = [
'lag' => 0,
'since' => INF,
'pending' =>
false ];
3041 foreach ( func_get_args()
as $db ) {
3043 $status = $db->getSessionLagStatus();
3044 if (
$status[
'lag'] ===
false ) {
3045 $res[
'lag'] =
false;
3046 } elseif (
$res[
'lag'] !==
false ) {
3050 $res[
'pending'] =
$res[
'pending'] ?: $db->writesPending();
3069 if ( $b instanceof
Blob ) {
3080 callable $lineCallback = null,
3081 callable $resultCallback = null,
3083 callable $inputCallback = null
3085 MediaWiki\suppressWarnings();
3086 $fp = fopen( $filename,
'r' );
3087 MediaWiki\restoreWarnings();
3089 if (
false === $fp ) {
3094 $fname = __METHOD__ .
"( $filename )";
3099 $fp, $lineCallback, $resultCallback, $fname, $inputCallback );
3111 $this->mSchemaVars =
$vars;
3116 callable $lineCallback = null,
3117 callable $resultCallback = null,
3118 $fname = __METHOD__,
3119 callable $inputCallback = null
3123 while ( !feof( $fp ) ) {
3124 if ( $lineCallback ) {
3125 call_user_func( $lineCallback );
3128 $line = trim( fgets( $fp ) );
3130 if (
$line ==
'' ) {
3146 if ( $done || feof( $fp ) ) {
3149 if ( !$inputCallback || call_user_func( $inputCallback, $cmd ) ) {
3152 if ( $resultCallback ) {
3153 call_user_func( $resultCallback,
$res, $this );
3156 if (
false ===
$res ) {
3159 return "Query \"{$cmd}\" failed with error code \"$err\".\n";
3177 if ( $this->delimiter ) {
3179 $newLine = preg_replace(
3180 '/' . preg_quote( $this->delimiter,
'/' ) .
'$/',
'', $newLine );
3181 if ( $newLine != $prev ) {
3211 return preg_replace_callback(
3213 /\* (\$wgDBprefix|[_i]) \*/ (\w*) | # 1-2. tableName, indexName
3214 \'\{\$ (\w+) }\' | # 3. addQuotes
3215 `\{\$ (\w+) }` | # 4. addIdentifierQuotes
3216 /\*\$ (\w+) \*/ # 5. leave unencoded
3221 if ( isset( $m[1] ) && $m[1] !==
'' ) {
3222 if ( $m[1] ===
'i' ) {
3227 } elseif ( isset( $m[3] ) && $m[3] !==
'' && array_key_exists( $m[3],
$vars ) ) {
3229 } elseif ( isset( $m[4] ) && $m[4] !==
'' && array_key_exists( $m[4],
$vars ) ) {
3231 } elseif ( isset( $m[5] ) && $m[5] !==
'' && array_key_exists( $m[5],
$vars ) ) {
3232 return $vars[$m[5]];
3248 if ( $this->mSchemaVars ) {
3271 public function lock( $lockName, $method, $timeout = 5 ) {
3272 $this->mNamedLocksHeld[$lockName] = 1;
3277 public function unlock( $lockName, $method ) {
3278 unset( $this->mNamedLocksHeld[$lockName] );
3289 "$fname: Cannot flush pre-lock snapshot because writes are pending ($fnames)."
3293 if ( !$this->
lock( $lockKey, $fname, $timeout ) ) {
3297 $unlocker =
new ScopedCallback(
function ()
use ( $lockKey, $fname ) {
3303 function ()
use ( $lockKey, $fname ) {
3304 $this->
unlock( $lockKey, $fname );
3309 $this->
unlock( $lockKey, $fname );
3313 $this->
commit( $fname, self::FLUSHING_INTERNAL );
3331 public function lockTables( $read, $write, $method, $lowPriority =
true ) {
3352 public function dropTable( $tableName, $fName = __METHOD__ ) {
3353 if ( !$this->
tableExists( $tableName, $fName ) ) {
3356 $sql =
"DROP TABLE " . $this->
tableName( $tableName ) .
" CASCADE";
3358 return $this->
query( $sql, $fName );
3366 return ( $expiry ==
'' || $expiry ==
'infinity' || $expiry == $this->
getInfinity() )
3372 if ( $expiry ==
'' || $expiry ==
'infinity' || $expiry == $this->
getInfinity() ) {
3391 $reason = $this->
getLBInfo(
'readOnlyReason' );
3393 return is_string( $reason ) ? $reason :
false;
3397 $this->tableAliases = $aliases;
3420 if ( !$this->mConn ) {
3423 'DB connection was already closed or the connection dropped.'
3443 $this->connLogger->warning(
3444 "Cloning " . get_class( $this ) .
" is not recomended; forking connection:\n" .
3450 $this->mOpened =
false;
3451 $this->mConn =
false;
3452 $this->mTrxEndCallbacks = [];
3454 $this->
open( $this->mServer, $this->mUser, $this->mPassword, $this->mDBname );
3455 $this->lastPing = microtime(
true );
3465 throw new RuntimeException(
'Database serialization may cause problems, since ' .
3466 'the connection is not restored on wakeup.' );
3473 if ( $this->mTrxLevel && $this->mTrxDoneWrites ) {
3474 trigger_error(
"Uncommitted DB writes (transaction from {$this->mTrxFname})." );
3478 if ( $danglingWriters ) {
3479 $fnames = implode(
', ', $danglingWriters );
3480 trigger_error(
"DB transaction writes or callbacks still pending ($fnames)." );
3483 if ( $this->mConn ) {
3486 \MediaWiki\suppressWarnings();
3488 \MediaWiki\restoreWarnings();
3489 $this->mConn =
false;
3490 $this->mOpened =
false;
3504 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