Пример #1
0
/************************************************************************
Add a single foreign key field definition to the data dictionary tables in
the database.  */
static
ulint
dict_create_add_foreign_field_to_dictionary(
/*========================================*/
					/* out: error code or DB_SUCCESS */
	ulint		field_nr,	/* in: foreign field number */
	dict_table_t*	table,		/* in: table */
	dict_foreign_t*	foreign,	/* in: foreign */
	trx_t*		trx)		/* in: transaction */
{
	pars_info_t*	info = pars_info_create();

	pars_info_add_str_literal(info, "id", foreign->id);

	pars_info_add_int4_literal(info, "pos", field_nr);

	pars_info_add_str_literal(info, "for_col_name",
				  foreign->foreign_col_names[field_nr]);

	pars_info_add_str_literal(info, "ref_col_name",
				  foreign->referenced_col_names[field_nr]);

	return(dict_foreign_eval_sql(
		       info,
		       "PROCEDURE P () IS\n"
		       "BEGIN\n"
		       "INSERT INTO SYS_FOREIGN_COLS VALUES"
		       "(:id, :pos, :for_col_name, :ref_col_name);\n"
		       "END;\n",
		       table, foreign, trx));
}
Пример #2
0
/************************************************************************
Add a single foreign key definition to the data dictionary tables in the
database. We also generate names to constraints that were not named by the
user. A generated constraint has a name of the format
databasename/tablename_ibfk_<number>, where the numbers start from 1, and
are given locally for this table, that is, the number is not global, as in
the old format constraints < 4.0.18 it used to be. */
static
ulint
dict_create_add_foreign_to_dictionary(
/*==================================*/
				/* out: error code or DB_SUCCESS */
	ulint*		id_nr,	/* in/out: number to use in id generation;
				incremented if used */
	dict_table_t*	table,	/* in: table */
	dict_foreign_t*	foreign,/* in: foreign */
	trx_t*		trx)	/* in: transaction */
{
	ulint		error;
	ulint		i;

	pars_info_t*	info = pars_info_create();

	if (foreign->id == NULL) {
		/* Generate a new constraint id */
		ulint	namelen	= strlen(table->name);
		char*	id	= mem_heap_alloc(foreign->heap, namelen + 20);
		/* no overflow if number < 1e13 */
		sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++);
		foreign->id = id;
	}

	pars_info_add_str_literal(info, "id", foreign->id);

	pars_info_add_str_literal(info, "for_name", table->name);

	pars_info_add_str_literal(info, "ref_name",
				  foreign->referenced_table_name);

	pars_info_add_int4_literal(info, "n_cols",
				   foreign->n_fields + (foreign->type << 24));

	error = dict_foreign_eval_sql(info,
				      "PROCEDURE P () IS\n"
				      "BEGIN\n"
				      "INSERT INTO SYS_FOREIGN VALUES"
				      "(:id, :for_name, :ref_name, :n_cols);\n"
				      "END;\n"
				      , table, foreign, trx);

	if (error != DB_SUCCESS) {

		return(error);
	}

	for (i = 0; i < foreign->n_fields; i++) {
		error = dict_create_add_foreign_field_to_dictionary(
			i, table, foreign, trx);

		if (error != DB_SUCCESS) {

			return(error);
		}
	}

	error = dict_foreign_eval_sql(NULL,
				      "PROCEDURE P () IS\n"
				      "BEGIN\n"
				      "COMMIT WORK;\n"
				      "END;\n"
				      , table, foreign, trx);

	return(error);
}
Пример #3
0
/********************************************************************//**
Add a single foreign key definition to the data dictionary tables in the
database. We also generate names to constraints that were not named by the
user. A generated constraint has a name of the format
databasename/tablename_ibfk_NUMBER, where the numbers start from 1, and
are given locally for this table, that is, the number is not global, as in
the old format constraints < 4.0.18 it used to be.
@return	error code or DB_SUCCESS */
static
ulint
dict_create_add_foreign_to_dictionary(
    /*==================================*/
    ulint*		id_nr,	/*!< in/out: number to use in id generation;
				incremented if used */
    dict_table_t*	table,	/*!< in: table */
    dict_foreign_t*	foreign,/*!< in: foreign */
    trx_t*		trx)	/*!< in: transaction */
{
    ulint		error;
    ulint		i;
    pars_info_t*	info;

    ut_ad(mutex_own(&(dict_sys->mutex)));

    if (foreign->id == NULL) {
        /* Generate a new constraint id */
        ulint	namelen	= strlen(table->name);
        char*	id	= mem_heap_alloc(foreign->heap, namelen + 20);

        if (row_is_mysql_tmp_table_name(table->name)) {
            sprintf(id, "%s_ibfk_%lu", table->name,
                    (ulong) (*id_nr)++);
        } else {
            char	table_name[MAX_TABLE_NAME_LEN + 20] = "";
            uint	errors = 0;

            strncpy(table_name, table->name,
                    MAX_TABLE_NAME_LEN + 20);

            innobase_convert_to_system_charset(
                strchr(table_name, '/') + 1,
                strchr(table->name, '/') + 1,
                MAX_TABLE_NAME_LEN, &errors);

            if (errors) {
                strncpy(table_name, table->name,
                        MAX_TABLE_NAME_LEN + 20);
            }

            sprintf(id, "%s_ibfk_%lu", table_name,
                    (ulong) (*id_nr)++);

            if (innobase_check_identifier_length(
                        strchr(id,'/') + 1)) {
                return(DB_IDENTIFIER_TOO_LONG);
            }
        }
        foreign->id = id;
    }

    info = pars_info_create();

    pars_info_add_str_literal(info, "id", foreign->id);

    pars_info_add_str_literal(info, "for_name", table->name);

    pars_info_add_str_literal(info, "ref_name",
                              foreign->referenced_table_name);

    pars_info_add_int4_literal(info, "n_cols",
                               foreign->n_fields + (foreign->type << 24));

    error = dict_foreign_eval_sql(info,
                                  "PROCEDURE P () IS\n"
                                  "BEGIN\n"
                                  "INSERT INTO SYS_FOREIGN VALUES"
                                  "(:id, :for_name, :ref_name, :n_cols);\n"
                                  "END;\n"
                                  , table, foreign, trx);

    if (error != DB_SUCCESS) {

        return(error);
    }

    for (i = 0; i < foreign->n_fields; i++) {
        error = dict_create_add_foreign_field_to_dictionary(
                    i, table, foreign, trx);

        if (error != DB_SUCCESS) {

            return(error);
        }
    }

    error = dict_foreign_eval_sql(NULL,
                                  "PROCEDURE P () IS\n"
                                  "BEGIN\n"
                                  "COMMIT WORK;\n"
                                  "END;\n"
                                  , table, foreign, trx);

    if (error == DB_SUCCESS) {


        if (foreign->foreign_table != NULL) {
            ib_rbt_t*	rbt
                = foreign->foreign_table->foreign_rbt;

            if (rbt == NULL) {
                rbt = dict_table_init_foreign_rbt(
                          foreign->foreign_table);
            } else {
                rbt_delete(rbt, foreign->id);
            }

            rbt_insert(rbt, foreign->id, &foreign);
        }

        if (foreign->referenced_table != NULL) {
            ib_rbt_t* rbt
                = foreign->referenced_table->referenced_rbt;

            if (rbt == NULL) {
                rbt = dict_table_init_referenced_rbt(
                          foreign->referenced_table);
            } else {
                rbt_delete(rbt, foreign->id);
            }
            rbt_insert(rbt, foreign->id, &foreign);
        }
    }

    return(error);
}