polardbxengine/sql/sql_sequence.h

261 lines
8.4 KiB
C++

/* Copyright (c) 2018, 2021, Alibaba 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/PolarDB-X Engine 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/PolarDB-X Engine.
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 SQL_SEQUENCE_INCLUDED
#define SQL_SEQUENCE_INCLUDED
#include "handler.h"
#include "lex_string.h" // LEX_STRING
#include "my_inttypes.h"
#include "sql/mem_root_array.h" // MEM_ROOT
#include "sql/parse_tree_nodes.h"
#include "sql/sql_cmd_ddl_table.h" // Sql_cmd_create_table
#include "sql/sequence_common.h" // Sequence_info
/**
Sequence engine as the builtin plugin.
The base table engine now only support InnoDB plugin.
*/
/**
The struture of SEQUENCE options parser
*/
template <Sequence_field field_num, typename FIELD_TYPE = ulonglong>
class PT_values_create_sequence_option : public PT_create_table_option {
public:
explicit PT_values_create_sequence_option(FIELD_TYPE value) : value(value) {}
virtual ~PT_values_create_sequence_option() {}
bool contextualize(Table_ddl_parse_context *pc) override {
if (PT_create_table_option::contextualize(pc)) return true;
pc->sequence_info->init_value(field_num, value);
return false;
}
private:
FIELD_TYPE value;
};
class PT_values_create_sequence_type : public PT_create_table_option {
public:
explicit PT_values_create_sequence_type(Sequence_type type) : m_type(type) {}
virtual ~PT_values_create_sequence_type() {}
bool contextualize(Table_ddl_parse_context *pc) override {
if (PT_create_table_option::contextualize(pc)) return true;
pc->sequence_info->init_type(m_type);
return false;
}
private:
Sequence_type m_type;
};
class PT_create_sequence_stmt : public PT_create_table_stmt {
public:
/**
@param mem_root MEM_ROOT to use for allocation
@param only_if_not_exists True if @SQL{CREATE %TABLE ... @B{IF NOT EXISTS}}
@param table_name @SQL{CREATE %TABLE ... @B{@<table name@>}}
@param on_duplicate DUPLICATE, IGNORE or fail with an error
on data duplication errors (relevant
for @SQL{CREATE TABLE ... SELECT}
statements).
@param opt_create_sequence_options
For @SQL {CREATE SEQUENCE ...}
*/
explicit PT_create_sequence_stmt(
MEM_ROOT *mem_root, bool only_if_not_exists, Table_ident *table_name,
On_duplicate on_duplicate, const Mem_root_array<PT_create_table_option *>
*opt_create_sequence_options)
: PT_create_table_stmt(mem_root, false, only_if_not_exists, table_name,
NULL, NULL, NULL, on_duplicate, NULL),
opt_create_sequence_options(opt_create_sequence_options) {}
/**
CREATE SEQUENCE statement command
@param[in] thd Connection context
@retval Sql_cmd SQL command
*/
Sql_cmd *make_cmd(THD *thd) override;
/**
Prepare sequence base engine
@param[in] thd Connection context
@param[in] table TABLE_LIST
@retval false success
@retval true failure
*/
bool prepare_sequence_engine(const THD *thd, const TABLE_LIST *table);
/**
Prepare and check sequence table columns
@param[in] thd Connection context
@retval false success
@retval true failure
*/
bool prepare_sequence_fields(const THD *thd);
/**
Check the fields whether it is consistent with pre-defined.
@param[in] alter_info All the DDL information
@retval false success
@retval true failure
*/
bool check_sequence_fields(Alter_info *alter_info) const;
private:
const Mem_root_array<PT_create_table_option *> *opt_create_sequence_options;
Sequence_info m_sequence_info;
};
/**
CREATE SEQUENCE statement cmd
*/
class Sql_cmd_create_sequence : public Sql_cmd_create_table {
typedef Sql_cmd_create_table super;
public:
explicit Sql_cmd_create_sequence(Alter_info *alter_info,
TABLE_LIST *query_expression_tables,
Sequence_info *sequence_info)
: Sql_cmd_create_table(alter_info, query_expression_tables),
m_sequence_info(sequence_info) {}
/* CREATE SEQUENCE is also SQLCOM_CREATE_TABLE */
enum_sql_command sql_command_code() const override {
return SQLCOM_CREATE_TABLE;
}
bool execute(THD *thd) override;
bool prepare(THD *thd) override;
private:
const Sequence_info *m_sequence_info;
};
class Open_sequence_table_ctx {
public:
/**
Temporary TABLE_LIST object that is used to hold opened table.
*/
class Table_list_state {
public:
/* Used by CREATE SEQUENCE. */
Table_list_state(THD *thd, TABLE_LIST *table) {
m_table = new (thd->mem_root) TABLE_LIST(table->db, table->db_length,
table->table_name, table->table_name_length,
table->alias, TL_WRITE_CONCURRENT_DEFAULT,
MDL_SHARED_WRITE);
m_table->open_strategy = TABLE_LIST::OPEN_IF_EXISTS;
m_table->open_type = OT_BASE_ONLY;
}
/* Used by reload sequence share cache */
Table_list_state(THD *thd, TABLE_SHARE *share) {
char *db = (char *)thd->memdup(share->db.str, share->db.length + 1);
char *table_name = (char *)thd->memdup(share->table_name.str,
share->table_name.length + 1);
char *alias = (char *)thd->memdup(share->table_name.str,
share->table_name.length + 1);
m_table = new (thd->mem_root) TABLE_LIST(db, share->db.length, table_name,
share->table_name.length, alias,
TL_WRITE_CONCURRENT_DEFAULT,
MDL_SHARED_WRITE);
m_table->open_strategy = TABLE_LIST::OPEN_IF_EXISTS;
m_table->open_type = OT_BASE_ONLY;
m_table->sequence_scan.set(Sequence_scan::ORIGINAL_SCAN);
}
/** The cloned TABLE_LIST will be free when statement end. */
~Table_list_state() {}
TABLE_LIST *cloned_table() const { return m_table; }
private:
THD *thd;
TABLE_LIST *m_table;
};
Open_sequence_table_ctx(THD *thd, TABLE_LIST *table_list);
Open_sequence_table_ctx(THD *thd, TABLE_SHARE *share);
virtual ~Open_sequence_table_ctx();
/**
Open and lock the sequence table.
@retval false success
@retval true failure
*/
bool open_table();
/**
Get the TABLE object
@retval table TABLE object
*/
TABLE *get_table() const {
if (m_inherit_table && m_inherit_table->table)
return m_inherit_table->table;
else
return m_state.cloned_table()->table;
}
private:
THD *m_thd;
TABLE_LIST *m_inherit_table;
Table_list_state m_state;
};
/**
When CREATE SQUENCE, beside of creating table structure, also need to insert
initial row into table.
*/
class Insert_sequence_table_ctx {
public:
Insert_sequence_table_ctx(THD *thd, TABLE_LIST *table_list,
const Sequence_info *seq_info);
virtual ~Insert_sequence_table_ctx();
/**
Write the sequence initial row.
@retval false success
@retval true failure
*/
bool write_record();
private:
Open_sequence_table_ctx otx;
THD *m_thd;
const Sequence_info *m_seq_info;
bool m_save_binlog_row_based;
};
#endif