MediaWiki  1.31.0
DatabasePostgres.php
Go to the documentation of this file.
1 <?php
23 namespace Wikimedia\Rdbms;
24 
25 use Wikimedia\Timestamp\ConvertibleTimestamp;
26 use Wikimedia\WaitConditionLoop;
28 use Exception;
29 
33 class DatabasePostgres extends Database {
35  protected $port;
36 
38  protected $lastResultHandle = null;
39 
41  private $numericVersion = null;
43  private $connectString;
45  private $coreSchema;
47  private $tempSchema;
49  private $keywordTableMap = [];
50 
56  public function __construct( array $params ) {
57  $this->port = isset( $params['port'] ) ? $params['port'] : false;
58  $this->keywordTableMap = isset( $params['keywordTableMap'] )
59  ? $params['keywordTableMap']
60  : [];
61 
62  parent::__construct( $params );
63  }
64 
65  public function getType() {
66  return 'postgres';
67  }
68 
69  public function implicitGroupby() {
70  return false;
71  }
72 
73  public function implicitOrderby() {
74  return false;
75  }
76 
77  public function hasConstraint( $name ) {
78  foreach ( $this->getCoreSchemas() as $schema ) {
79  $sql = "SELECT 1 FROM pg_catalog.pg_constraint c, pg_catalog.pg_namespace n " .
80  "WHERE c.connamespace = n.oid AND conname = " .
81  $this->addQuotes( $name ) . " AND n.nspname = " .
82  $this->addQuotes( $schema );
83  $res = $this->doQuery( $sql );
84  if ( $res && $this->numRows( $res ) ) {
85  return true;
86  }
87  }
88  return false;
89  }
90 
91  public function open( $server, $user, $password, $dbName ) {
92  # Test for Postgres support, to avoid suppressed fatal error
93  if ( !function_exists( 'pg_connect' ) ) {
94  throw new DBConnectionError(
95  $this,
96  "Postgres functions missing, have you compiled PHP with the --with-pgsql\n" .
97  "option? (Note: if you recently installed PHP, you may need to restart your\n" .
98  "webserver and database)\n"
99  );
100  }
101 
102  $this->server = $server;
103  $this->user = $user;
104  $this->password = $password;
105  $this->dbName = $dbName;
106 
107  $connectVars = [
108  // pg_connect() user $user as the default database. Since a database is *required*,
109  // at least pick a "don't care" database that is more likely to exist. This case
110  // arrises when LoadBalancer::getConnection( $i, [], '' ) is used.
111  'dbname' => strlen( $dbName ) ? $dbName : 'postgres',
112  'user' => $user,
113  'password' => $password
114  ];
115  if ( $server != false && $server != '' ) {
116  $connectVars['host'] = $server;
117  }
118  if ( (int)$this->port > 0 ) {
119  $connectVars['port'] = (int)$this->port;
120  }
121  if ( $this->flags & self::DBO_SSL ) {
122  $connectVars['sslmode'] = 1;
123  }
124 
125  $this->connectString = $this->makeConnectionString( $connectVars );
126  $this->close();
127  $this->installErrorHandler();
128 
129  try {
130  // Use new connections to let LoadBalancer/LBFactory handle reuse
131  $this->conn = pg_connect( $this->connectString, PGSQL_CONNECT_FORCE_NEW );
132  } catch ( Exception $ex ) {
133  $this->restoreErrorHandler();
134  throw $ex;
135  }
136 
137  $phpError = $this->restoreErrorHandler();
138 
139  if ( !$this->conn ) {
140  $this->queryLogger->debug(
141  "DB connection error\n" .
142  "Server: $server, Database: $dbName, User: $user, Password: " .
143  substr( $password, 0, 3 ) . "...\n"
144  );
145  $this->queryLogger->debug( $this->lastError() . "\n" );
146  throw new DBConnectionError( $this, str_replace( "\n", ' ', $phpError ) );
147  }
148 
149  $this->opened = true;
150 
151  # If called from the command-line (e.g. importDump), only show errors
152  if ( $this->cliMode ) {
153  $this->doQuery( "SET client_min_messages = 'ERROR'" );
154  }
155 
156  $this->query( "SET client_encoding='UTF8'", __METHOD__ );
157  $this->query( "SET datestyle = 'ISO, YMD'", __METHOD__ );
158  $this->query( "SET timezone = 'GMT'", __METHOD__ );
159  $this->query( "SET standard_conforming_strings = on", __METHOD__ );
160  $this->query( "SET bytea_output = 'escape'", __METHOD__ ); // PHP bug 53127
161 
162  $this->determineCoreSchema( $this->schema );
163  // The schema to be used is now in the search path; no need for explicit qualification
164  $this->schema = '';
165 
166  return $this->conn;
167  }
168 
169  public function databasesAreIndependent() {
170  return true;
171  }
172 
180  public function selectDB( $db ) {
181  if ( $this->dbName !== $db ) {
182  return (bool)$this->open( $this->server, $this->user, $this->password, $db );
183  } else {
184  return true;
185  }
186  }
187 
192  private function makeConnectionString( $vars ) {
193  $s = '';
194  foreach ( $vars as $name => $value ) {
195  $s .= "$name='" . str_replace( "'", "\\'", $value ) . "' ";
196  }
197 
198  return $s;
199  }
200 
201  protected function closeConnection() {
202  return $this->conn ? pg_close( $this->conn ) : true;
203  }
204 
205  protected function isTransactableQuery( $sql ) {
206  return parent::isTransactableQuery( $sql ) &&
207  !preg_match( '/^SELECT\s+pg_(try_|)advisory_\w+\(/', $sql );
208  }
209 
210  public function doQuery( $sql ) {
211  $conn = $this->getBindingHandle();
212 
213  $sql = mb_convert_encoding( $sql, 'UTF-8' );
214  // Clear previously left over PQresult
215  while ( $res = pg_get_result( $conn ) ) {
216  pg_free_result( $res );
217  }
218  if ( pg_send_query( $conn, $sql ) === false ) {
219  throw new DBUnexpectedError( $this, "Unable to post new query to PostgreSQL\n" );
220  }
221  $this->lastResultHandle = pg_get_result( $conn );
222  if ( pg_result_error( $this->lastResultHandle ) ) {
223  return false;
224  }
225 
227  }
228 
229  protected function dumpError() {
230  $diags = [
231  PGSQL_DIAG_SEVERITY,
232  PGSQL_DIAG_SQLSTATE,
233  PGSQL_DIAG_MESSAGE_PRIMARY,
234  PGSQL_DIAG_MESSAGE_DETAIL,
235  PGSQL_DIAG_MESSAGE_HINT,
236  PGSQL_DIAG_STATEMENT_POSITION,
237  PGSQL_DIAG_INTERNAL_POSITION,
238  PGSQL_DIAG_INTERNAL_QUERY,
239  PGSQL_DIAG_CONTEXT,
240  PGSQL_DIAG_SOURCE_FILE,
241  PGSQL_DIAG_SOURCE_LINE,
242  PGSQL_DIAG_SOURCE_FUNCTION
243  ];
244  foreach ( $diags as $d ) {
245  $this->queryLogger->debug( sprintf( "PgSQL ERROR(%d): %s\n",
246  $d, pg_result_error_field( $this->lastResultHandle, $d ) ) );
247  }
248  }
249 
250  public function freeResult( $res ) {
251  if ( $res instanceof ResultWrapper ) {
252  $res = $res->result;
253  }
254  Wikimedia\suppressWarnings();
255  $ok = pg_free_result( $res );
256  Wikimedia\restoreWarnings();
257  if ( !$ok ) {
258  throw new DBUnexpectedError( $this, "Unable to free Postgres result\n" );
259  }
260  }
261 
262  public function fetchObject( $res ) {
263  if ( $res instanceof ResultWrapper ) {
264  $res = $res->result;
265  }
266  Wikimedia\suppressWarnings();
267  $row = pg_fetch_object( $res );
268  Wikimedia\restoreWarnings();
269  # @todo FIXME: HACK HACK HACK HACK debug
270 
271  # @todo hashar: not sure if the following test really trigger if the object
272  # fetching failed.
273  $conn = $this->getBindingHandle();
274  if ( pg_last_error( $conn ) ) {
275  throw new DBUnexpectedError(
276  $this,
277  'SQL error: ' . htmlspecialchars( pg_last_error( $conn ) )
278  );
279  }
280 
281  return $row;
282  }
283 
284  public function fetchRow( $res ) {
285  if ( $res instanceof ResultWrapper ) {
286  $res = $res->result;
287  }
288  Wikimedia\suppressWarnings();
289  $row = pg_fetch_array( $res );
290  Wikimedia\restoreWarnings();
291 
292  $conn = $this->getBindingHandle();
293  if ( pg_last_error( $conn ) ) {
294  throw new DBUnexpectedError(
295  $this,
296  'SQL error: ' . htmlspecialchars( pg_last_error( $conn ) )
297  );
298  }
299 
300  return $row;
301  }
302 
303  public function numRows( $res ) {
304  if ( $res instanceof ResultWrapper ) {
305  $res = $res->result;
306  }
307  Wikimedia\suppressWarnings();
308  $n = pg_num_rows( $res );
309  Wikimedia\restoreWarnings();
310 
311  $conn = $this->getBindingHandle();
312  if ( pg_last_error( $conn ) ) {
313  throw new DBUnexpectedError(
314  $this,
315  'SQL error: ' . htmlspecialchars( pg_last_error( $conn ) )
316  );
317  }
318 
319  return $n;
320  }
321 
322  public function numFields( $res ) {
323  if ( $res instanceof ResultWrapper ) {
324  $res = $res->result;
325  }
326 
327  return pg_num_fields( $res );
328  }
329 
330  public function fieldName( $res, $n ) {
331  if ( $res instanceof ResultWrapper ) {
332  $res = $res->result;
333  }
334 
335  return pg_field_name( $res, $n );
336  }
337 
338  public function insertId() {
339  $res = $this->query( "SELECT lastval()" );
340  $row = $this->fetchRow( $res );
341  return is_null( $row[0] ) ? null : (int)$row[0];
342  }
343 
344  public function dataSeek( $res, $row ) {
345  if ( $res instanceof ResultWrapper ) {
346  $res = $res->result;
347  }
348 
349  return pg_result_seek( $res, $row );
350  }
351 
352  public function lastError() {
353  if ( $this->conn ) {
354  if ( $this->lastResultHandle ) {
355  return pg_result_error( $this->lastResultHandle );
356  } else {
357  return pg_last_error();
358  }
359  }
360 
361  return $this->getLastPHPError() ?: 'No database connection';
362  }
363 
364  public function lastErrno() {
365  if ( $this->lastResultHandle ) {
366  return pg_result_error_field( $this->lastResultHandle, PGSQL_DIAG_SQLSTATE );
367  } else {
368  return false;
369  }
370  }
371 
372  protected function fetchAffectedRowCount() {
373  if ( !$this->lastResultHandle ) {
374  return 0;
375  }
376 
377  return pg_affected_rows( $this->lastResultHandle );
378  }
379 
395  public function estimateRowCount( $table, $var = '*', $conds = '',
396  $fname = __METHOD__, $options = [], $join_conds = []
397  ) {
398  $conds = $this->normalizeConditions( $conds, $fname );
399  $column = $this->extractSingleFieldFromList( $var );
400  if ( is_string( $column ) && !in_array( $column, [ '*', '1' ] ) ) {
401  $conds[] = "$column IS NOT NULL";
402  }
403 
404  $options['EXPLAIN'] = true;
405  $res = $this->select( $table, $var, $conds, $fname, $options, $join_conds );
406  $rows = -1;
407  if ( $res ) {
408  $row = $this->fetchRow( $res );
409  $count = [];
410  if ( preg_match( '/rows=(\d+)/', $row[0], $count ) ) {
411  $rows = (int)$count[1];
412  }
413  }
414 
415  return $rows;
416  }
417 
418  public function indexInfo( $table, $index, $fname = __METHOD__ ) {
419  $sql = "SELECT indexname FROM pg_indexes WHERE tablename='$table'";
420  $res = $this->query( $sql, $fname );
421  if ( !$res ) {
422  return null;
423  }
424  foreach ( $res as $row ) {
425  if ( $row->indexname == $this->indexName( $index ) ) {
426  return $row;
427  }
428  }
429 
430  return false;
431  }
432 
433  public function indexAttributes( $index, $schema = false ) {
434  if ( $schema === false ) {
435  $schemas = $this->getCoreSchemas();
436  } else {
437  $schemas = [ $schema ];
438  }
439 
440  $eindex = $this->addQuotes( $index );
441 
442  foreach ( $schemas as $schema ) {
443  $eschema = $this->addQuotes( $schema );
444  /*
445  * A subquery would be not needed if we didn't care about the order
446  * of attributes, but we do
447  */
448  $sql = <<<__INDEXATTR__
449 
450  SELECT opcname,
451  attname,
452  i.indoption[s.g] as option,
453  pg_am.amname
454  FROM
455  (SELECT generate_series(array_lower(isub.indkey,1), array_upper(isub.indkey,1)) AS g
456  FROM
457  pg_index isub
458  JOIN pg_class cis
459  ON cis.oid=isub.indexrelid
460  JOIN pg_namespace ns
461  ON cis.relnamespace = ns.oid
462  WHERE cis.relname=$eindex AND ns.nspname=$eschema) AS s,
463  pg_attribute,
464  pg_opclass opcls,
465  pg_am,
466  pg_class ci
467  JOIN pg_index i
468  ON ci.oid=i.indexrelid
469  JOIN pg_class ct
470  ON ct.oid = i.indrelid
471  JOIN pg_namespace n
472  ON ci.relnamespace = n.oid
473  WHERE
474  ci.relname=$eindex AND n.nspname=$eschema
475  AND attrelid = ct.oid
476  AND i.indkey[s.g] = attnum
477  AND i.indclass[s.g] = opcls.oid
478  AND pg_am.oid = opcls.opcmethod
479 __INDEXATTR__;
480  $res = $this->query( $sql, __METHOD__ );
481  $a = [];
482  if ( $res ) {
483  foreach ( $res as $row ) {
484  $a[] = [
485  $row->attname,
486  $row->opcname,
487  $row->amname,
488  $row->option ];
489  }
490  return $a;
491  }
492  }
493  return null;
494  }
495 
496  public function indexUnique( $table, $index, $fname = __METHOD__ ) {
497  $sql = "SELECT indexname FROM pg_indexes WHERE tablename='{$table}'" .
498  " AND indexdef LIKE 'CREATE UNIQUE%(" .
499  $this->strencode( $this->indexName( $index ) ) .
500  ")'";
501  $res = $this->query( $sql, $fname );
502  if ( !$res ) {
503  return null;
504  }
505 
506  return $res->numRows() > 0;
507  }
508 
509  public function selectSQLText(
510  $table, $vars, $conds = '', $fname = __METHOD__, $options = [], $join_conds = []
511  ) {
512  if ( is_string( $options ) ) {
513  $options = [ $options ];
514  }
515 
516  // Change the FOR UPDATE option as necessary based on the join conditions. Then pass
517  // to the parent function to get the actual SQL text.
518  // In Postgres when using FOR UPDATE, only the main table and tables that are inner joined
519  // can be locked. That means tables in an outer join cannot be FOR UPDATE locked. Trying to
520  // do so causes a DB error. This wrapper checks which tables can be locked and adjusts it
521  // accordingly.
522  // MySQL uses "ORDER BY NULL" as an optimization hint, but that is illegal in PostgreSQL.
523  if ( is_array( $options ) ) {
524  $forUpdateKey = array_search( 'FOR UPDATE', $options, true );
525  if ( $forUpdateKey !== false && $join_conds ) {
526  unset( $options[$forUpdateKey] );
527  $options['FOR UPDATE'] = [];
528 
529  $toCheck = $table;
530  reset( $toCheck );
531  while ( $toCheck ) {
532  $alias = key( $toCheck );
533  $name = $toCheck[$alias];
534  unset( $toCheck[$alias] );
535 
536  $hasAlias = !is_numeric( $alias );
537  if ( !$hasAlias && is_string( $name ) ) {
538  $alias = $name;
539  }
540 
541  if ( !isset( $join_conds[$alias] ) ||
542  !preg_match( '/^(?:LEFT|RIGHT|FULL)(?: OUTER)? JOIN$/i', $join_conds[$alias][0] )
543  ) {
544  if ( is_array( $name ) ) {
545  // It's a parenthesized group, process all the tables inside the group.
546  $toCheck = array_merge( $toCheck, $name );
547  } else {
548  // Quote alias names so $this->tableName() won't mangle them
549  $options['FOR UPDATE'][] = $hasAlias ? $this->addIdentifierQuotes( $alias ) : $alias;
550  }
551  }
552  }
553  }
554 
555  if ( isset( $options['ORDER BY'] ) && $options['ORDER BY'] == 'NULL' ) {
556  unset( $options['ORDER BY'] );
557  }
558  }
559 
560  return parent::selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
561  }
562 
564  public function insert( $table, $args, $fname = __METHOD__, $options = [] ) {
565  if ( !count( $args ) ) {
566  return true;
567  }
568 
569  $table = $this->tableName( $table );
570  if ( !isset( $this->numericVersion ) ) {
571  $this->getServerVersion();
572  }
573 
574  if ( !is_array( $options ) ) {
575  $options = [ $options ];
576  }
577 
578  if ( isset( $args[0] ) && is_array( $args[0] ) ) {
579  $rows = $args;
580  $keys = array_keys( $args[0] );
581  } else {
582  $rows = [ $args ];
583  $keys = array_keys( $args );
584  }
585 
586  $ignore = in_array( 'IGNORE', $options );
587 
588  $sql = "INSERT INTO $table (" . implode( ',', $keys ) . ') VALUES ';
589 
590  if ( $this->numericVersion >= 9.5 || !$ignore ) {
591  // No IGNORE or our PG has "ON CONFLICT DO NOTHING"
592  $first = true;
593  foreach ( $rows as $row ) {
594  if ( $first ) {
595  $first = false;
596  } else {
597  $sql .= ',';
598  }
599  $sql .= '(' . $this->makeList( $row ) . ')';
600  }
601  if ( $ignore ) {
602  $sql .= ' ON CONFLICT DO NOTHING';
603  }
604  $this->query( $sql, $fname );
605  } else {
606  // Emulate IGNORE by doing each row individually, with savepoints
607  // to roll back as necessary.
608  $numrowsinserted = 0;
609 
610  $tok = $this->startAtomic( "$fname (outer)", self::ATOMIC_CANCELABLE );
611  try {
612  foreach ( $rows as $row ) {
613  $tempsql = $sql;
614  $tempsql .= '(' . $this->makeList( $row ) . ')';
615 
616  $this->startAtomic( "$fname (inner)", self::ATOMIC_CANCELABLE );
617  try {
618  $this->query( $tempsql, $fname );
619  $this->endAtomic( "$fname (inner)" );
620  $numrowsinserted++;
621  } catch ( DBQueryError $e ) {
622  $this->cancelAtomic( "$fname (inner)" );
623  // Our IGNORE is supposed to ignore duplicate key errors, but not others.
624  // (even though MySQL's version apparently ignores all errors)
625  if ( $e->errno !== '23505' ) {
626  throw $e;
627  }
628  }
629  }
630  } catch ( Exception $e ) {
631  $this->cancelAtomic( "$fname (outer)", $tok );
632  throw $e;
633  }
634  $this->endAtomic( "$fname (outer)" );
635 
636  // Set the affected row count for the whole operation
637  $this->affectedRowCount = $numrowsinserted;
638  }
639 
640  return true;
641  }
642 
662  public function nativeInsertSelect(
663  $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
664  $insertOptions = [], $selectOptions = [], $selectJoinConds = []
665  ) {
666  if ( !is_array( $insertOptions ) ) {
667  $insertOptions = [ $insertOptions ];
668  }
669 
670  if ( in_array( 'IGNORE', $insertOptions ) ) {
671  if ( $this->getServerVersion() >= 9.5 ) {
672  // Use ON CONFLICT DO NOTHING if we have it for IGNORE
673  $destTable = $this->tableName( $destTable );
674 
675  $selectSql = $this->selectSQLText(
676  $srcTable,
677  array_values( $varMap ),
678  $conds,
679  $fname,
680  $selectOptions,
681  $selectJoinConds
682  );
683 
684  $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ') ' .
685  $selectSql . ' ON CONFLICT DO NOTHING';
686 
687  return $this->query( $sql, $fname );
688  } else {
689  // IGNORE and we don't have ON CONFLICT DO NOTHING, so just use the non-native version
690  return $this->nonNativeInsertSelect(
691  $destTable, $srcTable, $varMap, $conds, $fname,
692  $insertOptions, $selectOptions, $selectJoinConds
693  );
694  }
695  }
696 
697  return parent::nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname,
698  $insertOptions, $selectOptions, $selectJoinConds );
699  }
700 
701  public function tableName( $name, $format = 'quoted' ) {
702  // Replace reserved words with better ones
703  $name = $this->remappedTableName( $name );
704 
705  return parent::tableName( $name, $format );
706  }
707 
712  public function remappedTableName( $name ) {
713  return isset( $this->keywordTableMap[$name] ) ? $this->keywordTableMap[$name] : $name;
714  }
715 
721  public function realTableName( $name, $format = 'quoted' ) {
722  return parent::tableName( $name, $format );
723  }
724 
725  public function nextSequenceValue( $seqName ) {
726  return new NextSequenceValue;
727  }
728 
735  public function currentSequenceValue( $seqName ) {
736  $safeseq = str_replace( "'", "''", $seqName );
737  $res = $this->query( "SELECT currval('$safeseq')" );
738  $row = $this->fetchRow( $res );
739  $currval = $row[0];
740 
741  return $currval;
742  }
743 
744  public function textFieldSize( $table, $field ) {
745  $table = $this->tableName( $table );
746  $sql = "SELECT t.typname as ftype,a.atttypmod as size
747  FROM pg_class c, pg_attribute a, pg_type t
748  WHERE relname='$table' AND a.attrelid=c.oid AND
749  a.atttypid=t.oid and a.attname='$field'";
750  $res = $this->query( $sql );
751  $row = $this->fetchObject( $res );
752  if ( $row->ftype == 'varchar' ) {
753  $size = $row->size - 4;
754  } else {
755  $size = $row->size;
756  }
757 
758  return $size;
759  }
760 
761  public function limitResult( $sql, $limit, $offset = false ) {
762  return "$sql LIMIT $limit " . ( is_numeric( $offset ) ? " OFFSET {$offset} " : '' );
763  }
764 
765  public function wasDeadlock() {
766  // https://www.postgresql.org/docs/9.2/static/errcodes-appendix.html
767  return $this->lastErrno() === '40P01';
768  }
769 
770  public function wasLockTimeout() {
771  // https://www.postgresql.org/docs/9.2/static/errcodes-appendix.html
772  return $this->lastErrno() === '55P03';
773  }
774 
775  public function wasConnectionError( $errno ) {
776  // https://www.postgresql.org/docs/9.2/static/errcodes-appendix.html
777  static $codes = [ '08000', '08003', '08006', '08001', '08004', '57P01', '57P03', '53300' ];
778 
779  return in_array( $errno, $codes, true );
780  }
781 
782  protected function wasKnownStatementRollbackError() {
783  return false; // transaction has to be rolled-back from error state
784  }
785 
786  public function duplicateTableStructure(
787  $oldName, $newName, $temporary = false, $fname = __METHOD__
788  ) {
789  $newNameE = $this->addIdentifierQuotes( $newName );
790  $oldNameE = $this->addIdentifierQuotes( $oldName );
791 
792  $temporary = $temporary ? 'TEMPORARY' : '';
793 
794  $ret = $this->query( "CREATE $temporary TABLE $newNameE " .
795  "(LIKE $oldNameE INCLUDING DEFAULTS INCLUDING INDEXES)", $fname );
796  if ( !$ret ) {
797  return $ret;
798  }
799 
800  $res = $this->query( 'SELECT attname FROM pg_class c'
801  . ' JOIN pg_namespace n ON (n.oid = c.relnamespace)'
802  . ' JOIN pg_attribute a ON (a.attrelid = c.oid)'
803  . ' JOIN pg_attrdef d ON (c.oid=d.adrelid and a.attnum=d.adnum)'
804  . ' WHERE relkind = \'r\''
805  . ' AND nspname = ' . $this->addQuotes( $this->getCoreSchema() )
806  . ' AND relname = ' . $this->addQuotes( $oldName )
807  . ' AND adsrc LIKE \'nextval(%\'',
808  $fname
809  );
810  $row = $this->fetchObject( $res );
811  if ( $row ) {
812  $field = $row->attname;
813  $newSeq = "{$newName}_{$field}_seq";
814  $fieldE = $this->addIdentifierQuotes( $field );
815  $newSeqE = $this->addIdentifierQuotes( $newSeq );
816  $newSeqQ = $this->addQuotes( $newSeq );
817  $this->query( "CREATE $temporary SEQUENCE $newSeqE OWNED BY $newNameE.$fieldE", $fname );
818  $this->query(
819  "ALTER TABLE $newNameE ALTER COLUMN $fieldE SET DEFAULT nextval({$newSeqQ}::regclass)",
820  $fname
821  );
822  }
823 
824  return $ret;
825  }
826 
827  public function resetSequenceForTable( $table, $fname = __METHOD__ ) {
828  $table = $this->tableName( $table, 'raw' );
829  foreach ( $this->getCoreSchemas() as $schema ) {
830  $res = $this->query(
831  'SELECT c.oid FROM pg_class c JOIN pg_namespace n ON (n.oid = c.relnamespace)'
832  . ' WHERE relkind = \'r\''
833  . ' AND nspname = ' . $this->addQuotes( $schema )
834  . ' AND relname = ' . $this->addQuotes( $table ),
835  $fname
836  );
837  if ( !$res || !$this->numRows( $res ) ) {
838  continue;
839  }
840 
841  $oid = $this->fetchObject( $res )->oid;
842  $res = $this->query( 'SELECT adsrc FROM pg_attribute a'
843  . ' JOIN pg_attrdef d ON (a.attrelid=d.adrelid and a.attnum=d.adnum)'
844  . " WHERE a.attrelid = $oid"
845  . ' AND adsrc LIKE \'nextval(%\'',
846  $fname
847  );
848  $row = $this->fetchObject( $res );
849  if ( $row ) {
850  $this->query(
851  'SELECT ' . preg_replace( '/^nextval\((.+)\)$/', 'setval($1,1,false)', $row->adsrc ),
852  $fname
853  );
854  return true;
855  }
856  return false;
857  }
858 
859  return false;
860  }
861 
862  public function listTables( $prefix = null, $fname = __METHOD__ ) {
863  $eschemas = implode( ',', array_map( [ $this, 'addQuotes' ], $this->getCoreSchemas() ) );
864  $result = $this->query(
865  "SELECT DISTINCT tablename FROM pg_tables WHERE schemaname IN ($eschemas)", $fname );
866  $endArray = [];
867 
868  foreach ( $result as $table ) {
869  $vars = get_object_vars( $table );
870  $table = array_pop( $vars );
871  if ( !$prefix || strpos( $table, $prefix ) === 0 ) {
872  $endArray[] = $table;
873  }
874  }
875 
876  return $endArray;
877  }
878 
879  public function timestamp( $ts = 0 ) {
880  $ct = new ConvertibleTimestamp( $ts );
881 
882  return $ct->getTimestamp( TS_POSTGRES );
883  }
884 
903  private function pg_array_parse( $text, &$output, $limit = false, $offset = 1 ) {
904  if ( false === $limit ) {
905  $limit = strlen( $text ) - 1;
906  $output = [];
907  }
908  if ( '{}' == $text ) {
909  return $output;
910  }
911  do {
912  if ( '{' != $text[$offset] ) {
913  preg_match( "/(\\{?\"([^\"\\\\]|\\\\.)*\"|[^,{}]+)+([,}]+)/",
914  $text, $match, 0, $offset );
915  $offset += strlen( $match[0] );
916  $output[] = ( '"' != $match[1][0]
917  ? $match[1]
918  : stripcslashes( substr( $match[1], 1, -1 ) ) );
919  if ( '},' == $match[3] ) {
920  return $output;
921  }
922  } else {
923  $offset = $this->pg_array_parse( $text, $output, $limit, $offset + 1 );
924  }
925  } while ( $limit > $offset );
926 
927  return $output;
928  }
929 
930  public function aggregateValue( $valuedata, $valuename = 'value' ) {
931  return $valuedata;
932  }
933 
934  public function getSoftwareLink() {
935  return '[{{int:version-db-postgres-url}} PostgreSQL]';
936  }
937 
945  public function getCurrentSchema() {
946  $res = $this->query( "SELECT current_schema()", __METHOD__ );
947  $row = $this->fetchRow( $res );
948 
949  return $row[0];
950  }
951 
962  public function getSchemas() {
963  $res = $this->query( "SELECT current_schemas(false)", __METHOD__ );
964  $row = $this->fetchRow( $res );
965  $schemas = [];
966 
967  /* PHP pgsql support does not support array type, "{a,b}" string is returned */
968 
969  return $this->pg_array_parse( $row[0], $schemas );
970  }
971 
981  public function getSearchPath() {
982  $res = $this->query( "SHOW search_path", __METHOD__ );
983  $row = $this->fetchRow( $res );
984 
985  /* PostgreSQL returns SHOW values as strings */
986 
987  return explode( ",", $row[0] );
988  }
989 
997  private function setSearchPath( $search_path ) {
998  $this->query( "SET search_path = " . implode( ", ", $search_path ) );
999  }
1000 
1015  public function determineCoreSchema( $desiredSchema ) {
1016  $this->begin( __METHOD__, self::TRANSACTION_INTERNAL );
1017  if ( $this->schemaExists( $desiredSchema ) ) {
1018  if ( in_array( $desiredSchema, $this->getSchemas() ) ) {
1019  $this->coreSchema = $desiredSchema;
1020  $this->queryLogger->debug(
1021  "Schema \"" . $desiredSchema . "\" already in the search path\n" );
1022  } else {
1028  $search_path = $this->getSearchPath();
1029  array_unshift( $search_path,
1030  $this->addIdentifierQuotes( $desiredSchema ) );
1031  $this->setSearchPath( $search_path );
1032  $this->coreSchema = $desiredSchema;
1033  $this->queryLogger->debug(
1034  "Schema \"" . $desiredSchema . "\" added to the search path\n" );
1035  }
1036  } else {
1037  $this->coreSchema = $this->getCurrentSchema();
1038  $this->queryLogger->debug(
1039  "Schema \"" . $desiredSchema . "\" not found, using current \"" .
1040  $this->coreSchema . "\"\n" );
1041  }
1042  /* Commit SET otherwise it will be rollbacked on error or IGNORE SELECT */
1043  $this->commit( __METHOD__, self::FLUSHING_INTERNAL );
1044  }
1045 
1052  public function getCoreSchema() {
1053  return $this->coreSchema;
1054  }
1055 
1062  public function getCoreSchemas() {
1063  if ( $this->tempSchema ) {
1064  return [ $this->tempSchema, $this->getCoreSchema() ];
1065  }
1066 
1067  $res = $this->query(
1068  "SELECT nspname FROM pg_catalog.pg_namespace n WHERE n.oid = pg_my_temp_schema()", __METHOD__
1069  );
1070  $row = $this->fetchObject( $res );
1071  if ( $row ) {
1072  $this->tempSchema = $row->nspname;
1073  return [ $this->tempSchema, $this->getCoreSchema() ];
1074  }
1075 
1076  return [ $this->getCoreSchema() ];
1077  }
1078 
1079  public function getServerVersion() {
1080  if ( !isset( $this->numericVersion ) ) {
1081  $conn = $this->getBindingHandle();
1082  $versionInfo = pg_version( $conn );
1083  if ( version_compare( $versionInfo['client'], '7.4.0', 'lt' ) ) {
1084  // Old client, abort install
1085  $this->numericVersion = '7.3 or earlier';
1086  } elseif ( isset( $versionInfo['server'] ) ) {
1087  // Normal client
1088  $this->numericVersion = $versionInfo['server'];
1089  } else {
1090  // T18937: broken pgsql extension from PHP<5.3
1091  $this->numericVersion = pg_parameter_status( $conn, 'server_version' );
1092  }
1093  }
1094 
1095  return $this->numericVersion;
1096  }
1097 
1106  private function relationExists( $table, $types, $schema = false ) {
1107  if ( !is_array( $types ) ) {
1108  $types = [ $types ];
1109  }
1110  if ( $schema === false ) {
1111  $schemas = $this->getCoreSchemas();
1112  } else {
1113  $schemas = [ $schema ];
1114  }
1115  $table = $this->realTableName( $table, 'raw' );
1116  $etable = $this->addQuotes( $table );
1117  foreach ( $schemas as $schema ) {
1118  $eschema = $this->addQuotes( $schema );
1119  $sql = "SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "
1120  . "WHERE c.relnamespace = n.oid AND c.relname = $etable AND n.nspname = $eschema "
1121  . "AND c.relkind IN ('" . implode( "','", $types ) . "')";
1122  $res = $this->query( $sql );
1123  if ( $res && $res->numRows() ) {
1124  return true;
1125  }
1126  }
1127 
1128  return false;
1129  }
1130 
1138  public function tableExists( $table, $fname = __METHOD__, $schema = false ) {
1139  return $this->relationExists( $table, [ 'r', 'v' ], $schema );
1140  }
1141 
1142  public function sequenceExists( $sequence, $schema = false ) {
1143  return $this->relationExists( $sequence, 'S', $schema );
1144  }
1145 
1146  public function triggerExists( $table, $trigger ) {
1147  $q = <<<SQL
1148  SELECT 1 FROM pg_class, pg_namespace, pg_trigger
1149  WHERE relnamespace=pg_namespace.oid AND relkind='r'
1150  AND tgrelid=pg_class.oid
1151  AND nspname=%s AND relname=%s AND tgname=%s
1152 SQL;
1153  foreach ( $this->getCoreSchemas() as $schema ) {
1154  $res = $this->query(
1155  sprintf(
1156  $q,
1157  $this->addQuotes( $schema ),
1158  $this->addQuotes( $table ),
1159  $this->addQuotes( $trigger )
1160  )
1161  );
1162  if ( $res && $res->numRows() ) {
1163  return true;
1164  }
1165  }
1166 
1167  return false;
1168  }
1169 
1170  public function ruleExists( $table, $rule ) {
1171  $exists = $this->selectField( 'pg_rules', 'rulename',
1172  [
1173  'rulename' => $rule,
1174  'tablename' => $table,
1175  'schemaname' => $this->getCoreSchemas()
1176  ]
1177  );
1178 
1179  return $exists === $rule;
1180  }
1181 
1182  public function constraintExists( $table, $constraint ) {
1183  foreach ( $this->getCoreSchemas() as $schema ) {
1184  $sql = sprintf( "SELECT 1 FROM information_schema.table_constraints " .
1185  "WHERE constraint_schema = %s AND table_name = %s AND constraint_name = %s",
1186  $this->addQuotes( $schema ),
1187  $this->addQuotes( $table ),
1188  $this->addQuotes( $constraint )
1189  );
1190  $res = $this->query( $sql );
1191  if ( $res && $res->numRows() ) {
1192  return true;
1193  }
1194  }
1195  return false;
1196  }
1197 
1203  public function schemaExists( $schema ) {
1204  if ( !strlen( $schema ) ) {
1205  return false; // short-circuit
1206  }
1207 
1208  $exists = $this->selectField(
1209  '"pg_catalog"."pg_namespace"', 1, [ 'nspname' => $schema ], __METHOD__ );
1210 
1211  return (bool)$exists;
1212  }
1213 
1219  public function roleExists( $roleName ) {
1220  $exists = $this->selectField( '"pg_catalog"."pg_roles"', 1,
1221  [ 'rolname' => $roleName ], __METHOD__ );
1222 
1223  return (bool)$exists;
1224  }
1225 
1231  public function fieldInfo( $table, $field ) {
1232  return PostgresField::fromText( $this, $table, $field );
1233  }
1234 
1241  public function fieldType( $res, $index ) {
1242  if ( $res instanceof ResultWrapper ) {
1243  $res = $res->result;
1244  }
1245 
1246  return pg_field_type( $res, $index );
1247  }
1248 
1249  public function encodeBlob( $b ) {
1250  return new PostgresBlob( pg_escape_bytea( $b ) );
1251  }
1252 
1253  public function decodeBlob( $b ) {
1254  if ( $b instanceof PostgresBlob ) {
1255  $b = $b->fetch();
1256  } elseif ( $b instanceof Blob ) {
1257  return $b->fetch();
1258  }
1259 
1260  return pg_unescape_bytea( $b );
1261  }
1262 
1263  public function strencode( $s ) {
1264  // Should not be called by us
1265  return pg_escape_string( $this->getBindingHandle(), (string)$s );
1266  }
1267 
1268  public function addQuotes( $s ) {
1269  $conn = $this->getBindingHandle();
1270 
1271  if ( is_null( $s ) ) {
1272  return 'NULL';
1273  } elseif ( is_bool( $s ) ) {
1274  return intval( $s );
1275  } elseif ( $s instanceof Blob ) {
1276  if ( $s instanceof PostgresBlob ) {
1277  $s = $s->fetch();
1278  } else {
1279  $s = pg_escape_bytea( $conn, $s->fetch() );
1280  }
1281  return "'$s'";
1282  } elseif ( $s instanceof NextSequenceValue ) {
1283  return 'DEFAULT';
1284  }
1285 
1286  return "'" . pg_escape_string( $conn, (string)$s ) . "'";
1287  }
1288 
1289  public function makeSelectOptions( $options ) {
1290  $preLimitTail = $postLimitTail = '';
1291  $startOpts = $useIndex = $ignoreIndex = '';
1292 
1293  $noKeyOptions = [];
1294  foreach ( $options as $key => $option ) {
1295  if ( is_numeric( $key ) ) {
1296  $noKeyOptions[$option] = true;
1297  }
1298  }
1299 
1300  $preLimitTail .= $this->makeGroupByWithHaving( $options );
1301 
1302  $preLimitTail .= $this->makeOrderBy( $options );
1303 
1304  if ( isset( $options['FOR UPDATE'] ) ) {
1305  $postLimitTail .= ' FOR UPDATE OF ' .
1306  implode( ', ', array_map( [ $this, 'tableName' ], $options['FOR UPDATE'] ) );
1307  } elseif ( isset( $noKeyOptions['FOR UPDATE'] ) ) {
1308  $postLimitTail .= ' FOR UPDATE';
1309  }
1310 
1311  if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) {
1312  $startOpts .= 'DISTINCT';
1313  }
1314 
1315  return [ $startOpts, $useIndex, $preLimitTail, $postLimitTail, $ignoreIndex ];
1316  }
1317 
1318  public function getDBname() {
1319  return $this->dbName;
1320  }
1321 
1322  public function getServer() {
1323  return $this->server;
1324  }
1325 
1326  public function buildConcat( $stringList ) {
1327  return implode( ' || ', $stringList );
1328  }
1329 
1330  public function buildGroupConcatField(
1331  $delimiter, $table, $field, $conds = '', $options = [], $join_conds = []
1332  ) {
1333  $fld = "array_to_string(array_agg($field)," . $this->addQuotes( $delimiter ) . ')';
1334 
1335  return '(' . $this->selectSQLText( $table, $fld, $conds, null, [], $join_conds ) . ')';
1336  }
1337 
1338  public function buildStringCast( $field ) {
1339  return $field . '::text';
1340  }
1341 
1342  public function streamStatementEnd( &$sql, &$newLine ) {
1343  # Allow dollar quoting for function declarations
1344  if ( substr( $newLine, 0, 4 ) == '$mw$' ) {
1345  if ( $this->delimiter ) {
1346  $this->delimiter = false;
1347  } else {
1348  $this->delimiter = ';';
1349  }
1350  }
1351 
1352  return parent::streamStatementEnd( $sql, $newLine );
1353  }
1354 
1355  public function doLockTables( array $read, array $write, $method ) {
1356  $tablesWrite = [];
1357  foreach ( $write as $table ) {
1358  $tablesWrite[] = $this->tableName( $table );
1359  }
1360  $tablesRead = [];
1361  foreach ( $read as $table ) {
1362  $tablesRead[] = $this->tableName( $table );
1363  }
1364 
1365  // Acquire locks for the duration of the current transaction...
1366  if ( $tablesWrite ) {
1367  $this->query(
1368  'LOCK TABLE ONLY ' . implode( ',', $tablesWrite ) . ' IN EXCLUSIVE MODE',
1369  $method
1370  );
1371  }
1372  if ( $tablesRead ) {
1373  $this->query(
1374  'LOCK TABLE ONLY ' . implode( ',', $tablesRead ) . ' IN SHARE MODE',
1375  $method
1376  );
1377  }
1378 
1379  return true;
1380  }
1381 
1382  public function lockIsFree( $lockName, $method ) {
1383  if ( !parent::lockIsFree( $lockName, $method ) ) {
1384  return false; // already held
1385  }
1386  // http://www.postgresql.org/docs/9.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
1387  $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
1388  $result = $this->query( "SELECT (CASE(pg_try_advisory_lock($key))
1389  WHEN 'f' THEN 'f' ELSE pg_advisory_unlock($key) END) AS lockstatus", $method );
1390  $row = $this->fetchObject( $result );
1391 
1392  return ( $row->lockstatus === 't' );
1393  }
1394 
1395  public function lock( $lockName, $method, $timeout = 5 ) {
1396  // http://www.postgresql.org/docs/9.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
1397  $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
1398  $loop = new WaitConditionLoop(
1399  function () use ( $lockName, $key, $timeout, $method ) {
1400  $res = $this->query( "SELECT pg_try_advisory_lock($key) AS lockstatus", $method );
1401  $row = $this->fetchObject( $res );
1402  if ( $row->lockstatus === 't' ) {
1403  parent::lock( $lockName, $method, $timeout ); // record
1404  return true;
1405  }
1406 
1407  return WaitConditionLoop::CONDITION_CONTINUE;
1408  },
1409  $timeout
1410  );
1411 
1412  return ( $loop->invoke() === $loop::CONDITION_REACHED );
1413  }
1414 
1415  public function unlock( $lockName, $method ) {
1416  // http://www.postgresql.org/docs/9.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
1417  $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
1418  $result = $this->query( "SELECT pg_advisory_unlock($key) as lockstatus", $method );
1419  $row = $this->fetchObject( $result );
1420 
1421  if ( $row->lockstatus === 't' ) {
1422  parent::unlock( $lockName, $method ); // record
1423  return true;
1424  }
1425 
1426  $this->queryLogger->debug( __METHOD__ . " failed to release lock\n" );
1427 
1428  return false;
1429  }
1430 
1431  public function serverIsReadOnly() {
1432  $res = $this->query( "SHOW default_transaction_read_only", __METHOD__ );
1433  $row = $this->fetchObject( $res );
1434 
1435  return $row ? ( strtolower( $row->default_transaction_read_only ) === 'on' ) : false;
1436  }
1437 
1442  private function bigintFromLockName( $lockName ) {
1443  return \Wikimedia\base_convert( substr( sha1( $lockName ), 0, 15 ), 16, 10 );
1444  }
1445 }
1446 
1447 class_alias( DatabasePostgres::class, 'DatabasePostgres' );
Wikimedia\Rdbms\DatabasePostgres\freeResult
freeResult( $res)
Free a result object returned by query() or select().
Definition: DatabasePostgres.php:250
Wikimedia\Rdbms\Database\getLastPHPError
getLastPHPError()
Definition: Database.php:861
Wikimedia\Rdbms\DatabasePostgres\resetSequenceForTable
resetSequenceForTable( $table, $fname=__METHOD__)
Definition: DatabasePostgres.php:827
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:48
Wikimedia\Rdbms\DatabasePostgres\doLockTables
doLockTables(array $read, array $write, $method)
Helper function for lockTables() that handles the actual table locking.
Definition: DatabasePostgres.php:1355
Wikimedia\Rdbms\DatabasePostgres\numFields
numFields( $res)
Get the number of fields in a result object.
Definition: DatabasePostgres.php:322
Wikimedia\Rdbms\DatabasePostgres\bigintFromLockName
bigintFromLockName( $lockName)
Definition: DatabasePostgres.php:1442
Wikimedia\Rdbms\Database\getBindingHandle
getBindingHandle()
Get the underlying binding connection handle.
Definition: Database.php:4488
Wikimedia\Rdbms\DatabasePostgres\tableName
tableName( $name, $format='quoted')
Format a table name ready for use in constructing an SQL query.
Definition: DatabasePostgres.php:701
Wikimedia\Rdbms\DatabasePostgres\getSoftwareLink
getSoftwareLink()
Returns a wikitext link to the DB's website, e.g., return "[https://www.mysql.com/ MySQL]"; Should at...
Definition: DatabasePostgres.php:934
Wikimedia\Rdbms\DatabasePostgres\closeConnection
closeConnection()
Closes underlying database connection.
Definition: DatabasePostgres.php:201
Wikimedia\Rdbms\DatabasePostgres\relationExists
relationExists( $table, $types, $schema=false)
Query whether a given relation exists (in the given schema, or the default mw one if not given)
Definition: DatabasePostgres.php:1106
Wikimedia\Rdbms\DatabasePostgres\getSchemas
getSchemas()
Return list of schemas which are accessible without schema name This is list does not contain magic k...
Definition: DatabasePostgres.php:962
Wikimedia\Rdbms\DatabasePostgres\implicitGroupby
implicitGroupby()
Returns true if this database does an implicit sort when doing GROUP BY.
Definition: DatabasePostgres.php:69
Wikimedia\Rdbms\DatabasePostgres\remappedTableName
remappedTableName( $name)
Definition: DatabasePostgres.php:712
Wikimedia\Rdbms\DatabasePostgres\addQuotes
addQuotes( $s)
Adds quotes and backslashes.
Definition: DatabasePostgres.php:1268
Wikimedia\Rdbms\DatabasePostgres\$connectString
string $connectString
Connect string to open a PostgreSQL connection.
Definition: DatabasePostgres.php:43
Wikimedia\Rdbms\DatabasePostgres\fetchAffectedRowCount
fetchAffectedRowCount()
Definition: DatabasePostgres.php:372
Wikimedia\Rdbms\DatabasePostgres\getCoreSchemas
getCoreSchemas()
Return schema names for temporary tables and core application tables.
Definition: DatabasePostgres.php:1062
n
while(( $__line=Maintenance::readconsole()) !==false) print n
Definition: eval.php:64
Wikimedia\Rdbms\DatabasePostgres\fieldInfo
fieldInfo( $table, $field)
Definition: DatabasePostgres.php:1231
captcha-old.count
count
Definition: captcha-old.py:249
Wikimedia\Rdbms\Database\$password
string $password
Password used to establish the current connection.
Definition: Database.php:83
Wikimedia\Rdbms\DatabasePostgres\unlock
unlock( $lockName, $method)
Release a lock.
Definition: DatabasePostgres.php:1415
$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. Return false to stop further processing of the tag $reader:XMLReader object $logInfo:Array of information 'ImportHandlePageXMLTag':When parsing a XML tag in a page. Return false to stop further processing of the tag $reader:XMLReader object & $pageInfo:Array of information 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. Return false to stop further processing of the tag $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. Return false to stop further processing of the tag $reader:XMLReader object 'ImportHandleUnknownUser':When a user doesn 't exist locally, this hook is called to give extensions an opportunity to auto-create it. If the auto-creation is successful, return false. $name:User name 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. Return false to stop further processing of the tag $reader:XMLReader object $revisionInfo:Array of information 'ImportLogInterwikiLink':Hook to change the interwiki link used in log entries and edit summaries for transwiki imports. & $fullInterwikiPrefix:Interwiki prefix, may contain colons. & $pageTitle:String that contains page title. 'ImportSources':Called when reading from the $wgImportSources configuration variable. Can be used to lazy-load the import sources list. & $importSources:The value of $wgImportSources. Modify as necessary. See the comment in DefaultSettings.php for the detail of how to structure this array. 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. & $title:Title object for the current page & $request:WebRequest & $ignoreRedirect:boolean to skip redirect check & $target:Title/string of redirect target & $article:Article object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) & $article:article(object) being checked 'IsTrustedProxy':Override the result of IP::isTrustedProxy() & $ip:IP being check & $result:Change this value to override the result of IP::isTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of Sanitizer::validateEmail(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetMagic':DEPRECATED! Use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language & $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetSpecialPageAliases':DEPRECATED! Use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language & $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code:language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Array with elements of the form "language:title" in the order that they will be output. & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LanguageSelector':Hook to change the language selector available on a page. $out:The output page. $cssClassName:CSS class name of the language selector. 'LinkBegin':DEPRECATED! Use HtmlPageLinkRendererBegin instead. Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:1985
Wikimedia\Rdbms\Database\$delimiter
string $delimiter
Definition: Database.php:140
Wikimedia\Rdbms\Database\endAtomic
endAtomic( $fname=__METHOD__)
Ends an atomic section of SQL statements.
Definition: Database.php:3562
Wikimedia\Rdbms\Database\indexName
indexName( $index)
Allows for index remapping in queries where this is not consistent across DBMS.
Definition: Database.php:2531
Wikimedia\Rdbms\DatabasePostgres\fieldType
fieldType( $res, $index)
pg_field_type() wrapper
Definition: DatabasePostgres.php:1241
FROM
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to and or sell copies of the and to permit persons to whom the Software is furnished to do subject to the following WITHOUT WARRANTY OF ANY EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR ARISING FROM
Definition: MIT-LICENSE.txt:10
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
Wikimedia\Rdbms\DatabasePostgres\$numericVersion
float string $numericVersion
Definition: DatabasePostgres.php:41
Wikimedia\Rdbms
Definition: ChronologyProtector.php:24
Wikimedia\Rdbms\Database\normalizeConditions
normalizeConditions( $conds, $fname)
Definition: Database.php:1796
$params
$params
Definition: styleTest.css.php:40
$s
$s
Definition: mergeMessageFileList.php:187
Wikimedia\Rdbms\Database\extractSingleFieldFromList
extractSingleFieldFromList( $var)
Definition: Database.php:1819
DBO_SSL
const DBO_SSL
Definition: defines.php:17
Wikimedia\Rdbms\DatabasePostgres
Definition: DatabasePostgres.php:33
$res
$res
Definition: database.txt:21
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:302
Wikimedia\Rdbms\ResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: ResultWrapper.php:24
Wikimedia\Rdbms\DatabasePostgres\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: DatabasePostgres.php:1289
Wikimedia\Rdbms\DatabasePostgres\textFieldSize
textFieldSize( $table, $field)
Returns the size of a text field, or -1 for "unlimited".
Definition: DatabasePostgres.php:744
Wikimedia\Rdbms\Database\cancelAtomic
cancelAtomic( $fname=__METHOD__, AtomicSectionIdentifier $sectionId=null)
Cancel an atomic section of SQL statements.
Definition: Database.php:3595
Wikimedia\Rdbms\DatabasePostgres\indexUnique
indexUnique( $table, $index, $fname=__METHOD__)
Definition: DatabasePostgres.php:496
Wikimedia\Rdbms\DatabasePostgres\insertId
insertId()
Get the inserted value of an auto-increment row.
Definition: DatabasePostgres.php:338
Wikimedia\Rdbms\DatabasePostgres\fetchObject
fetchObject( $res)
Fetch the next row from the given result object, in object form.
Definition: DatabasePostgres.php:262
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
Wikimedia\Rdbms\DatabasePostgres\aggregateValue
aggregateValue( $valuedata, $valuename='value')
Return aggregated value alias.
Definition: DatabasePostgres.php:930
Wikimedia\Rdbms\DatabasePostgres\roleExists
roleExists( $roleName)
Returns true if a given role (i.e.
Definition: DatabasePostgres.php:1219
Wikimedia\Rdbms\DatabasePostgres\nativeInsertSelect
nativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname=__METHOD__, $insertOptions=[], $selectOptions=[], $selectJoinConds=[])
INSERT SELECT wrapper $varMap must be an associative array of the form [ 'dest1' => 'source1',...
Definition: DatabasePostgres.php:662
Wikimedia\Rdbms\DatabasePostgres\insert
insert( $table, $args, $fname=__METHOD__, $options=[])
@inheritDoc
Definition: DatabasePostgres.php:564
Wikimedia\Rdbms\Database\begin
begin( $fname=__METHOD__, $mode=self::TRANSACTION_EXPLICIT)
Begin a transaction.
Definition: Database.php:3675
Wikimedia\Rdbms\DatabasePostgres\$coreSchema
string $coreSchema
Definition: DatabasePostgres.php:45
key
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 and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add in any and then calling but I prefer the flexibility This should also do the output encoding The system allocates a global one in $wgOut Title Represents the title of an and does all the work of translating among various forms such as plain database key
Definition: design.txt:25
Wikimedia\Rdbms\DatabasePostgres\encodeBlob
encodeBlob( $b)
Some DBMSs have a special format for inserting into blob fields, they don't allow simple quoted strin...
Definition: DatabasePostgres.php:1249
Wikimedia\Rdbms\DatabasePostgres\makeConnectionString
makeConnectionString( $vars)
Definition: DatabasePostgres.php:192
Wikimedia\Rdbms\DatabasePostgres\lockIsFree
lockIsFree( $lockName, $method)
Check to see if a named lock is not locked by any thread (non-blocking)
Definition: DatabasePostgres.php:1382
user
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 and we might be restricted by PHP settings such as safe mode or open_basedir We cannot assume that the software even has read access anywhere useful Many shared hosts run all users web applications under the same user
Definition: distributors.txt:9
Wikimedia\Rdbms\DatabasePostgres\isTransactableQuery
isTransactableQuery( $sql)
Determine whether a SQL statement is sensitive to isolation level.
Definition: DatabasePostgres.php:205
Wikimedia\Rdbms\Database\nonNativeInsertSelect
nonNativeInsertSelect( $destTable, $srcTable, $varMap, $conds, $fname=__METHOD__, $insertOptions=[], $selectOptions=[], $selectJoinConds=[])
Implementation of insertSelect() based on select() and insert()
Definition: Database.php:2909
Wikimedia\Rdbms\DatabasePostgres\schemaExists
schemaExists( $schema)
Query whether a given schema exists.
Definition: DatabasePostgres.php:1203
Wikimedia\Rdbms\DatabasePostgres\implicitOrderby
implicitOrderby()
Returns true if this database does an implicit order by when the column has an index For example: SEL...
Definition: DatabasePostgres.php:73
Wikimedia\Rdbms\Database\startAtomic
startAtomic( $fname=__METHOD__, $cancelable=self::ATOMIC_NOT_CANCELABLE)
Begin an atomic section of SQL statements.
Definition: Database.php:3534
Wikimedia\Rdbms\DatabasePostgres\limitResult
limitResult( $sql, $limit, $offset=false)
Construct a LIMIT query with optional offset.
Definition: DatabasePostgres.php:761
tableName
We use the convention $dbr for read and $dbw for write to help you keep track of whether the database object is a the world will explode Or to be a subsequent write query which succeeded on the master may fail when replicated to the slave due to a unique key collision Replication on the slave will stop and it may take hours to repair the database and get it back online Setting read_only in my cnf on the slave will avoid this but given the dire we prefer to have as many checks as possible We provide a but the wrapper functions like please read the documentation for tableName() and addQuotes(). You will need both of them. ------------------------------------------------------------------------ Basic query optimisation ------------------------------------------------------------------------ MediaWiki developers who need to write DB queries should have some understanding of databases and the performance issues associated with them. Patches containing unacceptably slow features will not be accepted. Unindexed queries are generally not welcome in MediaWiki
Wikimedia\Rdbms\DatabasePostgres\duplicateTableStructure
duplicateTableStructure( $oldName, $newName, $temporary=false, $fname=__METHOD__)
Creates a new table with structure copied from existing table.
Definition: DatabasePostgres.php:786
Wikimedia\Rdbms\PostgresField\fromText
static fromText(DatabasePostgres $db, $table, $field)
Definition: PostgresField.php:15
Wikimedia\Rdbms\DatabasePostgres\doQuery
doQuery( $sql)
Run a query and return a DBMS-dependent wrapper (that has all IResultWrapper methods)
Definition: DatabasePostgres.php:210
Wikimedia\Rdbms\DatabasePostgres\getDBname
getDBname()
Get the current DB name.
Definition: DatabasePostgres.php:1318
Wikimedia\Rdbms\DatabasePostgres\buildStringCast
buildStringCast( $field)
Definition: DatabasePostgres.php:1338
Wikimedia\Rdbms\DatabasePostgres\pg_array_parse
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://secure.php.net/manual/en/ref....
Definition: DatabasePostgres.php:903
Wikimedia\Rdbms\DatabasePostgres\lastErrno
lastErrno()
Get the last error number.
Definition: DatabasePostgres.php:364
Wikimedia\Rdbms\Database\$phpError
string bool $phpError
Definition: Database.php:77
Wikimedia\Rdbms\Database\$user
string $user
User that this instance is currently connected under the name of.
Definition: Database.php:81
Wikimedia\Rdbms\DatabasePostgres\$lastResultHandle
resource $lastResultHandle
Definition: DatabasePostgres.php:38
$output
$output
Definition: SyntaxHighlight.php:338
$vars
static configuration should be added through ResourceLoaderGetConfigVars instead & $vars
Definition: hooks.txt:2220
Wikimedia\Rdbms\DatabasePostgres\selectSQLText
selectSQLText( $table, $vars, $conds='', $fname=__METHOD__, $options=[], $join_conds=[])
The equivalent of IDatabase::select() except that the constructed SQL is returned,...
Definition: DatabasePostgres.php:509
Wikimedia\Rdbms\Database\commit
commit( $fname=__METHOD__, $flush=self::FLUSHING_ONE)
Commits a transaction previously started using begin().
Definition: Database.php:3739
Wikimedia\Rdbms\DatabasePostgres\numRows
numRows( $res)
Get the number of rows in a result object.
Definition: DatabasePostgres.php:303
port
storage can be distributed across multiple and multiple web servers can use the same cache cluster *********************W A R N I N G ***********************Memcached has no security or authentication Please ensure that your server is appropriately and that the port(s) used for memcached servers are not publicly accessible. Otherwise
Wikimedia\Rdbms\NextSequenceValue
Used by Database::nextSequenceValue() so Database::insert() can detect values coming from the depreca...
Definition: NextSequenceValue.php:11
Wikimedia\Rdbms\DatabasePostgres\strencode
strencode( $s)
Wrapper for addslashes()
Definition: DatabasePostgres.php:1263
Wikimedia\Rdbms\DBQueryError
Definition: DBQueryError.php:27
Wikimedia\Rdbms\DatabasePostgres\wasConnectionError
wasConnectionError( $errno)
Do not use this method outside of Database/DBError classes.
Definition: DatabasePostgres.php:775
$fname
if(defined( 'MW_SETUP_CALLBACK')) $fname
Customization point after all loading (constants, functions, classes, DefaultSettings,...
Definition: Setup.php:112
Wikimedia\Rdbms\Database\installErrorHandler
installErrorHandler()
Set a custom error handler for logging errors during database connection.
Definition: Database.php:838
Wikimedia\Rdbms\Database\restoreErrorHandler
restoreErrorHandler()
Restore the previous error handler and return the last PHP error for this DB.
Definition: Database.php:849
Wikimedia\Rdbms\DatabasePostgres\serverIsReadOnly
serverIsReadOnly()
Definition: DatabasePostgres.php:1431
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2163
$value
$value
Definition: styleTest.css.php:45
Wikimedia\Rdbms\DatabasePostgres\timestamp
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
Definition: DatabasePostgres.php:879
Wikimedia\Rdbms\DatabasePostgres\getServer
getServer()
Get the server hostname or IP address.
Definition: DatabasePostgres.php:1322
$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:1987
Wikimedia\Rdbms\Database\$conn
resource null $conn
Database connection.
Definition: Database.php:108
Wikimedia\Rdbms\DatabasePostgres\decodeBlob
decodeBlob( $b)
Some DBMSs return a special placeholder object representing blob fields in result objects.
Definition: DatabasePostgres.php:1253
Wikimedia\Rdbms\Database\query
query( $sql, $fname=__METHOD__, $tempIgnore=false)
Run an SQL query and return the result.
Definition: Database.php:1094
Wikimedia\Rdbms\DatabasePostgres\getCurrentSchema
getCurrentSchema()
Return current schema (executes SELECT current_schema()) Needs transaction.
Definition: DatabasePostgres.php:945
Wikimedia\Rdbms\DBUnexpectedError
Definition: DBUnexpectedError.php:27
Wikimedia\Rdbms\DatabasePostgres\realTableName
realTableName( $name, $format='quoted')
Definition: DatabasePostgres.php:721
Wikimedia\Rdbms\Database\selectField
selectField( $table, $var, $cond='', $fname=__METHOD__, $options=[], $join_conds=[])
A SELECT wrapper which returns a single field from a single result row.
Definition: Database.php:1466
Wikimedia\Rdbms\DatabasePostgres\nextSequenceValue
nextSequenceValue( $seqName)
Deprecated method, calls should be removed.
Definition: DatabasePostgres.php:725
Wikimedia\Rdbms\DatabasePostgres\buildConcat
buildConcat( $stringList)
Build a concatenation list to feed into a SQL query.
Definition: DatabasePostgres.php:1326
Wikimedia\Rdbms\Database\makeList
makeList( $a, $mode=self::LIST_COMMA)
Makes an encoded list of strings from an array.
Definition: Database.php:2013
Wikimedia\Rdbms\DatabasePostgres\getType
getType()
Get the type of the DBMS, as it appears in $wgDBtype.
Definition: DatabasePostgres.php:65
Wikimedia\Rdbms\Database\addIdentifierQuotes
addIdentifierQuotes( $s)
Quotes an identifier using backticks or "double quotes" depending on the database type.
Definition: Database.php:2563
Wikimedia\Rdbms\DatabasePostgres\getServerVersion
getServerVersion()
A string describing the current software version, like from mysql_get_server_info().
Definition: DatabasePostgres.php:1079
Wikimedia\Rdbms\Database\$schema
string $schema
Definition: Database.php:126
$args
if( $line===false) $args
Definition: cdb.php:64
Wikimedia\Rdbms\Database\close
close()
Close the database connection.
Definition: Database.php:900
flags
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 and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add in any and then calling but I prefer the flexibility This should also do the output encoding The system allocates a global one in $wgOut Title Represents the title of an and does all the work of translating among various forms such as plain database etc For and for historical it also represents a few features of articles that don t involve their such as access rights See also title txt Article Encapsulates access to the page table of the database The object represents a an and maintains state such as flags
Definition: design.txt:34
Wikimedia\Rdbms\DatabasePostgres\lastError
lastError()
Get a description of the last error.
Definition: DatabasePostgres.php:352
$rows
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction $rows
Definition: hooks.txt:2604
$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:1987
Wikimedia\Rdbms\DatabasePostgres\__construct
__construct(array $params)
Definition: DatabasePostgres.php:56
Wikimedia\Rdbms\DatabasePostgres\constraintExists
constraintExists( $table, $constraint)
Definition: DatabasePostgres.php:1182
Wikimedia\Rdbms\DatabasePostgres\wasLockTimeout
wasLockTimeout()
Determines if the last failure was due to a lock timeout.
Definition: DatabasePostgres.php:770
Wikimedia\Rdbms\DatabasePostgres\streamStatementEnd
streamStatementEnd(&$sql, &$newLine)
Called by sourceStream() to check if we've reached a statement end.
Definition: DatabasePostgres.php:1342
Wikimedia\Rdbms\Database\makeGroupByWithHaving
makeGroupByWithHaving( $options)
Returns an optional GROUP BY with an optional HAVING.
Definition: Database.php:1611
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
Wikimedia\Rdbms\DatabasePostgres\open
open( $server, $user, $password, $dbName)
Open a new connection to the database (closing any existing one)
Definition: DatabasePostgres.php:91
Wikimedia\Rdbms\DBConnectionError
Definition: DBConnectionError.php:26
Wikimedia
Wikimedia\Rdbms\DatabasePostgres\sequenceExists
sequenceExists( $sequence, $schema=false)
Definition: DatabasePostgres.php:1142
Wikimedia\Rdbms\Database\$server
string $server
Server that this instance is currently connected to.
Definition: Database.php:79
$keys
$keys
Definition: testCompression.php:67
Wikimedia\Rdbms\DatabasePostgres\tableExists
tableExists( $table, $fname=__METHOD__, $schema=false)
For backward compatibility, this function checks both tables and views.
Definition: DatabasePostgres.php:1138
Wikimedia\Rdbms\DatabasePostgres\$keywordTableMap
string[] $keywordTableMap
Map of (reserved table name => alternate table name)
Definition: DatabasePostgres.php:49
Wikimedia\Rdbms\DatabasePostgres\buildGroupConcatField
buildGroupConcatField( $delimiter, $table, $field, $conds='', $options=[], $join_conds=[])
Definition: DatabasePostgres.php:1330
Wikimedia\Rdbms\Database\makeOrderBy
makeOrderBy( $options)
Returns an optional ORDER BY.
Definition: Database.php:1637
Wikimedia\Rdbms\DatabasePostgres\dataSeek
dataSeek( $res, $row)
Change the position of the cursor in a result object.
Definition: DatabasePostgres.php:344
Wikimedia\Rdbms\DatabasePostgres\ruleExists
ruleExists( $table, $rule)
Definition: DatabasePostgres.php:1170
Wikimedia\Rdbms\Database\select
select( $table, $vars, $conds='', $fname=__METHOD__, $options=[], $join_conds=[])
Execute a SELECT query constructed using the various parameters provided.
Definition: Database.php:1649
Wikimedia\Rdbms\DatabasePostgres\wasKnownStatementRollbackError
wasKnownStatementRollbackError()
Definition: DatabasePostgres.php:782
Wikimedia\Rdbms\DatabasePostgres\fetchRow
fetchRow( $res)
Fetch the next row from the given result object, in associative array form.
Definition: DatabasePostgres.php:284
Wikimedia\Rdbms\DatabasePostgres\fieldName
fieldName( $res, $n)
Get a field name in a result object.
Definition: DatabasePostgres.php:330
Wikimedia\Rdbms\DatabasePostgres\selectDB
selectDB( $db)
Postgres doesn't support selectDB in the same way MySQL does.
Definition: DatabasePostgres.php:180
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
Wikimedia\Rdbms\DatabasePostgres\dumpError
dumpError()
Definition: DatabasePostgres.php:229
Wikimedia\Rdbms\DatabasePostgres\determineCoreSchema
determineCoreSchema( $desiredSchema)
Determine default schema for the current application Adjust this session schema search path if desire...
Definition: DatabasePostgres.php:1015
Wikimedia\Rdbms\DatabasePostgres\getSearchPath
getSearchPath()
Return search patch for schemas This is different from getSchemas() since it contain magic keywords (...
Definition: DatabasePostgres.php:981
Wikimedia\Rdbms\DatabasePostgres\getCoreSchema
getCoreSchema()
Return schema name for core application tables.
Definition: DatabasePostgres.php:1052
Wikimedia\Rdbms\DatabasePostgres\indexInfo
indexInfo( $table, $index, $fname=__METHOD__)
Get information about an index into an object.
Definition: DatabasePostgres.php:418
Wikimedia\Rdbms\DatabasePostgres\$tempSchema
string $tempSchema
Definition: DatabasePostgres.php:47
Wikimedia\Rdbms\DatabasePostgres\triggerExists
triggerExists( $table, $trigger)
Definition: DatabasePostgres.php:1146
Wikimedia\Rdbms\DatabasePostgres\currentSequenceValue
currentSequenceValue( $seqName)
Return the current value of a sequence.
Definition: DatabasePostgres.php:735
Wikimedia\Rdbms\DatabasePostgres\setSearchPath
setSearchPath( $search_path)
Update search_path, values should already be sanitized Values may contain magic keywords like "$user"...
Definition: DatabasePostgres.php:997
server
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 and we might be restricted by PHP settings such as safe mode or open_basedir We cannot assume that the software even has read access anywhere useful Many shared hosts run all users web applications under the same so they can t rely on Unix and must forbid reads to even standard directories like tmp lest users read each others files We cannot assume that the user has the ability to install or run any programs not written as web accessible PHP scripts Since anything that works on cheap shared hosting will work if you have shell or root access MediaWiki s design is based around catering to the lowest common denominator Although we support higher end setups as the way many things work by default is tailored toward shared hosting These defaults are unconventional from the point of view of and they certainly aren t ideal for someone who s installing MediaWiki as MediaWiki does not conform to normal Unix filesystem layout Hopefully we ll offer direct support for standard layouts in the but for now *any change to the location of files is unsupported *Moving things and leaving symlinks will *probably *not break but it is *strongly *advised not to try any more intrusive changes to get MediaWiki to conform more closely to your filesystem hierarchy Any such attempt will almost certainly result in unnecessary bugs The standard recommended location to install relative to the web is it should be possible to enable the appropriate rewrite rules by if you can reconfigure the web server
Definition: distributors.txt:53
Wikimedia\Rdbms\DatabasePostgres\wasDeadlock
wasDeadlock()
Determines if the last failure was due to a deadlock.
Definition: DatabasePostgres.php:765
Wikimedia\Rdbms\PostgresBlob
Definition: PostgresBlob.php:5
Wikimedia\Rdbms\DatabasePostgres\lock
lock( $lockName, $method, $timeout=5)
Acquire a named lock.
Definition: DatabasePostgres.php:1395
Wikimedia\Rdbms\DatabasePostgres\estimateRowCount
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 ...
Definition: DatabasePostgres.php:395
Wikimedia\Rdbms\DatabasePostgres\hasConstraint
hasConstraint( $name)
Definition: DatabasePostgres.php:77
Wikimedia\Rdbms\DatabasePostgres\listTables
listTables( $prefix=null, $fname=__METHOD__)
List all tables on the database.
Definition: DatabasePostgres.php:862
array
the array() calling protocol came about after MediaWiki 1.4rc1.
Wikimedia\Rdbms\DatabasePostgres\databasesAreIndependent
databasesAreIndependent()
Returns true if DBs are assumed to be on potentially different servers.
Definition: DatabasePostgres.php:169
Wikimedia\Rdbms\DatabasePostgres\$port
int bool $port
Definition: DatabasePostgres.php:35
Wikimedia\Rdbms\DatabasePostgres\indexAttributes
indexAttributes( $index, $schema=false)
Definition: DatabasePostgres.php:433
Wikimedia\Rdbms\Blob
Definition: Blob.php:5
Wikimedia\Rdbms\Database\$dbName
string $dbName
Database that this instance is currently connected to.
Definition: Database.php:85