@@ -2370,8 +2370,33 @@ func (p *Parser) parseBooleanAndExpression() (ast.BooleanExpression, error) {
23702370}
23712371
23722372func (p * Parser ) parseBooleanPrimaryExpression () (ast.BooleanExpression , error ) {
2373- // Check for parenthesized boolean expression
2373+ // Check for parenthesized expression - could be boolean or scalar subquery
23742374 if p .curTok .Type == TokenLParen {
2375+ // Peek ahead to see if it's a subquery (SELECT)
2376+ if p .peekTok .Type == TokenSelect {
2377+ // Parse as scalar subquery that will be used in a comparison
2378+ p .nextToken () // consume (
2379+ qe , err := p .parseQueryExpression ()
2380+ if err != nil {
2381+ return nil , err
2382+ }
2383+ if p .curTok .Type != TokenRParen {
2384+ return nil , fmt .Errorf ("expected ), got %s" , p .curTok .Literal )
2385+ }
2386+ p .nextToken () // consume )
2387+
2388+ subquery := & ast.ScalarSubquery {QueryExpression : qe }
2389+
2390+ // Now check for comparison operators
2391+ if p .isComparisonOperator () {
2392+ return p .parseComparisonAfterLeft (subquery )
2393+ }
2394+ // If no comparison, this might be used in other contexts
2395+ // For now, treat it as an error if used standalone
2396+ return nil , fmt .Errorf ("scalar subquery must be followed by a comparison operator" )
2397+ }
2398+
2399+ // Parse as parenthesized boolean expression
23752400 p .nextToken () // consume (
23762401
23772402 // Parse inner boolean expression
@@ -2567,6 +2592,51 @@ func (p *Parser) parseBooleanPrimaryExpression() (ast.BooleanExpression, error)
25672592 }, nil
25682593}
25692594
2595+ // isComparisonOperator checks if the current token is a comparison operator
2596+ func (p * Parser ) isComparisonOperator () bool {
2597+ switch p .curTok .Type {
2598+ case TokenEquals , TokenNotEqual , TokenLessThan , TokenGreaterThan ,
2599+ TokenLessOrEqual , TokenGreaterOrEqual :
2600+ return true
2601+ default :
2602+ return false
2603+ }
2604+ }
2605+
2606+ // parseComparisonAfterLeft parses a comparison expression after the left operand is already parsed
2607+ func (p * Parser ) parseComparisonAfterLeft (left ast.ScalarExpression ) (ast.BooleanExpression , error ) {
2608+ var compType string
2609+ switch p .curTok .Type {
2610+ case TokenEquals :
2611+ compType = "Equals"
2612+ case TokenNotEqual :
2613+ compType = "NotEqualToBrackets"
2614+ case TokenLessThan :
2615+ compType = "LessThan"
2616+ case TokenGreaterThan :
2617+ compType = "GreaterThan"
2618+ case TokenLessOrEqual :
2619+ compType = "LessThanOrEqualTo"
2620+ case TokenGreaterOrEqual :
2621+ compType = "GreaterThanOrEqualTo"
2622+ default :
2623+ return nil , fmt .Errorf ("expected comparison operator, got %s" , p .curTok .Literal )
2624+ }
2625+ p .nextToken ()
2626+
2627+ // Parse right scalar expression
2628+ right , err := p .parseScalarExpression ()
2629+ if err != nil {
2630+ return nil , err
2631+ }
2632+
2633+ return & ast.BooleanComparisonExpression {
2634+ ComparisonType : compType ,
2635+ FirstExpression : left ,
2636+ SecondExpression : right ,
2637+ }, nil
2638+ }
2639+
25702640// identifiersToSchemaObjectName converts a slice of identifiers to a SchemaObjectName.
25712641// For 1 identifier: BaseIdentifier
25722642// For 2 identifiers: SchemaIdentifier.BaseIdentifier
0 commit comments