Rewrite walks the expresison AST and resolves data types bottom up. In addition it also translates enum strings and rewrites their predicates.
(expression expr.Expr)
| 587 | // Rewrite walks the expresison AST and resolves data types bottom up. |
| 588 | // In addition it also translates enum strings and rewrites their predicates. |
| 589 | func (qc *AQLQueryContext) Rewrite(expression expr.Expr) expr.Expr { |
| 590 | switch e := expression.(type) { |
| 591 | case *expr.ParenExpr: |
| 592 | // Strip parenthesis from the input |
| 593 | return e.Expr |
| 594 | case *expr.VarRef: |
| 595 | tableID, columnID, err := qc.resolveColumn(e.Val) |
| 596 | if err != nil { |
| 597 | qc.Error = err |
| 598 | return expression |
| 599 | } |
| 600 | column := qc.TableScanners[tableID].Schema.Schema.Columns[columnID] |
| 601 | if column.Deleted { |
| 602 | qc.Error = utils.StackError(nil, "column %s of table %s has been deleted", |
| 603 | column.Name, qc.TableScanners[tableID].Schema.Schema.Name) |
| 604 | return expression |
| 605 | } |
| 606 | dataType := qc.TableScanners[tableID].Schema.ValueTypeByColumn[columnID] |
| 607 | e.ExprType = common.DataTypeToExprType[dataType] |
| 608 | e.TableID = tableID |
| 609 | e.ColumnID = columnID |
| 610 | dict := qc.TableScanners[tableID].Schema.EnumDicts[column.Name] |
| 611 | e.EnumDict = dict.Dict |
| 612 | e.EnumReverseDict = dict.ReverseDict |
| 613 | e.DataType = dataType |
| 614 | e.IsHLLColumn = column.HLLConfig.IsHLLColumn |
| 615 | case *expr.UnaryExpr: |
| 616 | if expr.IsUUIDColumn(e.Expr) && e.Op != expr.GET_HLL_VALUE { |
| 617 | qc.Error = utils.StackError(nil, "uuid column type only supports countdistincthll unary expression") |
| 618 | return expression |
| 619 | } |
| 620 | |
| 621 | if err := blockNumericOpsForColumnOverFourBytes(e.Op, e.Expr); err != nil { |
| 622 | qc.Error = err |
| 623 | return expression |
| 624 | } |
| 625 | |
| 626 | e.ExprType = e.Expr.Type() |
| 627 | switch e.Op { |
| 628 | case expr.EXCLAMATION, expr.NOT, expr.IS_FALSE: |
| 629 | e.ExprType = expr.Boolean |
| 630 | // Normalize the operator. |
| 631 | e.Op = expr.NOT |
| 632 | e.Expr = expr.Cast(e.Expr, expr.Boolean) |
| 633 | childExpr := e.Expr |
| 634 | callRef, isCallRef := childExpr.(*expr.Call) |
| 635 | if isCallRef && callRef.Name == expr.GeographyIntersectsCallName { |
| 636 | qc.Error = utils.StackError(nil, "Not %s condition is not allowed", expr.GeographyIntersectsCallName) |
| 637 | break |
| 638 | } |
| 639 | case expr.UNARY_MINUS: |
| 640 | // Upgrade to signed. |
| 641 | if e.ExprType < expr.Signed { |
| 642 | e.ExprType = expr.Signed |
| 643 | } |
| 644 | case expr.IS_NULL, expr.IS_NOT_NULL: |
| 645 | e.ExprType = expr.Boolean |
| 646 | case expr.IS_TRUE: |
no test coverage detected