diff --git a/router/qrouter/proxy_routing.go b/router/qrouter/proxy_routing.go index 09d95bf8a..b29f11162 100644 --- a/router/qrouter/proxy_routing.go +++ b/router/qrouter/proxy_routing.go @@ -944,6 +944,9 @@ func (qr *ProxyQrouter) routeWithRules(ctx context.Context, stmt lyx.Node, sph s return nil, err } case *lyx.Select: + + var deparseError error + /* We cannot route SQL statements without a FROM clause. However, there are a few cases to consider. */ if len(node.FromClause) == 0 && (node.LArg == nil || node.RArg == nil) { for _, expr := range node.TargetList { @@ -964,24 +967,19 @@ func (qr *ProxyQrouter) routeWithRules(ctx context.Context, stmt lyx.Node, sph s } } } - } else { - /* Deparse populates FromClause info, so do recurse into both branches if possible */ - if node.LArg != nil { - if err := qr.deparseShardingMapping(ctx, node.LArg, meta); err != nil { - return nil, err - } + } else if node.LArg != nil && node.RArg != nil { + /* deparse populates the FromClause info, + * so it do recurse into both branches, even if an error is encountered + */ + if err := qr.deparseShardingMapping(ctx, node.LArg, meta); err != nil { + deparseError = err } - if node.RArg != nil { - if err := qr.deparseShardingMapping(ctx, node.RArg, meta); err != nil { - return nil, err - } - } - if node.LArg == nil && node.RArg == nil { - /* SELECT stmts, which would be routed with their WHERE clause */ - if err := qr.deparseShardingMapping(ctx, stmt, meta); err != nil { - return nil, err - } + if err := qr.deparseShardingMapping(ctx, node.RArg, meta); err != nil { + deparseError = err } + } else { + /* SELECT stmts, which would be routed with their WHERE clause */ + deparseError = qr.deparseShardingMapping(ctx, stmt, meta) } /* @@ -1015,6 +1013,10 @@ func (qr *ProxyQrouter) routeWithRules(ctx context.Context, stmt lyx.Node, sph s return routingstate.RandomMatchState{}, nil } + if deparseError != nil { + return nil, deparseError + } + case *lyx.Delete, *lyx.Update: // UPDATE and/or DELETE, COPY stmts, which // would be routed with their WHERE clause diff --git a/router/qrouter/proxy_routing_test.go b/router/qrouter/proxy_routing_test.go index cace0229b..ef488a0ab 100644 --- a/router/qrouter/proxy_routing_test.go +++ b/router/qrouter/proxy_routing_test.go @@ -1678,6 +1678,19 @@ func TestRouteWithRules_Select(t *testing.T) { }, err: nil, }, + + { + query: ` + SELECT c.relname, NULL::pg_catalog.text FROM pg_catalog.pg_class c WHERE c.relkind IN ('r', 'p') AND (c.relname) LIKE 'x%' AND pg_catalog.pg_table_is_visible(c.oid) AND c.relnamespace <> (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = 'pg_catalog') +UNION ALL +SELECT NULL::pg_catalog.text, n.nspname FROM pg_catalog.pg_namespace n WHERE n.nspname LIKE 'x%' AND n.nspname NOT LIKE E'pg\\_%' +LIMIT 1000 +`, + distribution: distribution.ID, + exp: routingstate.RandomMatchState{}, + err: nil, + }, + // TODO rewrite routeByClause to support this // { // query: "SELECT * FROM users WHERE '5f57cd31-806f-4789-a6fa-1d959ec4c64a' = id;",