github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sqlbase/default_exprs.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package sqlbase 12 13 import ( 14 "context" 15 16 "github.com/cockroachdb/cockroach/pkg/sql/parser" 17 "github.com/cockroachdb/cockroach/pkg/sql/sem/transform" 18 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 19 ) 20 21 // MakeDefaultExprs returns a slice of the default expressions for the slice 22 // of input column descriptors, or nil if none of the input column descriptors 23 // have default expressions. 24 // The length of the result slice matches the length of the input column descriptors. 25 // For every column that has no default expression, a NULL expression is reported 26 // as default. 27 func MakeDefaultExprs( 28 ctx context.Context, 29 cols []ColumnDescriptor, 30 txCtx *transform.ExprTransformContext, 31 evalCtx *tree.EvalContext, 32 ) ([]tree.TypedExpr, error) { 33 // Check to see if any of the columns have DEFAULT expressions. If there 34 // are no DEFAULT expressions, we don't bother with constructing the 35 // defaults map as the defaults are all NULL. 36 haveDefaults := false 37 for i := range cols { 38 if cols[i].DefaultExpr != nil { 39 haveDefaults = true 40 break 41 } 42 } 43 if !haveDefaults { 44 return nil, nil 45 } 46 47 // Build the default expressions map from the parsed SELECT statement. 48 defaultExprs := make([]tree.TypedExpr, 0, len(cols)) 49 exprStrings := make([]string, 0, len(cols)) 50 for i := range cols { 51 col := &cols[i] 52 if col.DefaultExpr != nil { 53 exprStrings = append(exprStrings, *col.DefaultExpr) 54 } 55 } 56 exprs, err := parser.ParseExprs(exprStrings) 57 if err != nil { 58 return nil, err 59 } 60 61 defExprIdx := 0 62 semaCtx := tree.MakeSemaContext() 63 for i := range cols { 64 col := &cols[i] 65 if col.DefaultExpr == nil { 66 defaultExprs = append(defaultExprs, tree.DNull) 67 continue 68 } 69 expr := exprs[defExprIdx] 70 typedExpr, err := tree.TypeCheck(ctx, expr, &semaCtx, col.Type) 71 if err != nil { 72 return nil, err 73 } 74 if typedExpr, err = txCtx.NormalizeExpr(evalCtx, typedExpr); err != nil { 75 return nil, err 76 } 77 defaultExprs = append(defaultExprs, typedExpr) 78 defExprIdx++ 79 } 80 return defaultExprs, nil 81 } 82 83 // ProcessDefaultColumns adds columns with DEFAULT to cols if not present 84 // and returns the defaultExprs for cols. 85 func ProcessDefaultColumns( 86 ctx context.Context, 87 cols []ColumnDescriptor, 88 tableDesc *ImmutableTableDescriptor, 89 txCtx *transform.ExprTransformContext, 90 evalCtx *tree.EvalContext, 91 ) ([]ColumnDescriptor, []tree.TypedExpr, error) { 92 cols = processColumnSet(cols, tableDesc, func(col *ColumnDescriptor) bool { 93 return col.DefaultExpr != nil 94 }) 95 defaultExprs, err := MakeDefaultExprs(ctx, cols, txCtx, evalCtx) 96 return cols, defaultExprs, err 97 } 98 99 func processColumnSet( 100 cols []ColumnDescriptor, tableDesc *ImmutableTableDescriptor, inSet func(*ColumnDescriptor) bool, 101 ) []ColumnDescriptor { 102 colIDSet := make(map[ColumnID]struct{}, len(cols)) 103 for i := range cols { 104 colIDSet[cols[i].ID] = struct{}{} 105 } 106 107 // Add all public or columns in DELETE_AND_WRITE_ONLY state 108 // that satisfy the condition. 109 writable := tableDesc.WritableColumns() 110 for i := range writable { 111 col := &writable[i] 112 if inSet(col) { 113 if _, ok := colIDSet[col.ID]; !ok { 114 colIDSet[col.ID] = struct{}{} 115 cols = append(cols, *col) 116 } 117 } 118 } 119 return cols 120 }