MediaWiki  1.23.13
Database.php
Go to the documentation of this file.
1 <?php
2 
35 interface DatabaseType {
41  function getType();
42 
53  function open( $server, $user, $password, $dbName );
54 
65  function fetchObject( $res );
66 
76  function fetchRow( $res );
77 
84  function numRows( $res );
85 
93  function numFields( $res );
94 
103  function fieldName( $res, $n );
104 
117  function insertId();
118 
126  function dataSeek( $res, $row );
127 
134  function lastErrno();
135 
142  function lastError();
143 
153  function fieldInfo( $table, $field );
154 
162  function indexInfo( $table, $index, $fname = __METHOD__ );
163 
170  function affectedRows();
171 
178  function strencode( $s );
179 
188  function getSoftwareLink();
189 
196  function getServerVersion();
197 
205  function getServerInfo();
206 }
207 
212 interface IDatabase {
213 }
214 
219 abstract class DatabaseBase implements IDatabase, DatabaseType {
221  const DEADLOCK_TRIES = 4;
222 
224  const DEADLOCK_DELAY_MIN = 500000;
225 
227  const DEADLOCK_DELAY_MAX = 1500000;
228 
229 # ------------------------------------------------------------------------------
230 # Variables
231 # ------------------------------------------------------------------------------
232 
233  protected $mLastQuery = '';
234  protected $mDoneWrites = false;
235  protected $mPHPError = false;
236 
238 
240  protected $mConn = null;
241  protected $mOpened = false;
242 
244  protected $mTrxIdleCallbacks = array();
247 
248  protected $mTablePrefix;
249  protected $mSchema;
250  protected $mFlags;
251  protected $mForeign;
252  protected $mErrorCount = 0;
253  protected $mLBInfo = array();
254  protected $mDefaultBigSelects = null;
255  protected $mSchemaVars = false;
256 
257  protected $preparedArgs;
258 
259  protected $htmlErrors;
260 
261  protected $delimiter = ';';
262 
269  protected $mTrxLevel = 0;
270 
278  private $mTrxFname = null;
279 
286  private $mTrxDoneWrites = false;
287 
294  private $mTrxAutomatic = false;
295 
301  private $mTrxAtomicLevels;
302 
308  private $mTrxAutomaticAtomic = false;
309 
314  protected $fileHandle = null;
315 
320  protected $allViews = null;
321 
322 # ------------------------------------------------------------------------------
323 # Accessors
324 # ------------------------------------------------------------------------------
325  # These optionally set a variable and return the previous state
326 
334  public function getServerInfo() {
335  return $this->getServerVersion();
336  }
337 
341  public function getDelimiter() {
342  return $this->delimiter;
343  }
344 
354  public function debug( $debug = null ) {
355  return wfSetBit( $this->mFlags, DBO_DEBUG, $debug );
356  }
357 
379  public function bufferResults( $buffer = null ) {
380  if ( is_null( $buffer ) ) {
381  return !(bool)( $this->mFlags & DBO_NOBUFFER );
382  } else {
383  return !wfSetBit( $this->mFlags, DBO_NOBUFFER, !$buffer );
384  }
385  }
386 
399  public function ignoreErrors( $ignoreErrors = null ) {
400  return wfSetBit( $this->mFlags, DBO_IGNORE, $ignoreErrors );
401  }
402 
411  public function trxLevel() {
412  return $this->mTrxLevel;
413  }
414 
420  public function errorCount( $count = null ) {
421  return wfSetVar( $this->mErrorCount, $count );
422  }
423 
429  public function tablePrefix( $prefix = null ) {
430  return wfSetVar( $this->mTablePrefix, $prefix );
431  }
432 
438  public function dbSchema( $schema = null ) {
439  return wfSetVar( $this->mSchema, $schema );
440  }
441 
447  public function setFileHandle( $fh ) {
448  $this->fileHandle = $fh;
449  }
450 
460  public function getLBInfo( $name = null ) {
461  if ( is_null( $name ) ) {
462  return $this->mLBInfo;
463  } else {
464  if ( array_key_exists( $name, $this->mLBInfo ) ) {
465  return $this->mLBInfo[$name];
466  } else {
467  return null;
468  }
469  }
470  }
471 
480  public function setLBInfo( $name, $value = null ) {
481  if ( is_null( $value ) ) {
482  $this->mLBInfo = $name;
483  } else {
484  $this->mLBInfo[$name] = $value;
485  }
486  }
487 
495  public function setFakeSlaveLag( $lag ) {
496  }
497 
503  public function setFakeMaster( $enabled = true ) {
504  }
505 
511  public function cascadingDeletes() {
512  return false;
513  }
514 
520  public function cleanupTriggers() {
521  return false;
522  }
523 
530  public function strictIPs() {
531  return false;
532  }
533 
539  public function realTimestamps() {
540  return false;
541  }
542 
548  public function implicitGroupby() {
549  return true;
550  }
551 
558  public function implicitOrderby() {
559  return true;
560  }
561 
568  public function searchableIPs() {
569  return false;
570  }
571 
577  public function functionalIndexes() {
578  return false;
579  }
580 
585  public function lastQuery() {
586  return $this->mLastQuery;
587  }
588 
595  public function doneWrites() {
596  return $this->mDoneWrites;
597  }
598 
605  public function writesOrCallbacksPending() {
606  return $this->mTrxLevel && (
607  $this->mTrxDoneWrites || $this->mTrxIdleCallbacks || $this->mTrxPreCommitCallbacks
608  );
609  }
610 
615  public function isOpen() {
616  return $this->mOpened;
617  }
618 
630  public function setFlag( $flag ) {
631  global $wgDebugDBTransactions;
632  $this->mFlags |= $flag;
633  if ( ( $flag & DBO_TRX ) && $wgDebugDBTransactions ) {
634  wfDebug( "Implicit transactions are now enabled.\n" );
635  }
636  }
637 
649  public function clearFlag( $flag ) {
650  global $wgDebugDBTransactions;
651  $this->mFlags &= ~$flag;
652  if ( ( $flag & DBO_TRX ) && $wgDebugDBTransactions ) {
653  wfDebug( "Implicit transactions are now disabled.\n" );
654  }
655  }
656 
669  public function getFlag( $flag ) {
670  return !!( $this->mFlags & $flag );
671  }
672 
679  public function getProperty( $name ) {
680  return $this->$name;
681  }
682 
686  public function getWikiID() {
687  if ( $this->mTablePrefix ) {
688  return "{$this->mDBname}-{$this->mTablePrefix}";
689  } else {
690  return $this->mDBname;
691  }
692  }
693 
699  public function getSchemaPath() {
700  global $IP;
701  if ( file_exists( "$IP/maintenance/" . $this->getType() . "/tables.sql" ) ) {
702  return "$IP/maintenance/" . $this->getType() . "/tables.sql";
703  } else {
704  return "$IP/maintenance/tables.sql";
705  }
706  }
707 
708 # ------------------------------------------------------------------------------
709 # Other functions
710 # ------------------------------------------------------------------------------
711 
724  function __construct( $params = null ) {
725  global $wgDBprefix, $wgDBmwschema, $wgCommandLineMode, $wgDebugDBTransactions;
726 
727  $this->mTrxAtomicLevels = new SplStack;
728 
729  if ( is_array( $params ) ) { // MW 1.22
730  $server = $params['host'];
731  $user = $params['user'];
732  $password = $params['password'];
733  $dbName = $params['dbname'];
734  $flags = $params['flags'];
735  $tablePrefix = $params['tablePrefix'];
736  $schema = $params['schema'];
737  $foreign = $params['foreign'];
738  } else { // legacy calling pattern
739  wfDeprecated( __METHOD__ . " method called without parameter array.", "1.23" );
740  $args = func_get_args();
741  $server = isset( $args[0] ) ? $args[0] : false;
742  $user = isset( $args[1] ) ? $args[1] : false;
743  $password = isset( $args[2] ) ? $args[2] : false;
744  $dbName = isset( $args[3] ) ? $args[3] : false;
745  $flags = isset( $args[4] ) ? $args[4] : 0;
746  $tablePrefix = isset( $args[5] ) ? $args[5] : 'get from global';
747  $schema = 'get from global';
748  $foreign = isset( $args[6] ) ? $args[6] : false;
749  }
750 
751  $this->mFlags = $flags;
752  if ( $this->mFlags & DBO_DEFAULT ) {
753  if ( $wgCommandLineMode ) {
754  $this->mFlags &= ~DBO_TRX;
755  if ( $wgDebugDBTransactions ) {
756  wfDebug( "Implicit transaction open disabled.\n" );
757  }
758  } else {
759  $this->mFlags |= DBO_TRX;
760  if ( $wgDebugDBTransactions ) {
761  wfDebug( "Implicit transaction open enabled.\n" );
762  }
763  }
764  }
765 
767  if ( $tablePrefix == 'get from global' ) {
768  $this->mTablePrefix = $wgDBprefix;
769  } else {
770  $this->mTablePrefix = $tablePrefix;
771  }
772 
774  if ( $schema == 'get from global' ) {
775  $this->mSchema = $wgDBmwschema;
776  } else {
777  $this->mSchema = $schema;
778  }
779 
780  $this->mForeign = $foreign;
781 
782  if ( $user ) {
783  $this->open( $server, $user, $password, $dbName );
784  }
785  }
786 
792  public function __sleep() {
793  throw new MWException( 'Database serialization may cause problems, since ' .
794  'the connection is not restored on wakeup.' );
795  }
796 
819  final public static function factory( $dbType, $p = array() ) {
820  $canonicalDBTypes = array(
821  'mysql' => array( 'mysqli', 'mysql' ),
822  'postgres' => array(),
823  'sqlite' => array(),
824  'oracle' => array(),
825  'mssql' => array(),
826  );
827 
828  $driver = false;
829  $dbType = strtolower( $dbType );
830  if ( isset( $canonicalDBTypes[$dbType] ) && $canonicalDBTypes[$dbType] ) {
831  $possibleDrivers = $canonicalDBTypes[$dbType];
832  if ( !empty( $p['driver'] ) ) {
833  if ( in_array( $p['driver'], $possibleDrivers ) ) {
834  $driver = $p['driver'];
835  } else {
836  throw new MWException( __METHOD__ .
837  " cannot construct Database with type '$dbType' and driver '{$p['driver']}'" );
838  }
839  } else {
840  foreach ( $possibleDrivers as $posDriver ) {
841  if ( extension_loaded( $posDriver ) ) {
842  $driver = $posDriver;
843  break;
844  }
845  }
846  }
847  } else {
848  $driver = $dbType;
849  }
850  if ( $driver === false ) {
851  throw new MWException( __METHOD__ .
852  " no viable database extension found for type '$dbType'" );
853  }
854 
855  // Determine schema defaults. Currently Microsoft SQL Server uses $wgDBmwschema,
856  // and everything else doesn't use a schema (e.g. null)
857  // Although postgres and oracle support schemas, we don't use them (yet)
858  // to maintain backwards compatibility
859  $defaultSchemas = array(
860  'mysql' => null,
861  'postgres' => null,
862  'sqlite' => null,
863  'oracle' => null,
864  'mssql' => 'get from global',
865  );
866 
867  $class = 'Database' . ucfirst( $driver );
868  if ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) {
869  $params = array(
870  'host' => isset( $p['host'] ) ? $p['host'] : false,
871  'user' => isset( $p['user'] ) ? $p['user'] : false,
872  'password' => isset( $p['password'] ) ? $p['password'] : false,
873  'dbname' => isset( $p['dbname'] ) ? $p['dbname'] : false,
874  'flags' => isset( $p['flags'] ) ? $p['flags'] : 0,
875  'tablePrefix' => isset( $p['tablePrefix'] ) ? $p['tablePrefix'] : 'get from global',
876  'schema' => isset( $p['schema'] ) ? $p['schema'] : $defaultSchemas[$dbType],
877  'foreign' => isset( $p['foreign'] ) ? $p['foreign'] : false
878  );
879 
880  return new $class( $params );
881  } else {
882  return null;
883  }
884  }
885 
886  protected function installErrorHandler() {
887  $this->mPHPError = false;
888  $this->htmlErrors = ini_set( 'html_errors', '0' );
889  set_error_handler( array( $this, 'connectionErrorHandler' ) );
890  }
891 
895  protected function restoreErrorHandler() {
896  restore_error_handler();
897  if ( $this->htmlErrors !== false ) {
898  ini_set( 'html_errors', $this->htmlErrors );
899  }
900  if ( $this->mPHPError ) {
901  $error = preg_replace( '!\[<a.*</a>\]!', '', $this->mPHPError );
902  $error = preg_replace( '!^.*?:\s?(.*)$!', '$1', $error );
903 
904  return $error;
905  } else {
906  return false;
907  }
908  }
909 
914  public function connectionErrorHandler( $errno, $errstr ) {
915  $this->mPHPError = $errstr;
916  }
917 
925  public function close() {
926  if ( count( $this->mTrxIdleCallbacks ) ) { // sanity
927  throw new MWException( "Transaction idle callbacks still pending." );
928  }
929  $this->mOpened = false;
930  if ( $this->mConn ) {
931  if ( $this->trxLevel() ) {
932  if ( !$this->mTrxAutomatic ) {
933  wfWarn( "Transaction still in progress (from {$this->mTrxFname}), " .
934  " performing implicit commit before closing connection!" );
935  }
936 
937  $this->commit( __METHOD__, 'flush' );
938  }
939 
940  $ret = $this->closeConnection();
941  $this->mConn = false;
942 
943  return $ret;
944  } else {
945  return true;
946  }
947  }
948 
954  abstract protected function closeConnection();
955 
960  function reportConnectionError( $error = 'Unknown error' ) {
961  $myError = $this->lastError();
962  if ( $myError ) {
963  $error = $myError;
964  }
965 
966  # New method
967  throw new DBConnectionError( $this, $error );
968  }
969 
977  abstract protected function doQuery( $sql );
978 
986  public function isWriteQuery( $sql ) {
987  return !preg_match( '/^(?:SELECT|BEGIN|ROLLBACK|COMMIT|SET|SHOW|EXPLAIN|\(SELECT)\b/i', $sql );
988  }
989 
1012  public function query( $sql, $fname = __METHOD__, $tempIgnore = false ) {
1013  global $wgUser, $wgDebugDBTransactions;
1014 
1015  $this->mLastQuery = $sql;
1016  if ( !$this->mDoneWrites && $this->isWriteQuery( $sql ) ) {
1017  # Set a flag indicating that writes have been done
1018  wfDebug( __METHOD__ . ": Writes done: $sql\n" );
1019  $this->mDoneWrites = true;
1020  }
1021 
1022  # Add a comment for easy SHOW PROCESSLIST interpretation
1023  if ( is_object( $wgUser ) && $wgUser->isItemLoaded( 'name' ) ) {
1024  $userName = $wgUser->getName();
1025  if ( mb_strlen( $userName ) > 15 ) {
1026  $userName = mb_substr( $userName, 0, 15 ) . '...';
1027  }
1028  $userName = str_replace( '/', '', $userName );
1029  } else {
1030  $userName = '';
1031  }
1032 
1033  // Add trace comment to the begin of the sql string, right after the operator.
1034  // Or, for one-word queries (like "BEGIN" or COMMIT") add it to the end (bug 42598)
1035  $commentedSql = preg_replace( '/\s|$/', " /* $fname $userName */ ", $sql, 1 );
1036 
1037  # If DBO_TRX is set, start a transaction
1038  if ( ( $this->mFlags & DBO_TRX ) && !$this->mTrxLevel &&
1039  $sql != 'BEGIN' && $sql != 'COMMIT' && $sql != 'ROLLBACK'
1040  ) {
1041  # Avoid establishing transactions for SHOW and SET statements too -
1042  # that would delay transaction initializations to once connection
1043  # is really used by application
1044  $sqlstart = substr( $sql, 0, 10 ); // very much worth it, benchmark certified(tm)
1045  if ( strpos( $sqlstart, "SHOW " ) !== 0 && strpos( $sqlstart, "SET " ) !== 0 ) {
1046  if ( $wgDebugDBTransactions ) {
1047  wfDebug( "Implicit transaction start.\n" );
1048  }
1049  $this->begin( __METHOD__ . " ($fname)" );
1050  $this->mTrxAutomatic = true;
1051  }
1052  }
1053 
1054  # Keep track of whether the transaction has write queries pending
1055  if ( $this->mTrxLevel && !$this->mTrxDoneWrites && $this->isWriteQuery( $sql ) ) {
1056  $this->mTrxDoneWrites = true;
1057  Profiler::instance()->transactionWritingIn( $this->mServer, $this->mDBname );
1058  }
1059 
1060  $queryProf = '';
1061  $totalProf = '';
1062  $isMaster = !is_null( $this->getLBInfo( 'master' ) );
1063 
1064  if ( !Profiler::instance()->isStub() ) {
1065  # generalizeSQL will probably cut down the query to reasonable
1066  # logging size most of the time. The substr is really just a sanity check.
1067  if ( $isMaster ) {
1068  $queryProf = 'query-m: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 );
1069  $totalProf = 'DatabaseBase::query-master';
1070  } else {
1071  $queryProf = 'query: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 );
1072  $totalProf = 'DatabaseBase::query';
1073  }
1074  wfProfileIn( $totalProf );
1075  wfProfileIn( $queryProf );
1076  }
1077 
1078  if ( $this->debug() ) {
1079  static $cnt = 0;
1080 
1081  $cnt++;
1082  $sqlx = substr( $commentedSql, 0, 500 );
1083  $sqlx = strtr( $sqlx, "\t\n", ' ' );
1084 
1085  $master = $isMaster ? 'master' : 'slave';
1086  wfDebug( "Query {$this->mDBname} ($cnt) ($master): $sqlx\n" );
1087  }
1088 
1089  $queryId = MWDebug::query( $sql, $fname, $isMaster );
1090 
1091  # Do the query and handle errors
1092  $ret = $this->doQuery( $commentedSql );
1093 
1094  MWDebug::queryTime( $queryId );
1095 
1096  # Try reconnecting if the connection was lost
1097  if ( false === $ret && $this->wasErrorReissuable() ) {
1098  # Transaction is gone, like it or not
1099  $hadTrx = $this->mTrxLevel; // possible lost transaction
1100  $this->mTrxLevel = 0;
1101  wfDebug( "Connection lost, reconnecting...\n" );
1102 
1103  if ( $this->ping() ) {
1104  wfDebug( "Reconnected\n" );
1105  $sqlx = substr( $commentedSql, 0, 500 );
1106  $sqlx = strtr( $sqlx, "\t\n", ' ' );
1108  $elapsed = round( microtime( true ) - $wgRequestTime, 3 );
1109  if ( $elapsed < 300 ) {
1110  # Not a database error to lose a transaction after a minute or two
1111  wfLogDBError( "Connection lost and reconnected after {$elapsed}s, query: $sqlx" );
1112  }
1113  if ( !$hadTrx ) {
1114  # Should be safe to silently retry
1115  $ret = $this->doQuery( $commentedSql );
1116  }
1117  } else {
1118  wfDebug( "Failed\n" );
1119  }
1120  }
1121 
1122  if ( false === $ret ) {
1123  $this->reportQueryError( $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore );
1124  }
1125 
1126  if ( !Profiler::instance()->isStub() ) {
1127  wfProfileOut( $queryProf );
1128  wfProfileOut( $totalProf );
1129  }
1130 
1131  return $this->resultObject( $ret );
1132  }
1133 
1145  public function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
1146  # Ignore errors during error handling to avoid infinite recursion
1147  $ignore = $this->ignoreErrors( true );
1149 
1150  if ( $ignore || $tempIgnore ) {
1151  wfDebug( "SQL ERROR (ignored): $error\n" );
1152  $this->ignoreErrors( $ignore );
1153  } else {
1154  $sql1line = mb_substr( str_replace( "\n", "\\n", $sql ), 0, 5 * 1024 );
1155  wfLogDBError( "$fname\t{$this->mServer}\t$errno\t$error\t$sql1line" );
1156  wfDebug( "SQL ERROR: " . $error . "\n" );
1157  throw new DBQueryError( $this, $error, $errno, $sql, $fname );
1158  }
1159  }
1160 
1175  protected function prepare( $sql, $func = 'DatabaseBase::prepare' ) {
1176  /* MySQL doesn't support prepared statements (yet), so just
1177  * pack up the query for reference. We'll manually replace
1178  * the bits later.
1179  */
1180  return array( 'query' => $sql, 'func' => $func );
1181  }
1182 
1187  protected function freePrepared( $prepared ) {
1188  /* No-op by default */
1189  }
1190 
1198  public function execute( $prepared, $args = null ) {
1199  if ( !is_array( $args ) ) {
1200  # Pull the var args
1201  $args = func_get_args();
1202  array_shift( $args );
1203  }
1204 
1205  $sql = $this->fillPrepared( $prepared['query'], $args );
1207  return $this->query( $sql, $prepared['func'] );
1208  }
1209 
1217  public function fillPrepared( $preparedQuery, $args ) {
1218  reset( $args );
1219  $this->preparedArgs =& $args;
1220 
1221  return preg_replace_callback( '/(\\\\[?!&]|[?!&])/',
1222  array( &$this, 'fillPreparedArg' ), $preparedQuery );
1223  }
1224 
1234  protected function fillPreparedArg( $matches ) {
1235  switch ( $matches[1] ) {
1236  case '\\?':
1237  return '?';
1238  case '\\!':
1239  return '!';
1240  case '\\&':
1241  return '&';
1242  }
1243 
1244  list( /* $n */, $arg ) = each( $this->preparedArgs );
1245 
1246  switch ( $matches[1] ) {
1247  case '?':
1248  return $this->addQuotes( $arg );
1249  case '!':
1250  return $arg;
1251  case '&':
1252  # return $this->addQuotes( file_get_contents( $arg ) );
1253  throw new DBUnexpectedError(
1254  $this,
1255  '& mode is not implemented. If it\'s really needed, uncomment the line above.'
1256  );
1257  default:
1258  throw new DBUnexpectedError(
1259  $this,
1260  'Received invalid match. This should never happen!'
1261  );
1262  }
1263  }
1264 
1272  public function freeResult( $res ) {
1273  }
1274 
1292  public function selectField( $table, $var, $cond = '', $fname = __METHOD__,
1293  $options = array()
1294  ) {
1295  if ( !is_array( $options ) ) {
1296  $options = array( $options );
1297  }
1298 
1299  $options['LIMIT'] = 1;
1300 
1301  $res = $this->select( $table, $var, $cond, $fname, $options );
1302 
1303  if ( $res === false || !$this->numRows( $res ) ) {
1304  return false;
1305  }
1306 
1307  $row = $this->fetchRow( $res );
1308 
1309  if ( $row !== false ) {
1310  return reset( $row );
1311  } else {
1312  return false;
1313  }
1314  }
1315 
1325  public function makeSelectOptions( $options ) {
1326  $preLimitTail = $postLimitTail = '';
1327  $startOpts = '';
1328 
1329  $noKeyOptions = array();
1330 
1331  foreach ( $options as $key => $option ) {
1332  if ( is_numeric( $key ) ) {
1333  $noKeyOptions[$option] = true;
1334  }
1335  }
1336 
1337  $preLimitTail .= $this->makeGroupByWithHaving( $options );
1338 
1339  $preLimitTail .= $this->makeOrderBy( $options );
1340 
1341  // if (isset($options['LIMIT'])) {
1342  // $tailOpts .= $this->limitResult('', $options['LIMIT'],
1343  // isset($options['OFFSET']) ? $options['OFFSET']
1344  // : false);
1345  // }
1346 
1347  if ( isset( $noKeyOptions['FOR UPDATE'] ) ) {
1348  $postLimitTail .= ' FOR UPDATE';
1349  }
1350 
1351  if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) {
1352  $postLimitTail .= ' LOCK IN SHARE MODE';
1353  }
1354 
1355  if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) {
1356  $startOpts .= 'DISTINCT';
1357  }
1358 
1359  # Various MySQL extensions
1360  if ( isset( $noKeyOptions['STRAIGHT_JOIN'] ) ) {
1361  $startOpts .= ' /*! STRAIGHT_JOIN */';
1362  }
1363 
1364  if ( isset( $noKeyOptions['HIGH_PRIORITY'] ) ) {
1365  $startOpts .= ' HIGH_PRIORITY';
1366  }
1367 
1368  if ( isset( $noKeyOptions['SQL_BIG_RESULT'] ) ) {
1369  $startOpts .= ' SQL_BIG_RESULT';
1370  }
1371 
1372  if ( isset( $noKeyOptions['SQL_BUFFER_RESULT'] ) ) {
1373  $startOpts .= ' SQL_BUFFER_RESULT';
1374  }
1375 
1376  if ( isset( $noKeyOptions['SQL_SMALL_RESULT'] ) ) {
1377  $startOpts .= ' SQL_SMALL_RESULT';
1378  }
1379 
1380  if ( isset( $noKeyOptions['SQL_CALC_FOUND_ROWS'] ) ) {
1381  $startOpts .= ' SQL_CALC_FOUND_ROWS';
1382  }
1383 
1384  if ( isset( $noKeyOptions['SQL_CACHE'] ) ) {
1385  $startOpts .= ' SQL_CACHE';
1386  }
1387 
1388  if ( isset( $noKeyOptions['SQL_NO_CACHE'] ) ) {
1389  $startOpts .= ' SQL_NO_CACHE';
1390  }
1391 
1392  if ( isset( $options['USE INDEX'] ) && is_string( $options['USE INDEX'] ) ) {
1393  $useIndex = $this->useIndexClause( $options['USE INDEX'] );
1394  } else {
1395  $useIndex = '';
1396  }
1397 
1398  return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail );
1399  }
1400 
1409  public function makeGroupByWithHaving( $options ) {
1410  $sql = '';
1411  if ( isset( $options['GROUP BY'] ) ) {
1412  $gb = is_array( $options['GROUP BY'] )
1413  ? implode( ',', $options['GROUP BY'] )
1414  : $options['GROUP BY'];
1415  $sql .= ' GROUP BY ' . $gb;
1416  }
1417  if ( isset( $options['HAVING'] ) ) {
1418  $having = is_array( $options['HAVING'] )
1419  ? $this->makeList( $options['HAVING'], LIST_AND )
1420  : $options['HAVING'];
1421  $sql .= ' HAVING ' . $having;
1422  }
1423 
1424  return $sql;
1425  }
1426 
1435  public function makeOrderBy( $options ) {
1436  if ( isset( $options['ORDER BY'] ) ) {
1437  $ob = is_array( $options['ORDER BY'] )
1438  ? implode( ',', $options['ORDER BY'] )
1439  : $options['ORDER BY'];
1440 
1441  return ' ORDER BY ' . $ob;
1442  }
1443 
1444  return '';
1445  }
1446 
1586  public function select( $table, $vars, $conds = '', $fname = __METHOD__,
1587  $options = array(), $join_conds = array() ) {
1588  $sql = $this->selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
1589 
1590  return $this->query( $sql, $fname );
1591  }
1592 
1609  public function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__,
1610  $options = array(), $join_conds = array()
1611  ) {
1612  if ( is_array( $vars ) ) {
1613  $vars = implode( ',', $this->fieldNamesWithAlias( $vars ) );
1614  }
1615 
1616  $options = (array)$options;
1617  $useIndexes = ( isset( $options['USE INDEX'] ) && is_array( $options['USE INDEX'] ) )
1618  ? $options['USE INDEX']
1619  : array();
1620 
1621  if ( is_array( $table ) ) {
1622  $from = ' FROM ' .
1623  $this->tableNamesWithUseIndexOrJOIN( $table, $useIndexes, $join_conds );
1624  } elseif ( $table != '' ) {
1625  if ( $table[0] == ' ' ) {
1626  $from = ' FROM ' . $table;
1627  } else {
1628  $from = ' FROM ' .
1629  $this->tableNamesWithUseIndexOrJOIN( array( $table ), $useIndexes, array() );
1630  }
1631  } else {
1632  $from = '';
1633  }
1634 
1635  list( $startOpts, $useIndex, $preLimitTail, $postLimitTail ) =
1636  $this->makeSelectOptions( $options );
1637 
1638  if ( !empty( $conds ) ) {
1639  if ( is_array( $conds ) ) {
1640  $conds = $this->makeList( $conds, LIST_AND );
1641  }
1642  $sql = "SELECT $startOpts $vars $from $useIndex WHERE $conds $preLimitTail";
1643  } else {
1644  $sql = "SELECT $startOpts $vars $from $useIndex $preLimitTail";
1645  }
1646 
1647  if ( isset( $options['LIMIT'] ) ) {
1648  $sql = $this->limitResult( $sql, $options['LIMIT'],
1649  isset( $options['OFFSET'] ) ? $options['OFFSET'] : false );
1650  }
1651  $sql = "$sql $postLimitTail";
1652 
1653  if ( isset( $options['EXPLAIN'] ) ) {
1654  $sql = 'EXPLAIN ' . $sql;
1655  }
1656 
1657  return $sql;
1658  }
1659 
1674  public function selectRow( $table, $vars, $conds, $fname = __METHOD__,
1675  $options = array(), $join_conds = array()
1676  ) {
1677  $options = (array)$options;
1678  $options['LIMIT'] = 1;
1679  $res = $this->select( $table, $vars, $conds, $fname, $options, $join_conds );
1680 
1681  if ( $res === false ) {
1682  return false;
1683  }
1684 
1685  if ( !$this->numRows( $res ) ) {
1686  return false;
1687  }
1688 
1689  $obj = $this->fetchObject( $res );
1690 
1691  return $obj;
1692  }
1693 
1714  public function estimateRowCount( $table, $vars = '*', $conds = '',
1715  $fname = __METHOD__, $options = array()
1716  ) {
1717  $rows = 0;
1718  $res = $this->select( $table, array( 'rowcount' => 'COUNT(*)' ), $conds, $fname, $options );
1719 
1720  if ( $res ) {
1721  $row = $this->fetchRow( $res );
1722  $rows = ( isset( $row['rowcount'] ) ) ? $row['rowcount'] : 0;
1723  }
1724 
1725  return $rows;
1726  }
1727 
1736  static function generalizeSQL( $sql ) {
1737  # This does the same as the regexp below would do, but in such a way
1738  # as to avoid crashing php on some large strings.
1739  # $sql = preg_replace( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql );
1740 
1741  $sql = str_replace( "\\\\", '', $sql );
1742  $sql = str_replace( "\\'", '', $sql );
1743  $sql = str_replace( "\\\"", '', $sql );
1744  $sql = preg_replace( "/'.*'/s", "'X'", $sql );
1745  $sql = preg_replace( '/".*"/s', "'X'", $sql );
1746 
1747  # All newlines, tabs, etc replaced by single space
1748  $sql = preg_replace( '/\s+/', ' ', $sql );
1749 
1750  # All numbers => N
1751  $sql = preg_replace( '/-?\d+(,-?\d+)+/s', 'N,...,N', $sql );
1752  $sql = preg_replace( '/-?\d+/s', 'N', $sql );
1753 
1754  return $sql;
1755  }
1756 
1765  public function fieldExists( $table, $field, $fname = __METHOD__ ) {
1766  $info = $this->fieldInfo( $table, $field );
1767 
1768  return (bool)$info;
1769  }
1781  public function indexExists( $table, $index, $fname = __METHOD__ ) {
1782  if ( !$this->tableExists( $table ) ) {
1783  return null;
1784  }
1785 
1786  $info = $this->indexInfo( $table, $index, $fname );
1787  if ( is_null( $info ) ) {
1788  return null;
1789  } else {
1790  return $info !== false;
1791  }
1792  }
1793 
1801  public function tableExists( $table, $fname = __METHOD__ ) {
1802  $table = $this->tableName( $table );
1803  $old = $this->ignoreErrors( true );
1804  $res = $this->query( "SELECT 1 FROM $table LIMIT 1", $fname );
1805  $this->ignoreErrors( $old );
1806 
1807  return (bool)$res;
1808  }
1809 
1818  public function indexUnique( $table, $index ) {
1819  $indexInfo = $this->indexInfo( $table, $index );
1820 
1821  if ( !$indexInfo ) {
1822  return null;
1823  }
1824 
1825  return !$indexInfo[0]->Non_unique;
1826  }
1827 
1834  protected function makeInsertOptions( $options ) {
1835  return implode( ' ', $options );
1836  }
1837 
1871  public function insert( $table, $a, $fname = __METHOD__, $options = array() ) {
1872  # No rows to insert, easy just return now
1873  if ( !count( $a ) ) {
1874  return true;
1875  }
1876 
1877  $table = $this->tableName( $table );
1878 
1879  if ( !is_array( $options ) ) {
1880  $options = array( $options );
1881  }
1882 
1883  $fh = null;
1884  if ( isset( $options['fileHandle'] ) ) {
1885  $fh = $options['fileHandle'];
1886  }
1887  $options = $this->makeInsertOptions( $options );
1888 
1889  if ( isset( $a[0] ) && is_array( $a[0] ) ) {
1890  $multi = true;
1891  $keys = array_keys( $a[0] );
1892  } else {
1893  $multi = false;
1894  $keys = array_keys( $a );
1895  }
1896 
1897  $sql = 'INSERT ' . $options .
1898  " INTO $table (" . implode( ',', $keys ) . ') VALUES ';
1899 
1900  if ( $multi ) {
1901  $first = true;
1902  foreach ( $a as $row ) {
1903  if ( $first ) {
1904  $first = false;
1905  } else {
1906  $sql .= ',';
1907  }
1908  $sql .= '(' . $this->makeList( $row ) . ')';
1909  }
1910  } else {
1911  $sql .= '(' . $this->makeList( $a ) . ')';
1912  }
1913 
1914  if ( $fh !== null && false === fwrite( $fh, $sql ) ) {
1915  return false;
1916  } elseif ( $fh !== null ) {
1917  return true;
1918  }
1919 
1920  return (bool)$this->query( $sql, $fname );
1921  }
1922 
1929  protected function makeUpdateOptionsArray( $options ) {
1930  if ( !is_array( $options ) ) {
1931  $options = array( $options );
1932  }
1933 
1934  $opts = array();
1935 
1936  if ( in_array( 'LOW_PRIORITY', $options ) ) {
1937  $opts[] = $this->lowPriorityOption();
1938  }
1939 
1940  if ( in_array( 'IGNORE', $options ) ) {
1941  $opts[] = 'IGNORE';
1942  }
1943 
1944  return $opts;
1945  }
1946 
1953  protected function makeUpdateOptions( $options ) {
1954  $opts = $this->makeUpdateOptionsArray( $options );
1955 
1956  return implode( ' ', $opts );
1957  }
1958 
1977  function update( $table, $values, $conds, $fname = __METHOD__, $options = array() ) {
1978  $table = $this->tableName( $table );
1979  $opts = $this->makeUpdateOptions( $options );
1980  $sql = "UPDATE $opts $table SET " . $this->makeList( $values, LIST_SET );
1981 
1982  if ( $conds !== array() && $conds !== '*' ) {
1983  $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
1984  }
1985 
1986  return $this->query( $sql, $fname );
1987  }
1988 
2003  public function makeList( $a, $mode = LIST_COMMA ) {
2004  if ( !is_array( $a ) ) {
2005  throw new DBUnexpectedError( $this, 'DatabaseBase::makeList called with incorrect parameters' );
2006  }
2007 
2008  $first = true;
2009  $list = '';
2010 
2011  foreach ( $a as $field => $value ) {
2012  if ( !$first ) {
2013  if ( $mode == LIST_AND ) {
2014  $list .= ' AND ';
2015  } elseif ( $mode == LIST_OR ) {
2016  $list .= ' OR ';
2017  } else {
2018  $list .= ',';
2019  }
2020  } else {
2021  $first = false;
2022  }
2023 
2024  if ( ( $mode == LIST_AND || $mode == LIST_OR ) && is_numeric( $field ) ) {
2025  $list .= "($value)";
2026  } elseif ( ( $mode == LIST_SET ) && is_numeric( $field ) ) {
2027  $list .= "$value";
2028  } elseif ( ( $mode == LIST_AND || $mode == LIST_OR ) && is_array( $value ) ) {
2029  if ( count( $value ) == 0 ) {
2030  throw new MWException( __METHOD__ . ": empty input for field $field" );
2031  } elseif ( count( $value ) == 1 ) {
2032  // Special-case single values, as IN isn't terribly efficient
2033  // Don't necessarily assume the single key is 0; we don't
2034  // enforce linear numeric ordering on other arrays here.
2035  $value = array_values( $value );
2036  $list .= $field . " = " . $this->addQuotes( $value[0] );
2037  } else {
2038  $list .= $field . " IN (" . $this->makeList( $value ) . ") ";
2039  }
2040  } elseif ( $value === null ) {
2041  if ( $mode == LIST_AND || $mode == LIST_OR ) {
2042  $list .= "$field IS ";
2043  } elseif ( $mode == LIST_SET ) {
2044  $list .= "$field = ";
2045  }
2046  $list .= 'NULL';
2047  } else {
2048  if ( $mode == LIST_AND || $mode == LIST_OR || $mode == LIST_SET ) {
2049  $list .= "$field = ";
2050  }
2051  $list .= $mode == LIST_NAMES ? $value : $this->addQuotes( $value );
2052  }
2053  }
2054 
2055  return $list;
2056  }
2068  public function makeWhereFrom2d( $data, $baseKey, $subKey ) {
2069  $conds = array();
2070 
2071  foreach ( $data as $base => $sub ) {
2072  if ( count( $sub ) ) {
2073  $conds[] = $this->makeList(
2074  array( $baseKey => $base, $subKey => array_keys( $sub ) ),
2075  LIST_AND );
2076  }
2077  }
2078 
2079  if ( $conds ) {
2080  return $this->makeList( $conds, LIST_OR );
2081  } else {
2082  // Nothing to search for...
2083  return false;
2084  }
2085  }
2086 
2095  public function aggregateValue( $valuedata, $valuename = 'value' ) {
2096  return $valuename;
2097  }
2098 
2103  public function bitNot( $field ) {
2104  return "(~$field)";
2105  }
2106 
2112  public function bitAnd( $fieldLeft, $fieldRight ) {
2113  return "($fieldLeft & $fieldRight)";
2114  }
2115 
2121  public function bitOr( $fieldLeft, $fieldRight ) {
2122  return "($fieldLeft | $fieldRight)";
2123  }
2124 
2131  public function buildConcat( $stringList ) {
2132  return 'CONCAT(' . implode( ',', $stringList ) . ')';
2133  }
2134 
2151  public function buildGroupConcatField(
2152  $delim, $table, $field, $conds = '', $join_conds = array()
2153  ) {
2154  $fld = "GROUP_CONCAT($field SEPARATOR " . $this->addQuotes( $delim ) . ')';
2155 
2156  return '(' . $this->selectSQLText( $table, $fld, $conds, null, array(), $join_conds ) . ')';
2157  }
2158 
2168  public function selectDB( $db ) {
2169  # Stub. Shouldn't cause serious problems if it's not overridden, but
2170  # if your database engine supports a concept similar to MySQL's
2171  # databases you may as well.
2172  $this->mDBname = $db;
2173 
2174  return true;
2175  }
2180  public function getDBname() {
2181  return $this->mDBname;
2182  }
2183 
2187  public function getServer() {
2188  return $this->mServer;
2189  }
2190 
2208  public function tableName( $name, $format = 'quoted' ) {
2209  global $wgSharedDB, $wgSharedPrefix, $wgSharedTables, $wgSharedSchema;
2210  # Skip the entire process when we have a string quoted on both ends.
2211  # Note that we check the end so that we will still quote any use of
2212  # use of `database`.table. But won't break things if someone wants
2213  # to query a database table with a dot in the name.
2214  if ( $this->isQuotedIdentifier( $name ) ) {
2215  return $name;
2216  }
2217 
2218  # Lets test for any bits of text that should never show up in a table
2219  # name. Basically anything like JOIN or ON which are actually part of
2220  # SQL queries, but may end up inside of the table value to combine
2221  # sql. Such as how the API is doing.
2222  # Note that we use a whitespace test rather than a \b test to avoid
2223  # any remote case where a word like on may be inside of a table name
2224  # surrounded by symbols which may be considered word breaks.
2225  if ( preg_match( '/(^|\s)(DISTINCT|JOIN|ON|AS)(\s|$)/i', $name ) !== 0 ) {
2226  return $name;
2227  }
2228 
2229  # Split database and table into proper variables.
2230  # We reverse the explode so that database.table and table both output
2231  # the correct table.
2232  $dbDetails = explode( '.', $name, 2 );
2233  if ( count( $dbDetails ) == 3 ) {
2234  list( $database, $schema, $table ) = $dbDetails;
2235  # We don't want any prefix added in this case
2236  $prefix = '';
2237  } elseif ( count( $dbDetails ) == 2 ) {
2238  list( $database, $table ) = $dbDetails;
2239  # We don't want any prefix added in this case
2240  # In dbs that support it, $database may actually be the schema
2241  # but that doesn't affect any of the functionality here
2242  $prefix = '';
2243  $schema = null;
2244  } else {
2245  list( $table ) = $dbDetails;
2246  if ( $wgSharedDB !== null # We have a shared database
2247  && $this->mForeign == false # We're not working on a foreign database
2248  && !$this->isQuotedIdentifier( $table ) # Prevent shared tables listing '`table`'
2249  && in_array( $table, $wgSharedTables ) # A shared table is selected
2250  ) {
2251  $database = $wgSharedDB;
2252  $schema = $wgSharedSchema === null ? $this->mSchema : $wgSharedSchema;
2253  $prefix = $wgSharedPrefix === null ? $this->mTablePrefix : $wgSharedPrefix;
2254  } else {
2255  $database = null;
2256  $schema = $this->mSchema; # Default schema
2257  $prefix = $this->mTablePrefix; # Default prefix
2258  }
2259  }
2260 
2261  # Quote $table and apply the prefix if not quoted.
2262  # $tableName might be empty if this is called from Database::replaceVars()
2263  $tableName = "{$prefix}{$table}";
2264  if ( $format == 'quoted' && !$this->isQuotedIdentifier( $tableName ) && $tableName !== '' ) {
2265  $tableName = $this->addIdentifierQuotes( $tableName );
2266  }
2267 
2268  # Quote $schema and merge it with the table name if needed
2269  if ( $schema !== null ) {
2270  if ( $format == 'quoted' && !$this->isQuotedIdentifier( $schema ) ) {
2271  $schema = $this->addIdentifierQuotes( $schema );
2272  }
2273  $tableName = $schema . '.' . $tableName;
2274  }
2275 
2276  # Quote $database and merge it with the table name if needed
2277  if ( $database !== null ) {
2278  if ( $format == 'quoted' && !$this->isQuotedIdentifier( $database ) ) {
2279  $database = $this->addIdentifierQuotes( $database );
2280  }
2281  $tableName = $database . '.' . $tableName;
2282  }
2283 
2284  return $tableName;
2285  }
2286 
2298  public function tableNames() {
2299  $inArray = func_get_args();
2300  $retVal = array();
2301 
2302  foreach ( $inArray as $name ) {
2303  $retVal[$name] = $this->tableName( $name );
2304  }
2305 
2306  return $retVal;
2307  }
2308 
2320  public function tableNamesN() {
2321  $inArray = func_get_args();
2322  $retVal = array();
2323 
2324  foreach ( $inArray as $name ) {
2325  $retVal[] = $this->tableName( $name );
2326  }
2327 
2328  return $retVal;
2329  }
2330 
2339  public function tableNameWithAlias( $name, $alias = false ) {
2340  if ( !$alias || $alias == $name ) {
2341  return $this->tableName( $name );
2342  } else {
2343  return $this->tableName( $name ) . ' ' . $this->addIdentifierQuotes( $alias );
2344  }
2345  }
2346 
2353  public function tableNamesWithAlias( $tables ) {
2354  $retval = array();
2355  foreach ( $tables as $alias => $table ) {
2356  if ( is_numeric( $alias ) ) {
2357  $alias = $table;
2358  }
2359  $retval[] = $this->tableNameWithAlias( $table, $alias );
2360  }
2361 
2362  return $retval;
2363  }
2364 
2373  public function fieldNameWithAlias( $name, $alias = false ) {
2374  if ( !$alias || (string)$alias === (string)$name ) {
2375  return $name;
2376  } else {
2377  return $name . ' AS ' . $alias; //PostgreSQL needs AS
2378  }
2379  }
2380 
2387  public function fieldNamesWithAlias( $fields ) {
2388  $retval = array();
2389  foreach ( $fields as $alias => $field ) {
2390  if ( is_numeric( $alias ) ) {
2391  $alias = $field;
2392  }
2393  $retval[] = $this->fieldNameWithAlias( $field, $alias );
2394  }
2395 
2396  return $retval;
2397  }
2398 
2408  protected function tableNamesWithUseIndexOrJOIN(
2409  $tables, $use_index = array(), $join_conds = array()
2410  ) {
2411  $ret = array();
2412  $retJOIN = array();
2413  $use_index = (array)$use_index;
2414  $join_conds = (array)$join_conds;
2415 
2416  foreach ( $tables as $alias => $table ) {
2417  if ( !is_string( $alias ) ) {
2418  // No alias? Set it equal to the table name
2419  $alias = $table;
2420  }
2421  // Is there a JOIN clause for this table?
2422  if ( isset( $join_conds[$alias] ) ) {
2423  list( $joinType, $conds ) = $join_conds[$alias];
2424  $tableClause = $joinType;
2425  $tableClause .= ' ' . $this->tableNameWithAlias( $table, $alias );
2426  if ( isset( $use_index[$alias] ) ) { // has USE INDEX?
2427  $use = $this->useIndexClause( implode( ',', (array)$use_index[$alias] ) );
2428  if ( $use != '' ) {
2429  $tableClause .= ' ' . $use;
2430  }
2431  }
2432  $on = $this->makeList( (array)$conds, LIST_AND );
2433  if ( $on != '' ) {
2434  $tableClause .= ' ON (' . $on . ')';
2435  }
2436 
2437  $retJOIN[] = $tableClause;
2438  } elseif ( isset( $use_index[$alias] ) ) {
2439  // Is there an INDEX clause for this table?
2440  $tableClause = $this->tableNameWithAlias( $table, $alias );
2441  $tableClause .= ' ' . $this->useIndexClause(
2442  implode( ',', (array)$use_index[$alias] )
2443  );
2444 
2445  $ret[] = $tableClause;
2446  } else {
2447  $tableClause = $this->tableNameWithAlias( $table, $alias );
2448 
2449  $ret[] = $tableClause;
2450  }
2451  }
2452 
2453  // We can't separate explicit JOIN clauses with ',', use ' ' for those
2454  $implicitJoins = !empty( $ret ) ? implode( ',', $ret ) : "";
2455  $explicitJoins = !empty( $retJOIN ) ? implode( ' ', $retJOIN ) : "";
2457  // Compile our final table clause
2458  return implode( ' ', array( $implicitJoins, $explicitJoins ) );
2459  }
2460 
2467  protected function indexName( $index ) {
2468  // Backwards-compatibility hack
2469  $renamed = array(
2470  'ar_usertext_timestamp' => 'usertext_timestamp',
2471  'un_user_id' => 'user_id',
2472  'un_user_ip' => 'user_ip',
2473  );
2474 
2475  if ( isset( $renamed[$index] ) ) {
2476  return $renamed[$index];
2477  } else {
2478  return $index;
2479  }
2480  }
2481 
2488  public function addQuotes( $s ) {
2489  if ( $s === null ) {
2490  return 'NULL';
2491  } else {
2492  # This will also quote numeric values. This should be harmless,
2493  # and protects against weird problems that occur when they really
2494  # _are_ strings such as article titles and string->number->string
2495  # conversion is not 1:1.
2496  return "'" . $this->strencode( $s ) . "'";
2497  }
2498  }
2499 
2509  public function addIdentifierQuotes( $s ) {
2510  return '"' . str_replace( '"', '""', $s ) . '"';
2511  }
2512 
2520  public function isQuotedIdentifier( $name ) {
2521  return $name[0] == '"' && substr( $name, -1, 1 ) == '"';
2522  }
2523 
2528  protected function escapeLikeInternal( $s ) {
2529  $s = str_replace( '\\', '\\\\', $s );
2530  $s = $this->strencode( $s );
2531  $s = str_replace( array( '%', '_' ), array( '\%', '\_' ), $s );
2532 
2533  return $s;
2534  }
2535 
2552  public function buildLike() {
2553  $params = func_get_args();
2554 
2555  if ( count( $params ) > 0 && is_array( $params[0] ) ) {
2556  $params = $params[0];
2557  }
2558 
2559  $s = '';
2560 
2561  foreach ( $params as $value ) {
2562  if ( $value instanceof LikeMatch ) {
2563  $s .= $value->toString();
2564  } else {
2565  $s .= $this->escapeLikeInternal( $value );
2566  }
2567  }
2568 
2569  return " LIKE '" . $s . "' ";
2570  }
2571 
2577  public function anyChar() {
2578  return new LikeMatch( '_' );
2579  }
2580 
2586  public function anyString() {
2587  return new LikeMatch( '%' );
2588  }
2589 
2601  public function nextSequenceValue( $seqName ) {
2602  return null;
2603  }
2615  public function useIndexClause( $index ) {
2616  return '';
2617  }
2618 
2641  public function replace( $table, $uniqueIndexes, $rows, $fname = __METHOD__ ) {
2642  $quotedTable = $this->tableName( $table );
2643 
2644  if ( count( $rows ) == 0 ) {
2645  return;
2646  }
2647 
2648  # Single row case
2649  if ( !is_array( reset( $rows ) ) ) {
2650  $rows = array( $rows );
2651  }
2652 
2653  foreach ( $rows as $row ) {
2654  # Delete rows which collide
2655  if ( $uniqueIndexes ) {
2656  $sql = "DELETE FROM $quotedTable WHERE ";
2657  $first = true;
2658  foreach ( $uniqueIndexes as $index ) {
2659  if ( $first ) {
2660  $first = false;
2661  $sql .= '( ';
2662  } else {
2663  $sql .= ' ) OR ( ';
2664  }
2665  if ( is_array( $index ) ) {
2666  $first2 = true;
2667  foreach ( $index as $col ) {
2668  if ( $first2 ) {
2669  $first2 = false;
2670  } else {
2671  $sql .= ' AND ';
2672  }
2673  $sql .= $col . '=' . $this->addQuotes( $row[$col] );
2674  }
2675  } else {
2676  $sql .= $index . '=' . $this->addQuotes( $row[$index] );
2677  }
2678  }
2679  $sql .= ' )';
2680  $this->query( $sql, $fname );
2681  }
2682 
2683  # Now insert the row
2684  $this->insert( $table, $row, $fname );
2685  }
2686  }
2698  protected function nativeReplace( $table, $rows, $fname ) {
2699  $table = $this->tableName( $table );
2700 
2701  # Single row case
2702  if ( !is_array( reset( $rows ) ) ) {
2703  $rows = array( $rows );
2704  }
2705 
2706  $sql = "REPLACE INTO $table (" . implode( ',', array_keys( $rows[0] ) ) . ') VALUES ';
2707  $first = true;
2708 
2709  foreach ( $rows as $row ) {
2710  if ( $first ) {
2711  $first = false;
2712  } else {
2713  $sql .= ',';
2714  }
2715 
2716  $sql .= '(' . $this->makeList( $row ) . ')';
2717  }
2718 
2719  return $this->query( $sql, $fname );
2720  }
2721 
2756  public function upsert( $table, array $rows, array $uniqueIndexes, array $set,
2757  $fname = __METHOD__
2758  ) {
2759  if ( !count( $rows ) ) {
2760  return true; // nothing to do
2761  }
2762 
2763  if ( !is_array( reset( $rows ) ) ) {
2764  $rows = array( $rows );
2765  }
2766 
2767  if ( count( $uniqueIndexes ) ) {
2768  $clauses = array(); // list WHERE clauses that each identify a single row
2769  foreach ( $rows as $row ) {
2770  foreach ( $uniqueIndexes as $index ) {
2771  $index = is_array( $index ) ? $index : array( $index ); // columns
2772  $rowKey = array(); // unique key to this row
2773  foreach ( $index as $column ) {
2774  $rowKey[$column] = $row[$column];
2775  }
2776  $clauses[] = $this->makeList( $rowKey, LIST_AND );
2777  }
2778  }
2779  $where = array( $this->makeList( $clauses, LIST_OR ) );
2780  } else {
2781  $where = false;
2782  }
2783 
2784  $useTrx = !$this->mTrxLevel;
2785  if ( $useTrx ) {
2786  $this->begin( $fname );
2787  }
2788  try {
2789  # Update any existing conflicting row(s)
2790  if ( $where !== false ) {
2791  $ok = $this->update( $table, $set, $where, $fname );
2792  } else {
2793  $ok = true;
2794  }
2795  # Now insert any non-conflicting row(s)
2796  $ok = $this->insert( $table, $rows, $fname, array( 'IGNORE' ) ) && $ok;
2797  } catch ( Exception $e ) {
2798  if ( $useTrx ) {
2799  $this->rollback( $fname );
2800  }
2801  throw $e;
2802  }
2803  if ( $useTrx ) {
2804  $this->commit( $fname );
2805  }
2806 
2807  return $ok;
2808  }
2809 
2830  public function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds,
2831  $fname = __METHOD__
2832  ) {
2833  if ( !$conds ) {
2834  throw new DBUnexpectedError( $this,
2835  'DatabaseBase::deleteJoin() called with empty $conds' );
2836  }
2837 
2838  $delTable = $this->tableName( $delTable );
2839  $joinTable = $this->tableName( $joinTable );
2840  $sql = "DELETE FROM $delTable WHERE $delVar IN (SELECT $joinVar FROM $joinTable ";
2841  if ( $conds != '*' ) {
2842  $sql .= 'WHERE ' . $this->makeList( $conds, LIST_AND );
2843  }
2844  $sql .= ')';
2846  $this->query( $sql, $fname );
2847  }
2848 
2856  public function textFieldSize( $table, $field ) {
2857  $table = $this->tableName( $table );
2858  $sql = "SHOW COLUMNS FROM $table LIKE \"$field\";";
2859  $res = $this->query( $sql, 'DatabaseBase::textFieldSize' );
2860  $row = $this->fetchObject( $res );
2861 
2862  $m = array();
2863 
2864  if ( preg_match( '/\((.*)\)/', $row->Type, $m ) ) {
2865  $size = $m[1];
2866  } else {
2867  $size = -1;
2868  }
2869 
2870  return $size;
2871  }
2872 
2881  public function lowPriorityOption() {
2882  return '';
2883  }
2895  public function delete( $table, $conds, $fname = __METHOD__ ) {
2896  if ( !$conds ) {
2897  throw new DBUnexpectedError( $this, 'DatabaseBase::delete() called with no conditions' );
2898  }
2899 
2900  $table = $this->tableName( $table );
2901  $sql = "DELETE FROM $table";
2902 
2903  if ( $conds != '*' ) {
2904  if ( is_array( $conds ) ) {
2905  $conds = $this->makeList( $conds, LIST_AND );
2906  }
2907  $sql .= ' WHERE ' . $conds;
2908  }
2909 
2910  return $this->query( $sql, $fname );
2911  }
2912 
2939  public function insertSelect( $destTable, $srcTable, $varMap, $conds,
2940  $fname = __METHOD__,
2941  $insertOptions = array(), $selectOptions = array()
2942  ) {
2943  $destTable = $this->tableName( $destTable );
2944 
2945  if ( !is_array( $insertOptions ) ) {
2946  $insertOptions = array( $insertOptions );
2947  }
2948 
2949  $insertOptions = $this->makeInsertOptions( $insertOptions );
2950 
2951  if ( !is_array( $selectOptions ) ) {
2952  $selectOptions = array( $selectOptions );
2953  }
2954 
2955  list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions );
2956 
2957  if ( is_array( $srcTable ) ) {
2958  $srcTable = implode( ',', array_map( array( &$this, 'tableName' ), $srcTable ) );
2959  } else {
2960  $srcTable = $this->tableName( $srcTable );
2961  }
2962 
2963  $sql = "INSERT $insertOptions INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
2964  " SELECT $startOpts " . implode( ',', $varMap ) .
2965  " FROM $srcTable $useIndex ";
2966 
2967  if ( $conds != '*' ) {
2968  if ( is_array( $conds ) ) {
2969  $conds = $this->makeList( $conds, LIST_AND );
2970  }
2971  $sql .= " WHERE $conds";
2972  }
2973 
2974  $sql .= " $tailOpts";
2975 
2976  return $this->query( $sql, $fname );
2977  }
2978 
2998  public function limitResult( $sql, $limit, $offset = false ) {
2999  if ( !is_numeric( $limit ) ) {
3000  throw new DBUnexpectedError( $this, "Invalid non-numeric limit passed to limitResult()\n" );
3001  }
3003  return "$sql LIMIT "
3004  . ( ( is_numeric( $offset ) && $offset != 0 ) ? "{$offset}," : "" )
3005  . "{$limit} ";
3006  }
3007 
3013  public function unionSupportsOrderAndLimit() {
3014  return true; // True for almost every DB supported
3015  }
3016 
3025  public function unionQueries( $sqls, $all ) {
3026  $glue = $all ? ') UNION ALL (' : ') UNION (';
3027 
3028  return '(' . implode( $glue, $sqls ) . ')';
3029  }
3030 
3040  public function conditional( $cond, $trueVal, $falseVal ) {
3041  if ( is_array( $cond ) ) {
3042  $cond = $this->makeList( $cond, LIST_AND );
3043  }
3044 
3045  return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) ";
3046  }
3058  public function strreplace( $orig, $old, $new ) {
3059  return "REPLACE({$orig}, {$old}, {$new})";
3060  }
3061 
3068  public function getServerUptime() {
3069  return 0;
3070  }
3071 
3078  public function wasDeadlock() {
3079  return false;
3080  }
3081 
3088  public function wasLockTimeout() {
3089  return false;
3090  }
3091 
3099  public function wasErrorReissuable() {
3100  return false;
3101  }
3102 
3109  public function wasReadOnlyError() {
3110  return false;
3111  }
3112 
3131  public function deadlockLoop() {
3132  $this->begin( __METHOD__ );
3133  $args = func_get_args();
3134  $function = array_shift( $args );
3135  $oldIgnore = $this->ignoreErrors( true );
3136  $tries = self::DEADLOCK_TRIES;
3137 
3138  if ( is_array( $function ) ) {
3139  $fname = $function[0];
3140  } else {
3141  $fname = $function;
3142  }
3143 
3144  do {
3145  $retVal = call_user_func_array( $function, $args );
3146  $error = $this->lastError();
3147  $errno = $this->lastErrno();
3148  $sql = $this->lastQuery();
3149 
3150  if ( $errno ) {
3151  if ( $this->wasDeadlock() ) {
3152  # Retry
3153  usleep( mt_rand( self::DEADLOCK_DELAY_MIN, self::DEADLOCK_DELAY_MAX ) );
3154  } else {
3155  $this->reportQueryError( $error, $errno, $sql, $fname );
3156  }
3157  }
3158  } while ( $this->wasDeadlock() && --$tries > 0 );
3159 
3160  $this->ignoreErrors( $oldIgnore );
3161 
3162  if ( $tries <= 0 ) {
3163  $this->rollback( __METHOD__ );
3164  $this->reportQueryError( $error, $errno, $sql, $fname );
3165 
3166  return false;
3167  } else {
3168  $this->commit( __METHOD__ );
3169 
3170  return $retVal;
3171  }
3172  }
3184  public function masterPosWait( DBMasterPos $pos, $timeout ) {
3185  # Real waits are implemented in the subclass.
3186  return 0;
3187  }
3188 
3194  public function getSlavePos() {
3195  # Stub
3196  return false;
3197  }
3198 
3204  public function getMasterPos() {
3205  # Stub
3206  return false;
3207  }
3208 
3223  final public function onTransactionIdle( $callback ) {
3224  $this->mTrxIdleCallbacks[] = array( $callback, wfGetCaller() );
3225  if ( !$this->mTrxLevel ) {
3227  }
3228  }
3229 
3241  final public function onTransactionPreCommitOrIdle( $callback ) {
3242  if ( $this->mTrxLevel ) {
3243  $this->mTrxPreCommitCallbacks[] = array( $callback, wfGetCaller() );
3244  } else {
3245  $this->onTransactionIdle( $callback ); // this will trigger immediately
3246  }
3247  }
3248 
3254  protected function runOnTransactionIdleCallbacks() {
3255  $autoTrx = $this->getFlag( DBO_TRX ); // automatic begin() enabled?
3256 
3257  $e = null; // last exception
3258  do { // callbacks may add callbacks :)
3259  $callbacks = $this->mTrxIdleCallbacks;
3260  $this->mTrxIdleCallbacks = array(); // recursion guard
3261  foreach ( $callbacks as $callback ) {
3262  try {
3263  list( $phpCallback ) = $callback;
3264  $this->clearFlag( DBO_TRX ); // make each query its own transaction
3265  call_user_func( $phpCallback );
3266  $this->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
3267  } catch ( Exception $e ) {
3268  }
3269  }
3270  } while ( count( $this->mTrxIdleCallbacks ) );
3272  if ( $e instanceof Exception ) {
3273  throw $e; // re-throw any last exception
3274  }
3275  }
3276 
3282  protected function runOnTransactionPreCommitCallbacks() {
3283  $e = null; // last exception
3284  do { // callbacks may add callbacks :)
3285  $callbacks = $this->mTrxPreCommitCallbacks;
3286  $this->mTrxPreCommitCallbacks = array(); // recursion guard
3287  foreach ( $callbacks as $callback ) {
3288  try {
3289  list( $phpCallback ) = $callback;
3290  call_user_func( $phpCallback );
3291  } catch ( Exception $e ) {
3292  }
3293  }
3294  } while ( count( $this->mTrxPreCommitCallbacks ) );
3295 
3296  if ( $e instanceof Exception ) {
3297  throw $e; // re-throw any last exception
3298  }
3299  }
3300 
3325  final public function startAtomic( $fname = __METHOD__ ) {
3326  if ( !$this->mTrxLevel ) {
3327  $this->begin( $fname );
3328  $this->mTrxAutomatic = true;
3329  $this->mTrxAutomaticAtomic = true;
3330  }
3331 
3332  $this->mTrxAtomicLevels->push( $fname );
3333  }
3334 
3346  final public function endAtomic( $fname = __METHOD__ ) {
3347  if ( !$this->mTrxLevel ) {
3348  throw new DBUnexpectedError( $this, 'No atomic transaction is open.' );
3349  }
3350  if ( $this->mTrxAtomicLevels->isEmpty() ||
3351  $this->mTrxAtomicLevels->pop() !== $fname
3352  ) {
3353  throw new DBUnexpectedError( $this, 'Invalid atomic section ended.' );
3354  }
3355 
3356  if ( $this->mTrxAtomicLevels->isEmpty() && $this->mTrxAutomaticAtomic ) {
3357  $this->commit( $fname, 'flush' );
3358  }
3359  }
3360 
3376  final public function begin( $fname = __METHOD__ ) {
3377  global $wgDebugDBTransactions;
3378 
3379  if ( $this->mTrxLevel ) { // implicit commit
3380  if ( !$this->mTrxAtomicLevels->isEmpty() ) {
3381  // If the current transaction was an automatic atomic one, then we definitely have
3382  // a problem. Same if there is any unclosed atomic level.
3383  throw new DBUnexpectedError( $this,
3384  "Attempted to start explicit transaction when atomic levels are still open."
3385  );
3386  } elseif ( !$this->mTrxAutomatic ) {
3387  // We want to warn about inadvertently nested begin/commit pairs, but not about
3388  // auto-committing implicit transactions that were started by query() via DBO_TRX
3389  $msg = "$fname: Transaction already in progress (from {$this->mTrxFname}), " .
3390  " performing implicit commit!";
3391  wfWarn( $msg );
3392  wfLogDBError( $msg );
3393  } else {
3394  // if the transaction was automatic and has done write operations,
3395  // log it if $wgDebugDBTransactions is enabled.
3396  if ( $this->mTrxDoneWrites && $wgDebugDBTransactions ) {
3397  wfDebug( "$fname: Automatic transaction with writes in progress" .
3398  " (from {$this->mTrxFname}), performing implicit commit!\n"
3399  );
3400  }
3401  }
3402 
3404  $this->doCommit( $fname );
3405  if ( $this->mTrxDoneWrites ) {
3406  Profiler::instance()->transactionWritingOut( $this->mServer, $this->mDBname );
3407  }
3409  }
3410 
3411  $this->doBegin( $fname );
3412  $this->mTrxFname = $fname;
3413  $this->mTrxDoneWrites = false;
3414  $this->mTrxAutomatic = false;
3415  $this->mTrxAutomaticAtomic = false;
3416  $this->mTrxAtomicLevels = new SplStack;
3417  $this->mTrxIdleCallbacks = array();
3418  $this->mTrxPreCommitCallbacks = array();
3419  }
3420 
3427  protected function doBegin( $fname ) {
3428  $this->query( 'BEGIN', $fname );
3429  $this->mTrxLevel = 1;
3430  }
3431 
3446  final public function commit( $fname = __METHOD__, $flush = '' ) {
3447  if ( !$this->mTrxAtomicLevels->isEmpty() ) {
3448  // There are still atomic sections open. This cannot be ignored
3449  throw new DBUnexpectedError(
3450  $this,
3451  "Attempted to commit transaction while atomic sections are still open"
3452  );
3453  }
3454 
3455  if ( $flush !== 'flush' ) {
3456  if ( !$this->mTrxLevel ) {
3457  wfWarn( "$fname: No transaction to commit, something got out of sync!" );
3458  } elseif ( $this->mTrxAutomatic ) {
3459  wfWarn( "$fname: Explicit commit of implicit transaction. Something may be out of sync!" );
3460  }
3461  } else {
3462  if ( !$this->mTrxLevel ) {
3463  return; // nothing to do
3464  } elseif ( !$this->mTrxAutomatic ) {
3465  wfWarn( "$fname: Flushing an explicit transaction, getting out of sync!" );
3466  }
3467  }
3468 
3470  $this->doCommit( $fname );
3471  if ( $this->mTrxDoneWrites ) {
3472  Profiler::instance()->transactionWritingOut( $this->mServer, $this->mDBname );
3473  }
3475  }
3476 
3483  protected function doCommit( $fname ) {
3484  if ( $this->mTrxLevel ) {
3485  $this->query( 'COMMIT', $fname );
3486  $this->mTrxLevel = 0;
3487  }
3488  }
3489 
3503  final public function rollback( $fname = __METHOD__, $flush = '' ) {
3504  if ( $flush !== 'flush' ) {
3505  if ( !$this->mTrxLevel ) {
3506  wfWarn( "$fname: No transaction to rollback, something got out of sync!" );
3507  } elseif ( $this->mTrxAutomatic ) {
3508  wfWarn( "$fname: Explicit rollback of implicit transaction. Something may be out of sync!" );
3509  }
3510  } else {
3511  if ( !$this->mTrxLevel ) {
3512  return; // nothing to do
3513  } elseif ( !$this->mTrxAutomatic ) {
3514  wfWarn( "$fname: Flushing an explicit transaction, getting out of sync!" );
3515  }
3516  }
3517 
3518  $this->doRollback( $fname );
3519  $this->mTrxIdleCallbacks = array(); // cancel
3520  $this->mTrxPreCommitCallbacks = array(); // cancel
3521  $this->mTrxAtomicLevels = new SplStack;
3522  if ( $this->mTrxDoneWrites ) {
3523  Profiler::instance()->transactionWritingOut( $this->mServer, $this->mDBname );
3524  }
3525  }
3526 
3533  protected function doRollback( $fname ) {
3534  if ( $this->mTrxLevel ) {
3535  $this->query( 'ROLLBACK', $fname, true );
3536  $this->mTrxLevel = 0;
3537  }
3538  }
3539 
3555  public function duplicateTableStructure( $oldName, $newName, $temporary = false,
3556  $fname = __METHOD__
3557  ) {
3558  throw new MWException(
3559  'DatabaseBase::duplicateTableStructure is not implemented in descendant class' );
3560  }
3561 
3569  function listTables( $prefix = null, $fname = __METHOD__ ) {
3570  throw new MWException( 'DatabaseBase::listTables is not implemented in descendant class' );
3571  }
3572 
3577  final public function clearViewsCache() {
3578  $this->allViews = null;
3579  }
3580 
3592  public function listViews( $prefix = null, $fname = __METHOD__ ) {
3593  throw new MWException( 'DatabaseBase::listViews is not implemented in descendant class' );
3594  }
3595 
3603  public function isView( $name ) {
3604  throw new MWException( 'DatabaseBase::isView is not implemented in descendant class' );
3605  }
3606 
3618  public function timestamp( $ts = 0 ) {
3619  return wfTimestamp( TS_MW, $ts );
3620  }
3621 
3635  public function timestampOrNull( $ts = null ) {
3636  if ( is_null( $ts ) ) {
3637  return null;
3638  } else {
3639  return $this->timestamp( $ts );
3640  }
3641  }
3642 
3657  public function resultObject( $result ) {
3658  if ( empty( $result ) ) {
3659  return false;
3660  } elseif ( $result instanceof ResultWrapper ) {
3661  return $result;
3662  } elseif ( $result === true ) {
3663  // Successful write query
3664  return $result;
3665  } else {
3666  return new ResultWrapper( $this, $result );
3667  }
3668  }
3669 
3675  public function ping() {
3676  # Stub. Not essential to override.
3677  return true;
3678  }
3679 
3689  public function getLag() {
3690  return 0;
3691  }
3692 
3698  function maxListLen() {
3699  return 0;
3700  }
3701 
3711  public function encodeBlob( $b ) {
3712  return $b;
3713  }
3714 
3723  public function decodeBlob( $b ) {
3724  return $b;
3725  }
3737  public function setSessionOptions( array $options ) {
3738  }
3739 
3756  public function sourceFile(
3757  $filename, $lineCallback = false, $resultCallback = false, $fname = false, $inputCallback = false
3758  ) {
3760  $fp = fopen( $filename, 'r' );
3762 
3763  if ( false === $fp ) {
3764  throw new MWException( "Could not open \"{$filename}\".\n" );
3765  }
3766 
3767  if ( !$fname ) {
3768  $fname = __METHOD__ . "( $filename )";
3769  }
3770 
3771  try {
3772  $error = $this->sourceStream( $fp, $lineCallback, $resultCallback, $fname, $inputCallback );
3773  } catch ( MWException $e ) {
3774  fclose( $fp );
3775  throw $e;
3776  }
3777 
3778  fclose( $fp );
3779 
3780  return $error;
3781  }
3782 
3791  public function patchPath( $patch ) {
3792  global $IP;
3793 
3794  $dbType = $this->getType();
3795  if ( file_exists( "$IP/maintenance/$dbType/archives/$patch" ) ) {
3796  return "$IP/maintenance/$dbType/archives/$patch";
3797  } else {
3798  return "$IP/maintenance/archives/$patch";
3799  }
3800  }
3801 
3809  public function setSchemaVars( $vars ) {
3810  $this->mSchemaVars = $vars;
3811  }
3812 
3826  public function sourceStream( $fp, $lineCallback = false, $resultCallback = false,
3827  $fname = __METHOD__, $inputCallback = false
3828  ) {
3829  $cmd = '';
3830 
3831  while ( !feof( $fp ) ) {
3832  if ( $lineCallback ) {
3833  call_user_func( $lineCallback );
3834  }
3835 
3836  $line = trim( fgets( $fp ) );
3837 
3838  if ( $line == '' ) {
3839  continue;
3840  }
3841 
3842  if ( '-' == $line[0] && '-' == $line[1] ) {
3843  continue;
3844  }
3845 
3846  if ( $cmd != '' ) {
3847  $cmd .= ' ';
3848  }
3849 
3850  $done = $this->streamStatementEnd( $cmd, $line );
3851 
3852  $cmd .= "$line\n";
3853 
3854  if ( $done || feof( $fp ) ) {
3855  $cmd = $this->replaceVars( $cmd );
3856 
3857  if ( ( $inputCallback && call_user_func( $inputCallback, $cmd ) ) || !$inputCallback ) {
3858  $res = $this->query( $cmd, $fname );
3859 
3860  if ( $resultCallback ) {
3861  call_user_func( $resultCallback, $res, $this );
3862  }
3863 
3864  if ( false === $res ) {
3865  $err = $this->lastError();
3866 
3867  return "Query \"{$cmd}\" failed with error code \"$err\".\n";
3868  }
3869  }
3870  $cmd = '';
3871  }
3872  }
3874  return true;
3875  }
3876 
3884  public function streamStatementEnd( &$sql, &$newLine ) {
3885  if ( $this->delimiter ) {
3886  $prev = $newLine;
3887  $newLine = preg_replace( '/' . preg_quote( $this->delimiter, '/' ) . '$/', '', $newLine );
3888  if ( $newLine != $prev ) {
3889  return true;
3890  }
3891  }
3892 
3893  return false;
3894  }
3895 
3913  protected function replaceSchemaVars( $ins ) {
3914  $vars = $this->getSchemaVars();
3915  foreach ( $vars as $var => $value ) {
3916  // replace '{$var}'
3917  $ins = str_replace( '\'{$' . $var . '}\'', $this->addQuotes( $value ), $ins );
3918  // replace `{$var}`
3919  $ins = str_replace( '`{$' . $var . '}`', $this->addIdentifierQuotes( $value ), $ins );
3920  // replace /*$var*/
3921  $ins = str_replace( '/*$' . $var . '*/', $this->strencode( $value ), $ins );
3922  }
3923 
3924  return $ins;
3925  }
3926 
3933  protected function replaceVars( $ins ) {
3934  $ins = $this->replaceSchemaVars( $ins );
3935 
3936  // Table prefixes
3937  $ins = preg_replace_callback( '!/\*(?:\$wgDBprefix|_)\*/([a-zA-Z_0-9]*)!',
3938  array( $this, 'tableNameCallback' ), $ins );
3939 
3940  // Index names
3941  $ins = preg_replace_callback( '!/\*i\*/([a-zA-Z_0-9]*)!',
3942  array( $this, 'indexNameCallback' ), $ins );
3943 
3944  return $ins;
3945  }
3946 
3953  protected function getSchemaVars() {
3954  if ( $this->mSchemaVars ) {
3955  return $this->mSchemaVars;
3956  } else {
3957  return $this->getDefaultSchemaVars();
3958  }
3959  }
3960 
3969  protected function getDefaultSchemaVars() {
3970  return array();
3971  }
3972 
3979  protected function tableNameCallback( $matches ) {
3980  return $this->tableName( $matches[1] );
3981  }
3982 
3989  protected function indexNameCallback( $matches ) {
3990  return $this->indexName( $matches[1] );
3991  }
3992 
4001  public function lockIsFree( $lockName, $method ) {
4002  return true;
4003  }
4004 
4016  public function lock( $lockName, $method, $timeout = 5 ) {
4017  return true;
4018  }
4030  public function unlock( $lockName, $method ) {
4031  return true;
4032  }
4033 
4043  public function lockTables( $read, $write, $method, $lowPriority = true ) {
4044  return true;
4045  }
4046 
4053  public function unlockTables( $method ) {
4054  return true;
4055  }
4056 
4064  public function dropTable( $tableName, $fName = __METHOD__ ) {
4065  if ( !$this->tableExists( $tableName, $fName ) ) {
4066  return false;
4067  }
4068  $sql = "DROP TABLE " . $this->tableName( $tableName );
4069  if ( $this->cascadingDeletes() ) {
4070  $sql .= " CASCADE";
4071  }
4072 
4073  return $this->query( $sql, $fName );
4074  }
4075 
4082  public function getSearchEngine() {
4083  return 'SearchEngineDummy';
4084  }
4085 
4093  public function getInfinity() {
4094  return 'infinity';
4095  }
4096 
4103  public function encodeExpiry( $expiry ) {
4104  return ( $expiry == '' || $expiry == 'infinity' || $expiry == $this->getInfinity() )
4105  ? $this->getInfinity()
4106  : $this->timestamp( $expiry );
4107  }
4108 
4116  public function decodeExpiry( $expiry, $format = TS_MW ) {
4117  return ( $expiry == '' || $expiry == $this->getInfinity() )
4118  ? 'infinity'
4119  : wfTimestamp( $format, $expiry );
4120  }
4121 
4131  public function setBigSelects( $value = true ) {
4132  // no-op
4133  }
4138  public function __toString() {
4139  return (string)$this->mConn;
4140  }
4141 
4145  public function __destruct() {
4146  if ( $this->mTrxLevel && $this->mTrxDoneWrites ) {
4147  trigger_error( "Uncommitted DB writes (transaction from {$this->mTrxFname})." );
4148  }
4149  if ( count( $this->mTrxIdleCallbacks ) || count( $this->mTrxPreCommitCallbacks ) ) {
4150  $callers = array();
4151  foreach ( $this->mTrxIdleCallbacks as $callbackInfo ) {
4152  $callers[] = $callbackInfo[1];
4153  }
4154  $callers = implode( ', ', $callers );
4155  trigger_error( "DB transaction callbacks still pending (from $callers)." );
4156  }
4157  }
4158 }
DatabaseBase\writesOrCallbacksPending
writesOrCallbacksPending()
Returns true if there is a transaction open with possible write queries or transaction pre-commit/idl...
Definition: Database.php:594
DatabaseBase\tableName
tableName( $name, $format='quoted')
Format a table name ready for use in constructing an SQL query.
Definition: Database.php:2197
DatabaseBase\startAtomic
startAtomic( $fname=__METHOD__)
Begin an atomic section of statements.
Definition: Database.php:3314
DatabaseBase\replace
replace( $table, $uniqueIndexes, $rows, $fname=__METHOD__)
REPLACE query wrapper.
Definition: Database.php:2630
DatabaseBase\$mPassword
$mPassword
Definition: Database.php:237
DatabaseBase\replaceVars
replaceVars( $ins)
Replace variables in sourced SQL.
Definition: Database.php:3922
$wgUser
$wgUser
Definition: Setup.php:572
DatabaseBase\lastQuery
lastQuery()
Return the last query that went through DatabaseBase::query()
Definition: Database.php:574
$result
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. $reader:XMLReader object $logInfo:Array of information Return false to stop further processing of the tag 'ImportHandlePageXMLTag':When parsing a XML tag in a page. $reader:XMLReader object $pageInfo:Array of information Return false to stop further processing of the tag 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information Return false to stop further processing of the tag 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. $reader:XMLReader object Return false to stop further processing of the tag 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. $reader:XMLReader object $revisionInfo:Array of information Return false to stop further processing of the tag '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 '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. '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 '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 '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 wfIsTrustedProxy() $ip:IP being check $result:Change this value to override the result of wfIsTrustedProxy() '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 User::isValidEmailAddr(), 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. '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 '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) '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. 'LinkBegin':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
Definition: hooks.txt:1528
DatabaseBase\reportConnectionError
reportConnectionError( $error='Unknown error')
Definition: Database.php:949
DatabaseBase\doBegin
doBegin( $fname)
Issues the BEGIN command to the database server.
Definition: Database.php:3416
DatabaseBase\functionalIndexes
functionalIndexes()
Returns true if this database can use functional indexes.
Definition: Database.php:566
DatabaseBase\$mSchema
$mSchema
Definition: Database.php:246
DatabaseBase\debug
debug( $debug=null)
Boolean, controls output of large amounts of debug information.
Definition: Database.php:343
MWDebug\query
static query( $sql, $function, $isMaster)
Begins profiling on a database query.
Definition: Debug.php:334
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
DatabaseBase\wasReadOnlyError
wasReadOnlyError()
Determines if the last failure was due to the database being read-only.
Definition: Database.php:3098
DatabaseType\numRows
numRows( $res)
Get the number of rows in a result object.
DatabaseBase\$delimiter
$delimiter
Definition: Database.php:258
DatabaseBase\setLBInfo
setLBInfo( $name, $value=null)
Set the LB info array, or a member of it.
Definition: Database.php:469
DatabaseType\fetchRow
fetchRow( $res)
Fetch the next row from the given result object, in associative array form.
DatabaseBase\insertSelect
insertSelect( $destTable, $srcTable, $varMap, $conds, $fname=__METHOD__, $insertOptions=array(), $selectOptions=array())
INSERT SELECT wrapper.
Definition: Database.php:2928
DatabaseType\fieldInfo
fieldInfo( $table, $field)
mysql_fetch_field() wrapper Returns false if the field doesn't exist
DatabaseBase\$mDoneWrites
$mDoneWrites
Definition: Database.php:234
DatabaseBase\execute
execute( $prepared, $args=null)
Execute a prepared query with the various arguments.
Definition: Database.php:1187
Profiler\instance
static instance()
Singleton.
Definition: Profiler.php:127
DatabaseBase\onTransactionPreCommitOrIdle
onTransactionPreCommitOrIdle( $callback)
Run an anonymous function before the current transaction commits or now if there is none.
Definition: Database.php:3230
DatabaseBase\$mDefaultBigSelects
$mDefaultBigSelects
Definition: Database.php:251
DatabaseBase\$mSchemaVars
$mSchemaVars
Definition: Database.php:252
wfSetVar
wfSetVar(&$dest, $source, $force=false)
Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...
Definition: GlobalFunctions.php:2186
DatabaseBase\realTimestamps
realTimestamps()
Returns true if this database uses timestamps rather than integers.
Definition: Database.php:528
DatabaseBase\useIndexClause
useIndexClause( $index)
USE INDEX clause.
Definition: Database.php:2604
DatabaseBase\makeUpdateOptions
makeUpdateOptions( $options)
Make UPDATE options for the DatabaseBase::update function.
Definition: Database.php:1942
DatabaseBase\buildConcat
buildConcat( $stringList)
Build a concatenation list to feed into a SQL query.
Definition: Database.php:2120
DatabaseBase\makeList
makeList( $a, $mode=LIST_COMMA)
Makes an encoded list of strings from an array.
Definition: Database.php:1992
DatabaseBase\$fileHandle
resource $fileHandle
Definition: Database.php:304
DatabaseBase\makeWhereFrom2d
makeWhereFrom2d( $data, $baseKey, $subKey)
Build a partial where clause from a 2-d array such as used for LinkBatch.
Definition: Database.php:2057
wfSetBit
wfSetBit(&$dest, $bit, $state=true)
As for wfSetVar except setting a bit.
Definition: GlobalFunctions.php:2203
DatabaseBase\lockIsFree
lockIsFree( $lockName, $method)
Check to see if a named lock is available.
Definition: Database.php:3990
DatabaseBase\wasLockTimeout
wasLockTimeout()
Determines if the last failure was due to a lock timeout STUB.
Definition: Database.php:3077
DatabaseBase\bitAnd
bitAnd( $fieldLeft, $fieldRight)
Definition: Database.php:2101
DatabaseBase\close
close()
Closes a database connection.
Definition: Database.php:914
DatabaseBase\query
query( $sql, $fname=__METHOD__, $tempIgnore=false)
Run an SQL query and return the result.
Definition: Database.php:1001
DatabaseBase\freePrepared
freePrepared( $prepared)
Free a prepared query, generated by prepare().
Definition: Database.php:1176
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:2530
DatabaseType\affectedRows
affectedRows()
Get the number of rows affected by the last write query.
DatabaseBase\isQuotedIdentifier
isQuotedIdentifier( $name)
Returns if the given identifier looks quoted or not according to the database convention for quoting ...
Definition: Database.php:2509
wfProfileIn
wfProfileIn( $functionname)
Begin profiling of a function.
Definition: Profiler.php:33
DatabaseBase\indexNameCallback
indexNameCallback( $matches)
Index name callback.
Definition: Database.php:3978
$n
$n
Definition: RandomTest.php:76
DatabaseBase\$allViews
string[] $allViews
Definition: Database.php:309
$ret
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
Definition: hooks.txt:1530
wfSuppressWarnings
wfSuppressWarnings( $end=false)
Reference-counted warning suppression.
Definition: GlobalFunctions.php:2434
$from
$from
Definition: importImages.php:90
DatabaseBase\getFlag
getFlag( $flag)
Returns a boolean whether the flag $flag is set for this connection.
Definition: Database.php:658
DatabaseBase\getLag
getLag()
Get slave lag.
Definition: Database.php:3678
DatabaseBase\buildLike
buildLike()
LIKE statement wrapper, receives a variable-length argument list with parts of pattern to match conta...
Definition: Database.php:2541
DatabaseBase\resultObject
resultObject( $result)
Take the result from a query, and wrap it in a ResultWrapper if necessary.
Definition: Database.php:3646
$fname
if(!defined( 'MEDIAWIKI')) $fname
This file is not a valid entry point, perform no further processing unless MEDIAWIKI is defined.
Definition: Setup.php:35
DatabaseBase\lowPriorityOption
lowPriorityOption()
A string to insert into queries to show that they're low-priority, like MySQL's LOW_PRIORITY.
Definition: Database.php:2870
DatabaseBase\textFieldSize
textFieldSize( $table, $field)
Returns the size of a text field, or -1 for "unlimited".
Definition: Database.php:2845
$params
$params
Definition: styleTest.css.php:40
$limit
if( $sleep) $limit
Definition: importImages.php:99
DatabaseType\getServerVersion
getServerVersion()
A string describing the current software version, like from mysql_get_server_info().
DatabaseBase\makeOrderBy
makeOrderBy( $options)
Returns an optional ORDER BY.
Definition: Database.php:1424
DatabaseBase\$mOpened
$mOpened
Definition: Database.php:240
DatabaseBase\connectionErrorHandler
connectionErrorHandler( $errno, $errstr)
Definition: Database.php:903
DatabaseBase\bitNot
bitNot( $field)
Definition: Database.php:2092
DatabaseBase\setFileHandle
setFileHandle( $fh)
Set the filehandle to copy write statements to.
Definition: Database.php:436
DatabaseBase\anyString
anyString()
Returns a token for buildLike() that denotes a '' to be used in a LIKE query.
Definition: Database.php:2575
DatabaseBase\replaceSchemaVars
replaceSchemaVars( $ins)
Database independent variable replacement.
Definition: Database.php:3902
$s
$s
Definition: mergeMessageFileList.php:156
DatabaseBase\dropTable
dropTable( $tableName, $fName=__METHOD__)
Delete a table.
Definition: Database.php:4053
DatabaseBase\strictIPs
strictIPs()
Returns true if this database is strict about what can be put into an IP field.
Definition: Database.php:519
DatabaseBase\unionSupportsOrderAndLimit
unionSupportsOrderAndLimit()
Returns true if current database backend supports ORDER BY or LIMIT for separate subqueries within th...
Definition: Database.php:3002
DatabaseBase\getSchemaVars
getSchemaVars()
Get schema variables.
Definition: Database.php:3942
$flags
it s the revision text itself In either if gzip is the revision text is gzipped $flags
Definition: hooks.txt:2118
DBMasterPos
An object representing a master or slave position in a replicated setup.
Definition: DatabaseUtility.php:323
DatabaseBase\limitResult
limitResult( $sql, $limit, $offset=false)
Construct a LIMIT query with optional offset.
Definition: Database.php:2987
DatabaseBase\timestamp
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
Definition: Database.php:3607
DatabaseBase\encodeBlob
encodeBlob( $b)
Some DBMSs have a special format for inserting into blob fields, they don't allow simple quoted strin...
Definition: Database.php:3700
DatabaseBase\buildGroupConcatField
buildGroupConcatField( $delim, $table, $field, $conds='', $join_conds=array())
Build a GROUP_CONCAT or equivalent statement for a query.
Definition: Database.php:2140
DatabaseBase\implicitOrderby
implicitOrderby()
Returns true if this database does an implicit order by when the column has an index For example: SEL...
Definition: Database.php:547
DatabaseBase\selectRow
selectRow( $table, $vars, $conds, $fname=__METHOD__, $options=array(), $join_conds=array())
Single row SELECT wrapper.
Definition: Database.php:1663
DatabaseBase\$mTrxAutomaticAtomic
bool $mTrxAutomaticAtomic
Record if the current transaction was started implicitly by DatabaseBase::startAtomic.
Definition: Database.php:299
DatabaseBase\tableNamesWithUseIndexOrJOIN
tableNamesWithUseIndexOrJOIN( $tables, $use_index=array(), $join_conds=array())
Get the aliased table name clause for a FROM clause which might have a JOIN and/or USE INDEX clause.
Definition: Database.php:2397
LIST_AND
const LIST_AND
Definition: Defines.php:203
DatabaseBase\doQuery
doQuery( $sql)
The DBMS-dependent part of query()
DatabaseBase\tableExists
tableExists( $table, $fname=__METHOD__)
Query whether a given table exists.
Definition: Database.php:1790
DatabaseBase\__toString
__toString()
Definition: Database.php:4127
LikeMatch
Used by DatabaseBase::buildLike() to represent characters that have special meaning in SQL LIKE claus...
Definition: DatabaseUtility.php:296
DatabaseType\indexInfo
indexInfo( $table, $index, $fname=__METHOD__)
Get information about an index into an object.
DatabaseBase\tablePrefix
tablePrefix( $prefix=null)
Get/set the table prefix.
Definition: Database.php:418
DatabaseBase\setFakeSlaveLag
setFakeSlaveLag( $lag)
Set lag time in seconds for a fake slave.
Definition: Database.php:484
DatabaseBase\unlockTables
unlockTables( $method)
Unlock specific tables.
Definition: Database.php:4042
DatabaseBase\$mPHPError
$mPHPError
Definition: Database.php:235
DatabaseBase\__destruct
__destruct()
Run a few simple sanity checks.
Definition: Database.php:4134
DatabaseBase\setSchemaVars
setSchemaVars( $vars)
Set variables to be used in sourceFile/sourceStream, in preference to the ones in $GLOBALS.
Definition: Database.php:3798
DatabaseBase\update
update( $table, $values, $conds, $fname=__METHOD__, $options=array())
UPDATE wrapper.
Definition: Database.php:1966
DatabaseBase\selectSQLText
selectSQLText( $table, $vars, $conds='', $fname=__METHOD__, $options=array(), $join_conds=array())
The equivalent of DatabaseBase::select() except that the constructed SQL is returned,...
Definition: Database.php:1598
DatabaseBase\indexName
indexName( $index)
Get the name of an index in a given table.
Definition: Database.php:2456
DatabaseBase\errorCount
errorCount( $count=null)
Get/set the number of errors logged.
Definition: Database.php:409
DatabaseBase\getDelimiter
getDelimiter()
Definition: Database.php:330
DatabaseBase\addQuotes
addQuotes( $s)
Adds quotes and backslashes.
Definition: Database.php:2477
DatabaseBase\endAtomic
endAtomic( $fname=__METHOD__)
Ends an atomic section of SQL statements.
Definition: Database.php:3335
DatabaseBase\getWikiID
getWikiID()
Definition: Database.php:675
DatabaseBase\selectField
selectField( $table, $var, $cond='', $fname=__METHOD__, $options=array())
A SELECT wrapper which returns a single field from a single result row.
Definition: Database.php:1281
LIST_OR
const LIST_OR
Definition: Defines.php:206
DatabaseBase\doRollback
doRollback( $fname)
Issues the ROLLBACK command to the database server.
Definition: Database.php:3522
DatabaseBase\unlock
unlock( $lockName, $method)
Release a lock.
Definition: Database.php:4019
DatabaseBase\isView
isView( $name)
Differentiates between a TABLE and a VIEW.
Definition: Database.php:3592
MWException
MediaWiki exception.
Definition: MWException.php:26
DatabaseBase\$mDBname
$mDBname
Definition: Database.php:237
DatabaseBase\fillPrepared
fillPrepared( $preparedQuery, $args)
For faking prepared SQL statements on DBs that don't support it directly.
Definition: Database.php:1206
DatabaseBase\freeResult
freeResult( $res)
Free a result object returned by query() or select().
Definition: Database.php:1261
DatabaseType\getServerInfo
getServerInfo()
A string describing the current software version, and possibly other details in a user-friendly way.
DatabaseBase\$mConn
resource $mConn
Database connection *.
Definition: Database.php:239
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1174
DBQueryError
Definition: DatabaseError.php:306
DatabaseBase\select
select( $table, $vars, $conds='', $fname=__METHOD__, $options=array(), $join_conds=array())
Execute a SELECT query constructed using the various parameters provided.
Definition: Database.php:1575
wfRestoreWarnings
wfRestoreWarnings()
Restore error level to previous value.
Definition: GlobalFunctions.php:2464
table
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 then executing the whole list after the page is displayed We don t do anything smart like collating updates to the same table or such because the list is almost always going to have just one item on if so it s not worth the trouble Since there is a job queue in the jobs table
Definition: deferred.txt:11
DatabaseBase\getDefaultSchemaVars
getDefaultSchemaVars()
Get schema variables to use if none have been set via setSchemaVars().
Definition: Database.php:3958
$wgCommandLineMode
global $wgCommandLineMode
Definition: Setup.php:408
DatabaseBase\cleanupTriggers
cleanupTriggers()
Returns true if this database supports (and uses) triggers (e.g.
Definition: Database.php:509
DatabaseBase\tableNameCallback
tableNameCallback( $matches)
Table name callback.
Definition: Database.php:3968
$wgRequestTime
$wgRequestTime
Definition: WebStart.php:68
DatabaseBase\restoreErrorHandler
restoreErrorHandler()
Definition: Database.php:884
DatabaseBase\ignoreErrors
ignoreErrors( $ignoreErrors=null)
Turns on (false) or off (true) the automatic generation and sending of a "we're sorry,...
Definition: Database.php:388
MWDebug\queryTime
static queryTime( $id)
Calculates how long a query took.
Definition: Debug.php:356
DatabaseBase\setFlag
setFlag( $flag)
Set a flag for this connection.
Definition: Database.php:619
wfProfileOut
wfProfileOut( $functionname='missing')
Stop profiling of a function.
Definition: Profiler.php:46
LIST_SET
const LIST_SET
Definition: Defines.php:204
DatabaseBase\indexUnique
indexUnique( $table, $index)
Determines if a given index is unique.
Definition: Database.php:1807
DatabaseBase\$mTrxLevel
int $mTrxLevel
Either 1 if a transaction is active or 0 otherwise.
Definition: Database.php:265
DatabaseBase\reportQueryError
reportQueryError( $error, $errno, $sql, $fname, $tempIgnore=false)
Report a query error.
Definition: Database.php:1134
DatabaseBase\listTables
listTables( $prefix=null, $fname=__METHOD__)
List all tables on the database.
Definition: Database.php:3558
DatabaseBase\getSchemaPath
getSchemaPath()
Return a path to the DBMS-specific schema file, otherwise default to tables.sql.
Definition: Database.php:688
DatabaseBase\estimateRowCount
estimateRowCount( $table, $vars=' *', $conds='', $fname=__METHOD__, $options=array())
Estimate rows in dataset.
Definition: Database.php:1703
DatabaseBase\nativeReplace
nativeReplace( $table, $rows, $fname)
REPLACE query wrapper for MySQL and SQLite, which have a native REPLACE statement.
Definition: Database.php:2687
DatabaseBase\$mTrxAutomatic
bool $mTrxAutomatic
Record if the current transaction was started implicitly due to DBO_TRX being set.
Definition: Database.php:287
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
DatabaseBase\$mLBInfo
$mLBInfo
Definition: Database.php:250
DatabaseBase\wasErrorReissuable
wasErrorReissuable()
Determines if the last query error was something that should be dealt with by pinging the connection ...
Definition: Database.php:3088
DatabaseBase\clearViewsCache
clearViewsCache()
Reset the views process cache set by listViews()
Definition: Database.php:3566
DatabaseBase\DEADLOCK_TRIES
const DEADLOCK_TRIES
Number of times to re-try an operation in case of deadlock.
Definition: Database.php:221
DatabaseBase\isWriteQuery
isWriteQuery( $sql)
Determine whether a query writes to the DB.
Definition: Database.php:975
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
DatabaseType\numFields
numFields( $res)
Get the number of fields in a result object.
DatabaseBase\__sleep
__sleep()
Called by serialize.
Definition: Database.php:781
DBConnectionError
Definition: DatabaseError.php:98
DatabaseBase\factory
static factory( $dbType, $p=array())
Given a DB type, construct the name of the appropriate child class of DatabaseBase.
Definition: Database.php:808
DatabaseBase\$preparedArgs
$preparedArgs
Definition: Database.php:254
DatabaseBase\runOnTransactionPreCommitCallbacks
runOnTransactionPreCommitCallbacks()
Actually any "on transaction pre-commit" callbacks.
Definition: Database.php:3271
DatabaseBase\getServer
getServer()
Get the server hostname or IP address.
Definition: Database.php:2176
DatabaseBase\selectDB
selectDB( $db)
Change the current database.
Definition: Database.php:2157
DatabaseBase\implicitGroupby
implicitGroupby()
Returns true if this database does an implicit sort when doing GROUP BY.
Definition: Database.php:537
DBUnexpectedError
Definition: DatabaseError.php:438
DatabaseType\getSoftwareLink
getSoftwareLink()
Returns a wikitext link to the DB's website, e.g., return "[http://www.mysql.com/ MySQL]"; Should at ...
DatabaseBase\getServerInfo
getServerInfo()
A string describing the current software version, and possibly other details in a user-friendly way.
Definition: Database.php:323
DatabaseBase\$mTrxAtomicLevels
SplStack $mTrxAtomicLevels
Array of levels of atomicity within transactions.
Definition: Database.php:293
list
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
Definition: deferred.txt:11
DatabaseType\strencode
strencode( $s)
Wrapper for addslashes()
DatabaseType\getType
getType()
Get the type of the DBMS, as it appears in $wgDBtype.
DatabaseBase\makeGroupByWithHaving
makeGroupByWithHaving( $options)
Returns an optional GROUP BY with an optional HAVING.
Definition: Database.php:1398
LIST_COMMA
const LIST_COMMA
Definition: Defines.php:202
DatabaseType\insertId
insertId()
Get the inserted value of an auto-increment row.
database
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the database
Definition: design.txt:12
DatabaseBase\wasDeadlock
wasDeadlock()
Determines if the last failure was due to a deadlock STUB.
Definition: Database.php:3067
$options
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition: hooks.txt:1530
DatabaseBase\getProperty
getProperty( $name)
General read-only accessor.
Definition: Database.php:668
DatabaseBase\$mLastQuery
$mLastQuery
Definition: Database.php:233
$ok
$ok
Definition: UtfNormalTest.php:71
DatabaseBase\$mServer
$mServer
Definition: Database.php:237
DatabaseBase\getSlavePos
getSlavePos()
Get the replication position of this slave.
Definition: Database.php:3183
$line
$line
Definition: cdb.php:57
DatabaseBase\trxLevel
trxLevel()
Gets the current transaction level.
Definition: Database.php:400
DatabaseBase\sourceFile
sourceFile( $filename, $lineCallback=false, $resultCallback=false, $fname=false, $inputCallback=false)
Read and execute SQL commands from a file.
Definition: Database.php:3745
DatabaseBase\$mUser
$mUser
Definition: Database.php:237
DatabaseBase\fieldNamesWithAlias
fieldNamesWithAlias( $fields)
Gets an array of aliased field names.
Definition: Database.php:2376
TS_MW
const TS_MW
MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS)
Definition: GlobalFunctions.php:2478
wfDebug
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:980
DatabaseBase\deadlockLoop
deadlockLoop()
Perform a deadlock-prone transaction.
Definition: Database.php:3120
DatabaseBase\makeInsertOptions
makeInsertOptions( $options)
Helper for DatabaseBase::insert().
Definition: Database.php:1823
DatabaseBase\prepare
prepare( $sql, $func='DatabaseBase::prepare')
Intended to be compatible with the PEAR::DB wrapper functions.
Definition: Database.php:1164
DatabaseBase\anyChar
anyChar()
Returns a token for buildLike() that denotes a '_' to be used in a LIKE query.
Definition: Database.php:2566
$ignore
while(false !==( $line=fgets( $in))) if(! $columns) $ignore
Definition: Utf8Test.php:68
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:336
DatabaseBase\getInfinity
getInfinity()
Find out when 'infinity' is.
Definition: Database.php:4082
$matches
if(!defined( 'MEDIAWIKI')) if(!isset( $wgVersion)) $matches
Definition: NoLocalSettings.php:33
$size
$size
Definition: RandomTest.php:75
$value
$value
Definition: styleTest.css.php:45
wfLogDBError
wfLogDBError( $text)
Log for database errors.
Definition: GlobalFunctions.php:1134
DatabaseBase\decodeExpiry
decodeExpiry( $expiry, $format=TS_MW)
Decode an expiry time into a DBMS independent format.
Definition: Database.php:4105
DatabaseBase\unionQueries
unionQueries( $sqls, $all)
Construct a UNION query This is used for providing overload point for other DB abstractions not compa...
Definition: Database.php:3014
DatabaseBase\aggregateValue
aggregateValue( $valuedata, $valuename='value')
Return aggregated value alias.
Definition: Database.php:2084
DatabaseType\dataSeek
dataSeek( $res, $row)
Change the position of the cursor in a result object.
DatabaseBase\streamStatementEnd
streamStatementEnd(&$sql, &$newLine)
Called by sourceStream() to check if we've reached a statement end.
Definition: Database.php:3873
DatabaseBase
Database abstraction object.
Definition: Database.php:219
DatabaseBase\bitOr
bitOr( $fieldLeft, $fieldRight)
Definition: Database.php:2110
DatabaseBase\timestampOrNull
timestampOrNull( $ts=null)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
Definition: Database.php:3624
DatabaseBase\masterPosWait
masterPosWait(DBMasterPos $pos, $timeout)
Wait for the slave to catch up to a given master position.
Definition: Database.php:3173
DatabaseBase\makeSelectOptions
makeSelectOptions( $options)
Returns an optional USE INDEX clause to go after the table, and a string to go at the end of the quer...
Definition: Database.php:1314
DBO_NOBUFFER
const DBO_NOBUFFER
Definition: Defines.php:40
DatabaseBase\getDBname
getDBname()
Get the current DB name.
Definition: Database.php:2169
DatabaseBase\$mTrxDoneWrites
bool $mTrxDoneWrites
Record if possible write queries were done in the last transaction started.
Definition: Database.php:280
DatabaseBase\$mTrxIdleCallbacks
callable[] $mTrxIdleCallbacks
Definition: Database.php:242
DatabaseBase\getMasterPos
getMasterPos()
Get the position of this master.
Definition: Database.php:3193
DatabaseBase\$mForeign
$mForeign
Definition: Database.php:248
DatabaseBase\lockTables
lockTables( $read, $write, $method, $lowPriority=true)
Lock specific tables.
Definition: Database.php:4032
DatabaseType\lastError
lastError()
Get a description of the last error.
DatabaseBase\strreplace
strreplace( $orig, $old, $new)
Returns a comand for str_replace function in SQL query.
Definition: Database.php:3047
DatabaseBase\duplicateTableStructure
duplicateTableStructure( $oldName, $newName, $temporary=false, $fname=__METHOD__)
Creates a new table with structure copied from existing table Note that unlike most database abstract...
Definition: Database.php:3544
DatabaseBase\bufferResults
bufferResults( $buffer=null)
Turns buffering of SQL result sets on (true) or off (false).
Definition: Database.php:368
DatabaseBase\doCommit
doCommit( $fname)
Issues the COMMIT command to the database server.
Definition: Database.php:3472
$user
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 account $user
Definition: hooks.txt:237
IDatabase
Interface for classes that implement or wrap DatabaseBase.
Definition: Database.php:212
DatabaseType
Definition: Database.php:35
DatabaseBase\$mTrxPreCommitCallbacks
callable[] $mTrxPreCommitCallbacks
Definition: Database.php:243
DatabaseBase\getSearchEngine
getSearchEngine()
Get search engine class.
Definition: Database.php:4071
DatabaseBase\makeUpdateOptionsArray
makeUpdateOptionsArray( $options)
Make UPDATE options array for DatabaseBase::makeUpdateOptions.
Definition: Database.php:1918
DatabaseBase\commit
commit( $fname=__METHOD__, $flush='')
Commits a transaction previously started using begin().
Definition: Database.php:3435
$password
return false to override stock group addition can be modified try getUserPermissionsErrors userCan checks are continued by internal code can override on output return false to not delete it return false to override the default password checks this Boolean value will be checked to determine if the password was valid return false to implement your own hashing method & $password
Definition: hooks.txt:2702
DatabaseBase\installErrorHandler
installErrorHandler()
Definition: Database.php:875
DatabaseBase\rollback
rollback( $fname=__METHOD__, $flush='')
Rollback a transaction previously started using begin().
Definition: Database.php:3492
DatabaseBase\generalizeSQL
static generalizeSQL( $sql)
Removes most variables from an SQL query and replaces them with X or N for numbers.
Definition: Database.php:1725
DatabaseBase\$mFlags
$mFlags
Definition: Database.php:247
$count
$count
Definition: UtfNormalTest2.php:96
DatabaseBase\$mErrorCount
$mErrorCount
Definition: Database.php:249
DatabaseType\lastErrno
lastErrno()
Get the last error number.
DBO_DEFAULT
const DBO_DEFAULT
Definition: Defines.php:43
DatabaseBase\addIdentifierQuotes
addIdentifierQuotes( $s)
Quotes an identifier using backticks or "double quotes" depending on the database type.
Definition: Database.php:2498
$args
if( $line===false) $args
Definition: cdb.php:62
DatabaseBase\searchableIPs
searchableIPs()
Returns true if this database can do a native search on IP columns e.g.
Definition: Database.php:557
DatabaseBase\lock
lock( $lockName, $method, $timeout=5)
Acquire a named lock.
Definition: Database.php:4005
$debug
$debug
Definition: Setup.php:518
DatabaseBase\$mTablePrefix
$mTablePrefix
Definition: Database.php:245
DatabaseBase\DEADLOCK_DELAY_MIN
const DEADLOCK_DELAY_MIN
Minimum time to wait before retry, in microseconds.
Definition: Database.php:224
DatabaseBase\$mTrxFname
string $mTrxFname
Remembers the function name given for starting the most recent transaction via begin().
Definition: Database.php:273
DatabaseBase\isOpen
isOpen()
Is a connection to the database open?
Definition: Database.php:604
DatabaseBase\listViews
listViews( $prefix=null, $fname=__METHOD__)
Lists all the VIEWs in the database.
Definition: Database.php:3581
DatabaseBase\begin
begin( $fname=__METHOD__)
Begin a transaction.
Definition: Database.php:3365
DatabaseBase\doneWrites
doneWrites()
Returns true if the connection may have been used for write queries.
Definition: Database.php:584
DatabaseBase\setBigSelects
setBigSelects( $value=true)
Allow or deny "big selects" for this session only.
Definition: Database.php:4120
DatabaseBase\nextSequenceValue
nextSequenceValue( $seqName)
Returns an appropriately quoted sequence value for inserting a new row.
Definition: Database.php:2590
DatabaseBase\patchPath
patchPath( $patch)
Get the full path of a patch file.
Definition: Database.php:3780
DatabaseType\fetchObject
fetchObject( $res)
Fetch the next row from the given result object, in object form.
as
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
Definition: distributors.txt:9
$keys
$keys
Definition: testCompression.php:63
DatabaseBase\fieldExists
fieldExists( $table, $field, $fname=__METHOD__)
Determines whether a field exists in a table.
Definition: Database.php:1754
DatabaseBase\closeConnection
closeConnection()
Closes underlying database connection.
DatabaseBase\cascadingDeletes
cascadingDeletes()
Returns true if this database supports (and uses) cascading deletes.
Definition: Database.php:500
DatabaseBase\runOnTransactionIdleCallbacks
runOnTransactionIdleCallbacks()
Actually any "on transaction idle" callbacks.
Definition: Database.php:3243
DatabaseType\open
open( $server, $user, $password, $dbName)
Open a connection to the database.
DatabaseBase\ping
ping()
Ping the server and try to reconnect if it there is no connection.
Definition: Database.php:3664
DatabaseBase\getLBInfo
getLBInfo( $name=null)
Get properties passed down from the server info array of the load balancer.
Definition: Database.php:449
DatabaseBase\__construct
__construct( $params=null)
Constructor.
Definition: Database.php:713
wfWarn
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
Definition: GlobalFunctions.php:1188
LIST_NAMES
const LIST_NAMES
Definition: Defines.php:205
DatabaseBase\upsert
upsert( $table, array $rows, array $uniqueIndexes, array $set, $fname=__METHOD__)
INSERT ON DUPLICATE KEY UPDATE wrapper, upserts an array into a table.
Definition: Database.php:2745
DatabaseBase\DEADLOCK_DELAY_MAX
const DEADLOCK_DELAY_MAX
Maximum time to wait before retry.
Definition: Database.php:227
$vars
static configuration should be added through ResourceLoaderGetConfigVars instead & $vars
Definition: hooks.txt:1684
$error
usually copyright or history_copyright This message must be in HTML not wikitext $subpages will be ignored and the rest of subPageSubtitle() will run. 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink' whether MediaWiki currently thinks this is a CSS JS page Hooks may change this value to override the return value of Title::isCssOrJsPage(). 'TitleIsAlwaysKnown' whether MediaWiki currently thinks this page is known isMovable() always returns false. $title whether MediaWiki currently thinks this page is movable Hooks may change this value to override the return value of Title::isMovable(). 'TitleIsWikitextPage' whether MediaWiki currently thinks this is a wikitext page Hooks may change this value to override the return value of Title::isWikitextPage() 'TitleMove' use UploadVerification and UploadVerifyFile instead where the first element is the message key and the remaining elements are used as parameters to the message based on mime etc Preferred in most cases over UploadVerification object with all info about the upload string as detected by MediaWiki Handlers will typically only apply for specific mime types object & $error
Definition: hooks.txt:2578
DatabaseBase\maxListLen
maxListLen()
Return the maximum number of items allowed in a list, or 0 for unlimited.
Definition: Database.php:3687
DatabaseBase\dbSchema
dbSchema( $schema=null)
Get/set the db schema.
Definition: Database.php:427
DatabaseBase\deleteJoin
deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname=__METHOD__)
DELETE where the condition is a join.
Definition: Database.php:2819
DatabaseBase\sourceStream
sourceStream( $fp, $lineCallback=false, $resultCallback=false, $fname=__METHOD__, $inputCallback=false)
Read and execute commands from an open file handle.
Definition: Database.php:3815
DatabaseBase\encodeExpiry
encodeExpiry( $expiry)
Encode an expiry time into the DBMS dependent format.
Definition: Database.php:4092
$IP
$IP
Definition: WebStart.php:88
DatabaseBase\setSessionOptions
setSessionOptions(array $options)
Override database's default behavior.
Definition: Database.php:3726
DatabaseBase\clearFlag
clearFlag( $flag)
Clear a flag for this connection.
Definition: Database.php:638
DatabaseBase\escapeLikeInternal
escapeLikeInternal( $s)
Definition: Database.php:2517
DatabaseType\fieldName
fieldName( $res, $n)
Get a field name in a result object.
$res
$res
Definition: database.txt:21
DatabaseBase\$htmlErrors
$htmlErrors
Definition: Database.php:256
wfGetCaller
wfGetCaller( $level=2)
Get the name of the function which called this function wfGetCaller( 1 ) is the function with the wfG...
Definition: GlobalFunctions.php:1988
DatabaseBase\indexExists
indexExists( $table, $index, $fname=__METHOD__)
Determines whether an index exists Usually throws a DBQueryError on failure If errors are explicitly ...
Definition: Database.php:1770
DBO_IGNORE
const DBO_IGNORE
Definition: Defines.php:41
DBO_DEBUG
const DBO_DEBUG
Definition: Defines.php:39
DBO_TRX
const DBO_TRX
Definition: Defines.php:42
DatabaseBase\setFakeMaster
setFakeMaster( $enabled=true)
Make this connection a fake master.
Definition: Database.php:492
DatabaseBase\getServerUptime
getServerUptime()
Determines how long the server has been up STUB.
Definition: Database.php:3057
DatabaseBase\onTransactionIdle
onTransactionIdle( $callback)
Run an anonymous function as soon as there is no transaction pending.
Definition: Database.php:3212
DatabaseBase\conditional
conditional( $cond, $trueVal, $falseVal)
Returns an SQL expression for a simple conditional.
Definition: Database.php:3029
DatabaseBase\decodeBlob
decodeBlob( $b)
Some DBMSs return a special placeholder object representing blob fields in result objects.
Definition: Database.php:3712
ResultWrapper
Result wrapper for grabbing data queried by someone else.
Definition: DatabaseUtility.php:99
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:1632
DatabaseBase\fillPreparedArg
fillPreparedArg( $matches)
preg_callback func for fillPrepared() The arguments should be in $this->preparedArgs and must not be ...
Definition: Database.php:1223
DatabaseBase\insert
insert( $table, $a, $fname=__METHOD__, $options=array())
INSERT wrapper, inserts an array into a table.
Definition: Database.php:1860