Skip to content

Commit e716007

Browse files
committed
Add more tests and document edge cases
1 parent 0903628 commit e716007

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

tests/WP_SQLite_Driver_Tests.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6323,6 +6323,149 @@ public function testTransactionSavepoints(): void {
63236323
$this->assertSame( array(), (array) array_column( $result, 'id' ) );
63246324
}
63256325

6326+
public function testSelectOrderByAmbiguousColumnResolution(): void {
6327+
$this->assertQuery( 'CREATE TABLE t1 (id INT, name TEXT)' );
6328+
$this->assertQuery( 'CREATE TABLE t2 (id INT, name TEXT)' );
6329+
$this->assertQuery( 'INSERT INTO t1 (id, name) VALUES (1, "A1"), (2, "A2")' );
6330+
$this->assertQuery( 'INSERT INTO t2 (id, name) VALUES (1, "B2"), (2, "B1")' );
6331+
6332+
// The "name" column will be resolved to "t1.name" as per the SELECT item.
6333+
$result = $this->assertQuery( 'SELECT t1.name FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY name DESC' );
6334+
$this->assertEquals(
6335+
array(
6336+
(object) array( 'name' => 'A2' ),
6337+
(object) array( 'name' => 'A1' ),
6338+
),
6339+
$result
6340+
);
6341+
6342+
// The "name" column will be resolved to "t2.name" as per the SELECT item.
6343+
$result = $this->assertQuery( 'SELECT t2.name FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY name DESC' );
6344+
$this->assertEquals(
6345+
array(
6346+
(object) array( 'name' => 'B2' ),
6347+
(object) array( 'name' => 'B1' ),
6348+
),
6349+
$result
6350+
);
6351+
6352+
// The "name" column will be resolved to "t1.name", the "id" column will be resolved to "t2.id".
6353+
$this->assertQuery( 'INSERT INTO t1 (id, name) VALUES (3, "A2")' );
6354+
$this->assertQuery( 'INSERT INTO t2 (id, name) VALUES (3, "A2")' );
6355+
$result = $this->assertQuery( 'SELECT t2.id, t1.name FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY name, id DESC' );
6356+
$this->assertEquals(
6357+
array(
6358+
(object) array(
6359+
'id' => '1',
6360+
'name' => 'A1',
6361+
),
6362+
(object) array(
6363+
'id' => '3',
6364+
'name' => 'A2',
6365+
),
6366+
(object) array(
6367+
'id' => '2',
6368+
'name' => 'A2',
6369+
),
6370+
),
6371+
$result
6372+
);
6373+
6374+
// The "name" column will be resolved to "t1.name" in the subquery and to "t2.name" in the root query.
6375+
$result = $this->assertQuery(
6376+
'
6377+
SELECT t2.name, s.name AS subquery_name
6378+
FROM (SELECT t1.id, t1.name FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY name DESC LIMIT 1) s
6379+
JOIN t2 ON true
6380+
ORDER BY name DESC
6381+
'
6382+
);
6383+
$this->assertEquals(
6384+
array(
6385+
(object) array(
6386+
'name' => 'B2',
6387+
'subquery_name' => 'A2',
6388+
),
6389+
(object) array(
6390+
'name' => 'B1',
6391+
'subquery_name' => 'A2',
6392+
),
6393+
(object) array(
6394+
'name' => 'A2',
6395+
'subquery_name' => 'A2',
6396+
),
6397+
),
6398+
$result
6399+
);
6400+
6401+
// Parenthesized column reference can be used in both SELECT and ORDER BY lists.
6402+
$result = $this->assertQuery( 'SELECT (t1.name) FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY (((name))) DESC' );
6403+
$this->assertEquals(
6404+
array(
6405+
(object) array( '(t1.name)' => 'A2' ),
6406+
(object) array( '(t1.name)' => 'A2' ),
6407+
(object) array( '(t1.name)' => 'A1' ),
6408+
),
6409+
$result
6410+
);
6411+
6412+
/*
6413+
* With multiple identical aliases and no ambiguous column references,
6414+
* it just works, although sometimes the order may differ from MySQL.
6415+
* It may be nondeterministic, but it seems like MySQL picks the first
6416+
* non-column alias, while SQLite sorts by the first alias in the list.
6417+
*
6418+
* When we replace "SELECT t1.name" with "SELECT t2.name" in the query
6419+
* below, the SQLite order will differ from MySQL.
6420+
*/
6421+
$result = $this->assertQuery(
6422+
"
6423+
SELECT t1.name AS name, CONCAT(t1.name, '-one') AS name, CONCAT(t2.name, '-two') AS name
6424+
FROM t1 JOIN t2 ON t2.id = t1.id
6425+
ORDER BY name DESC
6426+
"
6427+
);
6428+
$this->assertEquals(
6429+
array(
6430+
(object) array( 'name' => 'B1-two' ),
6431+
(object) array( 'name' => 'A2-two' ),
6432+
(object) array( 'name' => 'B2-two' ),
6433+
),
6434+
$result
6435+
);
6436+
6437+
/*
6438+
* The following query fails with "ambiguous column name" in MySQL, but
6439+
* in SQLite, it works. It's OK to keep this difference as MySQL behaves
6440+
* rather strangely in this case:
6441+
*
6442+
* 1) This is OK in MySQL:
6443+
* SELECT t1.name AS col, 123 AS col ... ORDER BY col
6444+
* 2) This fails in MySQL:
6445+
* SELECT t1.name AS col, t2.name AS col ... ORDER BY col
6446+
*/
6447+
$this->assertQuery( 'SELECT t1.name AS col, t2.name AS col FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY col' );
6448+
}
6449+
6450+
public function testSelectOrderByAmbiguousColumnError(): void {
6451+
$this->assertQuery( 'CREATE TABLE t1 (id INT, name TEXT)' );
6452+
$this->assertQuery( 'CREATE TABLE t2 (id INT, name TEXT)' );
6453+
6454+
$this->expectException( 'WP_SQLite_Driver_Exception' );
6455+
$this->expectExceptionMessage( 'ambiguous column name: name' );
6456+
$this->assertQuery( 'SELECT t1.name, t2.name FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY name DESC' );
6457+
}
6458+
6459+
6460+
public function testSelectOrderByAmbiguousColumnErrorWithoutSelectList(): void {
6461+
$this->assertQuery( 'CREATE TABLE t1 (id INT, name TEXT)' );
6462+
$this->assertQuery( 'CREATE TABLE t2 (id INT, name TEXT)' );
6463+
6464+
$this->expectException( 'WP_SQLite_Driver_Exception' );
6465+
$this->expectExceptionMessage( 'ambiguous column name: name' );
6466+
$this->assertQuery( 'SELECT 1 FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY name' );
6467+
}
6468+
63266469
public function testRollbackNonExistentTransactionSavepoint(): void {
63276470
$this->expectException( 'WP_SQLite_Driver_Exception' );
63286471
$this->expectExceptionMessage( 'no such savepoint: sp1' );

0 commit comments

Comments
 (0)