func parseAndNormalizeExpr(t *testing.T, sql string) (parser.Expr, qvalMap) { q, err := parser.ParseTraditional("SELECT " + sql) if err != nil { t.Fatalf("%s: %v", sql, err) } expr := q[0].(*parser.Select).Exprs[0].Expr r, err := parser.NormalizeExpr(expr) if err != nil { t.Fatalf("%s: %v", sql, err) } // Perform qualified name resolution because {analyze,simplify}Expr want // expressions containing qvalues. s := &scanNode{} s.desc = &TableDescriptor{ Columns: []ColumnDescriptor{ {Name: "a", ID: 1, Type: ColumnType{Kind: ColumnType_INT}}, {Name: "b", ID: 2, Type: ColumnType{Kind: ColumnType_INT}}, {Name: "c", ID: 3, Type: ColumnType{Kind: ColumnType_INT}}, {Name: "d", ID: 4, Type: ColumnType{Kind: ColumnType_INT}}, {Name: "e", ID: 5, Type: ColumnType{Kind: ColumnType_INT}}, }, } s.visibleCols = s.desc.Columns r, err = s.resolveQNames(r) if err != nil { t.Fatalf("%s: %v", sql, err) } return r, s.qvals }
func parseAndNormalizeExpr(t *testing.T, sql string) (parser.Expr, qvalMap) { q, err := parser.ParseTraditional("SELECT " + sql) if err != nil { t.Fatalf("%s: %v", sql, err) } expr := q[0].(*parser.Select).Exprs[0].Expr expr, err = parser.NormalizeExpr(expr) if err != nil { t.Fatalf("%s: %v", sql, err) } // Perform qualified name resolution because {analyze,simplify}Expr want // expressions containing qvalues. s := &scanNode{} s.desc = testTableDesc() s.visibleCols = s.desc.Columns if err := s.desc.AllocateIDs(); err != nil { t.Fatal(err) } expr, err = s.resolveQNames(expr) if err != nil { t.Fatalf("%s: %v", sql, err) } if _, err := parser.TypeCheckExpr(expr); err != nil { t.Fatalf("%s: %v", sql, err) } return expr, s.qvals }
func (n *scanNode) initWhere(where *parser.Where) error { if where == nil { return nil } n.filter, n.err = n.resolveQNames(where.Expr) if n.err == nil { // Normalize the expression (this will also evaluate any branches that are // constant). n.filter, n.err = parser.NormalizeExpr(n.filter) } return n.err }
// limit constructs a limitNode based on the LIMIT and OFFSET clauses. func (*planner) limit(n *parser.Select, p planNode) (planNode, error) { if n.Limit == nil { return p, nil } var count, offset int64 data := []struct { name string src parser.Expr dst *int64 defaultVal int64 }{ {"LIMIT", n.Limit.Count, &count, math.MaxInt64}, {"OFFSET", n.Limit.Offset, &offset, 0}, } for _, datum := range data { if datum.src == nil { *datum.dst = datum.defaultVal } else { if parser.ContainsVars(datum.src) { return nil, fmt.Errorf("argument of %s must not contain variables", datum.name) } normalized, err := parser.NormalizeExpr(datum.src) if err != nil { return nil, err } dstDatum, err := parser.EvalExpr(normalized) if err != nil { return nil, err } if dstDatum == parser.DNull { *datum.dst = datum.defaultVal continue } if dstDInt, ok := dstDatum.(parser.DInt); ok { *datum.dst = int64(dstDInt) continue } return nil, fmt.Errorf("argument of %s must be type %s, not type %s", datum.name, parser.DummyInt.Type(), dstDatum.Type()) } } return &limitNode{planNode: p, count: count, offset: offset}, nil }
func (n *scanNode) initWhere(where *parser.Where) error { if where == nil { return nil } n.filter, n.err = n.resolveQNames(where.Expr) if n.err == nil { // Normalize the expression (this will also evaluate any branches that are // constant). n.filter, n.err = parser.NormalizeExpr(n.filter) } if n.err == nil { var whereType parser.Datum whereType, n.err = parser.TypeCheckExpr(n.filter) if n.err == nil { if !(whereType == parser.DummyBool || whereType == parser.DNull) { n.err = fmt.Errorf("argument of WHERE must be type %s, not type %s", parser.DummyBool.Type(), whereType.Type()) } } } return n.err }
func makeDefaultExprs(cols []ColumnDescriptor) ([]parser.Expr, error) { // Check to see if any of the columns have DEFAULT expressions. If there are // no DEFAULT expressions, we don't bother with constructing the defaults map // as the defaults are all NULL. haveDefaults := false for _, col := range cols { if col.DefaultExpr != nil { haveDefaults = true break } } if !haveDefaults { return nil, nil } // Build the default expressions map from the parsed SELECT statement. defaultExprs := make([]parser.Expr, 0, len(cols)) for _, col := range cols { if col.DefaultExpr == nil { defaultExprs = append(defaultExprs, parser.DNull) continue } expr, err := parser.ParseExpr(*col.DefaultExpr, parser.Traditional) if err != nil { return nil, err } expr, err = parser.NormalizeExpr(expr) if err != nil { return nil, err } if parser.ContainsVars(expr) { return nil, util.Errorf("default expression contains variables") } defaultExprs = append(defaultExprs, expr) } return defaultExprs, nil }
// orderBy constructs a sortNode based on the ORDER BY clause. Construction of // the sortNode might adjust the number of render targets in the scanNode if // any ordering expressions are specified. func (p *planner) orderBy(n *parser.Select, s *scanNode) (*sortNode, error) { if n.OrderBy == nil { return nil, nil } // We grab a copy of columns here because we might add new render targets // below. This is the set of columns requested by the query. columns := s.Columns() var ordering []int for _, o := range n.OrderBy { index := 0 // Normalize the expression which has the side-effect of evaluating // constant expressions and unwrapping expressions like "((a))" to "a". expr, err := parser.NormalizeExpr(o.Expr) if err != nil { return nil, err } if qname, ok := expr.(*parser.QualifiedName); ok { if len(qname.Indirect) == 0 { // Look for an output column that matches the qualified name. This // handles cases like: // // SELECT a AS b FROM t ORDER BY b target := string(qname.Base) for j, col := range columns { if equalName(target, col) { index = j + 1 break } } } if index == 0 { // No output column matched the qualified name, so look for an existing // render target that matches the column name. This handles cases like: // // SELECT a AS b FROM t ORDER BY a if err := qname.NormalizeColumnName(); err != nil { return nil, err } if qname.Table() == "" || equalName(s.desc.Alias, qname.Table()) { for j, r := range s.render { if qval, ok := r.(*qvalue); ok { if equalName(qval.col.Name, qname.Column()) { index = j + 1 break } } } } } } if index == 0 { // The order by expression matched neither an output column nor an // existing render target. if datum, ok := expr.(parser.Datum); ok { // If we evaluated to an int, use that as an index to order by. This // handles cases like: // // SELECT * FROM t ORDER BY 1 i, ok := datum.(parser.DInt) if !ok { return nil, fmt.Errorf("invalid ORDER BY: %s", expr) } index = int(i) if index < 1 || index > len(columns) { return nil, fmt.Errorf("invalid ORDER BY index: %d not in range [1, %d]", index, len(columns)) } } else { // Add a new render expression to use for ordering. This handles cases // were the expression is either not a qualified name or is a qualified // name that is otherwise not referenced by the query: // // SELECT a FROM t ORDER by b // SELECT a, b FROM t ORDER by a+b if err := s.addRender(parser.SelectExpr{Expr: expr}); err != nil { return nil, err } index = len(s.columns) } } if o.Direction == parser.Descending { index = -index } ordering = append(ordering, index) } return &sortNode{columns: columns, ordering: ordering}, nil }