Skip to content

Commit f5e6081

Browse files
committed
Add IS [NOT] DISTINCT FROM SOME/ANY/ALL (subquery) support
- Add SubqueryComparisonPredicate AST type for subquery comparisons - Parse SOME/ANY/ALL with subqueries after IS [NOT] DISTINCT FROM - Add marshaling for SubqueryComparisonPredicate - Enable 2 passing tests
1 parent dbc8185 commit f5e6081

5 files changed

Lines changed: 65 additions & 2 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package ast
2+
3+
// SubqueryComparisonPredicate represents a comparison with a subquery using ANY/SOME/ALL.
4+
// Example: col IS DISTINCT FROM SOME (SELECT ...), col > ALL (SELECT ...)
5+
type SubqueryComparisonPredicate struct {
6+
Expression ScalarExpression
7+
ComparisonType string // "IsDistinctFrom", "IsNotDistinctFrom", "Equals", etc.
8+
Subquery *ScalarSubquery
9+
SubqueryComparisonPredicateType string // "Any", "All"
10+
}
11+
12+
func (s *SubqueryComparisonPredicate) node() {}
13+
func (s *SubqueryComparisonPredicate) booleanExpression() {}

parser/marshal.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2519,6 +2519,19 @@ func booleanExpressionToJSON(expr ast.BooleanExpression) jsonNode {
25192519
}
25202520
node["IsNot"] = e.IsNot
25212521
return node
2522+
case *ast.SubqueryComparisonPredicate:
2523+
node := jsonNode{
2524+
"$type": "SubqueryComparisonPredicate",
2525+
"ComparisonType": e.ComparisonType,
2526+
"SubqueryComparisonPredicateType": e.SubqueryComparisonPredicateType,
2527+
}
2528+
if e.Expression != nil {
2529+
node["Expression"] = scalarExpressionToJSON(e.Expression)
2530+
}
2531+
if e.Subquery != nil {
2532+
node["Subquery"] = scalarExpressionToJSON(e.Subquery)
2533+
}
2534+
return node
25222535
case *ast.BooleanInExpression:
25232536
node := jsonNode{
25242537
"$type": "InPredicate",

parser/parse_select.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4330,6 +4330,43 @@ func (p *Parser) parseBooleanPrimaryExpression() (ast.BooleanExpression, error)
43304330
}, nil
43314331
}
43324332

4333+
// Check for SOME/ANY/ALL (subquery)
4334+
upperLit := strings.ToUpper(p.curTok.Literal)
4335+
if upperLit == "SOME" || upperLit == "ANY" || upperLit == "ALL" {
4336+
predicateType := "Any"
4337+
if upperLit == "ALL" {
4338+
predicateType = "All"
4339+
}
4340+
p.nextToken() // consume SOME/ANY/ALL
4341+
4342+
if p.curTok.Type != TokenLParen {
4343+
return nil, fmt.Errorf("expected ( after %s, got %s", upperLit, p.curTok.Literal)
4344+
}
4345+
p.nextToken() // consume (
4346+
4347+
subqueryExpr, err := p.parseQueryExpression()
4348+
if err != nil {
4349+
return nil, err
4350+
}
4351+
4352+
if p.curTok.Type != TokenRParen {
4353+
return nil, fmt.Errorf("expected ), got %s", p.curTok.Literal)
4354+
}
4355+
p.nextToken() // consume )
4356+
4357+
compType := "IsDistinctFrom"
4358+
if isNot {
4359+
compType = "IsNotDistinctFrom"
4360+
}
4361+
4362+
return &ast.SubqueryComparisonPredicate{
4363+
Expression: left,
4364+
ComparisonType: compType,
4365+
Subquery: &ast.ScalarSubquery{QueryExpression: subqueryExpr},
4366+
SubqueryComparisonPredicateType: predicateType,
4367+
}, nil
4368+
}
4369+
43334370
// Parse the second expression
43344371
secondExpr, err := p.parseScalarExpression()
43354372
if err != nil {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}

0 commit comments

Comments
 (0)