1 /* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 #ifndef SQL_INSERT_INCLUDED 24 #define SQL_INSERT_INCLUDED 25 26 #include "sql_class.h" // Query_result_interceptor 27 #include "sql_cmd_dml.h" // Sql_cmd_dml 28 #include "sql_data_change.h" // enum_duplicates 29 30 struct TABLE_LIST; 31 typedef List<Item> List_item; 32 33 int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, 34 TABLE_LIST *table_list); 35 void prepare_triggers_for_insert_stmt(TABLE *table); 36 int write_record(THD *thd, TABLE *table, 37 COPY_INFO *info, COPY_INFO *update); 38 bool validate_default_values_of_unset_fields(THD *thd, TABLE *table); 39 bool mysql_insert_select_prepare(THD *thd); 40 41 class Query_result_insert :public Query_result_interceptor 42 { 43 public: 44 TABLE_LIST *table_list; 45 TABLE *table; 46 private: 47 /** 48 The columns of the table to be inserted into, *or* the columns of the 49 table from which values are selected. For legacy reasons both are 50 allowed. 51 */ 52 List<Item> *fields; 53 protected: 54 /// ha_start_bulk_insert has been called. Never cleared. 55 bool bulk_insert_started; 56 public: 57 ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not 58 COPY_INFO info; 59 COPY_INFO update; ///< the UPDATE part of "info" 60 bool insert_into_view; 61 62 /** 63 Creates a Query_result_insert for routing a result set to an existing 64 table. 65 66 @param table_list_par The table reference for the destination table. 67 @param table_par The destination table. May be NULL. 68 @param target_columns See details. 69 @param target_or_source_columns See details. 70 @param update_fields The columns to be updated in case of duplicate 71 keys. May be NULL. 72 @param update_values The values to be assigned in case of duplicate 73 keys. May be NULL. 74 @param duplicate The policy for handling duplicates. 75 76 @todo This constructor takes 8 arguments, 6 of which are used to 77 immediately construct a COPY_INFO object. Obviously the constructor 78 should take the COPY_INFO object as argument instead. Also, some 79 Query_result_insert members initialized here are totally redundant, as they are 80 found inside the COPY_INFO. 81 82 The target_columns and target_or_source_columns arguments are set by 83 callers as follows: 84 @li if CREATE SELECT: 85 - target_columns == NULL, 86 - target_or_source_columns == expressions listed after SELECT, as in 87 CREATE ... SELECT expressions 88 @li if INSERT SELECT: 89 target_columns 90 == target_or_source_columns 91 == columns listed between INSERT and SELECT, as in 92 INSERT INTO t (columns) SELECT ... 93 94 We set the manage_defaults argument of info's constructor as follows 95 ([...] denotes something optional): 96 @li If target_columns==NULL, the statement is 97 @verbatim 98 CREATE TABLE a_table [(columns1)] SELECT expressions2 99 @endverbatim 100 so 'info' must manage defaults of columns1. 101 @li Otherwise it is: 102 @verbatim 103 INSERT INTO a_table [(columns1)] SELECT ... 104 @verbatim 105 target_columns is columns1, if not empty then 'info' must manage defaults 106 of other columns than columns1. 107 */ Query_result_insert(TABLE_LIST * table_list_par,TABLE * table_par,List<Item> * target_columns,List<Item> * target_or_source_columns,List<Item> * update_fields,List<Item> * update_values,enum_duplicates duplic)108 Query_result_insert(TABLE_LIST *table_list_par, 109 TABLE *table_par, 110 List<Item> *target_columns, 111 List<Item> *target_or_source_columns, 112 List<Item> *update_fields, 113 List<Item> *update_values, 114 enum_duplicates duplic) 115 :table_list(table_list_par), 116 table(table_par), 117 fields(target_or_source_columns), 118 bulk_insert_started(false), 119 autoinc_value_of_last_inserted_row(0), 120 info(COPY_INFO::INSERT_OPERATION, 121 target_columns, 122 // manage_defaults 123 (target_columns == NULL || target_columns->elements != 0), 124 duplic), 125 update(COPY_INFO::UPDATE_OPERATION, 126 update_fields, 127 update_values), 128 insert_into_view(table_list_par && table_list_par->is_view()) 129 { 130 DBUG_ASSERT(target_or_source_columns != NULL); 131 DBUG_ASSERT(target_columns == target_or_source_columns || 132 target_columns == NULL); 133 } 134 135 136 public: 137 ~Query_result_insert(); need_explain_interceptor()138 virtual bool need_explain_interceptor() const { return true; } 139 int prepare(List<Item> &list, SELECT_LEX_UNIT *u); 140 virtual int prepare2(void); 141 bool send_data(List<Item> &items); 142 virtual void store_values(List<Item> &values); 143 void send_error(uint errcode,const char *err); 144 bool send_eof(); 145 virtual void abort_result_set(); 146 /* not implemented: Query_result_insert is never re-used in prepared statements */ 147 void cleanup(); 148 }; 149 150 151 /** 152 @todo This class inherits a class which is non-abstract. This is not in 153 line with good programming practices and the inheritance should be broken 154 up. 155 */ 156 class Query_result_create: public Query_result_insert { 157 TABLE_LIST *create_table; 158 HA_CREATE_INFO *create_info; 159 TABLE_LIST *select_tables; 160 Alter_info *alter_info; 161 Field **field; 162 /* lock data for tmp table */ 163 MYSQL_LOCK *m_lock; 164 /* m_lock or thd->extra_lock */ 165 MYSQL_LOCK **m_plock; 166 public: Query_result_create(TABLE_LIST * table_arg,HA_CREATE_INFO * create_info_par,Alter_info * alter_info_arg,List<Item> & select_fields,enum_duplicates duplic,TABLE_LIST * select_tables_arg)167 Query_result_create(TABLE_LIST *table_arg, 168 HA_CREATE_INFO *create_info_par, 169 Alter_info *alter_info_arg, 170 List<Item> &select_fields, 171 enum_duplicates duplic, 172 TABLE_LIST *select_tables_arg) 173 :Query_result_insert (NULL, // table_list_par 174 NULL, // table_par 175 NULL, // target_columns 176 &select_fields, 177 NULL, // update_fields 178 NULL, // update_values 179 duplic), 180 create_table(table_arg), 181 create_info(create_info_par), 182 select_tables(select_tables_arg), 183 alter_info(alter_info_arg), 184 m_plock(NULL) 185 {} 186 int prepare(List<Item> &list, SELECT_LEX_UNIT *u); 187 188 int binlog_show_create_table(TABLE **tables, uint count); 189 void store_values(List<Item> &values); 190 void send_error(uint errcode,const char *err); 191 bool send_eof(); 192 virtual void abort_result_set(); 193 194 // Needed for access from local class MY_HOOKS in prepare(), since thd is proteted. get_thd(void)195 const THD *get_thd(void) { return thd; } get_create_info()196 const HA_CREATE_INFO *get_create_info() { return create_info; }; 197 int prepare2(void); 198 }; 199 200 201 class Sql_cmd_insert_base : public Sql_cmd_dml 202 { 203 /* 204 field_list was created for view and should be removed before PS/SP 205 rexecuton 206 */ 207 bool empty_field_list_on_rset; 208 209 protected: 210 const bool is_replace; 211 212 public: 213 /** 214 Field list to insert/replace 215 216 One of two things: 217 1. For the INSERT/REPLACE ... (col1, ... colN) VALUES ... syntax 218 this is a list of col1, ..., colN fields. 219 2. For the INSERT/REPLACE ... SET col1=x1, ... colM=xM syntax extension 220 this is a list of col1, ... colM fields as well. 221 */ 222 List<Item> insert_field_list; 223 /** 224 ON DUPLICATE KEY UPDATE data value list 225 */ 226 List<Item> insert_value_list; 227 /** 228 ON DUPLICATE KEY UPDATE field list 229 */ 230 List<Item> insert_update_list; 231 /** 232 Row data to insert/replace 233 234 One of two things: 235 1. For the INSERT/REPLACE ... VALUES (row1), (row2), ... (rowN) syntax 236 the list contains N List_item lists: one List_item per row. 237 2. For the INSERT/REPLACE ... SET col1=x1, ... colM=xM syntax extension 238 this list contains only 1 List_item of M data values: this way we 239 emulate this syntax: 240 INSERT/REPLACE ... (col1, ... colM) VALUE (x1, ..., xM); 241 */ 242 List<List_item> insert_many_values; // TODO: move to Sql_cmd_insert 243 244 const enum_duplicates duplicates; 245 246 explicit Sql_cmd_insert_base(bool is_replace_arg,enum_duplicates duplicates_arg)247 Sql_cmd_insert_base(bool is_replace_arg, enum_duplicates duplicates_arg) 248 : empty_field_list_on_rset(false), 249 is_replace(is_replace_arg), 250 duplicates(duplicates_arg) 251 {} 252 cleanup(THD * thd)253 virtual void cleanup(THD *thd) 254 { 255 if (empty_field_list_on_rset) 256 { 257 empty_field_list_on_rset= false; 258 insert_field_list.empty(); 259 } 260 } 261 262 263 protected: 264 bool mysql_prepare_insert(THD *thd, 265 TABLE_LIST *table_list, 266 List_item *values, 267 bool select_insert); 268 bool insert_precheck(THD *thd, TABLE_LIST *tables); 269 bool mysql_prepare_insert_check_table(THD *thd, 270 TABLE_LIST *table_list, 271 List<Item> &fields, 272 bool select_insert); 273 }; 274 275 276 class Sql_cmd_insert : public Sql_cmd_insert_base 277 { 278 public: 279 explicit Sql_cmd_insert(bool is_replace_arg,enum_duplicates duplicates_arg)280 Sql_cmd_insert(bool is_replace_arg, enum_duplicates duplicates_arg) 281 : Sql_cmd_insert_base(is_replace_arg, duplicates_arg) 282 {} 283 sql_command_code()284 virtual enum_sql_command sql_command_code() const 285 { 286 return is_replace ? SQLCOM_REPLACE : SQLCOM_INSERT; 287 } 288 289 virtual bool execute(THD *thd); 290 virtual bool prepared_statement_test(THD *thd); prepare(THD * thd)291 virtual bool prepare(THD *thd) { return false; } 292 293 private: 294 bool mysql_insert(THD *thd,TABLE_LIST *table); 295 296 bool mysql_test_insert(THD *thd, TABLE_LIST *table_list); 297 }; 298 299 300 class Sql_cmd_insert_select : public Sql_cmd_insert_base 301 { 302 public: 303 explicit Sql_cmd_insert_select(bool is_replace_arg,enum_duplicates duplicates_arg)304 Sql_cmd_insert_select(bool is_replace_arg, enum_duplicates duplicates_arg) 305 : Sql_cmd_insert_base(is_replace_arg, duplicates_arg) 306 {} 307 sql_command_code()308 virtual enum_sql_command sql_command_code() const 309 { 310 return is_replace ? SQLCOM_REPLACE_SELECT : SQLCOM_INSERT_SELECT; 311 } 312 313 virtual bool execute(THD *thd); 314 virtual bool prepared_statement_test(THD *thd); 315 virtual bool prepare(THD *thd); 316 317 protected: 318 bool mysql_insert_select_prepare(THD *thd); 319 }; 320 321 #endif /* SQL_INSERT_INCLUDED */ 322