summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/btr/btr0cur.cc17
-rw-r--r--storage/innobase/dict/dict0boot.cc3
-rw-r--r--storage/innobase/dict/dict0crea.cc132
-rw-r--r--storage/innobase/dict/dict0dict.cc2
-rw-r--r--storage/innobase/dict/dict0load.cc151
-rw-r--r--storage/innobase/handler/ha_innodb.cc631
-rw-r--r--storage/innobase/handler/ha_innodb.h11
-rw-r--r--storage/innobase/handler/handler0alter.cc114
-rw-r--r--storage/innobase/handler/i_s.cc394
-rw-r--r--storage/innobase/handler/i_s.h4
-rw-r--r--storage/innobase/include/db0err.h3
-rw-r--r--storage/innobase/include/dict0boot.h2
-rw-r--r--storage/innobase/include/dict0crea.h13
-rw-r--r--storage/innobase/include/dict0dict.h2
-rw-r--r--storage/innobase/include/dict0load.h28
-rw-r--r--storage/innobase/include/pars0grm.h2
-rw-r--r--storage/innobase/include/pars0pars.h3
-rw-r--r--storage/innobase/include/row0mysql.h12
-rw-r--r--storage/innobase/innodb.cmake5
-rw-r--r--storage/innobase/pars/pars0grm.cc729
-rw-r--r--storage/innobase/pars/pars0grm.y14
-rw-r--r--storage/innobase/pars/pars0pars.cc45
-rw-r--r--storage/innobase/pars/pars0sym.cc5
-rw-r--r--storage/innobase/que/que0que.cc8
-rw-r--r--storage/innobase/row/row0mysql.cc336
-rw-r--r--storage/innobase/row/row0sel.cc3
-rw-r--r--storage/innobase/srv/srv0start.cc11
-rw-r--r--storage/innobase/ut/ut0ut.cc4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result24
29 files changed, 2302 insertions, 406 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index f77caf7935d..34c51cefc50 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -1154,6 +1154,23 @@ static ulint btr_node_ptr_max_size(const dict_index_t* index)
continue;
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ /* SYS_FOREIGN.ID is defined as CHAR in the
+ InnoDB internal SQL parser, which translates
+ into the incorrect VARCHAR(0). InnoDB does
+ not enforce maximum lengths of columns, so
+ that is why any data can be inserted in the
+ first place.
+
+ Likewise, SYS_FOREIGN.FOR_NAME,
+ SYS_FOREIGN.REF_NAME, SYS_FOREIGN_COLS.ID, are
+ defined as CHAR, and also they are part of a key. */
+
+ ut_ad(!strcmp(index->table->name.m_name,
+ "SYS_FOREIGN")
+ || !strcmp(index->table->name.m_name,
+ "SYS_FOREIGN_COLS"));
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
ut_ad(!comp);
ut_ad(col->mtype == DATA_VARCHAR);
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index 833f2621de6..10e78877d05 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -242,12 +242,13 @@ dict_boot(void)
ut_ad(DICT_NUM_FIELDS__SYS_INDEXES == 10);
ut_ad(DICT_NUM_COLS__SYS_FIELDS == 3);
ut_ad(DICT_NUM_FIELDS__SYS_FIELDS == 5);
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
ut_ad(DICT_NUM_COLS__SYS_FOREIGN == 4);
ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN == 6);
ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_FOR_NAME == 2);
ut_ad(DICT_NUM_COLS__SYS_FOREIGN_COLS == 4);
ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_COLS == 6);
-
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
mtr_start(&mtr);
/* Create the hash tables etc. */
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 46ebe9a02a5..641610bd6c2 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -1383,6 +1383,138 @@ dict_check_if_system_table_exists(
return(error);
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+/****************************************************************//**
+Creates the foreign key constraints system tables inside InnoDB
+at server bootstrap or server start if they are not found or are
+not of the right form.
+@return DB_SUCCESS or error code */
+dberr_t
+dict_create_or_check_foreign_constraint_tables(void)
+/*================================================*/
+{
+ trx_t* trx;
+ my_bool srv_file_per_table_backup;
+ dberr_t err;
+ dberr_t sys_foreign_err;
+ dberr_t sys_foreign_cols_err;
+
+ ut_ad(!srv_any_background_activity());
+
+ /* Note: The master thread has not been started at this point. */
+
+
+ sys_foreign_err = dict_check_if_system_table_exists(
+ "SYS_FOREIGN", DICT_NUM_FIELDS__SYS_FOREIGN + 1, 3);
+ sys_foreign_cols_err = dict_check_if_system_table_exists(
+ "SYS_FOREIGN_COLS", DICT_NUM_FIELDS__SYS_FOREIGN_COLS + 1, 1);
+
+ if (sys_foreign_err == DB_SUCCESS
+ && sys_foreign_cols_err == DB_SUCCESS) {
+ return(DB_SUCCESS);
+ }
+
+ if (srv_read_only_mode
+ || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO) {
+ return(DB_READ_ONLY);
+ }
+
+ trx = trx_create();
+
+ trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
+
+ trx->op_info = "creating foreign key sys tables";
+
+ row_mysql_lock_data_dictionary(trx);
+
+ /* Check which incomplete table definition to drop. */
+
+ if (sys_foreign_err == DB_CORRUPTION) {
+ row_drop_table_after_create_fail("SYS_FOREIGN", trx);
+ }
+
+ if (sys_foreign_cols_err == DB_CORRUPTION) {
+ row_drop_table_after_create_fail("SYS_FOREIGN_COLS", trx);
+ }
+
+ ib::info() << "Creating foreign key constraint system tables.";
+
+ /* NOTE: in dict_load_foreigns we use the fact that
+ there are 2 secondary indexes on SYS_FOREIGN, and they
+ are defined just like below */
+
+ /* NOTE: when designing InnoDB's foreign key support in 2001, we made
+ an error and made the table names and the foreign key id of type
+ 'CHAR' (internally, really a VARCHAR). We should have made the type
+ VARBINARY, like in other InnoDB system tables, to get a clean
+ design. */
+
+ srv_file_per_table_backup = srv_file_per_table;
+
+ /* We always want SYSTEM tables to be created inside the system
+ tablespace. */
+
+ srv_file_per_table = 0;
+
+ err = que_eval_sql(
+ NULL,
+ "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
+ "BEGIN\n"
+ "CREATE TABLE\n"
+ "SYS_FOREIGN(ID CHAR, FOR_NAME CHAR,"
+ " REF_NAME CHAR, N_COLS INT);\n"
+ "CREATE UNIQUE CLUSTERED INDEX ID_IND"
+ " ON SYS_FOREIGN (ID);\n"
+ "CREATE INDEX FOR_IND"
+ " ON SYS_FOREIGN (FOR_NAME);\n"
+ "CREATE INDEX REF_IND"
+ " ON SYS_FOREIGN (REF_NAME);\n"
+ "CREATE TABLE\n"
+ "SYS_FOREIGN_COLS(ID CHAR, POS INT,"
+ " FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
+ "CREATE UNIQUE CLUSTERED INDEX ID_IND"
+ " ON SYS_FOREIGN_COLS (ID, POS);\n"
+ "END;\n",
+ FALSE, trx);
+
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
+ ib::error() << "Creation of SYS_FOREIGN and SYS_FOREIGN_COLS"
+ " failed: " << err << ". Tablespace is"
+ " full. Dropping incompletely created tables.";
+
+ ut_ad(err == DB_OUT_OF_FILE_SPACE
+ || err == DB_TOO_MANY_CONCURRENT_TRXS);
+
+ row_drop_table_after_create_fail("SYS_FOREIGN", trx);
+ row_drop_table_after_create_fail("SYS_FOREIGN_COLS", trx);
+
+ if (err == DB_OUT_OF_FILE_SPACE) {
+ err = DB_MUST_GET_MORE_FILE_SPACE;
+ }
+ }
+
+ trx_commit_for_mysql(trx);
+
+ row_mysql_unlock_data_dictionary(trx);
+
+ trx->free();
+
+ srv_file_per_table = srv_file_per_table_backup;
+
+ /* Note: The master thread has not been started at this point. */
+ /* Confirm and move to the non-LRU part of the table LRU list. */
+ sys_foreign_err = dict_check_if_system_table_exists(
+ "SYS_FOREIGN", DICT_NUM_FIELDS__SYS_FOREIGN + 1, 3);
+ ut_a(sys_foreign_err == DB_SUCCESS);
+
+ sys_foreign_cols_err = dict_check_if_system_table_exists(
+ "SYS_FOREIGN_COLS", DICT_NUM_FIELDS__SYS_FOREIGN_COLS + 1, 1);
+ ut_a(sys_foreign_cols_err == DB_SUCCESS);
+
+ return(err);
+}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
/** Creates the virtual column system table (SYS_VIRTUAL) inside InnoDB
at server bootstrap or server start if the table is not found or is
not of the right form.
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 0402ae5013f..b42cee7d514 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -3661,6 +3661,7 @@ dict_table_get_highest_foreign_id(
DBUG_RETURN(biggest_id);
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
/**********************************************************************//**
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement.
@return DB_SUCCESS or DB_CANNOT_DROP_CONSTRAINT if syntax error or the
@@ -3797,6 +3798,7 @@ syntax_error:
return(DB_CANNOT_DROP_CONSTRAINT);
}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index 44f46611b3c..133a6f204f2 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -507,6 +507,157 @@ dict_process_sys_fields_rec(
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+/********************************************************************//**
+This function parses a SYS_FOREIGN record and populate a dict_foreign_t
+structure with the information from the record. For detail information
+about SYS_FOREIGN fields, please refer to dict_load_foreign() function.
+@return error message, or NULL on success */
+const char*
+dict_process_sys_foreign_rec(
+/*=========================*/
+ mem_heap_t* heap, /*!< in/out: heap memory */
+ const rec_t* rec, /*!< in: current SYS_FOREIGN rec */
+ dict_foreign_t* foreign) /*!< out: dict_foreign_t struct
+ to be filled */
+{
+ ulint len;
+ const byte* field;
+
+ if (rec_get_deleted_flag(rec, 0)) {
+ return("delete-marked record in SYS_FOREIGN");
+ }
+
+ if (rec_get_n_fields_old(rec) != DICT_NUM_FIELDS__SYS_FOREIGN) {
+ return("wrong number of columns in SYS_FOREIGN record");
+ }
+
+ field = rec_get_nth_field_old(
+ rec, DICT_FLD__SYS_FOREIGN__ID, &len);
+ if (len == 0 || len == UNIV_SQL_NULL) {
+err_len:
+ return("incorrect column length in SYS_FOREIGN");
+ }
+
+ /* This receives a dict_foreign_t* that points to a stack variable.
+ So dict_foreign_free(foreign) is not used as elsewhere.
+ Since the heap used here is freed elsewhere, foreign->heap
+ is not assigned. */
+ foreign->id = mem_heap_strdupl(heap, (const char*) field, len);
+
+ rec_get_nth_field_offs_old(
+ rec, DICT_FLD__SYS_FOREIGN__DB_TRX_ID, &len);
+ if (len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL) {
+ goto err_len;
+ }
+ rec_get_nth_field_offs_old(
+ rec, DICT_FLD__SYS_FOREIGN__DB_ROLL_PTR, &len);
+ if (len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL) {
+ goto err_len;
+ }
+
+ /* The _lookup versions of the referenced and foreign table names
+ are not assigned since they are not used in this dict_foreign_t */
+
+ field = rec_get_nth_field_old(
+ rec, DICT_FLD__SYS_FOREIGN__FOR_NAME, &len);
+ if (len == 0 || len == UNIV_SQL_NULL) {
+ goto err_len;
+ }
+ foreign->foreign_table_name = mem_heap_strdupl(
+ heap, (const char*) field, len);
+
+ field = rec_get_nth_field_old(
+ rec, DICT_FLD__SYS_FOREIGN__REF_NAME, &len);
+ if (len == 0 || len == UNIV_SQL_NULL) {
+ goto err_len;
+ }
+ foreign->referenced_table_name = mem_heap_strdupl(
+ heap, (const char*) field, len);
+
+ field = rec_get_nth_field_old(
+ rec, DICT_FLD__SYS_FOREIGN__N_COLS, &len);
+ if (len != 4) {
+ goto err_len;
+ }
+ uint32_t n_fields_and_type = mach_read_from_4(field);
+
+ foreign->type = n_fields_and_type >> 24 & ((1U << 6) - 1);
+ foreign->n_fields = n_fields_and_type & dict_index_t::MAX_N_FIELDS;
+
+ return(NULL);
+}
+
+/********************************************************************//**
+This function parses a SYS_FOREIGN_COLS record and extract necessary
+information from the record and return to caller.
+@return error message, or NULL on success */
+const char*
+dict_process_sys_foreign_col_rec(
+/*=============================*/
+ mem_heap_t* heap, /*!< in/out: heap memory */
+ const rec_t* rec, /*!< in: current SYS_FOREIGN_COLS rec */
+ const char** name, /*!< out: foreign key constraint name */
+ const char** for_col_name, /*!< out: referencing column name */
+ const char** ref_col_name, /*!< out: referenced column name
+ in referenced table */
+ ulint* pos) /*!< out: column position */
+{
+ ulint len;
+ const byte* field;
+
+ if (rec_get_deleted_flag(rec, 0)) {
+ return("delete-marked record in SYS_FOREIGN_COLS");
+ }
+
+ if (rec_get_n_fields_old(rec) != DICT_NUM_FIELDS__SYS_FOREIGN_COLS) {
+ return("wrong number of columns in SYS_FOREIGN_COLS record");
+ }
+
+ field = rec_get_nth_field_old(
+ rec, DICT_FLD__SYS_FOREIGN_COLS__ID, &len);
+ if (len == 0 || len == UNIV_SQL_NULL) {
+err_len:
+ return("incorrect column length in SYS_FOREIGN_COLS");
+ }
+ *name = mem_heap_strdupl(heap, (char*) field, len);
+
+ field = rec_get_nth_field_old(
+ rec, DICT_FLD__SYS_FOREIGN_COLS__POS, &len);
+ if (len != 4) {
+ goto err_len;
+ }
+ *pos = mach_read_from_4(field);
+
+ rec_get_nth_field_offs_old(
+ rec, DICT_FLD__SYS_FOREIGN_COLS__DB_TRX_ID, &len);
+ if (len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL) {
+ goto err_len;
+ }
+ rec_get_nth_field_offs_old(
+ rec, DICT_FLD__SYS_FOREIGN_COLS__DB_ROLL_PTR, &len);
+ if (len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL) {
+ goto err_len;
+ }
+
+ field = rec_get_nth_field_old(
+ rec, DICT_FLD__SYS_FOREIGN_COLS__FOR_COL_NAME, &len);
+ if (len == 0 || len == UNIV_SQL_NULL) {
+ goto err_len;
+ }
+ *for_col_name = mem_heap_strdupl(heap, (char*) field, len);
+
+ field = rec_get_nth_field_old(
+ rec, DICT_FLD__SYS_FOREIGN_COLS__REF_COL_NAME, &len);
+ if (len == 0 || len == UNIV_SQL_NULL) {
+ goto err_len;
+ }
+ *ref_col_name = mem_heap_strdupl(heap, (char*) field, len);
+
+ return(NULL);
+}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
/********************************************************************//**
This function parses a SYS_TABLESPACES record, extracts necessary
information from the record and returns to caller.
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 6092dd337f0..a79b358728b 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -47,6 +47,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include <strfunc.h>
#include <sql_acl.h>
#include <sql_class.h>
+#include <sql_rename.h>
#include <sql_show.h>
#include <sql_table.h>
#include <table_cache.h>
@@ -482,6 +483,11 @@ const struct _ft_vft_ext ft_vft_ext_result = {innobase_fts_get_version,
innobase_fts_retrieve_docid,
innobase_fts_count_matches};
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+static dberr_t fk_check_legacy_storage(const char* table_name, trx_t* trx);
+static dberr_t fk_upgrade_legacy_storage(dict_table_t* table, trx_t* trx, THD *thd, TABLE_SHARE *share);
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
#ifdef HAVE_PSI_INTERFACE
# define PSI_KEY(n) {&n##_key, #n, 0}
/* All RWLOCK used in Innodb are SX-locks */
@@ -1797,6 +1803,10 @@ convert_error_code_to_mysql(
return(HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE);
case DB_COMPUTE_VALUE_FAILED:
return(HA_ERR_GENERIC); // impossible
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ case DB_LEGACY_FK:
+ return(HA_ERR_FK_UPGRADE);
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
}
}
@@ -5399,9 +5409,10 @@ initialize_auto_increment(dict_table_t* table, const Field* field)
@return error code
@retval 0 on success */
int
-ha_innobase::open(const char* name, int, uint)
+ha_innobase::open(const char* name, int, uint open_flags)
{
char norm_name[FN_REFLEN];
+ dberr_t err;
DBUG_ENTER("ha_innobase::open");
@@ -5509,8 +5520,39 @@ ha_innobase::open(const char* name, int, uint)
}
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ trx_t *trx = innobase_trx_allocate(thd);
+ if (!trx) {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ if (open_flags & HA_OPEN_FOR_REPAIR) {
+ err = fk_upgrade_legacy_storage(ib_table, trx, thd, table->s);
+ if (err == DB_LEGACY_FK) {
+ err = fk_check_legacy_storage(ib_table->name.m_name, trx);
+ if (err == DB_LEGACY_FK) {
+ push_warning_printf(
+ thd,
+ Sql_condition::WARN_LEVEL_WARN,
+ HA_ERR_FK_UPGRADE,
+ "Table %s failed to upgrade foreign keys (index is not corrupt)!",
+ table_share->table_name.str);
+ }
+ }
+ } else {
+ err = fk_check_legacy_storage(ib_table->name.m_name, trx);
+ }
+ trx_commit_for_mysql(trx);
+ trx->error_state = DB_SUCCESS;
+ trx->free();
+ if (err != DB_SUCCESS) {
+ dict_table_close(ib_table, FALSE, FALSE);
+ DBUG_RETURN(convert_error_code_to_mysql(
+ err, ib_table->flags, NULL));
+ }
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
mutex_enter(&dict_sys.mutex);
- dberr_t err = dict_load_foreigns(ib_table, table->s, NULL, false, DICT_ERR_IGNORE_FK_NOKEY);
+ err = dict_load_foreigns(ib_table, table->s, NULL, false, DICT_ERR_IGNORE_FK_NOKEY);
mutex_exit(&dict_sys.mutex);
if (err != DB_SUCCESS) {
dict_table_close(ib_table, FALSE, FALSE);
@@ -10186,7 +10228,7 @@ create_table_info_t::create_table_def()
table->name.m_name, field->field_name.str);
err_col:
dict_mem_table_free(table);
- ut_ad(trx_state_eq(m_trx, TRX_STATE_NOT_STARTED));
+// ut_ad(trx_state_eq(m_trx, TRX_STATE_NOT_STARTED));
DBUG_RETURN(HA_ERR_GENERIC);
}
@@ -12151,6 +12193,30 @@ create_table_info_t::create_foreign_keys()
return (DB_SUCCESS);
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+int create_table_info_t::check_legacy_fk()
+{
+ char table_name[MAX_FULL_NAME_LEN + 1];
+ char *bufptr= table_name;
+ size_t len;
+ if (dict_table_t::build_name(LEX_STRING_WITH_LEN(m_form->s->db),
+ LEX_STRING_WITH_LEN(m_form->s->table_name),
+ bufptr, len)) {
+ return HA_ERR_OUT_OF_MEM;
+ }
+ row_drop_table_check_legacy_data data;
+
+ dberr_t err = row_drop_table_check_legacy_fk(m_trx, table_name, data);
+ if (err != DB_SUCCESS) {
+ return convert_error_code_to_mysql(err, 0, NULL);
+ }
+ if (data.found) {
+ return HA_ERR_FK_UPGRADE;
+ }
+ return 0;
+}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
/** Create the internal innodb table.
@param create_fk whether to add FOREIGN KEY constraints */
int create_table_info_t::create_table(bool create_fk)
@@ -12169,6 +12235,15 @@ int create_table_info_t::create_table(bool create_fk)
the primary key is always number 0, if it exists */
ut_a(primary_key_no == -1 || primary_key_no == 0);
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ if (enum_sql_command(thd_sql_command(m_thd)) == SQLCOM_ALTER_TABLE) {
+ error = check_legacy_fk();
+ if (error) {
+ DBUG_RETURN(error);
+ }
+ }
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
error = create_table_def();
if (error) {
@@ -19380,6 +19455,84 @@ static MYSQL_SYSVAR_BOOL(encrypt_temporary_tables, innodb_encrypt_temporary_tabl
"Enrypt the temporary table data.",
NULL, NULL, false);
+#ifdef UNIV_DEBUG
+
+static char* innodb_eval_sql;
+
+static int innodb_eval_sql_validate(THD *thd, st_mysql_sys_var*,
+ void* save, st_mysql_value* value)
+{
+ /** Preamble to all SQL statements. */
+ static const char* sql_begin= "PROCEDURE P() IS\n";
+
+ /** Postamble to non-committing SQL statements. */
+ static const char* sql_end= "\nEND;\n";
+
+ char *sql, *str;
+ char buff[8192]; // size doesn't matter: val_str() reallocates
+ int len = sizeof(buff);
+
+ ut_ad(save != NULL);
+ ut_ad(value != NULL);
+
+ bool free_trx = false;
+ trx_t * trx = thd_to_trx(thd);
+ if (!trx) {
+ trx = trx_create();
+ if (!trx) {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return 1;
+ }
+ free_trx = true;
+ }
+ trx_start_if_not_started(trx, true);
+ sql = (char*) value->val_str(value, buff, &len);
+ if (!sql) {
+mem_err:
+ trx->error_state = DB_SUCCESS;
+ trx->free();
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return 1;
+ }
+ str = ut_str3cat(sql_begin, sql, sql_end);
+ if (!str) {
+ goto mem_err;
+ }
+
+ trx->op_info = "Evaluating internal SQL";
+
+ pars_info_t* info = pars_info_create();
+ info->fatal_syntax_err = false;
+ dberr_t err = que_eval_sql(info, str, true, trx);
+ ut_free(str);
+ if (err != DB_SUCCESS) {
+ trx->op_info = "Rollback of internal trx on innodb_eval_sql";
+ trx->dict_operation_lock_mode = RW_X_LATCH;
+ trx->rollback();
+ trx->dict_operation_lock_mode = 0;
+ trx->op_info = "";
+ ut_a(trx->error_state == DB_SUCCESS);
+ if (free_trx) {
+ trx->free();
+ }
+ ib_push_warning(trx, err, (err == DB_ERROR ? "Syntax error" : ut_strerr(err)));
+ return 1;
+ }
+ trx_commit_for_mysql(trx);
+ if (free_trx) {
+ trx->free();
+ }
+ *static_cast<const char**>(save) = sql;
+ return 0;
+}
+
+static MYSQL_SYSVAR_STR(eval_sql,
+ innodb_eval_sql,
+ PLUGIN_VAR_OPCMDARG|PLUGIN_VAR_MEMALLOC,
+ "Evaluate internal SQL",
+ innodb_eval_sql_validate, NULL, NULL);
+#endif /* UNIV_DEBUG */
+
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(autoextend_increment),
MYSQL_SYSVAR(buffer_pool_size),
@@ -19542,6 +19695,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(dict_stats_disabled_debug),
MYSQL_SYSVAR(master_thread_disabled_debug),
MYSQL_SYSVAR(sync_debug),
+ MYSQL_SYSVAR(eval_sql),
#endif /* UNIV_DEBUG */
MYSQL_SYSVAR(force_primary_key),
MYSQL_SYSVAR(fatal_semaphore_wait_threshold),
@@ -19603,6 +19757,10 @@ i_s_innodb_sys_tablestats,
i_s_innodb_sys_indexes,
i_s_innodb_sys_columns,
i_s_innodb_sys_fields,
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+i_s_innodb_sys_foreign,
+i_s_innodb_sys_foreign_cols,
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
i_s_innodb_sys_tablespaces,
i_s_innodb_sys_datafiles,
i_s_innodb_sys_virtual,
@@ -21015,6 +21173,471 @@ void ins_node_t::vers_update_end(row_prebuilt_t *prebuilt, bool history_row)
}
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+struct fk_legacy_data
+{
+ trx_t *trx;
+ dict_table_t *table;
+ TABLE_SHARE *s;
+ char ref_name[MAX_FULL_NAME_LEN + 1];
+ FK_info *fk;
+ dberr_t err;
+ FK_list foreign_keys;
+ fk_legacy_data(trx_t *_t, dict_table_t *_tab, TABLE_SHARE *_s) : trx(_t), table(_tab), s(_s), fk(NULL), err(DB_SUCCESS)
+ {};
+};
+
+static
+ibool
+fk_upgrade_create_fk(
+/*=================*/
+ void* row, /*!< in: sel_node_t* */
+ void* user_arg) /*!< in: fk_legacy_data */
+{
+ fk_legacy_data &d = *(fk_legacy_data *) user_arg;
+ d.err = DB_CANNOT_ADD_CONSTRAINT;
+ sel_node_t* node = static_cast<sel_node_t*>(row);
+ que_node_t* exp = node->select_list;
+
+ // Get foreign key ID
+ dfield_t* fld = que_node_get_val(exp);
+ char src_id[MAX_FULL_NAME_LEN + 1];
+ char dst_id[MAX_TABLE_NAME_LEN + 1];
+ char src_ref[MAX_FULL_NAME_LEN + 1];
+ ut_a(fld->len <= MAX_FULL_NAME_LEN);
+ memcpy(src_id, fld->data, fld->len);
+ src_id[fld->len] = 0;
+ LEX_CSTRING id;
+ id.str = (const char*) memchr(src_id, '/', fld->len);
+
+ if (id.str == NULL) {
+ id = { (char *) src_id, fld->len };
+ } else {
+ id.str++;
+ size_t prefix_len = id.str - src_id;
+ if (prefix_len >= fld->len) {
+ ib_foreign_warn(d.trx, DB_CANNOT_ADD_CONSTRAINT, d.s->table_name.str,
+ "Upgrade table %s with foreign key %s constraint"
+ " failed. Wrong foreign key ID!",
+ d.s->table_name.str, src_id);
+ return 0;
+ }
+ id.length = fld->len - prefix_len;
+ }
+
+ id.length = filename_to_tablename(id.str, dst_id, sizeof(dst_id));
+ ut_a(id.length);
+ id.str = dst_id;
+
+ for (FK_info &fk: d.s->foreign_keys) {
+ if (0 == cmp_ident(fk.foreign_id, id)) {
+ ib_foreign_warn(d.trx, DB_CANNOT_ADD_CONSTRAINT, d.s->table_name.str,
+ "Upgrade table %s with foreign key %s constraint"
+ " failed. Duplicate foreign key ID!",
+ d.s->table_name.str, src_id);
+ return 0;
+ }
+ }
+
+ // Get referenced table name
+ exp = que_node_get_next(exp);
+ fld = que_node_get_val(exp);
+ ut_a(fld);
+ char dst_db[MAX_TABLE_NAME_LEN + 1];
+ char dst_table[MAX_TABLE_NAME_LEN + 1];
+ ut_a(fld->len <= MAX_FULL_NAME_LEN);
+ memcpy(src_ref, fld->data, fld->len);
+ src_ref[fld->len] = 0;
+ memcpy(d.ref_name, src_ref, fld->len + 1);
+ LEX_CSTRING db, table;
+ table.str = (const char*) memchr(src_ref, '/', fld->len);
+
+ if (table.str == NULL) {
+ table = { (char *) src_ref, fld->len };
+ db = { NULL, 0 };
+ } else {
+ table.str++;
+ size_t prefix_len = table.str - src_ref;
+ if (prefix_len >= fld->len) {
+ ib_foreign_warn(d.trx, DB_CANNOT_ADD_CONSTRAINT, d.s->table_name.str,
+ "Upgrade table %s with foreign key %s constraint"
+ " failed. Wrong referenced table name!",
+ d.s->table_name.str, src_id);
+ return 0;
+ }
+ table.length = fld->len - prefix_len;
+ db = { src_ref, prefix_len - 1 };
+ src_ref[db.length] = 0;
+ }
+
+ table.length = filename_to_tablename(table.str, dst_table, sizeof(dst_table));
+ ut_a(table.length);
+ table.str = dst_table;
+
+ if (db.length) {
+ db.length = filename_to_tablename(db.str, dst_db, sizeof(dst_db));
+ ut_a(db.length);
+ db.str = dst_db;
+ }
+
+ ut_a(!que_node_get_next(exp));
+ d.fk= new (&d.s->mem_root) FK_info();
+ if (!d.fk) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+ d.fk->foreign_id.strdup(&d.s->mem_root, id);
+ if (!d.fk->foreign_id.str) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+ d.fk->foreign_db = d.s->db;
+ d.fk->foreign_table = d.s->table_name;
+ if (0 != cmp_table(d.s->db, db)) {
+ d.fk->referenced_db.strdup(&d.s->mem_root, db);
+ if (!d.fk->referenced_db.str) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+ }
+ d.fk->referenced_table.strdup(&d.s->mem_root, table);
+ if (!d.fk->referenced_table.str) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+ d.err = DB_LEGACY_FK;
+ return 1;
+}
+
+static
+ibool
+fk_upgrade_add_col(
+/*=================*/
+ void* row, /*!< in: sel_node_t* */
+ void* user_arg) /*!< in: fk_legacy_data */
+{
+ fk_legacy_data &d = *(fk_legacy_data *) user_arg;
+ if (d.err != DB_LEGACY_FK) {
+ return 0;
+ }
+ sel_node_t* node = static_cast<sel_node_t*>(row);
+ que_node_t* exp = node->select_list;
+
+ // Get FOR_COL_NAME
+ dfield_t* fld = que_node_get_val(exp);
+ ut_a(fld);
+ Lex_cstring *dst_f= new (&d.s->mem_root) Lex_cstring();
+ if (!dst_f) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+ dst_f->strdup(&d.s->mem_root, { (char *) fld->data, fld->len });
+ if (!dst_f->str) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+
+ if (d.fk->foreign_fields.push_back(dst_f, &d.s->mem_root)) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+
+ // Get REF_COL_NAME
+ exp = que_node_get_next(exp);
+ fld = que_node_get_val(exp);
+ ut_a(exp);
+ ut_a(fld);
+ dst_f= new (&d.s->mem_root) Lex_cstring();
+ if (!dst_f) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+ dst_f->strdup(&d.s->mem_root, { (char *) fld->data, fld->len });
+ if (!dst_f->str) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+
+ if (d.fk->referenced_fields.push_back(dst_f, &d.s->mem_root)) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+
+ ut_a(!que_node_get_next(exp));
+ return 1;
+}
+
+static
+ibool
+fk_upgrade_push_fk(
+/*=================*/
+ void* row, /*!< in: sel_node_t* */
+ void* user_arg) /*!< in: fk_legacy_data */
+{
+ fk_legacy_data &d = *(fk_legacy_data *) user_arg;
+ if (d.err != DB_LEGACY_FK) {
+ return 0;
+ }
+ // Check indexes on ref and on foreign
+ FK_info &fk = *d.fk;
+ ut_ad(fk.foreign_fields.elements < MAX_NUM_FK_COLUMNS);
+ ut_ad(fk.foreign_fields.elements == fk.referenced_fields.elements);
+ uint i= 0;
+ const char* column_names[MAX_NUM_FK_COLUMNS];
+ const char* ref_column_names[MAX_NUM_FK_COLUMNS];
+ dict_index_t* index;
+ List_iterator_fast<Lex_cstring> it(fk.referenced_fields);
+ for (Lex_cstring &col: fk.foreign_fields) {
+ column_names[i] = col.str;
+ Lex_cstring *rcol = it++;
+ ref_column_names[i++] = rcol->str;
+ }
+ mutex_enter(&dict_sys.mutex);
+ index = dict_foreign_find_index(
+ d.table, NULL, column_names, fk.foreign_fields.elements,
+ NULL, true, false);
+ if (!index) {
+ mutex_exit(&dict_sys.mutex);
+ ib_foreign_warn(d.trx, DB_CANNOT_ADD_CONSTRAINT, d.s->table_name.str,
+ "Upgrade table %s with foreign key %s constraint"
+ " failed. Foreign key index not found!",
+ d.s->table_name.str, fk.foreign_id.str);
+ d.err = DB_CANNOT_ADD_CONSTRAINT;
+ return 0;
+ }
+ dict_table_t* ref_table = dict_table_open_on_name(d.ref_name, true, false, DICT_ERR_IGNORE_FK_NOKEY);
+ if (!ref_table) {
+ mutex_exit(&dict_sys.mutex);
+ ib_foreign_warn(d.trx, DB_CANNOT_ADD_CONSTRAINT, d.s->table_name.str,
+ "Upgrade table %s with foreign key %s constraint"
+ " failed. Could not open referenced table!",
+ d.s->table_name.str, fk.foreign_id.str);
+ d.err = DB_CANNOT_ADD_CONSTRAINT;
+ return 0;
+ }
+ index = dict_foreign_find_index(
+ ref_table, NULL, ref_column_names, fk.foreign_fields.elements,
+ NULL, true, false);
+ dict_table_close(ref_table, true, false);
+ mutex_exit(&dict_sys.mutex);
+ if (!index) {
+ ib_foreign_warn(d.trx, DB_CANNOT_ADD_CONSTRAINT, d.s->table_name.str,
+ "Upgrade table %s with foreign key %s constraint"
+ " failed. Referenced key index not found!",
+ d.s->table_name.str, fk.foreign_id.str);
+ d.err = DB_CANNOT_ADD_CONSTRAINT;
+ return 0;
+ }
+ if (d.foreign_keys.push_back(d.fk, &d.s->mem_root)) {
+ d.err = DB_OUT_OF_MEMORY;
+ return 0;
+ }
+ d.fk = NULL;
+ return 1;
+}
+
+static
+dberr_t
+fk_upgrade_legacy_storage(dict_table_t* table, trx_t* trx, THD *thd, TABLE_SHARE *share)
+{
+ pars_info_t* info;
+ fk_legacy_data d(trx, table, share);
+
+ info = pars_info_create();
+ if (!info) {
+ return DB_OUT_OF_MEMORY;
+ }
+ pars_info_bind_function(info, "fk_upgrade_create_fk", fk_upgrade_create_fk, &d);
+ pars_info_bind_function(info, "fk_upgrade_add_col", fk_upgrade_add_col, &d);
+ pars_info_bind_function(info, "fk_upgrade_push_fk", fk_upgrade_push_fk, &d);
+ pars_info_add_str_literal(info, "for_name", table->name.m_name);
+ static const char sql_fetch[] =
+ "PROCEDURE FETCH_PROC () IS\n"
+ "fk_id CHAR;\n"
+ "unused CHAR;\n"
+ "DECLARE FUNCTION fk_upgrade_create_fk;\n"
+ "DECLARE FUNCTION fk_upgrade_add_col;\n"
+ "DECLARE FUNCTION fk_upgrade_push_fk;\n"
+
+ "DECLARE CURSOR c IS"
+ " SELECT ID, REF_NAME FROM SYS_FOREIGN"
+ " WHERE FOR_NAME = :for_name;"
+
+ "DECLARE CURSOR c2 IS"
+ " SELECT FOR_COL_NAME, REF_COL_NAME FROM SYS_FOREIGN_COLS"
+ " WHERE ID = fk_id;"
+
+ "DECLARE CURSOR c3 IS"
+ " SELECT ID FROM SYS_FOREIGN;"
+
+ "BEGIN\n"
+ "OPEN c;\n"
+ "WHILE 1 = 1 LOOP\n"
+ " FETCH c INTO fk_upgrade_create_fk() fk_id, unused;\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " EXIT;\n"
+ " END IF;\n"
+ " OPEN c2;\n"
+ " WHILE 1 = 1 LOOP\n"
+ " FETCH c2 INTO fk_upgrade_add_col();\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " CLOSE c2;\n"
+ " OPEN c3;\n"
+ " FETCH c3 INTO fk_upgrade_push_fk();\n"
+ " CLOSE c3;\n"
+ " EXIT;\n"
+ " END IF;\n"
+ " END LOOP;\n"
+ "END LOOP;\n"
+ "CLOSE c;\n"
+ "END;\n";
+
+ dberr_t err = que_eval_sql(info, sql_fetch, true, trx);
+ if (err != DB_SUCCESS) {
+ return err;
+ }
+
+ if (d.err != DB_LEGACY_FK) {
+ return d.err;
+ }
+
+ ut_ad(d.foreign_keys.elements);
+
+ // Got legacy foreign keys, update referenced shares
+ FK_table_backup fk_table_backup;
+ FK_create_vector ref_shares;
+ if (d.s->fk_handle_create(thd, ref_shares, &d.foreign_keys)) {
+ err = DB_ERROR;
+ goto rollback;
+ }
+
+ if (fk_table_backup.init(d.s)) {
+ err = DB_OUT_OF_MEMORY;
+ goto rollback;
+ }
+
+ // Push to main share. Share is already locked by Open_table_context.
+ for (FK_info &fk: d.foreign_keys) {
+ if (d.s->foreign_keys.push_back(&fk, &d.s->mem_root)) {
+ err = DB_OUT_OF_MEMORY;
+ goto rollback;
+ }
+ }
+
+ // Update foreign FRM
+ if (d.s->fk_write_shadow_frm()) {
+ err = DB_ERROR;
+ goto rollback;
+ }
+
+ // Update referenced FRMs
+ for (FK_ddl_backup &bak: ref_shares) {
+ if (bak.sa.share->fk_install_shadow_frm()) {
+ // TODO: MDEV-21053 atomicity
+ err = DB_ERROR;
+ goto rollback;
+ }
+ }
+
+ if (d.s->fk_install_shadow_frm()) {
+ err = DB_ERROR;
+ goto rollback;
+ }
+
+ fk_table_backup.commit();
+
+ // Drop legacy foreign keys
+ static const char sql_drop[] =
+ "PROCEDURE DROP_PROC () IS\n"
+ "fk_id CHAR;\n"
+ "DECLARE CURSOR c IS\n"
+ "SELECT ID FROM SYS_FOREIGN\n"
+ "WHERE FOR_NAME = :for_name\n"
+ "LOCK IN SHARE MODE;\n"
+ "BEGIN\n"
+ "OPEN c;\n"
+ "WHILE 1 = 1 LOOP\n"
+ " FETCH c INTO fk_id;\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " EXIT;\n"
+ " END IF;\n"
+ " DELETE FROM SYS_FOREIGN_COLS\n"
+ " WHERE ID = fk_id;\n"
+ " DELETE FROM SYS_FOREIGN\n"
+ " WHERE ID = fk_id;\n"
+ "END LOOP;\n"
+ "CLOSE c;\n"
+ "COMMIT WORK;\n"
+ "END;\n";
+
+ info = pars_info_create();
+ if (!info) {
+ return DB_OUT_OF_MEMORY;
+ }
+ pars_info_add_str_literal(info, "for_name", table->name.m_name);
+
+ err = que_eval_sql(info, sql_drop, true, trx);
+ if (err != DB_SUCCESS) {
+ return err;
+ }
+
+ return DB_LEGACY_FK;
+
+rollback:
+ for (FK_ddl_backup &bak: ref_shares) {
+ bak.rollback();
+ }
+ return err;
+}
+
+static
+ibool
+fk_check_upgrade(
+/*=================*/
+ void* row, /*!< in: sel_node_t* */
+ void* user_arg) /*!< in: bool do_upgrade */
+{
+ bool &do_upgrade = *(bool *) user_arg;
+ do_upgrade = true;
+ return 0;
+}
+
+static
+dberr_t
+fk_check_legacy_storage(const char* table_name, trx_t* trx)
+{
+ pars_info_t* info;
+ bool do_upgrade = false;
+
+ info = pars_info_create();
+ if (!info) {
+ return DB_OUT_OF_MEMORY;
+ }
+ pars_info_bind_function(info, "fk_check_upgrade", fk_check_upgrade, &do_upgrade);
+ pars_info_add_str_literal(info, "for_name", table_name);
+ static const char sql[] =
+ "PROCEDURE FK_PROC () IS\n"
+ "DECLARE FUNCTION fk_check_upgrade;\n"
+
+ "DECLARE CURSOR c IS"
+ " SELECT ID FROM SYS_FOREIGN"
+ " WHERE FOR_NAME = :for_name;"
+
+ "BEGIN\n"
+ "OPEN c;\n"
+ "FETCH c INTO fk_check_upgrade();\n"
+ "CLOSE c;\n"
+ "END;\n";
+
+ dberr_t err = que_eval_sql(info, sql, true, trx);
+ if (err == DB_SUCCESS && do_upgrade) {
+ err = DB_LEGACY_FK;
+ }
+
+ return err;
+}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
dberr_t
dict_load_foreigns(
dict_table_t* table,
@@ -21100,7 +21723,7 @@ dict_load_foreigns(
if (!foreign->foreign_table_name)
return DB_OUT_OF_MEMORY;
- if (dict_table_t::build_name(LEX_STRING_WITH_LEN(fk.referenced_db),
+ if (dict_table_t::build_name(LEX_STRING_WITH_LEN(fk.ref_db()),
LEX_STRING_WITH_LEN(fk.referenced_table), bufptr, len)) {
return DB_CANNOT_ADD_CONSTRAINT;
}
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 80cac0887a2..d8e04676db5 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -102,6 +102,13 @@ public:
int open(const char *name, int mode, uint test_if_locked) override;
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ bool auto_repair(int error) const override
+ {
+ return (error == HA_ERR_FK_UPGRADE);
+ }
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
handler* clone(const char *name, MEM_ROOT *mem_root) override;
int close(void) override;
@@ -744,6 +751,10 @@ private:
/** Create the internal innodb table definition. */
int create_table_def();
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ int check_legacy_fk();
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
/** Connection thread handle. */
THD* m_thd;
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 507f9cbba4f..355f1259f29 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -7171,6 +7171,71 @@ err_exit:
DBUG_RETURN(true);
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+static
+ibool
+innobase_drop_column_check_legacy_step(
+/*=================*/
+ void* row, /*!< in: sel_node_t* */
+ void* user_arg) /*!< out: bool found */
+{
+ bool &found = *(bool *) user_arg;
+ sel_node_t* node = static_cast<sel_node_t*>(row);
+ que_node_t* exp = node->select_list;
+ found = true;
+ ut_a(!que_node_get_next(exp));
+ return 0;
+}
+
+static
+dberr_t innobase_drop_column_check_legacy_fk(trx_t* trx, const char * table_name,
+ const char * col_name, bool &found)
+{
+ static const char sql_check[] =
+ "PROCEDURE FK_PROC () IS\n"
+ "fk_id CHAR;\n"
+ "DECLARE FUNCTION innobase_drop_column_check_legacy_step;\n"
+
+ "DECLARE CURSOR c IS"
+ " SELECT ID FROM SYS_FOREIGN"
+ " WHERE REF_NAME = :ref_name;\n"
+
+ "DECLARE CURSOR c2 IS"
+ " SELECT FOR_COL_NAME FROM SYS_FOREIGN_COLS"
+ " WHERE ID = fk_id AND REF_COL_NAME = :ref_col_name;\n"
+
+ "BEGIN\n"
+ "OPEN c;\n"
+ "WHILE 1 = 1 LOOP\n"
+ " FETCH c INTO fk_id;\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " EXIT;\n"
+ " END IF;\n"
+ " OPEN c2;\n"
+ " FETCH c2 INTO innobase_drop_column_check_legacy_step();\n"
+ " CLOSE c2;\n"
+ "END LOOP;\n"
+ "CLOSE c;\n"
+ "END;\n";
+
+ pars_info_t* info = pars_info_create();
+ if (!info) {
+ return DB_OUT_OF_MEMORY;
+ }
+ pars_info_bind_function(info, "innobase_drop_column_check_legacy_step",
+ innobase_drop_column_check_legacy_step, &found);
+ pars_info_add_str_literal(info, "ref_name", table_name);
+ pars_info_add_str_literal(info, "ref_col_name", col_name);
+
+ dberr_t err = que_eval_sql(info, sql_check, false, trx);
+ if (err != DB_SUCCESS) {
+ return err;
+ }
+
+ return DB_SUCCESS;
+}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
/* Check whether an index is needed for the foreign key constraint.
If so, if it is dropped, is there an equivalent index can play its role.
@return true if the index is needed and can't be dropped */
@@ -7224,6 +7289,19 @@ innobase_check_foreign_key_index(
}
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ bool found = false;
+ // NB: foreign keys always reference index by first field
+ if (DB_SUCCESS != innobase_drop_column_check_legacy_fk(
+ trx, indexed_table->name.m_name, index->fields[0].name, found)) {
+ return false;
+ }
+ if (found) {
+ trx->error_info = index;
+ return(true);
+ }
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
fks = &indexed_table->foreign_set;
/* Check for all FK references in current table using the index. */
@@ -8889,6 +8967,42 @@ err_exit:
rename_foreign:
trx->op_info = "renaming column in SYS_FOREIGN_COLS";
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ static const char sql_rename_ref[] =
+ "PROCEDURE FETCH_PROC () IS\n"
+ "fk_id CHAR;\n"
+
+ "DECLARE CURSOR c IS"
+ " SELECT ID FROM SYS_FOREIGN"
+ " WHERE REF_NAME = :ref_name;\n"
+
+ "BEGIN\n"
+ "OPEN c;\n"
+ "WHILE 1 = 1 LOOP\n"
+ " FETCH c INTO fk_id;\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " EXIT;\n"
+ " END IF;\n"
+ " UPDATE SYS_FOREIGN_COLS"
+ " SET REF_COL_NAME = :new"
+ " WHERE ID = fk_id AND REF_COL_NAME = :old;\n"
+ "END LOOP;\n"
+ "CLOSE c;\n"
+ "END;\n";
+
+ pars_info_t* info = pars_info_create();
+
+ pars_info_add_str_literal(info, "ref_name", ctx.old_table->name.m_name);
+ pars_info_add_str_literal(info, "old", from);
+ pars_info_add_str_literal(info, "new", to);
+
+ error = que_eval_sql(info, sql_rename_ref, false, trx);
+
+ if (error != DB_SUCCESS) {
+ goto err_exit;
+ }
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
std::set<dict_foreign_t*> fk_evict;
bool foreign_modified;
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 78235df58ba..3ec342a6e85 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -6057,6 +6057,400 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_fields =
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
};
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+namespace Show {
+/** SYS_FOREIGN ********************************************/
+/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN */
+static ST_FIELD_INFO innodb_sys_foreign_fields_info[] =
+{
+#define SYS_FOREIGN_ID 0
+ Column("ID", Varchar(NAME_LEN + 1), NOT_NULL),
+
+#define SYS_FOREIGN_FOR_NAME 1
+ Column("FOR_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
+
+#define SYS_FOREIGN_REF_NAME 2
+ Column("REF_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
+
+#define SYS_FOREIGN_NUM_COL 3
+ Column("N_COLS", ULong(), NOT_NULL),
+
+#define SYS_FOREIGN_TYPE 4
+ Column("TYPE", ULong(), NOT_NULL),
+
+ CEnd()
+};
+} // namespace Show
+
+/**********************************************************************//**
+Function to fill information_schema.innodb_sys_foreign with information
+collected by scanning SYS_FOREIGN table.
+@return 0 on success */
+static
+int
+i_s_dict_fill_sys_foreign(
+/*======================*/
+ THD* thd, /*!< in: thread */
+ dict_foreign_t* foreign, /*!< in: table */
+ TABLE* table_to_fill) /*!< in/out: fill this table */
+{
+ Field** fields;
+
+ DBUG_ENTER("i_s_dict_fill_sys_foreign");
+
+ fields = table_to_fill->field;
+
+ OK(field_store_string(fields[SYS_FOREIGN_ID], foreign->id));
+
+ OK(field_store_string(fields[SYS_FOREIGN_FOR_NAME],
+ foreign->foreign_table_name));
+
+ OK(field_store_string(fields[SYS_FOREIGN_REF_NAME],
+ foreign->referenced_table_name));
+
+ OK(fields[SYS_FOREIGN_NUM_COL]->store(foreign->n_fields));
+
+ OK(fields[SYS_FOREIGN_TYPE]->store(foreign->type));
+
+ OK(schema_table_store_record(thd, table_to_fill));
+
+ DBUG_RETURN(0);
+}
+
+/*******************************************************************//**
+Function to populate INFORMATION_SCHEMA.innodb_sys_foreign table. Loop
+through each record in SYS_FOREIGN, and extract the foreign key
+information.
+@return 0 on success */
+static
+int
+i_s_sys_foreign_fill_table(
+/*=======================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (not used) */
+{
+ btr_pcur_t pcur;
+ const rec_t* rec;
+ mem_heap_t* heap;
+ mtr_t mtr;
+
+ DBUG_ENTER("i_s_sys_foreign_fill_table");
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str);
+
+ /* deny access to user without PROCESS_ACL privilege */
+ if (check_global_access(thd, PROCESS_ACL)) {
+
+ DBUG_RETURN(0);
+ }
+
+ heap = mem_heap_create(1000);
+ mutex_enter(&dict_sys.mutex);
+ mtr_start(&mtr);
+
+ rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
+
+ while (rec) {
+ const char* err_msg;
+ dict_foreign_t foreign_rec;
+
+ /* Populate a dict_foreign_t structure with information from
+ a SYS_FOREIGN row */
+ err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
+
+ mtr_commit(&mtr);
+ mutex_exit(&dict_sys.mutex);
+
+ if (!err_msg) {
+ i_s_dict_fill_sys_foreign(thd, &foreign_rec,
+ tables->table);
+ } else {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_CANT_FIND_SYSTEM_REC, "%s",
+ err_msg);
+ }
+
+ mem_heap_empty(heap);
+
+ /* Get the next record */
+ mtr_start(&mtr);
+ mutex_enter(&dict_sys.mutex);
+ rec = dict_getnext_system(&pcur, &mtr);
+ }
+
+ mtr_commit(&mtr);
+ mutex_exit(&dict_sys.mutex);
+ mem_heap_free(heap);
+
+ DBUG_RETURN(0);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign
+@return 0 on success */
+static
+int
+innodb_sys_foreign_init(
+/*====================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("innodb_sys_foreign_init");
+
+ schema = (ST_SCHEMA_TABLE*) p;
+
+ schema->fields_info = Show::innodb_sys_foreign_fields_info;
+ schema->fill_table = i_s_sys_foreign_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_SYS_FOREIGN"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_FOREIGN"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_sys_foreign_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* Maria extension */
+ STRUCT_FLD(version_info, INNODB_VERSION_STR),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
+};
+
+namespace Show {
+/** SYS_FOREIGN_COLS ********************************************/
+/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS */
+static ST_FIELD_INFO innodb_sys_foreign_cols_fields_info[] =
+{
+#define SYS_FOREIGN_COL_ID 0
+ Column("ID", Varchar(NAME_LEN + 1), NOT_NULL),
+
+#define SYS_FOREIGN_COL_FOR_NAME 1
+ Column("FOR_COL_NAME", Varchar(NAME_CHAR_LEN), NOT_NULL),
+
+#define SYS_FOREIGN_COL_REF_NAME 2
+ Column("REF_COL_NAME", Varchar(NAME_CHAR_LEN), NOT_NULL),
+
+#define SYS_FOREIGN_COL_POS 3
+ Column("POS", ULong(), NOT_NULL),
+
+ CEnd()
+};
+} // namespace Show
+
+/**********************************************************************//**
+Function to fill information_schema.innodb_sys_foreign_cols with information
+collected by scanning SYS_FOREIGN_COLS table.
+@return 0 on success */
+static
+int
+i_s_dict_fill_sys_foreign_cols(
+/*==========================*/
+ THD* thd, /*!< in: thread */
+ const char* name, /*!< in: foreign key constraint name */
+ const char* for_col_name, /*!< in: referencing column name*/
+ const char* ref_col_name, /*!< in: referenced column
+ name */
+ ulint pos, /*!< in: column position */
+ TABLE* table_to_fill) /*!< in/out: fill this table */
+{
+ Field** fields;
+
+ DBUG_ENTER("i_s_dict_fill_sys_foreign_cols");
+
+ fields = table_to_fill->field;
+
+ OK(field_store_string(fields[SYS_FOREIGN_COL_ID], name));
+
+ OK(field_store_string(fields[SYS_FOREIGN_COL_FOR_NAME], for_col_name));
+
+ OK(field_store_string(fields[SYS_FOREIGN_COL_REF_NAME], ref_col_name));
+
+ OK(fields[SYS_FOREIGN_COL_POS]->store(pos, true));
+
+ OK(schema_table_store_record(thd, table_to_fill));
+
+ DBUG_RETURN(0);
+}
+/*******************************************************************//**
+Function to populate INFORMATION_SCHEMA.innodb_sys_foreign_cols table. Loop
+through each record in SYS_FOREIGN_COLS, and extract the foreign key column
+information and fill the INFORMATION_SCHEMA.innodb_sys_foreign_cols table.
+@return 0 on success */
+static
+int
+i_s_sys_foreign_cols_fill_table(
+/*============================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (not used) */
+{
+ btr_pcur_t pcur;
+ const rec_t* rec;
+ mem_heap_t* heap;
+ mtr_t mtr;
+
+ DBUG_ENTER("i_s_sys_foreign_cols_fill_table");
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str);
+
+ /* deny access to user without PROCESS_ACL privilege */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ heap = mem_heap_create(1000);
+ mutex_enter(&dict_sys.mutex);
+ mtr_start(&mtr);
+
+ rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
+
+ while (rec) {
+ const char* err_msg;
+ const char* name;
+ const char* for_col_name;
+ const char* ref_col_name;
+ ulint pos;
+
+ /* Extract necessary information from a SYS_FOREIGN_COLS row */
+ err_msg = dict_process_sys_foreign_col_rec(
+ heap, rec, &name, &for_col_name, &ref_col_name, &pos);
+
+ mtr_commit(&mtr);
+ mutex_exit(&dict_sys.mutex);
+
+ if (!err_msg) {
+ i_s_dict_fill_sys_foreign_cols(
+ thd, name, for_col_name, ref_col_name, pos,
+ tables->table);
+ } else {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_CANT_FIND_SYSTEM_REC, "%s",
+ err_msg);
+ }
+
+ mem_heap_empty(heap);
+
+ /* Get the next record */
+ mutex_enter(&dict_sys.mutex);
+ mtr_start(&mtr);
+ rec = dict_getnext_system(&pcur, &mtr);
+ }
+
+ mtr_commit(&mtr);
+ mutex_exit(&dict_sys.mutex);
+ mem_heap_free(heap);
+
+ DBUG_RETURN(0);
+}
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols
+@return 0 on success */
+static
+int
+innodb_sys_foreign_cols_init(
+/*========================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("innodb_sys_foreign_cols_init");
+
+ schema = (ST_SCHEMA_TABLE*) p;
+
+ schema->fields_info = Show::innodb_sys_foreign_cols_fields_info;
+ schema->fill_table = i_s_sys_foreign_cols_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign_cols =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_SYS_FOREIGN_COLS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_FOREIGN_COLS"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_sys_foreign_cols_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* Maria extension */
+ STRUCT_FLD(version_info, INNODB_VERSION_STR),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
+};
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
namespace Show {
/** SYS_TABLESPACES ********************************************/
/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES */
diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h
index 8779760e393..4efa8116476 100644
--- a/storage/innobase/handler/i_s.h
+++ b/storage/innobase/handler/i_s.h
@@ -56,6 +56,10 @@ extern struct st_maria_plugin i_s_innodb_sys_tablestats;
extern struct st_maria_plugin i_s_innodb_sys_indexes;
extern struct st_maria_plugin i_s_innodb_sys_columns;
extern struct st_maria_plugin i_s_innodb_sys_fields;
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+extern struct st_maria_plugin i_s_innodb_sys_foreign;
+extern struct st_maria_plugin i_s_innodb_sys_foreign_cols;
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
extern struct st_maria_plugin i_s_innodb_sys_tablespaces;
extern struct st_maria_plugin i_s_innodb_sys_datafiles;
extern struct st_maria_plugin i_s_innodb_mutexes;
diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h
index 6cfc63f4a9e..0689327e1a5 100644
--- a/storage/innobase/include/db0err.h
+++ b/storage/innobase/include/db0err.h
@@ -163,6 +163,9 @@ enum dberr_t {
DB_PAGE_CORRUPTED, /* Page read from tablespace is
corrupted. */
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ DB_LEGACY_FK,
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
/* The following are partial failure codes */
DB_FAIL = 1000,
DB_OVERFLOW,
diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h
index 0f96df8fd9f..8a24bb0c6c0 100644
--- a/storage/innobase/include/dict0boot.h
+++ b/storage/innobase/include/dict0boot.h
@@ -225,6 +225,7 @@ enum dict_fld_sys_fields_enum {
DICT_FLD__SYS_FIELDS__COL_NAME = 4,
DICT_NUM_FIELDS__SYS_FIELDS = 5
};
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
/* The columns in SYS_FOREIGN */
enum dict_col_sys_foreign_enum {
DICT_COL__SYS_FOREIGN__ID = 0,
@@ -267,6 +268,7 @@ enum dict_fld_sys_foreign_cols_enum {
DICT_FLD__SYS_FOREIGN_COLS__REF_COL_NAME = 5,
DICT_NUM_FIELDS__SYS_FOREIGN_COLS = 6
};
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
/* The columns in SYS_TABLESPACES */
enum dict_col_sys_tablespaces_enum {
DICT_COL__SYS_TABLESPACES__SPACE = 0,
diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h
index e2b793a0610..ab908fdf107 100644
--- a/storage/innobase/include/dict0crea.h
+++ b/storage/innobase/include/dict0crea.h
@@ -113,6 +113,17 @@ dict_create_index_tree_in_mem(
dict_index_t* index, /*!< in/out: index */
const trx_t* trx); /*!< in: InnoDB transaction handle */
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+/****************************************************************//**
+Creates the foreign key constraints system tables inside InnoDB
+at server bootstrap or server start if they are not found or are
+not of the right form.
+@return DB_SUCCESS or error code */
+dberr_t
+dict_create_or_check_foreign_constraint_tables(void);
+/*================================================*/
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
/********************************************************************//**
Generate a foreign key constraint name when it was not named by the user.
A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER,
@@ -171,6 +182,7 @@ dict_replace_tablespace_in_dictionary(
const char* path,
trx_t* trx);
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
/********************************************************************//**
Construct foreign key constraint defintion from data dictionary information.
*/
@@ -180,6 +192,7 @@ dict_foreign_def_get(
/*=================*/
dict_foreign_t* foreign,/*!< in: foreign */
trx_t* trx); /*!< in: trx */
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
/* Table create node structure */
struct tab_node_t{
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index b5319d51c9a..2edadb9ede5 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -462,6 +462,7 @@ dict_foreign_replace_index(
to use table->col_names */
const dict_index_t* index) /*!< in: index to be replaced */
MY_ATTRIBUTE((nonnull(1,3), warn_unused_result));
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
/**********************************************************************//**
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement.
@return DB_SUCCESS or DB_CANNOT_DROP_CONSTRAINT if syntax error or the
@@ -478,6 +479,7 @@ dict_foreign_parse_drop_constraints(
const char*** constraints_to_drop) /*!< out: id's of the
constraints to drop */
MY_ATTRIBUTE((nonnull, warn_unused_result));
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
/**********************************************************************//**
Returns a table object and increments its open handle count.
NOTE! This is a high-level function to be used mainly from outside the
diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h
index 63661f062b7..e241b7ade71 100644
--- a/storage/innobase/include/dict0load.h
+++ b/storage/innobase/include/dict0load.h
@@ -201,6 +201,34 @@ dict_process_sys_fields_rec(
ulint* pos, /*!< out: Field position */
index_id_t* index_id, /*!< out: current index id */
index_id_t last_id); /*!< in: previous index id */
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+/********************************************************************//**
+This function parses a SYS_FOREIGN record and populate a dict_foreign_t
+structure with the information from the record. For detail information
+about SYS_FOREIGN fields, please refer to dict_load_foreign() function
+@return error message, or NULL on success */
+const char*
+dict_process_sys_foreign_rec(
+/*=========================*/
+ mem_heap_t* heap, /*!< in/out: heap memory */
+ const rec_t* rec, /*!< in: current SYS_FOREIGN rec */
+ dict_foreign_t* foreign); /*!< out: dict_foreign_t to be
+ filled */
+/********************************************************************//**
+This function parses a SYS_FOREIGN_COLS record and extract necessary
+information from the record and return to caller.
+@return error message, or NULL on success */
+const char*
+dict_process_sys_foreign_col_rec(
+/*=============================*/
+ mem_heap_t* heap, /*!< in/out: heap memory */
+ const rec_t* rec, /*!< in: current SYS_FOREIGN_COLS rec */
+ const char** name, /*!< out: foreign key constraint name */
+ const char** for_col_name, /*!< out: referencing column name */
+ const char** ref_col_name, /*!< out: referenced column name
+ in referenced table */
+ ulint* pos); /*!< out: column position */
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
/********************************************************************//**
This function parses a SYS_TABLESPACES record, extracts necessary
information from the record and returns to caller.
diff --git a/storage/innobase/include/pars0grm.h b/storage/innobase/include/pars0grm.h
index 58d424abfdc..4d232352efa 100644
--- a/storage/innobase/include/pars0grm.h
+++ b/storage/innobase/include/pars0grm.h
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.4.1. */
/* Bison interface for Yacc-like parsers in C
diff --git a/storage/innobase/include/pars0pars.h b/storage/innobase/include/pars0pars.h
index 03aa72d3be8..acb44598bb7 100644
--- a/storage/innobase/include/pars0pars.h
+++ b/storage/innobase/include/pars0pars.h
@@ -583,6 +583,9 @@ struct pars_info_t {
ibool graph_owns_us; /*!< if TRUE (which is the default),
que_graph_free() will free us */
+#ifdef UNIV_DEBUG
+ bool fatal_syntax_err;
+#endif /* UNIV_DEBUG */
};
/** User-supplied function and argument. */
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index c4163f8d2e0..8433a82fddf 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -940,4 +940,16 @@ void
row_wait_for_background_drop_list_empty();
#endif /* UNIV_DEBUG */
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+struct row_drop_table_check_legacy_data
+{
+ char foreign_name[MAX_FULL_NAME_LEN + 1];
+ bool found;
+ row_drop_table_check_legacy_data() : found(false) {}
+};
+
+dberr_t row_drop_table_check_legacy_fk(trx_t* trx, const char * table_name,
+ row_drop_table_check_legacy_data &d);
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
#endif /* row0mysql.h */
diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake
index dc6afe59088..035750d19d3 100644
--- a/storage/innobase/innodb.cmake
+++ b/storage/innobase/innodb.cmake
@@ -194,6 +194,11 @@ IF (WITH_INNODB_DISALLOW_WRITES)
ADD_DEFINITIONS(-DWITH_INNODB_DISALLOW_WRITES)
ENDIF()
+OPTION(WITH_INNODB_LEGACY_FOREIGN_STORAGE "Create SYS_FOREIGN, SYS_FOREIGN_COLS tables" ON)
+IF (WITH_INNODB_LEGACY_FOREIGN_STORAGE)
+ ADD_DEFINITIONS(-DWITH_INNODB_LEGACY_FOREIGN_STORAGE)
+ENDIF()
+
# Include directories under innobase
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/innobase/include
diff --git a/storage/innobase/pars/pars0grm.cc b/storage/innobase/pars/pars0grm.cc
index 7e10a783310..eb918973823 100644
--- a/storage/innobase/pars/pars0grm.cc
+++ b/storage/innobase/pars/pars0grm.cc
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.4.1. */
/* Bison implementation for Yacc-like parsers in C
@@ -48,7 +48,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "3.4.2"
+#define YYBISON_VERSION "3.4.1"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -454,7 +454,7 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 5
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 603
+#define YYLAST 623
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 96
@@ -463,7 +463,7 @@ union yyalloc
/* YYNRULES -- Number of rules. */
#define YYNRULES 150
/* YYNSTATES -- Number of states. */
-#define YYNSTATES 300
+#define YYNSTATES 301
#define YYUNDEFTOK 2
#define YYMAXUTOK 335
@@ -526,13 +526,13 @@ static const yytype_uint16 yyrline[] =
228, 229, 234, 235, 236, 241, 242, 243, 247, 248,
256, 257, 258, 263, 265, 268, 272, 273, 277, 278,
283, 284, 289, 290, 291, 295, 296, 303, 318, 323,
- 326, 334, 340, 341, 346, 352, 361, 369, 377, 384,
- 392, 400, 407, 413, 414, 419, 420, 422, 426, 433,
- 439, 449, 453, 457, 464, 471, 475, 483, 492, 493,
- 498, 499, 504, 505, 511, 519, 520, 525, 526, 530,
- 531, 535, 549, 550, 554, 559, 564, 565, 566, 570,
- 576, 578, 579, 583, 591, 597, 598, 601, 603, 604,
- 608
+ 327, 336, 342, 343, 348, 354, 363, 371, 379, 386,
+ 394, 402, 409, 415, 416, 421, 422, 424, 428, 435,
+ 441, 451, 455, 459, 466, 473, 477, 485, 494, 495,
+ 500, 501, 506, 507, 513, 521, 522, 527, 528, 532,
+ 533, 537, 551, 552, 556, 561, 566, 567, 568, 572,
+ 578, 580, 581, 585, 593, 599, 600, 603, 605, 606,
+ 610
};
#endif
@@ -608,10 +608,10 @@ static const yytype_uint16 yytoknum[] =
};
# endif
-#define YYPACT_NINF -129
+#define YYPACT_NINF -162
#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-129)))
+ (!!((Yystate) == (-162)))
#define YYTABLE_NINF -1
@@ -622,36 +622,37 @@ static const yytype_uint16 yytoknum[] =
STATE-NUM. */
static const yytype_int16 yypact[] =
{
- 5, 34, 46, -28, -41, -129, -129, -12, 45, 57,
- 23, -129, 9, -129, -129, -129, 20, -9, -129, -129,
- -129, -129, 2, -129, 83, 87, 278, -129, 93, 28,
- 71, 427, 427, -129, 335, 105, 85, -1, 104, -27,
- 129, 132, 133, 76, 77, -129, 141, -129, 149, -129,
- 61, 19, 62, 118, 65, 66, 118, 68, 69, 70,
- 72, 73, 74, 75, 78, 79, 82, 84, 89, 90,
- 91, 94, 138, -129, 427, -129, -129, -129, -129, 86,
- 427, 96, -129, -129, -129, -129, -129, 427, 427, 438,
- 92, 454, 95, -129, 1, -129, -24, 130, 157, -1,
- -129, -129, 144, -1, -1, -129, 139, -129, 154, -129,
- -129, -129, 98, -129, -129, -129, 108, -129, -129, 345,
- -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
- -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
- -129, 112, 1, 135, 285, 143, -8, 15, 427, 427,
- 427, 427, 427, 278, 203, 427, 427, 427, 427, 427,
- 427, 427, 427, 278, 124, 204, 381, -1, 427, -129,
- 209, -129, 120, -129, 173, 215, 131, 427, 180, 1,
- -129, -129, -129, -129, 285, 285, 30, 30, 1, 10,
- -129, 30, 30, 30, 60, 60, -8, -8, 1, -39,
- 192, 137, -129, 136, -129, -13, -129, 472, 146, -129,
- 147, 225, 227, 151, -129, 136, -129, -21, 0, 229,
- 278, 427, -129, 213, 219, -129, 427, 220, -129, 237,
- 427, -1, 214, 427, 427, 209, 23, -129, 14, 196,
- 160, 158, 162, -129, -129, 278, 486, -129, 231, 1,
- -129, -129, -129, 218, 194, 517, 1, -129, 175, -129,
- 225, -1, -129, -129, -129, 278, -129, -129, 251, 234,
- 278, 266, 260, -129, 181, 278, 201, 239, -129, 235,
- 184, 271, -129, 272, 208, 275, 258, -129, -129, -129,
- 17, -129, -7, -129, -129, 277, -129, -129, -129, -129
+ 10, 21, 39, -47, -45, -162, -162, -44, 28, 41,
+ -5, -162, 6, -162, -162, -162, -38, -37, -162, -162,
+ -162, -162, -4, -162, 45, 47, 267, -162, 37, -28,
+ 8, 416, 416, -162, 324, 55, 24, 2, 35, -24,
+ 61, 62, 76, 17, 18, -162, 84, -162, 129, -162,
+ 4, -10, 5, 69, 12, 14, 69, 15, 19, 23,
+ 27, 34, 44, 48, 51, 53, 56, 57, 59, 65,
+ 70, 71, 74, -162, 416, -162, -162, -162, -162, 25,
+ 416, 36, -162, -162, -162, -162, -162, 416, 416, 436,
+ 54, 456, 68, -162, 537, -162, -29, 121, 147, 2,
+ -162, -162, 122, 2, 2, -162, 113, -162, 126, -162,
+ -162, -162, 78, -162, -162, -162, 79, -162, -162, 334,
+ -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+ -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+ -162, 85, 537, 114, 98, 117, 9, 355, 416, 416,
+ 416, 416, 416, 267, 172, 416, 416, 416, 416, 416,
+ 416, 416, 416, 267, 104, 183, 370, 2, 416, -162,
+ 185, -162, 103, -162, 151, 198, 118, 416, 161, 537,
+ -162, -162, -162, -162, 98, 98, 13, 13, 537, 49,
+ -162, 13, 13, 13, -7, -7, 9, 9, 537, -64,
+ 181, 120, -162, 119, -162, -26, -162, 474, 134, -162,
+ 123, 208, 210, 128, 183, 119, -162, -58, -57, 213,
+ 267, 416, -162, 197, 205, -162, 416, 201, -162, 222,
+ 416, 2, 202, 416, 416, 185, -5, -162, -53, 179,
+ 142, 119, 140, 144, -162, -162, 267, 489, -162, 219,
+ 537, -162, -162, -162, 200, 173, 519, 537, -162, 152,
+ -162, 208, 2, -162, -162, -162, 267, -162, -162, 233,
+ 220, 267, 250, 245, -162, 167, 267, 187, 225, -162,
+ 224, 168, 255, -162, 256, 192, 259, 243, -162, -162,
+ -162, -50, -162, -17, -162, -162, 262, -162, -162, -162,
+ -162
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -680,37 +681,38 @@ static const yytype_uint8 yydefact[] =
143, 48, 49, 37, 45, 46, 42, 43, 44, 105,
39, 38, 40, 41, 33, 32, 34, 35, 66, 0,
0, 0, 63, 74, 72, 76, 60, 0, 0, 92,
- 95, 0, 0, 63, 116, 115, 56, 0, 0, 0,
+ 95, 0, 0, 63, 62, 115, 56, 0, 0, 0,
0, 0, 103, 107, 0, 26, 0, 0, 69, 0,
0, 0, 78, 0, 0, 0, 0, 118, 0, 0,
- 0, 0, 0, 89, 94, 106, 0, 104, 0, 67,
- 109, 64, 61, 0, 80, 0, 91, 93, 120, 124,
- 0, 0, 59, 58, 57, 0, 108, 79, 0, 85,
- 0, 0, 122, 119, 0, 102, 0, 0, 87, 0,
- 0, 0, 117, 0, 0, 0, 0, 121, 123, 125,
- 0, 81, 82, 110, 131, 0, 83, 84, 86, 126
+ 0, 116, 0, 0, 89, 94, 106, 0, 104, 0,
+ 67, 109, 64, 61, 0, 80, 0, 91, 93, 120,
+ 124, 0, 0, 59, 58, 57, 0, 108, 79, 0,
+ 85, 0, 0, 122, 119, 0, 102, 0, 0, 87,
+ 0, 0, 0, 117, 0, 0, 0, 0, 121, 123,
+ 125, 0, 81, 82, 110, 131, 0, 83, 84, 86,
+ 126
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -129, -129, -48, -128, -30, -129, -129, -129, -129, -129,
- 113, 110, 123, -129, -129, -52, -129, -129, -129, -129,
- -40, -129, -129, 55, -129, 238, -129, -129, -129, -129,
- -129, -129, -129, 88, -129, -129, -129, -129, -129, -129,
- -129, -129, -129, -129, 35, -129, -129, -129, -129, -129,
- -129, -129, -129, -96, -129, -129, 81, 290, -129, -129,
- -129, 286, -129, -129
+ -162, -162, -48, -132, -30, -162, -162, -162, -162, -162,
+ -161, 94, 106, -162, -162, -52, -162, -162, -162, -162,
+ -35, -162, -162, 38, -162, 221, -162, -162, -162, -162,
+ -162, -162, -162, 60, -162, -162, -162, -162, -162, -162,
+ -162, -162, -162, -162, 26, -162, -162, -162, -162, -162,
+ -162, -162, -162, -96, -162, -162, 40, 266, -162, -162,
+ -162, 257, -162, -162
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
-1, 2, 47, 48, 94, 90, 217, 49, 214, 205,
- 203, 199, 95, 96, 97, 120, 254, 269, 298, 278,
+ 203, 199, 95, 96, 97, 120, 255, 270, 299, 279,
50, 51, 52, 209, 210, 121, 53, 54, 55, 56,
57, 58, 59, 222, 223, 224, 60, 61, 62, 63,
- 64, 65, 66, 67, 237, 238, 272, 282, 68, 290,
+ 64, 65, 66, 67, 237, 238, 273, 283, 68, 291,
106, 174, 69, 102, 70, 71, 16, 11, 12, 19,
20, 21, 22, 3
};
@@ -720,130 +722,134 @@ static const yytype_int16 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_uint16 yytable[] =
{
- 114, 89, 91, 169, 124, 152, 100, 171, 172, 148,
- 149, 117, 150, 151, 152, 165, 10, 30, 230, 1,
- 104, 26, 105, 148, 149, 189, 150, 151, 152, 296,
- 297, 31, 141, 220, 221, 200, 32, 33, 34, 13,
- 14, 4, 35, 152, 142, 24, 5, 34, 36, 7,
- 144, 37, 225, 38, 226, 17, 39, 146, 147, 116,
- 25, 6, 17, 9, 10, 154, 40, 41, 42, 166,
- 241, 206, 242, 152, 154, 43, 44, 101, 45, 8,
- 231, 155, 156, 157, 158, 159, 160, 161, 154, 179,
- 28, 243, 245, 226, 29, 155, 156, 157, 158, 159,
- 160, 161, 15, 154, 46, 259, 183, 260, 294, 23,
- 295, 72, 98, 158, 159, 160, 161, 73, 184, 185,
- 186, 187, 188, 74, 99, 191, 192, 193, 194, 195,
- 196, 197, 198, 154, 103, 252, 107, 275, 207, 108,
- 109, 114, 279, 110, 111, 160, 161, 198, 112, 119,
- 115, 118, 114, 232, 122, 123, 30, 126, 127, 128,
- 167, 129, 130, 131, 132, 274, 34, 133, 134, 113,
- 31, 135, 168, 136, 143, 32, 33, 34, 137, 138,
- 139, 35, 162, 140, 145, 164, 170, 36, 176, 173,
- 37, 246, 38, 175, 181, 39, 249, 114, 177, 30,
- 179, 180, 182, 255, 256, 40, 41, 42, 190, 201,
- 211, 202, 227, 31, 43, 44, 208, 45, 32, 33,
- 34, 212, 213, 216, 35, 219, 234, 114, 228, 229,
- 36, 114, 236, 37, 239, 38, 244, 221, 39, 248,
- 235, 240, 30, 46, 251, 250, 253, 261, 40, 41,
- 42, 262, 266, 263, 264, 286, 31, 43, 44, 267,
- 45, 32, 33, 34, 268, 271, 276, 35, 277, 280,
- 281, 283, 284, 36, 285, 287, 37, 288, 38, 289,
- 291, 39, 292, 293, 299, 30, 46, 218, 215, 204,
- 257, 40, 41, 42, 125, 273, 150, 151, 152, 31,
- 43, 44, 18, 45, 32, 33, 34, 0, 27, 0,
- 35, 247, 0, 0, 0, 0, 36, 258, 0, 37,
- 0, 38, 0, 0, 39, 0, 0, 0, 0, 46,
- 0, 0, 0, 0, 40, 41, 42, 0, 75, 76,
- 77, 78, 79, 43, 44, 80, 45, 0, 75, 76,
- 77, 78, 79, 0, 0, 80, 0, 0, 154, 0,
- 0, 0, 0, 0, 92, 155, 156, 157, 158, 159,
- 160, 161, 46, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 75, 76, 77, 78, 79, 178,
- 81, 80, 0, 0, 0, 82, 83, 84, 85, 86,
- 81, 0, 0, 0, 0, 82, 83, 84, 85, 86,
- 92, 0, 0, 0, 0, 0, 0, 0, 87, 0,
- 93, 0, 0, 0, 0, 88, 0, 0, 87, 0,
- 75, 76, 77, 78, 79, 88, 81, 80, 0, 0,
- 0, 82, 83, 84, 85, 86, 148, 149, 0, 150,
- 151, 152, 0, 0, 0, 0, 0, 0, 0, 0,
- 153, 0, 148, 149, 87, 150, 151, 152, 0, 0,
- 0, 88, 0, 0, 0, 0, 0, 0, 0, 163,
- 148, 149, 81, 150, 151, 152, 0, 82, 83, 84,
- 85, 86, 0, 0, 148, 149, 0, 150, 151, 152,
- 0, 0, 0, 0, 0, 233, 0, 0, 265, 0,
- 87, 154, 0, 0, 0, 0, 0, 88, 155, 156,
- 157, 158, 159, 160, 161, 148, 149, 154, 150, 151,
+ 114, 89, 91, 169, 124, 230, 152, 171, 172, 100,
+ 165, 13, 14, 10, 215, 26, 117, 24, 34, 297,
+ 298, 189, 152, 104, 1, 105, 152, 225, 4, 226,
+ 116, 200, 25, 242, 244, 243, 226, 141, 260, 5,
+ 261, 295, 6, 296, 142, 7, 9, 8, 10, 17,
+ 144, 23, 28, 241, 29, 72, 30, 146, 147, 17,
+ 74, 73, 98, 99, 166, 103, 154, 231, 107, 108,
+ 31, 206, 220, 221, 15, 32, 33, 34, 160, 161,
+ 101, 35, 154, 109, 110, 111, 154, 36, 246, 179,
+ 37, 112, 38, 115, 118, 39, 158, 159, 160, 161,
+ 119, 122, 34, 123, 126, 40, 41, 42, 127, 150,
+ 151, 152, 128, 143, 43, 44, 129, 45, 184, 185,
+ 186, 187, 188, 130, 145, 191, 192, 193, 194, 195,
+ 196, 197, 198, 131, 276, 253, 30, 132, 207, 280,
+ 133, 114, 134, 46, 162, 135, 136, 198, 137, 113,
+ 31, 167, 114, 232, 138, 32, 33, 34, 164, 139,
+ 140, 35, 168, 173, 170, 175, 275, 36, 176, 177,
+ 37, 154, 38, 181, 180, 39, 182, 190, 155, 156,
+ 157, 158, 159, 160, 161, 40, 41, 42, 30, 201,
+ 202, 247, 208, 211, 43, 44, 250, 45, 114, 212,
+ 179, 227, 31, 256, 257, 213, 219, 32, 33, 34,
+ 216, 228, 229, 35, 234, 236, 235, 239, 240, 36,
+ 245, 221, 37, 46, 38, 249, 251, 39, 114, 252,
+ 262, 30, 114, 263, 254, 264, 265, 40, 41, 42,
+ 267, 268, 272, 269, 287, 31, 43, 44, 277, 45,
+ 32, 33, 34, 281, 278, 282, 35, 284, 285, 288,
+ 286, 289, 36, 290, 292, 37, 293, 38, 294, 300,
+ 39, 218, 204, 258, 30, 46, 259, 125, 18, 27,
+ 40, 41, 42, 248, 0, 0, 0, 274, 31, 43,
+ 44, 0, 45, 32, 33, 34, 0, 0, 0, 35,
+ 0, 0, 0, 0, 0, 36, 0, 0, 37, 0,
+ 38, 0, 0, 39, 0, 0, 0, 0, 46, 0,
+ 0, 0, 0, 40, 41, 42, 0, 75, 76, 77,
+ 78, 79, 43, 44, 80, 45, 0, 75, 76, 77,
+ 78, 79, 0, 0, 80, 0, 0, 0, 0, 0,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0,
+ 0, 46, 0, 148, 149, 0, 150, 151, 152, 0,
+ 0, 0, 0, 75, 76, 77, 78, 79, 178, 81,
+ 80, 0, 0, 0, 82, 83, 84, 85, 86, 81,
+ 0, 0, 0, 0, 82, 83, 84, 85, 86, 92,
+ 0, 0, 0, 0, 0, 0, 0, 87, 0, 93,
+ 0, 0, 0, 0, 88, 0, 0, 87, 0, 75,
+ 76, 77, 78, 79, 88, 81, 80, 0, 154, 0,
+ 82, 83, 84, 85, 86, 155, 156, 157, 158, 159,
+ 160, 161, 0, 0, 148, 149, 183, 150, 151, 152,
+ 0, 0, 0, 87, 0, 0, 0, 0, 153, 0,
+ 88, 0, 0, 0, 148, 149, 0, 150, 151, 152,
+ 0, 81, 0, 0, 0, 0, 82, 83, 84, 85,
+ 86, 163, 148, 149, 0, 150, 151, 152, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 148, 149, 87,
+ 150, 151, 152, 0, 0, 0, 88, 233, 0, 154,
+ 0, 266, 0, 0, 0, 0, 155, 156, 157, 158,
+ 159, 160, 161, 0, 0, 0, 0, 148, 149, 154,
+ 150, 151, 152, 0, 0, 0, 155, 156, 157, 158,
+ 159, 160, 161, 0, 271, 148, 149, 154, 150, 151,
152, 0, 0, 0, 155, 156, 157, 158, 159, 160,
- 161, 0, 270, 0, 0, 154, 0, 0, 0, 0,
- 0, 0, 155, 156, 157, 158, 159, 160, 161, 154,
- 0, 0, 0, 0, 0, 0, 155, 156, 157, 158,
- 159, 160, 161, 0, 0, 0, 0, 0, 0, 0,
+ 161, 0, 154, 0, 0, 0, 0, 0, 0, 155,
+ 156, 157, 158, 159, 160, 161, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 154, 0, 0, 0, 0, 0, 0, 155,
+ 156, 157, 158, 159, 160, 161, 0, 0, 0, 0,
154, 0, 0, 0, 0, 0, 0, 155, 156, 157,
158, 159, 160, 161
};
static const yytype_int16 yycheck[] =
{
- 48, 31, 32, 99, 56, 13, 7, 103, 104, 8,
- 9, 51, 11, 12, 13, 39, 7, 7, 31, 14,
- 47, 19, 49, 8, 9, 153, 11, 12, 13, 36,
- 37, 21, 72, 23, 24, 163, 26, 27, 28, 16,
- 17, 7, 32, 13, 74, 54, 0, 28, 38, 90,
- 80, 41, 91, 43, 93, 53, 46, 87, 88, 40,
- 69, 89, 53, 18, 7, 73, 56, 57, 58, 93,
- 91, 167, 93, 13, 73, 65, 66, 78, 68, 91,
- 93, 80, 81, 82, 83, 84, 85, 86, 73, 119,
- 7, 91, 220, 93, 7, 80, 81, 82, 83, 84,
- 85, 86, 79, 73, 94, 91, 91, 93, 91, 89,
- 93, 18, 7, 83, 84, 85, 86, 89, 148, 149,
- 150, 151, 152, 52, 39, 155, 156, 157, 158, 159,
- 160, 161, 162, 73, 30, 231, 7, 265, 168, 7,
- 7, 189, 270, 67, 67, 85, 86, 177, 7, 31,
- 89, 89, 200, 205, 89, 89, 7, 89, 89, 89,
- 30, 89, 89, 89, 89, 261, 28, 89, 89, 20,
- 21, 89, 15, 89, 88, 26, 27, 28, 89, 89,
- 89, 32, 90, 89, 88, 90, 42, 38, 90, 50,
- 41, 221, 43, 39, 59, 46, 226, 245, 90, 7,
- 230, 89, 59, 233, 234, 56, 57, 58, 5, 85,
- 90, 7, 20, 21, 65, 66, 7, 68, 26, 27,
- 28, 48, 7, 92, 32, 45, 80, 275, 91, 93,
- 38, 279, 7, 41, 7, 43, 7, 24, 46, 20,
- 93, 90, 7, 94, 7, 25, 32, 51, 56, 57,
- 58, 91, 21, 95, 92, 20, 21, 65, 66, 41,
- 68, 26, 27, 28, 70, 90, 15, 32, 34, 3,
- 10, 90, 71, 38, 35, 91, 41, 6, 43, 7,
- 72, 46, 7, 25, 7, 7, 94, 177, 175, 166,
- 235, 56, 57, 58, 56, 260, 11, 12, 13, 21,
- 65, 66, 12, 68, 26, 27, 28, -1, 22, -1,
- 32, 223, -1, -1, -1, -1, 38, 236, -1, 41,
- -1, 43, -1, -1, 46, -1, -1, -1, -1, 94,
- -1, -1, -1, -1, 56, 57, 58, -1, 3, 4,
- 5, 6, 7, 65, 66, 10, 68, -1, 3, 4,
- 5, 6, 7, -1, -1, 10, -1, -1, 73, -1,
- -1, -1, -1, -1, 29, 80, 81, 82, 83, 84,
- 85, 86, 94, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3, 4, 5, 6, 7, 44,
- 55, 10, -1, -1, -1, 60, 61, 62, 63, 64,
- 55, -1, -1, -1, -1, 60, 61, 62, 63, 64,
- 29, -1, -1, -1, -1, -1, -1, -1, 83, -1,
- 85, -1, -1, -1, -1, 90, -1, -1, 83, -1,
- 3, 4, 5, 6, 7, 90, 55, 10, -1, -1,
- -1, 60, 61, 62, 63, 64, 8, 9, -1, 11,
- 12, 13, -1, -1, -1, -1, -1, -1, -1, -1,
- 22, -1, 8, 9, 83, 11, 12, 13, -1, -1,
- -1, 90, -1, -1, -1, -1, -1, -1, -1, 25,
- 8, 9, 55, 11, 12, 13, -1, 60, 61, 62,
- 63, 64, -1, -1, 8, 9, -1, 11, 12, 13,
- -1, -1, -1, -1, -1, 33, -1, -1, 22, -1,
- 83, 73, -1, -1, -1, -1, -1, 90, 80, 81,
- 82, 83, 84, 85, 86, 8, 9, 73, 11, 12,
+ 48, 31, 32, 99, 56, 31, 13, 103, 104, 7,
+ 39, 16, 17, 7, 175, 19, 51, 54, 28, 36,
+ 37, 153, 13, 47, 14, 49, 13, 91, 7, 93,
+ 40, 163, 69, 91, 91, 93, 93, 72, 91, 0,
+ 93, 91, 89, 93, 74, 90, 18, 91, 7, 53,
+ 80, 89, 7, 214, 7, 18, 7, 87, 88, 53,
+ 52, 89, 7, 39, 93, 30, 73, 93, 7, 7,
+ 21, 167, 23, 24, 79, 26, 27, 28, 85, 86,
+ 78, 32, 73, 7, 67, 67, 73, 38, 220, 119,
+ 41, 7, 43, 89, 89, 46, 83, 84, 85, 86,
+ 31, 89, 28, 89, 89, 56, 57, 58, 89, 11,
+ 12, 13, 89, 88, 65, 66, 89, 68, 148, 149,
+ 150, 151, 152, 89, 88, 155, 156, 157, 158, 159,
+ 160, 161, 162, 89, 266, 231, 7, 89, 168, 271,
+ 89, 189, 89, 94, 90, 89, 89, 177, 89, 20,
+ 21, 30, 200, 205, 89, 26, 27, 28, 90, 89,
+ 89, 32, 15, 50, 42, 39, 262, 38, 90, 90,
+ 41, 73, 43, 59, 89, 46, 59, 5, 80, 81,
+ 82, 83, 84, 85, 86, 56, 57, 58, 7, 85,
+ 7, 221, 7, 90, 65, 66, 226, 68, 246, 48,
+ 230, 20, 21, 233, 234, 7, 45, 26, 27, 28,
+ 92, 91, 93, 32, 80, 7, 93, 7, 90, 38,
+ 7, 24, 41, 94, 43, 20, 25, 46, 276, 7,
+ 51, 7, 280, 91, 32, 95, 92, 56, 57, 58,
+ 21, 41, 90, 70, 20, 21, 65, 66, 15, 68,
+ 26, 27, 28, 3, 34, 10, 32, 90, 71, 91,
+ 35, 6, 38, 7, 72, 41, 7, 43, 25, 7,
+ 46, 177, 166, 235, 7, 94, 236, 56, 12, 22,
+ 56, 57, 58, 223, -1, -1, -1, 261, 21, 65,
+ 66, -1, 68, 26, 27, 28, -1, -1, -1, 32,
+ -1, -1, -1, -1, -1, 38, -1, -1, 41, -1,
+ 43, -1, -1, 46, -1, -1, -1, -1, 94, -1,
+ -1, -1, -1, 56, 57, 58, -1, 3, 4, 5,
+ 6, 7, 65, 66, 10, 68, -1, 3, 4, 5,
+ 6, 7, -1, -1, 10, -1, -1, -1, -1, -1,
+ -1, -1, -1, 29, -1, -1, -1, -1, -1, -1,
+ -1, 94, -1, 8, 9, -1, 11, 12, 13, -1,
+ -1, -1, -1, 3, 4, 5, 6, 7, 44, 55,
+ 10, -1, -1, -1, 60, 61, 62, 63, 64, 55,
+ -1, -1, -1, -1, 60, 61, 62, 63, 64, 29,
+ -1, -1, -1, -1, -1, -1, -1, 83, -1, 85,
+ -1, -1, -1, -1, 90, -1, -1, 83, -1, 3,
+ 4, 5, 6, 7, 90, 55, 10, -1, 73, -1,
+ 60, 61, 62, 63, 64, 80, 81, 82, 83, 84,
+ 85, 86, -1, -1, 8, 9, 91, 11, 12, 13,
+ -1, -1, -1, 83, -1, -1, -1, -1, 22, -1,
+ 90, -1, -1, -1, 8, 9, -1, 11, 12, 13,
+ -1, 55, -1, -1, -1, -1, 60, 61, 62, 63,
+ 64, 25, 8, 9, -1, 11, 12, 13, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 8, 9, 83,
+ 11, 12, 13, -1, -1, -1, 90, 33, -1, 73,
+ -1, 22, -1, -1, -1, -1, 80, 81, 82, 83,
+ 84, 85, 86, -1, -1, -1, -1, 8, 9, 73,
+ 11, 12, 13, -1, -1, -1, 80, 81, 82, 83,
+ 84, 85, 86, -1, 25, 8, 9, 73, 11, 12,
13, -1, -1, -1, 80, 81, 82, 83, 84, 85,
- 86, -1, 25, -1, -1, 73, -1, -1, -1, -1,
- -1, -1, 80, 81, 82, 83, 84, 85, 86, 73,
- -1, -1, -1, -1, -1, -1, 80, 81, 82, 83,
- 84, 85, 86, -1, -1, -1, -1, -1, -1, -1,
+ 86, -1, 73, -1, -1, -1, -1, -1, -1, 80,
+ 81, 82, 83, 84, 85, 86, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 73, -1, -1, -1, -1, -1, -1, 80,
+ 81, 82, 83, 84, 85, 86, -1, -1, -1, -1,
73, -1, -1, -1, -1, -1, -1, 80, 81, 82,
83, 84, 85, 86
};
@@ -876,12 +882,13 @@ static const yytype_uint8 yystos[] =
120, 90, 48, 7, 104, 106, 92, 102, 107, 45,
23, 24, 129, 130, 131, 91, 93, 20, 91, 93,
31, 93, 111, 33, 80, 93, 7, 140, 141, 7,
- 90, 91, 93, 91, 7, 99, 100, 129, 20, 100,
- 25, 7, 149, 32, 112, 100, 100, 119, 152, 91,
- 93, 51, 91, 95, 92, 22, 21, 41, 70, 113,
- 25, 90, 142, 140, 149, 99, 15, 34, 115, 99,
- 3, 10, 143, 90, 71, 35, 20, 91, 6, 7,
- 145, 72, 7, 25, 91, 93, 36, 37, 114, 7
+ 90, 106, 91, 93, 91, 7, 99, 100, 129, 20,
+ 100, 25, 7, 149, 32, 112, 100, 100, 119, 152,
+ 91, 93, 51, 91, 95, 92, 22, 21, 41, 70,
+ 113, 25, 90, 142, 140, 149, 99, 15, 34, 115,
+ 99, 3, 10, 143, 90, 71, 35, 20, 91, 6,
+ 7, 145, 72, 7, 25, 91, 93, 36, 37, 114,
+ 7
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
@@ -919,7 +926,7 @@ static const yytype_uint8 yyr2[] =
0, 4, 0, 1, 1, 0, 4, 8, 3, 5,
2, 3, 1, 3, 4, 4, 2, 2, 3, 2,
2, 3, 4, 1, 2, 0, 2, 1, 7, 6,
- 10, 1, 1, 2, 2, 4, 4, 4, 1, 3,
+ 10, 1, 1, 2, 2, 4, 5, 4, 1, 3,
0, 3, 0, 2, 6, 1, 3, 0, 1, 0,
1, 10, 1, 1, 2, 2, 1, 1, 1, 3,
0, 1, 2, 6, 4, 1, 1, 0, 1, 2,
@@ -1009,9 +1016,7 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep)
if (yytype < YYNTOKENS)
YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
# endif
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
YYUSE (yytype);
- YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -1612,260 +1617,260 @@ yyreduce:
case 23:
#line 166 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); }
-#line 1616 "pars0grm.cc"
+#line 1621 "pars0grm.cc"
break;
case 24:
#line 168 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-1], yyvsp[0]); }
-#line 1622 "pars0grm.cc"
+#line 1627 "pars0grm.cc"
break;
case 25:
#line 172 "pars0grm.y"
{ yyval = yyvsp[0];}
-#line 1628 "pars0grm.cc"
+#line 1633 "pars0grm.cc"
break;
case 26:
#line 174 "pars0grm.y"
{ yyval = pars_func(yyvsp[-3], yyvsp[-1]); }
-#line 1634 "pars0grm.cc"
+#line 1639 "pars0grm.cc"
break;
case 27:
#line 175 "pars0grm.y"
{ yyval = yyvsp[0];}
-#line 1640 "pars0grm.cc"
+#line 1645 "pars0grm.cc"
break;
case 28:
#line 176 "pars0grm.y"
{ yyval = yyvsp[0];}
-#line 1646 "pars0grm.cc"
+#line 1651 "pars0grm.cc"
break;
case 29:
#line 177 "pars0grm.y"
{ yyval = yyvsp[0];}
-#line 1652 "pars0grm.cc"
+#line 1657 "pars0grm.cc"
break;
case 30:
#line 178 "pars0grm.y"
{ yyval = yyvsp[0];}
-#line 1658 "pars0grm.cc"
+#line 1663 "pars0grm.cc"
break;
case 31:
#line 179 "pars0grm.y"
{ yyval = yyvsp[0];}
-#line 1664 "pars0grm.cc"
+#line 1669 "pars0grm.cc"
break;
case 32:
#line 180 "pars0grm.y"
{ yyval = pars_op('+', yyvsp[-2], yyvsp[0]); }
-#line 1670 "pars0grm.cc"
+#line 1675 "pars0grm.cc"
break;
case 33:
#line 181 "pars0grm.y"
{ yyval = pars_op('-', yyvsp[-2], yyvsp[0]); }
-#line 1676 "pars0grm.cc"
+#line 1681 "pars0grm.cc"
break;
case 34:
#line 182 "pars0grm.y"
{ yyval = pars_op('*', yyvsp[-2], yyvsp[0]); }
-#line 1682 "pars0grm.cc"
+#line 1687 "pars0grm.cc"
break;
case 35:
#line 183 "pars0grm.y"
{ yyval = pars_op('/', yyvsp[-2], yyvsp[0]); }
-#line 1688 "pars0grm.cc"
+#line 1693 "pars0grm.cc"
break;
case 36:
#line 184 "pars0grm.y"
{ yyval = pars_op('-', yyvsp[0], NULL); }
-#line 1694 "pars0grm.cc"
+#line 1699 "pars0grm.cc"
break;
case 37:
#line 185 "pars0grm.y"
{ yyval = yyvsp[-1]; }
-#line 1700 "pars0grm.cc"
+#line 1705 "pars0grm.cc"
break;
case 38:
#line 186 "pars0grm.y"
{ yyval = pars_op('=', yyvsp[-2], yyvsp[0]); }
-#line 1706 "pars0grm.cc"
+#line 1711 "pars0grm.cc"
break;
case 39:
#line 188 "pars0grm.y"
{ yyval = pars_op(PARS_LIKE_TOKEN, yyvsp[-2], yyvsp[0]); }
-#line 1712 "pars0grm.cc"
+#line 1717 "pars0grm.cc"
break;
case 40:
#line 189 "pars0grm.y"
{ yyval = pars_op('<', yyvsp[-2], yyvsp[0]); }
-#line 1718 "pars0grm.cc"
+#line 1723 "pars0grm.cc"
break;
case 41:
#line 190 "pars0grm.y"
{ yyval = pars_op('>', yyvsp[-2], yyvsp[0]); }
-#line 1724 "pars0grm.cc"
+#line 1729 "pars0grm.cc"
break;
case 42:
#line 191 "pars0grm.y"
{ yyval = pars_op(PARS_GE_TOKEN, yyvsp[-2], yyvsp[0]); }
-#line 1730 "pars0grm.cc"
+#line 1735 "pars0grm.cc"
break;
case 43:
#line 192 "pars0grm.y"
{ yyval = pars_op(PARS_LE_TOKEN, yyvsp[-2], yyvsp[0]); }
-#line 1736 "pars0grm.cc"
+#line 1741 "pars0grm.cc"
break;
case 44:
#line 193 "pars0grm.y"
{ yyval = pars_op(PARS_NE_TOKEN, yyvsp[-2], yyvsp[0]); }
-#line 1742 "pars0grm.cc"
+#line 1747 "pars0grm.cc"
break;
case 45:
#line 194 "pars0grm.y"
{ yyval = pars_op(PARS_AND_TOKEN, yyvsp[-2], yyvsp[0]); }
-#line 1748 "pars0grm.cc"
+#line 1753 "pars0grm.cc"
break;
case 46:
#line 195 "pars0grm.y"
{ yyval = pars_op(PARS_OR_TOKEN, yyvsp[-2], yyvsp[0]); }
-#line 1754 "pars0grm.cc"
+#line 1759 "pars0grm.cc"
break;
case 47:
#line 196 "pars0grm.y"
{ yyval = pars_op(PARS_NOT_TOKEN, yyvsp[0], NULL); }
-#line 1760 "pars0grm.cc"
+#line 1765 "pars0grm.cc"
break;
case 48:
#line 198 "pars0grm.y"
{ yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); }
-#line 1766 "pars0grm.cc"
+#line 1771 "pars0grm.cc"
break;
case 49:
#line 200 "pars0grm.y"
{ yyval = pars_op(PARS_NOTFOUND_TOKEN, yyvsp[-2], NULL); }
-#line 1772 "pars0grm.cc"
+#line 1777 "pars0grm.cc"
break;
case 50:
#line 204 "pars0grm.y"
{ yyval = &pars_to_binary_token; }
-#line 1778 "pars0grm.cc"
+#line 1783 "pars0grm.cc"
break;
case 51:
#line 205 "pars0grm.y"
{ yyval = &pars_substr_token; }
-#line 1784 "pars0grm.cc"
+#line 1789 "pars0grm.cc"
break;
case 52:
#line 206 "pars0grm.y"
{ yyval = &pars_concat_token; }
-#line 1790 "pars0grm.cc"
+#line 1795 "pars0grm.cc"
break;
case 53:
#line 207 "pars0grm.y"
{ yyval = &pars_instr_token; }
-#line 1796 "pars0grm.cc"
+#line 1801 "pars0grm.cc"
break;
case 54:
#line 208 "pars0grm.y"
{ yyval = &pars_length_token; }
-#line 1802 "pars0grm.cc"
+#line 1807 "pars0grm.cc"
break;
case 58:
#line 219 "pars0grm.y"
{ yyval = pars_stored_procedure_call(
static_cast<sym_node_t*>(yyvsp[-4])); }
-#line 1809 "pars0grm.cc"
+#line 1814 "pars0grm.cc"
break;
case 59:
#line 224 "pars0grm.y"
{ yyval = yyvsp[-2]; }
-#line 1815 "pars0grm.cc"
+#line 1820 "pars0grm.cc"
break;
case 60:
#line 228 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); }
-#line 1821 "pars0grm.cc"
+#line 1826 "pars0grm.cc"
break;
case 61:
#line 230 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); }
-#line 1827 "pars0grm.cc"
+#line 1832 "pars0grm.cc"
break;
case 62:
#line 234 "pars0grm.y"
{ yyval = NULL; }
-#line 1833 "pars0grm.cc"
+#line 1838 "pars0grm.cc"
break;
case 63:
#line 235 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); }
-#line 1839 "pars0grm.cc"
+#line 1844 "pars0grm.cc"
break;
case 64:
#line 237 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); }
-#line 1845 "pars0grm.cc"
+#line 1850 "pars0grm.cc"
break;
case 65:
#line 241 "pars0grm.y"
{ yyval = NULL; }
-#line 1851 "pars0grm.cc"
+#line 1856 "pars0grm.cc"
break;
case 66:
#line 242 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]);}
-#line 1857 "pars0grm.cc"
+#line 1862 "pars0grm.cc"
break;
case 67:
#line 243 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); }
-#line 1863 "pars0grm.cc"
+#line 1868 "pars0grm.cc"
break;
case 68:
#line 247 "pars0grm.y"
{ yyval = yyvsp[0]; }
-#line 1869 "pars0grm.cc"
+#line 1874 "pars0grm.cc"
break;
case 69:
@@ -1874,105 +1879,105 @@ yyreduce:
que_node_list_add_last(NULL,
sym_tab_add_int_lit(
pars_sym_tab_global, 1))); }
-#line 1878 "pars0grm.cc"
+#line 1883 "pars0grm.cc"
break;
case 70:
#line 256 "pars0grm.y"
{ yyval = NULL; }
-#line 1884 "pars0grm.cc"
+#line 1889 "pars0grm.cc"
break;
case 71:
#line 257 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); }
-#line 1890 "pars0grm.cc"
+#line 1895 "pars0grm.cc"
break;
case 72:
#line 259 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); }
-#line 1896 "pars0grm.cc"
+#line 1901 "pars0grm.cc"
break;
case 73:
#line 263 "pars0grm.y"
{ yyval = pars_select_list(&pars_star_denoter,
NULL); }
-#line 1903 "pars0grm.cc"
+#line 1908 "pars0grm.cc"
break;
case 74:
#line 266 "pars0grm.y"
{ yyval = pars_select_list(
yyvsp[-2], static_cast<sym_node_t*>(yyvsp[0])); }
-#line 1910 "pars0grm.cc"
+#line 1915 "pars0grm.cc"
break;
case 75:
#line 268 "pars0grm.y"
{ yyval = pars_select_list(yyvsp[0], NULL); }
-#line 1916 "pars0grm.cc"
+#line 1921 "pars0grm.cc"
break;
case 76:
#line 272 "pars0grm.y"
{ yyval = NULL; }
-#line 1922 "pars0grm.cc"
+#line 1927 "pars0grm.cc"
break;
case 77:
#line 273 "pars0grm.y"
{ yyval = yyvsp[0]; }
-#line 1928 "pars0grm.cc"
+#line 1933 "pars0grm.cc"
break;
case 78:
#line 277 "pars0grm.y"
{ yyval = NULL; }
-#line 1934 "pars0grm.cc"
+#line 1939 "pars0grm.cc"
break;
case 79:
#line 279 "pars0grm.y"
{ yyval = &pars_update_token; }
-#line 1940 "pars0grm.cc"
+#line 1945 "pars0grm.cc"
break;
case 80:
#line 283 "pars0grm.y"
{ yyval = NULL; }
-#line 1946 "pars0grm.cc"
+#line 1951 "pars0grm.cc"
break;
case 81:
#line 285 "pars0grm.y"
{ yyval = &pars_share_token; }
-#line 1952 "pars0grm.cc"
+#line 1957 "pars0grm.cc"
break;
case 82:
#line 289 "pars0grm.y"
{ yyval = &pars_asc_token; }
-#line 1958 "pars0grm.cc"
+#line 1963 "pars0grm.cc"
break;
case 83:
#line 290 "pars0grm.y"
{ yyval = &pars_asc_token; }
-#line 1964 "pars0grm.cc"
+#line 1969 "pars0grm.cc"
break;
case 84:
#line 291 "pars0grm.y"
{ yyval = &pars_desc_token; }
-#line 1970 "pars0grm.cc"
+#line 1975 "pars0grm.cc"
break;
case 85:
#line 295 "pars0grm.y"
{ yyval = NULL; }
-#line 1976 "pars0grm.cc"
+#line 1981 "pars0grm.cc"
break;
case 86:
@@ -1980,7 +1985,7 @@ yyreduce:
{ yyval = pars_order_by(
static_cast<sym_node_t*>(yyvsp[-1]),
static_cast<pars_res_word_t*>(yyvsp[0])); }
-#line 1984 "pars0grm.cc"
+#line 1989 "pars0grm.cc"
break;
case 87:
@@ -1992,395 +1997,397 @@ yyreduce:
static_cast<pars_res_word_t*>(yyvsp[-2]),
static_cast<pars_res_word_t*>(yyvsp[-1]),
static_cast<order_node_t*>(yyvsp[0])); }
-#line 1996 "pars0grm.cc"
+#line 2001 "pars0grm.cc"
break;
case 88:
#line 319 "pars0grm.y"
{ yyval = yyvsp[0]; }
-#line 2002 "pars0grm.cc"
+#line 2007 "pars0grm.cc"
break;
case 89:
#line 324 "pars0grm.y"
- { yyval = pars_insert_statement(
- static_cast<sym_node_t*>(yyvsp[-4]), yyvsp[-1], NULL); }
-#line 2009 "pars0grm.cc"
+ { if (!(yyval = pars_insert_statement(
+ static_cast<sym_node_t*>(yyvsp[-4]), yyvsp[-1], NULL)))
+ YYABORT; }
+#line 2015 "pars0grm.cc"
break;
case 90:
-#line 327 "pars0grm.y"
- { yyval = pars_insert_statement(
+#line 328 "pars0grm.y"
+ { if (!(yyval = pars_insert_statement(
static_cast<sym_node_t*>(yyvsp[-1]),
NULL,
- static_cast<sel_node_t*>(yyvsp[0])); }
-#line 2018 "pars0grm.cc"
+ static_cast<sel_node_t*>(yyvsp[0]))))
+ YYABORT; }
+#line 2025 "pars0grm.cc"
break;
case 91:
-#line 334 "pars0grm.y"
+#line 336 "pars0grm.y"
{ yyval = pars_column_assignment(
static_cast<sym_node_t*>(yyvsp[-2]),
static_cast<que_node_t*>(yyvsp[0])); }
-#line 2026 "pars0grm.cc"
+#line 2033 "pars0grm.cc"
break;
case 92:
-#line 340 "pars0grm.y"
+#line 342 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); }
-#line 2032 "pars0grm.cc"
+#line 2039 "pars0grm.cc"
break;
case 93:
-#line 342 "pars0grm.y"
+#line 344 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); }
-#line 2038 "pars0grm.cc"
+#line 2045 "pars0grm.cc"
break;
case 94:
-#line 348 "pars0grm.y"
+#line 350 "pars0grm.y"
{ yyval = yyvsp[0]; }
-#line 2044 "pars0grm.cc"
+#line 2051 "pars0grm.cc"
break;
case 95:
-#line 354 "pars0grm.y"
+#line 356 "pars0grm.y"
{ yyval = pars_update_statement_start(
FALSE,
static_cast<sym_node_t*>(yyvsp[-2]),
static_cast<col_assign_node_t*>(yyvsp[0])); }
-#line 2053 "pars0grm.cc"
+#line 2060 "pars0grm.cc"
break;
case 96:
-#line 362 "pars0grm.y"
+#line 364 "pars0grm.y"
{ yyval = pars_update_statement(
static_cast<upd_node_t*>(yyvsp[-1]),
NULL,
static_cast<que_node_t*>(yyvsp[0])); }
-#line 2062 "pars0grm.cc"
+#line 2069 "pars0grm.cc"
break;
case 97:
-#line 370 "pars0grm.y"
+#line 372 "pars0grm.y"
{ yyval = pars_update_statement(
static_cast<upd_node_t*>(yyvsp[-1]),
static_cast<sym_node_t*>(yyvsp[0]),
NULL); }
-#line 2071 "pars0grm.cc"
+#line 2078 "pars0grm.cc"
break;
case 98:
-#line 378 "pars0grm.y"
+#line 380 "pars0grm.y"
{ yyval = pars_update_statement_start(
TRUE,
static_cast<sym_node_t*>(yyvsp[0]), NULL); }
-#line 2079 "pars0grm.cc"
+#line 2086 "pars0grm.cc"
break;
case 99:
-#line 385 "pars0grm.y"
+#line 387 "pars0grm.y"
{ yyval = pars_update_statement(
static_cast<upd_node_t*>(yyvsp[-1]),
NULL,
static_cast<que_node_t*>(yyvsp[0])); }
-#line 2088 "pars0grm.cc"
+#line 2095 "pars0grm.cc"
break;
case 100:
-#line 393 "pars0grm.y"
+#line 395 "pars0grm.y"
{ yyval = pars_update_statement(
static_cast<upd_node_t*>(yyvsp[-1]),
static_cast<sym_node_t*>(yyvsp[0]),
NULL); }
-#line 2097 "pars0grm.cc"
+#line 2104 "pars0grm.cc"
break;
case 101:
-#line 401 "pars0grm.y"
+#line 403 "pars0grm.y"
{ yyval = pars_assignment_statement(
static_cast<sym_node_t*>(yyvsp[-2]),
static_cast<que_node_t*>(yyvsp[0])); }
-#line 2105 "pars0grm.cc"
+#line 2112 "pars0grm.cc"
break;
case 102:
-#line 409 "pars0grm.y"
+#line 411 "pars0grm.y"
{ yyval = pars_elsif_element(yyvsp[-2], yyvsp[0]); }
-#line 2111 "pars0grm.cc"
+#line 2118 "pars0grm.cc"
break;
case 103:
-#line 413 "pars0grm.y"
+#line 415 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); }
-#line 2117 "pars0grm.cc"
+#line 2124 "pars0grm.cc"
break;
case 104:
-#line 415 "pars0grm.y"
+#line 417 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-1], yyvsp[0]); }
-#line 2123 "pars0grm.cc"
+#line 2130 "pars0grm.cc"
break;
case 105:
-#line 419 "pars0grm.y"
+#line 421 "pars0grm.y"
{ yyval = NULL; }
-#line 2129 "pars0grm.cc"
+#line 2136 "pars0grm.cc"
break;
case 106:
-#line 421 "pars0grm.y"
+#line 423 "pars0grm.y"
{ yyval = yyvsp[0]; }
-#line 2135 "pars0grm.cc"
+#line 2142 "pars0grm.cc"
break;
case 107:
-#line 422 "pars0grm.y"
+#line 424 "pars0grm.y"
{ yyval = yyvsp[0]; }
-#line 2141 "pars0grm.cc"
+#line 2148 "pars0grm.cc"
break;
case 108:
-#line 429 "pars0grm.y"
+#line 431 "pars0grm.y"
{ yyval = pars_if_statement(yyvsp[-5], yyvsp[-3], yyvsp[-2]); }
-#line 2147 "pars0grm.cc"
+#line 2154 "pars0grm.cc"
break;
case 109:
-#line 435 "pars0grm.y"
+#line 437 "pars0grm.y"
{ yyval = pars_while_statement(yyvsp[-4], yyvsp[-2]); }
-#line 2153 "pars0grm.cc"
+#line 2160 "pars0grm.cc"
break;
case 110:
-#line 443 "pars0grm.y"
+#line 445 "pars0grm.y"
{ yyval = pars_for_statement(
static_cast<sym_node_t*>(yyvsp[-8]),
yyvsp[-6], yyvsp[-4], yyvsp[-2]); }
-#line 2161 "pars0grm.cc"
+#line 2168 "pars0grm.cc"
break;
case 111:
-#line 449 "pars0grm.y"
+#line 451 "pars0grm.y"
{ yyval = pars_exit_statement(); }
-#line 2167 "pars0grm.cc"
+#line 2174 "pars0grm.cc"
break;
case 112:
-#line 453 "pars0grm.y"
+#line 455 "pars0grm.y"
{ yyval = pars_return_statement(); }
-#line 2173 "pars0grm.cc"
+#line 2180 "pars0grm.cc"
break;
case 113:
-#line 458 "pars0grm.y"
+#line 460 "pars0grm.y"
{ yyval = pars_open_statement(
ROW_SEL_OPEN_CURSOR,
static_cast<sym_node_t*>(yyvsp[0])); }
-#line 2181 "pars0grm.cc"
+#line 2188 "pars0grm.cc"
break;
case 114:
-#line 465 "pars0grm.y"
+#line 467 "pars0grm.y"
{ yyval = pars_open_statement(
ROW_SEL_CLOSE_CURSOR,
static_cast<sym_node_t*>(yyvsp[0])); }
-#line 2189 "pars0grm.cc"
+#line 2196 "pars0grm.cc"
break;
case 115:
-#line 472 "pars0grm.y"
+#line 474 "pars0grm.y"
{ yyval = pars_fetch_statement(
static_cast<sym_node_t*>(yyvsp[-2]),
static_cast<sym_node_t*>(yyvsp[0]), NULL); }
-#line 2197 "pars0grm.cc"
+#line 2204 "pars0grm.cc"
break;
case 116:
-#line 476 "pars0grm.y"
+#line 478 "pars0grm.y"
{ yyval = pars_fetch_statement(
- static_cast<sym_node_t*>(yyvsp[-2]),
- NULL,
- static_cast<sym_node_t*>(yyvsp[0])); }
-#line 2206 "pars0grm.cc"
+ static_cast<sym_node_t*>(yyvsp[-3]),
+ static_cast<sym_node_t*>(yyvsp[0]),
+ static_cast<sym_node_t*>(yyvsp[-1])); }
+#line 2213 "pars0grm.cc"
break;
case 117:
-#line 484 "pars0grm.y"
+#line 486 "pars0grm.y"
{ yyval = pars_column_def(
static_cast<sym_node_t*>(yyvsp[-3]),
static_cast<pars_res_word_t*>(yyvsp[-2]),
static_cast<sym_node_t*>(yyvsp[-1]),
yyvsp[0]); }
-#line 2216 "pars0grm.cc"
+#line 2223 "pars0grm.cc"
break;
case 118:
-#line 492 "pars0grm.y"
+#line 494 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); }
-#line 2222 "pars0grm.cc"
+#line 2229 "pars0grm.cc"
break;
case 119:
-#line 494 "pars0grm.y"
+#line 496 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); }
-#line 2228 "pars0grm.cc"
+#line 2235 "pars0grm.cc"
break;
case 120:
-#line 498 "pars0grm.y"
+#line 500 "pars0grm.y"
{ yyval = NULL; }
-#line 2234 "pars0grm.cc"
+#line 2241 "pars0grm.cc"
break;
case 121:
-#line 500 "pars0grm.y"
+#line 502 "pars0grm.y"
{ yyval = yyvsp[-1]; }
-#line 2240 "pars0grm.cc"
+#line 2247 "pars0grm.cc"
break;
case 122:
-#line 504 "pars0grm.y"
+#line 506 "pars0grm.y"
{ yyval = NULL; }
-#line 2246 "pars0grm.cc"
+#line 2253 "pars0grm.cc"
break;
case 123:
-#line 506 "pars0grm.y"
+#line 508 "pars0grm.y"
{ yyval = &pars_int_token;
/* pass any non-NULL pointer */ }
-#line 2253 "pars0grm.cc"
+#line 2260 "pars0grm.cc"
break;
case 124:
-#line 513 "pars0grm.y"
+#line 515 "pars0grm.y"
{ yyval = pars_create_table(
static_cast<sym_node_t*>(yyvsp[-3]),
static_cast<sym_node_t*>(yyvsp[-1])); }
-#line 2261 "pars0grm.cc"
+#line 2268 "pars0grm.cc"
break;
case 125:
-#line 519 "pars0grm.y"
+#line 521 "pars0grm.y"
{ yyval = que_node_list_add_last(NULL, yyvsp[0]); }
-#line 2267 "pars0grm.cc"
+#line 2274 "pars0grm.cc"
break;
case 126:
-#line 521 "pars0grm.y"
+#line 523 "pars0grm.y"
{ yyval = que_node_list_add_last(yyvsp[-2], yyvsp[0]); }
-#line 2273 "pars0grm.cc"
+#line 2280 "pars0grm.cc"
break;
case 127:
-#line 525 "pars0grm.y"
+#line 527 "pars0grm.y"
{ yyval = NULL; }
-#line 2279 "pars0grm.cc"
+#line 2286 "pars0grm.cc"
break;
case 128:
-#line 526 "pars0grm.y"
+#line 528 "pars0grm.y"
{ yyval = &pars_unique_token; }
-#line 2285 "pars0grm.cc"
+#line 2292 "pars0grm.cc"
break;
case 129:
-#line 530 "pars0grm.y"
+#line 532 "pars0grm.y"
{ yyval = NULL; }
-#line 2291 "pars0grm.cc"
+#line 2298 "pars0grm.cc"
break;
case 130:
-#line 531 "pars0grm.y"
+#line 533 "pars0grm.y"
{ yyval = &pars_clustered_token; }
-#line 2297 "pars0grm.cc"
+#line 2304 "pars0grm.cc"
break;
case 131:
-#line 540 "pars0grm.y"
+#line 542 "pars0grm.y"
{ yyval = pars_create_index(
static_cast<pars_res_word_t*>(yyvsp[-8]),
static_cast<pars_res_word_t*>(yyvsp[-7]),
static_cast<sym_node_t*>(yyvsp[-5]),
static_cast<sym_node_t*>(yyvsp[-3]),
static_cast<sym_node_t*>(yyvsp[-1])); }
-#line 2308 "pars0grm.cc"
+#line 2315 "pars0grm.cc"
break;
case 132:
-#line 549 "pars0grm.y"
+#line 551 "pars0grm.y"
{ yyval = yyvsp[0]; }
-#line 2314 "pars0grm.cc"
+#line 2321 "pars0grm.cc"
break;
case 133:
-#line 550 "pars0grm.y"
+#line 552 "pars0grm.y"
{ yyval = yyvsp[0]; }
-#line 2320 "pars0grm.cc"
+#line 2327 "pars0grm.cc"
break;
case 134:
-#line 555 "pars0grm.y"
+#line 557 "pars0grm.y"
{ yyval = pars_commit_statement(); }
-#line 2326 "pars0grm.cc"
+#line 2333 "pars0grm.cc"
break;
case 135:
-#line 560 "pars0grm.y"
+#line 562 "pars0grm.y"
{ yyval = pars_rollback_statement(); }
-#line 2332 "pars0grm.cc"
+#line 2339 "pars0grm.cc"
break;
case 136:
-#line 564 "pars0grm.y"
+#line 566 "pars0grm.y"
{ yyval = &pars_int_token; }
-#line 2338 "pars0grm.cc"
+#line 2345 "pars0grm.cc"
break;
case 137:
-#line 565 "pars0grm.y"
+#line 567 "pars0grm.y"
{ yyval = &pars_bigint_token; }
-#line 2344 "pars0grm.cc"
+#line 2351 "pars0grm.cc"
break;
case 138:
-#line 566 "pars0grm.y"
+#line 568 "pars0grm.y"
{ yyval = &pars_char_token; }
-#line 2350 "pars0grm.cc"
+#line 2357 "pars0grm.cc"
break;
case 139:
-#line 571 "pars0grm.y"
+#line 573 "pars0grm.y"
{ yyval = pars_variable_declaration(
static_cast<sym_node_t*>(yyvsp[-2]),
static_cast<pars_res_word_t*>(yyvsp[-1])); }
-#line 2358 "pars0grm.cc"
+#line 2365 "pars0grm.cc"
break;
case 143:
-#line 585 "pars0grm.y"
+#line 587 "pars0grm.y"
{ yyval = pars_cursor_declaration(
static_cast<sym_node_t*>(yyvsp[-3]),
static_cast<sel_node_t*>(yyvsp[-1])); }
-#line 2366 "pars0grm.cc"
+#line 2373 "pars0grm.cc"
break;
case 144:
-#line 592 "pars0grm.y"
+#line 594 "pars0grm.y"
{ yyval = pars_function_declaration(
static_cast<sym_node_t*>(yyvsp[-1])); }
-#line 2373 "pars0grm.cc"
+#line 2380 "pars0grm.cc"
break;
case 150:
-#line 614 "pars0grm.y"
+#line 616 "pars0grm.y"
{ yyval = pars_procedure_definition(
static_cast<sym_node_t*>(yyvsp[-8]), yyvsp[-1]); }
-#line 2380 "pars0grm.cc"
+#line 2387 "pars0grm.cc"
break;
-#line 2384 "pars0grm.cc"
+#line 2391 "pars0grm.cc"
default: break;
}
@@ -2612,5 +2619,5 @@ yyreturn:
#endif
return yyresult;
}
-#line 618 "pars0grm.y"
+#line 620 "pars0grm.y"
diff --git a/storage/innobase/pars/pars0grm.y b/storage/innobase/pars/pars0grm.y
index 625ed41bbd4..1d79ba34b52 100644
--- a/storage/innobase/pars/pars0grm.y
+++ b/storage/innobase/pars/pars0grm.y
@@ -321,13 +321,15 @@ insert_statement_start:
insert_statement:
insert_statement_start PARS_VALUES_TOKEN '(' exp_list ')'
- { $$ = pars_insert_statement(
- static_cast<sym_node_t*>($1), $4, NULL); }
+ { if (!($$ = pars_insert_statement(
+ static_cast<sym_node_t*>($1), $4, NULL)))
+ YYABORT; }
| insert_statement_start select_statement
- { $$ = pars_insert_statement(
+ { if (!($$ = pars_insert_statement(
static_cast<sym_node_t*>($1),
NULL,
- static_cast<sel_node_t*>($2)); }
+ static_cast<sel_node_t*>($2))))
+ YYABORT; }
;
column_assignment:
@@ -472,10 +474,10 @@ fetch_statement:
{ $$ = pars_fetch_statement(
static_cast<sym_node_t*>($2),
static_cast<sym_node_t*>($4), NULL); }
- | PARS_FETCH_TOKEN PARS_ID_TOKEN PARS_INTO_TOKEN user_function_call
+ | PARS_FETCH_TOKEN PARS_ID_TOKEN PARS_INTO_TOKEN user_function_call variable_list
{ $$ = pars_fetch_statement(
static_cast<sym_node_t*>($2),
- NULL,
+ static_cast<sym_node_t*>($5),
static_cast<sym_node_t*>($4)); }
;
diff --git a/storage/innobase/pars/pars0pars.cc b/storage/innobase/pars/pars0pars.cc
index 2f3791aeb5e..5e11e2c89e4 100644
--- a/storage/innobase/pars/pars0pars.cc
+++ b/storage/innobase/pars/pars0pars.cc
@@ -1296,6 +1296,14 @@ pars_insert_statement(
if (node->values_list) {
pars_resolve_exp_list_variables_and_types(NULL, values_list);
+#ifdef UNIV_DEBUG
+ if (!pars_sym_tab_global->info->fatal_syntax_err
+ && que_node_list_get_len(values_list)
+ != dict_table_get_n_user_cols(table_sym->table)) {
+
+ return NULL;
+ }
+#endif /* UNIV_DEBUG */
ut_a(que_node_list_get_len(values_list)
== dict_table_get_n_user_cols(table_sym->table));
}
@@ -1618,30 +1626,30 @@ pars_fetch_statement(
sym_node_t* cursor_decl;
fetch_node_t* node;
- /* Logical XOR. */
- ut_a(!into_list != !user_func);
+ ut_ad(into_list || user_func);
node = static_cast<fetch_node_t*>(
mem_heap_alloc(
pars_sym_tab_global->heap, sizeof(fetch_node_t)));
node->common.type = QUE_NODE_FETCH;
+ node->into_list = NULL;
+ node->func = NULL;
pars_resolve_exp_variables_and_types(NULL, cursor);
if (into_list) {
pars_resolve_exp_list_variables_and_types(NULL, into_list);
node->into_list = into_list;
- node->func = NULL;
- } else {
+ }
+
+ if (user_func) {
pars_resolve_exp_variables_and_types(NULL, user_func);
node->func = pars_info_lookup_user_func(
pars_sym_tab_global->info, user_func->name);
ut_a(node->func);
-
- node->into_list = NULL;
}
cursor_decl = cursor->alias;
@@ -1965,8 +1973,6 @@ yyerror(
/*!< in: error message string */
{
ut_ad(s);
-
- ib::fatal() << "PARSER: Syntax error in SQL string";
}
/*************************************************************//**
@@ -1997,7 +2003,17 @@ pars_sql(
pars_sym_tab_global->next_char_pos = 0;
pars_sym_tab_global->info = info;
- yyparse();
+ if (yyparse()) {
+#ifdef UNIV_DEBUG
+ if (info->fatal_syntax_err) {
+#endif /* UNIV_DEBUG */
+ ib::fatal() << "PARSER: Syntax error in SQL string";
+#ifdef UNIV_DEBUG
+ }
+ mem_heap_free(heap);
+ return NULL;
+#endif /* UNIV_DEBUG */
+ }
sym_node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list);
@@ -2066,13 +2082,24 @@ pars_info_create(void)
heap = mem_heap_create(512);
+ if (!heap) {
+ return NULL;
+ }
+
info = static_cast<pars_info_t*>(mem_heap_alloc(heap, sizeof(*info)));
+ if (!info) {
+ return NULL;
+ }
+
info->heap = heap;
info->funcs = NULL;
info->bound_lits = NULL;
info->bound_ids = NULL;
info->graph_owns_us = TRUE;
+#ifdef UNIV_DEBUG
+ info->fatal_syntax_err = true;
+#endif /* UNIV_DEBUG */
return(info);
}
diff --git a/storage/innobase/pars/pars0sym.cc b/storage/innobase/pars/pars0sym.cc
index 5e4c0e0f6e0..dc1f49ddb3b 100644
--- a/storage/innobase/pars/pars0sym.cc
+++ b/storage/innobase/pars/pars0sym.cc
@@ -207,6 +207,11 @@ sym_tab_add_bound_lit(
ulint len = 0;
blit = pars_info_get_bound_lit(sym_tab->info, name);
+#ifdef UNIV_DEBUG
+ if (!sym_tab->info->fatal_syntax_err && !blit) {
+ return NULL;
+ }
+#endif /* UNIV_DEBUG */
ut_a(blit);
node = static_cast<sym_node_t*>(
diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc
index 18fe7626d57..1e7ff847266 100644
--- a/storage/innobase/que/que0que.cc
+++ b/storage/innobase/que/que0que.cc
@@ -1116,6 +1116,14 @@ que_eval_sql(
mutex_exit(&dict_sys.mutex);
}
+#ifdef UNIV_DEBUG
+ if (!graph) {
+ trx->error_state = DB_ERROR;
+ DBUG_RETURN(trx->error_state);
+ }
+#endif /* UNIV_DEBUG */
+ ut_ad(graph);
+
graph->trx = trx;
trx->graph = NULL;
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 7251be09c5b..a1365a90dc4 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -3270,6 +3270,58 @@ row_drop_table_from_cache(
return(err);
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+static
+ibool
+row_drop_table_check_legacy_step(
+/*=================*/
+ void* row, /*!< in: sel_node_t* */
+ void* user_arg) /*!< in/out: row_drop_table_check_legacy_data */
+{
+ row_drop_table_check_legacy_data &d = *(row_drop_table_check_legacy_data *) user_arg;
+ sel_node_t* node = static_cast<sel_node_t*>(row);
+ que_node_t* exp = node->select_list;
+ dfield_t* fld = que_node_get_val(exp);
+ ut_a(fld->len < sizeof(d.foreign_name));
+ memcpy(d.foreign_name, fld->data, fld->len);
+ d.foreign_name[fld->len] = 0;
+ d.found = true;
+ ut_a(!que_node_get_next(exp));
+ return 0;
+}
+
+dberr_t row_drop_table_check_legacy_fk(trx_t* trx, const char * table_name, row_drop_table_check_legacy_data &d)
+{
+ static const char sql_check[] =
+ "PROCEDURE FK_PROC () IS\n"
+ "DECLARE FUNCTION row_drop_table_check_legacy_step;\n"
+
+ "DECLARE CURSOR c IS"
+ " SELECT FOR_NAME FROM SYS_FOREIGN"
+ " WHERE REF_NAME = :ref_name;\n"
+
+ "BEGIN\n"
+ "OPEN c;\n"
+ "FETCH c INTO row_drop_table_check_legacy_step();\n"
+ "CLOSE c;\n"
+ "END;\n";
+
+ pars_info_t* info = pars_info_create();
+ if (!info) {
+ return DB_OUT_OF_MEMORY;
+ }
+ pars_info_bind_function(info, "row_drop_table_check_legacy_step", row_drop_table_check_legacy_step, &d);
+ pars_info_add_str_literal(info, "ref_name", table_name);
+
+ dberr_t err = que_eval_sql(info, sql_check, false, trx);
+ if (err != DB_SUCCESS) {
+ return err;
+ }
+
+ return DB_SUCCESS;
+}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
/** Drop a table for MySQL.
If the data dictionary was not already locked by the transaction,
the transaction will be committed. Otherwise, the data dictionary
@@ -3453,15 +3505,41 @@ row_drop_table_for_mysql(
ut_print_name(ef, trx, name);
fputs("\n"
"because it is referenced by ", ef);
- ut_print_name(ef, trx,
- foreign->foreign_table_name);
+ ut_print_name(ef, trx, foreign->foreign_table_name);
putc('\n', ef);
mutex_exit(&dict_foreign_err_mutex);
goto funct_exit;
}
}
- }
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ row_drop_table_check_legacy_data data;
+
+ err = row_drop_table_check_legacy_fk(trx, table->name.m_name, data);
+ if (err != DB_SUCCESS) {
+ goto funct_exit;
+ }
+ if (data.found) {
+ FILE* ef = dict_foreign_err_file;
+
+ err = DB_CANNOT_DROP_CONSTRAINT;
+
+ mutex_enter(&dict_foreign_err_mutex);
+ rewind(ef);
+ ut_print_timestamp(ef);
+
+ fputs(" Cannot drop table ", ef);
+ ut_print_name(ef, trx, name);
+ fputs("\n"
+ "because it is referenced by ", ef);
+ ut_print_name(ef, trx, data.foreign_name);
+ putc('\n', ef);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ goto funct_exit;
+ }
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+ } // if (!srv_read_only_mode && trx->check_foreigns)
DBUG_EXECUTE_IF("row_drop_table_add_to_background", goto defer;);
@@ -3571,6 +3649,7 @@ defer:
pars_info_add_str_literal(info, "name", name);
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
if (sqlcom != SQLCOM_TRUNCATE
&& strchr(name, '/')
&& dict_table_get_low("SYS_FOREIGN")
@@ -3596,13 +3675,14 @@ defer:
"END LOOP;\n"
"CLOSE fk;\n"
"END;\n", FALSE, trx);
- if (err == DB_SUCCESS) {
- info = pars_info_create();
- pars_info_add_str_literal(info, "name", name);
- goto do_drop;
+ if (err != DB_SUCCESS) {
+ goto error;
}
- } else {
-do_drop:
+ info = pars_info_create();
+ pars_info_add_str_literal(info, "name", name);
+ }
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+ {
if (dict_table_get_low("SYS_VIRTUAL")) {
err = que_eval_sql(
info,
@@ -3675,6 +3755,9 @@ do_drop:
}
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+error:
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
switch (err) {
fil_space_t* space;
char* filepath;
@@ -3969,6 +4052,64 @@ loop:
DBUG_RETURN(err);
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+/****************************************************************//**
+Delete a single constraint.
+@return error code or DB_SUCCESS */
+static MY_ATTRIBUTE((nonnull, warn_unused_result))
+dberr_t
+row_delete_constraint_low(
+/*======================*/
+ const char* id, /*!< in: constraint id */
+ trx_t* trx) /*!< in: transaction handle */
+{
+ pars_info_t* info = pars_info_create();
+
+ pars_info_add_str_literal(info, "id", id);
+
+ return(que_eval_sql(info,
+ "PROCEDURE DELETE_CONSTRAINT () IS\n"
+ "BEGIN\n"
+ "DELETE FROM SYS_FOREIGN_COLS WHERE ID = :id;\n"
+ "DELETE FROM SYS_FOREIGN WHERE ID = :id;\n"
+ "END;\n"
+ , FALSE, trx));
+}
+
+/****************************************************************//**
+Delete a single constraint.
+@return error code or DB_SUCCESS */
+static MY_ATTRIBUTE((nonnull, warn_unused_result))
+dberr_t
+row_delete_constraint(
+/*==================*/
+ const char* id, /*!< in: constraint id */
+ const char* database_name, /*!< in: database name, with the
+ trailing '/' */
+ mem_heap_t* heap, /*!< in: memory heap */
+ trx_t* trx) /*!< in: transaction handle */
+{
+ dberr_t err;
+
+ /* New format constraints have ids <databasename>/<constraintname>. */
+ err = row_delete_constraint_low(
+ mem_heap_strcat(heap, database_name, id), trx);
+
+ if ((err == DB_SUCCESS) && !strchr(id, '/')) {
+ /* Old format < 4.0.18 constraints have constraint ids
+ NUMBER_NUMBER. We only try deleting them if the
+ constraint name does not contain a '/' character, otherwise
+ deleting a new format constraint named 'foo/bar' from
+ database 'baz' would remove constraint 'bar' from database
+ 'foo', if it existed. */
+
+ err = row_delete_constraint_low(id, trx);
+ }
+
+ return(err);
+}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
/*********************************************************************//**
Renames a table for MySQL.
@return error code or DB_SUCCESS */
@@ -3986,9 +4127,12 @@ row_rename_table_for_mysql(
ibool dict_locked = FALSE;
dberr_t err = DB_ERROR;
mem_heap_t* heap = NULL;
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
const char** constraints_to_drop = NULL;
ulint n_constraints_to_drop = 0;
- ibool old_is_tmp, new_is_tmp;
+ bool old_is_tmp;
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+ bool new_is_tmp;
pars_info_t* info = NULL;
int retry;
bool aux_fts_rename = false;
@@ -4012,7 +4156,9 @@ row_rename_table_for_mysql(
trx->op_info = "renaming table";
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
old_is_tmp = dict_table_t::is_temporary_name(old_name);
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
new_is_tmp = dict_table_t::is_temporary_name(new_name);
dict_locked = trx->dict_operation_lock_mode == RW_X_LATCH;
@@ -4084,7 +4230,9 @@ row_rename_table_for_mysql(
goto funct_exit;
- } else if (use_fk && !old_is_tmp && new_is_tmp) {
+ }
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ else if (use_fk && !old_is_tmp && new_is_tmp) {
/* MySQL is doing an ALTER TABLE command and it renames the
original table to a temporary table name. We want to preserve
the original foreign key constraint definitions despite the
@@ -4101,6 +4249,7 @@ row_rename_table_for_mysql(
goto funct_exit;
}
}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
/* Is a foreign key check running on this table? */
for (retry = 0; retry < 100
@@ -4180,6 +4329,142 @@ row_rename_table_for_mysql(
goto end;
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ if (!new_is_tmp) {
+ /* Rename all constraints. */
+ char new_table_name[MAX_TABLE_NAME_LEN + 1];
+ char old_table_utf8[MAX_TABLE_NAME_LEN + 1];
+ uint errors = 0;
+
+ strncpy(old_table_utf8, old_name, MAX_TABLE_NAME_LEN);
+ old_table_utf8[MAX_TABLE_NAME_LEN] = '\0';
+ innobase_convert_to_system_charset(
+ strchr(old_table_utf8, '/') + 1,
+ strchr(old_name, '/') +1,
+ MAX_TABLE_NAME_LEN, &errors);
+
+ if (errors) {
+ /* Table name could not be converted from charset
+ my_charset_filename to UTF-8. This means that the
+ table name is already in UTF-8 (#mysql#50). */
+ strncpy(old_table_utf8, old_name, MAX_TABLE_NAME_LEN);
+ old_table_utf8[MAX_TABLE_NAME_LEN] = '\0';
+ }
+
+ info = pars_info_create();
+
+ pars_info_add_str_literal(info, "new_table_name", new_name);
+ pars_info_add_str_literal(info, "old_table_name", old_name);
+ pars_info_add_str_literal(info, "old_table_name_utf8",
+ old_table_utf8);
+
+ strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN);
+ new_table_name[MAX_TABLE_NAME_LEN] = '\0';
+ innobase_convert_to_system_charset(
+ strchr(new_table_name, '/') + 1,
+ strchr(new_name, '/') +1,
+ MAX_TABLE_NAME_LEN, &errors);
+
+ if (errors) {
+ /* Table name could not be converted from charset
+ my_charset_filename to UTF-8. This means that the
+ table name is already in UTF-8 (#mysql#50). */
+ strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN);
+ new_table_name[MAX_TABLE_NAME_LEN] = '\0';
+ }
+
+ pars_info_add_str_literal(info, "new_table_utf8", new_table_name);
+
+ err = que_eval_sql(
+ info,
+ "PROCEDURE RENAME_CONSTRAINT_IDS () IS\n"
+ "gen_constr_prefix CHAR;\n"
+ "new_db_name CHAR;\n"
+ "foreign_id CHAR;\n"
+ "new_foreign_id CHAR;\n"
+ "old_db_name_len INT;\n"
+ "old_t_name_len INT;\n"
+ "new_db_name_len INT;\n"
+ "id_len INT;\n"
+ "offset INT;\n"
+ "found INT;\n"
+ "BEGIN\n"
+ "found := 1;\n"
+ "old_db_name_len := INSTR(:old_table_name, '/')-1;\n"
+ "new_db_name_len := INSTR(:new_table_name, '/')-1;\n"
+ "new_db_name := SUBSTR(:new_table_name, 0,\n"
+ " new_db_name_len);\n"
+ "old_t_name_len := LENGTH(:old_table_name);\n"
+ "gen_constr_prefix := CONCAT(:old_table_name_utf8,\n"
+ " '_ibfk_');\n"
+ "WHILE found = 1 LOOP\n"
+ " SELECT ID INTO foreign_id\n"
+ " FROM SYS_FOREIGN\n"
+ " WHERE FOR_NAME = :old_table_name\n"
+ " AND TO_BINARY(FOR_NAME)\n"
+ " = TO_BINARY(:old_table_name)\n"
+ " LOCK IN SHARE MODE;\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " found := 0;\n"
+ " ELSE\n"
+ " UPDATE SYS_FOREIGN\n"
+ " SET FOR_NAME = :new_table_name\n"
+ " WHERE ID = foreign_id;\n"
+ " id_len := LENGTH(foreign_id);\n"
+ " IF (INSTR(foreign_id, '/') > 0) THEN\n"
+ " IF (INSTR(foreign_id,\n"
+ " gen_constr_prefix) > 0)\n"
+ " THEN\n"
+ " offset := INSTR(foreign_id, '_ibfk_') - 1;\n"
+ " new_foreign_id :=\n"
+ " CONCAT(:new_table_utf8,\n"
+ " SUBSTR(foreign_id, offset,\n"
+ " id_len - offset));\n"
+ " ELSE\n"
+ " new_foreign_id :=\n"
+ " CONCAT(new_db_name,\n"
+ " SUBSTR(foreign_id,\n"
+ " old_db_name_len,\n"
+ " id_len - old_db_name_len));\n"
+ " END IF;\n"
+ " UPDATE SYS_FOREIGN\n"
+ " SET ID = new_foreign_id\n"
+ " WHERE ID = foreign_id;\n"
+ " UPDATE SYS_FOREIGN_COLS\n"
+ " SET ID = new_foreign_id\n"
+ " WHERE ID = foreign_id;\n"
+ " END IF;\n"
+ " END IF;\n"
+ "END LOOP;\n"
+ "UPDATE SYS_FOREIGN SET REF_NAME = :new_table_name\n"
+ "WHERE REF_NAME = :old_table_name\n"
+ " AND TO_BINARY(REF_NAME)\n"
+ " = TO_BINARY(:old_table_name);\n"
+ "END;\n"
+ , FALSE, trx);
+
+ } else if (n_constraints_to_drop > 0) {
+ /* Drop some constraints of tmp tables. */
+
+ ulint db_name_len = dict_get_db_name_len(old_name) + 1;
+ char* db_name = mem_heap_strdupl(heap, old_name,
+ db_name_len);
+ ulint i;
+
+ for (i = 0; i < n_constraints_to_drop; i++) {
+ err = row_delete_constraint(constraints_to_drop[i],
+ db_name, heap, trx);
+
+ if (err != DB_SUCCESS) {
+ break;
+ }
+ }
+ }
+ if (err != DB_SUCCESS) {
+ goto end;
+ }
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
+
if ((dict_table_has_fts_index(table)
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID))
&& !dict_tables_have_same_db(old_name, new_name)) {
@@ -4191,6 +4476,35 @@ row_rename_table_for_mysql(
end:
if (err != DB_SUCCESS) {
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ if (err == DB_DUPLICATE_KEY) {
+ ib::error() << "Possible reasons:";
+ ib::error() << "(1) Table rename would cause two"
+ " FOREIGN KEY constraints to have the same"
+ " internal name in case-insensitive"
+ " comparison.";
+ ib::error() << "(2) Table "
+ << ut_get_name(trx, new_name)
+ << " exists in the InnoDB internal data"
+ " dictionary though MySQL is trying to rename"
+ " table " << ut_get_name(trx, old_name)
+ << " to it. Have you deleted the .frm file and"
+ " not used DROP TABLE?";
+ ib::info() << TROUBLESHOOTING_MSG;
+ ib::error() << "If table "
+ << ut_get_name(trx, new_name)
+ << " is a temporary table #sql..., then"
+ " it can be that there are still queries"
+ " running on the table, and it will be dropped"
+ " automatically when the queries end. You can"
+ " drop the orphaned table inside InnoDB by"
+ " creating an InnoDB table with the same name"
+ " in another database and copying the .frm file"
+ " to the current database. Then MySQL thinks"
+ " the table exists, and DROP TABLE will"
+ " succeed.";
+ }
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
trx->error_state = DB_SUCCESS;
trx->rollback();
trx->error_state = DB_SUCCESS;
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 595a72eb415..58640c20db0 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -2349,7 +2349,8 @@ fetch_step(
if (node->into_list) {
sel_assign_into_var_values(node->into_list,
sel_node);
- } else {
+ }
+ if (node->func) {
ibool ret = (*node->func->func)(
sel_node, node->func->arg);
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 32b087b5d67..3e76dabc438 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1929,10 +1929,21 @@ skip_monitors:
}
}
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ /* Create the SYS_FOREIGN and SYS_FOREIGN_COLS system tables */
+ err = dict_create_or_check_foreign_constraint_tables();
+ if (err == DB_SUCCESS) {
+ err = dict_create_or_check_sys_tablespace();
+ if (err == DB_SUCCESS) {
+ err = dict_create_or_check_sys_virtual();
+ }
+ }
+#else
err = dict_create_or_check_sys_tablespace();
if (err == DB_SUCCESS) {
err = dict_create_or_check_sys_virtual();
}
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
switch (err) {
case DB_SUCCESS:
break;
diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc
index bf35e7857c5..e09d511ed22 100644
--- a/storage/innobase/ut/ut0ut.cc
+++ b/storage/innobase/ut/ut0ut.cc
@@ -472,6 +472,10 @@ ut_strerr(
return ("File system does not support punch hole (trim) operation.");
case DB_PAGE_CORRUPTED:
return("Page read from tablespace is corrupted.");
+#ifdef WITH_INNODB_LEGACY_FOREIGN_STORAGE
+ case DB_LEGACY_FK:
+ return("Table requires foreign keys upgrade.");
+#endif /* WITH_INNODB_LEGACY_FOREIGN_STORAGE */
/* do not add default: in order to produce a warning if new code
is added to the enum but not added here */
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result b/storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result
index 95dae68b4e6..90f163b7d4b 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result
@@ -1,16 +1,16 @@
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb DATA DIRECTORY = '/foo/bar/data';
-ERROR HY000: Can't create table `test`.`t1` (errno: 198 "Unknown error 198")
+ERROR HY000: Can't create table `test`.`t1` (errno: 199 "Unknown error 199")
show warnings;
Level Code Message
-Error 1005 Can't create table `test`.`t1` (errno: 198 "Unknown error 198")
-Warning 1296 Got error 198 'Specifying DATA DIRECTORY for an individual table is not supported.' from ROCKSDB
+Error 1005 Can't create table `test`.`t1` (errno: 199 "Unknown error 199")
+Warning 1296 Got error 199 'Specifying DATA DIRECTORY for an individual table is not supported.' from ROCKSDB
CREATE TABLE t1 (a INT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb INDEX DIRECTORY = '/foo/bar/index';
-ERROR HY000: Can't create table `test`.`t1` (errno: 199 "Unknown error 199")
+ERROR HY000: Can't create table `test`.`t1` (errno: 200 "Unknown error 200")
show warnings;
Level Code Message
-Error 1005 Can't create table `test`.`t1` (errno: 199 "Unknown error 199")
-Warning 1296 Got error 199 'Specifying INDEX DIRECTORY for an individual table is not supported.' from ROCKSDB
+Error 1005 Can't create table `test`.`t1` (errno: 200 "Unknown error 200")
+Warning 1296 Got error 200 'Specifying INDEX DIRECTORY for an individual table is not supported.' from ROCKSDB
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=rocksdb PARTITION BY RANGE (id)
(
PARTITION P0 VALUES LESS THAN (1000)
@@ -19,11 +19,11 @@ PARTITION P1 VALUES LESS THAN (2000)
DATA DIRECTORY = '/foo/bar/data/',
PARTITION P2 VALUES LESS THAN (MAXVALUE)
);
-ERROR HY000: Can't create table `test`.`t1` (errno: 198 "Unknown error 198")
+ERROR HY000: Can't create table `test`.`t1` (errno: 199 "Unknown error 199")
show warnings;
Level Code Message
-Error 1005 Can't create table `test`.`t1` (errno: 198 "Unknown error 198")
-Warning 1296 Got error 198 'Specifying DATA DIRECTORY for an individual table is not supported.' from ROCKSDB
+Error 1005 Can't create table `test`.`t1` (errno: 199 "Unknown error 199")
+Warning 1296 Got error 199 'Specifying DATA DIRECTORY for an individual table is not supported.' from ROCKSDB
Error 6 Error on delete of './test/t1.par' (Errcode: 2 "No such file or directory")
CREATE TABLE t1 (id int not null primary key) ENGINE=rocksdb PARTITION BY RANGE (id)
(
@@ -33,9 +33,9 @@ PARTITION P1 VALUES LESS THAN (2000)
INDEX DIRECTORY = '/foo/bar/data/',
PARTITION P2 VALUES LESS THAN (MAXVALUE)
);
-ERROR HY000: Can't create table `test`.`t1` (errno: 199 "Unknown error 199")
+ERROR HY000: Can't create table `test`.`t1` (errno: 200 "Unknown error 200")
show warnings;
Level Code Message
-Error 1005 Can't create table `test`.`t1` (errno: 199 "Unknown error 199")
-Warning 1296 Got error 199 'Specifying INDEX DIRECTORY for an individual table is not supported.' from ROCKSDB
+Error 1005 Can't create table `test`.`t1` (errno: 200 "Unknown error 200")
+Warning 1296 Got error 200 'Specifying INDEX DIRECTORY for an individual table is not supported.' from ROCKSDB
Error 6 Error on delete of './test/t1.par' (Errcode: 2 "No such file or directory")