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
fix(ast,analyzer): prevent VALUES subquery unwrap from dropping clauses
nodeAliasedTableExpr unconditionally unwrapped any subquery over
a VALUES clause when the inner SELECT had a single FROM item.
This discarded projections, LIMIT, ORDER BY, DISTINCT, WHERE,
GROUP BY, and HAVING because the guard only checked
len(inSelect.From) == 1.
Replace that check with isTrivialSelectStar, which only permits
unwrapping when the inner SELECT is a bare SELECT * with no
additional clauses. Non-trivial subqueries now correctly fall
through to the vitess.Subquery path, preserving all semantics.
Additionally, add a *plan.Offset guard to the TypeSanitizer so
OFFSET literals inside subqueries are kept as GMS types, matching
the existing *plan.Limit guard. Without this, OFFSET triggered
"invalid type: bigint" because GMS validateOffsetAndLimit only
recognizes its own type singletons.
Tests:
- Un-skip three mixed-type VALUES-in-subquery assertions
(projection, LIMIT, ORDER BY)
- Add mixed-type (int/decimal) variants to all integer-only
subquery test groups (DISTINCT, WHERE, GROUP BY, HAVING,
column aliasing, combined clauses, JOIN)
- Add OFFSET-only and LIMIT+OFFSET subquery assertions for
both integer and mixed-type VALUES
Refs: #2373
Query: `SELECT * FROM (SELECT DISTINCT * FROM (VALUES (1), (1), (2), (2), (3)) v(n)) sub;`,
630
+
Expected: []sql.Row{
631
+
{1},
632
+
{2},
633
+
{3},
634
+
},
635
+
},
636
+
{
637
+
Query: `SELECT * FROM (SELECT DISTINCT * FROM (VALUES (1), (1), (2.5), (2.5), (3)) v(n)) sub;`,
638
+
Expected: []sql.Row{
639
+
{Numeric("1")},
640
+
{Numeric("2.5")},
641
+
{Numeric("3")},
642
+
},
643
+
},
644
+
},
645
+
},
646
+
{
647
+
Name: "values inside subquery preserves WHERE",
648
+
Assertions: []ScriptTestAssertion{
649
+
{
650
+
Query: `SELECT * FROM (SELECT * FROM (VALUES (1), (2), (3), (4), (5)) v(n) WHERE n > 3) sub;`,
651
+
Expected: []sql.Row{
652
+
{4},
653
+
{5},
654
+
},
655
+
},
656
+
{
657
+
Query: `SELECT * FROM (SELECT * FROM (VALUES (1), (2.5), (3), (4.5), (5)) v(n) WHERE n > 3) sub;`,
658
+
Expected: []sql.Row{
659
+
{Numeric("4.5")},
660
+
{Numeric("5")},
661
+
},
662
+
},
663
+
},
664
+
},
665
+
{
666
+
Name: "values inside subquery preserves OFFSET",
667
+
Assertions: []ScriptTestAssertion{
668
+
{
669
+
Query: `SELECT * FROM (SELECT * FROM (VALUES (10), (20), (30)) v(n) OFFSET 1) sub;`,
670
+
Expected: []sql.Row{
671
+
{20},
672
+
{30},
673
+
},
674
+
},
675
+
{
676
+
Query: `SELECT * FROM (SELECT * FROM (VALUES (10), (20), (30), (40), (50)) v(n) LIMIT 2 OFFSET 1) sub;`,
677
+
Expected: []sql.Row{
678
+
{20},
679
+
{30},
680
+
},
681
+
},
682
+
{
683
+
Query: `SELECT * FROM (SELECT * FROM (VALUES (10), (20.5), (30)) v(n) OFFSET 1) sub;`,
684
+
Expected: []sql.Row{
685
+
{Numeric("20.5")},
686
+
{Numeric("30")},
687
+
},
688
+
},
689
+
{
690
+
Query: `SELECT * FROM (SELECT * FROM (VALUES (10), (20.5), (30), (40.5), (50)) v(n) LIMIT 2 OFFSET 1) sub;`,
691
+
Expected: []sql.Row{
692
+
{Numeric("20.5")},
693
+
{Numeric("30")},
694
+
},
695
+
},
696
+
},
697
+
},
698
+
{
699
+
Name: "values inside subquery preserves ORDER BY with LIMIT",
700
+
Assertions: []ScriptTestAssertion{
701
+
{
702
+
Query: `SELECT * FROM (SELECT * FROM (VALUES (5), (3), (1), (4), (2)) v(n) ORDER BY n LIMIT 3) sub;`,
703
+
Expected: []sql.Row{
704
+
{1},
705
+
{2},
706
+
{3},
707
+
},
708
+
},
709
+
{
710
+
Query: `SELECT * FROM (SELECT * FROM (VALUES (5), (3.5), (1), (4), (2.5)) v(n) ORDER BY n LIMIT 3) sub;`,
711
+
Expected: []sql.Row{
712
+
{Numeric("1")},
713
+
{Numeric("2.5")},
714
+
{Numeric("3.5")},
715
+
},
716
+
},
717
+
},
718
+
},
719
+
{
720
+
Name: "values inside subquery preserves GROUP BY with aggregate",
721
+
Assertions: []ScriptTestAssertion{
722
+
{
723
+
Query: `SELECT * FROM (SELECT n, count(*) AS cnt FROM (VALUES (1), (1), (2), (2), (2), (3)) v(n) GROUP BY n ORDER BY n) sub;`,
724
+
Expected: []sql.Row{
725
+
{1, int64(2)},
726
+
{2, int64(3)},
727
+
{3, int64(1)},
728
+
},
729
+
},
730
+
{
731
+
Query: `SELECT * FROM (SELECT n, count(*) AS cnt FROM (VALUES (1), (1), (2.5), (2.5), (2.5), (3)) v(n) GROUP BY n ORDER BY n) sub;`,
732
+
Expected: []sql.Row{
733
+
{Numeric("1"), int64(2)},
734
+
{Numeric("2.5"), int64(3)},
735
+
{Numeric("3"), int64(1)},
736
+
},
737
+
},
738
+
},
739
+
},
740
+
{
741
+
Name: "values inside subquery preserves HAVING",
742
+
Assertions: []ScriptTestAssertion{
743
+
{
744
+
Query: `SELECT * FROM (SELECT n, count(*) AS cnt FROM (VALUES (1), (1), (2), (2), (2), (3)) v(n) GROUP BY n HAVING count(*) > 1 ORDER BY n) sub;`,
745
+
Expected: []sql.Row{
746
+
{1, int64(2)},
747
+
{2, int64(3)},
748
+
},
749
+
},
750
+
{
751
+
Query: `SELECT * FROM (SELECT n, count(*) AS cnt FROM (VALUES (1), (1), (2.5), (2.5), (2.5), (3)) v(n) GROUP BY n HAVING count(*) > 1 ORDER BY n) sub;`,
0 commit comments