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
20class Alter_drop;
21class Alter_column;
22class Key;
23
24/**
25 Data describing the table being created by CREATE TABLE or
26 altered by ALTER TABLE.
27*/
28
29class Alter_info
30{
31public:
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
226private:
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. */
233class Alter_table_ctx
234{
235public:
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
297public:
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
320private:
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*/
343class Sql_cmd_common_alter_table : public Sql_cmd
344{
345protected:
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*/
365class Sql_cmd_alter_table : public Sql_cmd_common_alter_table
366{
367public:
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*/
384class Sql_cmd_alter_sequence : public Sql_cmd,
385 public DDL_options
386{
387public:
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*/
410class Sql_cmd_discard_import_tablespace : public Sql_cmd_common_alter_table
411{
412public:
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
424private:
425 const enum_tablespace_op_type m_tablespace_op;
426};
427
428#endif
429