summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-12-05 12:48:58 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-12-05 12:48:58 +0200
commitaeec6ecde0a8fd72e89aec98bccb47fc1ac1e415 (patch)
treeb92bb71ed0fc8231f2f56b037a3e9f7e65921650
parentdf039423a6009c24e525c1d193484e36800f2bc3 (diff)
parent6189774c37616fdc52019b35b0c6108b86e795da (diff)
downloadmariadb-git-aeec6ecde0a8fd72e89aec98bccb47fc1ac1e415.tar.gz
Merge 10.5
-rw-r--r--.gitignore1
-rw-r--r--VERSION2
-rw-r--r--client/CMakeLists.txt3
-rw-r--r--client/mariadb-conv.cc362
-rw-r--r--cmake/cpack_rpm.cmake8
-rw-r--r--extra/innochecksum.cc27
-rw-r--r--extra/mariabackup/backup_copy.cc3
-rw-r--r--extra/mariabackup/fil_cur.cc11
-rw-r--r--extra/mariabackup/fil_cur.h3
-rw-r--r--extra/mariabackup/xtrabackup.cc28
-rw-r--r--include/lf.h1
-rw-r--r--mysql-test/std_data/mariadb-conv/file01.utf16.txtbin0 -> 36 bytes
-rw-r--r--mysql-test/std_data/mariadb-conv/file01.utf8.txt3
-rw-r--r--mysql-test/std_data/mariadb-conv/file02.latin1.txt3
-rw-r--r--mysql-test/suite/client/mariadb-conv-cp932.result2
-rw-r--r--mysql-test/suite/client/mariadb-conv-cp932.test19
-rw-r--r--mysql-test/suite/client/mariadb-conv-utf16.result13
-rw-r--r--mysql-test/suite/client/mariadb-conv-utf16.test21
-rw-r--r--mysql-test/suite/client/mariadb-conv-utf8.result2
-rw-r--r--mysql-test/suite/client/mariadb-conv-utf8.test19
-rw-r--r--mysql-test/suite/client/mariadb-conv.result12
-rw-r--r--mysql-test/suite/client/mariadb-conv.test18
-rw-r--r--mysql-test/suite/innodb/r/log_file.result4
-rw-r--r--mysql-test/suite/innodb/t/doublewrite.test5
-rw-r--r--mysql-test/suite/innodb/t/log_file.test4
-rw-r--r--mysql-test/suite/mariabackup/undo_space_id.result10
-rw-r--r--mysql-test/suite/mariabackup/undo_space_id.test2
-rw-r--r--mysql-test/suite/period/r/delete.result12
-rw-r--r--mysql-test/suite/period/t/delete.test14
-rw-r--r--mysql-test/suite/versioning/r/delete_history.result12
-rw-r--r--mysql-test/suite/versioning/r/partition.result545
-rw-r--r--mysql-test/suite/versioning/r/partition_innodb.result67
-rw-r--r--mysql-test/suite/versioning/r/partition_rotation.result280
-rw-r--r--mysql-test/suite/versioning/r/select.result15
-rw-r--r--mysql-test/suite/versioning/r/update.result21
-rw-r--r--mysql-test/suite/versioning/r/view.result66
-rw-r--r--mysql-test/suite/versioning/t/delete_history.test11
-rw-r--r--mysql-test/suite/versioning/t/partition.test417
-rw-r--r--mysql-test/suite/versioning/t/partition_innodb.test80
-rw-r--r--mysql-test/suite/versioning/t/partition_rotation.test178
-rw-r--r--mysql-test/suite/versioning/t/select.test15
-rw-r--r--mysql-test/suite/versioning/t/update.test28
-rw-r--r--mysql-test/suite/versioning/t/view.test58
-rw-r--r--mysys/lf_alloc-pin.c14
-rw-r--r--plugin/versioning/versioning.cc3
-rw-r--r--sql/CMakeLists.txt16
-rw-r--r--sql/gen_sql_yacc_ora_yy.cmake15
-rw-r--r--sql/ha_partition.cc66
-rw-r--r--sql/ha_partition.h5
-rw-r--r--sql/handler.cc4
-rw-r--r--sql/handler.h24
-rw-r--r--sql/partition_info.cc107
-rw-r--r--sql/partition_info.h63
-rw-r--r--sql/proxy_protocol.cc2
-rw-r--r--sql/sql_derived.cc23
-rw-r--r--sql/sql_insert.cc31
-rw-r--r--sql/sql_partition.cc2
-rw-r--r--sql/sql_select.cc59
-rw-r--r--sql/sql_update.cc29
-rw-r--r--sql/sql_yacc.yy1110
-rw-r--r--sql/sql_yacc_ora.yy18623
-rw-r--r--sql/table.cc17
-rw-r--r--sql/table.h26
-rw-r--r--sql/vers_utils.h8
-rw-r--r--storage/innobase/btr/btr0btr.cc733
-rw-r--r--storage/innobase/btr/btr0bulk.cc144
-rw-r--r--storage/innobase/btr/btr0cur.cc462
-rw-r--r--storage/innobase/btr/btr0sea.cc3
-rw-r--r--storage/innobase/buf/buf0buf.cc5
-rw-r--r--storage/innobase/buf/buf0dblwr.cc188
-rw-r--r--storage/innobase/dict/dict0boot.cc103
-rw-r--r--storage/innobase/dict/dict0crea.cc31
-rw-r--r--storage/innobase/dict/dict0dict.cc9
-rw-r--r--storage/innobase/dict/dict0load.cc3
-rw-r--r--storage/innobase/fil/fil0crypt.cc125
-rw-r--r--storage/innobase/fil/fil0fil.cc17
-rw-r--r--storage/innobase/fsp/fsp0file.cc48
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc1088
-rw-r--r--storage/innobase/fut/fut0lst.cc689
-rw-r--r--storage/innobase/gis/gis0rtree.cc41
-rw-r--r--storage/innobase/handler/ha_innodb.cc12
-rw-r--r--storage/innobase/handler/handler0alter.cc6
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc429
-rw-r--r--storage/innobase/include/btr0btr.h30
-rw-r--r--storage/innobase/include/btr0btr.ic129
-rw-r--r--storage/innobase/include/btr0bulk.h20
-rw-r--r--storage/innobase/include/btr0cur.h9
-rw-r--r--storage/innobase/include/btr0cur.ic20
-rw-r--r--storage/innobase/include/buf0buf.h26
-rw-r--r--storage/innobase/include/buf0buf.ic36
-rw-r--r--storage/innobase/include/buf0dblwr.h2
-rw-r--r--storage/innobase/include/dict0boot.h13
-rw-r--r--storage/innobase/include/dict0crea.h3
-rw-r--r--storage/innobase/include/fil0crypt.h14
-rw-r--r--storage/innobase/include/fsp0file.h9
-rw-r--r--storage/innobase/include/fsp0fsp.h36
-rw-r--r--storage/innobase/include/fut0lst.h158
-rw-r--r--storage/innobase/include/fut0lst.ic80
-rw-r--r--storage/innobase/include/log0recv.h6
-rw-r--r--storage/innobase/include/mtr0log.h146
-rw-r--r--storage/innobase/include/mtr0log.ic29
-rw-r--r--storage/innobase/include/mtr0mtr.h64
-rw-r--r--storage/innobase/include/mtr0types.h2
-rw-r--r--storage/innobase/include/page0page.h57
-rw-r--r--storage/innobase/include/page0page.ic76
-rw-r--r--storage/innobase/include/row0ftsort.h4
-rw-r--r--storage/innobase/include/srv0srv.h5
-rw-r--r--storage/innobase/include/trx0purge.h10
-rw-r--r--storage/innobase/include/trx0rseg.h58
-rw-r--r--storage/innobase/include/trx0rseg.ic61
-rw-r--r--storage/innobase/include/trx0types.h2
-rw-r--r--storage/innobase/include/trx0undo.h146
-rw-r--r--storage/innobase/include/trx0undo.ic120
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/include/ut0byte.h10
-rw-r--r--storage/innobase/include/ut0byte.ic20
-rw-r--r--storage/innobase/log/log0log.cc10
-rw-r--r--storage/innobase/log/log0recv.cc60
-rw-r--r--storage/innobase/mtr/mtr0log.cc286
-rw-r--r--storage/innobase/os/os0file.cc42
-rw-r--r--storage/innobase/page/page0page.cc186
-rw-r--r--storage/innobase/page/page0zip.cc14
-rw-r--r--storage/innobase/row/row0ftsort.cc24
-rw-r--r--storage/innobase/row/row0import.cc80
-rw-r--r--storage/innobase/row/row0purge.cc60
-rw-r--r--storage/innobase/row/row0sel.cc9
-rw-r--r--storage/innobase/row/row0uins.cc31
-rw-r--r--storage/innobase/row/row0umod.cc49
-rw-r--r--storage/innobase/row/row0undo.cc35
-rw-r--r--storage/innobase/row/row0upd.cc5
-rw-r--r--storage/innobase/srv/srv0srv.cc5
-rw-r--r--storage/innobase/srv/srv0start.cc561
-rw-r--r--storage/innobase/trx/trx0purge.cc192
-rw-r--r--storage/innobase/trx/trx0rec.cc70
-rw-r--r--storage/innobase/trx/trx0rseg.cc276
-rw-r--r--storage/innobase/trx/trx0sys.cc36
-rw-r--r--storage/innobase/trx/trx0trx.cc18
-rw-r--r--storage/innobase/trx/trx0undo.cc869
-rw-r--r--storage/maria/ma_check.c2
-rw-r--r--storage/spider/ha_spider.cc35
-rw-r--r--storage/spider/ha_spider.h17
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_deinit.inc11
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_init.inc27
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_deinit.inc11
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_init.inc26
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/return_found_rows_insert.result179
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/return_found_rows_update.result99
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.test98
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.test78
-rw-r--r--storage/spider/spd_db_conn.cc26
-rw-r--r--storage/spider/spd_db_conn.h10
-rw-r--r--storage/spider/spd_db_handlersocket.cc16
-rw-r--r--storage/spider/spd_db_handlersocket.h5
-rw-r--r--storage/spider/spd_db_include.h6
-rw-r--r--storage/spider/spd_db_mysql.cc84
-rw-r--r--storage/spider/spd_db_mysql.h6
-rw-r--r--storage/spider/spd_db_oracle.cc16
-rw-r--r--storage/spider/spd_db_oracle.h5
-rw-r--r--tpool/aio_linux.cc9
-rw-r--r--tpool/aio_simulated.cc11
-rw-r--r--tpool/tpool.h3
163 files changed, 7345 insertions, 24550 deletions
diff --git a/.gitignore b/.gitignore
index 4e74d862823..42f654b5c6d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -173,6 +173,7 @@ sql/sql_yacc.cc
sql/sql_yacc.hh
sql/sql_yacc_ora.cc
sql/sql_yacc_ora.hh
+sql/sql_yacc_ora.yy
storage/heap/hp_test1
storage/heap/hp_test2
storage/maria/aria_chk
diff --git a/VERSION b/VERSION
index db4b7f6ec9e..873f6929850 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=10
MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=0
+MYSQL_VERSION_PATCH=1
SERVER_MATURITY=alpha
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 28a7db64250..164424a87ff 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -80,7 +80,8 @@ MYSQL_ADD_EXECUTABLE(mysqlslap mysqlslap.c)
SET_SOURCE_FILES_PROPERTIES(mysqlslap.c PROPERTIES COMPILE_FLAGS "-DTHREADS")
TARGET_LINK_LIBRARIES(mysqlslap ${CLIENT_LIB})
-MYSQL_ADD_EXECUTABLE(mariadb-conv mariadb-conv.cc)
+MYSQL_ADD_EXECUTABLE(mariadb-conv mariadb-conv.cc
+ ${CMAKE_SOURCE_DIR}/sql/sql_string.cc)
TARGET_LINK_LIBRARIES(mariadb-conv mysys strings)
# "WIN32" also covers 64 bit. "echo" is used in some files below "mysql-test/".
diff --git a/client/mariadb-conv.cc b/client/mariadb-conv.cc
index a4517e2ad25..c9185d48bbf 100644
--- a/client/mariadb-conv.cc
+++ b/client/mariadb-conv.cc
@@ -22,6 +22,8 @@
#include "mariadb.h"
#include "client_priv.h"
+#include "sql_string.h"
+#include "my_dir.h"
#define CONV_VERSION "1.0"
@@ -31,10 +33,12 @@ class CmdOpt
public:
const char *m_charset_from;
const char *m_charset_to;
+ const char *m_delimiter;
my_bool m_continue;
CmdOpt()
:m_charset_from("latin1"),
m_charset_to("latin1"),
+ m_delimiter(NULL),
m_continue(FALSE)
{ }
static CHARSET_INFO *csinfo_by_name(const char *csname)
@@ -61,9 +65,11 @@ static struct my_option long_options[] =
&opt.m_charset_from, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"to", 't', "Specifies the encoding of the output.", &opt.m_charset_to,
&opt.m_charset_to, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"continue", 'c', "When this option is given, characters that cannot be "
- "converted are silently discarded, instead of leading to a conversion error.",
+ {"continue", 'c', "Silently ignore conversion errors.",
&opt.m_continue, &opt.m_continue, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"delimiter", 0, "Treat the specified characters as delimiters.",
+ &opt.m_delimiter, &opt.m_delimiter, 0, GET_STR, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -76,69 +82,320 @@ get_one_option(const struct my_option *opt,
}
-class Conv
+class File_buffer: public Binary_string
{
- CHARSET_INFO *m_tocs;
- CHARSET_INFO *m_fromcs;
- bool m_continue;
public:
- Conv(CHARSET_INFO *tocs, CHARSET_INFO *fromcs, bool opt_continue)
- :m_tocs(tocs), m_fromcs(fromcs), m_continue(opt_continue)
- { }
- bool convert_file(FILE *infile) const;
- bool convert_file_by_name(const char *filename) const;
+ bool load_binary_stream(FILE *file);
+ bool load_binary_file_by_name(const char *file);
};
-bool Conv::convert_file(FILE *infile) const
+/*
+ Load data from a binary stream whose length is not known in advance,
+ e.g. from stdin.
+*/
+bool File_buffer::load_binary_stream(FILE *file)
+{
+ for ( ; ; )
+ {
+ char buf[1024];
+ if (length() + sizeof(buf) > UINT_MAX32 || reserve(sizeof(buf)))
+ {
+ fprintf(stderr, "Input data is too large\n");
+ return true;
+ }
+ size_t nbytes= my_fread(file, (uchar *) end(), sizeof(buf), MYF(0));
+ if (!nbytes || nbytes == (size_t) -1)
+ return false;
+ str_length+= (uint32) nbytes;
+ }
+ return false;
+}
+
+
+/*
+ Load data from a file by name.
+ The file size is know.
+*/
+bool File_buffer::load_binary_file_by_name(const char *filename)
{
- char from[FN_REFLEN + 1], to[FN_REFLEN + 2];
+ MY_STAT sbuf;
+ File fd;
- while (fgets(from, sizeof(from), infile) != NULL)
+ if (!my_stat(filename, &sbuf, MYF(0)))
+ {
+ fprintf(stderr, "my_stat failed for '%s'\n", filename);
+ return true;
+ }
+
+ if (!MY_S_ISREG(sbuf.st_mode))
{
- uint errors;
- size_t length= 0;
- for (char *s= from; s < from + sizeof(from); s++)
+ fprintf(stderr, "'%s' is not a regular file\n", filename);
+ return true;
+ }
+
+ if ((size_t) sbuf.st_size > UINT_MAX32)
+ {
+ fprintf(stderr, "File '%s' is too large\n", filename);
+ return true;
+ }
+
+ if (alloc((uint32) sbuf.st_size))
+ {
+ fprintf(stderr, "Failed to allocate read buffer\n");
+ return true;
+ }
+
+ if ((fd= my_open(filename, O_RDONLY, MYF(0))) == -1)
+ {
+ fprintf(stderr, "Could not open '%s'\n", filename);
+ return true;
+ }
+
+ size_t nbytes= my_read(fd, (uchar*) Ptr, (size_t)sbuf.st_size, MYF(0));
+ my_close(fd, MYF(0));
+ length((uint32) nbytes);
+
+ return false;
+}
+
+
+class Delimiter
+{
+protected:
+ bool m_delimiter[127];
+ bool m_has_delimiter_cached;
+ bool has_delimiter_slow() const
+ {
+ for (size_t i= 0; i < sizeof(m_delimiter); i++)
{
- if (*s == '\0' || *s == '\r' || *s == '\n')
+ if (m_delimiter[i])
+ return true;
+ }
+ return false;
+ }
+ bool unescape(char *to, char from) const
+ {
+ switch (from) {
+ case '\\': *to= '\\'; return false;
+ case 'r': *to= '\r'; return false;
+ case 'n': *to= '\n'; return false;
+ case 't': *to= '\t'; return false;
+ case '0': *to= '\0'; return false;
+ }
+ *to= '\0';
+ return true;
+ }
+ bool is_delimiter(char ch) const
+ {
+ return ch < 0 ? false : m_delimiter[(uint32) ch];
+ }
+public:
+ Delimiter()
+ :m_has_delimiter_cached(false)
+ {
+ bzero(&m_delimiter, sizeof(m_delimiter));
+ }
+ bool has_delimiter() const
+ {
+ return m_has_delimiter_cached;
+ }
+ bool set_delimiter_unescape(const char *str)
+ {
+ m_has_delimiter_cached= false;
+ for ( ; *str; str++)
+ {
+ if (*str < 0)
+ return true;
+ if (*str == '\\')
{
- *s= '\0';
- length= s - from;
- break;
+ char unescaped;
+ str++;
+ if (!*str || unescape(&unescaped, *str))
+ return true;
+ m_delimiter[(uint) unescaped]= true;
}
+ else
+ m_delimiter[(uint) *str]= true;
}
-
- if (!length)
+ m_has_delimiter_cached= has_delimiter_slow();
+ return false;
+ }
+ size_t get_delimiter_length(const char *str, const char *end) const
+ {
+ const char *str0= str;
+ for ( ; str < end; str++)
+ {
+ if (!is_delimiter(*str))
+ break;
+ }
+ return str - str0;
+ }
+ size_t get_data_length(const char *str, const char *end) const
+ {
+ const char *str0= str;
+ for ( ; str < end; str++)
{
- puts("");
- continue;
+ if (is_delimiter(*str))
+ break;
}
+ return str - str0;
+ }
+};
+
- length= my_convert(to, (uint32) (sizeof(to) - 1), m_tocs,
- from, (uint32) length, m_fromcs,
- &errors);
- to[length]= '\0';
- if (unlikely(!length || errors) && !m_continue)
+class Conv_inbuf
+{
+ const char *m_ptr;
+ const char *m_end;
+public:
+ Conv_inbuf(const char *from, size_t length)
+ :m_ptr(from), m_end(from + length)
+ { }
+ const char *ptr() const { return m_ptr; }
+ const char *end() const { return m_end; }
+ size_t length() const
+ {
+ return m_end - m_ptr;
+ }
+private:
+ LEX_CSTRING get_prefix(size_t len)
+ {
+ LEX_CSTRING res;
+ res.str= ptr();
+ res.length= len;
+ m_ptr+= len;
+ return res;
+ }
+ LEX_CSTRING get_empty_string() const
+ {
+ static LEX_CSTRING str= {NULL, 0};
+ return str;
+ }
+public:
+ LEX_CSTRING get_delimiter_chunk(const Delimiter &delimiter)
+ {
+ if (!delimiter.has_delimiter())
+ return get_empty_string();
+ size_t len= delimiter.get_delimiter_length(ptr(), end());
+ return get_prefix(len);
+ }
+ LEX_CSTRING get_data_chunk(const Delimiter &delimiter)
+ {
+ if (!delimiter.has_delimiter())
+ return get_prefix(length());
+ size_t len= delimiter.get_data_length(ptr(), end());
+ return get_prefix(len);
+ }
+};
+
+
+class Conv_outbuf: public Binary_string
+{
+public:
+ bool alloc(size_t out_max_length)
+ {
+ if (out_max_length >= UINT_MAX32)
+ {
+ fprintf(stderr, "The data needs a too large output buffer\n");
return true;
- else
- puts(to);
+ }
+ if (Binary_string::alloc((uint32) out_max_length))
+ {
+ fprintf(stderr, "Failed to allocate the output buffer\n");
+ return true;
+ }
+ return false;
}
+};
- return false;
-} /* convert */
+
+class Conv: public String_copier, public Delimiter
+{
+ CHARSET_INFO *m_tocs;
+ CHARSET_INFO *m_fromcs;
+ bool m_continue;
+public:
+ Conv(CHARSET_INFO *tocs, CHARSET_INFO *fromcs, bool opt_continue)
+ :m_tocs(tocs), m_fromcs(fromcs), m_continue(opt_continue)
+ { }
+ size_t out_buffer_max_length(size_t from_length) const
+ {
+ return from_length / m_fromcs->mbminlen * m_tocs->mbmaxlen;
+ }
+ bool convert_data(const char *from, size_t length);
+ bool convert_binary_stream(FILE *file)
+ {
+ File_buffer buf;
+ return buf.load_binary_stream(file) ||
+ convert_data(buf.ptr(), buf.length());
+ }
+ bool convert_binary_file_by_name(const char *filename)
+ {
+ File_buffer buf;
+ return buf.load_binary_file_by_name(filename)||
+ convert_data(buf.ptr(), buf.length());
+ }
+private:
+ void report_error(const char *from) const
+ {
+ if (well_formed_error_pos())
+ {
+ fflush(stdout);
+ fprintf(stderr,
+ "Illegal %s byte sequence at position %d\n",
+ m_fromcs->csname,
+ (uint) (well_formed_error_pos() - from));
+ }
+ else if (cannot_convert_error_pos())
+ {
+ fflush(stdout);
+ fprintf(stderr,
+ "Conversion from %s to %s failed at position %d\n",
+ m_fromcs->csname, m_tocs->csname,
+ (uint) (cannot_convert_error_pos() - from));
+ }
+ }
+ size_t write(const char *str, size_t length) const
+ {
+ return my_fwrite(stdout, (uchar *) str, length, MY_WME);
+ }
+};
-bool Conv::convert_file_by_name(const char *filename) const
+bool Conv::convert_data(const char *from, size_t from_length)
{
- FILE *fp;
- if ((fp= fopen(filename, "r")) == NULL)
+ Conv_inbuf inbuf(from, from_length);
+ Conv_outbuf outbuf;
+
+ if (outbuf.alloc(out_buffer_max_length(from_length)))
+ return true;
+
+ for ( ; ; )
{
- printf("can't open file %s", filename);
- return 1;
+ LEX_CSTRING delim, data;
+
+ delim= inbuf.get_delimiter_chunk(*this);
+ if (delim.length)
+ write(delim.str, delim.length);
+
+ data= inbuf.get_data_chunk(*this);
+ if (!data.length)
+ break;
+ size_t length= well_formed_copy(m_tocs,
+ (char *) outbuf.ptr(),
+ outbuf.alloced_length(),
+ m_fromcs, data.str, data.length);
+ outbuf.length((uint32) length);
+
+ if (most_important_error_pos() && !m_continue)
+ {
+ report_error(from);
+ return true;
+ }
+ write(outbuf.ptr(), outbuf.length());
}
- bool rc= convert_file(fp);
- fclose(fp);
- return rc;
+ return false;
}
@@ -159,7 +416,7 @@ public:
MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
puts("Character set conversion utility for MariaDB");
puts("Usage:");
- printf("%s [-f encoding] [-t encoding] [inputfile]...\n", my_progname);
+ printf("%s [OPTION...] [FILE...]\n", my_progname);
my_print_help(long_options);
}
};
@@ -190,17 +447,32 @@ int main(int argc, char *argv[])
}
Conv conv(charset_info_to, charset_info_from, opt.m_continue);
+ if (opt.m_delimiter)
+ {
+ if (charset_info_from->mbminlen > 1 ||
+ charset_info_to->mbminlen > 1)
+ {
+ fprintf(stderr, "--delimiter cannot be used with %s to %s conversion\n",
+ charset_info_from->csname, charset_info_to->csname);
+ return 1;
+ }
+ if (conv.set_delimiter_unescape(opt.m_delimiter))
+ {
+ fprintf(stderr, "Bad --delimiter value\n");
+ return 1;
+ }
+ }
if (argc == 0)
{
- if (conv.convert_file(stdin))
+ if (conv.convert_binary_stream(stdin))
return 1;
}
else
{
for (int i= 0; i < argc; i++)
{
- if (conv.convert_file_by_name(argv[i]))
+ if (conv.convert_binary_file_by_name(argv[i]))
return 1;
}
}
diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake
index f001ff11387..90b4cab53f8 100644
--- a/cmake/cpack_rpm.cmake
+++ b/cmake/cpack_rpm.cmake
@@ -195,7 +195,7 @@ MACRO(ALTERNATIVE_NAME real alt)
SET(p "CPACK_RPM_${real}_PACKAGE_PROVIDES")
SET(${p} "${${p}} ${alt} = ${ver} ${alt}%{?_isa} = ${ver} config(${alt}) = ${ver}")
SET(o "CPACK_RPM_${real}_PACKAGE_OBSOLETES")
- SET(${o} "${${o}} ${alt} ${alt}%{?_isa}")
+ SET(${o} "${${o}} ${alt}")
ENDMACRO(ALTERNATIVE_NAME)
ALTERNATIVE_NAME("devel" "mysql-devel")
@@ -215,8 +215,9 @@ ELSEIF(RPM MATCHES "fedora" OR RPM MATCHES "(rhel|centos)7")
ALTERNATIVE_NAME("server" "mariadb-server")
ALTERNATIVE_NAME("server" "mysql-compat-server")
ALTERNATIVE_NAME("test" "mariadb-test")
-ELSEIF(RPM MATCHES "(rhel|centos)8")
- SET(PYTHON_SHEBANG "/usr/bin/python3")
+ENDIF()
+IF(RPM MATCHES "fedora31" OR RPM MATCHES "(rhel|centos)8")
+ SET(PYTHON_SHEBANG "/usr/bin/python3" CACHE STRING "python shebang")
ENDIF()
# If we want to build build MariaDB-shared-compat,
@@ -249,6 +250,7 @@ IF(compat53 AND compat101)
STRING(REPLACE "\n" " " compat_provides "${compat_provides}")
STRING(REPLACE "\n" " " compat_obsoletes "${compat_obsoletes}")
+ STRING(REGEX REPLACE "[^ ]+\\([^ ]+ *" "" compat_obsoletes "${compat_obsoletes}")
SETA(CPACK_RPM_compat_PACKAGE_PROVIDES "${compat_provides}")
SETA(CPACK_RPM_compat_PACKAGE_OBSOLETES "${compat_obsoletes}")
diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc
index 3bc00b339b1..dae032ecd74 100644
--- a/extra/innochecksum.cc
+++ b/extra/innochecksum.cc
@@ -1551,8 +1551,6 @@ int main(
/* our input filename. */
char* filename;
/* Buffer to store pages read. */
- byte* buf_ptr = NULL;
- byte* xdes_ptr = NULL;
byte* buf = NULL;
byte* xdes = NULL;
/* bytes read count */
@@ -1632,10 +1630,10 @@ int main(
}
- buf_ptr = (byte*) malloc(UNIV_PAGE_SIZE_MAX * 2);
- xdes_ptr = (byte*)malloc(UNIV_PAGE_SIZE_MAX * 2);
- buf = (byte *) ut_align(buf_ptr, UNIV_PAGE_SIZE_MAX);
- xdes = (byte *) ut_align(xdes_ptr, UNIV_PAGE_SIZE_MAX);
+ buf = static_cast<byte*>(aligned_malloc(UNIV_PAGE_SIZE_MAX,
+ UNIV_PAGE_SIZE_MAX));
+ xdes = static_cast<byte*>(aligned_malloc(UNIV_PAGE_SIZE_MAX,
+ UNIV_PAGE_SIZE_MAX));
/* The file name is not optional. */
for (int i = 0; i < argc; ++i) {
@@ -2014,21 +2012,9 @@ first_non_zero:
fclose(log_file);
}
- free(buf_ptr);
- free(xdes_ptr);
-
- my_end(exit_status);
- DBUG_RETURN(exit_status);
+ goto common_exit;
my_exit:
- if (buf_ptr) {
- free(buf_ptr);
- }
-
- if (xdes_ptr) {
- free(xdes_ptr);
- }
-
if (!read_from_stdin && fil_in) {
fclose(fil_in);
}
@@ -2037,6 +2023,9 @@ my_exit:
fclose(log_file);
}
+common_exit:
+ aligned_free(buf);
+ aligned_free(xdes);
my_end(exit_status);
DBUG_RETURN(exit_status);
}
diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc
index 6ede0288e3a..ed977931423 100644
--- a/extra/mariabackup/backup_copy.cc
+++ b/extra/mariabackup/backup_copy.cc
@@ -466,14 +466,13 @@ struct datafile_cur_t {
char abs_path[FN_REFLEN];
MY_STAT statinfo;
uint thread_n;
- byte* orig_buf;
byte* buf;
size_t buf_size;
size_t buf_read;
size_t buf_offset;
explicit datafile_cur_t(const char* filename = NULL) :
- file(), thread_n(0), orig_buf(NULL), buf(NULL), buf_size(0),
+ file(), thread_n(0), buf(NULL), buf_size(0),
buf_read(0), buf_offset(0)
{
memset(rel_path, 0, sizeof rel_path);
diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc
index 453aab802c9..d1b2275a845 100644
--- a/extra/mariabackup/fil_cur.cc
+++ b/extra/mariabackup/fil_cur.cc
@@ -142,7 +142,7 @@ xb_fil_cur_open(
int err;
/* Initialize these first so xb_fil_cur_close() handles them correctly
in case of error */
- cursor->orig_buf = NULL;
+ cursor->buf = NULL;
cursor->node = NULL;
cursor->space_id = node->space->id;
@@ -238,10 +238,8 @@ xb_fil_cur_open(
/* Allocate read buffer */
cursor->buf_size = XB_FIL_CUR_PAGES * cursor->page_size;
- cursor->orig_buf = static_cast<byte *>
- (malloc(cursor->buf_size + srv_page_size));
- cursor->buf = static_cast<byte *>
- (ut_align(cursor->orig_buf, srv_page_size));
+ cursor->buf = static_cast<byte*>(aligned_malloc(cursor->buf_size,
+ srv_page_size));
cursor->buf_read = 0;
cursor->buf_npages = 0;
@@ -494,7 +492,8 @@ xb_fil_cur_close(
cursor->read_filter->deinit(&cursor->read_filter_ctxt);
}
- free(cursor->orig_buf);
+ aligned_free(cursor->buf);
+ cursor->buf = NULL;
if (cursor->node != NULL) {
xb_fil_node_close_file(cursor->node);
diff --git a/extra/mariabackup/fil_cur.h b/extra/mariabackup/fil_cur.h
index b789efde05f..70e4888ba63 100644
--- a/extra/mariabackup/fil_cur.h
+++ b/extra/mariabackup/fil_cur.h
@@ -44,8 +44,7 @@ struct xb_fil_cur_t {
xb_read_filt_t* read_filter; /*!< read filter */
xb_read_filt_ctxt_t read_filter_ctxt;
/*!< read filter context */
- byte* orig_buf; /*!< read buffer */
- byte* buf; /*!< aligned pointer for orig_buf */
+ byte* buf; /*!< read buffer */
size_t buf_size; /*!< buffer size in bytes */
size_t buf_read; /*!< number of read bytes in buffer
after the last cursor read */
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 03a82bfc58b..c53c9037bda 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -3269,8 +3269,6 @@ static dberr_t xb_assign_undo_space_start()
{
pfs_os_file_t file;
- byte* buf;
- byte* page;
bool ret;
dberr_t error = DB_SUCCESS;
ulint space;
@@ -3289,8 +3287,8 @@ static dberr_t xb_assign_undo_space_start()
return DB_ERROR;
}
- buf = static_cast<byte*>(ut_malloc_nokey(2U << srv_page_size_shift));
- page = static_cast<byte*>(ut_align(buf, srv_page_size));
+ byte* page = static_cast<byte*>
+ (aligned_malloc(srv_page_size, srv_page_size));
if (os_file_read(IORequestRead, file, page, 0, srv_page_size)
!= DB_SUCCESS) {
@@ -3337,7 +3335,7 @@ retry:
srv_undo_space_id_start = space;
func_exit:
- ut_free(buf);
+ aligned_free(page);
ret = os_file_close(file);
ut_a(ret);
@@ -4552,8 +4550,6 @@ xb_space_create_file(
pfs_os_file_t* file) /*!<out: file handle */
{
bool ret;
- byte* buf;
- byte* page;
*file = os_file_create_simple_no_error_handling(
0, path, OS_FILE_CREATE, OS_FILE_READ_WRITE, false, &ret);
@@ -4572,9 +4568,9 @@ xb_space_create_file(
return ret;
}
- buf = static_cast<byte *>(malloc(3U << srv_page_size_shift));
/* Align the memory for file i/o if we might have O_DIRECT set */
- page = static_cast<byte *>(ut_align(buf, srv_page_size));
+ byte* page = static_cast<byte*>(aligned_malloc(2 * srv_page_size,
+ srv_page_size));
memset(page, '\0', srv_page_size);
@@ -4608,7 +4604,7 @@ xb_space_create_file(
page_zip.data, 0, zip_size);
}
- free(buf);
+ aligned_free(page);
if (ret != DB_SUCCESS) {
msg("mariabackup: could not write the first page to %s",
@@ -4821,8 +4817,7 @@ xtrabackup_apply_delta(
xb_delta_info_t info(srv_page_size, 0, SRV_TMP_SPACE_ID);
ulint page_size;
ulint page_size_shift;
- byte* incremental_buffer_base = NULL;
- byte* incremental_buffer;
+ byte* incremental_buffer = NULL;
size_t offset;
@@ -4890,11 +4885,8 @@ xtrabackup_apply_delta(
posix_fadvise(dst_file, 0, 0, POSIX_FADV_DONTNEED);
/* allocate buffer for incremental backup (4096 pages) */
- incremental_buffer_base = static_cast<byte *>
- (malloc((page_size / 4 + 1) * page_size));
incremental_buffer = static_cast<byte *>
- (ut_align(incremental_buffer_base,
- page_size));
+ (aligned_malloc(page_size / 4 * page_size, page_size));
msg("Applying %s to %s...", src_path, dst_path);
@@ -5003,7 +4995,7 @@ xtrabackup_apply_delta(
incremental_buffers++;
}
- free(incremental_buffer_base);
+ aligned_free(incremental_buffer);
if (src_file != OS_FILE_CLOSED) {
os_file_close(src_file);
os_file_delete(0,src_path);
@@ -5013,7 +5005,7 @@ xtrabackup_apply_delta(
return TRUE;
error:
- free(incremental_buffer_base);
+ aligned_free(incremental_buffer);
if (src_file != OS_FILE_CLOSED)
os_file_close(src_file);
if (dst_file != OS_FILE_CLOSED)
diff --git a/include/lf.h b/include/lf.h
index fa8c2d3570c..933eb4938f8 100644
--- a/include/lf.h
+++ b/include/lf.h
@@ -65,7 +65,6 @@ typedef struct {
typedef struct {
void * volatile pin[LF_PINBOX_PINS];
LF_PINBOX *pinbox;
- void **stack_ends_here;
void *purgatory;
uint32 purgatory_count;
uint32 volatile link;
diff --git a/mysql-test/std_data/mariadb-conv/file01.utf16.txt b/mysql-test/std_data/mariadb-conv/file01.utf16.txt
new file mode 100644
index 00000000000..1ff100e48a1
--- /dev/null
+++ b/mysql-test/std_data/mariadb-conv/file01.utf16.txt
Binary files differ
diff --git a/mysql-test/std_data/mariadb-conv/file01.utf8.txt b/mysql-test/std_data/mariadb-conv/file01.utf8.txt
new file mode 100644
index 00000000000..cc065b71877
--- /dev/null
+++ b/mysql-test/std_data/mariadb-conv/file01.utf8.txt
@@ -0,0 +1,3 @@
+aaa
+xxxÑÑÑxxx
+bbb
diff --git a/mysql-test/std_data/mariadb-conv/file02.latin1.txt b/mysql-test/std_data/mariadb-conv/file02.latin1.txt
new file mode 100644
index 00000000000..28648e6f1e1
--- /dev/null
+++ b/mysql-test/std_data/mariadb-conv/file02.latin1.txt
@@ -0,0 +1,3 @@
+aaa
+xxxßßßxxx
+bbb
diff --git a/mysql-test/suite/client/mariadb-conv-cp932.result b/mysql-test/suite/client/mariadb-conv-cp932.result
index e18e36b81c9..efa428b9dde 100644
--- a/mysql-test/suite/client/mariadb-conv-cp932.result
+++ b/mysql-test/suite/client/mariadb-conv-cp932.result
@@ -21,6 +21,8 @@ BINARY CONVERT(a USING filename)
‘ªŽŽŽ‘—¿2
test/‘ªŽŽŽ‘—¿.frm
test/‘ªŽŽŽ‘—¿2.frm
+test/‘ªŽŽŽ‘—¿.frm
+test/‘ªŽŽŽ‘—¿2.frm
DROP TABLE t1;
# bulk convert with file
# --- Start of mariadb-conv for mysql-conv-test-cp932.txt ---
diff --git a/mysql-test/suite/client/mariadb-conv-cp932.test b/mysql-test/suite/client/mariadb-conv-cp932.test
index 40c9ba64044..1a9263b3f90 100644
--- a/mysql-test/suite/client/mariadb-conv-cp932.test
+++ b/mysql-test/suite/client/mariadb-conv-cp932.test
@@ -10,26 +10,27 @@ SET NAMES cp932;
--let $MYSQLD_DATADIR= `select @@datadir`
# simple I/O
---exec echo "‘ªŽŽŽ‘—¿" | $MARIADB_CONV -f cp932 -t filename
---exec echo "@6e2c@8a66@8cc7@6599@5eab" | $MARIADB_CONV -f filename -t cp932
+--exec echo "‘ªŽŽŽ‘—¿" | $MARIADB_CONV -f cp932 -t filename --delimiter="\r\n"
+--exec echo "@6e2c@8a66@8cc7@6599@5eab" | $MARIADB_CONV -f filename -t cp932 --delimiter="\r\n"
# undo query result
--let $query_result=`SELECT CONVERT(CONVERT('‘ªŽŽŽ‘—¿' USING filename) USING binary);`
--echo $query_result
---exec echo $query_result | $MARIADB_CONV -f filename -t cp932
+--exec echo $query_result | $MARIADB_CONV -f filename -t cp932 --delimiter="\r\n"
--let $reverse_query_result=`SELECT CONVERT(_filename '@6e2c@8a66@8cc7@6599@5eab' USING cp932);`
--echo $reverse_query_result
---exec echo $reverse_query_result | $MARIADB_CONV -f cp932 -t filename
+--exec echo $reverse_query_result | $MARIADB_CONV -f cp932 -t filename --delimiter="\r\n"
--echo # bulk convert with pipe
CREATE TABLE t1 (id SERIAL, a VARCHAR(64) CHARACTER SET cp932);
INSERT INTO t1 (a) VALUES ('‘ªŽŽŽ‘—¿'), ('‘ªŽŽŽ‘—¿2');
---exec $MYSQL -Dtest --default-character-set=cp932 -e "SELECT a FROM t1 ORDER BY id" | $MARIADB_CONV -f cp932 -t filename
+--exec $MYSQL -Dtest --default-character-set=cp932 -e "SELECT a FROM t1 ORDER BY id" | $MARIADB_CONV -f cp932 -t filename --delimiter="\r\n"
--exec $MYSQL -Dtest --default-character-set=cp932 -e "SELECT BINARY CONVERT(a USING filename) FROM t1 ORDER BY id"
---exec $MYSQL -Dtest --default-character-set=cp932 --column-names=0 -e "SELECT BINARY CONVERT(a USING filename) FROM t1 ORDER BY id" | $MARIADB_CONV -f filename -t cp932
---exec $MYSQL -Dtest --default-character-set=cp932 --column-names=0 -e "SELECT CONCAT('test/', BINARY CONVERT(a USING filename),'.frm') FROM t1 ORDER BY id" | $REPLACE "/" "@002f" "." "@002e"| $MARIADB_CONV -f filename -t cp932
+--exec $MYSQL -Dtest --default-character-set=cp932 --column-names=0 -e "SELECT BINARY CONVERT(a USING filename) FROM t1 ORDER BY id" | $MARIADB_CONV -f filename -t cp932 --delimiter="\r\n"
+--exec $MYSQL -Dtest --default-character-set=cp932 --column-names=0 -e "SELECT CONCAT('test/', BINARY CONVERT(a USING filename),'.frm') FROM t1 ORDER BY id" | $REPLACE "/" "@002f" "." "@002e"| $MARIADB_CONV -f filename -t cp932 --delimiter="\r\n"
+--exec $MYSQL -Dtest --default-character-set=cp932 --column-names=0 -e "SELECT CONCAT('test/', BINARY CONVERT(a USING filename),'.frm') FROM t1 ORDER BY id" | $MARIADB_CONV -f filename -t cp932 --delimiter="/.\r\n"
DROP TABLE t1;
@@ -44,12 +45,12 @@ DROP TABLE t1;
EOF
--echo # --- Start of mariadb-conv for mysql-conv-test-cp932.txt ---
---exec $MARIADB_CONV -f cp932 -t filename $MYSQL_TMP_DIR/mysql-conv-test-cp932.txt
+--exec $MARIADB_CONV -f cp932 -t filename --delimiter="\r\n" $MYSQL_TMP_DIR/mysql-conv-test-cp932.txt
--echo # --- End of mariadb-conv for mysql-conv-test-cp932.txt ---
--copy_file $MYSQL_TMP_DIR/mysql-conv-test-cp932.txt $MYSQL_TMP_DIR/mysql-conv-test-cp932-2.txt
--echo # --- Start of mariadb-conv for mysql-conv-test-cp932.txt and mysql-conv-test-cp932-2.txt ---
---exec $MARIADB_CONV -f cp932 -t filename $MYSQL_TMP_DIR/mysql-conv-test-cp932.txt $MYSQL_TMP_DIR/mysql-conv-test-cp932-2.txt
+--exec $MARIADB_CONV -f cp932 -t filename --delimiter="\r\n" $MYSQL_TMP_DIR/mysql-conv-test-cp932.txt $MYSQL_TMP_DIR/mysql-conv-test-cp932-2.txt
--echo # --- Start of mariadb-conv for mysql-conv-test-cp932.txt and mysql-conv-test-cp932-2.txt ---
--remove_file $MYSQL_TMP_DIR/mysql-conv-test-cp932.txt
diff --git a/mysql-test/suite/client/mariadb-conv-utf16.result b/mysql-test/suite/client/mariadb-conv-utf16.result
new file mode 100644
index 00000000000..76b98ef81ce
--- /dev/null
+++ b/mysql-test/suite/client/mariadb-conv-utf16.result
@@ -0,0 +1,13 @@
+#
+# MDEV-17088 Provide tools to encode/decode mysql-encoded file system names
+#
+SET NAMES utf8;
+# Bad delimiter
+--delimiter cannot be used with utf16 to utf8 conversion
+# Bad delimiter
+--delimiter cannot be used with utf8 to utf16 conversion
+# Start of file01.utf16.txt
+aaa
+xxxÑÑÑxxx
+bbb
+# End of file01.utf16.txt
diff --git a/mysql-test/suite/client/mariadb-conv-utf16.test b/mysql-test/suite/client/mariadb-conv-utf16.test
new file mode 100644
index 00000000000..98f9e8d28f1
--- /dev/null
+++ b/mysql-test/suite/client/mariadb-conv-utf16.test
@@ -0,0 +1,21 @@
+-- source include/have_utf16.inc
+-- source include/not_embedded.inc
+
+--echo #
+--echo # MDEV-17088 Provide tools to encode/decode mysql-encoded file system names
+--echo #
+
+--character_set utf8
+SET NAMES utf8;
+
+--echo # Bad delimiter
+--error 1
+--exec $MARIADB_CONV -f utf16 -t utf8 --delimiter="\r\n" $MYSQL_TEST_DIR/std_data/mariadb-conv/file01.utf16.txt 2>&1
+
+--echo # Bad delimiter
+--error 1
+--exec $MARIADB_CONV -f utf8 -t utf16 --delimiter="\r\n" $MYSQL_TEST_DIR/std_data/mariadb-conv/file01.utf8.txt 2>&1
+
+--echo # Start of file01.utf16.txt
+--exec $MARIADB_CONV -f utf16 -t utf8 $MYSQL_TEST_DIR/std_data/mariadb-conv/file01.utf16.txt 2>&1
+--echo # End of file01.utf16.txt
diff --git a/mysql-test/suite/client/mariadb-conv-utf8.result b/mysql-test/suite/client/mariadb-conv-utf8.result
index b38cb118c72..cae8268d523 100644
--- a/mysql-test/suite/client/mariadb-conv-utf8.result
+++ b/mysql-test/suite/client/mariadb-conv-utf8.result
@@ -21,6 +21,8 @@ BINARY CONVERT(a USING filename)
測試資料2
test/測試資料.frm
test/測試資料2.frm
+test/測試資料.frm
+test/測試資料2.frm
DROP TABLE t1;
# bulk convert with file
# --- Start of mariadb-conv for mysql-conv-test-utf8.txt ---
diff --git a/mysql-test/suite/client/mariadb-conv-utf8.test b/mysql-test/suite/client/mariadb-conv-utf8.test
index 2d5bfb4efe9..5002aadd6e9 100644
--- a/mysql-test/suite/client/mariadb-conv-utf8.test
+++ b/mysql-test/suite/client/mariadb-conv-utf8.test
@@ -10,26 +10,27 @@ SET NAMES utf8;
--let $MYSQLD_DATADIR= `select @@datadir`
# simple I/O
---exec echo "測試資料" | $MARIADB_CONV -f utf8 -t filename
---exec echo "@6e2c@8a66@8cc7@6599@5eab" | $MARIADB_CONV -f filename -t utf8
+--exec echo "測試資料" | $MARIADB_CONV -f utf8 -t filename --delimiter="\r\n"
+--exec echo "@6e2c@8a66@8cc7@6599@5eab" | $MARIADB_CONV -f filename -t utf8 --delimiter="\r\n"
# undo query result
--let $query_result=`SELECT CONVERT(CONVERT('測試資料' USING filename) USING binary);`
--echo $query_result
---exec echo $query_result | $MARIADB_CONV -f filename -t utf8
+--exec echo $query_result | $MARIADB_CONV -f filename -t utf8 --delimiter="\r\n"
--let $reverse_query_result=`SELECT CONVERT(_filename '@6e2c@8a66@8cc7@6599@5eab' USING utf8);`
--echo $reverse_query_result
---exec echo $reverse_query_result | $MARIADB_CONV -f utf8 -t filename
+--exec echo $reverse_query_result | $MARIADB_CONV -f utf8 -t filename --delimiter="\r\n"
--echo # bulk convert with pipe
CREATE TABLE t1 (id SERIAL, a VARCHAR(64) CHARACTER SET utf8);
INSERT INTO t1 (a) VALUES ('測試資料'), ('測試資料2');
---exec $MYSQL -Dtest --default-character-set=utf8 -e "SELECT a FROM t1 ORDER BY id" | $MARIADB_CONV -f utf8 -t filename
+--exec $MYSQL -Dtest --default-character-set=utf8 -e "SELECT a FROM t1 ORDER BY id" | $MARIADB_CONV -f utf8 -t filename --delimiter="\r\n"
--exec $MYSQL -Dtest --default-character-set=utf8 -e "SELECT BINARY CONVERT(a USING filename) FROM t1 ORDER BY id"
---exec $MYSQL -Dtest --default-character-set=utf8 --column-names=0 -e "SELECT BINARY CONVERT(a USING filename) FROM t1 ORDER BY id" | $MARIADB_CONV -f filename -t utf8
---exec $MYSQL -Dtest --default-character-set=utf8 --column-names=0 -e "SELECT CONCAT('test/', BINARY CONVERT(a USING filename),'.frm') FROM t1 ORDER BY id" | $REPLACE "/" "@002f" "." "@002e"| $MARIADB_CONV -f filename -t utf8
+--exec $MYSQL -Dtest --default-character-set=utf8 --column-names=0 -e "SELECT BINARY CONVERT(a USING filename) FROM t1 ORDER BY id" | $MARIADB_CONV -f filename -t utf8 --delimiter="\r\n"
+--exec $MYSQL -Dtest --default-character-set=utf8 --column-names=0 -e "SELECT CONCAT('test/', BINARY CONVERT(a USING filename),'.frm') FROM t1 ORDER BY id" | $REPLACE "/" "@002f" "." "@002e"| $MARIADB_CONV -f filename -t utf8 --delimiter="\r\n"
+--exec $MYSQL -Dtest --default-character-set=utf8 --column-names=0 -e "SELECT CONCAT('test/', BINARY CONVERT(a USING filename),'.frm') FROM t1 ORDER BY id" | $MARIADB_CONV -f filename -t utf8 --delimiter="/.\r\n"
DROP TABLE t1;
@@ -44,12 +45,12 @@ DROP TABLE t1;
EOF
--echo # --- Start of mariadb-conv for mysql-conv-test-utf8.txt ---
---exec $MARIADB_CONV -f utf8 -t filename $MYSQL_TMP_DIR/mysql-conv-test-utf8.txt
+--exec $MARIADB_CONV -f utf8 -t filename --delimiter="\r\n" $MYSQL_TMP_DIR/mysql-conv-test-utf8.txt
--echo # --- End of mariadb-conv for mysql-conv-test-utf8.txt ---
--copy_file $MYSQL_TMP_DIR/mysql-conv-test-utf8.txt $MYSQL_TMP_DIR/mysql-conv-test-utf8-2.txt
--echo # --- Start of mariadb-conv for mysql-conv-test-utf8.txt and mysql-conv-test-utf8-2.txt ---
---exec $MARIADB_CONV -f utf8 -t filename $MYSQL_TMP_DIR/mysql-conv-test-utf8.txt $MYSQL_TMP_DIR/mysql-conv-test-utf8-2.txt
+--exec $MARIADB_CONV -f utf8 -t filename --delimiter="\r\n" $MYSQL_TMP_DIR/mysql-conv-test-utf8.txt $MYSQL_TMP_DIR/mysql-conv-test-utf8-2.txt
--echo # --- Start of mariadb-conv for mysql-conv-test-utf8.txt and mysql-conv-test-utf8-2.txt ---
--remove_file $MYSQL_TMP_DIR/mysql-conv-test-utf8.txt
diff --git a/mysql-test/suite/client/mariadb-conv.result b/mysql-test/suite/client/mariadb-conv.result
index 1677a13de1d..432be04daae 100644
--- a/mysql-test/suite/client/mariadb-conv.result
+++ b/mysql-test/suite/client/mariadb-conv.result
@@ -11,3 +11,15 @@ mariadb-conv: unknown option '-r'
Character set unknown-cs is not supported
# unknown "from" character set
Character set unknown-cs is not supported
+# Bad delimiter
+Bad --delimiter value
+# Conversion error
+Conversion from utf8 to latin1 failed at position 7
+aaa
+xxx???xxx
+bbb
+# Bad input character
+Illegal utf8 byte sequence at position 7
+aaa
+xxx???xxx
+bbb
diff --git a/mysql-test/suite/client/mariadb-conv.test b/mysql-test/suite/client/mariadb-conv.test
index 2046b876b69..2be758b6fcf 100644
--- a/mysql-test/suite/client/mariadb-conv.test
+++ b/mysql-test/suite/client/mariadb-conv.test
@@ -6,8 +6,8 @@
--echo # default encoding
--exec echo "t1" | $MARIADB_CONV
---exec echo "t1" | $MARIADB_CONV -f filename
---exec echo "t1" | $MARIADB_CONV -t filename
+--exec echo "t1" | $MARIADB_CONV -f filename --delimiter="\r\n"
+--exec echo "t1" | $MARIADB_CONV -t filename --delimiter="\r\n"
--echo # invalid option
--replace_regex /.*mariadb-conv.*: unknown/mariadb-conv: unknown/
@@ -23,3 +23,17 @@
--replace_regex /.*mariadb-conv.*: unknown/mariadb-conv: unknown/
--error 1
--exec echo "t1" | $MARIADB_CONV -f unknown-cs -t latin1 2>&1 > /dev/null
+
+--echo # Bad delimiter
+--error 1
+--exec echo "t1" | $MARIADB_CONV --delimiter="\x" 2>&1 > /dev/null
+
+--echo # Conversion error
+--error 1
+--exec $MARIADB_CONV -f utf8 -t latin1 < $MYSQL_TEST_DIR/std_data/mariadb-conv/file01.utf8.txt 2>&1
+--exec $MARIADB_CONV -f utf8 -t latin1 -c < $MYSQL_TEST_DIR/std_data/mariadb-conv/file01.utf8.txt 2>&1
+
+--echo # Bad input character
+--error 1
+--exec $MARIADB_CONV -f utf8 -t latin1 < $MYSQL_TEST_DIR/std_data/mariadb-conv/file02.latin1.txt 2>&1
+--exec $MARIADB_CONV -f utf8 -t latin1 -c < $MYSQL_TEST_DIR/std_data/mariadb-conv/file02.latin1.txt 2>&1
diff --git a/mysql-test/suite/innodb/r/log_file.result b/mysql-test/suite/innodb/r/log_file.result
index a4599ef303f..afcc5dd47e9 100644
--- a/mysql-test/suite/innodb/r/log_file.result
+++ b/mysql-test/suite/innodb/r/log_file.result
@@ -217,7 +217,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
-FOUND 1 /InnoDB: Unable to open undo tablespace.*undo002/ in mysqld.1.err
+FOUND 1 /InnoDB: Expected to open innodb_undo_tablespaces=3 but was able to find only 1/ in mysqld.1.err
bak_ib_logfile0
bak_ib_logfile1
bak_ib_logfile2
@@ -255,7 +255,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
-FOUND 1 /InnoDB: Unable to open undo tablespace.*undo001/ in mysqld.1.err
+FOUND 1 /InnoDB: Expected to open innodb_undo_tablespaces=3 but was able to find only 0/ in mysqld.1.err
bak_ib_logfile0
bak_ib_logfile1
bak_ib_logfile2
diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test
index 87ff74a7d51..3bcc5d835e5 100644
--- a/mysql-test/suite/innodb/t/doublewrite.test
+++ b/mysql-test/suite/innodb/t/doublewrite.test
@@ -19,8 +19,9 @@ call mtr.add_suppression("InnoDB: New log files created");
call mtr.add_suppression("InnoDB: Cannot create doublewrite buffer: the first file in innodb_data_file_path must be at least (3|6|12)M\\.");
call mtr.add_suppression("InnoDB: Database creation was aborted");
call mtr.add_suppression("Plugin 'InnoDB' (init function returned error|registration as a STORAGE ENGINE failed)");
-call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile.*");
-call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: .*");
+call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile");
+call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: ");
+call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd");
--enable_query_log
--source include/restart_mysqld.inc
diff --git a/mysql-test/suite/innodb/t/log_file.test b/mysql-test/suite/innodb/t/log_file.test
index 8a82ab7f29f..5c2f44303da 100644
--- a/mysql-test/suite/innodb/t/log_file.test
+++ b/mysql-test/suite/innodb/t/log_file.test
@@ -171,7 +171,7 @@ let SEARCH_PATTERN=undo tablespace .*undo003.* exists\. Creating system tablespa
--source include/start_mysqld.inc
eval $check_no_innodb;
--source include/shutdown_mysqld.inc
-let SEARCH_PATTERN=InnoDB: Unable to open undo tablespace.*undo002;
+let SEARCH_PATTERN=InnoDB: Expected to open innodb_undo_tablespaces=3 but was able to find only 1;
--source include/search_pattern_in_file.inc
# clean up & Restore
--source ../include/log_file_cleanup.inc
@@ -183,7 +183,7 @@ let SEARCH_PATTERN=InnoDB: Unable to open undo tablespace.*undo002;
--source include/start_mysqld.inc
eval $check_no_innodb;
--source include/shutdown_mysqld.inc
-let SEARCH_PATTERN=InnoDB: Unable to open undo tablespace.*undo001;
+let SEARCH_PATTERN=InnoDB: Expected to open innodb_undo_tablespaces=3 but was able to find only 0;
--source include/search_pattern_in_file.inc
# clean up & Restore
diff --git a/mysql-test/suite/mariabackup/undo_space_id.result b/mysql-test/suite/mariabackup/undo_space_id.result
index 96d3e2a58f4..b03b9705569 100644
--- a/mysql-test/suite/mariabackup/undo_space_id.result
+++ b/mysql-test/suite/mariabackup/undo_space_id.result
@@ -1,13 +1,13 @@
-# Create 2 UNDO TABLESPACE(UNDO003, UNDO004)
+# Create 2 UNDO TABLESPACE(UNDO001(space_id =3), UNDO002(space_id =4))
CREATE TABLE t1(a varchar(60)) ENGINE INNODB;
start transaction;
INSERT INTO t1 VALUES(1);
# xtrabackup backup
# Display undo log files from target directory
-undo003
-undo004
+undo001
+undo002
# xtrabackup prepare
# Display undo log files from targer directory
-undo003
-undo004
+undo001
+undo002
DROP TABLE t1;
diff --git a/mysql-test/suite/mariabackup/undo_space_id.test b/mysql-test/suite/mariabackup/undo_space_id.test
index 8adeb18e5a7..b582554b28a 100644
--- a/mysql-test/suite/mariabackup/undo_space_id.test
+++ b/mysql-test/suite/mariabackup/undo_space_id.test
@@ -1,7 +1,7 @@
--source include/have_innodb.inc
--source include/have_debug.inc
---echo # Create 2 UNDO TABLESPACE(UNDO003, UNDO004)
+--echo # Create 2 UNDO TABLESPACE(UNDO001(space_id =3), UNDO002(space_id =4))
let $basedir=$MYSQLTEST_VARDIR/tmp/backup;
diff --git a/mysql-test/suite/period/r/delete.result b/mysql-test/suite/period/r/delete.result
index 428200a4564..451017e5340 100644
--- a/mysql-test/suite/period/r/delete.result
+++ b/mysql-test/suite/period/r/delete.result
@@ -353,6 +353,18 @@ id s e datediff(e, s)
1 1999-01-01 1999-01-03 2
1 2018-12-10 2018-12-12 2
2 1999-01-01 1999-01-03 2
+#
+# MDEV-18929 2nd execution of SP does not detect ER_VERS_NOT_VERSIONED
+#
+create or replace table t1 (id int, s date, e date, period for apptime(s,e));
+create or replace procedure sp()
+delete from t1 for portion of othertime from '2000-01-01' to '2018-01-01';
+call sp;
+ERROR HY000: Period `othertime` is not found in table
+call sp;
+ERROR HY000: Period `othertime` is not found in table
+drop table t1;
+drop procedure sp;
drop table t,t2,t3,log_tbl;
drop view v;
drop procedure log;
diff --git a/mysql-test/suite/period/t/delete.test b/mysql-test/suite/period/t/delete.test
index 00bc314160f..738d77d2c19 100644
--- a/mysql-test/suite/period/t/delete.test
+++ b/mysql-test/suite/period/t/delete.test
@@ -181,6 +181,20 @@ delete from t for portion of apptime from '1999-01-03' to '2018-12-10';
--sorted_result
select *, datediff(e, s) from t;
+--echo #
+--echo # MDEV-18929 2nd execution of SP does not detect ER_VERS_NOT_VERSIONED
+--echo #
+create or replace table t1 (id int, s date, e date, period for apptime(s,e));
+create or replace procedure sp()
+delete from t1 for portion of othertime from '2000-01-01' to '2018-01-01';
+--error ER_PERIOD_NOT_FOUND
+call sp;
+--error ER_PERIOD_NOT_FOUND
+call sp;
+drop table t1;
+drop procedure sp;
+
+
drop table t,t2,t3,log_tbl;
drop view v;
drop procedure log;
diff --git a/mysql-test/suite/versioning/r/delete_history.result b/mysql-test/suite/versioning/r/delete_history.result
index 46ef271db3d..cb865a835b3 100644
--- a/mysql-test/suite/versioning/r/delete_history.result
+++ b/mysql-test/suite/versioning/r/delete_history.result
@@ -1,3 +1,4 @@
+call mtr.add_suppression("need more HISTORY partitions");
create table t (a int);
delete history from t before system_time now();
ERROR HY000: Table `t` is not system-versioned
@@ -56,16 +57,15 @@ select * from t for system_time all;
a
drop procedure truncate_sp;
# Truncate partitioned
-create or replace table t (a int)
-with system versioning
-partition by system_time limit 1 (
-partition p0 history,
-partition p1 history,
-partition pn current);
+create or replace table t (a int) with system versioning
+partition by system_time limit 1 partitions 3;
insert into t values (1);
update t set a= 2;
update t set a= 3;
delete history from t;
+Warnings:
+Warning 4114 Versioned table `test`.`t`: last HISTORY partition (`p1`) is out of LIMIT, need more HISTORY partitions
+# The above warning is one command late (MDEV-20345) ^^^
select * from t for system_time all;
a
3
diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result
index a286cdf23be..583b42bf1ec 100644
--- a/mysql-test/suite/versioning/r/partition.result
+++ b/mysql-test/suite/versioning/r/partition.result
@@ -121,6 +121,28 @@ select x from t1;
x
1
2
+# rename works
+create or replace table t1 (x int) with system versioning
+partition by system_time;
+alter table t1 reorganize partition p0 into
+(partition custom_name history);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME
+(PARTITION `custom_name` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+# merge and split doesn't (MDEV-19938)
+create or replace table t1 (x int) with system versioning
+partition by system_time partitions 3;
+Warnings:
+Warning 4115 Maybe missing parameters: no rotation condition for multiple HISTORY partitions.
+alter table t1 reorganize partition p0, p1 into (partition p00 history);
+ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers
+alter table t1 reorganize partition p1 into (partition p1 history, partition p2 history);
+ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers
# Bug tempesta-tech/mariadb#260: incorrect IB partitioning warning
create or replace table t1 (x int)
with system versioning
@@ -267,13 +289,6 @@ x
6
7
8
-### Assertion in ALTER on warning from partitioning LIMIT [#446]
-create or replace table t1 (x int) with system versioning;
-insert into t1 values (1), (2);
-delete from t1;
-alter table t1 partition by system_time limit 1 (
-partition p1 history,
-partition pn current);
## rotation by INTERVAL
create or replace table t1 (x int)
with system versioning
@@ -282,6 +297,325 @@ ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'INTERVAL'
create table t1 (i int) with system versioning
partition by system_time interval 6 day limit 98;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'limit 98' at line 2
+create or replace table t1 (pk int) with system versioning
+partition by system_time interval 10 year partitions 3;
+ERROR 22003: TIMESTAMP value is out of range in 'INTERVAL'
+# INTERVAL and ALTER TABLE
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 hour;
+set @ts=(select partition_description from information_schema.partitions
+where table_schema='test' and table_name='t1' and partition_name='p0');
+alter table t1 add column b int;
+select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
+partition_name partition_ordinal_position partition_method timediff(partition_description, @ts)
+p0 1 SYSTEM_TIME 00:00:00.000000
+pn 2 SYSTEM_TIME NULL
+Warnings:
+Warning 1292 Incorrect time value: 'CURRENT'
+alter table t1 add partition (partition p1 history, partition p2 history);
+select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
+partition_name partition_ordinal_position partition_method timediff(partition_description, @ts)
+p0 1 SYSTEM_TIME 00:00:00.000000
+p1 2 SYSTEM_TIME 01:00:00.000000
+p2 3 SYSTEM_TIME 02:00:00.000000
+pn 4 SYSTEM_TIME NULL
+Warnings:
+Warning 1292 Incorrect time value: 'CURRENT'
+alter table t1 drop partition p0;
+select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
+partition_name partition_ordinal_position partition_method timediff(partition_description, @ts)
+p1 1 SYSTEM_TIME 01:00:00.000000
+p2 2 SYSTEM_TIME 02:00:00.000000
+pn 3 SYSTEM_TIME NULL
+Warnings:
+Warning 1292 Incorrect time value: 'CURRENT'
+alter table t1 drop partition p2;
+ERROR HY000: Can only drop oldest partitions when rotating by INTERVAL
+select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
+partition_name partition_ordinal_position partition_method timediff(partition_description, @ts)
+p1 1 SYSTEM_TIME 01:00:00.000000
+p2 2 SYSTEM_TIME 02:00:00.000000
+pn 3 SYSTEM_TIME NULL
+Warnings:
+Warning 1292 Incorrect time value: 'CURRENT'
+set timestamp=unix_timestamp('2001-02-03 10:20:30');
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day
+subpartition by key (i) subpartitions 2
+(partition p1 history, partition pn current);
+set timestamp=unix_timestamp('2001-02-03 10:20:40');
+insert t1 values (1);
+delete from t1;
+set timestamp=unix_timestamp('2001-02-04 10:20:50');
+insert t1 values (2);
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
+delete from t1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
+select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+subpartition_name partition_description table_rows
+p1sp0 2001-02-04 00:00:00 1
+p1sp1 2001-02-04 00:00:00 1
+pnsp0 CURRENT 0
+pnsp1 CURRENT 0
+set timestamp=unix_timestamp('2001-02-04 10:20:55');
+alter table t1 add partition (partition p0 history, partition p2 history);
+set timestamp=unix_timestamp('2001-02-04 10:30:00');
+insert t1 values (4),(5);
+set timestamp=unix_timestamp('2001-02-04 10:30:10');
+update t1 set i=6 where i=5;
+select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+subpartition_name partition_description table_rows
+p1sp0 2001-02-04 00:00:00 1
+p1sp1 2001-02-04 00:00:00 0
+p0sp0 2001-02-05 00:00:00 1
+p0sp1 2001-02-05 00:00:00 1
+p2sp0 2001-02-06 00:00:00 0
+p2sp1 2001-02-06 00:00:00 0
+pnsp0 CURRENT 0
+pnsp1 CURRENT 2
+## pruning check
+set @ts=(select partition_description from information_schema.partitions
+where table_schema='test' and table_name='t1' and partition_name='p0' limit 1);
+select * from t1;
+i
+4
+6
+explain partitions select * from t1;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL # Using where
+explain partitions select * from t1 for system_time as of '2001-02-04 10:20:30';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0_p0sp0,p0_p0sp1,p2_p2sp0,p2_p2sp1,pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL # Using where
+set @ts=(select row_end from t1 for system_time all where i=1);
+select * from t1 for system_time all where row_end = @ts;
+i
+1
+explain partitions select * from t1 for system_time all where row_end = @ts;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p1_p1sp0,p1_p1sp1 # NULL NULL NULL NULL # #
+## INTERVAL ... STARTS
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts 'a';
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '00:00:00';
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-00-01 00:00:00';
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts 946684800;
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-01 00:00:00';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'2000-01-01 00:00:00'
+PARTITIONS 2
+# Test STARTS warning
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'2000-01-01 00:00:00'
+PARTITIONS 2
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-01 00:00:01';
+Warnings:
+Warning 4164 `t1`: STARTS is later than query time, first history partition may exceed INTERVAL value
+# Test default STARTS rounding
+set timestamp= unix_timestamp('1999-12-15 13:33:33');
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 second;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 SECOND STARTS TIMESTAMP'1999-12-15 13:33:33'
+PARTITIONS 2
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 minute;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 MINUTE STARTS TIMESTAMP'1999-12-15 13:33:00'
+PARTITIONS 2
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 hour;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'1999-12-15 13:00:00'
+PARTITIONS 2
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'1999-12-15 00:00:00'
+PARTITIONS 2
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 month;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 MONTH STARTS TIMESTAMP'1999-12-15 00:00:00'
+PARTITIONS 2
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 year;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 YEAR STARTS TIMESTAMP'1999-12-15 00:00:00'
+PARTITIONS 2
+# seconds equivalent of 1 day does not round:
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 86400 second;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 86400 SECOND STARTS TIMESTAMP'1999-12-15 13:33:33'
+PARTITIONS 2
+# STARTS value is in local time_zone:
+set time_zone="+03:00";
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-01 00:00:00';
+Warnings:
+Warning 4164 `t1`: STARTS is later than query time, first history partition may exceed INTERVAL value
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t2 (i int) with system versioning
+partition by system_time interval 1 day;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'2000-01-01 00:00:00'
+PARTITIONS 2
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'2000-01-01 00:00:00'
+PARTITIONS 2
+set time_zone="+00:00";
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'1999-12-31 21:00:00'
+PARTITIONS 2
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'1999-12-31 21:00:00'
+PARTITIONS 2
+# Test rotation
+set timestamp= unix_timestamp('2001-01-01 00:00:00');
+# it's ok to add partitions for past:
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-01 00:00:00'
+partitions 3;
+# we are warned when we push to present:
+insert into t1 values (0);
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
+set timestamp= unix_timestamp('2001-01-01 00:00:01');
+update t1 set i= i + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
+set timestamp= unix_timestamp('2001-01-01 00:00:02');
+update t1 set i= i + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
+select *, row_end from t1 partition (p0);
+i row_end
+select *, row_end from t1 partition (p1);
+i row_end
+0 2001-01-01 00:00:01.000000
+1 2001-01-01 00:00:02.000000
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+# now we "overflow" first partition a bit:
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-03 00:00:00'
+partitions 3;
+Warnings:
+Warning 4164 `t1`: STARTS is later than query time, first history partition may exceed INTERVAL value
+insert into t1 values (0);
+set timestamp= unix_timestamp('2000-01-01 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-02 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-03 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-04 00:00:01');
+update t1 set i= i + 1;
+select *, row_end from t1 partition (p0);
+i row_end
+0 2000-01-01 00:00:01.000000
+1 2000-01-02 00:00:01.000000
+2 2000-01-03 00:00:01.000000
+select *, row_end from t1 partition (p1);
+i row_end
+3 2000-01-04 00:00:01.000000
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+# and this is how it usually goes:
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day
+partitions 3;
+insert into t1 values (0);
+set timestamp= unix_timestamp('2000-01-01 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-02 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-03 00:00:01');
+update t1 set i= i + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
+set timestamp= unix_timestamp('2000-01-04 00:00:01');
+update t1 set i= i + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
+alter table t1 add partition (partition p2 history, partition p3 history);
+select *, row_end from t1 partition (p0);
+i row_end
+0 2000-01-01 00:00:01.000000
+select *, row_end from t1 partition (p1);
+i row_end
+1 2000-01-02 00:00:01.000000
+select *, row_end from t1 partition (p2);
+i row_end
+2 2000-01-03 00:00:01.000000
+select *, row_end from t1 partition (p3);
+i row_end
+3 2000-01-04 00:00:01.000000
+drop tables t1, t2;
## Subpartitions
create or replace table t1 (x int)
with system versioning
@@ -302,34 +636,34 @@ x
delete from t1 where x < 3;
delete from t1;
delete from t1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of LIMIT, need more HISTORY partitions
select * from t1 partition (p0sp0);
x
1
-3
-5
select * from t1 partition (p0sp1);
x
2
-4
select * from t1 partition (p1sp0);
x
+3
+5
select * from t1 partition (p1sp1);
x
-create or replace table t1 (
-a bigint,
-row_start SYS_DATATYPE as row start invisible,
-row_end SYS_DATATYPE as row end invisible,
-period for system_time(row_start, row_end))
+4
+# check implicit sys fields for implicit engine of partitioned table
+create or replace table t1 (a bigint)
with system versioning
partition by range (a)
(partition p0 values less than (20) engine innodb,
partition p1 values less than maxvalue engine innodb);
insert into t1 values (1);
+select * from t1 partition (p0);
+a
+1
+# check for partition engine
create or replace table t1 (
-f_int1 integer default 0,
-row_start SYS_DATATYPE as row start invisible,
-row_end SYS_DATATYPE as row end invisible,
-period for system_time(row_start, row_end)
+f_int1 integer default 0
) with system versioning
partition by range(f_int1)
subpartition by hash(f_int1)
@@ -337,14 +671,97 @@ subpartition by hash(f_int1)
(subpartition subpart11 storage engine = 'innodb',
subpartition subpart12 storage engine = 'innodb'));
insert into t1 values (1);
+select * from t1 partition (part1);
+f_int1
+1
+#
+# TRX_ID versioning (moved from partition_innodb.test)
+#
+# MDEV-15951 system versioning by trx id doesn't work with partitioning
+# currently trx_id does not support partitioning by system_time
+create or replace table t1(
+i int,
+row_start bigint unsigned generated always as row start,
+row_end bigint unsigned generated always as row end,
+period for system_time(row_start, row_end)
+) engine=InnoDB with system versioning partition by system_time (
+partition p0 history,
+partition pn current
+);
+ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `t1`
+create or replace table t1(
+i int,
+row_start bigint unsigned generated always as row start,
+row_end bigint unsigned generated always as row end,
+period for system_time(row_start, row_end)
+) engine=InnoDB with system versioning;
+alter table t1 partition by system_time (
+partition p0 history,
+partition pn current
+);
+ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `t1`
+drop table t1;
+create or replace table t (
+a int primary key,
+row_start bigint unsigned as row start invisible,
+row_end bigint unsigned as row end invisible,
+period for system_time(row_start, row_end)
+) engine=innodb with system versioning
+partition by key() (
+partition p1,
+partition p2
+);
+ERROR HY000: Transaction-precise system-versioned tables do not support partitioning by ROW START or ROW END
+create or replace table t (
+a int primary key,
+row_start bigint unsigned as row start invisible,
+row_end bigint unsigned as row end invisible,
+period for system_time(row_start, row_end)
+) engine=innodb with system versioning
+partition by key(a, row_start) (
+partition p1,
+partition p2
+);
+ERROR HY000: Transaction-precise system-versioned tables do not support partitioning by ROW START or ROW END
+create or replace table t (
+a int primary key,
+row_start bigint unsigned as row start invisible,
+row_end bigint unsigned as row end invisible,
+period for system_time(row_start, row_end)
+) engine=innodb with system versioning
+partition by hash(a + row_end * 2) (
+partition p1,
+partition p2
+);
+ERROR HY000: Transaction-precise system-versioned tables do not support partitioning by ROW START or ROW END
+create or replace table t (
+a int primary key,
+row_start bigint unsigned as row start invisible,
+row_end bigint unsigned as row end invisible,
+period for system_time(row_start, row_end)
+) engine=innodb with system versioning
+partition by range columns (a, row_start) (
+partition p1 values less than (100, 100)
+);
+ERROR HY000: Transaction-precise system-versioned tables do not support partitioning by ROW START or ROW END
+#
+# Assertion in ALTER on warning from partitioning LIMIT [#446]
+#
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1), (2);
+delete from t1;
+alter table t1 partition by system_time limit 1 (
+partition p1 history,
+partition pn current);
+#
+# MDEV-14649 Assertion `t->mysql_col_len == 8' failed in row_insert_for_mysql
+#
create or replace table t1 (i int) engine=innodb partition by key(i);
-alter table t1
-add column row_start SYS_DATATYPE as row start invisible,
-add column row_end SYS_DATATYPE as row end invisible,
-add period for system_time(row_start, row_end),
-add system versioning;
+alter table t1 add system versioning;
insert into t1 values();
+#
# MDEV-14722 Assertion in ha_commit_trans for sub-statement
+#
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day;
create or replace table t2 (f int);
@@ -354,7 +771,9 @@ where table_name = 't1' into @a;
Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
insert into t2 values (1);
+#
# MDEV-14740 Locking assertion for system_time partitioning
+#
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 week;
create or replace table t2 (f int);
@@ -363,14 +782,18 @@ for each row select count(*) from t1 into @a;
Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
insert into t2 values (1);
+#
# MDEV-14747 ALTER PARTITION BY SYSTEM_TIME after LOCK TABLES
+#
create or replace table t1 (x int) with system versioning;
lock table t1 write;
alter table t1 partition by system_time interval 1 week (
partition p1 history,
partition pn current);
unlock tables;
+#
# MDEV-14748 Assertion in ha_myisammrg::attach_children()
+#
create or replace table t1 (x int) engine=myisam with system versioning
partition by system_time interval 1 month (partition p1 history, partition pn current);
create or replace table t2 (x int) engine=myisam;
@@ -379,7 +802,9 @@ create or replace table t4 (x int) engine=myisam;
create or replace trigger tr after insert on t4 for each row insert into t2
( select x from t3 ) union ( select x from t1 );
insert into t4 values (1);
+#
# MDEV-14821 Assertion failure
+#
create or replace table t1 (x int) with system versioning;
insert into t1 values (0), (1);
update t1 set x= x + 1;
@@ -389,7 +814,9 @@ partition p2 history,
partition pn current);
delete from t1 where x = 1;
delete from t1 where x = 2;
+#
# MDEV-14923 Assertion upon INSERT into locked versioned partitioned table
+#
create or replace table t1 (x int) with system versioning
partition by system_time;
lock table t1 write;
@@ -397,46 +824,6 @@ alter table t1 add partition (partition p0 history);
ERROR HY000: Duplicate partition name p0
insert into t1 values (1);
unlock tables;
-create or replace table t1 (pk int) with system versioning
-partition by system_time interval 10 year partitions 3;
-ERROR 22003: TIMESTAMP value is out of range in 'INTERVAL'
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 hour;
-set @ts=(select partition_description from information_schema.partitions
-where table_schema='test' and table_name='t1' and partition_name='p0');
-alter table t1 add column b int;
-select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
-partition_name partition_ordinal_position partition_method timediff(partition_description, @ts)
-p0 1 SYSTEM_TIME 00:00:00.000000
-pn 2 SYSTEM_TIME NULL
-Warnings:
-Warning 1292 Incorrect time value: 'CURRENT'
-alter table t1 add partition (partition p1 history, partition p2 history);
-select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
-partition_name partition_ordinal_position partition_method timediff(partition_description, @ts)
-p0 1 SYSTEM_TIME 00:00:00.000000
-p1 2 SYSTEM_TIME 01:00:00.000000
-p2 3 SYSTEM_TIME 02:00:00.000000
-pn 4 SYSTEM_TIME NULL
-Warnings:
-Warning 1292 Incorrect time value: 'CURRENT'
-alter table t1 drop partition p0;
-select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
-partition_name partition_ordinal_position partition_method timediff(partition_description, @ts)
-p1 1 SYSTEM_TIME 01:00:00.000000
-p2 2 SYSTEM_TIME 02:00:00.000000
-pn 3 SYSTEM_TIME NULL
-Warnings:
-Warning 1292 Incorrect time value: 'CURRENT'
-alter table t1 drop partition p2;
-ERROR HY000: Can only drop oldest partitions when rotating by INTERVAL
-select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
-partition_name partition_ordinal_position partition_method timediff(partition_description, @ts)
-p1 1 SYSTEM_TIME 01:00:00.000000
-p2 2 SYSTEM_TIME 02:00:00.000000
-pn 3 SYSTEM_TIME NULL
-Warnings:
-Warning 1292 Incorrect time value: 'CURRENT'
#
# MDEV-15103 Assertion in ha_partition::part_records() for updating VIEW
#
@@ -452,7 +839,9 @@ create or replace table t (a int) with system versioning
partition by system_time;
alter table t drop system versioning;
ERROR HY000: Can not DROP SYSTEM VERSIONING for table `t` partitioned BY SYSTEM_TIME
+#
# MDEV-15191 Assertion `bit < (map)->n_bits' failed in bitmap_is_set upon INSERT
+#
create or replace table t1 (i int) with system versioning;
insert into t1 values (1), (2);
update t1 set i= 3;
@@ -461,18 +850,32 @@ lock table t1 write;
alter table t1 add partition (partition p2 history);
insert into t1 values (4);
unlock tables;
+#
# MDEV-15036 Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())' in Diagnostics_area::set_ok_status or unexpected ER_RANGE_NOT_INCREASING_ERROR
+#
create or replace table t1 (a int) with system versioning
partition by system_time limit 2 partitions 4;
insert into t1 values (1),(2),(3);
update t1 set a = 4;
delete from t1;
delete from t1 where a is not null;
+#
# MDEV-14823 Wrong error message upon selecting from a system_time partition
+#
create or replace table t1 (i int) with system versioning partition by system_time limit 10;
select * from t1 partition (p0) for system_time all;
ERROR HY000: SYSTEM_TIME partitions in table `t1` does not support historical query
+# MDEV-18929 2nd execution of SP does not detect ER_VERS_NOT_VERSIONED
+create or replace procedure sp()
+select * from t1 partition (p0) for system_time all;
+call sp;
+ERROR HY000: SYSTEM_TIME partitions in table `t1` does not support historical query
+call sp;
+ERROR HY000: SYSTEM_TIME partitions in table `t1` does not support historical query
+drop procedure sp;
+#
# MDEV-15380 Index for versioned table gets corrupt after partitioning and DELETE
+#
create or replace table t1 (pk int primary key)
engine=myisam
with system versioning
@@ -583,3 +986,17 @@ x a
3 bar
4 bar
drop table t1;
+#
+# MDEV-21011 Table corruption reported for versioned partitioned table after DELETE: "Found a misplaced row"
+#
+create table t1 (a int) with system versioning
+partition by system_time limit 3
+(partition p1 history, partition p2 history, partition pn current);
+insert into t1 values (1),(2),(3),(4);
+delete from t1;
+delete from t1;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check note Not supported for non-INTERVAL history partitions
+test.t1 check note The storage engine for the table doesn't support check
+drop table t1;
diff --git a/mysql-test/suite/versioning/r/partition_innodb.result b/mysql-test/suite/versioning/r/partition_innodb.result
deleted file mode 100644
index afed90ffe05..00000000000
--- a/mysql-test/suite/versioning/r/partition_innodb.result
+++ /dev/null
@@ -1,67 +0,0 @@
-# MDEV-15951 system versioning by trx id doesn't work with partitioning
-# currently trx_id does not support partitioning by system_time
-create or replace table t1(
-i int,
-row_start bigint unsigned generated always as row start,
-row_end bigint unsigned generated always as row end,
-period for system_time(row_start, row_end)
-) engine=InnoDB with system versioning partition by system_time (
-partition p0 history,
-partition pn current
-);
-ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `t1`
-create or replace table t1(
-i int,
-row_start bigint unsigned generated always as row start,
-row_end bigint unsigned generated always as row end,
-period for system_time(row_start, row_end)
-) engine=InnoDB with system versioning;
-alter table t1 partition by system_time (
-partition p0 history,
-partition pn current
-);
-ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `t1`
-drop table t1;
-create or replace table t (
-a int primary key,
-row_start bigint unsigned as row start invisible,
-row_end bigint unsigned as row end invisible,
-period for system_time(row_start, row_end)
-) engine=innodb with system versioning
-partition by key() (
-partition p1,
-partition p2
-);
-ERROR HY000: Transaction-precise system-versioned tables do not support partitioning by ROW START or ROW END
-create or replace table t (
-a int primary key,
-row_start bigint unsigned as row start invisible,
-row_end bigint unsigned as row end invisible,
-period for system_time(row_start, row_end)
-) engine=innodb with system versioning
-partition by key(a, row_start) (
-partition p1,
-partition p2
-);
-ERROR HY000: Transaction-precise system-versioned tables do not support partitioning by ROW START or ROW END
-create or replace table t (
-a int primary key,
-row_start bigint unsigned as row start invisible,
-row_end bigint unsigned as row end invisible,
-period for system_time(row_start, row_end)
-) engine=innodb with system versioning
-partition by hash(a + row_end * 2) (
-partition p1,
-partition p2
-);
-ERROR HY000: Transaction-precise system-versioned tables do not support partitioning by ROW START or ROW END
-create or replace table t (
-a int primary key,
-row_start bigint unsigned as row start invisible,
-row_end bigint unsigned as row end invisible,
-period for system_time(row_start, row_end)
-) engine=innodb with system versioning
-partition by range columns (a, row_start) (
-partition p1 values less than (100, 100)
-);
-ERROR HY000: Transaction-precise system-versioned tables do not support partitioning by ROW START or ROW END
diff --git a/mysql-test/suite/versioning/r/partition_rotation.result b/mysql-test/suite/versioning/r/partition_rotation.result
deleted file mode 100644
index 2a9f313b00a..00000000000
--- a/mysql-test/suite/versioning/r/partition_rotation.result
+++ /dev/null
@@ -1,280 +0,0 @@
-set time_zone= "+00:00";
-call mtr.add_suppression("need more HISTORY partitions");
-set timestamp=unix_timestamp('2001-02-03 10:20:30');
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day
-subpartition by key (i) subpartitions 2
-(partition p1 history, partition pn current);
-set timestamp=unix_timestamp('2001-02-03 10:20:40');
-insert t1 values (1);
-delete from t1;
-set timestamp=unix_timestamp('2001-02-04 10:20:50');
-insert t1 values (2);
-Warnings:
-Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
-delete from t1;
-Warnings:
-Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
-select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
-subpartition_name partition_description table_rows
-p1sp0 2001-02-04 00:00:00 1
-p1sp1 2001-02-04 00:00:00 1
-pnsp0 CURRENT 0
-pnsp1 CURRENT 0
-set timestamp=unix_timestamp('2001-02-04 10:20:55');
-alter table t1 add partition (partition p0 history, partition p2 history);
-set timestamp=unix_timestamp('2001-02-04 10:30:00');
-insert t1 values (4),(5);
-set timestamp=unix_timestamp('2001-02-04 10:30:10');
-update t1 set i=6 where i=5;
-select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
-subpartition_name partition_description table_rows
-p1sp0 2001-02-04 00:00:00 1
-p1sp1 2001-02-04 00:00:00 0
-p0sp0 2001-02-05 00:00:00 1
-p0sp1 2001-02-05 00:00:00 1
-p2sp0 2001-02-06 00:00:00 0
-p2sp1 2001-02-06 00:00:00 0
-pnsp0 CURRENT 0
-pnsp1 CURRENT 2
-## pruning check
-set @ts=(select partition_description from information_schema.partitions
-where table_schema='test' and table_name='t1' and partition_name='p0' limit 1);
-select * from t1;
-i
-4
-6
-explain partitions select * from t1;
-id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL 2 Using where
-explain partitions select * from t1 for system_time as of '2001-02-04 10:20:30';
-id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0_p0sp0,p0_p0sp1,p2_p2sp0,p2_p2sp1,pn_pnsp0,pn_pnsp1 ALL NULL NULL NULL NULL # Using where
-set @ts=(select row_end from t1 for system_time all where i=1);
-select * from t1 for system_time all where row_end = @ts;
-i
-1
-explain partitions select * from t1 for system_time all where row_end = @ts;
-id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p1_p1sp0,p1_p1sp1 # NULL NULL NULL NULL # #
-## INTERVAL ... STARTS
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts 'a';
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '00:00:00';
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-00-01 00:00:00';
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts 946684800;
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-01 00:00:00';
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'2000-01-01 00:00:00'
-PARTITIONS 2
-# Test STARTS warning
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'2000-01-01 00:00:00'
-PARTITIONS 2
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-01 00:00:01';
-Warnings:
-Warning 4164 `t1`: STARTS is later than query time, first history partition may exceed INTERVAL value
-# Test default STARTS rounding
-set timestamp= unix_timestamp('1999-12-15 13:33:33');
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 second;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 SECOND STARTS TIMESTAMP'1999-12-15 13:33:33'
-PARTITIONS 2
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 minute;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 MINUTE STARTS TIMESTAMP'1999-12-15 13:33:00'
-PARTITIONS 2
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 hour;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'1999-12-15 13:00:00'
-PARTITIONS 2
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'1999-12-15 00:00:00'
-PARTITIONS 2
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 month;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 MONTH STARTS TIMESTAMP'1999-12-15 00:00:00'
-PARTITIONS 2
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 year;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 YEAR STARTS TIMESTAMP'1999-12-15 00:00:00'
-PARTITIONS 2
-# seconds equivalent of 1 day does not round:
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 86400 second;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 86400 SECOND STARTS TIMESTAMP'1999-12-15 13:33:33'
-PARTITIONS 2
-# STARTS value is in local time_zone:
-set time_zone="+03:00";
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-01 00:00:00';
-Warnings:
-Warning 4164 `t1`: STARTS is later than query time, first history partition may exceed INTERVAL value
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
-create or replace table t2 (i int) with system versioning
-partition by system_time interval 1 day;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'2000-01-01 00:00:00'
-PARTITIONS 2
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'2000-01-01 00:00:00'
-PARTITIONS 2
-set time_zone="+00:00";
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'1999-12-31 21:00:00'
-PARTITIONS 2
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `i` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
- PARTITION BY SYSTEM_TIME INTERVAL 1 DAY STARTS TIMESTAMP'1999-12-31 21:00:00'
-PARTITIONS 2
-# Test rotation
-set timestamp= unix_timestamp('2001-01-01 00:00:00');
-# it's ok to add partitions for past:
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-01 00:00:00'
-partitions 3;
-# we are warned when we push to present:
-insert into t1 values (0);
-Warnings:
-Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
-set timestamp= unix_timestamp('2001-01-01 00:00:01');
-update t1 set i= i + 1;
-Warnings:
-Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
-set timestamp= unix_timestamp('2001-01-01 00:00:02');
-update t1 set i= i + 1;
-Warnings:
-Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
-select *, row_end from t1 partition (p0);
-i row_end
-select *, row_end from t1 partition (p1);
-i row_end
-0 2001-01-01 00:00:01.000000
-1 2001-01-01 00:00:02.000000
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
-# now we "overflow" first partition a bit:
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-03 00:00:00'
-partitions 3;
-Warnings:
-Warning 4164 `t1`: STARTS is later than query time, first history partition may exceed INTERVAL value
-insert into t1 values (0);
-set timestamp= unix_timestamp('2000-01-01 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-02 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-03 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-04 00:00:01');
-update t1 set i= i + 1;
-select *, row_end from t1 partition (p0);
-i row_end
-0 2000-01-01 00:00:01.000000
-1 2000-01-02 00:00:01.000000
-2 2000-01-03 00:00:01.000000
-select *, row_end from t1 partition (p1);
-i row_end
-3 2000-01-04 00:00:01.000000
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
-# and this is how it usually goes:
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day
-partitions 3;
-insert into t1 values (0);
-set timestamp= unix_timestamp('2000-01-01 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-02 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-03 00:00:01');
-update t1 set i= i + 1;
-Warnings:
-Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
-set timestamp= unix_timestamp('2000-01-04 00:00:01');
-update t1 set i= i + 1;
-Warnings:
-Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
-alter table t1 add partition (partition p2 history, partition p3 history);
-select *, row_end from t1 partition (p0);
-i row_end
-0 2000-01-01 00:00:01.000000
-select *, row_end from t1 partition (p1);
-i row_end
-1 2000-01-02 00:00:01.000000
-select *, row_end from t1 partition (p2);
-i row_end
-2 2000-01-03 00:00:01.000000
-select *, row_end from t1 partition (p3);
-i row_end
-3 2000-01-04 00:00:01.000000
-drop tables t1, t2;
diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result
index 66e22de9b0e..87b09d8dff7 100644
--- a/mysql-test/suite/versioning/r/select.result
+++ b/mysql-test/suite/versioning/r/select.result
@@ -356,6 +356,21 @@ ERROR HY000: Table `t` is not system-versioned
create or replace table t1 (x int) with system versioning engine myisam;
select * from t1 for system_time as of transaction 1;
ERROR HY000: Transaction-precise system versioning for `t1` is not supported
+# MDEV-18929 2nd execution of SP does not detect ER_VERS_NOT_VERSIONED
+create or replace procedure sp()
+select * from t1 for system_time as of transaction 1;
+call sp;
+ERROR HY000: Transaction-precise system versioning for `t1` is not supported
+call sp;
+ERROR HY000: Transaction-precise system versioning for `t1` is not supported
+create or replace table t1 (a int);
+create or replace procedure sp()
+select * from t1 for system_time all;
+call sp;
+ERROR HY000: Table `t1` is not system-versioned
+call sp;
+ERROR HY000: Table `t1` is not system-versioned
+drop procedure sp;
create or replace table t1 (
x int,
sys_trx_start bigint unsigned as row start invisible,
diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result
index eaa8549b38a..64aa7c7068c 100644
--- a/mysql-test/suite/versioning/r/update.result
+++ b/mysql-test/suite/versioning/r/update.result
@@ -276,3 +276,24 @@ update t1 set a= '2012-12-12';
update v set a= '2000-01-01' order by b limit 1;
drop view v;
drop table t1, t2;
+#
+# MDEV-20441 ER_CRASHED_ON_USAGE upon update on versioned Aria table
+#
+create or replace table t1 (a varchar(8))
+engine=aria row_format=fixed
+with system versioning;
+insert into t1 (a) values ('foo');
+update t1 set a = 'bar';
+drop table t1;
+#
+# MDEV-21147 Assertion `marked_for_read()' upon UPDATE on versioned table via view
+#
+create or replace table t1 (
+pk int, a char(8), b char(8),
+primary key (pk)
+) with system versioning;
+create or replace view v1 as select * from t1;
+insert into t1 values (1, null, 'd') , (2, null, 'i') ;
+update v1 set a= null where b = '';
+drop view v1;
+drop table t1;
diff --git a/mysql-test/suite/versioning/r/view.result b/mysql-test/suite/versioning/r/view.result
index b33602f7336..3b3fe580af4 100644
--- a/mysql-test/suite/versioning/r/view.result
+++ b/mysql-test/suite/versioning/r/view.result
@@ -160,6 +160,7 @@ period for system_time (row_start, row_end)
) with system versioning;
insert into t1 values (1), (2);
create or replace view v1 as select * from t1 where x > 1;
+# update, delete
update v1 set x= x + 1;
select *, check_row(row_start, row_end) from t1 for system_time all order by x;
x check_row(row_start, row_end)
@@ -211,5 +212,70 @@ x check_row(row_start, row_end)
1 CURRENT ROW
2 HISTORICAL ROW
3 HISTORICAL ROW
+# replace
+create or replace table t1 (
+x int primary key, y int,
+row_start SYS_DATATYPE as row start invisible,
+row_end SYS_DATATYPE as row end invisible,
+period for system_time (row_start, row_end)
+) with system versioning;
+insert into t1 values (1, 0), (2, 0);
+create or replace view v1 as select * from t1 where x > 1;
+replace v1 values (1, 1);
+replace v1 values (2, 1);
+replace v1 values (3, 1);
+# REPLACE ignores VIEW condition because itself doesn't use WHERE
+select *, check_row(row_start, row_end) from t1 for system_time all order by x, row_end;
+x y check_row(row_start, row_end)
+1 0 HISTORICAL ROW
+1 1 CURRENT ROW
+2 0 HISTORICAL ROW
+2 1 CURRENT ROW
+3 1 CURRENT ROW
+# insert-select, on duplicate key
+insert v1 select * from t1 where x = 1 on duplicate key update x = v1.x - 1;
+select *, check_row(row_start, row_end) from t1 for system_time all order by x, row_end;
+x y check_row(row_start, row_end)
+0 1 CURRENT ROW
+1 0 HISTORICAL ROW
+1 1 HISTORICAL ROW
+2 0 HISTORICAL ROW
+2 1 CURRENT ROW
+3 1 CURRENT ROW
drop view v1, v2;
drop tables t1, t2;
+#
+# MDEV-21146 Assertion `m_lock_type == 2' in handler::ha_drop_table upon LOAD DATA
+#
+create table t1 (a int);
+create view v1 as select * from t1;
+create or replace table t1 (b int) with system versioning;
+load data infile 'xx' into table v1;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+drop view v1;
+drop table t1;
+#
+# MDEV-21155 Assertion with versioned table upon DELETE from view of view after replacing first view
+#
+create table t1 (a int);
+insert into t1 values (1);
+create table t2 (
+b int,
+row_start SYS_DATATYPE as row start invisible,
+row_end SYS_DATATYPE as row end invisible,
+period for system_time (row_start, row_end)
+) with system versioning;
+insert into t2 values (2);
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+create or replace view v1 as select * from t2;
+delete from v2;
+select * from t1;
+a
+1
+select *, check_row(row_start, row_end) from t2 for system_time all;
+b check_row(row_start, row_end)
+2 HISTORICAL ROW
+drop view v2;
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/suite/versioning/t/delete_history.test b/mysql-test/suite/versioning/t/delete_history.test
index 07fb4eb187a..fb5c8520bcb 100644
--- a/mysql-test/suite/versioning/t/delete_history.test
+++ b/mysql-test/suite/versioning/t/delete_history.test
@@ -2,6 +2,8 @@
--source include/have_partition.inc
--source suite/versioning/engines.inc
+call mtr.add_suppression("need more HISTORY partitions");
+
create table t (a int);
--error ER_VERS_NOT_VERSIONED
delete history from t before system_time now();
@@ -56,16 +58,13 @@ select * from t for system_time all;
drop procedure truncate_sp;
--echo # Truncate partitioned
-create or replace table t (a int)
-with system versioning
-partition by system_time limit 1 (
- partition p0 history,
- partition p1 history,
- partition pn current);
+create or replace table t (a int) with system versioning
+partition by system_time limit 1 partitions 3;
insert into t values (1);
update t set a= 2;
update t set a= 3;
delete history from t;
+--echo # The above warning is one command late (MDEV-20345) ^^^
select * from t for system_time all;
--echo # VIEW
diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test
index 64c4bc247c0..49a209f920e 100644
--- a/mysql-test/suite/versioning/t/partition.test
+++ b/mysql-test/suite/versioning/t/partition.test
@@ -123,6 +123,23 @@ alter table t1 drop partition p0;
select x from t1;
+--echo # rename works
+create or replace table t1 (x int) with system versioning
+partition by system_time;
+alter table t1 reorganize partition p0 into
+(partition custom_name history);
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+--echo # merge and split doesn't (MDEV-19938)
+create or replace table t1 (x int) with system versioning
+partition by system_time partitions 3;
+--error ER_REORG_HASH_ONLY_ON_SAME_NO
+alter table t1 reorganize partition p0, p1 into (partition p00 history);
+--error ER_REORG_HASH_ONLY_ON_SAME_NO
+alter table t1 reorganize partition p1 into (partition p1 history, partition p2 history);
+
+
--echo # Bug tempesta-tech/mariadb#260: incorrect IB partitioning warning
create or replace table t1 (x int)
with system versioning
@@ -224,13 +241,6 @@ insert into t1 values (7), (8);
delete from t1;
select * from t1 partition (p1) order by x;
---echo ### Assertion in ALTER on warning from partitioning LIMIT [#446]
-create or replace table t1 (x int) with system versioning;
-insert into t1 values (1), (2);
-delete from t1;
-alter table t1 partition by system_time limit 1 (
- partition p1 history,
- partition pn current);
--echo ## rotation by INTERVAL
--error ER_PART_WRONG_VALUE
@@ -242,6 +252,215 @@ partition by system_time interval 0 second partitions 3;
create table t1 (i int) with system versioning
partition by system_time interval 6 day limit 98;
+--error ER_DATA_OUT_OF_RANGE
+create or replace table t1 (pk int) with system versioning
+partition by system_time interval 10 year partitions 3;
+
+--echo # INTERVAL and ALTER TABLE
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 hour;
+
+set @ts=(select partition_description from information_schema.partitions
+ where table_schema='test' and table_name='t1' and partition_name='p0');
+
+alter table t1 add column b int;
+select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
+alter table t1 add partition (partition p1 history, partition p2 history);
+select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
+alter table t1 drop partition p0;
+select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
+--error ER_VERS_DROP_PARTITION_INTERVAL
+alter table t1 drop partition p2;
+select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
+
+#
+# partition rotation (moved from partition_rotation.test)
+#
+set timestamp=unix_timestamp('2001-02-03 10:20:30');
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day
+ subpartition by key (i) subpartitions 2
+ (partition p1 history, partition pn current);
+set timestamp=unix_timestamp('2001-02-03 10:20:40');
+insert t1 values (1); delete from t1;
+set timestamp=unix_timestamp('2001-02-04 10:20:50');
+insert t1 values (2); delete from t1;
+
+select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+
+set timestamp=unix_timestamp('2001-02-04 10:20:55');
+alter table t1 add partition (partition p0 history, partition p2 history);
+set timestamp=unix_timestamp('2001-02-04 10:30:00');
+insert t1 values (4),(5);
+set timestamp=unix_timestamp('2001-02-04 10:30:10');
+update t1 set i=6 where i=5;
+
+select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+
+--echo ## pruning check
+set @ts=(select partition_description from information_schema.partitions
+ where table_schema='test' and table_name='t1' and partition_name='p0' limit 1);
+--sorted_result
+select * from t1;
+--replace_column 10 #
+explain partitions select * from t1;
+--replace_column 10 #
+explain partitions select * from t1 for system_time as of '2001-02-04 10:20:30';
+set @ts=(select row_end from t1 for system_time all where i=1);
+select * from t1 for system_time all where row_end = @ts;
+--replace_column 5 # 10 # 11 #
+explain partitions select * from t1 for system_time all where row_end = @ts;
+
+--echo ## INTERVAL ... STARTS
+--error ER_PART_WRONG_VALUE
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts 'a';
+
+--error ER_PART_WRONG_VALUE
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '00:00:00';
+
+--error ER_PART_WRONG_VALUE
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-00-01 00:00:00';
+
+--error ER_PART_WRONG_VALUE
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts 946684800;
+
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-01 00:00:00';
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+--echo # Test STARTS warning
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-01 00:00:01';
+
+--echo # Test default STARTS rounding
+set timestamp= unix_timestamp('1999-12-15 13:33:33');
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 second;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 minute;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 hour;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 month;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 year;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+--echo # seconds equivalent of 1 day does not round:
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 86400 second;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+--echo # STARTS value is in local time_zone:
+set time_zone="+03:00";
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-01 00:00:00';
+
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t2 (i int) with system versioning
+partition by system_time interval 1 day;
+
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t2;
+set time_zone="+00:00";
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t2;
+
+--echo # Test rotation
+set timestamp= unix_timestamp('2001-01-01 00:00:00');
+--echo # it's ok to add partitions for past:
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-01 00:00:00'
+partitions 3;
+
+--echo # we are warned when we push to present:
+insert into t1 values (0);
+set timestamp= unix_timestamp('2001-01-01 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2001-01-01 00:00:02');
+update t1 set i= i + 1;
+
+select *, row_end from t1 partition (p0);
+select *, row_end from t1 partition (p1);
+
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+--echo # now we "overflow" first partition a bit:
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2000-01-03 00:00:00'
+partitions 3;
+
+insert into t1 values (0);
+set timestamp= unix_timestamp('2000-01-01 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-02 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-03 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-04 00:00:01');
+update t1 set i= i + 1;
+
+select *, row_end from t1 partition (p0);
+select *, row_end from t1 partition (p1);
+
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+--echo # and this is how it usually goes:
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day
+partitions 3;
+
+insert into t1 values (0);
+set timestamp= unix_timestamp('2000-01-01 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-02 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-03 00:00:01');
+update t1 set i= i + 1;
+set timestamp= unix_timestamp('2000-01-04 00:00:01');
+update t1 set i= i + 1;
+
+alter table t1 add partition (partition p2 history, partition p3 history);
+
+select *, row_end from t1 partition (p0);
+select *, row_end from t1 partition (p1);
+select *, row_end from t1 partition (p2);
+select *, row_end from t1 partition (p3);
+
+drop tables t1, t2;
+
--echo ## Subpartitions
create or replace table t1 (x int)
with system versioning
@@ -262,24 +481,18 @@ select * from t1 partition (p0sp1);
select * from t1 partition (p1sp0);
select * from t1 partition (p1sp1);
---replace_result $sys_datatype_expl SYS_DATATYPE
-eval create or replace table t1 (
- a bigint,
- row_start $sys_datatype_expl as row start invisible,
- row_end $sys_datatype_expl as row end invisible,
- period for system_time(row_start, row_end))
+--echo # check implicit sys fields for implicit engine of partitioned table
+create or replace table t1 (a bigint)
with system versioning
partition by range (a)
(partition p0 values less than (20) engine innodb,
partition p1 values less than maxvalue engine innodb);
insert into t1 values (1);
+select * from t1 partition (p0);
---replace_result $sys_datatype_expl SYS_DATATYPE
-eval create or replace table t1 (
- f_int1 integer default 0,
- row_start $sys_datatype_expl as row start invisible,
- row_end $sys_datatype_expl as row end invisible,
- period for system_time(row_start, row_end)
+--echo # check for partition engine
+create or replace table t1 (
+ f_int1 integer default 0
) with system versioning
partition by range(f_int1)
subpartition by hash(f_int1)
@@ -287,17 +500,106 @@ subpartition by hash(f_int1)
(subpartition subpart11 storage engine = 'innodb',
subpartition subpart12 storage engine = 'innodb'));
insert into t1 values (1);
+select * from t1 partition (part1);
+
+--echo #
+--echo # TRX_ID versioning (moved from partition_innodb.test)
+--echo #
+--echo # MDEV-15951 system versioning by trx id doesn't work with partitioning
+--echo # currently trx_id does not support partitioning by system_time
+--error ER_VERS_FIELD_WRONG_TYPE
+create or replace table t1(
+ i int,
+ row_start bigint unsigned generated always as row start,
+ row_end bigint unsigned generated always as row end,
+ period for system_time(row_start, row_end)
+) engine=InnoDB with system versioning partition by system_time (
+ partition p0 history,
+ partition pn current
+);
+
+create or replace table t1(
+ i int,
+ row_start bigint unsigned generated always as row start,
+ row_end bigint unsigned generated always as row end,
+ period for system_time(row_start, row_end)
+) engine=InnoDB with system versioning;
+
+--error ER_VERS_FIELD_WRONG_TYPE
+alter table t1 partition by system_time (
+ partition p0 history,
+ partition pn current
+);
+
+drop table t1;
+
+--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
+create or replace table t (
+ a int primary key,
+ row_start bigint unsigned as row start invisible,
+ row_end bigint unsigned as row end invisible,
+ period for system_time(row_start, row_end)
+) engine=innodb with system versioning
+partition by key() (
+ partition p1,
+ partition p2
+);
+
+--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
+create or replace table t (
+ a int primary key,
+ row_start bigint unsigned as row start invisible,
+ row_end bigint unsigned as row end invisible,
+ period for system_time(row_start, row_end)
+) engine=innodb with system versioning
+partition by key(a, row_start) (
+ partition p1,
+ partition p2
+);
+
+--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
+create or replace table t (
+ a int primary key,
+ row_start bigint unsigned as row start invisible,
+ row_end bigint unsigned as row end invisible,
+ period for system_time(row_start, row_end)
+) engine=innodb with system versioning
+partition by hash(a + row_end * 2) (
+ partition p1,
+ partition p2
+);
+
+--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
+create or replace table t (
+ a int primary key,
+ row_start bigint unsigned as row start invisible,
+ row_end bigint unsigned as row end invisible,
+ period for system_time(row_start, row_end)
+) engine=innodb with system versioning
+partition by range columns (a, row_start) (
+ partition p1 values less than (100, 100)
+);
+
+--echo #
+--echo # Assertion in ALTER on warning from partitioning LIMIT [#446]
+--echo #
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1), (2);
+delete from t1;
+alter table t1 partition by system_time limit 1 (
+ partition p1 history,
+ partition pn current);
+--echo #
+--echo # MDEV-14649 Assertion `t->mysql_col_len == 8' failed in row_insert_for_mysql
+--echo #
create or replace table t1 (i int) engine=innodb partition by key(i);
---replace_result $sys_datatype_expl SYS_DATATYPE
-eval alter table t1
- add column row_start $sys_datatype_expl as row start invisible,
- add column row_end $sys_datatype_expl as row end invisible,
- add period for system_time(row_start, row_end),
- add system versioning;
+alter table t1 add system versioning;
insert into t1 values();
+--echo #
--echo # MDEV-14722 Assertion in ha_commit_trans for sub-statement
+--echo #
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day;
create or replace table t2 (f int);
@@ -306,7 +608,9 @@ for each row select table_rows from information_schema.tables
where table_name = 't1' into @a;
insert into t2 values (1);
+--echo #
--echo # MDEV-14740 Locking assertion for system_time partitioning
+--echo #
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 week;
create or replace table t2 (f int);
@@ -314,7 +618,9 @@ create or replace trigger tr before insert on t2
for each row select count(*) from t1 into @a;
insert into t2 values (1);
+--echo #
--echo # MDEV-14747 ALTER PARTITION BY SYSTEM_TIME after LOCK TABLES
+--echo #
create or replace table t1 (x int) with system versioning;
lock table t1 write;
alter table t1 partition by system_time interval 1 week (
@@ -322,7 +628,9 @@ alter table t1 partition by system_time interval 1 week (
partition pn current);
unlock tables;
+--echo #
--echo # MDEV-14748 Assertion in ha_myisammrg::attach_children()
+--echo #
create or replace table t1 (x int) engine=myisam with system versioning
partition by system_time interval 1 month (partition p1 history, partition pn current);
create or replace table t2 (x int) engine=myisam;
@@ -332,17 +640,22 @@ create or replace trigger tr after insert on t4 for each row insert into t2
( select x from t3 ) union ( select x from t1 );
insert into t4 values (1);
+--echo #
--echo # MDEV-14821 Assertion failure
+--echo #
create or replace table t1 (x int) with system versioning;
insert into t1 values (0), (1);
update t1 set x= x + 1;
alter table t1 partition by system_time limit 1 (
partition p1 history,
partition p2 history,
- partition pn current);delete from t1 where x = 1;
+ partition pn current);
+delete from t1 where x = 1;
delete from t1 where x = 2;
+--echo #
--echo # MDEV-14923 Assertion upon INSERT into locked versioned partitioned table
+--echo #
create or replace table t1 (x int) with system versioning
partition by system_time;
lock table t1 write;
@@ -351,27 +664,6 @@ alter table t1 add partition (partition p0 history);
insert into t1 values (1);
unlock tables;
---error ER_DATA_OUT_OF_RANGE
-create or replace table t1 (pk int) with system versioning
-partition by system_time interval 10 year partitions 3;
-
-# INTERVAL and ALTER TABLE
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 hour;
-
-set @ts=(select partition_description from information_schema.partitions
- where table_schema='test' and table_name='t1' and partition_name='p0');
-
-alter table t1 add column b int;
-select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
-alter table t1 add partition (partition p1 history, partition p2 history);
-select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
-alter table t1 drop partition p0;
-select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
---error ER_VERS_DROP_PARTITION_INTERVAL
-alter table t1 drop partition p2;
-select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1';
-
--echo #
--echo # MDEV-15103 Assertion in ha_partition::part_records() for updating VIEW
--echo #
@@ -389,7 +681,9 @@ partition by system_time;
--error ER_DROP_VERSIONING_SYSTEM_TIME_PARTITION
alter table t drop system versioning;
+--echo #
--echo # MDEV-15191 Assertion `bit < (map)->n_bits' failed in bitmap_is_set upon INSERT
+--echo #
create or replace table t1 (i int) with system versioning;
insert into t1 values (1), (2);
update t1 set i= 3;
@@ -399,7 +693,9 @@ alter table t1 add partition (partition p2 history);
insert into t1 values (4);
unlock tables;
+--echo #
--echo # MDEV-15036 Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())' in Diagnostics_area::set_ok_status or unexpected ER_RANGE_NOT_INCREASING_ERROR
+--echo #
create or replace table t1 (a int) with system versioning
partition by system_time limit 2 partitions 4;
insert into t1 values (1),(2),(3);
@@ -407,12 +703,24 @@ update t1 set a = 4;
delete from t1;
delete from t1 where a is not null;
+--echo #
--echo # MDEV-14823 Wrong error message upon selecting from a system_time partition
+--echo #
create or replace table t1 (i int) with system versioning partition by system_time limit 10;
--error ER_VERS_QUERY_IN_PARTITION
select * from t1 partition (p0) for system_time all;
+--echo # MDEV-18929 2nd execution of SP does not detect ER_VERS_NOT_VERSIONED
+create or replace procedure sp()
+select * from t1 partition (p0) for system_time all;
+--error ER_VERS_QUERY_IN_PARTITION
+call sp;
+--error ER_VERS_QUERY_IN_PARTITION
+call sp;
+drop procedure sp;
+--echo #
--echo # MDEV-15380 Index for versioned table gets corrupt after partitioning and DELETE
+--echo #
create or replace table t1 (pk int primary key)
engine=myisam
with system versioning
@@ -501,4 +809,19 @@ update t1 set a= 'bar' limit 4;
select * from t1;
drop table t1;
+--echo #
+--echo # MDEV-21011 Table corruption reported for versioned partitioned table after DELETE: "Found a misplaced row"
+--echo #
+create table t1 (a int) with system versioning
+partition by system_time limit 3
+(partition p1 history, partition p2 history, partition pn current);
+insert into t1 values (1),(2),(3),(4);
+delete from t1;
+delete from t1;
+check table t1;
+
+# cleanup
+drop table t1;
+
+
--source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/partition_innodb.test b/mysql-test/suite/versioning/t/partition_innodb.test
deleted file mode 100644
index 088a4b81252..00000000000
--- a/mysql-test/suite/versioning/t/partition_innodb.test
+++ /dev/null
@@ -1,80 +0,0 @@
---source include/have_innodb.inc
---source include/have_partition.inc
---source suite/versioning/common.inc
-
---echo # MDEV-15951 system versioning by trx id doesn't work with partitioning
---echo # currently trx_id does not support partitioning by system_time
---error ER_VERS_FIELD_WRONG_TYPE
-create or replace table t1(
- i int,
- row_start bigint unsigned generated always as row start,
- row_end bigint unsigned generated always as row end,
- period for system_time(row_start, row_end)
-) engine=InnoDB with system versioning partition by system_time (
- partition p0 history,
- partition pn current
-);
-
-create or replace table t1(
- i int,
- row_start bigint unsigned generated always as row start,
- row_end bigint unsigned generated always as row end,
- period for system_time(row_start, row_end)
-) engine=InnoDB with system versioning;
-
---error ER_VERS_FIELD_WRONG_TYPE
-alter table t1 partition by system_time (
- partition p0 history,
- partition pn current
-);
-
-drop table t1;
-
---error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
-create or replace table t (
- a int primary key,
- row_start bigint unsigned as row start invisible,
- row_end bigint unsigned as row end invisible,
- period for system_time(row_start, row_end)
-) engine=innodb with system versioning
-partition by key() (
- partition p1,
- partition p2
-);
-
---error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
-create or replace table t (
- a int primary key,
- row_start bigint unsigned as row start invisible,
- row_end bigint unsigned as row end invisible,
- period for system_time(row_start, row_end)
-) engine=innodb with system versioning
-partition by key(a, row_start) (
- partition p1,
- partition p2
-);
-
---error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
-create or replace table t (
- a int primary key,
- row_start bigint unsigned as row start invisible,
- row_end bigint unsigned as row end invisible,
- period for system_time(row_start, row_end)
-) engine=innodb with system versioning
-partition by hash(a + row_end * 2) (
- partition p1,
- partition p2
-);
-
---error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
-create or replace table t (
- a int primary key,
- row_start bigint unsigned as row start invisible,
- row_end bigint unsigned as row end invisible,
- period for system_time(row_start, row_end)
-) engine=innodb with system versioning
-partition by range columns (a, row_start) (
- partition p1 values less than (100, 100)
-);
-
---source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/partition_rotation.test b/mysql-test/suite/versioning/t/partition_rotation.test
deleted file mode 100644
index 60b2e6c61fe..00000000000
--- a/mysql-test/suite/versioning/t/partition_rotation.test
+++ /dev/null
@@ -1,178 +0,0 @@
---source include/have_partition.inc
-
-set time_zone= "+00:00";
-call mtr.add_suppression("need more HISTORY partitions");
-
-#
-# partition rotation
-#
-set timestamp=unix_timestamp('2001-02-03 10:20:30');
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day
- subpartition by key (i) subpartitions 2
- (partition p1 history, partition pn current);
-set timestamp=unix_timestamp('2001-02-03 10:20:40');
-insert t1 values (1); delete from t1;
-set timestamp=unix_timestamp('2001-02-04 10:20:50');
-insert t1 values (2); delete from t1;
-
-select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
-
-set timestamp=unix_timestamp('2001-02-04 10:20:55');
-alter table t1 add partition (partition p0 history, partition p2 history);
-set timestamp=unix_timestamp('2001-02-04 10:30:00');
-insert t1 values (4),(5);
-set timestamp=unix_timestamp('2001-02-04 10:30:10');
-update t1 set i=6 where i=5;
-
-select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
-
---echo ## pruning check
-set @ts=(select partition_description from information_schema.partitions
- where table_schema='test' and table_name='t1' and partition_name='p0' limit 1);
---sorted_result
-select * from t1;
-explain partitions select * from t1;
---replace_column 10 #
-explain partitions select * from t1 for system_time as of '2001-02-04 10:20:30';
-set @ts=(select row_end from t1 for system_time all where i=1);
-select * from t1 for system_time all where row_end = @ts;
---replace_column 5 # 10 # 11 #
-explain partitions select * from t1 for system_time all where row_end = @ts;
-
---echo ## INTERVAL ... STARTS
---error ER_PART_WRONG_VALUE
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts 'a';
-
---error ER_PART_WRONG_VALUE
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '00:00:00';
-
---error ER_PART_WRONG_VALUE
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-00-01 00:00:00';
-
---error ER_PART_WRONG_VALUE
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts 946684800;
-
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-01 00:00:00';
-show create table t1;
-
---echo # Test STARTS warning
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day;
-show create table t1;
-
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-01 00:00:01';
-
---echo # Test default STARTS rounding
-set timestamp= unix_timestamp('1999-12-15 13:33:33');
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 second;
-show create table t1;
-
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 minute;
-show create table t1;
-
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 hour;
-show create table t1;
-
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day;
-show create table t1;
-
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 month;
-show create table t1;
-
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 year;
-show create table t1;
-
---echo # seconds equivalent of 1 day does not round:
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 86400 second;
-show create table t1;
-
---echo # STARTS value is in local time_zone:
-set time_zone="+03:00";
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-01 00:00:00';
-
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
-create or replace table t2 (i int) with system versioning
-partition by system_time interval 1 day;
-
-show create table t1;
-show create table t2;
-set time_zone="+00:00";
-show create table t1;
-show create table t2;
-
---echo # Test rotation
-set timestamp= unix_timestamp('2001-01-01 00:00:00');
---echo # it's ok to add partitions for past:
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-01 00:00:00'
-partitions 3;
-
---echo # we are warned when we push to present:
-insert into t1 values (0);
-set timestamp= unix_timestamp('2001-01-01 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2001-01-01 00:00:02');
-update t1 set i= i + 1;
-
-select *, row_end from t1 partition (p0);
-select *, row_end from t1 partition (p1);
-
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
---echo # now we "overflow" first partition a bit:
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day starts '2000-01-03 00:00:00'
-partitions 3;
-
-insert into t1 values (0);
-set timestamp= unix_timestamp('2000-01-01 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-02 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-03 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-04 00:00:01');
-update t1 set i= i + 1;
-
-select *, row_end from t1 partition (p0);
-select *, row_end from t1 partition (p1);
-
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
---echo # and this is how it usually goes:
-create or replace table t1 (i int) with system versioning
-partition by system_time interval 1 day
-partitions 3;
-
-insert into t1 values (0);
-set timestamp= unix_timestamp('2000-01-01 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-02 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-03 00:00:01');
-update t1 set i= i + 1;
-set timestamp= unix_timestamp('2000-01-04 00:00:01');
-update t1 set i= i + 1;
-
-alter table t1 add partition (partition p2 history, partition p3 history);
-
-select *, row_end from t1 partition (p0);
-select *, row_end from t1 partition (p1);
-select *, row_end from t1 partition (p2);
-select *, row_end from t1 partition (p3);
-
-drop tables t1, t2;
diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test
index e8d34e55b16..1767457401e 100644
--- a/mysql-test/suite/versioning/t/select.test
+++ b/mysql-test/suite/versioning/t/select.test
@@ -228,6 +228,21 @@ for system_time all as t;
create or replace table t1 (x int) with system versioning engine myisam;
--error ER_VERS_ENGINE_UNSUPPORTED
select * from t1 for system_time as of transaction 1;
+--echo # MDEV-18929 2nd execution of SP does not detect ER_VERS_NOT_VERSIONED
+create or replace procedure sp()
+select * from t1 for system_time as of transaction 1;
+--error ER_VERS_ENGINE_UNSUPPORTED
+call sp;
+--error ER_VERS_ENGINE_UNSUPPORTED
+call sp;
+create or replace table t1 (a int);
+create or replace procedure sp()
+select * from t1 for system_time all;
+--error ER_VERS_NOT_VERSIONED
+call sp;
+--error ER_VERS_NOT_VERSIONED
+call sp;
+drop procedure sp;
create or replace table t1 (
x int,
diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test
index e41c7d15995..baf3c1ec876 100644
--- a/mysql-test/suite/versioning/t/update.test
+++ b/mysql-test/suite/versioning/t/update.test
@@ -157,7 +157,6 @@ replace t1 values (1,2),(1,3),(2,4);
--echo #
--echo # MDEV-14829 Assertion `0' failed in Protocol::end_statement upon concurrent UPDATE
--echo #
-
create or replace table t1 (pk int, a char(3), b char(3), primary key(pk))
engine=innodb with system versioning;
@@ -192,4 +191,31 @@ drop view v;
drop table t1, t2;
--enable_warnings
+--echo #
+--echo # MDEV-20441 ER_CRASHED_ON_USAGE upon update on versioned Aria table
+--echo #
+create or replace table t1 (a varchar(8))
+engine=aria row_format=fixed
+with system versioning;
+
+insert into t1 (a) values ('foo');
+update t1 set a = 'bar';
+drop table t1;
+
+--echo #
+--echo # MDEV-21147 Assertion `marked_for_read()' upon UPDATE on versioned table via view
+--echo #
+create or replace table t1 (
+ pk int, a char(8), b char(8),
+ primary key (pk)
+) with system versioning;
+
+create or replace view v1 as select * from t1;
+insert into t1 values (1, null, 'd') , (2, null, 'i') ;
+update v1 set a= null where b = '';
+
+# cleanup
+drop view v1;
+drop table t1;
+
source suite/versioning/common_finish.inc;
diff --git a/mysql-test/suite/versioning/t/view.test b/mysql-test/suite/versioning/t/view.test
index c05fbfd3866..288f1eb6e21 100644
--- a/mysql-test/suite/versioning/t/view.test
+++ b/mysql-test/suite/versioning/t/view.test
@@ -136,6 +136,7 @@ eval create or replace table t1 (
) with system versioning;
insert into t1 values (1), (2);
create or replace view v1 as select * from t1 where x > 1;
+--echo # update, delete
update v1 set x= x + 1;
select *, check_row(row_start, row_end) from t1 for system_time all order by x;
insert v1 values (4);
@@ -153,8 +154,63 @@ select *, check_row(row_start, row_end) from t2 for system_time all order by x;
delete v1, v2 from v1 join v2 where v1.x = v2.x + 2;
select *, check_row(row_start, row_end) from t1 for system_time all order by x;
select *, check_row(row_start, row_end) from t2 for system_time all order by x;
-
+--echo # replace
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create or replace table t1 (
+ x int primary key, y int,
+ row_start $sys_datatype_expl as row start invisible,
+ row_end $sys_datatype_expl as row end invisible,
+ period for system_time (row_start, row_end)
+) with system versioning;
+insert into t1 values (1, 0), (2, 0);
+create or replace view v1 as select * from t1 where x > 1;
+replace v1 values (1, 1);
+replace v1 values (2, 1);
+replace v1 values (3, 1);
+--echo # REPLACE ignores VIEW condition because itself doesn't use WHERE
+select *, check_row(row_start, row_end) from t1 for system_time all order by x, row_end;
+--echo # insert-select, on duplicate key
+insert v1 select * from t1 where x = 1 on duplicate key update x = v1.x - 1;
+select *, check_row(row_start, row_end) from t1 for system_time all order by x, row_end;
drop view v1, v2;
drop tables t1, t2;
+--echo #
+--echo # MDEV-21146 Assertion `m_lock_type == 2' in handler::ha_drop_table upon LOAD DATA
+--echo #
+create table t1 (a int);
+create view v1 as select * from t1;
+create or replace table t1 (b int) with system versioning;
+--error ER_VIEW_INVALID
+load data infile 'xx' into table v1;
+
+# cleanup
+drop view v1;
+drop table t1;
+
+--echo #
+--echo # MDEV-21155 Assertion with versioned table upon DELETE from view of view after replacing first view
+--echo #
+create table t1 (a int);
+insert into t1 values (1);
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create table t2 (
+ b int,
+ row_start $sys_datatype_expl as row start invisible,
+ row_end $sys_datatype_expl as row end invisible,
+ period for system_time (row_start, row_end)
+) with system versioning;
+insert into t2 values (2);
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+create or replace view v1 as select * from t2;
+delete from v2;
+select * from t1;
+select *, check_row(row_start, row_end) from t2 for system_time all;
+
+# cleanup
+drop view v2;
+drop view v1;
+drop table t1, t2;
+
--source suite/versioning/common_finish.inc
diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c
index 2a0ee7fddf9..b98684556c3 100644
--- a/mysys/lf_alloc-pin.c
+++ b/mysys/lf_alloc-pin.c
@@ -151,7 +151,6 @@ void lf_pinbox_destroy(LF_PINBOX *pinbox)
*/
LF_PINS *lf_pinbox_get_pins(LF_PINBOX *pinbox)
{
- struct st_my_thread_var *var;
uint32 pins, next, top_ver;
LF_PINS *el;
/*
@@ -194,12 +193,7 @@ LF_PINS *lf_pinbox_get_pins(LF_PINBOX *pinbox)
el->link= pins;
el->purgatory_count= 0;
el->pinbox= pinbox;
- var= my_thread_var;
- /*
- Threads that do not call my_thread_init() should still be
- able to use the LF_HASH.
- */
- el->stack_ends_here= (var ? & var->stack_ends_here : NULL);
+
return el;
}
@@ -335,16 +329,18 @@ static void lf_pinbox_real_free(LF_PINS *pins)
void *list;
void **addr= NULL;
void *first= NULL, *last= NULL;
+ struct st_my_thread_var *var= my_thread_var;
+ void *stack_ends_here= var ? var->stack_ends_here : NULL;
LF_PINBOX *pinbox= pins->pinbox;
npins= pinbox->pins_in_array+1;
#ifdef HAVE_ALLOCA
- if (pins->stack_ends_here != NULL)
+ if (stack_ends_here != NULL)
{
int alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins;
/* create a sorted list of pinned addresses, to speed up searches */
- if (available_stack_size(&pinbox, *pins->stack_ends_here) >
+ if (available_stack_size(&pinbox, stack_ends_here) >
alloca_size + ALLOCA_SAFETY_MARGIN)
{
struct st_harvester hv;
diff --git a/plugin/versioning/versioning.cc b/plugin/versioning/versioning.cc
index 7e3c29e1494..a2f39352ab2 100644
--- a/plugin/versioning/versioning.cc
+++ b/plugin/versioning/versioning.cc
@@ -22,7 +22,8 @@
#include "sql_plugin.h" // st_plugin_int
#include "sql_class.h"
#include "item.h"
-#include "vers_utils.h"
+#include "table.h"
+#include "vers_string.h"
/* System Versioning: TRT_TRX_ID(), TRT_COMMIT_ID(), TRT_BEGIN_TS(), TRT_COMMIT_TS(), TRT_ISO_LEVEL() */
template <TR_table::field_id_t TRT_FIELD>
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 83a1ea0abe7..4545bca5768 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -62,6 +62,17 @@ ADD_CUSTOM_COMMAND(
DEPENDS gen_lex_token
)
+ADD_CUSTOM_COMMAND(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.yy
+ COMMAND ${CMAKE_COMMAND}
+ "-DIN=${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.yy"
+ "-DOUT=${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.yy"
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/gen_sql_yacc_ora_yy.cmake
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.yy
+)
+
+ADD_CUSTOM_TARGET(gen_sql_yacc_ora_yy DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.yy)
+
ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER)
IF(SSL_DEFINES)
@@ -367,8 +378,7 @@ IF (NOT BISON_FOUND)
ELSE()
BISON_TARGET(gen_sql_yacc ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.yy ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc
COMPILE_FLAGS "-p MYSQL")
-
- BISON_TARGET(gen_sql_yacc_ora ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc_ora.yy ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
+ BISON_TARGET(gen_sql_yacc_ora ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.yy ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
COMPILE_FLAGS "-p ORA")
ENDIF()
@@ -396,6 +406,8 @@ ADD_CUSTOM_TARGET(
${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
)
+ADD_DEPENDENCIES(GenServerSource gen_sql_yacc_ora_yy)
+
IF(WIN32 OR HAVE_DLOPEN AND NOT DISABLE_SHARED)
ADD_LIBRARY(udf_example MODULE udf_example.c udf_example.def)
SET_TARGET_PROPERTIES(udf_example PROPERTIES PREFIX "")
diff --git a/sql/gen_sql_yacc_ora_yy.cmake b/sql/gen_sql_yacc_ora_yy.cmake
new file mode 100644
index 00000000000..3fdd5d43f8d
--- /dev/null
+++ b/sql/gen_sql_yacc_ora_yy.cmake
@@ -0,0 +1,15 @@
+
+file(READ "${IN}" yytmp)
+
+# Comment out sql_mode=DEFAULT rules and directives (e.g. %expect, %type)
+string(REPLACE "/* Start SQL_MODE_DEFAULT_SPECIFIC */"
+ "/* Start SQL_MODE_DEFAULT_SPECIFIC" yytmp "${yytmp}")
+string(REPLACE "/* End SQL_MODE_DEFAULT_SPECIFIC */"
+ "End SQL_MODE_DEFAULT_SPECIFIC */" yytmp "${yytmp}")
+
+# Uncomment sql_mode=ORACLE rules and directives
+string(REPLACE "/* Start SQL_MODE_ORACLE_SPECIFIC"
+ "/* Start SQL_MODE_ORACLE_SPECIFIC */" yytmp "${yytmp}")
+string(REPLACE "End SQL_MODE_ORACLE_SPECIFIC */"
+ "/* End SQL_MODE_ORACLE_SPECIFIC */" yytmp "${yytmp}")
+file(WRITE "${OUT}" "${yytmp}")
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index d40913c21d1..77a53668638 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4821,6 +4821,42 @@ ha_rows ha_partition::guess_bulk_insert_rows()
}
+void ha_partition::sum_copy_info(handler *file)
+{
+ copy_info.records+= file->copy_info.records;
+ copy_info.touched+= file->copy_info.touched;
+ copy_info.copied+= file->copy_info.copied;
+ copy_info.deleted+= file->copy_info.deleted;
+ copy_info.updated+= file->copy_info.updated;
+}
+
+
+void ha_partition::sum_copy_infos()
+{
+ handler **file_array;
+ bzero(&copy_info, sizeof(copy_info));
+ file_array= m_file;
+ do
+ {
+ if (bitmap_is_set(&(m_opened_partitions), (uint)(file_array - m_file)))
+ sum_copy_info(*file_array);
+ } while (*(++file_array));
+}
+
+void ha_partition::reset_copy_info()
+{
+ handler **file_array;
+ bzero(&copy_info, sizeof(copy_info));
+ file_array= m_file;
+ do
+ {
+ if (bitmap_is_set(&(m_opened_partitions), (uint)(file_array - m_file)))
+ bzero(&(*file_array)->copy_info, sizeof(copy_info));
+ } while (*(++file_array));
+}
+
+
+
/*
Finish a large batch of insert rows
@@ -4852,6 +4888,7 @@ int ha_partition::end_bulk_insert()
int tmp;
if ((tmp= m_file[i]->ha_end_bulk_insert()))
error= tmp;
+ sum_copy_info(m_file[i]);
}
bitmap_clear_all(&m_bulk_insert_started);
DBUG_RETURN(error);
@@ -10779,8 +10816,8 @@ int ha_partition::indexes_are_disabled(void)
@param repair If true, move misplaced rows to correct partition.
@return Operation status.
- @retval 0 Success
- @retval != 0 Error
+ @retval HA_ADMIN_OK Success
+ @retval != HA_ADMIN_OK Error
*/
int ha_partition::check_misplaced_rows(uint read_part_id, bool do_repair)
@@ -10794,6 +10831,17 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool do_repair)
DBUG_ASSERT(m_file);
+ if (m_part_info->vers_info &&
+ read_part_id != m_part_info->vers_info->now_part->id &&
+ !m_part_info->vers_info->interval.is_set())
+ {
+ print_admin_msg(ha_thd(), MYSQL_ERRMSG_SIZE, "note",
+ table_share->db.str, table->alias,
+ opt_op_name[CHECK_PARTS],
+ "Not supported for non-INTERVAL history partitions");
+ DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
+ }
+
if (do_repair)
{
/* We must read the full row, if we need to move it! */
@@ -11150,6 +11198,7 @@ bool ha_partition::start_bulk_update()
do
{
+ bzero(&(*file)->copy_info, sizeof((*file)->copy_info));
if ((*file)->start_bulk_update())
DBUG_RETURN(TRUE);
} while (*(++file));
@@ -11207,6 +11256,7 @@ int ha_partition::end_bulk_update()
if ((tmp= (*file)->end_bulk_update()))
error= tmp;
} while (*(++file));
+ sum_copy_infos();
DBUG_RETURN(error);
}
@@ -11303,6 +11353,7 @@ int ha_partition::end_bulk_delete()
if ((tmp= (*file)->end_bulk_delete()))
error= tmp;
} while (*(++file));
+ sum_copy_infos();
DBUG_RETURN(error);
}
@@ -11419,11 +11470,13 @@ int ha_partition::pre_direct_update_rows_init(List<Item> *update_fields)
0 Success
*/
-int ha_partition::direct_update_rows(ha_rows *update_rows_result)
+int ha_partition::direct_update_rows(ha_rows *update_rows_result,
+ ha_rows *found_rows_result)
{
int error;
bool rnd_seq= FALSE;
ha_rows update_rows= 0;
+ ha_rows found_rows= 0;
uint32 i;
DBUG_ENTER("ha_partition::direct_update_rows");
@@ -11435,6 +11488,7 @@ int ha_partition::direct_update_rows(ha_rows *update_rows_result)
}
*update_rows_result= 0;
+ *found_rows_result= 0;
for (i= m_part_spec.start_part; i <= m_part_spec.end_part; i++)
{
handler *file= m_file[i];
@@ -11450,7 +11504,8 @@ int ha_partition::direct_update_rows(ha_rows *update_rows_result)
}
if (unlikely((error= (m_pre_calling ?
(file)->pre_direct_update_rows() :
- (file)->ha_direct_update_rows(&update_rows)))))
+ (file)->ha_direct_update_rows(&update_rows,
+ &found_rows)))))
{
if (rnd_seq)
{
@@ -11462,6 +11517,7 @@ int ha_partition::direct_update_rows(ha_rows *update_rows_result)
DBUG_RETURN(error);
}
*update_rows_result+= update_rows;
+ *found_rows_result+= found_rows;
}
if (rnd_seq)
{
@@ -11497,7 +11553,7 @@ int ha_partition::pre_direct_update_rows()
DBUG_ENTER("ha_partition::pre_direct_update_rows");
save_m_pre_calling= m_pre_calling;
m_pre_calling= TRUE;
- error= direct_update_rows(&not_used);
+ error= direct_update_rows(&not_used, &not_used);
m_pre_calling= save_m_pre_calling;
DBUG_RETURN(error);
}
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index ff02ea5aa1c..62adca8c72f 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -391,6 +391,9 @@ private:
part_share->next_auto_inc_val= part_share->prev_auto_inc_val;
handler::restore_auto_increment();
}
+ void sum_copy_info(handler *file);
+ void sum_copy_infos();
+ void reset_copy_info();
/** Temporary storage for new partitions Handler_shares during ALTER */
List<Parts_share_refs> m_new_partitions_share_refs;
/** Sorted array of partition ids in descending order of number of rows. */
@@ -657,7 +660,7 @@ public:
virtual int update_row(const uchar * old_data, const uchar * new_data);
virtual int direct_update_rows_init(List<Item> *update_fields);
virtual int pre_direct_update_rows_init(List<Item> *update_fields);
- virtual int direct_update_rows(ha_rows *update_rows);
+ virtual int direct_update_rows(ha_rows *update_rows, ha_rows *found_rows);
virtual int pre_direct_update_rows();
virtual bool start_bulk_delete();
virtual int end_bulk_delete();
diff --git a/sql/handler.cc b/sql/handler.cc
index 46a0c313c80..624eece9b09 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -6795,14 +6795,14 @@ int handler::ha_delete_row(const uchar *buf)
@retval != 0 Failure.
*/
-int handler::ha_direct_update_rows(ha_rows *update_rows)
+int handler::ha_direct_update_rows(ha_rows *update_rows, ha_rows *found_rows)
{
int error;
MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
mark_trx_read_write();
- error = direct_update_rows(update_rows);
+ error = direct_update_rows(update_rows, found_rows);
MYSQL_UPDATE_ROW_DONE(error);
return error;
}
diff --git a/sql/handler.h b/sql/handler.h
index 6c9b8f4edcb..e22361b3449 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -931,6 +931,16 @@ enum tablespace_access_mode
TS_NOT_ACCESSIBLE = 2
};
+/* Statistics about batch operations like bulk_insert */
+struct ha_copy_info
+{
+ ha_rows records; /* Used to check if rest of variables can be used */
+ ha_rows touched;
+ ha_rows copied;
+ ha_rows deleted;
+ ha_rows updated;
+};
+
struct handlerton;
class st_alter_tablespace : public Sql_alloc
{
@@ -3065,6 +3075,7 @@ public:
ulonglong rows_changed;
/* One bigger than needed to avoid to test if key == MAX_KEY */
ulonglong index_rows_read[MAX_KEY+1];
+ ha_copy_info copy_info;
private:
/* ANALYZE time tracker, if present */
@@ -3280,6 +3291,7 @@ public:
{
DBUG_ENTER("handler::ha_start_bulk_insert");
estimation_rows_to_insert= rows;
+ bzero(&copy_info,sizeof(copy_info));
start_bulk_insert(rows, flags);
DBUG_VOID_RETURN;
}
@@ -3351,6 +3363,13 @@ public:
{
rows_read= rows_changed= rows_tmp_read= 0;
bzero(index_rows_read, sizeof(index_rows_read));
+ bzero(&copy_info, sizeof(copy_info));
+ }
+ virtual void reset_copy_info() {}
+ void ha_reset_copy_info()
+ {
+ bzero(&copy_info, sizeof(copy_info));
+ reset_copy_info();
}
virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share)
{
@@ -4584,7 +4603,7 @@ private:
/* Perform initialization for a direct update request */
public:
- int ha_direct_update_rows(ha_rows *update_rows);
+ int ha_direct_update_rows(ha_rows *update_rows, ha_rows *found_rows);
virtual int direct_update_rows_init(List<Item> *update_fields)
{
return HA_ERR_WRONG_COMMAND;
@@ -4594,7 +4613,8 @@ private:
{
return HA_ERR_WRONG_COMMAND;
}
- virtual int direct_update_rows(ha_rows *update_rows __attribute__((unused)))
+ virtual int direct_update_rows(ha_rows *update_rows __attribute__((unused)),
+ ha_rows *found_rows __attribute__((unused)))
{
return HA_ERR_WRONG_COMMAND;
}
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index c2edd604f0d..252744a3a73 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -32,9 +32,10 @@
#include "sql_parse.h"
#include "sql_acl.h" // *_ACL
#include "sql_base.h" // fill_record
-#include "sql_statistics.h" // vers_stat_end
-#include "vers_utils.h"
#include "lock.h"
+#include "table.h"
+#include "sql_class.h"
+#include "vers_string.h"
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
@@ -196,49 +197,6 @@ bool partition_info::set_named_partition_bitmap(const char *part_name, size_t le
}
-
-/**
- Prune away partitions not mentioned in the PARTITION () clause,
- if used.
-
- @param table_list Table list pointing to table to prune.
-
- @return Operation status
- @retval false Success
- @retval true Failure
-*/
-bool partition_info::set_read_partitions(List<char> *partition_names)
-{
- DBUG_ENTER("partition_info::set_read_partitions");
- if (!partition_names || !partition_names->elements)
- {
- DBUG_RETURN(true);
- }
-
- uint num_names= partition_names->elements;
- List_iterator<char> partition_names_it(*partition_names);
- uint i= 0;
- /*
- TODO: When adding support for FK in partitioned tables, the referenced
- table must probably lock all partitions for read, and also write depending
- of ON DELETE/UPDATE.
- */
- bitmap_clear_all(&read_partitions);
-
- /* No check for duplicate names or overlapping partitions/subpartitions. */
-
- DBUG_PRINT("info", ("Searching through partition_name_hash"));
- do
- {
- char *part_name= partition_names_it++;
- if (add_named_partition(part_name, strlen(part_name)))
- DBUG_RETURN(true);
- } while (++i < num_names);
- DBUG_RETURN(false);
-}
-
-
-
/**
Prune away partitions not mentioned in the PARTITION () clause,
if used.
@@ -849,6 +807,15 @@ bool partition_info::has_unique_name(partition_element *element)
DBUG_RETURN(TRUE);
}
+
+/**
+ @brief Switch history partition according limit or interval
+
+ @note
+ vers_info->limit Limit by number of partition records
+ vers_info->interval Limit by fixed time interval
+ vers_info->hist_part (out) Working history partition
+*/
void partition_info::vers_set_hist_part(THD *thd)
{
if (vers_info->limit)
@@ -867,7 +834,7 @@ void partition_info::vers_set_hist_part(THD *thd)
vers_info->hist_part= next;
records= next_records;
}
- if (records > vers_info->limit)
+ if (records >= vers_info->limit)
{
if (next == vers_info->now_part)
{
@@ -904,49 +871,6 @@ void partition_info::vers_set_hist_part(THD *thd)
}
-bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add)
-{
- if (!table->versioned())
- {
- // frm must be corrupted, normally CREATE/ALTER TABLE checks for that
- my_error(ER_FILE_CORRUPT, MYF(0), table->s->path.str);
- return true;
- }
-
- DBUG_ASSERT(part_type == VERSIONING_PARTITION);
- DBUG_ASSERT(table->versioned(VERS_TIMESTAMP));
-
- if (!alter_add)
- {
- Field *row_end= table->vers_end_field();
- // needed in handle_list_of_fields()
- row_end->flags|= GET_FIXED_FIELDS_FLAG;
- Name_resolution_context *context= &thd->lex->current_select->context;
- Item *row_end_item= new (thd->mem_root) Item_field(thd, context, row_end);
- Item *row_end_ts= new (thd->mem_root) Item_func_unix_timestamp(thd, row_end_item);
- set_part_expr(thd, row_end_ts, false);
- }
-
- if (alter_add)
- {
- List_iterator<partition_element> it(partitions);
- partition_element *el;
- for(uint32 id= 0; ((el= it++)); id++)
- {
- DBUG_ASSERT(el->type != partition_element::CONVENTIONAL);
- /* Newly added element is inserted before AS_OF_NOW. */
- if (el->id == UINT_MAX32 || el->type == partition_element::CURRENT)
- {
- el->id= id;
- if (el->type == partition_element::CURRENT)
- break;
- }
- }
- }
- return false;
-}
-
-
/*
Check that the partition/subpartition is setup to use the correct
storage engine
@@ -1424,9 +1348,8 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
if (add_or_reorg_part)
{
- if (unlikely(part_type == VERSIONING_PARTITION &&
- vers_setup_expression(thd, add_or_reorg_part->partitions.elements)))
- goto end;
+ if (part_type == VERSIONING_PARTITION && add_or_reorg_part->partitions.elements)
+ vers_update_el_ids();
if (check_constants(thd, this))
goto end;
}
diff --git a/sql/partition_info.h b/sql/partition_info.h
index 3a34ad88d28..eb8e53a381a 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -385,11 +385,9 @@ private:
uint start_no);
char *create_default_subpartition_name(THD *thd, uint subpart_no,
const char *part_name);
- // FIXME: prune_partition_bitmaps() is duplicate of set_read_partitions()
- bool prune_partition_bitmaps(List<String> *partition_names);
+ bool prune_partition_bitmaps(List<String> *partition_names); // set_read_partitions() in 8.0
bool add_named_partition(const char *part_name, size_t length);
public:
- bool set_read_partitions(List<char> *partition_names);
bool has_unique_name(partition_element *element);
bool field_in_partition_expr(Field *field) const;
@@ -404,7 +402,8 @@ public:
return !limit;
}
void vers_set_hist_part(THD *thd);
- bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */
+ bool vers_fix_field_list(THD *thd);
+ void vers_update_el_ids();
partition_element *get_partition(uint part_id)
{
List_iterator<partition_element> it(partitions);
@@ -445,4 +444,60 @@ void init_all_partitions_iterator(partition_info *part_info,
part_iter->get_next= get_next_partition_id_range;
}
+
+/**
+ @brief Update part_field_list by row_end field name
+
+ @returns true on error; false on success
+*/
+inline
+bool partition_info::vers_fix_field_list(THD * thd)
+{
+ if (!table->versioned())
+ {
+ // frm must be corrupted, normally CREATE/ALTER TABLE checks for that
+ my_error(ER_FILE_CORRUPT, MYF(0), table->s->path.str);
+ return true;
+ }
+ DBUG_ASSERT(part_type == VERSIONING_PARTITION);
+ DBUG_ASSERT(table->versioned(VERS_TIMESTAMP));
+
+ Field *row_end= table->vers_end_field();
+ // needed in handle_list_of_fields()
+ row_end->flags|= GET_FIXED_FIELDS_FLAG;
+ Name_resolution_context *context= &thd->lex->current_select->context;
+ Item *row_end_item= new (thd->mem_root) Item_field(thd, context, row_end);
+ Item *row_end_ts= new (thd->mem_root) Item_func_unix_timestamp(thd, row_end_item);
+ set_part_expr(thd, row_end_ts, false);
+
+ return false;
+}
+
+
+/**
+ @brief Update partition_element's id
+
+ @returns true on error; false on success
+*/
+inline
+void partition_info::vers_update_el_ids()
+{
+ DBUG_ASSERT(part_type == VERSIONING_PARTITION);
+ DBUG_ASSERT(table->versioned(VERS_TIMESTAMP));
+
+ List_iterator<partition_element> it(partitions);
+ partition_element *el;
+ for(uint32 id= 0; ((el= it++)); id++)
+ {
+ DBUG_ASSERT(el->type != partition_element::CONVENTIONAL);
+ /* Newly added element is inserted before AS_OF_NOW. */
+ if (el->id == UINT_MAX32 || el->type == partition_element::CURRENT)
+ {
+ el->id= id;
+ if (el->type == partition_element::CURRENT)
+ break;
+ }
+ }
+}
+
#endif /* PARTITION_INFO_INCLUDED */
diff --git a/sql/proxy_protocol.cc b/sql/proxy_protocol.cc
index b54af619487..550813c6457 100644
--- a/sql/proxy_protocol.cc
+++ b/sql/proxy_protocol.cc
@@ -470,7 +470,7 @@ static int compare_bits(const void *s1, const void *s2, int bit_count)
int byte_count= bit_count / 8;
if (byte_count && (result= memcmp(s1, s2, byte_count)))
return result;
- int rem= byte_count % 8;
+ int rem= bit_count % 8;
if (rem)
{
// compare remaining bits i.e partial bytes.
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 09f8acc536c..fc6bf44bbb1 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -726,12 +726,27 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
{
/*
System versioned tables may still require to get versioning conditions
- (when updating view). See vers_setup_conds().
+ when modifying view (see vers_setup_conds()). Only UPDATE and DELETE are
+ affected because they use WHERE condition.
*/
if (!unit->prepared &&
derived->table->versioned() &&
- (res= unit->prepare(derived, derived->derived_result, 0)))
- goto exit;
+ derived->merge_underlying_list &&
+ /* choose only those merged views that do not select from other views */
+ !derived->merge_underlying_list->merge_underlying_list)
+ {
+ switch (thd->lex->sql_command)
+ {
+ case SQLCOM_DELETE:
+ case SQLCOM_DELETE_MULTI:
+ case SQLCOM_UPDATE:
+ case SQLCOM_UPDATE_MULTI:
+ if ((res= unit->prepare(derived, derived->derived_result, 0)))
+ goto exit;
+ default:
+ break;
+ }
+ }
DBUG_RETURN(FALSE);
}
@@ -881,7 +896,7 @@ exit:
{
if (!derived->is_with_table_recursive_reference())
{
- if (derived->table)
+ if (derived->table && derived->table->s->tmp_table)
free_tmp_table(thd, derived->table);
delete derived->derived_result;
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 329b6a130b0..63ce6ef30cf 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -897,6 +897,8 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
using_bulk_insert= 1;
table->file->ha_start_bulk_insert(values_list.elements);
}
+ else
+ table->file->ha_reset_copy_info();
}
thd->abort_on_warning= !ignore && thd->is_strict_mode();
@@ -1110,11 +1112,23 @@ values_loop_end:
auto_inc values from the delayed_insert thread as they share TABLE.
*/
table->file->ha_release_auto_increment();
- if (using_bulk_insert && unlikely(table->file->ha_end_bulk_insert()) &&
- !error)
+ if (using_bulk_insert)
+ {
+ if (unlikely(table->file->ha_end_bulk_insert()) &&
+ !error)
+ {
+ table->file->print_error(my_errno,MYF(0));
+ error=1;
+ }
+ }
+ /* Get better status from handler if handler supports it */
+ if (table->file->copy_info.records)
{
- table->file->print_error(my_errno,MYF(0));
- error=1;
+ DBUG_ASSERT(info.copied >= table->file->copy_info.copied);
+ info.touched= table->file->copy_info.touched;
+ info.copied= table->file->copy_info.copied;
+ info.deleted= table->file->copy_info.deleted;
+ info.updated= table->file->copy_info.updated;
}
if (duplic != DUP_ERROR || ignore)
{
@@ -1237,9 +1251,12 @@ values_loop_end:
retval= 0;
goto abort;
}
+ DBUG_PRINT("info", ("touched: %llu copied: %llu updated: %llu deleted: %llu",
+ (ulonglong) info.touched, (ulonglong) info.copied,
+ (ulonglong) info.updated, (ulonglong) info.deleted));
- if ((iteration * values_list.elements) == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) ||
- !thd->cuted_fields))
+ if ((iteration * values_list.elements) == 1 &&
+ (!(thd->variables.option_bits & OPTION_WARNINGS) || !thd->cuted_fields))
{
/*
Client expects an EOF/OK packet if result set metadata was sent. If
@@ -1652,6 +1669,8 @@ static int last_uniq_key(TABLE *table,uint keynr)
int vers_insert_history_row(TABLE *table)
{
DBUG_ASSERT(table->versioned(VERS_TIMESTAMP));
+ if (!table->vers_write)
+ return 0;
restore_record(table,record[1]);
// Set Sys_end to now()
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 9e31ce3b31c..ff5c1c6bc58 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -2013,7 +2013,7 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind)
else
{
if (part_info->part_type == VERSIONING_PARTITION &&
- part_info->vers_setup_expression(thd))
+ part_info->vers_fix_field_list(thd))
goto end;
if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
table, FALSE, is_create_table_ind)))
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 20dd8fe222e..220abd31187 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -896,9 +896,7 @@ bool skip_setup_conds(THD *thd)
int SELECT_LEX::period_setup_conds(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("SELECT_LEX::period_setup_conds");
-
- if (skip_setup_conds(thd))
- DBUG_RETURN(0);
+ const bool update_conds= !skip_setup_conds(thd);
Query_arena backup;
Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup);
@@ -919,11 +917,15 @@ int SELECT_LEX::period_setup_conds(THD *thd, TABLE_LIST *tables)
DBUG_RETURN(-1);
}
- conds.period= &table->table->s->period;
- result= and_items(thd, result,
- period_get_condition(thd, table, this, &conds, true));
+ if (update_conds)
+ {
+ conds.period= &table->table->s->period;
+ result= and_items(thd, result,
+ period_get_condition(thd, table, this, &conds, true));
+ }
}
- where= and_items(thd, where, result);
+ if (update_conds)
+ where= and_items(thd, where, result);
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -934,9 +936,7 @@ int SELECT_LEX::period_setup_conds(THD *thd, TABLE_LIST *tables)
int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("SELECT_LEX::vers_setup_conds");
-
- if (skip_setup_conds(thd))
- DBUG_RETURN(0);
+ const bool update_conds= !skip_setup_conds(thd);
if (!versioned_tables)
{
@@ -1007,13 +1007,15 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
*/
if (table->partition_names && table->table->part_info->vers_info)
{
- if (vers_conditions.is_set())
+ /* If the history is stored in partitions, then partitions
+ themselves are not versioned. */
+ if (vers_conditions.was_set())
{
my_error(ER_VERS_QUERY_IN_PARTITION, MYF(0), table->alias.str);
DBUG_RETURN(-1);
}
- else
- vers_conditions.init(SYSTEM_TIME_ALL);
+ else if (!vers_conditions.is_set())
+ vers_conditions.set_all();
}
#endif
@@ -1058,24 +1060,27 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
}
}
- vers_conditions.period = &table->table->s->vers;
- Item *cond= period_get_condition(thd, table, this, &vers_conditions,
- timestamps_only);
- if (is_select)
- table->on_expr= and_items(thd, table->on_expr, cond);
- else
+ if (update_conds)
{
- if (join)
+ vers_conditions.period = &table->table->s->vers;
+ Item *cond= period_get_condition(thd, table, this, &vers_conditions,
+ timestamps_only);
+ if (is_select)
+ table->on_expr= and_items(thd, table->on_expr, cond);
+ else
{
- where= and_items(thd, join->conds, cond);
- join->conds= where;
+ if (join)
+ {
+ where= and_items(thd, join->conds, cond);
+ join->conds= where;
+ }
+ else
+ where= and_items(thd, where, cond);
+ table->where= and_items(thd, table->where, cond);
}
- else
- where= and_items(thd, where, cond);
- table->where= and_items(thd, table->where, cond);
- }
- table->vers_conditions.type= SYSTEM_TIME_ALL;
+ table->vers_conditions.set_all();
+ }
} // for (table= tables; ...)
DBUG_RETURN(0);
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 739febf5e87..76cbb257fea 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -206,10 +206,10 @@ static bool check_fields(THD *thd, TABLE_LIST *table, List<Item> &items,
return FALSE;
}
-static bool check_has_vers_fields(TABLE *table, List<Item> &items)
+bool TABLE::vers_check_update(List<Item> &items)
{
List_iterator<Item> it(items);
- if (!table->versioned())
+ if (!versioned_write())
return false;
while (Item *item= it++)
@@ -217,8 +217,11 @@ static bool check_has_vers_fields(TABLE *table, List<Item> &items)
if (Item_field *item_field= item->field_for_view_update())
{
Field *field= item_field->field;
- if (field->table == table && !field->vers_update_unversioned())
+ if (field->table == this && !field->vers_update_unversioned())
+ {
+ no_cache= true;
return true;
+ }
}
}
return false;
@@ -480,7 +483,7 @@ int mysql_update(THD *thd,
{
DBUG_RETURN(1);
}
- bool has_vers_fields= check_has_vers_fields(table, fields);
+ bool has_vers_fields= table->vers_check_update(fields);
if (check_key_in_view(thd, table_list))
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE");
@@ -717,6 +720,11 @@ int mysql_update(THD *thd,
Later we also ensure that we are only using one table (no sub queries)
*/
+ DBUG_PRINT("info", ("HA_CAN_DIRECT_UPDATE_AND_DELETE: %s", (table->file->ha_table_flags() & HA_CAN_DIRECT_UPDATE_AND_DELETE) ? "TRUE" : "FALSE"));
+ DBUG_PRINT("info", ("using_io_buffer: %s", query_plan.using_io_buffer ? "TRUE" : "FALSE"));
+ DBUG_PRINT("info", ("ignore: %s", ignore ? "TRUE" : "FALSE"));
+ DBUG_PRINT("info", ("virtual_columns_marked_for_read: %s", table->check_virtual_columns_marked_for_read() ? "TRUE" : "FALSE"));
+ DBUG_PRINT("info", ("virtual_columns_marked_for_write: %s", table->check_virtual_columns_marked_for_write() ? "TRUE" : "FALSE"));
if ((table->file->ha_table_flags() & HA_CAN_DIRECT_UPDATE_AND_DELETE) &&
!has_triggers && !binlog_is_row &&
!query_plan.using_io_buffer && !ignore &&
@@ -927,11 +935,16 @@ update_begin:
if (do_direct_update)
{
/* Direct updating is supported */
+ ha_rows update_rows= 0, found_rows= 0;
DBUG_PRINT("info", ("Using direct update"));
table->reset_default_fields();
- if (unlikely(!(error= table->file->ha_direct_update_rows(&updated))))
+ if (unlikely(!(error= table->file->ha_direct_update_rows(&update_rows,
+ &found_rows))))
error= -1;
- found= updated;
+ updated= update_rows;
+ found= found_rows;
+ if (found < updated)
+ found= updated;
goto update_end;
}
@@ -2243,7 +2256,7 @@ multi_update::initialize_tables(JOIN *join)
if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables))
{
table_to_update= table; // Update table on the fly
- has_vers_fields= check_has_vers_fields(table, *fields);
+ has_vers_fields= table->vers_check_update(*fields);
continue;
}
}
@@ -2712,7 +2725,7 @@ int multi_update::do_updates()
if (table->vfield)
empty_record(table);
- has_vers_fields= check_has_vers_fields(table, *fields);
+ has_vers_fields= table->vers_check_update(*fields);
check_opt_it.rewind();
while(TABLE *tbl= check_opt_it++)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index fee02f78792..2bf7295c742 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -320,10 +320,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
- Currently there are 37 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
+
+/* Start SQL_MODE_DEFAULT_SPECIFIC */
%expect 37
+/* End SQL_MODE_DEFAULT_SPECIFIC */
+
+
+/* Start SQL_MODE_ORACLE_SPECIFIC
+%expect 40
+End SQL_MODE_ORACLE_SPECIFIC */
+
/*
Comments for TOKENS.
@@ -1715,7 +1723,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <vers_history_point> history_point
%type <vers_column_versioning> with_or_without_system
-/* Start of sql_mode=DEFAULT specific declarations */
+/* Start SQL_MODE_DEFAULT_SPECIFIC */
%type <NONE> sp_tail_standalone
%type <NONE> sp_unlabeled_block_not_atomic
%type <NONE> sp_proc_stmt_in_returns_clause
@@ -1727,8 +1735,45 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <spblock> sp_decl_variable_list
%type <spblock> sp_decl_variable_list_anchored
%type <kwd> reserved_keyword_udt_param_type
+/* End SQL_MODE_DEFAULT_SPECIFIC */
-/* End of sql_mode=DEFAULT specific declarations */
+
+/* Start SQL_MODE_ORACLE_SPECIFIC
+%type <NONE> set_assign
+%type <spvar_mode> sp_opt_inout
+%type <NONE> sp_tail_standalone
+%type <NONE> sp_labelable_stmt
+%type <simple_string> remember_end_opt
+%type <lex_str> opt_package_routine_end_name
+%type <lex_str> label_declaration_oracle
+%type <lex_str> labels_declaration_oracle
+%type <kwd> keyword_directly_assignable
+%type <ident_sys> ident_directly_assignable
+%type <ident_cli> ident_cli_directly_assignable
+%type <spname> opt_sp_name
+%type <spblock> sp_decl_body_list
+%type <spblock> opt_sp_decl_body_list
+%type <spblock> sp_decl_variable_list
+%type <spblock> sp_decl_variable_list_anchored
+%type <spblock> sp_decl_non_handler
+%type <spblock> sp_decl_non_handler_list
+%type <spblock> sp_decl_handler
+%type <spblock> sp_decl_handler_list
+%type <spblock> opt_sp_decl_handler_list
+%type <spblock> package_implementation_routine_definition
+%type <spblock> package_implementation_item_declaration
+%type <spblock> package_implementation_declare_section
+%type <spblock> package_implementation_declare_section_list1
+%type <spblock> package_implementation_declare_section_list2
+%type <spblock_handlers> sp_block_statements_and_exceptions
+%type <spblock_handlers> package_implementation_executable_section
+%type <sp_instr_addr> sp_instr_addr
+%type <num> opt_exception_clause exception_handlers
+%type <lex> remember_lex
+%type <lex> package_routine_lex
+%type <lex> package_specification_function
+%type <lex> package_specification_procedure
+End SQL_MODE_ORACLE_SPECIFIC */
%%
@@ -17587,7 +17632,12 @@ keep_gcc_happy:
}
;
-/* Start of sql_mode=DEFAULT specific rules */
+_empty:
+ /* Empty */
+ ;
+
+/* Start SQL_MODE_DEFAULT_SPECIFIC */
+
statement:
verb_clause
@@ -17616,16 +17666,14 @@ reserved_keyword_udt:
| reserved_keyword_udt_param_type
;
-/* Keywords that start an SP block section. */
+// Keywords that start an SP block section
keyword_sp_block_section:
BEGIN_MARIADB_SYM
| END
;
-/*
- Keywords that we allow for labels in SPs.
- Should not include keywords that start a statement or SP characteristics.
-*/
+// Keywords that we allow for labels in SPs.
+// Should not include keywords that start a statement or SP characteristics.
keyword_label:
keyword_data_type
| keyword_set_special_case
@@ -17650,7 +17698,7 @@ keyword_sp_decl:
;
opt_truncate_table_storage_clause:
- /* Empty */
+ _empty
;
@@ -17702,7 +17750,7 @@ sp_block_label:
;
sp_opt_default:
- /* Empty */ { $$ = NULL; }
+ _empty { $$ = NULL; }
| DEFAULT expr { $$ = $2; }
;
@@ -17856,16 +17904,16 @@ create_routine:
sp_decls:
- /* Empty */
+ _empty
{
$$.init();
}
| sp_decls sp_decl ';'
{
- /* We check for declarations out of (standard) order this way
- because letting the grammar rules reflect it caused tricky
- shift/reduce conflicts with the wrong result. (And we get
- better error handling this way.) */
+ // We check for declarations out of (standard) order this way
+ // because letting the grammar rules reflect it caused tricky
+ // shift/reduce conflicts with the wrong result. (And we get
+ // better error handling this way.)
if (unlikely(Lex->sp_declarations_join(&$$, $1, $2)))
MYSQL_YYABORT;
}
@@ -17904,15 +17952,15 @@ sp_decl_body:
;
-/*
- ps_proc_stmt_in_returns_clause is a statement that is allowed
- in the RETURNS clause of a stored function definition directly,
- without the BEGIN..END block.
- It should not include any syntax structures starting with '(', to avoid
- shift/reduce conflicts with the rule "field_type" and its sub-rules
- that scan an optional length, like CHAR(1) or YEAR(4).
- See MDEV-9166.
-*/
+
+// ps_proc_stmt_in_returns_clause is a statement that is allowed
+// in the RETURNS clause of a stored function definition directly,
+// without the BEGIN..END block.
+// It should not include any syntax structures starting with '(', to avoid
+// shift/reduce conflicts with the rule "field_type" and its sub-rules
+// that scan an optional length, like CHAR(1) or YEAR(4).
+// See MDEV-9166.
+
sp_proc_stmt_in_returns_clause:
sp_proc_stmt_return
| sp_labeled_block
@@ -17971,7 +18019,7 @@ sp_unlabeled_block:
;
sp_unlabeled_block_not_atomic:
- BEGIN_MARIADB_SYM not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */
+ BEGIN_MARIADB_SYM not ATOMIC_SYM // TODO: BEGIN ATOMIC (not -> opt_not)
{
if (unlikely(Lex->maybe_start_compound_statement(thd)))
MYSQL_YYABORT;
@@ -17987,7 +18035,1015 @@ sp_unlabeled_block_not_atomic:
;
-/* End of sql_mode=DEFAULT specific rules */
+/* End SQL_MODE_DEFAULT_SPECIFIC */
+
+
+/* Start SQL_MODE_ORACLE_SPECIFIC
+
+statement:
+ verb_clause
+ | set_assign
+ ;
+
+sp_statement:
+ statement
+ | ident_cli_directly_assignable
+ {
+ // Direct procedure call (without the CALL keyword)
+ Lex_ident_sys tmp(thd, &$1);
+ if (unlikely(Lex->call_statement_start(thd, &tmp)))
+ MYSQL_YYABORT;
+ }
+ opt_sp_cparam_list
+ | ident_cli_directly_assignable '.' ident
+ {
+ Lex_ident_sys tmp(thd, &$1);
+ if (unlikely(Lex->call_statement_start(thd, &tmp, &$3)))
+ MYSQL_YYABORT;
+ }
+ opt_sp_cparam_list
+ ;
+
+sp_if_then_statements:
+ sp_proc_stmts1_implicit_block { }
+ ;
+
+sp_case_then_statements:
+ sp_proc_stmts1_implicit_block { }
+ ;
+
+reserved_keyword_udt:
+ reserved_keyword_udt_not_param_type
+ ;
+
+// Keywords that start an SP block section.
+keyword_sp_block_section:
+ BEGIN_ORACLE_SYM
+ | END
+ ;
+
+// Keywords that we allow for labels in SPs.
+// Should not include keywords that start a statement or SP characteristics.
+keyword_label:
+ keyword_data_type
+ | keyword_set_special_case
+ | keyword_sp_var_and_label
+ | keyword_sysvar_type
+ | FUNCTION_SYM
+ | COMPRESSED_SYM
+ | EXCEPTION_ORACLE_SYM
+ ;
+
+keyword_sp_decl:
+ keyword_sp_head
+ | keyword_set_special_case
+ | keyword_sp_var_and_label
+ | keyword_sp_var_not_label
+ | keyword_sysvar_type
+ | keyword_verb_clause
+ | WINDOW_SYM
+ ;
+
+opt_truncate_table_storage_clause:
+ _empty
+ | DROP STORAGE_SYM
+ | REUSE_SYM STORAGE_SYM
+ ;
+
+
+ident_for_loop_index:
+ ident_directly_assignable
+ ;
+
+row_field_name:
+ ident_directly_assignable
+ {
+ if (!($$= Lex->row_field_name(thd, $1)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+while_body:
+ expr_lex LOOP_SYM
+ {
+ if (unlikely($1->sp_while_loop_expression(thd)))
+ MYSQL_YYABORT;
+ }
+ sp_proc_stmts1 END LOOP_SYM
+ {
+ if (unlikely(Lex->sp_while_loop_finalize(thd)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+for_loop_statements:
+ LOOP_SYM sp_proc_stmts1 END LOOP_SYM
+ { }
+ ;
+
+
+sp_control_label:
+ labels_declaration_oracle
+ ;
+
+sp_block_label:
+ labels_declaration_oracle
+ {
+ if (unlikely(Lex->spcont->block_label_declare(&$1)))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
+
+
+remember_end_opt:
+ {
+ if (yychar == YYEMPTY)
+ $$= (char*) YYLIP->get_cpp_ptr_rtrim();
+ else
+ $$= (char*) YYLIP->get_cpp_tok_end_rtrim();
+ }
+ ;
+
+sp_opt_default:
+ _empty { $$ = NULL; }
+ | DEFAULT expr { $$ = $2; }
+ | SET_VAR expr { $$ = $2; }
+ ;
+
+sp_opt_inout:
+ _empty { $$= sp_variable::MODE_IN; }
+ | sp_parameter_type
+ | IN_SYM OUT_SYM { $$= sp_variable::MODE_INOUT; }
+ ;
+
+sp_pdparam:
+ sp_param_name sp_opt_inout type_with_opt_collate
+ {
+ $1->mode= $2;
+ if (unlikely(Lex->sp_param_fill_definition($1, $3)))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
+ {
+ $1->mode= $2;
+ if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $1, $3, $5)))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name sp_opt_inout sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
+ {
+ $1->mode= $2;
+ if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $1, $3, $5, $7)))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name sp_opt_inout sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
+ {
+ $1->mode= $2;
+ if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $1, $3)))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
+ {
+ $1->mode= $2;
+ if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $1, $3, $5)))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name sp_opt_inout ROW_SYM row_type_body
+ {
+ $1->mode= $2;
+ if (unlikely(Lex->sphead->spvar_fill_row(thd, $1, $4)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+sp_proc_stmts1_implicit_block:
+ {
+ Lex->sp_block_init(thd);
+ }
+ sp_proc_stmts1
+ {
+ if (unlikely(Lex->sp_block_finalize(thd)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+remember_lex:
+ {
+ $$= thd->lex;
+ }
+ ;
+
+keyword_directly_assignable:
+ keyword_data_type
+ | keyword_cast_type
+ | keyword_set_special_case
+ | keyword_sp_var_and_label
+ | keyword_sp_var_not_label
+ | keyword_sysvar_type
+ | FUNCTION_SYM
+ | WINDOW_SYM
+ ;
+
+ident_directly_assignable:
+ IDENT_sys
+ | keyword_directly_assignable
+ {
+ if (unlikely($$.copy_keyword(thd, &$1)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+ident_cli_directly_assignable:
+ IDENT_cli
+ | keyword_directly_assignable { $$= $1; }
+ ;
+
+
+set_assign:
+ ident_cli_directly_assignable SET_VAR
+ {
+ LEX *lex=Lex;
+ lex->set_stmt_init();
+ if (sp_create_assignment_lex(thd, $1.pos()))
+ MYSQL_YYABORT;
+ }
+ set_expr_or_default
+ {
+ Lex_ident_sys tmp(thd, &$1);
+ if (unlikely(Lex->set_variable(&tmp, $4)) ||
+ unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
+ false)))
+ MYSQL_YYABORT;
+ }
+ | ident_cli_directly_assignable '.' ident SET_VAR
+ {
+ LEX *lex=Lex;
+ lex->set_stmt_init();
+ if (sp_create_assignment_lex(thd, $1.pos()))
+ MYSQL_YYABORT;
+ }
+ set_expr_or_default
+ {
+ LEX *lex= Lex;
+ DBUG_ASSERT(lex->var_list.is_empty());
+ Lex_ident_sys tmp(thd, &$1);
+ if (unlikely(lex->set_variable(&tmp, &$3, $6)) ||
+ unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
+ false)))
+ MYSQL_YYABORT;
+ }
+ | COLON_ORACLE_SYM ident '.' ident SET_VAR
+ {
+ LEX *lex= Lex;
+ if (unlikely(!lex->is_trigger_new_or_old_reference(&$2)))
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, $1.pos());
+ MYSQL_YYABORT;
+ }
+ lex->set_stmt_init();
+ if (sp_create_assignment_lex(thd, $1.pos()))
+ MYSQL_YYABORT;
+ }
+ set_expr_or_default
+ {
+ LEX_CSTRING tmp= { $2.str, $2.length };
+ if (unlikely(Lex->set_trigger_field(&tmp, &$4, $7)) ||
+ unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
+ false)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+labels_declaration_oracle:
+ label_declaration_oracle { $$= $1; }
+ | labels_declaration_oracle label_declaration_oracle { $$= $2; }
+ ;
+
+label_declaration_oracle:
+ SHIFT_LEFT label_ident SHIFT_RIGHT
+ {
+ if (unlikely(Lex->sp_push_goto_label(thd, &$2)))
+ MYSQL_YYABORT;
+ $$= $2;
+ }
+ ;
+
+opt_exception_clause:
+ _empty { $$= 0; }
+ | EXCEPTION_ORACLE_SYM exception_handlers { $$= $2; }
+ ;
+
+exception_handlers:
+ exception_handler { $$= 1; }
+ | exception_handlers exception_handler { $$= $1 + 1; }
+ ;
+
+exception_handler:
+ WHEN_SYM
+ {
+ if (unlikely(Lex->sp_handler_declaration_init(thd, sp_handler::EXIT)))
+ MYSQL_YYABORT;
+ }
+ sp_hcond_list
+ THEN_SYM
+ sp_proc_stmts1_implicit_block
+ {
+ if (unlikely(Lex->sp_handler_declaration_finalize(thd, sp_handler::EXIT)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_no_param:
+ _empty
+ {
+ Lex->sphead->m_param_begin= Lex->sphead->m_param_end=
+ YYLIP->get_cpp_tok_start() + 1;
+ }
+ ;
+
+opt_sp_parenthesized_fdparam_list:
+ sp_no_param
+ | sp_parenthesized_fdparam_list
+ ;
+
+opt_sp_parenthesized_pdparam_list:
+ sp_no_param
+ | sp_parenthesized_pdparam_list
+ ;
+
+
+opt_sp_name:
+ _empty { $$= NULL; }
+ | sp_name { $$= $1; }
+ ;
+
+
+opt_package_routine_end_name:
+ _empty { $$= null_clex_str; }
+ | ident { $$= $1; }
+ ;
+
+sp_tail_is:
+ IS
+ | AS
+ ;
+
+sp_instr_addr:
+ { $$= Lex->sphead->instructions(); }
+ ;
+
+sp_body:
+ {
+ Lex->sp_block_init(thd);
+ }
+ opt_sp_decl_body_list
+ {
+ if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
+ MYSQL_YYABORT;
+ }
+ BEGIN_ORACLE_SYM
+ sp_block_statements_and_exceptions
+ {
+ $2.hndlrs+= $5.hndlrs;
+ if (unlikely(Lex->sp_block_finalize(thd, $2)))
+ MYSQL_YYABORT;
+ }
+ END
+ ;
+
+create_package_chistic:
+ COMMENT_SYM TEXT_STRING_sys
+ { Lex->sp_chistics.comment= $2; }
+ | sp_suid
+ { Lex->sp_chistics.suid= $1; }
+ ;
+
+create_package_chistics:
+ create_package_chistic {}
+ | create_package_chistics create_package_chistic { }
+ ;
+
+opt_create_package_chistics:
+ _empty
+ | create_package_chistics { }
+ ;
+
+opt_create_package_chistics_init:
+ { Lex->sp_chistics.init(); }
+ opt_create_package_chistics
+ ;
+
+
+package_implementation_executable_section:
+ END
+ {
+ if (unlikely(Lex->sp_block_with_exceptions_add_empty(thd)))
+ MYSQL_YYABORT;
+ $$.init(0);
+ }
+ | BEGIN_ORACLE_SYM sp_block_statements_and_exceptions END { $$= $2; }
+ ;
+
+
+// Inside CREATE PACKAGE BODY, package-wide items (e.g. variables)
+// must be declared before routine definitions.
+
+package_implementation_declare_section:
+ package_implementation_declare_section_list1
+ | package_implementation_declare_section_list2
+ | package_implementation_declare_section_list1
+ package_implementation_declare_section_list2
+ { $$.join($1, $2); }
+ ;
+
+package_implementation_declare_section_list1:
+ package_implementation_item_declaration
+ | package_implementation_declare_section_list1
+ package_implementation_item_declaration
+ { $$.join($1, $2); }
+ ;
+
+package_implementation_declare_section_list2:
+ package_implementation_routine_definition
+ | package_implementation_declare_section_list2
+ package_implementation_routine_definition
+ { $$.join($1, $2); }
+ ;
+
+package_routine_lex:
+ {
+ if (unlikely(!($$= new (thd->mem_root)
+ sp_lex_local(thd, thd->lex))))
+ MYSQL_YYABORT;
+ thd->m_parser_state->m_yacc.reset_before_substatement();
+ }
+ ;
+
+
+package_specification_function:
+ remember_lex package_routine_lex ident
+ {
+ DBUG_ASSERT($1->sphead->get_package());
+ $2->sql_command= SQLCOM_CREATE_FUNCTION;
+ sp_name *spname= $1->make_sp_name_package_routine(thd, &$3);
+ if (unlikely(!spname))
+ MYSQL_YYABORT;
+ thd->lex= $2;
+ if (unlikely(!$2->make_sp_head_no_recursive(thd, spname,
+ &sp_handler_package_function,
+ NOT_AGGREGATE)))
+ MYSQL_YYABORT;
+ $1->sphead->get_package()->m_current_routine= $2;
+ (void) is_native_function_with_warn(thd, &$3);
+ }
+ opt_sp_parenthesized_fdparam_list
+ RETURN_ORACLE_SYM sf_return_type
+ sp_c_chistics
+ {
+ sp_head *sp= thd->lex->sphead;
+ sp->restore_thd_mem_root(thd);
+ thd->lex= $1;
+ $$= $2;
+ }
+ ;
+
+package_specification_procedure:
+ remember_lex package_routine_lex ident
+ {
+ DBUG_ASSERT($1->sphead->get_package());
+ $2->sql_command= SQLCOM_CREATE_PROCEDURE;
+ sp_name *spname= $1->make_sp_name_package_routine(thd, &$3);
+ if (unlikely(!spname))
+ MYSQL_YYABORT;
+ thd->lex= $2;
+ if (unlikely(!$2->make_sp_head_no_recursive(thd, spname,
+ &sp_handler_package_procedure,
+ DEFAULT_AGGREGATE)))
+ MYSQL_YYABORT;
+ $1->sphead->get_package()->m_current_routine= $2;
+ }
+ opt_sp_parenthesized_pdparam_list
+ sp_c_chistics
+ {
+ sp_head *sp= thd->lex->sphead;
+ sp->restore_thd_mem_root(thd);
+ thd->lex= $1;
+ $$= $2;
+ }
+ ;
+
+
+package_implementation_routine_definition:
+ FUNCTION_SYM package_specification_function
+ package_implementation_function_body ';'
+ {
+ sp_package *pkg= Lex->get_sp_package();
+ if (unlikely(pkg->add_routine_implementation($2)))
+ MYSQL_YYABORT;
+ pkg->m_current_routine= NULL;
+ $$.init();
+ }
+ | PROCEDURE_SYM package_specification_procedure
+ package_implementation_procedure_body ';'
+ {
+ sp_package *pkg= Lex->get_sp_package();
+ if (unlikely(pkg->add_routine_implementation($2)))
+ MYSQL_YYABORT;
+ pkg->m_current_routine= NULL;
+ $$.init();
+ }
+ | package_specification_element { $$.init(); }
+ ;
+
+
+package_implementation_function_body:
+ sp_tail_is remember_lex
+ {
+ sp_package *pkg= Lex->get_sp_package();
+ sp_head *sp= pkg->m_current_routine->sphead;
+ thd->lex= pkg->m_current_routine;
+ sp->reset_thd_mem_root(thd);
+ sp->set_body_start(thd, YYLIP->get_cpp_tok_start());
+ }
+ sp_body opt_package_routine_end_name
+ {
+ if (unlikely(thd->lex->sp_body_finalize_function(thd) ||
+ thd->lex->sphead->check_package_routine_end_name($5)))
+ MYSQL_YYABORT;
+ thd->lex= $2;
+ }
+ ;
+
+package_implementation_procedure_body:
+ sp_tail_is remember_lex
+ {
+ sp_package *pkg= Lex->get_sp_package();
+ sp_head *sp= pkg->m_current_routine->sphead;
+ thd->lex= pkg->m_current_routine;
+ sp->reset_thd_mem_root(thd);
+ sp->set_body_start(thd, YYLIP->get_cpp_tok_start());
+ }
+ sp_body opt_package_routine_end_name
+ {
+ if (unlikely(thd->lex->sp_body_finalize_procedure(thd) ||
+ thd->lex->sphead->check_package_routine_end_name($5)))
+ MYSQL_YYABORT;
+ thd->lex= $2;
+ }
+ ;
+
+
+package_implementation_item_declaration:
+ sp_decl_variable_list ';'
+ ;
+
+opt_package_specification_element_list:
+ _empty
+ | package_specification_element_list
+ ;
+
+package_specification_element_list:
+ package_specification_element
+ | package_specification_element_list package_specification_element
+ ;
+
+package_specification_element:
+ FUNCTION_SYM package_specification_function ';'
+ {
+ sp_package *pkg= Lex->get_sp_package();
+ if (unlikely(pkg->add_routine_declaration($2)))
+ MYSQL_YYABORT;
+ pkg->m_current_routine= NULL;
+ }
+ | PROCEDURE_SYM package_specification_procedure ';'
+ {
+ sp_package *pkg= Lex->get_sp_package();
+ if (unlikely(pkg->add_routine_declaration($2)))
+ MYSQL_YYABORT;
+ pkg->m_current_routine= NULL;
+ }
+ ;
+
+sp_decl_variable_list_anchored:
+ sp_decl_idents_init_vars
+ optionally_qualified_column_ident PERCENT_ORACLE_SYM TYPE_SYM
+ sp_opt_default
+ {
+ if (unlikely(Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $2, $5)))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ | sp_decl_idents_init_vars
+ optionally_qualified_column_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
+ sp_opt_default
+ {
+ if (unlikely(Lex->sp_variable_declarations_rowtype_finalize(thd, $1, $2, $5)))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ ;
+
+sp_param_name_and_type_anchored:
+ sp_param_name sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
+ {
+ if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $2, $4)))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
+ {
+ if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $2, $4, $6)))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
+ {
+ if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $2)))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
+ {
+ if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $2, $4)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+sf_c_chistics_and_body_standalone:
+ sp_c_chistics
+ {
+ LEX *lex= thd->lex;
+ lex->sphead->set_c_chistics(lex->sp_chistics);
+ lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
+ }
+ sp_tail_is
+ sp_body
+ {
+ if (unlikely(Lex->sp_body_finalize_function(thd)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_tail_standalone:
+ sp_name
+ {
+ if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1,
+ &sp_handler_procedure,
+ DEFAULT_AGGREGATE)))
+ MYSQL_YYABORT;
+ }
+ opt_sp_parenthesized_pdparam_list
+ sp_c_chistics
+ {
+ Lex->sphead->set_c_chistics(Lex->sp_chistics);
+ Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
+ }
+ sp_tail_is
+ sp_body
+ opt_sp_name
+ {
+ if (unlikely(Lex->sp_body_finalize_procedure_standalone(thd, $8)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+drop_routine:
+ DROP FUNCTION_SYM opt_if_exists ident '.' ident
+ {
+ if (Lex->stmt_drop_function($3, $4, $6))
+ MYSQL_YYABORT;
+ }
+ | DROP FUNCTION_SYM opt_if_exists ident
+ {
+ if (Lex->stmt_drop_function($3, $4))
+ MYSQL_YYABORT;
+ }
+ | DROP PROCEDURE_SYM opt_if_exists sp_name
+ {
+ if (Lex->stmt_drop_procedure($3, $4))
+ MYSQL_YYABORT;
+ }
+ | DROP PACKAGE_ORACLE_SYM opt_if_exists sp_name
+ {
+ LEX *lex= Lex;
+ lex->set_command(SQLCOM_DROP_PACKAGE, $3);
+ if (unlikely(lex->sphead))
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PACKAGE"));
+ lex->spname= $4;
+ }
+ | DROP PACKAGE_ORACLE_SYM BODY_ORACLE_SYM opt_if_exists sp_name
+ {
+ LEX *lex= Lex;
+ lex->set_command(SQLCOM_DROP_PACKAGE_BODY, $4);
+ if (unlikely(lex->sphead))
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PACKAGE BODY"));
+ lex->spname= $5;
+ }
+ ;
+
+
+create_routine:
+ create_or_replace definer_opt PROCEDURE_SYM opt_if_not_exists
+ {
+ if (Lex->stmt_create_procedure_start($1 | $4))
+ MYSQL_YYABORT;
+ }
+ sp_tail_standalone
+ {
+ Lex->stmt_create_routine_finalize();
+ }
+ | create_or_replace definer opt_aggregate FUNCTION_SYM opt_if_not_exists
+ sp_name
+ {
+ if (Lex->stmt_create_stored_function_start($1 | $5, $3, $6))
+ MYSQL_YYABORT;
+ }
+ opt_sp_parenthesized_fdparam_list
+ RETURN_ORACLE_SYM sf_return_type
+ sf_c_chistics_and_body_standalone
+ opt_sp_name
+ {
+ if (Lex->stmt_create_stored_function_finalize_standalone($12))
+ MYSQL_YYABORT;
+ }
+ | create_or_replace no_definer opt_aggregate FUNCTION_SYM opt_if_not_exists
+ sp_name
+ {
+ if (Lex->stmt_create_stored_function_start($1 | $5, $3, $6))
+ MYSQL_YYABORT;
+ }
+ opt_sp_parenthesized_fdparam_list
+ RETURN_ORACLE_SYM sf_return_type
+ sf_c_chistics_and_body_standalone
+ opt_sp_name
+ {
+ if (Lex->stmt_create_stored_function_finalize_standalone($12))
+ MYSQL_YYABORT;
+ }
+ | create_or_replace no_definer opt_aggregate FUNCTION_SYM opt_if_not_exists
+ ident RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
+ {
+ if (Lex->stmt_create_udf_function($1 | $5, $3, $6,
+ (Item_result) $8, $10))
+ MYSQL_YYABORT;
+ }
+ | create_or_replace definer_opt PACKAGE_ORACLE_SYM
+ opt_if_not_exists sp_name opt_create_package_chistics_init
+ sp_tail_is
+ remember_name
+ {
+ sp_package *pkg;
+ if (unlikely(!(pkg= Lex->
+ create_package_start(thd,
+ SQLCOM_CREATE_PACKAGE,
+ &sp_handler_package_spec,
+ $5, $1 | $4))))
+ MYSQL_YYABORT;
+ pkg->set_c_chistics(Lex->sp_chistics);
+ }
+ opt_package_specification_element_list END
+ remember_end_opt opt_sp_name
+ {
+ if (unlikely(Lex->create_package_finalize(thd, $5, $13, $8, $12)))
+ MYSQL_YYABORT;
+ }
+ | create_or_replace definer_opt PACKAGE_ORACLE_SYM BODY_ORACLE_SYM
+ opt_if_not_exists sp_name opt_create_package_chistics_init
+ sp_tail_is
+ remember_name
+ {
+ sp_package *pkg;
+ if (unlikely(!(pkg= Lex->
+ create_package_start(thd,
+ SQLCOM_CREATE_PACKAGE_BODY,
+ &sp_handler_package_body,
+ $6, $1 | $5))))
+ MYSQL_YYABORT;
+ pkg->set_c_chistics(Lex->sp_chistics);
+ Lex->sp_block_init(thd);
+ }
+ package_implementation_declare_section
+ {
+ if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
+ MYSQL_YYABORT;
+ }
+ package_implementation_executable_section
+ {
+ $11.hndlrs+= $13.hndlrs;
+ if (unlikely(Lex->sp_block_finalize(thd, $11)))
+ MYSQL_YYABORT;
+ }
+ remember_end_opt opt_sp_name
+ {
+ if (unlikely(Lex->create_package_finalize(thd, $6, $16, $9, $15)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_sp_decl_body_list:
+ _empty
+ {
+ $$.init();
+ }
+ | sp_decl_body_list { $$= $1; }
+ ;
+
+sp_decl_body_list:
+ sp_decl_non_handler_list
+ {
+ if (unlikely(Lex->sphead->sp_add_instr_cpush_for_cursors(thd, Lex->spcont)))
+ MYSQL_YYABORT;
+ }
+ opt_sp_decl_handler_list
+ {
+ $$.join($1, $3);
+ }
+ | sp_decl_handler_list
+ ;
+
+sp_decl_non_handler_list:
+ sp_decl_non_handler ';' { $$= $1; }
+ | sp_decl_non_handler_list sp_decl_non_handler ';'
+ {
+ $$.join($1, $2);
+ }
+ ;
+
+sp_decl_handler_list:
+ sp_decl_handler ';' { $$= $1; }
+ | sp_decl_handler_list sp_decl_handler ';'
+ {
+ $$.join($1, $2);
+ }
+ ;
+
+opt_sp_decl_handler_list:
+ _empty { $$.init(); }
+ | sp_decl_handler_list
+ ;
+
+sp_decl_non_handler:
+ sp_decl_variable_list
+ | ident_directly_assignable CONDITION_SYM FOR_SYM sp_cond
+ {
+ if (unlikely(Lex->spcont->declare_condition(thd, &$1, $4)))
+ MYSQL_YYABORT;
+ $$.vars= $$.hndlrs= $$.curs= 0;
+ $$.conds= 1;
+ }
+ | ident_directly_assignable EXCEPTION_ORACLE_SYM
+ {
+ sp_condition_value *spcond= new (thd->mem_root)
+ sp_condition_value_user_defined();
+ if (unlikely(!spcond) ||
+ unlikely(Lex->spcont->declare_condition(thd, &$1, spcond)))
+ MYSQL_YYABORT;
+ $$.vars= $$.hndlrs= $$.curs= 0;
+ $$.conds= 1;
+ }
+ | CURSOR_SYM ident_directly_assignable
+ {
+ Lex->sp_block_init(thd);
+ }
+ opt_parenthesized_cursor_formal_parameters
+ IS sp_cursor_stmt
+ {
+ sp_pcontext *param_ctx= Lex->spcont;
+ if (unlikely(Lex->sp_block_finalize(thd)))
+ MYSQL_YYABORT;
+ if (unlikely(Lex->sp_declare_cursor(thd, &$2, $6, param_ctx, false)))
+ MYSQL_YYABORT;
+ $$.vars= $$.conds= $$.hndlrs= 0;
+ $$.curs= 1;
+ }
+ ;
+
+
+sp_proc_stmt:
+ sp_labeled_block
+ | sp_unlabeled_block
+ | sp_labeled_control
+ | sp_unlabeled_control
+ | sp_labelable_stmt
+ | labels_declaration_oracle sp_labelable_stmt {}
+ ;
+
+sp_labelable_stmt:
+ sp_proc_stmt_statement
+ | sp_proc_stmt_continue_oracle
+ | sp_proc_stmt_exit_oracle
+ | sp_proc_stmt_leave
+ | sp_proc_stmt_iterate
+ | sp_proc_stmt_goto_oracle
+ | sp_proc_stmt_with_cursor
+ | sp_proc_stmt_return
+ | sp_proc_stmt_if
+ | case_stmt_specification
+ | NULL_SYM { }
+ ;
+
+sp_proc_stmt_compound_ok:
+ sp_proc_stmt_if
+ | case_stmt_specification
+ | sp_unlabeled_block
+ | sp_unlabeled_control
+ ;
+
+
+sp_labeled_block:
+ sp_block_label
+ BEGIN_ORACLE_SYM
+ {
+ Lex->sp_block_init(thd, &$1);
+ if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
+ MYSQL_YYABORT;
+ }
+ sp_block_statements_and_exceptions
+ END
+ sp_opt_label
+ {
+ if (unlikely(Lex->sp_block_finalize(thd, Lex_spblock($4), &$6)))
+ MYSQL_YYABORT;
+ }
+ | sp_block_label
+ DECLARE_ORACLE_SYM
+ {
+ Lex->sp_block_init(thd, &$1);
+ }
+ sp_decl_body_list
+ {
+ if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
+ MYSQL_YYABORT;
+ }
+ BEGIN_ORACLE_SYM
+ sp_block_statements_and_exceptions
+ END
+ sp_opt_label
+ {
+ $4.hndlrs+= $7.hndlrs;
+ if (unlikely(Lex->sp_block_finalize(thd, $4, &$9)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_not_atomic:
+ _empty
+ | not ATOMIC_SYM // TODO: BEGIN ATOMIC (not -> opt_not)
+ ;
+
+sp_unlabeled_block:
+ BEGIN_ORACLE_SYM opt_not_atomic
+ {
+ if (unlikely(Lex->maybe_start_compound_statement(thd)))
+ MYSQL_YYABORT;
+ Lex->sp_block_init(thd);
+ if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
+ MYSQL_YYABORT;
+ }
+ sp_block_statements_and_exceptions
+ END
+ {
+ if (unlikely(Lex->sp_block_finalize(thd, Lex_spblock($4))))
+ MYSQL_YYABORT;
+ }
+ | DECLARE_ORACLE_SYM
+ {
+ if (unlikely(Lex->maybe_start_compound_statement(thd)))
+ MYSQL_YYABORT;
+ Lex->sp_block_init(thd);
+ }
+ sp_decl_body_list
+ {
+ if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
+ MYSQL_YYABORT;
+ }
+ BEGIN_ORACLE_SYM
+ sp_block_statements_and_exceptions
+ END
+ {
+ $3.hndlrs+= $6.hndlrs;
+ if (unlikely(Lex->sp_block_finalize(thd, $3)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_block_statements_and_exceptions:
+ sp_instr_addr
+ sp_proc_stmts
+ {
+ if (unlikely(Lex->sp_block_with_exceptions_finalize_executable_section(thd, $1)))
+ MYSQL_YYABORT;
+ }
+ opt_exception_clause
+ {
+ if (unlikely(Lex->sp_block_with_exceptions_finalize_exceptions(thd, $1, $4)))
+ MYSQL_YYABORT;
+ $$.init($4);
+ }
+ ;
+
+End SQL_MODE_ORACLE_SPECIFIC */
/**
@} (end of group Parser)
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
deleted file mode 100644
index 6c4ed3c2c51..00000000000
--- a/sql/sql_yacc_ora.yy
+++ /dev/null
@@ -1,18623 +0,0 @@
-/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2019, MariaDB Corporation.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- 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 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-1335 USA */
-
-/* sql_yacc.yy */
-
-/**
- @defgroup Parser Parser
- @{
-*/
-
-%{
-#define YYLIP (& thd->m_parser_state->m_lip)
-#define YYPS (& thd->m_parser_state->m_yacc)
-#define YYCSCL (thd->variables.character_set_client)
-
-#define MYSQL_YACC
-#define YYINITDEPTH 100
-#define YYMAXDEPTH 3200 /* Because of 64K stack */
-#define Lex (thd->lex)
-
-#define Select Lex->current_select
-#include "mariadb.h"
-#include "sql_priv.h"
-#include "sql_parse.h" /* comp_*_creator */
-#include "sql_table.h" /* primary_key_name */
-#include "sql_partition.h" /* partition_info, HASH_PARTITION */
-#include "sql_acl.h" /* *_ACL */
-#include "sql_class.h" /* Key_part_spec, enum_filetype, Diag_condition_item_name */
-#include "slave.h"
-#include "lex_symbol.h"
-#include "item_create.h"
-#include "sp_head.h"
-#include "sp_rcontext.h"
-#include "sp.h"
-#include "sql_show.h"
-#include "sql_alter.h" // Sql_cmd_alter_table*
-#include "sql_truncate.h" // Sql_cmd_truncate_table
-#include "sql_admin.h" // Sql_cmd_analyze/Check..._table
-#include "sql_partition_admin.h" // Sql_cmd_alter_table_*_part.
-#include "sql_handler.h" // Sql_cmd_handler_*
-#include "sql_signal.h"
-#include "sql_get_diagnostics.h" // Sql_cmd_get_diagnostics
-#include "sql_cte.h"
-#include "sql_window.h"
-#include "item_windowfunc.h"
-#include "event_parse_data.h"
-#include "create_options.h"
-#include <myisam.h>
-#include <myisammrg.h>
-#include "keycaches.h"
-#include "set_var.h"
-#include "rpl_mi.h"
-#include "lex_token.h"
-#include "sql_lex.h"
-#include "sql_sequence.h"
-#include "my_base.h"
-#include "sql_type_json.h"
-
-/* this is to get the bison compilation windows warnings out */
-#ifdef _MSC_VER
-/* warning C4065: switch statement contains 'default' but no 'case' labels */
-#pragma warning (disable : 4065)
-#endif
-
-int yylex(void *yylval, void *yythd);
-
-#define yyoverflow(A,B,C,D,E,F) \
- { \
- size_t val= *(F); \
- if (unlikely(my_yyoverflow((B), (D), &val))) \
- { \
- yyerror(thd, (char*) (A)); \
- return 2; \
- } \
- else \
- { \
- *(F)= (YYSIZE_T)val; \
- } \
- }
-
-#define MYSQL_YYABORT \
- do \
- { \
- LEX::cleanup_lex_after_parse_error(thd); \
- YYABORT; \
- } while (0)
-
-#define MYSQL_YYABORT_UNLESS(A) \
- if (unlikely(!(A))) \
- { \
- thd->parse_error(); \
- MYSQL_YYABORT; \
- }
-
-#define my_yyabort_error(A) \
- do { my_error A; MYSQL_YYABORT; } while(0)
-
-#ifndef DBUG_OFF
-#define YYDEBUG 1
-#else
-#define YYDEBUG 0
-#endif
-
-
-/**
- @brief Bison callback to report a syntax/OOM error
-
- This function is invoked by the bison-generated parser
- when a syntax error, a parse error or an out-of-memory
- condition occurs. This function is not invoked when the
- parser is requested to abort by semantic action code
- by means of YYABORT or YYACCEPT macros. This is why these
- macros should not be used (use MYSQL_YYABORT/MYSQL_YYACCEPT
- instead).
-
- The parser will abort immediately after invoking this callback.
-
- This function is not for use in semantic actions and is internal to
- the parser, as it performs some pre-return cleanup.
- In semantic actions, please use thd->parse_error() or my_error to
- push an error into the error stack and MYSQL_YYABORT
- to abort from the parser.
-*/
-
-static void yyerror(THD *thd, const char *s)
-{
- /*
- Restore the original LEX if it was replaced when parsing
- a stored procedure. We must ensure that a parsing error
- does not leave any side effects in the THD.
- */
- LEX::cleanup_lex_after_parse_error(thd);
-
- /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
- if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
- s= ER_THD(thd, ER_SYNTAX_ERROR);
- thd->parse_error(s, 0);
-}
-
-
-#ifndef DBUG_OFF
-#define __CONCAT_UNDERSCORED(x,y) x ## _ ## y
-#define _CONCAT_UNDERSCORED(x,y) __CONCAT_UNDERSCORED(x,y)
-void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
-{
- /*
- MYSQLdebug is in sql/sql_yacc.cc, in bison generated code.
- Turning this option on is **VERY** verbose, and should be
- used when investigating a syntax error problem only.
-
- The syntax to run with bison traces is as follows :
- - Starting a server manually :
- mysqld --debug-dbug="d,parser_debug" ...
- - Running a test :
- mysql-test-run.pl --mysqld="--debug-dbug=d,parser_debug" ...
-
- The result will be in the process stderr (var/log/master.err)
- */
-
- extern int yydebug;
- yydebug= 1;
-}
-#endif
-
-
-#define bincmp_collation(X,Y) \
- do \
- { \
- if (unlikely(Lex->set_bincmp(X,Y))) \
- MYSQL_YYABORT; \
- } while(0)
-
-%}
-%union {
- int num;
- ulong ulong_num;
- ulonglong ulonglong_number;
- longlong longlong_number;
- uint sp_instr_addr;
-
- /* structs */
- LEX_CSTRING lex_str;
- Lex_ident_cli_st kwd;
- Lex_ident_cli_st ident_cli;
- Lex_ident_sys_st ident_sys;
- Lex_string_with_metadata_st lex_string_with_metadata;
- Lex_spblock_st spblock;
- Lex_spblock_handlers_st spblock_handlers;
- Lex_length_and_dec_st Lex_length_and_dec;
- Lex_cast_type_st Lex_cast_type;
- Lex_field_type_st Lex_field_type;
- Lex_dyncol_type_st Lex_dyncol_type;
- Lex_for_loop_st for_loop;
- Lex_for_loop_bounds_st for_loop_bounds;
- Lex_trim_st trim;
- vers_history_point_t vers_history_point;
- struct
- {
- enum sub_select_type unit_type;
- bool distinct;
- } unit_operation;
- struct
- {
- SELECT_LEX *first;
- SELECT_LEX *prev_last;
- } select_list;
- SQL_I_List<ORDER> *select_order;
- Lex_select_lock select_lock;
- Lex_select_limit select_limit;
- Lex_order_limit_lock *order_limit_lock;
-
- /* pointers */
- Create_field *create_field;
- Spvar_definition *spvar_definition;
- Row_definition_list *spvar_definition_list;
- const Type_handler *type_handler;
- CHARSET_INFO *charset;
- Condition_information_item *cond_info_item;
- DYNCALL_CREATE_DEF *dyncol_def;
- Diagnostics_information *diag_info;
- Item *item;
- Item_num *item_num;
- Item_param *item_param;
- Item_basic_constant *item_basic_constant;
- Key_part_spec *key_part;
- LEX *lex;
- sp_expr_lex *expr_lex;
- sp_assignment_lex *assignment_lex;
- class sp_lex_cursor *sp_cursor_stmt;
- LEX_CSTRING *lex_str_ptr;
- LEX_USER *lex_user;
- USER_AUTH *user_auth;
- List<Condition_information_item> *cond_info_list;
- List<DYNCALL_CREATE_DEF> *dyncol_def_list;
- List<Item> *item_list;
- List<sp_assignment_lex> *sp_assignment_lex_list;
- List<Statement_information_item> *stmt_info_list;
- List<String> *string_list;
- List<LEX_CSTRING> *lex_str_list;
- Statement_information_item *stmt_info_item;
- String *string;
- TABLE_LIST *table_list;
- Table_ident *table;
- Qualified_column_ident *qualified_column_ident;
- char *simple_string;
- const char *const_simple_string;
- chooser_compare_func_creator boolfunc2creator;
- class my_var *myvar;
- class sp_condition_value *spcondvalue;
- class sp_head *sphead;
- class sp_name *spname;
- class sp_variable *spvar;
- class With_clause *with_clause;
- class Virtual_column_info *virtual_column;
-
- handlerton *db_type;
- st_select_lex *select_lex;
- st_select_lex_unit *select_lex_unit;
- struct p_elem_val *p_elem_value;
- class Window_frame *window_frame;
- class Window_frame_bound *window_frame_bound;
- udf_func *udf;
- st_trg_execution_order trg_execution_order;
-
- /* enums */
- enum enum_sp_suid_behaviour sp_suid;
- enum enum_sp_aggregate_type sp_aggregate_type;
- enum enum_view_suid view_suid;
- enum Condition_information_item::Name cond_info_item_name;
- enum enum_diag_condition_item_name diag_condition_item_name;
- enum Diagnostics_information::Which_area diag_area;
- enum enum_fk_option m_fk_option;
- enum Item_udftype udf_type;
- enum Key::Keytype key_type;
- enum Statement_information_item::Name stmt_info_item_name;
- enum enum_filetype filetype;
- enum enum_tx_isolation tx_isolation;
- enum enum_var_type var_type;
- enum enum_yes_no_unknown m_yes_no_unk;
- enum ha_choice choice;
- enum ha_key_alg key_alg;
- enum ha_rkey_function ha_rkey_mode;
- enum index_hint_type index_hint;
- enum interval_type interval, interval_time_st;
- enum row_type row_type;
- enum sp_variable::enum_mode spvar_mode;
- enum thr_lock_type lock_type;
- enum enum_mysql_timestamp_type date_time_type;
- enum Window_frame_bound::Bound_precedence_type bound_precedence_type;
- enum Window_frame::Frame_units frame_units;
- enum Window_frame::Frame_exclusion frame_exclusion;
- enum trigger_order_type trigger_action_order_type;
- DDL_options_st object_ddl_options;
- enum vers_kind_t vers_range_unit;
- enum Column_definition::enum_column_versioning vers_column_versioning;
- enum plsql_cursor_attr_t plsql_cursor_attr;
-}
-
-%{
-/* avoid unintentional %union size increases, it's what a parser stack made of */
-static_assert(sizeof(YYSTYPE) == sizeof(void*)*2+8, "%union size check");
-bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
-%}
-
-%pure-parser /* We have threads */
-%parse-param { THD *thd }
-%lex-param { THD *thd }
-/*
- Currently there are 40 shift/reduce conflicts.
- We should not introduce new conflicts any more.
-*/
-%expect 40
-
-/*
- Comments for TOKENS.
- For each token, please include in the same line a comment that contains
- the following tags:
- SQL-2011-R : Reserved keyword as per SQL-2011
- SQL-2011-N : Non Reserved keyword as per SQL-2011
- SQL-2003-R : Reserved keyword as per SQL-2003
- SQL-2003-N : Non Reserved keyword as per SQL-2003
- SQL-1999-R : Reserved keyword as per SQL-1999
- SQL-1999-N : Non Reserved keyword as per SQL-1999
- MYSQL : MySQL extention (unspecified)
- MYSQL-FUNC : MySQL extention, function
- INTERNAL : Not a real token, lex optimization
- OPERATOR : SQL operator
- FUTURE-USE : Reserved for future use
-
- This makes the code grep-able, and helps maintenance.
-*/
-
-
-%token <lex_str> '@'
-
-/*
- Special purpose tokens
-*/
-%token <NONE> ABORT_SYM /* INTERNAL (used in lex) */
-%token <NONE> IMPOSSIBLE_ACTION /* To avoid warning for yyerrlab1 */
-%token <NONE> END_OF_INPUT /* INTERNAL */
-%token <kwd> COLON_ORACLE_SYM /* INTERNAL */
-%token <kwd> PARAM_MARKER /* INTERNAL */
-%token <NONE> FOR_SYSTEM_TIME_SYM /* INTERNAL */
-%token <NONE> LEFT_PAREN_ALT /* INTERNAL */
-%token <NONE> LEFT_PAREN_WITH /* INTERNAL */
-%token <NONE> LEFT_PAREN_LIKE /* INTERNAL */
-%token <NONE> ORACLE_CONCAT_SYM /* INTERNAL */
-%token <NONE> PERCENT_ORACLE_SYM /* INTERNAL */
-%token <NONE> WITH_CUBE_SYM /* INTERNAL */
-%token <NONE> WITH_ROLLUP_SYM /* INTERNAL */
-%token <NONE> WITH_SYSTEM_SYM /* INTERNAL */
-
-
-/*
- Identifiers
-*/
-%token IDENT
-%token IDENT_QUOTED
-%token LEX_HOSTNAME
-%token UNDERSCORE_CHARSET /* _latin1 */
-
-
-/*
- Literals
-*/
-%token BIN_NUM /* LITERAL */
-%token DECIMAL_NUM /* LITERAL */
-%token FLOAT_NUM /* LITERAL */
-%token HEX_NUM /* LITERAL */
-%token HEX_STRING /* LITERAL */
-%token LONG_NUM /* LITERAL */
-%token NCHAR_STRING /* LITERAL */
-%token NUM /* LITERAL */
-%token TEXT_STRING /* LITERAL */
-%token ULONGLONG_NUM /* LITERAL */
-
-
-/*
- Operators
-*/
-%token <NONE> AND_AND_SYM /* OPERATOR */
-%token <NONE> DOT_DOT_SYM /* OPERATOR */
-%token <NONE> EQUAL_SYM /* OPERATOR */
-%token <NONE> GE /* OPERATOR */
-%token <NONE> LE /* OPERATOR */
-%token <NONE> MYSQL_CONCAT_SYM /* OPERATOR */
-%token <NONE> NE /* OPERATOR */
-%token <NONE> NOT2_SYM /* OPERATOR */
-%token <NONE> OR2_SYM /* OPERATOR */
-%token <NONE> SET_VAR /* OPERATOR */
-%token <NONE> SHIFT_LEFT /* OPERATOR */
-%token <NONE> SHIFT_RIGHT /* OPERATOR */
-
-
-/*
- Reserved keywords
-*/
-%token <kwd> ACCESSIBLE_SYM
-%token <kwd> ADD /* SQL-2003-R */
-%token <kwd> ALL /* SQL-2003-R */
-%token <kwd> ALTER /* SQL-2003-R */
-%token <kwd> ANALYZE_SYM
-%token <kwd> AND_SYM /* SQL-2003-R */
-%token <kwd> ASC /* SQL-2003-N */
-%token <kwd> ASENSITIVE_SYM /* FUTURE-USE */
-%token <kwd> AS /* SQL-2003-R */
-%token <kwd> BEFORE_SYM /* SQL-2003-N */
-%token <kwd> BETWEEN_SYM /* SQL-2003-R */
-%token <kwd> BIGINT /* SQL-2003-R */
-%token <kwd> BINARY /* SQL-2003-R */
-%token <kwd> BIT_AND /* MYSQL-FUNC */
-%token <kwd> BIT_OR /* MYSQL-FUNC */
-%token <kwd> BIT_XOR /* MYSQL-FUNC */
-%token <kwd> BLOB_MARIADB_SYM /* SQL-2003-R */
-%token <kwd> BLOB_ORACLE_SYM /* Oracle-R */
-%token <kwd> BODY_ORACLE_SYM /* Oracle-R */
-%token <kwd> BOTH /* SQL-2003-R */
-%token <kwd> BY /* SQL-2003-R */
-%token <kwd> CALL_SYM /* SQL-2003-R */
-%token <kwd> CASCADE /* SQL-2003-N */
-%token <kwd> CASE_SYM /* SQL-2003-R */
-%token <kwd> CAST_SYM /* SQL-2003-R */
-%token <kwd> CHANGE
-%token <kwd> CHAR_SYM /* SQL-2003-R */
-%token <kwd> CHECK_SYM /* SQL-2003-R */
-%token <kwd> COLLATE_SYM /* SQL-2003-R */
-%token <kwd> CONDITION_SYM /* SQL-2003-R, SQL-2008-R */
-%token <kwd> CONSTRAINT /* SQL-2003-R */
-%token <kwd> CONTINUE_MARIADB_SYM /* SQL-2003-R, Oracle-R */
-%token <kwd> CONTINUE_ORACLE_SYM /* SQL-2003-R, Oracle-R */
-%token <kwd> CONVERT_SYM /* SQL-2003-N */
-%token <kwd> COUNT_SYM /* SQL-2003-N */
-%token <kwd> CREATE /* SQL-2003-R */
-%token <kwd> CROSS /* SQL-2003-R */
-%token <kwd> CUME_DIST_SYM
-%token <kwd> CURDATE /* MYSQL-FUNC */
-%token <kwd> CURRENT_ROLE /* SQL-2003-R */
-%token <kwd> CURRENT_USER /* SQL-2003-R */
-%token <kwd> CURSOR_SYM /* SQL-2003-R */
-%token <kwd> CURTIME /* MYSQL-FUNC */
-%token <kwd> DATABASE
-%token <kwd> DATABASES
-%token <kwd> DATE_ADD_INTERVAL /* MYSQL-FUNC */
-%token <kwd> DATE_SUB_INTERVAL /* MYSQL-FUNC */
-%token <kwd> DAY_HOUR_SYM
-%token <kwd> DAY_MICROSECOND_SYM
-%token <kwd> DAY_MINUTE_SYM
-%token <kwd> DAY_SECOND_SYM
-%token <kwd> DECIMAL_SYM /* SQL-2003-R */
-%token <kwd> DECLARE_MARIADB_SYM /* SQL-2003-R */
-%token <kwd> DECLARE_ORACLE_SYM /* Oracle-R */
-%token <kwd> DEFAULT /* SQL-2003-R */
-%token <kwd> DELETE_DOMAIN_ID_SYM
-%token <kwd> DELETE_SYM /* SQL-2003-R */
-%token <kwd> DENSE_RANK_SYM
-%token <kwd> DESCRIBE /* SQL-2003-R */
-%token <kwd> DESC /* SQL-2003-N */
-%token <kwd> DETERMINISTIC_SYM /* SQL-2003-R */
-%token <kwd> DISTINCT /* SQL-2003-R */
-%token <kwd> DIV_SYM
-%token <kwd> DO_DOMAIN_IDS_SYM
-%token <kwd> DOUBLE_SYM /* SQL-2003-R */
-%token <kwd> DROP /* SQL-2003-R */
-%token <kwd> DUAL_SYM
-%token <kwd> EACH_SYM /* SQL-2003-R */
-%token <kwd> ELSEIF_MARIADB_SYM
-%token <kwd> ELSE /* SQL-2003-R */
-%token <kwd> ELSIF_ORACLE_SYM /* PLSQL-R */
-%token <kwd> ENCLOSED
-%token <kwd> ESCAPED
-%token <kwd> EXCEPT_SYM /* SQL-2003-R */
-%token <kwd> EXISTS /* SQL-2003-R */
-%token <kwd> EXTRACT_SYM /* SQL-2003-N */
-%token <kwd> FALSE_SYM /* SQL-2003-R */
-%token <kwd> FETCH_SYM /* SQL-2003-R */
-%token <kwd> FIRST_VALUE_SYM /* SQL-2011 */
-%token <kwd> FLOAT_SYM /* SQL-2003-R */
-%token <kwd> FOREIGN /* SQL-2003-R */
-%token <kwd> FOR_SYM /* SQL-2003-R */
-%token <kwd> FROM
-%token <kwd> FULLTEXT_SYM
-%token <kwd> GOTO_ORACLE_SYM /* Oracle-R */
-%token <kwd> GRANT /* SQL-2003-R */
-%token <kwd> GROUP_CONCAT_SYM
-%token <rwd> JSON_ARRAYAGG_SYM
-%token <rwd> JSON_OBJECTAGG_SYM
-%token <kwd> GROUP_SYM /* SQL-2003-R */
-%token <kwd> HAVING /* SQL-2003-R */
-%token <kwd> HOUR_MICROSECOND_SYM
-%token <kwd> HOUR_MINUTE_SYM
-%token <kwd> HOUR_SECOND_SYM
-%token <kwd> IF_SYM
-%token <kwd> IGNORE_DOMAIN_IDS_SYM
-%token <kwd> IGNORE_SYM
-%token <kwd> INDEX_SYM
-%token <kwd> INFILE
-%token <kwd> INNER_SYM /* SQL-2003-R */
-%token <kwd> INOUT_SYM /* SQL-2003-R */
-%token <kwd> INSENSITIVE_SYM /* SQL-2003-R */
-%token <kwd> INSERT /* SQL-2003-R */
-%token <kwd> IN_SYM /* SQL-2003-R */
-%token <kwd> INTERSECT_SYM /* SQL-2003-R */
-%token <kwd> INTERVAL_SYM /* SQL-2003-R */
-%token <kwd> INTO /* SQL-2003-R */
-%token <kwd> INT_SYM /* SQL-2003-R */
-%token <kwd> IS /* SQL-2003-R */
-%token <kwd> ITERATE_SYM
-%token <kwd> JOIN_SYM /* SQL-2003-R */
-%token <kwd> KEYS
-%token <kwd> KEY_SYM /* SQL-2003-N */
-%token <kwd> KILL_SYM
-%token <kwd> LAG_SYM /* SQL-2011 */
-%token <kwd> LEADING /* SQL-2003-R */
-%token <kwd> LEAD_SYM /* SQL-2011 */
-%token <kwd> LEAVE_SYM
-%token <kwd> LEFT /* SQL-2003-R */
-%token <kwd> LIKE /* SQL-2003-R */
-%token <kwd> LIMIT
-%token <kwd> LINEAR_SYM
-%token <kwd> LINES
-%token <kwd> LOAD
-%token <kwd> LOCATOR_SYM /* SQL-2003-N */
-%token <kwd> LOCK_SYM
-%token <kwd> LONGBLOB
-%token <kwd> LONG_SYM
-%token <kwd> LONGTEXT
-%token <kwd> LOOP_SYM
-%token <kwd> LOW_PRIORITY
-%token <kwd> MASTER_SSL_VERIFY_SERVER_CERT_SYM
-%token <kwd> MATCH /* SQL-2003-R */
-%token <kwd> MAX_SYM /* SQL-2003-N */
-%token <kwd> MAXVALUE_SYM /* SQL-2003-N */
-%token <kwd> MEDIAN_SYM
-%token <kwd> MEDIUMBLOB
-%token <kwd> MEDIUMINT
-%token <kwd> MEDIUMTEXT
-%token <kwd> MIN_SYM /* SQL-2003-N */
-%token <kwd> MINUTE_MICROSECOND_SYM
-%token <kwd> MINUTE_SECOND_SYM
-%token <kwd> MODIFIES_SYM /* SQL-2003-R */
-%token <kwd> MOD_SYM /* SQL-2003-N */
-%token <kwd> NATURAL /* SQL-2003-R */
-%token <kwd> NEG
-%token <kwd> NOT_SYM /* SQL-2003-R */
-%token <kwd> NO_WRITE_TO_BINLOG
-%token <kwd> NOW_SYM
-%token <kwd> NTH_VALUE_SYM /* SQL-2011 */
-%token <kwd> NTILE_SYM
-%token <kwd> NULL_SYM /* SQL-2003-R */
-%token <kwd> NUMERIC_SYM /* SQL-2003-R */
-%token <kwd> ON /* SQL-2003-R */
-%token <kwd> OPTIMIZE
-%token <kwd> OPTIONALLY
-%token <kwd> ORDER_SYM /* SQL-2003-R */
-%token <kwd> OR_SYM /* SQL-2003-R */
-%token <kwd> OTHERS_ORACLE_SYM /* SQL-2011-N, PLSQL-R */
-%token <kwd> OUTER
-%token <kwd> OUTFILE
-%token <kwd> OUT_SYM /* SQL-2003-R */
-%token <kwd> OVER_SYM
-%token <kwd> PACKAGE_ORACLE_SYM /* Oracle-R */
-%token <kwd> PAGE_CHECKSUM_SYM
-%token <kwd> PARSE_VCOL_EXPR_SYM
-%token <kwd> PARTITION_SYM /* SQL-2003-R */
-%token <kwd> PERCENTILE_CONT_SYM
-%token <kwd> PERCENTILE_DISC_SYM
-%token <kwd> PERCENT_RANK_SYM
-%token <kwd> PORTION_SYM /* SQL-2016-R */
-%token <kwd> POSITION_SYM /* SQL-2003-N */
-%token <kwd> PRECISION /* SQL-2003-R */
-%token <kwd> PRIMARY_SYM /* SQL-2003-R */
-%token <kwd> PROCEDURE_SYM /* SQL-2003-R */
-%token <kwd> PURGE
-%token <kwd> RAISE_ORACLE_SYM /* PLSQL-R */
-%token <kwd> RANGE_SYM /* SQL-2003-R */
-%token <kwd> RANK_SYM
-%token <kwd> READS_SYM /* SQL-2003-R */
-%token <kwd> READ_SYM /* SQL-2003-N */
-%token <kwd> READ_WRITE_SYM
-%token <kwd> REAL /* SQL-2003-R */
-%token <kwd> RECURSIVE_SYM
-%token <kwd> REFERENCES /* SQL-2003-R */
-%token <kwd> REF_SYSTEM_ID_SYM
-%token <kwd> REGEXP
-%token <kwd> RELEASE_SYM /* SQL-2003-R */
-%token <kwd> RENAME
-%token <kwd> REPEAT_SYM /* MYSQL-FUNC */
-%token <kwd> REPLACE /* MYSQL-FUNC */
-%token <kwd> REQUIRE_SYM
-%token <kwd> RESIGNAL_SYM /* SQL-2003-R */
-%token <kwd> RESTRICT
-%token <kwd> RETURNING_SYM
-%token <kwd> RETURN_MARIADB_SYM /* SQL-2003-R, PLSQL-R */
-%token <kwd> RETURN_ORACLE_SYM /* SQL-2003-R, PLSQL-R */
-%token <kwd> REVOKE /* SQL-2003-R */
-%token <kwd> RIGHT /* SQL-2003-R */
-%token <kwd> ROW_NUMBER_SYM
-%token <kwd> ROWS_SYM /* SQL-2003-R */
-%token <kwd> ROWTYPE_ORACLE_SYM /* PLSQL-R */
-%token <kwd> SECOND_MICROSECOND_SYM
-%token <kwd> SELECT_SYM /* SQL-2003-R */
-%token <kwd> SENSITIVE_SYM /* FUTURE-USE */
-%token <kwd> SEPARATOR_SYM
-%token <kwd> SERVER_OPTIONS
-%token <kwd> SET /* SQL-2003-R */
-%token <kwd> SHOW
-%token <kwd> SIGNAL_SYM /* SQL-2003-R */
-%token <kwd> SMALLINT /* SQL-2003-R */
-%token <kwd> SPATIAL_SYM
-%token <kwd> SPECIFIC_SYM /* SQL-2003-R */
-%token <kwd> SQL_BIG_RESULT
-%token <kwd> SQLEXCEPTION_SYM /* SQL-2003-R */
-%token <kwd> SQL_SMALL_RESULT
-%token <kwd> SQLSTATE_SYM /* SQL-2003-R */
-%token <kwd> SQL_SYM /* SQL-2003-R */
-%token <kwd> SQLWARNING_SYM /* SQL-2003-R */
-%token <kwd> SSL_SYM
-%token <kwd> STARTING
-%token <kwd> STATS_AUTO_RECALC_SYM
-%token <kwd> STATS_PERSISTENT_SYM
-%token <kwd> STATS_SAMPLE_PAGES_SYM
-%token <kwd> STDDEV_SAMP_SYM /* SQL-2003-N */
-%token <kwd> STD_SYM
-%token <kwd> STRAIGHT_JOIN
-%token <kwd> SUBSTRING /* SQL-2003-N */
-%token <kwd> SUM_SYM /* SQL-2003-N */
-%token <kwd> SYSDATE
-%token <kwd> TABLE_REF_PRIORITY
-%token <kwd> TABLE_SYM /* SQL-2003-R */
-%token <kwd> TERMINATED
-%token <kwd> THEN_SYM /* SQL-2003-R */
-%token <kwd> TINYBLOB
-%token <kwd> TINYINT
-%token <kwd> TINYTEXT
-%token <kwd> TO_SYM /* SQL-2003-R */
-%token <kwd> TRAILING /* SQL-2003-R */
-%token <kwd> TRIGGER_SYM /* SQL-2003-R */
-%token <kwd> TRIM /* SQL-2003-N */
-%token <kwd> TRUE_SYM /* SQL-2003-R */
-%token <kwd> UNDO_SYM /* FUTURE-USE */
-%token <kwd> UNION_SYM /* SQL-2003-R */
-%token <kwd> UNIQUE_SYM
-%token <kwd> UNLOCK_SYM
-%token <kwd> UNSIGNED
-%token <kwd> UPDATE_SYM /* SQL-2003-R */
-%token <kwd> USAGE /* SQL-2003-N */
-%token <kwd> USE_SYM
-%token <kwd> USING /* SQL-2003-R */
-%token <kwd> UTC_DATE_SYM
-%token <kwd> UTC_TIMESTAMP_SYM
-%token <kwd> UTC_TIME_SYM
-%token <kwd> VALUES_IN_SYM
-%token <kwd> VALUES_LESS_SYM
-%token <kwd> VALUES /* SQL-2003-R */
-%token <kwd> VARBINARY
-%token <kwd> VARCHAR /* SQL-2003-R */
-%token <kwd> VARIANCE_SYM
-%token <kwd> VAR_SAMP_SYM
-%token <kwd> VARYING /* SQL-2003-R */
-%token <kwd> WHEN_SYM /* SQL-2003-R */
-%token <kwd> WHERE /* SQL-2003-R */
-%token <kwd> WHILE_SYM
-%token <kwd> WITH /* SQL-2003-R */
-%token <kwd> XOR
-%token <kwd> YEAR_MONTH_SYM
-%token <kwd> ZEROFILL
-
-
-/*
- Keywords that have different reserved status in std/oracle modes.
-*/
-%token <kwd> BODY_MARIADB_SYM // Oracle-R
-%token <kwd> ELSEIF_ORACLE_SYM
-%token <kwd> ELSIF_MARIADB_SYM // PLSQL-R
-%token <kwd> EXCEPTION_ORACLE_SYM // SQL-2003-N, PLSQL-R
-%token <kwd> GOTO_MARIADB_SYM // Oracle-R
-%token <kwd> OTHERS_MARIADB_SYM // SQL-2011-N, PLSQL-R
-%token <kwd> PACKAGE_MARIADB_SYM // Oracle-R
-%token <kwd> RAISE_MARIADB_SYM // PLSQL-R
-%token <kwd> ROWTYPE_MARIADB_SYM // PLSQL-R
-
-/*
- Non-reserved keywords
-*/
-
-%token <kwd> ACCOUNT_SYM /* MYSQL */
-%token <kwd> ACTION /* SQL-2003-N */
-%token <kwd> ADMIN_SYM /* SQL-2003-N */
-%token <kwd> ADDDATE_SYM /* MYSQL-FUNC */
-%token <kwd> AFTER_SYM /* SQL-2003-N */
-%token <kwd> AGAINST
-%token <kwd> AGGREGATE_SYM
-%token <kwd> ALGORITHM_SYM
-%token <kwd> ALWAYS_SYM
-%token <kwd> ANY_SYM /* SQL-2003-R */
-%token <kwd> ASCII_SYM /* MYSQL-FUNC */
-%token <kwd> AT_SYM /* SQL-2003-R */
-%token <kwd> ATOMIC_SYM /* SQL-2003-R */
-%token <kwd> AUTHORS_SYM
-%token <kwd> AUTOEXTEND_SIZE_SYM
-%token <kwd> AUTO_INC
-%token <kwd> AUTO_SYM
-%token <kwd> AVG_ROW_LENGTH
-%token <kwd> AVG_SYM /* SQL-2003-N */
-%token <kwd> BACKUP_SYM
-%token <kwd> BEGIN_MARIADB_SYM /* SQL-2003-R, PLSQL-R */
-%token <kwd> BEGIN_ORACLE_SYM /* SQL-2003-R, PLSQL-R */
-%token <kwd> BINLOG_SYM
-%token <kwd> BIT_SYM /* MYSQL-FUNC */
-%token <kwd> BLOCK_SYM
-%token <kwd> BOOL_SYM
-%token <kwd> BOOLEAN_SYM /* SQL-2003-R, PLSQL-R */
-%token <kwd> BTREE_SYM
-%token <kwd> BYTE_SYM
-%token <kwd> CACHE_SYM
-%token <kwd> CASCADED /* SQL-2003-R */
-%token <kwd> CATALOG_NAME_SYM /* SQL-2003-N */
-%token <kwd> CHAIN_SYM /* SQL-2003-N */
-%token <kwd> CHANGED
-%token <kwd> CHARSET
-%token <kwd> CHECKPOINT_SYM
-%token <kwd> CHECKSUM_SYM
-%token <kwd> CIPHER_SYM
-%token <kwd> CLASS_ORIGIN_SYM /* SQL-2003-N */
-%token <kwd> CLIENT_SYM
-%token <kwd> CLOB_MARIADB_SYM /* SQL-2003-R */
-%token <kwd> CLOB_ORACLE_SYM /* Oracle-R */
-%token <kwd> CLOSE_SYM /* SQL-2003-R */
-%token <kwd> COALESCE /* SQL-2003-N */
-%token <kwd> CODE_SYM
-%token <kwd> COLLATION_SYM /* SQL-2003-N */
-%token <kwd> COLUMNS
-%token <kwd> COLUMN_ADD_SYM
-%token <kwd> COLUMN_CHECK_SYM
-%token <kwd> COLUMN_CREATE_SYM
-%token <kwd> COLUMN_DELETE_SYM
-%token <kwd> COLUMN_GET_SYM
-%token <kwd> COLUMN_SYM /* SQL-2003-R */
-%token <kwd> COLUMN_NAME_SYM /* SQL-2003-N */
-%token <kwd> COMMENT_SYM /* Oracle-R */
-%token <kwd> COMMITTED_SYM /* SQL-2003-N */
-%token <kwd> COMMIT_SYM /* SQL-2003-R */
-%token <kwd> COMPACT_SYM
-%token <kwd> COMPLETION_SYM
-%token <kwd> COMPRESSED_SYM
-%token <kwd> CONCURRENT
-%token <kwd> CONNECTION_SYM
-%token <kwd> CONSISTENT_SYM
-%token <kwd> CONSTRAINT_CATALOG_SYM /* SQL-2003-N */
-%token <kwd> CONSTRAINT_NAME_SYM /* SQL-2003-N */
-%token <kwd> CONSTRAINT_SCHEMA_SYM /* SQL-2003-N */
-%token <kwd> CONTAINS_SYM /* SQL-2003-N */
-%token <kwd> CONTEXT_SYM
-%token <kwd> CONTRIBUTORS_SYM
-%token <kwd> CPU_SYM
-%token <kwd> CUBE_SYM /* SQL-2003-R */
-%token <kwd> CURRENT_SYM /* SQL-2003-R */
-%token <kwd> CURRENT_POS_SYM
-%token <kwd> CURSOR_NAME_SYM /* SQL-2003-N */
-%token <kwd> CYCLE_SYM
-%token <kwd> DATAFILE_SYM
-%token <kwd> DATA_SYM /* SQL-2003-N */
-%token <kwd> DATETIME
-%token <kwd> DATE_FORMAT_SYM /* MYSQL-FUNC */
-%token <kwd> DATE_SYM /* SQL-2003-R, Oracle-R, PLSQL-R */
-%token <kwd> DAY_SYM /* SQL-2003-R */
-%token <kwd> DEALLOCATE_SYM /* SQL-2003-R */
-%token <kwd> DECODE_MARIADB_SYM /* Function, non-reserved */
-%token <kwd> DECODE_ORACLE_SYM /* Function, non-reserved */
-%token <kwd> DEFINER_SYM
-%token <kwd> DELAYED_SYM
-%token <kwd> DELAY_KEY_WRITE_SYM
-%token <kwd> DES_KEY_FILE
-%token <kwd> DIAGNOSTICS_SYM /* SQL-2003-N */
-%token <kwd> DIRECTORY_SYM
-%token <kwd> DISABLE_SYM
-%token <kwd> DISCARD
-%token <kwd> DISK_SYM
-%token <kwd> DO_SYM
-%token <kwd> DUMPFILE
-%token <kwd> DUPLICATE_SYM
-%token <kwd> DYNAMIC_SYM /* SQL-2003-R */
-%token <kwd> ENABLE_SYM
-%token <kwd> END /* SQL-2003-R, PLSQL-R */
-%token <kwd> ENDS_SYM
-%token <kwd> ENGINES_SYM
-%token <kwd> ENGINE_SYM
-%token <kwd> ENUM
-%token <kwd> ERROR_SYM
-%token <kwd> ERRORS
-%token <kwd> ESCAPE_SYM /* SQL-2003-R */
-%token <kwd> EVENTS_SYM
-%token <kwd> EVENT_SYM
-%token <kwd> EVERY_SYM /* SQL-2003-N */
-%token <kwd> EXCHANGE_SYM
-%token <kwd> EXAMINED_SYM
-%token <kwd> EXCLUDE_SYM /* SQL-2011-N */
-%token <kwd> EXECUTE_SYM /* SQL-2003-R */
-%token <kwd> EXCEPTION_MARIADB_SYM /* SQL-2003-N, PLSQL-R */
-%token <kwd> EXIT_MARIADB_SYM /* PLSQL-R */
-%token <kwd> EXIT_ORACLE_SYM /* PLSQL-R */
-%token <kwd> EXPANSION_SYM
-%token <kwd> EXPIRE_SYM /* MySQL */
-%token <kwd> EXPORT_SYM
-%token <kwd> EXTENDED_SYM
-%token <kwd> EXTENT_SIZE_SYM
-%token <kwd> FAST_SYM
-%token <kwd> FAULTS_SYM
-%token <kwd> FILE_SYM
-%token <kwd> FIRST_SYM /* SQL-2003-N */
-%token <kwd> FIXED_SYM
-%token <kwd> FLUSH_SYM
-%token <kwd> FOLLOWS_SYM /* MYSQL trigger*/
-%token <kwd> FOLLOWING_SYM /* SQL-2011-N */
-%token <kwd> FORCE_SYM
-%token <kwd> FORMAT_SYM
-%token <kwd> FOUND_SYM /* SQL-2003-R */
-%token <kwd> FULL /* SQL-2003-R */
-%token <kwd> FUNCTION_SYM /* SQL-2003-R, Oracle-R */
-%token <kwd> GENERAL
-%token <kwd> GENERATED_SYM
-%token <kwd> GET_FORMAT /* MYSQL-FUNC */
-%token <kwd> GET_SYM /* SQL-2003-R */
-%token <kwd> GLOBAL_SYM /* SQL-2003-R */
-%token <kwd> GRANTS
-%token <kwd> HANDLER_SYM
-%token <kwd> HARD_SYM
-%token <kwd> HASH_SYM
-%token <kwd> HELP_SYM
-%token <kwd> HIGH_PRIORITY
-%token <kwd> HISTORY_SYM /* MYSQL */
-%token <kwd> HOST_SYM
-%token <kwd> HOSTS_SYM
-%token <kwd> HOUR_SYM /* SQL-2003-R */
-%token <kwd> ID_SYM /* MYSQL */
-%token <kwd> IDENTIFIED_SYM
-%token <kwd> IGNORE_SERVER_IDS_SYM
-%token <kwd> IMMEDIATE_SYM /* SQL-2003-R */
-%token <kwd> IMPORT
-%token <kwd> INCREMENT_SYM
-%token <kwd> INDEXES
-%token <kwd> INITIAL_SIZE_SYM
-%token <kwd> INSERT_METHOD
-%token <kwd> INSTALL_SYM
-%token <kwd> INVOKER_SYM
-%token <kwd> IO_SYM
-%token <kwd> IPC_SYM
-%token <kwd> ISOLATION /* SQL-2003-R */
-%token <kwd> ISOPEN_SYM /* Oracle-N */
-%token <kwd> ISSUER_SYM
-%token <kwd> INVISIBLE_SYM
-%token <kwd> JSON_SYM
-%token <kwd> KEY_BLOCK_SIZE
-%token <kwd> LANGUAGE_SYM /* SQL-2003-R */
-%token <kwd> LAST_SYM /* SQL-2003-N */
-%token <kwd> LAST_VALUE
-%token <kwd> LASTVAL_SYM /* PostgreSQL sequence function */
-%token <kwd> LEAVES
-%token <kwd> LESS_SYM
-%token <kwd> LEVEL_SYM
-%token <kwd> LIST_SYM
-%token <kwd> LOCAL_SYM /* SQL-2003-R */
-%token <kwd> LOCKS_SYM
-%token <kwd> LOGFILE_SYM
-%token <kwd> LOGS_SYM
-%token <kwd> MASTER_CONNECT_RETRY_SYM
-%token <kwd> MASTER_DELAY_SYM
-%token <kwd> MASTER_GTID_POS_SYM
-%token <kwd> MASTER_HOST_SYM
-%token <kwd> MASTER_LOG_FILE_SYM
-%token <kwd> MASTER_LOG_POS_SYM
-%token <kwd> MASTER_PASSWORD_SYM
-%token <kwd> MASTER_PORT_SYM
-%token <kwd> MASTER_SERVER_ID_SYM
-%token <kwd> MASTER_SSL_CAPATH_SYM
-%token <kwd> MASTER_SSL_CA_SYM
-%token <kwd> MASTER_SSL_CERT_SYM
-%token <kwd> MASTER_SSL_CIPHER_SYM
-%token <kwd> MASTER_SSL_CRL_SYM
-%token <kwd> MASTER_SSL_CRLPATH_SYM
-%token <kwd> MASTER_SSL_KEY_SYM
-%token <kwd> MASTER_SSL_SYM
-%token <kwd> MASTER_SYM
-%token <kwd> MASTER_USER_SYM
-%token <kwd> MASTER_USE_GTID_SYM
-%token <kwd> MASTER_HEARTBEAT_PERIOD_SYM
-%token <kwd> MAX_CONNECTIONS_PER_HOUR
-%token <kwd> MAX_QUERIES_PER_HOUR
-%token <kwd> MAX_ROWS
-%token <kwd> MAX_SIZE_SYM
-%token <kwd> MAX_UPDATES_PER_HOUR
-%token <kwd> MAX_STATEMENT_TIME_SYM
-%token <kwd> MAX_USER_CONNECTIONS_SYM
-%token <kwd> MEDIUM_SYM
-%token <kwd> MEMORY_SYM
-%token <kwd> MERGE_SYM /* SQL-2003-R */
-%token <kwd> MESSAGE_TEXT_SYM /* SQL-2003-N */
-%token <kwd> MICROSECOND_SYM /* MYSQL-FUNC */
-%token <kwd> MIGRATE_SYM
-%token <kwd> MINUTE_SYM /* SQL-2003-R */
-%token <kwd> MINVALUE_SYM
-%token <kwd> MIN_ROWS
-%token <kwd> MODE_SYM
-%token <kwd> MODIFY_SYM
-%token <kwd> MONTH_SYM /* SQL-2003-R */
-%token <kwd> MUTEX_SYM
-%token <kwd> MYSQL_SYM
-%token <kwd> MYSQL_ERRNO_SYM
-%token <kwd> NAMES_SYM /* SQL-2003-N */
-%token <kwd> NAME_SYM /* SQL-2003-N */
-%token <kwd> NATIONAL_SYM /* SQL-2003-R */
-%token <kwd> NCHAR_SYM /* SQL-2003-R */
-%token <kwd> NEVER_SYM /* MySQL */
-%token <kwd> NEW_SYM /* SQL-2003-R */
-%token <kwd> NEXT_SYM /* SQL-2003-N */
-%token <kwd> NEXTVAL_SYM /* PostgreSQL sequence function */
-%token <kwd> NOCACHE_SYM
-%token <kwd> NOCYCLE_SYM
-%token <kwd> NODEGROUP_SYM
-%token <kwd> NONE_SYM /* SQL-2003-R */
-%token <kwd> NOTFOUND_SYM /* Oracle-R */
-%token <kwd> NO_SYM /* SQL-2003-R */
-%token <kwd> NOMAXVALUE_SYM
-%token <kwd> NOMINVALUE_SYM
-%token <kwd> NO_WAIT_SYM
-%token <kwd> NOWAIT_SYM
-%token <kwd> NUMBER_MARIADB_SYM /* SQL-2003-N */
-%token <kwd> NUMBER_ORACLE_SYM /* Oracle-R, PLSQL-R */
-%token <kwd> NVARCHAR_SYM
-%token <kwd> OF_SYM /* SQL-1992-R, Oracle-R */
-%token <kwd> OFFSET_SYM
-%token <kwd> OLD_PASSWORD_SYM
-%token <kwd> ONE_SYM
-%token <kwd> ONLY_SYM /* SQL-2003-R */
-%token <kwd> ONLINE_SYM
-%token <kwd> OPEN_SYM /* SQL-2003-R */
-%token <kwd> OPTIONS_SYM
-%token <kwd> OPTION /* SQL-2003-N */
-%token <kwd> OWNER_SYM
-%token <kwd> PACK_KEYS_SYM
-%token <kwd> PAGE_SYM
-%token <kwd> PARSER_SYM
-%token <kwd> PARTIAL /* SQL-2003-N */
-%token <kwd> PARTITIONS_SYM
-%token <kwd> PARTITIONING_SYM
-%token <kwd> PASSWORD_SYM
-%token <kwd> PERIOD_SYM /* SQL-2011-R */
-%token <kwd> PERSISTENT_SYM
-%token <kwd> PHASE_SYM
-%token <kwd> PLUGINS_SYM
-%token <kwd> PLUGIN_SYM
-%token <kwd> PORT_SYM
-%token <kwd> PRECEDES_SYM /* MYSQL */
-%token <kwd> PRECEDING_SYM /* SQL-2011-N */
-%token <kwd> PREPARE_SYM /* SQL-2003-R */
-%token <kwd> PRESERVE_SYM
-%token <kwd> PREV_SYM
-%token <kwd> PREVIOUS_SYM
-%token <kwd> PRIVILEGES /* SQL-2003-N */
-%token <kwd> PROCESS
-%token <kwd> PROCESSLIST_SYM
-%token <kwd> PROFILE_SYM
-%token <kwd> PROFILES_SYM
-%token <kwd> PROXY_SYM
-%token <kwd> QUARTER_SYM
-%token <kwd> QUERY_SYM
-%token <kwd> QUICK
-%token <kwd> RAW_MARIADB_SYM
-%token <kwd> RAW_ORACLE_SYM /* Oracle-R */
-%token <kwd> READ_ONLY_SYM
-%token <kwd> REBUILD_SYM
-%token <kwd> RECOVER_SYM
-%token <kwd> REDOFILE_SYM
-%token <kwd> REDO_BUFFER_SIZE_SYM
-%token <kwd> REDUNDANT_SYM
-%token <kwd> RELAY
-%token <kwd> RELAYLOG_SYM
-%token <kwd> RELAY_LOG_FILE_SYM
-%token <kwd> RELAY_LOG_POS_SYM
-%token <kwd> RELAY_THREAD
-%token <kwd> RELOAD
-%token <kwd> REMOVE_SYM
-%token <kwd> REORGANIZE_SYM
-%token <kwd> REPAIR
-%token <kwd> REPEATABLE_SYM /* SQL-2003-N */
-%token <kwd> REPLICATION
-%token <kwd> RESET_SYM
-%token <kwd> RESTART_SYM
-%token <kwd> RESOURCES
-%token <kwd> RESTORE_SYM
-%token <kwd> RESUME_SYM
-%token <kwd> RETURNED_SQLSTATE_SYM /* SQL-2003-N */
-%token <kwd> RETURNS_SYM /* SQL-2003-R */
-%token <kwd> REUSE_SYM /* Oracle-R */
-%token <kwd> REVERSE_SYM
-%token <kwd> ROLE_SYM
-%token <kwd> ROLLBACK_SYM /* SQL-2003-R */
-%token <kwd> ROLLUP_SYM /* SQL-2003-R */
-%token <kwd> ROUTINE_SYM /* SQL-2003-N */
-%token <kwd> ROWCOUNT_SYM /* Oracle-N */
-%token <kwd> ROW_SYM /* SQL-2003-R */
-%token <kwd> ROW_COUNT_SYM /* SQL-2003-N */
-%token <kwd> ROW_FORMAT_SYM
-%token <kwd> RTREE_SYM
-%token <kwd> SAVEPOINT_SYM /* SQL-2003-R */
-%token <kwd> SCHEDULE_SYM
-%token <kwd> SCHEMA_NAME_SYM /* SQL-2003-N */
-%token <kwd> SECOND_SYM /* SQL-2003-R */
-%token <kwd> SECURITY_SYM /* SQL-2003-N */
-%token <kwd> SEQUENCE_SYM
-%token <kwd> SERIALIZABLE_SYM /* SQL-2003-N */
-%token <kwd> SERIAL_SYM
-%token <kwd> SESSION_SYM /* SQL-2003-N */
-%token <kwd> SERVER_SYM
-%token <kwd> SETVAL_SYM /* PostgreSQL sequence function */
-%token <kwd> SHARE_SYM
-%token <kwd> SHUTDOWN
-%token <kwd> SIGNED_SYM
-%token <kwd> SIMPLE_SYM /* SQL-2003-N */
-%token <kwd> SLAVE
-%token <kwd> SLAVES
-%token <kwd> SLAVE_POS_SYM
-%token <kwd> SLOW
-%token <kwd> SNAPSHOT_SYM
-%token <kwd> SOCKET_SYM
-%token <kwd> SOFT_SYM
-%token <kwd> SONAME_SYM
-%token <kwd> SOUNDS_SYM
-%token <kwd> SOURCE_SYM
-%token <kwd> SQL_BUFFER_RESULT
-%token <kwd> SQL_CACHE_SYM
-%token <kwd> SQL_CALC_FOUND_ROWS
-%token <kwd> SQL_NO_CACHE_SYM
-%token <kwd> SQL_THREAD
-%token <kwd> STAGE_SYM
-%token <kwd> STARTS_SYM
-%token <kwd> START_SYM /* SQL-2003-R */
-%token <kwd> STATEMENT_SYM
-%token <kwd> STATUS_SYM
-%token <kwd> STOP_SYM
-%token <kwd> STORAGE_SYM
-%token <kwd> STORED_SYM
-%token <kwd> STRING_SYM
-%token <kwd> SUBCLASS_ORIGIN_SYM /* SQL-2003-N */
-%token <kwd> SUBDATE_SYM
-%token <kwd> SUBJECT_SYM
-%token <kwd> SUBPARTITIONS_SYM
-%token <kwd> SUBPARTITION_SYM
-%token <kwd> SUPER_SYM
-%token <kwd> SUSPEND_SYM
-%token <kwd> SWAPS_SYM
-%token <kwd> SWITCHES_SYM
-%token <kwd> SYSTEM /* SQL-2011-R */
-%token <kwd> SYSTEM_TIME_SYM /* SQL-2011-R */
-%token <kwd> TABLES
-%token <kwd> TABLESPACE
-%token <kwd> TABLE_CHECKSUM_SYM
-%token <kwd> TABLE_NAME_SYM /* SQL-2003-N */
-%token <kwd> TEMPORARY /* SQL-2003-N */
-%token <kwd> TEMPTABLE_SYM
-%token <kwd> TEXT_SYM
-%token <kwd> THAN_SYM
-%token <kwd> TIES_SYM /* SQL-2011-N */
-%token <kwd> TIMESTAMP /* SQL-2003-R */
-%token <kwd> TIMESTAMP_ADD
-%token <kwd> TIMESTAMP_DIFF
-%token <kwd> TIME_SYM /* SQL-2003-R, Oracle-R */
-%token <kwd> TRANSACTION_SYM
-%token <kwd> TRANSACTIONAL_SYM
-%token <kwd> TRIGGERS_SYM
-%token <kwd> TRIM_ORACLE
-%token <kwd> TRUNCATE_SYM
-%token <kwd> TYPES_SYM
-%token <kwd> TYPE_SYM /* SQL-2003-N */
-%token <kwd> UDF_RETURNS_SYM
-%token <kwd> UNBOUNDED_SYM /* SQL-2011-N */
-%token <kwd> UNCOMMITTED_SYM /* SQL-2003-N */
-%token <kwd> UNDEFINED_SYM
-%token <kwd> UNDOFILE_SYM
-%token <kwd> UNDO_BUFFER_SIZE_SYM
-%token <kwd> UNICODE_SYM
-%token <kwd> UNINSTALL_SYM
-%token <kwd> UNKNOWN_SYM /* SQL-2003-R */
-%token <kwd> UNTIL_SYM
-%token <kwd> UPGRADE_SYM
-%token <kwd> USER_SYM /* SQL-2003-R */
-%token <kwd> USE_FRM
-%token <kwd> VALUE_SYM /* SQL-2003-R */
-%token <kwd> VARCHAR2_MARIADB_SYM
-%token <kwd> VARCHAR2_ORACLE_SYM /* Oracle-R, PLSQL-R */
-%token <kwd> VARIABLES
-%token <kwd> VERSIONING_SYM /* SQL-2011-R */
-%token <kwd> VIA_SYM
-%token <kwd> VIEW_SYM /* SQL-2003-N */
-%token <kwd> VIRTUAL_SYM
-%token <kwd> WAIT_SYM
-%token <kwd> WARNINGS
-%token <kwd> WEEK_SYM
-%token <kwd> WEIGHT_STRING_SYM
-%token <kwd> WINDOW_SYM /* SQL-2003-R */
-%token <kwd> WITHIN
-%token <kwd> WITHOUT /* SQL-2003-R */
-%token <kwd> WORK_SYM /* SQL-2003-N */
-%token <kwd> WRAPPER_SYM
-%token <kwd> WRITE_SYM /* SQL-2003-N */
-%token <kwd> X509_SYM
-%token <kwd> XA_SYM
-%token <kwd> XML_SYM
-%token <kwd> YEAR_SYM /* SQL-2003-R */
-
-
-/*
- Give ESCAPE (in LIKE) a very low precedence.
- This allows the concatenation operator || to be used on the right
- side of "LIKE" with sql_mode=PIPES_AS_CONCAT (without ORACLE):
- SELECT 'ab' LIKE 'a'||'b'||'c';
-*/
-%left PREC_BELOW_ESCAPE
-%left ESCAPE_SYM
-
-/* A dummy token to force the priority of table_ref production in a join. */
-%left CONDITIONLESS_JOIN
-%left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT ON_SYM USING
-
-%left SET_VAR
-%left OR_SYM OR2_SYM
-%left XOR
-%left AND_SYM AND_AND_SYM
-
-%left PREC_BELOW_NOT
-%left NOT_SYM
-
-%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
-%left '=' EQUAL_SYM GE '>' LE '<' NE IS LIKE SOUNDS_SYM REGEXP IN_SYM
-%left '|'
-%left '&'
-%left SHIFT_LEFT SHIFT_RIGHT
-%left '-' '+' ORACLE_CONCAT_SYM
-%left '*' '/' '%' DIV_SYM MOD_SYM
-%left '^'
-%left MYSQL_CONCAT_SYM
-%left NEG '~' NOT2_SYM BINARY
-%left COLLATE_SYM
-%left SUBQUERY_AS_EXPR
-
-/*
- Tokens that can change their meaning from identifier to something else
- in certain context.
-
- - TRANSACTION: identifier, history unit:
- SELECT transaction FROM t1;
- SELECT * FROM t1 FOR SYSTEM_TIME AS OF TRANSACTION @var;
-
- - TIMESTAMP: identifier, literal, history unit:
- SELECT timestamp FROM t1;
- SELECT TIMESTAMP '2001-01-01 10:20:30';
- SELECT * FROM t1 FOR SYSTEM_TIME AS OF TIMESTAMP CONCAT(@date,' ',@time);
-
- - PERIOD: identifier, period for system time:
- SELECT period FROM t1;
- ALTER TABLE DROP PERIOD FOR SYSTEM TIME;
-
- - SYSTEM: identifier, system versioning:
- SELECT system FROM t1;
- ALTER TABLE DROP SYSTEM VERSIONIONG;
-
- - USER: identifier, user:
- SELECT user FROM t1;
- KILL USER foo;
-
- Note, we need here only tokens that cause shift/reduce conflicts
- with keyword identifiers. For example:
- opt_clause1: %empty | KEYWORD ... ;
- clause2: opt_clause1 ident;
- KEYWORD can appear both in opt_clause1 and in "ident" through the "keyword"
- rule. So the parser reports a conflict on how to interpret KEYWORD:
- - as a start of non-empty branch in opt_clause1, or
- - as an identifier which follows the empty branch in opt_clause1.
-
- Example#1:
- alter_list_item:
- DROP opt_column opt_if_exists_table_element field_ident
- | DROP SYSTEM VERSIONING_SYM
- SYSTEM can be a keyword in field_ident, or can be a start of
- SYSTEM VERSIONING.
-
- Example#2:
- system_time_expr: AS OF_SYM history_point
- history_point: opt_history_unit bit_expr
- opt_history_unit: | TRANSACTION_SYM
- TRANSACTION can be a non-empty history unit, or can be an identifier
- in bit_expr.
-
- In the grammar below we use %prec to explicitely tell Bison to go
- through the empty branch in the optional rule only when the lookahead
- token does not belong to a small set of selected tokens.
-
- Tokens NEXT_SYM and PREVIOUS_SYM also change their meaning from
- identifiers to sequence operations when followed by VALUE_SYM:
- SELECT NEXT VALUE FOR s1, PREVIOUS VALUE FOR s1;
- but we don't need to list them here as they do not seem to cause
- conflicts (according to bison -v), as both meanings
- (as identifier, and as a sequence operation) are parts of the same target
- column_default_non_parenthesized_expr, and there are no any optional
- clauses between the start of column_default_non_parenthesized_expr
- and until NEXT_SYM / PREVIOUS_SYM.
-*/
-%left PREC_BELOW_IDENTIFIER_OPT_SPECIAL_CASE
-%left TRANSACTION_SYM TIMESTAMP PERIOD_SYM SYSTEM USER COMMENT_SYM
-
-
-/*
- Tokens that can appear in a token contraction on the second place
- and change the meaning of the previous token.
-
- - TEXT_STRING: changes the meaning of TIMESTAMP/TIME/DATE
- from identifier to literal:
- SELECT timestamp FROM t1;
- SELECT TIMESTAMP'2001-01-01 00:00:00' FROM t1;
-
- - Parenthesis: changes the meaning of TIMESTAMP/TIME/DATE
- from identifiers to CAST-alike functions:
- SELECT timestamp FROM t1;
- SELECT timestamp(1) FROM t1;
-
- - VALUE: changes NEXT and PREVIOUS from identifier to sequence operation:
- SELECT next, previous FROM t1;
- SELECT NEXT VALUE FOR s1, PREVIOUS VALUE FOR s1;
-
- - VERSIONING: changes SYSTEM from identifier to SYSTEM VERSIONING
- SELECT system FROM t1;
- ALTER TABLE t1 ADD SYSTEM VERSIONING;
-*/
-%left PREC_BELOW_CONTRACTION_TOKEN2
-%left TEXT_STRING '(' ')' VALUE_SYM VERSIONING_SYM
-%left EMPTY_FROM_CLAUSE
-%right INTO
-
-%type <lex_str>
- DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
- HEX_NUM HEX_STRING
- LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident_or_text
- TEXT_STRING_sys TEXT_STRING_literal
- key_cache_name
- sp_opt_label BIN_NUM TEXT_STRING_filesystem
- opt_constraint constraint opt_ident
- sp_block_label sp_control_label opt_place opt_db
-
-%type <ident_sys>
- IDENT_sys
- ident
- label_ident
- sp_decl_ident
- ident_or_empty
- ident_table_alias
- ident_sysvar_name
- ident_for_loop_index
-
-%type <lex_string_with_metadata>
- TEXT_STRING
- NCHAR_STRING
-
-%type <lex_str_ptr>
- opt_table_alias_clause
- table_alias_clause
-
-%type <ident_cli>
- IDENT
- IDENT_QUOTED
- IDENT_cli
- ident_cli
- ident_cli_set_usual_case
-
-%type <kwd>
- keyword_data_type
- keyword_cast_type
- keyword_ident
- keyword_label
- keyword_set_special_case
- keyword_set_usual_case
- keyword_sp_block_section
- keyword_sp_decl
- keyword_sp_head
- keyword_sp_var_and_label
- keyword_sp_var_not_label
- keyword_sysvar_name
- keyword_sysvar_type
- keyword_table_alias
- keyword_verb_clause
- charset
- reserved_keyword_udt
- reserved_keyword_udt_not_param_type
- non_reserved_keyword_udt
-
-%type <table>
- table_ident table_ident_nodb references xid
- table_ident_opt_wild create_like
-
-%type <qualified_column_ident>
- optionally_qualified_column_ident
-
-%type <simple_string>
- remember_name remember_end
- remember_tok_start
- wild_and_where
-
-%type <const_simple_string>
- field_length opt_field_length
- opt_compression_method
-
-%type <string>
- text_string hex_or_bin_String opt_gconcat_separator
-
-%type <type_handler> int_type real_type
-
-%type <Lex_field_type> type_with_opt_collate field_type
- field_type_numeric
- field_type_string
- field_type_lob
- field_type_temporal
- field_type_misc
-
-%type <Lex_dyncol_type> opt_dyncol_type dyncol_type
- numeric_dyncol_type temporal_dyncol_type string_dyncol_type
-
-%type <create_field> field_spec column_def
-
-%type <num>
- order_dir lock_option
- udf_type opt_local opt_no_write_to_binlog
- opt_temporary all_or_any opt_distinct opt_glimit_clause
- opt_ignore_leaves fulltext_options union_option
- opt_not
- transaction_access_mode_types
- opt_natural_language_mode opt_query_expansion
- opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
- ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
- optional_flush_tables_arguments
- opt_time_precision kill_type kill_option int_num
- opt_default_time_precision
- case_stmt_body opt_bin_mod opt_for_system_time_clause
- opt_if_exists_table_element opt_if_not_exists_table_element
- opt_recursive opt_format_xid opt_for_portion_of_time_clause
-
-%type <object_ddl_options>
- create_or_replace
- opt_if_not_exists
- opt_if_exists
-
-/*
- Bit field of MYSQL_START_TRANS_OPT_* flags.
-*/
-%type <num> opt_start_transaction_option_list
-%type <num> start_transaction_option_list
-%type <num> start_transaction_option
-
-%type <m_yes_no_unk>
- opt_chain opt_release
-
-%type <m_fk_option>
- delete_option
-
-%type <ulong_num>
- ulong_num real_ulong_num merge_insert_types
- ws_nweights
- ws_level_flag_desc ws_level_flag_reverse ws_level_flags
- opt_ws_levels ws_level_list ws_level_list_item ws_level_number
- ws_level_range ws_level_list_or_range bool
- field_options last_field_options
-
-%type <ulonglong_number>
- ulonglong_num real_ulonglong_num size_number
-
-%type <longlong_number>
- longlong_num
-
-%type <choice> choice
-
-%type <lock_type>
- replace_lock_option opt_low_priority insert_lock_option load_data_lock
- insert_replace_option
-
-%type <item>
- literal insert_ident order_ident temporal_literal
- simple_ident expr sum_expr in_sum_expr
- variable variable_aux bool_pri
- predicate bit_expr parenthesized_expr
- table_wild simple_expr column_default_non_parenthesized_expr udf_expr
- primary_expr string_factor_expr mysql_concatenation_expr
- select_sublist_qualified_asterisk
- expr_or_default set_expr_or_default
- signed_literal expr_or_literal
- opt_escape
- sp_opt_default
- simple_ident_nospvar
- field_or_var limit_option
- part_func_expr
- window_func_expr
- window_func
- simple_window_func
- inverse_distribution_function
- percentile_function
- inverse_distribution_function_def
- explicit_cursor_attr
- function_call_keyword
- function_call_keyword_timestamp
- function_call_nonkeyword
- function_call_generic
- function_call_conflict kill_expr
- signal_allowed_expr
- simple_target_specification
- condition_number
- opt_versioning_interval_start
-
-%type <item_param> param_marker
-
-%type <item_num>
- NUM_literal
-
-%type <item_basic_constant> text_literal
-
-%type <item_list>
- expr_list opt_udf_expr_list udf_expr_list when_list when_list_opt_else
- ident_list ident_list_arg opt_expr_list
- decode_when_list_oracle
- execute_using
- execute_params
-
-%type <sp_cursor_stmt>
- sp_cursor_stmt_lex
- sp_cursor_stmt
-
-%type <expr_lex>
- expr_lex
-
-%type <assignment_lex>
- assignment_source_lex
- assignment_source_expr
- for_loop_bound_expr
-
-%type <sp_assignment_lex_list>
- cursor_actual_parameters
- opt_parenthesized_cursor_actual_parameters
-
-%type <var_type>
- option_type opt_var_type opt_var_ident_type
-
-%type <key_type>
- opt_unique constraint_key_type fulltext spatial
-
-%type <key_alg>
- btree_or_rtree opt_key_algorithm_clause opt_USING_key_algorithm
-
-%type <string_list>
- using_list opt_use_partition use_partition
-
-%type <key_part>
- key_part
-
-%type <table_list>
- join_table_list join_table
- table_factor table_ref esc_table_ref
- table_primary_ident table_primary_ident_opt_parens
- table_primary_derived table_primary_derived_opt_parens
- derived_table_list table_reference_list_parens
- nested_table_reference_list join_table_parens
- update_table_list
-%type <date_time_type> date_time_type;
-%type <interval> interval
-
-%type <interval_time_st> interval_time_stamp
-
-%type <db_type> storage_engines known_storage_engines
-
-%type <row_type> row_types
-
-%type <tx_isolation> isolation_types
-
-%type <ha_rkey_mode> handler_rkey_mode
-
-%type <Lex_cast_type> cast_type cast_type_numeric cast_type_temporal
-
-%type <Lex_length_and_dec> precision opt_precision float_options
-
-%type <lex_user> user grant_user grant_role user_or_role current_role
- admin_option_for_role user_maybe_role
-
-%type <user_auth> opt_auth_str auth_expression auth_token
-
-%type <charset>
- opt_collate
- charset_name
- charset_or_alias
- charset_name_or_default
- old_or_new_charset_name
- old_or_new_charset_name_or_default
- collation_name
- collation_name_or_default
- opt_load_data_charset
- UNDERSCORE_CHARSET
-
-%type <select_lex> subselect
- query_specification
- table_value_constructor
- simple_table
- query_simple
- query_primary
- subquery
- select_into_query_specification
-
-%type <select_lex_unit>
- query_expression
- query_expression_no_with_clause
- query_expression_body_ext
- query_expression_body_ext_parens
- query_expression_body
- query_specification_start
-
-%type <boolfunc2creator> comp_op
-
-%type <dyncol_def> dyncall_create_element
-
-%type <dyncol_def_list> dyncall_create_list
-
-%type <myvar> select_outvar
-
-%type <virtual_column> opt_check_constraint check_constraint virtual_column_func
- column_default_expr
-
-%type <unit_operation> unit_type_decl
-
-%type <select_lock>
- opt_procedure_or_into
- opt_select_lock_type
- select_lock_type
- opt_lock_wait_timeout_new
-
-%type <select_limit> opt_limit_clause limit_clause limit_options
-
-%type <order_limit_lock>
- query_expression_tail
- opt_query_expression_tail
- order_or_limit
- order_limit_lock
- opt_order_limit_lock
-
-%type <select_order> opt_order_clause order_clause order_list
-
-%type <NONE>
- directly_executable_statement
- analyze_stmt_command backup backup_statements
- query verb_clause create create_routine change select select_into
- do drop drop_routine insert replace insert_start stmt_end
- insert_values update delete truncate rename compound_statement
- show describe load alter optimize keycache preload flush
- reset purge begin_stmt_mariadb commit rollback savepoint release
- slave master_def master_defs master_file_def slave_until_opts
- repair analyze opt_with_admin opt_with_admin_option
- analyze_table_list analyze_table_elem_spec
- opt_persistent_stat_clause persistent_stat_spec
- persistent_column_stat_spec persistent_index_stat_spec
- table_column_list table_index_list table_index_name
- check start checksum opt_returning
- field_list field_list_item kill key_def constraint_def
- keycache_list keycache_list_or_parts assign_to_keycache
- assign_to_keycache_parts
- preload_list preload_list_or_parts preload_keys preload_keys_parts
- select_item_list select_item values_list no_braces
- delete_limit_clause fields opt_values values
- no_braces_with_names opt_values_with_names values_with_names
- procedure_list procedure_list2 procedure_item
- field_def handler opt_generated_always
- opt_ignore opt_column opt_restrict
- grant revoke set lock unlock string_list
- opt_binary table_lock_list table_lock
- ref_list opt_match_clause opt_on_update_delete use
- opt_delete_options opt_delete_option varchar nchar nvarchar
- opt_outer table_list table_name table_alias_ref_list table_alias_ref
- attribute attribute_list
- compressed_deprecated_data_type_attribute
- compressed_deprecated_column_attribute
- column_list column_list_id
- opt_column_list grant_privileges grant_ident grant_list grant_option
- object_privilege object_privilege_list user_list user_and_role_list
- rename_list table_or_tables
- clear_privileges flush_options flush_option
- opt_flush_lock flush_lock flush_options_list
- equal optional_braces
- opt_mi_check_type opt_to mi_check_types
- table_to_table_list table_to_table opt_table_list opt_as
- handler_rkey_function handler_read_or_scan
- single_multi table_wild_list table_wild_one opt_wild
- opt_and
- select_var_list select_var_list_init help
- opt_extended_describe shutdown
- opt_format_json
- prepare execute deallocate
- statement
- sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
- opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
- view_list_opt view_list view_select
- trigger_tail event_tail
- install uninstall partition_entry binlog_base64_event
- normal_key_options normal_key_opts all_key_opt
- spatial_key_options fulltext_key_options normal_key_opt
- fulltext_key_opt spatial_key_opt fulltext_key_opts spatial_key_opts
- keep_gcc_happy
- key_using_alg
- part_column_list
- period_for_system_time
- period_for_application_time
- server_def server_options_list server_option
- definer_opt no_definer definer get_diagnostics
- parse_vcol_expr vcol_opt_specifier vcol_opt_attribute
- vcol_opt_attribute_list vcol_attribute
- opt_serial_attribute opt_serial_attribute_list serial_attribute
- explainable_command
- opt_lock_wait_timeout
- opt_delete_gtid_domain
- asrow_attribute
- opt_constraint_no_id
-
-%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
-%type <NONE> sp_if_then_statements sp_case_then_statements
-%type <NONE> sp_proc_stmt_statement sp_proc_stmt_return
-%type <NONE> sp_proc_stmt_compound_ok
-%type <NONE> sp_proc_stmt_if
-%type <NONE> sp_labeled_control sp_unlabeled_control
-%type <NONE> sp_labeled_block sp_unlabeled_block
-%type <NONE> sp_proc_stmt_continue_oracle
-%type <NONE> sp_proc_stmt_exit_oracle
-%type <NONE> sp_proc_stmt_leave
-%type <NONE> sp_proc_stmt_iterate
-%type <NONE> sp_proc_stmt_goto_oracle
-%type <NONE> sp_proc_stmt_with_cursor
-%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
-%type <NONE> case_stmt_specification
-%type <NONE> loop_body while_body repeat_body
-%type <NONE> for_loop_statements
-
-%type <num> view_algorithm view_check_option
-%type <view_suid> view_suid opt_view_suid
-
-%type <plsql_cursor_attr> plsql_cursor_attr
-%type <sp_suid> sp_suid
-%type <sp_aggregate_type> opt_aggregate
-
-%type <num> sp_decl_idents sp_decl_idents_init_vars
-%type <num> sp_handler_type sp_hcond_list
-%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
-%type <spname> sp_name
-%type <spvar> sp_param_name sp_param_name_and_type
-%type <spvar> sp_param_name_and_type_anchored
-%type <for_loop> sp_for_loop_index_and_bounds
-%type <for_loop_bounds> sp_for_loop_bounds
-%type <trim> trim_operands
-%type <num> opt_sp_for_loop_direction
-%type <spvar_mode> sp_parameter_type
-%type <index_hint> index_hint_type
-%type <num> index_hint_clause normal_join inner_join
-%type <filetype> data_or_xml
-
-%type <NONE> signal_stmt resignal_stmt raise_stmt_oracle
-%type <diag_condition_item_name> signal_condition_information_item_name
-
-%type <trg_execution_order> trigger_follows_precedes_clause;
-%type <trigger_action_order_type> trigger_action_order;
-
-%type <diag_area> which_area;
-%type <diag_info> diagnostics_information;
-%type <stmt_info_item> statement_information_item;
-%type <stmt_info_item_name> statement_information_item_name;
-%type <stmt_info_list> statement_information;
-%type <cond_info_item> condition_information_item;
-%type <cond_info_item_name> condition_information_item_name;
-%type <cond_info_list> condition_information;
-
-%type <spvar_definition> row_field_name row_field_definition
-%type <spvar_definition_list> row_field_definition_list row_type_body
-
-%type <NONE> opt_window_clause window_def_list window_def window_spec
-%type <lex_str_ptr> window_name
-%type <NONE> opt_window_ref opt_window_frame_clause
-%type <frame_units> window_frame_units;
-%type <NONE> window_frame_extent;
-%type <frame_exclusion> opt_window_frame_exclusion;
-%type <window_frame_bound> window_frame_start window_frame_bound;
-
-%type <kwd>
- '-' '+' '*' '/' '%' '(' ')'
- ',' '!' '{' '}' '&' '|'
-
-%type <with_clause> with_clause
-
-%type <lex_str_ptr> query_name
-
-%type <lex_str_list> opt_with_column_list
-
-%type <vers_range_unit> opt_history_unit
-%type <vers_history_point> history_point
-%type <vers_column_versioning> with_or_without_system
-
-/* Start of sql_mode=ORACLE specific declarations */
-%type <NONE> set_assign
-%type <spvar_mode> sp_opt_inout
-%type <NONE> sp_tail_standalone
-%type <NONE> sp_labelable_stmt
-%type <simple_string> remember_end_opt
-%type <lex_str> opt_package_routine_end_name
-%type <lex_str> label_declaration_oracle
-%type <lex_str> labels_declaration_oracle
-%type <kwd> keyword_directly_assignable
-%type <ident_sys> ident_directly_assignable
-%type <ident_cli> ident_cli_directly_assignable
-%type <spname> opt_sp_name
-%type <spblock> sp_decl_body_list
-%type <spblock> opt_sp_decl_body_list
-%type <spblock> sp_decl_variable_list
-%type <spblock> sp_decl_variable_list_anchored
-%type <spblock> sp_decl_non_handler
-%type <spblock> sp_decl_non_handler_list
-%type <spblock> sp_decl_handler
-%type <spblock> sp_decl_handler_list
-%type <spblock> opt_sp_decl_handler_list
-%type <spblock> package_implementation_routine_definition
-%type <spblock> package_implementation_item_declaration
-%type <spblock> package_implementation_declare_section
-%type <spblock> package_implementation_declare_section_list1
-%type <spblock> package_implementation_declare_section_list2
-%type <spblock_handlers> sp_block_statements_and_exceptions
-%type <spblock_handlers> package_implementation_executable_section
-%type <sp_instr_addr> sp_instr_addr
-%type <num> opt_exception_clause exception_handlers
-%type <lex> remember_lex
-%type <lex> package_routine_lex
-%type <lex> package_specification_function
-%type <lex> package_specification_procedure
-/* End of sql_mode=ORACLE specific declarations */
-
-%%
-
-
-/*
- Indentation of grammar rules:
-
-rule: <-- starts at col 1
- rule1a rule1b rule1c <-- starts at col 11
- { <-- starts at col 11
- code <-- starts at col 13, indentation is 2 spaces
- }
- | rule2a rule2b
- {
- code
- }
- ; <-- on a line by itself, starts at col 9
-
- Also, please do not use any <TAB>, but spaces.
- Having a uniform indentation in this file helps
- code reviews, patches, merges, and make maintenance easier.
- Tip: grep [[:cntrl:]] sql_yacc.yy
- Thanks.
-*/
-
-query:
- END_OF_INPUT
- {
- if (!thd->bootstrap &&
- (!(thd->lex->lex_options & OPTION_LEX_FOUND_COMMENT)))
- my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
-
- thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
- YYLIP->found_semicolon= NULL;
- }
- | directly_executable_statement
- {
- Lex_input_stream *lip = YYLIP;
-
- if ((thd->client_capabilities & CLIENT_MULTI_QUERIES) &&
- lip->multi_statements &&
- ! lip->eof())
- {
- /*
- We found a well formed query, and multi queries are allowed:
- - force the parser to stop after the ';'
- - mark the start of the next query for the next invocation
- of the parser.
- */
- lip->next_state= MY_LEX_END;
- lip->found_semicolon= lip->get_ptr();
- }
- else
- {
- /* Single query, terminated. */
- lip->found_semicolon= NULL;
- }
- }
- ';'
- opt_end_of_input
- | directly_executable_statement END_OF_INPUT
- {
- /* Single query, not terminated. */
- YYLIP->found_semicolon= NULL;
- }
- ;
-
-opt_end_of_input:
- /* empty */
- | END_OF_INPUT
- ;
-
-directly_executable_statement:
- statement
- | begin_stmt_mariadb
- | compound_statement
- ;
-
-/* Verb clauses, except begin and compound_statement */
-verb_clause:
- alter
- | analyze
- | analyze_stmt_command
- | backup
- | binlog_base64_event
- | call
- | change
- | check
- | checksum
- | commit
- | create
- | deallocate
- | delete
- | describe
- | do
- | drop
- | execute
- | flush
- | get_diagnostics
- | grant
- | handler
- | help
- | insert
- | install
- | keep_gcc_happy
- | keycache
- | kill
- | load
- | lock
- | optimize
- | parse_vcol_expr
- | partition_entry
- | preload
- | prepare
- | purge
- | raise_stmt_oracle
- | release
- | rename
- | repair
- | replace
- | reset
- | resignal_stmt
- | revoke
- | rollback
- | savepoint
- | select
- | select_into
- | set
- | signal_stmt
- | show
- | shutdown
- | slave
- | start
- | truncate
- | uninstall
- | unlock
- | update
- | use
- | xa
- ;
-
-deallocate:
- deallocate_or_drop PREPARE_SYM ident
- {
- Lex->stmt_deallocate_prepare($3);
- }
- ;
-
-deallocate_or_drop:
- DEALLOCATE_SYM
- | DROP
- ;
-
-prepare:
- PREPARE_SYM ident FROM
- { Lex->clause_that_disallows_subselect= "PREPARE..FROM"; }
- expr
- {
- Lex->clause_that_disallows_subselect= NULL;
- if (Lex->stmt_prepare($2, $5))
- MYSQL_YYABORT;
- }
- ;
-
-execute:
- EXECUTE_SYM ident execute_using
- {
- if (Lex->stmt_execute($2, $3))
- MYSQL_YYABORT;
- }
- | EXECUTE_SYM IMMEDIATE_SYM
- { Lex->clause_that_disallows_subselect= "EXECUTE IMMEDIATE"; }
- expr
- { Lex->clause_that_disallows_subselect= NULL; }
- execute_using
- {
- if (Lex->stmt_execute_immediate($4, $6))
- MYSQL_YYABORT;
- }
- ;
-
-execute_using:
- /* nothing */ { $$= NULL; }
- | USING
- { Lex->clause_that_disallows_subselect= "EXECUTE..USING"; }
- execute_params
- {
- $$= $3;
- Lex->clause_that_disallows_subselect= NULL;
- }
- ;
-
-execute_params:
- expr_or_default
- {
- if (unlikely(!($$= List<Item>::make(thd->mem_root, $1))))
- MYSQL_YYABORT;
- }
- | execute_params ',' expr_or_default
- {
- if (($$= $1)->push_back($3, thd->mem_root))
- MYSQL_YYABORT;
- }
- ;
-
-
-/* help */
-
-help:
- HELP_SYM
- {
- if (unlikely(Lex->sphead))
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HELP"));
- }
- ident_or_text
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_HELP;
- lex->help_arg= $3.str;
- }
- ;
-
-/* change master */
-
-change:
- CHANGE MASTER_SYM optional_connection_name TO_SYM
- {
- Lex->sql_command = SQLCOM_CHANGE_MASTER;
- }
- master_defs
- {}
- ;
-
-master_defs:
- master_def
- | master_defs ',' master_def
- ;
-
-master_def:
- MASTER_HOST_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.host = $3.str;
- }
- | MASTER_USER_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.user = $3.str;
- }
- | MASTER_PASSWORD_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.password = $3.str;
- }
- | MASTER_PORT_SYM '=' ulong_num
- {
- Lex->mi.port = $3;
- }
- | MASTER_CONNECT_RETRY_SYM '=' ulong_num
- {
- Lex->mi.connect_retry = $3;
- }
- | MASTER_DELAY_SYM '=' ulong_num
- {
- if ($3 > MASTER_DELAY_MAX)
- {
- my_error(ER_MASTER_DELAY_VALUE_OUT_OF_RANGE, MYF(0),
- (ulong) $3, (ulong) MASTER_DELAY_MAX);
- }
- else
- Lex->mi.sql_delay = $3;
- }
- | MASTER_SSL_SYM '=' ulong_num
- {
- Lex->mi.ssl= $3 ?
- LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE;
- }
- | MASTER_SSL_CA_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.ssl_ca= $3.str;
- }
- | MASTER_SSL_CAPATH_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.ssl_capath= $3.str;
- }
- | MASTER_SSL_CERT_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.ssl_cert= $3.str;
- }
- | MASTER_SSL_CIPHER_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.ssl_cipher= $3.str;
- }
- | MASTER_SSL_KEY_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.ssl_key= $3.str;
- }
- | MASTER_SSL_VERIFY_SERVER_CERT_SYM '=' ulong_num
- {
- Lex->mi.ssl_verify_server_cert= $3 ?
- LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE;
- }
- | MASTER_SSL_CRL_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.ssl_crl= $3.str;
- }
- | MASTER_SSL_CRLPATH_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.ssl_crlpath= $3.str;
- }
-
- | MASTER_HEARTBEAT_PERIOD_SYM '=' NUM_literal
- {
- Lex->mi.heartbeat_period= (float) $3->val_real();
- if (unlikely(Lex->mi.heartbeat_period >
- SLAVE_MAX_HEARTBEAT_PERIOD) ||
- unlikely(Lex->mi.heartbeat_period < 0.0))
- my_yyabort_error((ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0),
- SLAVE_MAX_HEARTBEAT_PERIOD));
-
- if (unlikely(Lex->mi.heartbeat_period > slave_net_timeout))
- {
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX,
- ER_THD(thd, ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX));
- }
- if (unlikely(Lex->mi.heartbeat_period < 0.001))
- {
- if (unlikely(Lex->mi.heartbeat_period != 0.0))
- {
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN,
- ER_THD(thd, ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN));
- Lex->mi.heartbeat_period= 0.0;
- }
- Lex->mi.heartbeat_opt= LEX_MASTER_INFO::LEX_MI_DISABLE;
- }
- Lex->mi.heartbeat_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
- }
- | IGNORE_SERVER_IDS_SYM '=' '(' ignore_server_id_list ')'
- {
- Lex->mi.repl_ignore_server_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
- }
- | DO_DOMAIN_IDS_SYM '=' '(' do_domain_id_list ')'
- {
- Lex->mi.repl_do_domain_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
- }
- | IGNORE_DOMAIN_IDS_SYM '=' '(' ignore_domain_id_list ')'
- {
- Lex->mi.repl_ignore_domain_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
- }
- |
- master_file_def
- ;
-
-ignore_server_id_list:
- /* Empty */
- | ignore_server_id
- | ignore_server_id_list ',' ignore_server_id
- ;
-
-ignore_server_id:
- ulong_num
- {
- insert_dynamic(&Lex->mi.repl_ignore_server_ids, (uchar*) &($1));
- }
- ;
-
-do_domain_id_list:
- /* Empty */
- | do_domain_id
- | do_domain_id_list ',' do_domain_id
- ;
-
-do_domain_id:
- ulong_num
- {
- insert_dynamic(&Lex->mi.repl_do_domain_ids, (uchar*) &($1));
- }
- ;
-
-ignore_domain_id_list:
- /* Empty */
- | ignore_domain_id
- | ignore_domain_id_list ',' ignore_domain_id
- ;
-
-ignore_domain_id:
- ulong_num
- {
- insert_dynamic(&Lex->mi.repl_ignore_domain_ids, (uchar*) &($1));
- }
- ;
-
-master_file_def:
- MASTER_LOG_FILE_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.log_file_name = $3.str;
- }
- | MASTER_LOG_POS_SYM '=' ulonglong_num
- {
- /*
- If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it
- instead of causing subsequent errors.
- We need to do it in this file, because only there we know that
- MASTER_LOG_POS has been explicitly specified. On the contrary
- in change_master() (sql_repl.cc) we cannot distinguish between 0
- (MASTER_LOG_POS explicitly specified as 0) and 0 (unspecified),
- whereas we want to distinguish (specified 0 means "read the binlog
- from 0" (4 in fact), unspecified means "don't change the position
- (keep the preceding value)").
- */
- Lex->mi.pos= MY_MAX(BIN_LOG_HEADER_SIZE, $3);
- }
- | RELAY_LOG_FILE_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.relay_log_name = $3.str;
- }
- | RELAY_LOG_POS_SYM '=' ulong_num
- {
- Lex->mi.relay_log_pos = $3;
- /* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
- Lex->mi.relay_log_pos= MY_MAX(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
- }
- | MASTER_USE_GTID_SYM '=' CURRENT_POS_SYM
- {
- if (unlikely(Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
- Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_CURRENT_POS;
- }
- | MASTER_USE_GTID_SYM '=' SLAVE_POS_SYM
- {
- if (unlikely(Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
- Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_SLAVE_POS;
- }
- | MASTER_USE_GTID_SYM '=' NO_SYM
- {
- if (unlikely(Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
- Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_NO;
- }
- ;
-
-optional_connection_name:
- /* empty */
- {
- LEX *lex= thd->lex;
- lex->mi.connection_name= null_clex_str;
- }
- | connection_name
- ;
-
-connection_name:
- TEXT_STRING_sys
- {
- Lex->mi.connection_name= $1;
-#ifdef HAVE_REPLICATION
- if (unlikely(check_master_connection_name(&$1)))
- my_yyabort_error((ER_WRONG_ARGUMENTS, MYF(0), "MASTER_CONNECTION_NAME"));
-#endif
- }
- ;
-
-/* create a table */
-
-create:
- create_or_replace opt_temporary TABLE_SYM opt_if_not_exists
- {
- LEX *lex= thd->lex;
- if (!(lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_create_table()))
- MYSQL_YYABORT;
- lex->create_info.init();
- if (lex->main_select_push())
- MYSQL_YYABORT;
- lex->current_select->parsing_place= BEFORE_OPT_LIST;
- if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
- MYSQL_YYABORT;
- }
- table_ident
- {
- LEX *lex= thd->lex;
- if (!lex->first_select_lex()->
- add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING,
- TL_WRITE, MDL_SHARED_UPGRADABLE))
- MYSQL_YYABORT;
- lex->alter_info.reset();
- /*
- For CREATE TABLE we should not open the table even if it exists.
- If the table exists, we should either not create it or replace it
- */
- lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
- lex->create_info.default_table_charset= NULL;
- lex->name= null_clex_str;
- lex->create_last_non_select_table= lex->last_table();
- }
- create_body
- {
- LEX *lex= thd->lex;
- create_table_set_open_action_and_adjust_tables(lex);
- Lex->pop_select(); //main select
- }
- | create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists table_ident
- {
- LEX *lex= thd->lex;
- if (lex->main_select_push())
- MYSQL_YYABORT;
- if (!(lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_create_sequence()))
- MYSQL_YYABORT;
- lex->create_info.init();
- if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2,
- $1 | $4)))
- MYSQL_YYABORT;
-
- if (!lex->first_select_lex()->
- add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING,
- TL_WRITE, MDL_EXCLUSIVE))
- MYSQL_YYABORT;
-
- /*
- For CREATE TABLE, an non-existing table is not an error.
- Instruct open_tables() to just take an MDL lock if the
- table does not exist.
- */
- lex->alter_info.reset();
- lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
- lex->name= null_clex_str;
- lex->create_last_non_select_table= lex->last_table();
- if (unlikely(!(lex->create_info.seq_create_info=
- new (thd->mem_root) sequence_definition())))
- MYSQL_YYABORT;
- }
- opt_sequence opt_create_table_options
- {
- LEX *lex= thd->lex;
-
- if (unlikely(lex->create_info.seq_create_info->check_and_adjust(1)))
- {
- my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
- lex->first_select_lex()->table_list.first->db.str,
- lex->first_select_lex()->table_list.first->
- table_name.str);
- MYSQL_YYABORT;
- }
-
- /* No fields specified, generate them */
- if (unlikely(prepare_sequence_fields(thd,
- &lex->alter_info.create_list)))
- MYSQL_YYABORT;
-
- /* CREATE SEQUENCE always creates a sequence */
- Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
- Lex->create_info.sequence= 1;
-
- create_table_set_open_action_and_adjust_tables(lex);
- Lex->pop_select(); //main select
- }
- | create_or_replace opt_unique INDEX_SYM opt_if_not_exists
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- ident
- opt_key_algorithm_clause
- ON table_ident
- {
- if (Lex->add_create_index_prepare($9))
- MYSQL_YYABORT;
- if (Lex->add_create_index($2, &$6, $7, $1 | $4))
- MYSQL_YYABORT;
- }
- '(' key_list ')' opt_lock_wait_timeout normal_key_options
- opt_index_lock_algorithm
- {
- Lex->pop_select(); //main select
- }
- | create_or_replace fulltext INDEX_SYM
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- opt_if_not_exists ident
- ON table_ident
- {
- if (Lex->add_create_index_prepare($8))
- MYSQL_YYABORT;
- if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
- MYSQL_YYABORT;
- }
- '(' key_list ')' opt_lock_wait_timeout fulltext_key_options
- opt_index_lock_algorithm
- {
- Lex->pop_select(); //main select
- }
- | create_or_replace spatial INDEX_SYM
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- opt_if_not_exists ident
- ON table_ident
- {
- if (Lex->add_create_index_prepare($8))
- MYSQL_YYABORT;
- if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
- MYSQL_YYABORT;
- }
- '(' key_list ')' opt_lock_wait_timeout spatial_key_options
- opt_index_lock_algorithm
- {
- Lex->pop_select(); //main select
- }
- | create_or_replace DATABASE opt_if_not_exists ident
- {
- Lex->create_info.default_table_charset= NULL;
- Lex->create_info.schema_comment= NULL;
- Lex->create_info.used_fields= 0;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- opt_create_database_options
- {
- LEX *lex=Lex;
- if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_DB, 0,
- $1 | $3)))
- MYSQL_YYABORT;
- lex->name= $4;
- Lex->pop_select(); //main select
- }
- | create_or_replace definer_opt opt_view_suid VIEW_SYM
- opt_if_not_exists table_ident
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- if (Lex->add_create_view(thd, $1 | $5,
- DTYPE_ALGORITHM_UNDEFINED, $3, $6))
- MYSQL_YYABORT;
- }
- view_list_opt AS view_select
- {
- Lex->pop_select(); //main select
- }
- | create_or_replace view_algorithm definer_opt opt_view_suid VIEW_SYM
- opt_if_not_exists table_ident
- {
- if (unlikely(Lex->add_create_view(thd, $1 | $6, $2, $4, $7)))
- MYSQL_YYABORT;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- view_list_opt AS view_select
- {
- Lex->pop_select(); //main select
- }
- | create_or_replace definer_opt TRIGGER_SYM
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- Lex->create_info.set($1);
- }
- trigger_tail
- {
- Lex->pop_select(); //main select
- }
- | create_or_replace definer_opt EVENT_SYM
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- Lex->create_info.set($1);
- }
- event_tail
- {
- Lex->pop_select(); //main select
- }
- | create_or_replace USER_SYM opt_if_not_exists clear_privileges
- grant_list opt_require_clause opt_resource_options opt_account_locking opt_password_expiration
- {
- if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER,
- $1 | $3)))
- MYSQL_YYABORT;
- }
- | create_or_replace ROLE_SYM opt_if_not_exists
- clear_privileges role_list opt_with_admin
- {
- if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_ROLE,
- $1 | $3)))
- MYSQL_YYABORT;
- }
- | CREATE LOGFILE_SYM GROUP_SYM logfile_group_info
- {
- Lex->alter_tablespace_info->ts_cmd_type= CREATE_LOGFILE_GROUP;
- }
- | CREATE TABLESPACE tablespace_info
- {
- Lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE;
- }
- | create_or_replace { Lex->set_command(SQLCOM_CREATE_SERVER, $1); }
- server_def
- { }
- | create_routine
- ;
-
-opt_sequence:
- /* empty */ { }
- | sequence_defs
- ;
-
-sequence_defs:
- sequence_def
- | sequence_defs sequence_def
- ;
-
-sequence_def:
- MINVALUE_SYM opt_equal longlong_num
- {
- Lex->create_info.seq_create_info->min_value= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
- }
- | NO_SYM MINVALUE_SYM
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
- }
- | NOMINVALUE_SYM
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
- }
- | MAXVALUE_SYM opt_equal longlong_num
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_max_value))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
- Lex->create_info.seq_create_info->max_value= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
- }
- | NO_SYM MAXVALUE_SYM
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
- }
- | NOMAXVALUE_SYM
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
- }
- | START_SYM opt_with longlong_num
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_start))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "START"));
- Lex->create_info.seq_create_info->start= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_start;
- }
- | INCREMENT_SYM opt_by longlong_num
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_increment))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "INCREMENT"));
- Lex->create_info.seq_create_info->increment= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_increment;
- }
- | CACHE_SYM opt_equal longlong_num
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_cache))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CACHE"));
- Lex->create_info.seq_create_info->cache= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
- }
- | NOCACHE_SYM
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_cache))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CACHE"));
- Lex->create_info.seq_create_info->cache= 0;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
- }
- | CYCLE_SYM
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_cycle))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CYCLE"));
- Lex->create_info.seq_create_info->cycle= 1;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
- }
- | NOCYCLE_SYM
- {
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_cycle))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CYCLE"));
- Lex->create_info.seq_create_info->cycle= 0;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
- }
- | RESTART_SYM
- {
- if (unlikely(Lex->sql_command != SQLCOM_ALTER_SEQUENCE))
- {
- thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
- YYABORT;
- }
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_restart))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "RESTART"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart;
- }
- | RESTART_SYM opt_with longlong_num
- {
- if (unlikely(Lex->sql_command != SQLCOM_ALTER_SEQUENCE))
- {
- thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
- YYABORT;
- }
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_restart))
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "RESTART"));
- Lex->create_info.seq_create_info->restart= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart | seq_field_used_restart_value;
- }
- ;
-
-server_def:
- SERVER_SYM opt_if_not_exists ident_or_text
- {
- if (unlikely(Lex->add_create_options_with_check($2)))
- MYSQL_YYABORT;
- Lex->server_options.reset($3);
- }
- FOREIGN DATA_SYM WRAPPER_SYM ident_or_text
- OPTIONS_SYM '(' server_options_list ')'
- { Lex->server_options.scheme= $8; }
- ;
-
-server_options_list:
- server_option
- | server_options_list ',' server_option
- ;
-
-server_option:
- USER_SYM TEXT_STRING_sys
- {
- MYSQL_YYABORT_UNLESS(Lex->server_options.username.str == 0);
- Lex->server_options.username= $2;
- }
- | HOST_SYM TEXT_STRING_sys
- {
- MYSQL_YYABORT_UNLESS(Lex->server_options.host.str == 0);
- Lex->server_options.host= $2;
- }
- | DATABASE TEXT_STRING_sys
- {
- MYSQL_YYABORT_UNLESS(Lex->server_options.db.str == 0);
- Lex->server_options.db= $2;
- }
- | OWNER_SYM TEXT_STRING_sys
- {
- MYSQL_YYABORT_UNLESS(Lex->server_options.owner.str == 0);
- Lex->server_options.owner= $2;
- }
- | PASSWORD_SYM TEXT_STRING_sys
- {
- MYSQL_YYABORT_UNLESS(Lex->server_options.password.str == 0);
- Lex->server_options.password= $2;
- }
- | SOCKET_SYM TEXT_STRING_sys
- {
- MYSQL_YYABORT_UNLESS(Lex->server_options.socket.str == 0);
- Lex->server_options.socket= $2;
- }
- | PORT_SYM ulong_num
- {
- Lex->server_options.port= $2;
- }
- ;
-
-event_tail:
- remember_name opt_if_not_exists sp_name
- {
- LEX *lex=Lex;
-
- lex->stmt_definition_begin= $1;
- if (unlikely(lex->add_create_options_with_check($2)))
- MYSQL_YYABORT;
- if (unlikely(!(lex->event_parse_data=
- Event_parse_data::new_instance(thd))))
- MYSQL_YYABORT;
- lex->event_parse_data->identifier= $3;
- lex->event_parse_data->on_completion=
- Event_parse_data::ON_COMPLETION_DROP;
-
- lex->sql_command= SQLCOM_CREATE_EVENT;
- /* We need that for disallowing subqueries */
- }
- ON SCHEDULE_SYM ev_schedule_time
- opt_ev_on_completion
- opt_ev_status
- opt_ev_comment
- DO_SYM ev_sql_stmt
- {
- /*
- sql_command is set here because some rules in ev_sql_stmt
- can overwrite it
- */
- Lex->sql_command= SQLCOM_CREATE_EVENT;
- }
- ;
-
-ev_schedule_time:
- EVERY_SYM expr interval
- {
- Lex->event_parse_data->item_expression= $2;
- Lex->event_parse_data->interval= $3;
- }
- ev_starts
- ev_ends
- | AT_SYM expr
- {
- Lex->event_parse_data->item_execute_at= $2;
- }
- ;
-
-opt_ev_status:
- /* empty */ { $$= 0; }
- | ENABLE_SYM
- {
- Lex->event_parse_data->status= Event_parse_data::ENABLED;
- Lex->event_parse_data->status_changed= true;
- $$= 1;
- }
- | DISABLE_SYM ON SLAVE
- {
- Lex->event_parse_data->status= Event_parse_data::SLAVESIDE_DISABLED;
- Lex->event_parse_data->status_changed= true;
- $$= 1;
- }
- | DISABLE_SYM
- {
- Lex->event_parse_data->status= Event_parse_data::DISABLED;
- Lex->event_parse_data->status_changed= true;
- $$= 1;
- }
- ;
-
-ev_starts:
- /* empty */
- {
- Item *item= new (thd->mem_root) Item_func_now_local(thd, 0);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- Lex->event_parse_data->item_starts= item;
- }
- | STARTS_SYM expr
- {
- Lex->event_parse_data->item_starts= $2;
- }
- ;
-
-ev_ends:
- /* empty */
- | ENDS_SYM expr
- {
- Lex->event_parse_data->item_ends= $2;
- }
- ;
-
-opt_ev_on_completion:
- /* empty */ { $$= 0; }
- | ev_on_completion
- ;
-
-ev_on_completion:
- ON COMPLETION_SYM opt_not PRESERVE_SYM
- {
- Lex->event_parse_data->on_completion= $3
- ? Event_parse_data::ON_COMPLETION_DROP
- : Event_parse_data::ON_COMPLETION_PRESERVE;
- $$= 1;
- }
- ;
-
-opt_ev_comment:
- /* empty */ { $$= 0; }
- | COMMENT_SYM TEXT_STRING_sys
- {
- Lex->comment= Lex->event_parse_data->comment= $2;
- $$= 1;
- }
- ;
-
-ev_sql_stmt:
- {
- LEX *lex= thd->lex;
- Lex_input_stream *lip= YYLIP;
-
- /*
- This stops the following :
- - CREATE EVENT ... DO CREATE EVENT ...;
- - ALTER EVENT ... DO CREATE EVENT ...;
- - CREATE EVENT ... DO ALTER EVENT DO ....;
- - CREATE PROCEDURE ... BEGIN CREATE EVENT ... END|
- This allows:
- - CREATE EVENT ... DO DROP EVENT yyy;
- - CREATE EVENT ... DO ALTER EVENT yyy;
- (the nested ALTER EVENT can have anything but DO clause)
- - ALTER EVENT ... DO ALTER EVENT yyy;
- (the nested ALTER EVENT can have anything but DO clause)
- - ALTER EVENT ... DO DROP EVENT yyy;
- - CREATE PROCEDURE ... BEGIN ALTER EVENT ... END|
- (the nested ALTER EVENT can have anything but DO clause)
- - CREATE PROCEDURE ... BEGIN DROP EVENT ... END|
- */
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0)));
-
- if (unlikely(!lex->make_sp_head(thd,
- lex->event_parse_data->identifier,
- &sp_handler_procedure,
- DEFAULT_AGGREGATE)))
- MYSQL_YYABORT;
-
- lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
- }
- sp_proc_stmt
- {
- /* return back to the original memory root ASAP */
- if (Lex->sp_body_finalize_event(thd))
- MYSQL_YYABORT;
- }
- ;
-
-clear_privileges:
- /* Nothing */
- {
- LEX *lex=Lex;
- lex->users_list.empty();
- lex->columns.empty();
- lex->grant= lex->grant_tot_col= 0;
- lex->all_privileges= 0;
- lex->first_select_lex()->db= null_clex_str;
- lex->account_options.reset();
- }
- ;
-
-opt_aggregate:
- /* Empty */ { $$= NOT_AGGREGATE; }
- | AGGREGATE_SYM { $$= GROUP_AGGREGATE; }
- ;
-
-sp_name:
- ident '.' ident
- {
- if (unlikely(!($$= Lex->make_sp_name(thd, &$1, &$3))))
- MYSQL_YYABORT;
- }
- | ident
- {
- if (unlikely(!($$= Lex->make_sp_name(thd, &$1))))
- MYSQL_YYABORT;
- }
- ;
-
-sp_a_chistics:
- /* Empty */ {}
- | sp_a_chistics sp_chistic {}
- ;
-
-sp_c_chistics:
- /* Empty */ {}
- | sp_c_chistics sp_c_chistic {}
- ;
-
-/* Characteristics for both create and alter */
-sp_chistic:
- COMMENT_SYM TEXT_STRING_sys
- { Lex->sp_chistics.comment= $2; }
- | LANGUAGE_SYM SQL_SYM
- { /* Just parse it, we only have one language for now. */ }
- | NO_SYM SQL_SYM
- { Lex->sp_chistics.daccess= SP_NO_SQL; }
- | CONTAINS_SYM SQL_SYM
- { Lex->sp_chistics.daccess= SP_CONTAINS_SQL; }
- | READS_SYM SQL_SYM DATA_SYM
- { Lex->sp_chistics.daccess= SP_READS_SQL_DATA; }
- | MODIFIES_SYM SQL_SYM DATA_SYM
- { Lex->sp_chistics.daccess= SP_MODIFIES_SQL_DATA; }
- | sp_suid
- { Lex->sp_chistics.suid= $1; }
- ;
-
-/* Create characteristics */
-sp_c_chistic:
- sp_chistic { }
- | opt_not DETERMINISTIC_SYM { Lex->sp_chistics.detistic= ! $1; }
- ;
-
-sp_suid:
- SQL_SYM SECURITY_SYM DEFINER_SYM { $$= SP_IS_SUID; }
- | SQL_SYM SECURITY_SYM INVOKER_SYM { $$= SP_IS_NOT_SUID; }
- ;
-
-call:
- CALL_SYM sp_name
- {
- if (unlikely(Lex->call_statement_start(thd, $2)))
- MYSQL_YYABORT;
- }
- opt_sp_cparam_list {}
- ;
-
-/* CALL parameters */
-opt_sp_cparam_list:
- /* Empty */
- | '(' opt_sp_cparams ')'
- ;
-
-opt_sp_cparams:
- /* Empty */
- | sp_cparams
- ;
-
-sp_cparams:
- sp_cparams ',' expr
- {
- Lex->value_list.push_back($3, thd->mem_root);
- }
- | expr
- {
- Lex->value_list.push_back($1, thd->mem_root);
- }
- ;
-
-/* Stored FUNCTION parameter declaration list */
-sp_fdparam_list:
- /* Empty */
- {
- Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start();
- Lex->sphead->m_param_end= Lex->sphead->m_param_begin;
- }
- |
- {
- Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start();
- }
- sp_fdparams
- {
- Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
- }
- ;
-
-sp_fdparams:
- sp_fdparams ',' sp_param_name_and_type
- | sp_param_name_and_type
- ;
-
-sp_param_name:
- ident
- {
- if (unlikely(!($$= Lex->sp_param_init(&$1))))
- MYSQL_YYABORT;
- }
- ;
-
-sp_param_name_and_type:
- sp_param_name type_with_opt_collate
- {
- if (unlikely(Lex->sp_param_fill_definition($$= $1, $2)))
- MYSQL_YYABORT;
- }
- | sp_param_name ROW_SYM row_type_body
- {
- if (unlikely(Lex->sphead->spvar_fill_row(thd, $$= $1, $3)))
- MYSQL_YYABORT;
- }
- | sp_param_name_and_type_anchored
- ;
-
-/* Stored PROCEDURE parameter declaration list */
-sp_pdparam_list:
- /* Empty */
- | sp_pdparams
- ;
-
-sp_pdparams:
- sp_pdparams ',' sp_pdparam
- | sp_pdparam
- ;
-
-sp_parameter_type:
- IN_SYM { $$= sp_variable::MODE_IN; }
- | OUT_SYM { $$= sp_variable::MODE_OUT; }
- | INOUT_SYM { $$= sp_variable::MODE_INOUT; }
- ;
-
-sp_parenthesized_pdparam_list:
- '('
- {
- Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start() + 1;
- }
- sp_pdparam_list
- ')'
- {
- Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
- }
- ;
-
-sp_parenthesized_fdparam_list:
- '(' sp_fdparam_list ')'
- ;
-
-sp_proc_stmts:
- /* Empty */ {}
- | sp_proc_stmts sp_proc_stmt ';'
- ;
-
-sp_proc_stmts1:
- sp_proc_stmt ';' {}
- | sp_proc_stmts1 sp_proc_stmt ';'
- ;
-
-
-optionally_qualified_column_ident:
- sp_decl_ident
- {
- if (unlikely(!($$= new (thd->mem_root)
- Qualified_column_ident(&$1))))
- MYSQL_YYABORT;
- }
- | sp_decl_ident '.' ident
- {
- if (unlikely(!($$= new (thd->mem_root)
- Qualified_column_ident(&$1, &$3))))
- MYSQL_YYABORT;
- }
- | sp_decl_ident '.' ident '.' ident
- {
- if (unlikely(!($$= new (thd->mem_root)
- Qualified_column_ident(thd, &$1, &$3, &$5))))
- MYSQL_YYABORT;
- }
- ;
-
-
-row_field_definition:
- row_field_name type_with_opt_collate
- {
- Lex->last_field->set_attributes(thd, $2, Lex->charset,
- COLUMN_DEFINITION_ROUTINE_LOCAL);
- }
- ;
-
-row_field_definition_list:
- row_field_definition
- {
- if (!($$= Row_definition_list::make(thd->mem_root, $1)))
- MYSQL_YYABORT;
- }
- | row_field_definition_list ',' row_field_definition
- {
- if (($$= $1)->append_uniq(thd->mem_root, $3))
- MYSQL_YYABORT;
- }
- ;
-
-row_type_body:
- '(' row_field_definition_list ')' { $$= $2; }
- ;
-
-sp_decl_idents_init_vars:
- sp_decl_idents
- {
- Lex->sp_variable_declarations_init(thd, $1);
- }
- ;
-
-sp_decl_variable_list:
- sp_decl_idents_init_vars
- type_with_opt_collate
- {
- Lex->last_field->set_attributes(thd, $2, Lex->charset,
- COLUMN_DEFINITION_ROUTINE_LOCAL);
- }
- sp_opt_default
- {
- if (unlikely(Lex->sp_variable_declarations_finalize(thd, $1,
- &Lex->last_field[0],
- $4)))
- MYSQL_YYABORT;
- $$.init_using_vars($1);
- }
- | sp_decl_idents_init_vars
- ROW_SYM row_type_body
- sp_opt_default
- {
- if (unlikely(Lex->sp_variable_declarations_row_finalize(thd, $1, $3, $4)))
- MYSQL_YYABORT;
- $$.init_using_vars($1);
- }
- | sp_decl_variable_list_anchored
- ;
-
-sp_decl_handler:
- sp_handler_type HANDLER_SYM FOR_SYM
- {
- if (unlikely(Lex->sp_handler_declaration_init(thd, $1)))
- MYSQL_YYABORT;
- }
- sp_hcond_list sp_proc_stmt
- {
- if (unlikely(Lex->sp_handler_declaration_finalize(thd, $1)))
- MYSQL_YYABORT;
- $$.vars= $$.conds= $$.curs= 0;
- $$.hndlrs= 1;
- }
- ;
-
-opt_parenthesized_cursor_formal_parameters:
- /* Empty */
- | '(' sp_fdparams ')'
- ;
-
-
-sp_cursor_stmt_lex:
- {
- DBUG_ASSERT(thd->lex->sphead);
- if (unlikely(!($$= new (thd->mem_root)
- sp_lex_cursor(thd, thd->lex))))
- MYSQL_YYABORT;
- }
- ;
-
-sp_cursor_stmt:
- sp_cursor_stmt_lex
- {
- DBUG_ASSERT(thd->free_list == NULL);
- Lex->sphead->reset_lex(thd, $1);
- }
- select
- {
- DBUG_ASSERT(Lex == $1);
- if (unlikely($1->stmt_finalize(thd)) ||
- unlikely($1->sphead->restore_lex(thd)))
- MYSQL_YYABORT;
- $$= $1;
- }
- ;
-
-sp_handler_type:
- EXIT_MARIADB_SYM { $$= sp_handler::EXIT; }
- | CONTINUE_MARIADB_SYM { $$= sp_handler::CONTINUE; }
- | EXIT_ORACLE_SYM { $$= sp_handler::EXIT; }
- | CONTINUE_ORACLE_SYM { $$= sp_handler::CONTINUE; }
- /*| UNDO_SYM { QQ No yet } */
- ;
-
-sp_hcond_list:
- sp_hcond_element
- { $$= 1; }
- | sp_hcond_list ',' sp_hcond_element
- { $$+= 1; }
- ;
-
-sp_hcond_element:
- sp_hcond
- {
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- sp_pcontext *ctx= lex->spcont->parent_context();
-
- if (unlikely(ctx->check_duplicate_handler($1)))
- my_yyabort_error((ER_SP_DUP_HANDLER, MYF(0)));
-
- sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction();
- i->add_condition($1);
- }
- ;
-
-sp_cond:
- ulong_num
- { /* mysql errno */
- if (unlikely($1 == 0))
- my_yyabort_error((ER_WRONG_VALUE, MYF(0), "CONDITION", "0"));
- $$= new (thd->mem_root) sp_condition_value($1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | sqlstate
- ;
-
-sqlstate:
- SQLSTATE_SYM opt_value TEXT_STRING_literal
- { /* SQLSTATE */
-
- /*
- An error is triggered:
- - if the specified string is not a valid SQLSTATE,
- - or if it represents the completion condition -- it is not
- allowed to SIGNAL, or declare a handler for the completion
- condition.
- */
- if (unlikely(!is_sqlstate_valid(&$3) ||
- is_sqlstate_completion($3.str)))
- my_yyabort_error((ER_SP_BAD_SQLSTATE, MYF(0), $3.str));
- $$= new (thd->mem_root) sp_condition_value($3.str);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_value:
- /* Empty */ {}
- | VALUE_SYM {}
- ;
-
-sp_hcond:
- sp_cond
- {
- $$= $1;
- }
- | ident /* CONDITION name */
- {
- $$= Lex->spcont->find_declared_or_predefined_condition(thd, &$1);
- if (unlikely($$ == NULL))
- my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
- }
- | SQLWARNING_SYM /* SQLSTATEs 01??? */
- {
- $$= new (thd->mem_root) sp_condition_value(sp_condition_value::WARNING);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | not FOUND_SYM /* SQLSTATEs 02??? */
- {
- $$= new (thd->mem_root) sp_condition_value(sp_condition_value::NOT_FOUND);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | SQLEXCEPTION_SYM /* All other SQLSTATEs */
- {
- $$= new (thd->mem_root) sp_condition_value(sp_condition_value::EXCEPTION);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | OTHERS_ORACLE_SYM /* All other SQLSTATEs */
- {
- $$= new (thd->mem_root) sp_condition_value(sp_condition_value::EXCEPTION);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-
-raise_stmt_oracle:
- RAISE_ORACLE_SYM opt_set_signal_information
- {
- if (unlikely(Lex->add_resignal_statement(thd, NULL)))
- MYSQL_YYABORT;
- }
- | RAISE_ORACLE_SYM signal_value opt_set_signal_information
- {
- if (unlikely(Lex->add_signal_statement(thd, $2)))
- MYSQL_YYABORT;
- }
- ;
-
-signal_stmt:
- SIGNAL_SYM signal_value opt_set_signal_information
- {
- if (Lex->add_signal_statement(thd, $2))
- MYSQL_YYABORT;
- }
- ;
-
-signal_value:
- ident
- {
- if (!($$= Lex->stmt_signal_value($1)))
- MYSQL_YYABORT;
- }
- | sqlstate
- { $$= $1; }
- ;
-
-opt_signal_value:
- /* empty */
- { $$= NULL; }
- | signal_value
- { $$= $1; }
- ;
-
-opt_set_signal_information:
- /* empty */
- {
- thd->m_parser_state->m_yacc.m_set_signal_info.clear();
- }
- | SET signal_information_item_list
- ;
-
-signal_information_item_list:
- signal_condition_information_item_name '=' signal_allowed_expr
- {
- Set_signal_information *info;
- info= &thd->m_parser_state->m_yacc.m_set_signal_info;
- int index= (int) $1;
- info->clear();
- info->m_item[index]= $3;
- }
- | signal_information_item_list ','
- signal_condition_information_item_name '=' signal_allowed_expr
- {
- Set_signal_information *info;
- info= &thd->m_parser_state->m_yacc.m_set_signal_info;
- int index= (int) $3;
- if (unlikely(info->m_item[index] != NULL))
- my_yyabort_error((ER_DUP_SIGNAL_SET, MYF(0),
- Diag_condition_item_names[index].str));
- info->m_item[index]= $5;
- }
- ;
-
-/*
- Only a limited subset of <expr> are allowed in SIGNAL/RESIGNAL.
-*/
-signal_allowed_expr:
- literal
- { $$= $1; }
- | variable
- {
- if ($1->type() == Item::FUNC_ITEM)
- {
- Item_func *item= (Item_func*) $1;
- if (unlikely(item->functype() == Item_func::SUSERVAR_FUNC))
- {
- /*
- Don't allow the following syntax:
- SIGNAL/RESIGNAL ...
- SET <signal condition item name> = @foo := expr
- */
- thd->parse_error();
- MYSQL_YYABORT;
- }
- }
- $$= $1;
- }
- | simple_ident
- { $$= $1; }
- ;
-
-/* conditions that can be set in signal / resignal */
-signal_condition_information_item_name:
- CLASS_ORIGIN_SYM
- { $$= DIAG_CLASS_ORIGIN; }
- | SUBCLASS_ORIGIN_SYM
- { $$= DIAG_SUBCLASS_ORIGIN; }
- | CONSTRAINT_CATALOG_SYM
- { $$= DIAG_CONSTRAINT_CATALOG; }
- | CONSTRAINT_SCHEMA_SYM
- { $$= DIAG_CONSTRAINT_SCHEMA; }
- | CONSTRAINT_NAME_SYM
- { $$= DIAG_CONSTRAINT_NAME; }
- | CATALOG_NAME_SYM
- { $$= DIAG_CATALOG_NAME; }
- | SCHEMA_NAME_SYM
- { $$= DIAG_SCHEMA_NAME; }
- | TABLE_NAME_SYM
- { $$= DIAG_TABLE_NAME; }
- | COLUMN_NAME_SYM
- { $$= DIAG_COLUMN_NAME; }
- | CURSOR_NAME_SYM
- { $$= DIAG_CURSOR_NAME; }
- | MESSAGE_TEXT_SYM
- { $$= DIAG_MESSAGE_TEXT; }
- | MYSQL_ERRNO_SYM
- { $$= DIAG_MYSQL_ERRNO; }
- ;
-
-resignal_stmt:
- RESIGNAL_SYM opt_signal_value opt_set_signal_information
- {
- if (unlikely(Lex->add_resignal_statement(thd, $2)))
- MYSQL_YYABORT;
- }
- ;
-
-get_diagnostics:
- GET_SYM which_area DIAGNOSTICS_SYM diagnostics_information
- {
- Diagnostics_information *info= $4;
-
- info->set_which_da($2);
-
- Lex->sql_command= SQLCOM_GET_DIAGNOSTICS;
- Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_get_diagnostics(info);
-
- if (unlikely(Lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-which_area:
- /* If <which area> is not specified, then CURRENT is implicit. */
- { $$= Diagnostics_information::CURRENT_AREA; }
- | CURRENT_SYM
- { $$= Diagnostics_information::CURRENT_AREA; }
- ;
-
-diagnostics_information:
- statement_information
- {
- $$= new (thd->mem_root) Statement_information($1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | CONDITION_SYM condition_number condition_information
- {
- $$= new (thd->mem_root) Condition_information($2, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-statement_information:
- statement_information_item
- {
- $$= new (thd->mem_root) List<Statement_information_item>;
- if (unlikely($$ == NULL) ||
- unlikely($$->push_back($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | statement_information ',' statement_information_item
- {
- if (unlikely($1->push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- $$= $1;
- }
- ;
-
-statement_information_item:
- simple_target_specification '=' statement_information_item_name
- {
- $$= new (thd->mem_root) Statement_information_item($3, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-simple_target_specification:
- ident_cli
- {
- if (unlikely(!($$= thd->lex->create_item_for_sp_var(&$1, NULL))))
- MYSQL_YYABORT;
- }
- | '@' ident_or_text
- {
- $$= new (thd->mem_root) Item_func_get_user_var(thd, &$2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-statement_information_item_name:
- NUMBER_MARIADB_SYM
- { $$= Statement_information_item::NUMBER; }
- | NUMBER_ORACLE_SYM
- { $$= Statement_information_item::NUMBER; }
- | ROW_COUNT_SYM
- { $$= Statement_information_item::ROW_COUNT; }
- ;
-
-/*
- Only a limited subset of <expr> are allowed in GET DIAGNOSTICS
- <condition number>, same subset as for SIGNAL/RESIGNAL.
-*/
-condition_number:
- signal_allowed_expr
- { $$= $1; }
- ;
-
-condition_information:
- condition_information_item
- {
- $$= new (thd->mem_root) List<Condition_information_item>;
- if (unlikely($$ == NULL) ||
- unlikely($$->push_back($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | condition_information ',' condition_information_item
- {
- if (unlikely($1->push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- $$= $1;
- }
- ;
-
-condition_information_item:
- simple_target_specification '=' condition_information_item_name
- {
- $$= new (thd->mem_root) Condition_information_item($3, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-condition_information_item_name:
- CLASS_ORIGIN_SYM
- { $$= Condition_information_item::CLASS_ORIGIN; }
- | SUBCLASS_ORIGIN_SYM
- { $$= Condition_information_item::SUBCLASS_ORIGIN; }
- | CONSTRAINT_CATALOG_SYM
- { $$= Condition_information_item::CONSTRAINT_CATALOG; }
- | CONSTRAINT_SCHEMA_SYM
- { $$= Condition_information_item::CONSTRAINT_SCHEMA; }
- | CONSTRAINT_NAME_SYM
- { $$= Condition_information_item::CONSTRAINT_NAME; }
- | CATALOG_NAME_SYM
- { $$= Condition_information_item::CATALOG_NAME; }
- | SCHEMA_NAME_SYM
- { $$= Condition_information_item::SCHEMA_NAME; }
- | TABLE_NAME_SYM
- { $$= Condition_information_item::TABLE_NAME; }
- | COLUMN_NAME_SYM
- { $$= Condition_information_item::COLUMN_NAME; }
- | CURSOR_NAME_SYM
- { $$= Condition_information_item::CURSOR_NAME; }
- | MESSAGE_TEXT_SYM
- { $$= Condition_information_item::MESSAGE_TEXT; }
- | MYSQL_ERRNO_SYM
- { $$= Condition_information_item::MYSQL_ERRNO; }
- | RETURNED_SQLSTATE_SYM
- { $$= Condition_information_item::RETURNED_SQLSTATE; }
- ;
-
-sp_decl_ident:
- IDENT_sys
- | keyword_sp_decl
- {
- if (unlikely($$.copy_ident_cli(thd, &$1)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_decl_idents:
- sp_decl_ident
- {
- /* NOTE: field definition is filled in sp_decl section. */
-
- LEX *lex= Lex;
- sp_pcontext *spc= lex->spcont;
-
- if (unlikely(spc->find_variable(&$1, TRUE)))
- my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $1.str));
- spc->add_variable(thd, &$1);
- $$= 1;
- }
- | sp_decl_idents ',' ident
- {
- /* NOTE: field definition is filled in sp_decl section. */
-
- LEX *lex= Lex;
- sp_pcontext *spc= lex->spcont;
-
- if (unlikely(spc->find_variable(&$3, TRUE)))
- my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $3.str));
- spc->add_variable(thd, &$3);
- $$= $1 + 1;
- }
- ;
-
-sp_proc_stmt_if:
- IF_SYM
- {
- if (unlikely(Lex->maybe_start_compound_statement(thd)))
- MYSQL_YYABORT;
- Lex->sphead->new_cont_backpatch(NULL);
- }
- sp_if END IF_SYM
- { Lex->sphead->do_cont_backpatch(); }
- ;
-
-sp_proc_stmt_statement:
- {
- LEX *lex= thd->lex;
- Lex_input_stream *lip= YYLIP;
-
- lex->sphead->reset_lex(thd);
- lex->sphead->m_tmp_query= lip->get_tok_start();
- }
- sp_statement
- {
- if (Lex->sp_proc_stmt_statement_finalize(thd, yychar == YYEMPTY) ||
- Lex->sphead->restore_lex(thd))
- MYSQL_YYABORT;
- }
- ;
-
-
-RETURN_ALLMODES_SYM:
- RETURN_MARIADB_SYM
- | RETURN_ORACLE_SYM
- ;
-
-sp_proc_stmt_return:
- RETURN_ALLMODES_SYM expr_lex
- {
- sp_head *sp= $2->sphead;
- if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, $2->spcont,
- $2->get_item(), $2)))
- MYSQL_YYABORT;
- }
- | RETURN_ORACLE_SYM
- {
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- if (unlikely(sp->m_handler->add_instr_preturn(thd, sp,
- lex->spcont)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_proc_stmt_exit_oracle:
- EXIT_ORACLE_SYM
- {
- if (unlikely(Lex->sp_exit_statement(thd, NULL)))
- MYSQL_YYABORT;
- }
- | EXIT_ORACLE_SYM label_ident
- {
- if (unlikely(Lex->sp_exit_statement(thd, &$2, NULL)))
- MYSQL_YYABORT;
- }
- | EXIT_ORACLE_SYM WHEN_SYM expr_lex
- {
- if (unlikely($3->sp_exit_statement(thd, $3->get_item())))
- MYSQL_YYABORT;
- }
- | EXIT_ORACLE_SYM label_ident WHEN_SYM expr_lex
- {
- if (unlikely($4->sp_exit_statement(thd, &$2, $4->get_item())))
- MYSQL_YYABORT;
- }
- ;
-
-sp_proc_stmt_continue_oracle:
- CONTINUE_ORACLE_SYM
- {
- if (unlikely(Lex->sp_continue_statement(thd)))
- MYSQL_YYABORT;
- }
- | CONTINUE_ORACLE_SYM label_ident
- {
- if (unlikely(Lex->sp_continue_statement(thd, &$2)))
- MYSQL_YYABORT;
- }
- | CONTINUE_ORACLE_SYM WHEN_SYM expr_lex
- {
- if (unlikely($3->sp_continue_when_statement(thd)))
- MYSQL_YYABORT;
- }
- | CONTINUE_ORACLE_SYM label_ident WHEN_SYM expr_lex
- {
- if (unlikely($4->sp_continue_when_statement(thd, &$2)))
- MYSQL_YYABORT;
- }
- ;
-
-
-sp_proc_stmt_leave:
- LEAVE_SYM label_ident
- {
- if (unlikely(Lex->sp_leave_statement(thd, &$2)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_proc_stmt_iterate:
- ITERATE_SYM label_ident
- {
- if (unlikely(Lex->sp_iterate_statement(thd, &$2)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_proc_stmt_goto_oracle:
- GOTO_ORACLE_SYM label_ident
- {
- if (unlikely(Lex->sp_goto_statement(thd, &$2)))
- MYSQL_YYABORT;
- }
- ;
-
-
-expr_lex:
- {
- DBUG_ASSERT(Lex->sphead);
- if (unlikely(!($<expr_lex>$= new (thd->mem_root)
- sp_expr_lex(thd, thd->lex))))
- MYSQL_YYABORT;
- Lex->sphead->reset_lex(thd, $<expr_lex>$);
- }
- expr
- {
- $$= $<expr_lex>1;
- $$->sp_lex_in_use= true;
- $$->set_item($2);
- if ($$->sphead->restore_lex(thd))
- MYSQL_YYABORT;
- }
- ;
-
-
-assignment_source_lex:
- {
- DBUG_ASSERT(Lex->sphead);
- if (unlikely(!($$= new (thd->mem_root)
- sp_assignment_lex(thd, thd->lex))))
- MYSQL_YYABORT;
- }
- ;
-
-assignment_source_expr:
- assignment_source_lex
- {
- DBUG_ASSERT(thd->free_list == NULL);
- Lex->sphead->reset_lex(thd, $1);
- }
- expr
- {
- DBUG_ASSERT($1 == thd->lex);
- $$= $1;
- $$->sp_lex_in_use= true;
- $$->set_item_and_free_list($3, thd->free_list);
- thd->free_list= NULL;
- if ($$->sphead->restore_lex(thd))
- MYSQL_YYABORT;
- }
- ;
-
-for_loop_bound_expr:
- assignment_source_lex
- {
- Lex->sphead->reset_lex(thd, $1);
- Lex->current_select->parsing_place= FOR_LOOP_BOUND;
- }
- expr
- {
- DBUG_ASSERT($1 == thd->lex);
- $$= $1;
- $$->sp_lex_in_use= true;
- $$->set_item_and_free_list($3, NULL);
- if (unlikely($$->sphead->restore_lex(thd)))
- MYSQL_YYABORT;
- Lex->current_select->parsing_place= NO_MATTER;
- }
- ;
-
-cursor_actual_parameters:
- assignment_source_expr
- {
- if (unlikely(!($$= new (thd->mem_root) List<sp_assignment_lex>)))
- MYSQL_YYABORT;
- $$->push_back($1, thd->mem_root);
- }
- | cursor_actual_parameters ',' assignment_source_expr
- {
- $$= $1;
- $$->push_back($3, thd->mem_root);
- }
- ;
-
-opt_parenthesized_cursor_actual_parameters:
- /* Empty */ { $$= NULL; }
- | '(' cursor_actual_parameters ')' { $$= $2; }
- ;
-
-sp_proc_stmt_with_cursor:
- sp_proc_stmt_open
- | sp_proc_stmt_fetch
- | sp_proc_stmt_close
- ;
-
-sp_proc_stmt_open:
- OPEN_SYM ident opt_parenthesized_cursor_actual_parameters
- {
- if (unlikely(Lex->sp_open_cursor(thd, &$2, $3)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_proc_stmt_fetch_head:
- FETCH_SYM ident INTO
- {
- if (unlikely(Lex->sp_add_cfetch(thd, &$2)))
- MYSQL_YYABORT;
- }
- | FETCH_SYM FROM ident INTO
- {
- if (unlikely(Lex->sp_add_cfetch(thd, &$3)))
- MYSQL_YYABORT;
- }
- | FETCH_SYM NEXT_SYM FROM ident INTO
- {
- if (unlikely(Lex->sp_add_cfetch(thd, &$4)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_proc_stmt_fetch:
- sp_proc_stmt_fetch_head sp_fetch_list { }
- | FETCH_SYM GROUP_SYM NEXT_SYM ROW_SYM
- {
- if (unlikely(Lex->sp_add_agg_cfetch()))
- MYSQL_YYABORT;
- }
- ;
-
-sp_proc_stmt_close:
- CLOSE_SYM ident
- {
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- uint offset;
- sp_instr_cclose *i;
-
- if (unlikely(!lex->spcont->find_cursor(&$2, &offset, false)))
- my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
- i= new (thd->mem_root)
- sp_instr_cclose(sp->instructions(), lex->spcont, offset);
- if (unlikely(i == NULL) ||
- unlikely(sp->add_instr(i)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_fetch_list:
- ident
- {
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- sp_pcontext *spc= lex->spcont;
- sp_variable *spv;
-
- if (unlikely(!spc || !(spv = spc->find_variable(&$1, false))))
- my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
-
- /* An SP local variable */
- sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
- i->add_to_varlist(spv);
- }
- | sp_fetch_list ',' ident
- {
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- sp_pcontext *spc= lex->spcont;
- sp_variable *spv;
-
- if (unlikely(!spc || !(spv = spc->find_variable(&$3, false))))
- my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $3.str));
-
- /* An SP local variable */
- sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
- i->add_to_varlist(spv);
- }
- ;
-
-sp_if:
- expr_lex THEN_SYM
- {
- if (unlikely($1->sp_if_expr(thd)))
- MYSQL_YYABORT;
- }
- sp_if_then_statements
- {
- if (unlikely($1->sp_if_after_statements(thd)))
- MYSQL_YYABORT;
- }
- sp_elseifs
- {
- LEX *lex= Lex;
-
- lex->sphead->backpatch(lex->spcont->pop_label());
- }
- ;
-
-sp_elseifs:
- /* Empty */
- | ELSEIF_MARIADB_SYM sp_if
- | ELSIF_ORACLE_SYM sp_if
- | ELSE sp_if_then_statements
- ;
-
-case_stmt_specification:
- CASE_SYM
- {
- if (unlikely(Lex->maybe_start_compound_statement(thd)))
- MYSQL_YYABORT;
-
- /**
- An example of the CASE statement in use is
- <pre>
- CREATE PROCEDURE proc_19194_simple(i int)
- BEGIN
- DECLARE str CHAR(10);
-
- CASE i
- WHEN 1 THEN SET str="1";
- WHEN 2 THEN SET str="2";
- WHEN 3 THEN SET str="3";
- ELSE SET str="unknown";
- END CASE;
-
- SELECT str;
- END
- </pre>
- The actions are used to generate the following code:
- <pre>
- SHOW PROCEDURE CODE proc_19194_simple;
- Pos Instruction
- 0 set str@1 NULL
- 1 set_case_expr (12) 0 i@0
- 2 jump_if_not 5(12) (case_expr@0 = 1)
- 3 set str@1 _latin1'1'
- 4 jump 12
- 5 jump_if_not 8(12) (case_expr@0 = 2)
- 6 set str@1 _latin1'2'
- 7 jump 12
- 8 jump_if_not 11(12) (case_expr@0 = 3)
- 9 set str@1 _latin1'3'
- 10 jump 12
- 11 set str@1 _latin1'unknown'
- 12 stmt 0 "SELECT str"
- </pre>
- */
-
- Lex->sphead->new_cont_backpatch(NULL);
-
- /*
- BACKPATCH: Creating target label for the jump to after END CASE
- (instruction 12 in the example)
- */
- Lex->spcont->push_label(thd, &empty_clex_str, Lex->sphead->instructions());
- }
- case_stmt_body
- else_clause_opt
- END
- CASE_SYM
- {
- /*
- BACKPATCH: Resolving forward jump from
- "case_stmt_action_then" to after END CASE
- (jump from instruction 4 to 12, 7 to 12 ... in the example)
- */
- Lex->sphead->backpatch(Lex->spcont->pop_label());
-
- if ($3)
- Lex->spcont->pop_case_expr_id();
-
- Lex->sphead->do_cont_backpatch();
- }
- ;
-
-case_stmt_body:
- expr_lex
- {
- if (unlikely($1->case_stmt_action_expr()))
- MYSQL_YYABORT;
- }
- simple_when_clause_list
- { $$= 1; }
- | searched_when_clause_list
- { $$= 0; }
- ;
-
-simple_when_clause_list:
- simple_when_clause
- | simple_when_clause_list simple_when_clause
- ;
-
-searched_when_clause_list:
- searched_when_clause
- | searched_when_clause_list searched_when_clause
- ;
-
-simple_when_clause:
- WHEN_SYM expr_lex
- {
- /* Simple case: <caseval> = <whenval> */
- if (unlikely($2->case_stmt_action_when(true)))
- MYSQL_YYABORT;
- }
- THEN_SYM
- sp_case_then_statements
- {
- if (unlikely(Lex->case_stmt_action_then()))
- MYSQL_YYABORT;
- }
- ;
-
-searched_when_clause:
- WHEN_SYM expr_lex
- {
- if (unlikely($2->case_stmt_action_when(false)))
- MYSQL_YYABORT;
- }
- THEN_SYM
- sp_case_then_statements
- {
- if (unlikely(Lex->case_stmt_action_then()))
- MYSQL_YYABORT;
- }
- ;
-
-else_clause_opt:
- /* empty */
- {
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- uint ip= sp->instructions();
- sp_instr_error *i= new (thd->mem_root)
- sp_instr_error(ip, lex->spcont, ER_SP_CASE_NOT_FOUND);
- if (unlikely(i == NULL) ||
- unlikely(sp->add_instr(i)))
- MYSQL_YYABORT;
- }
- | ELSE sp_case_then_statements
- ;
-
-sp_opt_label:
- /* Empty */ { $$= null_clex_str; }
- | label_ident { $$= $1; }
- ;
-
-/* This adds one shift/reduce conflict */
-opt_sp_for_loop_direction:
- /* Empty */ { $$= 1; }
- | REVERSE_SYM { $$= -1; }
- ;
-
-sp_for_loop_index_and_bounds:
- ident_for_loop_index sp_for_loop_bounds
- {
- if (unlikely(Lex->sp_for_loop_declarations(thd, &$$, &$1, $2)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_for_loop_bounds:
- IN_SYM opt_sp_for_loop_direction for_loop_bound_expr
- DOT_DOT_SYM for_loop_bound_expr
- {
- $$= Lex_for_loop_bounds_intrange($2, $3, $5);
- }
- | IN_SYM opt_sp_for_loop_direction for_loop_bound_expr
- {
- $$.m_direction= $2;
- $$.m_index= $3;
- $$.m_target_bound= NULL;
- $$.m_implicit_cursor= false;
- }
- | IN_SYM opt_sp_for_loop_direction '(' sp_cursor_stmt ')'
- {
- if (unlikely(Lex->sp_for_loop_implicit_cursor_statement(thd, &$$,
- $4)))
- MYSQL_YYABORT;
- }
- ;
-
-loop_body:
- sp_proc_stmts1 END LOOP_SYM
- {
- LEX *lex= Lex;
- uint ip= lex->sphead->instructions();
- sp_label *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i= new (thd->mem_root)
- sp_instr_jump(ip, lex->spcont, lab->ip);
- if (unlikely(i == NULL) ||
- unlikely(lex->sphead->add_instr(i)))
- MYSQL_YYABORT;
- }
- ;
-
-repeat_body:
- sp_proc_stmts1 UNTIL_SYM expr_lex END REPEAT_SYM
- {
- if ($3->sp_repeat_loop_finalize(thd))
- MYSQL_YYABORT;
- }
- ;
-
-pop_sp_loop_label:
- sp_opt_label
- {
- if (unlikely(Lex->sp_pop_loop_label(thd, &$1)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_labeled_control:
- sp_control_label LOOP_SYM
- {
- if (unlikely(Lex->sp_push_loop_label(thd, &$1)))
- MYSQL_YYABORT;
- }
- loop_body pop_sp_loop_label
- { }
- | sp_control_label WHILE_SYM
- {
- if (unlikely(Lex->sp_push_loop_label(thd, &$1)))
- MYSQL_YYABORT;
- }
- while_body pop_sp_loop_label
- { }
- | sp_control_label FOR_SYM
- {
- // See "The FOR LOOP statement" comments in sql_lex.cc
- Lex->sp_block_init(thd); // The outer DECLARE..BEGIN..END block
- }
- sp_for_loop_index_and_bounds
- {
- if (unlikely(Lex->sp_push_loop_label(thd, &$1))) // The inner WHILE block
- MYSQL_YYABORT;
- if (unlikely(Lex->sp_for_loop_condition_test(thd, $4)))
- MYSQL_YYABORT;
- }
- for_loop_statements
- {
- if (unlikely(Lex->sp_for_loop_finalize(thd, $4)))
- MYSQL_YYABORT;
- }
- pop_sp_loop_label // The inner WHILE block
- {
- if (unlikely(Lex->sp_for_loop_outer_block_finalize(thd, $4)))
- MYSQL_YYABORT;
- }
- | sp_control_label REPEAT_SYM
- {
- if (unlikely(Lex->sp_push_loop_label(thd, &$1)))
- MYSQL_YYABORT;
- }
- repeat_body pop_sp_loop_label
- { }
- ;
-
-sp_unlabeled_control:
- LOOP_SYM
- {
- if (unlikely(Lex->sp_push_loop_empty_label(thd)))
- MYSQL_YYABORT;
- }
- loop_body
- {
- Lex->sp_pop_loop_empty_label(thd);
- }
- | WHILE_SYM
- {
- if (unlikely(Lex->sp_push_loop_empty_label(thd)))
- MYSQL_YYABORT;
- }
- while_body
- {
- Lex->sp_pop_loop_empty_label(thd);
- }
- | FOR_SYM
- {
- // See "The FOR LOOP statement" comments in sql_lex.cc
- if (unlikely(Lex->maybe_start_compound_statement(thd)))
- MYSQL_YYABORT;
- Lex->sp_block_init(thd); // The outer DECLARE..BEGIN..END block
- }
- sp_for_loop_index_and_bounds
- {
- if (unlikely(Lex->sp_push_loop_empty_label(thd))) // The inner WHILE block
- MYSQL_YYABORT;
- if (unlikely(Lex->sp_for_loop_condition_test(thd, $3)))
- MYSQL_YYABORT;
- }
- for_loop_statements
- {
- if (unlikely(Lex->sp_for_loop_finalize(thd, $3)))
- MYSQL_YYABORT;
- Lex->sp_pop_loop_empty_label(thd); // The inner WHILE block
- if (unlikely(Lex->sp_for_loop_outer_block_finalize(thd, $3)))
- MYSQL_YYABORT;
- }
- | REPEAT_SYM
- {
- if (unlikely(Lex->sp_push_loop_empty_label(thd)))
- MYSQL_YYABORT;
- }
- repeat_body
- {
- Lex->sp_pop_loop_empty_label(thd);
- }
- ;
-
-trg_action_time:
- BEFORE_SYM
- { Lex->trg_chistics.action_time= TRG_ACTION_BEFORE; }
- | AFTER_SYM
- { Lex->trg_chistics.action_time= TRG_ACTION_AFTER; }
- ;
-
-trg_event:
- INSERT
- { Lex->trg_chistics.event= TRG_EVENT_INSERT; }
- | UPDATE_SYM
- { Lex->trg_chistics.event= TRG_EVENT_UPDATE; }
- | DELETE_SYM
- { Lex->trg_chistics.event= TRG_EVENT_DELETE; }
- ;
-/*
- This part of the parser contains common code for all TABLESPACE
- commands.
- CREATE TABLESPACE name ...
- ALTER TABLESPACE name CHANGE DATAFILE ...
- ALTER TABLESPACE name ADD DATAFILE ...
- ALTER TABLESPACE name access_mode
- CREATE LOGFILE GROUP_SYM name ...
- ALTER LOGFILE GROUP_SYM name ADD UNDOFILE ..
- ALTER LOGFILE GROUP_SYM name ADD REDOFILE ..
- DROP TABLESPACE name
- DROP LOGFILE GROUP_SYM name
-*/
-change_tablespace_access:
- tablespace_name
- ts_access_mode
- ;
-
-change_tablespace_info:
- tablespace_name
- CHANGE ts_datafile
- change_ts_option_list
- ;
-
-tablespace_info:
- tablespace_name
- ADD ts_datafile
- opt_logfile_group_name
- tablespace_option_list
- ;
-
-opt_logfile_group_name:
- /* empty */ {}
- | USE_SYM LOGFILE_SYM GROUP_SYM ident
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->logfile_group_name= $4.str;
- }
- ;
-
-alter_tablespace_info:
- tablespace_name
- ADD ts_datafile
- alter_tablespace_option_list
- {
- Lex->alter_tablespace_info->ts_alter_tablespace_type= ALTER_TABLESPACE_ADD_FILE;
- }
- | tablespace_name
- DROP ts_datafile
- alter_tablespace_option_list
- {
- Lex->alter_tablespace_info->ts_alter_tablespace_type= ALTER_TABLESPACE_DROP_FILE;
- }
- ;
-
-logfile_group_info:
- logfile_group_name
- add_log_file
- logfile_group_option_list
- ;
-
-alter_logfile_group_info:
- logfile_group_name
- add_log_file
- alter_logfile_group_option_list
- ;
-
-add_log_file:
- ADD lg_undofile
- | ADD lg_redofile
- ;
-
-change_ts_option_list:
- /* empty */ {}
- change_ts_options
- ;
-
-change_ts_options:
- change_ts_option
- | change_ts_options change_ts_option
- | change_ts_options ',' change_ts_option
- ;
-
-change_ts_option:
- opt_ts_initial_size
- | opt_ts_autoextend_size
- | opt_ts_max_size
- ;
-
-tablespace_option_list:
- tablespace_options
- ;
-
-tablespace_options:
- tablespace_option
- | tablespace_options tablespace_option
- | tablespace_options ',' tablespace_option
- ;
-
-tablespace_option:
- opt_ts_initial_size
- | opt_ts_autoextend_size
- | opt_ts_max_size
- | opt_ts_extent_size
- | opt_ts_nodegroup
- | opt_ts_engine
- | ts_wait
- | opt_ts_comment
- ;
-
-alter_tablespace_option_list:
- alter_tablespace_options
- ;
-
-alter_tablespace_options:
- alter_tablespace_option
- | alter_tablespace_options alter_tablespace_option
- | alter_tablespace_options ',' alter_tablespace_option
- ;
-
-alter_tablespace_option:
- opt_ts_initial_size
- | opt_ts_autoextend_size
- | opt_ts_max_size
- | opt_ts_engine
- | ts_wait
- ;
-
-logfile_group_option_list:
- logfile_group_options
- ;
-
-logfile_group_options:
- logfile_group_option
- | logfile_group_options logfile_group_option
- | logfile_group_options ',' logfile_group_option
- ;
-
-logfile_group_option:
- opt_ts_initial_size
- | opt_ts_undo_buffer_size
- | opt_ts_redo_buffer_size
- | opt_ts_nodegroup
- | opt_ts_engine
- | ts_wait
- | opt_ts_comment
- ;
-
-alter_logfile_group_option_list:
- alter_logfile_group_options
- ;
-
-alter_logfile_group_options:
- alter_logfile_group_option
- | alter_logfile_group_options alter_logfile_group_option
- | alter_logfile_group_options ',' alter_logfile_group_option
- ;
-
-alter_logfile_group_option:
- opt_ts_initial_size
- | opt_ts_engine
- | ts_wait
- ;
-
-
-ts_datafile:
- DATAFILE_SYM TEXT_STRING_sys
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->data_file_name= $2.str;
- }
- ;
-
-lg_undofile:
- UNDOFILE_SYM TEXT_STRING_sys
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->undo_file_name= $2.str;
- }
- ;
-
-lg_redofile:
- REDOFILE_SYM TEXT_STRING_sys
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->redo_file_name= $2.str;
- }
- ;
-
-tablespace_name:
- ident
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info= (new (thd->mem_root)
- st_alter_tablespace());
- if (unlikely(lex->alter_tablespace_info == NULL))
- MYSQL_YYABORT;
- lex->alter_tablespace_info->tablespace_name= $1.str;
- lex->sql_command= SQLCOM_ALTER_TABLESPACE;
- }
- ;
-
-logfile_group_name:
- ident
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info= (new (thd->mem_root)
- st_alter_tablespace());
- if (unlikely(lex->alter_tablespace_info == NULL))
- MYSQL_YYABORT;
- lex->alter_tablespace_info->logfile_group_name= $1.str;
- lex->sql_command= SQLCOM_ALTER_TABLESPACE;
- }
- ;
-
-ts_access_mode:
- READ_ONLY_SYM
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->ts_access_mode= TS_READ_ONLY;
- }
- | READ_WRITE_SYM
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->ts_access_mode= TS_READ_WRITE;
- }
- | NOT_SYM ACCESSIBLE_SYM
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->ts_access_mode= TS_NOT_ACCESSIBLE;
- }
- ;
-
-opt_ts_initial_size:
- INITIAL_SIZE_SYM opt_equal size_number
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->initial_size= $3;
- }
- ;
-
-opt_ts_autoextend_size:
- AUTOEXTEND_SIZE_SYM opt_equal size_number
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->autoextend_size= $3;
- }
- ;
-
-opt_ts_max_size:
- MAX_SIZE_SYM opt_equal size_number
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->max_size= $3;
- }
- ;
-
-opt_ts_extent_size:
- EXTENT_SIZE_SYM opt_equal size_number
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->extent_size= $3;
- }
- ;
-
-opt_ts_undo_buffer_size:
- UNDO_BUFFER_SIZE_SYM opt_equal size_number
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->undo_buffer_size= $3;
- }
- ;
-
-opt_ts_redo_buffer_size:
- REDO_BUFFER_SIZE_SYM opt_equal size_number
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->redo_buffer_size= $3;
- }
- ;
-
-opt_ts_nodegroup:
- NODEGROUP_SYM opt_equal real_ulong_num
- {
- LEX *lex= Lex;
- if (unlikely(lex->alter_tablespace_info->nodegroup_id != UNDEF_NODEGROUP))
- my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP"));
- lex->alter_tablespace_info->nodegroup_id= $3;
- }
- ;
-
-opt_ts_comment:
- COMMENT_SYM opt_equal TEXT_STRING_sys
- {
- LEX *lex= Lex;
- if (unlikely(lex->alter_tablespace_info->ts_comment != NULL))
- my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"COMMENT"));
- lex->alter_tablespace_info->ts_comment= $3.str;
- }
- ;
-
-opt_ts_engine:
- opt_storage ENGINE_SYM opt_equal storage_engines
- {
- LEX *lex= Lex;
- if (unlikely(lex->alter_tablespace_info->storage_engine != NULL))
- my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE, MYF(0),
- "STORAGE ENGINE"));
- lex->alter_tablespace_info->storage_engine= $4;
- }
- ;
-
-opt_ts_wait:
- /* empty */
- | ts_wait
- ;
-
-ts_wait:
- WAIT_SYM
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->wait_until_completed= TRUE;
- }
- | NO_WAIT_SYM
- {
- LEX *lex= Lex;
- if (unlikely(!(lex->alter_tablespace_info->wait_until_completed)))
- my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT"));
- lex->alter_tablespace_info->wait_until_completed= FALSE;
- }
- ;
-
-size_number:
- real_ulonglong_num { $$= $1;}
- | IDENT_sys
- {
- if ($1.to_size_number(&$$))
- MYSQL_YYABORT;
- }
- ;
-
-/*
- End tablespace part
-*/
-
-create_body:
- create_field_list_parens
- { Lex->create_info.option_list= NULL; }
- opt_create_table_options opt_create_partitioning opt_create_select {}
- | opt_create_table_options opt_create_partitioning opt_create_select {}
- | create_like
- {
-
- Lex->create_info.add(DDL_options_st::OPT_LIKE);
- TABLE_LIST *src_table= Lex->first_select_lex()->
- add_table_to_list(thd, $1, NULL, 0, TL_READ, MDL_SHARED_READ);
- if (unlikely(! src_table))
- MYSQL_YYABORT;
- /* CREATE TABLE ... LIKE is not allowed for views. */
- src_table->required_type= TABLE_TYPE_NORMAL;
- }
- ;
-
-create_like:
- LIKE table_ident { $$= $2; }
- | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; }
- ;
-
-opt_create_select:
- /* empty */ {}
- | opt_duplicate opt_as create_select_query_expression opt_versioning_option
- ;
-
-create_select_query_expression:
- query_expression
- {
- if (Lex->parsed_insert_select($1->first_select()))
- MYSQL_YYABORT;
- }
- | LEFT_PAREN_WITH with_clause query_expression_no_with_clause ')'
- {
- SELECT_LEX *first_select= $3->first_select();
- $3->set_with_clause($2);
- $2->attach_to(first_select);
- if (Lex->parsed_insert_select(first_select))
- MYSQL_YYABORT;
- }
- ;
-
-opt_create_partitioning:
- opt_partitioning
- {
- /*
- Remove all tables used in PARTITION clause from the global table
- list. Partitioning with subqueries is not allowed anyway.
- */
- TABLE_LIST *last_non_sel_table= Lex->create_last_non_select_table;
- last_non_sel_table->next_global= 0;
- Lex->query_tables_last= &last_non_sel_table->next_global;
- }
- ;
-
-/*
- This part of the parser is about handling of the partition information.
-
- Its first version was written by Mikael Ronström with lots of answers to
- questions provided by Antony Curtis.
-
- The partition grammar can be called from three places.
- 1) CREATE TABLE ... PARTITION ..
- 2) ALTER TABLE table_name PARTITION ...
- 3) PARTITION ...
-
- The first place is called when a new table is created from a MySQL client.
- The second place is called when a table is altered with the ALTER TABLE
- command from a MySQL client.
- The third place is called when opening an frm file and finding partition
- info in the .frm file. It is necessary to avoid allowing PARTITION to be
- an allowed entry point for SQL client queries. This is arranged by setting
- some state variables before arriving here.
-
- To be able to handle errors we will only set error code in this code
- and handle the error condition in the function calling the parser. This
- is necessary to ensure we can also handle errors when calling the parser
- from the openfrm function.
-*/
-opt_partitioning:
- /* empty */ {}
- | partitioning
- ;
-
-partitioning:
- PARTITION_SYM have_partitioning
- {
- LEX *lex= Lex;
- lex->part_info= new (thd->mem_root) partition_info();
- if (unlikely(!lex->part_info))
- MYSQL_YYABORT;
- if (lex->sql_command == SQLCOM_ALTER_TABLE)
- {
- lex->alter_info.partition_flags|= ALTER_PARTITION_INFO;
- }
- }
- partition
- ;
-
-have_partitioning:
- /* empty */
- {
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- LEX_CSTRING partition_name={STRING_WITH_LEN("partition")};
- if (unlikely(!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN)))
- my_yyabort_error((ER_OPTION_PREVENTS_STATEMENT, MYF(0),
- "--skip-partition"));
-#else
- my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), "partitioning",
- "--with-plugin-partition"));
-#endif
- }
- ;
-
-partition_entry:
- PARTITION_SYM
- {
- if (unlikely(!Lex->part_info))
- {
- thd->parse_error(ER_PARTITION_ENTRY_ERROR);
- MYSQL_YYABORT;
- }
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- /*
- We enter here when opening the frm file to translate
- partition info string into part_info data structure.
- */
- }
- partition
- {
- Lex->pop_select(); //main select
- }
- ;
-
-partition:
- BY
- { Lex->safe_to_cache_query= 1; }
- part_type_def opt_num_parts opt_sub_part part_defs
- ;
-
-part_type_def:
- opt_linear KEY_SYM opt_key_algo '(' part_field_list ')'
- {
- partition_info *part_info= Lex->part_info;
- part_info->list_of_part_fields= TRUE;
- part_info->column_list= FALSE;
- part_info->part_type= HASH_PARTITION;
- }
- | opt_linear HASH_SYM
- { Lex->part_info->part_type= HASH_PARTITION; }
- part_func {}
- | RANGE_SYM part_func
- { Lex->part_info->part_type= RANGE_PARTITION; }
- | RANGE_SYM part_column_list
- { Lex->part_info->part_type= RANGE_PARTITION; }
- | LIST_SYM
- {
- Select->parsing_place= IN_PART_FUNC;
- }
- part_func
- {
- Lex->part_info->part_type= LIST_PARTITION;
- Select->parsing_place= NO_MATTER;
- }
- | LIST_SYM part_column_list
- { Lex->part_info->part_type= LIST_PARTITION; }
- | SYSTEM_TIME_SYM
- {
- if (unlikely(Lex->part_info->vers_init_info(thd)))
- MYSQL_YYABORT;
- }
- opt_versioning_rotation
- ;
-
-opt_linear:
- /* empty */ {}
- | LINEAR_SYM
- { Lex->part_info->linear_hash_ind= TRUE;}
- ;
-
-opt_key_algo:
- /* empty */
- { Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_NONE;}
- | ALGORITHM_SYM '=' real_ulong_num
- {
- switch ($3) {
- case 1:
- Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_51;
- break;
- case 2:
- Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_55;
- break;
- default:
- thd->parse_error();
- MYSQL_YYABORT;
- }
- }
- ;
-
-part_field_list:
- /* empty */ {}
- | part_field_item_list {}
- ;
-
-part_field_item_list:
- part_field_item {}
- | part_field_item_list ',' part_field_item {}
- ;
-
-part_field_item:
- ident
- {
- partition_info *part_info= Lex->part_info;
- part_info->num_columns++;
- if (unlikely(part_info->part_field_list.push_back($1.str,
- thd->mem_root)))
- MYSQL_YYABORT;
- if (unlikely(part_info->num_columns > MAX_REF_PARTS))
- my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
- "list of partition fields"));
- }
- ;
-
-part_column_list:
- COLUMNS '(' part_field_list ')'
- {
- partition_info *part_info= Lex->part_info;
- part_info->column_list= TRUE;
- part_info->list_of_part_fields= TRUE;
- }
- ;
-
-
-part_func:
- '(' part_func_expr ')'
- {
- partition_info *part_info= Lex->part_info;
- if (unlikely(part_info->set_part_expr(thd, $2, FALSE)))
- MYSQL_YYABORT;
- part_info->num_columns= 1;
- part_info->column_list= FALSE;
- }
- ;
-
-sub_part_func:
- '(' part_func_expr ')'
- {
- if (unlikely(Lex->part_info->set_part_expr(thd, $2, TRUE)))
- MYSQL_YYABORT;
- }
- ;
-
-
-opt_num_parts:
- /* empty */ {}
- | PARTITIONS_SYM real_ulong_num
- {
- uint num_parts= $2;
- partition_info *part_info= Lex->part_info;
- if (unlikely(num_parts == 0))
- my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "partitions"));
-
- part_info->num_parts= num_parts;
- part_info->use_default_num_partitions= FALSE;
- }
- ;
-
-opt_sub_part:
- /* empty */ {}
- | SUBPARTITION_SYM BY opt_linear HASH_SYM sub_part_func
- { Lex->part_info->subpart_type= HASH_PARTITION; }
- opt_num_subparts {}
- | SUBPARTITION_SYM BY opt_linear KEY_SYM opt_key_algo
- '(' sub_part_field_list ')'
- {
- partition_info *part_info= Lex->part_info;
- part_info->subpart_type= HASH_PARTITION;
- part_info->list_of_subpart_fields= TRUE;
- }
- opt_num_subparts {}
- ;
-
-sub_part_field_list:
- sub_part_field_item {}
- | sub_part_field_list ',' sub_part_field_item {}
- ;
-
-sub_part_field_item:
- ident
- {
- partition_info *part_info= Lex->part_info;
- if (unlikely(part_info->subpart_field_list.push_back($1.str,
- thd->mem_root)))
- MYSQL_YYABORT;
-
- if (unlikely(part_info->subpart_field_list.elements > MAX_REF_PARTS))
- my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
- "list of subpartition fields"));
- }
- ;
-
-part_func_expr:
- bit_expr
- {
- if (unlikely(!Lex->safe_to_cache_query))
- {
- thd->parse_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
- MYSQL_YYABORT;
- }
- $$=$1;
- }
- ;
-
-opt_num_subparts:
- /* empty */ {}
- | SUBPARTITIONS_SYM real_ulong_num
- {
- uint num_parts= $2;
- LEX *lex= Lex;
- if (unlikely(num_parts == 0))
- my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "subpartitions"));
- lex->part_info->num_subparts= num_parts;
- lex->part_info->use_default_num_subpartitions= FALSE;
- }
- ;
-
-part_defs:
- /* empty */
- {
- partition_info *part_info= Lex->part_info;
- if (unlikely(part_info->part_type == RANGE_PARTITION))
- my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
- "RANGE"));
- if (unlikely(part_info->part_type == LIST_PARTITION))
- my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
- "LIST"));
- }
- | '(' part_def_list ')'
- {
- partition_info *part_info= Lex->part_info;
- uint count_curr_parts= part_info->partitions.elements;
- if (part_info->num_parts != 0)
- {
- if (unlikely(part_info->num_parts !=
- count_curr_parts))
- {
- thd->parse_error(ER_PARTITION_WRONG_NO_PART_ERROR);
- MYSQL_YYABORT;
- }
- }
- else if (count_curr_parts > 0)
- {
- part_info->num_parts= count_curr_parts;
- }
- part_info->count_curr_subparts= 0;
- }
- ;
-
-part_def_list:
- part_definition {}
- | part_def_list ',' part_definition {}
- ;
-
-part_definition:
- PARTITION_SYM
- {
- partition_info *part_info= Lex->part_info;
- partition_element *p_elem= new (thd->mem_root) partition_element();
-
- if (unlikely(!p_elem) ||
- unlikely(part_info->partitions.push_back(p_elem, thd->mem_root)))
- MYSQL_YYABORT;
-
- p_elem->part_state= PART_NORMAL;
- p_elem->id= part_info->partitions.elements - 1;
- part_info->curr_part_elem= p_elem;
- part_info->current_partition= p_elem;
- part_info->use_default_partitions= FALSE;
- part_info->use_default_num_partitions= FALSE;
- }
- part_name
- opt_part_values
- opt_part_options
- opt_sub_partition
- {}
- ;
-
-part_name:
- ident
- {
- partition_info *part_info= Lex->part_info;
- partition_element *p_elem= part_info->curr_part_elem;
- if (unlikely(check_ident_length(&$1)))
- MYSQL_YYABORT;
- p_elem->partition_name= $1.str;
- }
- ;
-
-opt_part_values:
- /* empty */
- {
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
- if (! lex->is_partition_management())
- {
- if (unlikely(part_info->error_if_requires_values()))
- MYSQL_YYABORT;
- if (unlikely(part_info->part_type == VERSIONING_PARTITION))
- my_yyabort_error((ER_VERS_WRONG_PARTS, MYF(0),
- lex->create_last_non_select_table->
- table_name.str));
- }
- else
- part_info->part_type= HASH_PARTITION;
- }
- | VALUES_LESS_SYM THAN_SYM
- {
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
- if (! lex->is_partition_management())
- {
- if (unlikely(part_info->part_type != RANGE_PARTITION))
- my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN"));
- }
- else
- part_info->part_type= RANGE_PARTITION;
- }
- part_func_max {}
- | VALUES_IN_SYM
- {
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
- if (! lex->is_partition_management())
- {
- if (unlikely(part_info->part_type != LIST_PARTITION))
- my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "LIST", "IN"));
- }
- else
- part_info->part_type= LIST_PARTITION;
- }
- part_values_in {}
- | CURRENT_SYM
- {
- if (Lex->part_values_current(thd))
- MYSQL_YYABORT;
- }
- | HISTORY_SYM
- {
- if (Lex->part_values_history(thd))
- MYSQL_YYABORT;
- }
- | DEFAULT
- {
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
- if (! lex->is_partition_management())
- {
- if (unlikely(part_info->part_type != LIST_PARTITION))
- my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "LIST", "DEFAULT"));
- }
- else
- part_info->part_type= LIST_PARTITION;
- if (unlikely(part_info->init_column_part(thd)))
- MYSQL_YYABORT;
- if (unlikely(part_info->add_max_value(thd)))
- MYSQL_YYABORT;
- }
- ;
-
-part_func_max:
- MAXVALUE_SYM
- {
- partition_info *part_info= Lex->part_info;
-
- if (unlikely(part_info->num_columns &&
- part_info->num_columns != 1U))
- {
- part_info->print_debug("Kilroy II", NULL);
- thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR);
- MYSQL_YYABORT;
- }
- else
- part_info->num_columns= 1U;
- if (unlikely(part_info->init_column_part(thd)))
- MYSQL_YYABORT;
- if (unlikely(part_info->add_max_value(thd)))
- MYSQL_YYABORT;
- }
- | part_value_item {}
- ;
-
-part_values_in:
- part_value_item
- {
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
- part_info->print_debug("part_values_in: part_value_item", NULL);
-
- if (part_info->num_columns != 1U)
- {
- if (unlikely(!lex->is_partition_management() ||
- part_info->num_columns == 0 ||
- part_info->num_columns > MAX_REF_PARTS))
- {
- part_info->print_debug("Kilroy III", NULL);
- thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR);
- MYSQL_YYABORT;
- }
- /*
- Reorganize the current large array into a list of small
- arrays with one entry in each array. This can happen
- in the first partition of an ALTER TABLE statement where
- we ADD or REORGANIZE partitions. Also can only happen
- for LIST partitions.
- */
- if (unlikely(part_info->reorganize_into_single_field_col_val(thd)))
- MYSQL_YYABORT;
- }
- }
- | '(' part_value_list ')'
- {
- partition_info *part_info= Lex->part_info;
- if (unlikely(part_info->num_columns < 2U))
- {
- thd->parse_error(ER_ROW_SINGLE_PARTITION_FIELD_ERROR);
- MYSQL_YYABORT;
- }
- }
- ;
-
-part_value_list:
- part_value_item {}
- | part_value_list ',' part_value_item {}
- ;
-
-part_value_item:
- '('
- {
- partition_info *part_info= Lex->part_info;
- part_info->print_debug("( part_value_item", NULL);
- /* Initialisation code needed for each list of value expressions */
- if (unlikely(!(part_info->part_type == LIST_PARTITION &&
- part_info->num_columns == 1U) &&
- part_info->init_column_part(thd)))
- MYSQL_YYABORT;
- }
- part_value_item_list {}
- ')'
- {
- partition_info *part_info= Lex->part_info;
- part_info->print_debug(") part_value_item", NULL);
- if (part_info->num_columns == 0)
- part_info->num_columns= part_info->curr_list_object;
- if (unlikely(part_info->num_columns != part_info->curr_list_object))
- {
- /*
- All value items lists must be of equal length, in some cases
- which is covered by the above if-statement we don't know yet
- how many columns is in the partition so the assignment above
- ensures that we only report errors when we know we have an
- error.
- */
- part_info->print_debug("Kilroy I", NULL);
- thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR);
- MYSQL_YYABORT;
- }
- part_info->curr_list_object= 0;
- }
- ;
-
-part_value_item_list:
- part_value_expr_item {}
- | part_value_item_list ',' part_value_expr_item {}
- ;
-
-part_value_expr_item:
- MAXVALUE_SYM
- {
- partition_info *part_info= Lex->part_info;
- if (unlikely(part_info->part_type == LIST_PARTITION))
- {
- thd->parse_error(ER_MAXVALUE_IN_VALUES_IN);
- MYSQL_YYABORT;
- }
- if (unlikely(part_info->add_max_value(thd)))
- MYSQL_YYABORT;
- }
- | bit_expr
- {
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
- Item *part_expr= $1;
-
- if (unlikely(!lex->safe_to_cache_query))
- {
- thd->parse_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
- MYSQL_YYABORT;
- }
- if (unlikely(part_info->add_column_list_value(thd, part_expr)))
- MYSQL_YYABORT;
- }
- ;
-
-
-opt_sub_partition:
- /* empty */
- {
- partition_info *part_info= Lex->part_info;
- if (unlikely(part_info->num_subparts != 0 &&
- !part_info->use_default_subpartitions))
- {
- /*
- We come here when we have defined subpartitions on the first
- partition but not on all the subsequent partitions.
- */
- thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
- MYSQL_YYABORT;
- }
- }
- | '(' sub_part_list ')'
- {
- partition_info *part_info= Lex->part_info;
- if (part_info->num_subparts != 0)
- {
- if (unlikely(part_info->num_subparts !=
- part_info->count_curr_subparts))
- {
- thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
- MYSQL_YYABORT;
- }
- }
- else if (part_info->count_curr_subparts > 0)
- {
- if (unlikely(part_info->partitions.elements > 1))
- {
- thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
- MYSQL_YYABORT;
- }
- part_info->num_subparts= part_info->count_curr_subparts;
- }
- part_info->count_curr_subparts= 0;
- }
- ;
-
-sub_part_list:
- sub_part_definition {}
- | sub_part_list ',' sub_part_definition {}
- ;
-
-sub_part_definition:
- SUBPARTITION_SYM
- {
- partition_info *part_info= Lex->part_info;
- partition_element *curr_part= part_info->current_partition;
- partition_element *sub_p_elem= new (thd->mem_root)
- partition_element(curr_part);
- if (unlikely(part_info->use_default_subpartitions &&
- part_info->partitions.elements >= 2))
- {
- /*
- create table t1 (a int)
- partition by list (a) subpartition by hash (a)
- (partition p0 values in (1),
- partition p1 values in (2) subpartition sp11);
- causes use to arrive since we are on the second
- partition, but still use_default_subpartitions
- is set. When we come here we're processing at least
- the second partition (the current partition processed
- have already been put into the partitions list.
- */
- thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
- MYSQL_YYABORT;
- }
- if (unlikely(!sub_p_elem) ||
- unlikely(curr_part->subpartitions.push_back(sub_p_elem, thd->mem_root)))
- MYSQL_YYABORT;
-
- sub_p_elem->id= curr_part->subpartitions.elements - 1;
- part_info->curr_part_elem= sub_p_elem;
- part_info->use_default_subpartitions= FALSE;
- part_info->use_default_num_subpartitions= FALSE;
- part_info->count_curr_subparts++;
- }
- sub_name opt_part_options {}
- ;
-
-sub_name:
- ident_or_text
- {
- if (unlikely(check_ident_length(&$1)))
- MYSQL_YYABORT;
- Lex->part_info->curr_part_elem->partition_name= $1.str;
- }
- ;
-
-opt_part_options:
- /* empty */ {}
- | opt_part_option_list {}
- ;
-
-opt_part_option_list:
- opt_part_option_list opt_part_option {}
- | opt_part_option {}
- ;
-
-opt_part_option:
- TABLESPACE opt_equal ident_or_text
- { Lex->part_info->curr_part_elem->tablespace_name= $3.str; }
- | opt_storage ENGINE_SYM opt_equal storage_engines
- {
- partition_info *part_info= Lex->part_info;
- part_info->curr_part_elem->engine_type= $4;
- part_info->default_engine_type= $4;
- }
- | CONNECTION_SYM opt_equal TEXT_STRING_sys
- {
- LEX *lex= Lex;
- lex->part_info->curr_part_elem->connect_string.str= $3.str;
- lex->part_info->curr_part_elem->connect_string.length= $3.length;
- }
- | NODEGROUP_SYM opt_equal real_ulong_num
- { Lex->part_info->curr_part_elem->nodegroup_id= (uint16) $3; }
- | MAX_ROWS opt_equal real_ulonglong_num
- { Lex->part_info->curr_part_elem->part_max_rows= (ha_rows) $3; }
- | MIN_ROWS opt_equal real_ulonglong_num
- { Lex->part_info->curr_part_elem->part_min_rows= (ha_rows) $3; }
- | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
- { Lex->part_info->curr_part_elem->data_file_name= $4.str; }
- | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
- { Lex->part_info->curr_part_elem->index_file_name= $4.str; }
- | COMMENT_SYM opt_equal TEXT_STRING_sys
- { Lex->part_info->curr_part_elem->part_comment= $3.str; }
- ;
-
-opt_versioning_rotation:
- /* empty */ {}
- | INTERVAL_SYM expr interval opt_versioning_interval_start
- {
- partition_info *part_info= Lex->part_info;
- const char *table_name= Lex->create_last_non_select_table->table_name.str;
- if (unlikely(part_info->vers_set_interval(thd, $2, $3, $4, table_name)))
- MYSQL_YYABORT;
- }
- | LIMIT ulonglong_num
- {
- partition_info *part_info= Lex->part_info;
- if (unlikely(part_info->vers_set_limit($2)))
- {
- my_error(ER_PART_WRONG_VALUE, MYF(0),
- Lex->create_last_non_select_table->table_name.str,
- "LIMIT");
- MYSQL_YYABORT;
- }
- }
- ;
-
-
-opt_versioning_interval_start:
- /* empty */
- {
- $$= NULL;
- }
- | STARTS_SYM literal
- {
- $$= $2;
- }
- ;
-
-/*
- End of partition parser part
-*/
-
-opt_as:
- /* empty */ {}
- | AS {}
- ;
-
-opt_create_database_options:
- /* empty */ {}
- | create_database_options {}
- ;
-
-create_database_options:
- create_database_option {}
- | create_database_options create_database_option {}
- ;
-
-create_database_option:
- default_collation {}
- | default_charset {}
- | COMMENT_SYM opt_equal TEXT_STRING_sys
- {
- Lex->create_info.schema_comment= thd->make_clex_string($3);
- Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT;
- }
- ;
-
-opt_if_not_exists_table_element:
- /* empty */
- {
- Lex->check_exists= FALSE;
- }
- | IF_SYM not EXISTS
- {
- Lex->check_exists= TRUE;
- }
- ;
-
-opt_if_not_exists:
- /* empty */
- {
- $$.init();
- }
- | IF_SYM not EXISTS
- {
- $$.set(DDL_options_st::OPT_IF_NOT_EXISTS);
- }
- ;
-
-create_or_replace:
- CREATE /* empty */
- {
- $$.init();
- }
- | CREATE OR_SYM REPLACE
- {
- $$.set(DDL_options_st::OPT_OR_REPLACE);
- }
- ;
-
-opt_create_table_options:
- /* empty */
- | create_table_options
- ;
-
-create_table_options_space_separated:
- create_table_option
- | create_table_option create_table_options_space_separated
- ;
-
-create_table_options:
- create_table_option
- | create_table_option create_table_options
- | create_table_option ',' create_table_options
- ;
-
-create_table_option:
- ENGINE_SYM opt_equal ident_or_text
- {
- LEX *lex= Lex;
- if (!lex->m_sql_cmd)
- {
- DBUG_ASSERT(lex->sql_command == SQLCOM_ALTER_TABLE);
- if (!(lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table()))
- MYSQL_YYABORT;
- }
- Storage_engine_name *opt=
- lex->m_sql_cmd->option_storage_engine_name();
- DBUG_ASSERT(opt); // Expect a proper Sql_cmd
- *opt= Storage_engine_name($3);
- lex->create_info.used_fields|= HA_CREATE_USED_ENGINE;
- }
- | MAX_ROWS opt_equal ulonglong_num
- {
- Lex->create_info.max_rows= $3;
- Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;
- }
- | MIN_ROWS opt_equal ulonglong_num
- {
- Lex->create_info.min_rows= $3;
- Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;
- }
- | AVG_ROW_LENGTH opt_equal ulong_num
- {
- Lex->create_info.avg_row_length=$3;
- Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;
- }
- | PASSWORD_SYM opt_equal TEXT_STRING_sys
- {
- Lex->create_info.password=$3.str;
- Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD;
- }
- | COMMENT_SYM opt_equal TEXT_STRING_sys
- {
- Lex->create_info.comment=$3;
- Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT;
- }
- | AUTO_INC opt_equal ulonglong_num
- {
- Lex->create_info.auto_increment_value=$3;
- Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;
- }
- | PACK_KEYS_SYM opt_equal ulong_num
- {
- switch($3) {
- case 0:
- Lex->create_info.table_options|= HA_OPTION_NO_PACK_KEYS;
- break;
- case 1:
- Lex->create_info.table_options|= HA_OPTION_PACK_KEYS;
- break;
- default:
- thd->parse_error();
- MYSQL_YYABORT;
- }
- Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
- }
- | PACK_KEYS_SYM opt_equal DEFAULT
- {
- Lex->create_info.table_options&=
- ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
- Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
- }
- | STATS_AUTO_RECALC_SYM opt_equal ulong_num
- {
- switch($3) {
- case 0:
- Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_OFF;
- break;
- case 1:
- Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_ON;
- break;
- default:
- thd->parse_error();
- MYSQL_YYABORT;
- }
- Lex->create_info.used_fields|= HA_CREATE_USED_STATS_AUTO_RECALC;
- }
- | STATS_AUTO_RECALC_SYM opt_equal DEFAULT
- {
- Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_DEFAULT;
- Lex->create_info.used_fields|= HA_CREATE_USED_STATS_AUTO_RECALC;
- }
- | STATS_PERSISTENT_SYM opt_equal ulong_num
- {
- switch($3) {
- case 0:
- Lex->create_info.table_options|= HA_OPTION_NO_STATS_PERSISTENT;
- break;
- case 1:
- Lex->create_info.table_options|= HA_OPTION_STATS_PERSISTENT;
- break;
- default:
- thd->parse_error();
- MYSQL_YYABORT;
- }
- Lex->create_info.used_fields|= HA_CREATE_USED_STATS_PERSISTENT;
- }
- | STATS_PERSISTENT_SYM opt_equal DEFAULT
- {
- Lex->create_info.table_options&=
- ~(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT);
- Lex->create_info.used_fields|= HA_CREATE_USED_STATS_PERSISTENT;
- }
- | STATS_SAMPLE_PAGES_SYM opt_equal ulong_num
- {
- /* From user point of view STATS_SAMPLE_PAGES can be specified as
- STATS_SAMPLE_PAGES=N (where 0<N<=65535, it does not make sense to
- scan 0 pages) or STATS_SAMPLE_PAGES=default. Internally we record
- =default as 0. See create_frm() in sql/table.cc, we use only two
- bytes for stats_sample_pages and this is why we do not allow
- larger values. 65535 pages, 16kb each means to sample 1GB, which
- is impractical. If at some point this needs to be extended, then
- we can store the higher bits from stats_sample_pages in .frm too. */
- if (unlikely($3 == 0 || $3 > 0xffff))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- Lex->create_info.stats_sample_pages=$3;
- Lex->create_info.used_fields|= HA_CREATE_USED_STATS_SAMPLE_PAGES;
- }
- | STATS_SAMPLE_PAGES_SYM opt_equal DEFAULT
- {
- Lex->create_info.stats_sample_pages=0;
- Lex->create_info.used_fields|= HA_CREATE_USED_STATS_SAMPLE_PAGES;
- }
- | CHECKSUM_SYM opt_equal ulong_num
- {
- Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM;
- Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM;
- }
- | TABLE_CHECKSUM_SYM opt_equal ulong_num
- {
- Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM;
- Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM;
- }
- | PAGE_CHECKSUM_SYM opt_equal choice
- {
- Lex->create_info.used_fields|= HA_CREATE_USED_PAGE_CHECKSUM;
- Lex->create_info.page_checksum= $3;
- }
- | DELAY_KEY_WRITE_SYM opt_equal ulong_num
- {
- Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE;
- Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE;
- }
- | ROW_FORMAT_SYM opt_equal row_types
- {
- Lex->create_info.row_type= $3;
- Lex->create_info.used_fields|= HA_CREATE_USED_ROW_FORMAT;
- }
- | UNION_SYM opt_equal
- {
- Lex->first_select_lex()->table_list.save_and_clear(&Lex->save_list);
- }
- '(' opt_table_list ')'
- {
- /*
- Move the union list to the merge_list and exclude its tables
- from the global list.
- */
- LEX *lex=Lex;
- lex->create_info.merge_list= lex->first_select_lex()->table_list.first;
- lex->first_select_lex()->table_list= lex->save_list;
- /*
- When excluding union list from the global list we assume that
- elements of the former immediately follow elements which represent
- table being created/altered and parent tables.
- */
- TABLE_LIST *last_non_sel_table= lex->create_last_non_select_table;
- DBUG_ASSERT(last_non_sel_table->next_global ==
- lex->create_info.merge_list);
- last_non_sel_table->next_global= 0;
- Lex->query_tables_last= &last_non_sel_table->next_global;
-
- lex->create_info.used_fields|= HA_CREATE_USED_UNION;
- }
- | default_charset
- | default_collation
- | INSERT_METHOD opt_equal merge_insert_types
- {
- Lex->create_info.merge_insert_method= $3;
- Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;
- }
- | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
- {
- Lex->create_info.data_file_name= $4.str;
- Lex->create_info.used_fields|= HA_CREATE_USED_DATADIR;
- }
- | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
- {
- Lex->create_info.index_file_name= $4.str;
- Lex->create_info.used_fields|= HA_CREATE_USED_INDEXDIR;
- }
- | TABLESPACE ident
- {Lex->create_info.tablespace= $2.str;}
- | STORAGE_SYM DISK_SYM
- {Lex->create_info.storage_media= HA_SM_DISK;}
- | STORAGE_SYM MEMORY_SYM
- {Lex->create_info.storage_media= HA_SM_MEMORY;}
- | CONNECTION_SYM opt_equal TEXT_STRING_sys
- {
- Lex->create_info.connect_string.str= $3.str;
- Lex->create_info.connect_string.length= $3.length;
- Lex->create_info.used_fields|= HA_CREATE_USED_CONNECTION;
- }
- | KEY_BLOCK_SIZE opt_equal ulong_num
- {
- Lex->create_info.used_fields|= HA_CREATE_USED_KEY_BLOCK_SIZE;
- Lex->create_info.key_block_size= $3;
- }
- | TRANSACTIONAL_SYM opt_equal choice
- {
- Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
- Lex->create_info.transactional= $3;
- }
- | IDENT_sys equal TEXT_STRING_sys
- {
- if (unlikely($3.length > ENGINE_OPTION_MAX_LENGTH))
- my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
- (void) new (thd->mem_root)
- engine_option_value($1, $3, true,
- &Lex->create_info.option_list,
- &Lex->option_list_last);
- }
- | IDENT_sys equal ident
- {
- if (unlikely($3.length > ENGINE_OPTION_MAX_LENGTH))
- my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
- (void) new (thd->mem_root)
- engine_option_value($1, $3, false,
- &Lex->create_info.option_list,
- &Lex->option_list_last);
- }
- | IDENT_sys equal real_ulonglong_num
- {
- (void) new (thd->mem_root)
- engine_option_value($1, $3, &Lex->create_info.option_list,
- &Lex->option_list_last, thd->mem_root);
- }
- | IDENT_sys equal DEFAULT
- {
- (void) new (thd->mem_root)
- engine_option_value($1, &Lex->create_info.option_list,
- &Lex->option_list_last);
- }
- | SEQUENCE_SYM opt_equal choice
- {
- Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
- Lex->create_info.sequence= ($3 == HA_CHOICE_YES);
- }
- | versioning_option
- ;
-
-opt_versioning_option:
- /* empty */
- | versioning_option
- ;
-
-versioning_option:
- WITH_SYSTEM_SYM VERSIONING_SYM
- {
- if (unlikely(Lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
- {
- if (DBUG_EVALUATE_IF("sysvers_force", 0, 1))
- {
- my_error(ER_VERS_NOT_SUPPORTED, MYF(0), "CREATE TEMPORARY TABLE");
- MYSQL_YYABORT;
- }
- }
- else
- {
- Lex->alter_info.flags|= ALTER_ADD_SYSTEM_VERSIONING;
- Lex->create_info.options|= HA_VERSIONED_TABLE;
- }
- }
- ;
-
-default_charset:
- opt_default charset opt_equal charset_name_or_default
- {
- if (unlikely(Lex->create_info.add_table_option_default_charset($4)))
- MYSQL_YYABORT;
- }
- ;
-
-default_collation:
- opt_default COLLATE_SYM opt_equal collation_name_or_default
- {
- HA_CREATE_INFO *cinfo= &Lex->create_info;
- if (unlikely((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
- cinfo->default_table_charset && $4 &&
- !($4= merge_charset_and_collation(cinfo->default_table_charset,
- $4))))
- MYSQL_YYABORT;
-
- Lex->create_info.default_table_charset= $4;
- Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
- }
- ;
-
-storage_engines:
- ident_or_text
- {
- if (Storage_engine_name($1).
- resolve_storage_engine_with_error(thd, &$$,
- thd->lex->create_info.tmp_table()))
- MYSQL_YYABORT;
- }
- ;
-
-known_storage_engines:
- ident_or_text
- {
- plugin_ref plugin;
- if (likely((plugin= ha_resolve_by_name(thd, &$1, false))))
- $$= plugin_hton(plugin);
- else
- my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
- }
- ;
-
-row_types:
- DEFAULT { $$= ROW_TYPE_DEFAULT; }
- | FIXED_SYM { $$= ROW_TYPE_FIXED; }
- | DYNAMIC_SYM { $$= ROW_TYPE_DYNAMIC; }
- | COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; }
- | REDUNDANT_SYM { $$= ROW_TYPE_REDUNDANT; }
- | COMPACT_SYM { $$= ROW_TYPE_COMPACT; }
- | PAGE_SYM { $$= ROW_TYPE_PAGE; }
- ;
-
-merge_insert_types:
- NO_SYM { $$= MERGE_INSERT_DISABLED; }
- | FIRST_SYM { $$= MERGE_INSERT_TO_FIRST; }
- | LAST_SYM { $$= MERGE_INSERT_TO_LAST; }
- ;
-
-udf_type:
- STRING_SYM {$$ = (int) STRING_RESULT; }
- | REAL {$$ = (int) REAL_RESULT; }
- | DECIMAL_SYM {$$ = (int) DECIMAL_RESULT; }
- | INT_SYM {$$ = (int) INT_RESULT; }
- ;
-
-
-create_field_list:
- field_list
- {
- Lex->create_last_non_select_table= Lex->last_table();
- }
- ;
-
-create_field_list_parens:
- LEFT_PAREN_ALT field_list ')'
- {
- Lex->create_last_non_select_table= Lex->last_table();
- }
- ;
-
-field_list:
- field_list_item
- | field_list ',' field_list_item
- ;
-
-field_list_item:
- column_def { }
- | key_def
- | constraint_def
- | period_for_system_time
- | PERIOD_SYM period_for_application_time { }
- ;
-
-column_def:
- field_spec
- { $$= $1; }
- | field_spec opt_constraint references
- {
- if (unlikely(Lex->add_column_foreign_key(&($1->field_name), &$2,
- $3, DDL_options())))
- MYSQL_YYABORT;
- $$= $1;
- }
- ;
-
-key_def:
- key_or_index opt_if_not_exists opt_ident opt_USING_key_algorithm
- {
- Lex->option_list= NULL;
- if (unlikely(Lex->add_key(Key::MULTIPLE, &$3, $4, $2)))
- MYSQL_YYABORT;
- }
- '(' key_list ')' normal_key_options { }
- | key_or_index opt_if_not_exists ident TYPE_SYM btree_or_rtree
- {
- Lex->option_list= NULL;
- if (unlikely(Lex->add_key(Key::MULTIPLE, &$3, $5, $2)))
- MYSQL_YYABORT;
- }
- '(' key_list ')' normal_key_options { }
- | fulltext opt_key_or_index opt_if_not_exists opt_ident
- {
- Lex->option_list= NULL;
- if (unlikely(Lex->add_key($1, &$4, HA_KEY_ALG_UNDEF, $3)))
- MYSQL_YYABORT;
- }
- '(' key_list ')' fulltext_key_options { }
- | spatial opt_key_or_index opt_if_not_exists opt_ident
- {
- Lex->option_list= NULL;
- if (unlikely(Lex->add_key($1, &$4, HA_KEY_ALG_UNDEF, $3)))
- MYSQL_YYABORT;
- }
- '(' key_list ')' spatial_key_options { }
- | opt_constraint constraint_key_type
- opt_if_not_exists opt_ident
- opt_USING_key_algorithm
- {
- Lex->option_list= NULL;
- if (unlikely(Lex->add_key($2, $4.str ? &$4 : &$1, $5, $3)))
- MYSQL_YYABORT;
- }
- '(' key_list ')' normal_key_options { }
- | opt_constraint constraint_key_type opt_if_not_exists ident
- TYPE_SYM btree_or_rtree
- {
- Lex->option_list= NULL;
- if (unlikely(Lex->add_key($2, $4.str ? &$4 : &$1, $6, $3)))
- MYSQL_YYABORT;
- }
- '(' key_list ')' normal_key_options { }
- | opt_constraint FOREIGN KEY_SYM opt_if_not_exists opt_ident
- {
- if (unlikely(Lex->check_add_key($4)) ||
- unlikely(!(Lex->last_key= (new (thd->mem_root)
- Key(Key::MULTIPLE,
- $1.str ? &$1 : &$5,
- HA_KEY_ALG_UNDEF, true, $4)))))
- MYSQL_YYABORT;
- Lex->option_list= NULL;
- }
- '(' key_list ')' references
- {
- if (unlikely(Lex->add_table_foreign_key($5.str ? &$5 : &$1,
- $1.str ? &$1 : &$5, $10, $4)))
- MYSQL_YYABORT;
- }
- ;
-
-constraint_def:
- opt_constraint check_constraint
- {
- Lex->add_constraint($1, $2, FALSE);
- }
- ;
-
-period_for_system_time:
- // If FOR_SYM is followed by SYSTEM_TIME_SYM then they are merged to: FOR_SYSTEM_TIME_SYM .
- PERIOD_SYM FOR_SYSTEM_TIME_SYM '(' ident ',' ident ')'
- {
- Vers_parse_info &info= Lex->vers_get_info();
- info.set_period($4, $6);
- }
- ;
-
-period_for_application_time:
- FOR_SYM ident '(' ident ',' ident ')'
- {
- if (Lex->add_period($2, $4, $6))
- MYSQL_YYABORT;
- }
- ;
-
-opt_check_constraint:
- /* empty */ { $$= (Virtual_column_info*) 0; }
- | check_constraint { $$= $1;}
- ;
-
-check_constraint:
- CHECK_SYM '(' expr ')'
- {
- Virtual_column_info *v= add_virtual_expression(thd, $3);
- if (unlikely(!v))
- MYSQL_YYABORT;
- $$= v;
- }
- ;
-
-opt_constraint_no_id:
- /* Empty */ {}
- | CONSTRAINT {}
- ;
-
-opt_constraint:
- /* empty */ { $$= null_clex_str; }
- | constraint { $$= $1; }
- ;
-
-constraint:
- CONSTRAINT opt_ident { $$=$2; }
- ;
-
-field_spec:
- field_ident
- {
- LEX *lex=Lex;
- Create_field *f= new (thd->mem_root) Create_field();
-
- if (unlikely(check_string_char_length(&$1, 0, NAME_CHAR_LEN,
- system_charset_info, 1)))
- my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str));
-
- if (unlikely(!f))
- MYSQL_YYABORT;
-
- lex->init_last_field(f, &$1, NULL);
- $<create_field>$= f;
- }
- field_type_or_serial opt_check_constraint
- {
- LEX *lex=Lex;
- $$= $<create_field>2;
-
- $$->check_constraint= $4;
-
- if (unlikely($$->check(thd)))
- MYSQL_YYABORT;
-
- lex->alter_info.create_list.push_back($$, thd->mem_root);
-
- $$->create_if_not_exists= Lex->check_exists;
- if ($$->flags & PRI_KEY_FLAG)
- lex->add_key_to_list(&$1, Key::PRIMARY, lex->check_exists);
- else if ($$->flags & UNIQUE_KEY_FLAG)
- lex->add_key_to_list(&$1, Key::UNIQUE, lex->check_exists);
- }
- ;
-
-field_type_or_serial:
- field_type
- {
- Lex->last_field->set_attributes(thd, $1, Lex->charset,
- COLUMN_DEFINITION_TABLE_FIELD);
- }
- field_def
- | SERIAL_SYM
- {
- Lex->last_field->set_handler(&type_handler_ulonglong);
- Lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG
- | UNSIGNED_FLAG | UNIQUE_KEY_FLAG;
- }
- opt_serial_attribute
- ;
-
-opt_serial_attribute:
- /* empty */ {}
- | opt_serial_attribute_list {}
- ;
-
-opt_serial_attribute_list:
- opt_serial_attribute_list serial_attribute {}
- | serial_attribute
- ;
-
-opt_asrow_attribute:
- /* empty */ {}
- | opt_asrow_attribute_list {}
- ;
-
-opt_asrow_attribute_list:
- opt_asrow_attribute_list asrow_attribute {}
- | asrow_attribute
- ;
-
-field_def:
- /* empty */ { }
- | attribute_list
- | attribute_list compressed_deprecated_column_attribute
- | attribute_list compressed_deprecated_column_attribute attribute_list
- | opt_generated_always AS virtual_column_func
- {
- Lex->last_field->vcol_info= $3;
- Lex->last_field->flags&= ~NOT_NULL_FLAG; // undo automatic NOT NULL for timestamps
- }
- vcol_opt_specifier vcol_opt_attribute
- | opt_generated_always AS ROW_SYM START_SYM opt_asrow_attribute
- {
- if (Lex->last_field_generated_always_as_row_start())
- MYSQL_YYABORT;
- }
- | opt_generated_always AS ROW_SYM END opt_asrow_attribute
- {
- if (Lex->last_field_generated_always_as_row_end())
- MYSQL_YYABORT;
- }
- ;
-
-opt_generated_always:
- /* empty */ {}
- | GENERATED_SYM ALWAYS_SYM {}
- ;
-
-vcol_opt_specifier:
- /* empty */
- {
- Lex->last_field->vcol_info->set_stored_in_db_flag(FALSE);
- }
- | VIRTUAL_SYM
- {
- Lex->last_field->vcol_info->set_stored_in_db_flag(FALSE);
- }
- | PERSISTENT_SYM
- {
- Lex->last_field->vcol_info->set_stored_in_db_flag(TRUE);
- }
- | STORED_SYM
- {
- Lex->last_field->vcol_info->set_stored_in_db_flag(TRUE);
- }
- ;
-
-vcol_opt_attribute:
- /* empty */ {}
- | vcol_opt_attribute_list {}
- ;
-
-vcol_opt_attribute_list:
- vcol_opt_attribute_list vcol_attribute {}
- | vcol_attribute
- ;
-
-vcol_attribute:
- UNIQUE_SYM
- {
- LEX *lex=Lex;
- lex->last_field->flags|= UNIQUE_KEY_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
- }
- | UNIQUE_SYM KEY_SYM
- {
- LEX *lex=Lex;
- lex->last_field->flags|= UNIQUE_KEY_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
- }
- | COMMENT_SYM TEXT_STRING_sys { Lex->last_field->comment= $2; }
- | INVISIBLE_SYM
- {
- Lex->last_field->invisible= INVISIBLE_USER;
- }
- ;
-
-parse_vcol_expr:
- PARSE_VCOL_EXPR_SYM
- {
- /*
- "PARSE_VCOL_EXPR" can only be used by the SQL server
- when reading a '*.frm' file.
- Prevent the end user from invoking this command.
- */
- MYSQL_YYABORT_UNLESS(Lex->parse_vcol_expr);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- expr
- {
- Virtual_column_info *v= add_virtual_expression(thd, $3);
- if (unlikely(!v))
- MYSQL_YYABORT;
- Lex->last_field->vcol_info= v;
- Lex->pop_select(); //main select
- }
- ;
-
-parenthesized_expr:
- expr
- | expr ',' expr_list
- {
- $3->push_front($1, thd->mem_root);
- $$= new (thd->mem_root) Item_row(thd, *$3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-virtual_column_func:
- '(' parenthesized_expr ')'
- {
- Virtual_column_info *v=
- add_virtual_expression(thd, $2);
- if (unlikely(!v))
- MYSQL_YYABORT;
- $$= v;
- }
- | subquery
- {
- Item *item;
- if (!(item= new (thd->mem_root) Item_singlerow_subselect(thd, $1)))
- MYSQL_YYABORT;
- Virtual_column_info *v= add_virtual_expression(thd, item);
- if (unlikely(!v))
- MYSQL_YYABORT;
- $$= v;
- }
- ;
-
-expr_or_literal: column_default_non_parenthesized_expr | signed_literal ;
-
-column_default_expr:
- virtual_column_func
- | expr_or_literal
- {
- if (unlikely(!($$= add_virtual_expression(thd, $1))))
- MYSQL_YYABORT;
- }
- ;
-
-field_type:
- field_type_numeric
- | field_type_temporal
- | field_type_string
- | field_type_lob
- | field_type_misc
- | IDENT_sys float_options srid_option
- {
- if (Lex->set_field_type_udt(&$$, $1, $2))
- MYSQL_YYABORT;
- }
- | reserved_keyword_udt float_options srid_option
- {
- if (Lex->set_field_type_udt(&$$, $1, $2))
- MYSQL_YYABORT;
- }
- | non_reserved_keyword_udt float_options srid_option
- {
- if (Lex->set_field_type_udt(&$$, $1, $2))
- MYSQL_YYABORT;
- }
- ;
-
-field_type_numeric:
- int_type opt_field_length last_field_options
- {
- $$.set_handler_length_flags($1, $2, (uint32) $3);
- }
- | real_type opt_precision last_field_options { $$.set($1, $2); }
- | FLOAT_SYM float_options last_field_options
- {
- $$.set(&type_handler_float, $2);
- if ($2.length() && !$2.dec())
- {
- int err;
- ulonglong tmp_length= my_strtoll10($2.length(), NULL, &err);
- if (unlikely(err || tmp_length > PRECISION_FOR_DOUBLE))
- my_yyabort_error((ER_WRONG_FIELD_SPEC, MYF(0),
- Lex->last_field->field_name.str));
- if (tmp_length > PRECISION_FOR_FLOAT)
- $$.set(&type_handler_double);
- else
- $$.set(&type_handler_float);
- }
- }
- | BIT_SYM opt_field_length
- {
- $$.set(&type_handler_bit, $2);
- }
- | BOOL_SYM
- {
- $$.set(&type_handler_stiny, "1");
- }
- | BOOLEAN_SYM
- {
- $$.set(&type_handler_stiny, "1");
- }
- | DECIMAL_SYM float_options last_field_options
- { $$.set(&type_handler_newdecimal, $2);}
- | NUMBER_ORACLE_SYM float_options last_field_options
- {
- if ($2.length() != 0)
- $$.set(&type_handler_newdecimal, $2);
- else
- $$.set(&type_handler_double);
- }
- | NUMERIC_SYM float_options last_field_options
- { $$.set(&type_handler_newdecimal, $2);}
- | FIXED_SYM float_options last_field_options
- { $$.set(&type_handler_newdecimal, $2);}
- ;
-
-
-opt_binary_and_compression:
- /* empty */
- | binary
- | binary compressed_deprecated_data_type_attribute
- | compressed opt_binary
- ;
-
-field_type_string:
- char opt_field_length opt_binary
- {
- $$.set(&type_handler_string, $2);
- }
- | nchar opt_field_length opt_bin_mod
- {
- $$.set(&type_handler_string, $2);
- bincmp_collation(national_charset_info, $3);
- }
- | BINARY opt_field_length
- {
- Lex->charset=&my_charset_bin;
- $$.set(&type_handler_string, $2);
- }
- | varchar opt_field_length opt_binary_and_compression
- {
- $$.set(&type_handler_varchar, $2);
- }
- | VARCHAR2_ORACLE_SYM opt_field_length opt_binary_and_compression
- {
- $$.set(&type_handler_varchar, $2);
- }
- | nvarchar opt_field_length opt_compressed opt_bin_mod
- {
- $$.set(&type_handler_varchar, $2);
- bincmp_collation(national_charset_info, $4);
- }
- | VARBINARY opt_field_length opt_compressed
- {
- Lex->charset=&my_charset_bin;
- $$.set(&type_handler_varchar, $2);
- }
- | RAW_ORACLE_SYM opt_field_length opt_compressed
- {
- Lex->charset= &my_charset_bin;
- $$.set(&type_handler_varchar, $2);
- }
- ;
-
-field_type_temporal:
- YEAR_SYM opt_field_length last_field_options
- {
- if ($2)
- {
- errno= 0;
- ulong length= strtoul($2, NULL, 10);
- if (errno == 0 && length <= MAX_FIELD_BLOBLENGTH && length != 4)
- {
- char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1];
- my_snprintf(buff, sizeof(buff), "YEAR(%lu)", length);
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
- ER_WARN_DEPRECATED_SYNTAX,
- ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
- buff, "YEAR(4)");
- }
- }
- $$.set(&type_handler_year, $2);
- }
- | DATE_SYM { $$.set(thd->type_handler_for_date()); }
- | TIME_SYM opt_field_length
- {
- $$.set(opt_mysql56_temporal_format ?
- static_cast<const Type_handler*>(&type_handler_time2) :
- static_cast<const Type_handler*>(&type_handler_time),
- $2);
- }
- | TIMESTAMP opt_field_length
- {
- if (thd->variables.sql_mode & MODE_MAXDB)
- $$.set(opt_mysql56_temporal_format ?
- static_cast<const Type_handler*>(&type_handler_datetime2) :
- static_cast<const Type_handler*>(&type_handler_datetime),
- $2);
- else
- {
- /*
- Unlike other types TIMESTAMP fields are NOT NULL by default.
- Unless --explicit-defaults-for-timestamp is given.
- */
- if (!opt_explicit_defaults_for_timestamp)
- Lex->last_field->flags|= NOT_NULL_FLAG;
- $$.set(opt_mysql56_temporal_format ?
- static_cast<const Type_handler*>(&type_handler_timestamp2):
- static_cast<const Type_handler*>(&type_handler_timestamp),
- $2);
- }
- }
- | DATETIME opt_field_length
- {
- $$.set(opt_mysql56_temporal_format ?
- static_cast<const Type_handler*>(&type_handler_datetime2) :
- static_cast<const Type_handler*>(&type_handler_datetime),
- $2);
- }
- ;
-
-
-field_type_lob:
- TINYBLOB opt_compressed
- {
- Lex->charset=&my_charset_bin;
- $$.set(&type_handler_tiny_blob);
- }
- | BLOB_MARIADB_SYM opt_field_length opt_compressed
- {
- Lex->charset=&my_charset_bin;
- $$.set(&type_handler_blob, $2);
- }
- | BLOB_ORACLE_SYM field_length opt_compressed
- {
- Lex->charset=&my_charset_bin;
- $$.set(&type_handler_blob, $2);
- }
- | BLOB_ORACLE_SYM opt_compressed
- {
- Lex->charset=&my_charset_bin;
- $$.set(&type_handler_long_blob);
- }
- | MEDIUMBLOB opt_compressed
- {
- Lex->charset=&my_charset_bin;
- $$.set(&type_handler_medium_blob);
- }
- | LONGBLOB opt_compressed
- {
- Lex->charset=&my_charset_bin;
- $$.set(&type_handler_long_blob);
- }
- | LONG_SYM VARBINARY opt_compressed
- {
- Lex->charset=&my_charset_bin;
- $$.set(&type_handler_medium_blob);
- }
- | LONG_SYM varchar opt_binary_and_compression
- { $$.set(&type_handler_medium_blob); }
- | TINYTEXT opt_binary_and_compression
- { $$.set(&type_handler_tiny_blob); }
- | TEXT_SYM opt_field_length opt_binary_and_compression
- { $$.set(&type_handler_blob, $2); }
- | MEDIUMTEXT opt_binary_and_compression
- { $$.set(&type_handler_medium_blob); }
- | LONGTEXT opt_binary_and_compression
- { $$.set(&type_handler_long_blob); }
- | CLOB_ORACLE_SYM opt_binary_and_compression
- { $$.set(&type_handler_long_blob); }
- | LONG_SYM opt_binary_and_compression
- { $$.set(&type_handler_medium_blob); }
- | JSON_SYM opt_compressed
- {
- Lex->charset= &my_charset_utf8mb4_bin;
- $$.set(&type_handler_json_longtext);
- }
- ;
-
-field_type_misc:
- ENUM '(' string_list ')' opt_binary
- { $$.set(&type_handler_enum); }
- | SET '(' string_list ')' opt_binary
- { $$.set(&type_handler_set); }
- ;
-
-char:
- CHAR_SYM {}
- ;
-
-nchar:
- NCHAR_SYM {}
- | NATIONAL_SYM CHAR_SYM {}
- ;
-
-varchar:
- char VARYING {}
- | VARCHAR {}
- ;
-
-nvarchar:
- NATIONAL_SYM VARCHAR {}
- | NVARCHAR_SYM {}
- | NCHAR_SYM VARCHAR {}
- | NATIONAL_SYM CHAR_SYM VARYING {}
- | NCHAR_SYM VARYING {}
- ;
-
-int_type:
- INT_SYM { $$= &type_handler_slong; }
- | TINYINT { $$= &type_handler_stiny; }
- | SMALLINT { $$= &type_handler_sshort; }
- | MEDIUMINT { $$= &type_handler_sint24; }
- | BIGINT { $$= &type_handler_slonglong; }
- ;
-
-real_type:
- REAL
- {
- $$= thd->variables.sql_mode & MODE_REAL_AS_FLOAT ?
- static_cast<const Type_handler *>(&type_handler_float) :
- static_cast<const Type_handler *>(&type_handler_double);
- }
- | DOUBLE_SYM { $$= &type_handler_double; }
- | DOUBLE_SYM PRECISION { $$= &type_handler_double; }
- ;
-
-srid_option:
- /* empty */
- { Lex->last_field->srid= 0; }
- |
- REF_SYSTEM_ID_SYM '=' NUM
- {
- Lex->last_field->srid=atoi($3.str);
- }
- ;
-
-float_options:
- /* empty */ { $$.set(0, 0); }
- | field_length { $$.set($1, 0); }
- | precision { $$= $1; }
- ;
-
-precision:
- '(' NUM ',' NUM ')' { $$.set($2.str, $4.str); }
- ;
-
-field_options:
- /* empty */ { $$= 0; }
- | SIGNED_SYM { $$= 0; }
- | UNSIGNED { $$= UNSIGNED_FLAG; }
- | ZEROFILL { $$= UNSIGNED_FLAG | ZEROFILL_FLAG; }
- | UNSIGNED ZEROFILL { $$= UNSIGNED_FLAG | ZEROFILL_FLAG; }
- | ZEROFILL UNSIGNED { $$= UNSIGNED_FLAG | ZEROFILL_FLAG; }
- ;
-
-last_field_options:
- field_options { Lex->last_field->flags|= ($$= $1); }
- ;
-
-field_length:
- '(' LONG_NUM ')' { $$= $2.str; }
- | '(' ULONGLONG_NUM ')' { $$= $2.str; }
- | '(' DECIMAL_NUM ')' { $$= $2.str; }
- | '(' NUM ')' { $$= $2.str; }
- ;
-
-opt_field_length:
- /* empty */ { $$= (char*) 0; /* use default length */ }
- | field_length { $$= $1; }
- ;
-
-opt_precision:
- /* empty */ { $$.set(0, 0); }
- | precision { $$= $1; }
- ;
-
-
-attribute_list:
- attribute_list attribute {}
- | attribute
- ;
-
-attribute:
- NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; }
- | DEFAULT column_default_expr { Lex->last_field->default_value= $2; }
- | ON UPDATE_SYM NOW_SYM opt_default_time_precision
- {
- Item *item= new (thd->mem_root) Item_func_now_local(thd, $4);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- Lex->last_field->on_update= item;
- }
- | AUTO_INC { Lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
- | SERIAL_SYM DEFAULT VALUE_SYM
- {
- LEX *lex=Lex;
- lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_KEY_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
- }
- | COLLATE_SYM collation_name
- {
- if (unlikely(Lex->charset && !my_charset_same(Lex->charset,$2)))
- my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- $2->name,Lex->charset->csname));
- Lex->last_field->charset= $2;
- }
- | serial_attribute
- ;
-
-opt_compression_method:
- /* empty */ { $$= NULL; }
- | equal ident { $$= $2.str; }
- ;
-
-opt_compressed:
- /* empty */ {}
- | compressed { }
- ;
-
-compressed:
- COMPRESSED_SYM opt_compression_method
- {
- if (unlikely(Lex->last_field->set_compressed($2)))
- MYSQL_YYABORT;
- }
- ;
-
-compressed_deprecated_data_type_attribute:
- COMPRESSED_SYM opt_compression_method
- {
- if (unlikely(Lex->last_field->set_compressed_deprecated(thd, $2)))
- MYSQL_YYABORT;
- }
- ;
-
-compressed_deprecated_column_attribute:
- COMPRESSED_SYM opt_compression_method
- {
- if (unlikely(Lex->last_field->
- set_compressed_deprecated_column_attribute(thd, $1.pos(), $2)))
- MYSQL_YYABORT;
- }
- ;
-
-asrow_attribute:
- not NULL_SYM
- {
- Lex->last_field->flags|= NOT_NULL_FLAG;
- }
- | opt_primary KEY_SYM
- {
- LEX *lex=Lex;
- lex->last_field->flags|= PRI_KEY_FLAG | NOT_NULL_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
- }
- | vcol_attribute
- ;
-
-serial_attribute:
- asrow_attribute
- | IDENT_sys equal TEXT_STRING_sys
- {
- if (unlikely($3.length > ENGINE_OPTION_MAX_LENGTH))
- my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
- (void) new (thd->mem_root)
- engine_option_value($1, $3, true,
- &Lex->last_field->option_list,
- &Lex->option_list_last);
- }
- | IDENT_sys equal ident
- {
- if (unlikely($3.length > ENGINE_OPTION_MAX_LENGTH))
- my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
- (void) new (thd->mem_root)
- engine_option_value($1, $3, false,
- &Lex->last_field->option_list,
- &Lex->option_list_last);
- }
- | IDENT_sys equal real_ulonglong_num
- {
- (void) new (thd->mem_root)
- engine_option_value($1, $3, &Lex->last_field->option_list,
- &Lex->option_list_last, thd->mem_root);
- }
- | IDENT_sys equal DEFAULT
- {
- (void) new (thd->mem_root)
- engine_option_value($1, &Lex->last_field->option_list,
- &Lex->option_list_last);
- }
- | with_or_without_system VERSIONING_SYM
- {
- Lex->last_field->versioning= $1;
- Lex->create_info.options|= HA_VERSIONED_TABLE;
- if (Lex->alter_info.flags & ALTER_DROP_SYSTEM_VERSIONING)
- {
- my_yyabort_error((ER_VERS_NOT_VERSIONED, MYF(0),
- Lex->create_last_non_select_table->table_name.str));
- }
- }
- ;
-
-with_or_without_system:
- WITH_SYSTEM_SYM
- {
- Lex->alter_info.flags|= ALTER_COLUMN_UNVERSIONED;
- Lex->create_info.vers_info.versioned_fields= true;
- $$= Column_definition::WITH_VERSIONING;
- }
- | WITHOUT SYSTEM
- {
- Lex->alter_info.flags|= ALTER_COLUMN_UNVERSIONED;
- Lex->create_info.vers_info.unversioned_fields= true;
- $$= Column_definition::WITHOUT_VERSIONING;
- }
- ;
-
-
-type_with_opt_collate:
- field_type opt_collate
- {
- $$= $1;
-
- if ($2)
- {
- if (unlikely(!(Lex->charset= merge_charset_and_collation(Lex->charset, $2))))
- MYSQL_YYABORT;
- }
- }
- ;
-
-charset:
- CHAR_SYM SET { $$= $1; }
- | CHARSET { $$= $1; }
- ;
-
-charset_name:
- ident_or_text
- {
- if (unlikely(!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0)))))
- my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
- }
- | BINARY { $$= &my_charset_bin; }
- ;
-
-charset_name_or_default:
- charset_name { $$=$1; }
- | DEFAULT { $$=NULL; }
- ;
-
-opt_load_data_charset:
- /* Empty */ { $$= NULL; }
- | charset charset_name_or_default { $$= $2; }
- ;
-
-old_or_new_charset_name:
- ident_or_text
- {
- if (unlikely(!($$=get_charset_by_csname($1.str,
- MY_CS_PRIMARY,MYF(0))) &&
- !($$=get_old_charset_by_name($1.str))))
- my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
- }
- | BINARY { $$= &my_charset_bin; }
- ;
-
-old_or_new_charset_name_or_default:
- old_or_new_charset_name { $$=$1; }
- | DEFAULT { $$=NULL; }
- ;
-
-collation_name:
- ident_or_text
- {
- if (unlikely(!($$= mysqld_collation_get_by_name($1.str))))
- MYSQL_YYABORT;
- }
- ;
-
-opt_collate:
- /* empty */ { $$=NULL; }
- | COLLATE_SYM collation_name_or_default { $$=$2; }
- ;
-
-collation_name_or_default:
- collation_name { $$=$1; }
- | DEFAULT { $$=NULL; }
- ;
-
-opt_default:
- /* empty */ {}
- | DEFAULT {}
- ;
-
-charset_or_alias:
- charset charset_name { $$= $2; }
- | ASCII_SYM { $$= &my_charset_latin1; }
- | UNICODE_SYM
- {
- if (unlikely(!($$= get_charset_by_csname("ucs2", MY_CS_PRIMARY,MYF(0)))))
- my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2"));
- }
- ;
-
-opt_binary:
- /* empty */ { bincmp_collation(NULL, false); }
- | binary {}
- ;
-
-binary:
- BYTE_SYM { bincmp_collation(&my_charset_bin, false); }
- | charset_or_alias opt_bin_mod { bincmp_collation($1, $2); }
- | BINARY { bincmp_collation(NULL, true); }
- | BINARY charset_or_alias { bincmp_collation($2, true); }
- ;
-
-opt_bin_mod:
- /* empty */ { $$= false; }
- | BINARY { $$= true; }
- ;
-
-ws_nweights:
- '(' real_ulong_num
- {
- if (unlikely($2 == 0))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- }
- ')'
- { $$= $2; }
- ;
-
-ws_level_flag_desc:
- ASC { $$= 0; }
- | DESC { $$= 1 << MY_STRXFRM_DESC_SHIFT; }
- ;
-
-ws_level_flag_reverse:
- REVERSE_SYM { $$= 1 << MY_STRXFRM_REVERSE_SHIFT; } ;
-
-ws_level_flags:
- /* empty */ { $$= 0; }
- | ws_level_flag_desc { $$= $1; }
- | ws_level_flag_desc ws_level_flag_reverse { $$= $1 | $2; }
- | ws_level_flag_reverse { $$= $1 ; }
- ;
-
-ws_level_number:
- real_ulong_num
- {
- $$= $1 < 1 ? 1 : ($1 > MY_STRXFRM_NLEVELS ? MY_STRXFRM_NLEVELS : $1);
- $$--;
- }
- ;
-
-ws_level_list_item:
- ws_level_number ws_level_flags
- {
- $$= (1 | $2) << $1;
- }
- ;
-
-ws_level_list:
- ws_level_list_item { $$= $1; }
- | ws_level_list ',' ws_level_list_item { $$|= $3; }
- ;
-
-ws_level_range:
- ws_level_number '-' ws_level_number
- {
- uint start= $1;
- uint end= $3;
- for ($$= 0; start <= end; start++)
- $$|= (1 << start);
- }
- ;
-
-ws_level_list_or_range:
- ws_level_list { $$= $1; }
- | ws_level_range { $$= $1; }
- ;
-
-opt_ws_levels:
- /* empty*/ { $$= 0; }
- | LEVEL_SYM ws_level_list_or_range { $$= $2; }
- ;
-
-opt_primary:
- /* empty */
- | PRIMARY_SYM
- ;
-
-references:
- REFERENCES
- table_ident
- opt_ref_list
- opt_match_clause
- opt_on_update_delete
- {
- $$=$2;
- }
- ;
-
-opt_ref_list:
- /* empty */
- { Lex->ref_list.empty(); }
- | '(' ref_list ')'
- ;
-
-ref_list:
- ref_list ',' ident
- {
- Key_part_spec *key= new (thd->mem_root) Key_part_spec(&$3, 0);
- if (unlikely(key == NULL))
- MYSQL_YYABORT;
- Lex->ref_list.push_back(key, thd->mem_root);
- }
- | ident
- {
- Key_part_spec *key= new (thd->mem_root) Key_part_spec(&$1, 0);
- if (unlikely(key == NULL))
- MYSQL_YYABORT;
- LEX *lex= Lex;
- lex->ref_list.empty();
- lex->ref_list.push_back(key, thd->mem_root);
- }
- ;
-
-opt_match_clause:
- /* empty */
- { Lex->fk_match_option= Foreign_key::FK_MATCH_UNDEF; }
- | MATCH FULL
- { Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; }
- | MATCH PARTIAL
- { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; }
- | MATCH SIMPLE_SYM
- { Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; }
- ;
-
-opt_on_update_delete:
- /* empty */
- {
- LEX *lex= Lex;
- lex->fk_update_opt= FK_OPTION_UNDEF;
- lex->fk_delete_opt= FK_OPTION_UNDEF;
- }
- | ON UPDATE_SYM delete_option
- {
- LEX *lex= Lex;
- lex->fk_update_opt= $3;
- lex->fk_delete_opt= FK_OPTION_UNDEF;
- }
- | ON DELETE_SYM delete_option
- {
- LEX *lex= Lex;
- lex->fk_update_opt= FK_OPTION_UNDEF;
- lex->fk_delete_opt= $3;
- }
- | ON UPDATE_SYM delete_option
- ON DELETE_SYM delete_option
- {
- LEX *lex= Lex;
- lex->fk_update_opt= $3;
- lex->fk_delete_opt= $6;
- }
- | ON DELETE_SYM delete_option
- ON UPDATE_SYM delete_option
- {
- LEX *lex= Lex;
- lex->fk_update_opt= $6;
- lex->fk_delete_opt= $3;
- }
- ;
-
-delete_option:
- RESTRICT { $$= FK_OPTION_RESTRICT; }
- | CASCADE { $$= FK_OPTION_CASCADE; }
- | SET NULL_SYM { $$= FK_OPTION_SET_NULL; }
- | NO_SYM ACTION { $$= FK_OPTION_NO_ACTION; }
- | SET DEFAULT { $$= FK_OPTION_SET_DEFAULT; }
- ;
-
-constraint_key_type:
- PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; }
- | UNIQUE_SYM opt_key_or_index { $$= Key::UNIQUE; }
- ;
-
-key_or_index:
- KEY_SYM {}
- | INDEX_SYM {}
- ;
-
-opt_key_or_index:
- /* empty */ {}
- | key_or_index
- ;
-
-keys_or_index:
- KEYS {}
- | INDEX_SYM {}
- | INDEXES {}
- ;
-
-opt_unique:
- /* empty */ { $$= Key::MULTIPLE; }
- | UNIQUE_SYM { $$= Key::UNIQUE; }
- ;
-
-fulltext:
- FULLTEXT_SYM { $$= Key::FULLTEXT;}
- ;
-
-spatial:
- SPATIAL_SYM
- {
-#ifdef HAVE_SPATIAL
- $$= Key::SPATIAL;
-#else
- my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
- sym_group_geom.needed_define));
-#endif
- }
- ;
-
-normal_key_options:
- /* empty */ {}
- | normal_key_opts { Lex->last_key->option_list= Lex->option_list; }
- ;
-
-fulltext_key_options:
- /* empty */ {}
- | fulltext_key_opts { Lex->last_key->option_list= Lex->option_list; }
- ;
-
-spatial_key_options:
- /* empty */ {}
- | spatial_key_opts { Lex->last_key->option_list= Lex->option_list; }
- ;
-
-normal_key_opts:
- normal_key_opt
- | normal_key_opts normal_key_opt
- ;
-
-spatial_key_opts:
- spatial_key_opt
- | spatial_key_opts spatial_key_opt
- ;
-
-fulltext_key_opts:
- fulltext_key_opt
- | fulltext_key_opts fulltext_key_opt
- ;
-
-opt_USING_key_algorithm:
- /* Empty*/ { $$= HA_KEY_ALG_UNDEF; }
- | USING btree_or_rtree { $$= $2; }
- ;
-
-/* TYPE is a valid identifier, so it's handled differently than USING */
-opt_key_algorithm_clause:
- /* Empty*/ { $$= HA_KEY_ALG_UNDEF; }
- | USING btree_or_rtree { $$= $2; }
- | TYPE_SYM btree_or_rtree { $$= $2; }
- ;
-
-key_using_alg:
- USING btree_or_rtree
- { Lex->last_key->key_create_info.algorithm= $2; }
- | TYPE_SYM btree_or_rtree
- { Lex->last_key->key_create_info.algorithm= $2; }
- ;
-
-all_key_opt:
- KEY_BLOCK_SIZE opt_equal ulong_num
- {
- Lex->last_key->key_create_info.block_size= $3;
- Lex->last_key->key_create_info.flags|= HA_USES_BLOCK_SIZE;
- }
- | COMMENT_SYM TEXT_STRING_sys
- { Lex->last_key->key_create_info.comment= $2; }
- | IDENT_sys equal TEXT_STRING_sys
- {
- if (unlikely($3.length > ENGINE_OPTION_MAX_LENGTH))
- my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
- (void) new (thd->mem_root)
- engine_option_value($1, $3, true, &Lex->option_list,
- &Lex->option_list_last);
- }
- | IDENT_sys equal ident
- {
- if (unlikely($3.length > ENGINE_OPTION_MAX_LENGTH))
- my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
- (void) new (thd->mem_root)
- engine_option_value($1, $3, false, &Lex->option_list,
- &Lex->option_list_last);
- }
- | IDENT_sys equal real_ulonglong_num
- {
- (void) new (thd->mem_root)
- engine_option_value($1, $3, &Lex->option_list,
- &Lex->option_list_last, thd->mem_root);
- }
- | IDENT_sys equal DEFAULT
- {
- (void) new (thd->mem_root)
- engine_option_value($1, &Lex->option_list,
- &Lex->option_list_last);
- }
- ;
-
-normal_key_opt:
- all_key_opt
- | key_using_alg
- ;
-
-spatial_key_opt:
- all_key_opt
- ;
-
-fulltext_key_opt:
- all_key_opt
- | WITH PARSER_SYM IDENT_sys
- {
- if (likely(plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN)))
- Lex->last_key->key_create_info.parser_name= $3;
- else
- my_yyabort_error((ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str));
- }
- ;
-
-btree_or_rtree:
- BTREE_SYM { $$= HA_KEY_ALG_BTREE; }
- | RTREE_SYM { $$= HA_KEY_ALG_RTREE; }
- | HASH_SYM { $$= HA_KEY_ALG_HASH; }
- ;
-
-key_list:
- key_list ',' key_part order_dir
- {
- Lex->last_key->columns.push_back($3, thd->mem_root);
- }
- | key_part order_dir
- {
- Lex->last_key->columns.push_back($1, thd->mem_root);
- }
- ;
-
-key_part:
- ident
- {
- $$= new (thd->mem_root) Key_part_spec(&$1, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | ident '(' NUM ')'
- {
- int key_part_len= atoi($3.str);
- if (unlikely(!key_part_len))
- my_yyabort_error((ER_KEY_PART_0, MYF(0), $1.str));
- $$= new (thd->mem_root) Key_part_spec(&$1, (uint) key_part_len);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_ident:
- /* empty */ { $$= null_clex_str; }
- | field_ident { $$= $1; }
- ;
-
-string_list:
- text_string
- { Lex->last_field->interval_list.push_back($1, thd->mem_root); }
- | string_list ',' text_string
- { Lex->last_field->interval_list.push_back($3, thd->mem_root); }
- ;
-
-/*
-** Alter table
-*/
-
-alter:
- ALTER
- {
- Lex->name= null_clex_str;
- Lex->table_type= TABLE_TYPE_UNKNOWN;
- Lex->sql_command= SQLCOM_ALTER_TABLE;
- Lex->duplicates= DUP_ERROR;
- Lex->first_select_lex()->order_list.empty();
- Lex->create_info.init();
- Lex->create_info.row_type= ROW_TYPE_NOT_USED;
- Lex->alter_info.reset();
- Lex->no_write_to_binlog= 0;
- Lex->create_info.storage_media= HA_SM_DEFAULT;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- DBUG_ASSERT(!Lex->m_sql_cmd);
- }
- alter_options TABLE_SYM table_ident opt_lock_wait_timeout
- {
- if (!Lex->first_select_lex()->
- add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING,
- TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE))
- MYSQL_YYABORT;
- Lex->first_select_lex()->db=
- (Lex->first_select_lex()->table_list.first)->db;
- Lex->create_last_non_select_table= Lex->last_table();
- Lex->mark_first_table_as_inserting();
- }
- alter_commands
- {
- if (likely(!Lex->m_sql_cmd))
- {
- /* Create a generic ALTER TABLE statment. */
- Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table();
- if (unlikely(Lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- Lex->pop_select(); //main select
- }
- | ALTER DATABASE ident_or_empty
- {
- Lex->create_info.default_table_charset= NULL;
- Lex->create_info.schema_comment= NULL;
- Lex->create_info.used_fields= 0;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- create_database_options
- {
- LEX *lex=Lex;
- lex->sql_command=SQLCOM_ALTER_DB;
- lex->name= $3;
- if (lex->name.str == NULL &&
- unlikely(lex->copy_db_to(&lex->name)))
- MYSQL_YYABORT;
- Lex->pop_select(); //main select
- }
- | ALTER DATABASE COMMENT_SYM opt_equal TEXT_STRING_sys
- {
- Lex->create_info.default_table_charset= NULL;
- Lex->create_info.used_fields= 0;
- Lex->create_info.schema_comment= thd->make_clex_string($5);
- Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT;
- }
- opt_create_database_options
- {
- LEX *lex=Lex;
- lex->sql_command=SQLCOM_ALTER_DB;
- lex->name= Lex_ident_sys();
- if (lex->name.str == NULL &&
- unlikely(lex->copy_db_to(&lex->name)))
- MYSQL_YYABORT;
- }
- | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM
- {
- LEX *lex= Lex;
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "DATABASE"));
- lex->sql_command= SQLCOM_ALTER_DB_UPGRADE;
- lex->name= $3;
- }
- | ALTER PROCEDURE_SYM sp_name
- {
- if (Lex->stmt_alter_procedure_start($3))
- MYSQL_YYABORT;
- }
- sp_a_chistics
- stmt_end {}
- | ALTER FUNCTION_SYM sp_name
- {
- if (Lex->stmt_alter_function_start($3))
- MYSQL_YYABORT;
- }
- sp_a_chistics
- stmt_end {}
- | ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM table_ident
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- if (Lex->add_alter_view(thd, $2, $4, $6))
- MYSQL_YYABORT;
- }
- view_list_opt AS view_select stmt_end {}
- | ALTER definer_opt opt_view_suid VIEW_SYM table_ident
- /*
- We have two separate rules for ALTER VIEW rather that
- optional view_algorithm above, to resolve the ambiguity
- with the ALTER EVENT below.
- */
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))
- MYSQL_YYABORT;
- }
- view_list_opt AS view_select stmt_end {}
- | ALTER definer_opt remember_name EVENT_SYM sp_name
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- /*
- It is safe to use Lex->spname because
- ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
- is not allowed. Lex->spname is used in the case of RENAME TO
- If it had to be supported spname had to be added to
- Event_parse_data.
- */
-
- if (unlikely(!(Lex->event_parse_data= Event_parse_data::new_instance(thd))))
- MYSQL_YYABORT;
- Lex->event_parse_data->identifier= $5;
-
- Lex->sql_command= SQLCOM_ALTER_EVENT;
- Lex->stmt_definition_begin= $3;
- }
- ev_alter_on_schedule_completion
- opt_ev_rename_to
- opt_ev_status
- opt_ev_comment
- opt_ev_sql_stmt
- {
- if (unlikely(!($7 || $8 || $9 || $10 || $11)))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- /*
- sql_command is set here because some rules in ev_sql_stmt
- can overwrite it
- */
- Lex->sql_command= SQLCOM_ALTER_EVENT;
- Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr();
-
- Lex->pop_select(); //main select
- }
- | ALTER TABLESPACE alter_tablespace_info
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->ts_cmd_type= ALTER_TABLESPACE;
- }
- | ALTER LOGFILE_SYM GROUP_SYM alter_logfile_group_info
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->ts_cmd_type= ALTER_LOGFILE_GROUP;
- }
- | ALTER TABLESPACE change_tablespace_info
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->ts_cmd_type= CHANGE_FILE_TABLESPACE;
- }
- | ALTER TABLESPACE change_tablespace_access
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->ts_cmd_type= ALTER_ACCESS_MODE_TABLESPACE;
- }
- | ALTER SERVER_SYM ident_or_text
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_ALTER_SERVER;
- lex->server_options.reset($3);
- } OPTIONS_SYM '(' server_options_list ')' { }
- /* ALTER USER foo is allowed for MySQL compatibility. */
- | ALTER opt_if_exists USER_SYM clear_privileges grant_list
- opt_require_clause opt_resource_options opt_account_locking opt_password_expiration
- {
- Lex->create_info.set($2);
- Lex->sql_command= SQLCOM_ALTER_USER;
- }
- | ALTER SEQUENCE_SYM opt_if_exists
- {
- LEX *lex= Lex;
- lex->name= null_clex_str;
- lex->table_type= TABLE_TYPE_UNKNOWN;
- lex->sql_command= SQLCOM_ALTER_SEQUENCE;
- lex->create_info.init();
- lex->no_write_to_binlog= 0;
- DBUG_ASSERT(!lex->m_sql_cmd);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- table_ident
- {
- LEX *lex= Lex;
- if (!(lex->create_info.seq_create_info= new (thd->mem_root)
- sequence_definition()) ||
- !lex->first_select_lex()->
- add_table_to_list(thd, $5, NULL, TL_OPTION_SEQUENCE,
- TL_WRITE, MDL_EXCLUSIVE))
- MYSQL_YYABORT;
- }
- sequence_defs
- {
- /* Create a generic ALTER SEQUENCE statment. */
- Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence($3);
- if (unlikely(Lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- } stmt_end {}
- ;
-
-opt_account_locking:
- /* Nothing */ {}
- | ACCOUNT_SYM LOCK_SYM
- {
- Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED;
- }
- | ACCOUNT_SYM UNLOCK_SYM
- {
- Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED;
- }
- ;
-opt_password_expiration:
- /* Nothing */ {}
- | PASSWORD_SYM EXPIRE_SYM
- {
- Lex->account_options.password_expire= PASSWORD_EXPIRE_NOW;
- }
- | PASSWORD_SYM EXPIRE_SYM NEVER_SYM
- {
- Lex->account_options.password_expire= PASSWORD_EXPIRE_NEVER;
- }
- | PASSWORD_SYM EXPIRE_SYM DEFAULT
- {
- Lex->account_options.password_expire= PASSWORD_EXPIRE_DEFAULT;
- }
- | PASSWORD_SYM EXPIRE_SYM INTERVAL_SYM NUM DAY_SYM
- {
- Lex->account_options.password_expire= PASSWORD_EXPIRE_INTERVAL;
- if (!(Lex->account_options.num_expiration_days= atoi($4.str)))
- my_yyabort_error((ER_WRONG_VALUE, MYF(0), "DAY", $4.str));
- }
- ;
-
-ev_alter_on_schedule_completion:
- /* empty */ { $$= 0;}
- | ON SCHEDULE_SYM ev_schedule_time { $$= 1; }
- | ev_on_completion { $$= 1; }
- | ON SCHEDULE_SYM ev_schedule_time ev_on_completion { $$= 1; }
- ;
-
-opt_ev_rename_to:
- /* empty */ { $$= 0;}
- | RENAME TO_SYM sp_name
- {
- /*
- Use lex's spname to hold the new name.
- The original name is in the Event_parse_data object
- */
- Lex->spname= $3;
- $$= 1;
- }
- ;
-
-opt_ev_sql_stmt:
- /* empty*/ { $$= 0;}
- | DO_SYM ev_sql_stmt { $$= 1; }
- ;
-
-ident_or_empty:
- /* empty */
- %prec PREC_BELOW_IDENTIFIER_OPT_SPECIAL_CASE { $$= Lex_ident_sys(); }
- | ident
- ;
-
-alter_commands:
- /* empty */
- | DISCARD TABLESPACE
- {
- Lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_discard_import_tablespace(
- Sql_cmd_discard_import_tablespace::DISCARD_TABLESPACE);
- if (unlikely(Lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- | IMPORT TABLESPACE
- {
- Lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_discard_import_tablespace(
- Sql_cmd_discard_import_tablespace::IMPORT_TABLESPACE);
- if (unlikely(Lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- | alter_list
- opt_partitioning
- | alter_list
- remove_partitioning
- | remove_partitioning
- | partitioning
-/*
- This part was added for release 5.1 by Mikael Ronstrm.
- From here we insert a number of commands to manage the partitions of a
- partitioned table such as adding partitions, dropping partitions,
- reorganising partitions in various manners. In future releases the list
- will be longer.
-*/
- | add_partition_rule
- | DROP PARTITION_SYM opt_if_exists alt_part_name_list
- {
- Lex->alter_info.partition_flags|= ALTER_PARTITION_DROP;
- DBUG_ASSERT(!Lex->if_exists());
- Lex->create_info.add($3);
- }
- | REBUILD_SYM PARTITION_SYM opt_no_write_to_binlog
- all_or_alt_part_name_list
- {
- LEX *lex= Lex;
- lex->alter_info.partition_flags|= ALTER_PARTITION_REBUILD;
- lex->no_write_to_binlog= $3;
- }
- | OPTIMIZE PARTITION_SYM opt_no_write_to_binlog
- all_or_alt_part_name_list
- {
- LEX *lex= thd->lex;
- lex->no_write_to_binlog= $3;
- lex->check_opt.init();
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_alter_table_optimize_partition();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- opt_no_write_to_binlog
- | ANALYZE_SYM PARTITION_SYM opt_no_write_to_binlog
- all_or_alt_part_name_list
- {
- LEX *lex= thd->lex;
- lex->no_write_to_binlog= $3;
- lex->check_opt.init();
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_alter_table_analyze_partition();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- | CHECK_SYM PARTITION_SYM all_or_alt_part_name_list
- {
- LEX *lex= thd->lex;
- lex->check_opt.init();
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_alter_table_check_partition();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- opt_mi_check_type
- | REPAIR PARTITION_SYM opt_no_write_to_binlog
- all_or_alt_part_name_list
- {
- LEX *lex= thd->lex;
- lex->no_write_to_binlog= $3;
- lex->check_opt.init();
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_alter_table_repair_partition();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- opt_mi_repair_type
- | COALESCE PARTITION_SYM opt_no_write_to_binlog real_ulong_num
- {
- LEX *lex= Lex;
- lex->alter_info.partition_flags|= ALTER_PARTITION_COALESCE;
- lex->no_write_to_binlog= $3;
- lex->alter_info.num_parts= $4;
- }
- | TRUNCATE_SYM PARTITION_SYM all_or_alt_part_name_list
- {
- LEX *lex= thd->lex;
- lex->check_opt.init();
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_alter_table_truncate_partition();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- | reorg_partition_rule
- | EXCHANGE_SYM PARTITION_SYM alt_part_name_item
- WITH TABLE_SYM table_ident have_partitioning
- {
- if (Lex->stmt_alter_table_exchange_partition($6))
- MYSQL_YYABORT;
- }
- ;
-
-remove_partitioning:
- REMOVE_SYM PARTITIONING_SYM
- {
- Lex->alter_info.partition_flags|= ALTER_PARTITION_REMOVE;
- }
- ;
-
-all_or_alt_part_name_list:
- ALL
- {
- Lex->alter_info.partition_flags|= ALTER_PARTITION_ALL;
- }
- | alt_part_name_list
- ;
-
-add_partition_rule:
- ADD PARTITION_SYM opt_if_not_exists
- opt_no_write_to_binlog
- {
- LEX *lex= Lex;
- lex->part_info= new (thd->mem_root) partition_info();
- if (unlikely(!lex->part_info))
- MYSQL_YYABORT;
-
- lex->alter_info.partition_flags|= ALTER_PARTITION_ADD;
- DBUG_ASSERT(!Lex->create_info.if_not_exists());
- lex->create_info.set($3);
- lex->no_write_to_binlog= $4;
- }
- add_part_extra
- {}
- ;
-
-add_part_extra:
- /* empty */
- | '(' part_def_list ')'
- {
- LEX *lex= Lex;
- lex->part_info->num_parts= lex->part_info->partitions.elements;
- }
- | PARTITIONS_SYM real_ulong_num
- {
- Lex->part_info->num_parts= $2;
- }
- ;
-
-reorg_partition_rule:
- REORGANIZE_SYM PARTITION_SYM opt_no_write_to_binlog
- {
- LEX *lex= Lex;
- lex->part_info= new (thd->mem_root) partition_info();
- if (unlikely(!lex->part_info))
- MYSQL_YYABORT;
-
- lex->no_write_to_binlog= $3;
- }
- reorg_parts_rule
- ;
-
-reorg_parts_rule:
- /* empty */
- {
- Lex->alter_info.partition_flags|= ALTER_PARTITION_TABLE_REORG;
- }
- | alt_part_name_list
- {
- Lex->alter_info.partition_flags|= ALTER_PARTITION_REORGANIZE;
- }
- INTO '(' part_def_list ')'
- {
- partition_info *part_info= Lex->part_info;
- part_info->num_parts= part_info->partitions.elements;
- }
- ;
-
-alt_part_name_list:
- alt_part_name_item {}
- | alt_part_name_list ',' alt_part_name_item {}
- ;
-
-alt_part_name_item:
- ident
- {
- if (unlikely(Lex->alter_info.partition_names.push_back($1.str,
- thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-/*
- End of management of partition commands
-*/
-
-alter_list:
- alter_list_item
- | alter_list ',' alter_list_item
- ;
-
-add_column:
- ADD opt_column opt_if_not_exists_table_element
- ;
-
-alter_list_item:
- add_column column_def opt_place
- {
- LEX *lex=Lex;
- lex->create_last_non_select_table= lex->last_table();
- lex->alter_info.flags|= ALTER_PARSER_ADD_COLUMN;
- $2->after= $3;
- }
- | ADD key_def
- {
- Lex->create_last_non_select_table= Lex->last_table();
- Lex->alter_info.flags|= ALTER_ADD_INDEX;
- }
- | ADD period_for_system_time
- {
- Lex->alter_info.flags|= ALTER_ADD_PERIOD;
- }
- | ADD
- PERIOD_SYM opt_if_not_exists_table_element period_for_application_time
- {
- Table_period_info &period= Lex->create_info.period_info;
- period.create_if_not_exists= Lex->check_exists;
- Lex->alter_info.flags|= ALTER_ADD_CHECK_CONSTRAINT;
- }
- | add_column '(' create_field_list ')'
- {
- LEX *lex=Lex;
- lex->alter_info.flags|= ALTER_PARSER_ADD_COLUMN;
- if (!lex->alter_info.key_list.is_empty())
- lex->alter_info.flags|= ALTER_ADD_INDEX;
- }
- | ADD constraint_def
- {
- Lex->alter_info.flags|= ALTER_ADD_CHECK_CONSTRAINT;
- }
- | ADD CONSTRAINT IF_SYM not EXISTS field_ident check_constraint
- {
- Lex->alter_info.flags|= ALTER_ADD_CHECK_CONSTRAINT;
- Lex->add_constraint($6, $7, TRUE);
- }
- | CHANGE opt_column opt_if_exists_table_element field_ident
- field_spec opt_place
- {
- Lex->alter_info.flags|= ALTER_CHANGE_COLUMN | ALTER_RENAME_COLUMN;
- Lex->create_last_non_select_table= Lex->last_table();
- $5->change= $4;
- $5->after= $6;
- }
- | MODIFY_SYM opt_column opt_if_exists_table_element
- field_spec opt_place
- {
- Lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
- Lex->create_last_non_select_table= Lex->last_table();
- $4->change= $4->field_name;
- $4->after= $5;
- }
- | DROP opt_column opt_if_exists_table_element field_ident opt_restrict
- {
- LEX *lex=Lex;
- Alter_drop *ad= (new (thd->mem_root)
- Alter_drop(Alter_drop::COLUMN, $4.str, $3));
- if (unlikely(ad == NULL))
- MYSQL_YYABORT;
- lex->alter_info.drop_list.push_back(ad, thd->mem_root);
- lex->alter_info.flags|= ALTER_PARSER_DROP_COLUMN;
- }
- | DROP CONSTRAINT opt_if_exists_table_element field_ident
- {
- LEX *lex=Lex;
- Alter_drop *ad= (new (thd->mem_root)
- Alter_drop(Alter_drop::CHECK_CONSTRAINT,
- $4.str, $3));
- if (unlikely(ad == NULL))
- MYSQL_YYABORT;
- lex->alter_info.drop_list.push_back(ad, thd->mem_root);
- lex->alter_info.flags|= ALTER_DROP_CHECK_CONSTRAINT;
- }
- | DROP FOREIGN KEY_SYM opt_if_exists_table_element field_ident
- {
- LEX *lex=Lex;
- Alter_drop *ad= (new (thd->mem_root)
- Alter_drop(Alter_drop::FOREIGN_KEY, $5.str, $4));
- if (unlikely(ad == NULL))
- MYSQL_YYABORT;
- lex->alter_info.drop_list.push_back(ad, thd->mem_root);
- lex->alter_info.flags|= ALTER_DROP_FOREIGN_KEY;
- }
- | DROP opt_constraint_no_id PRIMARY_SYM KEY_SYM
- {
- LEX *lex=Lex;
- Alter_drop *ad= (new (thd->mem_root)
- Alter_drop(Alter_drop::KEY, primary_key_name,
- FALSE));
- if (unlikely(ad == NULL))
- MYSQL_YYABORT;
- lex->alter_info.drop_list.push_back(ad, thd->mem_root);
- lex->alter_info.flags|= ALTER_DROP_INDEX;
- }
- | DROP key_or_index opt_if_exists_table_element field_ident
- {
- LEX *lex=Lex;
- Alter_drop *ad= (new (thd->mem_root)
- Alter_drop(Alter_drop::KEY, $4.str, $3));
- if (unlikely(ad == NULL))
- MYSQL_YYABORT;
- lex->alter_info.drop_list.push_back(ad, thd->mem_root);
- lex->alter_info.flags|= ALTER_DROP_INDEX;
- }
- | DISABLE_SYM KEYS
- {
- LEX *lex=Lex;
- lex->alter_info.keys_onoff= Alter_info::DISABLE;
- lex->alter_info.flags|= ALTER_KEYS_ONOFF;
- }
- | ENABLE_SYM KEYS
- {
- LEX *lex=Lex;
- lex->alter_info.keys_onoff= Alter_info::ENABLE;
- lex->alter_info.flags|= ALTER_KEYS_ONOFF;
- }
- | ALTER opt_column opt_if_exists_table_element field_ident SET DEFAULT column_default_expr
- {
- if (unlikely(Lex->add_alter_list($4.str, $7, $3)))
- MYSQL_YYABORT;
- }
- | ALTER opt_column opt_if_exists_table_element field_ident DROP DEFAULT
- {
- if (unlikely(Lex->add_alter_list($4.str, (Virtual_column_info*) 0,
- $3)))
- MYSQL_YYABORT;
- }
- | RENAME opt_to table_ident
- {
- LEX *lex=Lex;
- lex->first_select_lex()->db= $3->db;
- if (lex->first_select_lex()->db.str == NULL &&
- lex->copy_db_to(&lex->first_select_lex()->db))
- MYSQL_YYABORT;
- if (unlikely(check_table_name($3->table.str,$3->table.length,
- FALSE)) ||
- ($3->db.str && unlikely(check_db_name((LEX_STRING*) &$3->db))))
- my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3->table.str));
- lex->name= $3->table;
- lex->alter_info.flags|= ALTER_RENAME;
- }
- | CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
- {
- if (!$4)
- {
- $4= thd->variables.collation_database;
- }
- $5= $5 ? $5 : $4;
- if (unlikely(!my_charset_same($4,$5)))
- my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- $5->name, $4->csname));
- if (unlikely(Lex->create_info.add_alter_list_item_convert_to_charset($5)))
- MYSQL_YYABORT;
- Lex->alter_info.flags|= ALTER_CONVERT_TO;
- }
- | create_table_options_space_separated
- {
- LEX *lex=Lex;
- lex->alter_info.flags|= ALTER_OPTIONS;
- }
- | FORCE_SYM
- {
- Lex->alter_info.flags|= ALTER_RECREATE;
- }
- | alter_order_clause
- {
- LEX *lex=Lex;
- lex->alter_info.flags|= ALTER_ORDER;
- }
- | alter_algorithm_option
- | alter_lock_option
- | ADD SYSTEM VERSIONING_SYM
- {
- Lex->alter_info.flags|= ALTER_ADD_SYSTEM_VERSIONING;
- Lex->create_info.options|= HA_VERSIONED_TABLE;
- }
- | DROP SYSTEM VERSIONING_SYM
- {
- Lex->alter_info.flags|= ALTER_DROP_SYSTEM_VERSIONING;
- Lex->create_info.options&= ~HA_VERSIONED_TABLE;
- }
- | DROP PERIOD_SYM FOR_SYSTEM_TIME_SYM
- {
- Lex->alter_info.flags|= ALTER_DROP_PERIOD;
- }
- | DROP PERIOD_SYM opt_if_exists_table_element FOR_SYM ident
- {
- Alter_drop *ad= new Alter_drop(Alter_drop::PERIOD, $5.str, $3);
- if (unlikely(ad == NULL))
- MYSQL_YYABORT;
- Lex->alter_info.drop_list.push_back(ad, thd->mem_root);
- Lex->alter_info.flags|= ALTER_DROP_CHECK_CONSTRAINT;
- }
- ;
-
-opt_index_lock_algorithm:
- /* empty */
- | alter_lock_option
- | alter_algorithm_option
- | alter_lock_option alter_algorithm_option
- | alter_algorithm_option alter_lock_option
- ;
-
-alter_algorithm_option:
- ALGORITHM_SYM opt_equal DEFAULT
- {
- Lex->alter_info.requested_algorithm=
- Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT;
- }
- | ALGORITHM_SYM opt_equal ident
- {
- if (unlikely(Lex->alter_info.set_requested_algorithm(&$3)))
- my_yyabort_error((ER_UNKNOWN_ALTER_ALGORITHM, MYF(0), $3.str));
- }
- ;
-
-alter_lock_option:
- LOCK_SYM opt_equal DEFAULT
- {
- Lex->alter_info.requested_lock=
- Alter_info::ALTER_TABLE_LOCK_DEFAULT;
- }
- | LOCK_SYM opt_equal ident
- {
- if (unlikely(Lex->alter_info.set_requested_lock(&$3)))
- my_yyabort_error((ER_UNKNOWN_ALTER_LOCK, MYF(0), $3.str));
- }
- ;
-
-opt_column:
- /* empty */ {} %prec PREC_BELOW_IDENTIFIER_OPT_SPECIAL_CASE
- | COLUMN_SYM {}
- ;
-
-opt_ignore:
- /* empty */ { Lex->ignore= 0;}
- | IGNORE_SYM { Lex->ignore= 1;}
- ;
-
-alter_options:
- { Lex->ignore= 0;} alter_options_part2
- ;
-
-alter_options_part2:
- /* empty */
- | alter_option_list
- ;
-
-alter_option_list:
- alter_option_list alter_option
- | alter_option
- ;
-
-alter_option:
- IGNORE_SYM { Lex->ignore= 1;}
- | ONLINE_SYM
- {
- Lex->alter_info.requested_lock=
- Alter_info::ALTER_TABLE_LOCK_NONE;
- }
- ;
-
-opt_restrict:
- /* empty */ { Lex->drop_mode= DROP_DEFAULT; }
- | RESTRICT { Lex->drop_mode= DROP_RESTRICT; }
- | CASCADE { Lex->drop_mode= DROP_CASCADE; }
- ;
-
-opt_place:
- /* empty */ { $$= null_clex_str; }
- | AFTER_SYM ident
- {
- $$= $2;
- Lex->alter_info.flags |= ALTER_COLUMN_ORDER;
- }
- | FIRST_SYM
- {
- $$.str= first_keyword;
- $$.length= 5; /* Length of "first" */
- Lex->alter_info.flags |= ALTER_COLUMN_ORDER;
- }
- ;
-
-opt_to:
- /* empty */ {}
- | TO_SYM {}
- | '=' {}
- | AS {}
- ;
-
-slave:
- START_SYM SLAVE optional_connection_name slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_START;
- lex->type = 0;
- /* If you change this code don't forget to update SLAVE START too */
- }
- slave_until
- {}
- | START_SYM ALL SLAVES slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_ALL_START;
- lex->type = 0;
- /* If you change this code don't forget to update STOP SLAVE too */
- }
- {}
- | STOP_SYM SLAVE optional_connection_name slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_STOP;
- lex->type = 0;
- /* If you change this code don't forget to update SLAVE STOP too */
- }
- | STOP_SYM ALL SLAVES slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_ALL_STOP;
- lex->type = 0;
- /* If you change this code don't forget to update SLAVE STOP too */
- }
- ;
-
-start:
- START_SYM TRANSACTION_SYM opt_start_transaction_option_list
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_BEGIN;
- /* READ ONLY and READ WRITE are mutually exclusive. */
- if (unlikely(($3 & MYSQL_START_TRANS_OPT_READ_WRITE) &&
- ($3 & MYSQL_START_TRANS_OPT_READ_ONLY)))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- lex->start_transaction_opt= $3;
- }
- ;
-
-opt_start_transaction_option_list:
- /* empty */
- {
- $$= 0;
- }
- | start_transaction_option_list
- {
- $$= $1;
- }
- ;
-
-start_transaction_option_list:
- start_transaction_option
- {
- $$= $1;
- }
- | start_transaction_option_list ',' start_transaction_option
- {
- $$= $1 | $3;
- }
- ;
-
-start_transaction_option:
- WITH CONSISTENT_SYM SNAPSHOT_SYM
- {
- $$= MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT;
- }
- | READ_SYM ONLY_SYM
- {
- $$= MYSQL_START_TRANS_OPT_READ_ONLY;
- }
- | READ_SYM WRITE_SYM
- {
- $$= MYSQL_START_TRANS_OPT_READ_WRITE;
- }
- ;
-
-slave_thread_opts:
- { Lex->slave_thd_opt= 0; }
- slave_thread_opt_list
- {}
- ;
-
-slave_thread_opt_list:
- slave_thread_opt
- | slave_thread_opt_list ',' slave_thread_opt
- ;
-
-slave_thread_opt:
- /*empty*/ {}
- | SQL_THREAD { Lex->slave_thd_opt|=SLAVE_SQL; }
- | RELAY_THREAD { Lex->slave_thd_opt|=SLAVE_IO; }
- ;
-
-slave_until:
- /*empty*/ {}
- | UNTIL_SYM slave_until_opts
- {
- LEX *lex=Lex;
- if (unlikely(((lex->mi.log_file_name || lex->mi.pos) &&
- (lex->mi.relay_log_name || lex->mi.relay_log_pos)) ||
- !((lex->mi.log_file_name && lex->mi.pos) ||
- (lex->mi.relay_log_name && lex->mi.relay_log_pos))))
- my_yyabort_error((ER_BAD_SLAVE_UNTIL_COND, MYF(0)));
- }
- | UNTIL_SYM MASTER_GTID_POS_SYM '=' TEXT_STRING_sys
- {
- Lex->mi.gtid_pos_str = $4;
- }
- ;
-
-slave_until_opts:
- master_file_def
- | slave_until_opts ',' master_file_def
- ;
-
-checksum:
- CHECKSUM_SYM table_or_tables
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_CHECKSUM;
- /* Will be overridden during execution. */
- YYPS->m_lock_type= TL_UNLOCK;
- }
- table_list opt_checksum_type
- {}
- ;
-
-opt_checksum_type:
- /* nothing */ { Lex->check_opt.flags= 0; }
- | QUICK { Lex->check_opt.flags= T_QUICK; }
- | EXTENDED_SYM { Lex->check_opt.flags= T_EXTEND; }
- ;
-
-repair_table_or_view:
- table_or_tables table_list opt_mi_repair_type
- | VIEW_SYM
- { Lex->table_type= TABLE_TYPE_VIEW; }
- table_list opt_view_repair_type
- ;
-
-repair:
- REPAIR opt_no_write_to_binlog
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_REPAIR;
- lex->no_write_to_binlog= $2;
- lex->check_opt.init();
- lex->alter_info.reset();
- /* Will be overridden during execution. */
- YYPS->m_lock_type= TL_UNLOCK;
- }
- repair_table_or_view
- {
- LEX* lex= thd->lex;
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_mi_repair_type:
- /* empty */ { Lex->check_opt.flags = T_MEDIUM; }
- | mi_repair_types {}
- ;
-
-mi_repair_types:
- mi_repair_type {}
- | mi_repair_type mi_repair_types {}
- ;
-
-mi_repair_type:
- QUICK { Lex->check_opt.flags|= T_QUICK; }
- | EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
- | USE_FRM { Lex->check_opt.sql_flags|= TT_USEFRM; }
- ;
-
-opt_view_repair_type:
- /* empty */ { }
- | FROM MYSQL_SYM { Lex->check_opt.sql_flags|= TT_FROM_MYSQL; }
- ;
-
-analyze:
- ANALYZE_SYM opt_no_write_to_binlog table_or_tables
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_ANALYZE;
- lex->no_write_to_binlog= $2;
- lex->check_opt.init();
- lex->alter_info.reset();
- /* Will be overridden during execution. */
- YYPS->m_lock_type= TL_UNLOCK;
- }
- analyze_table_list
- {
- LEX* lex= thd->lex;
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-analyze_table_list:
- analyze_table_elem_spec
- | analyze_table_list ',' analyze_table_elem_spec
- ;
-
-analyze_table_elem_spec:
- table_name opt_persistent_stat_clause
- ;
-
-opt_persistent_stat_clause:
- /* empty */
- {}
- | PERSISTENT_SYM FOR_SYM persistent_stat_spec
- {
- thd->lex->with_persistent_for_clause= TRUE;
- }
- ;
-
-persistent_stat_spec:
- ALL
- {}
- | COLUMNS persistent_column_stat_spec INDEXES persistent_index_stat_spec
- {}
- ;
-
-persistent_column_stat_spec:
- ALL {}
- | '('
- {
- LEX* lex= thd->lex;
- lex->column_list= new (thd->mem_root) List<LEX_STRING>;
- if (unlikely(lex->column_list == NULL))
- MYSQL_YYABORT;
- }
- table_column_list
- ')'
- { }
- ;
-
-persistent_index_stat_spec:
- ALL {}
- | '('
- {
- LEX* lex= thd->lex;
- lex->index_list= new (thd->mem_root) List<LEX_STRING>;
- if (unlikely(lex->index_list == NULL))
- MYSQL_YYABORT;
- }
- table_index_list
- ')'
- { }
- ;
-
-table_column_list:
- /* empty */
- {}
- | ident
- {
- Lex->column_list->push_back((LEX_STRING*)
- thd->memdup(&$1, sizeof(LEX_STRING)), thd->mem_root);
- }
- | table_column_list ',' ident
- {
- Lex->column_list->push_back((LEX_STRING*)
- thd->memdup(&$3, sizeof(LEX_STRING)), thd->mem_root);
- }
- ;
-
-table_index_list:
- /* empty */
- {}
- | table_index_name
- | table_index_list ',' table_index_name
- ;
-
-table_index_name:
- ident
- {
- Lex->index_list->push_back((LEX_STRING*)
- thd->memdup(&$1, sizeof(LEX_STRING)),
- thd->mem_root);
- }
- |
- PRIMARY_SYM
- {
- LEX_STRING str= {(char*) "PRIMARY", 7};
- Lex->index_list->push_back((LEX_STRING*)
- thd->memdup(&str, sizeof(LEX_STRING)),
- thd->mem_root);
- }
- ;
-
-binlog_base64_event:
- BINLOG_SYM TEXT_STRING_sys
- {
- Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT;
- Lex->comment= $2;
- Lex->ident.str= NULL;
- Lex->ident.length= 0;
- }
- |
- BINLOG_SYM '@' ident_or_text ',' '@' ident_or_text
- {
- Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT;
- Lex->comment= $3;
- Lex->ident= $6;
- }
- ;
-
-check_view_or_table:
- table_or_tables table_list opt_mi_check_type
- | VIEW_SYM
- { Lex->table_type= TABLE_TYPE_VIEW; }
- table_list opt_view_check_type
- ;
-
-check: CHECK_SYM
- {
- LEX *lex=Lex;
-
- lex->sql_command = SQLCOM_CHECK;
- lex->check_opt.init();
- lex->alter_info.reset();
- /* Will be overridden during execution. */
- YYPS->m_lock_type= TL_UNLOCK;
- }
- check_view_or_table
- {
- LEX* lex= thd->lex;
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "CHECK"));
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_mi_check_type:
- /* empty */ { Lex->check_opt.flags = T_MEDIUM; }
- | mi_check_types {}
- ;
-
-mi_check_types:
- mi_check_type {}
- | mi_check_type mi_check_types {}
- ;
-
-mi_check_type:
- QUICK { Lex->check_opt.flags|= T_QUICK; }
- | FAST_SYM { Lex->check_opt.flags|= T_FAST; }
- | MEDIUM_SYM { Lex->check_opt.flags|= T_MEDIUM; }
- | EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
- | CHANGED { Lex->check_opt.flags|= T_CHECK_ONLY_CHANGED; }
- | FOR_SYM UPGRADE_SYM { Lex->check_opt.sql_flags|= TT_FOR_UPGRADE; }
- ;
-
-opt_view_check_type:
- /* empty */ { }
- | FOR_SYM UPGRADE_SYM { Lex->check_opt.sql_flags|= TT_FOR_UPGRADE; }
- ;
-
-optimize:
- OPTIMIZE opt_no_write_to_binlog table_or_tables
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_OPTIMIZE;
- lex->no_write_to_binlog= $2;
- lex->check_opt.init();
- lex->alter_info.reset();
- /* Will be overridden during execution. */
- YYPS->m_lock_type= TL_UNLOCK;
- }
- table_list opt_lock_wait_timeout
- {
- LEX* lex= thd->lex;
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_no_write_to_binlog:
- /* empty */ { $$= 0; }
- | NO_WRITE_TO_BINLOG { $$= 1; }
- | LOCAL_SYM { $$= 1; }
- ;
-
-rename:
- RENAME table_or_tables
- {
- Lex->sql_command= SQLCOM_RENAME_TABLE;
- }
- table_to_table_list
- {}
- | RENAME USER_SYM clear_privileges rename_list
- {
- Lex->sql_command = SQLCOM_RENAME_USER;
- }
- ;
-
-rename_list:
- user TO_SYM user
- {
- if (unlikely(Lex->users_list.push_back($1, thd->mem_root) ||
- Lex->users_list.push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | rename_list ',' user TO_SYM user
- {
- if (unlikely(Lex->users_list.push_back($3, thd->mem_root) ||
- Lex->users_list.push_back($5, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-table_to_table_list:
- table_to_table
- | table_to_table_list ',' table_to_table
- ;
-
-table_to_table:
- table_ident opt_lock_wait_timeout TO_SYM table_ident
- {
- LEX *lex=Lex;
- SELECT_LEX *sl= lex->current_select;
- if (unlikely(!sl->add_table_to_list(thd, $1,NULL,
- TL_OPTION_UPDATING,
- TL_IGNORE, MDL_EXCLUSIVE)) ||
- unlikely(!sl->add_table_to_list(thd, $4, NULL,
- TL_OPTION_UPDATING,
- TL_IGNORE, MDL_EXCLUSIVE)))
- MYSQL_YYABORT;
- }
- ;
-
-keycache:
- CACHE_SYM INDEX_SYM
- {
- Lex->alter_info.reset();
- }
- keycache_list_or_parts IN_SYM key_cache_name
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE;
- lex->ident= $6;
- }
- ;
-
-keycache_list_or_parts:
- keycache_list
- | assign_to_keycache_parts
- ;
-
-keycache_list:
- assign_to_keycache
- | keycache_list ',' assign_to_keycache
- ;
-
-assign_to_keycache:
- table_ident cache_keys_spec
- {
- if (unlikely(!Select->add_table_to_list(thd, $1, NULL, 0, TL_READ,
- MDL_SHARED_READ,
- Select->
- pop_index_hints())))
- MYSQL_YYABORT;
- }
- ;
-
-assign_to_keycache_parts:
- table_ident adm_partition cache_keys_spec
- {
- if (unlikely(!Select->add_table_to_list(thd, $1, NULL, 0, TL_READ,
- MDL_SHARED_READ,
- Select->
- pop_index_hints())))
- MYSQL_YYABORT;
- }
- ;
-
-key_cache_name:
- ident { $$= $1; }
- | DEFAULT { $$ = default_key_cache_base; }
- ;
-
-preload:
- LOAD INDEX_SYM INTO CACHE_SYM
- {
- LEX *lex=Lex;
- lex->sql_command=SQLCOM_PRELOAD_KEYS;
- lex->alter_info.reset();
- }
- preload_list_or_parts
- {}
- ;
-
-preload_list_or_parts:
- preload_keys_parts
- | preload_list
- ;
-
-preload_list:
- preload_keys
- | preload_list ',' preload_keys
- ;
-
-preload_keys:
- table_ident cache_keys_spec opt_ignore_leaves
- {
- if (unlikely(!Select->add_table_to_list(thd, $1, NULL, $3, TL_READ,
- MDL_SHARED_READ,
- Select->
- pop_index_hints())))
- MYSQL_YYABORT;
- }
- ;
-
-preload_keys_parts:
- table_ident adm_partition cache_keys_spec opt_ignore_leaves
- {
- if (unlikely(!Select->add_table_to_list(thd, $1, NULL, $4, TL_READ,
- MDL_SHARED_READ,
- Select->
- pop_index_hints())))
- MYSQL_YYABORT;
- }
- ;
-
-adm_partition:
- PARTITION_SYM have_partitioning
- {
- Lex->alter_info.partition_flags|= ALTER_PARTITION_ADMIN;
- }
- '(' all_or_alt_part_name_list ')'
- ;
-
-cache_keys_spec:
- {
- Lex->first_select_lex()->alloc_index_hints(thd);
- Select->set_index_hint_type(INDEX_HINT_USE,
- INDEX_HINT_MASK_ALL);
- }
- cache_key_list_or_empty
- ;
-
-cache_key_list_or_empty:
- /* empty */ { }
- | key_or_index '(' opt_key_usage_list ')'
- ;
-
-opt_ignore_leaves:
- /* empty */
- { $$= 0; }
- | IGNORE_SYM LEAVES { $$= TL_OPTION_IGNORE_LEAVES; }
- ;
-
-/*
- Select : retrieve data from table
-*/
-
-
-select:
- query_expression_no_with_clause
- {
- if (Lex->push_select($1->fake_select_lex ?
- $1->fake_select_lex :
- $1->first_select()))
- MYSQL_YYABORT;
- }
- opt_procedure_or_into
- {
- Lex->pop_select();
- $1->set_with_clause(NULL);
- if (Lex->select_finalize($1, $3))
- MYSQL_YYABORT;
- }
- | with_clause query_expression_no_with_clause
- {
- if (Lex->push_select($2->fake_select_lex ?
- $2->fake_select_lex :
- $2->first_select()))
- MYSQL_YYABORT;
- }
- opt_procedure_or_into
- {
- Lex->pop_select();
- $2->set_with_clause($1);
- $1->attach_to($2->first_select());
- if (Lex->select_finalize($2, $4))
- MYSQL_YYABORT;
- }
- ;
-
-select_into:
- select_into_query_specification
- {
- if (Lex->push_select($1))
- MYSQL_YYABORT;
- }
- opt_order_limit_lock
- {
- SELECT_LEX_UNIT *unit;
- if (!(unit = Lex->create_unit($1)))
- MYSQL_YYABORT;
- if ($3)
- unit= Lex->add_tail_to_query_expression_body(unit, $3);
- if (Lex->select_finalize(unit))
- MYSQL_YYABORT;
- }
- | with_clause
- select_into_query_specification
- {
- if (Lex->push_select($2))
- MYSQL_YYABORT;
- }
- opt_order_limit_lock
- {
- SELECT_LEX_UNIT *unit;
- if (!(unit = Lex->create_unit($2)))
- MYSQL_YYABORT;
- if ($4)
- unit= Lex->add_tail_to_query_expression_body(unit, $4);
- unit->set_with_clause($1);
- $1->attach_to($2);
- if (Lex->select_finalize(unit))
- MYSQL_YYABORT;
- }
- ;
-
-simple_table:
- query_specification { $$= $1; }
- | table_value_constructor { $$= $1; }
- ;
-
-table_value_constructor:
- VALUES
- {
- if (Lex->parsed_TVC_start())
- MYSQL_YYABORT;
- }
- values_list
- {
- if (!($$= Lex->parsed_TVC_end()))
- MYSQL_YYABORT;
- }
- ;
-
-query_specification_start:
- SELECT_SYM
- {
- SELECT_LEX *sel;
- LEX *lex= Lex;
- if (!(sel= lex->alloc_select(TRUE)) || lex->push_select(sel))
- MYSQL_YYABORT;
- sel->init_select();
- sel->braces= FALSE;
- }
- select_options
- {
- Select->parsing_place= SELECT_LIST;
- }
- select_item_list
- {
- Select->parsing_place= NO_MATTER;
- }
- ;
-
-query_specification:
- query_specification_start
- opt_from_clause
- opt_where_clause
- opt_group_clause
- opt_having_clause
- opt_window_clause
- {
- $$= Lex->pop_select();
- }
- ;
-
-select_into_query_specification:
- query_specification_start
- into
- opt_from_clause
- opt_where_clause
- opt_group_clause
- opt_having_clause
- opt_window_clause
- {
- $$= Lex->pop_select();
- }
- ;
-
-/**
-
- The following grammar for query expressions conformant to
- the latest SQL Standard is supported:
-
- <query expression> ::=
- [ <with clause> ] <query expression body>
- [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
-
- <with clause> ::=
- WITH [ RECURSIVE ] <with_list
-
- <with list> ::=
- <with list element> [ { <comma> <with list element> }... ]
-
- <with list element> ::=
- <query name> [ '(' <with column list> ')' ]
- AS <table subquery>
-
- <with column list> ::=
- <column name list>
-
- <query expression body> ::
- <query term>
- | <query expression body> UNION [ ALL | DISTINCT ] <query term>
- | <query expression body> EXCEPT [ DISTINCT ] <query term>
-
- <query term> ::=
- <query primary>
- | <query term> INTERSECT [ DISTINCT ] <query primary>
-
- <query primary> ::=
- <simple table>
- | '(' <query expression body>
- [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
- ')'
-
- <simple table>
- <query specification>
- | <table value constructor>
-
- <subquery>
- '(' <query_expression> ')'
-
-*/
-
-/*
- query_expression produces the same expressions as
- <query expression>
-*/
-
-query_expression:
- query_expression_no_with_clause
- {
- $1->set_with_clause(NULL);
- $$= $1;
- }
- | with_clause
- query_expression_no_with_clause
- {
- $2->set_with_clause($1);
- $1->attach_to($2->first_select());
- $$= $2;
- }
- ;
-
-/*
- query_expression_no_with_clause produces the same expressions as
- <query expression> without [ <with clause> ]
-*/
-
-query_expression_no_with_clause:
- query_expression_body_ext { $$= $1; }
- | query_expression_body_ext_parens { $$= $1; }
- ;
-
-/*
- query_expression_body_ext produces the same expressions as
- <query expression body>
- [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
- | '('... <query expression body>
- [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
- ')'...
- Note: number of ')' must be equal to the number of '(' in the rule above
-*/
-
-query_expression_body_ext:
- query_expression_body
- {
- if ($1->first_select()->next_select())
- {
- if (Lex->parsed_multi_operand_query_expression_body($1))
- MYSQL_YYABORT;
- }
- }
- opt_query_expression_tail
- {
- if (!$3)
- $$= $1;
- else
- $$= Lex->add_tail_to_query_expression_body($1, $3);
- }
- | query_expression_body_ext_parens
- {
- Lex->push_select(!$1->first_select()->next_select() ?
- $1->first_select() : $1->fake_select_lex);
- }
- query_expression_tail
- {
- if (!($$= Lex->add_tail_to_query_expression_body_ext_parens($1, $3)))
- MYSQL_YYABORT;
- }
- ;
-
-query_expression_body_ext_parens:
- '(' query_expression_body_ext_parens ')'
- { $$= $2; }
- | '(' query_expression_body_ext ')'
- {
- SELECT_LEX *sel= $2->first_select()->next_select() ?
- $2->fake_select_lex : $2->first_select();
- sel->braces= true;
- $$= $2;
- }
- ;
-
-/*
- query_expression_body produces the same expressions as
- <query expression body>
-*/
-
-query_expression_body:
- query_simple
- {
- Lex->push_select($1);
- if (!($$= Lex->create_unit($1)))
- MYSQL_YYABORT;
- }
- | query_expression_body
- unit_type_decl
- {
- if (!$1->first_select()->next_select())
- {
- Lex->pop_select();
- }
- }
- query_primary
- {
- if (!($$= Lex->add_primary_to_query_expression_body($1, $4,
- $2.unit_type,
- $2.distinct)))
- MYSQL_YYABORT;
- }
- | query_expression_body_ext_parens
- unit_type_decl
- query_primary
- {
- if (!($$= Lex->add_primary_to_query_expression_body_ext_parens(
- $1, $3,
- $2.unit_type,
- $2.distinct)))
- MYSQL_YYABORT;
- }
- ;
-
-/*
- query_primary produces the same expressions as
- <query primary>
-*/
-
-query_primary:
- query_simple
- { $$= $1; }
- | query_expression_body_ext_parens
- { $$= $1->first_select(); }
- ;
-
-/*
- query_simple produces the same expressions as
- <simple table>
-*/
-
-query_simple:
- simple_table { $$= $1;}
- ;
-
-subselect:
- query_expression
- {
- if (!($$= Lex->parsed_subselect($1)))
- YYABORT;
- }
- ;
-
-/*
- subquery produces the same expressions as
- <subquery>
-
- Consider the production rule of the SQL Standard
- subquery:
- '(' query_expression ')'
-
- This rule is equivalent to the rule
- subquery:
- '(' query_expression_no_with_clause ')'
- | '(' with_clause query_expression_no_with_clause ')'
- that in its turn is equivalent to
- subquery:
- '(' query_expression_body_ext ')'
- | query_expression_body_ext_parens
- | '(' with_clause query_expression_no_with_clause ')'
-
- The latter can be re-written into
- subquery:
- query_expression_body_ext_parens
- | '(' with_clause query_expression_no_with_clause ')'
-
- The last rule allows us to resolve properly the shift/reduce conflict
- when subquery is used in expressions such as in the following queries
- select (select * from t1 limit 1) + t2.a from t2
- select * from t1 where t1.a [not] in (select t2.a from t2)
-
- In the rule below %prec SUBQUERY_AS_EXPR forces the parser to perform a shift
- operation rather then a reduce operation when ')' is encountered and can be
- considered as the last symbol a query expression.
-*/
-
-subquery:
- query_expression_body_ext_parens %prec SUBQUERY_AS_EXPR
- {
- if (!$1->fake_select_lex)
- $1->first_select()->braces= false;
- else
- $1->fake_select_lex->braces= false;
- if (!($$= Lex->parsed_subselect($1)))
- YYABORT;
- }
- | '(' with_clause query_expression_no_with_clause ')'
- {
- $3->set_with_clause($2);
- $2->attach_to($3->first_select());
- if (!($$= Lex->parsed_subselect($3)))
- YYABORT;
- }
- ;
-
-opt_from_clause:
- /* empty */ %prec EMPTY_FROM_CLAUSE
- | from_clause
- ;
-
-from_clause:
- FROM table_reference_list
- ;
-
-table_reference_list:
- join_table_list
- {
- Select->context.table_list=
- Select->context.first_name_resolution_table=
- Select->table_list.first;
- }
- | DUAL_SYM
- /* oracle compatibility: oracle always requires FROM clause,
- and DUAL is system table without fields.
- Is "SELECT 1 FROM DUAL" any better than "SELECT 1" ?
- Hmmm :) */
- ;
-
-select_options:
- /* empty*/
- | select_option_list
- {
- if (unlikely((Select->options & SELECT_DISTINCT) &&
- (Select->options & SELECT_ALL)))
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT"));
- }
- ;
-
-opt_history_unit:
- /* empty*/ %prec PREC_BELOW_IDENTIFIER_OPT_SPECIAL_CASE
- {
- $$= VERS_TIMESTAMP;
- }
- | TRANSACTION_SYM
- {
- $$= VERS_TRX_ID;
- }
- | TIMESTAMP
- {
- $$= VERS_TIMESTAMP;
- }
- ;
-
-history_point:
- TIMESTAMP TEXT_STRING
- {
- Item *item;
- if (!(item= type_handler_datetime.create_literal_item(thd,
- $2.str, $2.length,
- YYCSCL, true)))
- MYSQL_YYABORT;
- $$= Vers_history_point(VERS_TIMESTAMP, item);
- }
- | function_call_keyword_timestamp
- {
- $$= Vers_history_point(VERS_TIMESTAMP, $1);
- }
- | opt_history_unit bit_expr
- {
- $$= Vers_history_point($1, $2);
- }
- ;
-
-for_portion_of_time_clause:
- FOR_SYM PORTION_SYM OF_SYM remember_tok_start ident FROM
- bit_expr TO_SYM bit_expr
- {
- if (unlikely(0 == strcasecmp($5.str, "SYSTEM_TIME")))
- {
- thd->parse_error(ER_SYNTAX_ERROR, $4);
- MYSQL_YYABORT;
- }
- Lex->period_conditions.init(SYSTEM_TIME_FROM_TO,
- Vers_history_point(VERS_TIMESTAMP, $7),
- Vers_history_point(VERS_TIMESTAMP, $9),
- $5);
- }
- ;
-
-opt_for_portion_of_time_clause:
- /* empty */
- {
- $$= false;
- }
- | for_portion_of_time_clause
- {
- $$= true;
- }
- ;
-
-opt_for_system_time_clause:
- /* empty */
- {
- $$= false;
- }
- | FOR_SYSTEM_TIME_SYM system_time_expr
- {
- $$= true;
- }
- ;
-
-system_time_expr:
- AS OF_SYM history_point
- {
- Lex->vers_conditions.init(SYSTEM_TIME_AS_OF, $3);
- }
- | ALL
- {
- Lex->vers_conditions.init(SYSTEM_TIME_ALL);
- }
- | FROM history_point TO_SYM history_point
- {
- Lex->vers_conditions.init(SYSTEM_TIME_FROM_TO, $2, $4);
- }
- | BETWEEN_SYM history_point AND_SYM history_point
- {
- Lex->vers_conditions.init(SYSTEM_TIME_BETWEEN, $2, $4);
- }
- ;
-
-select_option_list:
- select_option_list select_option
- | select_option
- ;
-
-select_option:
- query_expression_option
- | SQL_NO_CACHE_SYM
- {
- /*
- Allow this flag once per query.
- */
- if (Select->options & OPTION_NO_QUERY_CACHE)
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
- Select->options|= OPTION_NO_QUERY_CACHE;
- }
- | SQL_CACHE_SYM
- {
- /*
- Allow this flag once per query.
- */
- if (Select->options & OPTION_TO_QUERY_CACHE)
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
- Select->options|= OPTION_TO_QUERY_CACHE;
- }
- ;
-
-
-select_lock_type:
- FOR_SYM UPDATE_SYM opt_lock_wait_timeout_new
- {
- $$= $3;
- $$.defined_lock= TRUE;
- $$.update_lock= TRUE;
- }
- | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout_new
- {
- $$= $5;
- $$.defined_lock= TRUE;
- $$.update_lock= FALSE;
- }
- ;
-
-
-opt_select_lock_type:
- /* empty */
- {
- $$.empty();
- }
- | select_lock_type
- {
- $$= $1;
- }
- ;
-
-
-opt_lock_wait_timeout_new:
- /* empty */
- {
- $$.empty();
- }
- | WAIT_SYM ulong_num
- {
- $$.defined_timeout= TRUE;
- $$.timeout= $2;
- }
- | NOWAIT_SYM
- {
- $$.defined_timeout= TRUE;
- $$.timeout= 0;
- }
- ;
-
-select_item_list:
- select_item_list ',' select_item
- | select_item
- | '*'
- {
- Item *item= new (thd->mem_root)
- Item_field(thd, &thd->lex->current_select->context,
- star_clex_str);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- if (unlikely(add_item_to_list(thd, item)))
- MYSQL_YYABORT;
- (thd->lex->current_select->with_wild)++;
- }
- ;
-
-select_item:
- remember_name select_sublist_qualified_asterisk remember_end
- {
- if (unlikely(add_item_to_list(thd, $2)))
- MYSQL_YYABORT;
- }
- | remember_name expr remember_end select_alias
- {
- DBUG_ASSERT($1 < $3);
-
- if (unlikely(add_item_to_list(thd, $2)))
- MYSQL_YYABORT;
- if ($4.str)
- {
- if (unlikely(Lex->sql_command == SQLCOM_CREATE_VIEW &&
- check_column_name($4.str)))
- my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), $4.str));
- $2->is_autogenerated_name= FALSE;
- $2->set_name(thd, $4);
- }
- else if (!$2->name.str || $2->name.str == item_empty_name)
- {
- $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
- }
- }
- ;
-
-remember_tok_start:
- {
- $$= (char*) YYLIP->get_tok_start();
- }
- ;
-
-remember_name:
- {
- $$= (char*) YYLIP->get_cpp_tok_start();
- }
- ;
-
-remember_end:
- {
- $$= (char*) YYLIP->get_cpp_tok_end_rtrim();
- }
- ;
-
-select_alias:
- /* empty */ { $$=null_clex_str;}
- | AS ident { $$=$2; }
- | AS TEXT_STRING_sys { $$=$2; }
- | ident { $$=$1; }
- | TEXT_STRING_sys { $$=$1; }
- ;
-
-opt_default_time_precision:
- /* empty */ { $$= NOT_FIXED_DEC; }
- | '(' ')' { $$= NOT_FIXED_DEC; }
- | '(' real_ulong_num ')' { $$= $2; }
- ;
-
-opt_time_precision:
- /* empty */ { $$= 0; }
- | '(' ')' { $$= 0; }
- | '(' real_ulong_num ')' { $$= $2; }
- ;
-
-optional_braces:
- /* empty */ {}
- | '(' ')' {}
- ;
-
-/* all possible expressions */
-expr:
- expr or expr %prec OR_SYM
- {
- /*
- Design notes:
- Do not use a manually maintained stack like thd->lex->xxx_list,
- but use the internal bison stack ($$, $1 and $3) instead.
- Using the bison stack is:
- - more robust to changes in the grammar,
- - guaranteed to be in sync with the parser state,
- - better for performances (no memory allocation).
- */
- Item_cond_or *item1;
- Item_cond_or *item3;
- if (is_cond_or($1))
- {
- item1= (Item_cond_or*) $1;
- if (is_cond_or($3))
- {
- item3= (Item_cond_or*) $3;
- /*
- (X1 OR X2) OR (Y1 OR Y2) ==> OR (X1, X2, Y1, Y2)
- */
- item3->add_at_head(item1->argument_list());
- $$ = $3;
- }
- else
- {
- /*
- (X1 OR X2) OR Y ==> OR (X1, X2, Y)
- */
- item1->add($3, thd->mem_root);
- $$ = $1;
- }
- }
- else if (is_cond_or($3))
- {
- item3= (Item_cond_or*) $3;
- /*
- X OR (Y1 OR Y2) ==> OR (X, Y1, Y2)
- */
- item3->add_at_head($1, thd->mem_root);
- $$ = $3;
- }
- else
- {
- /* X OR Y */
- $$= new (thd->mem_root) Item_cond_or(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- }
- | expr XOR expr %prec XOR
- {
- /* XOR is a proprietary extension */
- $$= new (thd->mem_root) Item_func_xor(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | expr and expr %prec AND_SYM
- {
- /* See comments in rule expr: expr or expr */
- Item_cond_and *item1;
- Item_cond_and *item3;
- if (is_cond_and($1))
- {
- item1= (Item_cond_and*) $1;
- if (is_cond_and($3))
- {
- item3= (Item_cond_and*) $3;
- /*
- (X1 AND X2) AND (Y1 AND Y2) ==> AND (X1, X2, Y1, Y2)
- */
- item3->add_at_head(item1->argument_list());
- $$ = $3;
- }
- else
- {
- /*
- (X1 AND X2) AND Y ==> AND (X1, X2, Y)
- */
- item1->add($3, thd->mem_root);
- $$ = $1;
- }
- }
- else if (is_cond_and($3))
- {
- item3= (Item_cond_and*) $3;
- /*
- X AND (Y1 AND Y2) ==> AND (X, Y1, Y2)
- */
- item3->add_at_head($1, thd->mem_root);
- $$ = $3;
- }
- else
- {
- /* X AND Y */
- $$= new (thd->mem_root) Item_cond_and(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- }
- | NOT_SYM expr %prec NOT_SYM
- {
- $$= negate_expression(thd, $2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri IS TRUE_SYM %prec IS
- {
- $$= new (thd->mem_root) Item_func_istrue(thd, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri IS not TRUE_SYM %prec IS
- {
- $$= new (thd->mem_root) Item_func_isnottrue(thd, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri IS FALSE_SYM %prec IS
- {
- $$= new (thd->mem_root) Item_func_isfalse(thd, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri IS not FALSE_SYM %prec IS
- {
- $$= new (thd->mem_root) Item_func_isnotfalse(thd, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri IS UNKNOWN_SYM %prec IS
- {
- $$= new (thd->mem_root) Item_func_isnull(thd, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri IS not UNKNOWN_SYM %prec IS
- {
- $$= new (thd->mem_root) Item_func_isnotnull(thd, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri %prec PREC_BELOW_NOT
- ;
-
-bool_pri:
- bool_pri IS NULL_SYM %prec IS
- {
- $$= new (thd->mem_root) Item_func_isnull(thd, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri IS not NULL_SYM %prec IS
- {
- $$= new (thd->mem_root) Item_func_isnotnull(thd, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri EQUAL_SYM predicate %prec EQUAL_SYM
- {
- $$= new (thd->mem_root) Item_func_equal(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri comp_op predicate %prec '='
- {
- $$= (*$2)(0)->create(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bool_pri comp_op all_or_any '(' subselect ')' %prec '='
- {
- $$= all_any_subquery_creator(thd, $1, $2, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | predicate
- ;
-
-predicate:
- bit_expr IN_SYM subquery
- {
- $$= new (thd->mem_root) Item_in_subselect(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr not IN_SYM subquery
- {
- Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $4);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- $$= negate_expression(thd, item);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr IN_SYM '(' expr ')'
- {
- $$= handle_sql2003_note184_exception(thd, $1, true, $4);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr IN_SYM '(' expr ',' expr_list ')'
- {
- $6->push_front($4, thd->mem_root);
- $6->push_front($1, thd->mem_root);
- $$= new (thd->mem_root) Item_func_in(thd, *$6);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr not IN_SYM '(' expr ')'
- {
- $$= handle_sql2003_note184_exception(thd, $1, false, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr not IN_SYM '(' expr ',' expr_list ')'
- {
- $7->push_front($5, thd->mem_root);
- $7->push_front($1, thd->mem_root);
- Item_func_in *item= new (thd->mem_root) Item_func_in(thd, *$7);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- $$= item->neg_transformer(thd);
- }
- | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
- {
- $$= new (thd->mem_root) Item_func_between(thd, $1, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
- {
- Item_func_between *item;
- item= new (thd->mem_root) Item_func_between(thd, $1, $4, $6);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- $$= item->neg_transformer(thd);
- }
- | bit_expr SOUNDS_SYM LIKE bit_expr
- {
- Item *item1= new (thd->mem_root) Item_func_soundex(thd, $1);
- Item *item4= new (thd->mem_root) Item_func_soundex(thd, $4);
- if (unlikely(item1 == NULL) || unlikely(item4 == NULL))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_func_eq(thd, item1, item4);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr LIKE bit_expr opt_escape
- {
- $$= new (thd->mem_root) Item_func_like(thd, $1, $3, $4,
- Lex->escape_used);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr not LIKE bit_expr opt_escape
- {
- Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $5,
- Lex->escape_used);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- $$= item->neg_transformer(thd);
- }
- | bit_expr REGEXP bit_expr
- {
- $$= new (thd->mem_root) Item_func_regex(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr not REGEXP bit_expr
- {
- Item *item= new (thd->mem_root) Item_func_regex(thd, $1, $4);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- $$= negate_expression(thd, item);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr %prec PREC_BELOW_NOT
- ;
-
-bit_expr:
- bit_expr '|' bit_expr %prec '|'
- {
- $$= new (thd->mem_root) Item_func_bit_or(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr '&' bit_expr %prec '&'
- {
- $$= new (thd->mem_root) Item_func_bit_and(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr SHIFT_LEFT bit_expr %prec SHIFT_LEFT
- {
- $$= new (thd->mem_root) Item_func_shift_left(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr SHIFT_RIGHT bit_expr %prec SHIFT_RIGHT
- {
- $$= new (thd->mem_root) Item_func_shift_right(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr ORACLE_CONCAT_SYM bit_expr
- {
- $$= new (thd->mem_root) Item_func_concat_operator_oracle(thd,
- $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr '+' bit_expr %prec '+'
- {
- $$= new (thd->mem_root) Item_func_plus(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr '-' bit_expr %prec '-'
- {
- $$= new (thd->mem_root) Item_func_minus(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr '+' INTERVAL_SYM expr interval %prec '+'
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $1, $4, $5, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr '-' INTERVAL_SYM expr interval %prec '-'
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $1, $4, $5, 1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | INTERVAL_SYM expr interval '+' expr
- /* we cannot put interval before - */
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $5, $2, $3, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | '+' INTERVAL_SYM expr interval '+' expr %prec NEG
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $6, $3, $4, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | '-' INTERVAL_SYM expr interval '+' expr %prec NEG
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $6, $3, $4, 1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr '*' bit_expr %prec '*'
- {
- $$= new (thd->mem_root) Item_func_mul(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr '/' bit_expr %prec '/'
- {
- $$= new (thd->mem_root) Item_func_div(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr '%' bit_expr %prec '%'
- {
- $$= new (thd->mem_root) Item_func_mod(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr DIV_SYM bit_expr %prec DIV_SYM
- {
- $$= new (thd->mem_root) Item_func_int_div(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr MOD_SYM bit_expr %prec MOD_SYM
- {
- $$= new (thd->mem_root) Item_func_mod(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | bit_expr '^' bit_expr
- {
- $$= new (thd->mem_root) Item_func_bit_xor(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | mysql_concatenation_expr %prec '^'
- ;
-
-or:
- OR_SYM
- | OR2_SYM
- ;
-
-and:
- AND_SYM
- | AND_AND_SYM
- ;
-
-not:
- NOT_SYM
- | NOT2_SYM
- ;
-
-not2:
- '!'
- | NOT2_SYM
- ;
-
-comp_op:
- '=' { $$ = &comp_eq_creator; }
- | GE { $$ = &comp_ge_creator; }
- | '>' { $$ = &comp_gt_creator; }
- | LE { $$ = &comp_le_creator; }
- | '<' { $$ = &comp_lt_creator; }
- | NE { $$ = &comp_ne_creator; }
- ;
-
-all_or_any:
- ALL { $$ = 1; }
- | ANY_SYM { $$ = 0; }
- ;
-
-opt_dyncol_type:
- /* empty */
- {
- $$.set(DYN_COL_NULL); /* automatic type */
- Lex->charset= NULL;
- }
- | AS dyncol_type { $$= $2; }
- ;
-
-dyncol_type:
- numeric_dyncol_type { $$= $1; Lex->charset= NULL; }
- | temporal_dyncol_type { $$= $1; Lex->charset= NULL; }
- | string_dyncol_type { $$= $1; }
- ;
-
-numeric_dyncol_type:
- INT_SYM { $$.set(DYN_COL_INT); }
- | UNSIGNED INT_SYM { $$.set(DYN_COL_UINT); }
- | DOUBLE_SYM { $$.set(DYN_COL_DOUBLE); }
- | REAL { $$.set(DYN_COL_DOUBLE); }
- | FLOAT_SYM { $$.set(DYN_COL_DOUBLE); }
- | DECIMAL_SYM float_options { $$.set(DYN_COL_DECIMAL, $2); }
- ;
-
-temporal_dyncol_type:
- DATE_SYM { $$.set(DYN_COL_DATE); }
- | TIME_SYM opt_field_length { $$.set(DYN_COL_TIME, 0, $2); }
- | DATETIME opt_field_length { $$.set(DYN_COL_DATETIME, 0, $2); }
- ;
-
-string_dyncol_type:
- char
- { Lex->charset= thd->variables.collation_connection; }
- opt_binary
- {
- $$.set(DYN_COL_STRING);
- }
- | nchar
- {
- $$.set(DYN_COL_STRING);
- Lex->charset= national_charset_info;
- }
- ;
-
-dyncall_create_element:
- expr ',' expr opt_dyncol_type
- {
- LEX *lex= Lex;
- $$= (DYNCALL_CREATE_DEF *)
- alloc_root(thd->mem_root, sizeof(DYNCALL_CREATE_DEF));
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- $$->key= $1;
- $$->value= $3;
- $$->type= (DYNAMIC_COLUMN_TYPE)$4.dyncol_type();
- $$->cs= lex->charset;
- if ($4.length())
- $$->len= strtoul($4.length(), NULL, 10);
- else
- $$->len= 0;
- if ($4.dec())
- $$->frac= strtoul($4.dec(), NULL, 10);
- else
- $$->len= 0;
- }
- ;
-
-dyncall_create_list:
- dyncall_create_element
- {
- $$= new (thd->mem_root) List<DYNCALL_CREATE_DEF>;
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- $$->push_back($1, thd->mem_root);
- }
- | dyncall_create_list ',' dyncall_create_element
- {
- $1->push_back($3, thd->mem_root);
- $$= $1;
- }
- ;
-
-
-plsql_cursor_attr:
- ISOPEN_SYM { $$= PLSQL_CURSOR_ATTR_ISOPEN; }
- | FOUND_SYM { $$= PLSQL_CURSOR_ATTR_FOUND; }
- | NOTFOUND_SYM { $$= PLSQL_CURSOR_ATTR_NOTFOUND; }
- | ROWCOUNT_SYM { $$= PLSQL_CURSOR_ATTR_ROWCOUNT; }
- ;
-
-explicit_cursor_attr:
- ident PERCENT_ORACLE_SYM plsql_cursor_attr
- {
- if (unlikely(!($$= Lex->make_item_plsql_cursor_attr(thd, &$1, $3))))
- MYSQL_YYABORT;
- }
- ;
-
-
-trim_operands:
- expr { $$.set(TRIM_BOTH, $1); }
- | LEADING expr FROM expr { $$.set(TRIM_LEADING, $2, $4); }
- | TRAILING expr FROM expr { $$.set(TRIM_TRAILING, $2, $4); }
- | BOTH expr FROM expr { $$.set(TRIM_BOTH, $2, $4); }
- | LEADING FROM expr { $$.set(TRIM_LEADING, $3); }
- | TRAILING FROM expr { $$.set(TRIM_TRAILING, $3); }
- | BOTH FROM expr { $$.set(TRIM_BOTH, $3); }
- | expr FROM expr { $$.set(TRIM_BOTH, $1, $3); }
- ;
-
-/*
- Expressions that the parser allows in a column DEFAULT clause
- without parentheses. These expressions cannot end with a COLLATE clause.
-
- If we allowed any "expr" in DEFAULT clause, there would be a confusion
- in queries like this:
- CREATE TABLE t1 (a TEXT DEFAULT 'a' COLLATE latin1_bin);
- It would be not clear what COLLATE stands for:
- - the collation of the column `a`, or
- - the collation of the string literal 'a'
-
- This restriction allows to parse the above query unambiguiusly:
- COLLATE belongs to the column rather than the literal.
- If one needs COLLATE to belong to the literal, parentheses must be used:
- CREATE TABLE t1 (a TEXT DEFAULT ('a' COLLATE latin1_bin));
- Note: the COLLATE clause is rather meaningless here, but the query
- is syntactically correct.
-
- Note, some of the expressions are not actually allowed in DEFAULT,
- e.g. sum_expr, window_func_expr, ROW(...), VALUES().
- We could move them to simple_expr, but that would make
- these two queries return a different error messages:
- CREATE TABLE t1 (a INT DEFAULT AVG(1));
- CREATE TABLE t1 (a INT DEFAULT (AVG(1)));
- The first query would return "syntax error".
- Currenly both return:
- Function or expression 'avg(' is not allowed for 'DEFAULT' ...
-*/
-column_default_non_parenthesized_expr:
- simple_ident
- | function_call_keyword
- | function_call_nonkeyword
- | function_call_generic
- | function_call_conflict
- | literal
- | param_marker { $$= $1; }
- | variable
- | sum_expr
- {
- if (!Lex->select_stack_top)
- {
- my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0));
- MYSQL_YYABORT;
- }
- }
- | window_func_expr
- {
- if (!Lex->select_stack_top)
- {
- my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
- MYSQL_YYABORT;
- }
- }
- | inverse_distribution_function
- | ROW_SYM '(' expr ',' expr_list ')'
- {
- $5->push_front($3, thd->mem_root);
- $$= new (thd->mem_root) Item_row(thd, *$5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | EXISTS '(' subselect ')'
- {
- $$= new (thd->mem_root) Item_exists_subselect(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | '{' ident expr '}'
- {
- if (unlikely(!($$= $3->make_odbc_literal(thd, &$2))))
- MYSQL_YYABORT;
- }
- | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
- {
- $2->push_front($5, thd->mem_root);
- Item_func_match *i1= new (thd->mem_root) Item_func_match(thd, *$2,
- $6);
- if (unlikely(i1 == NULL))
- MYSQL_YYABORT;
- Select->add_ftfunc_to_list(thd, i1);
- $$= i1;
- }
- | CAST_SYM '(' expr AS cast_type ')'
- {
- if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3,
- Lex->charset))))
- MYSQL_YYABORT;
- }
- | CASE_SYM when_list_opt_else END
- {
- if (unlikely(!($$= new(thd->mem_root) Item_func_case_searched(thd, *$2))))
- MYSQL_YYABORT;
- }
- | CASE_SYM expr when_list_opt_else END
- {
- $3->push_front($2, thd->mem_root);
- if (unlikely(!($$= new (thd->mem_root) Item_func_case_simple(thd, *$3))))
- MYSQL_YYABORT;
- }
- | CONVERT_SYM '(' expr ',' cast_type ')'
- {
- if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3,
- Lex->charset))))
- MYSQL_YYABORT;
- }
- | CONVERT_SYM '(' expr USING charset_name ')'
- {
- $$= new (thd->mem_root) Item_func_conv_charset(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | DEFAULT '(' simple_ident ')'
- {
- Item_splocal *il= $3->get_item_splocal();
- if (unlikely(il))
- my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str));
- $$= new (thd->mem_root) Item_default_value(thd, Lex->current_context(),
- $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->default_used= TRUE;
- }
- | VALUE_SYM '(' simple_ident_nospvar ')'
- {
- $$= new (thd->mem_root) Item_insert_value(thd, Lex->current_context(),
- $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | NEXT_SYM VALUE_SYM FOR_SYM table_ident
- {
- if (unlikely(!($$= Lex->create_item_func_nextval(thd, $4))))
- MYSQL_YYABORT;
- }
- | NEXTVAL_SYM '(' table_ident ')'
- {
- if (unlikely(!($$= Lex->create_item_func_nextval(thd, $3))))
- MYSQL_YYABORT;
- }
- | PREVIOUS_SYM VALUE_SYM FOR_SYM table_ident
- {
- if (unlikely(!($$= Lex->create_item_func_lastval(thd, $4))))
- MYSQL_YYABORT;
- }
- | LASTVAL_SYM '(' table_ident ')'
- {
- if (unlikely(!($$= Lex->create_item_func_lastval(thd, $3))))
- MYSQL_YYABORT;
- }
- | SETVAL_SYM '(' table_ident ',' longlong_num ')'
- {
- if (unlikely(!($$= Lex->create_item_func_setval(thd, $3, $5, 0, 1))))
- MYSQL_YYABORT;
- }
- | SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ')'
- {
- if (unlikely(!($$= Lex->create_item_func_setval(thd, $3, $5, 0, $7))))
- MYSQL_YYABORT;
- }
- | SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ',' ulonglong_num ')'
- {
- if (unlikely(!($$= Lex->create_item_func_setval(thd, $3, $5, $9, $7))))
- MYSQL_YYABORT;
- }
- ;
-
-primary_expr:
- column_default_non_parenthesized_expr
- | explicit_cursor_attr
- | '(' parenthesized_expr ')' { $$= $2; }
- | subquery
- {
- if (!($$= Lex->create_item_query_expression(thd, $1->master_unit())))
- MYSQL_YYABORT;
- }
- ;
-
-string_factor_expr:
- primary_expr
- | string_factor_expr COLLATE_SYM collation_name
- {
- if (unlikely(!($$= new (thd->mem_root) Item_func_set_collation(thd, $1, $3))))
- MYSQL_YYABORT;
- }
- ;
-
-simple_expr:
- string_factor_expr %prec NEG
- | BINARY simple_expr
- {
- Type_cast_attributes at(&my_charset_bin);
- if (unlikely(!($$= type_handler_long_blob.create_typecast_item(thd, $2, at))))
- MYSQL_YYABORT;
- }
- | '+' simple_expr %prec NEG
- {
- $$= $2;
- }
- | '-' simple_expr %prec NEG
- {
- $$= $2->neg(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | '~' simple_expr %prec NEG
- {
- $$= new (thd->mem_root) Item_func_bit_neg(thd, $2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | not2 simple_expr %prec NEG
- {
- $$= negate_expression(thd, $2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-mysql_concatenation_expr:
- simple_expr
- | mysql_concatenation_expr MYSQL_CONCAT_SYM simple_expr
- {
- $$= new (thd->mem_root) Item_func_concat(thd, $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-function_call_keyword_timestamp:
- TIMESTAMP '(' expr ')'
- {
- $$= new (thd->mem_root) Item_datetime_typecast(thd, $3,
- AUTO_SEC_PART_DIGITS);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | TIMESTAMP '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_timestamp(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-/*
- Function call syntax using official SQL 2003 keywords.
- Because the function name is an official token,
- a dedicated grammar rule is needed in the parser.
- There is no potential for conflicts
-*/
-function_call_keyword:
- CHAR_SYM '(' expr_list ')'
- {
- $$= new (thd->mem_root) Item_func_char(thd, *$3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | CHAR_SYM '(' expr_list USING charset_name ')'
- {
- $$= new (thd->mem_root) Item_func_char(thd, *$3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | CURRENT_USER optional_braces
- {
- $$= new (thd->mem_root) Item_func_current_user(thd,
- Lex->current_context());
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
- Lex->safe_to_cache_query= 0;
- }
- | CURRENT_ROLE optional_braces
- {
- $$= new (thd->mem_root) Item_func_current_role(thd,
- Lex->current_context());
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
- Lex->safe_to_cache_query= 0;
- }
- | DATE_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_date_typecast(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | DAY_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_dayofmonth(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | HOUR_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_hour(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | INSERT '(' expr ',' expr ',' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_insert(thd, $3, $5, $7, $9);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | INTERVAL_SYM '(' expr ',' expr ')'
- {
- List<Item> *list= new (thd->mem_root) List<Item>;
- if (unlikely(list == NULL))
- MYSQL_YYABORT;
- if (unlikely(list->push_front($5, thd->mem_root)) ||
- unlikely(list->push_front($3, thd->mem_root)))
- MYSQL_YYABORT;
- Item_row *item= new (thd->mem_root) Item_row(thd, *list);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_func_interval(thd, item);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | INTERVAL_SYM '(' expr ',' expr ',' expr_list ')'
- {
- $7->push_front($5, thd->mem_root);
- $7->push_front($3, thd->mem_root);
- Item_row *item= new (thd->mem_root) Item_row(thd, *$7);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_func_interval(thd, item);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | LEFT '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_left(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | MINUTE_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_minute(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | MONTH_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_month(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | RIGHT '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_right(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | SECOND_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_second(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | SQL_SYM PERCENT_ORACLE_SYM ROWCOUNT_SYM
- {
- $$= new (thd->mem_root) Item_func_oracle_sql_rowcount(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
- Lex->safe_to_cache_query= 0;
- }
- | TIME_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_time_typecast(thd, $3,
- AUTO_SEC_PART_DIGITS);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | function_call_keyword_timestamp
- {
- $$= $1;
- }
- | TRIM '(' trim_operands ')'
- {
- if (unlikely(!($$= $3.make_item_func_trim(thd))))
- MYSQL_YYABORT;
- }
- | USER_SYM '(' ')'
- {
- $$= new (thd->mem_root) Item_func_user(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
- Lex->safe_to_cache_query=0;
- }
- | YEAR_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_year(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-/*
- Function calls using non reserved keywords, with special syntaxic forms.
- Dedicated grammar rules are needed because of the syntax,
- but also have the potential to cause incompatibilities with other
- parts of the language.
- MAINTAINER:
- The only reasons a function should be added here are:
- - for compatibility reasons with another SQL syntax (CURDATE),
- - for typing reasons (GET_FORMAT)
- Any other 'Syntaxic sugar' enhancements should be *STRONGLY*
- discouraged.
-*/
-function_call_nonkeyword:
- ADDDATE_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $5,
- INTERVAL_DAY, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | CURDATE optional_braces
- {
- $$= new (thd->mem_root) Item_func_curdate_local(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->safe_to_cache_query=0;
- }
- | CURTIME opt_time_precision
- {
- $$= new (thd->mem_root) Item_func_curtime_local(thd, $2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->safe_to_cache_query=0;
- }
- | DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | DATE_FORMAT_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_date_format(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | DATE_FORMAT_SYM '(' expr ',' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_date_format(thd, $3, $5, $7);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | DECODE_MARIADB_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_decode(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | DECODE_ORACLE_SYM '(' expr ',' decode_when_list_oracle ')'
- {
- $5->push_front($3, thd->mem_root);
- if (unlikely(!($$= new (thd->mem_root) Item_func_decode_oracle(thd, *$5))))
- MYSQL_YYABORT;
- }
- | EXTRACT_SYM '(' interval FROM expr ')'
- {
- $$=new (thd->mem_root) Item_extract(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | GET_FORMAT '(' date_time_type ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_get_format(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | NOW_SYM opt_time_precision
- {
- $$= new (thd->mem_root) Item_func_now_local(thd, $2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->safe_to_cache_query=0;
- }
- | POSITION_SYM '(' bit_expr IN_SYM expr ')'
- {
- $$= new (thd->mem_root) Item_func_locate(thd, $5, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | SUBDATE_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $5,
- INTERVAL_DAY, 1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | SUBSTRING '(' expr ',' expr ',' expr ')'
- {
- if (unlikely(!($$= Lex->make_item_func_substr(thd, $3, $5, $7))))
- MYSQL_YYABORT;
- }
- | SUBSTRING '(' expr ',' expr ')'
- {
- if (unlikely(!($$= Lex->make_item_func_substr(thd, $3, $5))))
- MYSQL_YYABORT;
- }
- | SUBSTRING '(' expr FROM expr FOR_SYM expr ')'
- {
- if (unlikely(!($$= Lex->make_item_func_substr(thd, $3, $5, $7))))
- MYSQL_YYABORT;
- }
- | SUBSTRING '(' expr FROM expr ')'
- {
- if (unlikely(!($$= Lex->make_item_func_substr(thd, $3, $5))))
- MYSQL_YYABORT;
- }
- | SYSDATE opt_time_precision
- {
- /*
- Unlike other time-related functions, SYSDATE() is
- replication-unsafe because it is not affected by the
- TIMESTAMP variable. It is unsafe even if
- sysdate_is_now=1, because the slave may have
- sysdate_is_now=0.
- */
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
- if (global_system_variables.sysdate_is_now == 0)
- $$= new (thd->mem_root) Item_func_sysdate_local(thd, $2);
- else
- $$= new (thd->mem_root) Item_func_now_local(thd, $2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->safe_to_cache_query=0;
- }
- | TIMESTAMP_ADD '(' interval_time_stamp ',' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_date_add_interval(thd, $7, $5, $3, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | TIMESTAMP_DIFF '(' interval_time_stamp ',' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_timestamp_diff(thd, $5, $7, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | TRIM_ORACLE '(' trim_operands ')'
- {
- if (unlikely(!($$= $3.make_item_func_trim_oracle(thd))))
- MYSQL_YYABORT;
- }
- | UTC_DATE_SYM optional_braces
- {
- $$= new (thd->mem_root) Item_func_curdate_utc(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->safe_to_cache_query=0;
- }
- | UTC_TIME_SYM opt_time_precision
- {
- $$= new (thd->mem_root) Item_func_curtime_utc(thd, $2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->safe_to_cache_query=0;
- }
- | UTC_TIMESTAMP_SYM opt_time_precision
- {
- $$= new (thd->mem_root) Item_func_now_utc(thd, $2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->safe_to_cache_query=0;
- }
- |
- COLUMN_ADD_SYM '(' expr ',' dyncall_create_list ')'
- {
- $$= create_func_dyncol_add(thd, $3, *$5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- COLUMN_DELETE_SYM '(' expr ',' expr_list ')'
- {
- $$= create_func_dyncol_delete(thd, $3, *$5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- COLUMN_CHECK_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_dyncol_check(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- COLUMN_CREATE_SYM '(' dyncall_create_list ')'
- {
- $$= create_func_dyncol_create(thd, *$3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
- {
- LEX *lex= Lex;
- $$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(),
- $7.length(), $7.dec(),
- lex->charset);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-/*
- Functions calls using a non reserved keyword, and using a regular syntax.
- Because the non reserved keyword is used in another part of the grammar,
- a dedicated rule is needed here.
-*/
-function_call_conflict:
- ASCII_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_ascii(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | CHARSET '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_charset(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | COALESCE '(' expr_list ')'
- {
- $$= new (thd->mem_root) Item_func_coalesce(thd, *$3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | COLLATION_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_collation(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | DATABASE '(' ')'
- {
- $$= new (thd->mem_root) Item_func_database(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->safe_to_cache_query=0;
- }
- | IF_SYM '(' expr ',' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_if(thd, $3, $5, $7);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | FORMAT_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_format(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | FORMAT_SYM '(' expr ',' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_format(thd, $3, $5, $7);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- /* LAST_VALUE here conflicts with the definition for window functions.
- We have these 2 separate rules to remove the shift/reduce conflict.
- */
- | LAST_VALUE '(' expr ')'
- {
- List<Item> *list= new (thd->mem_root) List<Item>;
- if (unlikely(list == NULL))
- MYSQL_YYABORT;
- list->push_back($3, thd->mem_root);
-
- $$= new (thd->mem_root) Item_func_last_value(thd, *list);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | LAST_VALUE '(' expr_list ',' expr ')'
- {
- $3->push_back($5, thd->mem_root);
- $$= new (thd->mem_root) Item_func_last_value(thd, *$3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | MICROSECOND_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_microsecond(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | MOD_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_mod(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | OLD_PASSWORD_SYM '(' expr ')'
- {
- $$= new (thd->mem_root)
- Item_func_password(thd, $3, Item_func_password::OLD);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | PASSWORD_SYM '(' expr ')'
- {
- Item* i1;
- i1= new (thd->mem_root) Item_func_password(thd, $3);
- if (unlikely(i1 == NULL))
- MYSQL_YYABORT;
- $$= i1;
- }
- | QUARTER_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_quarter(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | REPEAT_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_repeat(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | REPLACE '(' expr ',' expr ',' expr ')'
- {
- if (unlikely(!($$= Lex->make_item_func_replace(thd, $3, $5, $7))))
- MYSQL_YYABORT;
- }
- | REVERSE_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_reverse(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | ROW_COUNT_SYM '(' ')'
- {
- $$= new (thd->mem_root) Item_func_row_count(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
- Lex->safe_to_cache_query= 0;
- }
- | TRUNCATE_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_round(thd, $3, $5, 1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | WEEK_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_func_week(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | WEEK_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_week(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | WEIGHT_STRING_SYM '(' expr opt_ws_levels ')'
- {
- $$= new (thd->mem_root) Item_func_weight_string(thd, $3, 0, 0, $4);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | WEIGHT_STRING_SYM '(' expr AS CHAR_SYM ws_nweights opt_ws_levels ')'
- {
- $$= new (thd->mem_root)
- Item_func_weight_string(thd, $3, 0, $6,
- $7 | MY_STRXFRM_PAD_WITH_SPACE);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | WEIGHT_STRING_SYM '(' expr AS BINARY ws_nweights ')'
- {
- Item *item= new (thd->mem_root) Item_char_typecast(thd, $3, $6,
- &my_charset_bin);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- $$= new (thd->mem_root)
- Item_func_weight_string(thd, item, 0, $6,
- MY_STRXFRM_PAD_WITH_SPACE);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | WEIGHT_STRING_SYM '(' expr ',' ulong_num ',' ulong_num ',' ulong_num ')'
- {
- $$= new (thd->mem_root) Item_func_weight_string(thd, $3, $5, $7,
- $9);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-/*
- Regular function calls.
- The function name is *not* a token, and therefore is guaranteed to not
- introduce side effects to the language in general.
- MAINTAINER:
- All the new functions implemented for new features should fit into
- this category. The place to implement the function itself is
- in sql/item_create.cc
-*/
-function_call_generic:
- IDENT_sys '('
- {
-#ifdef HAVE_DLOPEN
- udf_func *udf= 0;
- LEX *lex= Lex;
- if (using_udf_functions &&
- (udf= find_udf($1.str, $1.length)) &&
- udf->type == UDFTYPE_AGGREGATE)
- {
- if (unlikely(lex->current_select->inc_in_sum_expr()))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- }
- /* Temporary placing the result of find_udf in $3 */
- $<udf>$= udf;
-#endif
- }
- opt_udf_expr_list ')'
- {
- const Type_handler *h;
- Create_func *builder;
- Item *item= NULL;
-
- if (unlikely(check_routine_name(&$1)))
- MYSQL_YYABORT;
-
- /*
- Implementation note:
- names are resolved with the following order:
- - MySQL native functions,
- - User Defined Functions,
- - Stored Functions (assuming the current <use> database)
-
- This will be revised with WL#2128 (SQL PATH)
- */
- if ((h= Type_handler::handler_by_name(thd, $1)) &&
- (item= h->make_constructor_item(thd, $4)))
- {
- // Found a constructor with a proper argument count
- }
- else if ((builder= find_native_function_builder(thd, &$1)))
- {
- item= builder->create_func(thd, &$1, $4);
- }
- else
- {
-#ifdef HAVE_DLOPEN
- /* Retrieving the result of find_udf */
- udf_func *udf= $<udf>3;
-
- if (udf)
- {
- if (udf->type == UDFTYPE_AGGREGATE)
- {
- Select->in_sum_expr--;
- }
-
- item= Create_udf_func::s_singleton.create(thd, udf, $4);
- }
- else
-#endif
- {
- builder= find_qualified_function_builder(thd);
- DBUG_ASSERT(builder);
- item= builder->create_func(thd, &$1, $4);
- }
- }
-
- if (unlikely(! ($$= item)))
- MYSQL_YYABORT;
- }
- | CONTAINS_SYM '(' opt_expr_list ')'
- {
- if (!($$= Lex->make_item_func_call_native_or_parse_error(thd,
- $1, $3)))
- MYSQL_YYABORT;
- }
- | WITHIN '(' opt_expr_list ')'
- {
- if (!($$= Lex->make_item_func_call_native_or_parse_error(thd,
- $1, $3)))
- MYSQL_YYABORT;
- }
- | ident_cli '.' ident_cli '(' opt_expr_list ')'
- {
- if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, $5))))
- MYSQL_YYABORT;
- }
- ;
-
-fulltext_options:
- opt_natural_language_mode opt_query_expansion
- { $$= $1 | $2; }
- | IN_SYM BOOLEAN_SYM MODE_SYM
- { $$= FT_BOOL; }
- ;
-
-opt_natural_language_mode:
- /* nothing */ { $$= FT_NL; }
- | IN_SYM NATURAL LANGUAGE_SYM MODE_SYM { $$= FT_NL; }
- ;
-
-opt_query_expansion:
- /* nothing */ { $$= 0; }
- | WITH QUERY_SYM EXPANSION_SYM { $$= FT_EXPAND; }
- ;
-
-opt_udf_expr_list:
- /* empty */ { $$= NULL; }
- | udf_expr_list { $$= $1; }
- ;
-
-udf_expr_list:
- udf_expr
- {
- $$= new (thd->mem_root) List<Item>;
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- $$->push_back($1, thd->mem_root);
- }
- | udf_expr_list ',' udf_expr
- {
- $1->push_back($3, thd->mem_root);
- $$= $1;
- }
- ;
-
-udf_expr:
- remember_name expr remember_end select_alias
- {
- /*
- Use Item::name as a storage for the attribute value of user
- defined function argument. It is safe to use Item::name
- because the syntax will not allow having an explicit name here.
- See WL#1017 re. udf attributes.
- */
- if ($4.str)
- {
- $2->is_autogenerated_name= FALSE;
- $2->set_name(thd, $4);
- }
- /*
- A field has to have its proper name in order for name
- resolution to work, something we are only guaranteed if we
- parse it out. If we hijack the input stream with
- remember_name we may get quoted or escaped names.
- */
- else if ($2->type() != Item::FIELD_ITEM &&
- $2->type() != Item::REF_ITEM /* For HAVING */ )
- $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
- $$= $2;
- }
- ;
-
-sum_expr:
- AVG_SYM '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_avg(thd, $3, FALSE);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | AVG_SYM '(' DISTINCT in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_avg(thd, $4, TRUE);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | BIT_AND '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_and(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | BIT_OR '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_or(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | BIT_XOR '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_xor(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | COUNT_SYM '(' opt_all '*' ')'
- {
- Item *item= new (thd->mem_root) Item_int(thd, (int32) 0L, 1);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_sum_count(thd, item);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | COUNT_SYM '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_count(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | COUNT_SYM '(' DISTINCT
- { Select->in_sum_expr++; }
- expr_list
- { Select->in_sum_expr--; }
- ')'
- {
- $$= new (thd->mem_root) Item_sum_count(thd, *$5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | MIN_SYM '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_min(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- /*
- According to ANSI SQL, DISTINCT is allowed and has
- no sense inside MIN and MAX grouping functions; so MIN|MAX(DISTINCT ...)
- is processed like an ordinary MIN | MAX()
- */
- | MIN_SYM '(' DISTINCT in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_min(thd, $4);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | MAX_SYM '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_max(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | MAX_SYM '(' DISTINCT in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_max(thd, $4);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | STD_SYM '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_std(thd, $3, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | VARIANCE_SYM '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_variance(thd, $3, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | STDDEV_SAMP_SYM '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_std(thd, $3, 1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | VAR_SAMP_SYM '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_variance(thd, $3, 1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | SUM_SYM '(' in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_sum(thd, $3, FALSE);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | SUM_SYM '(' DISTINCT in_sum_expr ')'
- {
- $$= new (thd->mem_root) Item_sum_sum(thd, $4, TRUE);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | GROUP_CONCAT_SYM '(' opt_distinct
- { Select->in_sum_expr++; }
- expr_list opt_gorder_clause
- opt_gconcat_separator opt_glimit_clause
- ')'
- {
- SELECT_LEX *sel= Select;
- sel->in_sum_expr--;
- $$= new (thd->mem_root)
- Item_func_group_concat(thd, Lex->current_context(),
- $3, $5,
- sel->gorder_list, $7, $8,
- sel->select_limit,
- sel->offset_limit);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- sel->select_limit= NULL;
- sel->offset_limit= NULL;
- sel->explicit_limit= 0;
- $5->empty();
- sel->gorder_list.empty();
- }
- | JSON_ARRAYAGG_SYM '(' opt_distinct
- { Select->in_sum_expr++; }
- expr_list opt_gorder_clause opt_glimit_clause
- ')'
- {
- SELECT_LEX *sel= Select;
- List<Item> *args= $5;
- sel->in_sum_expr--;
- if (args && args->elements > 1)
- {
- /* JSON_ARRAYAGG supports only one parameter */
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), "JSON_ARRAYAGG");
- MYSQL_YYABORT;
- }
- String* s= new (thd->mem_root) String(",", 1, &my_charset_latin1);
- if (unlikely(s == NULL))
- MYSQL_YYABORT;
-
- $$= new (thd->mem_root)
- Item_func_json_arrayagg(thd, Lex->current_context(),
- $3, args,
- sel->gorder_list, s, $7,
- sel->select_limit,
- sel->offset_limit);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- sel->select_limit= NULL;
- sel->offset_limit= NULL;
- sel->explicit_limit= 0;
- $5->empty();
- sel->gorder_list.empty();
- }
- | JSON_OBJECTAGG_SYM '('
- { Select->in_sum_expr++; }
- expr ',' expr ')'
- {
- SELECT_LEX *sel= Select;
- sel->in_sum_expr--;
-
- $$= new (thd->mem_root) Item_func_json_objectagg(thd, $4, $6);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-window_func_expr:
- window_func OVER_SYM window_name
- {
- $$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- if (unlikely(Select->add_window_func((Item_window_func *) $$)))
- MYSQL_YYABORT;
- }
- |
- window_func OVER_SYM window_spec
- {
- LEX *lex= Lex;
- if (unlikely(Select->add_window_spec(thd, lex->win_ref,
- Select->group_list,
- Select->order_list,
- lex->win_frame)))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1,
- thd->lex->win_spec);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- if (unlikely(Select->add_window_func((Item_window_func *) $$)))
- MYSQL_YYABORT;
- }
- ;
-
-window_func:
- simple_window_func
- |
- sum_expr
- {
- ((Item_sum *) $1)->mark_as_window_func_sum_expr();
- }
- |
- function_call_generic
- {
- Item* item = (Item*)$1;
- /* Only UDF aggregate here possible */
- if ((item == NULL) ||
- (item->type() != Item::SUM_FUNC_ITEM)
- || (((Item_sum *)item)->sum_func() != Item_sum::UDF_SUM_FUNC))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
-
- ((Item_sum *) $1)->mark_as_window_func_sum_expr();
- }
- ;
-
-simple_window_func:
- ROW_NUMBER_SYM '(' ')'
- {
- $$= new (thd->mem_root) Item_sum_row_number(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- RANK_SYM '(' ')'
- {
- $$= new (thd->mem_root) Item_sum_rank(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- DENSE_RANK_SYM '(' ')'
- {
- $$= new (thd->mem_root) Item_sum_dense_rank(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- PERCENT_RANK_SYM '(' ')'
- {
- $$= new (thd->mem_root) Item_sum_percent_rank(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- CUME_DIST_SYM '(' ')'
- {
- $$= new (thd->mem_root) Item_sum_cume_dist(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- NTILE_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_sum_ntile(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- FIRST_VALUE_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_sum_first_value(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- LAST_VALUE '(' expr ')'
- {
- $$= new (thd->mem_root) Item_sum_last_value(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- NTH_VALUE_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_sum_nth_value(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- LEAD_SYM '(' expr ')'
- {
- /* No second argument defaults to 1. */
- Item* item_offset= new (thd->mem_root) Item_uint(thd, 1);
- if (unlikely(item_offset == NULL))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_sum_lead(thd, $3, item_offset);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- LEAD_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_sum_lead(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- LAG_SYM '(' expr ')'
- {
- /* No second argument defaults to 1. */
- Item* item_offset= new (thd->mem_root) Item_uint(thd, 1);
- if (unlikely(item_offset == NULL))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_sum_lag(thd, $3, item_offset);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- |
- LAG_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_sum_lag(thd, $3, $5);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-
-
-inverse_distribution_function:
- percentile_function OVER_SYM
- '(' opt_window_partition_clause ')'
- {
- LEX *lex= Lex;
- if (unlikely(Select->add_window_spec(thd, lex->win_ref,
- Select->group_list,
- Select->order_list,
- NULL)))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1,
- thd->lex->win_spec);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- if (unlikely(Select->add_window_func((Item_window_func *) $$)))
- MYSQL_YYABORT;
- }
- ;
-
-percentile_function:
- inverse_distribution_function_def WITHIN GROUP_SYM '('
- { Select->prepare_add_window_spec(thd); }
- order_by_single_element_list ')'
- {
- $$= $1;
- }
- | MEDIAN_SYM '(' expr ')'
- {
- Item *args= new (thd->mem_root) Item_decimal(thd, "0.5", 3,
- thd->charset());
- if (unlikely(args == NULL) || unlikely(thd->is_error()))
- MYSQL_YYABORT;
- Select->prepare_add_window_spec(thd);
- if (unlikely(add_order_to_list(thd, $3,FALSE)))
- MYSQL_YYABORT;
-
- $$= new (thd->mem_root) Item_sum_percentile_cont(thd, args);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-inverse_distribution_function_def:
- PERCENTILE_CONT_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_sum_percentile_cont(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | PERCENTILE_DISC_SYM '(' expr ')'
- {
- $$= new (thd->mem_root) Item_sum_percentile_disc(thd, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-order_by_single_element_list:
- ORDER_SYM BY order_ident order_dir
- {
- if (unlikely(add_order_to_list(thd, $3,(bool) $4)))
- MYSQL_YYABORT;
- }
- ;
-
-
-window_name:
- ident
- {
- $$= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-variable:
- '@'
- {
- if (unlikely(! Lex->parsing_options.allows_variable))
- my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
- }
- variable_aux
- {
- $$= $3;
- }
- ;
-
-variable_aux:
- ident_or_text SET_VAR expr
- {
- Item_func_set_user_var *item;
- $$= item= new (thd->mem_root) Item_func_set_user_var(thd, &$1, $3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- LEX *lex= Lex;
- lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- lex->set_var_list.push_back(item, thd->mem_root);
- }
- | ident_or_text
- {
- $$= new (thd->mem_root) Item_func_get_user_var(thd, &$1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- LEX *lex= Lex;
- lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- }
- | '@' opt_var_ident_type ident_sysvar_name
- {
- if (unlikely(!($$= Lex->make_item_sysvar(thd, $2, &$3))))
- MYSQL_YYABORT;
- }
- | '@' opt_var_ident_type ident_sysvar_name '.' ident
- {
- if (unlikely(!($$= Lex->make_item_sysvar(thd, $2, &$3, &$5))))
- MYSQL_YYABORT;
- }
- ;
-
-opt_distinct:
- /* empty */ { $$ = 0; }
- | DISTINCT { $$ = 1; }
- ;
-
-opt_gconcat_separator:
- /* empty */
- {
- $$= new (thd->mem_root) String(",", 1, &my_charset_latin1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | SEPARATOR_SYM text_string { $$ = $2; }
- ;
-
-opt_gorder_clause:
- /* empty */
- | ORDER_SYM BY gorder_list
- ;
-
-gorder_list:
- gorder_list ',' order_ident order_dir
- {
- if (unlikely(add_gorder_to_list(thd, $3,(bool) $4)))
- MYSQL_YYABORT;
- }
- | order_ident order_dir
- {
- if (unlikely(add_gorder_to_list(thd, $1,(bool) $2)))
- MYSQL_YYABORT;
- }
- ;
-
-opt_glimit_clause:
- /* empty */ { $$ = 0; }
- | glimit_clause { $$ = 1; }
- ;
-
-glimit_clause_init:
- LIMIT{}
- ;
-
-glimit_clause:
- glimit_clause_init glimit_options
- {
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
- }
- ;
-
-glimit_options:
- limit_option
- {
- SELECT_LEX *sel= Select;
- sel->select_limit= $1;
- sel->offset_limit= 0;
- sel->explicit_limit= 1;
- }
- | limit_option ',' limit_option
- {
- SELECT_LEX *sel= Select;
- sel->select_limit= $3;
- sel->offset_limit= $1;
- sel->explicit_limit= 1;
- }
- | limit_option OFFSET_SYM limit_option
- {
- SELECT_LEX *sel= Select;
- sel->select_limit= $1;
- sel->offset_limit= $3;
- sel->explicit_limit= 1;
- }
- ;
-
-
-
-in_sum_expr:
- opt_all
- {
- LEX *lex= Lex;
- if (unlikely(lex->current_select->inc_in_sum_expr()))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- }
- expr
- {
- Select->in_sum_expr--;
- $$= $3;
- }
- ;
-
-cast_type:
- BINARY opt_field_length
- { $$.set(&type_handler_long_blob, $2); Lex->charset= &my_charset_bin; }
- | CHAR_SYM opt_field_length
- { Lex->charset= thd->variables.collation_connection; }
- opt_binary
- { $$.set(&type_handler_long_blob, $2); }
- | VARCHAR field_length
- { Lex->charset= thd->variables.collation_connection; }
- opt_binary
- { $$.set(&type_handler_long_blob, $2); }
- | VARCHAR2_ORACLE_SYM field_length
- { Lex->charset= thd->variables.collation_connection; }
- opt_binary
- { $$.set(&type_handler_long_blob, $2); }
- | NCHAR_SYM opt_field_length
- {
- Lex->charset= national_charset_info;
- $$.set(&type_handler_long_blob, $2, 0);
- }
- | cast_type_numeric { $$= $1; Lex->charset= NULL; }
- | cast_type_temporal { $$= $1; Lex->charset= NULL; }
- | IDENT_sys
- {
- if (Lex->set_cast_type_udt(&$$, $1))
- MYSQL_YYABORT;
- }
- | reserved_keyword_udt
- {
- if (Lex->set_cast_type_udt(&$$, $1))
- MYSQL_YYABORT;
- }
- | non_reserved_keyword_udt
- {
- if (Lex->set_cast_type_udt(&$$, $1))
- MYSQL_YYABORT;
- }
- ;
-
-cast_type_numeric:
- INT_SYM { $$.set(&type_handler_slonglong); }
- | SIGNED_SYM { $$.set(&type_handler_slonglong); }
- | SIGNED_SYM INT_SYM { $$.set(&type_handler_slonglong); }
- | UNSIGNED { $$.set(&type_handler_ulonglong); }
- | UNSIGNED INT_SYM { $$.set(&type_handler_ulonglong); }
- | DECIMAL_SYM float_options { $$.set(&type_handler_newdecimal, $2); }
- | FLOAT_SYM { $$.set(&type_handler_float); }
- | DOUBLE_SYM opt_precision { $$.set(&type_handler_double, $2); }
- ;
-
-cast_type_temporal:
- DATE_SYM { $$.set(&type_handler_newdate); }
- | TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); }
- | DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); }
- | INTERVAL_SYM DAY_SECOND_SYM field_length
- {
- $$.set(&type_handler_interval_DDhhmmssff, 0, $3);
- }
- ;
-
-opt_expr_list:
- /* empty */ { $$= NULL; }
- | expr_list { $$= $1;}
- ;
-
-expr_list:
- expr
- {
- if (unlikely(!($$= List<Item>::make(thd->mem_root, $1))))
- MYSQL_YYABORT;
- }
- | expr_list ',' expr
- {
- $1->push_back($3, thd->mem_root);
- $$= $1;
- }
- ;
-
-ident_list_arg:
- ident_list { $$= $1; }
- | '(' ident_list ')' { $$= $2; }
- ;
-
-ident_list:
- simple_ident
- {
- $$= new (thd->mem_root) List<Item>;
- if (unlikely($$ == NULL) ||
- unlikely($$->push_back($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | ident_list ',' simple_ident
- {
- $1->push_back($3, thd->mem_root);
- $$= $1;
- }
- ;
-
-when_list:
- WHEN_SYM expr THEN_SYM expr
- {
- $$= new (thd->mem_root) List<Item>;
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- if (unlikely($$->push_back($2, thd->mem_root) ||
- $$->push_back($4, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | when_list WHEN_SYM expr THEN_SYM expr
- {
- if (unlikely($1->push_back($3, thd->mem_root) ||
- $1->push_back($5, thd->mem_root)))
- MYSQL_YYABORT;
- $$= $1;
- }
- ;
-
-when_list_opt_else:
- when_list
- | when_list ELSE expr
- {
- if (unlikely($1->push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- $$= $1;
- }
- ;
-
-decode_when_list_oracle:
- expr ',' expr
- {
- $$= new (thd->mem_root) List<Item>;
- if (unlikely($$ == NULL) ||
- unlikely($$->push_back($1, thd->mem_root)) ||
- unlikely($$->push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
-
- }
- | decode_when_list_oracle ',' expr
- {
- $$= $1;
- if (unlikely($$->push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-
-/* Equivalent to <table reference> in the SQL:2003 standard. */
-/* Warning - may return NULL in case of incomplete SELECT */
-table_ref:
- table_factor { $$= $1; }
- | join_table
- {
- LEX *lex= Lex;
- if (unlikely(!($$= lex->current_select->nest_last_join(thd))))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- }
- ;
-
-join_table_list:
- derived_table_list { MYSQL_YYABORT_UNLESS($$=$1); }
- ;
-
-/*
- The ODBC escape syntax for Outer Join is: '{' OJ join_table '}'
- The parser does not define OJ as a token, any ident is accepted
- instead in $2 (ident). Also, all productions from table_ref can
- be escaped, not only join_table. Both syntax extensions are safe
- and are ignored.
-*/
-esc_table_ref:
- table_ref { $$=$1; }
- | '{' ident table_ref '}' { $$=$3; }
- ;
-
-/* Equivalent to <table reference list> in the SQL:2003 standard. */
-/* Warning - may return NULL in case of incomplete SELECT */
-derived_table_list:
- esc_table_ref
- {
- $$=$1;
- Select->add_joined_table($1);
- }
- | derived_table_list ',' esc_table_ref
- {
- MYSQL_YYABORT_UNLESS($1 && ($$=$3));
- Select->add_joined_table($3);
- }
- ;
-
-/*
- Notice that JOIN can be a left-associative operator in one context and
- a right-associative operator in another context (see the comment for
- st_select_lex::add_cross_joined_table).
-*/
-join_table:
- /* INNER JOIN variants */
- table_ref normal_join table_ref %prec CONDITIONLESS_JOIN
- {
- MYSQL_YYABORT_UNLESS($1 && ($$=$3));
- if (unlikely(Select->add_cross_joined_table($1, $3, $2)))
- MYSQL_YYABORT;
- }
- | table_ref normal_join table_ref
- ON
- {
- MYSQL_YYABORT_UNLESS($1 && $3);
- Select->add_joined_table($1);
- Select->add_joined_table($3);
- /* Change the current name resolution context to a local context. */
- if (unlikely(push_new_name_resolution_context(thd, $1, $3)))
- MYSQL_YYABORT;
- Select->parsing_place= IN_ON;
- }
- expr
- {
- $3->straight=$2;
- add_join_on(thd, $3, $6);
- $3->on_context= Lex->pop_context();
- Select->parsing_place= NO_MATTER;
- }
- | table_ref normal_join table_ref
- USING
- {
- MYSQL_YYABORT_UNLESS($1 && $3);
- Select->add_joined_table($1);
- Select->add_joined_table($3);
- }
- '(' using_list ')'
- {
- $3->straight=$2;
- add_join_natural($1,$3,$7,Select);
- $$=$3;
- }
- | table_ref NATURAL inner_join table_factor
- {
- MYSQL_YYABORT_UNLESS($1 && ($$=$4));
- Select->add_joined_table($1);
- Select->add_joined_table($4);
- $4->straight=$3;
- add_join_natural($1,$4,NULL,Select);
- }
-
- /* LEFT JOIN variants */
- | table_ref LEFT opt_outer JOIN_SYM table_ref
- ON
- {
- MYSQL_YYABORT_UNLESS($1 && $5);
- Select->add_joined_table($1);
- Select->add_joined_table($5);
- /* Change the current name resolution context to a local context. */
- if (unlikely(push_new_name_resolution_context(thd, $1, $5)))
- MYSQL_YYABORT;
- Select->parsing_place= IN_ON;
- }
- expr
- {
- add_join_on(thd, $5, $8);
- $5->on_context= Lex->pop_context();
- $5->outer_join|=JOIN_TYPE_LEFT;
- $$=$5;
- Select->parsing_place= NO_MATTER;
- }
- | table_ref LEFT opt_outer JOIN_SYM table_factor
- {
- MYSQL_YYABORT_UNLESS($1 && $5);
- Select->add_joined_table($1);
- Select->add_joined_table($5);
- }
- USING '(' using_list ')'
- {
- add_join_natural($1,$5,$9,Select);
- $5->outer_join|=JOIN_TYPE_LEFT;
- $$=$5;
- }
- | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
- {
- MYSQL_YYABORT_UNLESS($1 && $6);
- Select->add_joined_table($1);
- Select->add_joined_table($6);
- add_join_natural($1,$6,NULL,Select);
- $6->outer_join|=JOIN_TYPE_LEFT;
- $$=$6;
- }
-
- /* RIGHT JOIN variants */
- | table_ref RIGHT opt_outer JOIN_SYM table_ref
- ON
- {
- MYSQL_YYABORT_UNLESS($1 && $5);
- Select->add_joined_table($1);
- Select->add_joined_table($5);
- /* Change the current name resolution context to a local context. */
- if (unlikely(push_new_name_resolution_context(thd, $1, $5)))
- MYSQL_YYABORT;
- Select->parsing_place= IN_ON;
- }
- expr
- {
- LEX *lex= Lex;
- if (unlikely(!($$= lex->current_select->convert_right_join())))
- MYSQL_YYABORT;
- add_join_on(thd, $$, $8);
- $1->on_context= Lex->pop_context();
- Select->parsing_place= NO_MATTER;
- }
- | table_ref RIGHT opt_outer JOIN_SYM table_factor
- {
- MYSQL_YYABORT_UNLESS($1 && $5);
- Select->add_joined_table($1);
- Select->add_joined_table($5);
- }
- USING '(' using_list ')'
- {
- LEX *lex= Lex;
- if (unlikely(!($$= lex->current_select->convert_right_join())))
- MYSQL_YYABORT;
- add_join_natural($$,$5,$9,Select);
- }
- | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
- {
- MYSQL_YYABORT_UNLESS($1 && $6);
- Select->add_joined_table($1);
- Select->add_joined_table($6);
- add_join_natural($6,$1,NULL,Select);
- LEX *lex= Lex;
- if (unlikely(!($$= lex->current_select->convert_right_join())))
- MYSQL_YYABORT;
- }
- ;
-
-
-inner_join: /* $$ set if using STRAIGHT_JOIN, false otherwise */
- JOIN_SYM { $$ = 0; }
- | INNER_SYM JOIN_SYM { $$ = 0; }
- | STRAIGHT_JOIN { $$ = 1; }
- ;
-
-normal_join:
- inner_join { $$ = $1; }
- | CROSS JOIN_SYM { $$ = 0; }
- ;
-
-/*
- table PARTITION (list of partitions), reusing using_list instead of creating
- a new rule for partition_list.
-*/
-opt_use_partition:
- /* empty */ { $$= 0;}
- | use_partition
- ;
-
-use_partition:
- PARTITION_SYM '(' using_list ')' have_partitioning
- {
- $$= $3;
- Select->parsing_place= Select->save_parsing_place;
- Select->save_parsing_place= NO_MATTER;
- }
- ;
-
-table_factor:
- table_primary_ident_opt_parens { $$= $1; }
- | table_primary_derived_opt_parens { $$= $1; }
- | join_table_parens
- {
- $1->nested_join->nest_type= 0;
- $$= $1;
- }
- | table_reference_list_parens { $$= $1; }
- ;
-
-table_primary_ident_opt_parens:
- table_primary_ident { $$= $1; }
- | '(' table_primary_ident_opt_parens ')' { $$= $2; }
- ;
-
-table_primary_derived_opt_parens:
- table_primary_derived { $$= $1; }
- | '(' table_primary_derived_opt_parens ')' { $$= $2; }
- ;
-
-table_reference_list_parens:
- '(' table_reference_list_parens ')' { $$= $2; }
- | '(' nested_table_reference_list ')'
- {
- if (!($$= Select->end_nested_join(thd)))
- MYSQL_YYABORT;
- }
- ;
-
-nested_table_reference_list:
- table_ref ',' table_ref
- {
- if (Select->init_nested_join(thd))
- MYSQL_YYABORT;
- Select->add_joined_table($1);
- Select->add_joined_table($3);
- $$= $1->embedding;
- }
- | nested_table_reference_list ',' table_ref
- {
- Select->add_joined_table($3);
- $$= $1;
- }
- ;
-
-join_table_parens:
- '(' join_table_parens ')' { $$= $2; }
- | '(' join_table ')'
- {
- LEX *lex= Lex;
- if (!($$= lex->current_select->nest_last_join(thd)))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- }
- ;
-
-
-table_primary_ident:
- table_ident opt_use_partition opt_for_system_time_clause
- opt_table_alias_clause opt_key_definition
- {
- SELECT_LEX *sel= Select;
- sel->table_join_options= 0;
- if (!($$= Select->add_table_to_list(thd, $1, $4,
- Select->get_table_join_options(),
- YYPS->m_lock_type,
- YYPS->m_mdl_type,
- Select->pop_index_hints(),
- $2)))
- MYSQL_YYABORT;
- if ($3)
- $$->vers_conditions= Lex->vers_conditions;
- }
- ;
-
-table_primary_derived:
- subquery
- opt_for_system_time_clause table_alias_clause
- {
- if (!($$= Lex->parsed_derived_table($1->master_unit(), $2, $3)))
- MYSQL_YYABORT;
- }
- ;
-
-opt_outer:
- /* empty */ {}
- | OUTER {}
- ;
-
-index_hint_clause:
- /* empty */
- {
- $$= thd->variables.old_mode ? INDEX_HINT_MASK_JOIN : INDEX_HINT_MASK_ALL;
- }
- | FOR_SYM JOIN_SYM { $$= INDEX_HINT_MASK_JOIN; }
- | FOR_SYM ORDER_SYM BY { $$= INDEX_HINT_MASK_ORDER; }
- | FOR_SYM GROUP_SYM BY { $$= INDEX_HINT_MASK_GROUP; }
- ;
-
-index_hint_type:
- FORCE_SYM { $$= INDEX_HINT_FORCE; }
- | IGNORE_SYM { $$= INDEX_HINT_IGNORE; }
- ;
-
-index_hint_definition:
- index_hint_type key_or_index index_hint_clause
- {
- Select->set_index_hint_type($1, $3);
- }
- '(' key_usage_list ')'
- | USE_SYM key_or_index index_hint_clause
- {
- Select->set_index_hint_type(INDEX_HINT_USE, $3);
- }
- '(' opt_key_usage_list ')'
- ;
-
-index_hints_list:
- index_hint_definition
- | index_hints_list index_hint_definition
- ;
-
-opt_index_hints_list:
- /* empty */
- | { Select->alloc_index_hints(thd); } index_hints_list
- ;
-
-opt_key_definition:
- { Select->clear_index_hints(); }
- opt_index_hints_list
- ;
-
-opt_key_usage_list:
- /* empty */ { Select->add_index_hint(thd, NULL, 0); }
- | key_usage_list {}
- ;
-
-key_usage_element:
- ident
- { Select->add_index_hint(thd, $1.str, $1.length); }
- | PRIMARY_SYM
- { Select->add_index_hint(thd, "PRIMARY", 7); }
- ;
-
-key_usage_list:
- key_usage_element
- | key_usage_list ',' key_usage_element
- ;
-
-using_list:
- ident
- {
- if (unlikely(!($$= new (thd->mem_root) List<String>)))
- MYSQL_YYABORT;
- String *s= new (thd->mem_root) String((const char *) $1.str,
- $1.length,
- system_charset_info);
- if (unlikely(unlikely(s == NULL)))
- MYSQL_YYABORT;
- $$->push_back(s, thd->mem_root);
- }
- | using_list ',' ident
- {
- String *s= new (thd->mem_root) String((const char *) $3.str,
- $3.length,
- system_charset_info);
- if (unlikely(unlikely(s == NULL)))
- MYSQL_YYABORT;
- if (unlikely($1->push_back(s, thd->mem_root)))
- MYSQL_YYABORT;
- $$= $1;
- }
- ;
-
-interval:
- interval_time_stamp {}
- | DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; }
- | DAY_MICROSECOND_SYM { $$=INTERVAL_DAY_MICROSECOND; }
- | DAY_MINUTE_SYM { $$=INTERVAL_DAY_MINUTE; }
- | DAY_SECOND_SYM { $$=INTERVAL_DAY_SECOND; }
- | HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; }
- | HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; }
- | HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; }
- | MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; }
- | MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; }
- | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; }
- | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }
- ;
-
-interval_time_stamp:
- DAY_SYM { $$=INTERVAL_DAY; }
- | WEEK_SYM { $$=INTERVAL_WEEK; }
- | HOUR_SYM { $$=INTERVAL_HOUR; }
- | MINUTE_SYM { $$=INTERVAL_MINUTE; }
- | MONTH_SYM { $$=INTERVAL_MONTH; }
- | QUARTER_SYM { $$=INTERVAL_QUARTER; }
- | SECOND_SYM { $$=INTERVAL_SECOND; }
- | MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; }
- | YEAR_SYM { $$=INTERVAL_YEAR; }
- ;
-
-date_time_type:
- DATE_SYM {$$=MYSQL_TIMESTAMP_DATE;}
- | TIME_SYM {$$=MYSQL_TIMESTAMP_TIME;}
- | DATETIME {$$=MYSQL_TIMESTAMP_DATETIME;}
- | TIMESTAMP {$$=MYSQL_TIMESTAMP_DATETIME;}
- ;
-
-table_alias:
- /* empty */
- | AS
- | '='
- ;
-
-opt_table_alias_clause:
- /* empty */ { $$=0; }
- | table_alias_clause { $$= $1; }
- ;
-
-table_alias_clause:
- table_alias ident_table_alias
- {
- $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING));
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_all:
- /* empty */
- | ALL
- ;
-
-opt_where_clause:
- /* empty */ { Select->where= 0; }
- | WHERE
- {
- Select->parsing_place= IN_WHERE;
- }
- expr
- {
- SELECT_LEX *select= Select;
- select->where= normalize_cond(thd, $3);
- select->parsing_place= NO_MATTER;
- if ($3)
- $3->top_level_item();
- }
- ;
-
-opt_having_clause:
- /* empty */
- | HAVING
- {
- Select->parsing_place= IN_HAVING;
- }
- expr
- {
- SELECT_LEX *sel= Select;
- sel->having= normalize_cond(thd, $3);
- sel->parsing_place= NO_MATTER;
- if ($3)
- $3->top_level_item();
- }
- ;
-
-opt_escape:
- ESCAPE_SYM simple_expr
- {
- Lex->escape_used= TRUE;
- $$= $2;
- }
- | /* empty */ %prec PREC_BELOW_ESCAPE
- {
- Lex->escape_used= FALSE;
- $$= ((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ?
- new (thd->mem_root) Item_string_ascii(thd, "", 0) :
- new (thd->mem_root) Item_string_ascii(thd, "\\", 1));
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-/*
- group by statement in select
-*/
-
-opt_group_clause:
- /* empty */
- | GROUP_SYM BY group_list olap_opt
- ;
-
-group_list:
- group_list ',' order_ident order_dir
- {
- if (unlikely(add_group_to_list(thd, $3,(bool) $4)))
- MYSQL_YYABORT;
- }
- | order_ident order_dir
- {
- if (unlikely(add_group_to_list(thd, $1,(bool) $2)))
- MYSQL_YYABORT;
- }
- ;
-
-olap_opt:
- /* empty */ {}
- | WITH_CUBE_SYM
- {
- /*
- 'WITH CUBE' is reserved in the MySQL syntax, but not implemented,
- and cause LALR(2) conflicts.
- This syntax is not standard.
- MySQL syntax: GROUP BY col1, col2, col3 WITH CUBE
- SQL-2003: GROUP BY ... CUBE(col1, col2, col3)
- */
- LEX *lex=Lex;
- if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE))
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE",
- "global union parameters"));
- lex->current_select->olap= CUBE_TYPE;
-
- my_yyabort_error((ER_NOT_SUPPORTED_YET, MYF(0), "CUBE"));
- }
- | WITH_ROLLUP_SYM
- {
- /*
- 'WITH ROLLUP' is needed for backward compatibility,
- and cause LALR(2) conflicts.
- This syntax is not standard.
- MySQL syntax: GROUP BY col1, col2, col3 WITH ROLLUP
- SQL-2003: GROUP BY ... ROLLUP(col1, col2, col3)
- */
- LEX *lex= Lex;
- if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE))
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
- "global union parameters"));
- lex->current_select->olap= ROLLUP_TYPE;
- }
- ;
-
-/*
- optional window clause in select
-*/
-
-opt_window_clause:
- /* empty */
- {}
- | WINDOW_SYM
- window_def_list
- {}
- ;
-
-window_def_list:
- window_def_list ',' window_def
- | window_def
- ;
-
-window_def:
- window_name AS window_spec
- {
- LEX *lex= Lex;
- if (unlikely(Select->add_window_def(thd, $1, lex->win_ref,
- Select->group_list,
- Select->order_list,
- lex->win_frame)))
- MYSQL_YYABORT;
- }
- ;
-
-window_spec:
- '('
- { Select->prepare_add_window_spec(thd); }
- opt_window_ref opt_window_partition_clause
- opt_window_order_clause opt_window_frame_clause
- ')'
- { }
- ;
-
-opt_window_ref:
- /* empty */ {}
- | ident
- {
- thd->lex->win_ref= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
- if (unlikely(thd->lex->win_ref == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_window_partition_clause:
- /* empty */ { }
- | PARTITION_SYM BY group_list
- ;
-
-opt_window_order_clause:
- /* empty */ { }
- | ORDER_SYM BY order_list { Select->order_list= *($3); }
- ;
-
-opt_window_frame_clause:
- /* empty */ {}
- | window_frame_units window_frame_extent opt_window_frame_exclusion
- {
- LEX *lex= Lex;
- lex->win_frame=
- new (thd->mem_root) Window_frame($1,
- lex->frame_top_bound,
- lex->frame_bottom_bound,
- $3);
- if (unlikely(lex->win_frame == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-window_frame_units:
- ROWS_SYM { $$= Window_frame::UNITS_ROWS; }
- | RANGE_SYM { $$= Window_frame::UNITS_RANGE; }
- ;
-
-window_frame_extent:
- window_frame_start
- {
- LEX *lex= Lex;
- lex->frame_top_bound= $1;
- lex->frame_bottom_bound=
- new (thd->mem_root)
- Window_frame_bound(Window_frame_bound::CURRENT, NULL);
- if (unlikely(lex->frame_bottom_bound == NULL))
- MYSQL_YYABORT;
- }
- | BETWEEN_SYM window_frame_bound AND_SYM window_frame_bound
- {
- LEX *lex= Lex;
- lex->frame_top_bound= $2;
- lex->frame_bottom_bound= $4;
- }
- ;
-
-window_frame_start:
- UNBOUNDED_SYM PRECEDING_SYM
- {
- $$= new (thd->mem_root)
- Window_frame_bound(Window_frame_bound::PRECEDING, NULL);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | CURRENT_SYM ROW_SYM
- {
- $$= new (thd->mem_root)
- Window_frame_bound(Window_frame_bound::CURRENT, NULL);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | literal PRECEDING_SYM
- {
- $$= new (thd->mem_root)
- Window_frame_bound(Window_frame_bound::PRECEDING, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-window_frame_bound:
- window_frame_start { $$= $1; }
- | UNBOUNDED_SYM FOLLOWING_SYM
- {
- $$= new (thd->mem_root)
- Window_frame_bound(Window_frame_bound::FOLLOWING, NULL);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | literal FOLLOWING_SYM
- {
- $$= new (thd->mem_root)
- Window_frame_bound(Window_frame_bound::FOLLOWING, $1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_window_frame_exclusion:
- /* empty */ { $$= Window_frame::EXCL_NONE; }
- | EXCLUDE_SYM CURRENT_SYM ROW_SYM
- { $$= Window_frame::EXCL_CURRENT_ROW; }
- | EXCLUDE_SYM GROUP_SYM
- { $$= Window_frame::EXCL_GROUP; }
- | EXCLUDE_SYM TIES_SYM
- { $$= Window_frame::EXCL_TIES; }
- | EXCLUDE_SYM NO_SYM OTHERS_MARIADB_SYM
- { $$= Window_frame::EXCL_NONE; }
- | EXCLUDE_SYM NO_SYM OTHERS_ORACLE_SYM
- { $$= Window_frame::EXCL_NONE; }
- ;
-
-/*
- Order by statement in ALTER TABLE
-*/
-
-alter_order_clause:
- ORDER_SYM BY alter_order_list
- ;
-
-alter_order_list:
- alter_order_list ',' alter_order_item
- | alter_order_item
- ;
-
-alter_order_item:
- simple_ident_nospvar order_dir
- {
- bool ascending= ($2 == 1) ? true : false;
- if (unlikely(add_order_to_list(thd, $1, ascending)))
- MYSQL_YYABORT;
- }
- ;
-
-/*
- Order by statement in select
-*/
-
-opt_order_clause:
- /* empty */
- { $$= NULL; }
- | order_clause
- { $$= $1; }
- ;
-
-order_clause:
- ORDER_SYM BY
- {
- thd->where= "ORDER clause";
- }
- order_list
- {
- $$= $4;
- }
- ;
-
-order_list:
- order_list ',' order_ident order_dir
- {
- $$= $1;
- if (add_to_list(thd, *$$, $3,(bool) $4))
- MYSQL_YYABORT;
- }
- | order_ident order_dir
- {
- $$= new (thd->mem_root) SQL_I_List<ORDER>();
- if (add_to_list(thd, *$$, $1, (bool) $2))
- MYSQL_YYABORT;
- }
- ;
-
-order_dir:
- /* empty */ { $$ = 1; }
- | ASC { $$ =1; }
- | DESC { $$ =0; }
- ;
-
-opt_limit_clause:
- /* empty */
- { $$.empty(); }
- | limit_clause
- { $$= $1; }
- ;
-
-limit_clause:
- LIMIT limit_options
- {
- $$= $2;
- if (!$$.select_limit->basic_const_item() ||
- $$.select_limit->val_int() > 0)
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
- }
- | LIMIT limit_options
- ROWS_SYM EXAMINED_SYM limit_rows_option
- {
- $$= $2;
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
- }
- | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option
- {
- $$.select_limit= 0;
- $$.offset_limit= 0;
- $$.explicit_limit= 0;
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
- }
- ;
-
-opt_global_limit_clause:
- opt_limit_clause
- {
- Select->explicit_limit= $1.explicit_limit;
- Select->select_limit= $1.select_limit;
- Select->offset_limit= $1.offset_limit;
- }
- ;
-
-limit_options:
- limit_option
- {
- $$.select_limit= $1;
- $$.offset_limit= 0;
- $$.explicit_limit= 1;
- }
- | limit_option ',' limit_option
- {
- $$.select_limit= $3;
- $$.offset_limit= $1;
- $$.explicit_limit= 1;
- }
- | limit_option OFFSET_SYM limit_option
- {
- $$.select_limit= $1;
- $$.offset_limit= $3;
- $$.explicit_limit= 1;
- }
- ;
-
-limit_option:
- ident_cli
- {
- if (unlikely(!($$= Lex->create_item_limit(thd, &$1))))
- MYSQL_YYABORT;
- }
- | ident_cli '.' ident_cli
- {
- if (unlikely(!($$= Lex->create_item_limit(thd, &$1, &$3))))
- MYSQL_YYABORT;
- }
- | param_marker
- {
- $1->limit_clause_param= TRUE;
- }
- | ULONGLONG_NUM
- {
- $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | LONG_NUM
- {
- $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | NUM
- {
- $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-limit_rows_option:
- limit_option
- {
- LEX *lex=Lex;
- lex->limit_rows_examined= $1;
- }
- ;
-
-delete_limit_clause:
- /* empty */
- {
- LEX *lex=Lex;
- lex->current_select->select_limit= 0;
- }
- | LIMIT limit_option
- {
- SELECT_LEX *sel= Select;
- sel->select_limit= $2;
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
- sel->explicit_limit= 1;
- }
- | LIMIT ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
- | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
- ;
-
-order_limit_lock:
- order_or_limit
- {
- $$= $1;
- $$->lock.empty();
- }
- | order_or_limit select_lock_type
- {
- $$= $1;
- $$->lock= $2;
- }
- | select_lock_type
- {
- $$= new(thd->mem_root) Lex_order_limit_lock;
- if (!$$)
- YYABORT;
- $$->order_list= NULL;
- $$->limit.empty();
- $$->lock= $1;
- }
- ;
-
-opt_order_limit_lock:
- /* empty */
- {
- Lex->pop_select();
- $$= NULL;
- }
- | order_limit_lock { $$= $1; }
- ;
-
-query_expression_tail:
- order_limit_lock
- ;
-
-opt_query_expression_tail:
- opt_order_limit_lock
- ;
-
-opt_procedure_or_into:
- /* empty */
- {
- $$.empty();
- }
- | procedure_clause opt_select_lock_type
- {
- $$= $2;
- }
- | into opt_select_lock_type
- {
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_WARN_DEPRECATED_SYNTAX,
- ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
- "<select expression> INTO <destination>;",
- "'SELECT <select list> INTO <destination>"
- " FROM...'");
- $$= $2;
- }
- ;
-
-order_or_limit:
- order_clause opt_limit_clause
- {
- $$= new(thd->mem_root) Lex_order_limit_lock;
- if (!$$)
- YYABORT;
- $$->order_list= $1;
- $$->limit= $2;
- }
- | limit_clause
- {
- Lex_order_limit_lock *op= $$= new(thd->mem_root) Lex_order_limit_lock;
- if (!$$)
- YYABORT;
- op->order_list= NULL;
- op->limit= $1;
- $$->order_list= NULL;
- $$->limit= $1;
- }
- ;
-
-
-opt_plus:
- /* empty */
- | '+'
- ;
-
-int_num:
- opt_plus NUM { int error; $$= (int) my_strtoll10($2.str, (char**) 0, &error); }
- | '-' NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); }
- ;
-
-ulong_num:
- opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
- | HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
- | opt_plus LONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
- | opt_plus ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
- | opt_plus DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
- | opt_plus FLOAT_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
- ;
-
-real_ulong_num:
- NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
- | LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | dec_num_error { MYSQL_YYABORT; }
- ;
-
-longlong_num:
- opt_plus NUM { int error; $$= (longlong) my_strtoll10($2.str, (char**) 0, &error); }
- | LONG_NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); }
- | '-' NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
- | '-' LONG_NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
- ;
-
-ulonglong_num:
- opt_plus NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
- | opt_plus ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
- | opt_plus LONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
- | opt_plus DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
- | opt_plus FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
- ;
-
-real_ulonglong_num:
- NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | HEX_NUM { $$= strtoull($1.str, (char**) 0, 16); }
- | LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | dec_num_error { MYSQL_YYABORT; }
- ;
-
-dec_num_error:
- dec_num
- { thd->parse_error(ER_ONLY_INTEGERS_ALLOWED); }
- ;
-
-dec_num:
- DECIMAL_NUM
- | FLOAT_NUM
- ;
-
-choice:
- ulong_num { $$= $1 != 0 ? HA_CHOICE_YES : HA_CHOICE_NO; }
- | DEFAULT { $$= HA_CHOICE_UNDEF; }
- ;
-
-bool:
- ulong_num { $$= $1 != 0; }
- | TRUE_SYM { $$= 1; }
- | FALSE_SYM { $$= 0; }
- ;
-
-procedure_clause:
- PROCEDURE_SYM ident /* Procedure name */
- {
- LEX *lex=Lex;
-
- lex->proc_list.elements=0;
- lex->proc_list.first=0;
- lex->proc_list.next= &lex->proc_list.first;
- Item_field *item= new (thd->mem_root)
- Item_field(thd, &lex->current_select->context,
- $2);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- if (unlikely(add_proc_to_list(thd, item)))
- MYSQL_YYABORT;
- Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
-
- /*
- PROCEDURE CLAUSE cannot handle subquery as one of its parameter,
- so disallow any subqueries further.
- Alow subqueries back once the parameters are reduced.
- */
- Lex->clause_that_disallows_subselect= "PROCEDURE";
- Select->options|= OPTION_PROCEDURE_CLAUSE;
- }
- '(' procedure_list ')'
- {
- /* Subqueries are allowed from now.*/
- Lex->clause_that_disallows_subselect= NULL;
- }
- ;
-
-procedure_list:
- /* empty */ {}
- | procedure_list2 {}
- ;
-
-procedure_list2:
- procedure_list2 ',' procedure_item
- | procedure_item
- ;
-
-procedure_item:
- remember_name expr remember_end
- {
- if (unlikely(add_proc_to_list(thd, $2)))
- MYSQL_YYABORT;
- if (!$2->name.str || $2->name.str == item_empty_name)
- $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
- }
- ;
-
-select_var_list_init:
- {
- LEX *lex=Lex;
- if (!lex->describe &&
- unlikely((!(lex->result= new (thd->mem_root)
- select_dumpvar(thd)))))
- MYSQL_YYABORT;
- }
- select_var_list
- {}
- ;
-
-select_var_list:
- select_var_list ',' select_var_ident
- | select_var_ident {}
- ;
-
-select_var_ident: select_outvar
- {
- if (Lex->result)
- {
- if (unlikely($1 == NULL))
- MYSQL_YYABORT;
- ((select_dumpvar *)Lex->result)->var_list.push_back($1, thd->mem_root);
- }
- else
- {
- /*
- The parser won't create select_result instance only
- if it's an EXPLAIN.
- */
- DBUG_ASSERT(Lex->describe);
- }
- }
- ;
-
-select_outvar:
- '@' ident_or_text
- {
- $$ = Lex->result ? new (thd->mem_root) my_var_user(&$2) : NULL;
- }
- | ident_or_text
- {
- if (unlikely(!($$= Lex->create_outvar(thd, &$1)) && Lex->result))
- MYSQL_YYABORT;
- }
- | ident '.' ident
- {
- if (unlikely(!($$= Lex->create_outvar(thd, &$1, &$3)) && Lex->result))
- MYSQL_YYABORT;
- }
- ;
-
-into:
- INTO into_destination
- {}
- ;
-
-into_destination:
- OUTFILE TEXT_STRING_filesystem
- {
- LEX *lex= Lex;
- lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- if (unlikely(!(lex->exchange=
- new (thd->mem_root) sql_exchange($2.str, 0))) ||
- unlikely(!(lex->result=
- new (thd->mem_root)
- select_export(thd, lex->exchange))))
- MYSQL_YYABORT;
- }
- opt_load_data_charset
- { Lex->exchange->cs= $4; }
- opt_field_term opt_line_term
- | DUMPFILE TEXT_STRING_filesystem
- {
- LEX *lex=Lex;
- if (!lex->describe)
- {
- lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- if (unlikely(!(lex->exchange=
- new (thd->mem_root) sql_exchange($2.str,1))))
- MYSQL_YYABORT;
- if (unlikely(!(lex->result=
- new (thd->mem_root)
- select_dump(thd, lex->exchange))))
- MYSQL_YYABORT;
- }
- }
- | select_var_list_init
- {
- Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- }
- ;
-
-/*
- DO statement
-*/
-
-do:
- DO_SYM
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_DO;
- mysql_init_select(lex);
- }
- expr_list
- {
- Lex->insert_list= $3;
- }
- ;
-
-/*
- Drop : delete tables or index or user
-*/
-
-drop:
- DROP opt_temporary table_or_tables opt_if_exists
- {
- LEX *lex=Lex;
- lex->set_command(SQLCOM_DROP_TABLE, $2, $4);
- YYPS->m_lock_type= TL_UNLOCK;
- YYPS->m_mdl_type= MDL_EXCLUSIVE;
- }
- table_list opt_lock_wait_timeout opt_restrict
- {}
- | DROP INDEX_SYM opt_if_exists_table_element ident ON table_ident opt_lock_wait_timeout
- {
- LEX *lex=Lex;
- Alter_drop *ad= (new (thd->mem_root)
- Alter_drop(Alter_drop::KEY, $4.str, $3));
- if (unlikely(ad == NULL))
- MYSQL_YYABORT;
- lex->sql_command= SQLCOM_DROP_INDEX;
- lex->alter_info.reset();
- lex->alter_info.flags= ALTER_DROP_INDEX;
- lex->alter_info.drop_list.push_back(ad, thd->mem_root);
- if (unlikely(!lex->current_select->
- add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_UPGRADABLE)))
- MYSQL_YYABORT;
- }
- | DROP DATABASE opt_if_exists ident
- {
- LEX *lex=Lex;
- lex->set_command(SQLCOM_DROP_DB, $3);
- lex->name= $4;
- }
- | DROP USER_SYM opt_if_exists clear_privileges user_list
- {
- Lex->set_command(SQLCOM_DROP_USER, $3);
- }
- | DROP ROLE_SYM opt_if_exists clear_privileges role_list
- {
- Lex->set_command(SQLCOM_DROP_ROLE, $3);
- }
- | DROP VIEW_SYM opt_if_exists
- {
- LEX *lex= Lex;
- lex->set_command(SQLCOM_DROP_VIEW, $3);
- YYPS->m_lock_type= TL_UNLOCK;
- YYPS->m_mdl_type= MDL_EXCLUSIVE;
- }
- table_list opt_restrict
- {}
- | DROP EVENT_SYM opt_if_exists sp_name
- {
- Lex->spname= $4;
- Lex->set_command(SQLCOM_DROP_EVENT, $3);
- }
- | DROP TRIGGER_SYM opt_if_exists sp_name
- {
- LEX *lex= Lex;
- lex->set_command(SQLCOM_DROP_TRIGGER, $3);
- lex->spname= $4;
- }
- | DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->ts_cmd_type= DROP_TABLESPACE;
- }
- | DROP LOGFILE_SYM GROUP_SYM logfile_group_name opt_ts_engine opt_ts_wait
- {
- LEX *lex= Lex;
- lex->alter_tablespace_info->ts_cmd_type= DROP_LOGFILE_GROUP;
- }
- | DROP SERVER_SYM opt_if_exists ident_or_text
- {
- Lex->set_command(SQLCOM_DROP_SERVER, $3);
- Lex->server_options.reset($4);
- }
- | DROP opt_temporary SEQUENCE_SYM opt_if_exists
-
- {
- LEX *lex= Lex;
- lex->set_command(SQLCOM_DROP_SEQUENCE, $2, $4);
- lex->table_type= TABLE_TYPE_SEQUENCE;
- YYPS->m_lock_type= TL_UNLOCK;
- YYPS->m_mdl_type= MDL_EXCLUSIVE;
- }
- table_list
- {}
- | drop_routine
- ;
-
-table_list:
- table_name
- | table_list ',' table_name
- ;
-
-table_name:
- table_ident
- {
- if (!thd->lex->current_select_or_default()->
- add_table_to_list(thd, $1, NULL,
- TL_OPTION_UPDATING,
- YYPS->m_lock_type,
- YYPS->m_mdl_type))
- MYSQL_YYABORT;
- }
- ;
-
-table_name_with_opt_use_partition:
- table_ident opt_use_partition
- {
- if (unlikely(!Select->add_table_to_list(thd, $1, NULL,
- TL_OPTION_UPDATING,
- YYPS->m_lock_type,
- YYPS->m_mdl_type,
- NULL,
- $2)))
- MYSQL_YYABORT;
- }
- ;
-
-table_alias_ref_list:
- table_alias_ref
- | table_alias_ref_list ',' table_alias_ref
- ;
-
-table_alias_ref:
- table_ident_opt_wild
- {
- if (unlikely(!Select->
- add_table_to_list(thd, $1, NULL,
- (TL_OPTION_UPDATING |
- TL_OPTION_ALIAS),
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
- MYSQL_YYABORT;
- }
- ;
-
-opt_if_exists_table_element:
- /* empty */
- {
- Lex->check_exists= FALSE;
- $$= 0;
- }
- | IF_SYM EXISTS
- {
- Lex->check_exists= TRUE;
- $$= 1;
- }
- ;
-
-opt_if_exists:
- /* empty */
- {
- $$.set(DDL_options_st::OPT_NONE);
- }
- | IF_SYM EXISTS
- {
- $$.set(DDL_options_st::OPT_IF_EXISTS);
- }
- ;
-
-opt_temporary:
- /* empty */ { $$= 0; }
- | TEMPORARY { $$= HA_LEX_CREATE_TMP_TABLE; }
- ;
-/*
-** Insert : add new data to table
-*/
-
-insert:
- INSERT
- {
- Lex->sql_command= SQLCOM_INSERT;
- Lex->duplicates= DUP_ERROR;
- }
- insert_start insert_lock_option opt_ignore opt_into insert_table
- {
- Select->set_lock_for_tables($4, true);
- }
- insert_field_spec opt_insert_update opt_returning
- stmt_end
- {
- Lex->mark_first_table_as_inserting();
- }
- ;
-
-replace:
- REPLACE
- {
- Lex->sql_command = SQLCOM_REPLACE;
- Lex->duplicates= DUP_REPLACE;
- }
- insert_start replace_lock_option opt_into insert_table
- {
- Select->set_lock_for_tables($4, true);
- }
- insert_field_spec opt_returning
- stmt_end
- {
- Lex->mark_first_table_as_inserting();
- }
- ;
-
-insert_start: {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- mysql_init_select(Lex);
- Lex->current_select->parsing_place= BEFORE_OPT_LIST;
- }
- ;
-
-stmt_end: {
- Lex->pop_select(); //main select
- if (Lex->check_main_unit_semantics())
- MYSQL_YYABORT;
- }
- ;
-
-insert_lock_option:
- /* empty */
- {
- /*
- If it is SP we do not allow insert optimisation when result of
- insert visible only after the table unlocking but everyone can
- read table.
- */
- $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT);
- }
- | insert_replace_option
- | HIGH_PRIORITY { $$= TL_WRITE; }
- ;
-
-replace_lock_option:
- /* empty */ { $$= TL_WRITE_DEFAULT; }
- | insert_replace_option
- ;
-
-insert_replace_option:
- LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
- | DELAYED_SYM
- {
- Lex->keyword_delayed_begin_offset= (uint)($1.pos() - thd->query());
- Lex->keyword_delayed_end_offset= (uint)($1.end() - thd->query());
- $$= TL_WRITE_DELAYED;
- }
- ;
-
-opt_into: /* nothing */ | INTO ;
-
-insert_table:
- {
- Select->save_parsing_place= Select->parsing_place;
- }
- table_name_with_opt_use_partition
- {
- LEX *lex=Lex;
- //lex->field_list.empty();
- lex->many_values.empty();
- lex->insert_list=0;
- }
- ;
-
-insert_field_spec:
- insert_values {}
- | insert_field_list insert_values {}
- | SET
- {
- LEX *lex=Lex;
- if (unlikely(!(lex->insert_list= new (thd->mem_root) List_item)) ||
- unlikely(lex->many_values.push_back(lex->insert_list,
- thd->mem_root)))
- MYSQL_YYABORT;
- lex->current_select->parsing_place= NO_MATTER;
- }
- ident_eq_list
- ;
-
-insert_field_list:
- LEFT_PAREN_ALT opt_fields ')'
- {
- Lex->current_select->parsing_place= AFTER_LIST;
- }
- ;
-
-opt_fields:
- /* empty */
- | fields
- ;
-
-fields:
- fields ',' insert_ident
- { Lex->field_list.push_back($3, thd->mem_root); }
- | insert_ident { Lex->field_list.push_back($1, thd->mem_root); }
- ;
-
-
-
-insert_values:
- create_select_query_expression {}
- ;
-
-values_list:
- values_list ',' no_braces
- | no_braces_with_names
- ;
-
-ident_eq_list:
- ident_eq_list ',' ident_eq_value
- | ident_eq_value
- ;
-
-ident_eq_value:
- simple_ident_nospvar equal expr_or_default
- {
- LEX *lex=Lex;
- if (unlikely(lex->field_list.push_back($1, thd->mem_root)) ||
- unlikely(lex->insert_list->push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-equal:
- '=' {}
- | SET_VAR {}
- ;
-
-opt_equal:
- /* empty */ {}
- | equal {}
- ;
-
-opt_with:
- opt_equal {}
- | WITH {}
- ;
-
-opt_by:
- opt_equal {}
- | BY {}
- ;
-
-no_braces:
- '('
- {
- if (unlikely(!(Lex->insert_list= new (thd->mem_root) List_item)))
- MYSQL_YYABORT;
- }
- opt_values ')'
- {
- LEX *lex=Lex;
- if (unlikely(lex->many_values.push_back(lex->insert_list,
- thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-no_braces_with_names:
- '('
- {
- if (unlikely(!(Lex->insert_list= new (thd->mem_root) List_item)))
- MYSQL_YYABORT;
- }
- opt_values_with_names ')'
- {
- LEX *lex=Lex;
- if (unlikely(lex->many_values.push_back(lex->insert_list,
- thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-opt_values:
- /* empty */ {}
- | values
- ;
-
-opt_values_with_names:
- /* empty */ {}
- | values_with_names
- ;
-
-values:
- values ',' expr_or_default
- {
- if (unlikely(Lex->insert_list->push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | expr_or_default
- {
- if (unlikely(Lex->insert_list->push_back($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-values_with_names:
- values_with_names ',' remember_name expr_or_default remember_end
- {
- if (unlikely(Lex->insert_list->push_back($4, thd->mem_root)))
- MYSQL_YYABORT;
- // give some name in case of using in table value constuctor (TVC)
- if (!$4->name.str || $4->name.str == item_empty_name)
- $4->set_name(thd, $3, (uint) ($5 - $3), thd->charset());
- }
- | remember_name expr_or_default remember_end
- {
- if (unlikely(Lex->insert_list->push_back($2, thd->mem_root)))
- MYSQL_YYABORT;
- // give some name in case of using in table value constuctor (TVC)
- if (!$2->name.str || $2->name.str == item_empty_name)
- $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
- }
- ;
-
-expr_or_default:
- expr { $$= $1;}
- | DEFAULT
- {
- $$= new (thd->mem_root) Item_default_value(thd, Lex->current_context());
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | IGNORE_SYM
- {
- $$= new (thd->mem_root) Item_ignore_value(thd, Lex->current_context());
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_insert_update:
- /* empty */
- | ON DUPLICATE_SYM { Lex->duplicates= DUP_UPDATE; }
- KEY_SYM UPDATE_SYM
- {
- Select->parsing_place= IN_UPDATE_ON_DUP_KEY;
- }
- insert_update_list
- {
- Select->parsing_place= NO_MATTER;
- }
- ;
-
-update_table_list:
- table_ident opt_use_partition for_portion_of_time_clause
- opt_table_alias_clause opt_key_definition
- {
- SELECT_LEX *sel= Select;
- sel->table_join_options= 0;
- if (!($$= Select->add_table_to_list(thd, $1, $4,
- Select->get_table_join_options(),
- YYPS->m_lock_type,
- YYPS->m_mdl_type,
- Select->pop_index_hints(),
- $2)))
- MYSQL_YYABORT;
- $$->period_conditions= Lex->period_conditions;
- }
- | join_table_list { $$= $1; }
- ;
-
-/* Update rows in a table */
-
-update:
- UPDATE_SYM
- {
- LEX *lex= Lex;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- mysql_init_select(lex);
- lex->sql_command= SQLCOM_UPDATE;
- lex->duplicates= DUP_ERROR;
- }
- opt_low_priority opt_ignore update_table_list
- SET update_list
- {
- SELECT_LEX *slex= Lex->first_select_lex();
- if (slex->table_list.elements > 1)
- Lex->sql_command= SQLCOM_UPDATE_MULTI;
- else if (slex->get_table_list()->derived)
- {
- /* it is single table update and it is update of derived table */
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
- slex->get_table_list()->alias.str, "UPDATE");
- MYSQL_YYABORT;
- }
- /*
- In case of multi-update setting write lock for all tables may
- be too pessimistic. We will decrease lock level if possible in
- mysql_multi_update().
- */
- slex->set_lock_for_tables($3, slex->table_list.elements == 1);
- }
- opt_where_clause opt_order_clause delete_limit_clause
- {
- if ($10)
- Select->order_list= *($10);
- } stmt_end {}
- ;
-
-update_list:
- update_list ',' update_elem
- | update_elem
- ;
-
-update_elem:
- simple_ident_nospvar equal expr_or_default
- {
- if (unlikely(add_item_to_list(thd, $1)) ||
- unlikely(add_value_to_list(thd, $3)))
- MYSQL_YYABORT;
- }
- ;
-
-insert_update_list:
- insert_update_list ',' insert_update_elem
- | insert_update_elem
- ;
-
-insert_update_elem:
- simple_ident_nospvar equal expr_or_default
- {
- LEX *lex= Lex;
- if (unlikely(lex->update_list.push_back($1, thd->mem_root)) ||
- unlikely(lex->value_list.push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-opt_low_priority:
- /* empty */ { $$= TL_WRITE_DEFAULT; }
- | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
- ;
-
-/* Delete rows from a table */
-
-delete:
- DELETE_SYM
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_DELETE;
- YYPS->m_lock_type= TL_WRITE_DEFAULT;
- YYPS->m_mdl_type= MDL_SHARED_WRITE;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- mysql_init_select(lex);
- lex->ignore= 0;
- lex->first_select_lex()->order_list.empty();
- }
- delete_part2
- { }
- ;
-
-opt_delete_system_time:
- /* empty */
- {
- Lex->vers_conditions.init(SYSTEM_TIME_ALL);
- }
- | BEFORE_SYM SYSTEM_TIME_SYM history_point
- {
- Lex->vers_conditions.init(SYSTEM_TIME_BEFORE, $3);
- }
- ;
-
-delete_part2:
- opt_delete_options single_multi {}
- | HISTORY_SYM delete_single_table opt_delete_system_time
- {
- Lex->last_table()->vers_conditions= Lex->vers_conditions;
- Lex->pop_select(); //main select
- }
- ;
-
-delete_single_table:
- FROM table_ident opt_use_partition
- {
- if (unlikely(!Select->
- add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING,
- YYPS->m_lock_type,
- YYPS->m_mdl_type,
- NULL,
- $3)))
- MYSQL_YYABORT;
- YYPS->m_lock_type= TL_READ_DEFAULT;
- YYPS->m_mdl_type= MDL_SHARED_READ;
- }
- ;
-
-delete_single_table_for_period:
- delete_single_table opt_for_portion_of_time_clause
- {
- if ($2)
- Lex->last_table()->period_conditions= Lex->period_conditions;
- }
- ;
-
-single_multi:
- delete_single_table_for_period
- opt_where_clause
- opt_order_clause
- delete_limit_clause
- opt_returning
- {
- if ($3)
- Select->order_list= *($3);
- Lex->pop_select(); //main select
- }
- | table_wild_list
- {
- mysql_init_multi_delete(Lex);
- YYPS->m_lock_type= TL_READ_DEFAULT;
- YYPS->m_mdl_type= MDL_SHARED_READ;
- }
- FROM join_table_list opt_where_clause
- {
- if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex)))
- MYSQL_YYABORT;
- } stmt_end {}
- | FROM table_alias_ref_list
- {
- mysql_init_multi_delete(Lex);
- YYPS->m_lock_type= TL_READ_DEFAULT;
- YYPS->m_mdl_type= MDL_SHARED_READ;
- }
- USING join_table_list opt_where_clause
- {
- if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex)))
- MYSQL_YYABORT;
- } stmt_end {}
- ;
-
-opt_returning:
- /* empty */
- {
- DBUG_ASSERT(!Lex->has_returning());
- }
- | RETURNING_SYM
- {
- DBUG_ASSERT(!Lex->has_returning());
- if (($<num>$= (Select != Lex->returning())))
- {
- SELECT_LEX *sl= Lex->returning();
- sl->set_master_unit(0);
- Select->add_slave(Lex->create_unit(sl));
- sl->include_global((st_select_lex_node**)&Lex->all_selects_list);
- Lex->push_select(sl);
- }
- }
- select_item_list
- {
- if ($<num>2)
- Lex->pop_select();
- }
- ;
-
-table_wild_list:
- table_wild_one
- | table_wild_list ',' table_wild_one
- ;
-
-table_wild_one:
- ident opt_wild
- {
- Table_ident *ti= new (thd->mem_root) Table_ident(&$1);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!Select->
- add_table_to_list(thd,
- ti,
- NULL,
- (TL_OPTION_UPDATING |
- TL_OPTION_ALIAS),
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
- MYSQL_YYABORT;
- }
- | ident '.' ident opt_wild
- {
- Table_ident *ti= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!Select->
- add_table_to_list(thd,
- ti,
- NULL,
- (TL_OPTION_UPDATING |
- TL_OPTION_ALIAS),
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
- MYSQL_YYABORT;
- }
- ;
-
-opt_wild:
- /* empty */ {}
- | '.' '*' {}
- ;
-
-opt_delete_options:
- /* empty */ {}
- | opt_delete_option opt_delete_options {}
- ;
-
-opt_delete_option:
- QUICK { Select->options|= OPTION_QUICK; }
- | LOW_PRIORITY { YYPS->m_lock_type= TL_WRITE_LOW_PRIORITY; }
- | IGNORE_SYM { Lex->ignore= 1; }
- ;
-
-truncate:
- TRUNCATE_SYM
- {
- LEX* lex= Lex;
- lex->sql_command= SQLCOM_TRUNCATE;
- lex->alter_info.reset();
- lex->first_select_lex()->options= 0;
- lex->sql_cache= LEX::SQL_CACHE_UNSPECIFIED;
- lex->first_select_lex()->order_list.empty();
- YYPS->m_lock_type= TL_WRITE;
- YYPS->m_mdl_type= MDL_EXCLUSIVE;
- }
- opt_table_sym table_name opt_lock_wait_timeout
- {
- LEX* lex= thd->lex;
- DBUG_ASSERT(!lex->m_sql_cmd);
- lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table();
- if (unlikely(lex->m_sql_cmd == NULL))
- MYSQL_YYABORT;
- }
- opt_truncate_table_storage_clause { }
- ;
-
-opt_table_sym:
- /* empty */
- | TABLE_SYM
- ;
-
-opt_profile_defs:
- /* empty */
- | profile_defs;
-
-profile_defs:
- profile_def
- | profile_defs ',' profile_def;
-
-profile_def:
- CPU_SYM
- {
- Lex->profile_options|= PROFILE_CPU;
- }
- | MEMORY_SYM
- {
- Lex->profile_options|= PROFILE_MEMORY;
- }
- | BLOCK_SYM IO_SYM
- {
- Lex->profile_options|= PROFILE_BLOCK_IO;
- }
- | CONTEXT_SYM SWITCHES_SYM
- {
- Lex->profile_options|= PROFILE_CONTEXT;
- }
- | PAGE_SYM FAULTS_SYM
- {
- Lex->profile_options|= PROFILE_PAGE_FAULTS;
- }
- | IPC_SYM
- {
- Lex->profile_options|= PROFILE_IPC;
- }
- | SWAPS_SYM
- {
- Lex->profile_options|= PROFILE_SWAPS;
- }
- | SOURCE_SYM
- {
- Lex->profile_options|= PROFILE_SOURCE;
- }
- | ALL
- {
- Lex->profile_options|= PROFILE_ALL;
- }
- ;
-
-opt_profile_args:
- /* empty */
- {
- Lex->profile_query_id= 0;
- }
- | FOR_SYM QUERY_SYM NUM
- {
- Lex->profile_query_id= atoi($3.str);
- }
- ;
-
-/* Show things */
-
-show:
- SHOW
- {
- LEX *lex=Lex;
- lex->wild=0;
- lex->ident= null_clex_str;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- mysql_init_select(lex);
- lex->current_select->parsing_place= SELECT_LIST;
- lex->create_info.init();
- }
- show_param
- {
- Select->parsing_place= NO_MATTER;
- Lex->pop_select(); //main select
- }
- ;
-
-show_param:
- DATABASES wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_DATABASES;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_SCHEMATA)))
- MYSQL_YYABORT;
- }
- | opt_full TABLES opt_db wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->first_select_lex()->db= $3;
- if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
- MYSQL_YYABORT;
- }
- | opt_full TRIGGERS_SYM opt_db wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_TRIGGERS;
- lex->first_select_lex()->db= $3;
- if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
- MYSQL_YYABORT;
- }
- | EVENTS_SYM opt_db wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_EVENTS;
- lex->first_select_lex()->db= $2;
- if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
- MYSQL_YYABORT;
- }
- | TABLE_SYM STATUS_SYM opt_db wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
- lex->first_select_lex()->db= $3;
- if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
- MYSQL_YYABORT;
- }
- | OPEN_SYM TABLES opt_db wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
- lex->first_select_lex()->db= $3;
- if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
- MYSQL_YYABORT;
- }
- | PLUGINS_SYM
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_PLUGINS;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_PLUGINS)))
- MYSQL_YYABORT;
- }
- | PLUGINS_SYM SONAME_SYM TEXT_STRING_sys
- {
- Lex->ident= $3;
- Lex->sql_command= SQLCOM_SHOW_PLUGINS;
- if (unlikely(prepare_schema_table(thd, Lex, 0, SCH_ALL_PLUGINS)))
- MYSQL_YYABORT;
- }
- | PLUGINS_SYM SONAME_SYM wild_and_where
- {
- Lex->sql_command= SQLCOM_SHOW_PLUGINS;
- if (unlikely(prepare_schema_table(thd, Lex, 0, SCH_ALL_PLUGINS)))
- MYSQL_YYABORT;
- }
- | ENGINE_SYM known_storage_engines show_engine_param
- { Lex->create_info.db_type= $2; }
- | ENGINE_SYM ALL show_engine_param
- { Lex->create_info.db_type= NULL; }
- | opt_full COLUMNS from_or_in table_ident opt_db wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_FIELDS;
- if ($5.str)
- $4->change_db(&$5);
- if (unlikely(prepare_schema_table(thd, lex, $4, SCH_COLUMNS)))
- MYSQL_YYABORT;
- }
- | master_or_binary LOGS_SYM
- {
- Lex->sql_command = SQLCOM_SHOW_BINLOGS;
- }
- | SLAVE HOSTS_SYM
- {
- Lex->sql_command = SQLCOM_SHOW_SLAVE_HOSTS;
- }
- | BINLOG_SYM EVENTS_SYM binlog_in binlog_from
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
- }
- opt_global_limit_clause
- | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS;
- }
- opt_global_limit_clause
- | keys_or_index from_or_in table_ident opt_db opt_where_clause
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_KEYS;
- if ($4.str)
- $3->change_db(&$4);
- if (unlikely(prepare_schema_table(thd, lex, $3, SCH_STATISTICS)))
- MYSQL_YYABORT;
- }
- | opt_storage ENGINES_SYM
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_ENGINES)))
- MYSQL_YYABORT;
- }
- | AUTHORS_SYM
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_SHOW_AUTHORS;
- }
- | CONTRIBUTORS_SYM
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_SHOW_CONTRIBUTORS;
- }
- | PRIVILEGES
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_SHOW_PRIVILEGES;
- }
- | COUNT_SYM '(' '*' ')' WARNINGS
- {
- LEX_CSTRING var= {STRING_WITH_LEN("warning_count")};
- (void) create_select_for_variable(thd, &var);
- }
- | COUNT_SYM '(' '*' ')' ERRORS
- {
- LEX_CSTRING var= {STRING_WITH_LEN("error_count")};
- (void) create_select_for_variable(thd, &var);
- }
- | WARNINGS opt_global_limit_clause
- { Lex->sql_command = SQLCOM_SHOW_WARNS;}
- | ERRORS opt_global_limit_clause
- { Lex->sql_command = SQLCOM_SHOW_ERRORS;}
- | PROFILES_SYM
- { Lex->sql_command = SQLCOM_SHOW_PROFILES; }
- | PROFILE_SYM opt_profile_defs opt_profile_args opt_global_limit_clause
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_PROFILE;
- if (unlikely(prepare_schema_table(thd, lex, NULL, SCH_PROFILES)))
- MYSQL_YYABORT;
- }
- | opt_var_type STATUS_SYM wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_STATUS;
- lex->option_type= $1;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_SESSION_STATUS)))
- MYSQL_YYABORT;
- }
- | opt_full PROCESSLIST_SYM
- { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;}
- | opt_var_type VARIABLES wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_VARIABLES;
- lex->option_type= $1;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_SESSION_VARIABLES)))
- MYSQL_YYABORT;
- }
- | charset wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_CHARSETS;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_CHARSETS)))
- MYSQL_YYABORT;
- }
- | COLLATION_SYM wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_COLLATIONS;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_COLLATIONS)))
- MYSQL_YYABORT;
- }
- | GRANTS
- {
- Lex->sql_command= SQLCOM_SHOW_GRANTS;
- if (unlikely(!(Lex->grant_user=
- (LEX_USER*)thd->alloc(sizeof(LEX_USER)))))
- MYSQL_YYABORT;
- Lex->grant_user->user= current_user_and_current_role;
- }
- | GRANTS FOR_SYM user_or_role clear_privileges
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_SHOW_GRANTS;
- lex->grant_user=$3;
- }
- | CREATE DATABASE opt_if_not_exists ident
- {
- Lex->set_command(SQLCOM_SHOW_CREATE_DB, $3);
- Lex->name= $4;
- }
- | CREATE TABLE_SYM table_ident
- {
- LEX *lex= Lex;
- lex->sql_command = SQLCOM_SHOW_CREATE;
- if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL,0))
- MYSQL_YYABORT;
- lex->create_info.storage_media= HA_SM_DEFAULT;
- }
- | CREATE VIEW_SYM table_ident
- {
- LEX *lex= Lex;
- lex->sql_command = SQLCOM_SHOW_CREATE;
- if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0))
- MYSQL_YYABORT;
- lex->table_type= TABLE_TYPE_VIEW;
- }
- | CREATE SEQUENCE_SYM table_ident
- {
- LEX *lex= Lex;
- lex->sql_command = SQLCOM_SHOW_CREATE;
- if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0))
- MYSQL_YYABORT;
- lex->table_type= TABLE_TYPE_SEQUENCE;
- }
- | MASTER_SYM STATUS_SYM
- {
- Lex->sql_command = SQLCOM_SHOW_MASTER_STAT;
- }
- | ALL SLAVES STATUS_SYM
- {
- if (!(Lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_show_slave_status(true)))
- MYSQL_YYABORT;
- Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
- }
- | SLAVE STATUS_SYM
- {
- LEX *lex= thd->lex;
- lex->mi.connection_name= null_clex_str;
- if (!(lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_show_slave_status()))
- MYSQL_YYABORT;
- lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
- }
- | SLAVE connection_name STATUS_SYM
- {
- if (!(Lex->m_sql_cmd= new (thd->mem_root)
- Sql_cmd_show_slave_status()))
- MYSQL_YYABORT;
- Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
- }
- | CREATE PROCEDURE_SYM sp_name
- {
- LEX *lex= Lex;
-
- lex->sql_command = SQLCOM_SHOW_CREATE_PROC;
- lex->spname= $3;
- }
- | CREATE FUNCTION_SYM sp_name
- {
- LEX *lex= Lex;
-
- lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
- lex->spname= $3;
- }
- | CREATE PACKAGE_MARIADB_SYM sp_name
- {
- LEX *lex= Lex;
- lex->sql_command = SQLCOM_SHOW_CREATE_PACKAGE;
- lex->spname= $3;
- }
- | CREATE PACKAGE_ORACLE_SYM sp_name
- {
- LEX *lex= Lex;
- lex->sql_command = SQLCOM_SHOW_CREATE_PACKAGE;
- lex->spname= $3;
- }
- | CREATE PACKAGE_MARIADB_SYM BODY_MARIADB_SYM sp_name
- {
- LEX *lex= Lex;
- lex->sql_command = SQLCOM_SHOW_CREATE_PACKAGE_BODY;
- lex->spname= $4;
- }
- | CREATE PACKAGE_ORACLE_SYM BODY_ORACLE_SYM sp_name
- {
- LEX *lex= Lex;
- lex->sql_command = SQLCOM_SHOW_CREATE_PACKAGE_BODY;
- lex->spname= $4;
- }
- | CREATE TRIGGER_SYM sp_name
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_CREATE_TRIGGER;
- lex->spname= $3;
- }
- | CREATE USER_SYM
- {
- Lex->sql_command= SQLCOM_SHOW_CREATE_USER;
- if (unlikely(!(Lex->grant_user=
- (LEX_USER*)thd->alloc(sizeof(LEX_USER)))))
- MYSQL_YYABORT;
- Lex->grant_user->user= current_user;
- }
- | CREATE USER_SYM user
- {
- Lex->sql_command= SQLCOM_SHOW_CREATE_USER;
- Lex->grant_user= $3;
- }
- | PROCEDURE_SYM STATUS_SYM wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_STATUS_PROC;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_PROCEDURES)))
- MYSQL_YYABORT;
- }
- | FUNCTION_SYM STATUS_SYM wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_STATUS_FUNC;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_PROCEDURES)))
- MYSQL_YYABORT;
- }
- | PACKAGE_MARIADB_SYM STATUS_SYM wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_STATUS_PACKAGE;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_PROCEDURES)))
- MYSQL_YYABORT;
- }
- | PACKAGE_ORACLE_SYM STATUS_SYM wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_STATUS_PACKAGE;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_PROCEDURES)))
- MYSQL_YYABORT;
- }
- | PACKAGE_MARIADB_SYM BODY_MARIADB_SYM STATUS_SYM wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_STATUS_PACKAGE_BODY;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_PROCEDURES)))
- MYSQL_YYABORT;
- }
- | PACKAGE_ORACLE_SYM BODY_ORACLE_SYM STATUS_SYM wild_and_where
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_STATUS_PACKAGE_BODY;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_PROCEDURES)))
- MYSQL_YYABORT;
- }
- | PROCEDURE_SYM CODE_SYM sp_name
- {
- Lex->sql_command= SQLCOM_SHOW_PROC_CODE;
- Lex->spname= $3;
- }
- | FUNCTION_SYM CODE_SYM sp_name
- {
- Lex->sql_command= SQLCOM_SHOW_FUNC_CODE;
- Lex->spname= $3;
- }
- | PACKAGE_MARIADB_SYM BODY_MARIADB_SYM CODE_SYM sp_name
- {
- Lex->sql_command= SQLCOM_SHOW_PACKAGE_BODY_CODE;
- Lex->spname= $4;
- }
- | PACKAGE_ORACLE_SYM BODY_ORACLE_SYM CODE_SYM sp_name
- {
- Lex->sql_command= SQLCOM_SHOW_PACKAGE_BODY_CODE;
- Lex->spname= $4;
- }
- | CREATE EVENT_SYM sp_name
- {
- Lex->spname= $3;
- Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
- }
- | describe_command FOR_SYM expr
- {
- Lex->sql_command= SQLCOM_SHOW_EXPLAIN;
- if (unlikely(prepare_schema_table(thd, Lex, 0, SCH_EXPLAIN)))
- MYSQL_YYABORT;
- add_value_to_list(thd, $3);
- }
- | IDENT_sys remember_tok_start wild_and_where
- {
- LEX *lex= Lex;
- bool in_plugin;
- lex->sql_command= SQLCOM_SHOW_GENERIC;
- ST_SCHEMA_TABLE *table= find_schema_table(thd, &$1, &in_plugin);
- if (unlikely(!table || !table->old_format || !in_plugin))
- {
- thd->parse_error(ER_SYNTAX_ERROR, $2);
- MYSQL_YYABORT;
- }
- if (unlikely(lex->wild && table->idx_field1 < 0))
- {
- thd->parse_error(ER_SYNTAX_ERROR, $3);
- MYSQL_YYABORT;
- }
- if (unlikely(make_schema_select(thd, Lex->current_select, table)))
- MYSQL_YYABORT;
- }
- ;
-
-show_engine_param:
- STATUS_SYM
- { Lex->sql_command= SQLCOM_SHOW_ENGINE_STATUS; }
- | MUTEX_SYM
- { Lex->sql_command= SQLCOM_SHOW_ENGINE_MUTEX; }
- | LOGS_SYM
- { Lex->sql_command= SQLCOM_SHOW_ENGINE_LOGS; }
- ;
-
-master_or_binary:
- MASTER_SYM
- | BINARY
- ;
-
-opt_storage:
- /* empty */
- | STORAGE_SYM
- ;
-
-opt_db:
- /* empty */ { $$= null_clex_str; }
- | from_or_in ident { $$= $2; }
- ;
-
-opt_full:
- /* empty */ { Lex->verbose=0; }
- | FULL { Lex->verbose=1; }
- ;
-
-from_or_in:
- FROM
- | IN_SYM
- ;
-
-binlog_in:
- /* empty */ { Lex->mi.log_file_name = 0; }
- | IN_SYM TEXT_STRING_sys { Lex->mi.log_file_name = $2.str; }
- ;
-
-binlog_from:
- /* empty */ { Lex->mi.pos = 4; /* skip magic number */ }
- | FROM ulonglong_num { Lex->mi.pos = $2; }
- ;
-
-wild_and_where:
- /* empty */ { $$= 0; }
- | LIKE remember_tok_start TEXT_STRING_sys
- {
- Lex->wild= new (thd->mem_root) String($3.str, $3.length,
- system_charset_info);
- if (unlikely(Lex->wild == NULL))
- MYSQL_YYABORT;
- $$= $2;
- }
- | WHERE remember_tok_start expr
- {
- Select->where= normalize_cond(thd, $3);
- if ($3)
- $3->top_level_item();
- $$= $2;
- }
- ;
-
-/* A Oracle compatible synonym for show */
-describe:
- describe_command table_ident
- {
- LEX *lex= Lex;
- mysql_init_select(lex);
- lex->current_select->parsing_place= SELECT_LIST;
- lex->sql_command= SQLCOM_SHOW_FIELDS;
- lex->first_select_lex()->db= null_clex_str;
- lex->verbose= 0;
- if (unlikely(prepare_schema_table(thd, lex, $2, SCH_COLUMNS)))
- MYSQL_YYABORT;
- }
- opt_describe_column
- {
- Select->parsing_place= NO_MATTER;
- }
- | describe_command opt_extended_describe
- { Lex->describe|= DESCRIBE_NORMAL; }
- explainable_command
- {
- LEX *lex=Lex;
- lex->first_select_lex()->options|= SELECT_DESCRIBE;
- }
- ;
-
-explainable_command:
- select
- | select_into
- | insert
- | replace
- | update
- | delete
- ;
-
-describe_command:
- DESC
- | DESCRIBE
- ;
-
-analyze_stmt_command:
- ANALYZE_SYM opt_format_json explainable_command
- {
- Lex->analyze_stmt= true;
- }
- ;
-
-opt_extended_describe:
- EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
- | EXTENDED_SYM ALL
- { Lex->describe|= DESCRIBE_EXTENDED | DESCRIBE_EXTENDED2; }
- | PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; }
- | opt_format_json {}
- ;
-
-opt_format_json:
- /* empty */ {}
- | FORMAT_SYM '=' ident_or_text
- {
- if (lex_string_eq(&$3, STRING_WITH_LEN("JSON")))
- Lex->explain_json= true;
- else if (lex_string_eq(&$3, STRING_WITH_LEN("TRADITIONAL")))
- DBUG_ASSERT(Lex->explain_json==false);
- else
- my_yyabort_error((ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), "EXPLAIN",
- $3.str));
- }
- ;
-
-opt_describe_column:
- /* empty */ {}
- | text_string { Lex->wild= $1; }
- | ident
- {
- Lex->wild= new (thd->mem_root) String((const char*) $1.str,
- $1.length,
- system_charset_info);
- if (unlikely(Lex->wild == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-
-/* flush things */
-
-flush:
- FLUSH_SYM opt_no_write_to_binlog
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_FLUSH;
- lex->type= 0;
- lex->no_write_to_binlog= $2;
- }
- flush_options {}
- ;
-
-flush_options:
- table_or_tables
- {
- Lex->type|= REFRESH_TABLES;
- /*
- Set type of metadata and table locks for
- FLUSH TABLES table_list [WITH READ LOCK].
- */
- YYPS->m_lock_type= TL_READ_NO_INSERT;
- YYPS->m_mdl_type= MDL_SHARED_HIGH_PRIO;
- }
- opt_table_list opt_flush_lock
- {}
- | flush_options_list
- {}
- ;
-
-opt_flush_lock:
- /* empty */ {}
- | flush_lock
- {
- TABLE_LIST *tables= Lex->query_tables;
- for (; tables; tables= tables->next_global)
- {
- tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
- /* Don't try to flush views. */
- tables->required_type= TABLE_TYPE_NORMAL;
- /* Ignore temporary tables. */
- tables->open_type= OT_BASE_ONLY;
- }
- }
- ;
-
-flush_lock:
- WITH READ_SYM LOCK_SYM optional_flush_tables_arguments
- { Lex->type|= REFRESH_READ_LOCK | $4; }
- | FOR_SYM
- {
- if (unlikely(Lex->query_tables == NULL))
- {
- // Table list can't be empty
- thd->parse_error(ER_NO_TABLES_USED);
- MYSQL_YYABORT;
- }
- Lex->type|= REFRESH_FOR_EXPORT;
- } EXPORT_SYM {}
- ;
-
-flush_options_list:
- flush_options_list ',' flush_option
- | flush_option
- {}
- ;
-
-flush_option:
- ERROR_SYM LOGS_SYM
- { Lex->type|= REFRESH_ERROR_LOG; }
- | ENGINE_SYM LOGS_SYM
- { Lex->type|= REFRESH_ENGINE_LOG; }
- | GENERAL LOGS_SYM
- { Lex->type|= REFRESH_GENERAL_LOG; }
- | SLOW LOGS_SYM
- { Lex->type|= REFRESH_SLOW_LOG; }
- | BINARY LOGS_SYM opt_delete_gtid_domain
- { Lex->type|= REFRESH_BINARY_LOG; }
- | RELAY LOGS_SYM optional_connection_name
- {
- LEX *lex= Lex;
- if (unlikely(lex->type & REFRESH_RELAY_LOG))
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH", "RELAY LOGS"));
- lex->type|= REFRESH_RELAY_LOG;
- lex->relay_log_connection_name= lex->mi.connection_name;
- }
- | QUERY_SYM CACHE_SYM
- { Lex->type|= REFRESH_QUERY_CACHE_FREE; }
- | HOSTS_SYM
- { Lex->type|= REFRESH_HOSTS; }
- | PRIVILEGES
- { Lex->type|= REFRESH_GRANT; }
- | LOGS_SYM
- {
- Lex->type|= REFRESH_LOG;
- Lex->relay_log_connection_name= empty_clex_str;
- }
- | STATUS_SYM
- { Lex->type|= REFRESH_STATUS; }
- | SLAVE optional_connection_name
- {
- LEX *lex= Lex;
- if (unlikely(lex->type & REFRESH_SLAVE))
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH","SLAVE"));
- lex->type|= REFRESH_SLAVE;
- lex->reset_slave_info.all= false;
- }
- | MASTER_SYM
- { Lex->type|= REFRESH_MASTER; }
- | DES_KEY_FILE
- { Lex->type|= REFRESH_DES_KEY_FILE; }
- | RESOURCES
- { Lex->type|= REFRESH_USER_RESOURCES; }
- | SSL_SYM
- { Lex->type|= REFRESH_SSL;}
- | IDENT_sys remember_tok_start
- {
- Lex->type|= REFRESH_GENERIC;
- ST_SCHEMA_TABLE *table= find_schema_table(thd, &$1);
- if (unlikely(!table || !table->reset_table))
- {
- thd->parse_error(ER_SYNTAX_ERROR, $2);
- MYSQL_YYABORT;
- }
- if (unlikely(Lex->view_list.push_back((LEX_CSTRING*)
- thd->memdup(&$1, sizeof(LEX_CSTRING)),
- thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-opt_table_list:
- /* empty */ {}
- | table_list {}
- ;
-
-backup:
- BACKUP_SYM backup_statements {}
- ;
-
-backup_statements:
- STAGE_SYM ident
- {
- int type;
- if (unlikely(Lex->sphead))
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "BACKUP STAGE"));
- if ((type= find_type($2.str, &backup_stage_names,
- FIND_TYPE_NO_PREFIX)) <= 0)
- my_yyabort_error((ER_BACKUP_UNKNOWN_STAGE, MYF(0), $2.str));
- Lex->sql_command= SQLCOM_BACKUP;
- Lex->backup_stage= (backup_stages) (type-1);
- break;
- }
- | LOCK_SYM table_ident
- {
- if (unlikely(!Select->add_table_to_list(thd, $2, NULL, 0,
- TL_READ, MDL_SHARED_HIGH_PRIO)))
- MYSQL_YYABORT;
- Lex->sql_command= SQLCOM_BACKUP_LOCK;
- }
- | UNLOCK_SYM
- {
- /* Table list is empty for unlock */
- Lex->sql_command= SQLCOM_BACKUP_LOCK;
- }
- ;
-
-opt_delete_gtid_domain:
- /* empty */ {}
- | DELETE_DOMAIN_ID_SYM '=' '(' delete_domain_id_list ')'
- {}
- ;
-delete_domain_id_list:
- /* Empty */
- | delete_domain_id
- | delete_domain_id_list ',' delete_domain_id
- ;
-
-delete_domain_id:
- ulonglong_num
- {
- uint32 value= (uint32) $1;
- if ($1 > UINT_MAX32)
- {
- my_printf_error(ER_BINLOG_CANT_DELETE_GTID_DOMAIN,
- "The value of gtid domain being deleted ('%llu') "
- "exceeds its maximum size "
- "of 32 bit unsigned integer", MYF(0), $1);
- MYSQL_YYABORT;
- }
- insert_dynamic(&Lex->delete_gtid_domain, (uchar*) &value);
- }
- ;
-
-optional_flush_tables_arguments:
- /* empty */ {$$= 0;}
- | AND_SYM DISABLE_SYM CHECKPOINT_SYM {$$= REFRESH_CHECKPOINT; }
- ;
-
-reset:
- RESET_SYM
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_RESET; lex->type=0;
- }
- reset_options
- {}
- ;
-
-reset_options:
- reset_options ',' reset_option
- | reset_option
- ;
-
-reset_option:
- SLAVE { Lex->type|= REFRESH_SLAVE; }
- optional_connection_name
- slave_reset_options { }
- | MASTER_SYM
- {
- Lex->type|= REFRESH_MASTER;
- Lex->next_binlog_file_number= 0;
- }
- master_reset_options
- | QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE;}
- ;
-
-slave_reset_options:
- /* empty */ { Lex->reset_slave_info.all= false; }
- | ALL { Lex->reset_slave_info.all= true; }
- ;
-
-master_reset_options:
- /* empty */ {}
- | TO_SYM ulong_num
- {
- Lex->next_binlog_file_number = $2;
- }
- ;
-
-purge:
- PURGE master_or_binary LOGS_SYM TO_SYM TEXT_STRING_sys
- {
- Lex->stmt_purge_to($5);
- }
- | PURGE master_or_binary LOGS_SYM BEFORE_SYM
- { Lex->clause_that_disallows_subselect= "PURGE..BEFORE"; }
- expr
- {
- Lex->clause_that_disallows_subselect= NULL;
- if (Lex->stmt_purge_before($6))
- MYSQL_YYABORT;
- }
- ;
-
-
-/* kill threads */
-
-kill:
- KILL_SYM
- {
- LEX *lex=Lex;
- lex->value_list.empty();
- lex->users_list.empty();
- lex->sql_command= SQLCOM_KILL;
- lex->kill_type= KILL_TYPE_ID;
- }
- kill_type kill_option kill_expr
- {
- Lex->kill_signal= (killed_state) ($3 | $4);
- }
- ;
-
-kill_type:
- /* Empty */ { $$= (int) KILL_HARD_BIT; }
- | HARD_SYM { $$= (int) KILL_HARD_BIT; }
- | SOFT_SYM { $$= 0; }
- ;
-
-kill_option:
- /* empty */ { $$= (int) KILL_CONNECTION; }
- | CONNECTION_SYM { $$= (int) KILL_CONNECTION; }
- | QUERY_SYM { $$= (int) KILL_QUERY; }
- | QUERY_SYM ID_SYM
- {
- $$= (int) KILL_QUERY;
- Lex->kill_type= KILL_TYPE_QUERY;
- }
- ;
-
-kill_expr:
- expr
- {
- Lex->value_list.push_front($$, thd->mem_root);
- }
- | USER_SYM user
- {
- Lex->users_list.push_back($2, thd->mem_root);
- Lex->kill_type= KILL_TYPE_USER;
- }
- ;
-
-
-shutdown:
- SHUTDOWN { Lex->sql_command= SQLCOM_SHUTDOWN; }
- shutdown_option {}
- ;
-
-shutdown_option:
- /* Empty */ { Lex->is_shutdown_wait_for_slaves= false; }
- | WAIT_SYM FOR_SYM ALL SLAVES
- {
- Lex->is_shutdown_wait_for_slaves= true;
- }
- ;
-
-/* change database */
-
-use:
- USE_SYM ident
- {
- LEX *lex=Lex;
- lex->sql_command=SQLCOM_CHANGE_DB;
- lex->first_select_lex()->db= $2;
- }
- ;
-
-/* import, export of files */
-
-load:
- LOAD data_or_xml
- {
- LEX *lex= thd->lex;
-
- if (unlikely(lex->sphead))
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0),
- $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML");
- MYSQL_YYABORT;
- }
- if (lex->main_select_push())
- MYSQL_YYABORT;
- mysql_init_select(lex);
- }
- load_data_lock opt_local INFILE TEXT_STRING_filesystem
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_LOAD;
- lex->local_file= $5;
- lex->duplicates= DUP_ERROR;
- lex->ignore= 0;
- if (unlikely(!(lex->exchange= new (thd->mem_root)
- sql_exchange($7.str, 0, $2))))
- MYSQL_YYABORT;
- }
- opt_duplicate INTO TABLE_SYM table_ident opt_use_partition
- {
- LEX *lex=Lex;
- if (unlikely(!Select->add_table_to_list(thd, $12, NULL,
- TL_OPTION_UPDATING,
- $4, MDL_SHARED_WRITE,
- NULL, $13)))
- MYSQL_YYABORT;
- lex->field_list.empty();
- lex->update_list.empty();
- lex->value_list.empty();
- lex->many_values.empty();
- }
- opt_load_data_charset
- { Lex->exchange->cs= $15; }
- opt_xml_rows_identified_by
- opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
- opt_load_data_set_spec
- stmt_end
- {
- Lex->mark_first_table_as_inserting();
- }
- ;
-
-data_or_xml:
- DATA_SYM { $$= FILETYPE_CSV; }
- | XML_SYM { $$= FILETYPE_XML; }
- ;
-
-opt_local:
- /* empty */ { $$=0;}
- | LOCAL_SYM { $$=1;}
- ;
-
-load_data_lock:
- /* empty */ { $$= TL_WRITE_DEFAULT; }
- | CONCURRENT
- {
- /*
- Ignore this option in SP to avoid problem with query cache and
- triggers with non default priority locks
- */
- $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT);
- }
- | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
- ;
-
-opt_duplicate:
- /* empty */ { Lex->duplicates=DUP_ERROR; }
- | REPLACE { Lex->duplicates=DUP_REPLACE; }
- | IGNORE_SYM { Lex->ignore= 1; }
- ;
-
-opt_field_term:
- /* empty */
- | COLUMNS field_term_list
- ;
-
-field_term_list:
- field_term_list field_term
- | field_term
- ;
-
-field_term:
- TERMINATED BY text_string
- {
- DBUG_ASSERT(Lex->exchange != 0);
- Lex->exchange->field_term= $3;
- }
- | OPTIONALLY ENCLOSED BY text_string
- {
- LEX *lex= Lex;
- DBUG_ASSERT(lex->exchange != 0);
- lex->exchange->enclosed= $4;
- lex->exchange->opt_enclosed= 1;
- }
- | ENCLOSED BY text_string
- {
- DBUG_ASSERT(Lex->exchange != 0);
- Lex->exchange->enclosed= $3;
- }
- | ESCAPED BY text_string
- {
- DBUG_ASSERT(Lex->exchange != 0);
- Lex->exchange->escaped= $3;
- }
- ;
-
-opt_line_term:
- /* empty */
- | LINES line_term_list
- ;
-
-line_term_list:
- line_term_list line_term
- | line_term
- ;
-
-line_term:
- TERMINATED BY text_string
- {
- DBUG_ASSERT(Lex->exchange != 0);
- Lex->exchange->line_term= $3;
- }
- | STARTING BY text_string
- {
- DBUG_ASSERT(Lex->exchange != 0);
- Lex->exchange->line_start= $3;
- }
- ;
-
-opt_xml_rows_identified_by:
- /* empty */ { }
- | ROWS_SYM IDENTIFIED_SYM BY text_string
- { Lex->exchange->line_term = $4; }
- ;
-
-opt_ignore_lines:
- /* empty */
- | IGNORE_SYM NUM lines_or_rows
- {
- DBUG_ASSERT(Lex->exchange != 0);
- Lex->exchange->skip_lines= atol($2.str);
- }
- ;
-
-lines_or_rows:
- LINES { }
- | ROWS_SYM { }
- ;
-
-opt_field_or_var_spec:
- /* empty */ {}
- | '(' fields_or_vars ')' {}
- | '(' ')' {}
- ;
-
-fields_or_vars:
- fields_or_vars ',' field_or_var
- { Lex->field_list.push_back($3, thd->mem_root); }
- | field_or_var
- { Lex->field_list.push_back($1, thd->mem_root); }
- ;
-
-field_or_var:
- simple_ident_nospvar {$$= $1;}
- | '@' ident_or_text
- {
- $$= new (thd->mem_root) Item_user_var_as_out_param(thd, &$2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-opt_load_data_set_spec:
- /* empty */ {}
- | SET load_data_set_list {}
- ;
-
-load_data_set_list:
- load_data_set_list ',' load_data_set_elem
- | load_data_set_elem
- ;
-
-load_data_set_elem:
- simple_ident_nospvar equal remember_name expr_or_default remember_end
- {
- LEX *lex= Lex;
- if (unlikely(lex->update_list.push_back($1, thd->mem_root)) ||
- unlikely(lex->value_list.push_back($4, thd->mem_root)))
- MYSQL_YYABORT;
- $4->set_name_no_truncate(thd, $3, (uint) ($5 - $3), thd->charset());
- }
- ;
-
-/* Common definitions */
-
-text_literal:
- TEXT_STRING
- {
- if (unlikely(!($$= thd->make_string_literal($1))))
- MYSQL_YYABORT;
- }
- | NCHAR_STRING
- {
- if (unlikely(!($$= thd->make_string_literal_nchar($1))))
- MYSQL_YYABORT;
- }
- | UNDERSCORE_CHARSET TEXT_STRING
- {
- if (unlikely(!($$= thd->make_string_literal_charset($2, $1))))
- MYSQL_YYABORT;
- }
- | text_literal TEXT_STRING_literal
- {
- if (unlikely(!($$= $1->make_string_literal_concat(thd, &$2))))
- MYSQL_YYABORT;
- }
- ;
-
-text_string:
- TEXT_STRING_literal
- {
- $$= new (thd->mem_root) String($1.str,
- $1.length,
- thd->variables.collation_connection);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | hex_or_bin_String { $$= $1; }
- ;
-
-
-hex_or_bin_String:
- HEX_NUM
- {
- Item *tmp= new (thd->mem_root) Item_hex_hybrid(thd, $1.str,
- $1.length);
- if (unlikely(tmp == NULL))
- MYSQL_YYABORT;
- $$= tmp->val_str((String*) 0);
- }
- | HEX_STRING
- {
- Item *tmp= new (thd->mem_root) Item_hex_string(thd, $1.str,
- $1.length);
- if (unlikely(tmp == NULL))
- MYSQL_YYABORT;
- $$= tmp->val_str((String*) 0);
- }
- | BIN_NUM
- {
- Item *tmp= new (thd->mem_root) Item_bin_string(thd, $1.str,
- $1.length);
- if (unlikely(tmp == NULL))
- MYSQL_YYABORT;
- /*
- it is OK only emulate fix_fields, because we need only
- value of constant
- */
- $$= tmp->val_str((String*) 0);
- }
- ;
-
-param_marker:
- PARAM_MARKER
- {
- if (unlikely(!($$= Lex->add_placeholder(thd, &param_clex_str,
- YYLIP->get_tok_start(),
- YYLIP->get_tok_start() + 1))))
- MYSQL_YYABORT;
- }
- | COLON_ORACLE_SYM ident_cli
- {
- if (unlikely(!($$= Lex->add_placeholder(thd, &null_clex_str,
- $1.pos(), $2.end()))))
- MYSQL_YYABORT;
- }
- | COLON_ORACLE_SYM NUM
- {
- if (unlikely(!($$= Lex->add_placeholder(thd, &null_clex_str,
- $1.pos(),
- YYLIP->get_ptr()))))
- MYSQL_YYABORT;
- }
- ;
-
-signed_literal:
- '+' NUM_literal { $$ = $2; }
- | '-' NUM_literal
- {
- $2->max_length++;
- $$= $2->neg(thd);
- }
- ;
-
-literal:
- text_literal { $$ = $1; }
- | NUM_literal { $$ = $1; }
- | temporal_literal { $$= $1; }
- | NULL_SYM
- {
- /*
- For the digest computation, in this context only,
- NULL is considered a literal, hence reduced to '?'
- REDUCE:
- TOK_GENERIC_VALUE := NULL_SYM
- */
- YYLIP->reduce_digest_token(TOK_GENERIC_VALUE, NULL_SYM);
- $$= new (thd->mem_root) Item_null(thd);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- YYLIP->next_state= MY_LEX_OPERATOR_OR_IDENT;
- }
- | FALSE_SYM
- {
- $$= new (thd->mem_root) Item_bool(thd, (char*) "FALSE",0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | TRUE_SYM
- {
- $$= new (thd->mem_root) Item_bool(thd, (char*) "TRUE",1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | HEX_NUM
- {
- $$= new (thd->mem_root) Item_hex_hybrid(thd, $1.str, $1.length);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | HEX_STRING
- {
- $$= new (thd->mem_root) Item_hex_string(thd, $1.str, $1.length);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | BIN_NUM
- {
- $$= new (thd->mem_root) Item_bin_string(thd, $1.str, $1.length);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | UNDERSCORE_CHARSET hex_or_bin_String
- {
- Item_string_with_introducer *item_str;
- /*
- Pass NULL as name. Name will be set in the "select_item" rule and
- will include the introducer and the original hex/bin notation.
- */
- item_str= new (thd->mem_root)
- Item_string_with_introducer(thd, null_clex_str,
- $2->lex_cstring(), $1);
- if (unlikely(!item_str ||
- !item_str->check_well_formed_result(true)))
- MYSQL_YYABORT;
-
- $$= item_str;
- }
- ;
-
-NUM_literal:
- NUM
- {
- int error;
- $$= new (thd->mem_root)
- Item_int(thd, $1.str,
- (longlong) my_strtoll10($1.str, NULL, &error),
- $1.length);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | LONG_NUM
- {
- int error;
- $$= new (thd->mem_root)
- Item_int(thd, $1.str,
- (longlong) my_strtoll10($1.str, NULL, &error),
- $1.length);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | ULONGLONG_NUM
- {
- $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | DECIMAL_NUM
- {
- $$= new (thd->mem_root) Item_decimal(thd, $1.str, $1.length,
- thd->charset());
- if (unlikely($$ == NULL) || unlikely(thd->is_error()))
- MYSQL_YYABORT;
- }
- | FLOAT_NUM
- {
- $$= new (thd->mem_root) Item_float(thd, $1.str, $1.length);
- if (unlikely($$ == NULL) || unlikely(thd->is_error()))
- MYSQL_YYABORT;
- }
- ;
-
-
-temporal_literal:
- DATE_SYM TEXT_STRING
- {
- if (unlikely(!($$= type_handler_newdate.create_literal_item(thd,
- $2.str, $2.length,
- YYCSCL, true))))
- MYSQL_YYABORT;
- }
- | TIME_SYM TEXT_STRING
- {
- if (unlikely(!($$= type_handler_time2.create_literal_item(thd,
- $2.str, $2.length,
- YYCSCL, true))))
- MYSQL_YYABORT;
- }
- | TIMESTAMP TEXT_STRING
- {
- if (unlikely(!($$= type_handler_datetime.create_literal_item(thd,
- $2.str, $2.length,
- YYCSCL, true))))
- MYSQL_YYABORT;
- }
- ;
-
-with_clause:
- WITH opt_recursive
- {
- LEX *lex= Lex;
- With_clause *with_clause=
- new With_clause($2, Lex->curr_with_clause);
- if (unlikely(with_clause == NULL))
- MYSQL_YYABORT;
- lex->derived_tables|= DERIVED_WITH;
- lex->curr_with_clause= with_clause;
- with_clause->add_to_list(Lex->with_clauses_list_last_next);
- if (lex->current_select &&
- lex->current_select->parsing_place == BEFORE_OPT_LIST)
- lex->current_select->parsing_place= NO_MATTER;
- }
- with_list
- {
- $$= Lex->curr_with_clause;
- Lex->curr_with_clause= Lex->curr_with_clause->pop();
- }
- ;
-
-
-opt_recursive:
- /*empty*/ { $$= 0; }
- | RECURSIVE_SYM { $$= 1; }
- ;
-
-
-with_list:
- with_list_element
- | with_list ',' with_list_element
- ;
-
-
-with_list_element:
- query_name
- opt_with_column_list
- {
- $2= new List<LEX_CSTRING> (Lex->with_column_list);
- if (unlikely($2 == NULL))
- MYSQL_YYABORT;
- Lex->with_column_list.empty();
- }
- AS '(' query_expression ')'
- {
- LEX *lex= thd->lex;
- const char *query_start= lex->sphead ? lex->sphead->m_tmp_query
- : thd->query();
- const char *spec_start= $5.pos() + 1;
- With_element *elem= new With_element($1, *$2, $6);
- if (elem == NULL || Lex->curr_with_clause->add_with_element(elem))
- MYSQL_YYABORT;
- if (elem->set_unparsed_spec(thd, spec_start, $7.pos(),
- spec_start - query_start))
- MYSQL_YYABORT;
- }
- ;
-
-
-opt_with_column_list:
- /* empty */
- { $$= NULL; }
- | '(' with_column_list ')'
- { $$= NULL; }
- ;
-
-
-with_column_list:
- ident
- {
- Lex->with_column_list.push_back((LEX_CSTRING*)
- thd->memdup(&$1, sizeof(LEX_CSTRING)));
- }
- | with_column_list ',' ident
- {
- Lex->with_column_list.push_back((LEX_CSTRING*)
- thd->memdup(&$3, sizeof(LEX_CSTRING)));
- }
- ;
-
-
-query_name:
- ident
- {
- $$= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-
-
-/**********************************************************************
-** Creating different items.
-**********************************************************************/
-
-insert_ident:
- simple_ident_nospvar { $$=$1; }
- | table_wild { $$=$1; }
- ;
-
-table_wild:
- ident '.' '*'
- {
- if (unlikely(!($$= Lex->create_item_qualified_asterisk(thd, &$1))))
- MYSQL_YYABORT;
- }
- | ident '.' ident '.' '*'
- {
- if (unlikely(!($$= Lex->create_item_qualified_asterisk(thd, &$1, &$3))))
- MYSQL_YYABORT;
- }
- ;
-
-select_sublist_qualified_asterisk:
- ident_cli '.' '*'
- {
- if (unlikely(!($$= Lex->create_item_qualified_asterisk(thd, &$1))))
- MYSQL_YYABORT;
- }
- | ident_cli '.' ident_cli '.' '*'
- {
- if (unlikely(!($$= Lex->create_item_qualified_asterisk(thd, &$1, &$3))))
- MYSQL_YYABORT;
- }
- ;
-
-order_ident:
- expr { $$=$1; }
- ;
-
-
-simple_ident:
- ident_cli
- {
- if (unlikely(!($$= Lex->create_item_ident(thd, &$1))))
- MYSQL_YYABORT;
- }
- | ident_cli '.' ident_cli
- {
- if (unlikely(!($$= Lex->create_item_ident(thd, &$1, &$3))))
- MYSQL_YYABORT;
- }
- | '.' ident_cli '.' ident_cli
- {
- Lex_ident_cli empty($2.pos(), 0);
- if (unlikely(!($$= Lex->create_item_ident(thd, &empty, &$2, &$4))))
- MYSQL_YYABORT;
- }
- | ident_cli '.' ident_cli '.' ident_cli
- {
- if (unlikely(!($$= Lex->create_item_ident(thd, &$1, &$3, &$5))))
- MYSQL_YYABORT;
- }
- | COLON_ORACLE_SYM ident_cli '.' ident_cli
- {
- if (unlikely(!($$= Lex->make_item_colon_ident_ident(thd, &$2, &$4))))
- MYSQL_YYABORT;
- }
- ;
-
-simple_ident_nospvar:
- ident
- {
- if (unlikely(!($$= Lex->create_item_ident_nosp(thd, &$1))))
- MYSQL_YYABORT;
- }
- | ident '.' ident
- {
- if (unlikely(!($$= Lex->create_item_ident_nospvar(thd, &$1, &$3))))
- MYSQL_YYABORT;
- }
- | COLON_ORACLE_SYM ident_cli '.' ident_cli
- {
- if (unlikely(!($$= Lex->make_item_colon_ident_ident(thd, &$2, &$4))))
- MYSQL_YYABORT;
- }
- | '.' ident '.' ident
- {
- Lex_ident_sys none;
- if (unlikely(!($$= Lex->create_item_ident(thd, &none, &$2, &$4))))
- MYSQL_YYABORT;
- }
- | ident '.' ident '.' ident
- {
- if (unlikely(!($$= Lex->create_item_ident(thd, &$1, &$3, &$5))))
- MYSQL_YYABORT;
- }
- ;
-
-field_ident:
- ident { $$=$1;}
- | ident '.' ident '.' ident
- {
- TABLE_LIST *table= Select->table_list.first;
- if (unlikely(my_strcasecmp(table_alias_charset, $1.str,
- table->db.str)))
- my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
- if (unlikely(my_strcasecmp(table_alias_charset, $3.str,
- table->table_name.str)))
- my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3.str));
- $$=$5;
- }
- | ident '.' ident
- {
- TABLE_LIST *table= Select->table_list.first;
- if (unlikely(my_strcasecmp(table_alias_charset, $1.str,
- table->alias.str)))
- my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $1.str));
- $$=$3;
- }
- | '.' ident { $$=$2;} /* For Delphi */
- ;
-
-table_ident:
- ident
- {
- $$= new (thd->mem_root) Table_ident(&$1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | ident '.' ident
- {
- $$= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | '.' ident
- {
- /* For Delphi */
- $$= new (thd->mem_root) Table_ident(&$2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-table_ident_opt_wild:
- ident opt_wild
- {
- $$= new (thd->mem_root) Table_ident(&$1);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | ident '.' ident opt_wild
- {
- $$= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-table_ident_nodb:
- ident
- {
- LEX_CSTRING db={(char*) any_db,3};
- $$= new (thd->mem_root) Table_ident(thd, &db, &$1, 0);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-IDENT_cli:
- IDENT
- | IDENT_QUOTED
- ;
-
-ident_cli:
- IDENT
- | IDENT_QUOTED
- | keyword_ident { $$= $1; }
- ;
-
-IDENT_sys:
- IDENT_cli
- {
- if (unlikely(thd->to_ident_sys_alloc(&$$, &$1)))
- MYSQL_YYABORT;
- }
- ;
-
-TEXT_STRING_sys:
- TEXT_STRING
- {
- if (thd->make_text_string_sys(&$$, &$1))
- MYSQL_YYABORT;
- }
- ;
-
-TEXT_STRING_literal:
- TEXT_STRING
- {
- if (thd->make_text_string_connection(&$$, &$1))
- MYSQL_YYABORT;
- }
- ;
-
-TEXT_STRING_filesystem:
- TEXT_STRING
- {
- if (thd->make_text_string_filesystem(&$$, &$1))
- MYSQL_YYABORT;
- }
- ;
-
-ident_table_alias:
- IDENT_sys
- | keyword_table_alias
- {
- if (unlikely($$.copy_keyword(thd, &$1)))
- MYSQL_YYABORT;
- }
- ;
-
-ident_cli_set_usual_case:
- IDENT_cli { $$= $1; }
- | keyword_set_usual_case { $$= $1; }
- ;
-
-ident_sysvar_name:
- IDENT_sys
- | keyword_sysvar_name
- {
- if (unlikely($$.copy_keyword(thd, &$1)))
- MYSQL_YYABORT;
- }
- | TEXT_STRING_sys
- {
- if (unlikely($$.copy_sys(thd, &$1)))
- MYSQL_YYABORT;
- }
- ;
-
-
-ident:
- IDENT_sys
- | keyword_ident
- {
- if (unlikely($$.copy_keyword(thd, &$1)))
- MYSQL_YYABORT;
- }
- ;
-
-label_ident:
- IDENT_sys
- | keyword_label
- {
- if (unlikely($$.copy_keyword(thd, &$1)))
- MYSQL_YYABORT;
- }
- ;
-
-ident_or_text:
- ident { $$=$1;}
- | TEXT_STRING_sys { $$=$1;}
- | LEX_HOSTNAME { $$=$1;}
- ;
-
-user_maybe_role:
- ident_or_text
- {
- if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER)))))
- MYSQL_YYABORT;
- $$->user = $1;
-
- if (unlikely(check_string_char_length(&$$->user, ER_USERNAME,
- username_char_length,
- system_charset_info, 0)))
- MYSQL_YYABORT;
- }
- | ident_or_text '@' ident_or_text
- {
- if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER)))))
- MYSQL_YYABORT;
- $$->user = $1; $$->host=$3;
-
- if (unlikely(check_string_char_length(&$$->user, ER_USERNAME,
- username_char_length,
- system_charset_info, 0)) ||
- unlikely(check_host_name(&$$->host)))
- MYSQL_YYABORT;
- if ($$->host.str[0])
- {
- /*
- Convert hostname part of username to lowercase.
- It's OK to use in-place lowercase as long as
- the character set is utf8.
- */
- my_casedn_str(system_charset_info, (char*) $$->host.str);
- }
- else
- {
- /*
- fix historical undocumented convention that empty host is the
- same as '%'
- */
- $$->host= host_not_specified;
- }
- }
- | CURRENT_USER optional_braces
- {
- if (unlikely(!($$=(LEX_USER*)thd->calloc(sizeof(LEX_USER)))))
- MYSQL_YYABORT;
- $$->user= current_user;
- $$->auth= new (thd->mem_root) USER_AUTH();
- }
- ;
-
-user_or_role: user_maybe_role | current_role;
-
-user: user_maybe_role
- {
- if ($1->user.str != current_user.str && $1->host.str == 0)
- $1->host= host_not_specified;
- $$= $1;
- }
- ;
-
-/* Keywords which we allow as table aliases. */
-keyword_table_alias:
- keyword_data_type
- | keyword_cast_type
- | keyword_set_special_case
- | keyword_sp_block_section
- | keyword_sp_head
- | keyword_sp_var_and_label
- | keyword_sp_var_not_label
- | keyword_sysvar_type
- | keyword_verb_clause
- | FUNCTION_SYM
- | EXCEPTION_ORACLE_SYM
- ;
-
-/* Keyword that we allow for identifiers (except SP labels) */
-keyword_ident:
- keyword_data_type
- | keyword_cast_type
- | keyword_set_special_case
- | keyword_sp_block_section
- | keyword_sp_head
- | keyword_sp_var_and_label
- | keyword_sp_var_not_label
- | keyword_sysvar_type
- | keyword_verb_clause
- | FUNCTION_SYM
- | WINDOW_SYM
- | EXCEPTION_ORACLE_SYM
- ;
-
-keyword_sysvar_name:
- keyword_data_type
- | keyword_cast_type
- | keyword_set_special_case
- | keyword_sp_block_section
- | keyword_sp_head
- | keyword_sp_var_and_label
- | keyword_sp_var_not_label
- | keyword_verb_clause
- | FUNCTION_SYM
- | WINDOW_SYM
- | EXCEPTION_ORACLE_SYM
- ;
-
-keyword_set_usual_case:
- keyword_data_type
- | keyword_cast_type
- | keyword_sp_block_section
- | keyword_sp_head
- | keyword_sp_var_and_label
- | keyword_sp_var_not_label
- | keyword_sysvar_type
- | keyword_verb_clause
- | FUNCTION_SYM
- | WINDOW_SYM
- | EXCEPTION_ORACLE_SYM
- ;
-
-non_reserved_keyword_udt:
- keyword_sp_var_not_label
- | keyword_sp_head
- | keyword_verb_clause
- | keyword_set_special_case
- | keyword_sp_block_section
- | keyword_sysvar_type
- | keyword_sp_var_and_label
- ;
-
-/*
- Keywords that we allow in Oracle-style direct assignments:
- xxx := 10;
- but do not allow in labels in the default sql_mode:
- label:
- stmt1;
- stmt2;
- TODO: check if some of them can migrate to keyword_sp_var_and_label.
-*/
-keyword_sp_var_not_label:
- ASCII_SYM
- | BACKUP_SYM
- | BINLOG_SYM
- | BYTE_SYM
- | CACHE_SYM
- | CHECKSUM_SYM
- | CHECKPOINT_SYM
- | COLUMN_ADD_SYM
- | COLUMN_CHECK_SYM
- | COLUMN_CREATE_SYM
- | COLUMN_DELETE_SYM
- | COLUMN_GET_SYM
- | COMMENT_SYM
- | COMPRESSED_SYM
- | DEALLOCATE_SYM
- | EXAMINED_SYM
- | EXCLUDE_SYM
- | EXECUTE_SYM
- | FLUSH_SYM
- | FOLLOWING_SYM
- | FORMAT_SYM
- | GET_SYM
- | HELP_SYM
- | HOST_SYM
- | INSTALL_SYM
- | OPTION
- | OPTIONS_SYM
- | OTHERS_MARIADB_SYM
- | OWNER_SYM
- | PARSER_SYM
- | PERIOD_SYM
- | PORT_SYM
- | PRECEDING_SYM
- | PREPARE_SYM
- | REMOVE_SYM
- | RESET_SYM
- | RESTORE_SYM
- | SECURITY_SYM
- | SERVER_SYM
- | SOCKET_SYM
- | SLAVE
- | SLAVES
- | SONAME_SYM
- | START_SYM
- | STOP_SYM
- | STORED_SYM
- | TIES_SYM
- | UNICODE_SYM
- | UNINSTALL_SYM
- | UNBOUNDED_SYM
- | WITHIN
- | WRAPPER_SYM
- | XA_SYM
- | UPGRADE_SYM
- ;
-
-/*
- Keywords that can start optional clauses in SP or trigger declarations
- Allowed as identifiers (e.g. table, column names),
- but:
- - not allowed as SP label names
- - not allowed as variable names in Oracle-style assignments:
- xxx := 10;
-
- If we allowed these variables in assignments, there would be conflicts
- with SP characteristics, or verb clauses, or compound statements, e.g.:
- CREATE PROCEDURE p1 LANGUAGE ...
- would be either:
- CREATE PROCEDURE p1 LANGUAGE SQL BEGIN END;
- or
- CREATE PROCEDURE p1 LANGUAGE:=10;
-
- Note, these variables can still be assigned using quoted identifiers:
- `do`:= 10;
- "do":= 10; (when ANSI_QUOTES)
- or using a SET statement:
- SET do= 10;
-
- Note, some of these keywords are reserved keywords in Oracle.
- In case if heavy grammar conflicts are found in the future,
- we'll possibly need to make them reserved for sql_mode=ORACLE.
-
- TODO: Allow these variables as SP lables when sql_mode=ORACLE.
- TODO: Allow assigning of "SP characteristics" marked variables
- inside compound blocks.
- TODO: Allow "follows" and "precedes" as variables in compound blocks:
- BEGIN
- follows := 10;
- END;
- as they conflict only with non-block FOR EACH ROW statement:
- CREATE TRIGGER .. FOR EACH ROW follows:= 10;
- CREATE TRIGGER .. FOR EACH ROW FOLLOWS tr1 a:= 10;
-*/
-keyword_sp_head:
- CONTAINS_SYM /* SP characteristic */
- | LANGUAGE_SYM /* SP characteristic */
- | NO_SYM /* SP characteristic */
- | CHARSET /* SET CHARSET utf8; */
- | FOLLOWS_SYM /* Conflicts with assignment in FOR EACH */
- | PRECEDES_SYM /* Conflicts with assignment in FOR EACH */
- ;
-
-/*
- Keywords that start a statement.
- Generally allowed as identifiers (e.g. table, column names)
- - not allowed as SP label names
- - not allowed as variable names in Oracle-style assignments:
- xxx:=10
-*/
-keyword_verb_clause:
- CLOSE_SYM /* Verb clause. Reserved in Oracle */
- | COMMIT_SYM /* Verb clause. Reserved in Oracle */
- | DO_SYM /* Verb clause */
- | HANDLER_SYM /* Verb clause */
- | OPEN_SYM /* Verb clause. Reserved in Oracle */
- | REPAIR /* Verb clause */
- | ROLLBACK_SYM /* Verb clause. Reserved in Oracle */
- | SAVEPOINT_SYM /* Verb clause. Reserved in Oracle */
- | SHUTDOWN /* Verb clause */
- | TRUNCATE_SYM /* Verb clause. Reserved in Oracle */
- ;
-
-keyword_set_special_case:
- NAMES_SYM
- | ROLE_SYM
- | PASSWORD_SYM
- ;
-
-keyword_sysvar_type:
- GLOBAL_SYM
- | LOCAL_SYM
- | SESSION_SYM
- ;
-
-
-/*
- These keywords are generally allowed as identifiers,
- but not allowed as non-delimited SP variable names in sql_mode=ORACLE.
-*/
-keyword_data_type:
- BIT_SYM
- | BOOLEAN_SYM
- | BOOL_SYM
- | CLOB_MARIADB_SYM
- | CLOB_ORACLE_SYM
- | DATE_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2
- | DATETIME
- | ENUM
- | FIXED_SYM
- | JSON_SYM
- | MEDIUM_SYM
- | NATIONAL_SYM
- | NCHAR_SYM
- | NUMBER_MARIADB_SYM
- | NUMBER_ORACLE_SYM
- | NVARCHAR_SYM
- | RAW_MARIADB_SYM
- | RAW_ORACLE_SYM
- | ROW_SYM
- | SERIAL_SYM
- | TEXT_SYM
- | TIMESTAMP %prec PREC_BELOW_CONTRACTION_TOKEN2
- | TIME_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2
- | VARCHAR2_MARIADB_SYM
- | VARCHAR2_ORACLE_SYM
- | YEAR_SYM
- ;
-
-
-keyword_cast_type:
- SIGNED_SYM
- ;
-
-
-/*
- These keywords are fine for both SP variable names and SP labels.
-*/
-keyword_sp_var_and_label:
- ACTION
- | ACCOUNT_SYM
- | ADDDATE_SYM
- | ADMIN_SYM
- | AFTER_SYM
- | AGAINST
- | AGGREGATE_SYM
- | ALGORITHM_SYM
- | ALWAYS_SYM
- | ANY_SYM
- | AT_SYM
- | ATOMIC_SYM
- | AUTHORS_SYM
- | AUTO_INC
- | AUTOEXTEND_SIZE_SYM
- | AUTO_SYM
- | AVG_ROW_LENGTH
- | AVG_SYM
- | BLOCK_SYM
- | BODY_MARIADB_SYM
- | BTREE_SYM
- | CASCADED
- | CATALOG_NAME_SYM
- | CHAIN_SYM
- | CHANGED
- | CIPHER_SYM
- | CLIENT_SYM
- | CLASS_ORIGIN_SYM
- | COALESCE
- | CODE_SYM
- | COLLATION_SYM
- | COLUMN_NAME_SYM
- | COLUMNS
- | COMMITTED_SYM
- | COMPACT_SYM
- | COMPLETION_SYM
- | CONCURRENT
- | CONNECTION_SYM
- | CONSISTENT_SYM
- | CONSTRAINT_CATALOG_SYM
- | CONSTRAINT_SCHEMA_SYM
- | CONSTRAINT_NAME_SYM
- | CONTEXT_SYM
- | CONTRIBUTORS_SYM
- | CURRENT_POS_SYM
- | CPU_SYM
- | CUBE_SYM
- /*
- Although a reserved keyword in SQL:2003 (and :2008),
- not reserved in MySQL per WL#2111 specification.
- */
- | CURRENT_SYM
- | CURSOR_NAME_SYM
- | CYCLE_SYM
- | DATA_SYM
- | DATAFILE_SYM
- | DATE_FORMAT_SYM
- | DAY_SYM
- | DECODE_MARIADB_SYM
- | DECODE_ORACLE_SYM
- | DEFINER_SYM
- | DELAY_KEY_WRITE_SYM
- | DES_KEY_FILE
- | DIAGNOSTICS_SYM
- | DIRECTORY_SYM
- | DISABLE_SYM
- | DISCARD
- | DISK_SYM
- | DUMPFILE
- | DUPLICATE_SYM
- | DYNAMIC_SYM
- | ELSEIF_ORACLE_SYM
- | ELSIF_MARIADB_SYM
- | ENDS_SYM
- | ENGINE_SYM
- | ENGINES_SYM
- | ERROR_SYM
- | ERRORS
- | ESCAPE_SYM
- | EVENT_SYM
- | EVENTS_SYM
- | EVERY_SYM
- | EXCEPTION_MARIADB_SYM
- | EXCHANGE_SYM
- | EXPANSION_SYM
- | EXPIRE_SYM
- | EXPORT_SYM
- | EXTENDED_SYM
- | EXTENT_SIZE_SYM
- | FAULTS_SYM
- | FAST_SYM
- | FOUND_SYM
- | ENABLE_SYM
- | FULL
- | FILE_SYM
- | FIRST_SYM
- | GENERAL
- | GENERATED_SYM
- | GET_FORMAT
- | GRANTS
- | GOTO_MARIADB_SYM
- | HASH_SYM
- | HARD_SYM
- | HISTORY_SYM
- | HOSTS_SYM
- | HOUR_SYM
- | ID_SYM
- | IDENTIFIED_SYM
- | IGNORE_SERVER_IDS_SYM
- | INCREMENT_SYM
- | IMMEDIATE_SYM
- | INVOKER_SYM
- | IMPORT
- | INDEXES
- | INITIAL_SIZE_SYM
- | IO_SYM
- | IPC_SYM
- | ISOLATION
- | ISOPEN_SYM
- | ISSUER_SYM
- | INSERT_METHOD
- | INVISIBLE_SYM
- | KEY_BLOCK_SIZE
- | LAST_VALUE
- | LAST_SYM
- | LASTVAL_SYM
- | LEAVES
- | LESS_SYM
- | LEVEL_SYM
- | LIST_SYM
- | LOCKS_SYM
- | LOGFILE_SYM
- | LOGS_SYM
- | MAX_ROWS
- | MASTER_SYM
- | MASTER_HEARTBEAT_PERIOD_SYM
- | MASTER_GTID_POS_SYM
- | MASTER_HOST_SYM
- | MASTER_PORT_SYM
- | MASTER_LOG_FILE_SYM
- | MASTER_LOG_POS_SYM
- | MASTER_USER_SYM
- | MASTER_USE_GTID_SYM
- | MASTER_PASSWORD_SYM
- | MASTER_SERVER_ID_SYM
- | MASTER_CONNECT_RETRY_SYM
- | MASTER_DELAY_SYM
- | MASTER_SSL_SYM
- | MASTER_SSL_CA_SYM
- | MASTER_SSL_CAPATH_SYM
- | MASTER_SSL_CERT_SYM
- | MASTER_SSL_CIPHER_SYM
- | MASTER_SSL_CRL_SYM
- | MASTER_SSL_CRLPATH_SYM
- | MASTER_SSL_KEY_SYM
- | MAX_CONNECTIONS_PER_HOUR
- | MAX_QUERIES_PER_HOUR
- | MAX_SIZE_SYM
- | MAX_STATEMENT_TIME_SYM
- | MAX_UPDATES_PER_HOUR
- | MAX_USER_CONNECTIONS_SYM
- | MEMORY_SYM
- | MERGE_SYM
- | MESSAGE_TEXT_SYM
- | MICROSECOND_SYM
- | MIGRATE_SYM
- | MINUTE_SYM
- | MINVALUE_SYM
- | MIN_ROWS
- | MODIFY_SYM
- | MODE_SYM
- | MONTH_SYM
- | MUTEX_SYM
- | MYSQL_SYM
- | MYSQL_ERRNO_SYM
- | NAME_SYM
- | NEVER_SYM
- | NEXT_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2
- | NEXTVAL_SYM
- | NEW_SYM
- | NOCACHE_SYM
- | NOCYCLE_SYM
- | NOMINVALUE_SYM
- | NOMAXVALUE_SYM
- | NO_WAIT_SYM
- | NOWAIT_SYM
- | NODEGROUP_SYM
- | NONE_SYM
- | NOTFOUND_SYM
- | OF_SYM
- | OFFSET_SYM
- | OLD_PASSWORD_SYM
- | ONE_SYM
- | ONLINE_SYM
- | ONLY_SYM
- | PACKAGE_MARIADB_SYM
- | PACK_KEYS_SYM
- | PAGE_SYM
- | PARTIAL
- | PARTITIONING_SYM
- | PARTITIONS_SYM
- | PERSISTENT_SYM
- | PHASE_SYM
- | PLUGIN_SYM
- | PLUGINS_SYM
- | PRESERVE_SYM
- | PREV_SYM
- | PREVIOUS_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2
- | PRIVILEGES
- | PROCESS
- | PROCESSLIST_SYM
- | PROFILE_SYM
- | PROFILES_SYM
- | PROXY_SYM
- | QUARTER_SYM
- | QUERY_SYM
- | QUICK
- | RAISE_MARIADB_SYM
- | READ_ONLY_SYM
- | REBUILD_SYM
- | RECOVER_SYM
- | REDO_BUFFER_SIZE_SYM
- | REDOFILE_SYM
- | REDUNDANT_SYM
- | RELAY
- | RELAYLOG_SYM
- | RELAY_LOG_FILE_SYM
- | RELAY_LOG_POS_SYM
- | RELAY_THREAD
- | RELOAD
- | REORGANIZE_SYM
- | REPEATABLE_SYM
- | REPLICATION
- | RESOURCES
- | RESTART_SYM
- | RESUME_SYM
- | RETURNED_SQLSTATE_SYM
- | RETURNS_SYM
- | REUSE_SYM
- | REVERSE_SYM
- | ROLLUP_SYM
- | ROUTINE_SYM
- | ROWCOUNT_SYM
- | ROWTYPE_MARIADB_SYM
- | ROW_COUNT_SYM
- | ROW_FORMAT_SYM
- | RTREE_SYM
- | SCHEDULE_SYM
- | SCHEMA_NAME_SYM
- | SECOND_SYM
- | SEQUENCE_SYM
- | SERIALIZABLE_SYM
- | SETVAL_SYM
- | SIMPLE_SYM
- | SHARE_SYM
- | SLAVE_POS_SYM
- | SLOW
- | SNAPSHOT_SYM
- | SOFT_SYM
- | SOUNDS_SYM
- | SOURCE_SYM
- | SQL_CACHE_SYM
- | SQL_BUFFER_RESULT
- | SQL_NO_CACHE_SYM
- | SQL_THREAD
- | STAGE_SYM
- | STARTS_SYM
- | STATEMENT_SYM
- | STATUS_SYM
- | STORAGE_SYM
- | STRING_SYM
- | SUBCLASS_ORIGIN_SYM
- | SUBDATE_SYM
- | SUBJECT_SYM
- | SUBPARTITION_SYM
- | SUBPARTITIONS_SYM
- | SUPER_SYM
- | SUSPEND_SYM
- | SWAPS_SYM
- | SWITCHES_SYM
- | SYSTEM
- | SYSTEM_TIME_SYM
- | TABLE_NAME_SYM
- | TABLES
- | TABLE_CHECKSUM_SYM
- | TABLESPACE
- | TEMPORARY
- | TEMPTABLE_SYM
- | THAN_SYM
- | TRANSACTION_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2
- | TRANSACTIONAL_SYM
- | TRIGGERS_SYM
- | TRIM_ORACLE
- | TIMESTAMP_ADD
- | TIMESTAMP_DIFF
- | TYPES_SYM
- | TYPE_SYM
- | UDF_RETURNS_SYM
- | UNCOMMITTED_SYM
- | UNDEFINED_SYM
- | UNDO_BUFFER_SIZE_SYM
- | UNDOFILE_SYM
- | UNKNOWN_SYM
- | UNTIL_SYM
- | USER_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2
- | USE_FRM
- | VARIABLES
- | VERSIONING_SYM
- | VIEW_SYM
- | VIRTUAL_SYM
- | VALUE_SYM
- | WARNINGS
- | WAIT_SYM
- | WEEK_SYM
- | WEIGHT_STRING_SYM
- | WITHOUT
- | WORK_SYM
- | X509_SYM
- | XML_SYM
- | VIA_SYM
- ;
-
-
-reserved_keyword_udt_not_param_type:
- ACCESSIBLE_SYM
- | ADD
- | ALL
- | ALTER
- | ANALYZE_SYM
- | AND_SYM
- | AS
- | ASC
- | ASENSITIVE_SYM
- | BEFORE_SYM
- | BETWEEN_SYM
- | BIT_AND
- | BIT_OR
- | BIT_XOR
- | BODY_ORACLE_SYM
- | BOTH
- | BY
- | CALL_SYM
- | CASCADE
- | CASE_SYM
- | CAST_SYM
- | CHANGE
- | CHECK_SYM
- | COLLATE_SYM
- | CONSTRAINT
- | CONTINUE_MARIADB_SYM
- | CONTINUE_ORACLE_SYM
- | CONVERT_SYM
- | COUNT_SYM
- | CREATE
- | CROSS
- | CUME_DIST_SYM
- | CURDATE
- | CURRENT_USER
- | CURRENT_ROLE
- | CURTIME
- | DATABASE
- | DATABASES
- | DATE_ADD_INTERVAL
- | DATE_SUB_INTERVAL
- | DAY_HOUR_SYM
- | DAY_MICROSECOND_SYM
- | DAY_MINUTE_SYM
- | DAY_SECOND_SYM
- | DECLARE_MARIADB_SYM
- | DECLARE_ORACLE_SYM
- | DEFAULT
- | DELETE_DOMAIN_ID_SYM
- | DELETE_SYM
- | DENSE_RANK_SYM
- | DESC
- | DESCRIBE
- | DETERMINISTIC_SYM
- | DISTINCT
- | DIV_SYM
- | DO_DOMAIN_IDS_SYM
- | DROP
- | DUAL_SYM
- | EACH_SYM
- | ELSE
- | ELSEIF_MARIADB_SYM
- | ELSIF_ORACLE_SYM
- | ENCLOSED
- | ESCAPED
- | EXCEPT_SYM
- | EXISTS
- | EXTRACT_SYM
- | FALSE_SYM
- | FETCH_SYM
- | FIRST_VALUE_SYM
- | FOREIGN
- | FROM
- | FULLTEXT_SYM
- | GOTO_ORACLE_SYM
- | GRANT
- | GROUP_SYM
- | GROUP_CONCAT_SYM
- | LAG_SYM
- | LEAD_SYM
- | HAVING
- | HOUR_MICROSECOND_SYM
- | HOUR_MINUTE_SYM
- | HOUR_SECOND_SYM
- | IF_SYM
- | IGNORE_DOMAIN_IDS_SYM
- | IGNORE_SYM
- | INDEX_SYM
- | INFILE
- | INNER_SYM
- | INSENSITIVE_SYM
- | INSERT
- | INTERSECT_SYM
- | INTERVAL_SYM
- | INTO
- | IS
- | ITERATE_SYM
- | JOIN_SYM
- | KEYS
- | KEY_SYM
- | KILL_SYM
- | LEADING
- | LEAVE_SYM
- | LEFT
- | LIKE
- | LIMIT
- | LINEAR_SYM
- | LINES
- | LOAD
- | LOCATOR_SYM
- | LOCK_SYM
- | LOOP_SYM
- | LOW_PRIORITY
- | MASTER_SSL_VERIFY_SERVER_CERT_SYM
- | MATCH
- | MAX_SYM
- | MAXVALUE_SYM
- | MEDIAN_SYM
- | MINUTE_MICROSECOND_SYM
- | MINUTE_SECOND_SYM
- | MIN_SYM
- | MODIFIES_SYM
- | MOD_SYM
- | NATURAL
- | NEG
- | NOT_SYM
- | NOW_SYM
- | NO_WRITE_TO_BINLOG
- | NTILE_SYM
- | NULL_SYM
- | NTH_VALUE_SYM
- | ON
- | OPTIMIZE
- | OPTIONALLY
- | ORDER_SYM
- | OR_SYM
- | OTHERS_ORACLE_SYM
- | OUTER
- | OUTFILE
- | OVER_SYM
- | PACKAGE_ORACLE_SYM
- | PAGE_CHECKSUM_SYM
- | PARSE_VCOL_EXPR_SYM
- | PARTITION_SYM
- | PERCENT_RANK_SYM
- | PERCENTILE_CONT_SYM
- | PERCENTILE_DISC_SYM
- | PORTION_SYM
- | POSITION_SYM
- | PRECISION
- | PRIMARY_SYM
- | PROCEDURE_SYM
- | PURGE
- | RAISE_ORACLE_SYM
- | RANGE_SYM
- | RANK_SYM
- | READS_SYM
- | READ_SYM
- | READ_WRITE_SYM
- | RECURSIVE_SYM
- | REF_SYSTEM_ID_SYM
- | REFERENCES
- | REGEXP
- | RELEASE_SYM
- | RENAME
- | REPEAT_SYM
- | REPLACE
- | REQUIRE_SYM
- | RESIGNAL_SYM
- | RESTRICT
- | RETURNING_SYM
- | RETURN_MARIADB_SYM
- | RETURN_ORACLE_SYM
- | REVOKE
- | RIGHT
- | ROWS_SYM
- | ROWTYPE_ORACLE_SYM
- | ROW_NUMBER_SYM
- | SECOND_MICROSECOND_SYM
- | SELECT_SYM
- | SENSITIVE_SYM
- | SEPARATOR_SYM
- | SERVER_OPTIONS
- | SHOW
- | SIGNAL_SYM
- | SPATIAL_SYM
- | SPECIFIC_SYM
- | SQLEXCEPTION_SYM
- | SQLSTATE_SYM
- | SQLWARNING_SYM
- | SQL_BIG_RESULT
- | SQL_SMALL_RESULT
- | SQL_SYM
- | SSL_SYM
- | STARTING
- | STATS_AUTO_RECALC_SYM
- | STATS_PERSISTENT_SYM
- | STATS_SAMPLE_PAGES_SYM
- | STDDEV_SAMP_SYM
- | STD_SYM
- | STRAIGHT_JOIN
- | SUBSTRING
- | SUM_SYM
- | SYSDATE
- | TABLE_REF_PRIORITY
- | TABLE_SYM
- | TERMINATED
- | THEN_SYM
- | TO_SYM
- | TRAILING
- | TRIGGER_SYM
- | TRIM
- | TRUE_SYM
- | UNDO_SYM
- | UNION_SYM
- | UNIQUE_SYM
- | UNLOCK_SYM
- | UPDATE_SYM
- | USAGE
- | USE_SYM
- | USING
- | UTC_DATE_SYM
- | UTC_TIMESTAMP_SYM
- | UTC_TIME_SYM
- | VALUES
- | VALUES_IN_SYM
- | VALUES_LESS_SYM
- | VARIANCE_SYM
- | VARYING
- | VAR_SAMP_SYM
- | WHEN_SYM
- | WHERE
- | WHILE_SYM
- | WITH
- | XOR
- | YEAR_MONTH_SYM
- | ZEROFILL
- ;
-
-/*
- SQLCOM_SET_OPTION statement.
-
- Note that to avoid shift/reduce conflicts, we have separate rules for the
- first option listed in the statement.
-*/
-
-set:
- SET
- {
- LEX *lex=Lex;
- if (lex->main_select_push())
- MYSQL_YYABORT;
- lex->set_stmt_init();
- }
- set_param
- stmt_end {}
- ;
-
-set_param:
- option_value_no_option_type
- | option_value_no_option_type ',' option_value_list
- | TRANSACTION_SYM
- {
- Lex->option_type= OPT_DEFAULT;
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- transaction_characteristics
- {
- if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | option_type
- {
- Lex->option_type= $1;
- }
- start_option_value_list_following_option_type
- | STATEMENT_SYM
- set_stmt_option_list
- {
- LEX *lex= Lex;
- if (unlikely(lex->table_or_sp_used()))
- my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
- lex->stmt_var_list= lex->var_list;
- lex->var_list.empty();
- if (Lex->check_main_unit_semantics())
- MYSQL_YYABORT;
- }
- FOR_SYM directly_executable_statement
- ;
-
-set_stmt_option_list:
- /*
- Only system variables can be used here. If this condition is changed
- please check careful code under lex->option_type == OPT_STATEMENT
- condition on wrong type casts.
- */
- set_stmt_option
- | set_stmt_option_list ',' set_stmt_option
- ;
-
-/* Start of option value list, option_type was given */
-start_option_value_list_following_option_type:
- option_value_following_option_type
- | option_value_following_option_type ',' option_value_list
- | TRANSACTION_SYM
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- transaction_characteristics
- {
- if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- ;
-
-/* Repeating list of option values after first option value. */
-option_value_list:
- option_value
- | option_value_list ',' option_value
- ;
-
-/* Wrapper around option values following the first option value in the stmt. */
-option_value:
- option_type
- {
- Lex->option_type= $1;
- }
- option_value_following_option_type
- | option_value_no_option_type
- ;
-
-option_type:
- GLOBAL_SYM { $$=OPT_GLOBAL; }
- | LOCAL_SYM { $$=OPT_SESSION; }
- | SESSION_SYM { $$=OPT_SESSION; }
- ;
-
-opt_var_type:
- /* empty */ { $$=OPT_SESSION; }
- | GLOBAL_SYM { $$=OPT_GLOBAL; }
- | LOCAL_SYM { $$=OPT_SESSION; }
- | SESSION_SYM { $$=OPT_SESSION; }
- ;
-
-opt_var_ident_type:
- /* empty */ { $$=OPT_DEFAULT; }
- | GLOBAL_SYM '.' { $$=OPT_GLOBAL; }
- | LOCAL_SYM '.' { $$=OPT_SESSION; }
- | SESSION_SYM '.' { $$=OPT_SESSION; }
- ;
-
-/*
- SET STATEMENT options do not need their own LEX or Query_arena.
- Let's put them to the main ones.
-*/
-set_stmt_option:
- ident_cli equal set_expr_or_default
- {
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $3)))
- MYSQL_YYABORT;
- }
- | ident_cli '.' ident equal set_expr_or_default
- {
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $5)))
- MYSQL_YYABORT;
- }
- | DEFAULT '.' ident equal set_expr_or_default
- {
- if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $5)))
- MYSQL_YYABORT;
- }
- ;
-
-
-/* Option values with preceding option_type. */
-option_value_following_option_type:
- ident_cli equal
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $4)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | ident_cli '.' ident equal
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $6)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | DEFAULT '.' ident equal
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $6)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- ;
-
-/* Option values without preceding option_type. */
-option_value_no_option_type:
- ident_cli_set_usual_case equal
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->set_variable(&tmp, $4)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | ident_cli_set_usual_case '.' ident equal
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->set_variable(&tmp, &$3, $6)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | DEFAULT '.' ident equal
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- if (unlikely(Lex->set_default_system_variable(Lex->option_type, &$3, $6)))
- MYSQL_YYABORT;
- if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | '@' ident_or_text equal
- {
- if (sp_create_assignment_lex(thd, $1.str))
- MYSQL_YYABORT;
- }
- expr
- {
- if (unlikely(Lex->set_user_variable(thd, &$2, $5)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | '@' '@' opt_var_ident_type ident_sysvar_name equal
- {
- if (sp_create_assignment_lex(thd, $1.str))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- if (unlikely(Lex->set_system_variable($3, &$4, $7)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | '@' '@' opt_var_ident_type ident_sysvar_name '.' ident equal
- {
- if (sp_create_assignment_lex(thd, $1.str))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- if (unlikely(Lex->set_system_variable(thd, $3, &$4, &$6, $9)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | '@' '@' opt_var_ident_type DEFAULT '.' ident equal
- {
- if (sp_create_assignment_lex(thd, $1.str))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- if (unlikely(Lex->set_default_system_variable($3, &$6, $9)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | charset old_or_new_charset_name_or_default
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- LEX *lex= thd->lex;
- CHARSET_INFO *cs2;
- cs2= $2 ? $2: global_system_variables.character_set_client;
- set_var_collation_client *var;
- var= (new (thd->mem_root)
- set_var_collation_client(cs2,
- thd->variables.collation_database,
- cs2));
- if (unlikely(var == NULL))
- MYSQL_YYABORT;
- lex->var_list.push_back(var, thd->mem_root);
- if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | NAMES_SYM equal expr
- {
- LEX *lex= Lex;
- sp_pcontext *spc= lex->spcont;
- LEX_CSTRING names= { STRING_WITH_LEN("names") };
- if (unlikely(spc && spc->find_variable(&names, false)))
- my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
- else
- thd->parse_error();
- MYSQL_YYABORT;
- }
- | NAMES_SYM charset_name_or_default opt_collate
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- LEX *lex= Lex;
- CHARSET_INFO *cs2;
- CHARSET_INFO *cs3;
- cs2= $2 ? $2 : global_system_variables.character_set_client;
- cs3= $3 ? $3 : cs2;
- if (unlikely(!my_charset_same(cs2, cs3)))
- {
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- cs3->name, cs2->csname);
- MYSQL_YYABORT;
- }
- set_var_collation_client *var;
- var= new (thd->mem_root) set_var_collation_client(cs3, cs3, cs3);
- if (unlikely(var == NULL) ||
- unlikely(lex->var_list.push_back(var, thd->mem_root)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | DEFAULT ROLE_SYM grant_role
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- LEX *lex = Lex;
- LEX_USER *user;
- if (unlikely(!(user=(LEX_USER *) thd->calloc(sizeof(LEX_USER)))))
- MYSQL_YYABORT;
- user->user= current_user;
- set_var_default_role *var= (new (thd->mem_root)
- set_var_default_role(user,
- $3->user));
- if (unlikely(var == NULL) ||
- unlikely(lex->var_list.push_back(var, thd->mem_root)))
- MYSQL_YYABORT;
-
- thd->lex->autocommit= TRUE;
- if (lex->sphead)
- lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
- if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | DEFAULT ROLE_SYM grant_role FOR_SYM user
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- LEX *lex = Lex;
- set_var_default_role *var= (new (thd->mem_root)
- set_var_default_role($5, $3->user));
- if (unlikely(var == NULL) ||
- unlikely(lex->var_list.push_back(var, thd->mem_root)))
- MYSQL_YYABORT;
- thd->lex->autocommit= TRUE;
- if (lex->sphead)
- lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
- if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | ROLE_SYM ident_or_text
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- LEX *lex = Lex;
- set_var_role *var= new (thd->mem_root) set_var_role($2);
- if (unlikely(var == NULL) ||
- unlikely(lex->var_list.push_back(var, thd->mem_root)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | ROLE_SYM equal
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->set_variable(&tmp, $4)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- | PASSWORD_SYM opt_for_user text_or_password
- {
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- LEX *lex = Lex;
- set_var_password *var= (new (thd->mem_root)
- set_var_password(lex->definer));
- if (unlikely(var == NULL) ||
- unlikely(lex->var_list.push_back(var, thd->mem_root)))
- MYSQL_YYABORT;
- lex->autocommit= TRUE;
- if (lex->sphead)
- lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
- if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
- MYSQL_YYABORT;
- }
- ;
-
-
-transaction_characteristics:
- transaction_access_mode
- | isolation_level
- | transaction_access_mode ',' isolation_level
- | isolation_level ',' transaction_access_mode
- ;
-
-transaction_access_mode:
- transaction_access_mode_types
- {
- LEX *lex=Lex;
- Item *item= new (thd->mem_root) Item_int(thd, (int32) $1);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- set_var *var= (new (thd->mem_root)
- set_var(thd, lex->option_type,
- find_sys_var(thd, "tx_read_only"),
- &null_clex_str,
- item));
- if (unlikely(var == NULL))
- MYSQL_YYABORT;
- if (unlikely(lex->var_list.push_back(var, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-isolation_level:
- ISOLATION LEVEL_SYM isolation_types
- {
- LEX *lex=Lex;
- Item *item= new (thd->mem_root) Item_int(thd, (int32) $3);
- if (unlikely(item == NULL))
- MYSQL_YYABORT;
- set_var *var= (new (thd->mem_root)
- set_var(thd, lex->option_type,
- find_sys_var(thd, "tx_isolation"),
- &null_clex_str,
- item));
- if (unlikely(var == NULL) ||
- unlikely(lex->var_list.push_back(var, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-transaction_access_mode_types:
- READ_SYM ONLY_SYM { $$= true; }
- | READ_SYM WRITE_SYM { $$= false; }
- ;
-
-isolation_types:
- READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
- | READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; }
- | REPEATABLE_SYM READ_SYM { $$= ISO_REPEATABLE_READ; }
- | SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; }
- ;
-
-opt_for_user:
- equal
- {
- LEX *lex= thd->lex;
- sp_pcontext *spc= lex->spcont;
- LEX_CSTRING pw= { STRING_WITH_LEN("password") };
-
- if (unlikely(spc && spc->find_variable(&pw, false)))
- my_yyabort_error((ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str));
- if (unlikely(!(lex->definer= (LEX_USER*)
- thd->calloc(sizeof(LEX_USER)))))
- MYSQL_YYABORT;
- lex->definer->user= current_user;
- lex->definer->auth= new (thd->mem_root) USER_AUTH();
- }
- | FOR_SYM user equal { Lex->definer= $2; }
- ;
-
-text_or_password:
- TEXT_STRING
- {
- Lex->definer->auth= new (thd->mem_root) USER_AUTH();
- Lex->definer->auth->auth_str= $1;
- }
- | PASSWORD_SYM '(' TEXT_STRING ')'
- {
- Lex->definer->auth= new (thd->mem_root) USER_AUTH();
- Lex->definer->auth->pwtext= $3;
- }
- | OLD_PASSWORD_SYM '(' TEXT_STRING ')'
- {
- Lex->definer->auth= new (thd->mem_root) USER_AUTH();
- Lex->definer->auth->pwtext= $3;
- Lex->definer->auth->auth_str.str= Item_func_password::alloc(thd,
- $3.str, $3.length, Item_func_password::OLD);
- Lex->definer->auth->auth_str.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
- }
- ;
-
-set_expr_or_default:
- expr { $$=$1; }
- | DEFAULT { $$=0; }
- | ON
- {
- $$=new (thd->mem_root) Item_string_sys(thd, "ON", 2);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | ALL
- {
- $$=new (thd->mem_root) Item_string_sys(thd, "ALL", 3);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- | BINARY
- {
- $$=new (thd->mem_root) Item_string_sys(thd, "binary", 6);
- if (unlikely($$ == NULL))
- MYSQL_YYABORT;
- }
- ;
-
-/* Lock function */
-
-lock:
- LOCK_SYM table_or_tables
- {
- LEX *lex= Lex;
-
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
- lex->sql_command= SQLCOM_LOCK_TABLES;
- }
- table_lock_list opt_lock_wait_timeout
- {}
- ;
-
-opt_lock_wait_timeout:
- /* empty */
- {}
- | WAIT_SYM ulong_num
- {
- if (unlikely(set_statement_var_if_exists(thd, STRING_WITH_LEN("lock_wait_timeout"), $2)) ||
- unlikely(set_statement_var_if_exists(thd, STRING_WITH_LEN("innodb_lock_wait_timeout"), $2)))
- MYSQL_YYABORT;
- }
- | NOWAIT_SYM
- {
- if (unlikely(set_statement_var_if_exists(thd, STRING_WITH_LEN("lock_wait_timeout"), 0)) ||
- unlikely(set_statement_var_if_exists(thd, STRING_WITH_LEN("innodb_lock_wait_timeout"), 0)))
- MYSQL_YYABORT;
- }
- ;
-
-table_or_tables:
- TABLE_SYM { }
- | TABLES { }
- ;
-
-table_lock_list:
- table_lock
- | table_lock_list ',' table_lock
- ;
-
-table_lock:
- table_ident opt_table_alias_clause lock_option
- {
- thr_lock_type lock_type= (thr_lock_type) $3;
- bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE);
- ulong table_options= lock_for_write ? TL_OPTION_UPDATING : 0;
- enum_mdl_type mdl_type= !lock_for_write
- ? MDL_SHARED_READ
- : lock_type == TL_WRITE_CONCURRENT_INSERT
- ? MDL_SHARED_WRITE
- : MDL_SHARED_NO_READ_WRITE;
-
- if (unlikely(!Lex->current_select_or_default()->
- add_table_to_list(thd, $1, $2, table_options,
- lock_type, mdl_type)))
- MYSQL_YYABORT;
- }
- ;
-
-lock_option:
- READ_SYM { $$= TL_READ_NO_INSERT; }
- | WRITE_SYM { $$= TL_WRITE_DEFAULT; }
- | WRITE_SYM CONCURRENT
- {
- $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT);
- }
-
- | LOW_PRIORITY WRITE_SYM { $$= TL_WRITE_LOW_PRIORITY; }
- | READ_SYM LOCAL_SYM { $$= TL_READ; }
- ;
-
-unlock:
- UNLOCK_SYM
- {
- LEX *lex= Lex;
-
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
- lex->sql_command= SQLCOM_UNLOCK_TABLES;
- }
- table_or_tables
- {}
- ;
-
-/*
-** Handler: direct access to ISAM functions
-*/
-
-handler:
- HANDLER_SYM
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- handler_tail
- {
- Lex->pop_select(); //main select
- }
- ;
-
-handler_tail:
- table_ident OPEN_SYM opt_table_alias_clause
- {
- LEX *lex= Lex;
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
- lex->sql_command = SQLCOM_HA_OPEN;
- if (!lex->current_select->add_table_to_list(thd, $1, $3, 0))
- MYSQL_YYABORT;
- }
- | table_ident_nodb CLOSE_SYM
- {
- LEX *lex= Lex;
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
- lex->sql_command = SQLCOM_HA_CLOSE;
- if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
- MYSQL_YYABORT;
- }
- | table_ident_nodb READ_SYM
- {
- LEX *lex=Lex;
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
- lex->clause_that_disallows_subselect= "HANDLER..READ";
- lex->sql_command = SQLCOM_HA_READ;
- lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
- Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
- if (unlikely(one == NULL))
- MYSQL_YYABORT;
- lex->current_select->select_limit= one;
- lex->current_select->offset_limit= 0;
- lex->limit_rows_examined= 0;
- if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
- MYSQL_YYABORT;
- }
- handler_read_or_scan opt_where_clause opt_global_limit_clause
- {
- LEX *lex=Lex;
- lex->clause_that_disallows_subselect= NULL;
- if (!lex->current_select->explicit_limit)
- {
- Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
- if (one == NULL)
- MYSQL_YYABORT;
- lex->current_select->select_limit= one;
- lex->current_select->offset_limit= 0;
- lex->limit_rows_examined= 0;
- }
- /* Stored functions are not supported for HANDLER READ. */
- if (lex->uses_stored_routines())
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0),
- "stored functions in HANDLER ... READ");
- MYSQL_YYABORT;
- }
- }
- ;
-
-handler_read_or_scan:
- handler_scan_function { Lex->ident= null_clex_str; }
- | ident handler_rkey_function { Lex->ident= $1; }
- ;
-
-handler_scan_function:
- FIRST_SYM { Lex->ha_read_mode = RFIRST; }
- | NEXT_SYM { Lex->ha_read_mode = RNEXT; }
- ;
-
-handler_rkey_function:
- FIRST_SYM { Lex->ha_read_mode = RFIRST; }
- | NEXT_SYM { Lex->ha_read_mode = RNEXT; }
- | PREV_SYM { Lex->ha_read_mode = RPREV; }
- | LAST_SYM { Lex->ha_read_mode = RLAST; }
- | handler_rkey_mode
- {
- LEX *lex=Lex;
- lex->ha_read_mode = RKEY;
- lex->ha_rkey_mode=$1;
- if (unlikely(!(lex->insert_list= new (thd->mem_root) List_item)))
- MYSQL_YYABORT;
- }
- '(' values ')'
- {}
- ;
-
-handler_rkey_mode:
- '=' { $$=HA_READ_KEY_EXACT; }
- | GE { $$=HA_READ_KEY_OR_NEXT; }
- | LE { $$=HA_READ_KEY_OR_PREV; }
- | '>' { $$=HA_READ_AFTER_KEY; }
- | '<' { $$=HA_READ_BEFORE_KEY; }
- ;
-
-/* GRANT / REVOKE */
-
-revoke:
- REVOKE clear_privileges revoke_command
- {}
- ;
-
-revoke_command:
- grant_privileges ON opt_table grant_ident FROM user_and_role_list
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_REVOKE;
- lex->type= 0;
- }
- | grant_privileges ON FUNCTION_SYM grant_ident FROM user_and_role_list
- {
- if (unlikely(Lex->add_grant_command(thd, SQLCOM_REVOKE,
- TYPE_ENUM_FUNCTION)))
- MYSQL_YYABORT;
- }
- | grant_privileges ON PROCEDURE_SYM grant_ident FROM user_and_role_list
- {
- if (unlikely(Lex->add_grant_command(thd, SQLCOM_REVOKE,
- TYPE_ENUM_PROCEDURE)))
- MYSQL_YYABORT;
- }
- | grant_privileges ON PACKAGE_ORACLE_SYM grant_ident
- FROM user_and_role_list
- {
- if (unlikely(Lex->add_grant_command(thd, SQLCOM_REVOKE,
- TYPE_ENUM_PACKAGE)))
- MYSQL_YYABORT;
- }
- | grant_privileges ON PACKAGE_ORACLE_SYM BODY_ORACLE_SYM grant_ident
- FROM user_and_role_list
- {
- if (unlikely(Lex->add_grant_command(thd, SQLCOM_REVOKE,
- TYPE_ENUM_PACKAGE_BODY)))
- MYSQL_YYABORT;
- }
- | ALL opt_privileges ',' GRANT OPTION FROM user_and_role_list
- {
- Lex->sql_command = SQLCOM_REVOKE_ALL;
- }
- | PROXY_SYM ON user FROM user_list
- {
- LEX *lex= Lex;
- lex->users_list.push_front ($3);
- lex->sql_command= SQLCOM_REVOKE;
- lex->type= TYPE_ENUM_PROXY;
- }
- | admin_option_for_role FROM user_and_role_list
- {
- Lex->sql_command= SQLCOM_REVOKE_ROLE;
- if (unlikely(Lex->users_list.push_front($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-admin_option_for_role:
- ADMIN_SYM OPTION FOR_SYM grant_role
- { Lex->with_admin_option= true; $$= $4; }
- | grant_role
- { Lex->with_admin_option= false; $$= $1; }
- ;
-
-grant:
- GRANT clear_privileges grant_command
- {}
- ;
-
-grant_command:
- grant_privileges ON opt_table grant_ident TO_SYM grant_list
- opt_require_clause opt_grant_options
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_GRANT;
- lex->type= 0;
- }
- | grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list
- opt_require_clause opt_grant_options
- {
- if (unlikely(Lex->add_grant_command(thd, SQLCOM_GRANT,
- TYPE_ENUM_FUNCTION)))
- MYSQL_YYABORT;
- }
- | grant_privileges ON PROCEDURE_SYM grant_ident TO_SYM grant_list
- opt_require_clause opt_grant_options
- {
- if (unlikely(Lex->add_grant_command(thd, SQLCOM_GRANT,
- TYPE_ENUM_PROCEDURE)))
- MYSQL_YYABORT;
- }
- | grant_privileges ON PACKAGE_ORACLE_SYM grant_ident TO_SYM grant_list
- opt_require_clause opt_grant_options
- {
- if (unlikely(Lex->add_grant_command(thd, SQLCOM_GRANT,
- TYPE_ENUM_PACKAGE)))
- MYSQL_YYABORT;
- }
- | grant_privileges ON PACKAGE_ORACLE_SYM BODY_ORACLE_SYM grant_ident TO_SYM grant_list
- opt_require_clause opt_grant_options
- {
- if (unlikely(Lex->add_grant_command(thd, SQLCOM_GRANT,
- TYPE_ENUM_PACKAGE_BODY)))
- MYSQL_YYABORT;
- }
- | PROXY_SYM ON user TO_SYM grant_list opt_grant_option
- {
- LEX *lex= Lex;
- lex->users_list.push_front ($3);
- lex->sql_command= SQLCOM_GRANT;
- lex->type= TYPE_ENUM_PROXY;
- }
- | grant_role TO_SYM grant_list opt_with_admin_option
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_GRANT_ROLE;
- /* The first role is the one that is granted */
- if (unlikely(Lex->users_list.push_front($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
-
- ;
-
-opt_with_admin:
- /* nothing */ { Lex->definer = 0; }
- | WITH ADMIN_SYM user_or_role { Lex->definer = $3; }
- ;
-
-opt_with_admin_option:
- /* nothing */ { Lex->with_admin_option= false; }
- | WITH ADMIN_SYM OPTION { Lex->with_admin_option= true; }
- ;
-
-role_list:
- grant_role
- {
- if (unlikely(Lex->users_list.push_back($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | role_list ',' grant_role
- {
- if (unlikely(Lex->users_list.push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-current_role:
- CURRENT_ROLE optional_braces
- {
- if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER)))))
- MYSQL_YYABORT;
- $$->user= current_role;
- $$->auth= NULL;
- }
- ;
-
-grant_role:
- ident_or_text
- {
- CHARSET_INFO *cs= system_charset_info;
- /* trim end spaces (as they'll be lost in mysql.user anyway) */
- $1.length= cs->cset->lengthsp(cs, $1.str, $1.length);
- ((char*) $1.str)[$1.length] = '\0';
- if (unlikely($1.length == 0))
- my_yyabort_error((ER_INVALID_ROLE, MYF(0), ""));
- if (unlikely(!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER)))))
- MYSQL_YYABORT;
- $$->user= $1;
- $$->host= empty_clex_str;
- $$->auth= NULL;
-
- if (unlikely(check_string_char_length(&$$->user, ER_USERNAME,
- username_char_length,
- cs, 0)))
- MYSQL_YYABORT;
- }
- | current_role
- ;
-
-opt_table:
- /* Empty */
- | TABLE_SYM
- ;
-
-grant_privileges:
- object_privilege_list {}
- | ALL opt_privileges
- {
- Lex->all_privileges= 1;
- Lex->grant= GLOBAL_ACLS;
- }
- ;
-
-opt_privileges:
- /* empty */
- | PRIVILEGES
- ;
-
-object_privilege_list:
- object_privilege
- | object_privilege_list ',' object_privilege
- ;
-
-object_privilege:
- SELECT_SYM
- { Lex->which_columns = SELECT_ACL;}
- opt_column_list {}
- | INSERT
- { Lex->which_columns = INSERT_ACL;}
- opt_column_list {}
- | UPDATE_SYM
- { Lex->which_columns = UPDATE_ACL; }
- opt_column_list {}
- | REFERENCES
- { Lex->which_columns = REFERENCES_ACL;}
- opt_column_list {}
- | DELETE_SYM { Lex->grant |= DELETE_ACL;}
- | USAGE {}
- | INDEX_SYM { Lex->grant |= INDEX_ACL;}
- | ALTER { Lex->grant |= ALTER_ACL;}
- | CREATE { Lex->grant |= CREATE_ACL;}
- | DROP { Lex->grant |= DROP_ACL;}
- | EXECUTE_SYM { Lex->grant |= EXECUTE_ACL;}
- | RELOAD { Lex->grant |= RELOAD_ACL;}
- | SHUTDOWN { Lex->grant |= SHUTDOWN_ACL;}
- | PROCESS { Lex->grant |= PROCESS_ACL;}
- | FILE_SYM { Lex->grant |= FILE_ACL;}
- | GRANT OPTION { Lex->grant |= GRANT_ACL;}
- | SHOW DATABASES { Lex->grant |= SHOW_DB_ACL;}
- | SUPER_SYM { Lex->grant |= SUPER_ACL;}
- | CREATE TEMPORARY TABLES { Lex->grant |= CREATE_TMP_ACL;}
- | LOCK_SYM TABLES { Lex->grant |= LOCK_TABLES_ACL; }
- | REPLICATION SLAVE { Lex->grant |= REPL_SLAVE_ACL; }
- | REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL; }
- | CREATE VIEW_SYM { Lex->grant |= CREATE_VIEW_ACL; }
- | SHOW VIEW_SYM { Lex->grant |= SHOW_VIEW_ACL; }
- | CREATE ROUTINE_SYM { Lex->grant |= CREATE_PROC_ACL; }
- | ALTER ROUTINE_SYM { Lex->grant |= ALTER_PROC_ACL; }
- | CREATE USER_SYM { Lex->grant |= CREATE_USER_ACL; }
- | EVENT_SYM { Lex->grant |= EVENT_ACL;}
- | TRIGGER_SYM { Lex->grant |= TRIGGER_ACL; }
- | CREATE TABLESPACE { Lex->grant |= CREATE_TABLESPACE_ACL; }
- | DELETE_SYM HISTORY_SYM { Lex->grant |= DELETE_HISTORY_ACL; }
- ;
-
-opt_and:
- /* empty */ {}
- | AND_SYM {}
- ;
-
-require_list:
- require_list_element opt_and require_list
- | require_list_element
- ;
-
-require_list_element:
- SUBJECT_SYM TEXT_STRING
- {
- LEX *lex=Lex;
- if (lex->account_options.x509_subject.str)
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SUBJECT"));
- lex->account_options.x509_subject= $2;
- }
- | ISSUER_SYM TEXT_STRING
- {
- LEX *lex=Lex;
- if (lex->account_options.x509_issuer.str)
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "ISSUER"));
- lex->account_options.x509_issuer= $2;
- }
- | CIPHER_SYM TEXT_STRING
- {
- LEX *lex=Lex;
- if (lex->account_options.ssl_cipher.str)
- my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CIPHER"));
- lex->account_options.ssl_cipher= $2;
- }
- ;
-
-grant_ident:
- '*'
- {
- LEX *lex= Lex;
- if (unlikely(lex->copy_db_to(&lex->current_select->db)))
- MYSQL_YYABORT;
- if (lex->grant == GLOBAL_ACLS)
- lex->grant = DB_ACLS & ~GRANT_ACL;
- else if (unlikely(lex->columns.elements))
- my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
- }
- | ident '.' '*'
- {
- LEX *lex= Lex;
- lex->current_select->db= $1;
- if (lex->grant == GLOBAL_ACLS)
- lex->grant = DB_ACLS & ~GRANT_ACL;
- else if (unlikely(lex->columns.elements))
- my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
- }
- | '*' '.' '*'
- {
- LEX *lex= Lex;
- lex->current_select->db= null_clex_str;
- if (lex->grant == GLOBAL_ACLS)
- lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
- else if (unlikely(lex->columns.elements))
- my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
- }
- | table_ident
- {
- LEX *lex=Lex;
- if (unlikely(!lex->current_select->
- add_table_to_list(thd, $1,NULL,
- TL_OPTION_UPDATING)))
- MYSQL_YYABORT;
- if (lex->grant == GLOBAL_ACLS)
- lex->grant = TABLE_ACLS & ~GRANT_ACL;
- }
- ;
-
-user_list:
- user
- {
- if (unlikely(Lex->users_list.push_back($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | user_list ',' user
- {
- if (unlikely(Lex->users_list.push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-grant_list:
- grant_user
- {
- if (unlikely(Lex->users_list.push_back($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | grant_list ',' grant_user
- {
- if (unlikely(Lex->users_list.push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-user_and_role_list:
- user_or_role
- {
- if (unlikely(Lex->users_list.push_back($1, thd->mem_root)))
- MYSQL_YYABORT;
- }
- | user_and_role_list ',' user_or_role
- {
- if (unlikely(Lex->users_list.push_back($3, thd->mem_root)))
- MYSQL_YYABORT;
- }
- ;
-
-via_or_with: VIA_SYM | WITH ;
-using_or_as: USING | AS ;
-
-grant_user:
- user IDENTIFIED_SYM BY TEXT_STRING
- {
- $$= $1;
- $1->auth= new (thd->mem_root) USER_AUTH();
- $1->auth->pwtext= $4;
- }
- | user IDENTIFIED_SYM BY PASSWORD_SYM TEXT_STRING
- {
- $$= $1;
- $1->auth= new (thd->mem_root) USER_AUTH();
- $1->auth->auth_str= $5;
- }
- | user IDENTIFIED_SYM via_or_with auth_expression
- {
- $$= $1;
- $1->auth= $4;
- }
- | user_or_role
- {
- $$= $1;
- }
- ;
-
-auth_expression:
- auth_token OR_SYM auth_expression
- {
- $$= $1;
- DBUG_ASSERT($$->next == NULL);
- $$->next= $3;
- }
- | auth_token
- {
- $$= $1;
- }
- ;
-
-auth_token:
- ident_or_text opt_auth_str
- {
- $$= $2;
- $$->plugin= $1;
- }
- ;
-
-opt_auth_str:
- /* empty */
- {
- if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH))))
- MYSQL_YYABORT;
- }
- | using_or_as TEXT_STRING_sys
- {
- if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH))))
- MYSQL_YYABORT;
- $$->auth_str= $2;
- }
- | using_or_as PASSWORD_SYM '(' TEXT_STRING ')'
- {
- if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH))))
- MYSQL_YYABORT;
- $$->pwtext= $4;
- }
- ;
-
-opt_column_list:
- /* empty */
- {
- LEX *lex=Lex;
- lex->grant |= lex->which_columns;
- }
- | '(' column_list ')' { }
- ;
-
-column_list:
- column_list ',' column_list_id
- | column_list_id
- ;
-
-column_list_id:
- ident
- {
- String *new_str= new (thd->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
- if (unlikely(new_str == NULL))
- MYSQL_YYABORT;
- List_iterator <LEX_COLUMN> iter(Lex->columns);
- class LEX_COLUMN *point;
- LEX *lex=Lex;
- while ((point=iter++))
- {
- if (!my_strcasecmp(system_charset_info,
- point->column.c_ptr(), new_str->c_ptr()))
- break;
- }
- lex->grant_tot_col|= lex->which_columns;
- if (point)
- point->rights |= lex->which_columns;
- else
- {
- LEX_COLUMN *col= (new (thd->mem_root)
- LEX_COLUMN(*new_str,lex->which_columns));
- if (unlikely(col == NULL))
- MYSQL_YYABORT;
- lex->columns.push_back(col, thd->mem_root);
- }
- }
- ;
-
-opt_require_clause:
- /* empty */
- | REQUIRE_SYM require_list
- {
- Lex->account_options.ssl_type= SSL_TYPE_SPECIFIED;
- }
- | REQUIRE_SYM SSL_SYM
- {
- Lex->account_options.ssl_type= SSL_TYPE_ANY;
- }
- | REQUIRE_SYM X509_SYM
- {
- Lex->account_options.ssl_type= SSL_TYPE_X509;
- }
- | REQUIRE_SYM NONE_SYM
- {
- Lex->account_options.ssl_type= SSL_TYPE_NONE;
- }
- ;
-
-resource_option:
- MAX_QUERIES_PER_HOUR ulong_num
- {
- Lex->account_options.questions=$2;
- Lex->account_options.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR;
- }
- | MAX_UPDATES_PER_HOUR ulong_num
- {
- Lex->account_options.updates=$2;
- Lex->account_options.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR;
- }
- | MAX_CONNECTIONS_PER_HOUR ulong_num
- {
- Lex->account_options.conn_per_hour= $2;
- Lex->account_options.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR;
- }
- | MAX_USER_CONNECTIONS_SYM int_num
- {
- Lex->account_options.user_conn= $2;
- Lex->account_options.specified_limits|= USER_RESOURCES::USER_CONNECTIONS;
- }
- | MAX_STATEMENT_TIME_SYM NUM_literal
- {
- Lex->account_options.max_statement_time= $2->val_real();
- Lex->account_options.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME;
- }
- ;
-
-resource_option_list:
- resource_option_list resource_option {}
- | resource_option {}
- ;
-
-opt_resource_options:
- /* empty */ {}
- | WITH resource_option_list
- ;
-
-
-opt_grant_options:
- /* empty */ {}
- | WITH grant_option_list {}
- ;
-
-opt_grant_option:
- /* empty */ {}
- | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;}
- ;
-
-grant_option_list:
- grant_option_list grant_option {}
- | grant_option {}
- ;
-
-grant_option:
- GRANT OPTION { Lex->grant |= GRANT_ACL;}
- | resource_option {}
- ;
-
-begin_stmt_mariadb:
- BEGIN_MARIADB_SYM
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_BEGIN;
- lex->start_transaction_opt= 0;
- }
- opt_work {}
- ;
-
-compound_statement:
- sp_proc_stmt_compound_ok
- {
- Lex->sql_command= SQLCOM_COMPOUND;
- if (Lex->sp_body_finalize_procedure(thd))
- MYSQL_YYABORT;
- }
- ;
-
-opt_not:
- /* nothing */ { $$= 0; }
- | not { $$= 1; }
- ;
-
-opt_work:
- /* empty */ {}
- | WORK_SYM {}
- ;
-
-opt_chain:
- /* empty */
- { $$= TVL_UNKNOWN; }
- | AND_SYM NO_SYM CHAIN_SYM { $$= TVL_NO; }
- | AND_SYM CHAIN_SYM { $$= TVL_YES; }
- ;
-
-opt_release:
- /* empty */
- { $$= TVL_UNKNOWN; }
- | RELEASE_SYM { $$= TVL_YES; }
- | NO_SYM RELEASE_SYM { $$= TVL_NO; }
- ;
-
-commit:
- COMMIT_SYM opt_work opt_chain opt_release
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_COMMIT;
- /* Don't allow AND CHAIN RELEASE. */
- MYSQL_YYABORT_UNLESS($3 != TVL_YES || $4 != TVL_YES);
- lex->tx_chain= $3;
- lex->tx_release= $4;
- }
- ;
-
-rollback:
- ROLLBACK_SYM opt_work opt_chain opt_release
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_ROLLBACK;
- /* Don't allow AND CHAIN RELEASE. */
- MYSQL_YYABORT_UNLESS($3 != TVL_YES || $4 != TVL_YES);
- lex->tx_chain= $3;
- lex->tx_release= $4;
- }
- | ROLLBACK_SYM opt_work TO_SYM SAVEPOINT_SYM ident
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_ROLLBACK_TO_SAVEPOINT;
- lex->ident= $5;
- }
- | ROLLBACK_SYM opt_work TO_SYM ident
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_ROLLBACK_TO_SAVEPOINT;
- lex->ident= $4;
- }
- ;
-
-savepoint:
- SAVEPOINT_SYM ident
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_SAVEPOINT;
- lex->ident= $2;
- }
- ;
-
-release:
- RELEASE_SYM SAVEPOINT_SYM ident
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_RELEASE_SAVEPOINT;
- lex->ident= $3;
- }
- ;
-
-/*
- UNIONS : glue selects together
-*/
-
-unit_type_decl:
- UNION_SYM union_option
- { $$.unit_type= UNION_TYPE; $$.distinct= $2; }
- | INTERSECT_SYM union_option
- { $$.unit_type= INTERSECT_TYPE; $$.distinct= $2; }
- | EXCEPT_SYM union_option
- { $$.unit_type= EXCEPT_TYPE; $$.distinct= $2; }
- ;
-
-/*
- Start a UNION, for non-top level query expressions.
-*/
-union_option:
- /* empty */ { $$=1; }
- | DISTINCT { $$=1; }
- | ALL { $$=0; }
- ;
-
-query_expression_option:
- STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
- | HIGH_PRIORITY
- {
- YYPS->m_lock_type= TL_READ_HIGH_PRIORITY;
- YYPS->m_mdl_type= MDL_SHARED_READ;
- Select->options|= SELECT_HIGH_PRIORITY;
- }
- | DISTINCT { Select->options|= SELECT_DISTINCT; }
- | UNIQUE_SYM { Select->options|= SELECT_DISTINCT; }
- | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
- | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
- | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; }
- | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; }
- | ALL { Select->options|= SELECT_ALL; }
- ;
-
-/**************************************************************************
-
- DEFINER clause support.
-
-**************************************************************************/
-
-definer_opt:
- no_definer
- | definer
- ;
-
-no_definer:
- /* empty */
- {
- /*
- We have to distinguish missing DEFINER-clause from case when
- CURRENT_USER specified as definer explicitly in order to properly
- handle CREATE TRIGGER statements which come to replication thread
- from older master servers (i.e. to create non-suid trigger in this
- case).
- */
- thd->lex->definer= 0;
- }
- ;
-
-definer:
- DEFINER_SYM '=' user_or_role
- {
- Lex->definer= $3;
- Lex->account_options.reset();
- }
- ;
-
-/**************************************************************************
-
- CREATE VIEW statement parts.
-
-**************************************************************************/
-
-view_algorithm:
- ALGORITHM_SYM '=' UNDEFINED_SYM { $$= DTYPE_ALGORITHM_UNDEFINED; }
- | ALGORITHM_SYM '=' MERGE_SYM { $$= VIEW_ALGORITHM_MERGE; }
- | ALGORITHM_SYM '=' TEMPTABLE_SYM { $$= VIEW_ALGORITHM_TMPTABLE; }
- ;
-
-opt_view_suid:
- /* empty */ { $$= VIEW_SUID_DEFAULT; }
- | view_suid { $$= $1; }
- ;
-
-view_suid:
- SQL_SYM SECURITY_SYM DEFINER_SYM { $$= VIEW_SUID_DEFINER; }
- | SQL_SYM SECURITY_SYM INVOKER_SYM { $$= VIEW_SUID_INVOKER; }
- ;
-
-view_list_opt:
- /* empty */
- {}
- | '(' view_list ')' { }
- ;
-
-view_list:
- ident
- {
- Lex->view_list.push_back((LEX_CSTRING*)
- thd->memdup(&$1, sizeof(LEX_CSTRING)),
- thd->mem_root);
- }
- | view_list ',' ident
- {
- Lex->view_list.push_back((LEX_CSTRING*)
- thd->memdup(&$3, sizeof(LEX_CSTRING)),
- thd->mem_root);
- }
- ;
-
-view_select:
- {
- LEX *lex= Lex;
- lex->parsing_options.allows_variable= FALSE;
- lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr();
- }
- query_expression
- view_check_option
- {
- if (Lex->parsed_create_view($2, $3))
- MYSQL_YYABORT;
- }
- ;
-
-view_check_option:
- /* empty */ { $$= VIEW_CHECK_NONE; }
- | WITH CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; }
- | WITH CASCADED CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; }
- | WITH LOCAL_SYM CHECK_SYM OPTION { $$= VIEW_CHECK_LOCAL; }
- ;
-
-/**************************************************************************
-
- CREATE TRIGGER statement parts.
-
-**************************************************************************/
-
-trigger_action_order:
- FOLLOWS_SYM
- { $$= TRG_ORDER_FOLLOWS; }
- | PRECEDES_SYM
- { $$= TRG_ORDER_PRECEDES; }
- ;
-
-trigger_follows_precedes_clause:
- /* empty */
- {
- $$.ordering_clause= TRG_ORDER_NONE;
- $$.anchor_trigger_name.str= NULL;
- $$.anchor_trigger_name.length= 0;
- }
- |
- trigger_action_order ident_or_text
- {
- $$.ordering_clause= $1;
- $$.anchor_trigger_name= $2;
- }
- ;
-
-trigger_tail:
- remember_name
- opt_if_not_exists
- {
- if (unlikely(Lex->add_create_options_with_check($2)))
- MYSQL_YYABORT;
- }
- sp_name
- trg_action_time
- trg_event
- ON
- remember_name /* $8 */
- { /* $9 */
- Lex->raw_trg_on_table_name_begin= YYLIP->get_tok_start();
- }
- table_ident /* $10 */
- FOR_SYM
- remember_name /* $12 */
- { /* $13 */
- Lex->raw_trg_on_table_name_end= YYLIP->get_tok_start();
- }
- EACH_SYM
- ROW_SYM
- {
- Lex->trg_chistics.ordering_clause_begin= YYLIP->get_cpp_ptr();
- }
- trigger_follows_precedes_clause /* $17 */
- { /* $18 */
- LEX *lex= thd->lex;
- Lex_input_stream *lip= YYLIP;
-
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"));
-
- lex->stmt_definition_begin= $1;
- lex->ident.str= $8;
- lex->ident.length= $12 - $8;
- lex->spname= $4;
- (*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($17);
- lex->trg_chistics.ordering_clause_end= lip->get_cpp_ptr();
-
- if (unlikely(!lex->make_sp_head(thd, $4, &sp_handler_trigger,
- DEFAULT_AGGREGATE)))
- MYSQL_YYABORT;
-
- lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
- }
- sp_proc_stmt /* $19 */
- { /* $20 */
- LEX *lex= Lex;
-
- lex->sql_command= SQLCOM_CREATE_TRIGGER;
- if (lex->sp_body_finalize_trigger(thd))
- MYSQL_YYABORT;
-
- /*
- We have to do it after parsing trigger body, because some of
- sp_proc_stmt alternatives are not saving/restoring LEX, so
- lex->query_tables can be wiped out.
- */
- if (!lex->first_select_lex()->
- add_table_to_list(thd, $10, (LEX_CSTRING*) 0,
- TL_OPTION_UPDATING, TL_READ_NO_INSERT,
- MDL_SHARED_NO_WRITE))
- MYSQL_YYABORT;
- }
- ;
-
-/**************************************************************************
-
- CREATE FUNCTION | PROCEDURE statements parts.
-
-**************************************************************************/
-
-
-sf_return_type:
- {
- LEX *lex= Lex;
- lex->init_last_field(&lex->sphead->m_return_field_def,
- &empty_clex_str,
- thd->variables.collation_database);
- }
- type_with_opt_collate
- {
- if (unlikely(Lex->sf_return_fill_definition($2)))
- MYSQL_YYABORT;
- }
- ;
-
-
-/*************************************************************************/
-
-xa:
- XA_SYM begin_or_start xid opt_join_or_resume
- {
- Lex->sql_command = SQLCOM_XA_START;
- }
- | XA_SYM END xid opt_suspend
- {
- Lex->sql_command = SQLCOM_XA_END;
- }
- | XA_SYM PREPARE_SYM xid
- {
- Lex->sql_command = SQLCOM_XA_PREPARE;
- }
- | XA_SYM COMMIT_SYM xid opt_one_phase
- {
- Lex->sql_command = SQLCOM_XA_COMMIT;
- }
- | XA_SYM ROLLBACK_SYM xid
- {
- Lex->sql_command = SQLCOM_XA_ROLLBACK;
- }
- | XA_SYM RECOVER_SYM opt_format_xid
- {
- Lex->sql_command = SQLCOM_XA_RECOVER;
- Lex->verbose= $3;
- }
- ;
-
-opt_format_xid:
- /* empty */ { $$= false; }
- | FORMAT_SYM '=' ident_or_text
- {
- if (lex_string_eq(&$3, STRING_WITH_LEN("SQL")))
- $$= true;
- else if (lex_string_eq(&$3, STRING_WITH_LEN("RAW")))
- $$= false;
- else
- {
- my_yyabort_error((ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0),
- "XA RECOVER", $3.str));
- $$= false;
- }
- }
- ;
-
-xid:
- text_string
- {
- MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE);
- if (unlikely(!(Lex->xid=(XID *)thd->alloc(sizeof(XID)))))
- MYSQL_YYABORT;
- Lex->xid->set(1L, $1->ptr(), $1->length(), 0, 0);
- }
- | text_string ',' text_string
- {
- MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
- if (unlikely(!(Lex->xid=(XID *)thd->alloc(sizeof(XID)))))
- MYSQL_YYABORT;
- Lex->xid->set(1L, $1->ptr(), $1->length(), $3->ptr(), $3->length());
- }
- | text_string ',' text_string ',' ulong_num
- {
- MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
- if (unlikely(!(Lex->xid=(XID *)thd->alloc(sizeof(XID)))))
- MYSQL_YYABORT;
- Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length());
- }
- ;
-
-begin_or_start:
- BEGIN_MARIADB_SYM {}
- | BEGIN_ORACLE_SYM {}
- | START_SYM {}
- ;
-
-opt_join_or_resume:
- /* nothing */ { Lex->xa_opt=XA_NONE; }
- | JOIN_SYM { Lex->xa_opt=XA_JOIN; }
- | RESUME_SYM { Lex->xa_opt=XA_RESUME; }
- ;
-
-opt_one_phase:
- /* nothing */ { Lex->xa_opt=XA_NONE; }
- | ONE_SYM PHASE_SYM { Lex->xa_opt=XA_ONE_PHASE; }
- ;
-
-opt_suspend:
- /* nothing */
- { Lex->xa_opt=XA_NONE; }
- | SUSPEND_SYM
- { Lex->xa_opt=XA_SUSPEND; }
- opt_migrate
- ;
-
-opt_migrate:
- /* nothing */ {}
- | FOR_SYM MIGRATE_SYM { Lex->xa_opt=XA_FOR_MIGRATE; }
- ;
-
-install:
- INSTALL_SYM PLUGIN_SYM opt_if_not_exists ident SONAME_SYM TEXT_STRING_sys
- {
- if (Lex->stmt_install_plugin($3, $4, $6))
- MYSQL_YYABORT;
- }
- | INSTALL_SYM SONAME_SYM TEXT_STRING_sys
- {
- Lex->stmt_install_plugin($3);
- }
- ;
-
-uninstall:
- UNINSTALL_SYM PLUGIN_SYM opt_if_exists ident
- {
- if (Lex->stmt_uninstall_plugin_by_name($3, $4))
- MYSQL_YYABORT;
- }
- | UNINSTALL_SYM SONAME_SYM opt_if_exists TEXT_STRING_sys
- {
- if (Lex->stmt_uninstall_plugin_by_soname($3, $4))
- MYSQL_YYABORT;
- }
- ;
-
-/* Avoid compiler warning from sql_yacc.cc where yyerrlab1 is not used */
-keep_gcc_happy:
- IMPOSSIBLE_ACTION
- {
- YYERROR;
- }
- ;
-
-/* Start of sql_mode=ORACLE specific rules */
-
-statement:
- verb_clause
- | set_assign
- ;
-
-sp_statement:
- statement
- | ident_cli_directly_assignable
- {
- // Direct procedure call (without the CALL keyword)
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->call_statement_start(thd, &tmp)))
- MYSQL_YYABORT;
- }
- opt_sp_cparam_list
- | ident_cli_directly_assignable '.' ident
- {
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->call_statement_start(thd, &tmp, &$3)))
- MYSQL_YYABORT;
- }
- opt_sp_cparam_list
- ;
-
-sp_if_then_statements:
- sp_proc_stmts1_implicit_block { }
- ;
-
-sp_case_then_statements:
- sp_proc_stmts1_implicit_block { }
- ;
-
-reserved_keyword_udt:
- reserved_keyword_udt_not_param_type
- ;
-
-/* Keywords that start an SP block section. */
-keyword_sp_block_section:
- BEGIN_ORACLE_SYM
- | END
- ;
-
-/*
- Keywords that we allow for labels in SPs.
- Should not include keywords that start a statement or SP characteristics.
-*/
-keyword_label:
- keyword_data_type
- | keyword_set_special_case
- | keyword_sp_var_and_label
- | keyword_sysvar_type
- | FUNCTION_SYM
- | COMPRESSED_SYM
- | EXCEPTION_ORACLE_SYM
- ;
-
-keyword_sp_decl:
- keyword_sp_head
- | keyword_set_special_case
- | keyword_sp_var_and_label
- | keyword_sp_var_not_label
- | keyword_sysvar_type
- | keyword_verb_clause
- | WINDOW_SYM
- ;
-
-opt_truncate_table_storage_clause:
- /* Empty */
- | DROP STORAGE_SYM
- | REUSE_SYM STORAGE_SYM
- ;
-
-
-ident_for_loop_index:
- ident_directly_assignable
- ;
-
-row_field_name:
- ident_directly_assignable
- {
- if (!($$= Lex->row_field_name(thd, $1)))
- MYSQL_YYABORT;
- }
- ;
-
-while_body:
- expr_lex LOOP_SYM
- {
- if (unlikely($1->sp_while_loop_expression(thd)))
- MYSQL_YYABORT;
- }
- sp_proc_stmts1 END LOOP_SYM
- {
- if (unlikely(Lex->sp_while_loop_finalize(thd)))
- MYSQL_YYABORT;
- }
- ;
-
-for_loop_statements:
- LOOP_SYM sp_proc_stmts1 END LOOP_SYM
- { }
- ;
-
-
-sp_control_label:
- labels_declaration_oracle
- ;
-
-sp_block_label:
- labels_declaration_oracle
- {
- if (unlikely(Lex->spcont->block_label_declare(&$1)))
- MYSQL_YYABORT;
- $$= $1;
- }
- ;
-
-
-remember_end_opt:
- {
- if (yychar == YYEMPTY)
- $$= (char*) YYLIP->get_cpp_ptr_rtrim();
- else
- $$= (char*) YYLIP->get_cpp_tok_end_rtrim();
- }
- ;
-
-sp_opt_default:
- /* Empty */ { $$ = NULL; }
- | DEFAULT expr { $$ = $2; }
- | SET_VAR expr { $$ = $2; }
- ;
-
-sp_opt_inout:
- /*Empty*/ { $$= sp_variable::MODE_IN; }
- | sp_parameter_type
- | IN_SYM OUT_SYM { $$= sp_variable::MODE_INOUT; }
- ;
-
-sp_pdparam:
- sp_param_name sp_opt_inout type_with_opt_collate
- {
- $1->mode= $2;
- if (unlikely(Lex->sp_param_fill_definition($1, $3)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $1, $3, $5)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $1, $3, $5, $7)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $1, $3)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $1, $3, $5)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout ROW_SYM row_type_body
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_row(thd, $1, $4)))
- MYSQL_YYABORT;
- }
- ;
-
-
-sp_proc_stmts1_implicit_block:
- {
- Lex->sp_block_init(thd);
- }
- sp_proc_stmts1
- {
- if (unlikely(Lex->sp_block_finalize(thd)))
- MYSQL_YYABORT;
- }
- ;
-
-
-remember_lex:
- {
- $$= thd->lex;
- }
- ;
-
-keyword_directly_assignable:
- keyword_data_type
- | keyword_cast_type
- | keyword_set_special_case
- | keyword_sp_var_and_label
- | keyword_sp_var_not_label
- | keyword_sysvar_type
- | FUNCTION_SYM
- | WINDOW_SYM
- ;
-
-ident_directly_assignable:
- IDENT_sys
- | keyword_directly_assignable
- {
- if (unlikely($$.copy_keyword(thd, &$1)))
- MYSQL_YYABORT;
- }
- ;
-
-ident_cli_directly_assignable:
- IDENT_cli
- | keyword_directly_assignable { $$= $1; }
- ;
-
-
-set_assign:
- ident_cli_directly_assignable SET_VAR
- {
- LEX *lex=Lex;
- lex->set_stmt_init();
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(Lex->set_variable(&tmp, $4)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
- false)))
- MYSQL_YYABORT;
- }
- | ident_cli_directly_assignable '.' ident SET_VAR
- {
- LEX *lex=Lex;
- lex->set_stmt_init();
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- LEX *lex= Lex;
- DBUG_ASSERT(lex->var_list.is_empty());
- Lex_ident_sys tmp(thd, &$1);
- if (unlikely(lex->set_variable(&tmp, &$3, $6)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
- false)))
- MYSQL_YYABORT;
- }
- | COLON_ORACLE_SYM ident '.' ident SET_VAR
- {
- LEX *lex= Lex;
- if (unlikely(!lex->is_trigger_new_or_old_reference(&$2)))
- {
- thd->parse_error(ER_SYNTAX_ERROR, $1.pos());
- MYSQL_YYABORT;
- }
- lex->set_stmt_init();
- if (sp_create_assignment_lex(thd, $1.pos()))
- MYSQL_YYABORT;
- }
- set_expr_or_default
- {
- LEX_CSTRING tmp= { $2.str, $2.length };
- if (unlikely(Lex->set_trigger_field(&tmp, &$4, $7)) ||
- unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY,
- false)))
- MYSQL_YYABORT;
- }
- ;
-
-
-labels_declaration_oracle:
- label_declaration_oracle { $$= $1; }
- | labels_declaration_oracle label_declaration_oracle { $$= $2; }
- ;
-
-label_declaration_oracle:
- SHIFT_LEFT label_ident SHIFT_RIGHT
- {
- if (unlikely(Lex->sp_push_goto_label(thd, &$2)))
- MYSQL_YYABORT;
- $$= $2;
- }
- ;
-
-opt_exception_clause:
- /* Empty */ { $$= 0; }
- | EXCEPTION_ORACLE_SYM exception_handlers { $$= $2; }
- ;
-
-exception_handlers:
- exception_handler { $$= 1; }
- | exception_handlers exception_handler { $$= $1 + 1; }
- ;
-
-exception_handler:
- WHEN_SYM
- {
- if (unlikely(Lex->sp_handler_declaration_init(thd, sp_handler::EXIT)))
- MYSQL_YYABORT;
- }
- sp_hcond_list
- THEN_SYM
- sp_proc_stmts1_implicit_block
- {
- if (unlikely(Lex->sp_handler_declaration_finalize(thd, sp_handler::EXIT)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_no_param:
- /* Empty */
- {
- Lex->sphead->m_param_begin= Lex->sphead->m_param_end=
- YYLIP->get_cpp_tok_start() + 1;
- }
- ;
-
-opt_sp_parenthesized_fdparam_list:
- sp_no_param
- | sp_parenthesized_fdparam_list
- ;
-
-opt_sp_parenthesized_pdparam_list:
- sp_no_param
- | sp_parenthesized_pdparam_list
- ;
-
-
-opt_sp_name:
- /* Empty */ { $$= NULL; }
- | sp_name { $$= $1; }
- ;
-
-
-opt_package_routine_end_name:
- /* Empty */ { $$= null_clex_str; }
- | ident { $$= $1; }
- ;
-
-sp_tail_is:
- IS
- | AS
- ;
-
-sp_instr_addr:
- { $$= Lex->sphead->instructions(); }
- ;
-
-sp_body:
- {
- Lex->sp_block_init(thd);
- }
- opt_sp_decl_body_list
- {
- if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
- MYSQL_YYABORT;
- }
- BEGIN_ORACLE_SYM
- sp_block_statements_and_exceptions
- {
- $2.hndlrs+= $5.hndlrs;
- if (unlikely(Lex->sp_block_finalize(thd, $2)))
- MYSQL_YYABORT;
- }
- END
- ;
-
-create_package_chistic:
- COMMENT_SYM TEXT_STRING_sys
- { Lex->sp_chistics.comment= $2; }
- | sp_suid
- { Lex->sp_chistics.suid= $1; }
- ;
-
-create_package_chistics:
- create_package_chistic {}
- | create_package_chistics create_package_chistic { }
- ;
-
-opt_create_package_chistics:
- /* Empty */
- | create_package_chistics { }
- ;
-
-opt_create_package_chistics_init:
- { Lex->sp_chistics.init(); }
- opt_create_package_chistics
- ;
-
-
-package_implementation_executable_section:
- END
- {
- if (unlikely(Lex->sp_block_with_exceptions_add_empty(thd)))
- MYSQL_YYABORT;
- $$.init(0);
- }
- | BEGIN_ORACLE_SYM sp_block_statements_and_exceptions END { $$= $2; }
- ;
-
-/*
- Inside CREATE PACKAGE BODY, package-wide items (e.g. variables)
- must be declared before routine definitions.
-*/
-package_implementation_declare_section:
- package_implementation_declare_section_list1
- | package_implementation_declare_section_list2
- | package_implementation_declare_section_list1
- package_implementation_declare_section_list2
- { $$.join($1, $2); }
- ;
-
-package_implementation_declare_section_list1:
- package_implementation_item_declaration
- | package_implementation_declare_section_list1
- package_implementation_item_declaration
- { $$.join($1, $2); }
- ;
-
-package_implementation_declare_section_list2:
- package_implementation_routine_definition
- | package_implementation_declare_section_list2
- package_implementation_routine_definition
- { $$.join($1, $2); }
- ;
-
-package_routine_lex:
- {
- if (unlikely(!($$= new (thd->mem_root)
- sp_lex_local(thd, thd->lex))))
- MYSQL_YYABORT;
- thd->m_parser_state->m_yacc.reset_before_substatement();
- }
- ;
-
-
-package_specification_function:
- remember_lex package_routine_lex ident
- {
- DBUG_ASSERT($1->sphead->get_package());
- $2->sql_command= SQLCOM_CREATE_FUNCTION;
- sp_name *spname= $1->make_sp_name_package_routine(thd, &$3);
- if (unlikely(!spname))
- MYSQL_YYABORT;
- thd->lex= $2;
- if (unlikely(!$2->make_sp_head_no_recursive(thd, spname,
- &sp_handler_package_function,
- NOT_AGGREGATE)))
- MYSQL_YYABORT;
- $1->sphead->get_package()->m_current_routine= $2;
- (void) is_native_function_with_warn(thd, &$3);
- }
- opt_sp_parenthesized_fdparam_list
- RETURN_ORACLE_SYM sf_return_type
- sp_c_chistics
- {
- sp_head *sp= thd->lex->sphead;
- sp->restore_thd_mem_root(thd);
- thd->lex= $1;
- $$= $2;
- }
- ;
-
-package_specification_procedure:
- remember_lex package_routine_lex ident
- {
- DBUG_ASSERT($1->sphead->get_package());
- $2->sql_command= SQLCOM_CREATE_PROCEDURE;
- sp_name *spname= $1->make_sp_name_package_routine(thd, &$3);
- if (unlikely(!spname))
- MYSQL_YYABORT;
- thd->lex= $2;
- if (unlikely(!$2->make_sp_head_no_recursive(thd, spname,
- &sp_handler_package_procedure,
- DEFAULT_AGGREGATE)))
- MYSQL_YYABORT;
- $1->sphead->get_package()->m_current_routine= $2;
- }
- opt_sp_parenthesized_pdparam_list
- sp_c_chistics
- {
- sp_head *sp= thd->lex->sphead;
- sp->restore_thd_mem_root(thd);
- thd->lex= $1;
- $$= $2;
- }
- ;
-
-
-package_implementation_routine_definition:
- FUNCTION_SYM package_specification_function
- package_implementation_function_body ';'
- {
- sp_package *pkg= Lex->get_sp_package();
- if (unlikely(pkg->add_routine_implementation($2)))
- MYSQL_YYABORT;
- pkg->m_current_routine= NULL;
- $$.init();
- }
- | PROCEDURE_SYM package_specification_procedure
- package_implementation_procedure_body ';'
- {
- sp_package *pkg= Lex->get_sp_package();
- if (unlikely(pkg->add_routine_implementation($2)))
- MYSQL_YYABORT;
- pkg->m_current_routine= NULL;
- $$.init();
- }
- | package_specification_element { $$.init(); }
- ;
-
-
-package_implementation_function_body:
- sp_tail_is remember_lex
- {
- sp_package *pkg= Lex->get_sp_package();
- sp_head *sp= pkg->m_current_routine->sphead;
- thd->lex= pkg->m_current_routine;
- sp->reset_thd_mem_root(thd);
- sp->set_body_start(thd, YYLIP->get_cpp_tok_start());
- }
- sp_body opt_package_routine_end_name
- {
- if (unlikely(thd->lex->sp_body_finalize_function(thd) ||
- thd->lex->sphead->check_package_routine_end_name($5)))
- MYSQL_YYABORT;
- thd->lex= $2;
- }
- ;
-
-package_implementation_procedure_body:
- sp_tail_is remember_lex
- {
- sp_package *pkg= Lex->get_sp_package();
- sp_head *sp= pkg->m_current_routine->sphead;
- thd->lex= pkg->m_current_routine;
- sp->reset_thd_mem_root(thd);
- sp->set_body_start(thd, YYLIP->get_cpp_tok_start());
- }
- sp_body opt_package_routine_end_name
- {
- if (unlikely(thd->lex->sp_body_finalize_procedure(thd) ||
- thd->lex->sphead->check_package_routine_end_name($5)))
- MYSQL_YYABORT;
- thd->lex= $2;
- }
- ;
-
-
-package_implementation_item_declaration:
- sp_decl_variable_list ';'
- ;
-
-opt_package_specification_element_list:
- /* Empty */
- | package_specification_element_list
- ;
-
-package_specification_element_list:
- package_specification_element
- | package_specification_element_list package_specification_element
- ;
-
-package_specification_element:
- FUNCTION_SYM package_specification_function ';'
- {
- sp_package *pkg= Lex->get_sp_package();
- if (unlikely(pkg->add_routine_declaration($2)))
- MYSQL_YYABORT;
- pkg->m_current_routine= NULL;
- }
- | PROCEDURE_SYM package_specification_procedure ';'
- {
- sp_package *pkg= Lex->get_sp_package();
- if (unlikely(pkg->add_routine_declaration($2)))
- MYSQL_YYABORT;
- pkg->m_current_routine= NULL;
- }
- ;
-
-sp_decl_variable_list_anchored:
- sp_decl_idents_init_vars
- optionally_qualified_column_ident PERCENT_ORACLE_SYM TYPE_SYM
- sp_opt_default
- {
- if (unlikely(Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $2, $5)))
- MYSQL_YYABORT;
- $$.init_using_vars($1);
- }
- | sp_decl_idents_init_vars
- optionally_qualified_column_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
- sp_opt_default
- {
- if (unlikely(Lex->sp_variable_declarations_rowtype_finalize(thd, $1, $2, $5)))
- MYSQL_YYABORT;
- $$.init_using_vars($1);
- }
- ;
-
-sp_param_name_and_type_anchored:
- sp_param_name sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
- {
- if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $2, $4)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
- {
- if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $2, $4, $6)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
- {
- if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $2)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
- {
- if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $2, $4)))
- MYSQL_YYABORT;
- }
- ;
-
-
-sf_c_chistics_and_body_standalone:
- sp_c_chistics
- {
- LEX *lex= thd->lex;
- lex->sphead->set_c_chistics(lex->sp_chistics);
- lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
- }
- sp_tail_is
- sp_body
- {
- if (unlikely(Lex->sp_body_finalize_function(thd)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_tail_standalone:
- sp_name
- {
- if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1,
- &sp_handler_procedure,
- DEFAULT_AGGREGATE)))
- MYSQL_YYABORT;
- }
- opt_sp_parenthesized_pdparam_list
- sp_c_chistics
- {
- Lex->sphead->set_c_chistics(Lex->sp_chistics);
- Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
- }
- sp_tail_is
- sp_body
- opt_sp_name
- {
- if (unlikely(Lex->sp_body_finalize_procedure_standalone(thd, $8)))
- MYSQL_YYABORT;
- }
- ;
-
-drop_routine:
- DROP FUNCTION_SYM opt_if_exists ident '.' ident
- {
- if (Lex->stmt_drop_function($3, $4, $6))
- MYSQL_YYABORT;
- }
- | DROP FUNCTION_SYM opt_if_exists ident
- {
- if (Lex->stmt_drop_function($3, $4))
- MYSQL_YYABORT;
- }
- | DROP PROCEDURE_SYM opt_if_exists sp_name
- {
- if (Lex->stmt_drop_procedure($3, $4))
- MYSQL_YYABORT;
- }
- | DROP PACKAGE_ORACLE_SYM opt_if_exists sp_name
- {
- LEX *lex= Lex;
- lex->set_command(SQLCOM_DROP_PACKAGE, $3);
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PACKAGE"));
- lex->spname= $4;
- }
- | DROP PACKAGE_ORACLE_SYM BODY_ORACLE_SYM opt_if_exists sp_name
- {
- LEX *lex= Lex;
- lex->set_command(SQLCOM_DROP_PACKAGE_BODY, $4);
- if (unlikely(lex->sphead))
- my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PACKAGE BODY"));
- lex->spname= $5;
- }
- ;
-
-
-create_routine:
- create_or_replace definer_opt PROCEDURE_SYM opt_if_not_exists
- {
- if (Lex->stmt_create_procedure_start($1 | $4))
- MYSQL_YYABORT;
- }
- sp_tail_standalone
- {
- Lex->stmt_create_routine_finalize();
- }
- | create_or_replace definer opt_aggregate FUNCTION_SYM opt_if_not_exists
- sp_name
- {
- if (Lex->stmt_create_stored_function_start($1 | $5, $3, $6))
- MYSQL_YYABORT;
- }
- opt_sp_parenthesized_fdparam_list
- RETURN_ORACLE_SYM sf_return_type
- sf_c_chistics_and_body_standalone
- opt_sp_name
- {
- if (Lex->stmt_create_stored_function_finalize_standalone($12))
- MYSQL_YYABORT;
- }
- | create_or_replace no_definer opt_aggregate FUNCTION_SYM opt_if_not_exists
- sp_name
- {
- if (Lex->stmt_create_stored_function_start($1 | $5, $3, $6))
- MYSQL_YYABORT;
- }
- opt_sp_parenthesized_fdparam_list
- RETURN_ORACLE_SYM sf_return_type
- sf_c_chistics_and_body_standalone
- opt_sp_name
- {
- if (Lex->stmt_create_stored_function_finalize_standalone($12))
- MYSQL_YYABORT;
- }
- | create_or_replace no_definer opt_aggregate FUNCTION_SYM opt_if_not_exists
- ident RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
- {
- if (Lex->stmt_create_udf_function($1 | $5, $3, $6,
- (Item_result) $8, $10))
- MYSQL_YYABORT;
- }
- | create_or_replace definer_opt PACKAGE_ORACLE_SYM
- opt_if_not_exists sp_name opt_create_package_chistics_init
- sp_tail_is
- remember_name
- {
- sp_package *pkg;
- if (unlikely(!(pkg= Lex->
- create_package_start(thd,
- SQLCOM_CREATE_PACKAGE,
- &sp_handler_package_spec,
- $5, $1 | $4))))
- MYSQL_YYABORT;
- pkg->set_c_chistics(Lex->sp_chistics);
- }
- opt_package_specification_element_list END
- remember_end_opt opt_sp_name
- {
- if (unlikely(Lex->create_package_finalize(thd, $5, $13, $8, $12)))
- MYSQL_YYABORT;
- }
- | create_or_replace definer_opt PACKAGE_ORACLE_SYM BODY_ORACLE_SYM
- opt_if_not_exists sp_name opt_create_package_chistics_init
- sp_tail_is
- remember_name
- {
- sp_package *pkg;
- if (unlikely(!(pkg= Lex->
- create_package_start(thd,
- SQLCOM_CREATE_PACKAGE_BODY,
- &sp_handler_package_body,
- $6, $1 | $5))))
- MYSQL_YYABORT;
- pkg->set_c_chistics(Lex->sp_chistics);
- Lex->sp_block_init(thd);
- }
- package_implementation_declare_section
- {
- if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
- MYSQL_YYABORT;
- }
- package_implementation_executable_section
- {
- $11.hndlrs+= $13.hndlrs;
- if (unlikely(Lex->sp_block_finalize(thd, $11)))
- MYSQL_YYABORT;
- }
- remember_end_opt opt_sp_name
- {
- if (unlikely(Lex->create_package_finalize(thd, $6, $16, $9, $15)))
- MYSQL_YYABORT;
- }
- ;
-
-opt_sp_decl_body_list:
- /* Empty */
- {
- $$.init();
- }
- | sp_decl_body_list { $$= $1; }
- ;
-
-sp_decl_body_list:
- sp_decl_non_handler_list
- {
- if (unlikely(Lex->sphead->sp_add_instr_cpush_for_cursors(thd, Lex->spcont)))
- MYSQL_YYABORT;
- }
- opt_sp_decl_handler_list
- {
- $$.join($1, $3);
- }
- | sp_decl_handler_list
- ;
-
-sp_decl_non_handler_list:
- sp_decl_non_handler ';' { $$= $1; }
- | sp_decl_non_handler_list sp_decl_non_handler ';'
- {
- $$.join($1, $2);
- }
- ;
-
-sp_decl_handler_list:
- sp_decl_handler ';' { $$= $1; }
- | sp_decl_handler_list sp_decl_handler ';'
- {
- $$.join($1, $2);
- }
- ;
-
-opt_sp_decl_handler_list:
- /* Empty*/ { $$.init(); }
- | sp_decl_handler_list
- ;
-
-sp_decl_non_handler:
- sp_decl_variable_list
- | ident_directly_assignable CONDITION_SYM FOR_SYM sp_cond
- {
- if (unlikely(Lex->spcont->declare_condition(thd, &$1, $4)))
- MYSQL_YYABORT;
- $$.vars= $$.hndlrs= $$.curs= 0;
- $$.conds= 1;
- }
- | ident_directly_assignable EXCEPTION_ORACLE_SYM
- {
- sp_condition_value *spcond= new (thd->mem_root)
- sp_condition_value_user_defined();
- if (unlikely(!spcond) ||
- unlikely(Lex->spcont->declare_condition(thd, &$1, spcond)))
- MYSQL_YYABORT;
- $$.vars= $$.hndlrs= $$.curs= 0;
- $$.conds= 1;
- }
- | CURSOR_SYM ident_directly_assignable
- {
- Lex->sp_block_init(thd);
- }
- opt_parenthesized_cursor_formal_parameters
- IS sp_cursor_stmt
- {
- sp_pcontext *param_ctx= Lex->spcont;
- if (unlikely(Lex->sp_block_finalize(thd)))
- MYSQL_YYABORT;
- if (unlikely(Lex->sp_declare_cursor(thd, &$2, $6, param_ctx, false)))
- MYSQL_YYABORT;
- $$.vars= $$.conds= $$.hndlrs= 0;
- $$.curs= 1;
- }
- ;
-
-
-sp_proc_stmt:
- sp_labeled_block
- | sp_unlabeled_block
- | sp_labeled_control
- | sp_unlabeled_control
- | sp_labelable_stmt
- | labels_declaration_oracle sp_labelable_stmt {}
- ;
-
-sp_labelable_stmt:
- sp_proc_stmt_statement
- | sp_proc_stmt_continue_oracle
- | sp_proc_stmt_exit_oracle
- | sp_proc_stmt_leave
- | sp_proc_stmt_iterate
- | sp_proc_stmt_goto_oracle
- | sp_proc_stmt_with_cursor
- | sp_proc_stmt_return
- | sp_proc_stmt_if
- | case_stmt_specification
- | NULL_SYM { }
- ;
-
-sp_proc_stmt_compound_ok:
- sp_proc_stmt_if
- | case_stmt_specification
- | sp_unlabeled_block
- | sp_unlabeled_control
- ;
-
-
-sp_labeled_block:
- sp_block_label
- BEGIN_ORACLE_SYM
- {
- Lex->sp_block_init(thd, &$1);
- if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
- MYSQL_YYABORT;
- }
- sp_block_statements_and_exceptions
- END
- sp_opt_label
- {
- if (unlikely(Lex->sp_block_finalize(thd, Lex_spblock($4), &$6)))
- MYSQL_YYABORT;
- }
- | sp_block_label
- DECLARE_ORACLE_SYM
- {
- Lex->sp_block_init(thd, &$1);
- }
- sp_decl_body_list
- {
- if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
- MYSQL_YYABORT;
- }
- BEGIN_ORACLE_SYM
- sp_block_statements_and_exceptions
- END
- sp_opt_label
- {
- $4.hndlrs+= $7.hndlrs;
- if (unlikely(Lex->sp_block_finalize(thd, $4, &$9)))
- MYSQL_YYABORT;
- }
- ;
-
-opt_not_atomic:
- /* Empty */
- | not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */
- ;
-
-sp_unlabeled_block:
- BEGIN_ORACLE_SYM opt_not_atomic
- {
- if (unlikely(Lex->maybe_start_compound_statement(thd)))
- MYSQL_YYABORT;
- Lex->sp_block_init(thd);
- if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
- MYSQL_YYABORT;
- }
- sp_block_statements_and_exceptions
- END
- {
- if (unlikely(Lex->sp_block_finalize(thd, Lex_spblock($4))))
- MYSQL_YYABORT;
- }
- | DECLARE_ORACLE_SYM
- {
- if (unlikely(Lex->maybe_start_compound_statement(thd)))
- MYSQL_YYABORT;
- Lex->sp_block_init(thd);
- }
- sp_decl_body_list
- {
- if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd)))
- MYSQL_YYABORT;
- }
- BEGIN_ORACLE_SYM
- sp_block_statements_and_exceptions
- END
- {
- $3.hndlrs+= $6.hndlrs;
- if (unlikely(Lex->sp_block_finalize(thd, $3)))
- MYSQL_YYABORT;
- }
- ;
-
-sp_block_statements_and_exceptions:
- sp_instr_addr
- sp_proc_stmts
- {
- if (unlikely(Lex->sp_block_with_exceptions_finalize_executable_section(thd, $1)))
- MYSQL_YYABORT;
- }
- opt_exception_clause
- {
- if (unlikely(Lex->sp_block_with_exceptions_finalize_exceptions(thd, $1, $4)))
- MYSQL_YYABORT;
- $$.init($4);
- }
- ;
-
-/* End of sql_mode=ORACLE specific rules */
-
-/**
- @} (end of group Parser)
-*/
diff --git a/sql/table.cc b/sql/table.cc
index 2b1bb16ef24..d56981ce114 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -5249,6 +5249,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
check_unique_buf= NULL;
vers_write= s->versioned;
quick_condition_rows=0;
+ no_cache= false;
initialize_quick_structures();
#ifdef HAVE_REPLICATION
/* used in RBR Triggers */
@@ -7168,12 +7169,8 @@ void TABLE::mark_columns_needed_for_update()
/*
For System Versioning we have to read all columns since we store
a copy of previous row with modified row_end back to a table.
-
- Without write_set versioning.rpl,row is unstable until MDEV-16370 is
- applied.
*/
bitmap_union(read_set, &s->all_set);
- bitmap_union(write_set, &s->all_set);
need_signal= true;
}
if (check_constraints)
@@ -7336,8 +7333,16 @@ void TABLE::mark_columns_per_binlog_row_image()
binary log will include all columns read anyway.
*/
mark_columns_used_by_index_no_reset(s->primary_key, read_set);
- /* Only write columns that have changed */
- rpl_write_set= write_set;
+ if (versioned())
+ {
+ // TODO: After MDEV-18432 we don't pass history rows, so remove this:
+ rpl_write_set= &s->all_set;
+ }
+ else
+ {
+ /* Only write columns that have changed */
+ rpl_write_set= write_set;
+ }
break;
default:
diff --git a/sql/table.h b/sql/table.h
index 0c6917e7b62..5391177f625 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -326,7 +326,7 @@ typedef struct st_grant_info
enum tmp_table_type
{
- NO_TMP_TABLE, NON_TRANSACTIONAL_TMP_TABLE, TRANSACTIONAL_TMP_TABLE,
+ NO_TMP_TABLE= 0, NON_TRANSACTIONAL_TMP_TABLE, TRANSACTIONAL_TMP_TABLE,
INTERNAL_TMP_TABLE, SYSTEM_TMP_TABLE
};
enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP };
@@ -1595,9 +1595,16 @@ public:
return s->versioned == type;
}
- bool versioned_write(vers_kind_t type= VERS_UNDEFINED) const
+ bool versioned_write() const
{
DBUG_ASSERT(versioned() || !vers_write);
+ return versioned() ? vers_write : false;
+ }
+
+ bool versioned_write(vers_kind_t type) const
+ {
+ DBUG_ASSERT(type);
+ DBUG_ASSERT(versioned() || !vers_write);
return versioned(type) ? vers_write : false;
}
@@ -1620,6 +1627,8 @@ public:
int period_make_insert(Item *src, Field *dst);
int insert_portion_of_time(THD *thd, const vers_select_conds_t &period_conds,
ha_rows *rows_inserted);
+ bool vers_check_update(List<Item> &items);
+
int delete_row();
void vers_update_fields();
void vers_update_end();
@@ -1858,6 +1867,7 @@ public:
struct vers_select_conds_t
{
vers_system_time_t type;
+ vers_system_time_t orig_type;
bool used:1;
bool delete_history:1;
Vers_history_point start;
@@ -1872,6 +1882,7 @@ struct vers_select_conds_t
void empty()
{
type= SYSTEM_TIME_UNSPECIFIED;
+ orig_type= SYSTEM_TIME_UNSPECIFIED;
used= false;
delete_history= false;
start.empty();
@@ -1884,6 +1895,7 @@ struct vers_select_conds_t
Lex_ident _name= "SYSTEM_TIME")
{
type= _type;
+ orig_type= _type;
used= false;
delete_history= (type == SYSTEM_TIME_HISTORY ||
type == SYSTEM_TIME_BEFORE);
@@ -1892,6 +1904,12 @@ struct vers_select_conds_t
name= _name;
}
+ void set_all()
+ {
+ type= SYSTEM_TIME_ALL;
+ name= "SYSTEM_TIME";
+ }
+
void print(String *str, enum_query_type query_type) const;
bool init_from_sysvar(THD *thd);
@@ -1901,6 +1919,10 @@ struct vers_select_conds_t
return type != SYSTEM_TIME_UNSPECIFIED;
}
bool check_units(THD *thd);
+ bool was_set() const
+ {
+ return orig_type != SYSTEM_TIME_UNSPECIFIED;
+ }
bool eq(const vers_select_conds_t &conds) const;
};
diff --git a/sql/vers_utils.h b/sql/vers_utils.h
deleted file mode 100644
index 2bea191da9e..00000000000
--- a/sql/vers_utils.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef VERS_UTILS_INCLUDED
-#define VERS_UTILS_INCLUDED
-
-#include "table.h"
-#include "sql_class.h"
-#include "vers_string.h"
-
-#endif // VERS_UTILS_INCLUDED
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 8738d5ecbdf..49c9a28dac8 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -268,8 +268,7 @@ btr_root_get(
/* Intended to be used for segment list access.
SX lock doesn't block reading user data by other threads.
And block the segment list access by others.*/
- buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH,
- mtr);
+ buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
return(root ? buf_block_get_frame(root) : NULL);
}
@@ -442,22 +441,25 @@ btr_page_create(
page_t* page = buf_block_get_frame(block);
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ byte *index_id= &page[PAGE_HEADER + PAGE_INDEX_ID];
- if (page_zip) {
+ if (UNIV_LIKELY_NULL(page_zip)) {
page_create_zip(block, index, level, 0, mtr);
+ mach_write_to_8(index_id, index->id);
+ page_zip_write_header(page_zip, index_id, 8, mtr);
} else {
page_create(block, mtr, dict_table_is_comp(index->table),
dict_index_is_spatial(index));
/* Set the level of the new index page */
- btr_page_set_level(page, NULL, level, mtr);
+ mtr->write<2,mtr_t::OPT>(*block, PAGE_HEADER + PAGE_LEVEL
+ + block->frame, level);
+ mtr->write<8,mtr_t::OPT>(*block, index_id, index->id);
}
/* For Spatial Index, initialize the Split Sequence Number */
if (dict_index_is_spatial(index)) {
page_set_ssn_id(block, page_zip, 0, mtr);
}
-
- btr_page_set_index_id(page, page_zip, index->id, mtr);
}
/**************************************************************//**
@@ -471,15 +473,13 @@ btr_page_alloc_for_ibuf(
dict_index_t* index, /*!< in: index tree */
mtr_t* mtr) /*!< in: mtr */
{
- fil_addr_t node_addr;
- page_t* root;
- page_t* new_page;
buf_block_t* new_block;
- root = btr_root_get(index, mtr);
+ buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
- node_addr = flst_get_first(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST
- + root);
+ fil_addr_t node_addr = flst_get_first(PAGE_HEADER
+ + PAGE_BTR_IBUF_FREE_LIST
+ + root->frame);
ut_a(node_addr.page != FIL_NULL);
new_block = buf_page_get(
@@ -487,14 +487,12 @@ btr_page_alloc_for_ibuf(
index->table->space->zip_size(),
RW_X_LATCH, mtr);
- new_page = buf_block_get_frame(new_block);
buf_block_dbg_add_level(new_block, SYNC_IBUF_TREE_NODE_NEW);
- flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
+ flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
+ new_block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
mtr);
- ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- mtr));
+ ut_d(flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
return(new_block);
}
@@ -525,16 +523,12 @@ btr_page_alloc_low(
is already X-latched in mtr, do
not initialize the page. */
{
- fseg_header_t* seg_header;
- page_t* root;
+ page_t* root = btr_root_get(index, mtr);
- root = btr_root_get(index, mtr);
-
- if (level == 0) {
- seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
- } else {
- seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
- }
+ fseg_header_t* seg_header = (level
+ ? PAGE_HEADER + PAGE_BTR_SEG_TOP
+ : PAGE_HEADER + PAGE_BTR_SEG_LEAF)
+ + root;
/* Parameter TRUE below states that the caller has made the
reservation for free extents, and thus we know that a page can
@@ -613,42 +607,35 @@ btr_get_size(
mtr_t* mtr) /*!< in/out: mini-transaction where index
is s-latched */
{
- fseg_header_t* seg_header;
- page_t* root;
ulint n=0;
- ulint dummy;
ut_ad(srv_read_only_mode
|| mtr_memo_contains(mtr, dict_index_get_lock(index),
MTR_MEMO_S_LOCK));
+ ut_ad(flag == BTR_N_LEAF_PAGES || flag == BTR_TOTAL_SIZE);
if (index->page == FIL_NULL
|| dict_index_is_online_ddl(index)
- || !index->is_committed()) {
+ || !index->is_committed()
+ || !index->table->space) {
return(ULINT_UNDEFINED);
}
- root = btr_root_get(index, mtr);
-
- if (root) {
- if (flag == BTR_N_LEAF_PAGES) {
- seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
-
- fseg_n_reserved_pages(seg_header, &n, mtr);
-
- } else if (flag == BTR_TOTAL_SIZE) {
- seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
-
- n = fseg_n_reserved_pages(seg_header, &dummy, mtr);
-
- seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
-
- n += fseg_n_reserved_pages(seg_header, &dummy, mtr);
- } else {
- ut_error;
- }
+ buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
+ if (!root) {
+ return ULINT_UNDEFINED;
+ }
+ mtr_x_lock_space(index->table->space, mtr);
+ if (flag == BTR_N_LEAF_PAGES) {
+ fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF
+ + root->frame, &n, mtr);
} else {
- n = ULINT_UNDEFINED;
+ ulint dummy;
+ n = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_TOP
+ + root->frame, &dummy, mtr);
+ n += fseg_n_reserved_pages(*root,
+ PAGE_HEADER + PAGE_BTR_SEG_LEAF
+ + root->frame, &dummy, mtr);
}
return(n);
@@ -668,9 +655,6 @@ btr_get_size_and_reserved(
mtr_t* mtr) /*!< in/out: mini-transaction where index
is s-latched */
{
- fseg_header_t* seg_header;
- page_t* root;
- ulint n=ULINT_UNDEFINED;
ulint dummy;
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
@@ -680,26 +664,26 @@ btr_get_size_and_reserved(
if (index->page == FIL_NULL
|| dict_index_is_online_ddl(index)
- || !index->is_committed()) {
+ || !index->is_committed()
+ || !index->table->space) {
return(ULINT_UNDEFINED);
}
- root = btr_root_get(index, mtr);
+ buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
*used = 0;
+ if (!root) {
+ return ULINT_UNDEFINED;
+ }
- if (root) {
-
- seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
-
- n = fseg_n_reserved_pages(seg_header, used, mtr);
-
- if (flag == BTR_TOTAL_SIZE) {
- seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
-
- n += fseg_n_reserved_pages(seg_header, &dummy, mtr);
- *used += dummy;
+ mtr_x_lock_space(index->table->space, mtr);
- }
+ ulint n = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF
+ + root->frame, used, mtr);
+ if (flag == BTR_TOTAL_SIZE) {
+ n += fseg_n_reserved_pages(*root,
+ PAGE_HEADER + PAGE_BTR_SEG_TOP
+ + root->frame, &dummy, mtr);
+ *used += dummy;
}
return(n);
@@ -716,17 +700,14 @@ btr_page_free_for_ibuf(
buf_block_t* block, /*!< in: block to be freed, x-latched */
mtr_t* mtr) /*!< in: mtr */
{
- page_t* root;
-
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- root = btr_root_get(index, mtr);
- flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- buf_block_get_frame(block)
- + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
+ buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
- ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- mtr));
+ flst_add_first(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
+ block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
+
+ ut_d(flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
}
/** Free an index page.
@@ -779,39 +760,29 @@ void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
srv_immediate_scrub_data_uncompressed is set. */
}
-/**************************************************************//**
+/** Set the child page number in a node pointer record.
+@param[in,out] block non-leaf index page
+@param[in,out] rec node pointer record in the page
+@param[in] offsets rec_get_offsets(rec)
+@param[in] page_no child page number
+@param[in,out] mtr mini-transaction
Sets the child node file address in a node pointer. */
-UNIV_INLINE
-void
-btr_node_ptr_set_child_page_no(
-/*===========================*/
- rec_t* rec, /*!< in: node pointer record */
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
- part will be updated, or NULL */
- const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
- ulint page_no,/*!< in: child node address */
- mtr_t* mtr) /*!< in: mtr */
+inline void btr_node_ptr_set_child_page_no(buf_block_t *block,
+ rec_t *rec, const ulint *offsets,
+ ulint page_no, mtr_t *mtr)
{
- byte* field;
- ulint len;
-
- ut_ad(rec_offs_validate(rec, NULL, offsets));
- ut_ad(!page_rec_is_leaf(rec));
- ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
-
- /* The child address is in the last field */
- field = rec_get_nth_field(rec, offsets,
- rec_offs_n_fields(offsets) - 1, &len);
-
- ut_ad(len == REC_NODE_PTR_SIZE);
-
- if (page_zip) {
- page_zip_write_node_ptr(page_zip, rec,
- rec_offs_data_size(offsets),
- page_no, mtr);
- } else {
- mlog_write_ulint(field, page_no, MLOG_4BYTES, mtr);
- }
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(!page_rec_is_leaf(rec));
+ ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
+
+ const ulint offs= rec_offs_data_size(offsets);
+ ut_ad(rec_offs_nth_size(offsets, rec_offs_n_fields(offsets) - 1) ==
+ REC_NODE_PTR_SIZE);
+
+ if (UNIV_LIKELY_NULL(block->page.zip.data))
+ page_zip_write_node_ptr(&block->page.zip, rec, offs, page_no, mtr);
+ else
+ mtr->write<4>(*block, rec + offs - REC_NODE_PTR_SIZE, page_no);
}
/************************************************************//**
@@ -986,7 +957,7 @@ void btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
}
/** PAGE_INDEX_ID value for freed index B-trees */
-static const index_id_t BTR_FREED_INDEX_ID = 0;
+constexpr index_id_t BTR_FREED_INDEX_ID = 0;
/** Free a B-tree root page. btr_free_but_not_root() must already
have been called.
@@ -995,30 +966,33 @@ before mtr.commit().
@param[in,out] block index root page
@param[in,out] mtr mini-transaction
@param[in] invalidate whether to invalidate PAGE_INDEX_ID */
-static void btr_free_root(buf_block_t* block, mtr_t* mtr, bool invalidate)
+static void btr_free_root(buf_block_t *block, mtr_t *mtr, bool invalidate)
{
- fseg_header_t* header;
-
- ut_ad(mtr_memo_contains_flagged(mtr, block, MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr->is_named_space(block->page.id.space()));
+ ut_ad(mtr_memo_contains_flagged(mtr, block,
+ MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mtr->is_named_space(block->page.id.space()));
- btr_search_drop_page_hash_index(block);
+ btr_search_drop_page_hash_index(block);
- header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP;
#ifdef UNIV_BTR_DEBUG
- ut_a(btr_root_fseg_validate(header, block->page.id.space()));
+ ut_a(btr_root_fseg_validate(PAGE_HEADER + PAGE_BTR_SEG_TOP + block->frame,
+ block->page.id.space()));
#endif /* UNIV_BTR_DEBUG */
- if (invalidate) {
- btr_page_set_index_id(
- buf_block_get_frame(block),
- buf_block_get_page_zip(block),
- BTR_FREED_INDEX_ID, mtr);
- }
-
- while (!fseg_free_step(header, true, mtr)) {
- /* Free the entire segment in small steps. */
- }
+ if (invalidate)
+ {
+ byte *page_index_id= PAGE_HEADER + PAGE_INDEX_ID + block->frame;
+ if (UNIV_LIKELY_NULL(block->page.zip.data))
+ {
+ mach_write_to_8(page_index_id, BTR_FREED_INDEX_ID);
+ page_zip_write_header(&block->page.zip, page_index_id, 8, mtr);
+ }
+ else
+ mtr->write<8,mtr_t::OPT>(*block, page_index_id, BTR_FREED_INDEX_ID);
+ }
+
+ /* Free the entire segment in small steps. */
+ while (!fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_TOP + block->frame,
+ true, mtr));
}
/** Prepare to free a B-tree.
@@ -1076,8 +1050,6 @@ btr_create(
mtr_t* mtr)
{
buf_block_t* block;
- page_t* page;
- page_zip_des_t* page_zip;
ut_ad(mtr->is_named_space(space));
ut_ad(index_id != BTR_FREED_INDEX_ID);
@@ -1144,30 +1116,29 @@ btr_create(
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
}
- /* Create a new index page on the allocated segment page */
- page_zip = buf_block_get_page_zip(block);
+ byte* page_index_id = PAGE_HEADER + PAGE_INDEX_ID + block->frame;
- if (page_zip) {
- page = page_create_zip(block, index, 0, 0, mtr);
+ /* Create a new index page on the allocated segment page */
+ if (UNIV_LIKELY_NULL(block->page.zip.data)) {
+ page_create_zip(block, index, 0, 0, mtr);
+ mach_write_to_8(page_index_id, index_id);
+ page_zip_write_header(&block->page.zip, page_index_id, 8, mtr);
+ static_assert(FIL_PAGE_PREV % 8 == 0, "alignment");
+ memset_aligned<8>(FIL_PAGE_PREV + block->page.zip.data,
+ 0xff, 8);
} else {
- page = page_create(block, mtr,
- dict_table_is_comp(index->table),
- dict_index_is_spatial(index));
+ page_create(block, mtr, index->table->not_redundant(),
+ index->is_spatial());
/* Set the level of the new index page */
- btr_page_set_level(page, NULL, 0, mtr);
+ mtr->write<2,mtr_t::OPT>(*block, PAGE_HEADER + PAGE_LEVEL
+ + block->frame, 0U);
+ mtr->write<8,mtr_t::OPT>(*block, page_index_id, index_id);
}
- /* Set the index id of the page */
- btr_page_set_index_id(page, page_zip, index_id, mtr);
-
/* Set the next node and previous node fields */
compile_time_assert(FIL_PAGE_NEXT == FIL_PAGE_PREV + 4);
compile_time_assert(FIL_NULL == 0xffffffff);
- mlog_memset(block, FIL_PAGE_PREV, 8, 0xff, mtr);
- if (UNIV_LIKELY_NULL(page_zip)) {
- static_assert(FIL_PAGE_PREV % 8 == 0, "alignment");
- memset_aligned<8>(FIL_PAGE_PREV + page_zip->data, 0xff, 8);
- }
+ mtr->memset(block, FIL_PAGE_PREV, 8, 0xff);
/* We reset the free bits for the page in a separate
mini-transaction to allow creation of several trees in the
@@ -1184,7 +1155,8 @@ btr_create(
allowed size fit on the root page: this fact is needed to ensure
correctness of split algorithms */
- ut_ad(page_get_max_insert_size(page, 2) > 2 * BTR_PAGE_MAX_REC_SIZE);
+ ut_ad(page_get_max_insert_size(block->frame, 2)
+ > 2 * BTR_PAGE_MAX_REC_SIZE);
return(block->page.id.page_no());
}
@@ -1199,7 +1171,6 @@ btr_free_but_not_root(
buf_block_t* block,
mtr_log_t log_mode)
{
- ibool finished;
mtr_t mtr;
ut_ad(fil_page_index_page_check(block->frame));
@@ -1226,8 +1197,8 @@ leaf_loop:
/* NOTE: page hash indexes are dropped when a page is freed inside
fsp0fsp. */
- finished = fseg_free_step(root + PAGE_HEADER + PAGE_BTR_SEG_LEAF,
- true, &mtr);
+ bool finished = fseg_free_step(root + PAGE_HEADER + PAGE_BTR_SEG_LEAF,
+ true, &mtr);
mtr_commit(&mtr);
if (!finished) {
@@ -1390,7 +1361,7 @@ btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset)
page_set_autoinc(buf_page_get(page_id_t(space->id, index->page),
space->zip_size(),
RW_SX_LATCH, &mtr),
- index, autoinc, &mtr, reset);
+ autoinc, &mtr, reset);
mtr.commit();
}
@@ -1424,7 +1395,6 @@ btr_page_reorganize_low(
page_t* page = buf_block_get_frame(block);
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
buf_block_t* temp_block;
- page_t* temp_page;
ulint data_size1;
ulint data_size2;
ulint max_ins_size1;
@@ -1451,7 +1421,6 @@ btr_page_reorganize_low(
mtr_log_t log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
temp_block = buf_block_alloc(buf_pool);
- temp_page = temp_block->frame;
MONITOR_INC(MONITOR_INDEX_REORG_ATTEMPTS);
@@ -1461,7 +1430,8 @@ btr_page_reorganize_low(
|| dict_index_is_spatial(index));
/* Copy the old page to temporary space */
- buf_frame_copy(temp_page, page);
+ memcpy_aligned<UNIV_PAGE_SIZE_MIN>(temp_block->frame, block->frame,
+ srv_page_size);
if (!recovery) {
btr_search_drop_page_hash_index(block);
@@ -1479,12 +1449,14 @@ btr_page_reorganize_low(
do not copy the lock bits yet */
page_copy_rec_list_end_no_locks(block, temp_block,
- page_get_infimum_rec(temp_page),
+ page_get_infimum_rec(temp_block->frame),
index, mtr);
/* Copy the PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC. */
- memcpy(page + (PAGE_HEADER + PAGE_MAX_TRX_ID),
- temp_page + (PAGE_HEADER + PAGE_MAX_TRX_ID), 8);
+ static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment");
+ memcpy_aligned<8>(&block->frame[PAGE_HEADER + PAGE_MAX_TRX_ID],
+ &temp_block->frame[PAGE_HEADER + PAGE_MAX_TRX_ID],
+ 8);
/* PAGE_MAX_TRX_ID is unused in clustered index pages
(other than the root where it is repurposed as PAGE_ROOT_AUTO_INC),
non-leaf pages, and in temporary tables. It was always
@@ -1495,15 +1467,15 @@ btr_page_reorganize_low(
During redo log apply, dict_index_is_sec_or_ibuf() always
holds, even for clustered indexes. */
ut_ad(recovery || index->table->is_temporary()
- || !page_is_leaf(temp_page)
+ || !page_is_leaf(temp_block->frame)
|| !dict_index_is_sec_or_ibuf(index)
- || page_get_max_trx_id(page) != 0);
+ || page_get_max_trx_id(block->frame) != 0);
/* PAGE_MAX_TRX_ID must be zero on non-leaf pages other than
clustered index root pages. */
ut_ad(recovery
- || page_get_max_trx_id(page) == 0
+ || page_get_max_trx_id(block->frame) == 0
|| (dict_index_is_sec_or_ibuf(index)
- ? page_is_leaf(temp_page)
+ ? page_is_leaf(temp_block->frame)
: block->page.id.page_no() == index->page));
/* If innodb_log_compressed_pages is ON, page reorganize should log the
@@ -1520,29 +1492,32 @@ btr_page_reorganize_low(
/* Restore the old page and exit. */
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
/* Check that the bytes that we skip are identical. */
- ut_a(!memcmp(page, temp_page, PAGE_HEADER));
- ut_a(!memcmp(PAGE_HEADER + PAGE_N_RECS + page,
- PAGE_HEADER + PAGE_N_RECS + temp_page,
+ ut_a(!memcmp(page, temp_block->frame, PAGE_HEADER));
+ ut_a(!memcmp(PAGE_HEADER + PAGE_N_RECS + block->frame,
+ PAGE_HEADER + PAGE_N_RECS + temp_block->frame,
PAGE_DATA - (PAGE_HEADER + PAGE_N_RECS)));
- ut_a(!memcmp(srv_page_size - FIL_PAGE_DATA_END + page,
- srv_page_size - FIL_PAGE_DATA_END + temp_page,
- FIL_PAGE_DATA_END));
+ ut_a(!memcmp(srv_page_size - FIL_PAGE_DATA_END
+ + block->frame,
+ srv_page_size - FIL_PAGE_DATA_END
+ + temp_block->frame, FIL_PAGE_DATA_END));
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
- memcpy(PAGE_HEADER + page, PAGE_HEADER + temp_page,
- PAGE_N_RECS - PAGE_N_DIR_SLOTS);
- memcpy(PAGE_DATA + page, PAGE_DATA + temp_page,
+ memcpy_aligned<2>(PAGE_HEADER + block->frame,
+ PAGE_HEADER + temp_block->frame,
+ PAGE_N_RECS - PAGE_N_DIR_SLOTS);
+ memcpy(PAGE_DATA + block->frame, PAGE_DATA + temp_block->frame,
srv_page_size - PAGE_DATA - FIL_PAGE_DATA_END);
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
- ut_a(!memcmp(page, temp_page, srv_page_size));
+ ut_a(!memcmp(block->frame, temp_block->frame, srv_page_size));
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
goto func_exit;
}
- data_size2 = page_get_data_size(page);
- max_ins_size2 = page_get_max_insert_size_after_reorganize(page, 1);
+ data_size2 = page_get_data_size(block->frame);
+ max_ins_size2 = page_get_max_insert_size_after_reorganize(block->frame,
+ 1);
if (data_size1 != data_size2 || max_ins_size1 != max_ins_size2) {
ib::error()
@@ -1559,39 +1534,41 @@ btr_page_reorganize_low(
/* Restore the cursor position. */
if (pos > 0) {
- cursor->rec = page_rec_get_nth(page, pos);
+ cursor->rec = page_rec_get_nth(block->frame, pos);
} else {
- ut_ad(cursor->rec == page_get_infimum_rec(page));
+ ut_ad(cursor->rec == page_get_infimum_rec(block->frame));
}
#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page, index));
+ ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */
if (!recovery) {
if (block->page.id.page_no() == index->page
- && fil_page_get_type(temp_page) == FIL_PAGE_TYPE_INSTANT) {
+ && fil_page_get_type(temp_block->frame)
+ == FIL_PAGE_TYPE_INSTANT) {
/* Preserve the PAGE_INSTANT information. */
ut_ad(!page_zip);
ut_ad(index->is_instant());
static_assert(!(FIL_PAGE_TYPE % 2), "alignment");
- memcpy_aligned<2>(FIL_PAGE_TYPE + page,
- FIL_PAGE_TYPE + temp_page, 2);
+ memcpy_aligned<2>(FIL_PAGE_TYPE + block->frame,
+ FIL_PAGE_TYPE + temp_block->frame, 2);
static_assert(!((PAGE_HEADER+PAGE_INSTANT) % 2), "");
- memcpy_aligned<2>(PAGE_HEADER + PAGE_INSTANT + page,
+ memcpy_aligned<2>(PAGE_HEADER + PAGE_INSTANT
+ + block->frame,
PAGE_HEADER + PAGE_INSTANT
- + temp_page, 2);
+ + temp_block->frame, 2);
if (!index->table->instant) {
- } else if (page_is_comp(page)) {
- memcpy(PAGE_NEW_INFIMUM + page,
- PAGE_NEW_INFIMUM + temp_page, 8);
- memcpy(PAGE_NEW_SUPREMUM + page,
- PAGE_NEW_SUPREMUM + temp_page, 8);
+ } else if (page_is_comp(block->frame)) {
+ memcpy(PAGE_NEW_INFIMUM + block->frame,
+ PAGE_NEW_INFIMUM + temp_block->frame, 8);
+ memcpy(PAGE_NEW_SUPREMUM + block->frame,
+ PAGE_NEW_SUPREMUM + temp_block->frame, 8);
} else {
- memcpy(PAGE_OLD_INFIMUM + page,
- PAGE_OLD_INFIMUM + temp_page, 8);
- memcpy(PAGE_OLD_SUPREMUM + page,
- PAGE_OLD_SUPREMUM + temp_page, 8);
+ memcpy(PAGE_OLD_INFIMUM + block->frame,
+ PAGE_OLD_INFIMUM + temp_block->frame, 8);
+ memcpy(PAGE_OLD_SUPREMUM + block->frame,
+ PAGE_OLD_SUPREMUM + temp_block->frame, 8);
}
}
@@ -1636,24 +1613,25 @@ func_exit:
MONITOR_INC(MONITOR_INDEX_REORG_SUCCESSFUL);
}
- if (UNIV_UNLIKELY(fil_page_get_type(page) == FIL_PAGE_TYPE_INSTANT)) {
+ if (UNIV_UNLIKELY(fil_page_get_type(block->frame)
+ == FIL_PAGE_TYPE_INSTANT)) {
/* Log the PAGE_INSTANT information. */
ut_ad(!page_zip);
ut_ad(index->is_instant());
ut_ad(!recovery);
- mlog_write_ulint(FIL_PAGE_TYPE + page, FIL_PAGE_TYPE_INSTANT,
- MLOG_2BYTES, mtr);
- mlog_write_ulint(PAGE_HEADER + PAGE_INSTANT + page,
- mach_read_from_2(PAGE_HEADER + PAGE_INSTANT
- + page),
- MLOG_2BYTES, mtr);
+ mtr->write<2,mtr_t::FORCED>(*block, FIL_PAGE_TYPE
+ + block->frame,
+ FIL_PAGE_TYPE_INSTANT);
+ byte* instant = PAGE_HEADER + PAGE_INSTANT + block->frame;
+ mtr->write<2,mtr_t::FORCED>(*block, instant,
+ mach_read_from_2(instant));
if (!index->table->instant) {
- } else if (page_is_comp(page)) {
- mlog_log_string(PAGE_NEW_INFIMUM + page, 8, mtr);
- mlog_log_string(PAGE_NEW_SUPREMUM + page, 8, mtr);
+ } else if (page_is_comp(block->frame)) {
+ mtr->memcpy(*block, PAGE_NEW_INFIMUM, 8);
+ mtr->memcpy(*block, PAGE_NEW_SUPREMUM, 8);
} else {
- mlog_log_string(PAGE_OLD_INFIMUM + page, 8, mtr);
- mlog_log_string(PAGE_OLD_SUPREMUM + page, 8, mtr);
+ mtr->memcpy(*block, PAGE_OLD_INFIMUM, 8);
+ mtr->memcpy(*block, PAGE_OLD_SUPREMUM, 8);
}
}
@@ -1769,14 +1747,12 @@ btr_page_empty(
ulint level,
mtr_t* mtr)
{
- page_t* page = buf_block_get_frame(block);
-
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
ut_ad(page_zip == buf_block_get_page_zip(block));
ut_ad(!index->is_dummy);
ut_ad(index->table->space->id == block->page.id.space());
#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page, index));
+ ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */
btr_search_drop_page_hash_index(block);
@@ -1789,7 +1765,7 @@ btr_page_empty(
const ib_uint64_t autoinc
= dict_index_is_clust(index)
&& index->page == block->page.id.page_no()
- ? page_get_autoinc(page)
+ ? page_get_autoinc(block->frame)
: 0;
if (page_zip) {
@@ -1797,10 +1773,11 @@ btr_page_empty(
} else {
page_create(block, mtr, dict_table_is_comp(index->table),
dict_index_is_spatial(index));
- btr_page_set_level(page, NULL, level, mtr);
+ mtr->write<2,mtr_t::OPT>(*block, PAGE_HEADER + PAGE_LEVEL
+ + block->frame, level);
if (autoinc) {
- mlog_write_ull(PAGE_HEADER + PAGE_MAX_TRX_ID + page,
- autoinc, mtr);
+ mtr->write<8>(*block, PAGE_HEADER + PAGE_MAX_TRX_ID
+ + block->frame, autoinc);
}
}
}
@@ -1847,20 +1824,19 @@ void btr_set_instant(buf_block_t* root, const dict_index_t& index, mtr_t* mtr)
|| !page_get_instant(root->frame));
ut_ad(!memcmp(infimum, "infimum", 8));
ut_ad(!memcmp(supremum, "supremum", 8));
- mlog_write_ulint(page_type, FIL_PAGE_TYPE_INSTANT,
- MLOG_2BYTES, mtr);
+ mtr->write<2>(*root, page_type, FIL_PAGE_TYPE_INSTANT);
ut_ad(i <= PAGE_NO_DIRECTION);
i |= index.n_core_fields << 3;
- mlog_write_ulint(PAGE_HEADER + PAGE_INSTANT + root->frame, i,
- MLOG_2BYTES, mtr);
+ mtr->write<2>(*root, PAGE_HEADER + PAGE_INSTANT + root->frame,
+ i);
break;
}
if (index.table->instant) {
- mlog_memset(root, infimum - root->frame, 8, 0, mtr);
- mlog_memset(root, supremum - root->frame, 7, 0, mtr);
- mlog_write_ulint(&supremum[7], index.n_core_null_bytes,
- MLOG_1BYTE, mtr);
+ mtr->memset(root, infimum - root->frame, 8, 0);
+ mtr->memset(root, supremum - root->frame, 7, 0);
+ mtr->write<1,mtr_t::OPT>(*root, &supremum[7],
+ index.n_core_null_bytes);
}
}
@@ -1886,8 +1862,6 @@ btr_root_raise_and_insert(
mtr_t* mtr) /*!< in: mtr */
{
dict_index_t* index;
- page_t* root;
- page_t* new_page;
ulint new_page_no;
rec_t* rec;
dtuple_t* node_ptr;
@@ -1896,40 +1870,40 @@ btr_root_raise_and_insert(
page_cur_t* page_cursor;
page_zip_des_t* root_page_zip;
page_zip_des_t* new_page_zip;
- buf_block_t* root_block;
+ buf_block_t* root;
buf_block_t* new_block;
- root = btr_cur_get_page(cursor);
- root_block = btr_cur_get_block(cursor);
- root_page_zip = buf_block_get_page_zip(root_block);
- ut_ad(!page_is_empty(root));
+ root = btr_cur_get_block(cursor);
+ root_page_zip = buf_block_get_page_zip(root);
+ ut_ad(!page_is_empty(root->frame));
index = btr_cur_get_index(cursor);
ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable));
#ifdef UNIV_ZIP_DEBUG
- ut_a(!root_page_zip || page_zip_validate(root_page_zip, root, index));
+ ut_a(!root_page_zip || page_zip_validate(root_page_zip, root->frame,
+ index));
#endif /* UNIV_ZIP_DEBUG */
#ifdef UNIV_BTR_DEBUG
if (!dict_index_is_ibuf(index)) {
ulint space = index->table->space_id;
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
- + root, space));
+ + root->frame, space));
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
- + root, space));
+ + root->frame, space));
}
- ut_a(dict_index_get_page(index) == page_get_page_no(root));
+ ut_a(dict_index_get_page(index) == root->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */
ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
- ut_ad(mtr_memo_contains(mtr, root_block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains(mtr, root, MTR_MEMO_PAGE_X_FIX));
/* Allocate a new page to the tree. Root splitting is done by first
moving the root records to the new page, emptying the root, putting
a node pointer to the new page, and then splitting the new page. */
- level = btr_page_get_level(root);
+ level = btr_page_get_level(root->frame);
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
@@ -1937,7 +1911,6 @@ btr_root_raise_and_insert(
return(NULL);
}
- new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
ut_a(!new_page_zip == !root_page_zip);
ut_a(!new_page_zip
@@ -1947,12 +1920,17 @@ btr_root_raise_and_insert(
btr_page_create(new_block, new_page_zip, index, level, mtr);
/* Set the next node and previous node fields of new page */
- compile_time_assert(FIL_PAGE_NEXT == FIL_PAGE_PREV + 4);
- compile_time_assert(FIL_NULL == 0xffffffff);
- mlog_memset(new_block, FIL_PAGE_PREV, 8, 0xff, mtr);
- if (UNIV_LIKELY_NULL(new_page_zip)) {
- static_assert(FIL_PAGE_PREV % 8 == 0, "alignment");
- memset_aligned<8>(new_page_zip->data + FIL_PAGE_PREV, 0xff, 8);
+ if (!page_has_siblings(new_block->frame)) {
+ ut_ad(index->is_ibuf());
+ } else {
+ compile_time_assert(FIL_PAGE_NEXT == FIL_PAGE_PREV + 4);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+ mtr->memset(new_block, FIL_PAGE_PREV, 8, 0xff);
+ if (UNIV_LIKELY_NULL(new_page_zip)) {
+ static_assert(FIL_PAGE_PREV % 8 == 0, "alignment");
+ memset_aligned<8>(new_page_zip->data + FIL_PAGE_PREV,
+ 0xff, 8);
+ }
}
/* Copy the records from root to the new page one by one. */
@@ -1961,25 +1939,25 @@ btr_root_raise_and_insert(
#ifdef UNIV_ZIP_COPY
|| new_page_zip
#endif /* UNIV_ZIP_COPY */
- || !page_copy_rec_list_end(new_block, root_block,
- page_get_infimum_rec(root),
+ || !page_copy_rec_list_end(new_block, root,
+ page_get_infimum_rec(root->frame),
index, mtr)) {
ut_a(new_page_zip);
/* Copy the page byte for byte. */
page_zip_copy_recs(new_block,
- root_page_zip, root, index, mtr);
+ root_page_zip, root->frame, index, mtr);
/* Update the lock table and possible hash index. */
- lock_move_rec_list_end(new_block, root_block,
- page_get_infimum_rec(root));
+ lock_move_rec_list_end(new_block, root,
+ page_get_infimum_rec(root->frame));
/* Move any existing predicate locks */
if (dict_index_is_spatial(index)) {
- lock_prdt_rec_move(new_block, root_block);
+ lock_prdt_rec_move(new_block, root);
} else {
btr_search_move_or_delete_hash_entries(
- new_block, root_block);
+ new_block, root);
}
}
@@ -1989,25 +1967,28 @@ btr_root_raise_and_insert(
the field only matters on leaf pages, and the root no
longer is a leaf page. (Older versions of InnoDB did
set PAGE_MAX_TRX_ID on all secondary index pages.) */
- if (root_page_zip) {
- byte* p = PAGE_HEADER + PAGE_MAX_TRX_ID + root;
- memset(p, 0, 8);
+ byte* p = static_cast<byte*>(
+ MY_ASSUME_ALIGNED(PAGE_HEADER + PAGE_MAX_TRX_ID
+ + root->frame, 8));
+ if (UNIV_LIKELY_NULL(root_page_zip)) {
+ memset_aligned<8>(p, 0, 8);
page_zip_write_header(root_page_zip, p, 8, mtr);
- } else {
- mlog_write_ull(PAGE_HEADER + PAGE_MAX_TRX_ID
- + root, 0, mtr);
+ } else if (mach_read_from_8(p)) {
+ mtr->memset(root, PAGE_HEADER + PAGE_MAX_TRX_ID, 8, 0);
}
} else {
/* PAGE_ROOT_AUTO_INC is only present in the clustered index
root page; on other clustered index pages, we want to reserve
the field PAGE_MAX_TRX_ID for future use. */
- if (new_page_zip) {
- byte* p = PAGE_HEADER + PAGE_MAX_TRX_ID + new_page;
- memset(p, 0, 8);
+ byte* p = static_cast<byte*>(
+ MY_ASSUME_ALIGNED(PAGE_HEADER + PAGE_MAX_TRX_ID
+ + new_block->frame, 8));
+ if (UNIV_LIKELY_NULL(new_page_zip)) {
+ memset_aligned<8>(p, 0, 8);
page_zip_write_header(new_page_zip, p, 8, mtr);
- } else {
- mlog_write_ull(PAGE_HEADER + PAGE_MAX_TRX_ID
- + new_page, 0, mtr);
+ } else if (mach_read_from_8(p)) {
+ mtr->memset(new_block, PAGE_HEADER + PAGE_MAX_TRX_ID,
+ 8, 0);
}
}
@@ -2017,7 +1998,7 @@ btr_root_raise_and_insert(
root page: we cannot discard the lock structs on the root page */
if (!dict_table_is_locking_disabled(index->table)) {
- lock_update_root_raise(new_block, root_block);
+ lock_update_root_raise(new_block, root);
}
/* Create a memory heap where the node pointer is stored */
@@ -2025,7 +2006,7 @@ btr_root_raise_and_insert(
*heap = mem_heap_create(1000);
}
- rec = page_rec_get_next(page_get_infimum_rec(new_page));
+ rec = page_rec_get_next(page_get_infimum_rec(new_block->frame));
new_page_no = new_block->page.id.page_no();
/* Build the node pointer (= node key and page address) for the
@@ -2048,28 +2029,28 @@ btr_root_raise_and_insert(
| REC_INFO_MIN_REC_FLAG);
/* Rebuild the root page to get free space */
- btr_page_empty(root_block, root_page_zip, index, level + 1, mtr);
+ btr_page_empty(root, root_page_zip, index, level + 1, mtr);
/* btr_page_empty() is supposed to zero-initialize the field. */
- ut_ad(!page_get_instant(root_block->frame));
+ ut_ad(!page_get_instant(root->frame));
if (index->is_instant()) {
ut_ad(!root_page_zip);
- btr_set_instant(root_block, *index, mtr);
+ btr_set_instant(root, *index, mtr);
}
- ut_ad(!page_has_siblings(root));
+ ut_ad(!page_has_siblings(root->frame));
page_cursor = btr_cur_get_page_cur(cursor);
/* Insert node pointer to the root */
- page_cur_set_before_first(root_block, page_cursor);
+ page_cur_set_before_first(root, page_cursor);
node_ptr_rec = page_cur_tuple_insert(page_cursor, node_ptr,
index, offsets, heap, 0, mtr);
/* The root page should only contain the node pointer
- to new_page at this point. Thus, the data should fit. */
+ to new_block at this point. Thus, the data should fit. */
ut_a(node_ptr_rec);
/* We play safe and reset the free bits for the new page */
@@ -2503,19 +2484,12 @@ btr_attach_half_pages(
ulint direction, /*!< in: FSP_UP or FSP_DOWN */
mtr_t* mtr) /*!< in: mtr */
{
- ulint prev_page_no;
- ulint next_page_no;
- page_t* page = buf_block_get_frame(block);
- page_t* lower_page;
- page_t* upper_page;
- ulint lower_page_no;
- ulint upper_page_no;
- page_zip_des_t* lower_page_zip;
- page_zip_des_t* upper_page_zip;
dtuple_t* node_ptr_upper;
mem_heap_t* heap;
buf_block_t* prev_block = NULL;
buf_block_t* next_block = NULL;
+ buf_block_t* lower_block;
+ buf_block_t* upper_block;
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr_memo_contains(mtr, new_block, MTR_MEMO_PAGE_X_FIX));
@@ -2529,12 +2503,8 @@ btr_attach_half_pages(
btr_cur_t cursor;
ulint* offsets;
- lower_page = buf_block_get_frame(new_block);
- lower_page_no = new_block->page.id.page_no();
- lower_page_zip = buf_block_get_page_zip(new_block);
- upper_page = buf_block_get_frame(block);
- upper_page_no = block->page.id.page_no();
- upper_page_zip = buf_block_get_page_zip(block);
+ lower_block = new_block;
+ upper_block = block;
/* Look up the index for the node pointer to page */
offsets = btr_page_get_father_block(NULL, heap, index,
@@ -2544,17 +2514,13 @@ btr_attach_half_pages(
address of the new lower half */
btr_node_ptr_set_child_page_no(
+ btr_cur_get_block(&cursor),
btr_cur_get_rec(&cursor),
- btr_cur_get_page_zip(&cursor),
- offsets, lower_page_no, mtr);
+ offsets, lower_block->page.id.page_no(), mtr);
mem_heap_empty(heap);
} else {
- lower_page = buf_block_get_frame(block);
- lower_page_no = block->page.id.page_no();
- lower_page_zip = buf_block_get_page_zip(block);
- upper_page = buf_block_get_frame(new_block);
- upper_page_no = new_block->page.id.page_no();
- upper_page_zip = buf_block_get_page_zip(new_block);
+ lower_block = block;
+ upper_block = new_block;
}
/* Get the level of the split pages */
@@ -2562,8 +2528,8 @@ btr_attach_half_pages(
ut_ad(level == btr_page_get_level(buf_block_get_frame(new_block)));
/* Get the previous and next pages of page */
- prev_page_no = btr_page_get_prev(page);
- next_page_no = btr_page_get_next(page);
+ const uint32_t prev_page_no = btr_page_get_prev(block->frame);
+ const uint32_t next_page_no = btr_page_get_next(block->frame);
/* for consistency, both blocks should be locked, before change */
if (prev_page_no != FIL_NULL && direction == FSP_DOWN) {
@@ -2578,8 +2544,8 @@ btr_attach_half_pages(
/* Build the node pointer (= node key and page address) for the upper
half */
- node_ptr_upper = dict_index_build_node_ptr(index, split_rec,
- upper_page_no, heap, level);
+ node_ptr_upper = dict_index_build_node_ptr(
+ index, split_rec, upper_block->page.id.page_no(), heap, level);
/* Insert it next to the pointer to the lower half. Note that this
may generate recursion leading to a split on the higher level. */
@@ -2594,45 +2560,59 @@ btr_attach_half_pages(
if (prev_block) {
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(prev_block->frame) == page_is_comp(page));
+ ut_a(page_is_comp(prev_block->frame)
+ == page_is_comp(block->frame));
ut_a(btr_page_get_next(prev_block->frame)
== block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */
-
- btr_page_set_next(buf_block_get_frame(prev_block),
- buf_block_get_page_zip(prev_block),
- lower_page_no, mtr);
+ btr_page_set_next(prev_block, lower_block->page.id.page_no(),
+ mtr);
}
if (next_block) {
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
+ ut_a(page_is_comp(next_block->frame)
+ == page_is_comp(block->frame));
ut_a(btr_page_get_prev(next_block->frame)
- == page_get_page_no(page));
+ == block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */
-
- btr_page_set_prev(buf_block_get_frame(next_block),
- buf_block_get_page_zip(next_block),
- upper_page_no, mtr);
+ btr_page_set_prev(next_block, upper_block->page.id.page_no(),
+ mtr);
}
if (direction == FSP_DOWN) {
- /* lower_page is new */
- btr_page_set_prev(lower_page, lower_page_zip,
- prev_page_no, mtr);
+ ut_ad(lower_block == new_block);
+ ut_ad(btr_page_get_next(upper_block->frame) == next_page_no);
+ if (UNIV_UNLIKELY(btr_page_get_prev(lower_block->frame)
+ == prev_page_no)) {
+ ut_ad(index->is_ibuf());
+ } else {
+ btr_page_set_prev(lower_block, prev_page_no, mtr);
+ }
} else {
- ut_ad(btr_page_get_prev(lower_page) == prev_page_no);
+ ut_ad(upper_block == new_block);
+ ut_ad(btr_page_get_prev(lower_block->frame) == prev_page_no);
+ if (UNIV_UNLIKELY(btr_page_get_next(upper_block->frame)
+ == next_page_no)) {
+ ut_ad(index->is_ibuf());
+ } else {
+ btr_page_set_next(upper_block, next_page_no, mtr);
+ }
}
- btr_page_set_next(lower_page, lower_page_zip, upper_page_no, mtr);
- btr_page_set_prev(upper_page, upper_page_zip, lower_page_no, mtr);
-
- if (direction != FSP_DOWN) {
- /* upper_page is new */
- btr_page_set_next(upper_page, upper_page_zip,
- next_page_no, mtr);
+ if (UNIV_UNLIKELY(btr_page_get_next(lower_block->frame)
+ == upper_block->page.id.page_no())) {
+ ut_ad(index->is_ibuf());
+ } else {
+ btr_page_set_next(lower_block, upper_block->page.id.page_no(),
+ mtr);
+ }
+ if (UNIV_UNLIKELY(btr_page_get_prev(upper_block->frame)
+ == lower_block->page.id.page_no())) {
+ ut_ad(index->is_ibuf());
} else {
- ut_ad(btr_page_get_next(upper_page) == next_page_no);
+ btr_page_set_prev(upper_block, lower_block->page.id.page_no(),
+ mtr);
}
}
@@ -3226,60 +3206,34 @@ void btr_level_list_remove(const buf_block_t& block, const dict_index_t& index,
buf_block_t* prev_block = btr_block_get(
index, prev_page_no, RW_X_LATCH, page_is_leaf(page),
mtr);
- page_t* prev_page
- = buf_block_get_frame(prev_block);
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(prev_page) == page_is_comp(page));
+ ut_a(page_is_comp(prev_block->frame) == page_is_comp(page));
static_assert(FIL_PAGE_NEXT % 4 == 0, "alignment");
static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
- ut_a(!memcmp_aligned<4>(prev_page + FIL_PAGE_NEXT,
+ ut_a(!memcmp_aligned<4>(prev_block->frame + FIL_PAGE_NEXT,
page + FIL_PAGE_OFFSET, 4));
#endif /* UNIV_BTR_DEBUG */
- btr_page_set_next(prev_page,
- buf_block_get_page_zip(prev_block),
- next_page_no, mtr);
+ btr_page_set_next(prev_block, next_page_no, mtr);
}
if (next_page_no != FIL_NULL) {
buf_block_t* next_block = btr_block_get(
index, next_page_no, RW_X_LATCH, page_is_leaf(page),
mtr);
- page_t* next_page
- = buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(next_page) == page_is_comp(page));
+ ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
static_assert(FIL_PAGE_PREV % 4 == 0, "alignment");
static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
- ut_a(!memcmp_aligned<4>(next_page + FIL_PAGE_PREV,
+ ut_a(!memcmp_aligned<4>(next_block->frame + FIL_PAGE_PREV,
page + FIL_PAGE_OFFSET, 4));
#endif /* UNIV_BTR_DEBUG */
- btr_page_set_prev(next_page,
- buf_block_get_page_zip(next_block),
- prev_page_no, mtr);
+ btr_page_set_prev(next_block, prev_page_no, mtr);
}
}
/****************************************************************//**
-Writes the redo log record for setting an index record as the predefined
-minimum record. */
-UNIV_INLINE
-void
-btr_set_min_rec_mark_log(
-/*=====================*/
- rec_t* rec, /*!< in: record */
- mlog_id_t type, /*!< in: MLOG_COMP_REC_MIN_MARK or
- MLOG_REC_MIN_MARK */
- mtr_t* mtr) /*!< in: mtr */
-{
- mlog_write_initial_log_record(rec, type, mtr);
-
- /* Write rec offset as a 2-byte ulint */
- mlog_catenate_ulint(mtr, page_offset(rec), MLOG_2BYTES);
-}
-
-/****************************************************************//**
Parses the redo log record for setting an index record as the predefined
minimum record.
@return end of log record or NULL */
@@ -3289,7 +3243,7 @@ btr_parse_set_min_rec_mark(
const byte* ptr, /*!< in: buffer */
const byte* end_ptr,/*!< in: buffer end */
ulint comp, /*!< in: nonzero=compact page format */
- page_t* page, /*!< in: page or NULL */
+ buf_block_t* block, /*!< in: page or NULL */
mtr_t* mtr) /*!< in: mtr or NULL */
{
rec_t* rec;
@@ -3299,39 +3253,17 @@ btr_parse_set_min_rec_mark(
return(NULL);
}
- if (page) {
- ut_a(!page_is_comp(page) == !comp);
+ if (block) {
+ ut_a(!page_is_comp(block->frame) == !comp);
- rec = page + mach_read_from_2(ptr);
+ rec = block->frame + mach_read_from_2(ptr);
- btr_set_min_rec_mark(rec, mtr);
+ btr_set_min_rec_mark(rec, *block, mtr);
}
return(ptr + 2);
}
-/** Sets a record as the predefined minimum record. */
-void btr_set_min_rec_mark(rec_t* rec, mtr_t* mtr)
-{
- const bool comp = page_rec_is_comp(rec);
-
- ut_ad(rec == page_rec_get_next_const(page_get_infimum_rec(
- page_align(rec))));
- ut_ad(!(rec_get_info_bits(page_rec_get_next(rec), comp)
- & REC_INFO_MIN_REC_FLAG));
-
- size_t info_bits = rec_get_info_bits(rec, comp);
- if (comp) {
- rec_set_info_bits_new(rec, info_bits | REC_INFO_MIN_REC_FLAG);
-
- btr_set_min_rec_mark_log(rec, MLOG_COMP_REC_MIN_MARK, mtr);
- } else {
- rec_set_info_bits_old(rec, info_bits | REC_INFO_MIN_REC_FLAG);
-
- btr_set_min_rec_mark_log(rec, MLOG_REC_MIN_MARK, mtr);
- }
-}
-
/*************************************************************//**
If page is the only on its level, this function moves its records to the
father page, thus reducing the tree height.
@@ -3495,15 +3427,8 @@ btr_lift_page_up(
/* Go upward to root page, decrementing levels by one. */
for (i = lift_father_up ? 1 : 0; i < n_blocks; i++, page_level++) {
- page_t* page = buf_block_get_frame(blocks[i]);
- page_zip_des_t* page_zip= buf_block_get_page_zip(blocks[i]);
-
- ut_ad(btr_page_get_level(page) == page_level + 1);
-
- btr_page_set_level(page, page_zip, page_level, mtr);
-#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page, index));
-#endif /* UNIV_ZIP_DEBUG */
+ ut_ad(btr_page_get_level(blocks[i]->frame) == page_level + 1);
+ btr_page_set_level(blocks[i], page_level, mtr);
}
if (dict_index_is_spatial(index)) {
@@ -3877,8 +3802,8 @@ retry:
/* Replace the address of the old child node (= page) with the
address of the merge page to the right */
btr_node_ptr_set_child_page_no(
+ btr_cur_get_block(&father_cursor),
btr_cur_get_rec(&father_cursor),
- btr_cur_get_page_zip(&father_cursor),
offsets, right_page_no, mtr);
#ifdef UNIV_DEBUG
@@ -4180,10 +4105,7 @@ btr_discard_page(
ulint left_page_no;
ulint right_page_no;
buf_block_t* merge_block;
- page_t* merge_page;
buf_block_t* block;
- page_t* page;
- rec_t* node_ptr;
btr_cur_t parent_cursor;
block = btr_cur_get_block(cursor);
@@ -4206,16 +4128,15 @@ btr_discard_page(
/* Decide the page which will inherit the locks */
- left_page_no = btr_page_get_prev(buf_block_get_frame(block));
- right_page_no = btr_page_get_next(buf_block_get_frame(block));
+ left_page_no = btr_page_get_prev(block->frame);
+ right_page_no = btr_page_get_next(block->frame);
ut_d(bool parent_is_different = false);
if (left_page_no != FIL_NULL) {
merge_block = btr_block_get(*index, left_page_no, RW_X_LATCH,
true, mtr);
- merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
- ut_a(btr_page_get_next(merge_page)
+ ut_a(btr_page_get_next(merge_block->frame)
== block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */
ut_d(parent_is_different =
@@ -4227,39 +4148,32 @@ btr_discard_page(
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(*index, right_page_no, RW_X_LATCH,
true, mtr);
- merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
- ut_a(btr_page_get_prev(merge_page)
+ ut_a(btr_page_get_prev(merge_block->frame)
== block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */
ut_d(parent_is_different = page_rec_is_supremum(
page_rec_get_next(btr_cur_get_rec(&parent_cursor))));
+ if (!page_is_leaf(merge_block->frame)) {
+ rec_t* node_ptr = page_rec_get_next(
+ page_get_infimum_rec(merge_block->frame));
+ ut_ad(page_rec_is_user_rec(node_ptr));
+ /* We have to mark the leftmost node pointer as the
+ predefined minimum record. */
+ btr_set_min_rec_mark<true>(node_ptr, *merge_block,
+ mtr);
+ }
} else {
btr_discard_only_page_on_level(index, block, mtr);
return;
}
- page = buf_block_get_frame(block);
- ut_a(page_is_comp(merge_page) == page_is_comp(page));
+ ut_a(page_is_comp(merge_block->frame) == page_is_comp(block->frame));
+ ut_ad(!memcmp_aligned<2>(&merge_block->frame[PAGE_HEADER + PAGE_LEVEL],
+ &block->frame[PAGE_HEADER + PAGE_LEVEL], 2));
btr_search_drop_page_hash_index(block);
- if (left_page_no == FIL_NULL && !page_is_leaf(page)) {
-
- /* We have to mark the leftmost node pointer on the right
- side page as the predefined minimum record */
- node_ptr = page_rec_get_next(page_get_infimum_rec(merge_page));
-
- ut_ad(page_rec_is_user_rec(node_ptr));
-
- /* This will make page_zip_validate() fail on merge_page
- until btr_level_list_remove() completes. This is harmless,
- because everything will take place within a single
- mini-transaction and because writing to the redo log
- is an atomic operation (performed by mtr_commit()). */
- btr_set_min_rec_mark(node_ptr, mtr);
- }
-
if (dict_index_is_spatial(index)) {
rtr_node_ptr_delete(&parent_cursor, mtr);
} else {
@@ -4274,7 +4188,8 @@ btr_discard_page(
page_zip_des_t* merge_page_zip
= buf_block_get_page_zip(merge_block);
ut_a(!merge_page_zip
- || page_zip_validate(merge_page_zip, merge_page, index));
+ || page_zip_validate(merge_page_zip, merge_block->frame,
+ index));
}
#endif /* UNIV_ZIP_DEBUG */
diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc
index c64a64466d8..342174118ce 100644
--- a/storage/innobase/btr/btr0bulk.cc
+++ b/storage/innobase/btr/btr0bulk.cc
@@ -92,6 +92,8 @@ PageBulk::init()
new_page_zip = buf_block_get_page_zip(new_block);
new_page_no = page_get_page_no(new_page);
+ byte* index_id = PAGE_HEADER + PAGE_INDEX_ID + new_page;
+
if (new_page_zip) {
page_create_zip(new_block, m_index, m_level, 0,
&m_mtr);
@@ -100,11 +102,9 @@ PageBulk::init()
page_zip_write_header(new_page_zip,
FIL_PAGE_PREV + new_page,
8, &m_mtr);
- mach_write_to_8(PAGE_HEADER + PAGE_INDEX_ID + new_page,
- m_index->id);
- page_zip_write_header(new_page_zip,
- PAGE_HEADER + PAGE_INDEX_ID
- + new_page, 8, &m_mtr);
+ mach_write_to_8(index_id, m_index->id);
+ page_zip_write_header(new_page_zip, index_id,
+ 8, &m_mtr);
} else {
ut_ad(!dict_index_is_spatial(m_index));
page_create(new_block, &m_mtr,
@@ -113,11 +113,11 @@ PageBulk::init()
compile_time_assert(FIL_PAGE_NEXT
== FIL_PAGE_PREV + 4);
compile_time_assert(FIL_NULL == 0xffffffff);
- mlog_memset(new_block, FIL_PAGE_PREV, 8, 0xff, &m_mtr);
- mlog_write_ulint(PAGE_HEADER + PAGE_LEVEL + new_page,
- m_level, MLOG_2BYTES, &m_mtr);
- mlog_write_ull(PAGE_HEADER + PAGE_INDEX_ID + new_page,
- m_index->id, &m_mtr);
+ m_mtr.memset(new_block, FIL_PAGE_PREV, 8, 0xff);
+ m_mtr.write<2,mtr_t::OPT>(*new_block,
+ PAGE_HEADER + PAGE_LEVEL
+ + new_page, m_level);
+ m_mtr.write<8>(*new_block, index_id, m_index->id);
}
} else {
new_block = btr_block_get(*m_index, m_page_no, RW_X_LATCH,
@@ -130,7 +130,7 @@ PageBulk::init()
ut_ad(page_dir_get_n_heap(new_page) == PAGE_HEAP_NO_USER_LOW);
- btr_page_set_level(new_page, new_page_zip, m_level, &m_mtr);
+ btr_page_set_level(new_block, m_level, &m_mtr);
}
if (!m_level && dict_index_is_sec_or_ibuf(m_index)) {
@@ -169,13 +169,14 @@ PageBulk::init()
}
/** Insert a record in the page.
+@tparam fmt the page format
@param[in] rec record
@param[in] offsets record offsets */
-void
-PageBulk::insert(
- const rec_t* rec,
- ulint* offsets)
+template<PageBulk::format fmt>
+inline void PageBulk::insertPage(const rec_t *rec, ulint *offsets)
{
+ ut_ad((m_page_zip != nullptr) == (fmt == COMPRESSED));
+ ut_ad((fmt != REDUNDANT) == m_is_comp);
ulint rec_size;
ut_ad(m_heap != NULL);
@@ -210,7 +211,7 @@ PageBulk::insert(
/* 3. Set the n_owned field in the inserted record to zero,
and set the heap_no field. */
- if (m_is_comp) {
+ if (fmt != REDUNDANT) {
rec_set_n_owned_new(insert_rec, NULL, 0);
rec_set_heap_no_new(insert_rec,
PAGE_HEAP_NO_USER_LOW + m_rec_no);
@@ -242,15 +243,30 @@ PageBulk::insert(
m_cur_rec = insert_rec;
}
+/** Insert a record in the page.
+@param[in] rec record
+@param[in] offsets record offsets */
+inline void PageBulk::insert(const rec_t *rec, ulint *offsets)
+{
+ if (UNIV_LIKELY_NULL(m_page_zip))
+ insertPage<COMPRESSED>(rec, offsets);
+ else if (m_is_comp)
+ insertPage<DYNAMIC>(rec, offsets);
+ else
+ insertPage<REDUNDANT>(rec, offsets);
+}
+
/** Mark end of insertion to the page. Scan all records to set page dirs,
and set page header members.
-Note: we refer to page_copy_rec_list_end_to_created_page. */
-void
-PageBulk::finish()
+@tparam fmt the page format */
+template<PageBulk::format fmt>
+inline void PageBulk::finishPage()
{
ut_ad(m_rec_no > 0);
+ ut_ad((m_page_zip != nullptr) == (fmt == COMPRESSED));
+ ut_ad((fmt != REDUNDANT) == m_is_comp);
ut_ad(m_total_data + page_dir_calc_reserved_space(m_rec_no)
- <= page_get_free_space_of_empty(m_is_comp));
+ <= page_get_free_space_of_empty(fmt != REDUNDANT));
/* See page_copy_rec_list_end_to_created_page() */
ut_d(page_dir_set_n_slots(m_page, NULL, srv_page_size / 2));
@@ -304,26 +320,26 @@ PageBulk::finish()
ut_ad(!dict_index_is_spatial(m_index));
ut_ad(!page_get_instant(m_page));
-
- if (!m_flush_observer && !m_page_zip) {
- mlog_write_ulint(PAGE_HEADER + PAGE_N_DIR_SLOTS + m_page,
- 2 + slot_index, MLOG_2BYTES, &m_mtr);
- mlog_write_ulint(PAGE_HEADER + PAGE_HEAP_TOP + m_page,
- ulint(m_heap_top - m_page),
- MLOG_2BYTES, &m_mtr);
- mlog_write_ulint(PAGE_HEADER + PAGE_N_HEAP + m_page,
- (PAGE_HEAP_NO_USER_LOW + m_rec_no)
- | ulint(m_is_comp) << 15,
- MLOG_2BYTES, &m_mtr);
- mlog_write_ulint(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no,
- MLOG_2BYTES, &m_mtr);
- mlog_write_ulint(PAGE_HEADER + PAGE_LAST_INSERT + m_page,
- ulint(m_cur_rec - m_page),
- MLOG_2BYTES, &m_mtr);
- mlog_write_ulint(PAGE_HEADER + PAGE_DIRECTION_B - 1 + m_page,
- PAGE_RIGHT, MLOG_2BYTES, &m_mtr);
- mlog_write_ulint(PAGE_HEADER + PAGE_N_DIRECTION + m_page, 0,
- MLOG_2BYTES, &m_mtr);
+ ut_ad(!mach_read_from_2(PAGE_HEADER + PAGE_N_DIRECTION + m_page));
+
+ if (fmt != COMPRESSED && !m_flush_observer) {
+ m_mtr.write<2,mtr_t::OPT>(*m_block,
+ PAGE_HEADER + PAGE_N_DIR_SLOTS
+ + m_page, 2 + slot_index);
+ m_mtr.write<2>(*m_block, PAGE_HEADER + PAGE_HEAP_TOP + m_page,
+ ulint(m_heap_top - m_page));
+ m_mtr.write<2>(*m_block,
+ PAGE_HEADER + PAGE_N_HEAP + m_page,
+ (PAGE_HEAP_NO_USER_LOW + m_rec_no)
+ | uint16_t{fmt != REDUNDANT} << 15);
+ m_mtr.write<2>(*m_block,
+ PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no);
+ m_mtr.write<2>(*m_block,
+ PAGE_HEADER + PAGE_LAST_INSERT + m_page,
+ ulint(m_cur_rec - m_page));
+ m_mtr.write<2>(*m_block,
+ PAGE_HEADER + PAGE_DIRECTION_B - 1 + m_page,
+ PAGE_RIGHT);
} else {
/* For ROW_FORMAT=COMPRESSED, redo log may be written
in PageBulk::compress(). */
@@ -333,18 +349,29 @@ PageBulk::finish()
ulint(m_heap_top - m_page));
mach_write_to_2(PAGE_HEADER + PAGE_N_HEAP + m_page,
(PAGE_HEAP_NO_USER_LOW + m_rec_no)
- | ulint(m_is_comp) << 15);
+ | uint16_t{fmt != REDUNDANT} << 15);
mach_write_to_2(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no);
mach_write_to_2(PAGE_HEADER + PAGE_LAST_INSERT + m_page,
ulint(m_cur_rec - m_page));
mach_write_to_2(PAGE_HEADER + PAGE_DIRECTION_B - 1 + m_page,
PAGE_RIGHT);
- mach_write_to_2(PAGE_HEADER + PAGE_N_DIRECTION + m_page, 0);
}
m_block->skip_flush_check = false;
}
+/** Mark end of insertion to the page. Scan all records to set page dirs,
+and set page header members. */
+inline void PageBulk::finish()
+{
+ if (UNIV_LIKELY_NULL(m_page_zip))
+ finishPage<COMPRESSED>();
+ else if (m_is_comp)
+ finishPage<DYNAMIC>();
+ else
+ finishPage<REDUNDANT>();
+}
+
/** Commit inserts done to the page
@param[in] success Flag whether all inserts succeed. */
void
@@ -521,28 +548,24 @@ PageBulk::copyOut(
@param[in] next_page_no next page no */
inline void PageBulk::setNext(ulint next_page_no)
{
- if (UNIV_LIKELY_NULL(m_page_zip)) {
- /* For ROW_FORMAT=COMPRESSED, redo log may be written
- in PageBulk::compress(). */
- mach_write_to_4(m_page + FIL_PAGE_NEXT, next_page_no);
- } else {
- mlog_write_ulint(m_page + FIL_PAGE_NEXT, next_page_no,
- MLOG_4BYTES, &m_mtr);
- }
+ if (UNIV_LIKELY_NULL(m_page_zip))
+ /* For ROW_FORMAT=COMPRESSED, redo log may be written
+ in PageBulk::compress(). */
+ mach_write_to_4(m_page + FIL_PAGE_NEXT, next_page_no);
+ else
+ m_mtr.write<4>(*m_block, m_page + FIL_PAGE_NEXT, next_page_no);
}
/** Set previous page
@param[in] prev_page_no previous page no */
inline void PageBulk::setPrev(ulint prev_page_no)
{
- if (UNIV_LIKELY_NULL(m_page_zip)) {
- /* For ROW_FORMAT=COMPRESSED, redo log may be written
- in PageBulk::compress(). */
- mach_write_to_4(m_page + FIL_PAGE_PREV, prev_page_no);
- } else {
- mlog_write_ulint(m_page + FIL_PAGE_PREV, prev_page_no,
- MLOG_4BYTES, &m_mtr);
- }
+ if (UNIV_LIKELY_NULL(m_page_zip))
+ /* For ROW_FORMAT=COMPRESSED, redo log may be written
+ in PageBulk::compress(). */
+ mach_write_to_4(m_page + FIL_PAGE_PREV, prev_page_no);
+ else
+ m_mtr.write<4>(*m_block, m_page + FIL_PAGE_PREV, prev_page_no);
}
/** Check if required space is available in the page for the rec to be inserted.
@@ -748,9 +771,10 @@ BtrBulk::pageCommit(
page_bulk->setNext(next_page_bulk->getPageNo());
next_page_bulk->setPrev(page_bulk->getPageNo());
} else {
- /** Suppose a page is released and latched again, we need to
+ ut_ad(!page_has_next(page_bulk->getPage()));
+ /* If a page is released and latched again, we need to
mark it modified in mini-transaction. */
- page_bulk->setNext(FIL_NULL);
+ page_bulk->set_modified();
}
ut_ad(!rw_lock_own_flagged(&m_index->lock,
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index b7fb3227caf..932072ad182 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -154,8 +154,7 @@ static
void
btr_cur_unmark_extern_fields(
/*=========================*/
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
- part will be updated, or NULL */
+ buf_block_t* block, /*!< in/out: index page */
rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
@@ -181,8 +180,7 @@ btr_rec_free_updated_extern_fields(
dict_index_t* index, /*!< in: index of rec; the index tree MUST be
X-latched */
rec_t* rec, /*!< in: record */
- page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
- part will be updated, or NULL */
+ buf_block_t* block, /*!< in: index page of rec */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
const upd_t* update, /*!< in: update vector */
bool rollback,/*!< in: performing rollback? */
@@ -198,8 +196,7 @@ btr_rec_free_externally_stored_fields(
tree MUST be X-latched */
rec_t* rec, /*!< in: record */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
- page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
- part will be updated, or NULL */
+ buf_block_t* block, /*!< in: index page of rec */
bool rollback,/*!< in: performing rollback? */
mtr_t* mtr); /*!< in: mini-transaction handle which contains
an X-latch to record page and to the index
@@ -224,7 +221,6 @@ btr_cur_latch_leaves(
uint32_t left_page_no;
uint32_t right_page_no;
buf_block_t* get_block;
- page_t* page = buf_block_get_frame(block);
bool spatial;
btr_latch_leaves_t latch_leaves = {{NULL, NULL, NULL}, {0, 0, 0}};
@@ -252,7 +248,8 @@ btr_cur_latch_leaves(
true, mtr);
latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
+ ut_a(page_is_comp(get_block->frame)
+ == page_is_comp(block->frame));
#endif /* UNIV_BTR_DEBUG */
if (spatial) {
cursor->rtr_info->tree_blocks[RTR_MAX_LEVELS]
@@ -268,7 +265,7 @@ btr_cur_latch_leaves(
dict_index_get_lock(cursor->index),
MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
/* x-latch also siblings from left to right */
- left_page_no = btr_page_get_prev(page);
+ left_page_no = btr_page_get_prev(block->frame);
if (left_page_no != FIL_NULL) {
@@ -304,11 +301,12 @@ btr_cur_latch_leaves(
/* Sanity check only after both the blocks are latched. */
if (latch_leaves.blocks[0] != NULL) {
ut_a(page_is_comp(latch_leaves.blocks[0]->frame)
- == page_is_comp(page));
+ == page_is_comp(block->frame));
ut_a(btr_page_get_next(latch_leaves.blocks[0]->frame)
- == page_get_page_no(page));
+ == block->page.id.page_no());
}
- ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
+ ut_a(page_is_comp(get_block->frame)
+ == page_is_comp(block->frame));
#endif /* UNIV_BTR_DEBUG */
if (spatial) {
@@ -316,7 +314,7 @@ btr_cur_latch_leaves(
= get_block;
}
- right_page_no = btr_page_get_next(page);
+ right_page_no = btr_page_get_next(block->frame);
if (right_page_no != FIL_NULL) {
if (spatial) {
@@ -331,9 +329,9 @@ btr_cur_latch_leaves(
latch_leaves.blocks[2] = get_block;
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
- == page_is_comp(page));
+ == page_is_comp(block->frame));
ut_a(btr_page_get_prev(get_block->frame)
- == page_get_page_no(page));
+ == block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */
if (spatial) {
cursor->rtr_info->tree_blocks[
@@ -348,7 +346,7 @@ btr_cur_latch_leaves(
mode = latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH;
/* latch also left sibling */
rw_lock_s_lock(&block->lock);
- left_page_no = btr_page_get_prev(page);
+ left_page_no = btr_page_get_prev(block->frame);
rw_lock_s_unlock(&block->lock);
if (left_page_no != FIL_NULL) {
@@ -360,9 +358,9 @@ btr_cur_latch_leaves(
cursor->left_block = get_block;
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
- == page_is_comp(page));
+ == page_is_comp(block->frame));
ut_a(btr_page_get_next(get_block->frame)
- == page_get_page_no(page));
+ == block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */
}
@@ -372,7 +370,8 @@ btr_cur_latch_leaves(
true, mtr);
latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
+ ut_a(page_is_comp(get_block->frame)
+ == page_is_comp(block->frame));
#endif /* UNIV_BTR_DEBUG */
return(latch_leaves);
case BTR_CONT_MODIFY_TREE:
@@ -2424,8 +2423,7 @@ need_opposite_intention:
cursor->up_bytes = up_bytes;
if (autoinc) {
- page_set_autoinc(tree_blocks[0],
- index, autoinc, mtr, false);
+ page_set_autoinc(tree_blocks[0], autoinc, mtr, false);
}
#ifdef BTR_CUR_HASH_ADAPT
@@ -4160,8 +4158,6 @@ btr_cur_update_in_place(
further pages */
{
dict_index_t* index;
- buf_block_t* block;
- page_zip_des_t* page_zip;
dberr_t err;
rec_t* rec;
roll_ptr_t roll_ptr = 0;
@@ -4190,11 +4186,11 @@ btr_cur_update_in_place(
<< ") by " << ib::hex(trx_id) << ": "
<< rec_printer(rec, offsets).str());
- block = btr_cur_get_block(cursor);
- page_zip = buf_block_get_page_zip(block);
+ buf_block_t* block = btr_cur_get_block(cursor);
+ page_zip_des_t* page_zip = buf_block_get_page_zip(block);
/* Check that enough space is available on the compressed page. */
- if (page_zip) {
+ if (UNIV_LIKELY_NULL(page_zip)) {
ut_ad(!index->table->is_temporary());
if (!btr_cur_update_alloc_zip(
@@ -4277,8 +4273,7 @@ btr_cur_update_in_place(
/* The new updated record owns its possible externally
stored fields */
- btr_cur_unmark_extern_fields(page_zip,
- rec, index, offsets, mtr);
+ btr_cur_unmark_extern_fields(block, rec, index, offsets, mtr);
}
ut_ad(err == DB_SUCCESS);
@@ -4803,7 +4798,6 @@ btr_cur_pessimistic_update(
big_rec_t* dummy_big_rec;
dict_index_t* index;
buf_block_t* block;
- page_t* page;
page_zip_des_t* page_zip;
rec_t* rec;
page_cur_t* page_cursor;
@@ -4813,13 +4807,11 @@ btr_cur_pessimistic_update(
ibool was_first;
ulint n_reserved = 0;
ulint n_ext;
- ulint max_ins_size = 0;
*offsets = NULL;
*big_rec = NULL;
block = btr_cur_get_block(cursor);
- page = buf_block_get_frame(block);
page_zip = buf_block_get_page_zip(block);
index = cursor->index;
@@ -4828,7 +4820,7 @@ btr_cur_pessimistic_update(
MTR_MEMO_SX_LOCK));
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page, index));
+ ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */
ut_ad(!page_zip || !index->table->is_temporary());
/* The insert buffer tree should never be updated in place. */
@@ -4861,7 +4853,7 @@ btr_cur_pessimistic_update(
if (page_zip
&& optim_err != DB_ZIP_OVERFLOW
&& !dict_index_is_clust(index)
- && page_is_leaf(page)) {
+ && page_is_leaf(block->frame)) {
ut_ad(!index->table->is_temporary());
ibuf_update_free_bits_zip(block, mtr);
}
@@ -4910,7 +4902,7 @@ btr_cur_pessimistic_update(
/* We have to set appropriate extern storage bits in the new
record to be inserted: we have to remember which fields were such */
- ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
+ ut_ad(!page_is_comp(block->frame) || !rec_get_node_ptr_flag(rec));
ut_ad(rec_offs_validate(rec, index, *offsets));
if (index->is_primary()) {
n_ext += btr_push_update_extern_fields(
@@ -4933,12 +4925,12 @@ btr_cur_pessimistic_update(
DEBUG_SYNC_C("blob_rollback_middle");
btr_rec_free_updated_extern_fields(
- index, rec, page_zip, *offsets, update, true, mtr);
+ index, rec, block, *offsets, update, true, mtr);
}
if (page_zip_rec_needs_ext(
rec_get_converted_size(index, new_entry, n_ext),
- page_is_comp(page),
+ page_is_comp(block->frame),
dict_index_get_n_fields(index),
block->zip_size())
|| (UNIV_UNLIKELY(update->is_alter_metadata())
@@ -4954,14 +4946,15 @@ btr_cur_pessimistic_update(
BTR_KEEP_IBUF_BITMAP. */
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip
- || page_zip_validate(page_zip, page, index));
+ || page_zip_validate(page_zip, block->frame,
+ index));
#endif /* UNIV_ZIP_DEBUG */
index->table->space->release_free_extents(n_reserved);
err = DB_TOO_BIG_RECORD;
goto err_exit;
}
- ut_ad(page_is_leaf(page));
+ ut_ad(page_is_leaf(block->frame));
ut_ad(dict_index_is_clust(index));
ut_ad(flags & BTR_KEEP_POS_FLAG);
}
@@ -4996,10 +4989,9 @@ btr_cur_pessimistic_update(
btr_cur_write_sys(new_entry, index, trx_id, roll_ptr);
}
- if (!page_zip) {
- max_ins_size = page_get_max_insert_size_after_reorganize(
- page, 1);
- }
+ const ulint max_ins_size = page_zip
+ ? 0 : page_get_max_insert_size_after_reorganize(block->frame,
+ 1);
if (UNIV_UNLIKELY(is_metadata)) {
ut_ad(new_entry->is_metadata());
@@ -5027,7 +5019,7 @@ btr_cur_pessimistic_update(
}
#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page, index));
+ ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */
page_cursor = btr_cur_get_page_cur(cursor);
@@ -5058,8 +5050,8 @@ btr_cur_pessimistic_update(
|| rec_is_alter_metadata(rec, *index)) {
/* The new inserted record owns its possible externally
stored fields */
- btr_cur_unmark_extern_fields(
- page_zip, rec, index, *offsets, mtr);
+ btr_cur_unmark_extern_fields(btr_cur_get_block(cursor),
+ rec, index, *offsets, mtr);
} else {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
@@ -5067,7 +5059,7 @@ btr_cur_pessimistic_update(
}
bool adjust = big_rec_vec && (flags & BTR_KEEP_POS_FLAG);
- ut_ad(!adjust || page_is_leaf(page));
+ ut_ad(!adjust || page_is_leaf(block->frame));
if (btr_cur_compress_if_useful(cursor, adjust, mtr)) {
if (adjust) {
@@ -5075,7 +5067,7 @@ btr_cur_pessimistic_update(
true, *offsets);
}
} else if (!dict_index_is_clust(index)
- && page_is_leaf(page)) {
+ && page_is_leaf(block->frame)) {
/* Update the free bits in the insert buffer.
This is the same block which was skipped by
BTR_KEEP_IBUF_BITMAP. */
@@ -5090,7 +5082,7 @@ btr_cur_pessimistic_update(
if (!srv_read_only_mode
&& !big_rec_vec
- && page_is_leaf(page)
+ && page_is_leaf(block->frame)
&& !dict_index_is_online_ddl(index)) {
mtr_memo_release(mtr, dict_index_get_lock(index),
@@ -5115,13 +5107,13 @@ btr_cur_pessimistic_update(
BTR_KEEP_IBUF_BITMAP. */
if (!dict_index_is_clust(index)
&& !index->table->is_temporary()
- && page_is_leaf(page)) {
+ && page_is_leaf(block->frame)) {
ibuf_reset_free_bits(block);
}
}
if (big_rec_vec != NULL) {
- ut_ad(page_is_leaf(page));
+ ut_ad(page_is_leaf(block->frame));
ut_ad(dict_index_is_clust(index));
ut_ad(flags & BTR_KEEP_POS_FLAG);
@@ -5170,28 +5162,20 @@ btr_cur_pessimistic_update(
/* Update PAGE_MAX_TRX_ID in the index page header.
It was not updated by btr_cur_pessimistic_insert()
because of BTR_NO_LOCKING_FLAG. */
- buf_block_t* rec_block;
-
- rec_block = btr_cur_get_block(cursor);
-
- page_update_max_trx_id(rec_block,
- buf_block_get_page_zip(rec_block),
+ page_update_max_trx_id(btr_cur_get_block(cursor),
+ btr_cur_get_page_zip(cursor),
trx_id, mtr);
}
if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) {
/* The new inserted record owns its possible externally
stored fields */
- buf_block_t* rec_block = btr_cur_get_block(cursor);
-
#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page, index));
- page = buf_block_get_frame(rec_block);
+ ut_a(!page_zip || page_zip_validate(page_zip, block->frame,
+ index));
#endif /* UNIV_ZIP_DEBUG */
- page_zip = buf_block_get_page_zip(rec_block);
-
- btr_cur_unmark_extern_fields(page_zip,
- rec, index, *offsets, mtr);
+ btr_cur_unmark_extern_fields(btr_cur_get_block(cursor), rec,
+ index, *offsets, mtr);
} else {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
@@ -5222,7 +5206,8 @@ btr_cur_pessimistic_update(
return_after_reservations:
#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page, index));
+ ut_a(!page_zip || page_zip_validate(btr_cur_get_page_zip(cursor),
+ btr_cur_get_page(cursor), index));
#endif /* UNIV_ZIP_DEBUG */
index->table->space->release_free_extents(n_reserved);
@@ -5393,7 +5378,6 @@ btr_cur_del_mark_set_clust_rec(
{
roll_ptr_t roll_ptr;
dberr_t err;
- page_zip_des_t* page_zip;
trx_t* trx;
ut_ad(dict_index_is_clust(index));
@@ -5431,7 +5415,7 @@ btr_cur_del_mark_set_clust_rec(
the adaptive hash index does not depend on the delete-mark
and the delete-mark is being updated in place. */
- page_zip = buf_block_get_page_zip(block);
+ page_zip_des_t* page_zip = buf_block_get_page_zip(block);
btr_rec_set_deleted_flag(rec, page_zip, TRUE);
@@ -5629,17 +5613,15 @@ btr_cur_compress_if_useful(
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
- if (dict_index_is_spatial(cursor->index)) {
- const page_t* page = btr_cur_get_page(cursor);
- const trx_t* trx = NULL;
-
- if (cursor->rtr_info->thr != NULL) {
- trx = thr_get_trx(cursor->rtr_info->thr);
- }
+ if (cursor->index->is_spatial()) {
+ const trx_t* trx = cursor->rtr_info->thr
+ ? thr_get_trx(cursor->rtr_info->thr)
+ : NULL;
+ const buf_block_t* block = btr_cur_get_block(cursor);
/* Check whether page lock prevents the compression */
- if (!lock_test_prdt_page_lock(trx, page_get_space_id(page),
- page_get_page_no(page))) {
+ if (!lock_test_prdt_page_lock(trx, block->page.id.space(),
+ block->page.id.page_no())) {
return(false);
}
}
@@ -5905,7 +5887,7 @@ btr_cur_pessimistic_delete(
if (rec_offs_any_extern(offsets)) {
btr_rec_free_externally_stored_fields(index,
- rec, offsets, page_zip,
+ rec, offsets, block,
rollback, mtr);
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
@@ -6069,7 +6051,7 @@ discard_page:
offsets, mtr);
if (min_mark_next_rec) {
- btr_set_min_rec_mark(next_rec, mtr);
+ btr_set_min_rec_mark(next_rec, *block, mtr);
}
#ifdef UNIV_ZIP_DEBUG
@@ -6143,8 +6125,6 @@ btr_cur_add_path_info(
ulint root_height) /*!< in: root node height in tree */
{
btr_path_t* slot;
- const rec_t* rec;
- const page_t* page;
ut_a(cursor->path_arr);
@@ -6163,16 +6143,14 @@ btr_cur_add_path_info(
slot->nth_rec = ULINT_UNDEFINED;
}
- rec = btr_cur_get_rec(cursor);
-
slot = cursor->path_arr + (root_height - height);
- page = page_align(rec);
+ const buf_block_t* block = btr_cur_get_block(cursor);
- slot->nth_rec = page_rec_get_n_recs_before(rec);
- slot->n_recs = page_get_n_recs(page);
- slot->page_no = page_get_page_no(page);
- slot->page_level = btr_page_get_level(page);
+ slot->nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
+ slot->n_recs = page_get_n_recs(block->frame);
+ slot->page_no = block->page.id.page_no();
+ slot->page_level = btr_page_get_level(block->frame);
}
/*******************************************************************//**
@@ -7144,13 +7122,12 @@ static
void
btr_cur_set_ownership_of_extern_field(
/*==================================*/
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
- part will be updated, or NULL */
+ buf_block_t* block, /*!< in/out: index page */
rec_t* rec, /*!< in/out: clustered index record */
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
ulint i, /*!< in: field number */
- ibool val, /*!< in: value to set */
+ bool val, /*!< in: value to set */
mtr_t* mtr) /*!< in: mtr, or NULL if not logged */
{
byte* data;
@@ -7174,15 +7151,14 @@ btr_cur_set_ownership_of_extern_field(
byte_val |= BTR_EXTERN_OWNER_FLAG;
}
- if (page_zip) {
+ if (UNIV_LIKELY_NULL(block->page.zip.data)) {
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
- page_zip_write_blob_ptr(page_zip, rec, index, offsets, i, mtr);
- } else if (mtr != NULL) {
-
- mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val,
- MLOG_1BYTE, mtr);
+ page_zip_write_blob_ptr(&block->page.zip, rec, index, offsets,
+ i, mtr);
} else {
- mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
+ mtr->write<1,mtr_t::OPT>(*block,
+ data + local_len + BTR_EXTERN_LEN,
+ byte_val);
}
}
@@ -7194,8 +7170,7 @@ to free the field. */
void
btr_cur_disown_inherited_fields(
/*============================*/
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
- part will be updated, or NULL */
+ buf_block_t* block, /*!< in/out: index page */
rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
@@ -7212,7 +7187,7 @@ btr_cur_disown_inherited_fields(
if (rec_offs_nth_extern(offsets, i)
&& !upd_get_field_by_field_no(update, i, false)) {
btr_cur_set_ownership_of_extern_field(
- page_zip, rec, index, offsets, i, FALSE, mtr);
+ block, rec, index, offsets, i, false, mtr);
}
}
}
@@ -7225,29 +7200,23 @@ static
void
btr_cur_unmark_extern_fields(
/*=========================*/
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
- part will be updated, or NULL */
+ buf_block_t* block, /*!< in/out: index page */
rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
mtr_t* mtr) /*!< in: mtr, or NULL if not logged */
{
- ulint n;
- ulint i;
-
ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
- n = rec_offs_n_fields(offsets);
-
if (!rec_offs_any_extern(offsets)) {
-
return;
}
- for (i = 0; i < n; i++) {
- if (rec_offs_nth_extern(offsets, i)) {
+ const ulint n = rec_offs_n_fields(offsets);
+ for (ulint i = 0; i < n; i++) {
+ if (rec_offs_nth_extern(offsets, i)) {
btr_cur_set_ownership_of_extern_field(
- page_zip, rec, index, offsets, i, TRUE, mtr);
+ block, rec, index, offsets, i, true, mtr);
}
}
}
@@ -7453,9 +7422,7 @@ struct btr_blob_log_check_t {
if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) {
offs = page_offset(*m_rec);
- page_no = page_get_page_no(
- buf_block_get_frame(*m_block));
-
+ page_no = (*m_block)->page.id.page_no();
buf_block_buf_fix_inc(*m_block, __FILE__, __LINE__);
} else {
btr_pcur_store_position(m_pcur, m_mtr);
@@ -7648,7 +7615,6 @@ btr_store_big_rec_extern_fields(
for (ulint blob_npages = 0;; ++blob_npages) {
buf_block_t* block;
- page_t* page;
const ulint commit_freq = 4;
ulint r_extents;
@@ -7711,11 +7677,9 @@ btr_store_big_rec_extern_fields(
ut_a(block != NULL);
page_no = block->page.id.page_no();
- page = buf_block_get_frame(block);
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block;
- page_t* prev_page;
prev_block = buf_page_get(
page_id_t(space_id, prev_page_no),
@@ -7724,23 +7688,25 @@ btr_store_big_rec_extern_fields(
buf_block_dbg_add_level(prev_block,
SYNC_EXTERN_STORAGE);
- prev_page = buf_block_get_frame(prev_block);
if (page_zip) {
- mlog_write_ulint(
- prev_page + FIL_PAGE_NEXT,
- page_no, MLOG_4BYTES, &mtr);
- memcpy(buf_block_get_page_zip(
- prev_block)
- ->data + FIL_PAGE_NEXT,
- prev_page + FIL_PAGE_NEXT, 4);
+ mtr.write<4>(*prev_block,
+ prev_block->frame
+ + FIL_PAGE_NEXT,
+ page_no);
+ memcpy_aligned<4>(
+ buf_block_get_page_zip(
+ prev_block)
+ ->data + FIL_PAGE_NEXT,
+ prev_block->frame
+ + FIL_PAGE_NEXT, 4);
} else {
- mlog_write_ulint(
- prev_page + FIL_PAGE_DATA
- + BTR_BLOB_HDR_NEXT_PAGE_NO,
- page_no, MLOG_4BYTES, &mtr);
+ mtr.write<4>(*prev_block,
+ BTR_BLOB_HDR_NEXT_PAGE_NO
+ + FIL_PAGE_DATA
+ + prev_block->frame,
+ page_no);
}
-
} else if (dict_index_is_online_ddl(index)) {
row_log_table_blob_alloc(index, page_no);
}
@@ -7751,21 +7717,21 @@ btr_store_big_rec_extern_fields(
/* Write FIL_PAGE_TYPE to the redo log
separately, before logging any other
- changes to the page, so that the debug
+ changes to the block, so that the debug
assertions in
recv_parse_or_apply_log_rec_body() can
be made simpler. Before InnoDB Plugin
1.0.4, the initialization of
FIL_PAGE_TYPE was logged as part of
- the mlog_log_string() below. */
+ the mtr_t::memcpy() below. */
- mlog_write_ulint(page + FIL_PAGE_TYPE,
- prev_page_no == FIL_NULL
- ? FIL_PAGE_TYPE_ZBLOB
- : FIL_PAGE_TYPE_ZBLOB2,
- MLOG_2BYTES, &mtr);
+ mtr.write<2>(*block,
+ block->frame + FIL_PAGE_TYPE,
+ prev_page_no == FIL_NULL
+ ? FIL_PAGE_TYPE_ZBLOB
+ : FIL_PAGE_TYPE_ZBLOB2);
- c_stream.next_out = page
+ c_stream.next_out = block->frame
+ FIL_PAGE_DATA;
c_stream.avail_out = static_cast<uInt>(
payload_size_zip);
@@ -7778,8 +7744,7 @@ btr_store_big_rec_extern_fields(
compile_time_assert(FIL_PAGE_NEXT
== FIL_PAGE_PREV + 4);
compile_time_assert(FIL_NULL == 0xffffffff);
- mlog_memset(block, FIL_PAGE_PREV, 8, 0xff,
- &mtr);
+ mtr.memset(block, FIL_PAGE_PREV, 8, 0xff);
/* Write a back pointer to the record
into the otherwise unused area. This
information could be useful in
@@ -7799,27 +7764,23 @@ btr_store_big_rec_extern_fields(
Number */
ut_ad(!dict_index_is_spatial(index));
- mlog_write_ulint(page
- + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
- space_id,
- MLOG_4BYTES, &mtr);
- mlog_write_ulint(page
- + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
- rec_page_no,
- MLOG_4BYTES, &mtr);
- mlog_log_string(page
- + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
- page_zip_get_size(page_zip)
- - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
- - c_stream.avail_out,
- &mtr);
+ mtr.write<4>(*block, block->frame
+ + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+ space_id);
+ mtr.write<4>(*block, block->frame
+ + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
+ rec_page_no);
+ mtr.memcpy(*block,
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+ page_zip_get_size(page_zip)
+ - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+ - c_stream.avail_out);
/* Zero out the unused part of the page. */
if (c_stream.avail_out) {
- mlog_memset(block,
- page_zip_get_size(page_zip)
- - c_stream.avail_out,
- c_stream.avail_out,
- 0, &mtr);
+ mtr.memset(block,
+ page_zip_get_size(page_zip)
+ - c_stream.avail_out,
+ c_stream.avail_out, 0);
}
/* Copy the page to compressed storage,
because it will be flushed to disk
@@ -7828,7 +7789,7 @@ btr_store_big_rec_extern_fields(
ut_ad(blob_page_zip);
ut_ad(page_zip_get_size(blob_page_zip)
== page_zip_get_size(page_zip));
- memcpy(blob_page_zip->data, page,
+ memcpy(blob_page_zip->data, block->frame,
page_zip_get_size(page_zip));
if (err == Z_OK && prev_page_no != FIL_NULL) {
@@ -7880,9 +7841,9 @@ next_zip_page:
break;
}
} else {
- mlog_write_ulint(page + FIL_PAGE_TYPE,
- FIL_PAGE_TYPE_BLOB,
- MLOG_2BYTES, &mtr);
+ mtr.write<2>(*block, FIL_PAGE_TYPE
+ + block->frame,
+ FIL_PAGE_TYPE_BLOB);
if (extern_len > payload_size) {
store_len = payload_size;
@@ -7890,47 +7851,42 @@ next_zip_page:
store_len = extern_len;
}
- mlog_write_string(page + FIL_PAGE_DATA
- + BTR_BLOB_HDR_SIZE,
- (const byte*)
- big_rec_vec->fields[i].data
- + big_rec_vec->fields[i].len
- - extern_len,
- store_len, &mtr);
- mlog_write_ulint(page + FIL_PAGE_DATA
- + BTR_BLOB_HDR_PART_LEN,
- store_len, MLOG_4BYTES, &mtr);
- mlog_write_ulint(page + FIL_PAGE_DATA
- + BTR_BLOB_HDR_NEXT_PAGE_NO,
- FIL_NULL, MLOG_4BYTES, &mtr);
+ mtr.memcpy(block,
+ FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE,
+ (const byte*)
+ big_rec_vec->fields[i].data
+ + big_rec_vec->fields[i].len
+ - extern_len, store_len);
+ mtr.write<4>(*block, BTR_BLOB_HDR_PART_LEN
+ + FIL_PAGE_DATA + block->frame,
+ store_len);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+ mtr.memset(block, BTR_BLOB_HDR_NEXT_PAGE_NO
+ + FIL_PAGE_DATA, 4, 0xff);
extern_len -= store_len;
ut_ad(!mach_read_from_4(BTR_EXTERN_LEN
+ field_ref));
- mlog_write_ulint(field_ref
- + BTR_EXTERN_LEN + 4,
- big_rec_vec->fields[i].len
- - extern_len,
- MLOG_4BYTES, &mtr);
+ mtr.write<4>(*rec_block,
+ BTR_EXTERN_LEN + 4 + field_ref,
+ big_rec_vec->fields[i].len
+ - extern_len);
if (prev_page_no == FIL_NULL) {
ut_ad(blob_npages == 0);
- mlog_write_ulint(field_ref
- + BTR_EXTERN_SPACE_ID,
- space_id, MLOG_4BYTES,
- &mtr);
-
- mlog_write_ulint(field_ref
- + BTR_EXTERN_PAGE_NO,
- page_no, MLOG_4BYTES,
- &mtr);
-
- mlog_write_ulint(field_ref
- + BTR_EXTERN_OFFSET,
- FIL_PAGE_DATA,
- MLOG_4BYTES,
- &mtr);
+ mtr.write<4,mtr_t::OPT>(
+ *rec_block,
+ field_ref + BTR_EXTERN_SPACE_ID,
+ space_id);
+
+ mtr.write<4>(*rec_block, field_ref
+ + BTR_EXTERN_PAGE_NO,
+ page_no);
+
+ mtr.write<4>(*rec_block, field_ref
+ + BTR_EXTERN_OFFSET,
+ FIL_PAGE_DATA);
}
prev_page_no = page_no;
@@ -7981,40 +7937,30 @@ func_exit:
return(error);
}
-/*******************************************************************//**
-Check the FIL_PAGE_TYPE on an uncompressed BLOB page. */
-static
-void
-btr_check_blob_fil_page_type(
-/*=========================*/
- ulint space_id, /*!< in: space id */
- ulint page_no, /*!< in: page number */
- const page_t* page, /*!< in: page */
- ibool read) /*!< in: TRUE=read, FALSE=purge */
+/** Check the FIL_PAGE_TYPE on an uncompressed BLOB page.
+@param[in] block uncompressed BLOB page
+@param[in] read true=read, false=purge */
+static void btr_check_blob_fil_page_type(const buf_block_t& block, bool read)
{
- ulint type = fil_page_get_type(page);
-
- ut_a(space_id == page_get_space_id(page));
- ut_a(page_no == page_get_page_no(page));
-
- if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) {
- ulint flags = fil_space_get_flags(space_id);
-
-#ifndef UNIV_DEBUG /* Improve debug test coverage */
- if (!DICT_TF_HAS_ATOMIC_BLOBS(flags)) {
- /* Old versions of InnoDB did not initialize
- FIL_PAGE_TYPE on BLOB pages. Do not print
- anything about the type mismatch when reading
- a BLOB page that may be from old versions. */
- return;
- }
-#endif /* !UNIV_DEBUG */
-
- ib::fatal() << "FIL_PAGE_TYPE=" << type
- << " on BLOB " << (read ? "read" : "purge")
- << " space " << space_id << " page " << page_no
- << " flags " << flags;
- }
+ uint16_t type= fil_page_get_type(block.frame);
+
+ if (UNIV_LIKELY(type == FIL_PAGE_TYPE_BLOB))
+ return;
+ /* FIXME: take the tablespace as a parameter */
+ if (fil_space_t *space= fil_space_acquire_silent(block.page.id.space()))
+ {
+ /* Old versions of InnoDB did not initialize FIL_PAGE_TYPE on BLOB
+ pages. Do not print anything about the type mismatch when reading
+ a BLOB page that may be from old versions. */
+ if (space->full_crc32() || DICT_TF_HAS_ATOMIC_BLOBS(space->flags))
+ {
+ ib::fatal() << "FIL_PAGE_TYPE=" << type
+ << (read ? " on BLOB read file " : " on BLOB purge file ")
+ << space->chain.start->name
+ << " page " << block.page.id.page_no();
+ }
+ space->release();
+ }
}
/*******************************************************************//**
@@ -8038,8 +7984,7 @@ btr_free_externally_stored_field(
page_zip_write_blob_ptr(), or NULL */
const ulint* offsets, /*!< in: rec_get_offsets(rec, index),
or NULL */
- page_zip_des_t* page_zip, /*!< in: compressed page corresponding
- to rec, or NULL if rec == NULL */
+ buf_block_t* block, /*!< in/out: page of field_ref */
ulint i, /*!< in: field number of field_ref;
ignored if rec == NULL */
bool rollback, /*!< in: performing rollback? */
@@ -8084,10 +8029,8 @@ btr_free_externally_stored_field(
const ulint ext_zip_size = index->table->space->zip_size();
const ulint rec_zip_size = rec ? ext_zip_size : 0;
- if (rec == NULL) {
- /* This is a call from row_purge_upd_exist_or_extern(). */
- ut_ad(!page_zip);
- }
+ /* !rec holds in a call from purge when field_ref is in an undo page */
+ ut_ad(rec || !block->page.zip.data);
for (;;) {
#ifdef UNIV_DEBUG
@@ -8156,43 +8099,40 @@ btr_free_externally_stored_field(
btr_page_free(index, ext_block, &mtr, true);
- if (page_zip != NULL) {
+ if (UNIV_LIKELY_NULL(block->page.zip.data)) {
mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO,
next_page_no);
- mach_write_to_4(field_ref + BTR_EXTERN_LEN + 4,
- 0);
- page_zip_write_blob_ptr(page_zip, rec, index,
+ memset(field_ref + BTR_EXTERN_LEN, 0, 4);
+ page_zip_write_blob_ptr(&block->page.zip,
+ rec, index,
offsets, i, &mtr);
} else {
- mlog_write_ulint(field_ref
- + BTR_EXTERN_PAGE_NO,
- next_page_no,
- MLOG_4BYTES, &mtr);
- mlog_write_ulint(field_ref
- + BTR_EXTERN_LEN + 4, 0,
- MLOG_4BYTES, &mtr);
+ mtr.write<4>(*block,
+ BTR_EXTERN_PAGE_NO + field_ref,
+ next_page_no);
+ mtr.write<4>(*block,
+ BTR_EXTERN_LEN + 4 + field_ref,
+ 0U);
}
} else {
- ut_a(!page_zip);
- btr_check_blob_fil_page_type(space_id, page_no, page,
- FALSE);
+ ut_ad(!block->page.zip.data);
+ btr_check_blob_fil_page_type(*ext_block, false);
next_page_no = mach_read_from_4(
page + FIL_PAGE_DATA
+ BTR_BLOB_HDR_NEXT_PAGE_NO);
btr_page_free(index, ext_block, &mtr, true);
- mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO,
- next_page_no,
- MLOG_4BYTES, &mtr);
+ mtr.write<4>(*block, BTR_EXTERN_PAGE_NO + field_ref,
+ next_page_no);
/* Zero out the BLOB length. If the server
crashes during the execution of this function,
trx_rollback_all_recovered() could
dereference the half-deleted BLOB, fetching a
wrong prefix for the BLOB. */
- mlog_write_ulint(field_ref + BTR_EXTERN_LEN + 4,
- 0,
- MLOG_4BYTES, &mtr);
+ mtr.write<4,mtr_t::OPT>(*block,
+ BTR_EXTERN_LEN + 4 + field_ref,
+ 0U);
}
/* Commit mtr and release the BLOB block to save memory. */
@@ -8210,8 +8150,7 @@ btr_rec_free_externally_stored_fields(
tree MUST be X-latched */
rec_t* rec, /*!< in/out: record */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
- page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
- part will be updated, or NULL */
+ buf_block_t* block, /*!< in: index page of rec */
bool rollback,/*!< in: performing rollback? */
mtr_t* mtr) /*!< in: mini-transaction handle which contains
an X-latch to record page and to the index
@@ -8233,7 +8172,7 @@ btr_rec_free_externally_stored_fields(
if (rec_offs_nth_extern(offsets, i)) {
btr_free_externally_stored_field(
index, btr_rec_get_field_ref(rec, offsets, i),
- rec, offsets, page_zip, i, rollback, mtr);
+ rec, offsets, block, i, rollback, mtr);
}
}
}
@@ -8248,8 +8187,7 @@ btr_rec_free_updated_extern_fields(
dict_index_t* index, /*!< in: index of rec; the index tree MUST be
X-latched */
rec_t* rec, /*!< in/out: record */
- page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
- part will be updated, or NULL */
+ buf_block_t* block, /*!< in: index page of rec */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
const upd_t* update, /*!< in: update vector */
bool rollback,/*!< in: performing rollback? */
@@ -8277,7 +8215,7 @@ btr_rec_free_updated_extern_fields(
btr_free_externally_stored_field(
index, data + len - BTR_EXTERN_FIELD_REF_SIZE,
- rec, offsets, page_zip,
+ rec, offsets, block,
ufield->field_no, rollback, mtr);
}
}
@@ -8315,7 +8253,7 @@ btr_copy_blob_prefix(
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
page = buf_block_get_frame(block);
- btr_check_blob_fil_page_type(space_id, page_no, page, TRUE);
+ btr_check_blob_fil_page_type(*block, true);
blob_header = page + offset;
part_len = btr_blob_get_part_len(blob_header);
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index f073dbccdbd..5159caed3aa 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -2094,8 +2094,7 @@ btr_search_hash_table_validate(ulint hash_table_id)
ib::error() << "Error in an adaptive hash"
<< " index pointer to page "
- << page_id_t(page_get_space_id(page),
- page_get_page_no(page))
+ << block->page.id
<< ", ptr mem address "
<< reinterpret_cast<const void*>(
node->data)
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 6a2bc34c767..e8e9dd37ce1 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -1601,8 +1601,11 @@ buf_chunk_init(
opt_large_page_size is smaller than srv_page_size,
we may allocate one fewer block than requested. When
it is bigger, we may allocate more blocks than requested. */
+ static_assert(sizeof(byte*) == sizeof(ulint), "pointer size");
- frame = (byte*) ut_align(chunk->mem, srv_page_size);
+ frame = reinterpret_cast<byte*>((reinterpret_cast<ulint>(chunk->mem)
+ + srv_page_size - 1)
+ & ~ulint{srv_page_size - 1});
chunk->size = (chunk->mem_pfx.m_size >> srv_page_size_shift)
- (frame != chunk->mem);
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index 4605aa0c5e1..460874e086e 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -71,25 +71,13 @@ buf_dblwr_page_inside(
return(FALSE);
}
-/****************************************************************//**
-Calls buf_page_get() on the TRX_SYS_PAGE and returns a pointer to the
-doublewrite buffer within it.
-@return pointer to the doublewrite buffer within the filespace header
-page. */
-UNIV_INLINE
-byte*
-buf_dblwr_get(
-/*==========*/
- mtr_t* mtr) /*!< in/out: MTR to hold the page latch */
+/** @return the TRX_SYS page */
+inline buf_block_t *buf_dblwr_trx_sys_get(mtr_t *mtr)
{
- buf_block_t* block;
-
- block = buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
- 0, RW_X_LATCH, mtr);
-
- buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
-
- return(buf_block_get_frame(block) + TRX_SYS_DOUBLEWRITE);
+ buf_block_t *block= buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
+ 0, RW_X_LATCH, mtr);
+ buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
+ return block;
}
/********************************************************************//**
@@ -106,12 +94,7 @@ buf_dblwr_sync_datafiles()
/****************************************************************//**
Creates or initialializes the doublewrite buffer at a database start. */
-static
-void
-buf_dblwr_init(
-/*===========*/
- byte* doublewrite) /*!< in: pointer to the doublewrite buf
- header on trx sys page */
+static void buf_dblwr_init(const byte *doublewrite)
{
ulint buf_size;
@@ -143,12 +126,9 @@ buf_dblwr_init(
buf_dblwr->in_use = static_cast<bool*>(
ut_zalloc_nokey(buf_size * sizeof(bool)));
- buf_dblwr->write_buf_unaligned = static_cast<byte*>(
- ut_malloc_nokey((1 + buf_size) << srv_page_size_shift));
-
buf_dblwr->write_buf = static_cast<byte*>(
- ut_align(buf_dblwr->write_buf_unaligned,
- srv_page_size));
+ aligned_malloc(buf_size << srv_page_size_shift,
+ srv_page_size));
buf_dblwr->buf_block_arr = static_cast<buf_page_t**>(
ut_zalloc_nokey(buf_size * sizeof(void*)));
@@ -164,7 +144,6 @@ buf_dblwr_create()
{
buf_block_t* block2;
buf_block_t* new_block;
- byte* doublewrite;
byte* fseg_header;
ulint page_no;
ulint prev_page_no;
@@ -180,14 +159,15 @@ start_again:
mtr.start();
buf_dblwr_being_created = TRUE;
- doublewrite = buf_dblwr_get(&mtr);
+ buf_block_t *trx_sys_block = buf_dblwr_trx_sys_get(&mtr);
- if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC)
+ if (mach_read_from_4(TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC
+ + trx_sys_block->frame)
== TRX_SYS_DOUBLEWRITE_MAGIC_N) {
/* The doublewrite buffer has already been created:
just read in some numbers */
- buf_dblwr_init(doublewrite);
+ buf_dblwr_init(TRX_SYS_DOUBLEWRITE + trx_sys_block->frame);
mtr.commit();
buf_dblwr_being_created = FALSE;
@@ -229,7 +209,8 @@ too_small:
buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK);
- fseg_header = doublewrite + TRX_SYS_DOUBLEWRITE_FSEG;
+ fseg_header = TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG
+ + trx_sys_block->frame;
prev_page_no = 0;
for (i = 0; i < TRX_SYS_DOUBLEWRITE_BLOCKS * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
@@ -265,30 +246,38 @@ too_small:
recv_parse_or_apply_log_rec_body() will see a valid
page type. The flushes of new_block are actually
unnecessary here. */
- ut_d(mlog_write_ulint(FIL_PAGE_TYPE + new_block->frame,
- FIL_PAGE_TYPE_SYS, MLOG_2BYTES, &mtr));
+ ut_d(mtr.write<2>(*new_block,
+ FIL_PAGE_TYPE + new_block->frame,
+ FIL_PAGE_TYPE_SYS));
if (i == FSP_EXTENT_SIZE / 2) {
ut_a(page_no == FSP_EXTENT_SIZE);
- mlog_write_ulint(doublewrite
- + TRX_SYS_DOUBLEWRITE_BLOCK1,
- page_no, MLOG_4BYTES, &mtr);
- mlog_write_ulint(doublewrite
- + TRX_SYS_DOUBLEWRITE_REPEAT
- + TRX_SYS_DOUBLEWRITE_BLOCK1,
- page_no, MLOG_4BYTES, &mtr);
+ mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE
+ + TRX_SYS_DOUBLEWRITE_BLOCK1
+ + trx_sys_block->frame,
+ page_no);
+ mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE
+ + TRX_SYS_DOUBLEWRITE_REPEAT
+ + TRX_SYS_DOUBLEWRITE_BLOCK1
+ + trx_sys_block->frame,
+ page_no);
} else if (i == FSP_EXTENT_SIZE / 2
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
ut_a(page_no == 2 * FSP_EXTENT_SIZE);
- mlog_write_ulint(doublewrite
- + TRX_SYS_DOUBLEWRITE_BLOCK2,
- page_no, MLOG_4BYTES, &mtr);
- mlog_write_ulint(doublewrite
- + TRX_SYS_DOUBLEWRITE_REPEAT
- + TRX_SYS_DOUBLEWRITE_BLOCK2,
- page_no, MLOG_4BYTES, &mtr);
-
+ mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE
+ + TRX_SYS_DOUBLEWRITE_BLOCK2
+ + trx_sys_block->frame,
+ page_no);
+ mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE
+ + TRX_SYS_DOUBLEWRITE_REPEAT
+ + TRX_SYS_DOUBLEWRITE_BLOCK2
+ + trx_sys_block->frame,
+ page_no);
} else if (i > FSP_EXTENT_SIZE / 2) {
ut_a(page_no == prev_page_no + 1);
}
@@ -303,29 +292,32 @@ too_small:
lock the fseg header too many times. Since
this code is not done while any other threads
are active, restart the MTR occasionally. */
- mtr_commit(&mtr);
- mtr_start(&mtr);
- doublewrite = buf_dblwr_get(&mtr);
- fseg_header = doublewrite
- + TRX_SYS_DOUBLEWRITE_FSEG;
+ mtr.commit();
+ mtr.start();
+ trx_sys_block = buf_dblwr_trx_sys_get(&mtr);
+ fseg_header = TRX_SYS_DOUBLEWRITE
+ + TRX_SYS_DOUBLEWRITE_FSEG
+ + trx_sys_block->frame;
}
prev_page_no = page_no;
}
- mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC,
- TRX_SYS_DOUBLEWRITE_MAGIC_N,
- MLOG_4BYTES, &mtr);
- mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC
- + TRX_SYS_DOUBLEWRITE_REPEAT,
- TRX_SYS_DOUBLEWRITE_MAGIC_N,
- MLOG_4BYTES, &mtr);
-
- mlog_write_ulint(doublewrite
- + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED,
- TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N,
- MLOG_4BYTES, &mtr);
- mtr_commit(&mtr);
+ mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC
+ + trx_sys_block->frame,
+ TRX_SYS_DOUBLEWRITE_MAGIC_N);
+ mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC
+ + TRX_SYS_DOUBLEWRITE_REPEAT
+ + trx_sys_block->frame,
+ TRX_SYS_DOUBLEWRITE_MAGIC_N);
+
+ mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED
+ + trx_sys_block->frame,
+ TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N);
+ mtr.commit();
/* Flush the modified pages to disk and make a checkpoint */
log_make_checkpoint();
@@ -360,23 +352,18 @@ buf_dblwr_init_or_load_pages(
ulint space_id;
byte* read_buf;
byte* doublewrite;
- byte* unaligned_read_buf;
ibool reset_space_ids = FALSE;
recv_dblwr_t& recv_dblwr = recv_sys.dblwr;
/* We do the file i/o past the buffer pool */
-
- unaligned_read_buf = static_cast<byte*>(
- ut_malloc_nokey(3U << srv_page_size_shift));
-
read_buf = static_cast<byte*>(
- ut_align(unaligned_read_buf, srv_page_size));
+ aligned_malloc(2 * srv_page_size, srv_page_size));
/* Read the trx sys header to check if we are using the doublewrite
buffer */
dberr_t err;
- IORequest read_request(IORequest::READ);
+ IORequest read_request(IORequest::READ);
err = os_file_read(
read_request,
@@ -387,9 +374,8 @@ buf_dblwr_init_or_load_pages(
ib::error()
<< "Failed to read the system tablespace header page";
-
- ut_free(unaligned_read_buf);
-
+func_exit:
+ aligned_free(read_buf);
return(err);
}
@@ -408,8 +394,8 @@ buf_dblwr_init_or_load_pages(
buf = buf_dblwr->write_buf;
} else {
- ut_free(unaligned_read_buf);
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+ goto func_exit;
}
if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED)
@@ -437,10 +423,7 @@ buf_dblwr_init_or_load_pages(
ib::error()
<< "Failed to read the first double write buffer "
"extent";
-
- ut_free(unaligned_read_buf);
-
- return(err);
+ goto func_exit;
}
err = os_file_read(
@@ -455,10 +438,7 @@ buf_dblwr_init_or_load_pages(
ib::error()
<< "Failed to read the second double write buffer "
"extent";
-
- ut_free(unaligned_read_buf);
-
- return(err);
+ goto func_exit;
}
/* Check if any of these pages is half-written in data files, in the
@@ -485,10 +465,8 @@ buf_dblwr_init_or_load_pages(
+ i - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE;
}
- IORequest write_request(IORequest::WRITE);
-
err = os_file_write(
- write_request, path, file, page,
+ IORequestWrite, path, file, page,
source_page_no << srv_page_size_shift,
srv_page_size);
if (err != DB_SUCCESS) {
@@ -496,10 +474,7 @@ buf_dblwr_init_or_load_pages(
ib::error()
<< "Failed to write to the double write"
" buffer";
-
- ut_free(unaligned_read_buf);
-
- return(err);
+ goto func_exit;
}
} else if (mach_read_from_8(page + FIL_PAGE_LSN)) {
/* Each valid page header must contain
@@ -514,9 +489,8 @@ buf_dblwr_init_or_load_pages(
os_file_flush(file);
}
- ut_free(unaligned_read_buf);
-
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+ goto func_exit;
}
/** Process and remove the double write buffer pages for all tablespaces. */
@@ -525,18 +499,14 @@ buf_dblwr_process()
{
ulint page_no_dblwr = 0;
byte* read_buf;
- byte* unaligned_read_buf;
recv_dblwr_t& recv_dblwr = recv_sys.dblwr;
if (!buf_dblwr) {
return;
}
- unaligned_read_buf = static_cast<byte*>(
- ut_malloc_nokey(3U << srv_page_size_shift));
-
read_buf = static_cast<byte*>(
- ut_align(unaligned_read_buf, srv_page_size));
+ aligned_malloc(2 * srv_page_size, srv_page_size));
byte* const buf = read_buf + srv_page_size;
for (recv_dblwr_t::list::iterator i = recv_dblwr.pages.begin();
@@ -692,7 +662,7 @@ bad:
recv_dblwr.pages.clear();
fil_flush_file_spaces(FIL_TYPE_TABLESPACE);
- ut_free(unaligned_read_buf);
+ aligned_free(read_buf);
}
/****************************************************************//**
@@ -707,15 +677,9 @@ buf_dblwr_free()
os_event_destroy(buf_dblwr->b_event);
os_event_destroy(buf_dblwr->s_event);
- ut_free(buf_dblwr->write_buf_unaligned);
- buf_dblwr->write_buf_unaligned = NULL;
-
+ aligned_free(buf_dblwr->write_buf);
ut_free(buf_dblwr->buf_block_arr);
- buf_dblwr->buf_block_arr = NULL;
-
ut_free(buf_dblwr->in_use);
- buf_dblwr->in_use = NULL;
-
mutex_free(&buf_dblwr->mutex);
ut_free(buf_dblwr);
buf_dblwr = NULL;
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index cb763e6b099..f9d53267728 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -35,24 +35,13 @@ Created 4/18/1996 Heikki Tuuri
#include "log0recv.h"
#include "os0file.h"
-/**********************************************************************//**
-Gets a pointer to the dictionary header and x-latches its page.
-@return pointer to the dictionary header, page x-latched */
-dict_hdr_t*
-dict_hdr_get(
-/*=========*/
- mtr_t* mtr) /*!< in: mtr */
+/** @return the DICT_HDR block, x-latched */
+buf_block_t *dict_hdr_get(mtr_t* mtr)
{
- buf_block_t* block;
- dict_hdr_t* header;
-
- block = buf_page_get(page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO),
- 0, RW_X_LATCH, mtr);
- header = DICT_HDR + buf_block_get_frame(block);
-
- buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
-
- return(header);
+ buf_block_t *block= buf_page_get(page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO),
+ 0, RW_X_LATCH, mtr);
+ buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
+ return block;
}
/**********************************************************************//**
@@ -67,36 +56,41 @@ dict_hdr_get_new_id(
ulint* space_id) /*!< out: space id
(not assigned if NULL) */
{
- dict_hdr_t* dict_hdr;
ib_id_t id;
mtr_t mtr;
- mtr_start(&mtr);
- dict_hdr = dict_hdr_get(&mtr);
+ mtr.start();
+ buf_block_t* dict_hdr = dict_hdr_get(&mtr);
if (table_id) {
- id = mach_read_from_8(dict_hdr + DICT_HDR_TABLE_ID);
+ id = mach_read_from_8(DICT_HDR + DICT_HDR_TABLE_ID
+ + dict_hdr->frame);
id++;
- mlog_write_ull(dict_hdr + DICT_HDR_TABLE_ID, id, &mtr);
+ mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_TABLE_ID
+ + dict_hdr->frame, id);
*table_id = id;
}
if (index_id) {
- id = mach_read_from_8(dict_hdr + DICT_HDR_INDEX_ID);
+ id = mach_read_from_8(DICT_HDR + DICT_HDR_INDEX_ID
+ + dict_hdr->frame);
id++;
- mlog_write_ull(dict_hdr + DICT_HDR_INDEX_ID, id, &mtr);
+ mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_INDEX_ID
+ + dict_hdr->frame, id);
*index_id = id;
}
if (space_id) {
- *space_id = mach_read_from_4(dict_hdr + DICT_HDR_MAX_SPACE_ID);
+ *space_id = mach_read_from_4(DICT_HDR + DICT_HDR_MAX_SPACE_ID
+ + dict_hdr->frame);
if (fil_assign_new_space_id(space_id)) {
- mlog_write_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
- *space_id, MLOG_4BYTES, &mtr);
+ mtr.write<4>(*dict_hdr,
+ DICT_HDR + DICT_HDR_MAX_SPACE_ID
+ + dict_hdr->frame, *space_id);
}
}
- mtr_commit(&mtr);
+ mtr.commit();
}
/**********************************************************************//**
@@ -106,7 +100,6 @@ void
dict_hdr_flush_row_id(void)
/*=======================*/
{
- dict_hdr_t* dict_hdr;
row_id_t id;
mtr_t mtr;
@@ -114,13 +107,13 @@ dict_hdr_flush_row_id(void)
id = dict_sys.row_id;
- mtr_start(&mtr);
+ mtr.start();
- dict_hdr = dict_hdr_get(&mtr);
+ buf_block_t* d = dict_hdr_get(&mtr);
- mlog_write_ull(dict_hdr + DICT_HDR_ROW_ID, id, &mtr);
+ mtr.write<8>(*d, DICT_HDR + DICT_HDR_ROW_ID + d->frame, id);
- mtr_commit(&mtr);
+ mtr.commit();
}
/*****************************************************************//**
@@ -134,7 +127,6 @@ dict_hdr_create(
mtr_t* mtr) /*!< in: mtr */
{
buf_block_t* block;
- dict_hdr_t* dict_header;
ulint root_page_no;
ut_ad(mtr);
@@ -147,24 +139,22 @@ dict_hdr_create(
ut_a(DICT_HDR_PAGE_NO == block->page.id.page_no());
- dict_header = dict_hdr_get(mtr);
+ buf_block_t* d = dict_hdr_get(mtr);
/* Start counting row, table, index, and tree ids from
DICT_HDR_FIRST_ID */
- mlog_write_ull(dict_header + DICT_HDR_ROW_ID,
- DICT_HDR_FIRST_ID, mtr);
-
- mlog_write_ull(dict_header + DICT_HDR_TABLE_ID,
- DICT_HDR_FIRST_ID, mtr);
-
- mlog_write_ull(dict_header + DICT_HDR_INDEX_ID,
- DICT_HDR_FIRST_ID, mtr);
+ mtr->write<8>(*d, DICT_HDR + DICT_HDR_ROW_ID + d->frame,
+ DICT_HDR_FIRST_ID);
+ mtr->write<8>(*d, DICT_HDR + DICT_HDR_TABLE_ID + d->frame,
+ DICT_HDR_FIRST_ID);
+ mtr->write<8>(*d, DICT_HDR + DICT_HDR_INDEX_ID + d->frame,
+ DICT_HDR_FIRST_ID);
- ut_ad(mach_read_from_4(dict_header + DICT_HDR_MAX_SPACE_ID) == 0);
+ ut_ad(!mach_read_from_4(DICT_HDR + DICT_HDR_MAX_SPACE_ID + d->frame));
/* Obsolete, but we must initialize it anyway. */
- mlog_write_ulint(dict_header + DICT_HDR_MIX_ID_LOW,
- DICT_HDR_FIRST_ID, MLOG_4BYTES, mtr);
+ mtr->write<4>(*d, DICT_HDR + DICT_HDR_MIX_ID_LOW + d->frame,
+ DICT_HDR_FIRST_ID);
/* Create the B-tree roots for the clustered indexes of the basic
system tables */
@@ -178,8 +168,7 @@ dict_hdr_create(
return(FALSE);
}
- mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*d, DICT_HDR + DICT_HDR_TABLES + d->frame, root_page_no);
/*--------------------------*/
root_page_no = btr_create(DICT_UNIQUE,
fil_system.sys_space, DICT_TABLE_IDS_ID,
@@ -189,8 +178,8 @@ dict_hdr_create(
return(FALSE);
}
- mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*d, DICT_HDR + DICT_HDR_TABLE_IDS + d->frame,
+ root_page_no);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_COLUMNS_ID,
@@ -200,8 +189,8 @@ dict_hdr_create(
return(FALSE);
}
- mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*d, DICT_HDR + DICT_HDR_COLUMNS + d->frame,
+ root_page_no);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_INDEXES_ID,
@@ -211,8 +200,8 @@ dict_hdr_create(
return(FALSE);
}
- mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*d, DICT_HDR + DICT_HDR_INDEXES + d->frame,
+ root_page_no);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_FIELDS_ID,
@@ -222,8 +211,7 @@ dict_hdr_create(
return(FALSE);
}
- mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*d, DICT_HDR + DICT_HDR_FIELDS + d->frame, root_page_no);
/*--------------------------*/
return(TRUE);
@@ -239,7 +227,6 @@ dict_boot(void)
{
dict_table_t* table;
dict_index_t* index;
- dict_hdr_t* dict_hdr;
mem_heap_t* heap;
mtr_t mtr;
@@ -271,7 +258,7 @@ dict_boot(void)
mutex_enter(&dict_sys.mutex);
/* Get the dictionary header */
- dict_hdr = dict_hdr_get(&mtr);
+ const byte* dict_hdr = &dict_hdr_get(&mtr)->frame[DICT_HDR];
/* Because we only write new row ids to disk-based data structure
(dictionary header) when it is divisible by
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 1d2c570e1a1..19bf3b33cfa 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -373,16 +373,18 @@ dict_build_table_def_step(
mtr.start();
undo->table_id = trx->table_id;
undo->dict_operation = TRUE;
- page_t* page = trx_undo_page_get(
+ buf_block_t* block = trx_undo_page_get(
page_id_t(trx->rsegs.m_redo.rseg->space->id,
undo->hdr_page_no),
&mtr);
- mlog_write_ulint(page + undo->hdr_offset
- + TRX_UNDO_DICT_TRANS,
- TRUE, MLOG_1BYTE, &mtr);
- mlog_write_ull(page + undo->hdr_offset
- + TRX_UNDO_TABLE_ID,
- trx->table_id, &mtr);
+ mtr.write<1,mtr_t::OPT>(
+ *block,
+ block->frame + undo->hdr_offset
+ + TRX_UNDO_DICT_TRANS, 1U);
+ mtr.write<8,mtr_t::OPT>(
+ *block,
+ block->frame + undo->hdr_offset
+ + TRX_UNDO_TABLE_ID, trx->table_id);
mtr.commit();
log_write_up_to(mtr.commit_lsn(), true);
}
@@ -851,14 +853,13 @@ dict_create_index_tree_step(
err = DB_OUT_OF_FILE_SPACE; );
}
- ulint len;
- byte* data = rec_get_nth_field_old(btr_pcur_get_rec(&pcur),
+ ulint len;
+ byte* data = rec_get_nth_field_old(btr_pcur_get_rec(&pcur),
DICT_FLD__SYS_INDEXES__PAGE_NO,
&len);
ut_ad(len == 4);
- if (mach_read_from_4(data) != node->page_no) {
- mlog_write_ulint(data, node->page_no, MLOG_4BYTES, &mtr);
- }
+ mtr.write<4,mtr_t::OPT>(*btr_pcur_get_block(&pcur), data,
+ node->page_no);
mtr.commit();
@@ -898,12 +899,12 @@ dict_create_index_tree_in_mem(
}
/** Drop the index tree associated with a row in SYS_INDEXES table.
-@param[in,out] rec SYS_INDEXES record
@param[in,out] pcur persistent cursor on rec
@param[in,out] trx dictionary transaction
@param[in,out] mtr mini-transaction */
-void dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
+void dict_drop_index_tree(btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
{
+ rec_t* rec = btr_pcur_get_rec(pcur);
byte* ptr;
ulint len;
@@ -924,7 +925,7 @@ void dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
}
compile_time_assert(FIL_NULL == 0xffffffff);
- mlog_memset(ptr, 4, 0xff, mtr);
+ mtr->memset(btr_pcur_get_block(pcur), page_offset(ptr), 4, 0xff);
ptr = rec_get_nth_field_old(
rec, DICT_FLD__SYS_INDEXES__SPACE, &len);
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index b219e4f5860..72112ffc42b 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -4163,7 +4163,7 @@ dict_set_corrupted(
if (len != 4) {
goto fail;
}
- mlog_write_ulint(field, index->type, MLOG_4BYTES, &mtr);
+ mtr.write<4>(*btr_cur_get_block(&cursor), field, index->type);
status = "Flagged";
} else {
fail:
@@ -4263,11 +4263,8 @@ dict_index_set_merge_threshold(
DICT_FLD__SYS_INDEXES__MERGE_THRESHOLD, &len);
ut_ad(len == 4);
-
- if (len == 4) {
- mlog_write_ulint(field, merge_threshold,
- MLOG_4BYTES, &mtr);
- }
+ mtr.write<4,mtr_t::OPT>(*btr_cur_get_block(&cursor), field,
+ merge_threshold);
}
mtr_commit(&mtr);
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index 4b2467127a3..ebb8c4bc24f 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -1481,7 +1481,8 @@ void dict_check_tablespaces_and_store_max_id()
/* Initialize the max space_id from sys header */
mtr.start();
ulint max_space_id = mach_read_from_4(DICT_HDR_MAX_SPACE_ID
- + dict_hdr_get(&mtr));
+ + DICT_HDR
+ + dict_hdr_get(&mtr)->frame);
mtr.commit();
fil_set_max_space_id_if_bigger(max_space_id);
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index 39a83755452..7ffc328726f 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -321,7 +321,6 @@ fil_space_crypt_t* fil_space_read_crypt_data(ulint zip_size, const byte* page)
members */
crypt_data->type = type;
crypt_data->min_key_version = min_key_version;
- crypt_data->page0_offset = offset;
memcpy(crypt_data->iv, page + offset + MAGIC_SZ + 2, iv_length);
return crypt_data;
@@ -354,6 +353,34 @@ fil_space_destroy_crypt_data(
}
}
+/** Amend encryption information from redo log.
+@param[in] space tablespace
+@param[in] data encryption metadata */
+void fil_crypt_parse(fil_space_t* space, const byte* data)
+{
+ ut_ad(data[1] == MY_AES_BLOCK_SIZE);
+ if (void* buf = ut_zalloc_nokey(sizeof(fil_space_crypt_t))) {
+ fil_space_crypt_t* crypt_data = new(buf)
+ fil_space_crypt_t(
+ data[0],
+ mach_read_from_4(&data[2 + MY_AES_BLOCK_SIZE]),
+ mach_read_from_4(&data[6 + MY_AES_BLOCK_SIZE]),
+ static_cast<fil_encryption_t>
+ (data[10 + MY_AES_BLOCK_SIZE]));
+ memcpy(crypt_data->iv, data + 2, MY_AES_BLOCK_SIZE);
+ mutex_enter(&fil_system.mutex);
+ if (space->crypt_data) {
+ fil_space_merge_crypt_data(space->crypt_data,
+ crypt_data);
+ fil_space_destroy_crypt_data(&crypt_data);
+ crypt_data = space->crypt_data;
+ } else {
+ space->crypt_data = crypt_data;
+ }
+ mutex_exit(&fil_system.mutex);
+ }
+}
+
/** Fill crypt data information to the give page.
It should be called during ibd file creation.
@param[in] flags tablespace flags
@@ -367,7 +394,6 @@ fil_space_crypt_t::fill_page0(
const ulint offset = FSP_HEADER_OFFSET
+ fsp_header_get_encryption_offset(
fil_space_t::zip_size(flags));
- page0_offset = offset;
memcpy(page + offset, CRYPT_MAGIC, MAGIC_SZ);
mach_write_to_1(page + offset + MAGIC_SZ, type);
@@ -382,66 +408,34 @@ fil_space_crypt_t::fill_page0(
encryption);
}
-/******************************************************************
-Write crypt data to a page (0)
-@param[in] space tablespace
-@param[in,out] page0 first page of the tablespace
+/** Write encryption metadata to the first page.
+@param[in,out] block first page of the tablespace
@param[in,out] mtr mini-transaction */
-UNIV_INTERN
-void
-fil_space_crypt_t::write_page0(
- const fil_space_t* space,
- byte* page,
- mtr_t* mtr)
+void fil_space_crypt_t::write_page0(buf_block_t* block, mtr_t* mtr)
{
- ut_ad(this == space->crypt_data);
- const uint len = sizeof(iv);
const ulint offset = FSP_HEADER_OFFSET
- + fsp_header_get_encryption_offset(space->zip_size());
- page0_offset = offset;
-
- /*
- redo log this as bytewise updates to page 0
- followed by an MLOG_FILE_WRITE_CRYPT_DATA
- (that will during recovery update fil_space_t)
- */
- mlog_write_string(page + offset, CRYPT_MAGIC, MAGIC_SZ, mtr);
- mlog_write_ulint(page + offset + MAGIC_SZ + 0, type, MLOG_1BYTE, mtr);
- mlog_write_ulint(page + offset + MAGIC_SZ + 1, len, MLOG_1BYTE, mtr);
- mlog_write_string(page + offset + MAGIC_SZ + 2, iv, len,
- mtr);
- mlog_write_ulint(page + offset + MAGIC_SZ + 2 + len, min_key_version,
- MLOG_4BYTES, mtr);
- mlog_write_ulint(page + offset + MAGIC_SZ + 2 + len + 4, key_id,
- MLOG_4BYTES, mtr);
- mlog_write_ulint(page + offset + MAGIC_SZ + 2 + len + 8, encryption,
- MLOG_1BYTE, mtr);
-
- byte* log_ptr = mlog_open(mtr, 11 + 17 + len);
-
- if (log_ptr != NULL) {
- log_ptr = mlog_write_initial_log_record_fast(
- page,
- MLOG_FILE_WRITE_CRYPT_DATA,
- log_ptr, mtr);
- mach_write_to_4(log_ptr, space->id);
- log_ptr += 4;
- mach_write_to_2(log_ptr, offset);
- log_ptr += 2;
- mach_write_to_1(log_ptr, type);
- log_ptr += 1;
- mach_write_to_1(log_ptr, len);
- log_ptr += 1;
- mach_write_to_4(log_ptr, min_key_version);
- log_ptr += 4;
- mach_write_to_4(log_ptr, key_id);
- log_ptr += 4;
- mach_write_to_1(log_ptr, encryption);
- log_ptr += 1;
- mlog_close(mtr, log_ptr);
-
- mlog_catenate_string(mtr, iv, len);
- }
+ + fsp_header_get_encryption_offset(block->zip_size());
+ byte* b = block->frame + offset;
+
+ if (memcmp(b, CRYPT_MAGIC, MAGIC_SZ)) {
+ mtr->memcpy(block, offset, CRYPT_MAGIC, MAGIC_SZ);
+ }
+
+ b += MAGIC_SZ;
+ byte* const start = b;
+ *b++ = static_cast<byte>(type);
+ compile_time_assert(sizeof iv == MY_AES_BLOCK_SIZE);
+ compile_time_assert(sizeof iv == CRYPT_SCHEME_1_IV_LEN);
+ *b++ = sizeof iv;
+ memcpy(b, iv, sizeof iv);
+ b += sizeof iv;
+ mach_write_to_4(b, min_key_version);
+ b += 4;
+ mach_write_to_4(b, key_id);
+ b += 4;
+ *b++ = byte(encryption);
+ ut_ad(b - start == 11 + MY_AES_BLOCK_SIZE);
+ mtr->memcpy(*block, offset + MAGIC_SZ, b - start);
}
/******************************************************************
@@ -475,7 +469,7 @@ fil_parse_write_crypt_data(
ulint space_id = mach_read_from_4(ptr);
ptr += 4;
- uint offset = mach_read_from_2(ptr);
+ // uint offset = mach_read_from_2(ptr);
ptr += 2;
uint type = mach_read_from_1(ptr);
ptr += 1;
@@ -513,7 +507,6 @@ fil_parse_write_crypt_data(
fil_space_crypt_t* crypt_data = fil_space_create_crypt_data(
encryption, key_id);
- crypt_data->page0_offset = offset;
crypt_data->min_key_version = min_key_version;
crypt_data->type = type;
memcpy(crypt_data->iv, ptr, len);
@@ -1254,9 +1247,8 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space)
/* 3 - write crypt data to page 0 */
- byte* frame = buf_block_get_frame(block);
crypt_data->type = CRYPT_SCHEME_1;
- crypt_data->write_page0(space, frame, &mtr);
+ crypt_data->write_page0(block, &mtr);
mtr.commit();
@@ -2034,8 +2026,9 @@ fil_crypt_rotate_page(
modified = true;
/* force rotation by dummy updating page */
- mlog_write_ulint(frame + FIL_PAGE_SPACE_ID,
- space_id, MLOG_4BYTES, &mtr);
+ mtr.write<1,mtr_t::FORCED>(*block,
+ &frame[FIL_PAGE_SPACE_ID],
+ frame[FIL_PAGE_SPACE_ID]);
/* statistics */
state->crypt_stat.pages_modified++;
@@ -2241,7 +2234,7 @@ fil_crypt_flush_space(
RW_X_LATCH, NULL, BUF_GET,
__FILE__, __LINE__, &mtr, &err)) {
mtr.set_named_space(space);
- crypt_data->write_page0(space, block->frame, &mtr);
+ crypt_data->write_page0(block, &mtr);
}
mtr.commit();
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index e97a4e3ae0d..9565435b498 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -1837,12 +1837,10 @@ dberr_t
fil_write_flushed_lsn(
lsn_t lsn)
{
- byte* buf1;
byte* buf;
dberr_t err = DB_TABLESPACE_NOT_FOUND;
- buf1 = static_cast<byte*>(ut_malloc_nokey(2U << srv_page_size_shift));
- buf = static_cast<byte*>(ut_align(buf1, srv_page_size));
+ buf = static_cast<byte*>(aligned_malloc(srv_page_size, srv_page_size));
const page_id_t page_id(TRX_SYS_SPACE, 0);
@@ -1862,7 +1860,7 @@ fil_write_flushed_lsn(
fil_flush_file_spaces(FIL_TYPE_TABLESPACE);
}
- ut_free(buf1);
+ aligned_free(buf);
return(err);
}
@@ -2919,7 +2917,6 @@ fil_ibd_create(
dberr_t* err)
{
pfs_os_file_t file;
- byte* buf2;
byte* page;
bool success;
bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags) != 0;
@@ -2998,9 +2995,9 @@ err_exit:
with zeros from the call of os_file_set_size(), until a buffer pool
flush would write to it. */
- buf2 = static_cast<byte*>(ut_malloc_nokey(3U << srv_page_size_shift));
/* Align the memory for file i/o if we might have O_DIRECT set */
- page = static_cast<byte*>(ut_align(buf2, srv_page_size));
+ page = static_cast<byte*>(aligned_malloc(2 * srv_page_size,
+ srv_page_size));
memset(page, '\0', srv_page_size);
@@ -3048,7 +3045,7 @@ err_exit:
IORequestWrite, path, file, page, 0, srv_page_size);
}
- ut_free(buf2);
+ aligned_free(page);
if (*err != DB_SUCCESS) {
ib::error()
@@ -3899,8 +3896,8 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags)
<< " to " << ib::hex(flags);
}
mtr.set_named_space(space);
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
- + b->frame, flags, MLOG_4BYTES, &mtr);
+ mtr.write<4>(*b, FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
+ + b->frame, flags);
}
func_exit:
mtr.commit();
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index c21a75687e6..1ad73c83e1c 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -291,13 +291,10 @@ Datafile::read_first_page(bool read_only_mode)
}
}
- m_first_page_buf = static_cast<byte*>(
- ut_malloc_nokey(2 * UNIV_PAGE_SIZE_MAX));
-
/* Align the memory for a possible read from a raw device */
m_first_page = static_cast<byte*>(
- ut_align(m_first_page_buf, srv_page_size));
+ aligned_malloc(UNIV_PAGE_SIZE_MAX, srv_page_size));
IORequest request;
dberr_t err = DB_ERROR;
@@ -341,7 +338,17 @@ Datafile::read_first_page(bool read_only_mode)
}
if (m_order == 0) {
- m_space_id = fsp_header_get_space_id(m_first_page);
+ if (memcmp_aligned<4>(FIL_PAGE_SPACE_ID + m_first_page,
+ FSP_HEADER_OFFSET + FSP_SPACE_ID
+ + m_first_page, 4)) {
+ ib::error()
+ << "Inconsistent tablespace ID in "
+ << m_filepath;
+ return DB_CORRUPTION;
+ }
+
+ m_space_id = mach_read_from_4(FIL_PAGE_SPACE_ID
+ + m_first_page);
m_flags = fsp_header_get_flags(m_first_page);
if (!fil_space_t::is_valid_flags(m_flags, m_space_id)) {
ulint cflags = fsp_flags_convert_from_101(m_flags);
@@ -369,14 +376,10 @@ Datafile::read_first_page(bool read_only_mode)
}
/** Free the first page from memory when it is no longer needed. */
-void
-Datafile::free_first_page()
+void Datafile::free_first_page()
{
- if (m_first_page_buf) {
- ut_free(m_first_page_buf);
- m_first_page_buf = NULL;
- m_first_page = NULL;
- }
+ aligned_free(m_first_page);
+ m_first_page= nullptr;
}
/** Validates the datafile and checks that it conforms with the expected
@@ -504,7 +507,6 @@ Datafile::validate_first_page(lsn_t* flush_lsn)
error_txt = "Cannot read first page";
} else {
- ut_ad(m_first_page_buf);
ut_ad(m_first_page);
if (flush_lsn != NULL) {
@@ -653,11 +655,8 @@ Datafile::find_space_id()
<< "Page size:" << page_size
<< ". Pages to analyze:" << page_count;
- byte* buf = static_cast<byte*>(
- ut_malloc_nokey(2 * UNIV_PAGE_SIZE_MAX));
-
byte* page = static_cast<byte*>(
- ut_align(buf, UNIV_SECTOR_SIZE));
+ aligned_malloc(page_size, page_size));
ulint fsp_flags;
/* provide dummy value if the first os_file_read() fails */
@@ -674,19 +673,10 @@ Datafile::find_space_id()
}
for (ulint j = 0; j < page_count; ++j) {
-
- dberr_t err;
- ulint n_bytes = j * page_size;
- IORequest request(IORequest::READ);
-
- err = os_file_read(
- request, m_handle, page, n_bytes, page_size);
-
- if (err != DB_SUCCESS) {
-
+ if (os_file_read(IORequestRead, m_handle, page,
+ j * page_size, page_size)) {
ib::info()
<< "READ FAIL: page_no:" << j;
-
continue;
}
@@ -732,7 +722,7 @@ Datafile::find_space_id()
}
}
- ut_free(buf);
+ aligned_free(page);
ib::info()
<< "Page size: " << page_size
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index b6b244a45ba..260de1eadea 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -59,18 +59,6 @@ fsp_free_extent(
page_no_t offset,
mtr_t* mtr);
-/********************************************************************//**
-Marks a page used. The page must reside within the extents of the given
-segment. */
-static MY_ATTRIBUTE((nonnull))
-void
-fseg_mark_page_used(
-/*================*/
- fseg_inode_t* seg_inode,/*!< in: segment inode */
- page_no_t page, /*!< in: page offset */
- xdes_t* descr, /*!< in: extent descriptor */
- mtr_t* mtr); /*!< in/out: mini-transaction */
-
/** Returns the first extent descriptor for a segment.
We think of the extent lists of the segment catenated in the order
FSEG_FULL -> FSEG_NOT_FULL -> FSEG_FREE.
@@ -100,14 +88,15 @@ void
fsp_fill_free_list(
bool init_space,
fil_space_t* space,
- fsp_header_t* header,
+ buf_block_t* header,
mtr_t* mtr);
/** Allocates a single free page from a segment.
-This function implements the intelligent allocation strategy which tries
-to minimize file space fragmentation.
+This function implements the intelligent allocation strategy which tries to
+minimize file space fragmentation.
@param[in,out] space tablespace
@param[in,out] seg_inode segment inode
+@param[in,out] iblock segment inode page
@param[in] hint hint of which page would be desirable
@param[in] direction if the new page is needed because of
an index page split, and records are inserted there in order, into which
@@ -128,6 +117,7 @@ buf_block_t*
fseg_alloc_free_page_low(
fil_space_t* space,
fseg_inode_t* seg_inode,
+ buf_block_t* iblock,
ulint hint,
byte direction,
rw_lock_type_t rw_latch,
@@ -139,36 +129,35 @@ fseg_alloc_free_page_low(
)
MY_ATTRIBUTE((warn_unused_result));
-/** Gets a pointer to the space header and x-locks its page.
-@param[in] space tablespace
-@param[in,out] mtr mini-transaction
+/** Get the tablespace header block, SX-latched
+@param[in] space tablespace
+@param[in,out] mtr mini-transaction
@return pointer to the space header, page x-locked */
-inline fsp_header_t* fsp_get_space_header(const fil_space_t* space, mtr_t* mtr)
+inline buf_block_t *fsp_get_header(const fil_space_t *space, mtr_t *mtr)
{
- buf_block_t* block;
- fsp_header_t* header;
-
- ut_ad(space->purpose != FIL_TYPE_LOG);
-
- block = buf_page_get(page_id_t(space->id, 0), space->zip_size(),
- RW_SX_LATCH, mtr);
- header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- ut_ad(space->id == mach_read_from_4(FSP_SPACE_ID + header));
- return(header);
+ ut_ad(space->purpose != FIL_TYPE_LOG);
+
+ buf_block_t *block= buf_page_get(page_id_t(space->id, 0), space->zip_size(),
+ RW_SX_LATCH, mtr);
+ buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
+ ut_ad(space->id == mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID +
+ block->frame));
+ return block;
}
/** Set the XDES_FREE_BIT of a page.
@tparam free desired value of XDES_FREE_BIT
+@param[in] block extent descriptor block
@param[in,out] descr extent descriptor
@param[in] offset page offset within the extent
@param[in,out] mtr mini-transaction */
template<bool free>
-inline void xdes_set_free(xdes_t *descr, ulint offset, mtr_t *mtr)
+inline void xdes_set_free(const buf_block_t &block, xdes_t *descr,
+ ulint offset, mtr_t *mtr)
{
ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
ut_ad(offset < FSP_EXTENT_SIZE);
+ ut_ad(page_align(descr) == block.frame);
compile_time_assert(XDES_BITS_PER_PAGE == 2);
compile_time_assert(XDES_FREE_BIT == 0);
compile_time_assert(XDES_CLEAN_BIT == 1);
@@ -181,7 +170,7 @@ inline void xdes_set_free(xdes_t *descr, ulint offset, mtr_t *mtr)
byte val= free
? *b | 1 << (index & 7)
: *b & ~(1 << (index & 7));
- mlog_write_ulint(b, val, MLOG_1BYTE, mtr);
+ mtr->write<1>(block, b, val);
}
/**
@@ -226,22 +215,21 @@ inline bool xdes_is_full(const xdes_t *descr)
return FSP_EXTENT_SIZE == xdes_get_n_used(descr);
}
-/**********************************************************************//**
-Sets the state of an xdes. */
-UNIV_INLINE
-void
-xdes_set_state(
-/*===========*/
- xdes_t* descr, /*!< in/out: descriptor */
- ulint state, /*!< in: state to set */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+/** Set the state of an extent descriptor.
+@param[in] block extent descriptor block
+@param[in,out] descr extent descriptor
+@param[in] state the state
+@param[in,out] mtr mini-transaction */
+inline void xdes_set_state(const buf_block_t &block, xdes_t *descr,
+ byte state, mtr_t *mtr)
{
- ut_ad(descr && mtr);
- ut_ad(state >= XDES_FREE);
- ut_ad(state <= XDES_FSEG);
- ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
-
- mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr);
+ ut_ad(descr && mtr);
+ ut_ad(state >= XDES_FREE);
+ ut_ad(state <= XDES_FSEG);
+ ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(page_align(descr) == block.frame);
+ ut_ad(mach_read_from_4(descr + XDES_STATE) <= XDES_FSEG);
+ mtr->write<1>(block, XDES_STATE + 3 + descr, state);
}
/**********************************************************************//**
@@ -266,48 +254,87 @@ xdes_get_state(
/**********************************************************************//**
Inits an extent descriptor to the free and clean state. */
-UNIV_INLINE
+inline void xdes_init(const buf_block_t &block, xdes_t *descr, mtr_t *mtr)
+{
+ ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
+ mtr->memset(&block, uint16_t(descr - block.frame) + XDES_BITMAP,
+ XDES_SIZE - XDES_BITMAP, 0xff);
+ xdes_set_state(block, descr, XDES_FREE, mtr);
+}
+
+/** Mark a page used in an extent descriptor.
+@param[in,out] seg_inode segment inode
+@param[in,out] iblock segment inode page
+@param[in] page page number
+@param[in,out] descr extent descriptor
+@param[in,out] xdes extent descriptor page
+@param[in,out] mtr mini-transaction */
+static MY_ATTRIBUTE((nonnull))
void
-xdes_init(
-/*======*/
- xdes_t* descr, /*!< in: descriptor */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+fseg_mark_page_used(fseg_inode_t *seg_inode, buf_block_t *iblock,
+ ulint page, xdes_t *descr, buf_block_t *xdes, mtr_t *mtr)
{
- ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
- mlog_memset(descr + XDES_BITMAP, XDES_SIZE - XDES_BITMAP, 0xff, mtr);
- xdes_set_state(descr, XDES_FREE, mtr);
+ ut_ad(fil_page_get_type(iblock->frame) == FIL_PAGE_INODE);
+ ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
+ ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
+ ut_ad(!memcmp(seg_inode + FSEG_ID, descr + XDES_ID, 4));
+
+ const uint16_t xoffset= XDES_FLST_NODE + uint16_t(descr - xdes->frame);
+ const uint16_t ioffset= uint16_t(seg_inode - iblock->frame);
+
+ if (!xdes_get_n_used(descr))
+ {
+ /* We move the extent from the free list to the NOT_FULL list */
+ flst_remove(iblock, FSEG_FREE + ioffset, xdes, xoffset, mtr);
+ flst_add_last(iblock, FSEG_NOT_FULL + ioffset, xdes, xoffset, mtr);
+ }
+
+ ut_ad(xdes_is_free(descr, page % FSP_EXTENT_SIZE));
+
+ /* We mark the page as used */
+ xdes_set_free<false>(*xdes, descr, page % FSP_EXTENT_SIZE, mtr);
+
+ byte* p_not_full= seg_inode + FSEG_NOT_FULL_N_USED;
+ const uint32_t not_full_n_used= mach_read_from_4(p_not_full) + 1;
+ mtr->write<4>(*iblock, p_not_full, not_full_n_used);
+ if (xdes_is_full(descr))
+ {
+ /* We move the extent from the NOT_FULL list to the FULL list */
+ flst_remove(iblock, FSEG_NOT_FULL + ioffset, xdes, xoffset, mtr);
+ flst_add_last(iblock, FSEG_FULL + ioffset, xdes, xoffset, mtr);
+ mtr->write<4>(*iblock, seg_inode + FSEG_NOT_FULL_N_USED,
+ not_full_n_used - FSP_EXTENT_SIZE);
+ }
}
/** Get pointer to a the extent descriptor of a page.
@param[in,out] sp_header tablespace header page, x-latched
@param[in] space tablespace
@param[in] offset page offset
+@param[out] desc_block descriptor block
@param[in,out] mtr mini-transaction
@param[in] init_space whether the tablespace is being initialized
-@param[out] desc_block descriptor block, or NULL if it is
-the same as the tablespace header
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds free limit */
UNIV_INLINE MY_ATTRIBUTE((warn_unused_result))
xdes_t*
xdes_get_descriptor_with_space_hdr(
- fsp_header_t* sp_header,
+ buf_block_t* header,
const fil_space_t* space,
page_no_t offset,
+ buf_block_t** desc_block,
mtr_t* mtr,
- bool init_space = false,
- buf_block_t** desc_block = NULL)
+ bool init_space = false)
{
ulint limit;
ulint size;
ulint descr_page_no;
- page_t* descr_page;
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_SX_FIX));
- ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
+ ut_ad(mtr_memo_contains(mtr, header, MTR_MEMO_PAGE_SX_FIX));
/* Read free limit and space size */
- limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
- size = mach_read_from_4(sp_header + FSP_SIZE);
+ limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ + header->frame);
+ size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE + header->frame);
ut_ad(limit == space->free_limit
|| (space->free_limit == 0
&& (init_space
@@ -325,29 +352,23 @@ xdes_get_descriptor_with_space_hdr(
descr_page_no = xdes_calc_descriptor_page(zip_size, offset);
- buf_block_t* block;
+ buf_block_t* block = header;
- if (descr_page_no == 0) {
- /* It is on the space header page */
-
- descr_page = page_align(sp_header);
- block = NULL;
- } else {
+ if (descr_page_no) {
block = buf_page_get(
page_id_t(space->id, descr_page_no), zip_size,
RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- descr_page = buf_block_get_frame(block);
}
if (desc_block != NULL) {
*desc_block = block;
}
- return(descr_page + XDES_ARR_OFFSET
- + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset));
+ return XDES_ARR_OFFSET + XDES_SIZE
+ * xdes_calc_descriptor_index(zip_size, offset)
+ + block->frame;
}
/** Get the extent descriptor of a page.
@@ -359,24 +380,16 @@ defined, as they are uninitialized above the free limit.
@param[in] space tablespace
@param[in] offset page offset; if equal to the free limit, we
try to add new extents to the space free list
+@param[out] xdes extent descriptor page
@param[in,out] mtr mini-transaction
@return the extent descriptor */
-MY_ATTRIBUTE((warn_unused_result))
-static
-xdes_t*
-xdes_get_descriptor(const fil_space_t* space, page_no_t offset, mtr_t* mtr)
+static xdes_t* xdes_get_descriptor(const fil_space_t *space, page_no_t offset,
+ buf_block_t **xdes, mtr_t *mtr)
{
- buf_block_t* block;
- fsp_header_t* sp_header;
-
- block = buf_page_get(page_id_t(space->id, 0), space->zip_size(),
- RW_SX_LATCH, mtr);
-
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
- return(xdes_get_descriptor_with_space_hdr(
- sp_header, space, offset, mtr));
+ buf_block_t *block= buf_page_get(page_id_t(space->id, 0), space->zip_size(),
+ RW_SX_LATCH, mtr);
+ buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
+ return xdes_get_descriptor_with_space_hdr(block, space, offset, xdes, mtr);
}
/** Get the extent descriptor of a page.
@@ -429,6 +442,7 @@ extent descriptor resides is x-locked.
@param[in] space tablespace
@param[in] lst_node file address of the list node
contained in the descriptor
+@param[out] block extent descriptor block
@param[in,out] mtr mini-transaction
@return pointer to the extent descriptor */
MY_ATTRIBUTE((nonnull, warn_unused_result))
@@ -437,11 +451,12 @@ xdes_t*
xdes_lst_get_descriptor(
const fil_space_t* space,
fil_addr_t lst_node,
+ buf_block_t** block,
mtr_t* mtr)
{
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
return fut_get_ptr(space->id, space->zip_size(),
- lst_node, RW_SX_LATCH, mtr)
+ lst_node, RW_SX_LATCH, mtr, block)
- XDES_FLST_NODE;
}
@@ -559,20 +574,20 @@ void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr)
fsp_init_file_page(space, block, mtr);
- mlog_write_ulint(block->frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_FSP_HDR,
- MLOG_2BYTES, mtr);
+ mtr->write<2>(*block, block->frame + FIL_PAGE_TYPE,
+ FIL_PAGE_TYPE_FSP_HDR);
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_ID + block->frame,
- space->id, MLOG_4BYTES, mtr);
+ mtr->write<4,mtr_t::OPT>(*block, FSP_HEADER_OFFSET + FSP_SPACE_ID
+ + block->frame, space->id);
ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_NOT_USED
+ block->frame));
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SIZE + block->frame, size,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*block, FSP_HEADER_OFFSET + FSP_SIZE + block->frame,
+ size);
ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ block->frame));
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + block->frame,
- space->flags & ~FSP_FLAGS_MEM_MASK,
- MLOG_4BYTES, mtr);
+ mtr->write<4,mtr_t::OPT>(*block, FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
+ + block->frame,
+ space->flags & ~FSP_FLAGS_MEM_MASK);
ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ block->frame));
@@ -582,45 +597,19 @@ void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr)
flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, mtr);
flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, mtr);
- mlog_write_ull(FSP_HEADER_OFFSET + FSP_SEG_ID + block->frame, 1, mtr);
+ mtr->write<8>(*block, FSP_HEADER_OFFSET + FSP_SEG_ID + block->frame,
+ 1U);
fsp_fill_free_list(!is_system_tablespace(space->id),
- space, FSP_HEADER_OFFSET + block->frame, mtr);
+ space, block, mtr);
/* Write encryption metadata to page 0 if tablespace is
encrypted or encryption is disabled by table option. */
if (space->crypt_data &&
(space->crypt_data->should_encrypt() ||
space->crypt_data->not_encrypted())) {
- space->crypt_data->write_page0(space, block->frame, mtr);
- }
-}
-
-/**********************************************************************//**
-Reads the space id from the first page of a tablespace.
-@return space id, ULINT UNDEFINED if error */
-ulint
-fsp_header_get_space_id(
-/*====================*/
- const page_t* page) /*!< in: first page of a tablespace */
-{
- ulint fsp_id;
- ulint id;
-
- fsp_id = mach_read_from_4(FSP_HEADER_OFFSET + page + FSP_SPACE_ID);
-
- id = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
-
- DBUG_EXECUTE_IF("fsp_header_get_space_id_failure",
- id = ULINT_UNDEFINED;);
-
- if (id != fsp_id) {
- ib::error() << "Space ID in fsp header is " << fsp_id
- << ", but in the page header it is " << id << ".";
- return(ULINT_UNDEFINED);
+ space->crypt_data->write_page0(block, mtr);
}
-
- return(id);
}
/** Try to extend a single-table tablespace so that a page would fit in the
@@ -635,7 +624,7 @@ bool
fsp_try_extend_data_file_with_pages(
fil_space_t* space,
ulint page_no,
- fsp_header_t* header,
+ buf_block_t* header,
mtr_t* mtr)
{
bool success;
@@ -644,14 +633,15 @@ fsp_try_extend_data_file_with_pages(
ut_a(!is_system_tablespace(space->id));
ut_d(space->modify_check(*mtr));
- size = mach_read_from_4(header + FSP_SIZE);
+ size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE + header->frame);
ut_ad(size == space->size_in_header);
ut_a(page_no >= size);
success = fil_space_extend(space, page_no + 1);
/* The size may be less than we wanted if we ran out of disk space. */
- mlog_write_ulint(header + FSP_SIZE, space->size, MLOG_4BYTES, mtr);
+ mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_SIZE + header->frame,
+ space->size);
space->size_in_header = space->size;
return(success);
@@ -704,7 +694,7 @@ static ulint fsp_get_pages_to_extend_ibd(ulint physical_size, ulint size)
ATTRIBUTE_COLD __attribute__((nonnull))
static
ulint
-fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
+fsp_try_extend_data_file(fil_space_t *space, buf_block_t *header, mtr_t *mtr)
{
ulint size; /* current number of pages in the datafile */
ulint size_increase; /* number of pages to extend this file */
@@ -744,7 +734,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
return(0);
}
- size = mach_read_from_4(header + FSP_SIZE);
+ size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE + header->frame);
ut_ad(size == space->size_in_header);
const ulint ps = space->physical_size();
@@ -784,8 +774,8 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
space->size_in_header = ut_2pow_round(space->size, (1024 * 1024) / ps);
- mlog_write_ulint(
- header + FSP_SIZE, space->size_in_header, MLOG_4BYTES, mtr);
+ mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_SIZE + header->frame,
+ space->size_in_header);
return(size_increase);
}
@@ -803,7 +793,7 @@ void fil_block_reset_type(const buf_block_t& block, ulint type, mtr_t* mtr)
ib::info()
<< "Resetting invalid page " << block.page.id << " type "
<< fil_page_get_type(block.frame) << " to " << type << ".";
- mlog_write_ulint(block.frame + FIL_PAGE_TYPE, type, MLOG_2BYTES, mtr);
+ mtr->write<2>(block, block.frame + FIL_PAGE_TYPE, type);
}
/** Put new extents to the free list if there are free extents above the free
@@ -820,22 +810,21 @@ void
fsp_fill_free_list(
bool init_space,
fil_space_t* space,
- fsp_header_t* header,
+ buf_block_t* header,
mtr_t* mtr)
{
ulint limit;
ulint size;
xdes_t* descr;
ulint count = 0;
- ulint frag_n_used;
ulint i;
- ut_ad(page_offset(header) == FSP_HEADER_OFFSET);
ut_d(space->modify_check(*mtr));
/* Check if we can fill free list from above the free list limit */
- size = mach_read_from_4(header + FSP_SIZE);
- limit = mach_read_from_4(header + FSP_FREE_LIMIT);
+ size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE + header->frame);
+ limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ + header->frame);
ut_ad(size == space->size_in_header);
ut_ad(limit == space->free_limit);
@@ -868,8 +857,8 @@ fsp_fill_free_list(
== ut_2pow_remainder(i, ulint(space->physical_size()));
space->free_limit = i + FSP_EXTENT_SIZE;
- mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ + header->frame, i + FSP_EXTENT_SIZE);
if (init_xdes) {
@@ -891,10 +880,9 @@ fsp_fill_free_list(
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
fsp_init_file_page(space, block, mtr);
- mlog_write_ulint(buf_block_get_frame(block)
- + FIL_PAGE_TYPE,
- FIL_PAGE_TYPE_XDES,
- MLOG_2BYTES, mtr);
+ mtr->write<2>(*block,
+ FIL_PAGE_TYPE + block->frame,
+ FIL_PAGE_TYPE_XDES);
}
/* Initialize the ibuf bitmap page in a separate
@@ -905,7 +893,7 @@ fsp_fill_free_list(
if (space->purpose != FIL_TYPE_TEMPORARY) {
mtr_t ibuf_mtr;
- mtr_start(&ibuf_mtr);
+ ibuf_mtr.start();
ibuf_mtr.set_named_space(space);
const page_id_t page_id(
@@ -922,21 +910,22 @@ fsp_fill_free_list(
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
fsp_init_file_page(space, block, &ibuf_mtr);
- mlog_write_ulint(block->frame + FIL_PAGE_TYPE,
- FIL_PAGE_IBUF_BITMAP,
- MLOG_2BYTES, &ibuf_mtr);
- mtr_commit(&ibuf_mtr);
+ ibuf_mtr.write<2>(*block,
+ block->frame + FIL_PAGE_TYPE,
+ FIL_PAGE_IBUF_BITMAP);
+ ibuf_mtr.commit();
}
}
- buf_block_t* desc_block = NULL;
+ buf_block_t* xdes;
descr = xdes_get_descriptor_with_space_hdr(
- header, space, i, mtr, init_space, &desc_block);
- if (desc_block && !space->full_crc32()) {
- fil_block_check_type(
- *desc_block, FIL_PAGE_TYPE_XDES, mtr);
+ header, space, i, &xdes, mtr, init_space);
+ if (xdes != header && !space->full_crc32()) {
+ fil_block_check_type(*xdes, FIL_PAGE_TYPE_XDES, mtr);
}
- xdes_init(descr, mtr);
+ xdes_init(*xdes, descr, mtr);
+ const uint16_t xoffset= XDES_FLST_NODE
+ + uint16_t(descr - xdes->frame);
if (UNIV_UNLIKELY(init_xdes)) {
@@ -944,20 +933,21 @@ fsp_fill_free_list(
and the second is an ibuf bitmap page: mark them
used */
- xdes_set_free<false>(descr, 0, mtr);
- xdes_set_free<false>(descr, FSP_IBUF_BITMAP_OFFSET,
- mtr);
- xdes_set_state(descr, XDES_FREE_FRAG, mtr);
-
- flst_add_last(header + FSP_FREE_FRAG,
- descr + XDES_FLST_NODE, mtr);
- frag_n_used = mach_read_from_4(
- header + FSP_FRAG_N_USED);
- mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used + 2, MLOG_4BYTES, mtr);
+ xdes_set_free<false>(*xdes, descr, 0, mtr);
+ xdes_set_free<false>(*xdes, descr,
+ FSP_IBUF_BITMAP_OFFSET, mtr);
+ xdes_set_state(*xdes, descr, XDES_FREE_FRAG, mtr);
+
+ flst_add_last(header,
+ FSP_HEADER_OFFSET + FSP_FREE_FRAG,
+ xdes, xoffset, mtr);
+ byte* n_used = FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ + header->frame;
+ mtr->write<4>(*header, n_used,
+ 2U + mach_read_from_4(n_used));
} else {
- flst_add_last(header + FSP_FREE,
- descr + XDES_FLST_NODE, mtr);
+ flst_add_last(header, FSP_HEADER_OFFSET + FSP_FREE,
+ xdes, xoffset, mtr);
count++;
}
@@ -971,6 +961,7 @@ fsp_fill_free_list(
@param[in,out] space tablespace
@param[in] hint hint of which extent would be desirable: any
page offset in the extent goes; the hint must not be > FSP_FREE_LIMIT
+@param[out] xdes extent descriptor page
@param[in,out] mtr mini-transaction
@return extent descriptor, NULL if cannot be allocated */
static
@@ -978,19 +969,19 @@ xdes_t*
fsp_alloc_free_extent(
fil_space_t* space,
ulint hint,
+ buf_block_t** xdes,
mtr_t* mtr)
{
- fsp_header_t* header;
fil_addr_t first;
xdes_t* descr;
buf_block_t* desc_block = NULL;
- header = fsp_get_space_header(space, mtr);
+ buf_block_t* header = fsp_get_header(space, mtr);
descr = xdes_get_descriptor_with_space_hdr(
- header, space, hint, mtr, false, &desc_block);
+ header, space, hint, &desc_block, mtr);
- if (desc_block && !space->full_crc32()) {
+ if (desc_block != header && !space->full_crc32()) {
fil_block_check_type(*desc_block, FIL_PAGE_TYPE_XDES, mtr);
}
@@ -998,12 +989,14 @@ fsp_alloc_free_extent(
/* Ok, we can take this extent */
} else {
/* Take the first extent in the free list */
- first = flst_get_first(header + FSP_FREE);
+ first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE
+ + header->frame);
if (fil_addr_is_null(first)) {
fsp_fill_free_list(false, space, header, mtr);
- first = flst_get_first(header + FSP_FREE);
+ first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE
+ + header->frame);
}
if (fil_addr_is_null(first)) {
@@ -1011,49 +1004,52 @@ fsp_alloc_free_extent(
return(NULL); /* No free extents left */
}
- descr = xdes_lst_get_descriptor(space, first, mtr);
+ descr = xdes_lst_get_descriptor(space, first, &desc_block,
+ mtr);
}
- flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
+ flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE,
+ desc_block, uint16_t(descr - desc_block->frame)
+ + XDES_FLST_NODE, mtr);
space->free_len--;
+ *xdes = desc_block;
return(descr);
}
-/**********************************************************************//**
-Allocates a single free page from a space. */
-static MY_ATTRIBUTE((nonnull))
-void
-fsp_alloc_from_free_frag(
-/*=====================*/
- fsp_header_t* header, /*!< in/out: tablespace header */
- xdes_t* descr, /*!< in/out: extent descriptor */
- ulint bit, /*!< in: slot to allocate in the extent */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+/** Allocate a single free page.
+@param[in,out] header tablespace header
+@param[in,out] xdes extent descriptor page
+@param[in,out] descr extent descriptor
+@param[in] bit slot to allocate in the extent
+@param[in,out] mtr mini-transaction */
+static void
+fsp_alloc_from_free_frag(buf_block_t *header, buf_block_t *xdes, xdes_t *descr,
+ ulint bit, mtr_t *mtr)
{
- ulint frag_n_used;
-
ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
ut_a(xdes_is_free(descr, bit));
- xdes_set_free<false>(descr, bit, mtr);
+ xdes_set_free<false>(*xdes, descr, bit, mtr);
/* Update the FRAG_N_USED field */
- frag_n_used = mach_read_from_4(header + FSP_FRAG_N_USED);
- frag_n_used++;
- mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
- mtr);
+ byte* n_used_p = FSP_HEADER_OFFSET + FSP_FRAG_N_USED + header->frame;
+
+ uint32_t n_used = mach_read_from_4(n_used_p) + 1;
+
if (xdes_is_full(descr)) {
/* The fragment is full: move it to another list */
- flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
- mtr);
- xdes_set_state(descr, XDES_FULL_FRAG, mtr);
+ const uint16_t xoffset= XDES_FLST_NODE
+ + uint16_t(descr - xdes->frame);
+ flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
+ xdes, xoffset, mtr);
+ xdes_set_state(*xdes, descr, XDES_FULL_FRAG, mtr);
- flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
- mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
- mtr);
+ flst_add_last(header, FSP_HEADER_OFFSET + FSP_FULL_FRAG,
+ xdes, xoffset, mtr);
+ n_used -= FSP_EXTENT_SIZE;
}
+
+ mtr->write<4>(*header, n_used_p, n_used);
}
/** Gets a buffer block for an allocated page.
@@ -1132,23 +1128,25 @@ fsp_alloc_free_page(
mtr_t* mtr,
mtr_t* init_mtr)
{
- fsp_header_t* header;
fil_addr_t first;
xdes_t* descr;
ulint free;
const ulint space_id = space->id;
ut_d(space->modify_check(*mtr));
- header = fsp_get_space_header(space, mtr);
+ buf_block_t* block = fsp_get_header(space, mtr);
+ buf_block_t *xdes;
/* Get the hinted descriptor */
- descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
+ descr = xdes_get_descriptor_with_space_hdr(block, space, hint, &xdes,
+ mtr);
if (descr && (xdes_get_state(descr, mtr) == XDES_FREE_FRAG)) {
/* Ok, we can take this extent */
} else {
/* Else take the first extent in free_frag list */
- first = flst_get_first(header + FSP_FREE_FRAG);
+ first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE_FRAG
+ + block->frame);
if (fil_addr_is_null(first)) {
/* There are no partially full fragments: allocate
@@ -1158,7 +1156,7 @@ fsp_alloc_free_page(
FREE_FRAG list. But we will allocate our page from the
the free extent anyway. */
- descr = fsp_alloc_free_extent(space, hint, mtr);
+ descr = fsp_alloc_free_extent(space, hint, &xdes, mtr);
if (descr == NULL) {
/* No free space left */
@@ -1166,11 +1164,13 @@ fsp_alloc_free_page(
return(NULL);
}
- xdes_set_state(descr, XDES_FREE_FRAG, mtr);
- flst_add_last(header + FSP_FREE_FRAG,
- descr + XDES_FLST_NODE, mtr);
+ xdes_set_state(*xdes, descr, XDES_FREE_FRAG, mtr);
+ flst_add_last(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
+ xdes, XDES_FLST_NODE
+ + uint16_t(descr - xdes->frame), mtr);
} else {
- descr = xdes_lst_get_descriptor(space, first, mtr);
+ descr = xdes_lst_get_descriptor(space, first, &xdes,
+ mtr);
}
/* Reset the hint */
@@ -1191,7 +1191,8 @@ fsp_alloc_free_page(
page_no_t page_no = xdes_get_offset(descr) + free;
- page_no_t space_size = mach_read_from_4(header + FSP_SIZE);
+ page_no_t space_size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
+ + block->frame);
ut_ad(space_size == space->size_in_header
|| (space_id == TRX_SYS_SPACE
&& srv_startup_is_before_trx_rollback_phase));
@@ -1210,13 +1211,13 @@ fsp_alloc_free_page(
}
if (!fsp_try_extend_data_file_with_pages(space, page_no,
- header, mtr)) {
+ block, mtr)) {
/* No disk space left */
return(NULL);
}
}
- fsp_alloc_from_free_frag(header, descr, free, mtr);
+ fsp_alloc_from_free_frag(block, xdes, descr, free, mtr);
return fsp_page_create(space, page_no, rw_latch, mtr, init_mtr);
}
@@ -1229,7 +1230,6 @@ The page is marked as free and clean.
static void fsp_free_page(fil_space_t* space, page_no_t offset,
bool log, mtr_t* mtr)
{
- fsp_header_t* header;
xdes_t* descr;
ulint state;
ulint frag_n_used;
@@ -1239,10 +1239,11 @@ static void fsp_free_page(fil_space_t* space, page_no_t offset,
/* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */
- header = fsp_get_space_header(space, mtr);
+ buf_block_t* header = fsp_get_header(space, mtr);
+ buf_block_t* xdes;
- descr = xdes_get_descriptor_with_space_hdr(
- header, space, offset, mtr);
+ descr = xdes_get_descriptor_with_space_hdr(header, space, offset,
+ &xdes, mtr);
state = xdes_get_state(descr, mtr);
@@ -1292,56 +1293,57 @@ static void fsp_free_page(fil_space_t* space, page_no_t offset,
const ulint bit = offset % FSP_EXTENT_SIZE;
- xdes_set_free<true>(descr, bit, mtr);
+ xdes_set_free<true>(*xdes, descr, bit, mtr);
+
+ frag_n_used = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ + header->frame);
- frag_n_used = mach_read_from_4(header + FSP_FRAG_N_USED);
+ const uint16_t xoffset= XDES_FLST_NODE + uint16_t(descr - xdes->frame);
if (state == XDES_FULL_FRAG) {
/* The fragment was full: move it to another list */
- flst_remove(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
- mtr);
- xdes_set_state(descr, XDES_FREE_FRAG, mtr);
- flst_add_last(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
- mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used + FSP_EXTENT_SIZE - 1,
- MLOG_4BYTES, mtr);
+ flst_remove(header, FSP_HEADER_OFFSET + FSP_FULL_FRAG,
+ xdes, xoffset, mtr);
+ xdes_set_state(*xdes, descr, XDES_FREE_FRAG, mtr);
+ flst_add_last(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
+ xdes, xoffset, mtr);
+ mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ + header->frame,
+ frag_n_used + FSP_EXTENT_SIZE - 1);
} else {
ut_a(frag_n_used > 0);
- mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used - 1,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*header, FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ + header->frame, frag_n_used - 1);
}
if (!xdes_get_n_used(descr)) {
/* The extent has become free: move it to another list */
- flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
- mtr);
+ flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
+ xdes, xoffset, mtr);
fsp_free_extent(space, offset, mtr);
}
}
/** Return an extent to the free list of a space.
-@param[in,out] space tablespace
-@param[in] offset page number in the extent
-@param[in,out] mtr mini-transaction */
+@param[in,out] space tablespace
+@param[in] offset page number in the extent
+@param[in,out] mtr mini-transaction */
static void fsp_free_extent(fil_space_t* space, page_no_t offset, mtr_t* mtr)
{
- fsp_header_t* header;
- xdes_t* descr;
+ ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
+ buf_block_t *block= fsp_get_header(space, mtr);
+ buf_block_t *xdes;
- header = fsp_get_space_header(space, mtr);
+ xdes_t* descr= xdes_get_descriptor_with_space_hdr(block, space, offset,
+ &xdes, mtr);
+ ut_a(xdes_get_state(descr, mtr) != XDES_FREE);
- descr = xdes_get_descriptor_with_space_hdr(
- header, space, offset, mtr);
-
- ut_a(xdes_get_state(descr, mtr) != XDES_FREE);
+ xdes_init(*xdes, descr, mtr);
- xdes_init(descr, mtr);
-
- flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
- space->free_len++;
+ flst_add_last(block, FSP_HEADER_OFFSET + FSP_FREE,
+ xdes, XDES_FLST_NODE + uint16_t(descr - xdes->frame), mtr);
+ space->free_len++;
}
/** @return Number of segment inodes which fit on a single page */
@@ -1407,79 +1409,63 @@ fsp_seg_inode_page_find_free(const page_t* page, ulint i, ulint physical_size)
}
/** Allocate a file segment inode page.
-@param[in,out] space tablespace
-@param[in,out] space_header tablespace header
-@param[in,out] mtr mini-transaction
+@param[in,out] space tablespace
+@param[in,out] header tablespace header
+@param[in,out] mtr mini-transaction
@return whether the allocation succeeded */
MY_ATTRIBUTE((nonnull, warn_unused_result))
static
bool
-fsp_alloc_seg_inode_page(
- fil_space_t* space,
- fsp_header_t* space_header,
- mtr_t* mtr)
+fsp_alloc_seg_inode_page(fil_space_t *space, buf_block_t *header, mtr_t *mtr)
{
- buf_block_t* block;
-
- ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
- ut_ad(page_get_space_id(page_align(space_header)) == space->id);
-
- block = fsp_alloc_free_page(space, 0, RW_SX_LATCH, mtr, mtr);
+ ut_ad(header->page.id.space() == space->id);
+ buf_block_t *block= fsp_alloc_free_page(space, 0, RW_SX_LATCH, mtr, mtr);
- if (block == NULL) {
+ if (!block)
+ return false;
- return(false);
- }
+ buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
+ ut_ad(rw_lock_get_sx_lock_count(&block->lock) == 1);
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
- ut_ad(rw_lock_get_sx_lock_count(&block->lock) == 1);
-
- mlog_write_ulint(block->frame + FIL_PAGE_TYPE, FIL_PAGE_INODE,
- MLOG_2BYTES, mtr);
+ mtr->write<2>(*block, block->frame + FIL_PAGE_TYPE, FIL_PAGE_INODE);
#ifdef UNIV_DEBUG
- const byte* inode = FSEG_ID + FSEG_ARR_OFFSET + block->frame;
- for (ulint i = FSP_SEG_INODES_PER_PAGE(space->physical_size()); i--;
- inode += FSEG_INODE_SIZE) {
- ut_ad(!mach_read_from_8(inode));
- }
+ const byte *inode= FSEG_ID + FSEG_ARR_OFFSET + block->frame;
+ for (ulint i= FSP_SEG_INODES_PER_PAGE(space->physical_size()); i--;
+ inode += FSEG_INODE_SIZE)
+ ut_ad(!mach_read_from_8(inode));
#endif
- flst_add_last(
- space_header + FSP_SEG_INODES_FREE,
- block->frame + FSEG_INODE_PAGE_NODE, mtr);
-
- return(true);
+ flst_add_last(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE,
+ block, FSEG_INODE_PAGE_NODE, mtr);
+ return true;
}
/** Allocate a file segment inode.
-@param[in,out] space tablespace
-@param[in,out] space_header tablespace header
-@param[in,out] mtr mini-transaction
+@param[in,out] space tablespace
+@param[in,out] header tablespace header
+@param[out] iblock segment inode page
+@param[in,out] mtr mini-transaction
@return segment inode
@retval NULL if not enough space */
MY_ATTRIBUTE((nonnull, warn_unused_result))
-static
-fseg_inode_t*
-fsp_alloc_seg_inode(
- fil_space_t* space,
- fsp_header_t* space_header,
- mtr_t* mtr)
+static fseg_inode_t*
+fsp_alloc_seg_inode(fil_space_t *space, buf_block_t *header,
+ buf_block_t **iblock, mtr_t *mtr)
{
buf_block_t* block;
- page_t* page;
fseg_inode_t* inode;
- ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
-
/* Allocate a new segment inode page if needed. */
- if (flst_get_len(space_header + FSP_SEG_INODES_FREE) == 0
- && !fsp_alloc_seg_inode_page(space, space_header, mtr)) {
+ if (!flst_get_len(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE
+ + header->frame)
+ && !fsp_alloc_seg_inode_page(space, header, mtr)) {
return(NULL);
}
const page_id_t page_id(
space->id,
- flst_get_first(space_header + FSP_SEG_INODES_FREE).page);
+ flst_get_first(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE
+ + header->frame).page);
block = buf_page_get(page_id, space->zip_size(), RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
@@ -1487,79 +1473,68 @@ fsp_alloc_seg_inode(
fil_block_check_type(*block, FIL_PAGE_INODE, mtr);
}
- page = buf_block_get_frame(block);
-
const ulint physical_size = space->physical_size();
- ulint n = fsp_seg_inode_page_find_free(page, 0, physical_size);
+ ulint n = fsp_seg_inode_page_find_free(block->frame, 0, physical_size);
ut_a(n < FSP_SEG_INODES_PER_PAGE(physical_size));
- inode = fsp_seg_inode_page_get_nth_inode(page, n);
+ inode = fsp_seg_inode_page_get_nth_inode(block->frame, n);
- if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1,
+ if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(block->frame,
+ n + 1,
physical_size)) {
/* There are no other unused headers left on the page: move it
to another list */
-
- flst_remove(space_header + FSP_SEG_INODES_FREE,
- page + FSEG_INODE_PAGE_NODE, mtr);
-
- flst_add_last(space_header + FSP_SEG_INODES_FULL,
- page + FSEG_INODE_PAGE_NODE, mtr);
+ flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE,
+ block, FSEG_INODE_PAGE_NODE, mtr);
+ flst_add_last(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL,
+ block, FSEG_INODE_PAGE_NODE, mtr);
}
ut_ad(!mach_read_from_8(inode + FSEG_ID)
|| mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
+ *iblock = block;
return(inode);
}
/** Frees a file segment inode.
@param[in,out] space tablespace
@param[in,out] inode segment inode
+@param[in,out] iblock segment inode page
@param[in,out] mtr mini-transaction */
static void fsp_free_seg_inode(
fil_space_t* space,
fseg_inode_t* inode,
+ buf_block_t* iblock,
mtr_t* mtr)
{
- page_t* page;
- fsp_header_t* space_header;
-
ut_d(space->modify_check(*mtr));
- page = page_align(inode);
-
- space_header = fsp_get_space_header(space, mtr);
+ buf_block_t* header = fsp_get_header(space, mtr);
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
const ulint physical_size = space->physical_size();
if (ULINT_UNDEFINED
- == fsp_seg_inode_page_find_free(page, 0, physical_size)) {
-
+ == fsp_seg_inode_page_find_free(iblock->frame, 0, physical_size)) {
/* Move the page to another list */
-
- flst_remove(space_header + FSP_SEG_INODES_FULL,
- page + FSEG_INODE_PAGE_NODE, mtr);
-
- flst_add_last(space_header + FSP_SEG_INODES_FREE,
- page + FSEG_INODE_PAGE_NODE, mtr);
+ flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL,
+ iblock, FSEG_INODE_PAGE_NODE, mtr);
+ flst_add_last(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE,
+ iblock, FSEG_INODE_PAGE_NODE, mtr);
}
- mlog_write_ull(inode + FSEG_ID, 0, mtr);
- mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr);
+ mtr->write<8>(*iblock, inode + FSEG_ID, 0U);
+ mtr->write<4>(*iblock, inode + FSEG_MAGIC_N, 0xfa051ce3);
if (ULINT_UNDEFINED
- == fsp_seg_inode_page_find_used(page, physical_size)) {
-
+ == fsp_seg_inode_page_find_used(iblock->frame, physical_size)) {
/* There are no other used headers left on the page: free it */
-
- flst_remove(space_header + FSP_SEG_INODES_FREE,
- page + FSEG_INODE_PAGE_NODE, mtr);
-
- fsp_free_page(space, page_get_page_no(page), true, mtr);
+ flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE,
+ iblock, FSEG_INODE_PAGE_NODE, mtr);
+ fsp_free_page(space, iblock->page.id.page_no(), true, mtr);
}
}
@@ -1573,7 +1548,7 @@ static void fsp_free_seg_inode(
static
fseg_inode_t*
fseg_inode_try_get(
- fseg_header_t* header,
+ const fseg_header_t* header,
ulint space,
ulint zip_size,
mtr_t* mtr,
@@ -1610,7 +1585,7 @@ fseg_inode_try_get(
static
fseg_inode_t*
fseg_inode_get(
- fseg_header_t* header,
+ const fseg_header_t* header,
ulint space,
ulint zip_size,
mtr_t* mtr,
@@ -1642,24 +1617,21 @@ fseg_get_nth_frag_page_no(
+ n * FSEG_FRAG_SLOT_SIZE));
}
-/**********************************************************************//**
-Sets the page number in the nth fragment page slot. */
-UNIV_INLINE
-void
-fseg_set_nth_frag_page_no(
-/*======================*/
- fseg_inode_t* inode, /*!< in: segment inode */
- ulint n, /*!< in: slot index */
- ulint page_no,/*!< in: page number to set */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+/** Set the page number in the nth fragment page slot.
+@param[in,out] inode segment inode
+@param[in,out] iblock segment inode page
+@param[in] n slot index
+@param[in] page_no page number to set
+@param[in,out] mtr mini-transaction */
+inline void fseg_set_nth_frag_page_no(fseg_inode_t *inode, buf_block_t *iblock,
+ ulint n, ulint page_no, mtr_t *mtr)
{
- ut_ad(inode && mtr);
- ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
- ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
+ ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
+ ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
- mlog_write_ulint(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE,
- page_no, MLOG_4BYTES, mtr);
+ mtr->write<4>(*iblock, inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE,
+ page_no);
}
/**********************************************************************//**
@@ -1762,11 +1734,9 @@ fseg_create(
no need to do the check for this individual
operation */
{
- fsp_header_t* space_header;
fseg_inode_t* inode;
ib_id_t seg_id;
buf_block_t* block = 0; /* remove warning */
- fseg_header_t* header = 0; /* remove warning */
ulint n_reserved;
DBUG_ENTER("fseg_create");
@@ -1782,9 +1752,6 @@ fseg_create(
block = buf_page_get(page_id_t(space->id, page),
space->zip_size(),
RW_SX_LATCH, mtr);
-
- header = byte_offset + buf_block_get_frame(block);
-
if (!space->full_crc32()) {
fil_block_check_type(*block, space->id == TRX_SYS_SPACE
&& page == TRX_SYS_PAGE_NO
@@ -1800,9 +1767,10 @@ fseg_create(
DBUG_RETURN(NULL);
}
- space_header = fsp_get_space_header(space, mtr);
+ buf_block_t* header = fsp_get_header(space, mtr);
+ buf_block_t* iblock;
- inode = fsp_alloc_seg_inode(space, space_header, mtr);
+ inode = fsp_alloc_seg_inode(space, header, &iblock, mtr);
if (inode == NULL) {
goto funct_exit;
@@ -1811,26 +1779,28 @@ fseg_create(
/* Read the next segment id from space header and increment the
value in space header */
- seg_id = mach_read_from_8(space_header + FSP_SEG_ID);
+ seg_id = mach_read_from_8(FSP_HEADER_OFFSET + FSP_SEG_ID
+ + header->frame);
- mlog_write_ull(space_header + FSP_SEG_ID, seg_id + 1, mtr);
- mlog_write_ull(inode + FSEG_ID, seg_id, mtr);
+ mtr->write<8>(*header, FSP_HEADER_OFFSET + FSP_SEG_ID + header->frame,
+ seg_id + 1);
+ mtr->write<8>(*iblock, inode + FSEG_ID, seg_id);
ut_ad(!mach_read_from_4(inode + FSEG_NOT_FULL_N_USED));
- flst_init(inode + FSEG_FREE, mtr);
- flst_init(inode + FSEG_NOT_FULL, mtr);
- flst_init(inode + FSEG_FULL, mtr);
+ flst_init(*iblock, inode + FSEG_FREE, mtr);
+ flst_init(*iblock, inode + FSEG_NOT_FULL, mtr);
+ flst_init(*iblock, inode + FSEG_FULL, mtr);
- mlog_write_ulint(inode + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*iblock, inode + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE);
compile_time_assert(FSEG_FRAG_SLOT_SIZE == 4);
compile_time_assert(FIL_NULL == 0xffffffff);
- mlog_memset(inode + FSEG_FRAG_ARR,
- FSEG_FRAG_SLOT_SIZE * FSEG_FRAG_ARR_N_SLOTS, 0xff, mtr);
+ mtr->memset(iblock, uint16_t(inode - iblock->frame) + FSEG_FRAG_ARR,
+ FSEG_FRAG_SLOT_SIZE * FSEG_FRAG_ARR_N_SLOTS, 0xff);
if (page == 0) {
block = fseg_alloc_free_page_low(space,
- inode, 0, FSP_UP, RW_SX_LATCH,
+ inode, iblock, 0, FSP_UP,
+ RW_SX_LATCH,
mtr, mtr
#ifdef UNIV_DEBUG
, has_done_reservation
@@ -1842,25 +1812,24 @@ fseg_create(
ut_ad(!has_done_reservation || block != NULL);
if (block == NULL) {
- fsp_free_seg_inode(space, inode, mtr);
+ fsp_free_seg_inode(space, inode, iblock, mtr);
goto funct_exit;
}
ut_ad(rw_lock_get_sx_lock_count(&block->lock) == 1);
- header = byte_offset + buf_block_get_frame(block);
- mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE,
- FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
+ mtr->write<2>(*block, block->frame + FIL_PAGE_TYPE,
+ FIL_PAGE_TYPE_SYS);
}
- mlog_write_ulint(header + FSEG_HDR_OFFSET,
- page_offset(inode), MLOG_2BYTES, mtr);
+ mtr->write<2>(*block, byte_offset + FSEG_HDR_OFFSET
+ + block->frame, page_offset(inode));
- mlog_write_ulint(header + FSEG_HDR_PAGE_NO,
- page_get_page_no(page_align(inode)),
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*block, byte_offset + FSEG_HDR_PAGE_NO
+ + block->frame, iblock->page.id.page_no());
- mlog_write_ulint(header + FSEG_HDR_SPACE, space->id, MLOG_4BYTES, mtr);
+ mtr->write<4,mtr_t::OPT>(*block, byte_offset + FSEG_HDR_SPACE
+ + block->frame, space->id);
funct_exit:
if (!has_done_reservation) {
@@ -1900,48 +1869,41 @@ fseg_n_reserved_pages_low(
return(ret);
}
-/**********************************************************************//**
-Calculates the number of pages reserved by a segment, and how many pages are
-currently used.
+/** Calculate the number of pages reserved by a segment,
+and how many pages are currently used.
+@param[in] block buffer block containing the file segment header
+@param[in] header file segment header
+@param[out] used number of pages that are used (not more than reserved)
+@param[in,out] mtr mini-transaction
@return number of reserved pages */
-ulint
-fseg_n_reserved_pages(
-/*==================*/
- fseg_header_t* header, /*!< in: segment header */
- ulint* used, /*!< out: number of pages used (<= reserved) */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+ulint fseg_n_reserved_pages(const buf_block_t &block,
+ const fseg_header_t *header, ulint *used,
+ mtr_t *mtr)
{
- ulint ret;
- fseg_inode_t* inode;
- ulint space_id;
- fil_space_t* space;
-
- space_id = page_get_space_id(page_align(header));
- space = mtr_x_lock_space(space_id, mtr);
-
- inode = fseg_inode_get(header, space_id, space->zip_size(), mtr);
-
- ret = fseg_n_reserved_pages_low(inode, used, mtr);
-
- return(ret);
+ ut_ad(page_align(header) == block.frame);
+ return fseg_n_reserved_pages_low(fseg_inode_get(header,
+ block.page.id.space(),
+ block.zip_size(), mtr),
+ used, mtr);
}
/** Tries to fill the free list of a segment with consecutive free extents.
This happens if the segment is big enough to allow extents in the free list,
the free list is empty, and the extents can be allocated consecutively from
the hint onward.
-@param[in] inode segment inode
-@param[in] space tablespace
-@param[in] hint hint which extent would be good as the first
-extent
-@param[in,out] mtr mini-transaction */
+@param[in,out] inode segment inode
+@param[in,out] iblock segment inode page
+@param[in] space tablespace
+@param[in] hint hint which extent would be good as the first extent
+@param[in,out] mtr mini-transaction */
static
void
fseg_fill_free_list(
- fseg_inode_t* inode,
- fil_space_t* space,
- ulint hint,
- mtr_t* mtr)
+ fseg_inode_t* inode,
+ buf_block_t* iblock,
+ fil_space_t* space,
+ ulint hint,
+ mtr_t* mtr)
{
xdes_t* descr;
ulint i;
@@ -1969,7 +1931,8 @@ fseg_fill_free_list(
}
for (i = 0; i < FSEG_FREE_LIST_MAX_LEN; i++) {
- descr = xdes_get_descriptor(space, hint, mtr);
+ buf_block_t* xdes;
+ descr = xdes_get_descriptor(space, hint, &xdes, mtr);
if ((descr == NULL)
|| (XDES_FREE != xdes_get_state(descr, mtr))) {
@@ -1979,16 +1942,19 @@ fseg_fill_free_list(
return;
}
- descr = fsp_alloc_free_extent(space, hint, mtr);
+ descr = fsp_alloc_free_extent(space, hint, &xdes, mtr);
- xdes_set_state(descr, XDES_FSEG, mtr);
+ xdes_set_state(*xdes, descr, XDES_FSEG, mtr);
seg_id = mach_read_from_8(inode + FSEG_ID);
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE);
- mlog_write_ull(descr + XDES_ID, seg_id, mtr);
+ mtr->write<8>(*xdes, descr + XDES_ID, seg_id);
- flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
+ flst_add_last(iblock, FSEG_FREE
+ + uint16_t(inode - iblock->frame),
+ xdes, XDES_FLST_NODE
+ + uint16_t(descr - xdes->frame), mtr);
hint += FSP_EXTENT_SIZE;
}
}
@@ -1997,7 +1963,9 @@ fseg_fill_free_list(
the segment, then tries to allocate from the space free list.
NOTE that the extent returned still resides in the segment free list, it is
not yet taken off it!
-@param[in] inode segment inode
+@param[in,out] inode segment inode
+@param[in,out] iblock segment inode page
+@param[out] xdes extent descriptor page
@param[in,out] space tablespace
@param[in,out] mtr mini-transaction
@retval NULL if no page could be allocated
@@ -2008,6 +1976,8 @@ static
xdes_t*
fseg_alloc_free_extent(
fseg_inode_t* inode,
+ buf_block_t* iblock,
+ buf_block_t** xdes,
fil_space_t* space,
mtr_t* mtr)
{
@@ -2024,10 +1994,10 @@ fseg_alloc_free_extent(
first = flst_get_first(inode + FSEG_FREE);
- descr = xdes_lst_get_descriptor(space, first, mtr);
+ descr = xdes_lst_get_descriptor(space, first, xdes, mtr);
} else {
/* Segment free list was empty, allocate from space */
- descr = fsp_alloc_free_extent(space, 0, mtr);
+ descr = fsp_alloc_free_extent(space, 0, xdes, mtr);
if (descr == NULL) {
@@ -2036,12 +2006,15 @@ fseg_alloc_free_extent(
seg_id = mach_read_from_8(inode + FSEG_ID);
- xdes_set_state(descr, XDES_FSEG, mtr);
- mlog_write_ull(descr + XDES_ID, seg_id, mtr);
- flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
+ xdes_set_state(**xdes, descr, XDES_FSEG, mtr);
+ mtr->write<8,mtr_t::OPT>(**xdes, descr + XDES_ID, seg_id);
+ flst_add_last(iblock, FSEG_FREE
+ + uint16_t(inode - iblock->frame),
+ *xdes, XDES_FLST_NODE
+ + uint16_t(descr - (*xdes)->frame), mtr);
/* Try to fill the segment free list */
- fseg_fill_free_list(inode, space,
+ fseg_fill_free_list(inode, iblock, space,
xdes_get_offset(descr) + FSP_EXTENT_SIZE,
mtr);
}
@@ -2054,6 +2027,7 @@ This function implements the intelligent allocation strategy which tries to
minimize file space fragmentation.
@param[in,out] space tablespace
@param[in,out] seg_inode segment inode
+@param[in,out] iblock segment inode page
@param[in] hint hint of which page would be desirable
@param[in] direction if the new page is needed because of
an index page split, and records are inserted there in order, into which
@@ -2074,6 +2048,7 @@ buf_block_t*
fseg_alloc_free_page_low(
fil_space_t* space,
fseg_inode_t* seg_inode,
+ buf_block_t* iblock,
ulint hint,
byte direction,
rw_lock_type_t rw_latch,
@@ -2084,7 +2059,6 @@ fseg_alloc_free_page_low(
#endif /* UNIV_DEBUG */
)
{
- fsp_header_t* space_header;
ib_id_t seg_id;
ulint used;
ulint reserved;
@@ -2092,6 +2066,7 @@ fseg_alloc_free_page_low(
ulint ret_page; /*!< the allocated page offset, FIL_NULL
if could not be allocated */
xdes_t* ret_descr; /*!< the extent of the allocated page */
+ buf_block_t* xdes;
ulint n;
const ulint space_id = space->id;
@@ -2107,16 +2082,16 @@ fseg_alloc_free_page_low(
reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr);
- space_header = fsp_get_space_header(space, mtr);
+ buf_block_t* header = fsp_get_header(space, mtr);
- descr = xdes_get_descriptor_with_space_hdr(space_header, space,
- hint, mtr);
+ descr = xdes_get_descriptor_with_space_hdr(header, space, hint,
+ &xdes, mtr);
if (descr == NULL) {
/* Hint outside space or too high above free limit: reset
hint */
/* The file space header page is always allocated. */
hint = 0;
- descr = xdes_get_descriptor(space, hint, mtr);
+ descr = xdes_get_descriptor(space, hint, &xdes, mtr);
}
/* In the big if-else below we look for ret_page and ret_descr */
@@ -2142,26 +2117,28 @@ take_hinted_page:
=========================================================
the hinted page
===============*/
- ret_descr = fsp_alloc_free_extent(space, hint, mtr);
+ ret_descr = fsp_alloc_free_extent(space, hint, &xdes, mtr);
ut_a(ret_descr == descr);
- xdes_set_state(ret_descr, XDES_FSEG, mtr);
- mlog_write_ull(ret_descr + XDES_ID, seg_id, mtr);
- flst_add_last(seg_inode + FSEG_FREE,
- ret_descr + XDES_FLST_NODE, mtr);
+ xdes_set_state(*xdes, ret_descr, XDES_FSEG, mtr);
+ mtr->write<8,mtr_t::OPT>(*xdes, ret_descr + XDES_ID, seg_id);
+ flst_add_last(iblock, FSEG_FREE
+ + uint16_t(seg_inode - iblock->frame),
+ xdes, XDES_FLST_NODE
+ + uint16_t(ret_descr - xdes->frame), mtr);
/* Try to fill the segment free list */
- fseg_fill_free_list(seg_inode, space,
+ fseg_fill_free_list(seg_inode, iblock, space,
hint + FSP_EXTENT_SIZE, mtr);
goto take_hinted_page;
/*-----------------------------------------------------------*/
} else if ((direction != FSP_NO_DIR)
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
&& (used >= FSEG_FRAG_LIMIT)
- && (!!(ret_descr
- = fseg_alloc_free_extent(seg_inode, space, mtr)))) {
-
+ && !!(ret_descr = fseg_alloc_free_extent(seg_inode, iblock,
+ &xdes, space,
+ mtr))) {
/* 3. We take any free extent (which was already assigned above
===============================================================
in the if-condition to ret_descr) and take the lowest or
@@ -2204,7 +2181,7 @@ take_hinted_page:
return(NULL);
}
- ret_descr = xdes_lst_get_descriptor(space, first, mtr);
+ ret_descr = xdes_lst_get_descriptor(space, first, &xdes, mtr);
ret_page = xdes_get_offset(ret_descr)
+ xdes_find_free(ret_descr);
ut_ad(!has_done_reservation || ret_page != FIL_NULL);
@@ -2224,7 +2201,7 @@ take_hinted_page:
ut_a(n != ULINT_UNDEFINED);
fseg_set_nth_frag_page_no(
- seg_inode, n, block->page.id.page_no(),
+ seg_inode, iblock, n, block->page.id.page_no(),
mtr);
}
@@ -2235,7 +2212,8 @@ take_hinted_page:
} else {
/* 7. We allocate a new extent and take its first page
======================================================*/
- ret_descr = fseg_alloc_free_extent(seg_inode, space, mtr);
+ ret_descr = fseg_alloc_free_extent(seg_inode, iblock, &xdes,
+ space, mtr);
if (ret_descr == NULL) {
ret_page = FIL_NULL;
@@ -2268,7 +2246,7 @@ take_hinted_page:
}
if (!fsp_try_extend_data_file_with_pages(
- space, ret_page, space_header, mtr)) {
+ space, ret_page, header, mtr)) {
/* No disk space left */
ut_ad(!has_done_reservation);
return(NULL);
@@ -2283,10 +2261,14 @@ got_hinted_page:
The extent is still in the appropriate list (FSEG_NOT_FULL
or FSEG_FREE), and the page is not yet marked as used. */
- ut_ad(xdes_get_descriptor(space, ret_page, mtr) == ret_descr);
+ ut_d(buf_block_t* xxdes);
+ ut_ad(xdes_get_descriptor(space, ret_page, &xxdes, mtr)
+ == ret_descr);
+ ut_ad(xdes == xxdes);
ut_ad(xdes_is_free(ret_descr, ret_page % FSP_EXTENT_SIZE));
- fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr);
+ fseg_mark_page_used(seg_inode, iblock, ret_page, ret_descr,
+ xdes, mtr);
}
return fsp_page_create(space, ret_page, rw_latch, mtr, init_mtr);
@@ -2344,7 +2326,7 @@ fseg_alloc_free_page_general(
}
block = fseg_alloc_free_page_low(space,
- inode, hint, direction,
+ inode, iblock, hint, direction,
RW_X_LATCH, mtr, init_mtr
#ifdef UNIV_DEBUG
, has_done_reservation
@@ -2367,19 +2349,18 @@ of a single-table tablespace, and they are also physically initialized to
the data file. That is we have already extended the data file so that those
pages are inside the data file. If not, this function extends the tablespace
with pages.
-@param[in,out] space tablespace
-@param[in,out] space_header tablespace header, x-latched
-@param[in] size size of the tablespace in pages,
-must be less than FSP_EXTENT_SIZE
-@param[in,out] mtr mini-transaction
-@param[in] n_pages number of pages to reserve
+@param[in,out] space tablespace
+@param[in,out] header tablespace header, x-latched
+@param[in] size tablespace size in pages, less than FSP_EXTENT_SIZE
+@param[in,out] mtr mini-transaction
+@param[in] n_pages number of pages to reserve
@return true if there were at least n_pages free pages, or we were able
to extend */
static
bool
fsp_reserve_free_pages(
fil_space_t* space,
- fsp_header_t* space_header,
+ buf_block_t* header,
ulint size,
mtr_t* mtr,
ulint n_pages)
@@ -2390,15 +2371,16 @@ fsp_reserve_free_pages(
ut_a(!is_system_tablespace(space->id));
ut_a(size < FSP_EXTENT_SIZE);
- descr = xdes_get_descriptor_with_space_hdr(
- space_header, space, 0, mtr);
+ buf_block_t* xdes;
+ descr = xdes_get_descriptor_with_space_hdr(header, space, 0, &xdes,
+ mtr);
n_used = xdes_get_n_used(descr);
ut_a(n_used <= size);
return(size >= n_used + n_pages
|| fsp_try_extend_data_file_with_pages(
- space, n_used + n_pages - 1, space_header, mtr));
+ space, n_used + n_pages - 1, header, mtr));
}
/** Reserves free pages from a tablespace. All mini-transactions which may
@@ -2448,7 +2430,6 @@ fsp_reserve_free_extents(
mtr_t* mtr,
ulint n_pages)
{
- fsp_header_t* space_header;
ulint n_free_list_ext;
ulint free_limit;
ulint size;
@@ -2463,22 +2444,24 @@ fsp_reserve_free_extents(
mtr_x_lock_space(space, mtr);
const ulint physical_size = space->physical_size();
- space_header = fsp_get_space_header(space, mtr);
+ buf_block_t* header = fsp_get_header(space, mtr);
try_again:
- size = mach_read_from_4(space_header + FSP_SIZE);
+ size = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE + header->frame);
ut_ad(size == space->size_in_header);
if (size < FSP_EXTENT_SIZE && n_pages < FSP_EXTENT_SIZE / 2) {
/* Use different rules for small single-table tablespaces */
*n_reserved = 0;
- return(fsp_reserve_free_pages(space, space_header, size,
+ return(fsp_reserve_free_pages(space, header, size,
mtr, n_pages));
}
- n_free_list_ext = flst_get_len(space_header + FSP_FREE);
+ n_free_list_ext = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE
+ + header->frame);
ut_ad(space->free_len == n_free_list_ext);
- free_limit = mach_read_from_4(space_header + FSP_FREE_LIMIT);
+ free_limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ + header->frame);
ut_ad(space->free_limit == free_limit);
/* Below we play safe when counting free extents above the free limit:
@@ -2534,7 +2517,7 @@ try_again:
return(true);
}
try_to_extend:
- if (ulint n = fsp_try_extend_data_file(space, space_header, mtr)) {
+ if (ulint n = fsp_try_extend_data_file(space, header, mtr)) {
total_reserved += n;
goto try_again;
}
@@ -2542,58 +2525,6 @@ try_to_extend:
return(false);
}
-/********************************************************************//**
-Marks a page used. The page must reside within the extents of the given
-segment. */
-static MY_ATTRIBUTE((nonnull))
-void
-fseg_mark_page_used(
-/*================*/
- fseg_inode_t* seg_inode,/*!< in: segment inode */
- ulint page, /*!< in: page offset */
- xdes_t* descr, /*!< in: extent descriptor */
- mtr_t* mtr) /*!< in/out: mini-transaction */
-{
- ulint not_full_n_used;
-
- ut_ad(fil_page_get_type(page_align(seg_inode)) == FIL_PAGE_INODE);
- ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
- ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
- == FSEG_MAGIC_N_VALUE);
- ut_ad(!memcmp(seg_inode + FSEG_ID, descr + XDES_ID, 4));
-
- if (!xdes_get_n_used(descr)) {
- /* We move the extent from the free list to the
- NOT_FULL list */
- flst_remove(seg_inode + FSEG_FREE, descr + XDES_FLST_NODE,
- mtr);
- flst_add_last(seg_inode + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
- }
-
- ut_ad(xdes_is_free(descr, page % FSP_EXTENT_SIZE));
-
- /* We mark the page as used */
- xdes_set_free<false>(descr, page % FSP_EXTENT_SIZE, mtr);
-
- not_full_n_used = mach_read_from_4(seg_inode + FSEG_NOT_FULL_N_USED);
- not_full_n_used++;
- mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED, not_full_n_used,
- MLOG_4BYTES, mtr);
- if (xdes_is_full(descr)) {
- /* We move the extent from the NOT_FULL list to the
- FULL list */
- flst_remove(seg_inode + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
- flst_add_last(seg_inode + FSEG_FULL,
- descr + XDES_FLST_NODE, mtr);
-
- mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
- not_full_n_used - FSP_EXTENT_SIZE,
- MLOG_4BYTES, mtr);
- }
-}
-
/** Frees a single page of a segment.
@param[in] seg_inode segment inode
@param[in,out] space tablespace
@@ -2606,6 +2537,7 @@ static
void
fseg_free_page_low(
fseg_inode_t* seg_inode,
+ buf_block_t* iblock,
fil_space_t* space,
page_no_t offset,
#ifdef BTR_CUR_HASH_ADAPT
@@ -2614,9 +2546,6 @@ fseg_free_page_low(
bool log,
mtr_t* mtr)
{
- xdes_t* descr;
- ulint not_full_n_used;
- ulint state;
ib_id_t descr_id;
ib_id_t seg_id;
@@ -2625,6 +2554,7 @@ fseg_free_page_low(
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE);
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
+ ut_ad(iblock->frame == page_align(seg_inode));
ut_d(space->modify_check(*mtr));
#ifdef BTR_CUR_HASH_ADAPT
/* Drop search system page hash index if the page is found in
@@ -2636,7 +2566,8 @@ fseg_free_page_low(
}
#endif /* BTR_CUR_HASH_ADAPT */
- descr = xdes_get_descriptor(space, offset, mtr);
+ buf_block_t* xdes;
+ xdes_t* descr = xdes_get_descriptor(space, offset, &xdes, mtr);
if (xdes_is_free(descr, offset % FSP_EXTENT_SIZE)) {
ib::fatal() << "InnoDB is trying to free page "
@@ -2648,9 +2579,7 @@ fseg_free_page_low(
<< FORCE_RECOVERY_MSG;
}
- state = xdes_get_state(descr, mtr);
-
- if (state != XDES_FSEG) {
+ if (xdes_get_state(descr, mtr) != XDES_FSEG) {
/* The page is in the fragment pages of the segment */
for (ulint i = 0;; i++) {
if (fseg_get_nth_frag_page_no(seg_inode, i, mtr)
@@ -2659,8 +2588,9 @@ fseg_free_page_low(
}
compile_time_assert(FIL_NULL == 0xffffffff);
- mlog_memset(seg_inode + FSEG_FRAG_ARR
- + i * FSEG_FRAG_SLOT_SIZE, 4, 0xff, mtr);
+ mtr->memset(iblock, uint16_t(seg_inode - iblock->frame)
+ + FSEG_FRAG_ARR
+ + i * FSEG_FRAG_SLOT_SIZE, 4, 0xff);
break;
}
@@ -2688,30 +2618,32 @@ fseg_free_page_low(
<< FORCE_RECOVERY_MSG;
}
- not_full_n_used = mach_read_from_4(seg_inode + FSEG_NOT_FULL_N_USED);
+ byte* p_not_full = seg_inode + FSEG_NOT_FULL_N_USED;
+ uint32_t not_full_n_used = mach_read_from_4(p_not_full);
+ const uint16_t xoffset= XDES_FLST_NODE + uint16_t(descr - xdes->frame);
+ const uint16_t ioffset= uint16_t(seg_inode - iblock->frame);
+
if (xdes_is_full(descr)) {
/* The fragment is full: move it to another list */
- flst_remove(seg_inode + FSEG_FULL,
- descr + XDES_FLST_NODE, mtr);
- flst_add_last(seg_inode + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
- mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
- not_full_n_used + FSP_EXTENT_SIZE - 1,
- MLOG_4BYTES, mtr);
+ flst_remove(iblock, FSEG_FULL + ioffset, xdes, xoffset, mtr);
+ flst_add_last(iblock, FSEG_NOT_FULL + ioffset, xdes, xoffset,
+ mtr);
+ not_full_n_used += FSP_EXTENT_SIZE - 1;
} else {
ut_a(not_full_n_used > 0);
- mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
- not_full_n_used - 1, MLOG_4BYTES, mtr);
+ not_full_n_used--;
}
+ mtr->write<4>(*iblock, p_not_full, not_full_n_used);
+
const ulint bit = offset % FSP_EXTENT_SIZE;
- xdes_set_free<true>(descr, bit, mtr);
+ xdes_set_free<true>(*xdes, descr, bit, mtr);
if (!xdes_get_n_used(descr)) {
/* The extent has become free: free it to space */
- flst_remove(seg_inode + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
+ flst_remove(iblock, FSEG_NOT_FULL + ioffset, xdes, xoffset,
+ mtr);
fsp_free_extent(space, offset, mtr);
}
}
@@ -2755,7 +2687,7 @@ fseg_free_page_func(
fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
}
- fseg_free_page_low(seg_inode, space, offset, ahi, log, mtr);
+ fseg_free_page_low(seg_inode, iblock, space, offset, ahi, log, mtr);
ut_d(buf_page_set_file_page_was_freed(page_id_t(space->id, offset)));
@@ -2802,6 +2734,7 @@ static
void
fseg_free_extent(
fseg_inode_t* seg_inode,
+ buf_block_t* iblock,
fil_space_t* space,
ulint page,
#ifdef BTR_CUR_HASH_ADAPT
@@ -2810,13 +2743,11 @@ fseg_free_extent(
mtr_t* mtr)
{
ulint first_page_in_extent;
- xdes_t* descr;
- ulint not_full_n_used;
- ulint descr_n_used;
ut_ad(mtr != NULL);
- descr = xdes_get_descriptor(space, page, mtr);
+ buf_block_t* xdes;
+ xdes_t* descr = xdes_get_descriptor(space, page, &xdes, mtr);
ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8));
@@ -2842,23 +2773,23 @@ fseg_free_extent(
}
#endif /* BTR_CUR_HASH_ADAPT */
+ const uint16_t xoffset= XDES_FLST_NODE + uint16_t(descr - xdes->frame);
+ const uint16_t ioffset= uint16_t(seg_inode - iblock->frame);
+
if (xdes_is_full(descr)) {
- flst_remove(seg_inode + FSEG_FULL,
- descr + XDES_FLST_NODE, mtr);
+ flst_remove(iblock, FSEG_FULL + ioffset, xdes, xoffset, mtr);
} else if (!xdes_get_n_used(descr)) {
- flst_remove(seg_inode + FSEG_FREE,
- descr + XDES_FLST_NODE, mtr);
+ flst_remove(iblock, FSEG_FREE + ioffset, xdes, xoffset, mtr);
} else {
- flst_remove(seg_inode + FSEG_NOT_FULL,
- descr + XDES_FLST_NODE, mtr);
+ flst_remove(iblock, FSEG_NOT_FULL + ioffset, xdes, xoffset,
+ mtr);
- not_full_n_used = mach_read_from_4(FSEG_NOT_FULL_N_USED
- + seg_inode);
- descr_n_used = xdes_get_n_used(descr);
+ ulint not_full_n_used = mach_read_from_4(
+ FSEG_NOT_FULL_N_USED + seg_inode);
+ ulint descr_n_used = xdes_get_n_used(descr);
ut_a(not_full_n_used >= descr_n_used);
- mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
- not_full_n_used - descr_n_used,
- MLOG_4BYTES, mtr);
+ mtr->write<4>(*iblock, seg_inode + FSEG_NOT_FULL_N_USED,
+ not_full_n_used - descr_n_used);
}
fsp_free_extent(space, page, mtr);
@@ -2873,8 +2804,8 @@ fseg_free_extent(
}
#ifndef BTR_CUR_HASH_ADAPT
-# define fseg_free_extent(inode, space, page, ahi, mtr) \
- fseg_free_extent(inode, space, page, mtr)
+# define fseg_free_extent(inode, iblock, space, page, ahi, mtr) \
+ fseg_free_extent(inode, iblock, space, page, mtr)
#endif /* !BTR_CUR_HASH_ADAPT */
/**********************************************************************//**
@@ -2882,8 +2813,8 @@ Frees part of a segment. This function can be used to free a segment by
repeatedly calling this function in different mini-transactions. Doing
the freeing in a single mini-transaction might result in too big a
mini-transaction.
-@return TRUE if freeing completed */
-ibool
+@return true if freeing completed */
+bool
fseg_free_step_func(
fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header
resides on the first page of the frag list
@@ -2897,7 +2828,6 @@ fseg_free_step_func(
{
ulint n;
ulint page;
- xdes_t* descr;
fseg_inode_t* inode;
ulint space_id;
ulint header_page;
@@ -2907,22 +2837,22 @@ fseg_free_step_func(
space_id = page_get_space_id(page_align(header));
header_page = page_get_page_no(page_align(header));
- fil_space_t* space = mtr_x_lock_space(space_id, mtr);
-
- descr = xdes_get_descriptor(space, header_page, mtr);
+ fil_space_t* space = mtr_x_lock_space(space_id, mtr);
+ buf_block_t* xdes;
+ xdes_t* descr = xdes_get_descriptor(space, header_page, &xdes, mtr);
/* Check that the header resides on a page which has not been
freed yet */
ut_a(!xdes_is_free(descr, header_page % FSP_EXTENT_SIZE));
- buf_block_t* iblock;
+ buf_block_t* iblock;
const ulint zip_size = space->zip_size();
inode = fseg_inode_try_get(header, space_id, zip_size, mtr, &iblock);
if (inode == NULL) {
ib::info() << "Double free of inode from "
<< page_id_t(space_id, header_page);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(true);
}
if (!space->full_crc32()) {
@@ -2933,8 +2863,8 @@ fseg_free_step_func(
if (descr != NULL) {
/* Free the extent held by the segment */
page = xdes_get_offset(descr);
- fseg_free_extent(inode, space, page, ahi, mtr);
- DBUG_RETURN(FALSE);
+ fseg_free_extent(inode, iblock, space, page, ahi, mtr);
+ DBUG_RETURN(false);
}
/* Free a frag page */
@@ -2942,13 +2872,13 @@ fseg_free_step_func(
if (n == ULINT_UNDEFINED) {
/* Freeing completed: free the segment inode */
- fsp_free_seg_inode(space, inode, mtr);
+ fsp_free_seg_inode(space, inode, iblock, mtr);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(true);
}
fseg_free_page_low(
- inode, space,
+ inode, iblock, space,
fseg_get_nth_frag_page_no(inode, n, mtr),
ahi, true, mtr);
@@ -2956,19 +2886,19 @@ fseg_free_step_func(
if (n == ULINT_UNDEFINED) {
/* Freeing completed: free the segment inode */
- fsp_free_seg_inode(space, inode, mtr);
+ fsp_free_seg_inode(space, inode, iblock, mtr);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(true);
}
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
}
/**********************************************************************//**
Frees part of a segment. Differs from fseg_free_step because this function
leaves the header page unfreed.
-@return TRUE if freeing completed, except the header page */
-ibool
+@return true if freeing completed, except the header page */
+bool
fseg_free_step_not_header_func(
fseg_header_t* header, /*!< in: segment header which must reside on
the first fragment page of the segment */
@@ -3003,9 +2933,9 @@ fseg_free_step_not_header_func(
/* Free the extent held by the segment */
page = xdes_get_offset(descr);
- fseg_free_extent(inode, space, page, ahi, mtr);
+ fseg_free_extent(inode, iblock, space, page, ahi, mtr);
- return(FALSE);
+ return(false);
}
/* Free a frag page */
@@ -3020,12 +2950,12 @@ fseg_free_step_not_header_func(
if (page_no == page_get_page_no(page_align(header))) {
- return(TRUE);
+ return(true);
}
- fseg_free_page_low(inode, space, page_no, ahi, true, mtr);
+ fseg_free_page_low(inode, iblock, space, page_no, ahi, true, mtr);
- return(FALSE);
+ return(false);
}
/** Returns the first extent descriptor for a segment.
@@ -3058,10 +2988,12 @@ fseg_get_first_extent(
return(NULL);
}
- ut_ad(first.page != FIL_NULL);
+ DBUG_ASSERT(first.page != FIL_NULL);
+
+ buf_block_t *xdes;
return(first.page == FIL_NULL ? NULL
- : xdes_lst_get_descriptor(space, first, mtr));
+ : xdes_lst_get_descriptor(space, first, &xdes, mtr));
}
#ifdef UNIV_BTR_PRINT
diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc
index f6e83f61cbc..93249aeab54 100644
--- a/storage/innobase/fut/fut0lst.cc
+++ b/storage/innobase/fut/fut0lst.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -27,434 +28,300 @@ Created 11/28/1995 Heikki Tuuri
#include "buf0buf.h"
#include "page0page.h"
-/********************************************************************//**
-Adds a node to an empty list. */
-static
-void
-flst_add_to_empty(
-/*==============*/
- flst_base_node_t* base, /*!< in: pointer to base node of
- empty list */
- flst_node_t* node, /*!< in: node to add */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Add a node to an empty list. */
+static void flst_add_to_empty(buf_block_t *base, uint16_t boffset,
+ buf_block_t *add, uint16_t aoffset, mtr_t *mtr)
{
- ulint space;
- fil_addr_t node_addr;
-
- ut_ad(mtr && base && node);
- ut_ad(base != node);
- ut_ad(mtr_memo_contains_page_flagged(mtr, base,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr_memo_contains_page_flagged(mtr, node,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_a(!flst_get_len(base));
-
- buf_ptr_get_fsp_addr(node, &space, &node_addr);
-
- /* Update first and last fields of base node */
- flst_write_addr(base + FLST_FIRST, node_addr, mtr);
- flst_write_addr(base + FLST_LAST, node_addr, mtr);
-
- /* Set prev and next fields of node to add */
- flst_zero_addr(node + FLST_PREV, mtr);
- flst_zero_addr(node + FLST_NEXT, mtr);
-
- /* Update len of base node */
- mlog_write_ulint(base + FLST_LEN, 1, MLOG_4BYTES, mtr);
+ ut_ad(base != add || boffset != aoffset);
+ ut_ad(boffset < base->physical_size());
+ ut_ad(aoffset < add->physical_size());
+ ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ fil_addr_t addr= { add->page.id.page_no(), aoffset };
+
+ /* Update first and last fields of base node */
+ flst_write_addr(*base, base->frame + boffset + FLST_FIRST, addr, mtr);
+ /* MDEV-12353 TODO: use MEMMOVE record */
+ flst_write_addr(*base, base->frame + boffset + FLST_LAST, addr, mtr);
+
+ /* Set prev and next fields of node to add */
+ flst_zero_addr(*add, add->frame + aoffset + FLST_PREV, mtr);
+ flst_zero_addr(*add, add->frame + aoffset + FLST_NEXT, mtr);
+
+ /* Update len of base node */
+ ut_ad(!mach_read_from_4(base->frame + boffset + FLST_LEN));
+ mtr->write<1>(*base, base->frame + boffset + (FLST_LEN + 3), 1U);
}
-/********************************************************************//**
-Inserts a node after another in a list. */
-static
-void
-flst_insert_after(
-/*==============*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node1, /*!< in: node to insert after */
- flst_node_t* node2, /*!< in: node to add */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-/********************************************************************//**
-Inserts a node before another in a list. */
-static
-void
-flst_insert_before(
-/*===============*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node2, /*!< in: node to insert */
- flst_node_t* node3, /*!< in: node to insert before */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-
-/********************************************************************//**
-Adds a node as the last node in a list. */
-void
-flst_add_last(
-/*==========*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node, /*!< in: node to add */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Insert a node after another one.
+@param[in,out] base base node block
+@param[in] boffset byte offset of the base node
+@param[in,out] cur insert position block
+@param[in] coffset byte offset of the insert position
+@param[in,out] add block to be added
+@param[in] aoffset byte offset of the block to be added
+@param[in,outr] mtr mini-transaction */
+static void flst_insert_after(buf_block_t *base, uint16_t boffset,
+ buf_block_t *cur, uint16_t coffset,
+ buf_block_t *add, uint16_t aoffset, mtr_t *mtr)
{
- ulint space;
- fil_addr_t node_addr;
- ulint len;
- fil_addr_t last_addr;
-
- ut_ad(mtr && base && node);
- ut_ad(base != node);
- ut_ad(mtr_memo_contains_page_flagged(mtr, base,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr_memo_contains_page_flagged(mtr, node,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- len = flst_get_len(base);
- last_addr = flst_get_last(base);
-
- buf_ptr_get_fsp_addr(node, &space, &node_addr);
-
- /* If the list is not empty, call flst_insert_after */
- if (len != 0) {
- flst_node_t* last_node;
-
- if (last_addr.page == node_addr.page) {
- last_node = page_align(node) + last_addr.boffset;
- } else {
- fil_space_t* s = fil_space_acquire_silent(space);
- ulint zip_size = s ? s->zip_size() : 0;
- if (s) s->release();
-
- last_node = fut_get_ptr(space, zip_size, last_addr,
- RW_SX_LATCH, mtr);
- }
-
- flst_insert_after(base, last_node, node, mtr);
- } else {
- /* else call flst_add_to_empty */
- flst_add_to_empty(base, node, mtr);
- }
+ ut_ad(base != cur || boffset != coffset);
+ ut_ad(base != add || boffset != aoffset);
+ ut_ad(cur != add || coffset != aoffset);
+ ut_ad(boffset < base->physical_size());
+ ut_ad(coffset < cur->physical_size());
+ ut_ad(aoffset < add->physical_size());
+ ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mtr_memo_contains_page_flagged(mtr, cur->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+
+ fil_addr_t cur_addr= { cur->page.id.page_no(), coffset };
+ fil_addr_t add_addr= { add->page.id.page_no(), aoffset };
+ fil_addr_t next_addr= flst_get_next_addr(cur->frame + coffset);
+
+ flst_write_addr(*add, add->frame + aoffset + FLST_PREV, cur_addr, mtr);
+ flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, next_addr, mtr);
+
+ if (fil_addr_is_null(next_addr))
+ flst_write_addr(*base, base->frame + boffset + FLST_LAST, add_addr, mtr);
+ else
+ {
+ buf_block_t *block;
+ flst_node_t *next= fut_get_ptr(add->page.id.space(), add->zip_size(),
+ next_addr, RW_SX_LATCH, mtr, &block);
+ flst_write_addr(*block, next + FLST_PREV, add_addr, mtr);
+ }
+
+ flst_write_addr(*cur, cur->frame + coffset + FLST_NEXT, add_addr, mtr);
+
+ byte *len= &base->frame[boffset + FLST_LEN];
+ mtr->write<4>(*base, len, mach_read_from_4(len) + 1);
}
-/********************************************************************//**
-Adds a node as the first node in a list. */
-void
-flst_add_first(
-/*===========*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node, /*!< in: node to add */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Insert a node before another one.
+@param[in,out] base base node block
+@param[in] boffset byte offset of the base node
+@param[in,out] cur insert position block
+@param[in] coffset byte offset of the insert position
+@param[in,out] add block to be added
+@param[in] aoffset byte offset of the block to be added
+@param[in,outr] mtr mini-transaction */
+static void flst_insert_before(buf_block_t *base, uint16_t boffset,
+ buf_block_t *cur, uint16_t coffset,
+ buf_block_t *add, uint16_t aoffset, mtr_t *mtr)
{
- ulint space;
- fil_addr_t node_addr;
- ulint len;
- fil_addr_t first_addr;
- flst_node_t* first_node;
-
- ut_ad(mtr && base && node);
- ut_ad(base != node);
- ut_ad(mtr_memo_contains_page_flagged(mtr, base,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr_memo_contains_page_flagged(mtr, node,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- len = flst_get_len(base);
- first_addr = flst_get_first(base);
-
- buf_ptr_get_fsp_addr(node, &space, &node_addr);
-
- /* If the list is not empty, call flst_insert_before */
- if (len != 0) {
- if (first_addr.page == node_addr.page) {
- first_node = page_align(node) + first_addr.boffset;
- } else {
- fil_space_t* s = fil_space_acquire_silent(space);
- ulint zip_size = s ? s->zip_size() : 0;
- if (s) s->release();
-
- first_node = fut_get_ptr(space, zip_size, first_addr,
- RW_SX_LATCH, mtr);
- }
-
- flst_insert_before(base, node, first_node, mtr);
- } else {
- /* else call flst_add_to_empty */
- flst_add_to_empty(base, node, mtr);
- }
+ ut_ad(base != cur || boffset != coffset);
+ ut_ad(base != add || boffset != aoffset);
+ ut_ad(cur != add || coffset != aoffset);
+ ut_ad(boffset < base->physical_size());
+ ut_ad(coffset < cur->physical_size());
+ ut_ad(aoffset < add->physical_size());
+ ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mtr_memo_contains_page_flagged(mtr, cur->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+
+ fil_addr_t cur_addr= { cur->page.id.page_no(), coffset };
+ fil_addr_t add_addr= { add->page.id.page_no(), aoffset };
+ fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset);
+
+ flst_write_addr(*add, add->frame + aoffset + FLST_PREV, prev_addr, mtr);
+ flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, cur_addr, mtr);
+
+ if (fil_addr_is_null(prev_addr))
+ flst_write_addr(*base, base->frame + boffset + FLST_FIRST, add_addr, mtr);
+ else
+ {
+ buf_block_t *block;
+ flst_node_t *prev= fut_get_ptr(add->page.id.space(), add->zip_size(),
+ prev_addr, RW_SX_LATCH, mtr, &block);
+ flst_write_addr(*block, prev + FLST_NEXT, add_addr, mtr);
+ }
+
+ flst_write_addr(*cur, cur->frame + coffset + FLST_PREV, add_addr, mtr);
+
+ byte *len= &base->frame[boffset + FLST_LEN];
+ mtr->write<4>(*base, len, mach_read_from_4(len) + 1);
}
-/********************************************************************//**
-Inserts a node after another in a list. */
-static
-void
-flst_insert_after(
-/*==============*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node1, /*!< in: node to insert after */
- flst_node_t* node2, /*!< in: node to add */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Append a file list node to a list.
+@param[in,out] base base node block
+@param[in] boffset byte offset of the base node
+@param[in,out] add block to be added
+@param[in] aoffset byte offset of the node to be added
+@param[in,outr] mtr mini-transaction */
+void flst_add_last(buf_block_t *base, uint16_t boffset,
+ buf_block_t *add, uint16_t aoffset, mtr_t *mtr)
{
- ulint space;
- fil_addr_t node1_addr;
- fil_addr_t node2_addr;
- flst_node_t* node3;
- fil_addr_t node3_addr;
- ulint len;
-
- ut_ad(mtr && node1 && node2 && base);
- ut_ad(base != node1);
- ut_ad(base != node2);
- ut_ad(node2 != node1);
- ut_ad(mtr_memo_contains_page_flagged(mtr, base,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr_memo_contains_page_flagged(mtr, node1,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
-
- buf_ptr_get_fsp_addr(node1, &space, &node1_addr);
- buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
-
- node3_addr = flst_get_next_addr(node1);
-
- /* Set prev and next fields of node2 */
- flst_write_addr(node2 + FLST_PREV, node1_addr, mtr);
- flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr);
-
- if (!fil_addr_is_null(node3_addr)) {
- /* Update prev field of node3 */
- fil_space_t* s = fil_space_acquire_silent(space);
- ulint zip_size = s ? s->zip_size() : 0;
- if (s) s->release();
-
- node3 = fut_get_ptr(space, zip_size,
- node3_addr, RW_SX_LATCH, mtr);
- flst_write_addr(node3 + FLST_PREV, node2_addr, mtr);
- } else {
- /* node1 was last in list: update last field in base */
- flst_write_addr(base + FLST_LAST, node2_addr, mtr);
- }
-
- /* Set next field of node1 */
- flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr);
-
- /* Update len of base node */
- len = flst_get_len(base);
- mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr);
+ ut_ad(base != add || boffset != aoffset);
+ ut_ad(boffset < base->physical_size());
+ ut_ad(aoffset < add->physical_size());
+ ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+
+ if (!flst_get_len(base->frame + boffset))
+ flst_add_to_empty(base, boffset, add, aoffset, mtr);
+ else
+ {
+ fil_addr_t addr= flst_get_last(base->frame + boffset);
+ buf_block_t *cur= add;
+ const flst_node_t *c= addr.page == add->page.id.page_no()
+ ? add->frame + addr.boffset
+ : fut_get_ptr(add->page.id.space(), add->zip_size(), addr,
+ RW_SX_LATCH, mtr, &cur);
+ flst_insert_after(base, boffset, cur,
+ static_cast<uint16_t>(c - cur->frame),
+ add, aoffset, mtr);
+ }
}
-/********************************************************************//**
-Inserts a node before another in a list. */
-static
-void
-flst_insert_before(
-/*===============*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node2, /*!< in: node to insert */
- flst_node_t* node3, /*!< in: node to insert before */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Prepend a file list node to a list.
+@param[in,out] base base node block
+@param[in] boffset byte offset of the base node
+@param[in,out] add block to be added
+@param[in] aoffset byte offset of the node to be added
+@param[in,outr] mtr mini-transaction */
+void flst_add_first(buf_block_t *base, uint16_t boffset,
+ buf_block_t *add, uint16_t aoffset, mtr_t *mtr)
{
- ulint space;
- flst_node_t* node1;
- fil_addr_t node1_addr;
- fil_addr_t node2_addr;
- fil_addr_t node3_addr;
- ulint len;
-
- ut_ad(mtr && node2 && node3 && base);
- ut_ad(base != node2);
- ut_ad(base != node3);
- ut_ad(node2 != node3);
- ut_ad(mtr_memo_contains_page_flagged(mtr, base,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr_memo_contains_page_flagged(mtr, node3,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
-
- buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
- buf_ptr_get_fsp_addr(node3, &space, &node3_addr);
-
- node1_addr = flst_get_prev_addr(node3);
-
- /* Set prev and next fields of node2 */
- flst_write_addr(node2 + FLST_PREV, node1_addr, mtr);
- flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr);
-
- if (!fil_addr_is_null(node1_addr)) {
- fil_space_t* s = fil_space_acquire_silent(space);
- ulint zip_size = s ? s->zip_size() : 0;
- if (s) s->release();
-
- /* Update next field of node1 */
- node1 = fut_get_ptr(space, zip_size, node1_addr,
- RW_SX_LATCH, mtr);
- flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr);
- } else {
- /* node3 was first in list: update first field in base */
- flst_write_addr(base + FLST_FIRST, node2_addr, mtr);
- }
-
- /* Set prev field of node3 */
- flst_write_addr(node3 + FLST_PREV, node2_addr, mtr);
-
- /* Update len of base node */
- len = flst_get_len(base);
- mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr);
+ ut_ad(base != add || boffset != aoffset);
+ ut_ad(boffset < base->physical_size());
+ ut_ad(aoffset < add->physical_size());
+ ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+
+ if (!flst_get_len(base->frame + boffset))
+ flst_add_to_empty(base, boffset, add, aoffset, mtr);
+ else
+ {
+ fil_addr_t addr= flst_get_first(base->frame + boffset);
+ buf_block_t *cur= add;
+ const flst_node_t *c= addr.page == add->page.id.page_no()
+ ? add->frame + addr.boffset
+ : fut_get_ptr(add->page.id.space(), add->zip_size(), addr,
+ RW_SX_LATCH, mtr, &cur);
+ flst_insert_before(base, boffset, cur,
+ static_cast<uint16_t>(c - cur->frame),
+ add, aoffset, mtr);
+ }
}
-/********************************************************************//**
-Removes a node. */
-void
-flst_remove(
-/*========*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node2, /*!< in: node to remove */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Remove a file list node.
+@param[in,out] base base node block
+@param[in] boffset byte offset of the base node
+@param[in,out] cur block to be removed
+@param[in] coffset byte offset of the current record to be removed
+@param[in,outr] mtr mini-transaction */
+void flst_remove(buf_block_t *base, uint16_t boffset,
+ buf_block_t *cur, uint16_t coffset, mtr_t *mtr)
{
- ulint space;
- flst_node_t* node1;
- fil_addr_t node1_addr;
- fil_addr_t node2_addr;
- flst_node_t* node3;
- fil_addr_t node3_addr;
- ulint len;
-
- ut_ad(mtr && node2 && base);
- ut_ad(mtr_memo_contains_page_flagged(mtr, base,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
-
- buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
-
- fil_space_t* s = fil_space_acquire_silent(space);
- ulint zip_size = s ? s->zip_size() : 0;
- if (s) s->release();
-
- node1_addr = flst_get_prev_addr(node2);
- node3_addr = flst_get_next_addr(node2);
-
- if (!fil_addr_is_null(node1_addr)) {
-
- /* Update next field of node1 */
-
- if (node1_addr.page == node2_addr.page) {
-
- node1 = page_align(node2) + node1_addr.boffset;
- } else {
- node1 = fut_get_ptr(space, zip_size,
- node1_addr, RW_SX_LATCH, mtr);
- }
-
- ut_ad(node1 != node2);
-
- flst_write_addr(node1 + FLST_NEXT, node3_addr, mtr);
- } else {
- /* node2 was first in list: update first field in base */
- flst_write_addr(base + FLST_FIRST, node3_addr, mtr);
- }
-
- if (!fil_addr_is_null(node3_addr)) {
- /* Update prev field of node3 */
-
- if (node3_addr.page == node2_addr.page) {
-
- node3 = page_align(node2) + node3_addr.boffset;
- } else {
- node3 = fut_get_ptr(space, zip_size,
- node3_addr, RW_SX_LATCH, mtr);
- }
-
- ut_ad(node2 != node3);
-
- flst_write_addr(node3 + FLST_PREV, node1_addr, mtr);
- } else {
- /* node2 was last in list: update last field in base */
- flst_write_addr(base + FLST_LAST, node1_addr, mtr);
- }
-
- /* Update len of base node */
- len = flst_get_len(base);
- ut_ad(len > 0);
-
- mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr);
+ ut_ad(boffset < base->physical_size());
+ ut_ad(coffset < cur->physical_size());
+ ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ ut_ad(mtr_memo_contains_page_flagged(mtr, cur->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+
+ const fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset);
+ const fil_addr_t next_addr= flst_get_next_addr(cur->frame + coffset);
+
+ if (fil_addr_is_null(prev_addr))
+ flst_write_addr(*base, base->frame + boffset + FLST_FIRST, next_addr, mtr);
+ else
+ {
+ buf_block_t *block= cur;
+ flst_node_t *prev= prev_addr.page == cur->page.id.page_no()
+ ? cur->frame + prev_addr.boffset
+ : fut_get_ptr(cur->page.id.space(), cur->zip_size(), prev_addr,
+ RW_SX_LATCH, mtr, &block);
+ flst_write_addr(*block, prev + FLST_NEXT, next_addr, mtr);
+ }
+
+ if (fil_addr_is_null(next_addr))
+ flst_write_addr(*base, base->frame + boffset + FLST_LAST, prev_addr, mtr);
+ else
+ {
+ buf_block_t *block= cur;
+ flst_node_t *next= next_addr.page == cur->page.id.page_no()
+ ? cur->frame + next_addr.boffset
+ : fut_get_ptr(cur->page.id.space(), cur->zip_size(), next_addr,
+ RW_SX_LATCH, mtr, &block);
+ flst_write_addr(*block, next + FLST_PREV, prev_addr, mtr);
+ }
+
+ byte *len= &base->frame[boffset + FLST_LEN];
+ ut_ad(mach_read_from_4(len) > 0);
+ mtr->write<4>(*base, len, mach_read_from_4(len) - 1);
}
-/********************************************************************//**
-Validates a file-based list.
-@return TRUE if ok */
-ibool
-flst_validate(
-/*==========*/
- const flst_base_node_t* base, /*!< in: pointer to base node of list */
- mtr_t* mtr1) /*!< in: mtr */
+#ifdef UNIV_DEBUG
+/** Validate a file-based list. */
+void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr)
{
- ulint space;
- const flst_node_t* node;
- fil_addr_t node_addr;
- fil_addr_t base_addr;
- ulint len;
- ulint i;
- mtr_t mtr2;
-
- ut_ad(base);
- ut_ad(mtr_memo_contains_page_flagged(mtr1, base,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
-
- /* We use two mini-transaction handles: the first is used to
- lock the base node, and prevent other threads from modifying the
- list. The second is used to traverse the list. We cannot run the
- second mtr without committing it at times, because if the list
- is long, then the x-locked pages could fill the buffer resulting
- in a deadlock. */
-
- /* Find out the space id */
- buf_ptr_get_fsp_addr(base, &space, &base_addr);
-
- fil_space_t* s = fil_space_acquire_silent(space);
- ulint zip_size = s ? s->zip_size() : 0;
- if (s) s->release();
-
- len = flst_get_len(base);
- node_addr = flst_get_first(base);
-
- for (i = 0; i < len; i++) {
- mtr_start(&mtr2);
-
- node = fut_get_ptr(space, zip_size,
- node_addr, RW_SX_LATCH, &mtr2);
- node_addr = flst_get_next_addr(node);
-
- mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer
- becoming full */
- }
-
- ut_a(fil_addr_is_null(node_addr));
-
- node_addr = flst_get_last(base);
-
- for (i = 0; i < len; i++) {
- mtr_start(&mtr2);
-
- node = fut_get_ptr(space, zip_size,
- node_addr, RW_SX_LATCH, &mtr2);
- node_addr = flst_get_prev_addr(node);
-
- mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer
- becoming full */
- }
-
- ut_a(fil_addr_is_null(node_addr));
-
- return(TRUE);
+ ut_ad(boffset < base->physical_size());
+ ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame,
+ MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+
+ /* We use two mini-transaction handles: the first is used to lock
+ the base node, and prevent other threads from modifying the list.
+ The second is used to traverse the list. We cannot run the second
+ mtr without committing it at times, because if the list is long,
+ the x-locked pages could fill the buffer, resulting in a deadlock. */
+ mtr_t mtr2;
+
+ const uint32_t len= flst_get_len(base->frame + boffset);
+ fil_addr_t addr= flst_get_first(base->frame + boffset);
+
+ for (uint32_t i= len; i--; )
+ {
+ mtr2.start();
+ const flst_node_t *node= fut_get_ptr(base->page.id.space(),
+ base->zip_size(), addr,
+ RW_SX_LATCH, &mtr2);
+ addr= flst_get_next_addr(node);
+ mtr2.commit();
+ }
+
+ ut_ad(fil_addr_is_null(addr));
+
+ addr= flst_get_last(base->frame + boffset);
+
+ for (uint32_t i= len; i--; )
+ {
+ mtr2.start();
+ const flst_node_t *node= fut_get_ptr(base->page.id.space(),
+ base->zip_size(), addr,
+ RW_SX_LATCH, &mtr2);
+ addr= flst_get_prev_addr(node);
+ mtr2.commit();
+ }
+
+ ut_ad(fil_addr_is_null(addr));
}
+#endif
diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc
index db4788b8920..9dd50fb3cf1 100644
--- a/storage/innobase/gis/gis0rtree.cc
+++ b/storage/innobase/gis/gis0rtree.cc
@@ -446,7 +446,7 @@ update_mbr:
if (!ins_suc) {
ut_ad(rec_info & REC_INFO_MIN_REC_FLAG);
- btr_set_min_rec_mark(next_rec, mtr);
+ btr_set_min_rec_mark(next_rec, *block, mtr);
}
/* If there's more than 1 rec left in the page, delete
@@ -468,7 +468,7 @@ update_mbr:
mark the new leftmost node pointer as
the predefined minimum record */
rec_t* next_rec = page_rec_get_next(cur2_rec);
- btr_set_min_rec_mark(next_rec, mtr);
+ btr_set_min_rec_mark(next_rec, *block, mtr);
}
ut_ad(del_page_no
@@ -572,7 +572,7 @@ update_mbr:
mark the new leftmost node pointer as
the predefined minimum record */
rec_t* next_rec = page_rec_get_next(cur2_rec);
- btr_set_min_rec_mark(next_rec, mtr);
+ btr_set_min_rec_mark(next_rec, *block, mtr);
}
ut_ad(cur2_pno == del_page_no && cur2_rec != insert_rec);
@@ -628,12 +628,8 @@ rtr_adjust_upper_level(
rtr_mbr_t* new_mbr, /*!< in: MBR on the new page */
mtr_t* mtr) /*!< in: mtr */
{
- page_t* page;
- page_t* new_page;
ulint page_no;
ulint new_page_no;
- page_zip_des_t* page_zip;
- page_zip_des_t* new_page_zip;
dict_index_t* index = sea_cur->index;
btr_cur_t cursor;
ulint* offsets;
@@ -657,13 +653,9 @@ rtr_adjust_upper_level(
level = btr_page_get_level(buf_block_get_frame(block));
ut_ad(level == btr_page_get_level(buf_block_get_frame(new_block)));
- page = buf_block_get_frame(block);
page_no = block->page.id.page_no();
- page_zip = buf_block_get_page_zip(block);
- new_page = buf_block_get_frame(new_block);
new_page_no = new_block->page.id.page_no();
- new_page_zip = buf_block_get_page_zip(new_block);
/* Set new mbr for the old page on the upper level. */
/* Look up the index for the node pointer to page */
@@ -672,7 +664,8 @@ rtr_adjust_upper_level(
page_cursor = btr_cur_get_page_cur(&cursor);
- rtr_update_mbr_field(&cursor, offsets, NULL, page, mbr, NULL, mtr);
+ rtr_update_mbr_field(&cursor, offsets, NULL, block->frame, mbr, NULL,
+ mtr);
/* Already updated parent MBR, reset in our path */
if (sea_cur->rtr_info) {
@@ -686,7 +679,7 @@ rtr_adjust_upper_level(
/* Insert the node for the new page. */
node_ptr_upper = rtr_index_build_node_ptr(
index, new_mbr,
- page_rec_get_next(page_get_infimum_rec(new_page)),
+ page_rec_get_next(page_get_infimum_rec(new_block->frame)),
new_page_no, heap);
ulint up_match = 0;
@@ -742,26 +735,25 @@ rtr_adjust_upper_level(
ut_ad(block->zip_size() == index->table->space->zip_size());
- const uint32_t next_page_no = btr_page_get_next(page);
+ const uint32_t next_page_no = btr_page_get_next(block->frame);
if (next_page_no != FIL_NULL) {
buf_block_t* next_block = btr_block_get(
*index, next_page_no, RW_X_LATCH, false, mtr);
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
+ ut_a(page_is_comp(next_block->frame)
+ == page_is_comp(block->frame));
ut_a(btr_page_get_prev(next_block->frame)
== block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */
- btr_page_set_prev(buf_block_get_frame(next_block),
- buf_block_get_page_zip(next_block),
- new_page_no, mtr);
+ btr_page_set_prev(next_block, new_page_no, mtr);
}
- btr_page_set_next(page, page_zip, new_page_no, mtr);
+ btr_page_set_next(block, new_page_no, mtr);
- btr_page_set_prev(new_page, new_page_zip, page_no, mtr);
- btr_page_set_next(new_page, new_page_zip, next_page_no, mtr);
+ btr_page_set_prev(new_block, page_no, mtr);
+ btr_page_set_next(new_block, next_page_no, mtr);
}
/*************************************************************//**
@@ -848,11 +840,8 @@ rtr_split_page_move_rec_list(
ut_ad(!is_leaf || cur_split_node->key != first_rec);
rec = page_cur_insert_rec_low(
- page_cur_get_rec(&new_page_cursor),
- index,
- cur_split_node->key,
- offsets,
- mtr);
+ page_cur_get_rec(&new_page_cursor),
+ index, cur_split_node->key, offsets, mtr);
ut_a(rec);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 8406ce9319c..7268868e742 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -17828,14 +17828,10 @@ func_exit:
space->zip_size(), RW_X_LATCH, &mtr);
if (block != NULL) {
- byte* page = block->frame;
-
- ib::info() << "Dirtying page: " << page_id_t(
- page_get_space_id(page), page_get_page_no(page));
-
- mlog_write_ulint(page + FIL_PAGE_TYPE,
- fil_page_get_type(page),
- MLOG_2BYTES, &mtr);
+ ib::info() << "Dirtying page: " << block->page.id;
+ mtr.write<1,mtr_t::FORCED>(*block,
+ block->frame + FIL_PAGE_SPACE_ID,
+ block->frame[FIL_PAGE_SPACE_ID]);
}
mtr.commit();
goto func_exit;
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index a0b1af6c308..9af44550f0f 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -10181,12 +10181,12 @@ commit_cache_norebuild(
space->zip_size(),
RW_X_LATCH, &mtr)) {
mtr.set_named_space(space);
- mlog_write_ulint(
+ mtr.write<4,mtr_t::OPT>(
+ *b,
FSP_HEADER_OFFSET
+ FSP_SPACE_FLAGS + b->frame,
space->flags
- & ~FSP_FLAGS_MEM_MASK,
- MLOG_4BYTES, &mtr);
+ & ~FSP_FLAGS_MEM_MASK);
}
mtr.commit();
}
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index a9f9b14c696..4f2641b7e0f 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -332,17 +332,12 @@ ibuf_header_page_get(
return page;
}
-/******************************************************************//**
-Gets the root page and sx-latches it.
-@return insert buffer tree root page */
-static
-page_t*
-ibuf_tree_root_get(
-/*===============*/
- mtr_t* mtr) /*!< in: mtr */
+/** Acquire the change buffer root page.
+@param[in,out] mtr mini-transaction
+@return change buffer root page, SX-latched */
+static buf_block_t *ibuf_tree_root_get(mtr_t *mtr)
{
buf_block_t* block;
- page_t* root;
ut_ad(ibuf_inside(mtr));
ut_ad(mutex_own(&ibuf_mutex));
@@ -356,13 +351,11 @@ ibuf_tree_root_get(
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
- root = buf_block_get_frame(block);
-
- ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
- ut_ad(page_get_page_no(root) == FSP_IBUF_TREE_ROOT_PAGE_NO);
- ut_ad(ibuf.empty == page_is_empty(root));
+ ut_ad(page_get_space_id(block->frame) == IBUF_SPACE_ID);
+ ut_ad(page_get_page_no(block->frame) == FSP_IBUF_TREE_ROOT_PAGE_NO);
+ ut_ad(ibuf.empty == page_is_empty(block->frame));
- return(root);
+ return block;
}
/******************************************************************//**
@@ -418,7 +411,6 @@ ibuf_init_at_db_start(void)
{
page_t* root;
ulint n_used;
- page_t* header_page;
ut_ad(!ibuf.index);
mtr_t mtr;
@@ -426,7 +418,9 @@ ibuf_init_at_db_start(void)
compile_time_assert(IBUF_SPACE_ID == TRX_SYS_SPACE);
compile_time_assert(IBUF_SPACE_ID == 0);
mtr_x_lock_space(fil_system.sys_space, &mtr);
- header_page = ibuf_header_page_get(&mtr);
+ buf_block_t* header_page = buf_page_get(
+ page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO),
+ 0, RW_X_LATCH, &mtr);
if (!header_page) {
mtr.commit();
@@ -450,8 +444,9 @@ ibuf_init_at_db_start(void)
mutex_enter(&ibuf_mutex);
- fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
- &n_used, &mtr);
+ fseg_n_reserved_pages(*header_page,
+ IBUF_HEADER + IBUF_TREE_SEG_HEADER
+ + header_page->frame, &n_used, &mtr);
ut_ad(n_used >= 2);
@@ -624,29 +619,27 @@ ibuf_bitmap_page_get_bits_low(
}
/** Sets the desired bit for a given page in a bitmap page.
-@param[in,out] page bitmap page
+@tparam bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
+@param[in,out] block bitmap page
@param[in] page_id page id whose bits to set
@param[in] physical_size page size
-@param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
@param[in] val value to set
@param[in,out] mtr mtr containing an x-latch to the bitmap page */
-static
-void
+template<ulint bit>
+static void
ibuf_bitmap_page_set_bits(
- page_t* page,
+ buf_block_t* block,
const page_id_t page_id,
ulint physical_size,
- ulint bit,
ulint val,
mtr_t* mtr)
{
ulint byte_offset;
ulint bit_offset;
- ulint map_byte;
- ut_ad(bit < IBUF_BITS_PER_PAGE);
+ static_assert(bit < IBUF_BITS_PER_PAGE, "wrong bit");
compile_time_assert(!(IBUF_BITS_PER_PAGE % 2));
- ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr->is_named_space(page_id.space()));
bit_offset = (page_id.page_no() % physical_size)
@@ -657,21 +650,22 @@ ibuf_bitmap_page_set_bits(
ut_ad(byte_offset + IBUF_BITMAP < srv_page_size);
- map_byte = mach_read_from_1(page + IBUF_BITMAP + byte_offset);
+ byte* map_byte = &block->frame[IBUF_BITMAP + byte_offset];
+ byte b = *map_byte;
if (bit == IBUF_BITMAP_FREE) {
ut_ad(bit_offset + 1 < 8);
ut_ad(val <= 3);
-
- map_byte = ut_bit_set_nth(map_byte, bit_offset, val / 2);
- map_byte = ut_bit_set_nth(map_byte, bit_offset + 1, val % 2);
+ b &= ~(3U << bit_offset);
+ b |= ((val & 2) >> 1) << bit_offset
+ | (val & 1) << (bit_offset + 1);
} else {
ut_ad(val <= 1);
- map_byte = ut_bit_set_nth(map_byte, bit_offset, val);
+ b &= ~(1U << bit_offset);
+ b |= val << bit_offset;
}
- mlog_write_ulint(page + IBUF_BITMAP + byte_offset, map_byte,
- MLOG_1BYTE, mtr);
+ mtr->write<1,mtr_t::OPT>(*block, map_byte, b);
}
/** Calculates the bitmap page number for a given page number.
@@ -697,7 +691,7 @@ stored.
page containing the descriptor bits for the file page; the bitmap page
is x-latched */
static
-page_t*
+buf_block_t*
ibuf_bitmap_get_map_page_func(
const page_id_t page_id,
ulint zip_size,
@@ -718,8 +712,7 @@ ibuf_bitmap_get_map_page_func(
buf_block_dbg_add_level(block, SYNC_IBUF_BITMAP);
-
- return(buf_block_get_frame(block));
+ return block;
}
/** Gets the ibuf bitmap page where the bits describing a given file page are
@@ -749,31 +742,19 @@ ibuf_set_free_bits_low(
ulint val, /*!< in: value to set: < 4 */
mtr_t* mtr) /*!< in/out: mtr */
{
- page_t* bitmap_page;
- buf_frame_t* frame;
-
ut_ad(mtr->is_named_space(block->page.id.space()));
-
- if (!block) {
+ if (!page_is_leaf(block->frame)) {
return;
}
- frame = buf_block_get_frame(block);
-
- if (!frame || !page_is_leaf(frame)) {
- return;
- }
-
- bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->zip_size(), mtr);
-
#ifdef UNIV_IBUF_DEBUG
ut_a(val <= ibuf_index_page_calc_free(block));
#endif /* UNIV_IBUF_DEBUG */
- ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->physical_size(),
- IBUF_BITMAP_FREE, val, mtr);
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
+ ibuf_bitmap_get_map_page(block->page.id, block->zip_size(),
+ mtr),
+ block->page.id, block->physical_size(), val, mtr);
}
/************************************************************************//**
@@ -793,34 +774,21 @@ ibuf_set_free_bits_func(
#endif /* UNIV_IBUF_DEBUG */
ulint val) /*!< in: value to set: < 4 */
{
- mtr_t mtr;
- page_t* page;
- page_t* bitmap_page;
-
- page = buf_block_get_frame(block);
-
- if (!page_is_leaf(page)) {
-
+ if (!page_is_leaf(block->frame)) {
return;
}
- mtr_start(&mtr);
+ mtr_t mtr;
+ mtr.start();
const fil_space_t* space = mtr.set_named_space_id(
block->page.id.space());
- bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->zip_size(), &mtr);
+ buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
+ block->zip_size(),
+ &mtr);
- switch (space->purpose) {
- case FIL_TYPE_LOG:
- ut_ad(0);
- break;
- case FIL_TYPE_TABLESPACE:
- break;
- /* fall through */
- case FIL_TYPE_TEMPORARY:
- case FIL_TYPE_IMPORT:
- mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
+ if (space->purpose != FIL_TYPE_TABLESPACE) {
+ mtr.set_log_mode(MTR_LOG_NO_REDO);
}
#ifdef UNIV_IBUF_DEBUG
@@ -830,31 +798,17 @@ ibuf_set_free_bits_func(
old_val = ibuf_bitmap_page_get_bits(
bitmap_page, block->page.id,
IBUF_BITMAP_FREE, &mtr);
-# if 0
- if (old_val != max_val) {
- fprintf(stderr,
- "Ibuf: page %lu old val %lu max val %lu\n",
- page_get_page_no(page),
- old_val, max_val);
- }
-# endif
-
ut_a(old_val <= max_val);
}
-# if 0
- fprintf(stderr, "Setting page no %lu free bits to %lu should be %lu\n",
- page_get_page_no(page), val,
- ibuf_index_page_calc_free(block));
-# endif
ut_a(val <= ibuf_index_page_calc_free(block));
#endif /* UNIV_IBUF_DEBUG */
- ibuf_bitmap_page_set_bits(
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
bitmap_page, block->page.id, block->physical_size(),
- IBUF_BITMAP_FREE, val, &mtr);
+ val, &mtr);
- mtr_commit(&mtr);
+ mtr.commit();
}
/************************************************************************//**
@@ -929,19 +883,10 @@ ibuf_update_free_bits_zip(
buf_block_t* block, /*!< in/out: index page */
mtr_t* mtr) /*!< in/out: mtr */
{
- page_t* bitmap_page;
- ulint after;
+ ut_ad(page_is_leaf(block->frame));
+ ut_ad(block->zip_size());
- ut_a(block);
- buf_frame_t* frame = buf_block_get_frame(block);
- ut_a(frame);
- ut_a(page_is_leaf(frame));
- ut_a(block->zip_size());
-
- bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->zip_size(), mtr);
-
- after = ibuf_index_page_calc_free_zip(block);
+ ulint after = ibuf_index_page_calc_free_zip(block);
if (after == 0) {
/* We move the page to the front of the buffer pool LRU list:
@@ -952,9 +897,10 @@ ibuf_update_free_bits_zip(
buf_page_make_young(&block->page);
}
- ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->physical_size(),
- IBUF_BITMAP_FREE, after, mtr);
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
+ ibuf_bitmap_get_map_page(block->page.id, block->zip_size(),
+ mtr),
+ block->page.id, block->physical_size(), after, mtr);
}
/**********************************************************************//**
@@ -1029,7 +975,6 @@ ibuf_page_low(
{
ibool ret;
mtr_t local_mtr;
- page_t* bitmap_page;
ut_ad(!recv_no_ibuf_operations);
ut_ad(x_latch || mtr == NULL);
@@ -1064,10 +1009,8 @@ ibuf_page_low(
zip_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
file, line, &local_mtr, &err);
- bitmap_page = buf_block_get_frame(block);
-
ret = ibuf_bitmap_page_get_bits_low(
- bitmap_page, page_id, zip_size,
+ block->frame, page_id, zip_size,
MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF);
mtr_commit(&local_mtr);
@@ -1080,10 +1023,10 @@ ibuf_page_low(
mtr_start(mtr);
}
- bitmap_page = ibuf_bitmap_get_map_page_func(page_id, zip_size,
- file, line, mtr);
-
- ret = ibuf_bitmap_page_get_bits(bitmap_page, page_id, zip_size,
+ ret = ibuf_bitmap_page_get_bits(ibuf_bitmap_get_map_page_func(
+ page_id, zip_size, file, line,
+ mtr)->frame,
+ page_id, zip_size,
IBUF_BITMAP_IBUF, mtr);
if (mtr == &local_mtr) {
@@ -1891,23 +1834,16 @@ ibuf_data_too_much_free(void)
return(ibuf.free_list_len >= 3 + (ibuf.size / 2) + 3 * ibuf.height);
}
-/*********************************************************************//**
-Allocates a new page from the ibuf file segment and adds it to the free
-list.
-@return TRUE on success, FALSE if no space left */
-static
-ibool
-ibuf_add_free_page(void)
-/*====================*/
+/** Allocate a change buffer page.
+@retval true on success
+@retval false if no space left */
+static bool ibuf_add_free_page()
{
mtr_t mtr;
page_t* header_page;
buf_block_t* block;
- page_t* page;
- page_t* root;
- page_t* bitmap_page;
- mtr_start(&mtr);
+ mtr.start();
/* Acquire the fsp latch before the ibuf header, obeying the latching
order */
mtr_x_lock_space(fil_system.sys_space, &mtr);
@@ -1928,26 +1864,24 @@ ibuf_add_free_page(void)
&mtr);
if (block == NULL) {
- mtr_commit(&mtr);
-
- return(FALSE);
+ mtr.commit();
+ return false;
}
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
ibuf_enter(&mtr);
mutex_enter(&ibuf_mutex);
- root = ibuf_tree_root_get(&mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
- page = buf_block_get_frame(block);
- mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_IBUF_FREE_LIST,
- MLOG_2BYTES, &mtr);
+ mtr.write<2>(*block, block->frame + FIL_PAGE_TYPE,
+ FIL_PAGE_IBUF_FREE_LIST);
/* Add the page to the free list and update the ibuf size data */
- flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
+ flst_add_last(ibuf_tree_root_get(&mtr),
+ PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
+ block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
ibuf.seg_size++;
ibuf.free_list_len++;
@@ -1955,17 +1889,18 @@ ibuf_add_free_page(void)
/* Set the bit indicating that this page is now an ibuf tree page
(level 2 page) */
- const page_id_t page_id(IBUF_SPACE_ID, block->page.id.page_no());
- bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
+ const page_id_t page_id(IBUF_SPACE_ID, block->page.id.page_no());
+ buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
mutex_exit(&ibuf_mutex);
- ibuf_bitmap_page_set_bits(bitmap_page, page_id, srv_page_size,
- IBUF_BITMAP_IBUF, TRUE, &mtr);
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>(bitmap_page, page_id,
+ srv_page_size, true,
+ &mtr);
ibuf_mtr_commit(&mtr);
- return(TRUE);
+ return true;
}
/*********************************************************************//**
@@ -1979,9 +1914,6 @@ ibuf_remove_free_page(void)
mtr_t mtr2;
page_t* header_page;
ulint page_no;
- page_t* page;
- page_t* root;
- page_t* bitmap_page;
log_free_check();
@@ -2009,12 +1941,12 @@ ibuf_remove_free_page(void)
ibuf_mtr_start(&mtr2);
- root = ibuf_tree_root_get(&mtr2);
+ buf_block_t* root = ibuf_tree_root_get(&mtr2);
mutex_exit(&ibuf_mutex);
page_no = flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST
- + root).page;
+ + root->frame).page;
/* NOTE that we must release the latch on the ibuf tree root
because in fseg_free_page we access level 1 pages, and the root
@@ -2044,22 +1976,15 @@ ibuf_remove_free_page(void)
root = ibuf_tree_root_get(&mtr);
ut_ad(page_no == flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST
- + root).page);
+ + root->frame).page);
- {
- buf_block_t* block;
-
- block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
-
- buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
-
- page = buf_block_get_frame(block);
- }
+ buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
/* Remove the page from the free list and update the ibuf size data */
- flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
+ flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
+ block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
mutex_exit(&ibuf_pessimistic_insert_mutex);
@@ -2069,13 +1994,12 @@ ibuf_remove_free_page(void)
/* Set the bit indicating that this page is no more an ibuf tree page
(level 2 page) */
- bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
+ buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
mutex_exit(&ibuf_mutex);
- ibuf_bitmap_page_set_bits(
- bitmap_page, page_id, srv_page_size,
- IBUF_BITMAP_IBUF, FALSE, &mtr);
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>(
+ bitmap_page, page_id, srv_page_size, false, &mtr);
ut_d(buf_page_set_file_page_was_freed(page_id));
@@ -2512,10 +2436,8 @@ ibuf_merge_pages(
and the whole B-tree must be empty. InnoDB does not
allow empty B-tree pages other than the root. */
ut_ad(ibuf.empty);
- ut_ad(page_get_space_id(btr_pcur_get_page(&pcur))
- == IBUF_SPACE_ID);
- ut_ad(page_get_page_no(btr_pcur_get_page(&pcur))
- == FSP_IBUF_TREE_ROOT_PAGE_NO);
+ ut_ad(btr_pcur_get_block(&pcur)->page.id
+ == page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO));
ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur);
@@ -2573,11 +2495,8 @@ ibuf_merge_space(
and the whole B-tree must be empty. InnoDB does not
allow empty B-tree pages other than the root. */
ut_ad(ibuf.empty);
- ut_ad(page_get_space_id(btr_pcur_get_page(&pcur))
- == IBUF_SPACE_ID);
- ut_ad(page_get_page_no(btr_pcur_get_page(&pcur))
- == FSP_IBUF_TREE_ROOT_PAGE_NO);
-
+ ut_ad(btr_pcur_get_block(&pcur)->page.id
+ == page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO));
} else {
sum_sizes = ibuf_get_merge_pages(
@@ -3305,8 +3224,7 @@ ibuf_insert_low(
ulint buffered;
lint min_n_recs;
rec_t* ins_rec;
- ibool old_bit_value;
- page_t* bitmap_page;
+ buf_block_t* bitmap_page;
buf_block_t* block;
page_t* root;
dberr_t err;
@@ -3459,8 +3377,8 @@ fail_exit:
if (op == IBUF_OP_INSERT) {
ulint bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, physical_size, IBUF_BITMAP_FREE,
- &bitmap_mtr);
+ bitmap_page->frame, page_id, physical_size,
+ IBUF_BITMAP_FREE, &bitmap_mtr);
if (buffered + entry_size + page_dir_calc_reserved_space(1)
> ibuf_index_page_calc_free_from_bits(physical_size,
@@ -3505,17 +3423,8 @@ fail_exit:
/* Set the bitmap bit denoting that the insert buffer contains
buffered entries for this index page, if the bit is not set yet */
-
- old_bit_value = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, physical_size,
- IBUF_BITMAP_BUFFERED, &bitmap_mtr);
-
- if (!old_bit_value) {
- ibuf_bitmap_page_set_bits(bitmap_page, page_id, physical_size,
- IBUF_BITMAP_BUFFERED, TRUE,
- &bitmap_mtr);
- }
-
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
+ bitmap_page, page_id, physical_size, true, &bitmap_mtr);
ibuf_mtr_commit(&bitmap_mtr);
cursor = btr_pcur_get_btr_cur(&pcur);
@@ -3548,7 +3457,7 @@ fail_exit:
which would cause the sx-latching of the root after that to
break the latching order. */
- root = ibuf_tree_root_get(&mtr);
+ root = ibuf_tree_root_get(&mtr)->frame;
err = btr_cur_optimistic_insert(
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
@@ -3760,9 +3669,6 @@ ibuf_insert_to_index_page_low(
page_cur_t* page_cur)/*!< in/out: cursor positioned on the record
after which to insert the buffered entry */
{
- const page_t* page;
- const page_t* bitmap_page;
- ulint old_bits;
rec_t* rec;
DBUG_ENTER("ibuf_insert_to_index_page_low");
@@ -3790,11 +3696,10 @@ ibuf_insert_to_index_page_low(
DBUG_RETURN(rec);
}
- page = buf_block_get_frame(block);
-
ib::error() << "Insert buffer insert fails; page free "
- << page_get_max_insert_size(page, 1) << ", dtuple size "
- << rec_get_converted_size(index, entry, 0);
+ << page_get_max_insert_size(block->frame, 1)
+ << ", dtuple size "
+ << rec_get_converted_size(index, entry, 0);
fputs("InnoDB: Cannot insert index record ", stderr);
dtuple_print(stderr, entry);
@@ -3802,14 +3707,14 @@ ibuf_insert_to_index_page_low(
"InnoDB: is now probably corrupt. Please run CHECK TABLE on\n"
"InnoDB: that table.\n", stderr);
- bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->zip_size(), mtr);
- old_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, block->page.id, block->zip_size(),
- IBUF_BITMAP_FREE, mtr);
-
ib::error() << "page " << block->page.id << ", size "
- << block->physical_size() << ", bitmap bits " << old_bits;
+ << block->physical_size() << ", bitmap bits "
+ << ibuf_bitmap_page_get_bits(
+ ibuf_bitmap_get_map_page(block->page.id,
+ block->zip_size(),
+ mtr)->frame,
+ block->page.id, block->zip_size(),
+ IBUF_BITMAP_FREE, mtr);
ib::error() << BUG_REPORT_MSG;
@@ -3898,7 +3803,6 @@ dump:
if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) {
upd_t* update;
- page_zip_des_t* page_zip;
rec = page_cur_get_rec(&page_cur);
@@ -3910,8 +3814,7 @@ dump:
ULINT_UNDEFINED, &heap);
update = row_upd_build_sec_rec_difference_binary(
rec, index, offsets, entry, heap);
-
- page_zip = buf_block_get_page_zip(block);
+ page_zip_des_t* page_zip = buf_block_get_page_zip(block);
if (update->n_fields == 0) {
/* The records only differ in the delete-mark.
@@ -4023,7 +3926,7 @@ ibuf_set_del_mark(
if (low_match == dtuple_get_n_fields(entry)) {
rec_t* rec;
- page_zip_des_t* page_zip;
+ page_zip_des_t* page_zip;
rec = page_cur_get_rec(&page_cur);
page_zip = page_cur_get_page_zip(&page_cur);
@@ -4272,7 +4175,7 @@ bool ibuf_delete_rec(ulint space, ulint page_no, btr_pcur_t* pcur,
goto func_exit;
}
- root = ibuf_tree_root_get(mtr);
+ root = ibuf_tree_root_get(mtr)->frame;
btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur), 0,
false, mtr);
@@ -4317,10 +4220,10 @@ bool ibuf_page_exists(const buf_page_t& bpage)
bool bitmap_bits = false;
ibuf_mtr_start(&mtr);
- if (const page_t* bitmap_page = ibuf_bitmap_get_map_page(
+ if (const buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
bpage.id, bpage.zip_size(), &mtr)) {
bitmap_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, bpage.id, bpage.zip_size(),
+ bitmap_page->frame, bpage.id, bpage.zip_size(),
IBUF_BITMAP_BUFFERED, &mtr) != 0;
}
ibuf_mtr_commit(&mtr);
@@ -4351,7 +4254,6 @@ ibuf_merge_or_delete_for_page(
#ifdef UNIV_IBUF_DEBUG
ulint volume = 0;
#endif /* UNIV_IBUF_DEBUG */
- page_zip_des_t* page_zip = NULL;
bool corruption_noticed = false;
mtr_t mtr;
@@ -4385,18 +4287,18 @@ ibuf_merge_or_delete_for_page(
block = NULL;
update_ibuf_bitmap = false;
} else {
- page_t* bitmap_page = NULL;
ulint bitmap_bits = 0;
ibuf_mtr_start(&mtr);
- bitmap_page = ibuf_bitmap_get_map_page(
+ buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
page_id, zip_size, &mtr);
- if (bitmap_page &&
- fil_page_get_type(bitmap_page) != FIL_PAGE_TYPE_ALLOCATED) {
+ if (bitmap_page
+ && fil_page_get_type(bitmap_page->frame)
+ != FIL_PAGE_TYPE_ALLOCATED) {
bitmap_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, zip_size,
+ bitmap_page->frame, page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr);
}
@@ -4429,7 +4331,6 @@ ibuf_merge_or_delete_for_page(
the debug checks. */
rw_lock_x_lock_move_ownership(&(block->lock));
- page_zip = buf_block_get_page_zip(block);
if (!fil_page_index_page_check(block->frame)
|| !page_is_leaf(block->frame)) {
@@ -4496,8 +4397,7 @@ loop:
|| ibuf_rec_get_space(&mtr, rec) != page_id.space()) {
if (block != NULL) {
- page_header_reset_last_insert(
- block->frame, page_zip, &mtr);
+ page_header_reset_last_insert(block, &mtr);
}
goto reset_bit;
@@ -4519,8 +4419,9 @@ loop:
ibuf_op_t op = ibuf_rec_get_op_type(&mtr, rec);
max_trx_id = page_get_max_trx_id(page_align(rec));
- page_update_max_trx_id(block, page_zip, max_trx_id,
- &mtr);
+ page_update_max_trx_id(block,
+ buf_block_get_page_zip(block),
+ max_trx_id, &mtr);
ut_ad(page_validate(page_align(rec), ibuf.index));
@@ -4635,28 +4536,17 @@ loop:
}
reset_bit:
- if (update_ibuf_bitmap) {
- page_t* bitmap_page;
-
- bitmap_page = ibuf_bitmap_get_map_page(page_id, zip_size,
- &mtr);
-
- ibuf_bitmap_page_set_bits(
- bitmap_page, page_id, physical_size,
- IBUF_BITMAP_BUFFERED, FALSE, &mtr);
+ if (!update_ibuf_bitmap) {
+ } else if (buf_block_t* bitmap = ibuf_bitmap_get_map_page(
+ page_id, zip_size, &mtr)) {
+ /* FIXME: update the bitmap byte only once! */
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
+ bitmap, page_id, physical_size, false, &mtr);
if (block != NULL) {
- ulint old_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, zip_size,
- IBUF_BITMAP_FREE, &mtr);
-
- ulint new_bits = ibuf_index_page_calc_free(block);
-
- if (old_bits != new_bits) {
- ibuf_bitmap_page_set_bits(
- bitmap_page, page_id, physical_size,
- IBUF_BITMAP_FREE, new_bits, &mtr);
- }
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
+ bitmap, page_id, physical_size,
+ ibuf_index_page_calc_free(block), &mtr);
}
}
@@ -4760,18 +4650,15 @@ bool
ibuf_is_empty(void)
/*===============*/
{
- bool is_empty;
- const page_t* root;
mtr_t mtr;
ibuf_mtr_start(&mtr);
- mutex_enter(&ibuf_mutex);
- root = ibuf_tree_root_get(&mtr);
- mutex_exit(&ibuf_mutex);
-
- is_empty = page_is_empty(root);
+ ut_d(mutex_enter(&ibuf_mutex));
+ const buf_block_t* root = ibuf_tree_root_get(&mtr);
+ bool is_empty = page_is_empty(root->frame);
ut_a(is_empty == ibuf.empty);
+ ut_d(mutex_exit(&ibuf_mutex));
ibuf_mtr_commit(&mtr);
return(is_empty);
@@ -4849,9 +4736,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
the space, as usual. */
for (page_no = 0; page_no < size; page_no += physical_size) {
- page_t* bitmap_page;
- ulint i;
-
if (trx_is_interrupted(trx)) {
mutex_exit(&ibuf_mutex);
return(DB_INTERRUPTED);
@@ -4863,10 +4747,15 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
ibuf_enter(&mtr);
- bitmap_page = ibuf_bitmap_get_map_page(
+ buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
page_id_t(space->id, page_no), zip_size, &mtr);
+ if (!bitmap_page) {
+ mutex_exit(&ibuf_mutex);
+ mtr.commit();
+ return DB_CORRUPTION;
+ }
- if (buf_page_is_zeroes(bitmap_page, physical_size)) {
+ if (buf_page_is_zeroes(bitmap_page->frame, physical_size)) {
/* This means we got all-zero page instead of
ibuf bitmap page. The subsequent page should be
all-zero pages. */
@@ -4886,17 +4775,13 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
continue;
}
- if (!bitmap_page) {
- mutex_exit(&ibuf_mutex);
- return DB_CORRUPTION;
- }
-
- for (i = FSP_IBUF_BITMAP_OFFSET + 1; i < physical_size; i++) {
+ for (ulint i = FSP_IBUF_BITMAP_OFFSET + 1; i < physical_size;
+ i++) {
const ulint offset = page_no + i;
const page_id_t cur_page_id(space->id, offset);
if (ibuf_bitmap_page_get_bits(
- bitmap_page, cur_page_id, zip_size,
+ bitmap_page->frame, cur_page_id, zip_size,
IBUF_BITMAP_IBUF, &mtr)) {
mutex_exit(&ibuf_mutex);
@@ -4914,7 +4799,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
}
if (ibuf_bitmap_page_get_bits(
- bitmap_page, cur_page_id, zip_size,
+ bitmap_page->frame, cur_page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr)) {
ib_errf(trx->mysql_thd,
@@ -4928,10 +4813,9 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
/* Tolerate this error, so that
slightly corrupted tables can be
imported and dumped. Clear the bit. */
- ibuf_bitmap_page_set_bits(
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
bitmap_page, cur_page_id,
- physical_size,
- IBUF_BITMAP_BUFFERED, FALSE, &mtr);
+ physical_size, false, &mtr);
}
}
@@ -4951,7 +4835,6 @@ ibuf_set_bitmap_for_bulk_load(
buf_block_t* block,
bool reset)
{
- page_t* bitmap_page;
mtr_t mtr;
ulint free_val;
@@ -4959,20 +4842,22 @@ ibuf_set_bitmap_for_bulk_load(
free_val = ibuf_index_page_calc_free(block);
- mtr_start(&mtr);
+ mtr.start();
fil_space_t* space = mtr.set_named_space_id(block->page.id.space());
- bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- space->zip_size(), &mtr);
+ buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
+ space->zip_size(),
+ &mtr);
free_val = reset ? 0 : ibuf_index_page_calc_free(block);
- ibuf_bitmap_page_set_bits(
+ /* FIXME: update the bitmap byte only once! */
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
bitmap_page, block->page.id, block->physical_size(),
- IBUF_BITMAP_FREE, free_val, &mtr);
+ free_val, &mtr);
- ibuf_bitmap_page_set_bits(
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
bitmap_page, block->page.id, block->physical_size(),
- IBUF_BITMAP_BUFFERED, FALSE, &mtr);
+ false, &mtr);
- mtr_commit(&mtr);
+ mtr.commit();
}
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index c58715560ee..e23ad166534 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -523,8 +523,28 @@ btr_insert_on_non_leaf_level_func(
#define btr_insert_on_non_leaf_level(f,i,l,t,m) \
btr_insert_on_non_leaf_level_func(f,i,l,t,__FILE__,__LINE__,m)
-/** Sets a record as the predefined minimum record. */
-void btr_set_min_rec_mark(rec_t* rec, mtr_t* mtr) MY_ATTRIBUTE((nonnull));
+/** Set a child page pointer record as the predefined minimum record.
+@tparam has_prev whether the page is supposed to have a left sibling
+@param[in,out] rec leftmost record on a leftmost non-leaf page
+@param[in,out] block buffer pool block
+@param[in,out] mtr mini-transaction */
+template<bool has_prev= false>
+inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
+ mtr_t *mtr)
+{
+ ut_ad(block.frame == page_align(rec));
+ ut_ad(!page_is_leaf(block.frame));
+ ut_ad(has_prev == page_has_prev(block.frame));
+
+ rec-= page_rec_is_comp(rec) ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS;
+
+ if (block.page.zip.data)
+ /* This flag is computed from other contents on a ROW_FORMAT=COMPRESSED
+ page. We are not modifying the compressed page frame at all. */
+ *rec|= REC_INFO_MIN_REC_FLAG;
+ else
+ mtr->write<1>(block, rec, *rec | REC_INFO_MIN_REC_FLAG);
+}
/** Seek to the parent page of a B-tree page.
@param[in,out] index b-tree
@@ -581,15 +601,15 @@ btr_discard_page(
Parses the redo log record for setting an index record as the predefined
minimum record.
@return end of log record or NULL */
+ATTRIBUTE_COLD MY_ATTRIBUTE((nonnull(1,2), warn_unused_result))
const byte*
btr_parse_set_min_rec_mark(
/*=======================*/
const byte* ptr, /*!< in: buffer */
const byte* end_ptr,/*!< in: buffer end */
ulint comp, /*!< in: nonzero=compact page format */
- page_t* page, /*!< in: page or NULL */
- mtr_t* mtr) /*!< in: mtr or NULL */
- MY_ATTRIBUTE((nonnull(1,2), warn_unused_result));
+ buf_block_t* block, /*!< in: page or NULL */
+ mtr_t* mtr); /*!< in: mtr or NULL */
/***********************************************************//**
Parses a redo log record of reorganizing a page.
@return end of log record or NULL */
diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic
index e06127efaa3..427bd130b79 100644
--- a/storage/innobase/include/btr0btr.ic
+++ b/storage/innobase/include/btr0btr.ic
@@ -30,28 +30,6 @@ Created 6/2/1994 Heikki Tuuri
#include "page0zip.h"
/**************************************************************//**
-Sets the index id field of a page. */
-UNIV_INLINE
-void
-btr_page_set_index_id(
-/*==================*/
- page_t* page, /*!< in: page to be created */
- page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
- part will be updated, or NULL */
- index_id_t id, /*!< in: index id */
- mtr_t* mtr) /*!< in: mtr */
-{
- if (page_zip) {
- mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), id);
- page_zip_write_header(page_zip,
- page + (PAGE_HEADER + PAGE_INDEX_ID),
- 8, mtr);
- } else {
- mlog_write_ull(page + (PAGE_HEADER + PAGE_INDEX_ID), id, mtr);
- }
-}
-
-/**************************************************************//**
Gets the index id field of a page.
@return index id */
UNIV_INLINE
@@ -63,77 +41,56 @@ btr_page_get_index_id(
return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID));
}
-/********************************************************//**
-Sets the node level field in an index page. */
-UNIV_INLINE
-void
-btr_page_set_level(
-/*===============*/
- page_t* page, /*!< in: index page */
- page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
- part will be updated, or NULL */
- ulint level, /*!< in: level, leaf level == 0 */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Set PAGE_LEVEL.
+@param[in,out] block buffer block
+@param[in] level page level
+@param[in,out] mtr mini-transaction */
+inline
+void btr_page_set_level(buf_block_t *block, ulint level, mtr_t *mtr)
{
- ut_ad(page != NULL);
- ut_ad(mtr != NULL);
- ut_ad(level <= BTR_MAX_NODE_LEVEL);
-
- if (page_zip) {
- mach_write_to_2(page + (PAGE_HEADER + PAGE_LEVEL), level);
- page_zip_write_header(page_zip,
- page + (PAGE_HEADER + PAGE_LEVEL),
- 2, mtr);
- } else {
- mlog_write_ulint(page + (PAGE_HEADER + PAGE_LEVEL), level,
- MLOG_2BYTES, mtr);
- }
+ ut_ad(level <= BTR_MAX_NODE_LEVEL);
+
+ byte *page_level= PAGE_HEADER + PAGE_LEVEL + block->frame;
+
+ if (UNIV_LIKELY_NULL(block->page.zip.data))
+ {
+ mach_write_to_2(page_level, level);
+ page_zip_write_header(&block->page.zip, page_level, 2, mtr);
+ }
+ else
+ mtr->write<2,mtr_t::OPT>(*block, page_level, level);
}
-/********************************************************//**
-Sets the next index page field. */
-UNIV_INLINE
-void
-btr_page_set_next(
-/*==============*/
- page_t* page, /*!< in: index page */
- page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
- part will be updated, or NULL */
- ulint next, /*!< in: next page number */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Set FIL_PAGE_NEXT.
+@param[in,out] block buffer block
+@param[in] next number of successor page
+@param[in,out] mtr mini-transaction */
+inline void btr_page_set_next(buf_block_t *block, ulint next, mtr_t *mtr)
{
- ut_ad(page != NULL);
- ut_ad(mtr != NULL);
-
- if (page_zip) {
- mach_write_to_4(page + FIL_PAGE_NEXT, next);
- page_zip_write_header(page_zip, page + FIL_PAGE_NEXT, 4, mtr);
- } else {
- mlog_write_ulint(page + FIL_PAGE_NEXT, next, MLOG_4BYTES, mtr);
- }
+ byte *fil_page_next= block->frame + FIL_PAGE_NEXT;
+ if (UNIV_LIKELY_NULL(block->page.zip.data))
+ {
+ mach_write_to_4(fil_page_next, next);
+ page_zip_write_header(&block->page.zip, fil_page_next, 4, mtr);
+ }
+ else
+ mtr->write<4>(*block, fil_page_next, next);
}
-/********************************************************//**
-Sets the previous index page field. */
-UNIV_INLINE
-void
-btr_page_set_prev(
-/*==============*/
- page_t* page, /*!< in: index page */
- page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
- part will be updated, or NULL */
- ulint prev, /*!< in: previous page number */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Set FIL_PAGE_PREV.
+@param[in,out] block buffer block
+@param[in] prev number of predecessor page
+@param[in,out] mtr mini-transaction */
+inline void btr_page_set_prev(buf_block_t *block, ulint prev, mtr_t *mtr)
{
- ut_ad(page != NULL);
- ut_ad(mtr != NULL);
-
- if (page_zip) {
- mach_write_to_4(page + FIL_PAGE_PREV, prev);
- page_zip_write_header(page_zip, page + FIL_PAGE_PREV, 4, mtr);
- } else {
- mlog_write_ulint(page + FIL_PAGE_PREV, prev, MLOG_4BYTES, mtr);
- }
+ byte *fil_page_prev= block->frame + FIL_PAGE_PREV;
+ if (UNIV_LIKELY_NULL(block->page.zip.data))
+ {
+ mach_write_to_4(fil_page_prev, prev);
+ page_zip_write_header(&block->page.zip, fil_page_prev, 4, mtr);
+ }
+ else
+ mtr->write<4>(*block, fil_page_prev, prev);
}
/**************************************************************//**
diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h
index d1a8af22d68..6bed9e47b17 100644
--- a/storage/innobase/include/btr0bulk.h
+++ b/storage/innobase/include/btr0bulk.h
@@ -101,11 +101,25 @@ public:
/** Insert a record in the page.
@param[in] rec record
@param[in] offsets record offsets */
- void insert(const rec_t* rec, ulint* offsets);
+ inline void insert(const rec_t* rec, ulint* offsets);
+private:
+ /** Page format */
+ enum format { REDUNDANT, DYNAMIC, COMPRESSED };
+ /** Mark end of insertion to the page. Scan all records to set page
+ dirs, and set page header members.
+ @tparam format the page format */
+ template<format> inline void finishPage();
+ /** Insert a record in the page.
+ @tparam format the page format
+ @param[in] rec record
+ @param[in] offsets record offsets */
+ template<format> inline void insertPage(const rec_t* rec,
+ ulint* offsets);
+public:
/** Mark end of insertion to the page. Scan all records to set page
dirs, and set page header members. */
- void finish();
+ inline void finish();
/** Commit mtr for a page
@param[in] success Flag whether all inserts succeed. */
@@ -199,6 +213,8 @@ public:
return(m_err);
}
+ void set_modified() { m_mtr.set_modified(); }
+
/* Memory heap for internal allocation */
mem_heap_t* m_heap;
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index bcdbb08e81f..659232bc7fc 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -646,8 +646,7 @@ to free the field. */
void
btr_cur_disown_inherited_fields(
/*============================*/
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
- part will be updated, or NULL */
+ buf_block_t* block, /*!< in/out: index page */
rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
@@ -722,12 +721,12 @@ btr_free_externally_stored_field(
page_zip_write_blob_ptr(), or NULL */
const ulint* offsets, /*!< in: rec_get_offsets(rec, index),
or NULL */
- page_zip_des_t* page_zip, /*!< in: compressed page corresponding
- to rec, or NULL if rec == NULL */
+ buf_block_t* block, /*!< in/out: page of field_ref */
ulint i, /*!< in: field number of field_ref;
ignored if rec == NULL */
bool rollback, /*!< in: performing rollback? */
- mtr_t* local_mtr); /*!< in: mtr containing the latch */
+ mtr_t* local_mtr) /*!< in: mtr containing the latch */
+ MY_ATTRIBUTE((nonnull(1,2,5,8)));
/** Copies the prefix of an externally stored field of a record.
The clustered index record must be protected by a lock or a page latch.
diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic
index be6ac28129e..694bd32cfe0 100644
--- a/storage/innobase/include/btr0cur.ic
+++ b/storage/innobase/include/btr0cur.ic
@@ -137,17 +137,17 @@ btr_cur_compress_recommendation(
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2U,
return(FALSE));
- if (page_get_data_size(page)
- < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)
- || !page_has_siblings(page)) {
+ if (!page_has_siblings(page)
+ || page_get_data_size(page)
+ < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
/* The page fillfactor has dropped below a predefined
minimum value OR the level in the B-tree contains just
one page: we recommend compression if this is not the
root page. */
- return(dict_index_get_page(cursor->index)
- != page_get_page_no(page));
+ return cursor->index->page
+ != btr_cur_get_block(cursor)->page.id.page_no();
}
return(FALSE);
@@ -172,17 +172,17 @@ btr_cur_can_delete_without_compress(
page = btr_cur_get_page(cursor);
- if (page_get_data_size(page) - rec_size
- < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)
- || !page_has_siblings(page) || page_get_n_recs(page) < 2) {
+ if (!page_has_siblings(page) || page_get_n_recs(page) < 2
+ || page_get_data_size(page) - rec_size
+ < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
/* The page fillfactor will drop below a predefined
minimum value, OR the level in the B-tree contains just
one page, OR the page will become empty: we recommend
compression if this is not the root page. */
- return(dict_index_get_page(cursor->index)
- == page_get_page_no(page));
+ return cursor->index->page
+ == btr_cur_get_block(cursor)->page.id.page_no();
}
return(TRUE);
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 997b471f52b..9ed16993ea5 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -323,16 +323,6 @@ buf_block_free(
/*===========*/
buf_block_t* block); /*!< in, own: block to be freed */
-/*********************************************************************//**
-Copies contents of a buffer frame to a given buffer.
-@return buf */
-UNIV_INLINE
-byte*
-buf_frame_copy(
-/*===========*/
- byte* buf, /*!< in: buffer to copy to */
- const buf_frame_t* frame); /*!< in: buffer frame */
-
/**************************************************************//**
NOTE! The following macros should be used instead of buf_page_get_gen,
to improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed
@@ -697,7 +687,6 @@ inline uint buf_page_full_crc32_size(const byte* buf, bool* comp, bool* cr)
return page_size;
}
-#ifndef UNIV_INNOCHECKSUM
# ifdef UNIV_LINUX
# include <stdlib.h>
# endif
@@ -726,16 +715,7 @@ inline void aligned_free(void *ptr)
#endif
}
-/**********************************************************************//**
-Gets the space id, page offset, and byte offset within page of a
-pointer pointing to a buffer frame containing a file page. */
-UNIV_INLINE
-void
-buf_ptr_get_fsp_addr(
-/*=================*/
- const void* ptr, /*!< in: pointer to a buffer frame */
- ulint* space, /*!< out: space id */
- fil_addr_t* addr); /*!< out: page offset and byte offset */
+#ifndef UNIV_INNOCHECKSUM
/**********************************************************************//**
Gets the hash value of a block. This can be used in searches in the
lock hash table.
@@ -1104,9 +1084,9 @@ buf_block_get_frame(
Gets the compressed page descriptor corresponding to an uncompressed page
if applicable. */
#define buf_block_get_page_zip(block) \
- ((block)->page.zip.data ? &(block)->page.zip : NULL)
+ (UNIV_LIKELY_NULL((block)->page.zip.data) ? &(block)->page.zip : NULL)
#define is_buf_block_get_page_zip(block) \
- ((block)->page.zip.data != 0)
+ UNIV_LIKELY_NULL((block)->page.zip.data)
#ifdef BTR_CUR_HASH_ADAPT
/** Get a buffer block from an adaptive hash index pointer.
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 15869e9ed0c..45cafcdf3fe 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -759,25 +759,6 @@ buf_frame_align(
}
/**********************************************************************//**
-Gets the space id, page offset, and byte offset within page of a
-pointer pointing to a buffer frame containing a file page. */
-UNIV_INLINE
-void
-buf_ptr_get_fsp_addr(
-/*=================*/
- const void* ptr, /*!< in: pointer to a buffer frame */
- ulint* space, /*!< out: space id */
- fil_addr_t* addr) /*!< out: page offset and byte offset */
-{
- const page_t* page = (const page_t*) ut_align_down(ptr,
- srv_page_size);
-
- *space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- addr->page = mach_read_from_4(page + FIL_PAGE_OFFSET);
- addr->boffset = static_cast<uint16_t>(ut_align_offset(ptr, srv_page_size));
-}
-
-/**********************************************************************//**
Gets the hash value of the page the pointer is pointing to. This can be used
in searches in the lock hash table.
@return lock hash value */
@@ -847,23 +828,6 @@ buf_block_free(
buf_pool_mutex_exit(buf_pool);
}
-/*********************************************************************//**
-Copies contents of a buffer frame to a given buffer.
-@return buf */
-UNIV_INLINE
-byte*
-buf_frame_copy(
-/*===========*/
- byte* buf, /*!< in: buffer to copy to */
- const buf_frame_t* frame) /*!< in: buffer frame */
-{
- ut_ad(buf && frame);
-
- memcpy(buf, frame, srv_page_size);
-
- return(buf);
-}
-
/********************************************************************//**
Increments the modify clock of a frame by 1. The caller must (1) own the
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h
index 68662ac3b89..17fa84a85cc 100644
--- a/storage/innobase/include/buf0dblwr.h
+++ b/storage/innobase/include/buf0dblwr.h
@@ -150,8 +150,6 @@ struct buf_dblwr_t{
doublewrite buffer, aligned to an
address divisible by srv_page_size
(which is required by Windows aio) */
- byte* write_buf_unaligned;/*!< pointer to write_buf,
- but unaligned */
buf_page_t** buf_block_arr;/*!< array to store pointers to
the buffer blocks which have been
cached to write_buf */
diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h
index 778471b77ae..3144303c1a1 100644
--- a/storage/innobase/include/dict0boot.h
+++ b/storage/innobase/include/dict0boot.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, MariaDB Corporation.
+Copyright (c) 2018, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -33,15 +33,8 @@ Created 4/18/1996 Heikki Tuuri
#include "buf0buf.h"
#include "dict0dict.h"
-typedef byte dict_hdr_t;
-
-/**********************************************************************//**
-Gets a pointer to the dictionary header and x-latches its page.
-@return pointer to the dictionary header, page x-latched */
-dict_hdr_t*
-dict_hdr_get(
-/*=========*/
- mtr_t* mtr); /*!< in: mtr */
+/** @return the DICT_HDR block, x-latched */
+buf_block_t *dict_hdr_get(mtr_t* mtr);
/**********************************************************************//**
Returns a new table, index, or space id. */
void
diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h
index 6775154b73a..02854877f99 100644
--- a/storage/innobase/include/dict0crea.h
+++ b/storage/innobase/include/dict0crea.h
@@ -97,11 +97,10 @@ dict_create_index_tree(
const trx_t* trx); /*!< in: InnoDB transaction handle */
/** Drop the index tree associated with a row in SYS_INDEXES table.
-@param[in,out] rec SYS_INDEXES record
@param[in,out] pcur persistent cursor on rec
@param[in,out] trx dictionary transaction
@param[in,out] mtr mini-transaction */
-void dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
+void dict_drop_index_tree(btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
MY_ATTRIBUTE((nonnull));
/***************************************************************//**
diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h
index dc63377317a..c604c4f70d3 100644
--- a/storage/innobase/include/fil0crypt.h
+++ b/storage/innobase/include/fil0crypt.h
@@ -115,7 +115,6 @@ struct fil_space_crypt_t : st_encryption_scheme
fil_encryption_t new_encryption)
: st_encryption_scheme(),
min_key_version(new_min_key_version),
- page0_offset(0),
encryption(new_encryption),
key_found(0),
rotate_state()
@@ -184,14 +183,12 @@ struct fil_space_crypt_t : st_encryption_scheme
@param[in,out] page first page of the tablespace */
void fill_page0(ulint flags, byte* page);
- /** Write crypt data to a page (0)
- @param[in] space tablespace
- @param[in,out] page0 first page of the tablespace
+ /** Write encryption metadata to the first page.
+ @param[in,out] block first page of the tablespace
@param[in,out] mtr mini-transaction */
- void write_page0(const fil_space_t* space, byte* page0, mtr_t* mtr);
+ void write_page0(buf_block_t* block, mtr_t* mtr);
uint min_key_version; // min key version for this space
- ulint page0_offset; // byte offset on page 0 for crypt data
fil_encryption_t encryption; // Encryption setup
ib_mutex_t mutex; // mutex protecting following variables
@@ -308,6 +305,11 @@ fil_parse_write_crypt_data(
dberr_t* err)
MY_ATTRIBUTE((warn_unused_result));
+/** Amend encryption information from redo log.
+@param[in] space tablespace
+@param[in] data encryption metadata */
+void fil_crypt_parse(fil_space_t* space, const byte* data);
+
/** Encrypt a buffer.
@param[in,out] crypt_data Crypt data
@param[in] space space_id
diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h
index 15485769429..759970bb46d 100644
--- a/storage/innobase/include/fsp0file.h
+++ b/storage/innobase/include/fsp0file.h
@@ -61,7 +61,6 @@ public:
m_flags(),
m_exists(),
m_is_valid(),
- m_first_page_buf(),
m_first_page(),
m_last_os_error(),
m_file_info()
@@ -83,7 +82,6 @@ public:
m_flags(flags),
m_exists(),
m_is_valid(),
- m_first_page_buf(),
m_first_page(),
m_last_os_error(),
m_file_info()
@@ -103,7 +101,6 @@ public:
m_flags(file.m_flags),
m_exists(file.m_exists),
m_is_valid(file.m_is_valid),
- m_first_page_buf(),
m_first_page(),
m_last_os_error(),
m_file_info()
@@ -162,7 +159,6 @@ public:
/* Do not make a copy of the first page,
it should be reread if needed */
- m_first_page_buf = NULL;
m_first_page = NULL;
return(*this);
@@ -459,10 +455,7 @@ private:
/* true if the tablespace is valid */
bool m_is_valid;
- /** Buffer to hold first page */
- byte* m_first_page_buf;
-
- /** Pointer to the first page held in the buffer above */
+ /** Aligned buffer to hold first page */
byte* m_first_page;
protected:
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index a87f1fb2fe6..48a1ef5de8b 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -101,7 +101,6 @@ see the table in fsp0types.h @{ */
#define FSP_HEADER_OFFSET FIL_PAGE_DATA
/* The data structures in files are defined just as byte strings in C */
-typedef byte fsp_header_t;
typedef byte xdes_t;
/* SPACE HEADER
@@ -207,7 +206,7 @@ typedef byte fseg_inode_t;
(16 + 3 * FLST_BASE_NODE_SIZE \
+ FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
-#define FSEG_MAGIC_N_VALUE 97937874
+static constexpr uint32_t FSEG_MAGIC_N_VALUE= 97937874;
#define FSEG_FILLFACTOR 8 /* If this value is x, then if
the number of unused but reserved
@@ -303,14 +302,6 @@ inline bool xdes_is_free(const xdes_t *descr, ulint offset)
#ifndef UNIV_INNOCHECKSUM
/* @} */
-/**********************************************************************//**
-Reads the space id from the first page of a tablespace.
-@return space id, ULINT UNDEFINED if error */
-ulint
-fsp_header_get_space_id(
-/*====================*/
- const page_t* page); /*!< in: first page of a tablespace */
-
/** Read a tablespace header field.
@param[in] page first page of a tablespace
@param[in] field the header field
@@ -392,16 +383,17 @@ fseg_create(
no need to do the check for this individual
operation */
-/**********************************************************************//**
-Calculates the number of pages reserved by a segment, and how many pages are
-currently used.
+/** Calculate the number of pages reserved by a segment,
+and how many pages are currently used.
+@param[in] block buffer block containing the file segment header
+@param[in] header file segment header
+@param[out] used number of pages that are used (not more than reserved)
+@param[in,out] mtr mini-transaction
@return number of reserved pages */
-ulint
-fseg_n_reserved_pages(
-/*==================*/
- fseg_header_t* header, /*!< in: segment header */
- ulint* used, /*!< out: number of pages used (<= reserved) */
- mtr_t* mtr); /*!< in/out: mini-transaction */
+ulint fseg_n_reserved_pages(const buf_block_t &block,
+ const fseg_header_t *header, ulint *used,
+ mtr_t *mtr)
+ MY_ATTRIBUTE((nonnull));
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize
@@ -534,7 +526,7 @@ by repeatedly calling this function in different mini-transactions.
Doing the freeing in a single mini-transaction might result in
too big a mini-transaction.
@return TRUE if freeing completed */
-ibool
+bool
fseg_free_step_func(
fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header
resides on the first page of the frag list
@@ -554,8 +546,8 @@ fseg_free_step_func(
/**********************************************************************//**
Frees part of a segment. Differs from fseg_free_step because this function
leaves the header page unfreed.
-@return TRUE if freeing completed, except the header page */
-ibool
+@return true if freeing completed, except the header page */
+bool
fseg_free_step_not_header_func(
fseg_header_t* header, /*!< in: segment header which must reside on
the first fragment page of the segment */
diff --git a/storage/innobase/include/fut0lst.h b/storage/innobase/include/fut0lst.h
index d009e5b050a..e9355948599 100644
--- a/storage/innobase/include/fut0lst.h
+++ b/storage/innobase/include/fut0lst.h
@@ -68,79 +68,91 @@ typedef byte flst_node_t;
@param[in,out] block file page
@param[in] ofs byte offset of the list base node
@param[in,out] mtr mini-transaction */
-inline void flst_init(buf_block_t* block, uint16_t ofs, mtr_t* mtr)
+inline void flst_init(const buf_block_t* block, uint16_t ofs, mtr_t* mtr)
{
- ut_ad(0 == mach_read_from_2(FLST_LEN + ofs + block->frame));
- ut_ad(0 == mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs
- + block->frame));
- ut_ad(0 == mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs
- + block->frame));
- compile_time_assert(FIL_NULL == 0xffU * 0x1010101U);
- mlog_memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
- mlog_memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
+ ut_ad(!mach_read_from_2(FLST_LEN + ofs + block->frame));
+ ut_ad(!mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs + block->frame));
+ ut_ad(!mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs + block->frame));
+ compile_time_assert(FIL_NULL == 0xffU * 0x1010101U);
+ mtr->memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff);
+ mtr->memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff);
}
/** Write a null file address.
-@param[in,out] faddr file address to be zeroed otu
-@param[in,out] mtr mini-transaction */
-inline void flst_zero_addr(fil_faddr_t* faddr, mtr_t* mtr)
+@param[in] b file page
+@param[in,out] addr file address to be zeroed out
+@param[in,out] mtr mini-transaction */
+inline void flst_zero_addr(const buf_block_t& b, fil_faddr_t *addr, mtr_t *mtr)
+{
+ if (mach_read_from_4(addr + FIL_ADDR_PAGE) != FIL_NULL)
+ mtr->memset(&b, ulint(addr - b.frame) + FIL_ADDR_PAGE, 4, 0xff);
+ mtr->write<2,mtr_t::OPT>(b, addr + FIL_ADDR_BYTE, 0U);
+}
+
+/** Write a file address.
+@param[in] block file page
+@param[in,out] faddr file address location
+@param[in] addr file address to be written out
+@param[in,out] mtr mini-transaction */
+inline void flst_write_addr(const buf_block_t& block, fil_faddr_t *faddr,
+ fil_addr_t addr, mtr_t* mtr)
+{
+ ut_ad(mtr->memo_contains_page_flagged(faddr,
+ MTR_MEMO_PAGE_X_FIX
+ | MTR_MEMO_PAGE_SX_FIX));
+ ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA);
+ ut_a(ut_align_offset(faddr, srv_page_size) >= FIL_PAGE_DATA);
+
+ mtr->write<4,mtr_t::OPT>(block, faddr + FIL_ADDR_PAGE, addr.page);
+ mtr->write<2,mtr_t::OPT>(block, faddr + FIL_ADDR_BYTE, addr.boffset);
+}
+
+/** Initialize a list base node.
+@param[in] block file page
+@param[in,out] base base node
+@param[in,out] mtr mini-transaction */
+inline void flst_init(const buf_block_t& block, byte *base, mtr_t *mtr)
{
- if (mach_read_from_4(faddr + FIL_ADDR_PAGE) != FIL_NULL) {
- mlog_memset(faddr + FIL_ADDR_PAGE, 4, 0xff, mtr);
- }
- if (mach_read_from_2(faddr + FIL_ADDR_BYTE)) {
- mlog_write_ulint(faddr + FIL_ADDR_BYTE, 0, MLOG_2BYTES, mtr);
- }
+ ut_ad(mtr->memo_contains_page_flagged(base, MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+ mtr->write<4,mtr_t::OPT>(block, base + FLST_LEN, 0U);
+ flst_zero_addr(block, base + FLST_FIRST, mtr);
+ flst_zero_addr(block, base + FLST_LAST, mtr);
}
-/********************************************************************//**
-Initializes a list base node. */
-UNIV_INLINE
-void
-flst_init(
-/*======*/
- flst_base_node_t* base, /*!< in: pointer to base node */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-/********************************************************************//**
-Adds a node as the last node in a list. */
-void
-flst_add_last(
-/*==========*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node, /*!< in: node to add */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-/********************************************************************//**
-Adds a node as the first node in a list. */
-void
-flst_add_first(
-/*===========*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node, /*!< in: node to add */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-/********************************************************************//**
-Removes a node. */
-void
-flst_remove(
-/*========*/
- flst_base_node_t* base, /*!< in: pointer to base node of list */
- flst_node_t* node2, /*!< in: node to remove */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-/** Get the length of a list.
-@param[in] base base node
-@return length */
-UNIV_INLINE
-uint32_t
-flst_get_len(
- const flst_base_node_t* base);
-/********************************************************************//**
-Writes a file address. */
-UNIV_INLINE
-void
-flst_write_addr(
-/*============*/
- fil_faddr_t* faddr, /*!< in: pointer to file faddress */
- fil_addr_t addr, /*!< in: file address */
- mtr_t* mtr); /*!< in: mini-transaction handle */
+/** Append a file list node to a list.
+@param[in,out] base base node block
+@param[in] boffset byte offset of the base node
+@param[in,out] add block to be added
+@param[in] aoffset byte offset of the node to be added
+@param[in,outr] mtr mini-transaction */
+void flst_add_last(buf_block_t *base, uint16_t boffset,
+ buf_block_t *add, uint16_t aoffset, mtr_t *mtr)
+ MY_ATTRIBUTE((nonnull));
+/** Prepend a file list node to a list.
+@param[in,out] base base node block
+@param[in] boffset byte offset of the base node
+@param[in,out] add block to be added
+@param[in] aoffset byte offset of the node to be added
+@param[in,outr] mtr mini-transaction */
+void flst_add_first(buf_block_t *base, uint16_t boffset,
+ buf_block_t *add, uint16_t aoffset, mtr_t *mtr)
+ MY_ATTRIBUTE((nonnull));
+/** Remove a file list node.
+@param[in,out] base base node block
+@param[in] boffset byte offset of the base node
+@param[in,out] cur block to be removed
+@param[in] coffset byte offset of the current record to be removed
+@param[in,outr] mtr mini-transaction */
+void flst_remove(buf_block_t *base, uint16_t boffset,
+ buf_block_t *cur, uint16_t coffset, mtr_t *mtr)
+ MY_ATTRIBUTE((nonnull));
+
+/** @return the length of a list */
+inline uint32_t flst_get_len(const flst_base_node_t *base)
+{
+ return mach_read_from_4(base + FLST_LEN);
+}
/** @return a file address */
inline fil_addr_t flst_read_addr(const fil_faddr_t *faddr)
@@ -176,16 +188,10 @@ inline fil_addr_t flst_get_prev_addr(const flst_node_t *node)
return flst_read_addr(node + FLST_PREV);
}
-/********************************************************************//**
-Validates a file-based list.
-@return TRUE if ok */
-ibool
-flst_validate(
-/*==========*/
- const flst_base_node_t* base, /*!< in: pointer to base node of list */
- mtr_t* mtr1); /*!< in: mtr */
-
-#include "fut0lst.ic"
+#ifdef UNIV_DEBUG
+/** Validate a file-based list. */
+void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr);
+#endif
#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/include/fut0lst.ic b/storage/innobase/include/fut0lst.ic
deleted file mode 100644
index b672001f660..00000000000
--- a/storage/innobase/include/fut0lst.ic
+++ /dev/null
@@ -1,80 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2019, MariaDB Corporation.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-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 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 Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/******************************************************************//**
-@file include/fut0lst.ic
-File-based list utilities
-
-Created 11/28/1995 Heikki Tuuri
-***********************************************************************/
-
-#include "buf0buf.h"
-
-/********************************************************************//**
-Writes a file address. */
-UNIV_INLINE
-void
-flst_write_addr(
-/*============*/
- fil_faddr_t* faddr, /*!< in: pointer to file faddress */
- fil_addr_t addr, /*!< in: file address */
- mtr_t* mtr) /*!< in: mini-transaction handle */
-{
- ut_ad(faddr && mtr);
- ut_ad(mtr_memo_contains_page_flagged(mtr, faddr,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
- ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA);
- ut_a(ut_align_offset(faddr, srv_page_size) >= FIL_PAGE_DATA);
-
- mlog_write_ulint(faddr + FIL_ADDR_PAGE, addr.page, MLOG_4BYTES, mtr);
- mlog_write_ulint(faddr + FIL_ADDR_BYTE, addr.boffset,
- MLOG_2BYTES, mtr);
-}
-
-/********************************************************************//**
-Initializes a list base node. */
-UNIV_INLINE
-void
-flst_init(
-/*======*/
- flst_base_node_t* base, /*!< in: pointer to base node */
- mtr_t* mtr) /*!< in: mini-transaction handle */
-{
- ut_ad(mtr_memo_contains_page_flagged(mtr, base,
- MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
-
- if (mach_read_from_4(base + FLST_LEN)) {
- mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr);
- }
- flst_zero_addr(base + FLST_FIRST, mtr);
- flst_zero_addr(base + FLST_LAST, mtr);
-}
-
-/** Get the length of a list.
-@param[in] base base node
-@return length */
-UNIV_INLINE
-uint32_t
-flst_get_len(
- const flst_base_node_t* base)
-{
- return(mach_read_from_4(base + FLST_LEN));
-}
diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h
index 1ba916d3315..de14857c5d6 100644
--- a/storage/innobase/include/log0recv.h
+++ b/storage/innobase/include/log0recv.h
@@ -80,10 +80,8 @@ recv_sys_var_init(void);
/*===================*/
/** Apply recv_sys.pages to persistent data pages.
-@param[in] last_batch whether the change buffer merge will be
- performed as part of the operation */
-void
-recv_apply_hashed_log_recs(bool last_batch);
+@param[in] last_batch whether redo log writes are possible */
+void recv_apply_hashed_log_recs(bool last_batch);
/** Whether to store redo log records in recv_sys.pages */
enum store_t {
diff --git a/storage/innobase/include/mtr0log.h b/storage/innobase/include/mtr0log.h
index 9fc19673230..e937dbfcb58 100644
--- a/storage/innobase/include/mtr0log.h
+++ b/storage/innobase/include/mtr0log.h
@@ -34,73 +34,6 @@ Created 12/7/1995 Heikki Tuuri
struct dict_index_t;
/********************************************************//**
-Writes 1, 2 or 4 bytes to a file page. Writes the corresponding log
-record to the mini-transaction log if mtr is not NULL. */
-void
-mlog_write_ulint(
-/*=============*/
- byte* ptr, /*!< in: pointer where to write */
- ulint val, /*!< in: value to write */
- mlog_id_t type, /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-
-/********************************************************//**
-Writes 8 bytes to a file page. Writes the corresponding log
-record to the mini-transaction log, only if mtr is not NULL */
-void
-mlog_write_ull(
-/*===========*/
- byte* ptr, /*!< in: pointer where to write */
- ib_uint64_t val, /*!< in: value to write */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-/********************************************************//**
-Writes a string to a file page buffered in the buffer pool. Writes the
-corresponding log record to the mini-transaction log. */
-void
-mlog_write_string(
-/*==============*/
- byte* ptr, /*!< in: pointer where to write */
- const byte* str, /*!< in: string to write */
- ulint len, /*!< in: string length */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-/********************************************************//**
-Logs a write of a string to a file page buffered in the buffer pool.
-Writes the corresponding log record to the mini-transaction log. */
-void
-mlog_log_string(
-/*============*/
- byte* ptr, /*!< in: pointer written to */
- ulint len, /*!< in: string length */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-
-/** Initialize a string of bytes.
-@param[in,out] b buffer page
-@param[in] ofs byte offset from block->frame
-@param[in] len length of the data to write
-@param[in] val the data byte to write
-@param[in,out] mtr mini-transaction */
-void
-mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr);
-
-/** Initialize a string of bytes.
-@param[in,out] byte byte address
-@param[in] len length of the data to write
-@param[in] val the data byte to write
-@param[in,out] mtr mini-transaction */
-void mlog_memset(byte* b, ulint len, byte val, mtr_t* mtr);
-
-/********************************************************//**
-Writes initial part of a log record consisting of one-byte item
-type and four-byte space and page numbers. */
-void
-mlog_write_initial_log_record(
-/*==========================*/
- const byte* ptr, /*!< in: pointer to (inside) a buffer
- frame holding the file page where
- modification is made */
- mlog_id_t type, /*!< in: log item type: MLOG_1BYTE, ... */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-/********************************************************//**
Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */
UNIV_INLINE
void
@@ -135,14 +68,6 @@ mlog_catenate_ulint_compressed(
mtr_t* mtr, /*!< in: mtr */
ulint val); /*!< in: value to write */
/********************************************************//**
-Catenates a compressed 64-bit integer to mlog. */
-UNIV_INLINE
-void
-mlog_catenate_ull_compressed(
-/*=========================*/
- mtr_t* mtr, /*!< in: mtr */
- ib_uint64_t val); /*!< in: value to write */
-/********************************************************//**
Opens a buffer to mlog. It must be closed with mlog_close.
@return buffer, NULL if log mode MTR_LOG_NONE */
UNIV_INLINE
@@ -162,6 +87,71 @@ mlog_close(
byte* ptr); /*!< in: buffer space from ptr up was
not used */
+/** Write 1, 2, 4, or 8 bytes to a file page.
+@param[in] block file page
+@param[in,out] ptr pointer in file page
+@param[in] val value to write
+@tparam l number of bytes to write
+@tparam w write request type
+@tparam V type of val */
+template<unsigned l,mtr_t::write_type w,typename V>
+inline void mtr_t::write(const buf_block_t &block, byte *ptr, V val)
+{
+ ut_ad(ut_align_down(ptr, srv_page_size) == block.frame);
+ ut_ad(m_log_mode == MTR_LOG_NONE || m_log_mode == MTR_LOG_NO_REDO ||
+ !block.page.zip.data ||
+ /* written by fil_crypt_rotate_page() or innodb_make_page_dirty()? */
+ (w == FORCED && l == 1 && ptr == &block.frame[FIL_PAGE_SPACE_ID]) ||
+ mach_read_from_2(block.frame + FIL_PAGE_TYPE) <= FIL_PAGE_TYPE_ZBLOB2);
+ static_assert(l == 1 || l == 2 || l == 4 || l == 8, "wrong length");
+
+ switch (l) {
+ case 1:
+ if (w == OPT && mach_read_from_1(ptr) == val) return;
+ ut_ad(w != NORMAL || mach_read_from_1(ptr) != val);
+ ut_ad(val == static_cast<byte>(val));
+ *ptr= static_cast<byte>(val);
+ break;
+ case 2:
+ ut_ad(val == static_cast<uint16_t>(val));
+ if (w == OPT && mach_read_from_2(ptr) == val) return;
+ ut_ad(w != NORMAL || mach_read_from_2(ptr) != val);
+ mach_write_to_2(ptr, static_cast<uint16_t>(val));
+ break;
+ case 4:
+ ut_ad(val == static_cast<uint32_t>(val));
+ if (w == OPT && mach_read_from_4(ptr) == val) return;
+ ut_ad(w != NORMAL || mach_read_from_4(ptr) != val);
+ mach_write_to_4(ptr, static_cast<uint32_t>(val));
+ break;
+ case 8:
+ if (w == OPT && mach_read_from_8(ptr) == val) return;
+ ut_ad(w != NORMAL || mach_read_from_8(ptr) != val);
+ mach_write_to_8(ptr, val);
+ break;
+ }
+ byte *log_ptr= mlog_open(this, 11 + 2 + (l == 8 ? 9 : 5));
+ if (!log_ptr)
+ return;
+ if (l == 8)
+ log_write(block, ptr, static_cast<mlog_id_t>(l), log_ptr, uint64_t{val});
+ else
+ log_write(block, ptr, static_cast<mlog_id_t>(l), log_ptr,
+ static_cast<uint32_t>(val));
+}
+
+/** Write a byte string to a page.
+@param[in,out] b buffer page
+@param[in] ofs byte offset from b->frame
+@param[in] str the data to write
+@param[in] len length of the data to write */
+inline
+void mtr_t::memcpy(buf_block_t *b, ulint offset, const void *str, ulint len)
+{
+ ::memcpy(b->frame + offset, str, len);
+ memcpy(*b, offset, len);
+}
+
/** Writes a log record about an operation.
@param[in] type redo log record type
@param[in] space_id tablespace identifier
@@ -195,7 +185,7 @@ mlog_write_initial_log_record_fast(
been opened */
mtr_t* mtr); /*!< in: mtr */
/********************************************************//**
-Parses an initial log record written by mlog_write_initial_log_record.
+Parses an initial log record written by mlog_write_initial_log_record_low().
@return parsed record end, NULL if not a complete record */
const byte*
mlog_parse_initial_log_record(
@@ -206,7 +196,7 @@ mlog_parse_initial_log_record(
ulint* space, /*!< out: space id */
ulint* page_no);/*!< out: page number */
/********************************************************//**
-Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset.
+Parses a log record written by mtr_t::write(), mtr_t::memset().
@return parsed record end, NULL if not a complete record */
const byte*
mlog_parse_nbytes(
@@ -218,7 +208,7 @@ mlog_parse_nbytes(
or NULL */
void* page_zip);/*!< in/out: compressed page, or NULL */
/********************************************************//**
-Parses a log record written by mlog_write_string.
+Parses a log record written by mtr_t::memcpy().
@return parsed record end, NULL if not a complete record */
const byte*
mlog_parse_string(
diff --git a/storage/innobase/include/mtr0log.ic b/storage/innobase/include/mtr0log.ic
index b7ba92ff1a5..d493c0959a9 100644
--- a/storage/innobase/include/mtr0log.ic
+++ b/storage/innobase/include/mtr0log.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -141,30 +141,6 @@ mlog_catenate_ulint_compressed(
mlog_close(mtr, log_ptr);
}
-/********************************************************//**
-Catenates a compressed 64-bit integer to mlog. */
-UNIV_INLINE
-void
-mlog_catenate_ull_compressed(
-/*=========================*/
- mtr_t* mtr, /*!< in: mtr */
- ib_uint64_t val) /*!< in: value to write */
-{
- byte* log_ptr;
-
- log_ptr = mlog_open(mtr, 15);
-
- /* If no logging is requested, we may return now */
- if (log_ptr == NULL) {
-
- return;
- }
-
- log_ptr += mach_u64_write_compressed(log_ptr, val);
-
- mlog_close(mtr, log_ptr);
-}
-
/** Writes a log record about an operation.
@param[in] type redo log record type
@param[in] space_id tablespace identifier
@@ -181,14 +157,13 @@ mlog_write_initial_log_record_low(
byte* log_ptr,
mtr_t* mtr)
{
- ut_ad(type <= MLOG_BIGGEST_TYPE || EXTRA_CHECK_MLOG_NUMBER(type));
+ ut_ad(type <= MLOG_BIGGEST_TYPE);
ut_ad(type == MLOG_FILE_NAME
|| type == MLOG_FILE_DELETE
|| type == MLOG_FILE_CREATE2
|| type == MLOG_FILE_RENAME2
|| type == MLOG_INDEX_LOAD
|| type == MLOG_TRUNCATE
- || type == MLOG_FILE_WRITE_CRYPT_DATA
|| mtr->is_named_space(space_id));
mach_write_to_1(log_ptr, type);
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index ee1e3eadd71..635270d8a11 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -425,7 +425,71 @@ struct mtr_t {
static inline bool is_block_dirtied(const buf_block_t* block)
MY_ATTRIBUTE((warn_unused_result));
+ /** Write request types */
+ enum write_type
+ {
+ /** the page is guaranteed to always change */
+ NORMAL= 0,
+ /** optional: the page contents might not change */
+ OPT,
+ /** force a write, even if the page contents is not changing */
+ FORCED
+ };
+
+ /** Write 1, 2, 4, or 8 bytes to a file page.
+ @param[in] block file page
+ @param[in,out] ptr pointer in file page
+ @param[in] val value to write
+ @tparam l number of bytes to write
+ @tparam w write request type
+ @tparam V type of val */
+ template<unsigned l,write_type w= NORMAL,typename V>
+ inline void write(const buf_block_t &block, byte *ptr, V val)
+ MY_ATTRIBUTE((nonnull));
+
+ /** Log a write of a byte string to a page.
+ @param[in] b buffer page
+ @param[in] ofs byte offset from b->frame
+ @param[in] str the data to write
+ @param[in] len length of the data to write */
+ void memcpy(const buf_block_t &b, ulint ofs, ulint len);
+
+ /** Write a byte string to a page.
+ @param[in,out] b buffer page
+ @param[in] ofs byte offset from b->frame
+ @param[in] str the data to write
+ @param[in] len length of the data to write */
+ inline void memcpy(buf_block_t *b, ulint offset, const void *str, ulint len);
+
+ /** Initialize a string of bytes.
+ @param[in,out] b buffer page
+ @param[in] ofs byte offset from b->frame
+ @param[in] len length of the data to write
+ @param[in] val the data byte to write */
+ void memset(const buf_block_t* b, ulint ofs, ulint len, byte val);
+
private:
+ /**
+ Write a log record for writing 1, 2, or 4 bytes.
+ @param[in] block file page
+ @param[in,out] ptr pointer in file page
+ @param[in] l number of bytes to write
+ @param[in,out] log_ptr log record buffer
+ @param[in] val value to write */
+ void log_write(const buf_block_t &block, byte *ptr, mlog_id_t l,
+ byte *log_ptr, uint32_t val)
+ MY_ATTRIBUTE((nonnull));
+ /**
+ Write a log record for writing 8 bytes.
+ @param[in] block file page
+ @param[in,out] ptr pointer in file page
+ @param[in] l number of bytes to write (8)
+ @param[in,out] log_ptr log record buffer
+ @param[in] val value to write */
+ void log_write(const buf_block_t &block, byte *ptr, mlog_id_t l,
+ byte *log_ptr, uint64_t val)
+ MY_ATTRIBUTE((nonnull));
+
/** Prepare to write the mini-transaction log to the redo log buffer.
@return number of bytes to write in finish_write() */
inline ulint prepare_write();
diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h
index 7b5fd457d9f..06ac4a62e78 100644
--- a/storage/innobase/include/mtr0types.h
+++ b/storage/innobase/include/mtr0types.h
@@ -52,7 +52,7 @@ enum mtr_log_t {
/** @name Log item types
The log items are declared 'byte' so that the compiler can warn if val
-and type parameters are switched in a call to mlog_write_ulint. NOTE!
+and type parameters are switched in a call to mlog_write. NOTE!
For 1 - 8 bytes, the flag value must give the length also! @{ */
enum mlog_id_t {
/** if the mtr contains only one log record for one page,
diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h
index 7c9f85c47c7..a438d111086 100644
--- a/storage/innobase/include/page0page.h
+++ b/storage/innobase/include/page0page.h
@@ -31,6 +31,7 @@ Created 2/2/1994 Heikki Tuuri
#include "fil0fil.h"
#include "buf0buf.h"
#include "rem0rec.h"
+#include "mach0data.h"
#ifndef UNIV_INNOCHECKSUM
#include "dict0dict.h"
#include "data0data.h"
@@ -42,8 +43,6 @@ Created 2/2/1994 Heikki Tuuri
Index page header starts at the first offset left free by the FIL-module */
typedef byte page_header_t;
-#else
-# include "mach0data.h"
#endif /* !UNIV_INNOCHECKSUM */
#define PAGE_HEADER FSEG_PAGE_DATA /* index page header starts at this
@@ -393,13 +392,17 @@ inline
bool
page_rec_is_infimum(const rec_t* rec);
-/*************************************************************//**
-Returns the max trx id field value. */
-UNIV_INLINE
-trx_id_t
-page_get_max_trx_id(
-/*================*/
- const page_t* page); /*!< in: page */
+/** Read PAGE_MAX_TRX_ID.
+@param[in] page index page
+@return the value of PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC */
+inline trx_id_t page_get_max_trx_id(const page_t *page)
+{
+ static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment");
+ const byte *p= static_cast<const byte*>
+ (MY_ASSUME_ALIGNED(page + PAGE_HEADER + PAGE_MAX_TRX_ID, 8));
+ return mach_read_from_8(p);
+}
+
/*************************************************************//**
Sets the max trx id field value. */
void
@@ -424,7 +427,6 @@ page_update_max_trx_id(
/** Persist the AUTO_INCREMENT value on a clustered index root page.
@param[in,out] block clustered index root page
-@param[in] index clustered index
@param[in] autoinc next available AUTO_INCREMENT value
@param[in,out] mtr mini-transaction
@param[in] reset whether to reset the AUTO_INCREMENT
@@ -433,7 +435,6 @@ page_update_max_trx_id(
void
page_set_autoinc(
buf_block_t* block,
- const dict_index_t* index MY_ATTRIBUTE((unused)),
ib_uint64_t autoinc,
mtr_t* mtr,
bool reset)
@@ -517,17 +518,12 @@ page_header_set_ptr(
ulint field, /*!< in/out: PAGE_FREE, ... */
const byte* ptr); /*!< in: pointer or NULL*/
-/*************************************************************//**
-Resets the last insert info field in the page header. Writes to mlog
-about this operation. */
-UNIV_INLINE
-void
-page_header_reset_last_insert(
-/*==========================*/
- page_t* page, /*!< in: page */
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose
- uncompressed part will be updated, or NULL */
- mtr_t* mtr); /*!< in: mtr */
+/**
+Reset PAGE_LAST_INSERT.
+@param[in,out] block file page
+@param[in,out] mtr mini-transaction */
+inline void page_header_reset_last_insert(buf_block_t *block, mtr_t *mtr)
+ MY_ATTRIBUTE((nonnull));
#define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page))
#define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page))
@@ -663,14 +659,17 @@ ibool
page_rec_check(
/*===========*/
const rec_t* rec); /*!< in: record */
-/***************************************************************//**
-Gets the record pointed to by a directory slot.
+/** Get the record pointed to by a directory slot.
+@param[in] slot directory slot
@return pointer to record */
-UNIV_INLINE
-const rec_t*
-page_dir_slot_get_rec(
-/*==================*/
- const page_dir_slot_t* slot); /*!< in: directory slot */
+inline rec_t *page_dir_slot_get_rec(page_dir_slot_t *slot)
+{
+ return page_align(slot) + mach_read_from_2(slot);
+}
+inline const rec_t *page_dir_slot_get_rec(const page_dir_slot_t *slot)
+{
+ return page_dir_slot_get_rec(const_cast<rec_t*>(slot));
+}
/***************************************************************//**
This is used to set the record offset in a directory slot. */
UNIV_INLINE
diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic
index d13f5732faf..ccc76c7ce3b 100644
--- a/storage/innobase/include/page0page.ic
+++ b/storage/innobase/include/page0page.ic
@@ -28,25 +28,11 @@ Created 2/2/1994 Heikki Tuuri
#define page0page_ic
#ifndef UNIV_INNOCHECKSUM
-#include "mach0data.h"
#include "rem0cmp.h"
#include "mtr0log.h"
#include "page0zip.h"
/*************************************************************//**
-Returns the max trx id field value. */
-UNIV_INLINE
-trx_id_t
-page_get_max_trx_id(
-/*================*/
- const page_t* page) /*!< in: page */
-{
- ut_ad(page);
-
- return(mach_read_from_8(page + PAGE_HEADER + PAGE_MAX_TRX_ID));
-}
-
-/*************************************************************//**
Sets the max trx id field value if trx_id is bigger than the previous
value. */
UNIV_INLINE
@@ -115,21 +101,16 @@ page_set_ssn_id(
node_seq_t ssn_id, /*!< in: transaction id */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
- page_t* page = buf_block_get_frame(block);
-
ut_ad(!mtr || mtr_memo_contains_flagged(mtr, block,
MTR_MEMO_PAGE_SX_FIX
| MTR_MEMO_PAGE_X_FIX));
- if (page_zip) {
- mach_write_to_8(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id);
- page_zip_write_header(page_zip,
- page + FIL_RTREE_SPLIT_SEQ_NUM,
- 8, mtr);
- } else if (mtr) {
- mlog_write_ull(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id, mtr);
+ byte* ssn = block->frame + FIL_RTREE_SPLIT_SEQ_NUM;
+ if (UNIV_LIKELY_NULL(page_zip)) {
+ mach_write_to_8(ssn, ssn_id);
+ page_zip_write_header(page_zip, ssn, 8, mtr);
} else {
- mach_write_to_8(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id);
+ mtr->write<8,mtr_t::OPT>(*block, ssn, ssn_id);
}
}
@@ -229,30 +210,21 @@ page_header_set_ptr(
page_header_set_field(page, page_zip, field, offs);
}
-/*************************************************************//**
-Resets the last insert info field in the page header. Writes to mlog
-about this operation. */
-UNIV_INLINE
-void
-page_header_reset_last_insert(
-/*==========================*/
- page_t* page, /*!< in/out: page */
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose
- uncompressed part will be updated, or NULL */
- mtr_t* mtr) /*!< in: mtr */
+/**
+Reset PAGE_LAST_INSERT.
+@param[in,out] block file page
+@param[in,out] mtr mini-transaction */
+inline void page_header_reset_last_insert(buf_block_t *block, mtr_t *mtr)
{
- ut_ad(page != NULL);
- ut_ad(mtr != NULL);
+ byte *b= &block->frame[PAGE_HEADER + PAGE_LAST_INSERT];
- if (page_zip) {
- mach_write_to_2(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0);
- page_zip_write_header(page_zip,
- page + (PAGE_HEADER + PAGE_LAST_INSERT),
- 2, mtr);
- } else {
- mlog_write_ulint(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0,
- MLOG_2BYTES, mtr);
- }
+ if (UNIV_LIKELY_NULL(block->page.zip.data))
+ {
+ mach_write_to_2(b, 0);
+ page_zip_write_header(&block->page.zip, b, 2, mtr);
+ }
+ else
+ mtr->write<2,mtr_t::OPT>(*block, b, 0U);
}
/***************************************************************//**
@@ -542,18 +514,6 @@ page_rec_check(
}
/***************************************************************//**
-Gets the record pointed to by a directory slot.
-@return pointer to record */
-UNIV_INLINE
-const rec_t*
-page_dir_slot_get_rec(
-/*==================*/
- const page_dir_slot_t* slot) /*!< in: directory slot */
-{
- return(page_align(slot) + mach_read_from_2(slot));
-}
-
-/***************************************************************//**
This is used to set the record offset in a directory slot. */
UNIV_INLINE
void
diff --git a/storage/innobase/include/row0ftsort.h b/storage/innobase/include/row0ftsort.h
index a00d4bbba6a..0da8cb32353 100644
--- a/storage/innobase/include/row0ftsort.h
+++ b/storage/innobase/include/row0ftsort.h
@@ -80,12 +80,8 @@ struct fts_psort_t {
/*!< sort file */
row_merge_block_t* merge_block[FTS_NUM_AUX_INDEX];
/*!< buffer to write to file */
- row_merge_block_t* block_alloc[FTS_NUM_AUX_INDEX];
- /*!< buffer to allocated */
row_merge_block_t* crypt_block[FTS_NUM_AUX_INDEX];
/*!< buffer to crypt data */
- row_merge_block_t* crypt_alloc[FTS_NUM_AUX_INDEX];
- /*!< buffer to allocated */
ulint child_status; /*!< child task status */
ulint state; /*!< parent state */
fts_doc_list_t fts_doc_list; /*!< doc list to process */
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index d4556640c23..1d2155bfec7 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -321,8 +321,9 @@ extern my_bool srv_undo_log_truncate;
/* Enables or disables this prefix optimization. Disabled by default. */
extern my_bool srv_prefix_index_cluster_optimization;
-/** Default size of UNDO tablespace while it is created new. */
-extern const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
+/** Default size of UNDO tablespace (10MiB for innodb_page_size=16k) */
+constexpr ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES= (10U << 20) /
+ UNIV_PAGE_SIZE_DEF;
extern char* srv_log_group_home_dir;
diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h
index 40a37c2d97e..0d2820c3270 100644
--- a/storage/innobase/include/trx0purge.h
+++ b/storage/innobase/include/trx0purge.h
@@ -183,15 +183,15 @@ public:
to purge */
trx_rseg_t* rseg; /*!< Rollback segment for the next undo
record to purge */
- ulint page_no; /*!< Page number for the next undo
+ uint32_t page_no; /*!< Page number for the next undo
record to purge, page number of the
log header, if dummy record */
- ulint offset; /*!< Page offset for the next undo
+ uint32_t hdr_page_no; /*!< Header page of the undo log where
+ the next record to purge belongs */
+ uint16_t offset; /*!< Page offset for the next undo
record to purge, 0 if the dummy
record */
- ulint hdr_page_no; /*!< Header page of the undo log where
- the next record to purge belongs */
- ulint hdr_offset; /*!< Header byte offset on the page */
+ uint16_t hdr_offset; /*!< Header byte offset on the page */
TrxUndoRsegsIterator
diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h
index d4fdb19a988..937e05dfba6 100644
--- a/storage/innobase/include/trx0rseg.h
+++ b/storage/innobase/include/trx0rseg.h
@@ -36,7 +36,7 @@ Created 3/26/1996 Heikki Tuuri
@param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */
UNIV_INLINE
-trx_rsegf_t*
+buf_block_t*
trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr);
/** Gets a newly created rollback segment header.
@@ -45,29 +45,12 @@ trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr);
@param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */
UNIV_INLINE
-trx_rsegf_t*
+buf_block_t*
trx_rsegf_get_new(
ulint space,
ulint page_no,
mtr_t* mtr);
-/***************************************************************//**
-Sets the file page number of the nth undo log slot. */
-UNIV_INLINE
-void
-trx_rsegf_set_nth_undo(
-/*===================*/
- trx_rsegf_t* rsegf, /*!< in: rollback segment header */
- ulint n, /*!< in: index of slot */
- ulint page_no,/*!< in: page number of the undo log segment */
- mtr_t* mtr); /*!< in: mtr */
-/****************************************************************//**
-Looks for a free slot for an undo log segment.
-@return slot index or ULINT_UNDEFINED if not found */
-UNIV_INLINE
-ulint
-trx_rsegf_undo_find_free(const trx_rsegf_t* rsegf);
-
/** Create a rollback segment header.
@param[in,out] space system, undo, or temporary tablespace
@param[in] rseg_id rollback segment identifier
@@ -102,17 +85,6 @@ trx_rseg_create(ulint space_id)
void
trx_temp_rseg_create();
-/********************************************************************
-Get the number of unique rollback tablespaces in use except space id 0.
-The last space id will be the sentinel value ULINT_UNDEFINED. The array
-will be sorted on space id. Note: space_ids should have have space for
-TRX_SYS_N_RSEGS + 1 elements.
-@return number of unique rollback tablespaces in use. */
-ulint
-trx_rseg_get_n_undo_tablespaces(
-/*============================*/
- ulint* space_ids); /*!< out: array of space ids of
- UNDO tablespaces */
/* Number of undo log slots in a rollback segment file copy */
#define TRX_RSEG_N_SLOTS (srv_page_size / 16)
@@ -155,10 +127,10 @@ struct trx_rseg_t {
/** Page number of the last not yet purged log header in the history
list; FIL_NULL if all list purged */
- ulint last_page_no;
+ uint32_t last_page_no;
/** Byte offset of the last not yet purged log header */
- ulint last_offset;
+ uint16_t last_offset;
/** trx_t::no * 2 + old_insert of the last not yet purged log */
trx_id_t last_commit;
@@ -255,15 +227,13 @@ If no binlog information is present, the first byte is NUL. */
/*-------------------------------------------------------------*/
/** Read the page number of an undo log slot.
-@param[in] rsegf rollback segment header
-@param[in] n slot number */
-inline
-uint32_t
-trx_rsegf_get_nth_undo(const trx_rsegf_t* rsegf, ulint n)
+@param[in] rseg_header rollback segment header
+@param[in] n slot number */
+inline uint32_t trx_rsegf_get_nth_undo(const buf_block_t *rseg_header, ulint n)
{
- ut_ad(n < TRX_RSEG_N_SLOTS);
- return mach_read_from_4(rsegf + TRX_RSEG_UNDO_SLOTS
- + n * TRX_RSEG_SLOT_SIZE);
+ ut_ad(n < TRX_RSEG_N_SLOTS);
+ return mach_read_from_4(TRX_RSEG + TRX_RSEG_UNDO_SLOTS +
+ n * TRX_RSEG_SLOT_SIZE + rseg_header->frame);
}
#ifdef WITH_WSREP
@@ -273,7 +243,7 @@ trx_rsegf_get_nth_undo(const trx_rsegf_t* rsegf, ulint n)
@param[in,out] mtr mini-transaction */
void
trx_rseg_update_wsrep_checkpoint(
- trx_rsegf_t* rseg_header,
+ buf_block_t* rseg_header,
const XID* xid,
mtr_t* mtr);
@@ -295,7 +265,7 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid);
/** Upgrade a rollback segment header page to MariaDB 10.3 format.
@param[in,out] rseg_header rollback segment header page
@param[in,out] mtr mini-transaction */
-void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr);
+void trx_rseg_format_upgrade(buf_block_t *rseg_header, mtr_t *mtr);
/** Update the offset information about the end of the binlog entry
which corresponds to the transaction just being committed.
@@ -304,8 +274,8 @@ up to which replication has proceeded.
@param[in,out] rseg_header rollback segment header
@param[in] trx committing transaction
@param[in,out] mtr mini-transaction */
-void
-trx_rseg_update_binlog_offset(byte* rseg_header, const trx_t* trx, mtr_t* mtr);
+void trx_rseg_update_binlog_offset(buf_block_t *rseg_header, const trx_t *trx,
+ mtr_t *mtr);
#include "trx0rseg.ic"
diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic
index 0cff8fa1f5c..e0e8c175a5d 100644
--- a/storage/innobase/include/trx0rseg.ic
+++ b/storage/innobase/include/trx0rseg.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -33,7 +33,7 @@ Created 3/26/1996 Heikki Tuuri
@param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */
UNIV_INLINE
-trx_rsegf_t*
+buf_block_t*
trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr)
{
ut_ad(space == fil_system.sys_space || space == fil_system.temp_space
@@ -44,8 +44,7 @@ trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr)
0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER);
-
- return TRX_RSEG + block->frame;
+ return block;
}
/** Gets a newly created rollback segment header.
@@ -54,14 +53,13 @@ trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr)
@param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */
UNIV_INLINE
-trx_rsegf_t*
+buf_block_t*
trx_rsegf_get_new(
ulint space,
ulint page_no,
mtr_t* mtr)
{
buf_block_t* block;
- trx_rsegf_t* header;
ut_ad(space <= srv_undo_tablespaces_active || space == SRV_TMP_SPACE_ID
|| !srv_was_started);
@@ -70,54 +68,5 @@ trx_rsegf_get_new(
block = buf_page_get(page_id_t(space, page_no), 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
-
- header = TRX_RSEG + buf_block_get_frame(block);
-
- return(header);
-}
-
-/***************************************************************//**
-Sets the file page number of the nth undo log slot. */
-UNIV_INLINE
-void
-trx_rsegf_set_nth_undo(
-/*===================*/
- trx_rsegf_t* rsegf, /*!< in: rollback segment header */
- ulint n, /*!< in: index of slot */
- ulint page_no,/*!< in: page number of the undo log segment */
- mtr_t* mtr) /*!< in: mtr */
-{
- ut_a(n < TRX_RSEG_N_SLOTS);
-
- mlog_write_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + n * TRX_RSEG_SLOT_SIZE,
- page_no, MLOG_4BYTES, mtr);
-}
-
-/****************************************************************//**
-Looks for a free slot for an undo log segment.
-@return slot index or ULINT_UNDEFINED if not found */
-UNIV_INLINE
-ulint
-trx_rsegf_undo_find_free(const trx_rsegf_t* rsegf)
-{
- ulint i;
- ulint page_no;
- ulint max_slots = TRX_RSEG_N_SLOTS;
-
-#ifdef UNIV_DEBUG
- if (trx_rseg_n_slots_debug) {
- max_slots = ut_min(static_cast<ulint>(trx_rseg_n_slots_debug),
- static_cast<ulint>(TRX_RSEG_N_SLOTS));
- }
-#endif
-
- for (i = 0; i < max_slots; i++) {
- page_no = trx_rsegf_get_nth_undo(rsegf, i);
-
- if (page_no == FIL_NULL) {
- return(i);
- }
- }
-
- return(ULINT_UNDEFINED);
+ return block;
}
diff --git a/storage/innobase/include/trx0types.h b/storage/innobase/include/trx0types.h
index 2aaec580d65..83d6d2c0db2 100644
--- a/storage/innobase/include/trx0types.h
+++ b/storage/innobase/include/trx0types.h
@@ -121,8 +121,6 @@ struct trx_savept_t{
/** File objects */
/* @{ */
-/** Rollback segment header */
-typedef byte trx_rsegf_t;
/** Undo segment header */
typedef byte trx_usegf_t;
/** Undo log header */
diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h
index ce92e5de5e1..8dec56a5e7d 100644
--- a/storage/innobase/include/trx0undo.h
+++ b/storage/innobase/include/trx0undo.h
@@ -46,10 +46,10 @@ UNIV_INLINE
roll_ptr_t
trx_undo_build_roll_ptr(
/*====================*/
- ibool is_insert, /*!< in: TRUE if insert undo log */
+ bool is_insert, /*!< in: TRUE if insert undo log */
ulint rseg_id, /*!< in: rollback segment id */
- ulint page_no, /*!< in: page number */
- ulint offset); /*!< in: offset of the undo entry within page */
+ uint32_t page_no, /*!< in: page number */
+ uint16_t offset); /*!< in: offset of the undo entry within page */
/***********************************************************************//**
Decodes a roll pointer. */
UNIV_INLINE
@@ -57,16 +57,16 @@ void
trx_undo_decode_roll_ptr(
/*=====================*/
roll_ptr_t roll_ptr, /*!< in: roll pointer */
- ibool* is_insert, /*!< out: TRUE if insert undo log */
+ bool* is_insert, /*!< out: TRUE if insert undo log */
ulint* rseg_id, /*!< out: rollback segment id */
- ulint* page_no, /*!< out: page number */
- ulint* offset); /*!< out: offset of the undo
+ uint32_t* page_no, /*!< out: page number */
+ uint16_t* offset); /*!< out: offset of the undo
entry within page */
/***********************************************************************//**
-Returns TRUE if the roll pointer is of the insert type.
-@return TRUE if insert undo log */
+Determine if DB_ROLL_PTR is of the insert type.
+@return true if insert */
UNIV_INLINE
-ibool
+bool
trx_undo_roll_ptr_is_insert(
/*========================*/
roll_ptr_t roll_ptr); /*!< in: roll pointer */
@@ -101,7 +101,7 @@ inline roll_ptr_t trx_read_roll_ptr(const byte* ptr)
@param[in,out] mtr mini-transaction
@return pointer to page x-latched */
UNIV_INLINE
-page_t*
+buf_block_t*
trx_undo_page_get(const page_id_t page_id, mtr_t* mtr);
/** Gets an undo log page and s-latches it.
@@ -109,56 +109,52 @@ trx_undo_page_get(const page_id_t page_id, mtr_t* mtr);
@param[in,out] mtr mini-transaction
@return pointer to page s-latched */
UNIV_INLINE
-page_t*
+buf_block_t*
trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr);
-/******************************************************************//**
-Returns the next undo log record on the page in the specified log, or
-NULL if none exists.
-@return pointer to record, NULL if none */
-UNIV_INLINE
-trx_undo_rec_t*
-trx_undo_page_get_next_rec(
-/*=======================*/
- trx_undo_rec_t* rec, /*!< in: undo log record */
- ulint page_no,/*!< in: undo log header page number */
- ulint offset);/*!< in: undo log header offset on page */
-/***********************************************************************//**
-Gets the previous record in an undo log.
-@return undo log record, the page s-latched, NULL if none */
+/** Get the next record in an undo log.
+@param[in] undo_page undo log page
+@param[in] rec undo record offset in the page
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@return undo log record, the page latched, NULL if none */
+inline trx_undo_rec_t*
+trx_undo_page_get_next_rec(const buf_block_t *undo_page, uint16_t rec,
+ uint32_t page_no, uint16_t offset);
+/** Get the previous record in an undo log.
+@param[in,out] block undo log page
+@param[in] rec undo record offset in the page
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@param[in] shared latching mode: true=RW_S_LATCH, false=RW_X_LATCH
+@param[in,out] mtr mini-transaction
+@return undo log record, the page latched, NULL if none */
trx_undo_rec_t*
-trx_undo_get_prev_rec(
-/*==================*/
- trx_undo_rec_t* rec, /*!< in: undo record */
- ulint page_no,/*!< in: undo log header page number */
- ulint offset, /*!< in: undo log header offset on page */
- bool shared, /*!< in: true=S-latch, false=X-latch */
- mtr_t* mtr); /*!< in: mtr */
-/***********************************************************************//**
-Gets the next record in an undo log.
-@return undo log record, the page s-latched, NULL if none */
+trx_undo_get_prev_rec(buf_block_t *&block, uint16_t rec, uint32_t page_no,
+ uint16_t offset, bool shared, mtr_t *mtr);
+/** Get the next record in an undo log.
+@param[in,out] block undo log page
+@param[in] rec undo record offset in the page
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@param[in,out] mtr mini-transaction
+@return undo log record, the page latched, NULL if none */
trx_undo_rec_t*
-trx_undo_get_next_rec(
-/*==================*/
- trx_undo_rec_t* rec, /*!< in: undo record */
- ulint page_no,/*!< in: undo log header page number */
- ulint offset, /*!< in: undo log header offset on page */
- mtr_t* mtr); /*!< in: mtr */
-
-/** Gets the first record in an undo log.
-@param[in] space undo log header space
-@param[in] page_no undo log header page number
-@param[in] offset undo log header offset on page
-@param[in] mode latching mode: RW_S_LATCH or RW_X_LATCH
-@param[in,out] mtr mini-transaction
+trx_undo_get_next_rec(buf_block_t *&block, uint16_t rec, uint32_t page_no,
+ uint16_t offset, mtr_t *mtr);
+
+/** Get the first record in an undo log.
+@param[in] space undo log header space
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@param[in] mode latching mode: RW_S_LATCH or RW_X_LATCH
+@param[out] block undo log page
+@param[in,out] mtr mini-transaction
@return undo log record, the page latched, NULL if none */
trx_undo_rec_t*
-trx_undo_get_first_rec(
- fil_space_t* space,
- ulint page_no,
- ulint offset,
- ulint mode,
- mtr_t* mtr);
+trx_undo_get_first_rec(const fil_space_t &space, uint32_t page_no,
+ uint16_t offset, ulint mode, buf_block_t*& block,
+ mtr_t *mtr);
/** Allocate an undo log page.
@param[in,out] undo undo log
@@ -193,8 +189,8 @@ freed, but emptied, if all the records there are below the limit.
void
trx_undo_truncate_start(
trx_rseg_t* rseg,
- ulint hdr_page_no,
- ulint hdr_offset,
+ uint32_t hdr_page_no,
+ uint16_t hdr_offset,
undo_no_t limit);
/** Mark that an undo log header belongs to a data dictionary transaction.
@param[in] trx dictionary transaction
@@ -227,7 +223,7 @@ trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo,
/******************************************************************//**
Sets the state of the undo log segment at a transaction finish.
@return undo log segment header page, x-latched */
-page_t*
+buf_block_t*
trx_undo_set_state_at_finish(
/*=========================*/
trx_undo_t* undo, /*!< in: undo log memory copy */
@@ -237,14 +233,10 @@ trx_undo_set_state_at_finish(
@param[in,out] trx transaction
@param[in,out] undo undo log
@param[in] rollback false=XA PREPARE, true=XA ROLLBACK
-@param[in,out] mtr mini-transaction
-@return undo log segment header page, x-latched */
-page_t*
-trx_undo_set_state_at_prepare(
- trx_t* trx,
- trx_undo_t* undo,
- bool rollback,
- mtr_t* mtr);
+@param[in,out] mtr mini-transaction */
+void trx_undo_set_state_at_prepare(trx_t *trx, trx_undo_t *undo, bool rollback,
+ mtr_t *mtr)
+ MY_ATTRIBUTE((nonnull));
/** Free an old insert or temporary undo log after commit or rollback.
The information is not needed after a commit or rollback, therefore
@@ -281,14 +273,14 @@ trx_undo_parse_page_header_reuse(
/** Parse the redo log entry of an undo log page header create.
@param[in] ptr redo log record
@param[in] end_ptr end of log buffer
-@param[in,out] page page frame or NULL
+@param[in,out] block page frame or NULL
@param[in,out] mtr mini-transaction or NULL
@return end of log record or NULL */
byte*
trx_undo_parse_page_header(
const byte* ptr,
const byte* end_ptr,
- page_t* page,
+ buf_block_t* block,
mtr_t* mtr);
/** Read an undo log when starting up the database.
@param[in,out] rseg rollback segment
@@ -296,9 +288,9 @@ trx_undo_parse_page_header(
@param[in] page_no undo log segment page number
@param[in,out] max_trx_id the largest observed transaction ID
@return size of the undo log in pages */
-ulint
-trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
- trx_id_t& max_trx_id);
+uint32_t
+trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no,
+ trx_id_t &max_trx_id);
#endif /* !UNIV_INNOCHECKSUM */
@@ -340,20 +332,20 @@ struct trx_undo_t {
id */
trx_rseg_t* rseg; /*!< rseg where the undo log belongs */
/*-----------------------------*/
- ulint hdr_page_no; /*!< page number of the header page in
+ uint32_t hdr_page_no; /*!< page number of the header page in
the undo log */
- ulint hdr_offset; /*!< header offset of the undo log on
- the page */
- ulint last_page_no; /*!< page number of the last page in the
+ uint32_t last_page_no; /*!< page number of the last page in the
undo log; this may differ from
top_page_no during a rollback */
- ulint size; /*!< current size in pages */
+ uint16_t hdr_offset; /*!< header offset of the undo log on
+ the page */
+ uint32_t size; /*!< current size in pages */
/*-----------------------------*/
- ulint top_page_no; /*!< page number where the latest undo
+ uint32_t top_page_no; /*!< page number where the latest undo
log record was catenated; during
rollback the page from which the latest
undo record was chosen */
- ulint top_offset; /*!< offset of the latest undo record,
+ uint16_t top_offset; /*!< offset of the latest undo record,
i.e., the topmost element in the undo
log if we think of it as a stack */
undo_no_t top_undo_no; /*!< undo number of the latest record
diff --git a/storage/innobase/include/trx0undo.ic b/storage/innobase/include/trx0undo.ic
index 6d1ec16869e..06e31eb55b3 100644
--- a/storage/innobase/include/trx0undo.ic
+++ b/storage/innobase/include/trx0undo.ic
@@ -34,22 +34,17 @@ UNIV_INLINE
roll_ptr_t
trx_undo_build_roll_ptr(
/*====================*/
- ibool is_insert, /*!< in: TRUE if insert undo log */
+ bool is_insert, /*!< in: TRUE if insert undo log */
ulint rseg_id, /*!< in: rollback segment id */
- ulint page_no, /*!< in: page number */
- ulint offset) /*!< in: offset of the undo entry within page */
+ uint32_t page_no, /*!< in: page number */
+ uint16_t offset) /*!< in: offset of the undo entry within page */
{
- roll_ptr_t roll_ptr;
- compile_time_assert(DATA_ROLL_PTR_LEN == 7);
- ut_ad(is_insert == 0 || is_insert == 1);
- ut_ad(rseg_id < TRX_SYS_N_RSEGS);
- ut_ad(offset < 65536);
-
- roll_ptr = (roll_ptr_t) is_insert << ROLL_PTR_INSERT_FLAG_POS
- | (roll_ptr_t) rseg_id << ROLL_PTR_RSEG_ID_POS
- | (roll_ptr_t) page_no << ROLL_PTR_PAGE_POS
- | offset;
- return(roll_ptr);
+ compile_time_assert(DATA_ROLL_PTR_LEN == 7);
+ ut_ad(rseg_id < TRX_SYS_N_RSEGS);
+
+ return roll_ptr_t{is_insert} << ROLL_PTR_INSERT_FLAG_POS |
+ roll_ptr_t{rseg_id} << ROLL_PTR_RSEG_ID_POS |
+ roll_ptr_t{page_no} << ROLL_PTR_PAGE_POS | offset;
}
/***********************************************************************//**
@@ -59,35 +54,32 @@ void
trx_undo_decode_roll_ptr(
/*=====================*/
roll_ptr_t roll_ptr, /*!< in: roll pointer */
- ibool* is_insert, /*!< out: TRUE if insert undo log */
+ bool* is_insert, /*!< out: TRUE if insert undo log */
ulint* rseg_id, /*!< out: rollback segment id */
- ulint* page_no, /*!< out: page number */
- ulint* offset) /*!< out: offset of the undo
+ uint32_t* page_no, /*!< out: page number */
+ uint16_t* offset) /*!< out: offset of the undo
entry within page */
{
- compile_time_assert(DATA_ROLL_PTR_LEN == 7);
- ut_ad(roll_ptr < (1ULL << 56));
- *offset = (ulint) roll_ptr & 0xFFFF;
- roll_ptr >>= 16;
- *page_no = (ulint) roll_ptr & 0xFFFFFFFF;
- roll_ptr >>= 32;
- *rseg_id = (ulint) roll_ptr & 0x7F;
- roll_ptr >>= 7;
- *is_insert = (ibool) roll_ptr; /* TRUE==1 */
+ compile_time_assert(DATA_ROLL_PTR_LEN == 7);
+ ut_ad(roll_ptr < (1ULL << 56));
+ *offset= static_cast<uint16_t>(roll_ptr);
+ *page_no= static_cast<uint32_t>(roll_ptr >> 16);
+ *rseg_id= static_cast<ulint>(roll_ptr >> 48 & 0x7F);
+ *is_insert= static_cast<bool>(roll_ptr >> 55);
}
/***********************************************************************//**
-Returns TRUE if the roll pointer is of the insert type.
-@return TRUE if insert undo log */
+Determine if DB_ROLL_PTR is of the insert type.
+@return true if insert */
UNIV_INLINE
-ibool
+bool
trx_undo_roll_ptr_is_insert(
/*========================*/
roll_ptr_t roll_ptr) /*!< in: roll pointer */
{
compile_time_assert(DATA_ROLL_PTR_LEN == 7);
ut_ad(roll_ptr < (1ULL << (ROLL_PTR_INSERT_FLAG_POS + 1)));
- return((ibool) (roll_ptr >> ROLL_PTR_INSERT_FLAG_POS));
+ return static_cast<bool>(roll_ptr >> ROLL_PTR_INSERT_FLAG_POS);
}
/***********************************************************************//**
@@ -108,14 +100,13 @@ trx_undo_trx_id_is_insert(
@param[in,out] mtr mini-transaction
@return pointer to page x-latched */
UNIV_INLINE
-page_t*
+buf_block_t*
trx_undo_page_get(const page_id_t page_id, mtr_t* mtr)
{
buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
-
- return(buf_block_get_frame(block));
+ return block;
}
/** Gets an undo log page and s-latches it.
@@ -123,14 +114,14 @@ trx_undo_page_get(const page_id_t page_id, mtr_t* mtr)
@param[in,out] mtr mini-transaction
@return pointer to page s-latched */
UNIV_INLINE
-page_t*
+buf_block_t*
trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr)
{
buf_block_t* block = buf_page_get(page_id, 0, RW_S_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
- return(buf_block_get_frame(block));
+ return block;
}
/** Determine the end offset of undo log records of an undo log page.
@@ -139,46 +130,29 @@ trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr)
@param[in] offset undo log header offset
@return end offset */
inline
-uint16_t
-trx_undo_page_get_end(const page_t* undo_page, ulint page_no, ulint offset)
+uint16_t trx_undo_page_get_end(const buf_block_t *undo_page, uint32_t page_no,
+ uint16_t offset)
{
- if (page_no == page_get_page_no(undo_page)) {
- if (uint16_t end = mach_read_from_2(TRX_UNDO_NEXT_LOG
- + offset + undo_page)) {
- return end;
- }
- }
-
- return mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
- + undo_page);
+ if (page_no == undo_page->page.id.page_no())
+ if (uint16_t end = mach_read_from_2(TRX_UNDO_NEXT_LOG + offset +
+ undo_page->frame))
+ return end;
+
+ return mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE +
+ undo_page->frame);
}
-/******************************************************************//**
-Returns the next undo log record on the page in the specified log, or
-NULL if none exists.
-@return pointer to record, NULL if none */
-UNIV_INLINE
-trx_undo_rec_t*
-trx_undo_page_get_next_rec(
-/*=======================*/
- trx_undo_rec_t* rec, /*!< in: undo log record */
- ulint page_no,/*!< in: undo log header page number */
- ulint offset) /*!< in: undo log header offset on page */
+/** Get the next record in an undo log.
+@param[in] undo_page undo log page
+@param[in] rec undo record offset in the page
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@return undo log record, the page latched, NULL if none */
+inline trx_undo_rec_t*
+trx_undo_page_get_next_rec(const buf_block_t *undo_page, uint16_t rec,
+ uint32_t page_no, uint16_t offset)
{
- page_t* undo_page;
- ulint end;
- ulint next;
-
- undo_page = (page_t*) ut_align_down(rec, srv_page_size);
-
- end = trx_undo_page_get_end(undo_page, page_no, offset);
-
- next = mach_read_from_2(rec);
-
- if (next == end) {
-
- return(NULL);
- }
-
- return(undo_page + next);
+ uint16_t end= trx_undo_page_get_end(undo_page, page_no, offset);
+ uint16_t next= mach_read_from_2(undo_page->frame + rec);
+ return next == end ? nullptr : undo_page->frame + next;
}
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index d9652784218..ce87617fa8d 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -633,8 +633,6 @@ typedef void* os_thread_ret_t;
extern ulong srv_page_size_shift;
extern ulong srv_page_size;
-static const size_t UNIV_SECTOR_SIZE = 512;
-
/* Dimension of spatial object we support so far. It has its root in
myisam/sp_defs.h. We only support 2 dimension data */
#define SPDIMS 2
diff --git a/storage/innobase/include/ut0byte.h b/storage/innobase/include/ut0byte.h
index 4ce931e0189..d79f6ab414c 100644
--- a/storage/innobase/include/ut0byte.h
+++ b/storage/innobase/include/ut0byte.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -62,15 +63,6 @@ ut_uint64_align_up(
ulint align_no); /*!< in: align by this number
which must be a power of 2 */
/*********************************************************//**
-The following function rounds up a pointer to the nearest aligned address.
-@return aligned pointer */
-UNIV_INLINE
-void*
-ut_align(
-/*=====*/
- const void* ptr, /*!< in: pointer */
- ulint align_no); /*!< in: align by this number */
-/*********************************************************//**
The following function rounds down a pointer to the nearest
aligned address.
@return aligned pointer */
diff --git a/storage/innobase/include/ut0byte.ic b/storage/innobase/include/ut0byte.ic
index e6e60f07886..699111b343b 100644
--- a/storage/innobase/include/ut0byte.ic
+++ b/storage/innobase/include/ut0byte.ic
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -75,25 +76,6 @@ ut_uint64_align_up(
}
/*********************************************************//**
-The following function rounds up a pointer to the nearest aligned address.
-@return aligned pointer */
-UNIV_INLINE
-void*
-ut_align(
-/*=====*/
- const void* ptr, /*!< in: pointer */
- ulint align_no) /*!< in: align by this number */
-{
- ut_ad(align_no > 0);
- ut_ad(((align_no - 1) & align_no) == 0);
- ut_ad(ptr);
-
- ut_ad(sizeof(void*) == sizeof(ulint));
-
- return((void*)((((ulint) ptr) + align_no - 1) & ~(align_no - 1)));
-}
-
-/*********************************************************//**
The following function rounds down a pointer to the nearest
aligned address.
@return aligned pointer */
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 9a0abb8853c..8078c608644 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -62,7 +62,7 @@ General philosophy of InnoDB redo-logs:
through mtr, which in mtr_commit() writes log records
to the InnoDB redo log.
-2) Normally these changes are performed using a mlog_write_ulint()
+2) Normally these changes are performed using a mlog_write()
or similar function.
3) In some page level operations only a code number of a
@@ -822,14 +822,14 @@ log_buffer_switch()
if (log_sys.first_in_use) {
log_sys.first_in_use = false;
- ut_ad(log_sys.buf == ut_align(log_sys.buf,
- OS_FILE_LOG_BLOCK_SIZE));
+ ut_ad(log_sys.buf == ut_align_down(log_sys.buf,
+ OS_FILE_LOG_BLOCK_SIZE));
log_sys.buf += srv_log_buffer_size;
} else {
log_sys.first_in_use = true;
log_sys.buf -= srv_log_buffer_size;
- ut_ad(log_sys.buf == ut_align(log_sys.buf,
- OS_FILE_LOG_BLOCK_SIZE));
+ ut_ad(log_sys.buf == ut_align_down(log_sys.buf,
+ OS_FILE_LOG_BLOCK_SIZE));
}
/* Copy the last block to new buf */
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 46ab1702419..5d41ff1fb03 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -254,10 +254,8 @@ public:
lsn_t lsn;
/** Whether btr_page_create() avoided a read of the page.
- At the end of the last recovery batch, ibuf_merge()
- will invoke change buffer merge for pages that reside
- in the buffer pool. (In the last batch, loading pages
- would trigger change buffer merge.) */
+ At the end of the last recovery batch, mark_ibuf_exist()
+ will mark pages for which this flag is set. */
bool created;
};
@@ -307,14 +305,9 @@ public:
}
}
- /** On the last recovery batch, mark whether the page contains
- change buffered changes for the list of pages that were initialized
+ /** On the last recovery batch, mark whether there exist
+ buffered changes for the pages that were initialized
by buf_page_create() and still reside in the buffer pool.
-
- Note: When MDEV-14481 implements redo log apply in the
- background, we will have to ensure that buf_page_get_gen()
- will not deliver stale pages to users (pages on which the
- change buffer was not merged yet).
@param[in,out] mtr dummy mini-transaction */
void mark_ibuf_exist(mtr_t& mtr)
{
@@ -1462,10 +1455,8 @@ parse_log:
}
#endif /* UNIV_DEBUG */
ptr = mlog_parse_nbytes(type, ptr, end_ptr, page, page_zip);
- if (ptr != NULL && page != NULL
- && page_no == 0 && type == MLOG_4BYTES) {
- ulint offs = mach_read_from_2(old_ptr);
- switch (offs) {
+ if (ptr && page && !page_no && type == MLOG_4BYTES) {
+ switch (ulint offs = mach_read_from_2(old_ptr)) {
fil_space_t* space;
ulint val;
default:
@@ -1621,7 +1612,7 @@ parse_log:
break;
case MLOG_UNDO_HDR_CREATE:
ut_ad(!page || page_type == FIL_PAGE_UNDO_LOG);
- ptr = trx_undo_parse_page_header(ptr, end_ptr, page, mtr);
+ ptr = trx_undo_parse_page_header(ptr, end_ptr, block, mtr);
break;
case MLOG_REC_MIN_MARK: case MLOG_COMP_REC_MIN_MARK:
ut_ad(!page || fil_page_type_is_index(page_type));
@@ -1632,7 +1623,7 @@ parse_log:
ut_a(type == MLOG_COMP_REC_MIN_MARK || !page_zip);
ptr = btr_parse_set_min_rec_mark(
ptr, end_ptr, type == MLOG_COMP_REC_MIN_MARK,
- page, mtr);
+ block, mtr);
break;
case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE:
ut_ad(!page || fil_page_type_is_index(page_type));
@@ -1662,6 +1653,25 @@ parse_log:
this record yet. */
break;
case MLOG_WRITE_STRING:
+ if (page_no || mach_read_from_2(ptr + 2)
+ != 11 + MY_AES_BLOCK_SIZE) {
+ /* Not writing crypt_info */
+ } else if (fil_space_t* space
+ = fil_space_acquire_silent(space_id)) {
+ if (mach_read_from_2(ptr)
+ == FSP_HEADER_OFFSET + XDES_ARR_OFFSET + MAGIC_SZ
+ + space->physical_size() * XDES_SIZE
+ / FSP_EXTENT_SIZE
+ && (ptr[4] == CRYPT_SCHEME_UNENCRYPTED
+ || ptr[4] == CRYPT_SCHEME_1)
+ && ptr[5] == MY_AES_BLOCK_SIZE
+ && ptr[6 + MY_AES_BLOCK_SIZE + 4 + 4]
+ <= FIL_ENCRYPTION_OFF) {
+ /* from fil_space_crypt_t::write_page0() */
+ fil_crypt_parse(space, ptr + 4);
+ }
+ space->release();
+ }
ptr = mlog_parse_string(ptr, end_ptr, page, page_zip);
break;
case MLOG_ZIP_WRITE_NODE_PTR:
@@ -2083,8 +2093,7 @@ static void recv_read_in_area(page_id_t page_id)
}
/** Apply recv_sys.pages to persistent data pages.
-@param[in] last_batch whether the change buffer merge will be
- performed as part of the operation */
+@param[in] last_batch whether redo log writes are possible */
void recv_apply_hashed_log_recs(bool last_batch)
{
ut_ad(srv_operation == SRV_OPERATION_NORMAL
@@ -3182,10 +3191,6 @@ recv_group_scan_log_recs(
do {
if (last_phase && store_to_hash == STORE_NO) {
store_to_hash = STORE_IF_EXISTS;
- /* We must not allow change buffer
- merge here, because it would generate
- redo log records before we have
- finished the redo log scan. */
recv_apply_hashed_log_recs(false);
}
@@ -3397,6 +3402,15 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
ut_ad(srv_operation == SRV_OPERATION_NORMAL
|| srv_operation == SRV_OPERATION_RESTORE
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT);
+#ifdef UNIV_DEBUG
+ for (ulint i= 0; i < srv_buf_pool_instances; i++) {
+ buf_pool_t* buf_pool = buf_pool_from_array(i);
+ buf_flush_list_mutex_enter(buf_pool);
+ ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
+ ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
+ buf_flush_list_mutex_exit(buf_pool);
+ }
+#endif
/* Initialize red-black tree for fast insertions into the
flush_list during recovery process. */
diff --git a/storage/innobase/mtr/mtr0log.cc b/storage/innobase/mtr/mtr0log.cc
index 34f988db46a..60ed8830593 100644
--- a/storage/innobase/mtr/mtr0log.cc
+++ b/storage/innobase/mtr/mtr0log.cc
@@ -64,7 +64,7 @@ mlog_write_initial_log_record(
{
byte* log_ptr;
- ut_ad(type <= MLOG_BIGGEST_TYPE || EXTRA_CHECK_MLOG_NUMBER(type));
+ ut_ad(type <= MLOG_BIGGEST_TYPE);
ut_ad(type > MLOG_8BYTES);
log_ptr = mlog_open(mtr, 11);
@@ -121,7 +121,7 @@ mlog_parse_initial_log_record(
}
/********************************************************//**
-Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset.
+Parses a log record written by mtr_t::write(), mtr_t::memset().
@return parsed record end, NULL if not a complete record or a corrupt record */
const byte*
mlog_parse_nbytes(
@@ -244,139 +244,92 @@ mlog_parse_nbytes(
return const_cast<byte*>(ptr);
}
-/********************************************************//**
-Writes 1, 2 or 4 bytes to a file page. Writes the corresponding log
-record to the mini-transaction log if mtr is not NULL. */
-void
-mlog_write_ulint(
-/*=============*/
- byte* ptr, /*!< in: pointer where to write */
- ulint val, /*!< in: value to write */
- mlog_id_t type, /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/**
+Write a log record for writing 1, 2, 4, or 8 bytes.
+@param[in] block file page
+@param[in,out] ptr pointer in file page
+@param[in] l number of bytes to write
+@param[in,out] log_ptr log record buffer
+@param[in,out] mtr mini-transaction */
+static byte *
+mlog_log_write_low(const buf_block_t &block, byte *ptr, mlog_id_t l,
+ byte *log_ptr, mtr_t &mtr)
{
- switch (type) {
- case MLOG_1BYTE:
- mach_write_to_1(ptr, val);
- break;
- case MLOG_2BYTES:
- mach_write_to_2(ptr, val);
- break;
- case MLOG_4BYTES:
- mach_write_to_4(ptr, val);
- break;
- default:
- ut_error;
- }
-
- if (mtr != 0) {
- byte* log_ptr = mlog_open(mtr, 11 + 2 + 5);
-
- /* If no logging is requested, we may return now */
-
- if (log_ptr != 0) {
-
- log_ptr = mlog_write_initial_log_record_fast(
- ptr, type, log_ptr, mtr);
-
- mach_write_to_2(log_ptr, page_offset(ptr));
- log_ptr += 2;
-
- log_ptr += mach_write_compressed(log_ptr, val);
-
- mlog_close(mtr, log_ptr);
- }
- }
+ ut_ad(block.page.state == BUF_BLOCK_FILE_PAGE);
+ ut_ad(ptr >= block.frame + FIL_PAGE_OFFSET);
+ ut_ad(ptr + unsigned(l) <= &block.frame[srv_page_size - FIL_PAGE_DATA_END]);
+ log_ptr= mlog_write_initial_log_record_low(l,
+ block.page.id.space(),
+ block.page.id.page_no(),
+ log_ptr, &mtr);
+ mach_write_to_2(log_ptr, page_offset(ptr));
+ return log_ptr + 2;
}
-/********************************************************//**
-Writes 8 bytes to a file page. Writes the corresponding log
-record to the mini-transaction log, only if mtr is not NULL */
-void
-mlog_write_ull(
-/*===========*/
- byte* ptr, /*!< in: pointer where to write */
- ib_uint64_t val, /*!< in: value to write */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/**
+Write a log record for writing 1, 2, or 4 bytes.
+@param[in] block file page
+@param[in,out] ptr pointer in file page
+@param[in] l number of bytes to write
+@param[in,out] log_ptr log record buffer
+@param[in] val value to write */
+void mtr_t::log_write(const buf_block_t &block, byte *ptr, mlog_id_t l,
+ byte *log_ptr, uint32_t val)
{
- mach_write_to_8(ptr, val);
-
- if (mtr != 0) {
- byte* log_ptr = mlog_open(mtr, 11 + 2 + 9);
-
- /* If no logging is requested, we may return now */
- if (log_ptr != 0) {
-
- log_ptr = mlog_write_initial_log_record_fast(
- ptr, MLOG_8BYTES, log_ptr, mtr);
-
- mach_write_to_2(log_ptr, page_offset(ptr));
- log_ptr += 2;
-
- log_ptr += mach_u64_write_compressed(log_ptr, val);
-
- mlog_close(mtr, log_ptr);
- }
- }
+ ut_ad(l == MLOG_1BYTE || l == MLOG_2BYTES || l == MLOG_4BYTES);
+ log_ptr= mlog_log_write_low(block, ptr, l, log_ptr, *this);
+ log_ptr+= mach_write_compressed(log_ptr, val);
+ mlog_close(this, log_ptr);
}
-/********************************************************//**
-Writes a string to a file page buffered in the buffer pool. Writes the
-corresponding log record to the mini-transaction log. */
-void
-mlog_write_string(
-/*==============*/
- byte* ptr, /*!< in: pointer where to write */
- const byte* str, /*!< in: string to write */
- ulint len, /*!< in: string length */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/**
+Write a log record for writing 8 bytes.
+@param[in] block file page
+@param[in,out] ptr pointer in file page
+@param[in] l number of bytes to write
+@param[in,out] log_ptr log record buffer
+@param[in] val value to write */
+void mtr_t::log_write(const buf_block_t &block, byte *ptr, mlog_id_t l,
+ byte *log_ptr, uint64_t val)
{
- ut_ad(ptr && mtr);
- ut_a(len < srv_page_size);
-
- memcpy(ptr, str, len);
-
- mlog_log_string(ptr, len, mtr);
+ ut_ad(l == MLOG_8BYTES);
+ log_ptr= mlog_log_write_low(block, ptr, l, log_ptr, *this);
+ log_ptr+= mach_u64_write_compressed(log_ptr, val);
+ mlog_close(this, log_ptr);
}
-/********************************************************//**
-Logs a write of a string to a file page buffered in the buffer pool.
-Writes the corresponding log record to the mini-transaction log. */
-void
-mlog_log_string(
-/*============*/
- byte* ptr, /*!< in: pointer written to */
- ulint len, /*!< in: string length */
- mtr_t* mtr) /*!< in: mini-transaction handle */
+/** Log a write of a byte string to a page.
+@param[in] b buffer page
+@param[in] ofs byte offset from b->frame
+@param[in] str the data to write
+@param[in] len length of the data to write */
+void mtr_t::memcpy(const buf_block_t &b, ulint ofs, ulint len)
{
- byte* log_ptr;
-
- ut_ad(ptr && mtr);
- ut_ad(len <= srv_page_size);
-
- log_ptr = mlog_open(mtr, 30);
-
- /* If no logging is requested, we may return now */
- if (log_ptr == NULL) {
-
- return;
- }
-
- log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_WRITE_STRING,
- log_ptr, mtr);
- mach_write_to_2(log_ptr, page_offset(ptr));
- log_ptr += 2;
-
- mach_write_to_2(log_ptr, len);
- log_ptr += 2;
-
- mlog_close(mtr, log_ptr);
-
- mlog_catenate_string(mtr, ptr, len);
+ ut_ad(len);
+ ut_ad(ofs <= ulint(srv_page_size));
+ ut_ad(ofs + len <= ulint(srv_page_size));
+ ut_ad(ofs + len < PAGE_DATA || !b.page.zip.data ||
+ mach_read_from_2(b.frame + FIL_PAGE_TYPE) <= FIL_PAGE_TYPE_ZBLOB2);
+
+ set_modified();
+ if (get_log_mode() != MTR_LOG_ALL)
+ {
+ ut_ad(get_log_mode() == MTR_LOG_NONE ||
+ get_log_mode() == MTR_LOG_NO_REDO);
+ return;
+ }
+
+ byte *l= get_log()->open(11 + 2 + 2);
+ l= mlog_write_initial_log_record_low(MLOG_WRITE_STRING, b.page.id.space(),
+ b.page.id.page_no(), l, this);
+ mach_write_to_2(l, ofs);
+ mach_write_to_2(l + 2, len);
+ mlog_close(this, l + 4);
+ mlog_catenate_string(this, b.frame + ofs, len);
}
/********************************************************//**
-Parses a log record written by mlog_write_string.
+Parses a log record written by mtr_t::memcpy().
@return parsed record end, NULL if not a complete record */
const byte*
mlog_parse_string(
@@ -427,69 +380,34 @@ mlog_parse_string(
}
/** Initialize a string of bytes.
-@param[in,out] b buffer page
-@param[in] ofs byte offset from block->frame
-@param[in] len length of the data to write
-@param[in] val the data byte to write
-@param[in,out] mtr mini-transaction */
-void
-mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr)
-{
- ut_ad(len);
- ut_ad(ofs <= ulint(srv_page_size));
- ut_ad(ofs + len <= ulint(srv_page_size));
- memset(ofs + b->frame, val, len);
-
- mtr->set_modified();
- switch (mtr->get_log_mode()) {
- case MTR_LOG_NONE:
- case MTR_LOG_NO_REDO:
- return;
- case MTR_LOG_SHORT_INSERTS:
- ut_ad(0);
- /* fall through */
- case MTR_LOG_ALL:
- break;
- }
-
- byte* l = mtr->get_log()->open(11 + 2 + 2 + 1);
- l = mlog_write_initial_log_record_low(
- MLOG_MEMSET, b->page.id.space(), b->page.id.page_no(), l, mtr);
- mach_write_to_2(l, ofs);
- mach_write_to_2(l + 2, len);
- l[4] = val;
- mlog_close(mtr, l + 5);
-}
-
-/** Initialize a string of bytes.
-@param[in,out] byte byte address
-@param[in] len length of the data to write
-@param[in] val the data byte to write
-@param[in,out] mtr mini-transaction */
-void mlog_memset(byte* b, ulint len, byte val, mtr_t* mtr)
+@param[in,out] b buffer page
+@param[in] ofs byte offset from block->frame
+@param[in] len length of the data to write
+@param[in] val the data byte to write */
+void mtr_t::memset(const buf_block_t* b, ulint ofs, ulint len, byte val)
{
- ut_ad(len);
- ut_ad(page_offset(b) + len <= ulint(srv_page_size));
- memset(b, val, len);
-
- mtr->set_modified();
- switch (mtr->get_log_mode()) {
- case MTR_LOG_NONE:
- case MTR_LOG_NO_REDO:
- return;
- case MTR_LOG_SHORT_INSERTS:
- ut_ad(0);
- /* fall through */
- case MTR_LOG_ALL:
- break;
- }
-
- byte* l = mtr->get_log()->open(11 + 2 + 2 + 1);
- l = mlog_write_initial_log_record_fast(b, MLOG_MEMSET, l, mtr);
- mach_write_to_2(l, page_offset(b));
- mach_write_to_2(l + 2, len);
- l[4] = val;
- mlog_close(mtr, l + 5);
+ ut_ad(len);
+ ut_ad(ofs <= ulint(srv_page_size));
+ ut_ad(ofs + len <= ulint(srv_page_size));
+ ut_ad(ofs + len < PAGE_DATA || !b->page.zip.data ||
+ mach_read_from_2(b->frame + FIL_PAGE_TYPE) <= FIL_PAGE_TYPE_ZBLOB2);
+ ::memset(ofs + b->frame, val, len);
+
+ set_modified();
+ if (get_log_mode() != MTR_LOG_ALL)
+ {
+ ut_ad(get_log_mode() == MTR_LOG_NONE ||
+ get_log_mode() == MTR_LOG_NO_REDO);
+ return;
+ }
+
+ byte *l= get_log()->open(11 + 2 + 2 + 1);
+ l= mlog_write_initial_log_record_low(MLOG_MEMSET, b->page.id.space(),
+ b->page.id.page_no(), l, this);
+ mach_write_to_2(l, ofs);
+ mach_write_to_2(l + 2, len);
+ l[4]= val;
+ mlog_close(this, l + 5);
}
/********************************************************//**
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index d4bf270217b..2f5dd12b407 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -3627,12 +3627,8 @@ fallback:
<< srv_page_size_shift;
/* Align the buffer for possible raw i/o */
- byte* buf2;
-
- buf2 = static_cast<byte*>(ut_malloc_nokey(buf_size + srv_page_size));
-
- byte* buf = static_cast<byte*>(ut_align(buf2, srv_page_size));
-
+ byte* buf = static_cast<byte*>(aligned_malloc(buf_size,
+ srv_page_size));
/* Write buffer full of zeros */
memset(buf, 0, buf_size);
@@ -3661,7 +3657,7 @@ fallback:
current_size += n_bytes;
}
- ut_free(buf2);
+ aligned_free(buf);
return(current_size >= size && os_file_flush(file));
}
@@ -3959,13 +3955,13 @@ static bool is_linux_native_aio_supported()
memset(&io_event, 0x0, sizeof(io_event));
- byte* buf = static_cast<byte*>(ut_malloc_nokey(srv_page_size * 2));
- byte* ptr = static_cast<byte*>(ut_align(buf, srv_page_size));
+ byte* ptr = static_cast<byte*>(aligned_malloc(srv_page_size,
+ srv_page_size));
struct iocb iocb;
/* Suppress valgrind warning. */
- memset(buf, 0x00, srv_page_size * 2);
+ memset(ptr, 0, srv_page_size);
memset(&iocb, 0x0, sizeof(iocb));
struct iocb* p_iocb = &iocb;
@@ -3988,7 +3984,7 @@ static bool is_linux_native_aio_supported()
err = io_getevents(io_ctx, 1, 1, &io_event, NULL);
}
- ut_free(buf);
+ aligned_free(ptr);
my_close(fd, MYF(MY_WME));
switch (err) {
@@ -4464,17 +4460,20 @@ bool fil_node_t::read_page0(bool first)
return false;
}
- byte* buf2 = static_cast<byte*>(ut_malloc_nokey(2 * psize));
-
- /* Align the memory for file i/o if we might have O_DIRECT set */
- byte* page = static_cast<byte*>(ut_align(buf2, psize));
- IORequest request(IORequest::READ);
- if (os_file_read(request, handle, page, 0, psize) != DB_SUCCESS) {
+ page_t *page= static_cast<byte*>(aligned_malloc(psize, psize));
+ if (os_file_read(IORequestRead, handle, page, 0, psize)
+ != DB_SUCCESS) {
ib::error() << "Unable to read first page of file " << name;
- ut_free(buf2);
+corrupted:
+ aligned_free(page);
return false;
}
- const ulint space_id = fsp_header_get_space_id(page);
+
+ const ulint space_id = memcmp_aligned<4>(
+ FIL_PAGE_SPACE_ID + page,
+ FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4)
+ ? ULINT_UNDEFINED
+ : mach_read_from_4(FIL_PAGE_SPACE_ID + page);
ulint flags = fsp_header_get_flags(page);
const ulint size = fsp_header_get_field(page, FSP_SIZE);
const ulint free_limit = fsp_header_get_field(page, FSP_FREE_LIMIT);
@@ -4489,8 +4488,7 @@ invalid:
<< ib::hex(space->flags)
<< " but found " << ib::hex(flags)
<< " in the file " << name;
- ut_free(buf2);
- return false;
+ goto corrupted;
}
ulint cf = cflags & ~FSP_FLAGS_MEM_MASK;
@@ -4511,7 +4509,7 @@ invalid:
space->crypt_data = fil_space_read_crypt_data(
fil_space_t::zip_size(flags), page);
}
- ut_free(buf2);
+ aligned_free(page);
if (UNIV_UNLIKELY(space_id != space->id)) {
ib::error() << "Expected tablespace id " << space->id
diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc
index e6d32d416bb..a7d5c16464f 100644
--- a/storage/innobase/page/page0page.cc
+++ b/storage/innobase/page/page0page.cc
@@ -196,24 +196,19 @@ page_set_max_trx_id(
trx_id_t trx_id, /*!< in: transaction id */
mtr_t* mtr) /*!< in/out: mini-transaction, or NULL */
{
- page_t* page = buf_block_get_frame(block);
- ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
-
- /* It is not necessary to write this change to the redo log, as
- during a database recovery we assume that the max trx id of every
- page is the maximum trx id assigned before the crash. */
-
- if (page_zip) {
- mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
- page_zip_write_header(page_zip,
- page + (PAGE_HEADER + PAGE_MAX_TRX_ID),
- 8, mtr);
- } else if (mtr) {
- mlog_write_ull(page + (PAGE_HEADER + PAGE_MAX_TRX_ID),
- trx_id, mtr);
- } else {
- mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
- }
+ ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment");
+ byte *max_trx_id= static_cast<byte*>(MY_ASSUME_ALIGNED(PAGE_MAX_TRX_ID
+ + PAGE_HEADER
+ + block->frame, 8));
+
+ if (UNIV_LIKELY_NULL(page_zip))
+ {
+ mach_write_to_8(max_trx_id, trx_id);
+ page_zip_write_header(page_zip, max_trx_id, 8, mtr);
+ }
+ else
+ mtr->write<8>(*block, max_trx_id, trx_id);
}
/** Persist the AUTO_INCREMENT value on a clustered index root page.
@@ -227,51 +222,23 @@ page_set_max_trx_id(
void
page_set_autoinc(
buf_block_t* block,
- const dict_index_t* index MY_ATTRIBUTE((unused)),
ib_uint64_t autoinc,
mtr_t* mtr,
bool reset)
{
- ut_ad(mtr_memo_contains_flagged(
- mtr, block, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
- ut_ad(index->is_primary());
- ut_ad(index->page == block->page.id.page_no());
- ut_ad(index->table->space_id == block->page.id.space());
-
- byte* field = PAGE_HEADER + PAGE_ROOT_AUTO_INC
- + buf_block_get_frame(block);
- if (!reset && mach_read_from_8(field) >= autoinc) {
- /* nothing to update */
- } else if (page_zip_des_t* page_zip = buf_block_get_page_zip(block)) {
- mach_write_to_8(field, autoinc);
- page_zip_write_header(page_zip, field, 8, mtr);
- } else {
- mlog_write_ull(field, autoinc, mtr);
- }
-}
-
-/**********************************************************//**
-Writes a log record of page creation. */
-UNIV_INLINE
-void
-page_create_write_log(
-/*==================*/
- buf_frame_t* frame, /*!< in: a buffer frame where the page is
- created */
- mtr_t* mtr, /*!< in: mini-transaction handle */
- ibool comp, /*!< in: TRUE=compact page format */
- bool is_rtree) /*!< in: whether it is R-tree */
-{
- mlog_id_t type;
-
- if (is_rtree) {
- type = comp ? MLOG_COMP_PAGE_CREATE_RTREE
- : MLOG_PAGE_CREATE_RTREE;
- } else {
- type = comp ? MLOG_COMP_PAGE_CREATE : MLOG_PAGE_CREATE;
- }
-
- mlog_write_initial_log_record(frame, type, mtr);
+ ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX));
+
+ byte *field= PAGE_HEADER + PAGE_ROOT_AUTO_INC + block->frame;
+ if (!reset && mach_read_from_8(field) >= autoinc)
+ /* nothing to update */;
+ else if (page_zip_des_t* page_zip = buf_block_get_page_zip(block))
+ {
+ mach_write_to_8(field, autoinc);
+ page_zip_write_header(page_zip, field, 8, mtr);
+ }
+ else
+ mtr->write<8,mtr_t::OPT>(*block, field, autoinc);
}
/** The page infimum and supremum of an empty page in ROW_FORMAT=REDUNDANT */
@@ -398,7 +365,22 @@ page_create(
bool is_rtree) /*!< in: whether it is a R-Tree page */
{
ut_ad(mtr->is_named_space(block->page.id.space()));
- page_create_write_log(buf_block_get_frame(block), mtr, comp, is_rtree);
+ mtr->set_modified();
+ if (mtr->get_log_mode() != MTR_LOG_ALL) {
+ ut_ad(mtr->get_log_mode() == MTR_LOG_NONE
+ || mtr->get_log_mode() == MTR_LOG_NO_REDO);
+ } else {
+ mlog_id_t type = is_rtree
+ ? (comp
+ ? MLOG_COMP_PAGE_CREATE_RTREE
+ : MLOG_PAGE_CREATE_RTREE)
+ : (comp ? MLOG_COMP_PAGE_CREATE : MLOG_PAGE_CREATE);
+ byte *l= mtr->get_log()->open(11);
+ l = mlog_write_initial_log_record_low(
+ type, block->page.id.space(), block->page.id.page_no(),
+ l, mtr);
+ mlog_close(mtr, l);
+ }
return(page_create_low(block, comp, is_rtree));
}
@@ -492,12 +474,12 @@ page_create_empty(
page_header_get_field(page, PAGE_LEVEL),
max_trx_id, mtr);
} else {
- page_create(block, mtr, page_is_comp(page),
- dict_index_is_spatial(index));
+ page_create(block, mtr, index->table->not_redundant(),
+ index->is_spatial());
if (max_trx_id) {
- mlog_write_ull(PAGE_HEADER + PAGE_MAX_TRX_ID + page,
- max_trx_id, mtr);
+ mtr->write<8>(*block, PAGE_HEADER + PAGE_MAX_TRX_ID
+ + block->frame, max_trx_id);
}
}
}
@@ -590,12 +572,13 @@ page_copy_rec_list_end(
{
page_t* new_page = buf_block_get_frame(new_block);
page_zip_des_t* new_page_zip = buf_block_get_page_zip(new_block);
- page_t* page = page_align(rec);
+ page_t* page = block->frame;
rec_t* ret = page_rec_get_next(
page_get_infimum_rec(new_page));
ulint num_moved = 0;
rtr_rec_move_t* rec_move = NULL;
mem_heap_t* heap = NULL;
+ ut_ad(page_align(rec) == page);
#ifdef UNIV_ZIP_DEBUG
if (new_page_zip) {
@@ -819,8 +802,9 @@ page_copy_rec_list_start(
for MVCC. */
if (is_leaf && dict_index_is_sec_or_ibuf(index)
&& !index->table->is_temporary()) {
- page_update_max_trx_id(new_block, NULL,
- page_get_max_trx_id(page_align(rec)),
+ page_update_max_trx_id(new_block,
+ new_page_zip,
+ page_get_max_trx_id(block->frame),
mtr);
}
@@ -988,7 +972,6 @@ page_delete_rec_list_end(
rec_t* prev_rec;
ulint n_owned;
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
- page_t* page = page_align(rec);
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -996,8 +979,9 @@ page_delete_rec_list_end(
ut_ad(size == ULINT_UNDEFINED || size < srv_page_size);
ut_ad(!page_zip || page_rec_is_comp(rec));
+ ut_ad(page_align(rec) == block->frame);
#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page, index));
+ ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */
if (page_rec_is_supremum(rec)) {
@@ -1015,19 +999,21 @@ page_delete_rec_list_end(
only be executed when applying redo log that was
generated by an older version of MySQL. */
} else if (page_rec_is_infimum(rec)
- || n_recs == page_get_n_recs(page)) {
+ || n_recs == page_get_n_recs(block->frame)) {
delete_all:
/* We are deleting all records. */
page_create_empty(block, index, mtr);
return;
- } else if (page_is_comp(page)) {
- if (page_rec_get_next_low(page + PAGE_NEW_INFIMUM, 1) == rec) {
+ } else if (page_is_comp(block->frame)) {
+ if (page_rec_get_next_low(block->frame + PAGE_NEW_INFIMUM, 1)
+ == rec) {
/* We are deleting everything from the first
user record onwards. */
goto delete_all;
}
} else {
- if (page_rec_get_next_low(page + PAGE_OLD_INFIMUM, 0) == rec) {
+ if (page_rec_get_next_low(block->frame + PAGE_OLD_INFIMUM, 0)
+ == rec) {
/* We are deleting everything from the first
user record onwards. */
goto delete_all;
@@ -1037,23 +1023,23 @@ delete_all:
/* Reset the last insert info in the page header and increment
the modify clock for the frame */
- page_header_set_ptr(page, page_zip, PAGE_LAST_INSERT, NULL);
+ page_header_set_ptr(block->frame, page_zip, PAGE_LAST_INSERT, NULL);
/* The page gets invalid for optimistic searches: increment the
frame modify clock */
buf_block_modify_clock_inc(block);
- page_delete_rec_list_write_log(rec, index, page_is_comp(page)
+ page_delete_rec_list_write_log(rec, index, page_is_comp(block->frame)
? MLOG_COMP_LIST_END_DELETE
: MLOG_LIST_END_DELETE, mtr);
- const bool is_leaf = page_is_leaf(page);
+ const bool is_leaf = page_is_leaf(block->frame);
if (page_zip) {
mtr_log_t log_mode;
- ut_a(page_is_comp(page));
+ ut_ad(page_is_comp(block->frame));
/* Individual deletes are not logged */
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
@@ -1066,7 +1052,7 @@ delete_all:
ULINT_UNDEFINED, &heap);
rec = rec_get_next_ptr(rec, TRUE);
#ifdef UNIV_ZIP_DEBUG
- ut_a(page_zip_validate(page_zip, page, index));
+ ut_a(page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */
page_cur_delete_rec(&cur, index, offsets, mtr);
} while (page_offset(rec) != PAGE_NEW_SUPREMUM);
@@ -1083,7 +1069,7 @@ delete_all:
prev_rec = page_rec_get_prev(rec);
- last_rec = page_rec_get_prev(page_get_supremum_rec(page));
+ last_rec = page_rec_get_prev(page_get_supremum_rec(block->frame));
bool scrub = srv_immediate_scrub_data_uncompressed;
if ((size == ULINT_UNDEFINED) || (n_recs == ULINT_UNDEFINED) ||
@@ -1099,7 +1085,7 @@ delete_all:
is_leaf,
ULINT_UNDEFINED, &heap);
s = rec_offs_size(offsets);
- ut_ad(ulint(rec2 - page) + s
+ ut_ad(ulint(rec2 - block->frame) + s
- rec_offs_extra_size(offsets)
< srv_page_size);
ut_ad(size + s < srv_page_size);
@@ -1125,7 +1111,7 @@ delete_all:
of the records owned by the supremum record, as it is allowed to be
less than PAGE_DIR_SLOT_MIN_N_OWNED */
- if (page_is_comp(page)) {
+ if (page_is_comp(block->frame)) {
rec_t* rec2 = rec;
ulint count = 0;
@@ -1140,7 +1126,7 @@ delete_all:
n_owned = rec_get_n_owned_new(rec2) - count;
slot_index = page_dir_find_owner_slot(rec2);
ut_ad(slot_index > 0);
- slot = page_dir_get_nth_slot(page, slot_index);
+ slot = page_dir_get_nth_slot(block->frame, slot_index);
} else {
rec_t* rec2 = rec;
ulint count = 0;
@@ -1156,28 +1142,30 @@ delete_all:
n_owned = rec_get_n_owned_old(rec2) - count;
slot_index = page_dir_find_owner_slot(rec2);
ut_ad(slot_index > 0);
- slot = page_dir_get_nth_slot(page, slot_index);
+ slot = page_dir_get_nth_slot(block->frame, slot_index);
}
- page_dir_slot_set_rec(slot, page_get_supremum_rec(page));
+ page_dir_slot_set_rec(slot, page_get_supremum_rec(block->frame));
page_dir_slot_set_n_owned(slot, NULL, n_owned);
- page_dir_set_n_slots(page, NULL, slot_index + 1);
+ page_dir_set_n_slots(block->frame, NULL, slot_index + 1);
/* Remove the record chain segment from the record chain */
- page_rec_set_next(prev_rec, page_get_supremum_rec(page));
+ page_rec_set_next(prev_rec, page_get_supremum_rec(block->frame));
/* Catenate the deleted chain segment to the page free list */
- page_rec_set_next(last_rec, page_header_get_ptr(page, PAGE_FREE));
- page_header_set_ptr(page, NULL, PAGE_FREE, rec);
+ page_rec_set_next(last_rec, page_header_get_ptr(block->frame,
+ PAGE_FREE));
+ page_header_set_ptr(block->frame, NULL, PAGE_FREE, rec);
- page_header_set_field(page, NULL, PAGE_GARBAGE, size
- + page_header_get_field(page, PAGE_GARBAGE));
+ page_header_set_field(block->frame, NULL, PAGE_GARBAGE, size
+ + page_header_get_field(block->frame,
+ PAGE_GARBAGE));
- ut_ad(page_get_n_recs(page) > n_recs);
- page_header_set_field(page, NULL, PAGE_N_RECS,
- (ulint)(page_get_n_recs(page) - n_recs));
+ ut_ad(page_get_n_recs(block->frame) > n_recs);
+ page_header_set_field(block->frame, NULL, PAGE_N_RECS,
+ ulint{page_get_n_recs(block->frame) - n_recs});
}
/*************************************************************//**
@@ -2587,19 +2575,17 @@ page_delete_rec(
ut_ad(page_is_leaf(page));
if (!rec_offs_any_extern(offsets)
- && ((page_get_data_size(page) - rec_offs_size(offsets)
- < BTR_CUR_PAGE_COMPRESS_LIMIT(index))
- || !page_has_siblings(page)
- || (page_get_n_recs(page) < 2))) {
-
- ulint root_page_no = dict_index_get_page(index);
+ && (!page_has_siblings(page)
+ || (page_get_n_recs(page) < 2)
+ || page_get_data_size(page) - rec_offs_size(offsets)
+ < BTR_CUR_PAGE_COMPRESS_LIMIT(index))) {
/* The page fillfactor will drop below a predefined
minimum value, OR the level in the B-tree contains just
one page, OR the page will become empty: we recommend
compression if this is not the root page. */
- no_compress_needed = page_get_page_no(page) == root_page_no;
+ no_compress_needed = block->page.id.page_no() == index->page;
} else {
no_compress_needed = true;
}
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 37cf73f6831..f862cf8dce0 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -1363,7 +1363,7 @@ page_zip_compress(
<< " index "
<< index->name()
<< " page "
- << page_get_page_no(page)
+ << block->page.id.page_no()
<< "("
<< (page_is_leaf(page) ? "leaf" : "non-leaf")
<< ")";
@@ -3285,8 +3285,6 @@ page_zip_validate_low(
TRUE=ignore the MIN_REC_FLAG */
{
page_zip_des_t temp_page_zip;
- byte* temp_page_buf;
- page_t* temp_page;
ibool valid;
if (memcmp(page_zip->data + FIL_PAGE_PREV, page + FIL_PAGE_PREV,
@@ -3309,9 +3307,8 @@ page_zip_validate_low(
/* page_zip_decompress() expects the uncompressed page to be
srv_page_size aligned. */
- temp_page_buf = static_cast<byte*>(
- ut_malloc_nokey(2 << srv_page_size_shift));
- temp_page = static_cast<byte*>(ut_align(temp_page_buf, srv_page_size));
+ page_t* temp_page = static_cast<byte*>(aligned_malloc(srv_page_size,
+ srv_page_size));
UNIV_MEM_ASSERT_RW(page, srv_page_size);
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
@@ -3467,7 +3464,7 @@ func_exit:
page_zip_hexdump(page, srv_page_size);
page_zip_hexdump(temp_page, srv_page_size);
}
- ut_free(temp_page_buf);
+ aligned_free(temp_page);
return(valid);
}
@@ -4725,7 +4722,8 @@ page_zip_reorganize(
temp_page = temp_block->frame;
/* Copy the old page to temporary space */
- buf_frame_copy(temp_page, page);
+ memcpy_aligned<UNIV_PAGE_SIZE_MIN>(temp_block->frame, block->frame,
+ srv_page_size);
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index ca3de3e2af0..851be1e4096 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -252,14 +252,9 @@ row_fts_psort_info_init(
}
/* Need to align memory for O_DIRECT write */
- psort_info[j].block_alloc[i] =
- static_cast<row_merge_block_t*>(ut_malloc_nokey(
- block_size + 1024));
-
psort_info[j].merge_block[i] =
static_cast<row_merge_block_t*>(
- ut_align(
- psort_info[j].block_alloc[i], 1024));
+ aligned_malloc(block_size, 1024));
if (!psort_info[j].merge_block[i]) {
ret = FALSE;
@@ -269,23 +264,17 @@ row_fts_psort_info_init(
/* If tablespace is encrypted, allocate additional buffer for
encryption/decryption. */
if (encrypted) {
-
/* Need to align memory for O_DIRECT write */
- psort_info[j].crypt_alloc[i] =
- static_cast<row_merge_block_t*>(ut_malloc_nokey(
- block_size + 1024));
-
psort_info[j].crypt_block[i] =
static_cast<row_merge_block_t*>(
- ut_align(
- psort_info[j].crypt_alloc[i], 1024));
+ aligned_malloc(block_size,
+ 1024));
if (!psort_info[j].crypt_block[i]) {
ret = FALSE;
goto func_exit;
}
} else {
- psort_info[j].crypt_alloc[i] = NULL;
psort_info[j].crypt_block[i] = NULL;
}
}
@@ -337,12 +326,9 @@ row_fts_psort_info_destroy(
psort_info[j].merge_file[i]);
}
- ut_free(psort_info[j].block_alloc[i]);
+ aligned_free(psort_info[j].merge_block[i]);
ut_free(psort_info[j].merge_file[i]);
-
- if (psort_info[j].crypt_alloc[i]) {
- ut_free(psort_info[j].crypt_alloc[i]);
- }
+ aligned_free(psort_info[j].crypt_block[i]);
}
mutex_free(&psort_info[j].mutex);
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index 321c7d21a6c..0e352996690 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -1903,36 +1903,25 @@ clear_page_max_trx_id:
/** Validate the space flags and update tablespace header page.
@param block block read from file, not from the buffer pool.
@retval DB_SUCCESS or error code */
-inline
-dberr_t
-PageConverter::update_header(
- buf_block_t* block) UNIV_NOTHROW
+inline dberr_t PageConverter::update_header(buf_block_t* block) UNIV_NOTHROW
{
- /* Check for valid header */
- switch (fsp_header_get_space_id(get_frame(block))) {
- case 0:
- return(DB_CORRUPTION);
- case ULINT_UNDEFINED:
- ib::warn() << "Space id check in the header failed: ignored";
- }
-
- memset(get_frame(block) + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,0,8);
-
- /* Write back the adjusted flags. */
- mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
- + get_frame(block), m_space_flags);
-
- /* Write space_id to the tablespace header, page 0. */
- mach_write_to_4(
- get_frame(block) + FSP_HEADER_OFFSET + FSP_SPACE_ID,
- get_space_id());
-
- /* This is on every page in the tablespace. */
- mach_write_to_4(
- get_frame(block) + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
- get_space_id());
-
- return(DB_SUCCESS);
+ byte *frame= get_frame(block);
+ if (memcmp_aligned<4>(FIL_PAGE_SPACE_ID + frame,
+ FSP_HEADER_OFFSET + FSP_SPACE_ID + frame, 4))
+ ib::warn() << "Space id check in the header failed: ignored";
+ else if (!mach_read_from_4(FIL_PAGE_SPACE_ID + frame))
+ return DB_CORRUPTION;
+
+ memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);
+
+ /* Write space_id to the tablespace header, page 0. */
+ mach_write_to_4(FIL_PAGE_SPACE_ID + frame, get_space_id());
+ memcpy_aligned<4>(FSP_HEADER_OFFSET + FSP_SPACE_ID + frame,
+ FIL_PAGE_SPACE_ID + frame, 4);
+ /* Write back the adjusted flags. */
+ mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + frame, m_space_flags);
+
+ return DB_SUCCESS;
}
/** Update the page, set the space id, max trx id and index id.
@@ -3667,11 +3656,10 @@ fil_tablespace_iterate(
/* Allocate a page to read in the tablespace header, so that we
can determine the page size and zip_size (if it is compressed).
- We allocate an extra page in case it is a compressed table. One
- page is to ensure alignement. */
+ We allocate an extra page in case it is a compressed table. */
- void* page_ptr = ut_malloc_nokey(3U << srv_page_size_shift);
- byte* page = static_cast<byte*>(ut_align(page_ptr, srv_page_size));
+ byte* page = static_cast<byte*>(aligned_malloc(2 * srv_page_size,
+ srv_page_size));
buf_block_t* block = reinterpret_cast<buf_block_t*>
(ut_zalloc_nokey(sizeof *block));
@@ -3723,20 +3711,16 @@ fil_tablespace_iterate(
iter.n_io_buffers = n_io_buffers;
/* Add an extra page for compressed page scratch area. */
- void* io_buffer = ut_malloc_nokey(
- (2 + iter.n_io_buffers) << srv_page_size_shift);
-
iter.io_buffer = static_cast<byte*>(
- ut_align(io_buffer, srv_page_size));
+ aligned_malloc((1 + iter.n_io_buffers)
+ << srv_page_size_shift, srv_page_size));
- void* crypt_io_buffer = NULL;
- if (iter.crypt_data) {
- crypt_io_buffer = ut_malloc_nokey(
- (2 + iter.n_io_buffers)
- << srv_page_size_shift);
- iter.crypt_io_buffer = static_cast<byte*>(
- ut_align(crypt_io_buffer, srv_page_size));
- }
+ iter.crypt_io_buffer = iter.crypt_data
+ ? static_cast<byte*>(
+ aligned_malloc((1 + iter.n_io_buffers)
+ << srv_page_size_shift,
+ srv_page_size))
+ : NULL;
if (block->page.zip.ssize) {
ut_ad(iter.n_io_buffers == 1);
@@ -3750,8 +3734,8 @@ fil_tablespace_iterate(
fil_space_destroy_crypt_data(&iter.crypt_data);
}
- ut_free(crypt_io_buffer);
- ut_free(io_buffer);
+ aligned_free(iter.crypt_io_buffer);
+ aligned_free(iter.io_buffer);
}
if (err == DB_SUCCESS) {
@@ -3767,7 +3751,7 @@ fil_tablespace_iterate(
os_file_close(file);
- ut_free(page_ptr);
+ aligned_free(page);
ut_free(filepath);
ut_free(block);
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index 197ff55964b..f9f45dc7e1e 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -488,26 +488,21 @@ row_purge_remove_sec_if_poss_leaf(
goto func_exit_no_pcur;
}
- if (dict_index_is_spatial(index)) {
- const page_t* page;
- const trx_t* trx = NULL;
-
- if (btr_cur->rtr_info != NULL
- && btr_cur->rtr_info->thr != NULL) {
- trx = thr_get_trx(
- btr_cur->rtr_info->thr);
- }
-
- page = btr_cur_get_page(btr_cur);
-
- if (!lock_test_prdt_page_lock(
- trx,
- page_get_space_id(page),
- page_get_page_no(page))
- && page_get_n_recs(page) < 2
- && btr_cur_get_block(btr_cur)
- ->page.id.page_no() !=
- dict_index_get_page(index)) {
+ if (index->is_spatial()) {
+ const buf_block_t* block = btr_cur_get_block(
+ btr_cur);
+
+ if (block->page.id.page_no()
+ != index->page
+ && page_get_n_recs(block->frame) < 2
+ && !lock_test_prdt_page_lock(
+ btr_cur->rtr_info
+ && btr_cur->rtr_info->thr
+ ? thr_get_trx(
+ btr_cur->rtr_info->thr)
+ : NULL,
+ block->page.id.space(),
+ block->page.id.page_no())) {
/* this is the last record on page,
and it has a "page" lock on it,
which mean search is still depending
@@ -515,8 +510,7 @@ row_purge_remove_sec_if_poss_leaf(
DBUG_LOG("purge",
"skip purging last"
" record on page "
- << btr_cur_get_block(btr_cur)
- ->page.id);
+ << block->page.id);
btr_pcur_close(&pcur);
mtr.commit();
@@ -711,8 +705,15 @@ static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr)
byte* ptr = rec_get_nth_field(
rec, offsets, trx_id_pos, &len);
ut_ad(len == DATA_TRX_ID_LEN);
- mlog_write_string(ptr, reset_trx_id,
- sizeof reset_trx_id, mtr);
+ buf_block_t* block = btr_pcur_get_block(
+ &node->pcur);
+ uint16_t offs = page_offset(ptr);
+ mtr->memset(block, offs, DATA_TRX_ID_LEN, 0);
+ offs += DATA_TRX_ID_LEN;
+ mtr->write<1,mtr_t::OPT>(*block, block->frame
+ + offs, 0x80U);
+ mtr->memset(block, offs + 1,
+ DATA_ROLL_PTR_LEN - 1, 0);
}
}
}
@@ -784,12 +785,11 @@ skip_secondaries:
if (dfield_is_ext(&ufield->new_val)) {
trx_rseg_t* rseg;
buf_block_t* block;
- ulint internal_offset;
byte* data_field;
- ibool is_insert;
+ bool is_insert;
ulint rseg_id;
- ulint page_no;
- ulint offset;
+ uint32_t page_no;
+ uint16_t offset;
/* We use the fact that new_val points to
undo_rec and get thus the offset of
@@ -797,7 +797,7 @@ skip_secondaries:
can calculate from node->roll_ptr the file
address of the new_val data */
- internal_offset = ulint(
+ const uint16_t internal_offset = uint16_t(
static_cast<const byte*>
(dfield_get_data(&ufield->new_val))
- undo_rec);
@@ -849,7 +849,7 @@ skip_secondaries:
index,
data_field + dfield_get_len(&ufield->new_val)
- BTR_EXTERN_FIELD_REF_SIZE,
- NULL, NULL, NULL, 0, false, &mtr);
+ NULL, NULL, block, 0, false, &mtr);
mtr.commit();
}
}
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 47a77a74908..de810a428d2 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -4762,14 +4762,13 @@ wrong_offs:
ib::error() << "Rec address "
<< static_cast<const void*>(rec)
<< ", buf block fix count "
- << btr_cur_get_block(
- btr_pcur_get_btr_cur(pcur))->page
+ << btr_pcur_get_block(pcur)->page
.buf_fix_count;
ib::error() << "Index corruption: rec offs "
<< page_offset(rec) << " next offs "
<< next_offs << ", page no "
- << page_get_page_no(page_align(rec))
+ << btr_pcur_get_block(pcur)->page.id.page_no()
<< ", index " << index->name
<< " of table " << index->table->name
<< ". Run CHECK TABLE. You may need to"
@@ -4786,7 +4785,7 @@ wrong_offs:
ib::info() << "Index corruption: rec offs "
<< page_offset(rec) << " next offs "
<< next_offs << ", page no "
- << page_get_page_no(page_align(rec))
+ << btr_pcur_get_block(pcur)->page.id.page_no()
<< ", index " << index->name
<< " of table " << index->table->name
<< ". We try to skip the rest of the page.";
@@ -4814,7 +4813,7 @@ wrong_offs:
ib::error() << "Index corruption: rec offs "
<< page_offset(rec) << " next offs "
<< next_offs << ", page no "
- << page_get_page_no(page_align(rec))
+ << btr_pcur_get_block(pcur)->page.id.page_no()
<< ", index " << index->name
<< " of table " << index->table->name
<< ". We try to skip the record.";
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index 341146c0a36..b1c80d98399 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -130,8 +130,7 @@ row_undo_ins_remove_clust_rec(
== RW_X_LATCH);
ut_ad(node->rec_type == TRX_UNDO_INSERT_REC);
- dict_drop_index_tree(rec, &node->pcur, node->trx,
- &mtr);
+ dict_drop_index_tree(&node->pcur, node->trx, &mtr);
mtr.commit();
mtr.start();
@@ -208,25 +207,29 @@ func_exit:
/* When rolling back the very first instant ADD COLUMN
operation, reset the root page to the basic state. */
ut_ad(!index->table->is_temporary());
- if (page_t* root = btr_root_get(index, &mtr)) {
- byte* page_type = root + FIL_PAGE_TYPE;
+ if (buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH,
+ &mtr)) {
+ byte* page_type = root->frame + FIL_PAGE_TYPE;
ut_ad(mach_read_from_2(page_type)
== FIL_PAGE_TYPE_INSTANT
|| mach_read_from_2(page_type)
== FIL_PAGE_INDEX);
- mlog_write_ulint(page_type, FIL_PAGE_INDEX,
- MLOG_2BYTES, &mtr);
- byte* instant = PAGE_INSTANT + PAGE_HEADER + root;
- mlog_write_ulint(instant,
- page_ptr_get_direction(instant + 1),
- MLOG_2BYTES, &mtr);
- rec_t* infimum = page_get_infimum_rec(root);
- rec_t* supremum = page_get_supremum_rec(root);
+ mtr.write<2,mtr_t::OPT>(*root, page_type,
+ FIL_PAGE_INDEX);
+ byte* instant = PAGE_INSTANT + PAGE_HEADER
+ + root->frame;
+ mtr.write<2,mtr_t::OPT>(
+ *root, instant,
+ page_ptr_get_direction(instant + 1));
+ rec_t* infimum = page_get_infimum_rec(root->frame);
+ rec_t* supremum = page_get_supremum_rec(root->frame);
static const byte str[8 + 8] = "supremuminfimum";
if (memcmp(infimum, str + 8, 8)
|| memcmp(supremum, str, 8)) {
- mlog_write_string(infimum, str + 8, 8, &mtr);
- mlog_write_string(supremum, str, 8, &mtr);
+ mtr.memcpy(root, page_offset(infimum),
+ str + 8, 8);
+ mtr.memcpy(root, page_offset(supremum),
+ str, 8);
}
}
}
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index 4775dc12348..0ecfa412938 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -156,26 +156,27 @@ row_undo_mod_clust_low(
&& node->ref == &trx_undo_metadata
&& btr_cur_get_index(btr_cur)->table->instant
&& node->update->info_bits == REC_INFO_METADATA_ADD) {
- if (page_t* root = btr_root_get(
- btr_cur_get_index(btr_cur), mtr)) {
- byte* infimum;
- byte *supremum;
- if (page_is_comp(root)) {
- infimum = PAGE_NEW_INFIMUM + root;
- supremum = PAGE_NEW_SUPREMUM + root;
+ if (buf_block_t* root = btr_root_block_get(
+ btr_cur_get_index(btr_cur), RW_SX_LATCH,
+ mtr)) {
+ uint16_t infimum, supremum;
+ if (page_is_comp(root->frame)) {
+ infimum = PAGE_NEW_INFIMUM;
+ supremum = PAGE_NEW_SUPREMUM;
} else {
- infimum = PAGE_OLD_INFIMUM + root;
- supremum = PAGE_OLD_SUPREMUM + root;
+ infimum = PAGE_OLD_INFIMUM;
+ supremum = PAGE_OLD_SUPREMUM;
}
- ut_ad(!memcmp(infimum, INFIMUM, 8)
- == !memcmp(supremum, SUPREMUM, 8));
+ ut_ad(!memcmp(root->frame + infimum,
+ INFIMUM, 8)
+ == !memcmp(root->frame + supremum,
+ SUPREMUM, 8));
- if (memcmp(infimum, INFIMUM, 8)) {
- mlog_write_string(infimum, INFIMUM,
- 8, mtr);
- mlog_write_string(supremum, SUPREMUM,
- 8, mtr);
+ if (memcmp(root->frame + infimum, INFIMUM, 8)) {
+ mtr->memcpy(root, infimum, INFIMUM, 8);
+ mtr->memcpy(root, supremum, SUPREMUM,
+ 8);
}
}
}
@@ -457,7 +458,7 @@ row_undo_mod_clust(
if (trx_id_offset) {
} else if (rec_is_metadata(rec, *index)) {
ut_ad(!buf_block_get_page_zip(btr_pcur_get_block(
- &node->pcur)));
+ pcur)));
for (unsigned i = index->first_user_field(); i--; ) {
trx_id_offset += index->fields[i].fixed_len;
}
@@ -479,15 +480,21 @@ row_undo_mod_clust(
|| rec_is_alter_metadata(rec, *index));
index->set_modified(mtr);
if (page_zip_des_t* page_zip = buf_block_get_page_zip(
- btr_pcur_get_block(&node->pcur))) {
+ btr_pcur_get_block(pcur))) {
page_zip_write_trx_id_and_roll_ptr(
page_zip, rec, offsets, trx_id_pos,
0, 1ULL << ROLL_PTR_INSERT_FLAG_POS,
&mtr);
} else {
- mlog_write_string(rec + trx_id_offset,
- reset_trx_id,
- sizeof reset_trx_id, &mtr);
+ buf_block_t* block = btr_pcur_get_block(pcur);
+ uint16_t offs = page_offset(rec
+ + trx_id_offset);
+ mtr.memset(block, offs, DATA_TRX_ID_LEN, 0);
+ offs += DATA_TRX_ID_LEN;
+ mtr.write<1,mtr_t::OPT>(*block, block->frame
+ + offs, 0x80U);
+ mtr.memset(block, offs + 1,
+ DATA_ROLL_PTR_LEN - 1, 0);
}
}
} else {
diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc
index 18364f16ec5..1580a8e92cd 100644
--- a/storage/innobase/row/row0undo.cc
+++ b/storage/innobase/row/row0undo.cc
@@ -335,37 +335,30 @@ static bool row_undo_rec_get(undo_node_t* node)
mtr_t mtr;
mtr.start();
- page_t* undo_page = trx_undo_page_get_s_latched(
+ buf_block_t* undo_page = trx_undo_page_get_s_latched(
page_id_t(undo->rseg->space->id, undo->top_page_no), &mtr);
- ulint offset = undo->top_offset;
-
- trx_undo_rec_t* prev_rec = trx_undo_get_prev_rec(
- undo_page + offset, undo->hdr_page_no, undo->hdr_offset,
- true, &mtr);
-
- if (prev_rec == NULL) {
- undo->top_undo_no = IB_ID_MAX;
- ut_ad(undo->empty());
- } else {
- page_t* prev_rec_page = page_align(prev_rec);
-
- if (prev_rec_page != undo_page) {
+ uint16_t offset = undo->top_offset;
+ buf_block_t* prev_page = undo_page;
+ if (trx_undo_rec_t* prev_rec = trx_undo_get_prev_rec(
+ prev_page, offset, undo->hdr_page_no, undo->hdr_offset,
+ true, &mtr)) {
+ if (prev_page != undo_page) {
trx->pages_undone++;
}
- undo->top_page_no = page_get_page_no(prev_rec_page);
- undo->top_offset = ulint(prev_rec - prev_rec_page);
+ undo->top_page_no = prev_page->page.id.page_no();
+ undo->top_offset = page_offset(prev_rec);
undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec);
ut_ad(!undo->empty());
+ } else {
+ undo->top_undo_no = IB_ID_MAX;
+ ut_ad(undo->empty());
}
- {
- const trx_undo_rec_t* undo_rec = undo_page + offset;
- node->undo_rec = trx_undo_rec_copy(undo_rec, node->heap);
- }
-
+ node->undo_rec = trx_undo_rec_copy(undo_page->frame + offset,
+ node->heap);
mtr.commit();
switch (trx_undo_rec_get_type(node->undo_rec)) {
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index 5c71bfe4029..8535f2430fc 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -2755,7 +2755,7 @@ err_exit:
insert fails, then this disown will be undone
when the operation is rolled back. */
btr_cur_disown_inherited_fields(
- btr_cur_get_page_zip(btr_cur),
+ btr_cur_get_block(btr_cur),
rec, index, offsets, node->update,
mtr);
}
@@ -3124,8 +3124,7 @@ row_upd_clust_step(
ut_ad(!dict_index_is_online_ddl(index));
- dict_drop_index_tree(
- btr_pcur_get_rec(pcur), pcur, trx, &mtr);
+ dict_drop_index_tree(pcur, trx, &mtr);
mtr.commit();
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index c7823d2e2d8..5d5023d83af 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -125,10 +125,6 @@ my_bool srv_undo_log_truncate;
/** Maximum size of undo tablespace. */
unsigned long long srv_max_undo_log_size;
-/** Default undo tablespace size in UNIV_PAGEs count (10MB). */
-const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES =
- ((1024 * 1024) * 10) / UNIV_PAGE_SIZE_DEF;
-
/** Set if InnoDB must operate in read-only mode. We don't do any
recovery and open all tables in RO mode instead of RW mode. We don't
sync the max trx id to disk either. */
@@ -2033,7 +2029,6 @@ static bool srv_task_execute()
}
-
/** Do the actual purge operation.
@param[in,out] n_total_purged total number of purged pages
@return length of history list before the last purge batch. */
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 4c80425e6dd..3ea2f967b68 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -488,15 +488,10 @@ create_log_files_rename(
return(err);
}
-/*********************************************************************//**
-Create undo tablespace.
+/** Create an undo tablespace file
+@param[in] name file name
@return DB_SUCCESS or error code */
-static
-dberr_t
-srv_undo_tablespace_create(
-/*=======================*/
- const char* name, /*!< in: tablespace name */
- ulint size) /*!< in: tablespace size in pages */
+static dberr_t srv_undo_tablespace_create(const char* name)
{
pfs_os_file_t fh;
bool ret;
@@ -532,18 +527,15 @@ srv_undo_tablespace_create(
" be created";
ib::info() << "Setting file " << name << " size to "
- << (size >> (20 - srv_page_size_shift)) << " MB";
+ << (SRV_UNDO_TABLESPACE_SIZE_IN_PAGES >> (20 - srv_page_size_shift)) << " MB";
ib::info() << "Database physically writes the file full: "
<< "wait...";
- ret = os_file_set_size(
- name, fh, os_offset_t(size) << srv_page_size_shift);
-
- if (!ret) {
- ib::info() << "Error in creating " << name
- << ": probably out of disk space";
-
+ if (!os_file_set_size(name, fh, os_offset_t
+ {SRV_UNDO_TABLESPACE_SIZE_IN_PAGES}
+ << srv_page_size_shift)) {
+ ib::error() << "Unable to allocate " << name;
err = DB_ERROR;
}
@@ -553,77 +545,163 @@ srv_undo_tablespace_create(
return(err);
}
-/** Open an undo tablespace.
-@param[in] name tablespace file name
-@param[in] space_id tablespace ID
-@param[in] create_new_db whether undo tablespaces are being created
-@return whether the tablespace was opened */
-static bool srv_undo_tablespace_open(const char* name, ulint space_id,
- bool create_new_db)
+/* Validate the number of undo opened undo tablespace and user given
+undo tablespace
+@return DB_SUCCESS if it is valid */
+static dberr_t srv_validate_undo_tablespaces()
{
- pfs_os_file_t fh;
- bool success;
- char undo_name[sizeof "innodb_undo000"];
-
- snprintf(undo_name, sizeof(undo_name),
- "innodb_undo%03u", static_cast<unsigned>(space_id));
-
- fh = os_file_create(
- innodb_data_file_key, name, OS_FILE_OPEN
- | OS_FILE_ON_ERROR_NO_EXIT | OS_FILE_ON_ERROR_SILENT,
- OS_FILE_AIO, OS_DATA_FILE, srv_read_only_mode, &success);
- if (!success) {
- return false;
- }
-
- os_offset_t size = os_file_get_size(fh);
- ut_a(size != os_offset_t(-1));
-
- /* Load the tablespace into InnoDB's internal data structures. */
-
- /* We set the biggest space id to the undo tablespace
- because InnoDB hasn't opened any other tablespace apart
- from the system tablespace. */
-
- fil_set_max_space_id_if_bigger(space_id);
-
- ulint fsp_flags;
- switch (srv_checksum_algorithm) {
- case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
- case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
- fsp_flags = (FSP_FLAGS_FCRC32_MASK_MARKER
- | FSP_FLAGS_FCRC32_PAGE_SSIZE());
- break;
- default:
- fsp_flags = FSP_FLAGS_PAGE_SSIZE();
- }
-
- fil_space_t* space = fil_space_create(undo_name, space_id, fsp_flags,
- FIL_TYPE_TABLESPACE, NULL);
-
- ut_a(fil_validate());
- ut_a(space);
-
- fil_node_t* file = space->add(name, fh, 0, false, true);
-
- mutex_enter(&fil_system.mutex);
-
- if (create_new_db) {
- space->size = file->size = ulint(size >> srv_page_size_shift);
- space->size_in_header = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
- } else {
- success = file->read_page0(true);
- if (!success) {
- os_file_close(file->handle);
- file->handle = OS_FILE_CLOSED;
- ut_a(fil_system.n_open > 0);
- fil_system.n_open--;
- }
- }
+ /* If the user says that there are fewer than what we find we
+ tolerate that discrepancy but not the inverse. Because there could
+ be unused undo tablespaces for future use. */
+
+ if (srv_undo_tablespaces > srv_undo_tablespaces_open)
+ {
+ ib::error() << "Expected to open innodb_undo_tablespaces="
+ << srv_undo_tablespaces
+ << " but was able to find only "
+ << srv_undo_tablespaces_open;
+
+ return DB_ERROR;
+ }
+ else if (srv_undo_tablespaces_open > 0)
+ {
+ ib::info() << "Opened " << srv_undo_tablespaces_open
+ << " undo tablespaces";
+
+ if (srv_undo_tablespaces == 0)
+ ib::warn() << "innodb_undo_tablespaces=0 disables"
+ " dedicated undo log tablespaces";
+ }
+ return DB_SUCCESS;
+}
- mutex_exit(&fil_system.mutex);
+/** @return the number of active undo tablespaces (except system tablespace) */
+static ulint trx_rseg_get_n_undo_tablespaces()
+{
+ std::set<uint32_t> space_ids;
+ mtr_t mtr;
+ mtr.start();
+
+ if (const buf_block_t *sys_header= trx_sysf_get(&mtr, false))
+ for (ulint rseg_id= 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++)
+ if (trx_sysf_rseg_get_page_no(sys_header, rseg_id) != FIL_NULL)
+ if (uint32_t space= trx_sysf_rseg_get_space(sys_header, rseg_id))
+ space_ids.insert(space);
+ mtr.commit();
+ return space_ids.size();
+}
- return success;
+/** Open an undo tablespace.
+@param[in] create whether undo tablespaces are being created
+@param[in] name tablespace file name
+@param[in] i undo tablespace count
+@return undo tablespace identifier
+@retval 0 on failure */
+static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i)
+{
+ bool success;
+ char undo_name[sizeof "innodb_undo000"];
+ ulint space_id= 0;
+ ulint fsp_flags= 0;
+
+ if (create)
+ {
+ space_id= srv_undo_space_id_start + i;
+ snprintf(undo_name, sizeof(undo_name),
+ "innodb_undo%03u", static_cast<unsigned>(space_id));
+ switch (srv_checksum_algorithm) {
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
+ fsp_flags= FSP_FLAGS_FCRC32_MASK_MARKER | FSP_FLAGS_FCRC32_PAGE_SSIZE();
+ break;
+ default:
+ fsp_flags= FSP_FLAGS_PAGE_SSIZE();
+ }
+ }
+
+ pfs_os_file_t fh= os_file_create(innodb_data_file_key, name, OS_FILE_OPEN |
+ OS_FILE_ON_ERROR_NO_EXIT |
+ OS_FILE_ON_ERROR_SILENT,
+ OS_FILE_AIO, OS_DATA_FILE,
+ srv_read_only_mode, &success);
+
+ if (!success)
+ return 0;
+
+ os_offset_t size= os_file_get_size(fh);
+ ut_a(size != os_offset_t(-1));
+
+ if (!create)
+ {
+ page_t *page= static_cast<byte*>(aligned_malloc(srv_page_size,
+ srv_page_size));
+ dberr_t err= os_file_read(IORequestRead, fh, page, 0, srv_page_size);
+ if (err != DB_SUCCESS)
+ {
+err_exit:
+ ib::error() << "Unable to read first page of file " << name;
+ aligned_free(page);
+ return err;
+ }
+
+ uint32_t id= mach_read_from_4(FIL_PAGE_SPACE_ID + page);
+ if (id == 0 || id >= SRV_LOG_SPACE_FIRST_ID ||
+ memcmp_aligned<4>(FIL_PAGE_SPACE_ID + page,
+ FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4))
+ {
+ ib::error() << "Inconsistent tablespace ID in file " << name;
+ err= DB_CORRUPTION;
+ goto err_exit;
+ }
+
+ fsp_flags= mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
+ if (buf_page_is_corrupted(false, page, fsp_flags))
+ {
+ ib::error() << "Checksum mismatch in the first page of file " << name;
+ err= DB_CORRUPTION;
+ goto err_exit;
+ }
+
+ space_id= id;
+ snprintf(undo_name, sizeof undo_name, "innodb_undo%03u", id);
+ aligned_free(page);
+ }
+
+ /* Load the tablespace into InnoDB's internal data structures. */
+
+ /* We set the biggest space id to the undo tablespace
+ because InnoDB hasn't opened any other tablespace apart
+ from the system tablespace. */
+
+ fil_set_max_space_id_if_bigger(space_id);
+
+ fil_space_t *space= fil_space_create(undo_name, space_id, fsp_flags,
+ FIL_TYPE_TABLESPACE, NULL);
+ ut_a(fil_validate());
+ ut_a(space);
+
+ fil_node_t *file= space->add(name, fh, 0, false, true);
+ mutex_enter(&fil_system.mutex);
+
+ if (create)
+ {
+ space->size= file->size= ulint(size >> srv_page_size_shift);
+ space->size_in_header= SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
+ }
+ else
+ {
+ success= file->read_page0(true);
+ if (!success)
+ {
+ os_file_close(file->handle);
+ file->handle= OS_FILE_CLOSED;
+ ut_a(fil_system.n_open > 0);
+ fil_system.n_open--;
+ }
+ }
+
+ mutex_exit(&fil_system.mutex);
+ return space_id;
}
/** Check if undo tablespaces and redo log files exist before creating a
@@ -702,194 +780,125 @@ srv_check_undo_redo_logs_exists()
return(DB_SUCCESS);
}
+static dberr_t srv_all_undo_tablespaces_open(bool create_new_db, ulint n_undo)
+{
+ /* Open all the undo tablespaces that are currently in use. If we
+ fail to open any of these it is a fatal error. The tablespace ids
+ should be contiguous. It is a fatal error because they are required
+ for recovery and are referenced by the UNDO logs (a.k.a RBS). */
+
+ ulint prev_id= create_new_db ? srv_undo_space_id_start - 1 : 0;
+
+ for (ulint i= 0; i < n_undo; ++i)
+ {
+ char name[OS_FILE_MAX_PATH];
+ snprintf(name, sizeof name, "%s%cundo%03zu", srv_undo_dir,
+ OS_PATH_SEPARATOR, i + 1);
+ ulint space_id= srv_undo_tablespace_open(create_new_db, name, i);
+ if (!space_id)
+ {
+ if (!create_new_db)
+ break;
+ ib::error() << "Unable to open create tablespace '" << name << "'.";
+ return DB_ERROR;
+ }
+
+ /* Should be no gaps in undo tablespace ids. */
+ ut_a(!i || prev_id + 1 == space_id);
+
+ prev_id= space_id;
+
+ /* Note the first undo tablespace id in case of
+ no active undo tablespace. */
+ if (0 == srv_undo_tablespaces_open++)
+ srv_undo_space_id_start= space_id;
+ }
+
+ /* Open any extra unused undo tablespaces. These must be contiguous.
+ We stop at the first failure. These are undo tablespaces that are
+ not in use and therefore not required by recovery. We only check
+ that there are no gaps. */
+
+ for (ulint i= prev_id + 1; i < srv_undo_space_id_start + TRX_SYS_N_RSEGS;
+ ++i)
+ {
+ char name[OS_FILE_MAX_PATH];
+ snprintf(name, sizeof(name),
+ "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i);
+ if (!srv_undo_tablespace_open(create_new_db, name, i))
+ break;
+ ++srv_undo_tablespaces_open;
+ }
+
+ return srv_validate_undo_tablespaces();
+}
+
/** Open the configured number of dedicated undo tablespaces.
@param[in] create_new_db whether the database is being initialized
@return DB_SUCCESS or error code */
dberr_t
srv_undo_tablespaces_init(bool create_new_db)
{
- ulint i;
- dberr_t err = DB_SUCCESS;
- ulint prev_space_id = 0;
- ulint n_undo_tablespaces;
- ulint undo_tablespace_ids[TRX_SYS_N_RSEGS + 1];
-
- srv_undo_tablespaces_open = 0;
-
- ut_a(srv_undo_tablespaces <= TRX_SYS_N_RSEGS);
- ut_a(!create_new_db || srv_operation == SRV_OPERATION_NORMAL);
-
- if (srv_undo_tablespaces == 1) { /* 1 is not allowed, make it 0 */
- srv_undo_tablespaces = 0;
- }
-
- memset(undo_tablespace_ids, 0x0, sizeof(undo_tablespace_ids));
-
- /* Create the undo spaces only if we are creating a new
- instance. We don't allow creating of new undo tablespaces
- in an existing instance (yet). This restriction exists because
- we check in several places for SYSTEM tablespaces to be less than
- the min of user defined tablespace ids. Once we implement saving
- the location of the undo tablespaces and their space ids this
- restriction will/should be lifted. */
-
- for (i = 0; create_new_db && i < srv_undo_tablespaces; ++i) {
- char name[OS_FILE_MAX_PATH];
- ulint space_id = i + 1;
-
- DBUG_EXECUTE_IF("innodb_undo_upgrade",
- space_id = i + 3;);
-
- snprintf(
- name, sizeof(name),
- "%s%cundo%03zu",
- srv_undo_dir, OS_PATH_SEPARATOR, space_id);
-
- if (i == 0) {
- srv_undo_space_id_start = space_id;
- prev_space_id = srv_undo_space_id_start - 1;
- }
-
- undo_tablespace_ids[i] = space_id;
-
- err = srv_undo_tablespace_create(
- name, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES);
-
- if (err != DB_SUCCESS) {
- ib::error() << "Could not create undo tablespace '"
- << name << "'.";
- return(err);
- }
- }
-
- /* Get the tablespace ids of all the undo segments excluding
- the system tablespace (0). If we are creating a new instance then
- we build the undo_tablespace_ids ourselves since they don't
- already exist. */
- n_undo_tablespaces = create_new_db
- || srv_operation == SRV_OPERATION_BACKUP
- || srv_operation == SRV_OPERATION_RESTORE_DELTA
- ? srv_undo_tablespaces
- : trx_rseg_get_n_undo_tablespaces(undo_tablespace_ids);
- srv_undo_tablespaces_active = srv_undo_tablespaces;
-
- switch (srv_operation) {
- case SRV_OPERATION_RESTORE_DELTA:
- case SRV_OPERATION_BACKUP:
- for (i = 0; i < n_undo_tablespaces; i++) {
- undo_tablespace_ids[i] = i + srv_undo_space_id_start;
- }
-
- prev_space_id = srv_undo_space_id_start - 1;
- break;
- case SRV_OPERATION_NORMAL:
- case SRV_OPERATION_RESTORE:
- case SRV_OPERATION_RESTORE_EXPORT:
- break;
- }
-
- /* Open all the undo tablespaces that are currently in use. If we
- fail to open any of these it is a fatal error. The tablespace ids
- should be contiguous. It is a fatal error because they are required
- for recovery and are referenced by the UNDO logs (a.k.a RBS). */
-
- for (i = 0; i < n_undo_tablespaces; ++i) {
- char name[OS_FILE_MAX_PATH];
-
- snprintf(
- name, sizeof(name),
- "%s%cundo%03zu",
- srv_undo_dir, OS_PATH_SEPARATOR,
- undo_tablespace_ids[i]);
-
- /* Should be no gaps in undo tablespace ids. */
- ut_a(!i || prev_space_id + 1 == undo_tablespace_ids[i]);
-
- /* The system space id should not be in this array. */
- ut_a(undo_tablespace_ids[i] != 0);
- ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED);
-
- if (!srv_undo_tablespace_open(name, undo_tablespace_ids[i],
- create_new_db)) {
- ib::error() << "Unable to open undo tablespace '"
- << name << "'.";
- return DB_ERROR;
- }
-
- prev_space_id = undo_tablespace_ids[i];
-
- /* Note the first undo tablespace id in case of
- no active undo tablespace. */
- if (0 == srv_undo_tablespaces_open++) {
- srv_undo_space_id_start = undo_tablespace_ids[i];
- }
- }
-
- /* Open any extra unused undo tablespaces. These must be contiguous.
- We stop at the first failure. These are undo tablespaces that are
- not in use and therefore not required by recovery. We only check
- that there are no gaps. */
-
- for (i = prev_space_id + 1;
- i < srv_undo_space_id_start + TRX_SYS_N_RSEGS; ++i) {
- char name[OS_FILE_MAX_PATH];
-
- snprintf(
- name, sizeof(name),
- "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i);
-
- if (!srv_undo_tablespace_open(name, i, create_new_db)) {
- err = DB_ERROR;
- break;
- }
-
- ++n_undo_tablespaces;
-
- ++srv_undo_tablespaces_open;
- }
-
- /* Initialize srv_undo_space_id_start=0 when there are no
- dedicated undo tablespaces. */
- if (n_undo_tablespaces == 0) {
- srv_undo_space_id_start = 0;
- }
-
- /* If the user says that there are fewer than what we find we
- tolerate that discrepancy but not the inverse. Because there could
- be unused undo tablespaces for future use. */
-
- if (srv_undo_tablespaces > n_undo_tablespaces) {
- ib::error() << "Expected to open innodb_undo_tablespaces="
- << srv_undo_tablespaces
- << " but was able to find only "
- << n_undo_tablespaces;
-
- return(err != DB_SUCCESS ? err : DB_ERROR);
-
- } else if (n_undo_tablespaces > 0) {
-
- ib::info() << "Opened " << n_undo_tablespaces
- << " undo tablespaces";
-
- if (srv_undo_tablespaces == 0) {
- ib::warn() << "innodb_undo_tablespaces=0 disables"
- " dedicated undo log tablespaces";
- }
- }
-
- if (create_new_db) {
- mtr_t mtr;
-
- for (i = 0; i < n_undo_tablespaces; ++i) {
- mtr.start();
- fsp_header_init(fil_space_get(undo_tablespace_ids[i]),
- SRV_UNDO_TABLESPACE_SIZE_IN_PAGES,
- &mtr);
- mtr.commit();
- }
- }
-
- return(DB_SUCCESS);
+ srv_undo_tablespaces_open= 0;
+
+ ut_a(srv_undo_tablespaces <= TRX_SYS_N_RSEGS);
+ ut_a(!create_new_db || srv_operation == SRV_OPERATION_NORMAL);
+
+ if (srv_undo_tablespaces == 1)
+ srv_undo_tablespaces= 0;
+
+ /* Create the undo spaces only if we are creating a new
+ instance. We don't allow creating of new undo tablespaces
+ in an existing instance (yet). */
+ if (create_new_db)
+ {
+ srv_undo_space_id_start= 1;
+ DBUG_EXECUTE_IF("innodb_undo_upgrade", srv_undo_space_id_start= 3;);
+
+ for (ulint i= 0; i < srv_undo_tablespaces; ++i)
+ {
+ char name[OS_FILE_MAX_PATH];
+ snprintf(name, sizeof name, "%s%cundo%03zu",
+ srv_undo_dir, OS_PATH_SEPARATOR, i + 1);
+ if (dberr_t err= srv_undo_tablespace_create(name))
+ {
+ ib::error() << "Could not create undo tablespace '" << name << "'.";
+ return err;
+ }
+ }
+ }
+
+ /* Get the tablespace ids of all the undo segments excluding
+ the system tablespace (0). If we are creating a new instance then
+ we build the undo_tablespace_ids ourselves since they don't
+ already exist. */
+ srv_undo_tablespaces_active= srv_undo_tablespaces;
+
+ ulint n_undo= (create_new_db || srv_operation == SRV_OPERATION_BACKUP ||
+ srv_operation == SRV_OPERATION_RESTORE_DELTA)
+ ? srv_undo_tablespaces : TRX_SYS_N_RSEGS;
+
+ if (dberr_t err= srv_all_undo_tablespaces_open(create_new_db, n_undo))
+ return err;
+
+ /* Initialize srv_undo_space_id_start=0 when there are no
+ dedicated undo tablespaces. */
+ if (srv_undo_tablespaces_open == 0)
+ srv_undo_space_id_start= 0;
+
+ if (create_new_db)
+ {
+ mtr_t mtr;
+ for (ulint i= 0; i < srv_undo_tablespaces; ++i)
+ {
+ mtr.start();
+ fsp_header_init(fil_space_get(srv_undo_space_id_start + i),
+ SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr);
+ mtr.commit();
+ }
+ }
+
+ return DB_SUCCESS;
}
/** Create the temporary file tablespace.
@@ -1736,14 +1745,6 @@ files_checked:
return(srv_init_abort(err));
}
} else {
- /* Work around the bug that we were performing a dirty read of
- at least the TRX_SYS page into the buffer pool above, without
- reading or applying any redo logs.
-
- MDEV-19229 FIXME: Remove the dirty reads and this call.
- Add an assertion that the buffer pool is empty. */
- buf_pool_invalidate();
-
/* We always try to do a recovery, even if the database had
been shut down normally: this is the normal startup path */
@@ -1767,6 +1768,12 @@ files_checked:
case SRV_OPERATION_RESTORE:
/* This must precede
recv_apply_hashed_log_recs(true). */
+ srv_undo_tablespaces_active
+ = trx_rseg_get_n_undo_tablespaces();
+ err = srv_validate_undo_tablespaces();
+ if (err != DB_SUCCESS) {
+ return srv_init_abort(err);
+ }
trx_lists_init_at_db_start();
break;
case SRV_OPERATION_RESTORE_DELTA:
@@ -1813,9 +1820,9 @@ files_checked:
ut_ad(size == fil_system.sys_space
->size_in_header);
size += sum_of_new_sizes;
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SIZE
- + block->frame, size,
- MLOG_4BYTES, &mtr);
+ mtr.write<4>(*block,
+ FSP_HEADER_OFFSET + FSP_SIZE
+ + block->frame, size);
fil_system.sys_space->size_in_header = size;
mtr.commit();
/* Immediately write the log record about
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index cb9142f2148..e5c09b4756a 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -213,15 +213,16 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
|| undo == trx->rsegs.m_redo.old_insert);
trx_rseg_t* rseg = trx->rsegs.m_redo.rseg;
ut_ad(undo->rseg == rseg);
- trx_rsegf_t* rseg_header = trx_rsegf_get(
+ buf_block_t* rseg_header = trx_rsegf_get(
rseg->space, rseg->page_no, mtr);
- page_t* undo_page = trx_undo_set_state_at_finish(
+ buf_block_t* undo_page = trx_undo_set_state_at_finish(
undo, mtr);
- trx_ulogf_t* undo_header = undo_page + undo->hdr_offset;
+ trx_ulogf_t* undo_header = undo_page->frame + undo->hdr_offset;
ut_ad(mach_read_from_2(undo_header + TRX_UNDO_NEEDS_PURGE) <= 1);
- if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG_FORMAT + rseg_header))) {
+ if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
+ + rseg_header->frame))) {
/* This database must have been upgraded from
before MariaDB 10.3.5. */
trx_rseg_format_upgrade(rseg_header, mtr);
@@ -230,23 +231,27 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
if (undo->state != TRX_UNDO_CACHED) {
/* The undo log segment will not be reused */
ut_a(undo->id < TRX_RSEG_N_SLOTS);
- trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL, mtr);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+ mtr->memset(rseg_header,
+ TRX_RSEG + TRX_RSEG_UNDO_SLOTS
+ + undo->id * TRX_RSEG_SLOT_SIZE, 4, 0xff);
MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_USED);
uint32_t hist_size = mach_read_from_4(TRX_RSEG_HISTORY_SIZE
- + rseg_header);
+ + TRX_RSEG
+ + rseg_header->frame);
ut_ad(undo->size == flst_get_len(TRX_UNDO_SEG_HDR
+ TRX_UNDO_PAGE_LIST
- + undo_page));
-
- mlog_write_ulint(
- rseg_header + TRX_RSEG_HISTORY_SIZE,
- hist_size + undo->size, MLOG_4BYTES, mtr);
-
- mlog_write_ull(rseg_header + TRX_RSEG_MAX_TRX_ID,
- trx_sys.get_max_trx_id(), mtr);
+ + undo_page->frame));
+
+ mtr->write<4>(*rseg_header, TRX_RSEG + TRX_RSEG_HISTORY_SIZE
+ + rseg_header->frame,
+ hist_size + undo->size);
+ mtr->write<8>(*rseg_header, TRX_RSEG + TRX_RSEG_MAX_TRX_ID
+ + rseg_header->frame,
+ trx_sys.get_max_trx_id());
}
/* After the purge thread has been given permission to exit,
@@ -289,16 +294,17 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
}
/* Add the log as the first in the history list */
- flst_add_first(rseg_header + TRX_RSEG_HISTORY,
- undo_header + TRX_UNDO_HISTORY_NODE, mtr);
+ flst_add_first(rseg_header, TRX_RSEG + TRX_RSEG_HISTORY,
+ undo_page, undo->hdr_offset + TRX_UNDO_HISTORY_NODE,
+ mtr);
- mlog_write_ull(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr);
+ mtr->write<8>(*undo_page, undo_header + TRX_UNDO_TRX_NO, trx->no);
/* This is needed for upgrading old undo log pages from
before MariaDB 10.3.1. */
if (UNIV_UNLIKELY(!mach_read_from_2(undo_header
+ TRX_UNDO_NEEDS_PURGE))) {
- mlog_write_ulint(undo_header + TRX_UNDO_NEEDS_PURGE, 1,
- MLOG_2BYTES, mtr);
+ mtr->write<2>(*undo_page, undo_header + TRX_UNDO_NEEDS_PURGE,
+ 1U);
}
if (rseg->last_page_no == FIL_NULL) {
@@ -322,19 +328,16 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
}
/** Remove undo log header from the history list.
-@param[in,out] rseg_hdr rollback segment header
-@param[in] log_hdr undo log segment header
-@param[in,out] mtr mini transaction. */
-static
-void
-trx_purge_remove_log_hdr(
- trx_rsegf_t* rseg_hdr,
- trx_ulogf_t* log_hdr,
- mtr_t* mtr)
+@param[in,out] rseg rollback segment header page
+@param[in] log undo log segment header page
+@param[in] offset byte offset in the undo log segment header page
+@param[in,out] mtr mini-transaction */
+static void trx_purge_remove_log_hdr(buf_block_t *rseg, buf_block_t* log,
+ uint16_t offset, mtr_t *mtr)
{
- flst_remove(rseg_hdr + TRX_RSEG_HISTORY,
- log_hdr + TRX_UNDO_HISTORY_NODE, mtr);
- trx_sys.rseg_history_len--;
+ flst_remove(rseg, TRX_RSEG + TRX_RSEG_HISTORY,
+ log, offset + TRX_UNDO_HISTORY_NODE, mtr);
+ trx_sys.rseg_history_len--;
}
/** Free an undo log segment, and remove the header from the history list.
@@ -345,14 +348,12 @@ void
trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
{
mtr_t mtr;
- trx_rsegf_t* rseg_hdr;
- page_t* undo_page;
mtr.start();
mutex_enter(&rseg->mutex);
- rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
- undo_page = trx_undo_page_get(
+ buf_block_t* rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
+ buf_block_t* block = trx_undo_page_get(
page_id_t(rseg->space->id, hdr_addr.page), &mtr);
/* Mark the last undo log totally purged, so that if the
@@ -360,12 +361,12 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
again. The list of pages in the undo log tail gets
inconsistent during the freeing of the segment, and therefore
purge should not try to access them again. */
- mlog_write_ulint(undo_page + hdr_addr.boffset + TRX_UNDO_NEEDS_PURGE,
- 0, MLOG_2BYTES, &mtr);
+ mtr.write<2>(*block, block->frame + hdr_addr.boffset
+ + TRX_UNDO_NEEDS_PURGE, 0U);
while (!fseg_free_step_not_header(
TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
- + undo_page, false, &mtr)) {
+ + block->frame, false, &mtr)) {
mutex_exit(&rseg->mutex);
mtr.commit();
@@ -375,7 +376,7 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
- undo_page = trx_undo_page_get(
+ block = trx_undo_page_get(
page_id_t(rseg->space->id, hdr_addr.page), &mtr);
}
@@ -383,15 +384,15 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
stored in the list base node tells us how big it was before we
started the freeing. */
- const ulint seg_size = flst_get_len(
- TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + undo_page);
+ const uint32_t seg_size = flst_get_len(
+ TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + block->frame);
/* We may free the undo log segment header page; it must be freed
within the same mtr as the undo log header is removed from the
history list: otherwise, in case of a database crash, the segment
could become inaccessible garbage in the file space. */
- trx_purge_remove_log_hdr(rseg_hdr, undo_page + hdr_addr.boffset, &mtr);
+ trx_purge_remove_log_hdr(rseg_hdr, block, hdr_addr.boffset, &mtr);
do {
@@ -401,14 +402,12 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
fsp0fsp.cc. */
} while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
- + undo_page, false, &mtr));
+ + block->frame, false, &mtr));
- const ulint hist_size = mach_read_from_4(rseg_hdr
- + TRX_RSEG_HISTORY_SIZE);
- ut_ad(hist_size >= seg_size);
+ byte* hist = TRX_RSEG + TRX_RSEG_HISTORY_SIZE + rseg_hdr->frame;
+ ut_ad(mach_read_from_4(hist) >= seg_size);
- mlog_write_ulint(rseg_hdr + TRX_RSEG_HISTORY_SIZE,
- hist_size - seg_size, MLOG_4BYTES, &mtr);
+ mtr.write<4>(*rseg_hdr, hist, mach_read_from_4(hist) - seg_size);
ut_ad(rseg->curr_size >= seg_size);
@@ -430,10 +429,6 @@ trx_purge_truncate_rseg_history(
{
fil_addr_t hdr_addr;
fil_addr_t prev_hdr_addr;
- trx_rsegf_t* rseg_hdr;
- page_t* undo_page;
- trx_ulogf_t* log_hdr;
- trx_usegf_t* seg_hdr;
mtr_t mtr;
trx_id_t undo_trx_no;
@@ -441,10 +436,10 @@ trx_purge_truncate_rseg_history(
ut_ad(rseg.is_persistent());
mutex_enter(&rseg.mutex);
- rseg_hdr = trx_rsegf_get(rseg.space, rseg.page_no, &mtr);
+ buf_block_t* rseg_hdr = trx_rsegf_get(rseg.space, rseg.page_no, &mtr);
- hdr_addr = trx_purge_get_log_from_hist(flst_get_last(TRX_RSEG_HISTORY
- + rseg_hdr));
+ hdr_addr = trx_purge_get_log_from_hist(
+ flst_get_last(TRX_RSEG + TRX_RSEG_HISTORY + rseg_hdr->frame));
loop:
if (hdr_addr.page == FIL_NULL) {
func_exit:
@@ -453,12 +448,11 @@ func_exit:
return;
}
- undo_page = trx_undo_page_get(page_id_t(rseg.space->id, hdr_addr.page),
- &mtr);
-
- log_hdr = undo_page + hdr_addr.boffset;
-
- undo_trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO);
+ buf_block_t* block = trx_undo_page_get(page_id_t(rseg.space->id,
+ hdr_addr.page),
+ &mtr);
+ undo_trx_no = mach_read_from_8(block->frame + hdr_addr.boffset
+ + TRX_UNDO_TRX_NO);
if (undo_trx_no >= limit.trx_no()) {
if (undo_trx_no == limit.trx_no()) {
@@ -471,12 +465,13 @@ func_exit:
}
prev_hdr_addr = trx_purge_get_log_from_hist(
- flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE));
-
- seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
+ flst_get_prev_addr(block->frame + hdr_addr.boffset
+ + TRX_UNDO_HISTORY_NODE));
- if ((mach_read_from_2(seg_hdr + TRX_UNDO_STATE) == TRX_UNDO_TO_PURGE)
- && (mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG) == 0)) {
+ if (mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + block->frame)
+ == TRX_UNDO_TO_PURGE
+ && !mach_read_from_2(block->frame + hdr_addr.boffset
+ + TRX_UNDO_NEXT_LOG)) {
/* We can free the whole log segment */
@@ -488,7 +483,8 @@ func_exit:
trx_purge_free_segment(&rseg, hdr_addr);
} else {
/* Remove the log hdr from the rseg history. */
- trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr);
+ trx_purge_remove_log_hdr(rseg_hdr, block, hdr_addr.boffset,
+ &mtr);
mutex_exit(&rseg.mutex);
mtr.commit();
@@ -827,8 +823,6 @@ static void trx_purge_rseg_get_next_history_log(
ulint* n_pages_handled)/*!< in/out: number of UNDO pages
handled */
{
- page_t* undo_page;
- trx_ulogf_t* log_hdr;
fil_addr_t prev_log_addr;
trx_id_t trx_no;
mtr_t mtr;
@@ -843,11 +837,12 @@ static void trx_purge_rseg_get_next_history_log(
mtr.start();
- undo_page = trx_undo_page_get_s_latched(
+ const buf_block_t* undo_page = trx_undo_page_get_s_latched(
page_id_t(purge_sys.rseg->space->id,
purge_sys.rseg->last_page_no), &mtr);
- log_hdr = undo_page + purge_sys.rseg->last_offset;
+ const trx_ulogf_t* log_hdr = undo_page->frame
+ + purge_sys.rseg->last_offset;
/* Increase the purge page count by one for every handled log */
@@ -875,7 +870,7 @@ static void trx_purge_rseg_get_next_history_log(
log_hdr = trx_undo_page_get_s_latched(
page_id_t(purge_sys.rseg->space->id, prev_log_addr.page),
- &mtr)
+ &mtr)->frame
+ prev_log_addr.boffset;
trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO);
@@ -910,8 +905,8 @@ static
void
trx_purge_read_undo_rec()
{
- ulint offset;
- ulint page_no;
+ uint16_t offset;
+ uint32_t page_no;
ib_uint64_t undo_no;
purge_sys.hdr_offset = purge_sys.rseg->last_offset;
@@ -920,13 +915,15 @@ trx_purge_read_undo_rec()
if (purge_sys.rseg->needs_purge) {
mtr_t mtr;
mtr.start();
+ buf_block_t* undo_page;
if (trx_undo_rec_t* undo_rec = trx_undo_get_first_rec(
- purge_sys.rseg->space, purge_sys.hdr_page_no,
- purge_sys.hdr_offset, RW_S_LATCH, &mtr)) {
+ *purge_sys.rseg->space, purge_sys.hdr_page_no,
+ purge_sys.hdr_offset, RW_S_LATCH,
+ undo_page, &mtr)) {
offset = page_offset(undo_rec);
undo_no = trx_undo_rec_get_undo_no(undo_rec);
- page_no = page_get_page_no(page_align(undo_rec));
+ page_no = undo_page->page.id.page_no();
} else {
offset = 0;
undo_no = 0;
@@ -976,22 +973,14 @@ trx_purge_get_next_rec(
handled */
mem_heap_t* heap) /*!< in: memory heap where copied */
{
- trx_undo_rec_t* rec;
- trx_undo_rec_t* rec_copy;
- trx_undo_rec_t* rec2;
- page_t* undo_page;
- page_t* page;
- ulint offset;
- ulint page_no;
- ulint space;
mtr_t mtr;
ut_ad(purge_sys.next_stored);
ut_ad(purge_sys.tail.trx_no() < purge_sys.view.low_limit_no());
- space = purge_sys.rseg->space->id;
- page_no = purge_sys.page_no;
- offset = purge_sys.offset;
+ const ulint space = purge_sys.rseg->space->id;
+ const uint32_t page_no = purge_sys.page_no;
+ const uint16_t offset = purge_sys.offset;
if (offset == 0) {
/* It is the dummy undo log record, which means that there is
@@ -1008,16 +997,16 @@ trx_purge_get_next_rec(
mtr_start(&mtr);
- undo_page = trx_undo_page_get_s_latched(page_id_t(space, page_no),
- &mtr);
+ buf_block_t* undo_page = trx_undo_page_get_s_latched(
+ page_id_t(space, page_no), &mtr);
+ buf_block_t* rec2_page = undo_page;
- rec = undo_page + offset;
-
- rec2 = trx_undo_page_get_next_rec(rec, purge_sys.hdr_page_no,
- purge_sys.hdr_offset);
+ const trx_undo_rec_t* rec2 = trx_undo_page_get_next_rec(
+ undo_page, offset, purge_sys.hdr_page_no, purge_sys.hdr_offset);
if (rec2 == NULL) {
- rec2 = trx_undo_get_next_rec(rec, purge_sys.hdr_page_no,
+ rec2 = trx_undo_get_next_rec(rec2_page, offset,
+ purge_sys.hdr_page_no,
purge_sys.hdr_offset, &mtr);
}
@@ -1034,22 +1023,19 @@ trx_purge_get_next_rec(
undo_page = trx_undo_page_get_s_latched(
page_id_t(space, page_no), &mtr);
-
- rec = undo_page + offset;
} else {
- page = page_align(rec2);
-
- purge_sys.offset = ulint(rec2 - page);
- purge_sys.page_no = page_get_page_no(page);
+ purge_sys.offset = page_offset(rec2);
+ purge_sys.page_no = rec2_page->page.id.page_no();
purge_sys.tail.undo_no = trx_undo_rec_get_undo_no(rec2);
- if (undo_page != page) {
+ if (undo_page != rec2_page) {
/* We advance to a new page of the undo log: */
(*n_pages_handled)++;
}
}
- rec_copy = trx_undo_rec_copy(rec, heap);
+ trx_undo_rec_t* rec_copy = trx_undo_rec_copy(undo_page->frame + offset,
+ heap);
mtr_commit(&mtr);
diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc
index c4fa6e94ad5..2628d4841fc 100644
--- a/storage/innobase/trx/trx0rec.cc
+++ b/storage/innobase/trx/trx0rec.cc
@@ -162,7 +162,7 @@ that was written to ptr. Update the first free value by the number of bytes
written for this undo record.
@return offset of the inserted entry on the page if succeeded, 0 if fail */
static
-ulint
+uint16_t
trx_undo_page_set_next_prev_and_add(
/*================================*/
buf_block_t* undo_block, /*!< in/out: undo log page */
@@ -170,30 +170,22 @@ trx_undo_page_set_next_prev_and_add(
written on this undo page. */
mtr_t* mtr) /*!< in: mtr */
{
- ulint first_free; /*!< offset within undo_page */
- ulint end_of_rec; /*!< offset within undo_page */
- byte* ptr_to_first_free;
- /* pointer within undo_page
- that points to the next free
- offset value within undo_page.*/
-
- ut_ad(ptr > undo_block->frame);
- ut_ad(ptr < undo_block->frame + srv_page_size);
+ ut_ad(page_align(ptr) == undo_block->frame);
if (UNIV_UNLIKELY(trx_undo_left(undo_block, ptr) < 2)) {
return(0);
}
- ptr_to_first_free = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
+ byte* ptr_to_first_free = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
+ undo_block->frame;
- first_free = mach_read_from_2(ptr_to_first_free);
+ uint16_t first_free = mach_read_from_2(ptr_to_first_free);
/* Write offset of the previous undo log record */
mach_write_to_2(ptr, first_free);
ptr += 2;
- end_of_rec = ulint(ptr - undo_block->frame);
+ uint16_t end_of_rec = uint16_t(ptr - undo_block->frame);
/* Write offset of the next undo log record */
mach_write_to_2(undo_block->frame + first_free, end_of_rec);
@@ -457,7 +449,7 @@ trx_undo_report_insert_virtual(
Reports in the undo log of an insert of a clustered index record.
@return offset of the inserted entry on the page if succeed, 0 if fail */
static
-ulint
+uint16_t
trx_undo_page_report_insert(
/*========================*/
buf_block_t* undo_block, /*!< in: undo log page */
@@ -467,10 +459,6 @@ trx_undo_page_report_insert(
inserted to the clustered index */
mtr_t* mtr) /*!< in: mtr */
{
- ulint first_free;
- byte* ptr;
- ulint i;
-
ut_ad(dict_index_is_clust(index));
/* MariaDB 10.3.1+ in trx_undo_page_init() always initializes
TRX_UNDO_PAGE_TYPE as 0, but previous versions wrote
@@ -479,9 +467,10 @@ trx_undo_page_report_insert(
ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ undo_block->frame) <= 2);
- first_free = mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
- + undo_block->frame);
- ptr = undo_block->frame + first_free;
+ uint16_t first_free = mach_read_from_2(TRX_UNDO_PAGE_HDR
+ + TRX_UNDO_PAGE_FREE
+ + undo_block->frame);
+ byte* ptr = undo_block->frame + first_free;
ut_ad(first_free <= srv_page_size);
@@ -509,7 +498,7 @@ trx_undo_page_report_insert(
goto done;
}
- for (i = 0; i < dict_index_get_n_unique(index); i++) {
+ for (unsigned i = 0; i < dict_index_get_n_unique(index); i++) {
const dfield_t* field = dtuple_get_nth_field(clust_entry, i);
ulint flen = dfield_get_len(field);
@@ -572,12 +561,14 @@ trx_undo_rec_get_pars(
*updated_extern = !!(type_cmpl & TRX_UNDO_UPD_EXTERN);
type_cmpl &= ~TRX_UNDO_UPD_EXTERN;
-
*type = type_cmpl & (TRX_UNDO_CMPL_INFO_MULT - 1);
+ ut_ad(*type >= TRX_UNDO_RENAME_TABLE);
+ ut_ad(*type <= TRX_UNDO_DEL_MARK_REC);
*cmpl_info = type_cmpl / TRX_UNDO_CMPL_INFO_MULT;
*undo_no = mach_read_next_much_compressed(&ptr);
*table_id = mach_read_next_much_compressed(&ptr);
+ ut_ad(*table_id);
return(const_cast<byte*>(ptr));
}
@@ -856,7 +847,7 @@ record.
@return byte offset of the inserted undo log entry on the page if
succeed, 0 if fail */
static
-ulint
+uint16_t
trx_undo_page_report_modify(
/*========================*/
buf_block_t* undo_block, /*!< in: undo log page */
@@ -875,7 +866,6 @@ trx_undo_page_report_modify(
virtual column info */
mtr_t* mtr) /*!< in: mtr */
{
- ulint first_free;
byte* ptr;
ut_ad(index->is_primary());
@@ -887,8 +877,9 @@ trx_undo_page_report_modify(
ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ undo_block->frame) <= 2);
- first_free = mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
- + undo_block->frame);
+ uint16_t first_free = mach_read_from_2(TRX_UNDO_PAGE_HDR
+ + TRX_UNDO_PAGE_FREE
+ + undo_block->frame);
ptr = undo_block->frame + first_free;
ut_ad(first_free <= srv_page_size);
@@ -1953,13 +1944,13 @@ trx_undo_erase_page_end(page_t* undo_page)
@return byte offset of the undo log record
@retval 0 in case of failure */
static
-ulint
+uint16_t
trx_undo_page_report_rename(trx_t* trx, const dict_table_t* table,
buf_block_t* block, mtr_t* mtr)
{
byte* ptr_first_free = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
+ block->frame;
- ulint first_free = mach_read_from_2(ptr_first_free);
+ uint16_t first_free = mach_read_from_2(ptr_first_free);
ut_ad(first_free >= TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
ut_ad(first_free <= srv_page_size);
byte* start = block->frame + first_free;
@@ -1985,7 +1976,7 @@ trx_undo_page_report_rename(trx_t* trx, const dict_table_t* table,
ptr += len;
mach_write_to_2(ptr, first_free);
ptr += 2;
- ulint offset = page_offset(ptr);
+ uint16_t offset = page_offset(ptr);
mach_write_to_2(start, offset);
mach_write_to_2(ptr_first_free, offset);
@@ -2014,7 +2005,7 @@ dberr_t trx_undo_report_rename(trx_t* trx, const dict_table_t* table)
ut_ad(loop_count++ < 2);
ut_ad(undo->last_page_no == block->page.id.page_no());
- if (ulint offset = trx_undo_page_report_rename(
+ if (uint16_t offset = trx_undo_page_report_rename(
trx, table, block, &mtr)) {
undo->withdraw_clock = buf_withdraw_clock;
undo->top_page_no = undo->last_page_no;
@@ -2118,7 +2109,7 @@ trx_undo_report_row_operation(
ut_ad(undo != NULL);
do {
- ulint offset = !rec
+ uint16_t offset = !rec
? trx_undo_page_report_insert(
undo_block, trx, index, clust_entry, &mtr)
: trx_undo_page_report_modify(
@@ -2240,11 +2231,10 @@ trx_undo_get_undo_rec_low(
{
trx_undo_rec_t* undo_rec;
ulint rseg_id;
- ulint page_no;
- ulint offset;
- const page_t* undo_page;
+ uint32_t page_no;
+ uint16_t offset;
trx_rseg_t* rseg;
- ibool is_insert;
+ bool is_insert;
mtr_t mtr;
trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no,
@@ -2254,14 +2244,14 @@ trx_undo_get_undo_rec_low(
rseg = trx_sys.rseg_array[rseg_id];
ut_ad(rseg->is_persistent());
- mtr_start(&mtr);
+ mtr.start();
- undo_page = trx_undo_page_get_s_latched(
+ buf_block_t* undo_page = trx_undo_page_get_s_latched(
page_id_t(rseg->space->id, page_no), &mtr);
- undo_rec = trx_undo_rec_copy(undo_page + offset, heap);
+ undo_rec = trx_undo_rec_copy(undo_page->frame + offset, heap);
- mtr_commit(&mtr);
+ mtr.commit();
return(undo_rec);
}
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index c33b4fda6ae..546a4c51e03 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -31,8 +31,6 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0purge.h"
#include "srv0mon.h"
-#include <algorithm>
-
#ifdef WITH_WSREP
#include <mysql/service_wsrep.h>
@@ -49,7 +47,7 @@ static unsigned char wsrep_uuid[16];
@param[in,out] mtr mini transaction */
static void
trx_rseg_write_wsrep_checkpoint(
- trx_rsegf_t* rseg_header,
+ buf_block_t* rseg_header,
const XID* xid,
mtr_t* mtr)
{
@@ -57,26 +55,29 @@ trx_rseg_write_wsrep_checkpoint(
DBUG_ASSERT(xid->bqual_length >= 0);
DBUG_ASSERT(xid->gtrid_length + xid->bqual_length < XIDDATASIZE);
- mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header,
- uint32_t(xid->formatID),
- MLOG_4BYTES, mtr);
+ mtr->write<4,mtr_t::OPT>(*rseg_header,
+ TRX_RSEG + TRX_RSEG_WSREP_XID_FORMAT
+ + rseg_header->frame,
+ uint32_t(xid->formatID));
- mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header,
- uint32_t(xid->gtrid_length),
- MLOG_4BYTES, mtr);
+ mtr->write<4,mtr_t::OPT>(*rseg_header,
+ TRX_RSEG + TRX_RSEG_WSREP_XID_GTRID_LEN
+ + rseg_header->frame,
+ uint32_t(xid->gtrid_length));
- mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header,
- uint32_t(xid->bqual_length),
- MLOG_4BYTES, mtr);
+ mtr->write<4,mtr_t::OPT>(*rseg_header,
+ TRX_RSEG + TRX_RSEG_WSREP_XID_BQUAL_LEN
+ + rseg_header->frame,
+ uint32_t(xid->bqual_length));
const ulint xid_length = static_cast<ulint>(xid->gtrid_length
+ xid->bqual_length);
- mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header,
- reinterpret_cast<const byte*>(xid->data),
- xid_length, mtr);
+ mtr->memcpy(rseg_header, TRX_RSEG + TRX_RSEG_WSREP_XID_DATA,
+ xid->data, xid_length);
if (UNIV_LIKELY(xid_length < XIDDATASIZE)) {
- mlog_memset(TRX_RSEG_WSREP_XID_DATA + rseg_header + xid_length,
- XIDDATASIZE - xid_length, 0, mtr);
+ mtr->memset(rseg_header,
+ TRX_RSEG + TRX_RSEG_WSREP_XID_DATA + xid_length,
+ XIDDATASIZE - xid_length, 0);
}
}
@@ -86,7 +87,7 @@ trx_rseg_write_wsrep_checkpoint(
@param[in,out] mtr mini-transaction */
void
trx_rseg_update_wsrep_checkpoint(
- trx_rsegf_t* rseg_header,
+ buf_block_t* rseg_header,
const XID* xid,
mtr_t* mtr)
{
@@ -109,16 +110,13 @@ trx_rseg_update_wsrep_checkpoint(
}
/** Clear the WSREP XID information from rollback segment header.
-@param[in,out] rseg_header Rollback segment header
-@param[in,out] mtr mini-transaction */
-static void
-trx_rseg_clear_wsrep_checkpoint(
- trx_rsegf_t* rseg_header,
- mtr_t* mtr)
+@param[in,out] block rollback segment header
+@param[in,out] mtr mini-transaction */
+static void trx_rseg_clear_wsrep_checkpoint(buf_block_t *block, mtr_t *mtr)
{
- mlog_memset(rseg_header + TRX_RSEG_WSREP_XID_INFO,
- TRX_RSEG_WSREP_XID_DATA + XIDDATASIZE
- - TRX_RSEG_WSREP_XID_INFO, 0, mtr);
+ mtr->memset(block, TRX_RSEG + TRX_RSEG_WSREP_XID_INFO,
+ TRX_RSEG_WSREP_XID_DATA + XIDDATASIZE - TRX_RSEG_WSREP_XID_INFO,
+ 0);
}
static void
@@ -133,9 +131,10 @@ trx_rseg_update_wsrep_checkpoint(const XID* xid, mtr_t* mtr)
sizeof wsrep_uuid);
const trx_rseg_t* rseg = trx_sys.rseg_array[0];
- trx_rsegf_t* rseg_header = trx_rsegf_get(rseg->space, rseg->page_no,
+ buf_block_t* rseg_header = trx_rsegf_get(rseg->space, rseg->page_no,
mtr);
- if (UNIV_UNLIKELY(mach_read_from_4(rseg_header + TRX_RSEG_FORMAT))) {
+ if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
+ + rseg_header->frame))) {
trx_rseg_format_upgrade(rseg_header, mtr);
}
@@ -178,25 +177,26 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid)
@param[out] xid Transaction XID
@return whether the WSREP XID was present */
static
-bool trx_rseg_read_wsrep_checkpoint(const trx_rsegf_t* rseg_header, XID& xid)
+bool trx_rseg_read_wsrep_checkpoint(const buf_block_t *rseg_header, XID &xid)
{
int formatID = static_cast<int>(
- mach_read_from_4(
- TRX_RSEG_WSREP_XID_FORMAT + rseg_header));
+ mach_read_from_4(TRX_RSEG + TRX_RSEG_WSREP_XID_FORMAT
+ + rseg_header->frame));
if (formatID == 0) {
return false;
}
xid.formatID = formatID;
xid.gtrid_length = static_cast<int>(
- mach_read_from_4(
- TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header));
+ mach_read_from_4(TRX_RSEG + TRX_RSEG_WSREP_XID_GTRID_LEN
+ + rseg_header->frame));
xid.bqual_length = static_cast<int>(
- mach_read_from_4(
- TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header));
+ mach_read_from_4(TRX_RSEG + TRX_RSEG_WSREP_XID_BQUAL_LEN
+ + rseg_header->frame));
- memcpy(xid.data, TRX_RSEG_WSREP_XID_DATA + rseg_header, XIDDATASIZE);
+ memcpy(xid.data, TRX_RSEG + TRX_RSEG_WSREP_XID_DATA
+ + rseg_header->frame, XIDDATASIZE);
return true;
}
@@ -252,10 +252,11 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid)
continue;
}
- const trx_rsegf_t* rseg_header = trx_rsegf_get_new(
+ const buf_block_t* rseg_header = trx_rsegf_get_new(
trx_sysf_rseg_get_space(sys, rseg_id), page_no, &mtr);
- if (mach_read_from_4(rseg_header + TRX_RSEG_FORMAT)) {
+ if (mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
+ + rseg_header->frame)) {
continue;
}
@@ -279,17 +280,15 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid)
/** Upgrade a rollback segment header page to MariaDB 10.3 format.
@param[in,out] rseg_header rollback segment header page
@param[in,out] mtr mini-transaction */
-void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr)
+void trx_rseg_format_upgrade(buf_block_t *rseg_header, mtr_t *mtr)
{
- ut_ad(page_offset(rseg_header) == TRX_RSEG);
- byte* rseg_format = TRX_RSEG_FORMAT + rseg_header;
- mlog_write_ulint(rseg_format, 0, MLOG_4BYTES, mtr);
- /* Clear also possible garbage at the end of the page. Old
- InnoDB versions did not initialize unused parts of pages. */
- mlog_memset(TRX_RSEG_MAX_TRX_ID + 8 + rseg_header,
- srv_page_size
- - (FIL_PAGE_DATA_END
- + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8), 0, mtr);
+ mtr->memset(rseg_header, TRX_RSEG + TRX_RSEG_FORMAT, 4, 0);
+ /* Clear also possible garbage at the end of the page. Old
+ InnoDB versions did not initialize unused parts of pages. */
+ mtr->memset(rseg_header, TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8,
+ srv_page_size
+ - (FIL_PAGE_DATA_END + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8),
+ 0);
}
/** Create a rollback segment header.
@@ -330,23 +329,23 @@ trx_rseg_header_create(
flst_init(block, TRX_RSEG_HISTORY + TRX_RSEG, mtr);
/* Reset the undo log slots */
- mlog_memset(block, TRX_RSEG_UNDO_SLOTS + TRX_RSEG,
- TRX_RSEG_N_SLOTS * 4, 0xff, mtr);
+ mtr->memset(block, TRX_RSEG_UNDO_SLOTS + TRX_RSEG,
+ TRX_RSEG_N_SLOTS * 4, 0xff);
if (sys_header) {
/* Add the rollback segment info to the free slot in
the trx system header */
- mlog_write_ulint(TRX_SYS + TRX_SYS_RSEGS
- + TRX_SYS_RSEG_SPACE
- + rseg_id * TRX_SYS_RSEG_SLOT_SIZE
- + sys_header->frame,
- space->id, MLOG_4BYTES, mtr);
- mlog_write_ulint(TRX_SYS + TRX_SYS_RSEGS
- + TRX_SYS_RSEG_PAGE_NO
- + rseg_id * TRX_SYS_RSEG_SLOT_SIZE
- + sys_header->frame,
- block->page.id.page_no(), MLOG_4BYTES, mtr);
+ mtr->write<4,mtr_t::OPT>(
+ *sys_header,
+ TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_SPACE
+ + rseg_id * TRX_SYS_RSEG_SLOT_SIZE
+ + sys_header->frame, space->id);
+ mtr->write<4,mtr_t::OPT>(
+ *sys_header,
+ TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_PAGE_NO
+ + rseg_id * TRX_SYS_RSEG_SLOT_SIZE
+ + sys_header->frame, block->page.id.page_no());
}
return block;
@@ -410,29 +409,28 @@ trx_rseg_mem_create(ulint id, fil_space_t* space, ulint page_no)
}
/** Read the undo log lists.
-@param[in,out] rseg rollback segment
-@param[in,out] max_trx_id maximum observed transaction identifier
-@param[in] rseg_header rollback segment header
+@param[in,out] rseg rollback segment
+@param[in,out] max_trx_id maximum observed transaction identifier
+@param[in] rseg_header rollback segment header
@return the combined size of undo log segments in pages */
-static
-ulint
-trx_undo_lists_init(trx_rseg_t* rseg, trx_id_t& max_trx_id,
- const trx_rsegf_t* rseg_header)
+static ulint trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id,
+ const buf_block_t *rseg_header)
{
- ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN);
+ ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN);
- ulint size = 0;
+ ulint size= 0;
- for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) {
- ulint page_no = trx_rsegf_get_nth_undo(rseg_header, i);
- if (page_no != FIL_NULL) {
- size += trx_undo_mem_create_at_db_start(
- rseg, i, page_no, max_trx_id);
- MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED);
- }
- }
+ for (ulint i= 0; i < TRX_RSEG_N_SLOTS; i++)
+ {
+ uint32_t page_no= trx_rsegf_get_nth_undo(rseg_header, i);
+ if (page_no != FIL_NULL)
+ {
+ size+= trx_undo_mem_create_at_db_start(rseg, i, page_no, max_trx_id);
+ MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED);
+ }
+ }
- return(size);
+ return size;
}
/** Restore the state of a persistent rollback segment.
@@ -443,20 +441,20 @@ static
void
trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
{
- trx_rsegf_t* rseg_header = trx_rsegf_get_new(
+ buf_block_t* rseg_hdr = trx_rsegf_get_new(
rseg->space->id, rseg->page_no, mtr);
- if (mach_read_from_4(rseg_header + TRX_RSEG_FORMAT) == 0) {
- trx_id_t id = mach_read_from_8(rseg_header
- + TRX_RSEG_MAX_TRX_ID);
+ if (!mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT + rseg_hdr->frame)) {
+ trx_id_t id = mach_read_from_8(TRX_RSEG + TRX_RSEG_MAX_TRX_ID
+ + rseg_hdr->frame);
if (id > max_trx_id) {
max_trx_id = id;
}
- if (rseg_header[TRX_RSEG_BINLOG_NAME]) {
- const char* binlog_name = reinterpret_cast<const char*>
- (rseg_header) + TRX_RSEG_BINLOG_NAME;
+ const char* binlog_name = TRX_RSEG + TRX_RSEG_BINLOG_NAME
+ + reinterpret_cast<const char*>(rseg_hdr->frame);
+ if (*binlog_name) {
compile_time_assert(TRX_RSEG_BINLOG_NAME_LEN == sizeof
trx_sys.recovered_binlog_filename);
@@ -468,7 +466,8 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
if (cmp >= 0) {
uint64_t binlog_offset = mach_read_from_8(
- rseg_header + TRX_RSEG_BINLOG_OFFSET);
+ TRX_RSEG + TRX_RSEG_BINLOG_OFFSET
+ + rseg_hdr->frame);
if (cmp) {
memcpy(trx_sys.
recovered_binlog_filename,
@@ -485,7 +484,7 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
#ifdef WITH_WSREP
trx_rseg_read_wsrep_checkpoint(
- rseg_header, trx_sys.recovered_wsrep_xid);
+ rseg_hdr, trx_sys.recovered_wsrep_xid);
#endif
}
}
@@ -499,32 +498,37 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
/* Initialize the undo log lists according to the rseg header */
- rseg->curr_size = mach_read_from_4(rseg_header + TRX_RSEG_HISTORY_SIZE)
- + 1 + trx_undo_lists_init(rseg, max_trx_id, rseg_header);
+ rseg->curr_size = mach_read_from_4(TRX_RSEG + TRX_RSEG_HISTORY_SIZE
+ + rseg_hdr->frame)
+ + 1 + trx_undo_lists_init(rseg, max_trx_id, rseg_hdr);
- if (auto len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) {
+ if (auto len = flst_get_len(TRX_RSEG + TRX_RSEG_HISTORY
+ + rseg_hdr->frame)) {
trx_sys.rseg_history_len += len;
fil_addr_t node_addr = trx_purge_get_log_from_hist(
- flst_get_last(rseg_header + TRX_RSEG_HISTORY));
+ flst_get_last(TRX_RSEG + TRX_RSEG_HISTORY
+ + rseg_hdr->frame));
rseg->last_page_no = node_addr.page;
rseg->last_offset = node_addr.boffset;
- const trx_ulogf_t* undo_log_hdr = trx_undo_page_get(
- page_id_t(rseg->space->id, node_addr.page), mtr)
- + node_addr.boffset;
+ const buf_block_t* block = trx_undo_page_get(
+ page_id_t(rseg->space->id, node_addr.page), mtr);
- trx_id_t id = mach_read_from_8(undo_log_hdr + TRX_UNDO_TRX_ID);
+ trx_id_t id = mach_read_from_8(block->frame + node_addr.boffset
+ + TRX_UNDO_TRX_ID);
if (id > max_trx_id) {
max_trx_id = id;
}
- id = mach_read_from_8(undo_log_hdr + TRX_UNDO_TRX_NO);
+ id = mach_read_from_8(block->frame + node_addr.boffset
+ + TRX_UNDO_TRX_NO);
if (id > max_trx_id) {
max_trx_id = id;
}
- unsigned purge = mach_read_from_2(
- undo_log_hdr + TRX_UNDO_NEEDS_PURGE);
+ unsigned purge = mach_read_from_2(block->frame
+ + node_addr.boffset
+ + TRX_UNDO_NEEDS_PURGE);
ut_ad(purge <= 1);
rseg->set_last_trx_no(id, purge != 0);
rseg->needs_purge = purge != 0;
@@ -638,9 +642,9 @@ trx_rseg_array_init()
}
/* Finally, clear WSREP XID in TRX_SYS page. */
- const buf_block_t* sys = trx_sysf_get(&mtr);
- mlog_memset(TRX_SYS + TRX_SYS_WSREP_XID_INFO + sys->frame,
- TRX_SYS_WSREP_XID_LEN, 0, &mtr);
+ mtr.memset(trx_sysf_get(&mtr),
+ TRX_SYS + TRX_SYS_WSREP_XID_INFO,
+ TRX_SYS_WSREP_XID_LEN, 0);
mtr.commit();
}
#endif
@@ -709,55 +713,6 @@ trx_temp_rseg_create()
}
}
-/********************************************************************
-Get the number of unique rollback tablespaces in use except space id 0.
-The last space id will be the sentinel value ULINT_UNDEFINED. The array
-will be sorted on space id. Note: space_ids should have have space for
-TRX_SYS_N_RSEGS + 1 elements.
-@return number of unique rollback tablespaces in use. */
-ulint
-trx_rseg_get_n_undo_tablespaces(
-/*============================*/
- ulint* space_ids) /*!< out: array of space ids of
- UNDO tablespaces */
-{
- mtr_t mtr;
- mtr.start();
-
- buf_block_t* sys_header = trx_sysf_get(&mtr, false);
- if (!sys_header) {
- mtr.commit();
- return 0;
- }
-
- ulint* end = space_ids;
-
- for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) {
- uint32_t page_no = trx_sysf_rseg_get_page_no(sys_header,
- rseg_id);
-
- if (page_no == FIL_NULL) {
- continue;
- }
-
- if (ulint space = trx_sysf_rseg_get_space(sys_header,
- rseg_id)) {
- if (std::find(space_ids, end, space) == end) {
- *end++ = space;
- }
- }
- }
-
- mtr.commit();
-
- ut_a(end - space_ids <= TRX_SYS_N_RSEGS);
- *end = ULINT_UNDEFINED;
-
- std::sort(space_ids, end);
-
- return ulint(end - space_ids);
-}
-
/** Update the offset information about the end of the binlog entry
which corresponds to the transaction just being committed.
In a replication slave, this updates the master binlog position
@@ -765,8 +720,8 @@ up to which replication has proceeded.
@param[in,out] rseg_header rollback segment header
@param[in] trx committing transaction
@param[in,out] mtr mini-transaction */
-void
-trx_rseg_update_binlog_offset(byte* rseg_header, const trx_t* trx, mtr_t* mtr)
+void trx_rseg_update_binlog_offset(buf_block_t *rseg_header, const trx_t *trx,
+ mtr_t *mtr)
{
DBUG_LOG("trx", "trx_mysql_binlog_offset: " << trx->mysql_log_offset);
@@ -778,13 +733,14 @@ trx_rseg_update_binlog_offset(byte* rseg_header, const trx_t* trx, mtr_t* mtr)
return;
}
- mlog_write_ull(rseg_header + TRX_RSEG_BINLOG_OFFSET,
- trx->mysql_log_offset, mtr);
- byte* p = rseg_header + TRX_RSEG_BINLOG_NAME;
- const byte* binlog_name = reinterpret_cast<const byte*>
- (trx->mysql_log_file_name);
+ mtr->write<8,mtr_t::OPT>(*rseg_header,
+ TRX_RSEG + TRX_RSEG_BINLOG_OFFSET
+ + rseg_header->frame,
+ trx->mysql_log_offset);
- if (memcmp(binlog_name, p, len)) {
- mlog_write_string(p, binlog_name, len, mtr);
+ if (memcmp(trx->mysql_log_file_name, TRX_RSEG + TRX_RSEG_BINLOG_NAME
+ + rseg_header->frame, len)) {
+ mtr->memcpy(rseg_header, TRX_RSEG + TRX_RSEG_BINLOG_NAME,
+ trx->mysql_log_file_name, len);
}
}
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index 4c0ca852aef..aa2fe4bff45 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -147,8 +147,6 @@ trx_sysf_create(
{
ulint slot_no;
buf_block_t* block;
- page_t* page;
- byte* ptr;
ut_ad(mtr);
@@ -167,31 +165,29 @@ trx_sysf_create(
ut_a(block->page.id.page_no() == TRX_SYS_PAGE_NO);
- page = buf_block_get_frame(block);
+ mtr->write<2>(*block, FIL_PAGE_TYPE + block->frame,
+ FIL_PAGE_TYPE_TRX_SYS);
- mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_TRX_SYS,
- MLOG_2BYTES, mtr);
-
- /* Reset the doublewrite buffer magic number to zero so that we
- know that the doublewrite buffer has not yet been created (this
- suppresses a Valgrind warning) */
-
- mlog_write_ulint(page + TRX_SYS_DOUBLEWRITE
- + TRX_SYS_DOUBLEWRITE_MAGIC, 0, MLOG_4BYTES, mtr);
+ ut_ad(!mach_read_from_4(block->frame
+ + TRX_SYS_DOUBLEWRITE
+ + TRX_SYS_DOUBLEWRITE_MAGIC));
/* Reset the rollback segment slots. Old versions of InnoDB
(before MySQL 5.5) define TRX_SYS_N_RSEGS as 256 and expect
that the whole array is initialized. */
- ptr = TRX_SYS + TRX_SYS_RSEGS + page;
compile_time_assert(256 >= TRX_SYS_N_RSEGS);
- memset(ptr, 0xff, 256 * TRX_SYS_RSEG_SLOT_SIZE);
- ptr += 256 * TRX_SYS_RSEG_SLOT_SIZE;
- ut_a(ptr <= page + (srv_page_size - FIL_PAGE_DATA_END));
-
+ compile_time_assert(TRX_SYS + TRX_SYS_RSEGS
+ + 256 * TRX_SYS_RSEG_SLOT_SIZE
+ <= UNIV_PAGE_SIZE_MIN - FIL_PAGE_DATA_END);
+ mtr->memset(block, TRX_SYS + TRX_SYS_RSEGS,
+ 256 * TRX_SYS_RSEG_SLOT_SIZE, 0xff);
/* Initialize all of the page. This part used to be uninitialized. */
- mlog_memset(block, ptr - page,
- srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr),
- 0, mtr);
+ mtr->memset(block, TRX_SYS + TRX_SYS_RSEGS
+ + 256 * TRX_SYS_RSEG_SLOT_SIZE,
+ srv_page_size
+ - (FIL_PAGE_DATA_END + TRX_SYS + TRX_SYS_RSEGS
+ + 256 * TRX_SYS_RSEG_SLOT_SIZE),
+ 0);
/* Create the first rollback segment in the SYSTEM tablespace */
slot_no = trx_sys_rseg_find_free(block);
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index bf26b5b20ef..0f4df89e068 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -565,8 +565,6 @@ trx_resurrect_table_locks(
const trx_undo_t* undo) /*!< in: undo log */
{
mtr_t mtr;
- page_t* undo_page;
- trx_undo_rec_t* undo_rec;
table_id_set tables;
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) ||
@@ -581,11 +579,11 @@ trx_resurrect_table_locks(
/* trx_rseg_mem_create() may have acquired an X-latch on this
page, so we cannot acquire an S-latch. */
- undo_page = trx_undo_page_get(
+ buf_block_t* block = trx_undo_page_get(
page_id_t(trx->rsegs.m_redo.rseg->space->id,
undo->top_page_no), &mtr);
-
- undo_rec = undo_page + undo->top_offset;
+ buf_block_t* undo_block = block;
+ trx_undo_rec_t* undo_rec = block->frame + undo->top_offset;
do {
ulint type;
@@ -594,11 +592,9 @@ trx_resurrect_table_locks(
ulint cmpl_info;
bool updated_extern;
- page_t* undo_rec_page = page_align(undo_rec);
-
- if (undo_rec_page != undo_page) {
- mtr.release_page(undo_page, MTR_MEMO_PAGE_X_FIX);
- undo_page = undo_rec_page;
+ if (undo_block != block) {
+ mtr.memo_release(undo_block, MTR_MEMO_PAGE_X_FIX);
+ undo_block = block;
}
trx_undo_rec_get_pars(
@@ -607,7 +603,7 @@ trx_resurrect_table_locks(
tables.insert(table_id);
undo_rec = trx_undo_get_prev_rec(
- undo_rec, undo->hdr_page_no,
+ block, page_offset(undo_rec), undo->hdr_page_no,
undo->hdr_offset, false, &mtr);
} while (undo_rec);
diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc
index ac61e41da01..bcd21d7f250 100644
--- a/storage/innobase/trx/trx0undo.cc
+++ b/storage/innobase/trx/trx0undo.cc
@@ -105,37 +105,36 @@ trx_undo_mem_create(
trx_id_t trx_id, /*!< in: id of the trx for which the undo log
is created */
const XID* xid, /*!< in: X/Open XA transaction identification*/
- ulint page_no,/*!< in: undo log header page number */
- ulint offset);/*!< in: undo log header byte offset on page */
+ uint32_t page_no,/*!< in: undo log header page number */
+ uint16_t offset);/*!< in: undo log header byte offset on page */
/** Determine the start offset of undo log records of an undo log page.
-@param[in] undo_page undo log page
+@param[in] block undo log page
@param[in] page_no undo log header page number
@param[in] offset undo log header offset
@return start offset */
static
-uint16_t
-trx_undo_page_get_start(const page_t* undo_page, ulint page_no, ulint offset)
+uint16_t trx_undo_page_get_start(const buf_block_t *block, uint32_t page_no,
+ uint16_t offset)
{
- return page_no == page_get_page_no(undo_page)
- ? mach_read_from_2(offset + TRX_UNDO_LOG_START + undo_page)
- : TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE;
+ return page_no == block->page.id.page_no()
+ ? mach_read_from_2(offset + TRX_UNDO_LOG_START + block->frame)
+ : TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE;
}
/** Get the first undo log record on a page.
-@param[in] page undo log page
+@param[in] block undo log page
@param[in] page_no undo log header page number
@param[in] offset undo log header page offset
@return pointer to first record
@retval NULL if none exists */
-static
-trx_undo_rec_t*
-trx_undo_page_get_first_rec(page_t* page, ulint page_no, ulint offset)
+static trx_undo_rec_t*
+trx_undo_page_get_first_rec(const buf_block_t *block, uint32_t page_no,
+ uint16_t offset)
{
- ulint start = trx_undo_page_get_start(page, page_no, offset);
- return start == trx_undo_page_get_end(page, page_no, offset)
- ? NULL
- : page + start;
+ uint16_t start= trx_undo_page_get_start(block, page_no, offset);
+ return start == trx_undo_page_get_end(block, page_no, offset)
+ ? nullptr : block->frame + start;
}
/** Get the last undo log record on a page.
@@ -146,58 +145,43 @@ trx_undo_page_get_first_rec(page_t* page, ulint page_no, ulint offset)
@retval NULL if none exists */
static
trx_undo_rec_t*
-trx_undo_page_get_last_rec(page_t* page, ulint page_no, ulint offset)
+trx_undo_page_get_last_rec(const buf_block_t *block, uint32_t page_no,
+ uint16_t offset)
{
- ulint end = trx_undo_page_get_end(page, page_no, offset);
-
- return trx_undo_page_get_start(page, page_no, offset) == end
- ? NULL
- : page + mach_read_from_2(page + end - 2);
+ uint16_t end= trx_undo_page_get_end(block, page_no, offset);
+ return trx_undo_page_get_start(block, page_no, offset) == end
+ ? nullptr : block->frame + mach_read_from_2(block->frame + end - 2);
}
-/***********************************************************************//**
-Gets the previous record in an undo log from the previous page.
-@return undo log record, the page s-latched, NULL if none */
-static
-trx_undo_rec_t*
-trx_undo_get_prev_rec_from_prev_page(
-/*=================================*/
- trx_undo_rec_t* rec, /*!< in: undo record */
- ulint page_no,/*!< in: undo log header page number */
- ulint offset, /*!< in: undo log header offset on page */
- bool shared, /*!< in: true=S-latch, false=X-latch */
- mtr_t* mtr) /*!< in: mtr */
+/** Get the previous record in an undo log from the previous page.
+@param[in,out] block undo log page
+@param[in] rec undo record offset in the page
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@param[in] shared latching mode: true=RW_S_LATCH, false=RW_X_LATCH
+@param[in,out] mtr mini-transaction
+@return undo log record, the page latched, NULL if none */
+static trx_undo_rec_t*
+trx_undo_get_prev_rec_from_prev_page(buf_block_t *&block, uint16_t rec,
+ uint32_t page_no, uint16_t offset,
+ bool shared, mtr_t *mtr)
{
- ulint space;
- ulint prev_page_no;
- page_t* prev_page;
- page_t* undo_page;
+ uint32_t prev_page_no= flst_get_prev_addr(TRX_UNDO_PAGE_HDR +
+ TRX_UNDO_PAGE_NODE +
+ block->frame).page;
- undo_page = page_align(rec);
+ if (prev_page_no == FIL_NULL)
+ return NULL;
- prev_page_no = flst_get_prev_addr(undo_page + TRX_UNDO_PAGE_HDR
- + TRX_UNDO_PAGE_NODE)
- .page;
+ block = buf_page_get(page_id_t(block->page.id.space(), prev_page_no),
+ 0, shared ? RW_S_LATCH : RW_X_LATCH, mtr);
+ buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
- if (prev_page_no == FIL_NULL) {
-
- return(NULL);
- }
-
- space = page_get_space_id(undo_page);
-
- buf_block_t* block = buf_page_get(
- page_id_t(space, prev_page_no), 0,
- shared ? RW_S_LATCH : RW_X_LATCH, mtr);
-
- buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
-
- prev_page = buf_block_get_frame(block);
-
- return(trx_undo_page_get_last_rec(prev_page, page_no, offset));
+ return trx_undo_page_get_last_rec(block, page_no, offset);
}
/** Get the previous undo log record.
+@param[in] block undo log page
@param[in] rec undo log record
@param[in] page_no undo log header page number
@param[in] offset undo log header page offset
@@ -205,169 +189,105 @@ trx_undo_get_prev_rec_from_prev_page(
@retval NULL if none */
static
trx_undo_rec_t*
-trx_undo_page_get_prev_rec(trx_undo_rec_t* rec, ulint page_no, ulint offset)
+trx_undo_page_get_prev_rec(const buf_block_t *block, trx_undo_rec_t *rec,
+ uint32_t page_no, uint16_t offset)
{
- page_t* undo_page;
- ulint start;
-
- undo_page = (page_t*) ut_align_down(rec, srv_page_size);
-
- start = trx_undo_page_get_start(undo_page, page_no, offset);
-
- if (start + undo_page == rec) {
-
- return(NULL);
- }
-
- return(undo_page + mach_read_from_2(rec - 2));
+ ut_ad(block->frame == page_align(rec));
+ return rec == block->frame + trx_undo_page_get_start(block, page_no, offset)
+ ? nullptr
+ : block->frame + mach_read_from_2(rec - 2);
}
-/***********************************************************************//**
-Gets the previous record in an undo log.
-@return undo log record, the page s-latched, NULL if none */
+/** Get the previous record in an undo log.
+@param[in,out] block undo log page
+@param[in] rec undo record offset in the page
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@param[in] shared latching mode: true=RW_S_LATCH, false=RW_X_LATCH
+@param[in,out] mtr mini-transaction
+@return undo log record, the page latched, NULL if none */
trx_undo_rec_t*
-trx_undo_get_prev_rec(
-/*==================*/
- trx_undo_rec_t* rec, /*!< in: undo record */
- ulint page_no,/*!< in: undo log header page number */
- ulint offset, /*!< in: undo log header offset on page */
- bool shared, /*!< in: true=S-latch, false=X-latch */
- mtr_t* mtr) /*!< in: mtr */
+trx_undo_get_prev_rec(buf_block_t *&block, uint16_t rec, uint32_t page_no,
+ uint16_t offset, bool shared, mtr_t *mtr)
{
- trx_undo_rec_t* prev_rec;
-
- prev_rec = trx_undo_page_get_prev_rec(rec, page_no, offset);
+ if (trx_undo_rec_t *prev= trx_undo_page_get_prev_rec(block,
+ block->frame + rec,
+ page_no, offset))
+ return prev;
- if (prev_rec) {
-
- return(prev_rec);
- }
+ /* We have to go to the previous undo log page to look for the
+ previous record */
- /* We have to go to the previous undo log page to look for the
- previous record */
-
- return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset,
- shared, mtr));
+ return trx_undo_get_prev_rec_from_prev_page(block, rec, page_no, offset,
+ shared, mtr);
}
-/** Gets the next record in an undo log from the next page.
-@param[in] space undo log header space
-@param[in] undo_page undo log page
-@param[in] page_no undo log header page number
-@param[in] offset undo log header offset on page
-@param[in] mode latch mode: RW_S_LATCH or RW_X_LATCH
-@param[in,out] mtr mini-transaction
+/** Get the next record in an undo log from the next page.
+@param[in,out] block undo log page
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@param[in] mode latching mode: RW_S_LATCH or RW_X_LATCH
+@param[in,out] mtr mini-transaction
@return undo log record, the page latched, NULL if none */
-static
-trx_undo_rec_t*
-trx_undo_get_next_rec_from_next_page(
- ulint space,
- const page_t* undo_page,
- ulint page_no,
- ulint offset,
- ulint mode,
- mtr_t* mtr)
+static trx_undo_rec_t*
+trx_undo_get_next_rec_from_next_page(buf_block_t *&block, uint32_t page_no,
+ uint16_t offset, ulint mode, mtr_t *mtr)
{
- const trx_ulogf_t* log_hdr;
- ulint next_page_no;
- page_t* next_page;
- ulint next;
-
- if (page_no == page_get_page_no(undo_page)) {
-
- log_hdr = undo_page + offset;
- next = mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG);
-
- if (next != 0) {
-
- return(NULL);
- }
- }
-
- next_page_no = flst_get_next_addr(TRX_UNDO_PAGE_HDR
- + TRX_UNDO_PAGE_NODE + undo_page)
- .page;
- if (next_page_no == FIL_NULL) {
-
- return(NULL);
- }
+ if (page_no == block->page.id.page_no() &&
+ mach_read_from_2(block->frame + offset + TRX_UNDO_NEXT_LOG))
+ return NULL;
- const page_id_t next_page_id(space, next_page_no);
+ ulint next= flst_get_next_addr(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE +
+ block->frame).page;
+ if (next == FIL_NULL)
+ return NULL;
- if (mode == RW_S_LATCH) {
- next_page = trx_undo_page_get_s_latched(
- next_page_id, mtr);
- } else {
- ut_ad(mode == RW_X_LATCH);
- next_page = trx_undo_page_get(next_page_id, mtr);
- }
+ block= buf_page_get(page_id_t(block->page.id.space(), next), 0, mode, mtr);
+ buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
- return(trx_undo_page_get_first_rec(next_page, page_no, offset));
+ return trx_undo_page_get_first_rec(block, page_no, offset);
}
-/***********************************************************************//**
-Gets the next record in an undo log.
-@return undo log record, the page s-latched, NULL if none */
+/** Get the next record in an undo log.
+@param[in,out] block undo log page
+@param[in] rec undo record offset in the page
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@param[in,out] mtr mini-transaction
+@return undo log record, the page latched, NULL if none */
trx_undo_rec_t*
-trx_undo_get_next_rec(
-/*==================*/
- trx_undo_rec_t* rec, /*!< in: undo record */
- ulint page_no,/*!< in: undo log header page number */
- ulint offset, /*!< in: undo log header offset on page */
- mtr_t* mtr) /*!< in: mtr */
+trx_undo_get_next_rec(buf_block_t *&block, uint16_t rec, uint32_t page_no,
+ uint16_t offset, mtr_t *mtr)
{
- ulint space;
- trx_undo_rec_t* next_rec;
+ if (trx_undo_rec_t *next= trx_undo_page_get_next_rec(block, rec, page_no,
+ offset))
+ return next;
- next_rec = trx_undo_page_get_next_rec(rec, page_no, offset);
-
- if (next_rec) {
- return(next_rec);
- }
-
- space = page_get_space_id(page_align(rec));
-
- return(trx_undo_get_next_rec_from_next_page(space,
- page_align(rec),
- page_no, offset,
- RW_S_LATCH, mtr));
+ return trx_undo_get_next_rec_from_next_page(block, page_no, offset,
+ RW_S_LATCH, mtr);
}
-/** Gets the first record in an undo log.
-@param[in] space undo log header space
-@param[in] page_no undo log header page number
-@param[in] offset undo log header offset on page
-@param[in] mode latching mode: RW_S_LATCH or RW_X_LATCH
-@param[in,out] mtr mini-transaction
+/** Get the first record in an undo log.
+@param[in] space undo log header space
+@param[in] page_no undo log header page number
+@param[in] offset undo log header offset on page
+@param[in] mode latching mode: RW_S_LATCH or RW_X_LATCH
+@param[out] block undo log page
+@param[in,out] mtr mini-transaction
@return undo log record, the page latched, NULL if none */
trx_undo_rec_t*
-trx_undo_get_first_rec(
- fil_space_t* space,
- ulint page_no,
- ulint offset,
- ulint mode,
- mtr_t* mtr)
+trx_undo_get_first_rec(const fil_space_t &space, uint32_t page_no,
+ uint16_t offset, ulint mode, buf_block_t*& block,
+ mtr_t *mtr)
{
- page_t* undo_page;
- trx_undo_rec_t* rec;
-
- const page_id_t page_id(space->id, page_no);
-
- if (mode == RW_S_LATCH) {
- undo_page = trx_undo_page_get_s_latched(page_id, mtr);
- } else {
- undo_page = trx_undo_page_get(page_id, mtr);
- }
-
- rec = trx_undo_page_get_first_rec(undo_page, page_no, offset);
+ block = buf_page_get(page_id_t(space.id, page_no), 0, mode, mtr);
+ buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
- if (rec) {
- return(rec);
- }
+ if (trx_undo_rec_t *rec= trx_undo_page_get_first_rec(block, page_no, offset))
+ return rec;
- return(trx_undo_get_next_rec_from_next_page(space->id,
- undo_page, page_no, offset,
- mode, mtr));
+ return trx_undo_get_next_rec_from_next_page(block, page_no, offset, mode,
+ mtr);
}
/*============== UNDO LOG FILE COPY CREATION AND FREEING ==================*/
@@ -455,9 +375,9 @@ trx_undo_parse_page_header_reuse(
}
/** Initialize the fields in an undo log segment page.
-@param[in,out] undo_block undo page
+@param[in,out] undo_block undo log segment page
@param[in,out] mtr mini-transaction */
-static void trx_undo_page_init(buf_block_t* undo_block, mtr_t* mtr)
+static void trx_undo_page_init(const buf_block_t *undo_block, mtr_t *mtr)
{
page_t* page = undo_block->frame;
mach_write_to_2(FIL_PAGE_TYPE + page, FIL_PAGE_UNDO_LOG);
@@ -489,6 +409,26 @@ static void trx_undo_page_init(buf_block_t* undo_block, mtr_t* mtr)
mlog_close(mtr, log_ptr);
}
+/** Look for a free slot for an undo log segment.
+@param rseg_header rollback segment header
+@return slot index
+@retval ULINT_UNDEFINED if not found */
+static ulint trx_rsegf_undo_find_free(const buf_block_t *rseg_header)
+{
+ ulint max_slots= TRX_RSEG_N_SLOTS;
+
+#ifdef UNIV_DEBUG
+ if (trx_rseg_n_slots_debug)
+ max_slots= std::min<ulint>(trx_rseg_n_slots_debug, TRX_RSEG_N_SLOTS);
+#endif
+
+ for (ulint i= 0; i < max_slots; i++)
+ if (trx_rsegf_get_nth_undo(rseg_header, i) == FIL_NULL)
+ return i;
+
+ return ULINT_UNDEFINED;
+}
+
/** Create an undo log segment.
@param[in,out] space tablespace
@param[in,out] rseg_hdr rollback segment header (x-latched)
@@ -499,15 +439,14 @@ static void trx_undo_page_init(buf_block_t* undo_block, mtr_t* mtr)
@retval NULL on failure */
static MY_ATTRIBUTE((nonnull, warn_unused_result))
buf_block_t*
-trx_undo_seg_create(fil_space_t* space, trx_rsegf_t* rseg_hdr, ulint* id,
- dberr_t* err, mtr_t* mtr)
+trx_undo_seg_create(fil_space_t *space, buf_block_t *rseg_hdr, ulint *id,
+ dberr_t *err, mtr_t *mtr)
{
- ulint slot_no;
buf_block_t* block;
ulint n_reserved;
bool success;
- slot_no = trx_rsegf_undo_find_free(rseg_hdr);
+ const ulint slot_no = trx_rsegf_undo_find_free(rseg_hdr);
if (slot_no == ULINT_UNDEFINED) {
ib::warn() << "Cannot find a free slot for an undo log. Do"
@@ -518,6 +457,8 @@ trx_undo_seg_create(fil_space_t* space, trx_rsegf_t* rseg_hdr, ulint* id,
return NULL;
}
+ ut_ad(slot_no < TRX_RSEG_N_SLOTS);
+
success = fsp_reserve_free_extents(&n_reserved, space, 2, FSP_UNDO,
mtr);
if (!success) {
@@ -540,22 +481,22 @@ trx_undo_seg_create(fil_space_t* space, trx_rsegf_t* rseg_hdr, ulint* id,
trx_undo_page_init(block, mtr);
- mlog_write_ulint(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE + block->frame,
- TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE,
- MLOG_2BYTES, mtr);
-
- mlog_write_ulint(TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG + block->frame,
- 0, MLOG_2BYTES, mtr);
+ mtr->write<2,mtr_t::OPT>(*block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
+ + block->frame,
+ TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE);
+ mtr->write<2,mtr_t::OPT>(*block, TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG
+ + block->frame, 0U);
- flst_init(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + block->frame, mtr);
+ flst_init(*block, TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + block->frame,
+ mtr);
- flst_add_last(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + block->frame,
- TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + block->frame,
- mtr);
+ flst_add_last(block, TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST,
+ block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr);
*id = slot_no;
- trx_rsegf_set_nth_undo(rseg_hdr, slot_no, block->page.id.page_no(),
- mtr);
+ mtr->write<4>(*rseg_hdr, TRX_RSEG + TRX_RSEG_UNDO_SLOTS
+ + slot_no * TRX_RSEG_SLOT_SIZE + rseg_hdr->frame,
+ block->page.id.page_no());
MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED);
@@ -563,77 +504,43 @@ trx_undo_seg_create(fil_space_t* space, trx_rsegf_t* rseg_hdr, ulint* id,
return block;
}
-/**********************************************************************//**
-Writes the mtr log entry of an undo log header initialization. */
-UNIV_INLINE
-void
-trx_undo_header_create_log(
-/*=======================*/
- const page_t* undo_page, /*!< in: undo log header page */
- trx_id_t trx_id, /*!< in: transaction id */
- mtr_t* mtr) /*!< in: mtr */
-{
- mlog_write_initial_log_record(undo_page, MLOG_UNDO_HDR_CREATE, mtr);
-
- mlog_catenate_ull_compressed(mtr, trx_id);
-}
-
/***************************************************************//**
Creates a new undo log header in file. NOTE that this function has its own
log record type MLOG_UNDO_HDR_CREATE. You must NOT change the operation of
this function!
+@param[in,out] undo_page undo log segment header page
+@param[in] trx_id transaction identifier
+@param[in,out] mtr mini-transaction
@return header byte offset on page */
-static
-ulint
-trx_undo_header_create(
-/*===================*/
- page_t* undo_page, /*!< in/out: undo log segment
- header page, x-latched; it is
- assumed that there is
- TRX_UNDO_LOG_XA_HDR_SIZE bytes
- free space on it */
- trx_id_t trx_id, /*!< in: transaction id */
- mtr_t* mtr) /*!< in: mtr */
+static uint16_t trx_undo_header_create(buf_block_t *undo_page, trx_id_t trx_id,
+ mtr_t* mtr)
{
- trx_upagef_t* page_hdr;
- trx_usegf_t* seg_hdr;
- trx_ulogf_t* log_hdr;
- ulint prev_log;
- ulint free;
- ulint new_free;
-
- ut_ad(mtr && undo_page);
-
- page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
- seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
-
- free = mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE);
-
- log_hdr = undo_page + free;
-
- new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
+ byte* page_free = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
+ + undo_page->frame;
+ uint16_t free = mach_read_from_2(page_free);
+ uint16_t new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < srv_page_size - 100);
- mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free);
-
- mach_write_to_2(page_hdr + TRX_UNDO_PAGE_FREE, new_free);
+ mach_write_to_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_START
+ + undo_page->frame, new_free);
+ mach_write_to_2(page_free, new_free);
- mach_write_to_2(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_ACTIVE);
+ mach_write_to_2(TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + undo_page->frame,
+ TRX_UNDO_ACTIVE);
+ byte* last_log = TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG
+ + undo_page->frame;
- prev_log = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG);
+ uint16_t prev_log = mach_read_from_2(last_log);
if (prev_log != 0) {
- trx_ulogf_t* prev_log_hdr;
-
- prev_log_hdr = undo_page + prev_log;
-
- mach_write_to_2(prev_log_hdr + TRX_UNDO_NEXT_LOG, free);
+ mach_write_to_2(prev_log + TRX_UNDO_NEXT_LOG + undo_page->frame,
+ free);
}
- mach_write_to_2(seg_hdr + TRX_UNDO_LAST_LOG, free);
+ mach_write_to_2(last_log, free);
- log_hdr = undo_page + free;
+ trx_ulogf_t* log_hdr = undo_page->frame + free;
mach_write_to_2(log_hdr + TRX_UNDO_NEEDS_PURGE, 1);
@@ -647,45 +554,53 @@ trx_undo_header_create(
mach_write_to_2(log_hdr + TRX_UNDO_PREV_LOG, prev_log);
/* Write the log record about the header creation */
- trx_undo_header_create_log(undo_page, trx_id, mtr);
+ mtr->set_modified();
+ if (mtr->get_log_mode() != MTR_LOG_ALL) {
+ ut_ad(mtr->get_log_mode() == MTR_LOG_NONE
+ || mtr->get_log_mode() == MTR_LOG_NO_REDO);
+ return free;
+ }
+
+ byte* log_ptr = mtr->get_log()->open(11 + 15);
+ log_ptr = mlog_write_initial_log_record_low(
+ MLOG_UNDO_HDR_CREATE,
+ undo_page->page.id.space(),
+ undo_page->page.id.page_no(),
+ log_ptr, mtr);
+ log_ptr += mach_u64_write_compressed(log_ptr, trx_id);
+ mlog_close(mtr, log_ptr);
return(free);
}
-/********************************************************************//**
-Write X/Open XA Transaction Identification (XID) to undo log header */
-static
-void
-trx_undo_write_xid(
-/*===============*/
- trx_ulogf_t* log_hdr,/*!< in: undo log header */
- const XID* xid, /*!< in: X/Open XA Transaction Identification */
- mtr_t* mtr) /*!< in: mtr */
+/** Write X/Open XA Transaction Identifier (XID) to undo log header
+@param[in,out] block undo header page
+@param[in] offset undo header record offset
+@param[in] xid distributed transaction identifier
+@param[in,out] mtr mini-transaction */
+static void trx_undo_write_xid(buf_block_t *block, uint16_t offset,
+ const XID &xid, mtr_t *mtr)
{
- DBUG_ASSERT(xid->gtrid_length >= 0);
- DBUG_ASSERT(xid->bqual_length >= 0);
- DBUG_ASSERT(xid->gtrid_length + xid->bqual_length < XIDDATASIZE);
-
- mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT,
- static_cast<ulint>(xid->formatID),
- MLOG_4BYTES, mtr);
-
- mlog_write_ulint(log_hdr + TRX_UNDO_XA_TRID_LEN,
- static_cast<ulint>(xid->gtrid_length),
- MLOG_4BYTES, mtr);
-
- mlog_write_ulint(log_hdr + TRX_UNDO_XA_BQUAL_LEN,
- static_cast<ulint>(xid->bqual_length),
- MLOG_4BYTES, mtr);
- const ulint xid_length = static_cast<ulint>(xid->gtrid_length
- + xid->bqual_length);
- mlog_write_string(log_hdr + TRX_UNDO_XA_XID,
- reinterpret_cast<const byte*>(xid->data),
- xid_length, mtr);
- if (UNIV_LIKELY(xid_length < XIDDATASIZE)) {
- mlog_memset(log_hdr + TRX_UNDO_XA_XID + xid_length,
- XIDDATASIZE - xid_length, 0, mtr);
- }
+ DBUG_ASSERT(xid.gtrid_length >= 0);
+ DBUG_ASSERT(xid.bqual_length >= 0);
+ DBUG_ASSERT(xid.gtrid_length + xid.bqual_length < XIDDATASIZE);
+ DBUG_ASSERT(mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG +
+ block->frame) == offset);
+
+ trx_ulogf_t* log_hdr= block->frame + offset;
+
+ mtr->write<4,mtr_t::OPT>(*block, log_hdr + TRX_UNDO_XA_FORMAT,
+ static_cast<uint32_t>(xid.formatID));
+ mtr->write<4,mtr_t::OPT>(*block, log_hdr + TRX_UNDO_XA_TRID_LEN,
+ static_cast<uint32_t>(xid.gtrid_length));
+ mtr->write<4,mtr_t::OPT>(*block, log_hdr + TRX_UNDO_XA_BQUAL_LEN,
+ static_cast<uint32_t>(xid.bqual_length));
+ const ulint xid_length= static_cast<ulint>(xid.gtrid_length
+ + xid.bqual_length);
+ mtr->memcpy(block, offset + TRX_UNDO_XA_XID, xid.data, xid_length);
+ if (UNIV_LIKELY(xid_length < XIDDATASIZE))
+ mtr->memset(block, offset + TRX_UNDO_XA_XID + xid_length,
+ XIDDATASIZE - xid_length, 0);
}
/********************************************************************//**
@@ -706,65 +621,50 @@ trx_undo_read_xid(const trx_ulogf_t* log_hdr, XID* xid)
memcpy(xid->data, log_hdr + TRX_UNDO_XA_XID, XIDDATASIZE);
}
-/***************************************************************//**
-Adds space for the XA XID after an undo log old-style header. */
-static
-void
-trx_undo_header_add_space_for_xid(
-/*==============================*/
- page_t* undo_page,/*!< in: undo log segment header page */
- trx_ulogf_t* log_hdr,/*!< in: undo log header */
- mtr_t* mtr) /*!< in: mtr */
+/** Add space for the XA XID after an undo log old-style header.
+@param[in,out] block undo page
+@param[in] offset offset of the undo log header
+@param[in,out] mtr mini-transaction */
+static void trx_undo_header_add_space_for_xid(buf_block_t *block, ulint offset,
+ mtr_t *mtr)
{
- trx_upagef_t* page_hdr;
- ulint free;
- ulint new_free;
-
- page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
-
- free = mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE);
-
- /* free is now the end offset of the old style undo log header */
-
- ut_a(free == (ulint)(log_hdr - undo_page) + TRX_UNDO_LOG_OLD_HDR_SIZE);
-
- new_free = free + (TRX_UNDO_LOG_XA_HDR_SIZE
- - TRX_UNDO_LOG_OLD_HDR_SIZE);
-
- /* Add space for a XID after the header, update the free offset
- fields on the undo log page and in the undo log header */
-
- mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_START, new_free,
- MLOG_2BYTES, mtr);
-
- mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_FREE, new_free,
- MLOG_2BYTES, mtr);
-
- mlog_write_ulint(log_hdr + TRX_UNDO_LOG_START, new_free,
- MLOG_2BYTES, mtr);
+ uint16_t free= mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE +
+ block->frame);
+ /* free is now the end offset of the old style undo log header */
+ ut_a(free == offset + TRX_UNDO_LOG_OLD_HDR_SIZE);
+ free += TRX_UNDO_LOG_XA_HDR_SIZE - TRX_UNDO_LOG_OLD_HDR_SIZE;
+ /* Add space for a XID after the header, update the free offset
+ fields on the undo log page and in the undo log header */
+
+ mtr->write<2>(*block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_START + block->frame,
+ free);
+ /* MDEV-12353 TODO: use MEMMOVE record */
+ mtr->write<2>(*block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE + block->frame,
+ free);
+ mtr->write<2>(*block, offset + TRX_UNDO_LOG_START + block->frame, free);
}
/** Parse the redo log entry of an undo log page header create.
@param[in] ptr redo log record
@param[in] end_ptr end of log buffer
-@param[in,out] page page frame or NULL
+@param[in,out] block page frame or NULL
@param[in,out] mtr mini-transaction or NULL
@return end of log record or NULL */
byte*
trx_undo_parse_page_header(
const byte* ptr,
const byte* end_ptr,
- page_t* page,
+ buf_block_t* block,
mtr_t* mtr)
{
trx_id_t trx_id = mach_u64_parse_compressed(&ptr, end_ptr);
- if (ptr != NULL && page != NULL) {
- trx_undo_header_create(page, trx_id, mtr);
- return(const_cast<byte*>(ptr));
+ if (ptr && block) {
+ trx_undo_header_create(block, trx_id, mtr);
+
}
- return(const_cast<byte*>(ptr));
+ return const_cast<byte*>(ptr);
}
/** Allocate an undo log page.
@@ -777,7 +677,6 @@ buf_block_t* trx_undo_add_page(trx_undo_t* undo, mtr_t* mtr)
trx_rseg_t* rseg = undo->rseg;
buf_block_t* new_block = NULL;
ulint n_reserved;
- page_t* header_page;
/* When we add a page to an undo log, this is analogous to
a pessimistic insert in a B-tree, and we must reserve the
@@ -785,7 +684,7 @@ buf_block_t* trx_undo_add_page(trx_undo_t* undo, mtr_t* mtr)
mutex_enter(&rseg->mutex);
- header_page = trx_undo_page_get(
+ buf_block_t* header_block = trx_undo_page_get(
page_id_t(undo->rseg->space->id, undo->hdr_page_no), mtr);
if (!fsp_reserve_free_extents(&n_reserved, undo->rseg->space, 1,
@@ -795,7 +694,7 @@ buf_block_t* trx_undo_add_page(trx_undo_t* undo, mtr_t* mtr)
new_block = fseg_alloc_free_page_general(
TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
- + header_page,
+ + header_block->frame,
undo->top_page_no + 1, FSP_UP, TRUE, mtr, mtr);
rseg->space->release_free_extents(n_reserved);
@@ -810,11 +709,8 @@ buf_block_t* trx_undo_add_page(trx_undo_t* undo, mtr_t* mtr)
trx_undo_page_init(new_block, mtr);
- flst_add_last(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST
- + header_page,
- TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE
- + new_block->frame,
- mtr);
+ flst_add_last(header_block, TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST,
+ new_block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr);
undo->size++;
rseg->curr_size++;
@@ -827,14 +723,14 @@ func_exit:
Frees an undo log page that is not the header page.
@return last page number in remaining log */
static
-ulint
+uint32_t
trx_undo_free_page(
/*===============*/
trx_rseg_t* rseg, /*!< in: rollback segment */
bool in_history, /*!< in: TRUE if the undo log is in the history
list */
- ulint hdr_page_no, /*!< in: header page number */
- ulint page_no, /*!< in: page number to free: must not be the
+ uint32_t hdr_page_no, /*!< in: header page number */
+ uint32_t page_no, /*!< in: page number to free: must not be the
header page */
mtr_t* mtr) /*!< in: mtr which does not have a latch to any
undo log page; the caller must have reserved
@@ -845,28 +741,31 @@ trx_undo_free_page(
ut_a(hdr_page_no != page_no);
ut_ad(mutex_own(&(rseg->mutex)));
- page_t* undo_page = trx_undo_page_get(page_id_t(space, page_no), mtr);
- page_t* header_page = trx_undo_page_get(page_id_t(space, hdr_page_no),
- mtr);
+ buf_block_t* undo_block = trx_undo_page_get(page_id_t(space, page_no),
+ mtr);
+ buf_block_t* header_block = trx_undo_page_get(page_id_t(space,
+ hdr_page_no),
+ mtr);
- flst_remove(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_page,
- TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + undo_page, mtr);
+ flst_remove(header_block, TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST,
+ undo_block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr);
- fseg_free_page(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + header_page,
+ fseg_free_page(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
+ + header_block->frame,
rseg->space, page_no, false, true, mtr);
const fil_addr_t last_addr = flst_get_last(
- TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_page);
+ TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_block->frame);
rseg->curr_size--;
if (in_history) {
- trx_rsegf_t* rseg_header = trx_rsegf_get(
+ buf_block_t* rseg_header = trx_rsegf_get(
rseg->space, rseg->page_no, mtr);
- uint32_t hist_size = mach_read_from_4(
- rseg_header + TRX_RSEG_HISTORY_SIZE);
+ byte* rseg_hist_size = TRX_RSEG + TRX_RSEG_HISTORY_SIZE
+ + rseg_header->frame;
+ uint32_t hist_size = mach_read_from_4(rseg_hist_size);
ut_ad(hist_size > 0);
- mlog_write_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
- hist_size - 1, MLOG_4BYTES, mtr);
+ mtr->write<4>(*rseg_header, rseg_hist_size, hist_size - 1);
}
return(last_addr.page);
@@ -905,11 +804,11 @@ void trx_undo_truncate_end(trx_undo_t& undo, undo_no_t limit, bool is_temp)
trx_undo_rec_t* trunc_here = NULL;
mutex_enter(&undo.rseg->mutex);
- page_t* undo_page = trx_undo_page_get(
+ buf_block_t* undo_block = trx_undo_page_get(
page_id_t(undo.rseg->space->id, undo.last_page_no),
&mtr);
trx_undo_rec_t* rec = trx_undo_page_get_last_rec(
- undo_page, undo.hdr_page_no, undo.hdr_offset);
+ undo_block, undo.hdr_page_no, undo.hdr_offset);
while (rec) {
if (trx_undo_rec_get_undo_no(rec) < limit) {
goto func_exit;
@@ -917,7 +816,7 @@ void trx_undo_truncate_end(trx_undo_t& undo, undo_no_t limit, bool is_temp)
/* Truncate at least this record off, maybe more */
trunc_here = rec;
- rec = trx_undo_page_get_prev_rec(rec,
+ rec = trx_undo_page_get_prev_rec(undo_block, rec,
undo.hdr_page_no,
undo.hdr_offset);
}
@@ -933,10 +832,10 @@ func_exit:
mutex_exit(&undo.rseg->mutex);
if (trunc_here) {
- mlog_write_ulint(undo_page + TRX_UNDO_PAGE_HDR
- + TRX_UNDO_PAGE_FREE,
- ulint(trunc_here - undo_page),
- MLOG_2BYTES, &mtr);
+ mtr.write<2>(*undo_block,
+ TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
+ + undo_block->frame,
+ ulint(trunc_here - undo_block->frame));
}
mtr.commit();
@@ -955,14 +854,12 @@ freed, but emptied, if all the records there are below the limit.
void
trx_undo_truncate_start(
trx_rseg_t* rseg,
- ulint hdr_page_no,
- ulint hdr_offset,
+ uint32_t hdr_page_no,
+ uint16_t hdr_offset,
undo_no_t limit)
{
- page_t* undo_page;
trx_undo_rec_t* rec;
trx_undo_rec_t* last_rec;
- ulint page_no;
mtr_t mtr;
ut_ad(mutex_own(&(rseg->mutex)));
@@ -977,42 +874,36 @@ loop:
mtr.set_log_mode(MTR_LOG_NO_REDO);
}
- rec = trx_undo_get_first_rec(rseg->space, hdr_page_no, hdr_offset,
- RW_X_LATCH, &mtr);
+ buf_block_t* undo_page;
+ rec = trx_undo_get_first_rec(*rseg->space, hdr_page_no, hdr_offset,
+ RW_X_LATCH, undo_page, &mtr);
if (rec == NULL) {
/* Already empty */
-
- mtr_commit(&mtr);
-
+done:
+ mtr.commit();
return;
}
- undo_page = page_align(rec);
-
last_rec = trx_undo_page_get_last_rec(undo_page, hdr_page_no,
hdr_offset);
if (trx_undo_rec_get_undo_no(last_rec) >= limit) {
-
- mtr_commit(&mtr);
-
- return;
+ goto done;
}
- page_no = page_get_page_no(undo_page);
-
- if (page_no == hdr_page_no) {
+ if (undo_page->page.id.page_no() == hdr_page_no) {
uint16_t end = mach_read_from_2(hdr_offset + TRX_UNDO_NEXT_LOG
- + undo_page);
+ + undo_page->frame);
if (end == 0) {
end = mach_read_from_2(TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_FREE
- + undo_page);
+ + undo_page->frame);
}
- mlog_write_ulint(undo_page + hdr_offset + TRX_UNDO_LOG_START,
- end, MLOG_2BYTES, &mtr);
+ mtr.write<2>(*undo_page, undo_page->frame + hdr_offset
+ + TRX_UNDO_LOG_START, end);
} else {
- trx_undo_free_page(rseg, true, hdr_page_no, page_no, &mtr);
+ trx_undo_free_page(rseg, true, hdr_page_no,
+ undo_page->page.id.page_no(), &mtr);
}
mtr_commit(&mtr);
@@ -1023,52 +914,43 @@ loop:
/** Frees an undo log segment which is not in the history list.
@param[in] undo undo log
@param[in] noredo whether the undo tablespace is redo logged */
-static
-void
-trx_undo_seg_free(
- const trx_undo_t* undo,
- bool noredo)
+static void trx_undo_seg_free(const trx_undo_t* undo, bool noredo)
{
- trx_rseg_t* rseg;
- fseg_header_t* file_seg;
- trx_rsegf_t* rseg_header;
- trx_usegf_t* seg_header;
- ibool finished;
- mtr_t mtr;
+ ut_ad(undo->id < TRX_RSEG_N_SLOTS);
- rseg = undo->rseg;
+ trx_rseg_t* const rseg = undo->rseg;
+ bool finished;
+ mtr_t mtr;
do {
-
- mtr_start(&mtr);
+ mtr.start();
if (noredo) {
mtr.set_log_mode(MTR_LOG_NO_REDO);
}
- mutex_enter(&(rseg->mutex));
+ mutex_enter(&rseg->mutex);
- seg_header = trx_undo_page_get(page_id_t(undo->rseg->space->id,
- undo->hdr_page_no),
- &mtr)
- + TRX_UNDO_SEG_HDR;
+ buf_block_t* block = trx_undo_page_get(
+ page_id_t(rseg->space->id, undo->hdr_page_no), &mtr);
- file_seg = seg_header + TRX_UNDO_FSEG_HEADER;
+ fseg_header_t* file_seg = TRX_UNDO_SEG_HDR
+ + TRX_UNDO_FSEG_HEADER + block->frame;
finished = fseg_free_step(file_seg, false, &mtr);
if (finished) {
/* Update the rseg header */
- rseg_header = trx_rsegf_get(
+ buf_block_t* rseg_header = trx_rsegf_get(
rseg->space, rseg->page_no, &mtr);
- trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL,
- &mtr);
-
+ compile_time_assert(FIL_NULL == 0xffffffff);
+ mtr.memset(rseg_header, TRX_RSEG + TRX_RSEG_UNDO_SLOTS
+ + undo->id * TRX_RSEG_SLOT_SIZE, 4, 0xff);
MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_USED);
}
- mutex_exit(&(rseg->mutex));
- mtr_commit(&mtr);
+ mutex_exit(&rseg->mutex);
+ mtr.commit();
} while (!finished);
}
@@ -1080,9 +962,9 @@ trx_undo_seg_free(
@param[in] page_no undo log segment page number
@param[in,out] max_trx_id the largest observed transaction ID
@return size of the undo log in pages */
-ulint
-trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
- trx_id_t& max_trx_id)
+uint32_t
+trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no,
+ trx_id_t &max_trx_id)
{
mtr_t mtr;
XID xid;
@@ -1090,18 +972,18 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
ut_ad(id < TRX_RSEG_N_SLOTS);
mtr.start();
- const page_t* undo_page = trx_undo_page_get(
+ const buf_block_t* block = trx_undo_page_get(
page_id_t(rseg->space->id, page_no), &mtr);
const ulint type = mach_read_from_2(
- TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE + undo_page);
+ TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE + block->frame);
ut_ad(type == 0 || type == TRX_UNDO_INSERT || type == TRX_UNDO_UPDATE);
- uint state = mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_STATE
- + undo_page);
- uint offset = mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG
- + undo_page);
+ uint16_t state = mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_STATE
+ + block->frame);
+ uint16_t offset = mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG
+ + block->frame);
- const trx_ulogf_t* undo_header = undo_page + offset;
+ const trx_ulogf_t* undo_header = block->frame + offset;
/* Read X/Open XA transaction identification if it exists, or
set it to NULL. */
@@ -1125,7 +1007,7 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
undo->dict_operation = undo_header[TRX_UNDO_DICT_TRANS];
undo->table_id = mach_read_from_8(undo_header + TRX_UNDO_TABLE_ID);
undo->size = flst_get_len(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST
- + undo_page);
+ + block->frame);
if (UNIV_UNLIKELY(state == TRX_UNDO_TO_FREE)) {
/* This is an old-format insert_undo log segment that
@@ -1143,17 +1025,17 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
}
fil_addr_t last_addr = flst_get_last(
- TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + undo_page);
+ TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + block->frame);
undo->last_page_no = last_addr.page;
undo->top_page_no = last_addr.page;
- page_t* last_page = trx_undo_page_get(
+ const buf_block_t* last = trx_undo_page_get(
page_id_t(rseg->space->id, undo->last_page_no), &mtr);
if (const trx_undo_rec_t* rec = trx_undo_page_get_last_rec(
- last_page, page_no, offset)) {
- undo->top_offset = ulint(rec - last_page);
+ last, page_no, offset)) {
+ undo->top_offset = uint16_t(rec - last->frame);
undo->top_undo_no = trx_undo_rec_get_undo_no(rec);
ut_ad(!undo->empty());
} else {
@@ -1189,8 +1071,8 @@ trx_undo_mem_create(
trx_id_t trx_id, /*!< in: id of the trx for which the undo log
is created */
const XID* xid, /*!< in: X/Open transaction identification */
- ulint page_no,/*!< in: undo log header page number */
- ulint offset) /*!< in: undo log header byte offset on page */
+ uint32_t page_no,/*!< in: undo log header page number */
+ uint16_t offset) /*!< in: undo log header byte offset on page */
{
trx_undo_t* undo;
@@ -1238,7 +1120,7 @@ trx_undo_mem_init_for_reuse(
trx_id_t trx_id, /*!< in: id of the trx for which the undo log
is created */
const XID* xid, /*!< in: X/Open XA transaction identification*/
- ulint offset) /*!< in: undo log header byte offset on page */
+ uint16_t offset) /*!< in: undo log header byte offset on page */
{
ut_ad(mutex_own(&((undo->rseg)->mutex)));
@@ -1282,10 +1164,9 @@ trx_undo_create(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo,
rseg->curr_size++;
- ulint offset = trx_undo_header_create(block->frame, trx->id, mtr);
+ uint16_t offset = trx_undo_header_create(block, trx->id, mtr);
- trx_undo_header_add_space_for_xid(block->frame, block->frame + offset,
- mtr);
+ trx_undo_header_add_space_for_xid(block, offset, mtr);
*undo = trx_undo_mem_create(rseg, id, trx->id, trx->xid,
block->page.id.page_no(), offset);
@@ -1307,10 +1188,10 @@ trx_undo_create(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo,
case TRX_DICT_OP_TABLE:
(*undo)->table_id = trx->table_id;
(*undo)->dict_operation = TRUE;
- mlog_write_ulint(block->frame + offset + TRX_UNDO_DICT_TRANS,
- TRUE, MLOG_1BYTE, mtr);
- mlog_write_ull(block->frame + offset + TRX_UNDO_TABLE_ID,
- trx->table_id, mtr);
+ mtr->write<1,mtr_t::OPT>(*block, block->frame + offset
+ + TRX_UNDO_DICT_TRANS, 1U);
+ mtr->write<8,mtr_t::OPT>(*block, block->frame + offset
+ + TRX_UNDO_TABLE_ID, trx->table_id);
}
*err = DB_SUCCESS;
@@ -1355,19 +1236,18 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo,
*pundo = undo;
- ulint offset = trx_undo_header_create(block->frame, trx->id, mtr);
+ uint16_t offset = trx_undo_header_create(block, trx->id, mtr);
/* Reset the TRX_UNDO_PAGE_TYPE in case this page is being
repurposed after upgrading to MariaDB 10.3. */
if (ut_d(ulint type =) UNIV_UNLIKELY(
mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ block->frame))) {
ut_ad(type == TRX_UNDO_INSERT || type == TRX_UNDO_UPDATE);
- mlog_write_ulint(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
- + block->frame, 0, MLOG_2BYTES, mtr);
+ mtr->write<2>(*block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ + block->frame, 0U);
}
- trx_undo_header_add_space_for_xid(block->frame, block->frame + offset,
- mtr);
+ trx_undo_header_add_space_for_xid(block, offset, mtr);
trx_undo_mem_init_for_reuse(undo, trx->id, trx->xid, offset);
@@ -1385,10 +1265,10 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo,
case TRX_DICT_OP_TABLE:
undo->table_id = trx->table_id;
undo->dict_operation = TRUE;
- mlog_write_ulint(block->frame + offset + TRX_UNDO_DICT_TRANS,
- TRUE, MLOG_1BYTE, mtr);
- mlog_write_ull(block->frame + offset + TRX_UNDO_TABLE_ID,
- trx->table_id, mtr);
+ mtr->write<1,mtr_t::OPT>(*block, block->frame + offset
+ + TRX_UNDO_DICT_TRANS, 1U);
+ mtr->write<8,mtr_t::OPT>(*block, block->frame + offset
+ + TRX_UNDO_TABLE_ID, trx->table_id);
}
return block;
@@ -1502,39 +1382,28 @@ func_exit:
/******************************************************************//**
Sets the state of the undo log segment at a transaction finish.
@return undo log segment header page, x-latched */
-page_t*
+buf_block_t*
trx_undo_set_state_at_finish(
/*=========================*/
trx_undo_t* undo, /*!< in: undo log memory copy */
mtr_t* mtr) /*!< in: mtr */
{
- trx_usegf_t* seg_hdr;
- trx_upagef_t* page_hdr;
- page_t* undo_page;
- ulint state;
-
ut_a(undo->id < TRX_RSEG_N_SLOTS);
- undo_page = trx_undo_page_get(
+ buf_block_t* block = trx_undo_page_get(
page_id_t(undo->rseg->space->id, undo->hdr_page_no), mtr);
- seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
- page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
-
- if (undo->size == 1
- && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
- < TRX_UNDO_PAGE_REUSE_LIMIT) {
-
- state = TRX_UNDO_CACHED;
- } else {
- state = TRX_UNDO_TO_PURGE;
- }
+ const uint16_t state = undo->size == 1
+ && TRX_UNDO_PAGE_REUSE_LIMIT
+ > mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
+ + block->frame)
+ ? TRX_UNDO_CACHED
+ : TRX_UNDO_TO_PURGE;
undo->state = state;
-
- mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, state, MLOG_2BYTES, mtr);
-
- return(undo_page);
+ mtr->write<2>(*block, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE
+ + block->frame, state);
+ return block;
}
/** Set the state of the undo log segment at a XA PREPARE or XA ROLLBACK.
@@ -1543,32 +1412,19 @@ trx_undo_set_state_at_finish(
@param[in] rollback false=XA PREPARE, true=XA ROLLBACK
@param[in,out] mtr mini-transaction
@return undo log segment header page, x-latched */
-page_t*
-trx_undo_set_state_at_prepare(
- trx_t* trx,
- trx_undo_t* undo,
- bool rollback,
- mtr_t* mtr)
+void trx_undo_set_state_at_prepare(trx_t *trx, trx_undo_t *undo, bool rollback,
+ mtr_t *mtr)
{
- trx_usegf_t* seg_hdr;
- trx_ulogf_t* undo_header;
- page_t* undo_page;
- ulint offset;
-
- ut_ad(trx && undo && mtr);
-
ut_a(undo->id < TRX_RSEG_N_SLOTS);
- undo_page = trx_undo_page_get(
+ buf_block_t* block = trx_undo_page_get(
page_id_t(undo->rseg->space->id, undo->hdr_page_no), mtr);
- seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
-
if (rollback) {
ut_ad(undo->state == TRX_UNDO_PREPARED);
- mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_ACTIVE,
- MLOG_2BYTES, mtr);
- return(undo_page);
+ mtr->write<2>(*block, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE
+ + block->frame, TRX_UNDO_ACTIVE);
+ return;
}
/*------------------------------*/
@@ -1577,18 +1433,13 @@ trx_undo_set_state_at_prepare(
undo->xid = *trx->xid;
/*------------------------------*/
- mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, undo->state,
- MLOG_2BYTES, mtr);
-
- offset = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG);
- undo_header = undo_page + offset;
-
- mlog_write_ulint(undo_header + TRX_UNDO_XID_EXISTS,
- TRUE, MLOG_1BYTE, mtr);
-
- trx_undo_write_xid(undo_header, &undo->xid, mtr);
+ mtr->write<2>(*block, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + block->frame,
+ undo->state);
+ uint16_t offset = mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG
+ + block->frame);
+ mtr->write<1>(*block, block->frame + offset + TRX_UNDO_XID_EXISTS, 1U);
- return(undo_page);
+ trx_undo_write_xid(block, offset, undo->xid, mtr);
}
/** Free an old insert or temporary undo log after commit or rollback.
@@ -1616,7 +1467,7 @@ trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp)
/* Delete first the undo log segment in the file */
mutex_exit(&rseg->mutex);
- trx_undo_seg_free(undo, true);
+ trx_undo_seg_free(undo, is_temp);
mutex_enter(&rseg->mutex);
ut_ad(rseg->curr_size > undo->size);
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index dd4163f11eb..79c78628065 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -6195,7 +6195,7 @@ end:
}
- /* write suffix to data file if neaded */
+/* Write suffix to data file if needed */
int maria_write_data_suffix(MARIA_SORT_INFO *sort_info, my_bool fix_datafile)
{
diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc
index 5920f802c9e..1cec6c894c2 100644
--- a/storage/spider/ha_spider.cc
+++ b/storage/spider/ha_spider.cc
@@ -9787,6 +9787,7 @@ void ha_spider::start_bulk_insert(
bulk_insert = TRUE;
bulk_size = -1;
store_last_insert_id = 0;
+ bzero(&copy_info, sizeof(copy_info));
DBUG_VOID_RETURN;
}
@@ -9799,7 +9800,7 @@ int ha_spider::end_bulk_insert()
bulk_insert = FALSE;
if (bulk_size == -1)
DBUG_RETURN(0);
- if ((error_num = spider_db_bulk_insert(this, table, TRUE)))
+ if ((error_num = spider_db_bulk_insert(this, table, &copy_info, TRUE)))
DBUG_RETURN(check_error_mode(error_num));
DBUG_RETURN(0);
}
@@ -9933,7 +9934,7 @@ int ha_spider::write_row(
else
bulk_size = 0;
}
- if ((error_num = spider_db_bulk_insert(this, table, FALSE)))
+ if ((error_num = spider_db_bulk_insert(this, table, &copy_info, FALSE)))
DBUG_RETURN(check_error_mode(error_num));
#ifdef HA_CAN_BULK_ACCESS
@@ -10558,7 +10559,8 @@ int ha_spider::direct_update_rows(
uint range_count,
bool sorted,
uchar *new_data,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num;
THD *thd = ha_thd();
@@ -10585,17 +10587,17 @@ int ha_spider::direct_update_rows(
if (is_bulk_access_clone)
{
bulk_access_pre_called = FALSE;
- DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows));
+ DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows, found_rows));
}
DBUG_RETURN(bulk_access_link_exec_tgt->spider->ha_direct_update_rows(
- ranges, range_count, sorted, new_data, update_rows));
+ ranges, range_count, sorted, new_data, update_rows, found_rows));
}
#endif
if (
(active_index != MAX_KEY && (error_num = index_handler_init())) ||
(active_index == MAX_KEY && (error_num = rnd_handler_init())) ||
(error_num = spider_db_direct_update(this, table, ranges, range_count,
- update_rows))
+ update_rows, found_rows))
)
DBUG_RETURN(check_error_mode(error_num));
@@ -10603,14 +10605,15 @@ int ha_spider::direct_update_rows(
if (bulk_access_executing && is_bulk_access_clone)
{
bulk_req_exec();
- DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows));
+ DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows, found_rows));
}
#endif
DBUG_RETURN(0);
}
#else
int ha_spider::direct_update_rows(
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num;
THD *thd = ha_thd();
@@ -10637,16 +10640,16 @@ int ha_spider::direct_update_rows(
if (is_bulk_access_clone)
{
bulk_access_pre_called = FALSE;
- DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows));
+ DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows, found_rows));
}
DBUG_RETURN(bulk_access_link_exec_tgt->spider->ha_direct_update_rows(
- update_rows));
+ update_rows, found_rows));
}
#endif
if (
(active_index != MAX_KEY && (error_num = index_handler_init())) ||
(active_index == MAX_KEY && (error_num = rnd_handler_init())) ||
- (error_num = spider_db_direct_update(this, table, update_rows))
+ (error_num = spider_db_direct_update(this, table, update_rows, found_rows))
)
DBUG_RETURN(check_error_mode(error_num));
@@ -10654,7 +10657,7 @@ int ha_spider::direct_update_rows(
if (bulk_access_executing && is_bulk_access_clone)
{
bulk_req_exec();
- DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows));
+ DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows, found_rows));
}
#endif
DBUG_RETURN(0);
@@ -10668,21 +10671,23 @@ int ha_spider::pre_direct_update_rows(
uint range_count,
bool sorted,
uchar *new_data,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
DBUG_ENTER("ha_spider::pre_direct_update_rows");
DBUG_PRINT("info",("spider this=%p", this));
DBUG_RETURN(bulk_access_link_current->spider->ha_direct_update_rows(ranges,
- range_count, sorted, new_data, update_rows));
+ range_count, sorted, new_data, update_rows, found_rows));
}
#else
int ha_spider::pre_direct_update_rows()
{
uint update_rows;
+ uint found_rows;
DBUG_ENTER("ha_spider::pre_direct_update_rows");
DBUG_PRINT("info",("spider this=%p", this));
DBUG_RETURN(bulk_access_link_current->spider->ha_direct_update_rows(
- &update_rows));
+ &update_rows, &found_rows));
}
#endif
#endif
diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h
index a146745aa97..edd7b8c881f 100644
--- a/storage/spider/ha_spider.h
+++ b/storage/spider/ha_spider.h
@@ -685,20 +685,22 @@ public:
#endif
#endif
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS
- inline int direct_update_rows(ha_rows *update_rows)
+ inline int direct_update_rows(ha_rows *update_rows, ha_rows *found_rows)
{
- return direct_update_rows(NULL, 0, FALSE, NULL, update_rows);
+ return direct_update_rows(NULL, 0, FALSE, NULL, update_rows, found_rows);
}
int direct_update_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
uchar *new_data,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_row
);
#else
int direct_update_rows(
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_row
);
#endif
#ifdef HA_CAN_BULK_ACCESS
@@ -706,15 +708,18 @@ public:
inline int pre_direct_update_rows()
{
ha_rows update_rows;
+ ha_rows found_rows;
- return pre_direct_update_rows(NULL, 0, FALSE, NULL, &update_rows);
+ return pre_direct_update_rows(NULL, 0, FALSE, NULL, &update_rows,
+ &found_rows);
}
int pre_direct_update_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
uchar *new_data,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_row
);
#else
int pre_direct_update_rows();
diff --git a/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_deinit.inc
new file mode 100644
index 00000000000..76b7582abfe
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_deinit.inc
@@ -0,0 +1,11 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_init.inc b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_init.inc
new file mode 100644
index 00000000000..da6778de504
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_init.inc
@@ -0,0 +1,27 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ PRIMARY KEY (skey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %';
+--let $MASTER_1_SET_COMMAND=set session spider_direct_dup_insert=1 $STR_SEMICOLON
diff --git a/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_deinit.inc
new file mode 100644
index 00000000000..76b7582abfe
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_deinit.inc
@@ -0,0 +1,11 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_init.inc b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_init.inc
new file mode 100644
index 00000000000..884ef74c47e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_init.inc
@@ -0,0 +1,26 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ KEY idx1 (skey,dt)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%update %';
diff --git a/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_insert.result b/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_insert.result
new file mode 100644
index 00000000000..df88d7a5165
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_insert.result
@@ -0,0 +1,179 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-18973
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+skey int NOT NULL,
+dt date NOT NULL,
+tm time NOT NULL,
+PRIMARY KEY (skey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00');
+FLUSH TABLES;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+EXE_MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND INSERT IGNORE INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(2, '2013-02-01', '13:00:00'),(4, '2013-03-01', '13:00:00'),(7, '2013-04-01', '13:00:00'),(8, '2013-05-01', '13:00:00'),(10, '2013-06-01', '13:00:00'),(11, '2013-07-01', '13:00:00'),(12, '2013-08-01', '13:00:00'),(13, '2013-09-01', '13:00:00'),(14, '2013-10-01', '13:00:00')" auto_test_local
+--------------
+set session spider_direct_dup_insert=1
+--------------
+
+Query OK, 0 rows affected
+
+--------------
+INSERT IGNORE INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(2, '2013-02-01', '13:00:00'),(4, '2013-03-01', '13:00:00'),(7, '2013-04-01', '13:00:00'),(8, '2013-05-01', '13:00:00'),(10, '2013-06-01', '13:00:00'),(11, '2013-07-01', '13:00:00'),(12, '2013-08-01', '13:00:00'),(13, '2013-09-01', '13:00:00'),(14, '2013-10-01', '13:00:00')
+--------------
+
+Query OK, 5 rows affected
+Records: 10 Duplicates: 5 Warnings: 0
+
+Bye
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %';
+argument
+insert ignore into `auto_test_remote`.`tbl_a`(`skey`,`dt`,`tm`)values(0,_latin1'2013-01-01',_latin1'13:00:00'),(2,_latin1'2013-02-01',_latin1'13:00:00'),(4,_latin1'2013-03-01',_latin1'13:00:00'),(7,_latin1'2013-04-01',_latin1'13:00:00'),(8,_latin1'2013-05-01',_latin1'13:00:00'),(10,_latin1'2013-06-01',_latin1'13:00:00'),(11,_latin1'2013-07-01',_latin1'13:00:00'),(12,_latin1'2013-08-01',_latin1'13:00:00'),(13,_latin1'2013-09-01',_latin1'13:00:00'),(14,_latin1'2013-10-01',_latin1'13:00:00')
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %'
+SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+skey dt tm
+0 2012-01-01 12:00:00
+1 2012-02-01 12:00:00
+2 2012-03-01 12:00:00
+3 2012-04-01 12:00:00
+4 2012-05-01 12:00:00
+5 2012-06-01 12:00:00
+6 2012-07-01 12:00:00
+7 2012-08-01 12:00:00
+8 2012-09-01 12:00:00
+9 2012-10-01 12:00:00
+10 2013-06-01 13:00:00
+11 2013-07-01 13:00:00
+12 2013-08-01 13:00:00
+13 2013-09-01 13:00:00
+14 2013-10-01 13:00:00
+TRUNCATE TABLE mysql.general_log;
+EXE_MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND REPLACE INTO tbl_a (skey, dt, tm) VALUES (1, '2012-02-01', '12:00:00'),(3, '2012-12-01', '11:00:00'),(8, '2012-11-30', '11:00:00'),(9, '2012-11-29', '11:00:00'),(10, '2012-11-28', '11:00:00'),(15, '2012-11-27', '11:00:00'),(16, '2012-11-26', '11:00:00'),(17, '2012-11-25', '11:00:00'),(18, '2012-11-24', '11:00:00'),(19, '2012-11-23', '11:00:00')" auto_test_local
+--------------
+set session spider_direct_dup_insert=1
+--------------
+
+Query OK, 0 rows affected
+
+--------------
+REPLACE INTO tbl_a (skey, dt, tm) VALUES (1, '2012-02-01', '12:00:00'),(3, '2012-12-01', '11:00:00'),(8, '2012-11-30', '11:00:00'),(9, '2012-11-29', '11:00:00'),(10, '2012-11-28', '11:00:00'),(15, '2012-11-27', '11:00:00'),(16, '2012-11-26', '11:00:00'),(17, '2012-11-25', '11:00:00'),(18, '2012-11-24', '11:00:00'),(19, '2012-11-23', '11:00:00')
+--------------
+
+Query OK, 14 rows affected
+Records: 10 Duplicates: 4 Warnings: 0
+
+Bye
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %';
+argument
+replace into `auto_test_remote`.`tbl_a`(`skey`,`dt`,`tm`)values(1,_latin1'2012-02-01',_latin1'12:00:00'),(3,_latin1'2012-12-01',_latin1'11:00:00'),(8,_latin1'2012-11-30',_latin1'11:00:00'),(9,_latin1'2012-11-29',_latin1'11:00:00'),(10,_latin1'2012-11-28',_latin1'11:00:00'),(15,_latin1'2012-11-27',_latin1'11:00:00'),(16,_latin1'2012-11-26',_latin1'11:00:00'),(17,_latin1'2012-11-25',_latin1'11:00:00'),(18,_latin1'2012-11-24',_latin1'11:00:00'),(19,_latin1'2012-11-23',_latin1'11:00:00')
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %'
+SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+skey dt tm
+0 2012-01-01 12:00:00
+1 2012-02-01 12:00:00
+2 2012-03-01 12:00:00
+3 2012-12-01 11:00:00
+4 2012-05-01 12:00:00
+5 2012-06-01 12:00:00
+6 2012-07-01 12:00:00
+7 2012-08-01 12:00:00
+8 2012-11-30 11:00:00
+9 2012-11-29 11:00:00
+10 2012-11-28 11:00:00
+11 2013-07-01 13:00:00
+12 2013-08-01 13:00:00
+13 2013-09-01 13:00:00
+14 2013-10-01 13:00:00
+15 2012-11-27 11:00:00
+16 2012-11-26 11:00:00
+17 2012-11-25 11:00:00
+18 2012-11-24 11:00:00
+19 2012-11-23 11:00:00
+TRUNCATE TABLE mysql.general_log;
+EXE_MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND INSERT INTO tbl_a (skey, dt, tm) VALUES (1, '2012-11-01', '11:00:00'),(3, '2012-12-01', '11:00:00'),(11, '2012-11-30', '11:00:00'),(15, '2012-11-29', '11:00:00'),(16, '2012-11-28', '11:00:00'),(20, '2012-11-27', '11:00:00'),(21, '2012-11-26', '11:00:00'),(22, '2012-11-25', '11:00:00'),(23, '2012-11-24', '11:00:00'),(24, '2012-11-23', '11:00:00') ON DUPLICATE KEY UPDATE dt=VALUE(dt), tm=VALUE(tm)" auto_test_local
+--------------
+set session spider_direct_dup_insert=1
+--------------
+
+Query OK, 0 rows affected
+
+--------------
+INSERT INTO tbl_a (skey, dt, tm) VALUES (1, '2012-11-01', '11:00:00'),(3, '2012-12-01', '11:00:00'),(11, '2012-11-30', '11:00:00'),(15, '2012-11-29', '11:00:00'),(16, '2012-11-28', '11:00:00'),(20, '2012-11-27', '11:00:00'),(21, '2012-11-26', '11:00:00'),(22, '2012-11-25', '11:00:00'),(23, '2012-11-24', '11:00:00'),(24, '2012-11-23', '11:00:00') ON DUPLICATE KEY UPDATE dt=VALUE(dt), tm=VALUE(tm)
+--------------
+
+Query OK, 13 rows affected
+Records: 10 Duplicates: 4 Warnings: 0
+
+Bye
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`skey`,`dt`,`tm`)values(1,_latin1'2012-11-01',_latin1'11:00:00'),(3,_latin1'2012-12-01',_latin1'11:00:00'),(11,_latin1'2012-11-30',_latin1'11:00:00'),(15,_latin1'2012-11-29',_latin1'11:00:00'),(16,_latin1'2012-11-28',_latin1'11:00:00'),(20,_latin1'2012-11-27',_latin1'11:00:00'),(21,_latin1'2012-11-26',_latin1'11:00:00'),(22,_latin1'2012-11-25',_latin1'11:00:00'),(23,_latin1'2012-11-24',_latin1'11:00:00'),(24,_latin1'2012-11-23',_latin1'11:00:00') on duplicate key update `dt` = values(`dt`),`tm` = values(`tm`)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %'
+SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+skey dt tm
+0 2012-01-01 12:00:00
+1 2012-11-01 11:00:00
+2 2012-03-01 12:00:00
+3 2012-12-01 11:00:00
+4 2012-05-01 12:00:00
+5 2012-06-01 12:00:00
+6 2012-07-01 12:00:00
+7 2012-08-01 12:00:00
+8 2012-11-30 11:00:00
+9 2012-11-29 11:00:00
+10 2012-11-28 11:00:00
+11 2012-11-30 11:00:00
+12 2013-08-01 13:00:00
+13 2013-09-01 13:00:00
+14 2013-10-01 13:00:00
+15 2012-11-29 11:00:00
+16 2012-11-28 11:00:00
+17 2012-11-25 11:00:00
+18 2012-11-24 11:00:00
+19 2012-11-23 11:00:00
+20 2012-11-27 11:00:00
+21 2012-11-26 11:00:00
+22 2012-11-25 11:00:00
+23 2012-11-24 11:00:00
+24 2012-11-23 11:00:00
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_update.result b/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_update.result
new file mode 100644
index 00000000000..2ebc2693dc5
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_update.result
@@ -0,0 +1,99 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-18973
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+skey int NOT NULL,
+dt date NOT NULL,
+tm time NOT NULL,
+KEY idx1 (skey,dt)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00');
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(1, '2013-02-01', '13:00:00'),(2, '2013-03-01', '13:00:00'),(3, '2013-04-01', '13:00:00'),(4, '2013-05-01', '13:00:00'),(5, '2013-06-01', '13:00:00'),(6, '2013-07-01', '13:00:00'),(7, '2013-08-01', '13:00:00'),(8, '2013-09-01', '13:00:00'),(9, '2013-10-01', '13:00:00');
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-11-01', '11:00:00'),(1, '2012-12-01', '11:00:00'),(2, '2012-11-30', '11:00:00'),(3, '2012-11-29', '11:00:00'),(4, '2012-11-28', '11:00:00'),(5, '2012-11-27', '11:00:00'),(6, '2012-11-26', '11:00:00'),(7, '2012-11-25', '11:00:00'),(8, '2012-11-24', '11:00:00'),(9, '2012-11-23', '11:00:00');
+FLUSH TABLES;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+EXE_MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "UPDATE tbl_a SET tm = '12:00:00' WHERE skey = 0" auto_test_local
+--------------
+UPDATE tbl_a SET tm = '12:00:00' WHERE skey = 0
+--------------
+
+Query OK, 2 rows affected
+Rows matched: 3 Changed: 2 Warnings: 0
+
+Bye
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%update %';
+argument
+update `auto_test_remote`.`tbl_a` set `tm` = _latin1'12:00:00' where (`skey` = 0)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%update %'
+SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+skey dt tm
+0 2012-01-01 12:00:00
+0 2013-01-01 12:00:00
+0 2012-11-01 12:00:00
+1 2012-12-01 11:00:00
+1 2013-02-01 13:00:00
+1 2012-02-01 12:00:00
+2 2013-03-01 13:00:00
+2 2012-11-30 11:00:00
+2 2012-03-01 12:00:00
+3 2012-11-29 11:00:00
+3 2013-04-01 13:00:00
+3 2012-04-01 12:00:00
+4 2012-11-28 11:00:00
+4 2012-05-01 12:00:00
+4 2013-05-01 13:00:00
+5 2012-11-27 11:00:00
+5 2012-06-01 12:00:00
+5 2013-06-01 13:00:00
+6 2013-07-01 13:00:00
+6 2012-11-26 11:00:00
+6 2012-07-01 12:00:00
+7 2012-11-25 11:00:00
+7 2012-08-01 12:00:00
+7 2013-08-01 13:00:00
+8 2012-09-01 12:00:00
+8 2013-09-01 13:00:00
+8 2012-11-24 11:00:00
+9 2012-10-01 12:00:00
+9 2013-10-01 13:00:00
+9 2012-11-23 11:00:00
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.cnf b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.test b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.test
new file mode 100644
index 00000000000..ea2a2147910
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.test
@@ -0,0 +1,98 @@
+--source ../include/return_found_rows_insert_init.inc
+--echo
+--echo this test is for MDEV-18973
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ PRIMARY KEY (skey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ PRIMARY KEY (skey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00');
+FLUSH TABLES;
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--disable_query_log
+echo EXE_MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND INSERT IGNORE INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(2, '2013-02-01', '13:00:00'),(4, '2013-03-01', '13:00:00'),(7, '2013-04-01', '13:00:00'),(8, '2013-05-01', '13:00:00'),(10, '2013-06-01', '13:00:00'),(11, '2013-07-01', '13:00:00'),(12, '2013-08-01', '13:00:00'),(13, '2013-09-01', '13:00:00'),(14, '2013-10-01', '13:00:00')" auto_test_local;
+exec $EXE_MYSQL -v -v -u root -h localhost -P $MASTER_1_MYPORT -S $MASTER_1_MYSOCK -e "$MASTER_1_SET_COMMAND INSERT IGNORE INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(2, '2013-02-01', '13:00:00'),(4, '2013-03-01', '13:00:00'),(7, '2013-04-01', '13:00:00'),(8, '2013-05-01', '13:00:00'),(10, '2013-06-01', '13:00:00'),(11, '2013-07-01', '13:00:00'),(12, '2013-08-01', '13:00:00'),(13, '2013-09-01', '13:00:00'),(14, '2013-10-01', '13:00:00')" auto_test_local;
+--enable_query_log
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+TRUNCATE TABLE mysql.general_log;
+
+--disable_query_log
+echo EXE_MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND REPLACE INTO tbl_a (skey, dt, tm) VALUES (1, '2012-02-01', '12:00:00'),(3, '2012-12-01', '11:00:00'),(8, '2012-11-30', '11:00:00'),(9, '2012-11-29', '11:00:00'),(10, '2012-11-28', '11:00:00'),(15, '2012-11-27', '11:00:00'),(16, '2012-11-26', '11:00:00'),(17, '2012-11-25', '11:00:00'),(18, '2012-11-24', '11:00:00'),(19, '2012-11-23', '11:00:00')" auto_test_local;
+exec $EXE_MYSQL -v -v -u root -h localhost -P $MASTER_1_MYPORT -S $MASTER_1_MYSOCK -e "$MASTER_1_SET_COMMAND REPLACE INTO tbl_a (skey, dt, tm) VALUES (1, '2012-02-01', '12:00:00'),(3, '2012-12-01', '11:00:00'),(8, '2012-11-30', '11:00:00'),(9, '2012-11-29', '11:00:00'),(10, '2012-11-28', '11:00:00'),(15, '2012-11-27', '11:00:00'),(16, '2012-11-26', '11:00:00'),(17, '2012-11-25', '11:00:00'),(18, '2012-11-24', '11:00:00'),(19, '2012-11-23', '11:00:00')" auto_test_local;
+--enable_query_log
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+TRUNCATE TABLE mysql.general_log;
+
+--disable_query_log
+echo EXE_MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND INSERT INTO tbl_a (skey, dt, tm) VALUES (1, '2012-11-01', '11:00:00'),(3, '2012-12-01', '11:00:00'),(11, '2012-11-30', '11:00:00'),(15, '2012-11-29', '11:00:00'),(16, '2012-11-28', '11:00:00'),(20, '2012-11-27', '11:00:00'),(21, '2012-11-26', '11:00:00'),(22, '2012-11-25', '11:00:00'),(23, '2012-11-24', '11:00:00'),(24, '2012-11-23', '11:00:00') ON DUPLICATE KEY UPDATE dt=VALUE(dt), tm=VALUE(tm)" auto_test_local;
+exec $EXE_MYSQL -v -v -u root -h localhost -P $MASTER_1_MYPORT -S $MASTER_1_MYSOCK -e "$MASTER_1_SET_COMMAND INSERT INTO tbl_a (skey, dt, tm) VALUES (1, '2012-11-01', '11:00:00'),(3, '2012-12-01', '11:00:00'),(11, '2012-11-30', '11:00:00'),(15, '2012-11-29', '11:00:00'),(16, '2012-11-28', '11:00:00'),(20, '2012-11-27', '11:00:00'),(21, '2012-11-26', '11:00:00'),(22, '2012-11-25', '11:00:00'),(23, '2012-11-24', '11:00:00'),(24, '2012-11-23', '11:00:00') ON DUPLICATE KEY UPDATE dt=VALUE(dt), tm=VALUE(tm)" auto_test_local;
+--enable_query_log
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/return_found_rows_insert_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.cnf b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.test b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.test
new file mode 100644
index 00000000000..31f1d9c4c6c
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.test
@@ -0,0 +1,78 @@
+--source ../include/return_found_rows_update_init.inc
+--echo
+--echo this test is for MDEV-18973
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ KEY idx1 (skey,dt)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ KEY idx1 (skey,dt)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00');
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(1, '2013-02-01', '13:00:00'),(2, '2013-03-01', '13:00:00'),(3, '2013-04-01', '13:00:00'),(4, '2013-05-01', '13:00:00'),(5, '2013-06-01', '13:00:00'),(6, '2013-07-01', '13:00:00'),(7, '2013-08-01', '13:00:00'),(8, '2013-09-01', '13:00:00'),(9, '2013-10-01', '13:00:00');
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-11-01', '11:00:00'),(1, '2012-12-01', '11:00:00'),(2, '2012-11-30', '11:00:00'),(3, '2012-11-29', '11:00:00'),(4, '2012-11-28', '11:00:00'),(5, '2012-11-27', '11:00:00'),(6, '2012-11-26', '11:00:00'),(7, '2012-11-25', '11:00:00'),(8, '2012-11-24', '11:00:00'),(9, '2012-11-23', '11:00:00');
+FLUSH TABLES;
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--disable_query_log
+echo EXE_MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "UPDATE tbl_a SET tm = '12:00:00' WHERE skey = 0" auto_test_local;
+exec $EXE_MYSQL -v -v -u root -h localhost -P $MASTER_1_MYPORT -S $MASTER_1_MYSOCK -e "UPDATE tbl_a SET tm = '12:00:00' WHERE skey = 0" auto_test_local;
+--enable_query_log
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/return_found_rows_update_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc
index aa82f0b0fb1..8d635296854 100644
--- a/storage/spider/spd_db_conn.cc
+++ b/storage/spider/spd_db_conn.cc
@@ -5975,6 +5975,7 @@ int spider_db_bulk_insert_init(
int spider_db_bulk_insert(
ha_spider *spider,
TABLE *table,
+ ha_copy_info *copy_info,
bool bulk_end
) {
int error_num, first_insert_link_idx = -1;
@@ -6021,6 +6022,7 @@ int spider_db_bulk_insert(
if (!spider->is_bulk_access_clone)
{
#endif
+ bool insert_info = FALSE;
for (
roop_count2 = spider_conn_link_idx_next(share->link_statuses,
spider->conn_link_idx, -1, share->link_count,
@@ -6169,6 +6171,11 @@ int spider_db_bulk_insert(
}
conn->mta_conn_mutex_lock_already = mta_conn_mutex_lock_already_backup;
conn->mta_conn_mutex_unlock_later = mta_conn_mutex_unlock_later_backup;
+ if (!insert_info && copy_info)
+ {
+ insert_info =
+ conn->db_conn->inserted_info(dbton_handler, copy_info);
+ }
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
if (conn->conn_kind != SPIDER_CONN_KIND_MYSQL)
{
@@ -6922,7 +6929,8 @@ int spider_db_direct_update(
TABLE *table,
KEY_MULTI_RANGE *ranges,
uint range_count,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num, roop_count;
SPIDER_SHARE *share = spider->share;
@@ -7195,6 +7203,8 @@ int spider_db_direct_update(
{
*update_rows = spider->conns[roop_count]->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = spider->conns[roop_count]->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -7216,6 +7226,8 @@ int spider_db_direct_update(
{
*update_rows = conn->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = conn->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
result->free_result();
@@ -7253,7 +7265,8 @@ int spider_db_direct_update(
int spider_db_direct_update(
ha_spider *spider,
TABLE *table,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num, roop_count;
SPIDER_SHARE *share = spider->share;
@@ -7446,6 +7459,8 @@ int spider_db_direct_update(
{
*update_rows = spider->conns[roop_count]->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = spider->conns[roop_count]->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
#ifdef HA_CAN_BULK_ACCESS
@@ -7465,7 +7480,8 @@ int spider_db_direct_update(
#ifdef HA_CAN_BULK_ACCESS
int spider_db_bulk_direct_update(
ha_spider *spider,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num = 0, roop_count, tmp_error_num;
SPIDER_SHARE *share = spider->share;
@@ -7510,6 +7526,8 @@ int spider_db_bulk_direct_update(
{
*update_rows = spider->conns[roop_count]->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = spider->conns[roop_count]->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -7531,6 +7549,8 @@ int spider_db_bulk_direct_update(
{
*update_rows = conn->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = conn->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
result->free_result();
diff --git a/storage/spider/spd_db_conn.h b/storage/spider/spd_db_conn.h
index 0300dc6c407..6fdb4b694ae 100644
--- a/storage/spider/spd_db_conn.h
+++ b/storage/spider/spd_db_conn.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -745,6 +746,7 @@ int spider_db_bulk_insert_init(
int spider_db_bulk_insert(
ha_spider *spider,
TABLE *table,
+ ha_copy_info *copy_info,
bool bulk_end
);
@@ -788,13 +790,15 @@ int spider_db_direct_update(
TABLE *table,
KEY_MULTI_RANGE *ranges,
uint range_count,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
);
#else
int spider_db_direct_update(
ha_spider *spider,
TABLE *table,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
);
#endif
#endif
diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc
index 091f48a2460..7408ec33cee 100644
--- a/storage/spider/spd_db_handlersocket.cc
+++ b/storage/spider/spd_db_handlersocket.cc
@@ -1655,6 +1655,22 @@ uint spider_db_handlersocket::affected_rows()
DBUG_RETURN((uint) my_strtoll10(hs_row->begin(), (char**) NULL, &error_num));
}
+uint spider_db_handlersocket::matched_rows()
+{
+ DBUG_ENTER("spider_db_handlersocket::matched_rows");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(0);
+}
+
+bool spider_db_handlersocket::inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+) {
+ DBUG_ENTER("spider_db_handlersocket::inserted_info");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(FALSE);
+}
+
ulonglong spider_db_handlersocket::last_insert_id()
{
DBUG_ENTER("spider_db_handlersocket::last_insert_id");
diff --git a/storage/spider/spd_db_handlersocket.h b/storage/spider/spd_db_handlersocket.h
index d2beb2124c0..19a4a391ed6 100644
--- a/storage/spider/spd_db_handlersocket.h
+++ b/storage/spider/spd_db_handlersocket.h
@@ -335,6 +335,11 @@ public:
);
int next_result();
uint affected_rows();
+ uint matched_rows();
+ bool inserted_info(
+ spider_db_handler *handler,
+ spider_copy_info *copy_info
+ );
ulonglong last_insert_id();
int set_character_set(
const char *csname
diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h
index 56a88a2b7bc..4daa5c71b93 100644
--- a/storage/spider/spd_db_include.h
+++ b/storage/spider/spd_db_include.h
@@ -259,6 +259,7 @@ typedef struct st_spider_transaction SPIDER_TRX;
typedef struct st_spider_share SPIDER_SHARE;
class ha_spider;
class spider_db_copy_table;
+class spider_db_handler;
class spider_string
{
@@ -1109,6 +1110,11 @@ public:
) = 0;
virtual int next_result() = 0;
virtual uint affected_rows() = 0;
+ virtual uint matched_rows() = 0;
+ virtual bool inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+ ) = 0;
virtual ulonglong last_insert_id() = 0;
virtual int set_character_set(
const char *csname
diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
index 6b551804c87..2c35bd7bf28 100644
--- a/storage/spider/spd_db_mysql.cc
+++ b/storage/spider/spd_db_mysql.cc
@@ -184,6 +184,11 @@ static uchar SPIDER_SQL_LINESTRING_HEAD_STR[] =
{0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00};
#define SPIDER_SQL_LINESTRING_HEAD_LEN sizeof(SPIDER_SQL_LINESTRING_HEAD_STR)
+#define SPIDER_SQL_DIRECT_INSERT_KIND_INSERT 0
+#define SPIDER_SQL_DIRECT_INSERT_KIND_REPLACE 1
+#define SPIDER_SQL_DIRECT_INSERT_KIND_IGNORE 2
+#define SPIDER_SQL_DIRECT_INSERT_KIND_DUP_UPDATE 3
+
static const char *spider_db_table_lock_str[] =
{
" read local,",
@@ -2444,6 +2449,81 @@ uint spider_db_mbase::affected_rows()
DBUG_RETURN((uint) last_used_con->affected_rows);
}
+uint spider_db_mbase::matched_rows()
+{
+ MYSQL *last_used_con;
+ DBUG_ENTER("spider_db_mysql::matched_rows");
+ DBUG_PRINT("info", ("spider this=%p", this));
+#if MYSQL_VERSION_ID < 50500
+ last_used_con = db_conn->last_used_con;
+#else
+ last_used_con = db_conn;
+#endif
+ /* Rows matched: 65 Changed: 65 Warnings: 0 */
+ const char *info = last_used_con->info;
+ if (!info)
+ DBUG_RETURN(0);
+ DBUG_PRINT("info", ("spider info=%s", info));
+ const char *begin = strstr(info, "Rows matched: ");
+ if (!begin)
+ DBUG_RETURN(0);
+ DBUG_RETURN(atoi(begin + strlen("Rows matched: ")));
+}
+
+bool spider_db_mbase::inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+) {
+ MYSQL *last_used_con;
+ uchar direct_insert_kind =
+ ((spider_mbase_handler *) handler)->direct_insert_kind;
+ DBUG_ENTER("spider_db_mysql::inserted_info");
+ DBUG_PRINT("info", ("spider this=%p", this));
+ if (direct_insert_kind == SPIDER_SQL_DIRECT_INSERT_KIND_INSERT)
+ {
+ DBUG_RETURN(TRUE);
+ }
+#if MYSQL_VERSION_ID < 50500
+ last_used_con = db_conn->last_used_con;
+#else
+ last_used_con = db_conn;
+#endif
+ /* Records: 10 Duplicates: 4 Warnings: 0 */
+ const char *info = last_used_con->info;
+ if (!info)
+ DBUG_RETURN(FALSE);
+ DBUG_PRINT("info", ("spider info=%s", info));
+ const char *begin = strstr(info, "Records: ");
+ if (!begin)
+ DBUG_RETURN(FALSE);
+ begin += strlen("Records: ");
+ uint records = atoi(begin);
+ begin = strstr(begin, "Duplicates: ");
+ if (!begin)
+ DBUG_RETURN(FALSE);
+ uint duplicates = atoi(begin + strlen("Duplicates: "));
+ copy_info->records+= records;
+ switch (direct_insert_kind)
+ {
+ case SPIDER_SQL_DIRECT_INSERT_KIND_IGNORE:
+ copy_info->copied+= duplicates;
+ break;
+ case SPIDER_SQL_DIRECT_INSERT_KIND_REPLACE:
+ copy_info->copied+= records;
+ copy_info->deleted+= duplicates;
+ break;
+ case SPIDER_SQL_DIRECT_INSERT_KIND_DUP_UPDATE:
+ copy_info->touched+= (last_used_con->affected_rows - (duplicates * 2));
+ copy_info->copied+= (last_used_con->affected_rows - duplicates);
+ copy_info->updated+= duplicates;
+ break;
+ default:
+ DBUG_ASSERT(0);
+ DBUG_RETURN(FALSE);
+ }
+ DBUG_RETURN(TRUE);
+}
+
ulonglong spider_db_mbase::last_insert_id()
{
MYSQL *last_used_con;
@@ -9017,6 +9097,7 @@ int spider_mbase_handler::append_insert(
) {
SPIDER_SHARE *share = spider->share;
DBUG_ENTER("spider_mbase_handler::append_insert");
+ direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_INSERT;
if (
(
spider->write_can_replace ||
@@ -9026,6 +9107,7 @@ int spider_mbase_handler::append_insert(
) &&
spider->direct_dup_insert
) {
+ direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_REPLACE;
if (str->reserve(SPIDER_SQL_REPLACE_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_REPLACE_STR, SPIDER_SQL_REPLACE_LEN);
@@ -9073,6 +9155,7 @@ int spider_mbase_handler::append_insert(
spider->sql_command != SQLCOM_REPLACE &&
spider->sql_command != SQLCOM_REPLACE_SELECT
) {
+ direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_IGNORE;
if (str->reserve(SPIDER_SQL_SQL_IGNORE_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_SQL_IGNORE_STR, SPIDER_SQL_SQL_IGNORE_LEN);
@@ -11911,6 +11994,7 @@ int spider_mbase_handler::append_insert_terminator(
dup_update_sql.length()
) {
DBUG_PRINT("info",("spider add duplicate key update"));
+ direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_DUP_UPDATE;
str->length(str->length() - SPIDER_SQL_COMMA_LEN);
if (str->reserve(SPIDER_SQL_DUPLICATE_KEY_UPDATE_LEN +
dup_update_sql.length()))
diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h
index 51db3b1f2fa..626bb4d5624 100644
--- a/storage/spider/spd_db_mysql.h
+++ b/storage/spider/spd_db_mysql.h
@@ -453,6 +453,11 @@ public:
);
int next_result();
uint affected_rows();
+ uint matched_rows();
+ bool inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+ );
ulonglong last_insert_id();
int set_character_set(
const char *csname
@@ -801,6 +806,7 @@ public:
spider_mbase_share *mysql_share;
SPIDER_LINK_FOR_HASH *link_for_hash;
uchar *minimum_select_bitmap;
+ uchar direct_insert_kind;
spider_mbase_handler(
ha_spider *spider,
spider_mbase_share *share,
diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc
index e56cb31a32c..1a14537cd9f 100644
--- a/storage/spider/spd_db_oracle.cc
+++ b/storage/spider/spd_db_oracle.cc
@@ -1731,6 +1731,22 @@ uint spider_db_oracle::affected_rows()
DBUG_RETURN(update_rows);
}
+uint spider_db_oracle::matched_rows()
+{
+ DBUG_ENTER("spider_db_oracle::matched_rows");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(0);
+}
+
+bool spider_db_oracle::inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+) {
+ DBUG_ENTER("spider_db_oracle::inserted_info");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(FALSE);
+}
+
ulonglong spider_db_oracle::last_insert_id()
{
DBUG_ENTER("spider_db_oracle::last_insert_id");
diff --git a/storage/spider/spd_db_oracle.h b/storage/spider/spd_db_oracle.h
index a4be417bc67..ebdc23a9bfa 100644
--- a/storage/spider/spd_db_oracle.h
+++ b/storage/spider/spd_db_oracle.h
@@ -385,6 +385,11 @@ public:
);
int next_result();
uint affected_rows();
+ uint matched_rows();
+ bool inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+ );
ulonglong last_insert_id();
int set_character_set(
const char *csname
diff --git a/tpool/aio_linux.cc b/tpool/aio_linux.cc
index 0a4820a2412..24bc04c75ba 100644
--- a/tpool/aio_linux.cc
+++ b/tpool/aio_linux.cc
@@ -39,7 +39,6 @@ namespace tpool
class aio_linux : public aio
{
- int m_max_io_count;
thread_pool* m_pool;
io_context_t m_io_ctx;
bool m_in_shutdown;
@@ -62,7 +61,7 @@ class aio_linux : public aio
long long res = event.res;
if (res < 0)
{
- iocb->m_err = -res;
+ iocb->m_err = static_cast<int>(-res);
iocb->m_ret_len = 0;
}
else
@@ -93,8 +92,8 @@ class aio_linux : public aio
}
public:
- aio_linux(io_context_t ctx, thread_pool* pool, size_t max_count)
- : m_max_io_count(max_count), m_pool(pool), m_io_ctx(ctx),
+ aio_linux(io_context_t ctx, thread_pool* pool)
+ : m_pool(pool), m_io_ctx(ctx),
m_in_shutdown(), m_getevent_thread(getevent_thread_routine, this)
{
}
@@ -146,7 +145,7 @@ aio* create_linux_aio(thread_pool* pool, int max_io)
fprintf(stderr, "io_setup(%d) returned %d\n", max_io, ret);
return nullptr;
}
- return new aio_linux(ctx, pool, max_io);
+ return new aio_linux(ctx, pool);
}
#else
aio* create_linux_aio(thread_pool* pool, int max_aio)
diff --git a/tpool/aio_simulated.cc b/tpool/aio_simulated.cc
index 7deaf745aa2..4811797a75e 100644
--- a/tpool/aio_simulated.cc
+++ b/tpool/aio_simulated.cc
@@ -133,7 +133,11 @@ public:
static void simulated_aio_callback(void *param)
{
aiocb *cb= (aiocb *) param;
- int ret_len;
+#ifdef _WIN32
+ size_t ret_len;
+#else
+ ssize_t ret_len;
+#endif
int err= 0;
switch (cb->m_opcode)
{
@@ -146,14 +150,13 @@ public:
default:
abort();
}
- if (ret_len < 0)
- {
#ifdef _WIN32
+ if (static_cast<int>(ret_len) < 0)
err= GetLastError();
#else
+ if (ret_len < 0)
err= errno;
#endif
- }
cb->m_ret_len = ret_len;
cb->m_err = err;
cb->m_callback(cb);
diff --git a/tpool/tpool.h b/tpool/tpool.h
index ad63e25bdd7..8659e8adc74 100644
--- a/tpool/tpool.h
+++ b/tpool/tpool.h
@@ -110,7 +110,6 @@ enum class aio_opcode
AIO_PWRITE
};
const int MAX_AIO_USERDATA_LEN= 40;
-struct aiocb;
/** IO control block, includes parameters for the IO, and the callback*/
@@ -129,7 +128,7 @@ struct aiocb
callback_func m_callback;
task_group* m_group;
/* Returned length and error code*/
- int m_ret_len;
+ size_t m_ret_len;
int m_err;
void *m_internal;
task m_internal_task;