summaryrefslogtreecommitdiff
path: root/www/wiki/tests/phpunit/includes/db/DatabasePostgresTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/tests/phpunit/includes/db/DatabasePostgresTest.php')
-rw-r--r--www/wiki/tests/phpunit/includes/db/DatabasePostgresTest.php177
1 files changed, 177 insertions, 0 deletions
diff --git a/www/wiki/tests/phpunit/includes/db/DatabasePostgresTest.php b/www/wiki/tests/phpunit/includes/db/DatabasePostgresTest.php
new file mode 100644
index 00000000..5c2aa2bb
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/db/DatabasePostgresTest.php
@@ -0,0 +1,177 @@
+<?php
+
+use Wikimedia\Rdbms\IDatabase;
+use Wikimedia\Rdbms\DatabasePostgres;
+use Wikimedia\ScopedCallback;
+use Wikimedia\TestingAccessWrapper;
+
+/**
+ * @group Database
+ */
+class DatabasePostgresTest extends MediaWikiTestCase {
+
+ private function doTestInsertIgnore() {
+ $reset = new ScopedCallback( function () {
+ if ( $this->db->explicitTrxActive() ) {
+ $this->db->rollback( __METHOD__ );
+ }
+ $this->db->query( 'DROP TABLE IF EXISTS ' . $this->db->tableName( 'foo' ) );
+ } );
+
+ $this->db->query(
+ "CREATE TEMPORARY TABLE {$this->db->tableName( 'foo' )} (i INTEGER NOT NULL PRIMARY KEY)"
+ );
+ $this->db->insert( 'foo', [ [ 'i' => 1 ], [ 'i' => 2 ] ], __METHOD__ );
+
+ // Normal INSERT IGNORE
+ $this->db->begin( __METHOD__ );
+ $this->db->insert(
+ 'foo', [ [ 'i' => 3 ], [ 'i' => 2 ], [ 'i' => 5 ] ], __METHOD__, [ 'IGNORE' ]
+ );
+ $this->assertSame( 2, $this->db->affectedRows() );
+ $this->assertSame(
+ [ '1', '2', '3', '5' ],
+ $this->db->selectFieldValues( 'foo', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
+ );
+ $this->db->rollback( __METHOD__ );
+
+ // INSERT IGNORE doesn't ignore stuff like NOT NULL violations
+ $this->db->begin( __METHOD__ );
+ $this->db->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+ try {
+ $this->db->insert(
+ 'foo', [ [ 'i' => 7 ], [ 'i' => null ] ], __METHOD__, [ 'IGNORE' ]
+ );
+ $this->db->endAtomic( __METHOD__ );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( DBQueryError $e ) {
+ $this->assertSame( 0, $this->db->affectedRows() );
+ $this->db->cancelAtomic( __METHOD__ );
+ }
+ $this->assertSame(
+ [ '1', '2' ],
+ $this->db->selectFieldValues( 'foo', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
+ );
+ $this->db->rollback( __METHOD__ );
+ }
+
+ /**
+ * @covers Wikimedia\Rdbms\DatabasePostgres::insert
+ */
+ public function testInsertIgnoreOld() {
+ if ( !$this->db instanceof DatabasePostgres ) {
+ $this->markTestSkipped( 'Not PostgreSQL' );
+ }
+ if ( $this->db->getServerVersion() < 9.5 ) {
+ $this->doTestInsertIgnore();
+ } else {
+ // Hack version to make it take the old code path
+ $w = TestingAccessWrapper::newFromObject( $this->db );
+ $oldVer = $w->numericVersion;
+ $w->numericVersion = 9.4;
+ try {
+ $this->doTestInsertIgnore();
+ } finally {
+ $w->numericVersion = $oldVer;
+ }
+ }
+ }
+
+ /**
+ * @covers Wikimedia\Rdbms\DatabasePostgres::insert
+ */
+ public function testInsertIgnoreNew() {
+ if ( !$this->db instanceof DatabasePostgres ) {
+ $this->markTestSkipped( 'Not PostgreSQL' );
+ }
+ if ( $this->db->getServerVersion() < 9.5 ) {
+ $this->markTestSkipped( 'PostgreSQL version is ' . $this->db->getServerVersion() );
+ }
+
+ $this->doTestInsertIgnore();
+ }
+
+ private function doTestInsertSelectIgnore() {
+ $reset = new ScopedCallback( function () {
+ if ( $this->db->explicitTrxActive() ) {
+ $this->db->rollback( __METHOD__ );
+ }
+ $this->db->query( 'DROP TABLE IF EXISTS ' . $this->db->tableName( 'foo' ) );
+ $this->db->query( 'DROP TABLE IF EXISTS ' . $this->db->tableName( 'bar' ) );
+ } );
+
+ $this->db->query(
+ "CREATE TEMPORARY TABLE {$this->db->tableName( 'foo' )} (i INTEGER)"
+ );
+ $this->db->query(
+ "CREATE TEMPORARY TABLE {$this->db->tableName( 'bar' )} (i INTEGER NOT NULL PRIMARY KEY)"
+ );
+ $this->db->insert( 'bar', [ [ 'i' => 1 ], [ 'i' => 2 ] ], __METHOD__ );
+
+ // Normal INSERT IGNORE
+ $this->db->begin( __METHOD__ );
+ $this->db->insert( 'foo', [ [ 'i' => 3 ], [ 'i' => 2 ], [ 'i' => 5 ] ], __METHOD__ );
+ $this->db->insertSelect( 'bar', 'foo', [ 'i' => 'i' ], [], __METHOD__, [ 'IGNORE' ] );
+ $this->assertSame( 2, $this->db->affectedRows() );
+ $this->assertSame(
+ [ '1', '2', '3', '5' ],
+ $this->db->selectFieldValues( 'bar', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
+ );
+ $this->db->rollback( __METHOD__ );
+
+ // INSERT IGNORE doesn't ignore stuff like NOT NULL violations
+ $this->db->begin( __METHOD__ );
+ $this->db->insert( 'foo', [ [ 'i' => 7 ], [ 'i' => null ] ], __METHOD__ );
+ $this->db->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+ try {
+ $this->db->insertSelect( 'bar', 'foo', [ 'i' => 'i' ], [], __METHOD__, [ 'IGNORE' ] );
+ $this->db->endAtomic( __METHOD__ );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( DBQueryError $e ) {
+ $this->assertSame( 0, $this->db->affectedRows() );
+ $this->db->cancelAtomic( __METHOD__ );
+ }
+ $this->assertSame(
+ [ '1', '2' ],
+ $this->db->selectFieldValues( 'bar', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
+ );
+ $this->db->rollback( __METHOD__ );
+ }
+
+ /**
+ * @covers Wikimedia\Rdbms\DatabasePostgres::nativeInsertSelect
+ */
+ public function testInsertSelectIgnoreOld() {
+ if ( !$this->db instanceof DatabasePostgres ) {
+ $this->markTestSkipped( 'Not PostgreSQL' );
+ }
+ if ( $this->db->getServerVersion() < 9.5 ) {
+ $this->doTestInsertSelectIgnore();
+ } else {
+ // Hack version to make it take the old code path
+ $w = TestingAccessWrapper::newFromObject( $this->db );
+ $oldVer = $w->numericVersion;
+ $w->numericVersion = 9.4;
+ try {
+ $this->doTestInsertSelectIgnore();
+ } finally {
+ $w->numericVersion = $oldVer;
+ }
+ }
+ }
+
+ /**
+ * @covers Wikimedia\Rdbms\DatabasePostgres::nativeInsertSelect
+ */
+ public function testInsertSelectIgnoreNew() {
+ if ( !$this->db instanceof DatabasePostgres ) {
+ $this->markTestSkipped( 'Not PostgreSQL' );
+ }
+ if ( $this->db->getServerVersion() < 9.5 ) {
+ $this->markTestSkipped( 'PostgreSQL version is ' . $this->db->getServerVersion() );
+ }
+
+ $this->doTestInsertSelectIgnore();
+ }
+
+}