MediaWiki  master
DatabaseSqlite.php
Go to the documentation of this file.
1 <?php
24 namespace Wikimedia\Rdbms;
25 
26 use FSLockManager;
27 use LockManager;
28 use NullLockManager;
29 use PDO;
30 use PDOException;
31 use RuntimeException;
32 use stdClass;
33 
37 class DatabaseSqlite extends Database {
39  protected $dbDir;
41  protected $dbPath;
43  protected $trxMode;
44 
47 
49  protected $conn;
50 
52  protected $lockMgr;
53 
55  private $version;
56 
58  private $sessionAttachedDbs = [];
59 
61  private static $VALID_TRX_MODES = [ '', 'DEFERRED', 'IMMEDIATE', 'EXCLUSIVE' ];
62 
64  private static $VALID_PRAGMAS = [
65  // Optimizations or requirements regarding fsync() usage
66  'synchronous' => [ 'EXTRA', 'FULL', 'NORMAL', 'OFF' ],
67  // Optimizations for TEMPORARY tables
68  'temp_store' => [ 'FILE', 'MEMORY' ]
69  ];
70 
78  public function __construct( array $params ) {
79  if ( isset( $params['dbFilePath'] ) ) {
80  $this->dbPath = $params['dbFilePath'];
81  if ( !strlen( $params['dbname'] ) ) {
82  $params['dbname'] = self::generateDatabaseName( $this->dbPath );
83  }
84  } elseif ( isset( $params['dbDirectory'] ) ) {
85  $this->dbDir = $params['dbDirectory'];
86  }
87 
88  parent::__construct( $params );
89 
90  $this->trxMode = strtoupper( $params['trxMode'] ?? '' );
91 
92  $lockDirectory = $this->getLockFileDirectory();
93  if ( $lockDirectory !== null ) {
94  $this->lockMgr = new FSLockManager( [
95  'domain' => $this->getDomainID(),
96  'lockDirectory' => $lockDirectory
97  ] );
98  } else {
99  $this->lockMgr = new NullLockManager( [ 'domain' => $this->getDomainID() ] );
100  }
101  }
102 
103  protected static function getAttributes() {
104  return [
105  self::ATTR_DB_IS_FILE => true,
106  self::ATTR_DB_LEVEL_LOCKING => true
107  ];
108  }
109 
119  public static function newStandaloneInstance( $filename, array $p = [] ) {
120  $p['dbFilePath'] = $filename;
121  $p['schema'] = null;
122  $p['tablePrefix'] = '';
124  $db = Database::factory( 'sqlite', $p );
125 
126  return $db;
127  }
128 
132  public function getType() {
133  return 'sqlite';
134  }
135 
136  protected function open( $server, $user, $pass, $dbName, $schema, $tablePrefix ) {
137  $this->close( __METHOD__ );
138 
139  // Note that for SQLite, $server, $user, and $pass are ignored
140 
141  if ( $schema !== null ) {
142  throw $this->newExceptionAfterConnectError( "Got schema '$schema'; not supported." );
143  }
144 
145  if ( $this->dbPath !== null ) {
147  } elseif ( $this->dbDir !== null ) {
148  $path = self::generateFileName( $this->dbDir, $dbName );
149  } else {
150  throw $this->newExceptionAfterConnectError( "DB path or directory required" );
151  }
152 
153  // Check if the database file already exists but is non-readable
154  if (
155  !self::isProcessMemoryPath( $path ) &&
156  file_exists( $path ) &&
157  !is_readable( $path )
158  ) {
159  throw $this->newExceptionAfterConnectError( 'SQLite database file is not readable' );
160  } elseif ( !in_array( $this->trxMode, self::$VALID_TRX_MODES, true ) ) {
161  throw $this->newExceptionAfterConnectError( "Got mode '{$this->trxMode}' for BEGIN" );
162  }
163 
164  $this->server = 'localhost';
165 
166  $attributes = [];
167  if ( $this->getFlag( self::DBO_PERSISTENT ) ) {
168  // Persistent connections can avoid some schema index reading overhead.
169  // On the other hand, they can cause horrible contention with DBO_TRX.
170  if ( $this->getFlag( self::DBO_TRX ) || $this->getFlag( self::DBO_DEFAULT ) ) {
171  $this->connLogger->warning(
172  __METHOD__ . ": ignoring DBO_PERSISTENT due to DBO_TRX or DBO_DEFAULT",
173  $this->getLogContext()
174  );
175  } else {
176  $attributes[PDO::ATTR_PERSISTENT] = true;
177  }
178  }
179 
180  try {
181  // Open the database file, creating it if it does not yet exist
182  $this->conn = new PDO( "sqlite:$path", null, null, $attributes );
183  } catch ( PDOException $e ) {
184  throw $this->newExceptionAfterConnectError( $e->getMessage() );
185  }
186 
187  $this->currentDomain = new DatabaseDomain( $dbName, null, $tablePrefix );
188 
189  try {
190  $flags = self::QUERY_IGNORE_DBO_TRX | self::QUERY_NO_RETRY;
191  // Enforce LIKE to be case sensitive, just like MySQL
192  $this->query( 'PRAGMA case_sensitive_like = 1', __METHOD__, $flags );
193  // Set any connection-level custom PRAGMA options
194  $pragmas = array_intersect_key( $this->connectionVariables, self::$VALID_PRAGMAS );
195  $pragmas += $this->getDefaultPragmas();
196  foreach ( $pragmas as $name => $value ) {
197  $allowed = self::$VALID_PRAGMAS[$name];
198  if ( in_array( $value, $allowed, true ) ) {
199  $this->query( "PRAGMA $name = $value", __METHOD__, $flags );
200  }
201  }
203  } catch ( RuntimeException $e ) {
204  throw $this->newExceptionAfterConnectError( $e->getMessage() );
205  }
206  }
207 
211  private function getDefaultPragmas() {
212  $variables = [];
213 
214  if ( !$this->cliMode ) {
215  $variables['temp_store'] = 'MEMORY';
216  }
217 
218  return $variables;
219  }
220 
226  public function getDbFilePath() {
227  return $this->dbPath ?? self::generateFileName( $this->dbDir, $this->getDBname() );
228  }
229 
233  public function getLockFileDirectory() {
234  if ( $this->dbPath !== null && !self::isProcessMemoryPath( $this->dbPath ) ) {
235  return dirname( $this->dbPath ) . '/locks';
236  } elseif ( $this->dbDir !== null && !self::isProcessMemoryPath( $this->dbDir ) ) {
237  return $this->dbDir . '/locks';
238  }
239 
240  return null;
241  }
242 
247  protected function closeConnection() {
248  $this->conn = null;
249 
250  return true;
251  }
252 
260  public static function generateFileName( $dir, $dbName ) {
261  if ( $dir == '' ) {
262  throw new DBUnexpectedError( null, __CLASS__ . ": no DB directory specified" );
263  } elseif ( self::isProcessMemoryPath( $dir ) ) {
264  throw new DBUnexpectedError(
265  null,
266  __CLASS__ . ": cannot use process memory directory '$dir'"
267  );
268  } elseif ( !strlen( $dbName ) ) {
269  throw new DBUnexpectedError( null, __CLASS__ . ": no DB name specified" );
270  }
271 
272  return "$dir/$dbName.sqlite";
273  }
274 
279  private static function generateDatabaseName( $path ) {
280  if ( preg_match( '/^(:memory:$|file::memory:)/', $path ) ) {
281  // E.g. "file::memory:?cache=shared" => ":memory":
282  return ':memory:';
283  } elseif ( preg_match( '/^file::([^?]+)\?mode=memory(&|$)/', $path, $m ) ) {
284  // E.g. "file:memdb1?mode=memory" => ":memdb1:"
285  return ":{$m[1]}:";
286  } else {
287  // E.g. "/home/.../some_db.sqlite3" => "some_db"
288  return preg_replace( '/\.sqlite\d?$/', '', basename( $path ) );
289  }
290  }
291 
296  private static function isProcessMemoryPath( $path ) {
297  return preg_match( '/^(:memory:$|file:(:memory:|[^?]+\?mode=memory(&|$)))/', $path );
298  }
299 
304  public static function getFulltextSearchModule() {
305  static $cachedResult = null;
306  if ( $cachedResult !== null ) {
307  return $cachedResult;
308  }
309  $cachedResult = false;
310  $table = 'dummy_search_test';
311 
312  $db = self::newStandaloneInstance( ':memory:' );
313  if ( $db->query(
314  "CREATE VIRTUAL TABLE $table USING FTS3(dummy_field)",
315  __METHOD__,
316  IDatabase::QUERY_SILENCE_ERRORS
317  ) ) {
318  $cachedResult = 'FTS3';
319  }
320  $db->close( __METHOD__ );
321 
322  return $cachedResult;
323  }
324 
337  public function attachDatabase( $name, $file = false, $fname = __METHOD__ ) {
338  $file = is_string( $file ) ? $file : self::generateFileName( $this->dbDir, $name );
339  $encFile = $this->addQuotes( $file );
340 
341  return $this->query(
342  "ATTACH DATABASE $encFile AS $name",
343  $fname,
344  self::QUERY_IGNORE_DBO_TRX
345  );
346  }
347 
348  protected function isWriteQuery( $sql, $flags ) {
349  return parent::isWriteQuery( $sql, $flags ) && !preg_match( '/^(ATTACH|PRAGMA)\b/i', $sql );
350  }
351 
352  protected function isTransactableQuery( $sql ) {
353  return parent::isTransactableQuery( $sql ) && !in_array(
354  $this->getQueryVerb( $sql ),
355  [ 'ATTACH', 'PRAGMA' ],
356  true
357  );
358  }
359 
366  protected function doQuery( $sql ) {
367  $res = $this->getBindingHandle()->query( $sql );
368  if ( $res === false ) {
369  return false;
370  }
371 
372  $resource = ResultWrapper::unwrap( $res );
373  $this->lastAffectedRowCount = $resource->rowCount();
374  $res = new ResultWrapper( $this, $resource->fetchAll() );
375 
376  return $res;
377  }
378 
382  public function freeResult( $res ) {
383  if ( $res instanceof ResultWrapper ) {
384  $res->free();
385  }
386  }
387 
392  public function fetchObject( $res ) {
393  $resource =& ResultWrapper::unwrap( $res );
394 
395  $cur = current( $resource );
396  if ( is_array( $cur ) ) {
397  next( $resource );
398  $obj = (object)[];
399  foreach ( $cur as $k => $v ) {
400  if ( !is_numeric( $k ) ) {
401  $obj->$k = $v;
402  }
403  }
404 
405  return $obj;
406  }
407 
408  return false;
409  }
410 
415  public function fetchRow( $res ) {
416  $resource =& ResultWrapper::unwrap( $res );
417  $cur = current( $resource );
418  if ( is_array( $cur ) ) {
419  next( $resource );
420 
421  return $cur;
422  }
423 
424  return false;
425  }
426 
433  public function numRows( $res ) {
434  // false does not implement Countable
435  $resource = ResultWrapper::unwrap( $res );
436 
437  return is_array( $resource ) ? count( $resource ) : 0;
438  }
439 
444  public function numFields( $res ) {
445  $resource = ResultWrapper::unwrap( $res );
446  if ( is_array( $resource ) && count( $resource ) > 0 ) {
447  // The size of the result array is twice the number of fields. (T67578)
448  return count( $resource[0] ) / 2;
449  } else {
450  // If the result is empty return 0
451  return 0;
452  }
453  }
454 
460  public function fieldName( $res, $n ) {
461  $resource = ResultWrapper::unwrap( $res );
462  if ( is_array( $resource ) ) {
463  $keys = array_keys( $resource[0] );
464 
465  return $keys[$n];
466  }
467 
468  return false;
469  }
470 
471  protected function doSelectDomain( DatabaseDomain $domain ) {
472  if ( $domain->getSchema() !== null ) {
473  throw new DBExpectedError(
474  $this,
475  __CLASS__ . ": domain '{$domain->getId()}' has a schema component"
476  );
477  }
478 
479  $database = $domain->getDatabase();
480  // A null database means "don't care" so leave it as is and update the table prefix
481  if ( $database === null ) {
482  $this->currentDomain = new DatabaseDomain(
483  $this->currentDomain->getDatabase(),
484  null,
485  $domain->getTablePrefix()
486  );
487 
488  return true;
489  }
490 
491  if ( $database !== $this->getDBname() ) {
492  throw new DBExpectedError(
493  $this,
494  __CLASS__ . ": cannot change database (got '$database')"
495  );
496  }
497 
498  return true;
499  }
500 
508  public function tableName( $name, $format = 'quoted' ) {
509  // table names starting with sqlite_ are reserved
510  if ( strpos( $name, 'sqlite_' ) === 0 ) {
511  return $name;
512  }
513 
514  return str_replace( '"', '', parent::tableName( $name, $format ) );
515  }
516 
522  public function insertId() {
523  // PDO::lastInsertId yields a string :(
524  return intval( $this->getBindingHandle()->lastInsertId() );
525  }
526 
531  public function dataSeek( $res, $row ) {
532  $resource =& ResultWrapper::unwrap( $res );
533  reset( $resource );
534  if ( $row > 0 ) {
535  for ( $i = 0; $i < $row; $i++ ) {
536  next( $resource );
537  }
538  }
539  }
540 
544  public function lastError() {
545  if ( !is_object( $this->conn ) ) {
546  return "Cannot return last error, no db connection";
547  }
548  $e = $this->conn->errorInfo();
549 
550  return $e[2] ?? '';
551  }
552 
556  public function lastErrno() {
557  if ( !is_object( $this->conn ) ) {
558  return "Cannot return last error, no db connection";
559  } else {
560  $info = $this->conn->errorInfo();
561 
562  return $info[1];
563  }
564  }
565 
569  protected function fetchAffectedRowCount() {
571  }
572 
573  public function tableExists( $table, $fname = __METHOD__ ) {
574  $tableRaw = $this->tableName( $table, 'raw' );
575  if ( isset( $this->sessionTempTables[$tableRaw] ) ) {
576  return true; // already known to exist
577  }
578 
579  $encTable = $this->addQuotes( $tableRaw );
580  $res = $this->query(
581  "SELECT 1 FROM sqlite_master WHERE type='table' AND name=$encTable",
582  __METHOD__,
583  self::QUERY_IGNORE_DBO_TRX
584  );
585 
586  return $res->numRows() ? true : false;
587  }
588 
599  public function indexInfo( $table, $index, $fname = __METHOD__ ) {
600  $sql = 'PRAGMA index_info(' . $this->addQuotes( $this->indexName( $index ) ) . ')';
601  $res = $this->query( $sql, $fname, self::QUERY_IGNORE_DBO_TRX );
602  if ( !$res || $res->numRows() == 0 ) {
603  return false;
604  }
605  $info = [];
606  foreach ( $res as $row ) {
607  $info[] = $row->name;
608  }
609 
610  return $info;
611  }
612 
619  public function indexUnique( $table, $index, $fname = __METHOD__ ) {
620  $row = $this->selectRow( 'sqlite_master', '*',
621  [
622  'type' => 'index',
623  'name' => $this->indexName( $index ),
624  ], $fname );
625  if ( !$row || !isset( $row->sql ) ) {
626  return null;
627  }
628 
629  // $row->sql will be of the form CREATE [UNIQUE] INDEX ...
630  $indexPos = strpos( $row->sql, 'INDEX' );
631  if ( $indexPos === false ) {
632  return null;
633  }
634  $firstPart = substr( $row->sql, 0, $indexPos );
635  $options = explode( ' ', $firstPart );
636 
637  return in_array( 'UNIQUE', $options );
638  }
639 
640  protected function makeSelectOptions( array $options ) {
641  // Remove problematic options that the base implementation converts to SQL
642  foreach ( $options as $k => $v ) {
643  if ( is_numeric( $k ) && ( $v === 'FOR UPDATE' || $v === 'LOCK IN SHARE MODE' ) ) {
644  $options[$k] = '';
645  }
646  }
647 
648  return parent::makeSelectOptions( $options );
649  }
650 
655  protected function makeUpdateOptionsArray( $options ) {
656  $options = parent::makeUpdateOptionsArray( $options );
657  $options = $this->rewriteIgnoreKeyword( $options );
658 
659  return $options;
660  }
661 
666  private function rewriteIgnoreKeyword( $options ) {
667  # SQLite uses OR IGNORE not just IGNORE
668  foreach ( $options as $k => $v ) {
669  if ( $v == 'IGNORE' ) {
670  $options[$k] = 'OR IGNORE';
671  }
672  }
673 
674  return $options;
675  }
676 
678  return [ 'INSERT OR IGNORE INTO', '' ];
679  }
680 
681  protected function doReplace( $table, array $uniqueKeys, array $rows, $fname ) {
682  $encTable = $this->tableName( $table );
683  list( $sqlColumns, $sqlTuples ) = $this->makeInsertLists( $rows );
684  // https://sqlite.org/lang_insert.html
685  $this->query( "REPLACE INTO $encTable ($sqlColumns) VALUES $sqlTuples", $fname );
686  }
687 
696  public function textFieldSize( $table, $field ) {
697  return -1;
698  }
699 
703  public function unionSupportsOrderAndLimit() {
704  return false;
705  }
706 
712  public function unionQueries( $sqls, $all ) {
713  $glue = $all ? ' UNION ALL ' : ' UNION ';
714 
715  return implode( $glue, $sqls );
716  }
717 
721  public function wasDeadlock() {
722  return $this->lastErrno() == 5; // SQLITE_BUSY
723  }
724 
728  public function wasReadOnlyError() {
729  return $this->lastErrno() == 8; // SQLITE_READONLY;
730  }
731 
732  public function wasConnectionError( $errno ) {
733  return $errno == 17; // SQLITE_SCHEMA;
734  }
735 
736  protected function wasKnownStatementRollbackError() {
737  // ON CONFLICT ROLLBACK clauses make it so that SQLITE_CONSTRAINT error is
738  // ambiguous with regard to whether it implies a ROLLBACK or an ABORT happened.
739  // https://sqlite.org/lang_createtable.html#uniqueconst
740  // https://sqlite.org/lang_conflict.html
741  return false;
742  }
743 
744  public function serverIsReadOnly() {
745  $this->assertHasConnectionHandle();
746 
747  $path = $this->getDbFilePath();
748 
749  return ( !self::isProcessMemoryPath( $path ) && !is_writable( $path ) );
750  }
751 
755  public function getSoftwareLink() {
756  return "[{{int:version-db-sqlite-url}} SQLite]";
757  }
758 
762  public function getServerVersion() {
763  if ( $this->version === null ) {
764  $this->version = $this->getBindingHandle()->getAttribute( PDO::ATTR_SERVER_VERSION );
765  }
766 
767  return $this->version;
768  }
769 
778  public function fieldInfo( $table, $field ) {
779  $tableName = $this->tableName( $table );
780  $sql = 'PRAGMA table_info(' . $this->addQuotes( $tableName ) . ')';
781  $res = $this->query( $sql, __METHOD__, self::QUERY_IGNORE_DBO_TRX );
782  foreach ( $res as $row ) {
783  if ( $row->name == $field ) {
784  return new SQLiteField( $row, $tableName );
785  }
786  }
787 
788  return false;
789  }
790 
791  protected function doBegin( $fname = '' ) {
792  if ( $this->trxMode != '' ) {
793  $this->query( "BEGIN {$this->trxMode}", $fname );
794  } else {
795  $this->query( 'BEGIN', $fname );
796  }
797  }
798 
803  public function strencode( $s ) {
804  return substr( $this->addQuotes( $s ), 1, -1 );
805  }
806 
811  public function encodeBlob( $b ) {
812  return new Blob( $b );
813  }
814 
819  public function decodeBlob( $b ) {
820  if ( $b instanceof Blob ) {
821  $b = $b->fetch();
822  }
823 
824  return $b;
825  }
826 
831  public function addQuotes( $s ) {
832  if ( $s instanceof Blob ) {
833  return "x'" . bin2hex( $s->fetch() ) . "'";
834  } elseif ( is_bool( $s ) ) {
835  return (string)(int)$s;
836  } elseif ( is_int( $s ) ) {
837  return (string)$s;
838  } elseif ( strpos( (string)$s, "\0" ) !== false ) {
839  // SQLite doesn't support \0 in strings, so use the hex representation as a workaround.
840  // This is a known limitation of SQLite's mprintf function which PDO
841  // should work around, but doesn't. I have reported this to php.net as bug #63419:
842  // https://bugs.php.net/bug.php?id=63419
843  // There was already a similar report for SQLite3::escapeString, bug #62361:
844  // https://bugs.php.net/bug.php?id=62361
845  // There is an additional bug regarding sorting this data after insert
846  // on older versions of sqlite shipped with ubuntu 12.04
847  // https://phabricator.wikimedia.org/T74367
848  $this->queryLogger->debug(
849  __FUNCTION__ .
850  ': Quoting value containing null byte. ' .
851  'For consistency all binary data should have been ' .
852  'first processed with self::encodeBlob()'
853  );
854  return "x'" . bin2hex( (string)$s ) . "'";
855  } else {
856  return $this->getBindingHandle()->quote( (string)$s );
857  }
858  }
859 
860  public function buildSubstring( $input, $startPosition, $length = null ) {
861  $this->assertBuildSubstringParams( $startPosition, $length );
862  $params = [ $input, $startPosition ];
863  if ( $length !== null ) {
864  $params[] = $length;
865  }
866  return 'SUBSTR(' . implode( ',', $params ) . ')';
867  }
868 
874  public function buildStringCast( $field ) {
875  return 'CAST ( ' . $field . ' AS TEXT )';
876  }
877 
884  public function deadlockLoop( ...$args ) {
885  $function = array_shift( $args );
886 
887  return $function( ...$args );
888  }
889 
894  protected function replaceVars( $s ) {
895  $s = parent::replaceVars( $s );
896  if ( preg_match( '/^\s*(CREATE|ALTER) TABLE/i', $s ) ) {
897  // CREATE TABLE hacks to allow schema file sharing with MySQL
898 
899  // binary/varbinary column type -> blob
900  $s = preg_replace( '/\b(var)?binary(\‍(\d+\‍))/i', 'BLOB', $s );
901  // no such thing as unsigned
902  $s = preg_replace( '/\b(un)?signed\b/i', '', $s );
903  // INT -> INTEGER
904  $s = preg_replace( '/\b(tiny|small|medium|big|)int(\s*\‍(\s*\d+\s*\‍)|\b)/i', 'INTEGER', $s );
905  // floating point types -> REAL
906  $s = preg_replace(
907  '/\b(float|double(\s+precision)?)(\s*\‍(\s*\d+\s*(,\s*\d+\s*)?\‍)|\b)/i',
908  'REAL',
909  $s
910  );
911  // varchar -> TEXT
912  $s = preg_replace( '/\b(var)?char\s*\‍(.*?\‍)/i', 'TEXT', $s );
913  // TEXT normalization
914  $s = preg_replace( '/\b(tiny|medium|long)text\b/i', 'TEXT', $s );
915  // BLOB normalization
916  $s = preg_replace( '/\b(tiny|small|medium|long|)blob\b/i', 'BLOB', $s );
917  // BOOL -> INTEGER
918  $s = preg_replace( '/\bbool(ean)?\b/i', 'INTEGER', $s );
919  // DATETIME -> TEXT
920  $s = preg_replace( '/\b(datetime|timestamp)\b/i', 'TEXT', $s );
921  // No ENUM type
922  $s = preg_replace( '/\benum\s*\‍([^)]*\‍)/i', 'TEXT', $s );
923  // binary collation type -> nothing
924  $s = preg_replace( '/\bbinary\b/i', '', $s );
925  // auto_increment -> autoincrement
926  $s = preg_replace( '/\bauto_increment\b/i', 'AUTOINCREMENT', $s );
927  // No explicit options
928  $s = preg_replace( '/\‍)[^);]*(;?)\s*$/', ')\1', $s );
929  // AUTOINCREMENT should immedidately follow PRIMARY KEY
930  $s = preg_replace( '/primary key (.*?) autoincrement/i', 'PRIMARY KEY AUTOINCREMENT $1', $s );
931  } elseif ( preg_match( '/^\s*CREATE (\s*(?:UNIQUE|FULLTEXT)\s+)?INDEX/i', $s ) ) {
932  // No truncated indexes
933  $s = preg_replace( '/\‍(\d+\‍)/', '', $s );
934  // No FULLTEXT
935  $s = preg_replace( '/\bfulltext\b/i', '', $s );
936  } elseif ( preg_match( '/^\s*DROP INDEX/i', $s ) ) {
937  // DROP INDEX is database-wide, not table-specific, so no ON <table> clause.
938  $s = preg_replace( '/\sON\s+[^\s]*/i', '', $s );
939  } elseif ( preg_match( '/^\s*INSERT IGNORE\b/i', $s ) ) {
940  // INSERT IGNORE --> INSERT OR IGNORE
941  $s = preg_replace( '/^\s*INSERT IGNORE\b/i', 'INSERT OR IGNORE', $s );
942  }
943 
944  return $s;
945  }
946 
947  public function lock( $lockName, $method, $timeout = 5 ) {
948  $status = $this->lockMgr->lock( [ $lockName ], LockManager::LOCK_EX, $timeout );
949  if (
950  $this->lockMgr instanceof FSLockManager &&
951  $status->hasMessage( 'lockmanager-fail-openlock' )
952  ) {
953  throw new DBError( $this, "Cannot create directory \"{$this->getLockFileDirectory()}\"" );
954  }
955 
956  return $status->isOK();
957  }
958 
959  public function unlock( $lockName, $method ) {
960  return $this->lockMgr->unlock( [ $lockName ], LockManager::LOCK_EX )->isGood();
961  }
962 
969  public function buildConcat( $stringList ) {
970  return '(' . implode( ') || (', $stringList ) . ')';
971  }
972 
973  public function buildGroupConcatField(
974  $delim, $table, $field, $conds = '', $join_conds = []
975  ) {
976  $fld = "group_concat($field," . $this->addQuotes( $delim ) . ')';
977 
978  return '(' . $this->selectSQLText( $table, $fld, $conds, null, [], $join_conds ) . ')';
979  }
980 
981  public function buildGreatest( $fields, $values ) {
982  return $this->buildSuperlative( 'MAX', $fields, $values );
983  }
984 
985  public function buildLeast( $fields, $values ) {
986  return $this->buildSuperlative( 'MIN', $fields, $values );
987  }
988 
997  public function duplicateTableStructure(
998  $oldName, $newName, $temporary = false, $fname = __METHOD__
999  ) {
1000  $queryFlags = self::QUERY_PSEUDO_PERMANENT | self::QUERY_IGNORE_DBO_TRX;
1001 
1002  $res = $this->query(
1003  "SELECT sql FROM sqlite_master WHERE tbl_name=" .
1004  $this->addQuotes( $oldName ) . " AND type='table'",
1005  $fname,
1006  $queryFlags
1007  );
1008  $obj = $this->fetchObject( $res );
1009  if ( !$obj ) {
1010  throw new RuntimeException( "Couldn't retrieve structure for table $oldName" );
1011  }
1012  $sql = $obj->sql;
1013  $sql = preg_replace(
1014  '/(?<=\W)"?' .
1015  preg_quote( trim( $this->addIdentifierQuotes( $oldName ), '"' ), '/' ) .
1016  '"?(?=\W)/',
1017  $this->addIdentifierQuotes( $newName ),
1018  $sql,
1019  1
1020  );
1021  if ( $temporary ) {
1022  if ( preg_match( '/^\\s*CREATE\\s+VIRTUAL\\s+TABLE\b/i', $sql ) ) {
1023  $this->queryLogger->debug(
1024  "Table $oldName is virtual, can't create a temporary duplicate." );
1025  } else {
1026  $sql = str_replace( 'CREATE TABLE', 'CREATE TEMPORARY TABLE', $sql );
1027  }
1028  }
1029 
1030  $res = $this->query( $sql, $fname, $queryFlags );
1031 
1032  // Take over indexes
1033  $indexList = $this->query(
1034  'PRAGMA INDEX_LIST(' . $this->addQuotes( $oldName ) . ')',
1035  $fname,
1036  $queryFlags
1037  );
1038  foreach ( $indexList as $index ) {
1039  if ( strpos( $index->name, 'sqlite_autoindex' ) === 0 ) {
1040  continue;
1041  }
1042 
1043  if ( $index->unique ) {
1044  $sql = 'CREATE UNIQUE INDEX';
1045  } else {
1046  $sql = 'CREATE INDEX';
1047  }
1048  // Try to come up with a new index name, given indexes have database scope in SQLite
1049  $indexName = $newName . '_' . $index->name;
1050  $sql .= ' ' . $indexName . ' ON ' . $newName;
1051 
1052  $indexInfo = $this->query(
1053  'PRAGMA INDEX_INFO(' . $this->addQuotes( $index->name ) . ')',
1054  $fname,
1055  $queryFlags
1056  );
1057  $fields = [];
1058  foreach ( $indexInfo as $indexInfoRow ) {
1059  $fields[$indexInfoRow->seqno] = $indexInfoRow->name;
1060  }
1061 
1062  $sql .= '(' . implode( ',', $fields ) . ')';
1063 
1064  $this->query( $sql, __METHOD__ );
1065  }
1066 
1067  return $res;
1068  }
1069 
1078  public function listTables( $prefix = null, $fname = __METHOD__ ) {
1079  $result = $this->query(
1080  "SELECT name FROM sqlite_master WHERE type = 'table'",
1081  $fname,
1082  self::QUERY_IGNORE_DBO_TRX
1083  );
1084 
1085  $endArray = [];
1086 
1087  foreach ( $result as $table ) {
1088  $vars = get_object_vars( $table );
1089  $table = array_pop( $vars );
1090 
1091  if ( !$prefix || strpos( $table, $prefix ) === 0 ) {
1092  if ( strpos( $table, 'sqlite_' ) !== 0 ) {
1093  $endArray[] = $table;
1094  }
1095  }
1096  }
1097 
1098  return $endArray;
1099  }
1100 
1101  public function dropTable( $table, $fname = __METHOD__ ) {
1102  if ( !$this->tableExists( $table, $fname ) ) {
1103  return false;
1104  }
1105 
1106  // No CASCADE support; https://www.sqlite.org/lang_droptable.html
1107  $sql = "DROP TABLE " . $this->tableName( $table );
1108  $this->query( $sql, $fname, self::QUERY_IGNORE_DBO_TRX );
1109 
1110  return true;
1111  }
1112 
1113  protected function doTruncate( array $tables, $fname ) {
1114  $this->startAtomic( $fname );
1115 
1116  $encSeqNames = [];
1117  foreach ( $tables as $table ) {
1118  // Use "truncate" optimization; https://www.sqlite.org/lang_delete.html
1119  $sql = "DELETE FROM " . $this->tableName( $table );
1120  $this->query( $sql, $fname, self::QUERY_CHANGE_SCHEMA );
1121 
1122  $encSeqNames[] = $this->addQuotes( $this->tableName( $table, 'raw' ) );
1123  }
1124 
1125  $encMasterTable = $this->addIdentifierQuotes( 'sqlite_sequence' );
1126  $this->query(
1127  "DELETE FROM $encMasterTable WHERE name IN(" . implode( ',', $encSeqNames ) . ")",
1128  $fname,
1129  self::QUERY_CHANGE_SCHEMA
1130  );
1131 
1132  $this->endAtomic( $fname );
1133  }
1134 
1135  public function setTableAliases( array $aliases ) {
1136  parent::setTableAliases( $aliases );
1137  if ( $this->isOpen() ) {
1139  }
1140  }
1141 
1145  private function attachDatabasesFromTableAliases() {
1146  foreach ( $this->tableAliases as $params ) {
1147  if (
1148  $params['dbname'] !== $this->getDBname() &&
1149  !isset( $this->sessionAttachedDbs[$params['dbname']] )
1150  ) {
1151  $this->attachDatabase( $params['dbname'], false, __METHOD__ );
1152  $this->sessionAttachedDbs[$params['dbname']] = true;
1153  }
1154  }
1155  }
1156 
1157  public function databasesAreIndependent() {
1158  return true;
1159  }
1160 
1161  protected function doHandleSessionLossPreconnect() {
1162  $this->sessionAttachedDbs = [];
1163  }
1164 
1168  protected function getBindingHandle() {
1169  return parent::getBindingHandle();
1170  }
1171 }
1172 
1176 class_alias( DatabaseSqlite::class, 'DatabaseSqlite' );
DBO_PERSISTENT
const DBO_PERSISTENT
Definition: defines.php:14
Wikimedia\Rdbms\SQLiteField
Definition: SQLiteField.php:5
Wikimedia\Rdbms\DatabaseSqlite\$trxMode
string $trxMode
Transaction mode.
Definition: DatabaseSqlite.php:43
Wikimedia\Rdbms\DatabaseSqlite\fieldInfo
fieldInfo( $table, $field)
Get information about a given field Returns false if the field does not exist.
Definition: DatabaseSqlite.php:778
Wikimedia\Rdbms\DatabaseSqlite\$lockMgr
FSLockManager $lockMgr
(hopefully on the same server as the DB)
Definition: DatabaseSqlite.php:52
LockManager
Class for handling resource locking.
Definition: LockManager.php:48
Wikimedia\Rdbms\DatabaseSqlite\getBindingHandle
getBindingHandle()
Definition: DatabaseSqlite.php:1168
Wikimedia\Rdbms\DatabaseSqlite\addQuotes
addQuotes( $s)
Definition: DatabaseSqlite.php:831
Wikimedia\Rdbms\DatabaseSqlite\$VALID_PRAGMAS
static string[][] $VALID_PRAGMAS
Definition: DatabaseSqlite.php:64
Wikimedia\Rdbms\DatabaseSqlite\fetchRow
fetchRow( $res)
Definition: DatabaseSqlite.php:415
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:50
Wikimedia\Rdbms\DatabaseSqlite\doHandleSessionLossPreconnect
doHandleSessionLossPreconnect()
Reset any additional subclass trx* and session* fields Stable to override.
Definition: DatabaseSqlite.php:1161
Wikimedia\Rdbms\DatabaseSqlite
Definition: DatabaseSqlite.php:37
Wikimedia\Rdbms\DatabaseSqlite\wasKnownStatementRollbackError
wasKnownStatementRollbackError()
Stable to override.
Definition: DatabaseSqlite.php:736
Wikimedia\Rdbms\DatabaseSqlite\listTables
listTables( $prefix=null, $fname=__METHOD__)
List all tables on the database.
Definition: DatabaseSqlite.php:1078
FSLockManager
Simple version of LockManager based on using FS lock files.
Definition: FSLockManager.php:36
Wikimedia\Rdbms\DatabaseSqlite\deadlockLoop
deadlockLoop(... $args)
No-op version of deadlockLoop.
Definition: DatabaseSqlite.php:884
Wikimedia\Rdbms\DatabaseSqlite\unlock
unlock( $lockName, $method)
Release a lock.Named locks are not related to transactionsName of lock to release Name of the calling...
Definition: DatabaseSqlite.php:959
Wikimedia\Rdbms\Database\getDomainID
getDomainID()
Return the currently selected domain ID.
Definition: Database.php:809
Wikimedia\Rdbms\DatabaseSqlite\open
open( $server, $user, $pass, $dbName, $schema, $tablePrefix)
Open a new connection to the database (closing any existing one)
Definition: DatabaseSqlite.php:136
Wikimedia\Rdbms\DatabaseSqlite\makeInsertNonConflictingVerbAndOptions
makeInsertNonConflictingVerbAndOptions()
Stable to override.
Definition: DatabaseSqlite.php:677
Wikimedia\Rdbms\Database\assertHasConnectionHandle
assertHasConnectionHandle()
Make sure there is an open connection handle (alive or not) as a sanity check.
Definition: Database.php:976
Wikimedia\Rdbms\DatabaseSqlite\attachDatabasesFromTableAliases
attachDatabasesFromTableAliases()
Issue ATTATCH statements for all unattached foreign DBs in table aliases.
Definition: DatabaseSqlite.php:1145
Wikimedia\Rdbms\Database\factory
static factory( $type, $params=[], $connect=self::NEW_CONNECTED)
Construct a Database subclass instance given a database type and parameters.
Definition: Database.php:396
true
return true
Definition: router.php:90
Wikimedia\Rdbms\DatabaseSqlite\unionSupportsOrderAndLimit
unionSupportsOrderAndLimit()
Definition: DatabaseSqlite.php:703
Wikimedia\Rdbms\DatabaseSqlite\$version
string null $version
Definition: DatabaseSqlite.php:55
Wikimedia\Rdbms\DatabaseSqlite\databasesAreIndependent
databasesAreIndependent()
Returns true if DBs are assumed to be on potentially different servers.In systems like mysql/mariadb,...
Definition: DatabaseSqlite.php:1157
Wikimedia\Rdbms\DatabaseSqlite\isProcessMemoryPath
static isProcessMemoryPath( $path)
Definition: DatabaseSqlite.php:296
Wikimedia\Rdbms\DatabaseSqlite\buildLeast
buildLeast( $fields, $values)
Build a LEAST function statement comparing columns/values.Integer and float values in $values will no...
Definition: DatabaseSqlite.php:985
Wikimedia\Rdbms\DatabaseSqlite\getLockFileDirectory
getLockFileDirectory()
Definition: DatabaseSqlite.php:233
Wikimedia\Rdbms\Database\endAtomic
endAtomic( $fname=__METHOD__)
Ends an atomic section of SQL statements.
Definition: Database.php:4337
Wikimedia\Rdbms\Database\indexName
indexName( $index)
Allows for index remapping in queries where this is not consistent across DBMS.
Definition: Database.php:3102
Wikimedia\Rdbms\DatabaseDomain\getTablePrefix
getTablePrefix()
Definition: DatabaseDomain.php:189
Wikimedia\Rdbms\DatabaseSqlite\fetchAffectedRowCount
fetchAffectedRowCount()
Definition: DatabaseSqlite.php:569
Wikimedia\Rdbms\DatabaseSqlite\doTruncate
doTruncate(array $tables, $fname)
Definition: DatabaseSqlite.php:1113
Wikimedia\Rdbms\DatabaseSqlite\encodeBlob
encodeBlob( $b)
Definition: DatabaseSqlite.php:811
Wikimedia\Rdbms\DatabaseSqlite\setTableAliases
setTableAliases(array $aliases)
Make certain table names use their own database, schema, and table prefix when passed into SQL querie...
Definition: DatabaseSqlite.php:1135
Wikimedia\Rdbms
Definition: ChronologyProtector.php:24
Wikimedia\Rdbms\DatabaseSqlite\doReplace
doReplace( $table, array $uniqueKeys, array $rows, $fname)
Definition: DatabaseSqlite.php:681
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
Wikimedia\Rdbms\DatabaseSqlite\lastError
lastError()
Definition: DatabaseSqlite.php:544
Wikimedia\Rdbms\DatabaseSqlite\getServerVersion
getServerVersion()
Definition: DatabaseSqlite.php:762
$s
$s
Definition: mergeMessageFileList.php:185
Wikimedia\Rdbms\DatabaseSqlite\dataSeek
dataSeek( $res, $row)
Definition: DatabaseSqlite.php:531
Wikimedia\Rdbms\DatabaseSqlite\strencode
strencode( $s)
Definition: DatabaseSqlite.php:803
Wikimedia\Rdbms\DatabaseDomain\getDatabase
getDatabase()
Definition: DatabaseDomain.php:175
Wikimedia\Rdbms\DatabaseSqlite\buildSubstring
buildSubstring( $input, $startPosition, $length=null)
Stable to override Stable to override
Definition: DatabaseSqlite.php:860
Wikimedia\Rdbms\ResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: ResultWrapper.php:23
Wikimedia\Rdbms\DatabaseSqlite\closeConnection
closeConnection()
Does not actually close the connection, just destroys the reference for GC to do its work.
Definition: DatabaseSqlite.php:247
Wikimedia\Rdbms\DatabaseSqlite\isWriteQuery
isWriteQuery( $sql, $flags)
Determine whether a query writes to the DB.
Definition: DatabaseSqlite.php:348
$res
$res
Definition: testCompression.php:57
Wikimedia\Rdbms\DatabaseSqlite\dropTable
dropTable( $table, $fname=__METHOD__)
Delete a table.
Definition: DatabaseSqlite.php:1101
Wikimedia\Rdbms\Database\getFlag
getFlag( $flag)
Returns a boolean whether the flag $flag is set for this connection.
Definition: Database.php:805
Wikimedia\Rdbms\DBError
Database error base class @newable Stable to extend.
Definition: DBError.php:32
Wikimedia\Rdbms\DatabaseSqlite\buildStringCast
buildStringCast( $field)
Definition: DatabaseSqlite.php:874
DBO_TRX
const DBO_TRX
Definition: defines.php:12
Wikimedia\Rdbms\DatabaseSqlite\unionQueries
unionQueries( $sqls, $all)
Definition: DatabaseSqlite.php:712
Wikimedia\Rdbms\Database\close
close( $fname=__METHOD__, $owner=null)
Close the database connection.
Definition: Database.php:898
Wikimedia\Rdbms\DatabaseSqlite\$lastAffectedRowCount
int $lastAffectedRowCount
The number of rows affected as an integer.
Definition: DatabaseSqlite.php:46
Wikimedia\Rdbms\Database\assertBuildSubstringParams
assertBuildSubstringParams( $startPosition, $length)
Check type and bounds for parameters to self::buildSubstring()
Definition: Database.php:2693
NullLockManager
Simple version of LockManager that only does lock reference counting.
Definition: NullLockManager.php:28
Wikimedia\Rdbms\DatabaseSqlite\buildGreatest
buildGreatest( $fields, $values)
Build a GREATEST function statement comparing columns/values.Integer and float values in $values will...
Definition: DatabaseSqlite.php:981
Wikimedia\Rdbms\Database\startAtomic
startAtomic( $fname=__METHOD__, $cancelable=self::ATOMIC_NOT_CANCELABLE)
Begin an atomic section of SQL statements.
Definition: Database.php:4307
Wikimedia\Rdbms\DatabaseSqlite\wasDeadlock
wasDeadlock()
Definition: DatabaseSqlite.php:721
Wikimedia\Rdbms\DatabaseSqlite\generateFileName
static generateFileName( $dir, $dbName)
Generates a database file name.
Definition: DatabaseSqlite.php:260
Wikimedia\Rdbms\DatabaseSqlite\doBegin
doBegin( $fname='')
Issues the BEGIN command to the database server.
Definition: DatabaseSqlite.php:791
Wikimedia\Rdbms\DatabaseSqlite\$conn
PDO $conn
Definition: DatabaseSqlite.php:49
Wikimedia\Rdbms\Database\selectSQLText
selectSQLText( $table, $vars, $conds='', $fname=__METHOD__, $options=[], $join_conds=[])
Take the same arguments as IDatabase::select() and return the SQL it would use.This can be useful for...
Definition: Database.php:1914
Wikimedia\Rdbms\Database\makeInsertLists
makeInsertLists(array $rows)
Make SQL lists of columns, row tuples for INSERT/VALUES expressions.
Definition: Database.php:2383
$args
if( $line===false) $args
Definition: mcc.php:124
Wikimedia\Rdbms\Database\$user
string $user
User that this instance is currently connected under the name of.
Definition: Database.php:80
Wikimedia\Rdbms\DatabaseSqlite\tableExists
tableExists( $table, $fname=__METHOD__)
Query whether a given table exists.
Definition: DatabaseSqlite.php:573
Wikimedia\Rdbms\DatabaseSqlite\$VALID_TRX_MODES
static string[] $VALID_TRX_MODES
See https://www.sqlite.org/lang_transaction.html.
Definition: DatabaseSqlite.php:61
Wikimedia\Rdbms\DatabaseSqlite\getDbFilePath
getDbFilePath()
Definition: DatabaseSqlite.php:226
Wikimedia\Rdbms\DatabaseSqlite\numRows
numRows( $res)
The PDO::Statement class implements the array interface so count() will work.
Definition: DatabaseSqlite.php:433
Wikimedia\Rdbms\DatabaseSqlite\replaceVars
replaceVars( $s)
Definition: DatabaseSqlite.php:894
Wikimedia\Rdbms\DatabaseSqlite\fieldName
fieldName( $res, $n)
Definition: DatabaseSqlite.php:460
Wikimedia\Rdbms\Database\selectRow
selectRow( $table, $vars, $conds, $fname=__METHOD__, $options=[], $join_conds=[])
Wrapper to IDatabase::select() that only fetches one row (via LIMIT)
Definition: Database.php:2001
Wikimedia\Rdbms\Database\buildSuperlative
buildSuperlative( $sqlfunc, $fields, $values)
Build a superlative function statement comparing columns/values.
Definition: Database.php:2641
Wikimedia\Rdbms\DatabaseSqlite\lock
lock( $lockName, $method, $timeout=5)
Acquire a named lock.Named locks are not related to transactionsName of lock to aquire Name of the ca...
Definition: DatabaseSqlite.php:947
Wikimedia\Rdbms\DatabaseSqlite\fetchObject
fetchObject( $res)
Definition: DatabaseSqlite.php:392
Wikimedia\Rdbms\Database\getLogContext
getLogContext(array $extras=[])
Create a log context to pass to PSR-3 logger functions.
Definition: Database.php:887
Wikimedia\Rdbms\DatabaseSqlite\doQuery
doQuery( $sql)
SQLite doesn't allow buffered results or data seeking etc, so we'll use fetchAll as the result.
Definition: DatabaseSqlite.php:366
Wikimedia\Rdbms\DatabaseSqlite\$dbDir
string null $dbDir
Directory for SQLite database files listed under their DB name.
Definition: DatabaseSqlite.php:39
Wikimedia\Rdbms\DatabaseSqlite\getAttributes
static getAttributes()
Stable to override.
Definition: DatabaseSqlite.php:103
Wikimedia\Rdbms\Database\query
query( $sql, $fname=__METHOD__, $flags=self::QUERY_NORMAL)
Run an SQL query and return the result.
Definition: Database.php:1216
Wikimedia\Rdbms\DatabaseSqlite\getType
getType()
Definition: DatabaseSqlite.php:132
Wikimedia\Rdbms\DatabaseSqlite\buildGroupConcatField
buildGroupConcatField( $delim, $table, $field, $conds='', $join_conds=[])
Build a GROUP_CONCAT or equivalent statement for a query.This is useful for combining a field for sev...
Definition: DatabaseSqlite.php:973
Wikimedia\Rdbms\DatabaseSqlite\attachDatabase
attachDatabase( $name, $file=false, $fname=__METHOD__)
Attaches external database to the connection handle.
Definition: DatabaseSqlite.php:337
Wikimedia\Rdbms\DBUnexpectedError
@newable Stable to extend
Definition: DBUnexpectedError.php:29
Wikimedia\Rdbms\DatabaseSqlite\isTransactableQuery
isTransactableQuery( $sql)
Determine whether a SQL statement is sensitive to isolation level.
Definition: DatabaseSqlite.php:352
Wikimedia\Rdbms\DatabaseSqlite\generateDatabaseName
static generateDatabaseName( $path)
Definition: DatabaseSqlite.php:279
Wikimedia\Rdbms\DatabaseSqlite\newStandaloneInstance
static newStandaloneInstance( $filename, array $p=[])
Definition: DatabaseSqlite.php:119
Wikimedia\Rdbms\Database\addIdentifierQuotes
addIdentifierQuotes( $s)
Escape a SQL identifier (e.g.table, column, database) for use in a SQL queryDepending on the database...
Definition: Database.php:3129
Wikimedia\Rdbms\DatabaseSqlite\getFulltextSearchModule
static getFulltextSearchModule()
Returns version of currently supported SQLite fulltext search module or false if none present.
Definition: DatabaseSqlite.php:304
Wikimedia\Rdbms\Database\getQueryVerb
getQueryVerb( $sql)
Definition: Database.php:1086
Wikimedia\Rdbms\DatabaseSqlite\$dbPath
string null $dbPath
Explicit path for the SQLite database file.
Definition: DatabaseSqlite.php:41
Wikimedia\Rdbms\DatabaseSqlite\makeUpdateOptionsArray
makeUpdateOptionsArray( $options)
Definition: DatabaseSqlite.php:655
Wikimedia\Rdbms\DatabaseSqlite\getSoftwareLink
getSoftwareLink()
Definition: DatabaseSqlite.php:755
Wikimedia\Rdbms\Database\newExceptionAfterConnectError
newExceptionAfterConnectError( $error)
Definition: Database.php:1707
Wikimedia\Rdbms\DatabaseSqlite\insertId
insertId()
This must be called after nextSequenceVal.
Definition: DatabaseSqlite.php:522
Wikimedia\Rdbms\DBExpectedError
Base class for the more common types of database errors.
Definition: DBExpectedError.php:34
Wikimedia\Rdbms\DatabaseSqlite\$sessionAttachedDbs
array $sessionAttachedDbs
List of shared database already attached to this connection.
Definition: DatabaseSqlite.php:58
Wikimedia\Rdbms\DatabaseSqlite\freeResult
freeResult( $res)
Definition: DatabaseSqlite.php:382
Wikimedia\Rdbms\DatabaseSqlite\lastErrno
lastErrno()
Definition: DatabaseSqlite.php:556
$path
$path
Definition: NoLocalSettings.php:25
Wikimedia\Rdbms\DatabaseDomain\getSchema
getSchema()
Definition: DatabaseDomain.php:182
Wikimedia\Rdbms\DatabaseSqlite\indexUnique
indexUnique( $table, $index, $fname=__METHOD__)
Definition: DatabaseSqlite.php:619
Wikimedia\Rdbms\DatabaseSqlite\wasReadOnlyError
wasReadOnlyError()
Definition: DatabaseSqlite.php:728
Wikimedia\Rdbms\Database\$server
string $server
Server that this instance is currently connected to.
Definition: Database.php:78
$keys
$keys
Definition: testCompression.php:72
Wikimedia\Rdbms\Database\isOpen
isOpen()
Definition: Database.php:758
Wikimedia\Rdbms\DatabaseSqlite\doSelectDomain
doSelectDomain(DatabaseDomain $domain)
Stable to override.
Definition: DatabaseSqlite.php:471
Wikimedia\Rdbms\Database\$flags
int $flags
Current bit field of class DBO_* constants.
Definition: Database.php:99
Wikimedia\Rdbms\DatabaseSqlite\__construct
__construct(array $params)
Additional params include:
Definition: DatabaseSqlite.php:78
Wikimedia\Rdbms\DatabaseSqlite\buildConcat
buildConcat( $stringList)
Build a concatenation list to feed into a SQL query.
Definition: DatabaseSqlite.php:969
Wikimedia\Rdbms\DatabaseSqlite\wasConnectionError
wasConnectionError( $errno)
Do not use this method outside of Database/DBError classes.
Definition: DatabaseSqlite.php:732
Wikimedia\Rdbms\DatabaseDomain
Class to handle database/schema/prefix specifications for IDatabase.
Definition: DatabaseDomain.php:40
LockManager\LOCK_EX
const LOCK_EX
Definition: LockManager.php:71
Wikimedia\Rdbms\DatabaseSqlite\decodeBlob
decodeBlob( $b)
Definition: DatabaseSqlite.php:819
DBO_DEFAULT
const DBO_DEFAULT
Definition: defines.php:13
Wikimedia\Rdbms\ResultWrapper\unwrap
static & unwrap(&$res)
Get the underlying RDBMS driver-specific result resource.
Definition: ResultWrapper.php:59
Wikimedia\Rdbms\DatabaseSqlite\getDefaultPragmas
getDefaultPragmas()
Definition: DatabaseSqlite.php:211
Wikimedia\Rdbms\DatabaseSqlite\serverIsReadOnly
serverIsReadOnly()
bool Whether the DB is marked as read-only server-side 1.28 Stable to override Stable to override
Definition: DatabaseSqlite.php:744
Wikimedia\Rdbms\DatabaseSqlite\duplicateTableStructure
duplicateTableStructure( $oldName, $newName, $temporary=false, $fname=__METHOD__)
Definition: DatabaseSqlite.php:997
Wikimedia\Rdbms\DatabaseSqlite\numFields
numFields( $res)
Definition: DatabaseSqlite.php:444
Wikimedia\Rdbms\DatabaseSqlite\tableName
tableName( $name, $format='quoted')
Use MySQL's naming (accounts for prefix etc) but remove surrounding backticks.
Definition: DatabaseSqlite.php:508
Wikimedia\Rdbms\DatabaseSqlite\rewriteIgnoreKeyword
rewriteIgnoreKeyword( $options)
Definition: DatabaseSqlite.php:666
Wikimedia\Rdbms\DatabaseSqlite\indexInfo
indexInfo( $table, $index, $fname=__METHOD__)
Returns information about an index Returns false if the index does not exist.
Definition: DatabaseSqlite.php:599
Wikimedia\Rdbms\DatabaseSqlite\textFieldSize
textFieldSize( $table, $field)
Returns the size of a text field, or -1 for "unlimited" In SQLite this is SQLITE_MAX_LENGTH,...
Definition: DatabaseSqlite.php:696
Wikimedia\Rdbms\Database\getDBname
getDBname()
Get the current DB name.
Definition: Database.php:2790
Wikimedia\Rdbms\Blob
@newable Stable to extend
Definition: Blob.php:9
Wikimedia\Rdbms\DatabaseSqlite\makeSelectOptions
makeSelectOptions(array $options)
Returns an optional USE INDEX clause to go after the table, and a string to go at the end of the quer...
Definition: DatabaseSqlite.php:640