1/*****************************************************************************
2
3Copyright (c) 1996, 2019, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is also distributed with certain software (including but not
10limited to OpenSSL) that is licensed under separate terms, as designated in a
11particular file or component or in included license documentation. The authors
12of MySQL hereby grant you an additional permission to link the program and
13your derivative works with the separately licensed software that they have
14included with MySQL.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24
25*****************************************************************************/
26
27/** @file include/dict0crea.ic
28 Database object creation
29
30 Created 1/8/1996 Heikki Tuuri
31 *******************************************************/
32
33#include "ha_prototypes.h"
34
35#include "mem0mem.h"
36
37/** Checks if a table name contains the string "/#sql" which denotes temporary
38 tables in MySQL.
39 @return true if temporary table */
40bool row_is_mysql_tmp_table_name(const char *name)
41    MY_ATTRIBUTE((warn_unused_result));
42/*!< in: table name in the form
43'database/tablename' */
44
45/** Generate a foreign key constraint name when it was not named by the user.
46 A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER,
47 where the numbers start from 1, and are given locally for this table, that is,
48 the number is not global, as it used to be before MySQL 4.0.18.  */
49UNIV_INLINE
50dberr_t dict_create_add_foreign_id(
51    ulint *id_nr,            /*!< in/out: number to use in id generation;
52                             incremented if used */
53    const char *name,        /*!< in: table name */
54    dict_foreign_t *foreign) /*!< in/out: foreign key */
55{
56  DBUG_TRACE;
57
58  if (foreign->id == nullptr) {
59    /* Generate a new constraint id */
60    ulint namelen = strlen(name);
61    char *id = static_cast<char *>(mem_heap_alloc(foreign->heap, namelen + 20));
62
63    if (row_is_mysql_tmp_table_name(name)) {
64      /* no overflow if number < 1e13 */
65      sprintf(id, "%s_ibfk_%lu", name, (ulong)(*id_nr)++);
66    } else {
67      char table_name[MAX_TABLE_NAME_LEN + 20 + 1] = "";
68      uint errors = 0;
69
70      strncpy(table_name, name, MAX_TABLE_NAME_LEN + 20);
71
72      innobase_convert_to_system_charset(strchr(table_name, '/') + 1,
73                                         strchr(name, '/') + 1,
74                                         MAX_TABLE_NAME_LEN, &errors);
75
76      if (errors) {
77        strncpy(table_name, name, MAX_TABLE_NAME_LEN + 20);
78      }
79
80      /* no overflow if number < 1e13 */
81      sprintf(id, "%s_ibfk_%lu", table_name, (ulong)(*id_nr)++);
82
83      if (innobase_check_identifier_length(strchr(id, '/') + 1)) {
84        /* Server has already done this check,
85        So assert here */
86        ut_ad(0);
87        return DB_IDENTIFIER_TOO_LONG;
88      }
89    }
90    foreign->id = id;
91
92    DBUG_PRINT("dict_create_add_foreign_id", ("generated foreign id: %s", id));
93  }
94
95  return DB_SUCCESS;
96}
97
98/** Compose a column number for a virtual column, stored in the "POS" field
99of Sys_columns. The column number includes both its virtual column sequence
100(the "nth" virtual column) and its actual column position in original table
101@param[in]	v_pos		virtual column sequence
102@param[in]	col_pos		column position in original table definition
103@return composed column position number */
104UNIV_INLINE
105ulint dict_create_v_col_pos(ulint v_pos, ulint col_pos) {
106  ut_ad(v_pos <= REC_MAX_N_FIELDS);
107  ut_ad(col_pos <= REC_MAX_N_FIELDS);
108
109  return (((v_pos + 1) << 16) + col_pos);
110}
111
112/** Get the column number for a virtual column (the column position in
113original table), stored in the "POS" field of Sys_columns
114@param[in]	pos		virtual column position
115@return column position in original table */
116UNIV_INLINE
117ulint dict_get_v_col_mysql_pos(ulint pos) { return (pos & 0xFFFF); }
118
119/** Get a virtual column sequence (the "nth" virtual column) for a
120virtual column, stord in the "POS" field of Sys_columns
121@param[in]	pos		virtual column position
122@return virtual column sequence */
123UNIV_INLINE
124ulint dict_get_v_col_pos(ulint pos) { return ((pos >> 16) - 1); }
125