From 96974ef3836e1cc46853b2e9218c5b3841d870e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Taylor?= Date: Thu, 18 Jul 2024 07:28:16 +0200 Subject: [PATCH] Handle dual queries with LIMIT on the vtgate (#16400) Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/select.go | 19 +++++++++++++++- .../planbuilder/testdata/select_cases.json | 22 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 01dfd8aa387..6927c5315ac 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -242,11 +242,28 @@ func createSelectOperator(ctx *plancontext.PlanningContext, selStmt sqlparser.Se } func isOnlyDual(sel *sqlparser.Select) bool { - if sel.Where != nil || sel.GroupBy != nil || sel.Having != nil || sel.Limit != nil || sel.OrderBy != nil { + if sel.Where != nil || sel.GroupBy != nil || sel.Having != nil || sel.OrderBy != nil { // we can only deal with queries without any other subclauses - just SELECT and FROM, nothing else is allowed return false } + if sel.Limit != nil { + if sel.Limit.Offset != nil { + return false + } + limit := sel.Limit.Rowcount + switch limit := limit.(type) { + case nil: + case *sqlparser.Literal: + if limit.Val == "0" { + // A limit with any value other than zero can still return a row + return false + } + default: + return false + } + } + if len(sel.From) > 1 { return false } diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index f1134847deb..6dcd95ff09d 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -2744,6 +2744,28 @@ ] } }, + { + "comment": "Dual query should be handled on the vtgate even with a LIMIT", + "query": "select last_insert_id() limit 1", + "plan": { + "QueryType": "SELECT", + "Original": "select last_insert_id() limit 1", + "Instructions": { + "OperatorType": "Projection", + "Expressions": [ + ":__lastInsertId as last_insert_id()" + ], + "Inputs": [ + { + "OperatorType": "SingleRow" + } + ] + }, + "TablesUsed": [ + "main.dual" + ] + } + }, { "comment": "PullOut subquery with an aggregation that should be typed in the final output", "query": "select (select sum(col) from user) from user_extra",