From a7c1eebcbc96c8ecef15a30978091aae71f229c9 Mon Sep 17 00:00:00 2001 From: Bar Weiss Date: Thu, 20 Mar 2025 10:32:09 +0200 Subject: [PATCH 1/2] Fix the order of LIMIT and OFFSET clauses when using the Presto flavor (issue #195) Queries that have both a limit and an offset build a query with a limit clause *before* the offset clause. ```go fmt.Println(Select("*").From("table").Offset(5).Limit(10)) // SELECT * FROM table LIMIT 10 OFFSET 5 ``` This seems to generate syntax errors in Trino. [Presto documentation specifies OFFSET before LIMIT](https://prestodb.io/docs/current/sql/select.html#limit-clause) in the SELECT statement documentation too, but is not very explicit about the reverse not being supported. If the OFFSET and LIMIT clauses are swapped, the query succeeds. Expected: ```go fmt.Println(Select("*").From("table").Offset(5).Limit(10)) // SELECT * FROM table OFFSET 5 LIMIT 10 ``` --- select.go | 12 +++++++++++- select_test.go | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/select.go b/select.go index 8b698e0..dde2ece 100644 --- a/select.go +++ b/select.go @@ -457,7 +457,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{ buf.WriteLeadingString("LIMIT ") buf.WriteString(sb.limitVar) } - case PostgreSQL, Presto: + case PostgreSQL: if len(sb.limitVar) > 0 { buf.WriteLeadingString("LIMIT ") buf.WriteString(sb.limitVar) @@ -467,6 +467,16 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{ buf.WriteLeadingString("OFFSET ") buf.WriteString(sb.offsetVar) } + case Presto: + if len(sb.offsetVar) > 0 { + buf.WriteLeadingString("OFFSET ") + buf.WriteString(sb.offsetVar) + } + + if len(sb.limitVar) > 0 { + buf.WriteLeadingString("LIMIT ") + buf.WriteString(sb.limitVar) + } case SQLServer: // If ORDER BY is not set, sort column #1 by default. diff --git a/select_test.go b/select_test.go index 1d631d2..cdebad1 100644 --- a/select_test.go +++ b/select_test.go @@ -229,9 +229,9 @@ func ExampleSelectBuilder_limit_offset() { // Presto // #1: SELECT * FROM user // #2: SELECT * FROM user OFFSET ? - // #3: SELECT * FROM user LIMIT ? OFFSET ? + // #3: SELECT * FROM user OFFSET ? LIMIT ? // #4: SELECT * FROM user LIMIT ? - // #5: SELECT * FROM user ORDER BY id LIMIT ? OFFSET ? + // #5: SELECT * FROM user ORDER BY id OFFSET ? LIMIT ? // // Oracle // #1: SELECT * FROM user From baa39209c6b3edc9581cfb322015a45435a20eb8 Mon Sep 17 00:00:00 2001 From: Bar Weiss Date: Thu, 20 Mar 2025 10:47:05 +0200 Subject: [PATCH 2/2] Add some in-code documentation --- select.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/select.go b/select.go index dde2ece..6dcbc2e 100644 --- a/select.go +++ b/select.go @@ -468,6 +468,10 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{ buf.WriteString(sb.offsetVar) } case Presto: + // There might be a hidden constraint in Presto requiring offset to be set before limit. + // The select statement documentation (https://prestodb.io/docs/current/sql/select.html) + // puts offset before limit, and Trino, which is based on Presto, seems + // to require this specific order. if len(sb.offsetVar) > 0 { buf.WriteLeadingString("OFFSET ") buf.WriteString(sb.offsetVar)