r113487 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r113486‎ | r113487 | r113488 >
Date:17:24, 9 March 2012
Author:saper
Status:resolved (Comments)
Tags:1.19 
Comment:
Handle PostgreSQL transaction errors and improve schema detection

* Introduce $wgDebugDBTransactions facility to help
figure out what's going on with transactions.
Currently PostgreSQL only.

PostgresTransactionState can be easily be made more general
to trace all sorts of state machinery.

* Improve r113408: we don't need to full reconnect on error,
rollback is enough.

Rolling back breaks search_path, as PostgreSQL
can manage sessions settings under transaction therefore
we need to improve schema sniffing introduced in r82674

* Introduce few schema handling functions. This could
probably be generalized for other databases like DB2 and Oracle.

* Fix bug 15816 - Add a switch for SETting the search_path

We try to avoid touching search_path at all unless
really necessary. Even in this case we append MediaWiki
core schema to the front of the list.

* No longer add $wgDBmwschema to PostgreSQL role search_path
in the installer. This is no longer necessary as
setting schema on connect should ReallyWorkNow(tm).

* Get rid as much as possible of $wgDBmwschema and
bring us one step closer to fix bug 16794 (wgSharedDB
support).

All references to core MediaWiki schema in PostgreSQL
specific code should now use Database::getCoreSchema()
unless we know what we are doing.

Followup-To: r113408 r82674
Modified paths:
  • /trunk/phase3/RELEASE-NOTES-1.20 (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/db/Database.php (modified) (history)
  • /trunk/phase3/includes/db/DatabasePostgres.php (modified) (history)
  • /trunk/phase3/includes/installer/PostgresInstaller.php (modified) (history)
  • /trunk/phase3/includes/installer/PostgresUpdater.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/db/DatabasePostgres.php
@@ -16,8 +16,6 @@
1717 * @return null|PostgresField
1818 */
1919 static function fromText( $db, $table, $field ) {
20 - global $wgDBmwschema;
21 -
2220 $q = <<<SQL
2321 SELECT
2422 attnotnull, attlen, COALESCE(conname, '') AS conname,
@@ -42,7 +40,7 @@
4341 $table = $db->tableName( $table, 'raw' );
4442 $res = $db->query(
4543 sprintf( $q,
46 - $db->addQuotes( $wgDBmwschema ),
 44+ $db->addQuotes( $db->getCoreSchema() ),
4745 $db->addQuotes( $table ),
4846 $db->addQuotes( $field )
4947 )
@@ -98,8 +96,86 @@
9997 }
10098
10199 /**
 100+ * Used to debug transaction processing
 101+ * Only used if $wgDebugDBTransactions is true
 102+ *
 103+ * @since 1.20
102104 * @ingroup Database
103105 */
 106+class PostgresTransactionState {
 107+
 108+ static $WATCHED = array(
 109+ array(
 110+ "desc" => "Connection state changed from %s -> %s\n",
 111+ "states" => array(
 112+ PGSQL_CONNECTION_OK => "OK",
 113+ PGSQL_CONNECTION_BAD => "BAD"
 114+ )
 115+ ),
 116+ array(
 117+ "desc" => "Transaction state changed from %s -> %s\n",
 118+ "states" => array(
 119+ PGSQL_TRANSACTION_IDLE => "IDLE",
 120+ PGSQL_TRANSACTION_ACTIVE => "ACTIVE",
 121+ PGSQL_TRANSACTION_INTRANS => "TRANS",
 122+ PGSQL_TRANSACTION_INERROR => "ERROR",
 123+ PGSQL_TRANSACTION_UNKNOWN => "UNKNOWN"
 124+ )
 125+ )
 126+ );
 127+
 128+ public function __construct( $conn ) {
 129+ $this->mConn = $conn;
 130+ $this->update();
 131+ $this->mCurrentState = $this->mNewState;
 132+ }
 133+
 134+ public function update() {
 135+ $this->mNewState = array(
 136+ pg_connection_status( $this->mConn ),
 137+ pg_transaction_status( $this->mConn )
 138+ );
 139+ }
 140+
 141+ public function check() {
 142+ global $wgDebugDBTransactions;
 143+ $this->update();
 144+ if ( $wgDebugDBTransactions ) {
 145+ if ( $this->mCurrentState !== $this->mNewState ) {
 146+ $old = reset( $this->mCurrentState );
 147+ $new = reset( $this->mNewState );
 148+ foreach ( self::$WATCHED as $watched ) {
 149+ if ($old !== $new) {
 150+ $this->log_changed($old, $new, $watched);
 151+ }
 152+ $old = next( $this->mCurrentState );
 153+ $new = next( $this->mNewState );
 154+
 155+ }
 156+ }
 157+ }
 158+ $this->mCurrentState = $this->mNewState;
 159+ }
 160+
 161+ protected function describe_changed( $status, $desc_table ) {
 162+ if( isset( $desc_table[$status] ) ) {
 163+ return $desc_table[$status];
 164+ } else {
 165+ return "STATUS " . $status;
 166+ }
 167+ }
 168+
 169+ protected function log_changed( $old, $new, $watched ) {
 170+ wfDebug(sprintf($watched["desc"],
 171+ $this->describe_changed( $old, $watched["states"] ),
 172+ $this->describe_changed( $new, $watched["states"] ))
 173+ );
 174+ }
 175+}
 176+
 177+/**
 178+ * @ingroup Database
 179+ */
104180 class DatabasePostgres extends DatabaseBase {
105181 var $mInsertId = null;
106182 var $mLastResult = null;
@@ -136,9 +212,8 @@
137213 }
138214
139215 function hasConstraint( $name ) {
140 - global $wgDBmwschema;
141216 $SQL = "SELECT 1 FROM pg_catalog.pg_constraint c, pg_catalog.pg_namespace n WHERE c.connamespace = n.oid AND conname = '" .
142 - pg_escape_string( $this->mConn, $name ) . "' AND n.nspname = '" . pg_escape_string( $this->mConn, $wgDBmwschema ) ."'";
 217+ pg_escape_string( $this->mConn, $name ) . "' AND n.nspname = '" . pg_escape_string( $this->mConn, $this->mConn->getCoreSchema() ) ."'";
143218 $res = $this->doQuery( $SQL );
144219 return $this->numRows( $res );
145220 }
@@ -177,10 +252,6 @@
178253 $connectVars['port'] = $port;
179254 }
180255 $this->connectString = $this->makeConnectionString( $connectVars, PGSQL_CONNECT_FORCE_NEW );
181 - $this->reOpen();
182 - }
183 -
184 - function reOpen() {
185256 $this->close();
186257 $this->installErrorHandler();
187258 $this->mConn = pg_connect( $this->connectString );
@@ -194,6 +265,7 @@
195266 }
196267
197268 $this->mOpened = true;
 269+ $this->mTransactionState = new PostgresTransactionState( $this->mConn );
198270
199271 global $wgCommandLineMode;
200272 # If called from the command-line (e.g. importDump), only show errors
@@ -207,12 +279,7 @@
208280 $this->query( "SET standard_conforming_strings = on", __METHOD__ );
209281
210282 global $wgDBmwschema;
211 - if ( $this->schemaExists( $wgDBmwschema ) ) {
212 - $safeschema = $this->addIdentifierQuotes( $wgDBmwschema );
213 - $this->doQuery( "SET search_path = $safeschema" );
214 - } else {
215 - $this->doQuery( "SET search_path = public" );
216 - }
 283+ $this->determineCoreSchema( $wgDBmwschema );
217284
218285 return $this->mConn;
219286 }
@@ -248,17 +315,20 @@
249316 }
250317
251318 protected function doQuery( $sql ) {
 319+ global $wgDebugDBTransactions;
252320 if ( function_exists( 'mb_convert_encoding' ) ) {
253321 $sql = mb_convert_encoding( $sql, 'UTF-8' );
254322 }
 323+ $this->mTransactionState->check();
255324 $this->mLastResult = pg_query( $this->mConn, $sql );
256 - $this->mAffectedRows = null; // use pg_affected_rows(mLastResult)
 325+ $this->mTransactionState->check();
 326+ $this->mAffectedRows = null;
257327 return $this->mLastResult;
258328 }
259329
260330 function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
 331+ /* Transaction stays in the ERROR state until rolledback */
261332 $this->rollback( __METHOD__ );
262 - $this->reOpen();
263333 parent::reportQueryError( $error, $errno, $sql, $fname, $tempIgnore );
264334 }
265335
@@ -502,7 +572,7 @@
503573 $tempsql .= '(' . $this->makeList( $row ) . ')';
504574
505575 if ( $ignore ) {
506 - pg_query( $this->mConn, "SAVEPOINT $ignore" );
 576+ $this->doQuery( "SAVEPOINT $ignore" );
507577 }
508578
509579 $tempres = (bool)$this->query( $tempsql, $fname, $ignore );
@@ -510,9 +580,9 @@
511581 if ( $ignore ) {
512582 $bar = pg_last_error();
513583 if ( $bar != false ) {
514 - pg_query( $this->mConn, "ROLLBACK TO $ignore" );
 584+ $this->doQuery( $this->mConn, "ROLLBACK TO $ignore" );
515585 } else {
516 - pg_query( $this->mConn, "RELEASE $ignore" );
 586+ $this->doQuery( $this->mConn, "RELEASE $ignore" );
517587 $numrowsinserted++;
518588 }
519589 }
@@ -527,7 +597,7 @@
528598 } else {
529599 // Not multi, just a lone insert
530600 if ( $ignore ) {
531 - pg_query($this->mConn, "SAVEPOINT $ignore");
 601+ $this->doQuery( "SAVEPOINT $ignore" );
532602 }
533603
534604 $sql .= '(' . $this->makeList( $args ) . ')';
@@ -535,9 +605,9 @@
536606 if ( $ignore ) {
537607 $bar = pg_last_error();
538608 if ( $bar != false ) {
539 - pg_query( $this->mConn, "ROLLBACK TO $ignore" );
 609+ $this->doQuery( "ROLLBACK TO $ignore" );
540610 } else {
541 - pg_query( $this->mConn, "RELEASE $ignore" );
 611+ $this->doQuery( "RELEASE $ignore" );
542612 $numrowsinserted++;
543613 }
544614 }
@@ -597,7 +667,7 @@
598668 }
599669 $olde = error_reporting( 0 );
600670 $numrowsinserted = 0;
601 - pg_query( $this->mConn, "SAVEPOINT $ignore");
 671+ $this->doQuery( "SAVEPOINT $ignore" );
602672 }
603673
604674 $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
@@ -614,9 +684,9 @@
615685 if( $ignore ) {
616686 $bar = pg_last_error();
617687 if( $bar != false ) {
618 - pg_query( $this->mConn, "ROLLBACK TO $ignore" );
 688+ $this->doQuery( "ROLLBACK TO $ignore" );
619689 } else {
620 - pg_query( $this->mConn, "RELEASE $ignore" );
 690+ $this->doQuery( "RELEASE $ignore" );
621691 $numrowsinserted++;
622692 }
623693 $olde = error_reporting( $olde );
@@ -702,10 +772,8 @@
703773 }
704774
705775 function listTables( $prefix = null, $fname = 'DatabasePostgres::listTables' ) {
706 - global $wgDBmwschema;
707 - $eschema = $this->addQuotes( $wgDBmwschema );
 776+ $eschema = $this->addQuotes( $this->getCoreSchema() );
708777 $result = $this->query( "SELECT tablename FROM pg_tables WHERE schemaname = $eschema", $fname );
709 -
710778 $endArray = array();
711779
712780 foreach( $result as $table ) {
@@ -723,6 +791,48 @@
724792 return wfTimestamp( TS_POSTGRES, $ts );
725793 }
726794
 795+
 796+ /*
 797+ * Posted by cc[plus]php[at]c2se[dot]com on 25-Mar-2009 09:12
 798+ * to http://www.php.net/manual/en/ref.pgsql.php
 799+ *
 800+ * Parsing a postgres array can be a tricky problem, he's my
 801+ * take on this, it handles multi-dimensional arrays plus
 802+ * escaping using a nasty regexp to determine the limits of each
 803+ * data-item.
 804+ *
 805+ * This should really be handled by PHP PostgreSQL module
 806+ *
 807+ * @since 1.20
 808+ * @param text string: postgreql array returned in a text form like {a,b}
 809+ * @param output string
 810+ * @param limit int
 811+ * @param offset int
 812+ * @return string
 813+ */
 814+
 815+ function pg_array_parse( $text, &$output, $limit = false, $offset = 1 ) {
 816+ if( false === $limit ) {
 817+ $limit = strlen( $text )-1;
 818+ $output = array();
 819+ }
 820+ if( '{}' != $text )
 821+ do {
 822+ if ( '{' != $text{$offset} ) {
 823+ preg_match( "/(\\{?\"([^\"\\\\]|\\\\.)*\"|[^,{}]+)+([,}]+)/",
 824+ $text, $match, 0, $offset );
 825+ $offset += strlen( $match[0] );
 826+ $output[] = ( '"' != $match[1]{0}
 827+ ? $match[1]
 828+ : stripcslashes( substr( $match[1], 1, -1 ) ) );
 829+ if ( '},' == $match[3] )
 830+ return $output;
 831+ } else
 832+ $offset = $this->pg_array_parse( $text, $output[], $limit, $offset+1 );
 833+ } while ( $limit > $offset );
 834+ return $output;
 835+ }
 836+
727837 /**
728838 * Return aggregated value function call
729839 */
@@ -737,7 +847,115 @@
738848 return '[http://www.postgresql.org/ PostgreSQL]';
739849 }
740850
 851+
741852 /**
 853+ * Return current schema (executes SELECT current_schema())
 854+ * Needs transaction
 855+ *
 856+ * @since 1.20
 857+ * @return string return default schema for the current session
 858+ */
 859+ function getCurrentSchema() {
 860+ $res = $this->query( "SELECT current_schema()", __METHOD__);
 861+ $row = $this->fetchRow( $res );
 862+ return $row[0];
 863+ }
 864+
 865+ /**
 866+ * Return list of schemas which are accessible without schema name
 867+ * This is list does not contain magic keywords like "$user"
 868+ * Needs transaction
 869+ *
 870+ * @seealso getSearchPath()
 871+ * @seealso setSearchPath()
 872+ * @since 1.20
 873+ * @return array list of actual schemas for the current sesson
 874+ */
 875+ function getSchemas() {
 876+ $res = $this->query( "SELECT current_schemas(false)", __METHOD__);
 877+ $row = $this->fetchRow( $res );
 878+ $schemas = array();
 879+ /* PHP pgsql support does not support array type, "{a,b}" string is returned */
 880+ return $this->pg_array_parse($row[0], $schemas);
 881+ }
 882+
 883+ /**
 884+ * Return search patch for schemas
 885+ * This is different from getSchemas() since it contain magic keywords
 886+ * (like "$user").
 887+ * Needs transaction
 888+ *
 889+ * @since 1.20
 890+ * @return array how to search for table names schemas for the current user
 891+ */
 892+ function getSearchPath() {
 893+ $res = $this->query( "SHOW search_path", __METHOD__);
 894+ $row = $this->fetchRow( $res );
 895+ /* PostgreSQL returns SHOW values as strings */
 896+ return explode(",", $row[0]);
 897+ }
 898+
 899+ function setSearchPath( $search_path ) {
 900+ /**
 901+ * Update search_path, values should already be sanitized
 902+ * Values may contain magic keywords like "$user"
 903+ * @since 1.20
 904+ *
 905+ * @param array list of schemas to be searched by default
 906+ */
 907+ $this->query( "SET search_path = " . implode(", ", $search_path) );
 908+ }
 909+
 910+ /**
 911+ * Determine default schema for MediaWiki core
 912+ * Adjust this session schema search path if desired schema exists
 913+ * and is not alread there.
 914+ *
 915+ * We need to have name of the core schema stored to be able
 916+ * to query database metadata.
 917+ *
 918+ * This will be also called by the installer after the schema is created
 919+ *
 920+ * @since 1.20
 921+ * @param desired_schema string
 922+ */
 923+ function determineCoreSchema( $desired_schema ) {
 924+ $this->begin( __METHOD__ );
 925+ if ( $this->schemaExists( $desired_schema ) ) {
 926+ if ( in_array( $desired_schema, $this->getSchemas() ) ) {
 927+ $this->mCoreSchema = $desired_schema;
 928+ wfDebug("Schema \"" . $desired_schema . "\" already in the search path\n");
 929+ } else {
 930+ /**
 931+ * Apped our schema (e.g. 'mediawiki') in front
 932+ * of the search path
 933+ * Fixes bug 15816
 934+ */
 935+ $search_path = $this->getSearchPath();
 936+ array_unshift( $search_path,
 937+ $this->addIdentifierQuotes( $desired_schema ));
 938+ $this->setSearchPath( $search_path );
 939+ wfDebug("Schema \"" . $desired_schema . "\" added to the search path\n");
 940+ }
 941+ } else {
 942+ $this->mCoreSchema = $this->getCurrentSchema();
 943+ wfDebug("Schema \"" . $desired_schema . "\" not found, using current \"". $this->mCoreSchema ."\"\n");
 944+ }
 945+ /* Commit SET otherwise it will be rollbacked on error or IGNORE SELECT */
 946+ $this->commit( __METHOD__ );
 947+ }
 948+
 949+ /**
 950+ * Return schema name fore core MediaWiki tables
 951+ *
 952+ * @since 1.20
 953+ * @return string core schema name
 954+ */
 955+ function getCoreSchema() {
 956+ return $this->mCoreSchema;
 957+ }
 958+
 959+ /**
742960 * @return string Version information from the database
743961 */
744962 function getServerVersion() {
@@ -763,12 +981,11 @@
764982 * @return bool
765983 */
766984 function relationExists( $table, $types, $schema = false ) {
767 - global $wgDBmwschema;
768985 if ( !is_array( $types ) ) {
769986 $types = array( $types );
770987 }
771988 if ( !$schema ) {
772 - $schema = $wgDBmwschema;
 989+ $schema = $this->getCoreSchema();
773990 }
774991 $table = $this->tableName( $table, 'raw' );
775992 $etable = $this->addQuotes( $table );
@@ -795,8 +1012,6 @@
7961013 }
7971014
7981015 function triggerExists( $table, $trigger ) {
799 - global $wgDBmwschema;
800 -
8011016 $q = <<<SQL
8021017 SELECT 1 FROM pg_class, pg_namespace, pg_trigger
8031018 WHERE relnamespace=pg_namespace.oid AND relkind='r'
@@ -806,7 +1021,7 @@
8071022 $res = $this->query(
8081023 sprintf(
8091024 $q,
810 - $this->addQuotes( $wgDBmwschema ),
 1025+ $this->addQuotes( $this->getCoreSchema() ),
8111026 $this->addQuotes( $table ),
8121027 $this->addQuotes( $trigger )
8131028 )
@@ -819,22 +1034,20 @@
8201035 }
8211036
8221037 function ruleExists( $table, $rule ) {
823 - global $wgDBmwschema;
8241038 $exists = $this->selectField( 'pg_rules', 'rulename',
8251039 array(
8261040 'rulename' => $rule,
8271041 'tablename' => $table,
828 - 'schemaname' => $wgDBmwschema
 1042+ 'schemaname' => $this->getCoreSchema()
8291043 )
8301044 );
8311045 return $exists === $rule;
8321046 }
8331047
8341048 function constraintExists( $table, $constraint ) {
835 - global $wgDBmwschema;
8361049 $SQL = sprintf( "SELECT 1 FROM information_schema.table_constraints ".
8371050 "WHERE constraint_schema = %s AND table_name = %s AND constraint_name = %s",
838 - $this->addQuotes( $wgDBmwschema ),
 1051+ $this->addQuotes( $this->getCoreSchema() ),
8391052 $this->addQuotes( $table ),
8401053 $this->addQuotes( $constraint )
8411054 );
Index: trunk/phase3/includes/db/Database.php
@@ -784,7 +784,7 @@
785785 * @return bool
786786 */
787787 function isWriteQuery( $sql ) {
788 - return !preg_match( '/^(?:SELECT|BEGIN|COMMIT|SET|SHOW|\(SELECT)\b/i', $sql );
 788+ return !preg_match( '/^(?:SELECT|BEGIN|ROLLBACK|COMMIT|SET|SHOW|\(SELECT)\b/i', $sql );
789789 }
790790
791791 /**
Index: trunk/phase3/includes/installer/PostgresUpdater.php
@@ -270,7 +270,6 @@
271271 }
272272
273273 protected function describeTable( $table ) {
274 - global $wgDBmwschema;
275274 $q = <<<END
276275 SELECT attname, attnum FROM pg_namespace, pg_class, pg_attribute
277276 WHERE pg_class.relnamespace = pg_namespace.oid
@@ -279,7 +278,7 @@
280279 END;
281280 $res = $this->db->query( sprintf( $q,
282281 $this->db->addQuotes( $table ),
283 - $this->db->addQuotes( $wgDBmwschema ) ) );
 282+ $this->db->addQuotes( $this->db->getCoreSchema() ) ) );
284283 if ( !$res ) {
285284 return null;
286285 }
@@ -295,8 +294,6 @@
296295 }
297296
298297 function describeIndex( $idx ) {
299 - global $wgDBmwschema;
300 -
301298 // first fetch the key (which is a list of columns ords) and
302299 // the table the index applies to (an oid)
303300 $q = <<<END
@@ -309,7 +306,7 @@
310307 $res = $this->db->query(
311308 sprintf(
312309 $q,
313 - $this->db->addQuotes( $wgDBmwschema ),
 310+ $this->db->addQuotes( $this->db->getCoreSchea() ),
314311 $this->db->addQuotes( $idx )
315312 )
316313 );
@@ -346,7 +343,6 @@
347344 }
348345
349346 function fkeyDeltype( $fkey ) {
350 - global $wgDBmwschema;
351347 $q = <<<END
352348 SELECT confdeltype FROM pg_constraint, pg_namespace
353349 WHERE connamespace=pg_namespace.oid
@@ -356,7 +352,7 @@
357353 $r = $this->db->query(
358354 sprintf(
359355 $q,
360 - $this->db->addQuotes( $wgDBmwschema ),
 356+ $this->db->addQuotes( $this->db->getCoreSchema() ),
361357 $this->db->addQuotes( $fkey )
362358 )
363359 );
@@ -367,7 +363,6 @@
368364 }
369365
370366 function ruleDef( $table, $rule ) {
371 - global $wgDBmwschema;
372367 $q = <<<END
373368 SELECT definition FROM pg_rules
374369 WHERE schemaname = %s
@@ -377,7 +372,7 @@
378373 $r = $this->db->query(
379374 sprintf(
380375 $q,
381 - $this->db->addQuotes( $wgDBmwschema ),
 376+ $this->db->addQuotes( $this->db->getCoreSchema() ),
382377 $this->db->addQuotes( $table ),
383378 $this->db->addQuotes( $rule )
384379 )
Index: trunk/phase3/includes/installer/PostgresInstaller.php
@@ -431,10 +431,6 @@
432432 $conn = $status->value;
433433
434434 $dbName = $this->getVar( 'wgDBname' );
435 - //$schema = $this->getVar( 'wgDBmwschema' );
436 - //$user = $this->getVar( 'wgDBuser' );
437 - //$safeschema = $conn->addIdentifierQuotes( $schema );
438 - //$safeuser = $conn->addIdentifierQuotes( $user );
439435
440436 $exists = $conn->selectField( '"pg_catalog"."pg_database"', '1',
441437 array( 'datname' => $dbName ), __METHOD__ );
@@ -466,14 +462,8 @@
467463 }
468464 }
469465
470 - // If we created a user, alter it now to search the new schema by default
471 - if ( $this->getVar( '_CreateDBAccount' ) ) {
472 - $conn->query( "ALTER ROLE $safeuser SET search_path = $safeschema, public",
473 - __METHOD__ );
474 - }
475 -
476466 // Select the new schema in the current connection
477 - $conn->query( "SET search_path = $safeschema" );
 467+ $conn->determineCoreSchema( $schema );
478468 return Status::newGood();
479469 }
480470
@@ -493,10 +483,8 @@
494484 }
495485 $conn = $status->value;
496486
497 - //$schema = $this->getVar( 'wgDBmwschema' );
498487 $safeuser = $conn->addIdentifierQuotes( $this->getVar( 'wgDBuser' ) );
499488 $safepass = $conn->addQuotes( $this->getVar( 'wgDBpassword' ) );
500 - //$safeschema = $conn->addIdentifierQuotes( $schema );
501489
502490 // Check if the user already exists
503491 $userExists = $conn->roleExists( $this->getVar( 'wgDBuser' ) );
Index: trunk/phase3/includes/DefaultSettings.php
@@ -4060,6 +4060,11 @@
40614061 $wgDebugComments = false;
40624062
40634063 /**
 4064+ * Extensive database transaction state debugging
 4065+ */
 4066+$wgDebugDBTransactions = false;
 4067+
 4068+/**
40644069 * Write SQL queries to the debug log
40654070 */
40664071 $wgDebugDumpSql = false;
Index: trunk/phase3/RELEASE-NOTES-1.20
@@ -22,6 +22,7 @@
2323 * (bug 27619) Remove preference option to display broken links as link?
2424 * (bug 34896) Update jQuery JSON plugin to v2.3 (2011-09-17)
2525 * (bug 34302) Add CSS classes to email fields in user preferences
 26+* Introduced $wgDebugDBTransactions to trace transaction status (currently PostgreSQL only)
2627
2728 === Bug fixes in 1.20 ===
2829 * (bug 30245) Use the correct way to construct a log page title.
@@ -42,6 +43,7 @@
4344 Special:MyPage and Special:MyTalk
4445 * (bug 34929) Show the correct diff when a section edit is rejected by the spam
4546 filter
 47+* (bug 15816) Add a switch for SETting the search_path (Postgres)
4648
4749 === API changes in 1.20 ===
4850 * (bug 34316) Add ability to retrieve maximum upload size from MediaWiki API.

Follow-up revisions

RevisionCommit summaryAuthorDate
r113498Fix broken unit tests post r113487...reedy18:52, 9 March 2012
r113499Fix up some documentation weirdness from r113487reedy18:55, 9 March 2012
r113500PHP Fatal error: Call to undefined method DatabasePostgres::getCoreSchea() i...reedy19:01, 9 March 2012
r113501Fix syntax error and indenting from r113487reedy19:05, 9 March 2012
r113534Fix PostgreSQL updater broken by r113487saper22:29, 9 March 2012

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r82674Various Postgres fixes (bug 26612 stuff)...demon16:01, 23 February 2011
r89393Apply a patch adapted from the one on Bug #16794...mah04:10, 3 June 2011
r106025Bug 16794 - $wgSharedDB PostgreSQL support...mah15:06, 13 December 2011
r113408PostgreSQL: Improve SQL error handling...saper21:44, 8 March 2012

Comments

#Comment by Saper (talk | contribs)   17:26, 9 March 2012

Improved error handling is worth adding in 1.19

#Comment by Reedy (talk | contribs)   18:52, 9 March 2012

pg_array_parse:

  • You're missing a few extra braces
    • On the if( '{}' != $text )
    • On if ( '},' == $match[3] )
    • On the else
$offset = $this->pg_array_parse( $text, $output[], $limit, $offset+1 );

That isn't valid syntax, you either want to just use $output, or $output[$foobar]


You'd also broken UnitTests, but fixed that in r113498

[exec] PHP Fatal error:  Call to a member function getCoreSchema() on a non-object in /var/lib/jenkins/jobs/MediaWiki-postgres-phpunit/workspace/mw-core/includes/db/DatabasePostgres.php on line 216
#Comment by Saper (talk | contribs)   19:22, 9 March 2012

Thanks for fixing those.

Still need to fix updater:


Yeah, thanks for
"CREATE SEQUENCE logging_log_id_seq"
from within function "".
Database returned error "1: ERROR:  relation "logging_log_id_seq" already exists"
Backtrace:
#0 /usr/home/saper/public_html/pg/w/includes/db/DatabasePostgres.php(332): DatabaseBase->reportQueryError('ERROR:  relatio...', 1, 'CREATE SEQUENCE...', '', false)
#1 /usr/home/saper/public_html/pg/w/includes/db/Database.php(906): DatabasePostgres->reportQueryError('ERROR:  relatio...', 1, 'CREATE SEQUENCE...', '', false)
#2 /usr/home/saper/public_html/pg/w/includes/installer/PostgresUpdater.php(393): DatabaseBase->query('CREATE SEQUENCE...')
#3 [internal function]: PostgresUpdater->addSequence('logging_log_id_...')
#4 /usr/home/saper/public_html/pg/w/includes/installer/DatabaseUpdater.php(281): call_user_func_array(Array, Array)
#5 /usr/home/saper/public_html/pg/w/includes/installer/DatabaseUpdater.php(244): DatabaseUpdater->runUpdates(Array, false)
#6 /usr/home/saper/public_html/pg/w/maintenance/update.php(121): DatabaseUpdater->doUpdates(Array)
#7 /usr/home/saper/public_html/pg/w/maintenance/doMaintenance.php(105): UpdateMediaWiki->execute()
#Comment by Saper (talk | contribs)   22:30, 9 March 2012

Repaired in r113487

#Comment by Saper (talk | contribs)   22:31, 9 March 2012

er, r113534

#Comment by Saper (talk | contribs)   17:45, 15 March 2012

Issues fixed by followup edits.

#Comment by Saper (talk | contribs)   17:45, 15 March 2012

Issues fixed by followup edits.

#Comment by MaxSem (talk | contribs)   17:40, 21 March 2012

Is everything resolved here?

#Comment by Saper (talk | contribs)   18:59, 21 March 2012

Should be fine already.

I am using this code to track down things like bug 35357 and bug 35358 as well as I got finally the PostgreSQL updater doing its job.

#Comment by 😂 (talk | contribs)   19:01, 21 March 2012

I'm going to tentatively mark this resolved. Everything *looks* fixed and the postgres unit tests are passing.

#Comment by Krinkle (talk | contribs)   05:02, 5 July 2012

Reminder: Old revs in svn tagged for merging to 1.19. Please remove tag when done or no longer relevant.

Status & tagging log