You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
$this->driver->query( 'CREATE TABLE t1 (id INT, name TEXT)' );
1501
+
$this->driver->query( 'CREATE TABLE t2 (id INT, name TEXT)' );
1502
+
1503
+
// Ambiguous column in HAVING clause is disambiguated by the SELECT item list.
1504
+
$this->assertQuery(
1505
+
'SELECT `t1`.`name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `t1`.`name`',
1506
+
'SELECT t1.name FROM t1 JOIN t2 ON t2.id = t1.id HAVING name'
1507
+
);
1508
+
1509
+
// Multiple ambiguous columns in HAVING clause are also disambiguated (AND).
1510
+
$this->assertQuery(
1511
+
'SELECT `t1`.`id` , `t1`.`name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `t1`.`id` AND `t1`.`name`',
1512
+
'SELECT t1.id, t1.name FROM t1 JOIN t2 ON t2.id = t1.id HAVING id AND name'
1513
+
);
1514
+
1515
+
// Multiple ambiguous columns in HAVING clause are also disambiguated (OR).
1516
+
$this->assertQuery(
1517
+
'SELECT `t1`.`id` , `t1`.`name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `t1`.`id` OR `t1`.`name`',
1518
+
'SELECT t1.id, t1.name FROM t1 JOIN t2 ON t2.id = t1.id HAVING id OR name'
1519
+
);
1520
+
1521
+
// The disambiguation works with subqueries.
1522
+
$this->assertQuery(
1523
+
'SELECT `name` FROM ( SELECT `t1`.`name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `t1`.`name` ) GROUP BY 1 HAVING `name`',
1524
+
'SELECT name FROM (SELECT t1.name FROM t1 JOIN t2 ON t2.id = t1.id HAVING name) HAVING name'
1525
+
);
1526
+
1527
+
// The disambiguation works in both root and subquery contexts at the same time.
1528
+
$this->assertQuery(
1529
+
'SELECT `ta`.`name` FROM ( SELECT `t2`.`name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `t2`.`name` ) `ta` GROUP BY 1 HAVING `ta`.`name`',
1530
+
'SELECT ta.name FROM (SELECT t2.name FROM t1 JOIN t2 ON t2.id = t1.id HAVING name) ta HAVING name'
1531
+
);
1532
+
1533
+
// When the HAVING item is nested in a simple parentheses expression, the disambiguation still works.
1534
+
$this->assertQuery(
1535
+
'SELECT `t1`.`name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `t1`.`name`',
1536
+
'SELECT t1.name FROM t1 JOIN t2 ON t2.id = t1.id HAVING (((name)))'
1537
+
);
1538
+
1539
+
// When the SELECT item is nested in a complex expression, the column is not disambiguated (like in MySQL).
1540
+
$this->assertQuery(
1541
+
"SELECT (`t1`.`name` || 'test') AS `CONCAT(t1.name, 'test')` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `name`",
1542
+
"SELECT CONCAT(t1.name, 'test') FROM t1 JOIN t2 ON t2.id = t1.id HAVING name"
1543
+
);
1544
+
1545
+
// When the HAVING item is used in an aggregate function, the column is not disambiguated (like in MySQL).
1546
+
$this->assertQuery(
1547
+
'SELECT `t1`.`name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING COUNT ( `name` ) > 1',
1548
+
'SELECT t1.name FROM t1 JOIN t2 ON t2.id = t1.id HAVING COUNT(name) > 1'
1549
+
);
1550
+
1551
+
/*
1552
+
* The following edge case behaves differently than in MySQL.
1553
+
* This seems to be due to a quirk in SQLite, where the behavior of the
1554
+
* HAVING clause is different from the ORDER BY clause:
1555
+
* - ORDER BY: SQLite will pick the first column or alias for sorting.
1556
+
* - HAVING: SQLite will fail with an "ambiguous column name" error.
1557
+
*
1558
+
* @TODO: We can consider fixing this more correctly.
1559
+
*/
1560
+
$this->assertQuery(
1561
+
"SELECT `t1`.`name` , 'test' AS `name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `name`",
1562
+
"SELECT t1.name, 'test' AS `name` FROM t1 JOIN t2 ON t2.id = t1.id HAVING name"
1563
+
);
1564
+
1565
+
// When the HAVING item uses an alias, there is no ambiguity.
1566
+
$this->assertQuery(
1567
+
'SELECT `t1`.`name` AS `t1_name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `t1_name`',
1568
+
'SELECT t1.name AS t1_name FROM t1 JOIN t2 ON t2.id = t1.id HAVING `t1_name`'
1569
+
);
1570
+
1571
+
/*
1572
+
* The following edge case should actually be disambiguated, as it is in MySQL.
1573
+
* THe HAVING clause behaves strangely in MySQL:
1574
+
* - HAVING COUNT(name), HAVING SUM(name), etc. are not disambiguated.
1575
+
* - HAVING name = 1, HAVING (name = (name + 1)), etc. are disambiguated.
1576
+
* - With HAVING, MySQL seems to only recognize the columns listed in the SELECT clause.
1577
+
*
1578
+
* @TODO: We can consider fixing this more correctly.
1579
+
*/
1580
+
$this->assertQuery(
1581
+
'SELECT `t1`.`name` FROM `t1` JOIN `t2` ON `t2`.`id` = `t1`.`id` GROUP BY 1 HAVING `name` = 1',
1582
+
'SELECT t1.name FROM t1 JOIN t2 ON t2.id = t1.id HAVING name = 1'
0 commit comments