3 use Wikimedia\Rdbms\IDatabase
;
4 use Wikimedia\Rdbms\DatabasePostgres
;
5 use Wikimedia\ScopedCallback
;
6 use Wikimedia\TestingAccessWrapper
;
11 class DatabasePostgresTest
extends MediaWikiTestCase
{
13 private function doTestInsertIgnore() {
14 $reset = new ScopedCallback( function () {
15 if ( $this->db
->explicitTrxActive() ) {
16 $this->db
->rollback( __METHOD__
);
18 $this->db
->query( 'DROP TABLE IF EXISTS ' . $this->db
->tableName( 'foo' ) );
22 "CREATE TEMPORARY TABLE {$this->db->tableName( 'foo' )} (i INTEGER NOT NULL PRIMARY KEY)"
24 $this->db
->insert( 'foo', [ [ 'i' => 1 ], [ 'i' => 2 ] ], __METHOD__
);
26 // Normal INSERT IGNORE
27 $this->db
->begin( __METHOD__
);
29 'foo', [ [ 'i' => 3 ], [ 'i' => 2 ], [ 'i' => 5 ] ], __METHOD__
, [ 'IGNORE' ]
31 $this->assertSame( 2, $this->db
->affectedRows() );
33 [ '1', '2', '3', '5' ],
34 $this->db
->selectFieldValues( 'foo', 'i', [], __METHOD__
, [ 'ORDER BY' => 'i' ] )
36 $this->db
->rollback( __METHOD__
);
38 // INSERT IGNORE doesn't ignore stuff like NOT NULL violations
39 $this->db
->begin( __METHOD__
);
40 $this->db
->startAtomic( __METHOD__
, IDatabase
::ATOMIC_CANCELABLE
);
43 'foo', [ [ 'i' => 7 ], [ 'i' => null ] ], __METHOD__
, [ 'IGNORE' ]
45 $this->db
->endAtomic( __METHOD__
);
46 $this->fail( 'Expected exception not thrown' );
47 } catch ( DBQueryError
$e ) {
48 $this->assertSame( 0, $this->db
->affectedRows() );
49 $this->db
->cancelAtomic( __METHOD__
);
53 $this->db
->selectFieldValues( 'foo', 'i', [], __METHOD__
, [ 'ORDER BY' => 'i' ] )
55 $this->db
->rollback( __METHOD__
);
59 * @covers Wikimedia\Rdbms\DatabasePostgres::insert
61 public function testInsertIgnoreOld() {
62 if ( !$this->db
instanceof DatabasePostgres
) {
63 $this->markTestSkipped( 'Not PostgreSQL' );
65 if ( $this->db
->getServerVersion() < 9.5 ) {
66 $this->doTestInsertIgnore();
68 // Hack version to make it take the old code path
69 $w = TestingAccessWrapper
::newFromObject( $this->db
);
70 $oldVer = $w->numericVersion
;
71 $w->numericVersion
= 9.4;
73 $this->doTestInsertIgnore();
75 $w->numericVersion
= $oldVer;
81 * @covers Wikimedia\Rdbms\DatabasePostgres::insert
83 public function testInsertIgnoreNew() {
84 if ( !$this->db
instanceof DatabasePostgres
) {
85 $this->markTestSkipped( 'Not PostgreSQL' );
87 if ( $this->db
->getServerVersion() < 9.5 ) {
88 $this->markTestSkipped( 'PostgreSQL version is ' . $this->db
->getServerVersion() );
91 $this->doTestInsertIgnore();
94 private function doTestInsertSelectIgnore() {
95 $reset = new ScopedCallback( function () {
96 if ( $this->db
->explicitTrxActive() ) {
97 $this->db
->rollback( __METHOD__
);
99 $this->db
->query( 'DROP TABLE IF EXISTS ' . $this->db
->tableName( 'foo' ) );
100 $this->db
->query( 'DROP TABLE IF EXISTS ' . $this->db
->tableName( 'bar' ) );
104 "CREATE TEMPORARY TABLE {$this->db->tableName( 'foo' )} (i INTEGER)"
107 "CREATE TEMPORARY TABLE {$this->db->tableName( 'bar' )} (i INTEGER NOT NULL PRIMARY KEY)"
109 $this->db
->insert( 'bar', [ [ 'i' => 1 ], [ 'i' => 2 ] ], __METHOD__
);
111 // Normal INSERT IGNORE
112 $this->db
->begin( __METHOD__
);
113 $this->db
->insert( 'foo', [ [ 'i' => 3 ], [ 'i' => 2 ], [ 'i' => 5 ] ], __METHOD__
);
114 $this->db
->insertSelect( 'bar', 'foo', [ 'i' => 'i' ], [], __METHOD__
, [ 'IGNORE' ] );
115 $this->assertSame( 2, $this->db
->affectedRows() );
117 [ '1', '2', '3', '5' ],
118 $this->db
->selectFieldValues( 'bar', 'i', [], __METHOD__
, [ 'ORDER BY' => 'i' ] )
120 $this->db
->rollback( __METHOD__
);
122 // INSERT IGNORE doesn't ignore stuff like NOT NULL violations
123 $this->db
->begin( __METHOD__
);
124 $this->db
->insert( 'foo', [ [ 'i' => 7 ], [ 'i' => null ] ], __METHOD__
);
125 $this->db
->startAtomic( __METHOD__
, IDatabase
::ATOMIC_CANCELABLE
);
127 $this->db
->insertSelect( 'bar', 'foo', [ 'i' => 'i' ], [], __METHOD__
, [ 'IGNORE' ] );
128 $this->db
->endAtomic( __METHOD__
);
129 $this->fail( 'Expected exception not thrown' );
130 } catch ( DBQueryError
$e ) {
131 $this->assertSame( 0, $this->db
->affectedRows() );
132 $this->db
->cancelAtomic( __METHOD__
);
136 $this->db
->selectFieldValues( 'bar', 'i', [], __METHOD__
, [ 'ORDER BY' => 'i' ] )
138 $this->db
->rollback( __METHOD__
);
142 * @covers Wikimedia\Rdbms\DatabasePostgres::nativeInsertSelect
144 public function testInsertSelectIgnoreOld() {
145 if ( !$this->db
instanceof DatabasePostgres
) {
146 $this->markTestSkipped( 'Not PostgreSQL' );
148 if ( $this->db
->getServerVersion() < 9.5 ) {
149 $this->doTestInsertSelectIgnore();
151 // Hack version to make it take the old code path
152 $w = TestingAccessWrapper
::newFromObject( $this->db
);
153 $oldVer = $w->numericVersion
;
154 $w->numericVersion
= 9.4;
156 $this->doTestInsertSelectIgnore();
158 $w->numericVersion
= $oldVer;
164 * @covers Wikimedia\Rdbms\DatabasePostgres::nativeInsertSelect
166 public function testInsertSelectIgnoreNew() {
167 if ( !$this->db
instanceof DatabasePostgres
) {
168 $this->markTestSkipped( 'Not PostgreSQL' );
170 if ( $this->db
->getServerVersion() < 9.5 ) {
171 $this->markTestSkipped( 'PostgreSQL version is ' . $this->db
->getServerVersion() );
174 $this->doTestInsertSelectIgnore();