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