@@ -90,6 +90,65 @@ func resolveInsertRows(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Sc
9090 })
9191}
9292
93+ func validateInsertRows (ctx * sql.Context , a * Analyzer , n sql.Node , scope * plan.Scope , sel RuleSelector , qFlags * sql.QueryFlags ) (sql.Node , transform.TreeIdentity , error ) {
94+ if _ , ok := n .(* plan.TriggerExecutor ); ok {
95+ return n , transform .SameTree , nil
96+ } else if _ , ok := n .(* plan.CreateProcedure ); ok {
97+ return n , transform .SameTree , nil
98+ }
99+ // We capture all INSERTs along the tree, such as those inside of block statements.
100+ var err error
101+ transform .Inspect (n , func (n sql.Node ) bool {
102+ insert , ok := n .(* plan.InsertInto )
103+ if ! ok {
104+ return true
105+ }
106+
107+ var insertable sql.InsertableTable
108+ table := getResolvedTable (insert .Destination )
109+ insertable , err = plan .GetInsertable (table )
110+ if err != nil {
111+ return false
112+ }
113+
114+ source := insert .Source
115+ dstSchema := insertable .Schema ()
116+
117+ // normalize the column name
118+ columnNames := make ([]string , len (insert .ColumnNames ))
119+ for i , name := range insert .ColumnNames {
120+ columnNames [i ] = strings .ToLower (name )
121+ }
122+
123+ // If no columns are given and value tuples are not all empty, use the full schema
124+ if len (columnNames ) == 0 && existsNonZeroValueCount (source ) {
125+ columnNames = make ([]string , len (dstSchema ))
126+ for i , f := range dstSchema {
127+ columnNames [i ] = f .Name
128+ }
129+ }
130+
131+ for _ , col := range dstSchema {
132+ colIdx := findColIdx (col .Name , columnNames )
133+ if colIdx != - 1 {
134+ continue
135+ }
136+
137+ if _ , isTrigExec := source .(* plan.TriggerExecutor ); ! isTrigExec && ! col .AutoIncrement && ! col .Nullable && col .Default == nil && col .Generated == nil {
138+ err = sql .ErrInsertIntoNonNullableDefaultNullColumn .New (col .Name )
139+ return false
140+ }
141+ }
142+
143+ return true
144+ })
145+
146+ if err != nil {
147+ return nil , transform .SameTree , err
148+ }
149+ return n , transform .SameTree , nil
150+ }
151+
93152// Ensures that the number of elements in each Value tuple is empty
94153func existsNonZeroValueCount (values sql.Node ) bool {
95154 switch node := values .(type ) {
@@ -123,15 +182,11 @@ func wrapRowSource(ctx *sql.Context, insertSource sql.Node, destTbl sql.Table, s
123182
124183 for i , col := range schema {
125184 colIdx := findColIdx (col .Name , columnNames )
126- // if column was not explicitly specified, try to substitute with default or generated value
127185 if colIdx == - 1 {
128186 defaultExpr := col .Default
129187 if defaultExpr == nil {
130188 defaultExpr = col .Generated
131189 }
132- if ! col .Nullable && defaultExpr == nil && ! col .AutoIncrement {
133- return nil , - 1 , sql .ErrInsertIntoNonNullableDefaultNullColumn .New (col .Name )
134- }
135190
136191 var err error
137192 colNameToIdx := make (map [string ]int )
0 commit comments