Merge "Add namespace translation for N'Ko"
[lhc/web/wiklou.git] / tests / phpunit / includes / db / DatabasePostgresTest.php
1 <?php
2
3 use Wikimedia\Rdbms\Database;
4 use Wikimedia\Rdbms\IDatabase;
5 use Wikimedia\Rdbms\DatabasePostgres;
6 use Wikimedia\ScopedCallback;
7 use Wikimedia\TestingAccessWrapper;
8
9 /**
10 * @group Database
11 */
12 class DatabasePostgresTest extends MediaWikiTestCase {
13
14 private function doTestInsertIgnore() {
15 $fname = __METHOD__;
16 $reset = new ScopedCallback( function () use ( $fname ) {
17 if ( $this->db->explicitTrxActive() ) {
18 $this->db->rollback( $fname );
19 }
20 $this->db->query( 'DROP TABLE IF EXISTS ' . $this->db->tableName( 'foo' ), $fname );
21 } );
22
23 $this->db->query(
24 "CREATE TEMPORARY TABLE {$this->db->tableName( 'foo' )} (i INTEGER NOT NULL PRIMARY KEY)",
25 __METHOD__
26 );
27 $this->db->insert( 'foo', [ [ 'i' => 1 ], [ 'i' => 2 ] ], __METHOD__ );
28
29 // Normal INSERT IGNORE
30 $this->db->begin( __METHOD__ );
31 $this->db->insert(
32 'foo', [ [ 'i' => 3 ], [ 'i' => 2 ], [ 'i' => 5 ] ], __METHOD__, [ 'IGNORE' ]
33 );
34 $this->assertSame( 2, $this->db->affectedRows() );
35 $this->assertSame(
36 [ '1', '2', '3', '5' ],
37 $this->db->selectFieldValues( 'foo', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
38 );
39 $this->db->rollback( __METHOD__ );
40
41 // INSERT IGNORE doesn't ignore stuff like NOT NULL violations
42 $this->db->begin( __METHOD__ );
43 $this->db->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
44 try {
45 $this->db->insert(
46 'foo', [ [ 'i' => 7 ], [ 'i' => null ] ], __METHOD__, [ 'IGNORE' ]
47 );
48 $this->db->endAtomic( __METHOD__ );
49 $this->fail( 'Expected exception not thrown' );
50 } catch ( DBQueryError $e ) {
51 $this->assertSame( 0, $this->db->affectedRows() );
52 $this->db->cancelAtomic( __METHOD__ );
53 }
54 $this->assertSame(
55 [ '1', '2' ],
56 $this->db->selectFieldValues( 'foo', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
57 );
58 $this->db->rollback( __METHOD__ );
59 }
60
61 /**
62 * @covers Wikimedia\Rdbms\DatabasePostgres::insert
63 */
64 public function testInsertIgnoreOld() {
65 if ( !$this->db instanceof DatabasePostgres ) {
66 $this->markTestSkipped( 'Not PostgreSQL' );
67 }
68 if ( $this->db->getServerVersion() < 9.5 ) {
69 $this->doTestInsertIgnore();
70 } else {
71 // Hack version to make it take the old code path
72 $w = TestingAccessWrapper::newFromObject( $this->db );
73 $oldVer = $w->numericVersion;
74 $w->numericVersion = 9.4;
75 try {
76 $this->doTestInsertIgnore();
77 } finally {
78 $w->numericVersion = $oldVer;
79 }
80 }
81 }
82
83 /**
84 * @covers Wikimedia\Rdbms\DatabasePostgres::insert
85 */
86 public function testInsertIgnoreNew() {
87 if ( !$this->db instanceof DatabasePostgres ) {
88 $this->markTestSkipped( 'Not PostgreSQL' );
89 }
90 if ( $this->db->getServerVersion() < 9.5 ) {
91 $this->markTestSkipped( 'PostgreSQL version is ' . $this->db->getServerVersion() );
92 }
93
94 $this->doTestInsertIgnore();
95 }
96
97 private function doTestInsertSelectIgnore() {
98 $fname = __METHOD__;
99 $reset = new ScopedCallback( function () use ( $fname ) {
100 if ( $this->db->explicitTrxActive() ) {
101 $this->db->rollback( $fname );
102 }
103 $this->db->query( 'DROP TABLE IF EXISTS ' . $this->db->tableName( 'foo' ), $fname );
104 $this->db->query( 'DROP TABLE IF EXISTS ' . $this->db->tableName( 'bar' ), $fname );
105 } );
106
107 $this->db->query(
108 "CREATE TEMPORARY TABLE {$this->db->tableName( 'foo' )} (i INTEGER)",
109 __METHOD__
110 );
111 $this->db->query(
112 "CREATE TEMPORARY TABLE {$this->db->tableName( 'bar' )} (i INTEGER NOT NULL PRIMARY KEY)",
113 __METHOD__
114 );
115 $this->db->insert( 'bar', [ [ 'i' => 1 ], [ 'i' => 2 ] ], __METHOD__ );
116
117 // Normal INSERT IGNORE
118 $this->db->begin( __METHOD__ );
119 $this->db->insert( 'foo', [ [ 'i' => 3 ], [ 'i' => 2 ], [ 'i' => 5 ] ], __METHOD__ );
120 $this->db->insertSelect( 'bar', 'foo', [ 'i' => 'i' ], [], __METHOD__, [ 'IGNORE' ] );
121 $this->assertSame( 2, $this->db->affectedRows() );
122 $this->assertSame(
123 [ '1', '2', '3', '5' ],
124 $this->db->selectFieldValues( 'bar', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
125 );
126 $this->db->rollback( __METHOD__ );
127
128 // INSERT IGNORE doesn't ignore stuff like NOT NULL violations
129 $this->db->begin( __METHOD__ );
130 $this->db->insert( 'foo', [ [ 'i' => 7 ], [ 'i' => null ] ], __METHOD__ );
131 $this->db->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
132 try {
133 $this->db->insertSelect( 'bar', 'foo', [ 'i' => 'i' ], [], __METHOD__, [ 'IGNORE' ] );
134 $this->db->endAtomic( __METHOD__ );
135 $this->fail( 'Expected exception not thrown' );
136 } catch ( DBQueryError $e ) {
137 $this->assertSame( 0, $this->db->affectedRows() );
138 $this->db->cancelAtomic( __METHOD__ );
139 }
140 $this->assertSame(
141 [ '1', '2' ],
142 $this->db->selectFieldValues( 'bar', 'i', [], __METHOD__, [ 'ORDER BY' => 'i' ] )
143 );
144 $this->db->rollback( __METHOD__ );
145 }
146
147 /**
148 * @covers Wikimedia\Rdbms\DatabasePostgres::nativeInsertSelect
149 */
150 public function testInsertSelectIgnoreOld() {
151 if ( !$this->db instanceof DatabasePostgres ) {
152 $this->markTestSkipped( 'Not PostgreSQL' );
153 }
154 if ( $this->db->getServerVersion() < 9.5 ) {
155 $this->doTestInsertSelectIgnore();
156 } else {
157 // Hack version to make it take the old code path
158 $w = TestingAccessWrapper::newFromObject( $this->db );
159 $oldVer = $w->numericVersion;
160 $w->numericVersion = 9.4;
161 try {
162 $this->doTestInsertSelectIgnore();
163 } finally {
164 $w->numericVersion = $oldVer;
165 }
166 }
167 }
168
169 /**
170 * @covers Wikimedia\Rdbms\DatabasePostgres::nativeInsertSelect
171 */
172 public function testInsertSelectIgnoreNew() {
173 if ( !$this->db instanceof DatabasePostgres ) {
174 $this->markTestSkipped( 'Not PostgreSQL' );
175 }
176 if ( $this->db->getServerVersion() < 9.5 ) {
177 $this->markTestSkipped( 'PostgreSQL version is ' . $this->db->getServerVersion() );
178 }
179
180 $this->doTestInsertSelectIgnore();
181 }
182
183 /**
184 * @covers \Wikimedia\Rdbms\DatabasePostgres::getAttributes
185 */
186 public function testAttributes() {
187 $this->assertTrue( DatabasePostgres::getAttributes()[Database::ATTR_SCHEMAS_AS_TABLE_GROUPS] );
188 }
189 }