123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- <?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();
- }
- }
|