@@ -96,6 +96,7 @@ static bool check_view_single_update(List<Item> &fields, TABLE_LIST *view,
9696 @param table_list The table for insert.
9797 @param fields The insert fields.
9898 @param value_count Number of values supplied
99+ = 0: INSERT ... SELECT, delay field count check
99100 @param check_unique If duplicate values should be rejected.
100101 @param[out] insert_table_ref resolved reference to base table
101102
@@ -113,15 +114,15 @@ static bool check_insert_fields(THD *thd, TABLE_LIST *table_list,
113114
114115 DBUG_ASSERT (table_list->updatable );
115116
116- if (fields.elements == 0 && value_count != 0 )
117+ if (fields.elements == 0 )
117118 {
118119 // No field list supplied, use field list of table being updated.
119120
120121 DBUG_ASSERT (table); // This branch is not reached with a view:
121122
122123 *insert_table_ref= table_list;
123124
124- if (value_count != table->s ->fields )
125+ if (value_count > 0 && value_count != table->s ->fields )
125126 {
126127 my_error (ER_WRONG_VALUE_COUNT_ON_ROW, MYF (0 ), 1L );
127128 return true ;
@@ -146,7 +147,7 @@ static bool check_insert_fields(THD *thd, TABLE_LIST *table_list,
146147 Name_resolution_context_state ctx_state;
147148 int res;
148149
149- if (fields.elements != value_count)
150+ if (value_count > 0 && fields.elements != value_count)
150151 {
151152 my_error (ER_WRONG_VALUE_COUNT_ON_ROW, MYF (0 ), 1L );
152153 return true ;
@@ -1153,15 +1154,15 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
11531154 if (mysql_prepare_insert_check_table (thd, table_list, fields, select_insert))
11541155 DBUG_RETURN (true );
11551156
1157+ // Save the state of the current name resolution context.
1158+ ctx_state.save_state (context, table_list);
1159+
11561160 // Prepare the lists of columns and values in the statement.
11571161 if (values)
11581162 {
1159- /* if we have INSERT ... VALUES () we cannot have a GROUP BY clause */
1163+ // if we have INSERT ... VALUES () we cannot have a GROUP BY clause
11601164 DBUG_ASSERT (!select_lex->group_list .elements );
11611165
1162- /* Save the state of the current name resolution context. */
1163- ctx_state.save_state (context, table_list);
1164-
11651166 /*
11661167 Perform name resolution only in the first table - 'table_list',
11671168 which is the table that is inserted into.
@@ -1192,18 +1193,73 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
11921193 if (!res && duplic == DUP_UPDATE)
11931194 {
11941195 select_lex->no_wrap_view_item = true ;
1195- // Setup the fields to be modified
1196+ // Resolve the columns that will be updated
11961197 res= setup_fields (thd, Ref_ptr_array (),
11971198 update_fields, MARK_COLUMNS_WRITE, 0 , 0 );
11981199 select_lex->no_wrap_view_item = false ;
11991200 if (!res)
12001201 res= check_valid_table_refs (table_list, update_fields, map);
12011202 }
1203+ }
1204+ else if (thd->stmt_arena ->is_stmt_prepare ())
1205+ {
1206+ /*
1207+ This section of code is more or less a duplicate of the code in
1208+ select_insert::prepare, and the 'if' branch above.
1209+ @todo Consolidate these three sections into one.
1210+ */
1211+ /*
1212+ Perform name resolution only in the first table - 'table_list',
1213+ which is the table that is inserted into.
1214+ */
1215+ table_list->next_local = NULL ;
1216+ thd->dup_field = NULL ;
1217+ context->resolve_in_table_list_only (table_list);
12021218
1203- /* Restore the current context. */
1204- ctx_state.restore_state (context, table_list);
1219+ res= check_insert_fields (thd, context->table_list , fields, 0 ,
1220+ !insert_into_view, insert_table_ref);
1221+ table_map map= 0 ;
1222+ if (!res)
1223+ map= (*insert_table_ref)->table ->map ;
1224+
1225+ if (!res && duplic == DUP_UPDATE)
1226+ {
1227+ select_lex->no_wrap_view_item = true ;
1228+
1229+ // Resolve the columns that will be updated
1230+ res= setup_fields (thd, Ref_ptr_array (),
1231+ update_fields, MARK_COLUMNS_WRITE, 0 , 0 );
1232+ select_lex->no_wrap_view_item = false ;
1233+ if (!res)
1234+ res= check_valid_table_refs (table_list, update_fields, map);
1235+
1236+ DBUG_ASSERT (!table_list->next_name_resolution_table );
1237+ if (select_lex->group_list .elements == 0 && !select_lex->with_sum_func )
1238+ {
1239+ /*
1240+ There are two separata name resolution contexts:
1241+ the INSERT table and the tables in the SELECT expression
1242+ Make a single context out of them by concatenating the lists:
1243+ */
1244+ table_list->next_name_resolution_table =
1245+ ctx_state.get_first_name_resolution_table ();
1246+ }
1247+ thd->lex ->in_update_value_clause = true ;
1248+ if (!res)
1249+ res= setup_fields (thd, Ref_ptr_array (), update_values,
1250+ MARK_COLUMNS_READ, 0 , 0 );
1251+ thd->lex ->in_update_value_clause = false ;
1252+
1253+ /*
1254+ Notice that there is no need to apply the Item::update_value_transformer
1255+ here, as this will be done during EXECUTE in select_insert::prepare().
1256+ */
1257+ }
12051258 }
12061259
1260+ // Restore the current name resolution context
1261+ ctx_state.restore_state (context, table_list);
1262+
12071263 if (res)
12081264 DBUG_RETURN (res);
12091265
0 commit comments