1 /* Copyright (c) 2014, 2020, 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 #include "sql/dd/impl/types/table_impl.h"
24 
25 #include <string.h>
26 #include <set>
27 #include <sstream>
28 #include <string>
29 
30 #include "my_rapidjson_size_t.h"  // IWYU pragma: keep
31 
32 #include <rapidjson/document.h>
33 #include <rapidjson/prettywriter.h>
34 
35 #include "m_string.h"
36 #include "my_dbug.h"
37 #include "my_sys.h"
38 #include "mysqld_error.h"                         // ER_*
39 #include "sql/current_thd.h"                      // current_thd
40 #include "sql/dd/impl/bootstrap/bootstrap_ctx.h"  // dd::bootstrap::DD_bootstrap_ctx
41 #include "sql/dd/impl/dictionary_impl.h"          // Dictionary_impl
42 #include "sql/dd/impl/properties_impl.h"          // Properties_impl
43 #include "sql/dd/impl/raw/raw_record.h"           // Raw_record
44 #include "sql/dd/impl/raw/raw_record_set.h"       // Raw_record_set
45 #include "sql/dd/impl/raw/raw_table.h"            // Raw_table
46 #include "sql/dd/impl/sdi_impl.h"                 // sdi read/write functions
47 #include "sql/dd/impl/tables/check_constraints.h"  // Check_constraints
48 #include "sql/dd/impl/tables/columns.h"            // Columns
49 #include "sql/dd/impl/tables/foreign_keys.h"       // Foreign_keys
50 #include "sql/dd/impl/tables/indexes.h"            // Indexes
51 #include "sql/dd/impl/tables/schemata.h"           // Schemata
52 #include "sql/dd/impl/tables/table_partitions.h"   // Table_partitions
53 #include "sql/dd/impl/tables/tables.h"             // Tables
54 #include "sql/dd/impl/tables/triggers.h"           // Triggers
55 #include "sql/dd/impl/transaction_impl.h"          // Open_dictionary_tables_ctx
56 #include "sql/dd/impl/types/check_constraint_impl.h"  // Check_constraint_impl
57 #include "sql/dd/impl/types/foreign_key_impl.h"       // Foreign_key_impl
58 #include "sql/dd/impl/types/index_impl.h"             // Index_impl
59 #include "sql/dd/impl/types/partition_impl.h"         // Partition_impl
60 #include "sql/dd/impl/types/trigger_impl.h"           // Trigger_impl
61 #include "sql/dd/properties.h"
62 #include "sql/dd/string_type.h"   // dd::String_type
63 #include "sql/dd/types/column.h"  // Column
64 #include "sql/dd/types/foreign_key.h"
65 #include "sql/dd/types/index.h"
66 #include "sql/dd/types/partition.h"
67 #include "sql/dd/types/weak_object.h"
68 #include "sql/sql_class.h"
69 
70 using dd::tables::Check_constraints;
71 using dd::tables::Foreign_keys;
72 using dd::tables::Indexes;
73 using dd::tables::Table_partitions;
74 using dd::tables::Tables;
75 using dd::tables::Triggers;
76 
77 namespace dd {
78 
79 class Sdi_rcontext;
80 class Sdi_wcontext;
81 
82 ///////////////////////////////////////////////////////////////////////////
83 // Table_impl implementation.
84 ///////////////////////////////////////////////////////////////////////////
85 
Table_impl()86 Table_impl::Table_impl()
87     : m_se_private_id(INVALID_OBJECT_ID),
88       m_se_private_data(),
89       m_row_format(RF_FIXED),
90       m_is_temporary(false),
91       m_partition_type(PT_NONE),
92       m_default_partitioning(DP_NONE),
93       m_subpartition_type(ST_NONE),
94       m_default_subpartitioning(DP_NONE),
95       m_indexes(),
96       m_foreign_keys(),
97       m_partitions(),
98       m_triggers(),
99       m_check_constraints(),
100       m_collation_id(INVALID_OBJECT_ID),
101       m_tablespace_id(INVALID_OBJECT_ID) {}
102 
~Table_impl()103 Table_impl::~Table_impl() { delete_container_pointers(m_foreign_key_parents); }
104 
105 ///////////////////////////////////////////////////////////////////////////
106 
validate() const107 bool Table_impl::validate() const {
108   if (Abstract_table_impl::validate()) return true;
109 
110   if (m_collation_id == INVALID_OBJECT_ID) {
111     my_error(ER_INVALID_DD_OBJECT, MYF(0), DD_table::instance().name().c_str(),
112              "Collation ID not set.");
113     return true;
114   }
115 
116   if (m_engine.empty()) {
117     my_error(ER_INVALID_DD_OBJECT, MYF(0), DD_table::instance().name().c_str(),
118              "Engine name is not set.");
119     return true;
120   }
121 
122   return false;
123 }
124 
125 ///////////////////////////////////////////////////////////////////////////
126 
load_foreign_key_parents(Open_dictionary_tables_ctx * otx)127 bool Table_impl::load_foreign_key_parents(Open_dictionary_tables_ctx *otx) {
128   /*
129     Read information about FKs where this table is the parent.
130     The relevant tables are already opened.
131   */
132 
133   // 1. Read the parent's schema name based on schema_id.
134   Raw_table *schema_table = otx->get_table<dd::Schema>();
135   DBUG_ASSERT(schema_table);
136   Primary_id_key schema_pk(schema_id());
137 
138   std::unique_ptr<Raw_record_set> schema_rs;
139   if (schema_table->open_record_set(&schema_pk, schema_rs)) return true;
140 
141   Raw_record *schema_rec = schema_rs->current_record();
142   DBUG_ASSERT(schema_rec);
143   if (schema_rec == nullptr) return true;
144 
145   // 2. Build a key for searching the FK table.
146   Table_reference_range_key parent_ref_key(
147       tables::Foreign_keys::INDEX_K_REF_CATALOG_REF_SCHEMA_REF_TABLE,
148       tables::Foreign_keys::FIELD_REFERENCED_TABLE_CATALOG,
149       String_type(Dictionary_impl::default_catalog_name()),
150       tables::Foreign_keys::FIELD_REFERENCED_TABLE_SCHEMA,
151       schema_rec->read_str(tables::Schemata::FIELD_NAME),
152       tables::Foreign_keys::FIELD_REFERENCED_TABLE, name());
153 
154   // 3. Get the FK record set where this table is parent.
155   Raw_table *foreign_key_table = otx->get_table<dd::Foreign_key>();
156   DBUG_ASSERT(foreign_key_table);
157 
158   std::unique_ptr<Raw_record_set> child_fk_rs;
159   if (foreign_key_table->open_record_set(&parent_ref_key, child_fk_rs))
160     return true;
161 
162   Raw_record *child_fk_rec = child_fk_rs->current_record();
163   while (child_fk_rec) {
164     // 4.1 Get the child table record based on the child table id.
165     Primary_id_key child_pk(
166         child_fk_rec->read_int(tables::Foreign_keys::FIELD_TABLE_ID));
167     Raw_table *tables_table = otx->get_table<dd::Table>();
168     DBUG_ASSERT(tables_table);
169 
170     std::unique_ptr<Raw_record_set> child_table_rs;
171     if (tables_table->open_record_set(&child_pk, child_table_rs)) return true;
172 
173     Raw_record *child_table = child_table_rs->current_record();
174     DBUG_ASSERT(child_table);
175     if (child_table == nullptr) return true;
176 
177     /*
178        4.2 Filter out child tables belonging to different SEs.
179            This is not supported at the moment and we don't want
180            such FKs to show up as Foreign_key_parent objects.
181     */
182     if (my_strcasecmp(
183             system_charset_info,
184             child_table->read_str(tables::Tables::FIELD_ENGINE).c_str(),
185             m_engine.c_str()) != 0) {
186       if (child_fk_rs->next(child_fk_rec)) return true;
187       continue;
188     }
189 
190     // 5. Get the child schema record based on schema id from the table record.
191     schema_pk.update(child_table->read_int(tables::Tables::FIELD_SCHEMA_ID));
192     schema_rs.reset(nullptr);  // Must end index read to allow new index read.
193     if (schema_table->open_record_set(&schema_pk, schema_rs)) return true;
194 
195     schema_rec = schema_rs->current_record();
196     DBUG_ASSERT(schema_rec);
197     if (schema_rec == nullptr) return true;
198 
199     // 6. Collect the relevant information.
200     Foreign_key_parent *fk_parent = add_foreign_key_parent();
201     fk_parent->set_child_schema_name(
202         schema_rec->read_str(tables::Schemata::FIELD_NAME));
203     fk_parent->set_child_table_name(
204         child_table->read_str(tables::Tables::FIELD_NAME));
205     fk_parent->set_fk_name(
206         child_fk_rec->read_str(tables::Foreign_keys::FIELD_NAME));
207 
208     Foreign_key::enum_rule update_rule = static_cast<Foreign_key::enum_rule>(
209         child_fk_rec->read_int(tables::Foreign_keys::FIELD_UPDATE_RULE));
210 
211     fk_parent->set_update_rule(update_rule);
212 
213     Foreign_key::enum_rule delete_rule = static_cast<Foreign_key::enum_rule>(
214         child_fk_rec->read_int(tables::Foreign_keys::FIELD_DELETE_RULE));
215 
216     fk_parent->set_delete_rule(delete_rule);
217 
218     // 7. Get next child record.
219     if (child_fk_rs->next(child_fk_rec)) return true;
220   }
221 
222   return false;
223 }
224 
225 ///////////////////////////////////////////////////////////////////////////
226 
reload_foreign_key_parents(THD * thd)227 bool Table_impl::reload_foreign_key_parents(THD *thd) {
228   /*
229      Use READ UNCOMMITTED isolation, so this method works correctly when
230      called from the middle of atomic DDL statements.
231    */
232   dd::Transaction_ro trx(thd, ISO_READ_UNCOMMITTED);
233 
234   // Register and open tables.
235   trx.otx.register_tables<dd::Table>();
236   if (trx.otx.open_tables()) {
237     DBUG_ASSERT(thd->is_system_thread() || thd->killed || thd->is_error());
238     return true;
239   }
240 
241   // Delete and reload the foreign key parents.
242   delete_container_pointers(m_foreign_key_parents);
243 
244   return load_foreign_key_parents(&trx.otx);
245 }
246 
247 ///////////////////////////////////////////////////////////////////////////
248 
restore_children(Open_dictionary_tables_ctx * otx)249 bool Table_impl::restore_children(Open_dictionary_tables_ctx *otx) {
250   // NOTE: the order of restoring collections is important because:
251   //   - Index-objects reference Column-objects
252   //     (thus, Column-objects must be loaded before Index-objects).
253   //   - Foreign_key-objects reference both Index-objects and Column-objects.
254   //     (thus, both Indexes and Columns must be loaded before FKs).
255   //   - Partitions should be loaded at the end, as it refers to
256   //     indexes.
257 
258   /*
259     Do not load check constraints if upgrade is from the DD version before
260     check constraints support. Check constraint support is introduced in 80016.
261   */
262   bool skip_check_constraints =
263       (bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before(
264           bootstrap::DD_VERSION_80016));
265 
266   return (
267       Abstract_table_impl::restore_children(otx) ||
268       m_indexes.restore_items(this, otx, otx->get_table<Index>(),
269                               Indexes::create_key_by_table_id(this->id())) ||
270       m_foreign_keys.restore_items(
271           this, otx, otx->get_table<Foreign_key>(),
272           Foreign_keys::create_key_by_table_id(this->id()),
273           Foreign_key_order_comparator()) ||
274       m_partitions.restore_items(
275           this, otx, otx->get_table<Partition>(),
276           Table_partitions::create_key_by_parent_partition_id(
277               this->id(), dd::INVALID_OBJECT_ID),
278           // Sort partitions first on level and then on number.
279           Partition_order_comparator()) ||
280       m_triggers.restore_items(this, otx, otx->get_table<Trigger>(),
281                                Triggers::create_key_by_table_id(this->id()),
282                                Trigger_order_comparator()) ||
283       load_foreign_key_parents(otx) ||
284       (!skip_check_constraints &&
285        m_check_constraints.restore_items(
286            this, otx, otx->get_table<Check_constraint>(),
287            Check_constraints::create_key_by_table_id(this->id()),
288            Check_constraint_order_comparator())));
289 }
290 
291 ///////////////////////////////////////////////////////////////////////////
292 
store_triggers(Open_dictionary_tables_ctx * otx)293 bool Table_impl::store_triggers(Open_dictionary_tables_ctx *otx) {
294   /*
295     There is a requirement to keep the collection items in
296     following order.  The reason is,
297 
298     Suppose we are updating a dd::Table object with,
299       a) We already have a trigger 't1' with ID 1.
300       b) We added a new trigger 't2' added preceding to 't1'.
301     We have a row for a) in (DD) disk with action_order=1.
302 
303     The expectation is that row b) should have action_order=1
304     and row a) should have action_order=2.
305 
306     If we try to store row b) first with action_order=1, then
307     there is possibility violating the constraint
308       "UNIQUE KEY (table_id, event_type,
309                    action_timing, action_order)"
310     because row a) might also contain the same event_type and
311     action_timing as that of b). And we would fail inserting
312     row b).
313 
314     This demands us to drop all the triggers which are already
315     present on disk and then store any new triggers.  This
316     would not violate the above unique constraint.
317 
318     However we should avoid trying to drop triggers if no triggers
319     existed before. Such an attempt will lead to index lookup which
320     might cause acquisition of gap lock on index supremum in InnoDB.
321     This might lead to deadlock if two independent CREATE TRIGGER
322     are executed concurrently and both acquire gap locks on index
323     supremum first and then try to insert their records into this gap.
324   */
325   bool needs_delete = m_triggers.has_removed_items();
326 
327   if (!needs_delete) {
328     /* Check if there are any non-new Trigger objects. */
329     for (const Trigger *trigger : *triggers()) {
330       if (trigger->id() != INVALID_OBJECT_ID) {
331         needs_delete = true;
332         break;
333       }
334     }
335   }
336 
337   if (needs_delete) {
338     if (m_triggers.drop_items(otx, otx->get_table<Trigger>(),
339                               Triggers::create_key_by_table_id(this->id())))
340       return true;
341 
342     /*
343       In-case a trigger is dropped, we need to avoid dropping it
344       second time. So clear all the removed items.
345     */
346     m_triggers.clear_removed_items();
347   }
348 
349   // Store the items.
350   return m_triggers.store_items(otx);
351 }
352 
353 ///////////////////////////////////////////////////////////////////////////
354 
store_children(Open_dictionary_tables_ctx * otx)355 bool Table_impl::store_children(Open_dictionary_tables_ctx *otx) {
356   /*
357     Do not store check constraints if upgrade is from the DD version before
358     check constraints support. Check constraint support is introduced in 80016.
359   */
360   bool skip_check_constraints =
361       (bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before(
362           bootstrap::DD_VERSION_80016));
363 
364   return Abstract_table_impl::store_children(otx) ||
365          // Note that indexes has to be stored first, as
366          // partitions refer indexes.
367          m_indexes.store_items(otx) || m_foreign_keys.store_items(otx) ||
368          m_partitions.store_items(otx) || store_triggers(otx) ||
369          (!skip_check_constraints && m_check_constraints.store_items(otx));
370 }
371 
372 ///////////////////////////////////////////////////////////////////////////
373 
drop_children(Open_dictionary_tables_ctx * otx) const374 bool Table_impl::drop_children(Open_dictionary_tables_ctx *otx) const {
375   // Note that partition collection has to be dropped first
376   // as it has foreign key to indexes.
377 
378   return m_check_constraints.drop_items(
379              otx, otx->get_table<Check_constraint>(),
380              Check_constraints::create_key_by_table_id(this->id())) ||
381          m_triggers.drop_items(otx, otx->get_table<Trigger>(),
382                                Triggers::create_key_by_table_id(this->id())) ||
383          m_partitions.drop_items(
384              otx, otx->get_table<Partition>(),
385              Table_partitions::create_key_by_table_id(this->id())) ||
386          m_foreign_keys.drop_items(
387              otx, otx->get_table<Foreign_key>(),
388              Foreign_keys::create_key_by_table_id(this->id())) ||
389          m_indexes.drop_items(otx, otx->get_table<Index>(),
390                               Indexes::create_key_by_table_id(this->id())) ||
391          Abstract_table_impl::drop_children(otx);
392 }
393 
394 /////////////////////////////////////////////////////////////////////////
395 
restore_attributes(const Raw_record & r)396 bool Table_impl::restore_attributes(const Raw_record &r) {
397   {
398     enum_table_type table_type =
399         static_cast<enum_table_type>(r.read_int(Tables::FIELD_TYPE));
400 
401     if (table_type != enum_table_type::BASE_TABLE) return true;
402   }
403 
404   if (Abstract_table_impl::restore_attributes(r)) return true;
405 
406   m_comment = r.read_str(Tables::FIELD_COMMENT);
407   m_row_format = (enum_row_format)r.read_int(Tables::FIELD_ROW_FORMAT);
408 
409   // Partitioning related fields (NULL -> enum value 0!)
410 
411   m_partition_type =
412       (enum_partition_type)r.read_int(Tables::FIELD_PARTITION_TYPE, 0);
413 
414   m_default_partitioning = (enum_default_partitioning)r.read_int(
415       Tables::FIELD_DEFAULT_PARTITIONING, 0);
416 
417   m_subpartition_type =
418       (enum_subpartition_type)r.read_int(Tables::FIELD_SUBPARTITION_TYPE, 0);
419 
420   m_default_subpartitioning = (enum_default_partitioning)r.read_int(
421       Tables::FIELD_DEFAULT_SUBPARTITIONING, 0);
422 
423   // Special cases dealing with NULL values for nullable fields
424 
425   m_se_private_id = dd::tables::Tables::read_se_private_id(r);
426 
427   m_collation_id = r.read_ref_id(Tables::FIELD_COLLATION_ID);
428   m_tablespace_id = r.read_ref_id(Tables::FIELD_TABLESPACE_ID);
429 
430   set_se_private_data(r.read_str(Tables::FIELD_SE_PRIVATE_DATA, ""));
431 
432   // m_engine_attribute and m_secondary_engine_attribute added in 80021
433   if (!bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before(
434           bootstrap::DD_VERSION_80021)) {
435     m_engine_attribute = r.read_str(Tables::FIELD_ENGINE_ATTRIBUTE, "");
436     m_secondary_engine_attribute =
437         r.read_str(Tables::FIELD_SECONDARY_ENGINE_ATTRIBUTE, "");
438   }
439 
440   m_engine = r.read_str(Tables::FIELD_ENGINE);
441 
442   // m_last_checked_for_upgrade_version added in 80012
443   if (bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before(
444           bootstrap::DD_VERSION_80013)) {
445     m_last_checked_for_upgrade_version_id = 0;
446   } else {
447     m_last_checked_for_upgrade_version_id =
448         r.read_int(Tables::FIELD_LAST_CHECKED_FOR_UPGRADE_VERSION_ID, 0);
449   }
450   m_partition_expression = r.read_str(Tables::FIELD_PARTITION_EXPRESSION, "");
451   m_partition_expression_utf8 =
452       r.read_str(Tables::FIELD_PARTITION_EXPRESSION_UTF8, "");
453   m_subpartition_expression =
454       r.read_str(Tables::FIELD_SUBPARTITION_EXPRESSION, "");
455   m_subpartition_expression_utf8 =
456       r.read_str(Tables::FIELD_SUBPARTITION_EXPRESSION_UTF8, "");
457 
458   return false;
459 }
460 
461 ///////////////////////////////////////////////////////////////////////////
462 
store_attributes(Raw_record * r)463 bool Table_impl::store_attributes(Raw_record *r) {
464   //
465   // Special cases dealing with NULL values for nullable fields
466   //   - Store NULL if version is not set
467   //     Eg: USER_VIEW or SYSTEM_VIEW may not have version set
468   //   - Store NULL if se_private_id is not set
469   //     Eg: A non-innodb table may not have se_private_id
470   //   - Store NULL if collation id is not set
471   //     Eg: USER_VIEW will not have collation id set.
472   //   - Store NULL if tablespace id is not set
473   //     Eg: A non-innodb table may not have tablespace
474   //   - Store NULL in options if there are no key=value pairs
475   //   - Store NULL in se_private_data if there are no key=value pairs
476   //   - Store NULL in partition type if not set.
477   //   - Store NULL in partition expression if not set.
478   //   - Store NULL in default partitioning if not set.
479   //   - Store NULL in subpartition type if not set.
480   //   - Store NULL in subpartition expression if not set.
481   //   - Store NULL in default subpartitioning if not set.
482   //
483 
484   // Temporary table definitions are never persisted.
485   DBUG_ASSERT(!m_is_temporary);
486 
487   // Store last_checked_for_upgrade_version_id only if we're not upgrading
488   if (!bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before(
489           bootstrap::DD_VERSION_80013) &&
490       r->store(Tables::FIELD_LAST_CHECKED_FOR_UPGRADE_VERSION_ID,
491                m_last_checked_for_upgrade_version_id)) {
492     return true;
493   }
494 
495   // Store engine_attribute and secondary_engine_attribute only if
496   // we're not upgrading
497   if (!bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before(
498           bootstrap::DD_VERSION_80021) &&
499       (r->store(Tables::FIELD_ENGINE_ATTRIBUTE, m_engine_attribute,
500                 m_engine_attribute.empty()) ||
501        r->store(Tables::FIELD_SECONDARY_ENGINE_ATTRIBUTE,
502                 m_secondary_engine_attribute,
503                 m_secondary_engine_attribute.empty()))) {
504     return true;
505   }
506 
507   // Store field values
508   return Abstract_table_impl::store_attributes(r) ||
509          r->store(Tables::FIELD_ENGINE, m_engine) ||
510          r->store_ref_id(Tables::FIELD_COLLATION_ID, m_collation_id) ||
511          r->store(Tables::FIELD_COMMENT, m_comment) ||
512          r->store(Tables::FIELD_SE_PRIVATE_DATA, m_se_private_data) ||
513          r->store(Tables::FIELD_SE_PRIVATE_ID, m_se_private_id,
514                   m_se_private_id == (Object_id)-1) ||
515          r->store(Tables::FIELD_ROW_FORMAT, m_row_format) ||
516          r->store_ref_id(Tables::FIELD_TABLESPACE_ID, m_tablespace_id) ||
517          r->store(Tables::FIELD_PARTITION_TYPE, m_partition_type,
518                   m_partition_type == PT_NONE) ||
519          r->store(Tables::FIELD_PARTITION_EXPRESSION, m_partition_expression,
520                   m_partition_expression.empty()) ||
521          r->store(Tables::FIELD_PARTITION_EXPRESSION_UTF8,
522                   m_partition_expression_utf8,
523                   m_partition_expression_utf8.empty()) ||
524          r->store(Tables::FIELD_DEFAULT_PARTITIONING, m_default_partitioning,
525                   m_default_partitioning == DP_NONE) ||
526          r->store(Tables::FIELD_SUBPARTITION_TYPE, m_subpartition_type,
527                   m_subpartition_type == ST_NONE) ||
528          r->store(Tables::FIELD_SUBPARTITION_EXPRESSION,
529                   m_subpartition_expression,
530                   m_subpartition_expression.empty()) ||
531          r->store(Tables::FIELD_SUBPARTITION_EXPRESSION_UTF8,
532                   m_subpartition_expression_utf8,
533                   m_subpartition_expression_utf8.empty()) ||
534          r->store(Tables::FIELD_DEFAULT_SUBPARTITIONING,
535                   m_default_subpartitioning,
536                   m_default_subpartitioning == DP_NONE);
537 }
538 
539 ///////////////////////////////////////////////////////////////////////////
540 static_assert(Tables::NUMBER_OF_FIELDS == 37,
541               "Tables definition has changed, check if serialize() and "
542               "deserialize() need to be updated!");
serialize(Sdi_wcontext * wctx,Sdi_writer * w) const543 void Table_impl::serialize(Sdi_wcontext *wctx, Sdi_writer *w) const {
544   // Temporary table definitions are never persisted.
545   DBUG_ASSERT(!m_is_temporary);
546 
547   w->StartObject();
548   Abstract_table_impl::serialize(wctx, w);
549   write(w, m_se_private_id, STRING_WITH_LEN("se_private_id"));
550   write(w, m_engine, STRING_WITH_LEN("engine"));
551   write(w, m_last_checked_for_upgrade_version_id,
552         STRING_WITH_LEN("last_checked_for_upgrade_version_id"));
553   write(w, m_comment, STRING_WITH_LEN("comment"));
554   write_properties(w, m_se_private_data, STRING_WITH_LEN("se_private_data"));
555   write(w, m_engine_attribute, STRING_WITH_LEN("engine_attribute"));
556   write(w, m_secondary_engine_attribute,
557         STRING_WITH_LEN("secondary_engine_attribute"));
558   write_enum(w, m_row_format, STRING_WITH_LEN("row_format"));
559   write_enum(w, m_partition_type, STRING_WITH_LEN("partition_type"));
560   write(w, m_partition_expression, STRING_WITH_LEN("partition_expression"));
561   write(w, m_partition_expression_utf8,
562         STRING_WITH_LEN("partition_expression_utf8"));
563   write_enum(w, m_default_partitioning,
564              STRING_WITH_LEN("default_partitioning"));
565   write_enum(w, m_subpartition_type, STRING_WITH_LEN("subpartition_type"));
566   write(w, m_subpartition_expression,
567         STRING_WITH_LEN("subpartition_expression"));
568   write(w, m_subpartition_expression_utf8,
569         STRING_WITH_LEN("subpartition_expression_utf8"));
570   write_enum(w, m_default_subpartitioning,
571              STRING_WITH_LEN("default_subpartitioning"));
572   serialize_each(wctx, w, m_indexes, STRING_WITH_LEN("indexes"));
573   serialize_each(wctx, w, m_foreign_keys, STRING_WITH_LEN("foreign_keys"));
574   serialize_each(wctx, w, m_check_constraints,
575                  STRING_WITH_LEN("check_constraints"));
576   serialize_each(wctx, w, m_partitions, STRING_WITH_LEN("partitions"));
577   write(w, m_collation_id, STRING_WITH_LEN("collation_id"));
578   serialize_tablespace_ref(wctx, w, m_tablespace_id,
579                            STRING_WITH_LEN("tablespace_ref"));
580   w->EndObject();
581 }
582 
583 ///////////////////////////////////////////////////////////////////////////
584 
deserialize(Sdi_rcontext * rctx,const RJ_Value & val)585 bool Table_impl::deserialize(Sdi_rcontext *rctx, const RJ_Value &val) {
586   Abstract_table_impl::deserialize(rctx, val);
587   read(&m_se_private_id, val, "se_private_id");
588   read(&m_engine, val, "engine");
589   read(&m_last_checked_for_upgrade_version_id, val,
590        "last_checked_for_upgrade_version_id");
591   read(&m_comment, val, "comment");
592   read_properties(&m_se_private_data, val, "se_private_data");
593   read(&m_engine_attribute, val, "engine_attribute");
594   read(&m_secondary_engine_attribute, val, "secondary_engine_attribute");
595   read_enum(&m_row_format, val, "row_format");
596   read_enum(&m_partition_type, val, "partition_type");
597   read(&m_partition_expression, val, "partition_expression");
598   read(&m_partition_expression_utf8, val, "partition_expression_utf8");
599   read_enum(&m_default_partitioning, val, "default_partitioning");
600   read_enum(&m_subpartition_type, val, "subpartition_type");
601   read(&m_subpartition_expression, val, "subpartition_expression");
602   read(&m_subpartition_expression_utf8, val, "subpartition_expression_utf8");
603   read_enum(&m_default_subpartitioning, val, "default_subpartitioning");
604 
605   // Note! Deserialization of ordinal position cross-referenced
606   // objects (i.e. Index and Column) must happen before deserializing
607   // objects which refrence these objects:
608   // Foreign_key_element -> Column,
609   // Foreign_key         -> Index,
610   // Index_element       -> Column,
611   // Partition_index     -> Index
612   // Otherwise the cross-references will not be deserialized correctly
613   // (as we don't know the address of the referenced Column or Index
614   // object).
615 
616   deserialize_each(
617       rctx, [this]() { return add_index(); }, val, "indexes");
618 
619   deserialize_each(
620       rctx, [this]() { return add_foreign_key(); }, val, "foreign_keys");
621   deserialize_each(
622       rctx, [this]() { return add_check_constraint(); }, val,
623       "check_constraints");
624   deserialize_each(
625       rctx, [this]() { return add_partition(); }, val, "partitions");
626   read(&m_collation_id, val, "collation_id");
627 #ifndef XTRABACKUP
628   return deserialize_tablespace_ref(rctx, &m_tablespace_id, val,
629                                     "tablespace_id");
630 #else
631   return false;
632 #endif
633 }
634 
635 ///////////////////////////////////////////////////////////////////////////
636 
debug_print(String_type & outb) const637 void Table_impl::debug_print(String_type &outb) const {
638   String_type s;
639   Abstract_table_impl::debug_print(s);
640 
641   dd::Stringstream_type ss;
642   ss << "TABLE OBJECT: { " << s << "m_engine: " << m_engine << "; "
643      << "m_last_checked_for_upgrade_version_id: "
644      << m_last_checked_for_upgrade_version_id << "; "
645      << "m_collation: {OID: " << m_collation_id << "}; "
646      << "m_comment: " << m_comment << "; "
647      << "m_se_private_data " << m_se_private_data.raw_string() << "; "
648      << "m_se_private_id: {OID: " << m_se_private_id << "}; "
649      << "m_engine_attribute: " << m_engine_attribute << "; "
650      << "m_secondary_engine_attribute: " << m_secondary_engine_attribute << "; "
651      << "m_row_format: " << m_row_format << "; "
652      << "m_is_temporary: " << m_is_temporary << "; "
653      << "m_tablespace: {OID: " << m_tablespace_id << "}; "
654      << "m_partition_type " << m_partition_type << "; "
655      << "m_default_partitioning " << m_default_partitioning << "; "
656      << "m_partition_expression " << m_partition_expression << "; "
657      << "m_partition_expression_utf8 " << m_partition_expression_utf8 << "; "
658      << "m_subpartition_type " << m_subpartition_type << "; "
659      << "m_default_subpartitioning " << m_default_subpartitioning << "; "
660      << "m_subpartition_expression " << m_subpartition_expression << "; "
661      << "m_subpartition_expression_utf8 " << m_subpartition_expression_utf8
662      << "; "
663      << "m_partitions: " << m_partitions.size() << " [ ";
664 
665   {
666     for (const Partition *i : partitions()) {
667       String_type sp;
668       i->debug_print(sp);
669       ss << sp << " | ";
670     }
671   }
672 
673   ss << "] m_indexes: " << m_indexes.size() << " [ ";
674 
675   {
676     for (const Index *i : indexes()) {
677       String_type si;
678       i->debug_print(si);
679       ss << si << " | ";
680     }
681   }
682 
683   ss << "] m_foreign_keys: " << m_foreign_keys.size() << " [ ";
684 
685   {
686     for (const Foreign_key *fk : foreign_keys()) {
687       String_type sfk;
688       fk->debug_print(sfk);
689       ss << sfk << " | ";
690     }
691   }
692 
693   ss << "] m_check_constraints: " << m_check_constraints.size() << " [ ";
694 
695   {
696     for (const Check_constraint *cc : check_constraints()) {
697       String_type scc;
698       cc->debug_print(scc);
699       ss << scc << " | ";
700     }
701   }
702 
703   ss << "] m_triggers: " << m_triggers.size() << " [ ";
704 
705   {
706     for (const Trigger *trig : triggers()) {
707       String_type st;
708       trig->debug_print(st);
709       ss << st << " | ";
710     }
711   }
712   ss << "] ";
713 
714   ss << " }";
715 
716   outb = ss.str();
717 }
718 
719 ///////////////////////////////////////////////////////////////////////////
720 // Index collection.
721 ///////////////////////////////////////////////////////////////////////////
722 
add_index()723 Index *Table_impl::add_index() {
724   Index_impl *i = new (std::nothrow) Index_impl(this);
725   m_indexes.push_back(i);
726   return i;
727 }
728 
729 ///////////////////////////////////////////////////////////////////////////
730 
add_first_index()731 Index *Table_impl::add_first_index() {
732   Index_impl *i = new (std::nothrow) Index_impl(this);
733   m_indexes.push_front(i);
734   return i;
735 }
736 
737 ///////////////////////////////////////////////////////////////////////////
738 
get_index(Object_id index_id)739 Index *Table_impl::get_index(Object_id index_id) {
740   for (Index *i : m_indexes) {
741     if (i->id() == index_id) return i;
742   }
743 
744   return nullptr;
745 }
746 
747 ///////////////////////////////////////////////////////////////////////////
748 // Foreign key collection.
749 ///////////////////////////////////////////////////////////////////////////
750 
add_foreign_key()751 Foreign_key *Table_impl::add_foreign_key() {
752   Foreign_key_impl *fk = new (std::nothrow) Foreign_key_impl(this);
753   m_foreign_keys.push_back(fk);
754   return fk;
755 }
756 
757 ///////////////////////////////////////////////////////////////////////////
758 // Foreign key parent collection.
759 ///////////////////////////////////////////////////////////////////////////
760 
add_foreign_key_parent()761 Foreign_key_parent *Table_impl::add_foreign_key_parent() {
762   Foreign_key_parent *fk_parent = new (std::nothrow) Foreign_key_parent();
763   m_foreign_key_parents.push_back(fk_parent);
764   return fk_parent;
765 }
766 
767 ///////////////////////////////////////////////////////////////////////////
768 // Partition collection.
769 ///////////////////////////////////////////////////////////////////////////
770 
add_partition()771 Partition *Table_impl::add_partition() {
772   Partition_impl *i = new (std::nothrow) Partition_impl(this);
773   m_partitions.push_back(i);
774 
775   return i;
776 }
777 
778 ///////////////////////////////////////////////////////////////////////////
779 
get_partition(Object_id partition_id)780 Partition *Table_impl::get_partition(Object_id partition_id) {
781   for (Partition *i : m_partitions) {
782     if (i->id() == partition_id) return i;
783   }
784 
785   return nullptr;
786 }
787 
788 ///////////////////////////////////////////////////////////////////////////
789 // Trigger collection.
790 ///////////////////////////////////////////////////////////////////////////
791 
get_max_action_order(Trigger::enum_action_timing at,Trigger::enum_event_type et) const792 uint Table_impl::get_max_action_order(Trigger::enum_action_timing at,
793                                       Trigger::enum_event_type et) const {
794   uint max_order = 0;
795   for (const Trigger *trig : triggers()) {
796     if (trig->action_timing() == at && trig->event_type() == et) max_order++;
797   }
798 
799   return max_order;
800 }
801 
802 ///////////////////////////////////////////////////////////////////////////
803 
reorder_action_order(Trigger::enum_action_timing at,Trigger::enum_event_type et)804 void Table_impl::reorder_action_order(Trigger::enum_action_timing at,
805                                       Trigger::enum_event_type et) {
806   uint new_order = 1;
807   for (Trigger *trigger : *triggers()) {
808     if (trigger->action_timing() == at && trigger->event_type() == et)
809       trigger->set_action_order(new_order++);
810   }
811 }
812 
813 ///////////////////////////////////////////////////////////////////////////
814 
create_trigger()815 Trigger_impl *Table_impl::create_trigger() {
816   Trigger_impl *trigger = new (std::nothrow) Trigger_impl(this);
817   if (trigger == nullptr) return nullptr;
818 
819   THD *thd = current_thd;
820   trigger->set_created(thd->query_start_timeval_trunc(2));
821   trigger->set_last_altered(thd->query_start_timeval_trunc(2));
822 
823   return trigger;
824 }
825 
826 ///////////////////////////////////////////////////////////////////////////
827 
add_trigger(Trigger::enum_action_timing at,Trigger::enum_event_type et)828 Trigger *Table_impl::add_trigger(Trigger::enum_action_timing at,
829                                  Trigger::enum_event_type et) {
830   Trigger_impl *trigger = create_trigger();
831   if (trigger == nullptr) return nullptr;
832 
833   m_triggers.push_back(trigger);
834   trigger->set_action_timing(at);
835   trigger->set_event_type(et);
836   trigger->set_action_order(get_max_action_order(at, et));
837 
838   return trigger;
839 }
840 
841 ///////////////////////////////////////////////////////////////////////////
842 
get_trigger(const char * name) const843 const Trigger *Table_impl::get_trigger(const char *name) const {
844   const uchar *src_trg_name = pointer_cast<const uchar *>(name);
845   size_t src_trg_name_len = strlen(name);
846   for (const Trigger *trigger : triggers()) {
847     if (!my_strnncoll(dd::tables::Triggers::name_collation(), src_trg_name,
848                       src_trg_name_len,
849                       pointer_cast<const uchar *>(trigger->name().c_str()),
850                       trigger->name().length()))
851       return trigger;
852   }
853 
854   return nullptr;
855 }
856 
857 ///////////////////////////////////////////////////////////////////////////
858 
add_trigger_following(const Trigger * trigger,Trigger::enum_action_timing at,Trigger::enum_event_type et)859 Trigger *Table_impl::add_trigger_following(const Trigger *trigger,
860                                            Trigger::enum_action_timing at,
861                                            Trigger::enum_event_type et) {
862   DBUG_ASSERT(trigger != nullptr && trigger->action_timing() == at &&
863               trigger->event_type() == et);
864 
865   // Allocate new Trigger object.
866   Trigger_impl *new_trigger = create_trigger();
867   if (new_trigger == nullptr) return nullptr;
868 
869   Trigger_collection::iterator it =
870       m_triggers.find(dynamic_cast<const Trigger_impl *>(trigger));
871 
872   if (++it != m_triggers.end())
873     m_triggers.insert(it, new_trigger);
874   else
875     m_triggers.push_back(new_trigger);
876 
877   new_trigger->set_action_timing(at);
878   new_trigger->set_event_type(et);
879 
880   reorder_action_order(at, et);
881   return new_trigger;
882 }
883 
884 ///////////////////////////////////////////////////////////////////////////
885 
add_trigger_preceding(const Trigger * trigger,Trigger::enum_action_timing at,Trigger::enum_event_type et)886 Trigger *Table_impl::add_trigger_preceding(const Trigger *trigger,
887                                            Trigger::enum_action_timing at,
888                                            Trigger::enum_event_type et) {
889   DBUG_ASSERT(trigger != nullptr && trigger->action_timing() == at &&
890               trigger->event_type() == et);
891 
892   Trigger_impl *new_trigger = create_trigger();
893   if (new_trigger == nullptr) return nullptr;
894 
895   new_trigger->set_action_timing(at);
896   new_trigger->set_event_type(et);
897 
898   Trigger_collection::iterator it =
899       m_triggers.find(dynamic_cast<const Trigger_impl *>(trigger));
900   m_triggers.insert(it, new_trigger);
901 
902   reorder_action_order(at, et);
903 
904   return new_trigger;
905 }
906 
907 ///////////////////////////////////////////////////////////////////////////
908 
copy_triggers(const Table * tab_obj)909 void Table_impl::copy_triggers(const Table *tab_obj) {
910   DBUG_ASSERT(tab_obj != nullptr);
911 
912   for (const Trigger *trig : tab_obj->triggers()) {
913     /*
914       Reset the trigger primary key ID, so that a new row is
915       created for them, when the object is stored. Following is
916       the issue if we don't do that.
917 
918       * When the triggers are copied by dd::Table::copy_triggers(),
919         it retained the old trigger ID's. This is fine in theory
920         to re-use ID. But see below points.
921 
922       * thd->dd_client()->update() updates the dd::Table object which
923         contains the moved triggers. The DD framework would insert
924         these triggers with same old trigger ID in mysql.triggers.id.
925         This too is fine.
926 
927       * After inserting a row, we set dd::Trigger_impl::m_id
928         only if a new id m_table->file->insert_id_for_cur_row was
929         generated. The problem here is that there was no new row ID
930         generated as we did retain old mysql.triggers.id. Hence we
931         end-up marking the dd::Trigger_impl::m_id as INVALID_OBJECT_ID.
932         Note that the value stored in DD is now difference than the
933         value in in-memory dd::Trigger_impl object.
934 
935       * Later if the same object is updated (may be rename operation)
936         then as the dd::Trigger_impl::m_id is INVALID_OBJECT_ID, we
937         end-up creating a duplicate row which already exists.
938 
939       So, It is not necessary to retain the old trigger ID's, the
940       dd::Table::copy_triggers() API now sets the ID's of cloned
941       trigger objects to INVALID_OBJECT_ID. This will work fine as the
942       m_table->file->insert_id_for_cur_row gets generated as expected
943       and the trigger metadata on DD table mysql.triggers and in-memory
944       DD object dd::Trigger_impl would both be same.
945     */
946     Trigger_impl *new_trigger =
947         new Trigger_impl(*dynamic_cast<const Trigger_impl *>(trig), this);
948     DBUG_ASSERT(new_trigger != nullptr);
949 
950     new_trigger->set_id(INVALID_OBJECT_ID);
951 
952     m_triggers.push_back(new_trigger);
953   }
954 }
955 
956 ///////////////////////////////////////////////////////////////////////////
957 
drop_all_triggers()958 void Table_impl::drop_all_triggers() { m_triggers.remove_all(); }
959 
960 ///////////////////////////////////////////////////////////////////////////
961 
drop_trigger(const Trigger * trigger)962 void Table_impl::drop_trigger(const Trigger *trigger) {
963   DBUG_ASSERT(trigger != nullptr);
964   dd::Trigger::enum_action_timing at = trigger->action_timing();
965   dd::Trigger::enum_event_type et = trigger->event_type();
966 
967   m_triggers.remove(
968       dynamic_cast<Trigger_impl *>(const_cast<Trigger *>(trigger)));
969 
970   reorder_action_order(at, et);
971 }
972 
973 ///////////////////////////////////////////////////////////////////////////
974 // Check constraint collection.
975 ///////////////////////////////////////////////////////////////////////////
976 
add_check_constraint()977 Check_constraint *Table_impl::add_check_constraint() {
978   Check_constraint_impl *cc = new (std::nothrow) Check_constraint_impl(this);
979   if (cc != nullptr) m_check_constraints.push_back(cc);
980   return cc;
981 }
982 
983 ///////////////////////////////////////////////////////////////////////////
984 
get_partition(const String_type & name)985 Partition *Table_impl::get_partition(const String_type &name) {
986   for (Partition *i : m_partitions) {
987     if (i->name() == name) return i;
988   }
989 
990   return nullptr;
991 }
992 
993 ///////////////////////////////////////////////////////////////////////////
994 
update_aux_key(Aux_key * key,const String_type & engine,Object_id se_private_id)995 bool Table::update_aux_key(Aux_key *key, const String_type &engine,
996                            Object_id se_private_id) {
997   if (se_private_id != INVALID_OBJECT_ID)
998     return Tables::update_aux_key(key, engine, se_private_id);
999 
1000   return true;
1001 }
1002 
1003 ///////////////////////////////////////////////////////////////////////////
1004 
register_tables(Open_dictionary_tables_ctx * otx)1005 void Table_impl::register_tables(Open_dictionary_tables_ctx *otx) {
1006   otx->add_table<Tables>();
1007 
1008   otx->register_tables<Schema>();
1009   otx->register_tables<Column>();
1010   otx->register_tables<Index>();
1011   otx->register_tables<Foreign_key>();
1012   otx->register_tables<Partition>();
1013   otx->register_tables<Trigger>();
1014   /*
1015     Do not register check constraint table if upgrade is from the DD version
1016     before check constraints support. Check constraint is introduced in 8.0.15.
1017   */
1018   if (!bootstrap::DD_bootstrap_ctx::instance().is_dd_upgrade_from_before(
1019           bootstrap::DD_VERSION_80016))
1020     otx->register_tables<Check_constraint>();
1021 }
1022 
1023 ///////////////////////////////////////////////////////////////////////////
1024 
Table_impl(const Table_impl & src)1025 Table_impl::Table_impl(const Table_impl &src)
1026     : Weak_object(src),
1027       Abstract_table_impl(src),
1028       m_se_private_id(src.m_se_private_id),
1029       m_engine(src.m_engine),
1030       m_comment(src.m_comment),
1031       m_last_checked_for_upgrade_version_id{
1032           src.m_last_checked_for_upgrade_version_id},
1033       m_se_private_data(src.m_se_private_data),
1034       m_engine_attribute(src.m_engine_attribute),
1035       m_secondary_engine_attribute(src.m_secondary_engine_attribute),
1036       m_row_format(src.m_row_format),
1037       m_is_temporary(src.m_is_temporary),
1038       m_partition_type(src.m_partition_type),
1039       m_partition_expression(src.m_partition_expression),
1040       m_partition_expression_utf8(src.m_partition_expression_utf8),
1041       m_default_partitioning(src.m_default_partitioning),
1042       m_subpartition_type(src.m_subpartition_type),
1043       m_subpartition_expression(src.m_subpartition_expression),
1044       m_subpartition_expression_utf8(src.m_subpartition_expression_utf8),
1045       m_default_subpartitioning(src.m_default_subpartitioning),
1046       m_indexes(),
1047       m_foreign_keys(),
1048       m_partitions(),
1049       m_triggers(),
1050       m_check_constraints(),
1051       m_collation_id(src.m_collation_id),
1052       m_tablespace_id(src.m_tablespace_id) {
1053   m_indexes.deep_copy(src.m_indexes, this);
1054   m_foreign_keys.deep_copy(src.m_foreign_keys, this);
1055   for (auto fk_parent : src.m_foreign_key_parents)
1056     m_foreign_key_parents.push_back(new (std::nothrow)
1057                                         Foreign_key_parent(*fk_parent));
1058   m_partitions.deep_copy(src.m_partitions, this);
1059   m_triggers.deep_copy(src.m_triggers, this);
1060   m_check_constraints.deep_copy(src.m_check_constraints, this);
1061 }
1062 }  // namespace dd
1063