From: Brad Jorsch Date: Wed, 30 Aug 2017 19:51:50 +0000 (-0400) Subject: Fix various PostgreSQL failures X-Git-Tag: 1.31.0-rc.0~2253 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/exercices/bilan.php?a=commitdiff_plain;h=91b86399b1ea8fa51750f7cd836651993f23ff9a;p=lhc%2Fweb%2Fwiklou.git Fix various PostgreSQL failures * Fix schema for image_comment_temp. * Provide values in CommentStoreTest::provideInsertRoundTrip() for columns where the PG schema doesn't have a default value but the MySQL schema does. * Call nextSequenceValue() from CommentStoreTest::testInsertRoundTrip(). * Correctly handle $options being the string 'FOR UPDATE' in DatabasePostgres::selectSQLText() * Correctly handle the initial table in DatabasePostgres::selectSQLText() FOR UPDATE mangling. * Correctly handle aliases in DatabasePostgres::selectSQLText() FOR UPDATE mangling. Tests in PG are still going to be broken thanks to the fact that nextSequenceValue() and insertId() can't be separated by another nextSequenceValue()/insertId() pair. That should be taken care of by T164898/T164900. Change-Id: Ia770a003ca9170ab8bcc1436d8afe30700e00ada --- diff --git a/includes/libs/rdbms/database/DatabasePostgres.php b/includes/libs/rdbms/database/DatabasePostgres.php index bdac06c121..fcfd93700d 100644 --- a/includes/libs/rdbms/database/DatabasePostgres.php +++ b/includes/libs/rdbms/database/DatabasePostgres.php @@ -521,6 +521,10 @@ __INDEXATTR__; public function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__, $options = [], $join_conds = [] ) { + if ( is_string( $options ) ) { + $options = [ $options ]; + } + // Change the FOR UPDATE option as necessary based on the join conditions. Then pass // to the parent function to get the actual SQL text. // In Postgres when using FOR UPDATE, only the main table and tables that are inner joined @@ -532,12 +536,28 @@ __INDEXATTR__; $forUpdateKey = array_search( 'FOR UPDATE', $options, true ); if ( $forUpdateKey !== false && $join_conds ) { unset( $options[$forUpdateKey] ); + $options['FOR UPDATE'] = []; + + // All tables not in $join_conds are good + foreach ( $table as $alias => $name ) { + if ( is_numeric( $alias ) ) { + $alias = $name; + } + if ( !isset( $join_conds[$alias] ) ) { + $options['FOR UPDATE'][] = $alias; + } + } foreach ( $join_conds as $table_cond => $join_cond ) { if ( 0 === preg_match( '/^(?:LEFT|RIGHT|FULL)(?: OUTER)? JOIN$/i', $join_cond[0] ) ) { $options['FOR UPDATE'][] = $table_cond; } } + + // Quote alias names so $this->tableName() won't mangle them + $options['FOR UPDATE'] = array_map( function ( $name ) use ( $table ) { + return isset( $table[$name] ) ? $this->addIdentifierQuotes( $name ) : $name; + }, $options['FOR UPDATE'] ); } if ( isset( $options['ORDER BY'] ) && $options['ORDER BY'] == 'NULL' ) { diff --git a/maintenance/postgres/archives/patch-comment-table.sql b/maintenance/postgres/archives/patch-comment-table.sql index 8f2b3f32ae..243a3b3144 100644 --- a/maintenance/postgres/archives/patch-comment-table.sql +++ b/maintenance/postgres/archives/patch-comment-table.sql @@ -21,7 +21,7 @@ CREATE UNIQUE INDEX revcomment_rev ON revision_comment_temp (revcomment_rev); CREATE TABLE image_comment_temp ( imgcomment_name TEXT NOT NULL, - imgcomment_comment_id INTEGER NOT NULL, - PRIMARY KEY (imgcomment_name, imgcomment_comment_id) + imgcomment_description_id INTEGER NOT NULL, + PRIMARY KEY (imgcomment_name, imgcomment_description_id) ); CREATE UNIQUE INDEX imgcomment_name ON image_comment_temp (imgcomment_name); diff --git a/maintenance/postgres/tables.sql b/maintenance/postgres/tables.sql index c7ace89c9e..eea9e68514 100644 --- a/maintenance/postgres/tables.sql +++ b/maintenance/postgres/tables.sql @@ -358,8 +358,8 @@ CREATE INDEX img_sha1 ON image (img_sha1); CREATE TABLE image_comment_temp ( imgcomment_name TEXT NOT NULL, - imgcomment_comment_id INTEGER NOT NULL, - PRIMARY KEY (imgcomment_name, imgcomment_comment_id) + imgcomment_description_id INTEGER NOT NULL, + PRIMARY KEY (imgcomment_name, imgcomment_description_id) ); CREATE UNIQUE INDEX imgcomment_name ON image_comment_temp (imgcomment_name); diff --git a/tests/phpunit/includes/CommentStoreTest.php b/tests/phpunit/includes/CommentStoreTest.php index 6dd092524e..b65136aded 100644 --- a/tests/phpunit/includes/CommentStoreTest.php +++ b/tests/phpunit/includes/CommentStoreTest.php @@ -363,6 +363,7 @@ class CommentStoreTest extends MediaWikiLangTestCase { $this->assertArrayNotHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" ); } + $extraFields[$pk] = $this->db->nextSequenceValue( "{$table}_{$pk}_seq" ); $this->db->insert( $table, $extraFields + $fields, __METHOD__ ); $id = $this->db->insertId(); if ( $usesTemp ) { @@ -404,17 +405,25 @@ class CommentStoreTest extends MediaWikiLangTestCase { } public static function provideInsertRoundTrip() { + $db = wfGetDB( DB_REPLICA ); // for timestamps + $msgComment = new Message( 'parentheses', [ 'message comment' ] ); $textCommentMsg = new RawMessage( '$1', [ 'text comment' ] ); $nestedMsgComment = new Message( [ 'parentheses', 'rawmessage' ], [ new Message( 'mainpage' ) ] ); $ipbfields = [ 'ipb_range_start' => '', 'ipb_range_end' => '', + 'ipb_by' => 0, + 'ipb_timestamp' => $db->timestamp(), + 'ipb_expiry' => $db->getInfinity(), ]; $revfields = [ 'rev_page' => 42, 'rev_text_id' => 42, 'rev_len' => 0, + 'rev_user' => 0, + 'rev_user_text' => '', + 'rev_timestamp' => $db->timestamp(), ]; $comStoreComment = new CommentStoreComment( null, 'comment store comment', null, [ 'foo' => 'bar' ]