// limit constructs a limitNode based on the LIMIT and OFFSET clauses. func (p *planner) limit(n *parser.Select, plan planNode) (planNode, error) { if n.Limit == nil { return plan, 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, util.Errorf("argument of %s must not contain variables", datum.name) } normalized, err := p.parser.NormalizeExpr(p.evalCtx, datum.src) if err != nil { return nil, err } dstDatum, err := normalized.Eval(p.evalCtx) 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()) } } if count != math.MaxInt64 { plan.SetLimitHint(offset + count) } return &limitNode{planNode: plan, count: count, offset: offset}, nil }
// SanitizeDefaultExpr verifies a default expression is valid and has the // correct type. func SanitizeDefaultExpr(expr parser.Expr, colDatumType parser.Datum) error { typedExpr, err := parser.TypeCheck(expr, nil, colDatumType) if err != nil { return err } if defaultType := typedExpr.ReturnType(); !colDatumType.TypeEqual(defaultType) { return incompatibleColumnDefaultTypeError(colDatumType, defaultType) } if parser.ContainsVars(typedExpr) { return defaultContainsPlaceholdersError(typedExpr) } return nil }
// SanitizeVarFreeExpr verifies a default expression is valid, has the // correct type and contains no variable expressions. func SanitizeVarFreeExpr(expr parser.Expr, expectedType parser.Datum, context string) error { if parser.ContainsVars(expr) { return exprContainsVarsError(context, expr) } typedExpr, err := parser.TypeCheck(expr, nil, expectedType) if err != nil { return err } if defaultType := typedExpr.ReturnType(); !expectedType.TypeEqual(defaultType) { return incompatibleExprTypeError(context, expectedType, defaultType) } return nil }
func makeDefaultExprs( cols []sqlbase.ColumnDescriptor, parse *parser.Parser, evalCtx parser.EvalContext, ) ([]parser.TypedExpr, 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.TypedExpr, 0, len(cols)) for _, col := range cols { if col.DefaultExpr == nil { defaultExprs = append(defaultExprs, parser.DNull) continue } expr, err := parser.ParseExprTraditional(*col.DefaultExpr) if err != nil { return nil, err } typedExpr, err := parser.TypeCheck(expr, nil, col.Type.ToDatumType()) if err != nil { return nil, err } if typedExpr, err = parse.NormalizeExpr(evalCtx, typedExpr); err != nil { return nil, err } if parser.ContainsVars(typedExpr) { return nil, util.Errorf("default expression contains variables") } defaultExprs = append(defaultExprs, typedExpr) } return defaultExprs, nil }
func (p *planner) 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.ParseExprTraditional(*col.DefaultExpr) if err != nil { return nil, err } expr, err = p.parser.NormalizeExpr(p.evalCtx, 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 }