)
SELECT ... FROM ((SELECT ... FROM test.t1) t)
SELECT ... FROM (SELECT ... FROM test.t1) t
DB_query_builder
from()
,
$this->qb_from
SELECT ... FROM test1, test2
(SELECT test.t1, test.t2) t
(SELECT t1
t2) t
CI_DB_mysqli_driver
CI_DB_mysql_driver
_from_tables()
FROM ...
$this->qb_join
count($this->qb_from) > 1
(...)
extends
extends CI_Loader
database()
(
fromSubquery()
我們手邊都是 MariaDB 10.x,要重現有一點麻煩
不過,根據 syntax error 是從
)
開始這點,我查到 MySQL 8.0 有個 2022 年被回報的 bug:#107160 - Upgrade from 5.7 to 8.0 fails with syntax ...
這個回報目前只進入 Verified 狀態,還沒有被處理
問題似乎出在 subquery 外面的括號
SELECT ... FROM ((SELECT ... FROM test.t1) t)
這樣寫可以:
SELECT ... FROM (SELECT ... FROM test.t1) t
原本的寫法在 MySQL 5.7 與 MariaDB 都沒有問題;而 MySQL 8.0 這邊不確定是改變了語法,還是有 bug
這篇 Stack Overflow 上的討論串:
Parentheses surrounding sub-query alias, syntax chan...
底下的回答認為,根據目前的文件,syntax 應該沒有變
說起來如果外面的括號也取一個 alias,不知道會不會正常
DB_query_builder
的from()
會用逗號(,
)把傳入的參數分開,放入$this->qb_from
陣列。這本來是為了SELECT ... FROM test1, test2
這種情況而設計但 subquery 如果是
(SELECT test.t1, test.t2) t
的話,就會因此被分割為(SELECT t1
與t2) t
CI_DB_mysqli_driver
與CI_DB_mysql_driver
的_from_tables()
,是用來組成FROM ...
後面 table 名稱的部分。這裡當$this->qb_join
不為空且count($this->qb_from) > 1
的話,就會在輸出的字串外面多加一層小括號((...)
),導致上面的情況我最後用了有點奇怪的方法處理:由於 CI 的 DB driver 預設無法被
extends
,我extends CI_Loader
然後把database()
改成可以吃自訂的 driver 檔案接著在想要蓋掉
from()
還是_from_tables()
from()
改成有(
的話,就不理會,
,將它當成一整個 table 名稱(實際上也確實是一整個 table 名稱)CI 3 最新版沒特別處理此問題,CI 4 我則不確定。不過 CI 4 有內建的 subquery builder,我猜可能不會有這個問題
fromSubquery()
方法:確實光靠
from()
本身區分是不是 subquery 應該超級不準確,我好像也該考慮在 CI 3 新增一個方法來處理快讓我醒來!!!