123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- /* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License, version 2.0,
- as published by the Free Software Foundation.
- This program is also distributed with certain software (including
- but not limited to OpenSSL) that is licensed under separate terms,
- as designated in a particular file or component or in included license
- documentation. The authors of MySQL hereby grant you an additional
- permission to link the program and your derivative works with the
- separately licensed software that they have included with MySQL.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License, version 2.0, for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
- #ifndef KEY_SPEC_INCLUDED
- #define KEY_SPEC_INCLUDED
- #include <sys/types.h>
- #include "lex_string.h"
- #include "m_string.h"
- #include "my_base.h"
- #include "sql/mem_root_array.h"
- #include "sql/sql_list.h"
- class Create_field;
- class Item;
- class THD;
- struct MEM_ROOT;
- enum keytype {
- KEYTYPE_PRIMARY,
- KEYTYPE_UNIQUE,
- KEYTYPE_MULTIPLE,
- KEYTYPE_FULLTEXT,
- KEYTYPE_SPATIAL,
- KEYTYPE_FOREIGN
- };
- enum fk_option {
- FK_OPTION_UNDEF,
- FK_OPTION_RESTRICT,
- FK_OPTION_CASCADE,
- FK_OPTION_SET_NULL,
- FK_OPTION_NO_ACTION,
- FK_OPTION_DEFAULT
- };
- enum fk_match_opt {
- FK_MATCH_UNDEF,
- FK_MATCH_FULL,
- FK_MATCH_PARTIAL,
- FK_MATCH_SIMPLE
- };
- enum enum_order { ORDER_NOT_RELEVANT = 1, ORDER_ASC, ORDER_DESC };
- class KEY_CREATE_INFO {
- public:
- enum ha_key_alg algorithm = HA_KEY_ALG_SE_SPECIFIC;
- /**
- A flag which indicates that index algorithm was explicitly specified
- by user.
- */
- bool is_algorithm_explicit = false;
- ulong block_size = 0;
- LEX_CSTRING parser_name = {NullS, 0};
- LEX_CSTRING comment = {NullS, 0};
- bool is_visible = true;
- KEY_CREATE_INFO() = default;
- explicit KEY_CREATE_INFO(bool is_visible_arg) : is_visible(is_visible_arg) {}
- };
- extern KEY_CREATE_INFO default_key_create_info;
- class Key_part_spec {
- public:
- Key_part_spec(Item *expression, enum_order order)
- : m_is_ascending((order == ORDER_DESC) ? false : true),
- m_is_explicit(order != ORDER_NOT_RELEVANT),
- m_field_name(nullptr),
- m_prefix_length(0),
- m_expression(expression),
- m_has_expression(true) {}
- Key_part_spec(const char *column_name, Item *expression, enum_order order)
- : m_is_ascending((order == ORDER_DESC) ? false : true),
- m_is_explicit(order != ORDER_NOT_RELEVANT),
- m_field_name(column_name),
- m_prefix_length(0),
- m_expression(expression),
- m_has_expression(true) {}
- Key_part_spec(LEX_CSTRING column_name, uint prefix_length, enum_order order)
- : m_is_ascending((order == ORDER_DESC) ? false : true),
- m_is_explicit(order != ORDER_NOT_RELEVANT),
- m_field_name(column_name.str),
- m_prefix_length(prefix_length),
- m_expression(nullptr),
- m_has_expression(false) {}
- bool operator==(const Key_part_spec &other) const;
- /**
- Construct a copy of this Key_part_spec. field_name is copied
- by-pointer as it is known to never change. At the same time
- 'length' may be reset in mysql_prepare_create_table, and this
- is why we supply it with a copy.
- @return If out of memory, 0 is returned and an error is set in
- THD.
- */
- Key_part_spec *clone(MEM_ROOT *mem_root) const {
- return new (mem_root) Key_part_spec(*this);
- }
- const char *get_field_name() const { return m_field_name; }
- uint get_prefix_length() const { return m_prefix_length; }
- Item *get_expression() const {
- DBUG_ASSERT(has_expression());
- return m_expression;
- }
- /**
- @retval true if this is an ascending index.
- @retval false if this is a descending index.
- */
- bool is_ascending() const { return m_is_ascending; }
- /**
- @retval true if the user explicitly specified the index direction when
- creating the index.
- @retval false if the user didn't specify the index direction.
- */
- bool is_explicit() const { return m_is_explicit; }
- /**
- Resolve the expression that this key part contains. Should only be called
- if has_expression() returns true.
- @param thd thread handler.
- @retval true if an error occurred.
- @retval false on success.
- */
- bool resolve_expression(THD *thd);
- /**
- Set the name and the prefix length of the column this key part references.
- The supplied column name string should have a lifetime equal to or longer
- than this Key_part_spec
- @param name the new column that this key part points to.
- @param prefix_length the prefix length of the index, or 0 if no length is
- specified.
- */
- void set_name_and_prefix_length(const char *name, uint prefix_length);
- /**
- @retval true if this index has an expression. In that case, this a
- functional key part.
- @retval false if this index doesn't have an expression. In that case this
- key part references a normal column.
- */
- bool has_expression() const { return m_has_expression; }
- private:
- /// true <=> ascending, false <=> descending.
- const bool m_is_ascending;
- /// true <=> ASC/DESC is explicitly specified, false <=> implicit ASC
- const bool m_is_explicit;
- /// The name of the column that this key part points to.
- const char *m_field_name;
- /// The prefix length of this index.
- uint m_prefix_length;
- /**
- The indexed expression if this is a functional key part. If this key part
- points to a "normal" column, m_expression is nullptr.
- */
- Item *m_expression;
- /**
- Whether this key part has an expression or not. If so, this is a functional
- key part.
- */
- bool m_has_expression;
- };
- class Key_spec {
- public:
- const keytype type;
- const KEY_CREATE_INFO key_create_info;
- Mem_root_array<Key_part_spec *> columns;
- LEX_CSTRING name;
- const bool generated;
- /**
- A flag to determine if we will check for duplicate indexes.
- This typically means that the key information was specified
- directly by the user (set by the parser) or a column
- associated with it was dropped.
- */
- const bool check_for_duplicate_indexes;
- Key_spec(MEM_ROOT *mem_root, keytype type_par, const LEX_CSTRING &name_arg,
- const KEY_CREATE_INFO *key_info_arg, bool generated_arg,
- bool check_for_duplicate_indexes_arg, List<Key_part_spec> &cols)
- : type(type_par),
- key_create_info(*key_info_arg),
- columns(mem_root),
- name(name_arg),
- generated(generated_arg),
- check_for_duplicate_indexes(check_for_duplicate_indexes_arg) {
- columns.reserve(cols.elements);
- List_iterator<Key_part_spec> it(cols);
- Key_part_spec *column;
- while ((column = it++)) columns.push_back(column);
- }
- virtual ~Key_spec() {}
- };
- class Foreign_key_spec : public Key_spec {
- public:
- const LEX_CSTRING ref_db;
- const LEX_CSTRING orig_ref_db;
- const LEX_CSTRING ref_table;
- const LEX_CSTRING orig_ref_table;
- Mem_root_array<Key_part_spec *> ref_columns;
- const fk_option delete_opt;
- const fk_option update_opt;
- const fk_match_opt match_opt;
- Foreign_key_spec(MEM_ROOT *mem_root, const LEX_CSTRING &name_arg,
- List<Key_part_spec> cols, const LEX_CSTRING &ref_db_arg,
- const LEX_CSTRING &orig_ref_db_arg,
- const LEX_CSTRING &ref_table_arg,
- const LEX_CSTRING &orig_ref_table_arg,
- List<Key_part_spec> *ref_cols, fk_option delete_opt_arg,
- fk_option update_opt_arg, fk_match_opt match_opt_arg)
- : Key_spec(mem_root, KEYTYPE_FOREIGN, name_arg, &default_key_create_info,
- false,
- false, // We don't check for duplicate FKs.
- cols),
- ref_db(ref_db_arg),
- orig_ref_db(orig_ref_db_arg),
- ref_table(ref_table_arg),
- orig_ref_table(orig_ref_table_arg),
- ref_columns(mem_root),
- delete_opt(delete_opt_arg),
- update_opt(update_opt_arg),
- match_opt(match_opt_arg) {
- if (ref_cols) {
- ref_columns.reserve(ref_cols->elements);
- List_iterator<Key_part_spec> it(*ref_cols);
- Key_part_spec *ref_column;
- while ((ref_column = it++)) ref_columns.push_back(ref_column);
- }
- }
- /**
- Check if the foreign key name has valid length and its options
- are compatible with columns on which the FK is created.
- @param thd Thread handle
- @param table_name Table name (for error reporting)
- @param table_fields List of columns
- @retval false Key valid
- @retval true Key invalid
- */
- bool validate(THD *thd, const char *table_name,
- List<Create_field> &table_fields) const;
- };
- /**
- Test if a foreign key (= generated key) is a prefix of the given key
- (ignoring key name, key type and order of columns)
- @note This is only used to test if an index for a FOREIGN KEY exists.
- We only compare field names.
- @retval false Generated key is a prefix of other key
- @retval true Not equal
- */
- bool foreign_key_prefix(const Key_spec *a, const Key_spec *b);
- #endif // KEY_SPEC_INCLUDED
|