1 | /* Copyright (c) 2010, 2014, Oracle and/or its affiliates. |
2 | Copyright (c) 2013, 2018, MariaDB Corporation. |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by |
6 | the Free Software Foundation; version 2 of the License. |
7 | |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | GNU General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU General Public License |
14 | along with this program; if not, write to the Free Software |
15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
16 | |
17 | #ifndef SQL_ALTER_TABLE_H |
18 | #define SQL_ALTER_TABLE_H |
19 | |
20 | class Alter_drop; |
21 | class Alter_column; |
22 | class Key; |
23 | |
24 | /** |
25 | Data describing the table being created by CREATE TABLE or |
26 | altered by ALTER TABLE. |
27 | */ |
28 | |
29 | class Alter_info |
30 | { |
31 | public: |
32 | |
33 | enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE }; |
34 | |
35 | bool data_modifying() const |
36 | { |
37 | return flags & ( |
38 | ALTER_PARSER_ADD_COLUMN | |
39 | ALTER_PARSER_DROP_COLUMN | |
40 | ALTER_CHANGE_COLUMN | |
41 | ALTER_COLUMN_ORDER); |
42 | } |
43 | |
44 | /** |
45 | The different values of the ALGORITHM clause. |
46 | Describes which algorithm to use when altering the table. |
47 | */ |
48 | enum enum_alter_table_algorithm |
49 | { |
50 | /* |
51 | Use thd->variables.alter_algorithm for alter method. If this is also |
52 | default then use the fastest possible ALTER TABLE method |
53 | (INSTANT, NOCOPY, INPLACE, COPY) |
54 | */ |
55 | ALTER_TABLE_ALGORITHM_DEFAULT, |
56 | |
57 | // Copy if supported, error otherwise. |
58 | ALTER_TABLE_ALGORITHM_COPY, |
59 | |
60 | // In-place if supported, error otherwise. |
61 | ALTER_TABLE_ALGORITHM_INPLACE, |
62 | |
63 | // No Copy will refuse any operation which does rebuild. |
64 | ALTER_TABLE_ALGORITHM_NOCOPY, |
65 | |
66 | // Instant should allow any operation that changes metadata only. |
67 | ALTER_TABLE_ALGORITHM_INSTANT |
68 | }; |
69 | |
70 | |
71 | /** |
72 | The different values of the LOCK clause. |
73 | Describes the level of concurrency during ALTER TABLE. |
74 | */ |
75 | enum enum_alter_table_lock |
76 | { |
77 | // Maximum supported level of concurency for the given operation. |
78 | ALTER_TABLE_LOCK_DEFAULT, |
79 | |
80 | // Allow concurrent reads & writes. If not supported, give error. |
81 | ALTER_TABLE_LOCK_NONE, |
82 | |
83 | // Allow concurrent reads only. If not supported, give error. |
84 | ALTER_TABLE_LOCK_SHARED, |
85 | |
86 | // Block reads and writes. |
87 | ALTER_TABLE_LOCK_EXCLUSIVE |
88 | }; |
89 | |
90 | |
91 | // Columns and keys to be dropped. |
92 | List<Alter_drop> drop_list; |
93 | // Columns for ALTER_COLUMN_CHANGE_DEFAULT. |
94 | List<Alter_column> alter_list; |
95 | // List of keys, used by both CREATE and ALTER TABLE. |
96 | List<Key> key_list; |
97 | // List of columns, used by both CREATE and ALTER TABLE. |
98 | List<Create_field> create_list; |
99 | |
100 | enum flags_bits |
101 | { |
102 | CHECK_CONSTRAINT_IF_NOT_EXISTS= 1 |
103 | }; |
104 | List<Virtual_column_info> check_constraint_list; |
105 | // Type of ALTER TABLE operation. |
106 | alter_table_operations flags; |
107 | ulong partition_flags; |
108 | // Enable or disable keys. |
109 | enum_enable_or_disable keys_onoff; |
110 | // List of partitions. |
111 | List<const char> partition_names; |
112 | // Number of partitions. |
113 | uint num_parts; |
114 | // Type of ALTER TABLE algorithm. |
115 | enum_alter_table_algorithm requested_algorithm; |
116 | // Type of ALTER TABLE lock. |
117 | enum_alter_table_lock requested_lock; |
118 | |
119 | |
120 | Alter_info() : |
121 | flags(0), partition_flags(0), |
122 | keys_onoff(LEAVE_AS_IS), |
123 | num_parts(0), |
124 | requested_algorithm(ALTER_TABLE_ALGORITHM_DEFAULT), |
125 | requested_lock(ALTER_TABLE_LOCK_DEFAULT) |
126 | {} |
127 | |
128 | void reset() |
129 | { |
130 | drop_list.empty(); |
131 | alter_list.empty(); |
132 | key_list.empty(); |
133 | create_list.empty(); |
134 | check_constraint_list.empty(); |
135 | flags= 0; |
136 | partition_flags= 0; |
137 | keys_onoff= LEAVE_AS_IS; |
138 | num_parts= 0; |
139 | partition_names.empty(); |
140 | requested_algorithm= ALTER_TABLE_ALGORITHM_DEFAULT; |
141 | requested_lock= ALTER_TABLE_LOCK_DEFAULT; |
142 | } |
143 | |
144 | |
145 | /** |
146 | Construct a copy of this object to be used for mysql_alter_table |
147 | and mysql_create_table. |
148 | |
149 | Historically, these two functions modify their Alter_info |
150 | arguments. This behaviour breaks re-execution of prepared |
151 | statements and stored procedures and is compensated by always |
152 | supplying a copy of Alter_info to these functions. |
153 | |
154 | @param rhs Alter_info to make copy of |
155 | @param mem_root Mem_root for new Alter_info |
156 | |
157 | @note You need to use check the error in THD for out |
158 | of memory condition after calling this function. |
159 | */ |
160 | Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root); |
161 | |
162 | |
163 | /** |
164 | Parses the given string and sets requested_algorithm |
165 | if the string value matches a supported value. |
166 | Supported values: INPLACE, COPY, DEFAULT |
167 | |
168 | @param str String containing the supplied value |
169 | @retval false Supported value found, state updated |
170 | @retval true Not supported value, no changes made |
171 | */ |
172 | bool set_requested_algorithm(const LEX_CSTRING *str); |
173 | |
174 | |
175 | /** |
176 | Parses the given string and sets requested_lock |
177 | if the string value matches a supported value. |
178 | Supported values: NONE, SHARED, EXCLUSIVE, DEFAULT |
179 | |
180 | @param str String containing the supplied value |
181 | @retval false Supported value found, state updated |
182 | @retval true Not supported value, no changes made |
183 | */ |
184 | |
185 | bool set_requested_lock(const LEX_CSTRING *str); |
186 | |
187 | /** |
188 | Returns the algorithm value in the format "algorithm=value" |
189 | */ |
190 | const char* algorithm() const; |
191 | |
192 | /** |
193 | Returns the lock value in the format "lock=value" |
194 | */ |
195 | const char* lock() const; |
196 | |
197 | /** |
198 | Check whether the given result can be supported |
199 | with the specified user alter algorithm. |
200 | |
201 | @param thd Thread handle |
202 | @param result Operation supported for inplace alter |
203 | @param ha_alter_info Structure describing changes to be done |
204 | by ALTER TABLE and holding data during |
205 | in-place alter |
206 | @retval false Supported operation |
207 | @retval true Not supported value |
208 | */ |
209 | bool supports_algorithm(THD *thd, enum_alter_inplace_result result, |
210 | const Alter_inplace_info *ha_alter_info); |
211 | |
212 | /** |
213 | Check whether the given result can be supported |
214 | with the specified user lock type. |
215 | |
216 | @param result Operation supported for inplace alter |
217 | @param ha_alter_info Structure describing changes to be done |
218 | by ALTER TABLE and holding data during |
219 | in-place alter |
220 | @retval false Supported lock type |
221 | @retval true Not supported value |
222 | */ |
223 | bool supports_lock(THD *thd, enum_alter_inplace_result result, |
224 | const Alter_inplace_info *ha_alter_info); |
225 | |
226 | private: |
227 | Alter_info &operator=(const Alter_info &rhs); // not implemented |
228 | Alter_info(const Alter_info &rhs); // not implemented |
229 | }; |
230 | |
231 | |
232 | /** Runtime context for ALTER TABLE. */ |
233 | class Alter_table_ctx |
234 | { |
235 | public: |
236 | Alter_table_ctx(); |
237 | |
238 | Alter_table_ctx(THD *thd, TABLE_LIST *table_list, uint tables_opened_arg, |
239 | const LEX_CSTRING *new_db_arg, const LEX_CSTRING *new_name_arg); |
240 | |
241 | /** |
242 | @return true if the table is moved to another database, false otherwise. |
243 | */ |
244 | bool is_database_changed() const |
245 | { return (new_db.str != db.str); }; |
246 | |
247 | /** |
248 | @return true if the table is renamed, false otherwise. |
249 | */ |
250 | bool is_table_renamed() const |
251 | { return (is_database_changed() || new_name.str != table_name.str); }; |
252 | |
253 | /** |
254 | @return filename (including .frm) for the new table. |
255 | */ |
256 | const char *get_new_filename() const |
257 | { |
258 | DBUG_ASSERT(!tmp_table); |
259 | return new_filename; |
260 | } |
261 | |
262 | /** |
263 | @return path to the original table. |
264 | */ |
265 | const char *get_path() const |
266 | { |
267 | DBUG_ASSERT(!tmp_table); |
268 | return path; |
269 | } |
270 | |
271 | /** |
272 | @return path to the new table. |
273 | */ |
274 | const char *get_new_path() const |
275 | { |
276 | DBUG_ASSERT(!tmp_table); |
277 | return new_path; |
278 | } |
279 | |
280 | /** |
281 | @return path to the temporary table created during ALTER TABLE. |
282 | */ |
283 | const char *get_tmp_path() const |
284 | { return tmp_path; } |
285 | |
286 | /** |
287 | Mark ALTER TABLE as needing to produce foreign key error if |
288 | it deletes a row from the table being changed. |
289 | */ |
290 | void set_fk_error_if_delete_row(FOREIGN_KEY_INFO *fk) |
291 | { |
292 | fk_error_if_delete_row= true; |
293 | fk_error_id= fk->foreign_id->str; |
294 | fk_error_table= fk->foreign_table->str; |
295 | } |
296 | |
297 | public: |
298 | Create_field *datetime_field; |
299 | bool error_if_not_empty; |
300 | uint tables_opened; |
301 | LEX_CSTRING db; |
302 | LEX_CSTRING table_name; |
303 | LEX_CSTRING alias; |
304 | LEX_CSTRING new_db; |
305 | LEX_CSTRING new_name; |
306 | LEX_CSTRING new_alias; |
307 | LEX_CSTRING tmp_name; |
308 | char tmp_buff[80]; |
309 | /** |
310 | Indicates that if a row is deleted during copying of data from old version |
311 | of table to the new version ER_FK_CANNOT_DELETE_PARENT error should be |
312 | emitted. |
313 | */ |
314 | bool fk_error_if_delete_row; |
315 | /** Name of foreign key for the above error. */ |
316 | const char *fk_error_id; |
317 | /** Name of table for the above error. */ |
318 | const char *fk_error_table; |
319 | |
320 | private: |
321 | char new_filename[FN_REFLEN + 1]; |
322 | char new_alias_buff[NAME_LEN + 1]; |
323 | char tmp_name_buff[NAME_LEN + 1]; |
324 | char path[FN_REFLEN + 1]; |
325 | char new_path[FN_REFLEN + 1]; |
326 | char tmp_path[FN_REFLEN + 1]; |
327 | |
328 | #ifdef DBUG_ASSERT_EXISTS |
329 | /** Indicates that we are altering temporary table. Used only in asserts. */ |
330 | bool tmp_table; |
331 | #endif |
332 | |
333 | Alter_table_ctx &operator=(const Alter_table_ctx &rhs); // not implemented |
334 | Alter_table_ctx(const Alter_table_ctx &rhs); // not implemented |
335 | }; |
336 | |
337 | |
338 | /** |
339 | Sql_cmd_common_alter_table represents the common properties of the ALTER TABLE |
340 | statements. |
341 | @todo move Alter_info and other ALTER generic structures from Lex here. |
342 | */ |
343 | class Sql_cmd_common_alter_table : public Sql_cmd |
344 | { |
345 | protected: |
346 | /** |
347 | Constructor. |
348 | */ |
349 | Sql_cmd_common_alter_table() |
350 | {} |
351 | |
352 | virtual ~Sql_cmd_common_alter_table() |
353 | {} |
354 | |
355 | virtual enum_sql_command sql_command_code() const |
356 | { |
357 | return SQLCOM_ALTER_TABLE; |
358 | } |
359 | }; |
360 | |
361 | /** |
362 | Sql_cmd_alter_table represents the generic ALTER TABLE statement. |
363 | @todo move Alter_info and other ALTER specific structures from Lex here. |
364 | */ |
365 | class Sql_cmd_alter_table : public Sql_cmd_common_alter_table |
366 | { |
367 | public: |
368 | /** |
369 | Constructor, used to represent a ALTER TABLE statement. |
370 | */ |
371 | Sql_cmd_alter_table() |
372 | {} |
373 | |
374 | ~Sql_cmd_alter_table() |
375 | {} |
376 | |
377 | bool execute(THD *thd); |
378 | }; |
379 | |
380 | |
381 | /** |
382 | Sql_cmd_alter_sequence represents the ALTER SEQUENCE statement. |
383 | */ |
384 | class Sql_cmd_alter_sequence : public Sql_cmd, |
385 | public DDL_options |
386 | { |
387 | public: |
388 | /** |
389 | Constructor, used to represent a ALTER TABLE statement. |
390 | */ |
391 | Sql_cmd_alter_sequence(const DDL_options &options) |
392 | :DDL_options(options) |
393 | {} |
394 | |
395 | ~Sql_cmd_alter_sequence() |
396 | {} |
397 | |
398 | enum_sql_command sql_command_code() const |
399 | { |
400 | return SQLCOM_ALTER_SEQUENCE; |
401 | } |
402 | bool execute(THD *thd); |
403 | }; |
404 | |
405 | |
406 | /** |
407 | Sql_cmd_alter_table_tablespace represents ALTER TABLE |
408 | IMPORT/DISCARD TABLESPACE statements. |
409 | */ |
410 | class Sql_cmd_discard_import_tablespace : public Sql_cmd_common_alter_table |
411 | { |
412 | public: |
413 | enum enum_tablespace_op_type |
414 | { |
415 | DISCARD_TABLESPACE, IMPORT_TABLESPACE |
416 | }; |
417 | |
418 | Sql_cmd_discard_import_tablespace(enum_tablespace_op_type tablespace_op_arg) |
419 | : m_tablespace_op(tablespace_op_arg) |
420 | {} |
421 | |
422 | bool execute(THD *thd); |
423 | |
424 | private: |
425 | const enum_tablespace_op_type m_tablespace_op; |
426 | }; |
427 | |
428 | #endif |
429 | |