26use Wikimedia\Timestamp\ConvertibleTimestamp;
27use Wikimedia\WaitConditionLoop;
55 $this->port = intval( $params[
'port'] ??
null );
57 if ( isset( $params[
'keywordTableMap'] ) ) {
59 'DatabasePostgres::__construct() is deprecated',
'1.37'
62 $this->keywordTableMap = $params[
'keywordTableMap'];
65 parent::__construct( $params );
77 if ( !function_exists(
'pg_connect' ) ) {
79 "Postgres functions missing, have you compiled PHP with the --with-pgsql\n" .
80 "option? (Note: if you recently installed PHP, you may need to restart your\n" .
81 "webserver and database)"
85 $this->
close( __METHOD__ );
90 'dbname' => strlen( $db ) ? $db :
'postgres',
97 if ( $this->port > 0 ) {
100 if ( $this->
getFlag( self::DBO_SSL ) ) {
101 $connectVars[
'sslmode'] =
'require';
107 $this->conn = pg_connect( $connectString, PGSQL_CONNECT_FORCE_NEW ) ?:
null;
108 }
catch ( RuntimeException $e ) {
114 if ( !$this->conn ) {
123 'client_encoding' =>
'UTF8',
124 'datestyle' =>
'ISO, YMD',
126 'standard_conforming_strings' =>
'on',
127 'bytea_output' =>
'escape',
128 'client_min_messages' =>
'ERROR'
130 foreach ( $variables as $var => $val ) {
134 self::QUERY_IGNORE_DBO_TRX | self::QUERY_NO_RETRY | self::QUERY_CHANGE_TRX
138 $this->currentDomain =
new DatabaseDomain( $db, $schema, $tablePrefix );
139 }
catch ( RuntimeException $e ) {
145 if ( $this->coreSchema === $this->currentDomain->getSchema() ) {
150 return parent::relationSchemaQualifier();
162 $this->connectionParams[self::CONN_HOST],
163 $this->connectionParams[self::CONN_USER],
164 $this->connectionParams[self::CONN_PASSWORD],
170 $this->currentDomain = $domain;
182 foreach ( $vars as $name => $value ) {
183 $s .=
"$name='" . str_replace(
"'",
"\\'", $value ) .
"' ";
190 return $this->conn ? pg_close( $this->conn ) :
true;
194 return parent::isTransactableQuery( $sql ) &&
195 !preg_match(
'/^SELECT\s+pg_(try_|)advisory_\w+\(/', $sql );
205 $sql = mb_convert_encoding( $sql,
'UTF-8' );
207 while (
$res = pg_get_result(
$conn ) ) {
208 pg_free_result(
$res );
210 if ( pg_send_query(
$conn, $sql ) ===
false ) {
211 throw new DBUnexpectedError( $this,
"Unable to post new query to PostgreSQL\n" );
213 $this->lastResultHandle = pg_get_result(
$conn );
214 if ( pg_result_error( $this->lastResultHandle ) ) {
218 return $this->lastResultHandle ?
226 PGSQL_DIAG_MESSAGE_PRIMARY,
227 PGSQL_DIAG_MESSAGE_DETAIL,
228 PGSQL_DIAG_MESSAGE_HINT,
229 PGSQL_DIAG_STATEMENT_POSITION,
230 PGSQL_DIAG_INTERNAL_POSITION,
231 PGSQL_DIAG_INTERNAL_QUERY,
233 PGSQL_DIAG_SOURCE_FILE,
234 PGSQL_DIAG_SOURCE_LINE,
235 PGSQL_DIAG_SOURCE_FUNCTION
237 foreach ( $diags as $d ) {
238 $this->queryLogger->debug( sprintf(
"PgSQL ERROR(%d): %s",
239 $d, pg_result_error_field( $this->lastResultHandle, $d ) ) );
247 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
251 return $row[0] ===
null ? null : (int)$row[0];
256 if ( $this->lastResultHandle ) {
257 return pg_result_error( $this->lastResultHandle );
259 return pg_last_error();
267 if ( $this->lastResultHandle ) {
268 return pg_result_error_field( $this->lastResultHandle, PGSQL_DIAG_SQLSTATE );
275 if ( !$this->lastResultHandle ) {
279 return pg_affected_rows( $this->lastResultHandle );
298 $fname = __METHOD__, $options = [], $join_conds = []
302 if ( is_string( $column ) && !in_array( $column, [
'*',
'1' ] ) ) {
303 $conds[] =
"$column IS NOT NULL";
306 $options[
'EXPLAIN'] =
true;
307 $res = $this->
select( $table, $var, $conds, $fname, $options, $join_conds );
312 if ( preg_match(
'/rows=(\d+)/', $row[0], $count ) ) {
313 $rows = (int)$count[1];
320 public function indexInfo( $table, $index, $fname = __METHOD__ ) {
322 "SELECT indexname FROM pg_indexes WHERE tablename='$table'",
324 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
329 foreach (
$res as $row ) {
330 if ( $row->indexname == $this->indexName( $index ) ) {
339 if ( $schema ===
false ) {
342 $schemas = [ $schema ];
347 $flags = self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE;
348 foreach ( $schemas as $schema ) {
354 $sql = <<<__INDEXATTR__
358 i.indoption[s.g] as option,
361 (SELECT generate_series(array_lower(isub.indkey,1), array_upper(isub.indkey,1)) AS g
365 ON cis.oid=isub.indexrelid
367 ON cis.relnamespace = ns.oid
368 WHERE cis.relname=$eindex AND ns.nspname=$eschema) AS s,
374 ON ci.oid=i.indexrelid
376 ON ct.oid = i.indrelid
378 ON ci.relnamespace =
n.oid
380 ci.relname=$eindex AND
n.nspname=$eschema
381 AND attrelid = ct.oid
382 AND i.indkey[s.g] = attnum
383 AND i.indclass[s.g] = opcls.oid
384 AND pg_am.oid = opcls.opcmethod
389 foreach (
$res as $row ) {
402 public function indexUnique( $table, $index, $fname = __METHOD__ ) {
403 $flags = self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE;
404 $sql =
"SELECT indexname FROM pg_indexes WHERE tablename='{$table}'" .
405 " AND indexdef LIKE 'CREATE UNIQUE%(" .
413 return $res->numRows() > 0;
417 $table, $vars, $conds =
'', $fname = __METHOD__, $options = [], $join_conds = []
419 if ( is_string( $options ) ) {
420 $options = [ $options ];
430 if ( is_array( $options ) ) {
431 $forUpdateKey = array_search(
'FOR UPDATE', $options,
true );
432 if ( $forUpdateKey !==
false && $join_conds ) {
433 unset( $options[$forUpdateKey] );
434 $options[
'FOR UPDATE'] = [];
439 $alias = key( $toCheck );
440 $name = $toCheck[$alias];
441 unset( $toCheck[$alias] );
443 $hasAlias = !is_numeric( $alias );
444 if ( !$hasAlias && is_string( $name ) ) {
448 if ( !isset( $join_conds[$alias] ) ||
449 !preg_match(
'/^(?:LEFT|RIGHT|FULL)(?: OUTER)? JOIN$/i', $join_conds[$alias][0] )
451 if ( is_array( $name ) ) {
453 $toCheck = array_merge( $toCheck, $name );
462 if ( isset( $options[
'ORDER BY'] ) && $options[
'ORDER BY'] ==
'NULL' ) {
463 unset( $options[
'ORDER BY'] );
467 return parent::selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
471 return [
'INSERT INTO',
'ON CONFLICT DO NOTHING' ];
477 parent::doInsertNonConflicting( $table, $rows, $fname );
484 $tok = $this->
startAtomic(
"$fname (outer)", self::ATOMIC_CANCELABLE );
487 foreach ( $rows as $row ) {
489 $tempsql =
"INSERT INTO $encTable ($sqlColumns) VALUES $sqlTuples";
491 $this->
startAtomic(
"$fname (inner)", self::ATOMIC_CANCELABLE );
493 $this->
query( $tempsql, $fname, self::QUERY_CHANGE_ROWS );
500 if ( $e->errno !==
'23505' ) {
505 }
catch ( RuntimeException $e ) {
517 $options = array_diff( $options, [
'IGNORE' ] );
519 return parent::makeUpdateOptionsArray( $options );
546 array $insertOptions,
547 array $selectOptions,
550 if ( in_array(
'IGNORE', $insertOptions ) ) {
553 $destTable = $this->
tableName( $destTable );
557 array_values( $varMap ),
564 $sql =
"INSERT INTO $destTable (" . implode(
',', array_keys( $varMap ) ) .
') ' .
565 $selectSql .
' ON CONFLICT DO NOTHING';
567 $this->
query( $sql, $fname, self::QUERY_CHANGE_ROWS );
571 $destTable, $srcTable, $varMap, $conds, $fname,
572 $insertOptions, $selectOptions, $selectJoinConds
576 parent::doInsertSelectNative( $destTable, $srcTable, $varMap, $conds, $fname,
577 $insertOptions, $selectOptions, $selectJoinConds );
581 public function tableName( $name, $format =
'quoted' ) {
582 return parent::tableName( $name, $format );
593 return $this->keywordTableMap[$name] ?? $name;
602 return parent::tableName( $name, $format );
617 "SELECT currval('" . str_replace(
"'",
"''", $seqName ) .
"')",
619 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
628 $flags = self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE;
630 $sql =
"SELECT t.typname as ftype,a.atttypmod as size
631 FROM pg_class c, pg_attribute a, pg_type t
632 WHERE relname='$encTable' AND a.attrelid=c.oid AND
633 a.atttypid=t.oid and a.attname='$field'";
636 if ( $row->ftype ==
'varchar' ) {
637 $size = $row->size - 4;
646 return "$sql LIMIT $limit " . ( is_numeric( $offset ) ?
" OFFSET {$offset} " :
'' );
661 static $codes = [
'08000',
'08003',
'08006',
'08001',
'08004',
'57P01',
'57P03',
'53300' ];
663 return in_array( $errno, $codes,
true );
671 $oldName, $newName, $temporary =
false, $fname = __METHOD__
676 $temporary = $temporary ?
'TEMPORARY' :
'';
679 "CREATE $temporary TABLE $newNameE " .
680 "(LIKE $oldNameE INCLUDING DEFAULTS INCLUDING INDEXES)",
682 self::QUERY_PSEUDO_PERMANENT | self::QUERY_CHANGE_SCHEMA
689 'SELECT attname FROM pg_class c'
690 .
' JOIN pg_namespace n ON (n.oid = c.relnamespace)'
691 .
' JOIN pg_attribute a ON (a.attrelid = c.oid)'
692 .
' JOIN pg_attrdef d ON (c.oid=d.adrelid and a.attnum=d.adnum)'
693 .
' WHERE relkind = \'r\''
695 .
' AND relname = ' . $this->
addQuotes( $oldName )
696 .
' AND pg_get_expr(adbin, adrelid) LIKE \'nextval(%\'',
698 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
702 $field = $row->attname;
703 $newSeq =
"{$newName}_{$field}_seq";
708 "CREATE $temporary SEQUENCE $newSeqE OWNED BY $newNameE.$fieldE",
710 self::QUERY_CHANGE_SCHEMA
713 "ALTER TABLE $newNameE ALTER COLUMN $fieldE SET DEFAULT nextval({$newSeqQ}::regclass)",
715 self::QUERY_CHANGE_SCHEMA
724 $sql =
"TRUNCATE TABLE " . implode(
',', $encTables ) .
" RESTART IDENTITY";
725 $this->
query( $sql, $fname, self::QUERY_CHANGE_SCHEMA );
734 public function listTables( $prefix =
'', $fname = __METHOD__ ) {
735 $eschemas = implode(
',', array_map( [ $this,
'addQuotes' ], $this->
getCoreSchemas() ) );
736 $result = $this->
query(
737 "SELECT DISTINCT tablename FROM pg_tables WHERE schemaname IN ($eschemas)",
739 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
743 foreach ( $result as $table ) {
744 $vars = get_object_vars( $table );
745 $table = array_pop( $vars );
746 if ( $prefix ==
'' || strpos( $table, $prefix ) === 0 ) {
747 $endArray[] = $table;
755 $ct =
new ConvertibleTimestamp( $ts );
757 return $ct->getTimestamp( TS_POSTGRES );
778 private function pg_array_parse( $text, &$output, $limit =
false, $offset = 1 ) {
779 if ( $limit ===
false ) {
780 $limit = strlen( $text ) - 1;
783 if ( $text ==
'{}' ) {
787 if ( $text[$offset] !=
'{' ) {
788 preg_match(
"/(\\{?\"([^\"\\\\]|\\\\.)*\"|[^,{}]+)+([,}]+)/",
789 $text, $match, 0, $offset );
790 $offset += strlen( $match[0] );
791 $output[] = ( $match[1][0] !=
'"'
793 : stripcslashes( substr( $match[1], 1, -1 ) ) );
794 if ( $match[3] ==
'},' ) {
798 $offset = $this->
pg_array_parse( $text, $output, $limit, $offset + 1 );
800 }
while ( $limit > $offset );
810 return '[{{int:version-db-postgres-url}} PostgreSQL]';
822 "SELECT current_schema()",
824 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
843 "SELECT current_schemas(false)",
845 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
868 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
874 return explode(
",", $row[0] );
886 "SET search_path = " . implode(
", ", $search_path ),
888 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_TRX
912 __METHOD__ .
": a transaction is currently active"
917 if ( in_array( $desiredSchema, $this->
getSchemas() ) ) {
918 $this->coreSchema = $desiredSchema;
919 $this->queryLogger->debug(
920 "Schema \"" . $desiredSchema .
"\" already in the search path\n" );
926 $this->coreSchema = $desiredSchema;
927 $this->queryLogger->debug(
928 "Schema \"" . $desiredSchema .
"\" added to the search path\n" );
932 $this->queryLogger->debug(
933 "Schema \"" . $desiredSchema .
"\" not found, using current \"" .
934 $this->coreSchema .
"\"\n" );
955 if ( $this->tempSchema ) {
960 "SELECT nspname FROM pg_catalog.pg_namespace n WHERE n.oid = pg_my_temp_schema()",
962 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
966 $this->tempSchema = $row->nspname;
974 if ( !isset( $this->numericVersion ) ) {
976 $versionInfo = pg_version(
$conn );
977 if ( version_compare( $versionInfo[
'client'],
'7.4.0',
'lt' ) ) {
979 $this->numericVersion =
'7.3 or earlier';
980 } elseif ( isset( $versionInfo[
'server'] ) ) {
982 $this->numericVersion = $versionInfo[
'server'];
985 $this->numericVersion = pg_parameter_status(
$conn,
'server_version' );
1001 if ( !is_array( $types ) ) {
1002 $types = [ $types ];
1004 if ( $schema ===
false ) {
1007 $schemas = [ $schema ];
1011 foreach ( $schemas as $schema ) {
1013 $sql =
"SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "
1014 .
"WHERE c.relnamespace = n.oid AND c.relname = $etable AND n.nspname = $eschema "
1015 .
"AND c.relkind IN ('" . implode(
"','", $types ) .
"')";
1019 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
1036 public function tableExists( $table, $fname = __METHOD__, $schema =
false ) {
1046 SELECT 1 FROM pg_class, pg_namespace, pg_trigger
1047 WHERE relnamespace=pg_namespace.oid AND relkind=
'r'
1048 AND tgrelid=pg_class.oid
1049 AND nspname=%s AND relname=%s AND tgname=%s
1060 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
1071 $exists = $this->
selectField(
'pg_rules',
'rulename',
1073 'rulename' => $rule,
1074 'tablename' => $table,
1080 return $exists === $rule;
1085 $sql = sprintf(
"SELECT 1 FROM information_schema.table_constraints " .
1086 "WHERE constraint_schema = %s AND table_name = %s AND constraint_name = %s",
1094 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
1109 if ( !strlen( $schema ) ) {
1114 "SELECT 1 FROM pg_catalog.pg_namespace " .
1115 "WHERE nspname = " . $this->
addQuotes( $schema ) .
" LIMIT 1",
1117 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
1130 "SELECT 1 FROM pg_catalog.pg_roles " .
1131 "WHERE rolname = " . $this->
addQuotes( $roleName ) .
" LIMIT 1",
1133 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
1159 return pg_field_type(
$res->getInternalResult(), $index );
1169 } elseif ( $b instanceof
Blob ) {
1173 return pg_unescape_bytea( $b );
1184 if (
$s ===
null ) {
1186 } elseif ( is_bool(
$s ) ) {
1187 return (
string)intval(
$s );
1188 } elseif ( is_int(
$s ) ) {
1190 } elseif (
$s instanceof
Blob ) {
1194 $s = pg_escape_bytea(
$conn,
$s->fetch() );
1201 return "'" . pg_escape_string(
$conn, (
string)
$s ) .
"'";
1205 $preLimitTail = $postLimitTail =
'';
1206 $startOpts = $useIndex = $ignoreIndex =
'';
1209 foreach ( $options as $key => $option ) {
1210 if ( is_numeric( $key ) ) {
1211 $noKeyOptions[$option] =
true;
1219 if ( isset( $options[
'FOR UPDATE'] ) ) {
1220 $postLimitTail .=
' FOR UPDATE OF ' .
1221 implode(
', ', array_map( [ $this,
'tableName' ], $options[
'FOR UPDATE'] ) );
1222 } elseif ( isset( $noKeyOptions[
'FOR UPDATE'] ) ) {
1223 $postLimitTail .=
' FOR UPDATE';
1226 if ( isset( $noKeyOptions[
'DISTINCT'] ) || isset( $noKeyOptions[
'DISTINCTROW'] ) ) {
1227 $startOpts .=
'DISTINCT';
1230 return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
1234 return implode(
' || ', $stringList );
1238 $delim, $table, $field, $conds =
'', $join_conds = []
1240 $fld =
"array_to_string(array_agg($field)," . $this->
addQuotes( $delim ) .
')';
1242 return '(' . $this->
selectSQLText( $table, $fld, $conds,
null, [], $join_conds ) .
')';
1246 return $field .
'::text';
1250 # Allow dollar quoting for function declarations
1251 if ( substr( $newLine, 0, 4 ) ==
'$mw$' ) {
1252 if ( $this->delimiter ) {
1253 $this->delimiter =
false;
1255 $this->delimiter =
';';
1259 return parent::streamStatementEnd( $sql, $newLine );
1264 foreach ( $write as $table ) {
1265 $tablesWrite[] = $this->
tableName( $table );
1268 foreach ( $read as $table ) {
1269 $tablesRead[] = $this->
tableName( $table );
1273 if ( $tablesWrite ) {
1275 'LOCK TABLE ONLY ' . implode(
',', $tablesWrite ) .
' IN EXCLUSIVE MODE',
1277 self::QUERY_CHANGE_ROWS
1280 if ( $tablesRead ) {
1282 'LOCK TABLE ONLY ' . implode(
',', $tablesRead ) .
' IN SHARE MODE',
1284 self::QUERY_CHANGE_ROWS
1296 "SELECT (CASE(pg_try_advisory_lock($key))
1297 WHEN 'f' THEN 'f' ELSE pg_advisory_unlock($key) END) AS unlocked",
1299 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
1303 return ( $row->unlocked ===
't' );
1306 public function doLock(
string $lockName,
string $method,
int $timeout ) {
1311 $loop =
new WaitConditionLoop(
1312 function () use ( $lockName, $key, $timeout, $method, &$acquired ) {
1314 "SELECT (CASE WHEN pg_try_advisory_lock($key) " .
1315 "THEN EXTRACT(epoch from clock_timestamp()) " .
1319 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_ROWS
1323 if ( $row->acquired !==
null ) {
1324 $acquired = (float)$row->acquired;
1326 return WaitConditionLoop::CONDITION_REACHED;
1329 return WaitConditionLoop::CONDITION_CONTINUE;
1338 public function doUnlock(
string $lockName,
string $method ) {
1342 $result = $this->
query(
1343 "SELECT pg_advisory_unlock($key) AS released",
1345 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_ROWS
1349 return ( $row->released ===
't' );
1354 "SHOW default_transaction_read_only",
1356 self::QUERY_IGNORE_DBO_TRX | self::QUERY_CHANGE_NONE
1360 return $row ? ( strtolower( $row->default_transaction_read_only ) ===
'on' ) :
false;
1364 return [ self::ATTR_SCHEMAS_AS_TABLE_GROUPS =>
true ];
1372 return \Wikimedia\base_convert( substr( sha1( $lockName ), 0, 15 ), 16, 10 );
1379class_alias( DatabasePostgres::class,
'DatabasePostgres' );
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
Class to handle database/schema/prefix specifications for IDatabase.
getCoreSchemas()
Return schema names for temporary tables and core application tables.
buildConcat( $stringList)
Build a concatenation list to feed into a SQL query.stringto override
buildStringCast( $field)
string 1.28to override
determineCoreSchema( $desiredSchema)
Determine default schema for the current application Adjust this session schema search path if desire...
duplicateTableStructure( $oldName, $newName, $temporary=false, $fname=__METHOD__)
Creates a new table with structure copied from existing table.Note that unlike most database abstract...
fieldInfo( $table, $field)
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...
doLock(string $lockName, string $method, int $timeout)
insertId()
Get the inserted value of an auto-increment row.
indexAttributes( $index, $schema=false)
databasesAreIndependent()
Returns true if DBs are assumed to be on potentially different servers.In systems like mysql/mariadb,...
setSearchPath( $search_path)
Update search_path, values should already be sanitized Values may contain magic keywords like "$user"...
relationSchemaQualifier()
doUnlock(string $lockName, string $method)
pg_array_parse( $text, &$output, $limit=false, $offset=1)
Posted by cc[plus]php[at]c2se[dot]com on 25-Mar-2009 09:12 to https://www.php.net/manual/en/ref....
null string[] $keywordTableMap
Map of (reserved table name => alternate table name)
streamStatementEnd(&$sql, &$newLine)
Called by sourceStream() to check if we've reached a statement end.
doLockIsFree(string $lockName, string $method)
implicitOrderby()
Returns true if this database does an implicit order by when the column has an index For example: SEL...
nextSequenceValue( $seqName)
Deprecated method, calls should be removed.
doSelectDomain(DatabaseDomain $domain)
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by ConvertibleTimestamp to the format used for ins...
roleExists( $roleName)
Returns true if a given role (i.e.
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...
makeUpdateOptionsArray( $options)
Make UPDATE options array for Database::makeUpdateOptions.
getSchemas()
Return list of schemas which are accessible without schema name This is list does not contain magic k...
indexInfo( $table, $index, $fname=__METHOD__)
Get information about an index into an object.
schemaExists( $schema)
Query whether a given schema exists.
estimateRowCount( $table, $var=' *', $conds='', $fname=__METHOD__, $options=[], $join_conds=[])
Estimate rows in dataset Returns estimated count, based on EXPLAIN output This is not necessarily an ...
lastError()
Get a description of the last error.
wasConnectionError( $errno)
Do not use this method outside of Database/DBError classes.
addQuotes( $s)
Escape and quote a raw value string for use in a SQL query.stringto override
wasKnownStatementRollbackError()
limitResult( $sql, $limit, $offset=false)
Construct a LIMIT query with optional offset.The SQL should be adjusted so that only the first $limit...
sequenceExists( $sequence, $schema=false)
wasDeadlock()
Determines if the last failure was due to a deadlock.Note that during a deadlock, the prior transacti...
__construct(array $params)
doTruncate(array $tables, $fname)
makeInsertNonConflictingVerbAndOptions()
doInsertNonConflicting( $table, array $rows, $fname)
currentSequenceValue( $seqName)
Return the current value of a sequence.
lastErrno()
Get the last error number.
getCoreSchema()
Return schema name for core application tables.
strencode( $s)
Wrapper for addslashes()
isTransactableQuery( $sql)
Determine whether a SQL statement is sensitive to isolation level.
wasLockTimeout()
Determines if the last failure was due to a lock timeout.Note that during a lock wait timeout,...
triggerExists( $table, $trigger)
indexUnique( $table, $index, $fname=__METHOD__)
Determines if a given index is unique.boolto override
open( $server, $user, $password, $db, $schema, $tablePrefix)
Open a new connection to the database (closing any existing one)
float string $numericVersion
getServerVersion()
A string describing the current software version, like from mysql_get_server_info()
fieldType( $res, $index)
pg_field_type() wrapper
doLockTables(array $read, array $write, $method)
Helper function for lockTables() that handles the actual table locking.
resource null $lastResultHandle
textFieldSize( $table, $field)
Returns the size of a text field, or -1 for "unlimited".intto override
makeConnectionString( $vars)
getCurrentSchema()
Return current schema (executes SELECT current_schema()) Needs transaction.
getSearchPath()
Return search patch for schemas This is different from getSchemas() since it contain magic keywords (...
bigintFromLockName( $lockName)
tableExists( $table, $fname=__METHOD__, $schema=false)
For backward compatibility, this function checks both tables and views.
ruleExists( $table, $rule)
remappedTableName( $name)
decodeBlob( $b)
Some DBMSs return a special placeholder object representing blob fields in result objects....
relationExists( $table, $types, $schema=false)
Query whether a given relation exists (in the given schema, or the default mw one if not given)
encodeBlob( $b)
Some DBMSs have a special format for inserting into blob fields, they don't allow simple quoted strin...
realTableName( $name, $format='quoted')
closeConnection()
Closes underlying database connection.
constraintExists( $table, $constraint)
getType()
Get the RDBMS type of the server (e.g.
listTables( $prefix='', $fname=__METHOD__)
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...
getSoftwareLink()
Returns a wikitext style link to the DB's website (e.g.
aggregateValue( $valuedata, $valuename='value')
Return aggregated value alias.array|string Since 1.33 to override
doInsertSelectNative( $destTable, $srcTable, array $varMap, $conds, $fname, array $insertOptions, array $selectOptions, $selectJoinConds)
INSERT SELECT wrapper $varMap must be an associative array of the form [ 'dest1' => 'source1',...
serverIsReadOnly()
bool Whether the DB is marked as read-only server-side query} 1.28to override
tableName( $name, $format='quoted')
Format a table name ready for use in constructing an SQL query.This does two important things: it quo...
static fromText(DatabasePostgres $db, $table, $field)
foreach( $mmfl['setupFiles'] as $fileName) if($queue) if(empty( $mmfl['quiet'])) $s