@@ -69,7 +69,12 @@ func (p *planner) CreateTable(ctx context.Context, n *tree.CreateTable) (planNod
69
69
return nil , err
70
70
}
71
71
72
- numColNames := len (n .AsColumnNames )
72
+ numColNames := 0
73
+ for i := 0 ; i < len (n .Defs ); i ++ {
74
+ if _ , ok := n .Defs [i ].(* tree.ColumnTableDef ); ok {
75
+ numColNames ++
76
+ }
77
+ }
73
78
numColumns := len (planColumns (sourcePlan ))
74
79
if numColNames != 0 && numColNames != numColumns {
75
80
sourcePlan .Close (ctx )
@@ -80,12 +85,22 @@ func (p *planner) CreateTable(ctx context.Context, n *tree.CreateTable) (planNod
80
85
}
81
86
82
87
// Synthesize an input column that provides the default value for the
83
- // hidden rowid column.
88
+ // hidden rowid column, if none of the provided columns are specified
89
+ // as the PRIMARY KEY.
84
90
synthRowID = true
91
+ for _ , def := range n .Defs {
92
+ if d , ok := def .(* tree.ColumnTableDef ); ok && d .PrimaryKey {
93
+ synthRowID = false
94
+ break
95
+ }
96
+ }
85
97
}
86
98
87
99
ct := & createTableNode {n : n , dbDesc : dbDesc , sourcePlan : sourcePlan }
88
100
ct .run .synthRowID = synthRowID
101
+ // This method is only invoked if the heuristic planner was used in the
102
+ // planning stage.
103
+ ct .run .fromHeuristicPlanner = true
89
104
return ct , nil
90
105
}
91
106
@@ -95,10 +110,17 @@ type createTableRun struct {
95
110
autoCommit autoCommitOpt
96
111
97
112
// synthRowID indicates whether an input column needs to be synthesized to
98
- // provide the default value for the hidden rowid column. The optimizer's
99
- // plan already includes this column (so synthRowID is false), whereas the
100
- // heuristic planner's plan does not (so synthRowID is true).
113
+ // provide the default value for the hidden rowid column. The optimizer's plan
114
+ // already includes this column if a user specified PK does not exist (so
115
+ // synthRowID is false), whereas the heuristic planner's plan does not in this
116
+ // case (so synthRowID is true).
101
117
synthRowID bool
118
+
119
+ // fromHeuristicPlanner indicates whether the planning was performed by the
120
+ // heuristic planner instead of the optimizer. This is used to determine
121
+ // whether or not a row_id was synthesized as part of the planning stage, if a
122
+ // user defined PK is not specified.
123
+ fromHeuristicPlanner bool
102
124
}
103
125
104
126
func (n * createTableNode ) startExec (params runParams ) error {
@@ -139,15 +161,18 @@ func (n *createTableNode) startExec(params runParams) error {
139
161
}
140
162
141
163
asCols = planColumns (n .sourcePlan )
142
- if ! n .run .synthRowID {
143
- // rowID column is already present in the input as the last column, so
144
- // ignore it for the purpose of creating column metadata (because
164
+ if ! n .run .fromHeuristicPlanner && ! n .n .AsHasUserSpecifiedPrimaryKey () {
165
+ // rowID column is already present in the input as the last column if it
166
+ // was planned by the optimizer and the user did not specify a PRIMARY
167
+ // KEY. So ignore it for the purpose of creating column metadata (because
145
168
// makeTableDescIfAs does it automatically).
146
169
asCols = asCols [:len (asCols )- 1 ]
147
170
}
148
- desc , err = makeTableDescIfAs (
171
+
172
+ desc , err = makeTableDescIfAs (params ,
149
173
n .n , n .dbDesc .ID , id , creationTime , asCols ,
150
- privs , & params .p .semaCtx , params .p .EvalContext ())
174
+ privs , params .p .EvalContext ())
175
+
151
176
if err != nil {
152
177
return err
153
178
}
@@ -259,9 +284,9 @@ func (n *createTableNode) startExec(params runParams) error {
259
284
return err
260
285
}
261
286
262
- // Prepare the buffer for row values. At this point, one more
263
- // column has been added by ensurePrimaryKey() to the list of
264
- // columns in sourcePlan .
287
+ // Prepare the buffer for row values. At this point, one more column has
288
+ // been added by ensurePrimaryKey() to the list of columns in sourcePlan, if
289
+ // a PRIMARY KEY is not specified by the user .
265
290
rowBuffer := make (tree.Datums , len (desc .Columns ))
266
291
pkColIdx := len (desc .Columns ) - 1
267
292
@@ -985,38 +1010,51 @@ func getFinalSourceQuery(source *tree.Select, evalCtx *tree.EvalContext) string
985
1010
// makeTableDescIfAs is the MakeTableDesc method for when we have a table
986
1011
// that is created with the CREATE AS format.
987
1012
func makeTableDescIfAs (
1013
+ params runParams ,
988
1014
p * tree.CreateTable ,
989
1015
parentID , id sqlbase.ID ,
990
1016
creationTime hlc.Timestamp ,
991
1017
resultColumns []sqlbase.ResultColumn ,
992
1018
privileges * sqlbase.PrivilegeDescriptor ,
993
- semaCtx * tree.SemaContext ,
994
1019
evalContext * tree.EvalContext ,
995
1020
) (desc sqlbase.MutableTableDescriptor , err error ) {
996
- desc = InitTableDescriptor (id , parentID , p .Table .Table (), creationTime , privileges )
997
- desc .CreateQuery = getFinalSourceQuery (p .AsSource , evalContext )
998
-
999
- for i , colRes := range resultColumns {
1000
- columnTableDef := tree.ColumnTableDef {Name : tree .Name (colRes .Name ), Type : colRes .Typ }
1001
- columnTableDef .Nullable .Nullability = tree .SilentNull
1002
- if len (p .AsColumnNames ) > i {
1003
- columnTableDef .Name = p .AsColumnNames [i ]
1004
- }
1005
-
1006
- // The new types in the CREATE TABLE AS column specs never use
1007
- // SERIAL so we need not process SERIAL types here.
1008
- col , _ , _ , err := sqlbase .MakeColumnDefDescs (& columnTableDef , semaCtx )
1009
- if err != nil {
1010
- return desc , err
1021
+ colResIndex := 0
1022
+ // TableDefs for a CREATE TABLE ... AS AST node comprise of a ColumnTableDef
1023
+ // for each column, and a ConstraintTableDef for any constraints on those
1024
+ // columns.
1025
+ for _ , defs := range p .Defs {
1026
+ var d * tree.ColumnTableDef
1027
+ var ok bool
1028
+ if d , ok = defs .(* tree.ColumnTableDef ); ok {
1029
+ d .Type = resultColumns [colResIndex ].Typ
1030
+ colResIndex ++
1031
+ }
1032
+ }
1033
+
1034
+ // If there are no TableDefs defined by the parser, then we construct a
1035
+ // ColumnTableDef for each column using resultColumns.
1036
+ if len (p .Defs ) == 0 {
1037
+ for _ , colRes := range resultColumns {
1038
+ var d * tree.ColumnTableDef
1039
+ var ok bool
1040
+ var tableDef tree.TableDef = & tree.ColumnTableDef {Name : tree .Name (colRes .Name ), Type : colRes .Typ }
1041
+ if d , ok = tableDef .(* tree.ColumnTableDef ); ! ok {
1042
+ return desc , errors .Errorf ("failed to cast type to ColumnTableDef\n " )
1043
+ }
1044
+ d .Nullable .Nullability = tree .SilentNull
1045
+ p .Defs = append (p .Defs , tableDef )
1011
1046
}
1012
- desc .AddColumn (col )
1013
1047
}
1014
1048
1015
- // AllocateIDs mutates its receiver. `return desc, desc.AllocateIDs()`
1016
- // happens to work in gc, but does not work in gccgo.
1017
- //
1018
- // See https://github.com/golang/go/issues/23188.
1019
- err = desc .AllocateIDs ()
1049
+ desc , err = makeTableDesc (
1050
+ params ,
1051
+ p ,
1052
+ parentID , id ,
1053
+ creationTime ,
1054
+ privileges ,
1055
+ nil , /* affected */
1056
+ )
1057
+ desc .CreateQuery = getFinalSourceQuery (p .AsSource , evalContext )
1020
1058
return desc , err
1021
1059
}
1022
1060
0 commit comments