@@ -643,6 +643,20 @@ func (p *Parser) parsePrimaryExpression() (ast.ScalarExpression, error) {
643643 p .nextToken () // consume N
644644 return p .parseNationalStringLiteral ()
645645 }
646+ // Check for CAST/CONVERT special functions
647+ upper := strings .ToUpper (p .curTok .Literal )
648+ if upper == "CAST" && p .peekTok .Type == TokenLParen {
649+ return p .parseCastCall ()
650+ }
651+ if upper == "CONVERT" && p .peekTok .Type == TokenLParen {
652+ return p .parseConvertCall ()
653+ }
654+ if upper == "TRY_CAST" && p .peekTok .Type == TokenLParen {
655+ return p .parseTryCastCall ()
656+ }
657+ if upper == "TRY_CONVERT" && p .peekTok .Type == TokenLParen {
658+ return p .parseTryConvertCall ()
659+ }
646660 return p .parseColumnReferenceOrFunctionCall ()
647661 case TokenNumber :
648662 val := p .curTok .Literal
@@ -2169,3 +2183,207 @@ func identifiersToSchemaObjectName(identifiers []*ast.Identifier) *ast.SchemaObj
21692183
21702184// ======================= New Statement Parsing Functions =======================
21712185
2186+
2187+ // parseCastCall parses a CAST expression: CAST(expression AS data_type)
2188+ func (p * Parser ) parseCastCall () (ast.ScalarExpression , error ) {
2189+ p .nextToken () // consume CAST
2190+ if p .curTok .Type != TokenLParen {
2191+ return nil , fmt .Errorf ("expected ( after CAST, got %s" , p .curTok .Literal )
2192+ }
2193+ p .nextToken () // consume (
2194+
2195+ // Parse the expression
2196+ expr , err := p .parseScalarExpression ()
2197+ if err != nil {
2198+ return nil , err
2199+ }
2200+
2201+ // Expect AS
2202+ if p .curTok .Type != TokenAs {
2203+ return nil , fmt .Errorf ("expected AS in CAST, got %s" , p .curTok .Literal )
2204+ }
2205+ p .nextToken () // consume AS
2206+
2207+ // Parse the data type
2208+ dt , err := p .parseDataTypeReference ()
2209+ if err != nil {
2210+ return nil , err
2211+ }
2212+
2213+ // Expect )
2214+ if p .curTok .Type != TokenRParen {
2215+ return nil , fmt .Errorf ("expected ) in CAST, got %s" , p .curTok .Literal )
2216+ }
2217+ p .nextToken () // consume )
2218+
2219+ cast := & ast.CastCall {
2220+ DataType : dt ,
2221+ Parameter : expr ,
2222+ }
2223+
2224+ // Check for COLLATE clause
2225+ if strings .ToUpper (p .curTok .Literal ) == "COLLATE" {
2226+ p .nextToken () // consume COLLATE
2227+ cast .Collation = p .parseIdentifier ()
2228+ }
2229+
2230+ return cast , nil
2231+ }
2232+
2233+ // parseConvertCall parses a CONVERT expression: CONVERT(data_type, expression [, style])
2234+ func (p * Parser ) parseConvertCall () (ast.ScalarExpression , error ) {
2235+ p .nextToken () // consume CONVERT
2236+ if p .curTok .Type != TokenLParen {
2237+ return nil , fmt .Errorf ("expected ( after CONVERT, got %s" , p .curTok .Literal )
2238+ }
2239+ p .nextToken () // consume (
2240+
2241+ // Parse the data type first
2242+ dt , err := p .parseDataTypeReference ()
2243+ if err != nil {
2244+ return nil , err
2245+ }
2246+
2247+ // Expect comma
2248+ if p .curTok .Type != TokenComma {
2249+ return nil , fmt .Errorf ("expected , in CONVERT, got %s" , p .curTok .Literal )
2250+ }
2251+ p .nextToken () // consume ,
2252+
2253+ // Parse the expression
2254+ expr , err := p .parseScalarExpression ()
2255+ if err != nil {
2256+ return nil , err
2257+ }
2258+
2259+ convert := & ast.ConvertCall {
2260+ DataType : dt ,
2261+ Parameter : expr ,
2262+ }
2263+
2264+ // Check for optional style parameter
2265+ if p .curTok .Type == TokenComma {
2266+ p .nextToken () // consume ,
2267+ style , err := p .parseScalarExpression ()
2268+ if err != nil {
2269+ return nil , err
2270+ }
2271+ convert .Style = style
2272+ }
2273+
2274+ // Expect )
2275+ if p .curTok .Type != TokenRParen {
2276+ return nil , fmt .Errorf ("expected ) in CONVERT, got %s" , p .curTok .Literal )
2277+ }
2278+ p .nextToken () // consume )
2279+
2280+ // Check for COLLATE clause
2281+ if strings .ToUpper (p .curTok .Literal ) == "COLLATE" {
2282+ p .nextToken () // consume COLLATE
2283+ convert .Collation = p .parseIdentifier ()
2284+ }
2285+
2286+ return convert , nil
2287+ }
2288+
2289+ // parseTryCastCall parses a TRY_CAST expression
2290+ func (p * Parser ) parseTryCastCall () (ast.ScalarExpression , error ) {
2291+ p .nextToken () // consume TRY_CAST
2292+ if p .curTok .Type != TokenLParen {
2293+ return nil , fmt .Errorf ("expected ( after TRY_CAST, got %s" , p .curTok .Literal )
2294+ }
2295+ p .nextToken () // consume (
2296+
2297+ // Parse the expression
2298+ expr , err := p .parseScalarExpression ()
2299+ if err != nil {
2300+ return nil , err
2301+ }
2302+
2303+ // Expect AS
2304+ if p .curTok .Type != TokenAs {
2305+ return nil , fmt .Errorf ("expected AS in TRY_CAST, got %s" , p .curTok .Literal )
2306+ }
2307+ p .nextToken () // consume AS
2308+
2309+ // Parse the data type
2310+ dt , err := p .parseDataTypeReference ()
2311+ if err != nil {
2312+ return nil , err
2313+ }
2314+
2315+ // Expect )
2316+ if p .curTok .Type != TokenRParen {
2317+ return nil , fmt .Errorf ("expected ) in TRY_CAST, got %s" , p .curTok .Literal )
2318+ }
2319+ p .nextToken () // consume )
2320+
2321+ cast := & ast.TryCastCall {
2322+ DataType : dt ,
2323+ Parameter : expr ,
2324+ }
2325+
2326+ // Check for COLLATE clause
2327+ if strings .ToUpper (p .curTok .Literal ) == "COLLATE" {
2328+ p .nextToken () // consume COLLATE
2329+ cast .Collation = p .parseIdentifier ()
2330+ }
2331+
2332+ return cast , nil
2333+ }
2334+
2335+ // parseTryConvertCall parses a TRY_CONVERT expression
2336+ func (p * Parser ) parseTryConvertCall () (ast.ScalarExpression , error ) {
2337+ p .nextToken () // consume TRY_CONVERT
2338+ if p .curTok .Type != TokenLParen {
2339+ return nil , fmt .Errorf ("expected ( after TRY_CONVERT, got %s" , p .curTok .Literal )
2340+ }
2341+ p .nextToken () // consume (
2342+
2343+ // Parse the data type first
2344+ dt , err := p .parseDataTypeReference ()
2345+ if err != nil {
2346+ return nil , err
2347+ }
2348+
2349+ // Expect comma
2350+ if p .curTok .Type != TokenComma {
2351+ return nil , fmt .Errorf ("expected , in TRY_CONVERT, got %s" , p .curTok .Literal )
2352+ }
2353+ p .nextToken () // consume ,
2354+
2355+ // Parse the expression
2356+ expr , err := p .parseScalarExpression ()
2357+ if err != nil {
2358+ return nil , err
2359+ }
2360+
2361+ convert := & ast.TryConvertCall {
2362+ DataType : dt ,
2363+ Parameter : expr ,
2364+ }
2365+
2366+ // Check for optional style parameter
2367+ if p .curTok .Type == TokenComma {
2368+ p .nextToken () // consume ,
2369+ style , err := p .parseScalarExpression ()
2370+ if err != nil {
2371+ return nil , err
2372+ }
2373+ convert .Style = style
2374+ }
2375+
2376+ // Expect )
2377+ if p .curTok .Type != TokenRParen {
2378+ return nil , fmt .Errorf ("expected ) in TRY_CONVERT, got %s" , p .curTok .Literal )
2379+ }
2380+ p .nextToken () // consume )
2381+
2382+ // Check for COLLATE clause
2383+ if strings .ToUpper (p .curTok .Literal ) == "COLLATE" {
2384+ p .nextToken () // consume COLLATE
2385+ convert .Collation = p .parseIdentifier ()
2386+ }
2387+
2388+ return convert , nil
2389+ }
0 commit comments