parseJSONExpression parses JSON/JSONB operators (PostgreSQL) and type casting Handles: ->, ->>, #>, #>>, @>, <@, ?, ?|, ?&, #-, ::
()
| 208 | // parseJSONExpression parses JSON/JSONB operators (PostgreSQL) and type casting |
| 209 | // Handles: ->, ->>, #>, #>>, @>, <@, ?, ?|, ?&, #-, :: |
| 210 | func (p *Parser) parseJSONExpression() (ast.Expression, error) { |
| 211 | // Parse the left side using primary expression |
| 212 | left, err := p.parsePrimaryExpression() |
| 213 | if err != nil { |
| 214 | return nil, err |
| 215 | } |
| 216 | |
| 217 | // Snowflake VARIANT path: `expr:field[.field|[idx]]*`. Must run before |
| 218 | // the `::` cast loop so that `col:a.b::int` casts the full path rather |
| 219 | // than treating the path as a bare expression. |
| 220 | if p.dialect == string(keywords.DialectSnowflake) && p.isType(models.TokenTypeColon) { |
| 221 | vp, err := p.parseSnowflakeVariantPath(left) |
| 222 | if err != nil { |
| 223 | return nil, err |
| 224 | } |
| 225 | left = vp |
| 226 | } |
| 227 | |
| 228 | // Handle type casting (::) with highest precedence |
| 229 | // PostgreSQL: expr::type (e.g., '123'::integer, column::text) |
| 230 | for p.isType(models.TokenTypeDoubleColon) { |
| 231 | p.advance() // Consume :: |
| 232 | |
| 233 | // Parse the target data type |
| 234 | dataType, err := p.parseDataType() |
| 235 | if err != nil { |
| 236 | return nil, err |
| 237 | } |
| 238 | |
| 239 | left = &ast.CastExpression{ |
| 240 | Expr: left, |
| 241 | Type: dataType, |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | // Handle JSON operators (left-associative for chaining like data->'a'->'b') |
| 246 | for p.isJSONOperator() { |
| 247 | opPos := p.currentLocation() |
| 248 | operator := p.currentToken.Token.Value |
| 249 | operatorType := p.currentToken.Token.Type |
| 250 | p.advance() // Consume JSON operator |
| 251 | |
| 252 | // Parse the right side |
| 253 | right, err := p.parsePrimaryExpression() |
| 254 | if err != nil { |
| 255 | return nil, err |
| 256 | } |
| 257 | |
| 258 | left = &ast.BinaryExpression{ |
| 259 | Left: left, |
| 260 | Operator: operator, |
| 261 | Right: right, |
| 262 | Pos: opPos, |
| 263 | } |
| 264 | |
| 265 | // Store operator type for semantic analysis if needed |
| 266 | _ = operatorType |
| 267 |
no test coverage detected