summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-10-30 11:15:30 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-10-30 11:15:30 +0200
commit898521e2dd8a4a6706cba01b6ef0a7cea4114fd0 (patch)
tree4ef9a6ddc4298574bb75db673c2412f83c107c5b /sql
parent571bcf9aaaf59b84e24bbfb809738dea25495d78 (diff)
parent199863d72b7cccaa4c75641c50c45a83b568ab8c (diff)
downloadmariadb-git-898521e2dd8a4a6706cba01b6ef0a7cea4114fd0.tar.gz
Merge 10.4 into 10.5
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt2
-rw-r--r--sql/handle_connections_win.cc66
-rw-r--r--sql/item.h19
-rw-r--r--sql/item_cmpfunc.cc29
-rw-r--r--sql/item_cmpfunc.h19
-rw-r--r--sql/item_func.cc3
-rw-r--r--sql/item_jsonfunc.cc2
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/item_subselect.h2
-rw-r--r--sql/item_timefunc.cc4
-rw-r--r--sql/item_timefunc.h2
-rw-r--r--sql/mf_iocache_encr.cc10
-rw-r--r--sql/session_tracker.cc3
-rw-r--r--sql/set_var.cc3
-rw-r--r--sql/sql_acl.cc54
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_lex.cc16
-rw-r--r--sql/sql_parse.cc10
-rw-r--r--sql/sql_select.cc40
-rw-r--r--sql/sql_select.h3
-rw-r--r--sql/sql_show.cc170
-rw-r--r--sql/sql_type.cc60
-rw-r--r--sql/sql_type.h42
-rw-r--r--sql/sql_update.cc15
-rw-r--r--sql/sql_yacc.yy141
-rw-r--r--sql/table.h1
26 files changed, 401 insertions, 322 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 7f6945c728a..e4760e1daae 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -194,7 +194,7 @@ DTRACE_INSTRUMENT(sql)
TARGET_LINK_LIBRARIES(sql
mysys mysys_ssl dbug strings vio pcre2-8
tpool
- ${LIBWRAP} ${LIBCRYPT} ${LIBDL} ${CMAKE_THREAD_LIBS_INIT}
+ ${LIBWRAP} ${LIBCRYPT} ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT}
${SSL_LIBRARIES}
${LIBSYSTEMD})
diff --git a/sql/handle_connections_win.cc b/sql/handle_connections_win.cc
index 11c7beee773..b61130dd6e9 100644
--- a/sql/handle_connections_win.cc
+++ b/sql/handle_connections_win.cc
@@ -310,6 +310,64 @@ retry :
}
};
+/*
+ Create a security descriptor for pipe.
+ - Use low integrity level, so that it is possible to connect
+ from any process.
+ - Give current user read/write access to pipe.
+ - Give Everyone read/write access to pipe minus FILE_CREATE_PIPE_INSTANCE
+*/
+static void init_pipe_security_descriptor()
+{
+#define SDDL_FMT "S:(ML;; NW;;; LW) D:(A;; 0x%08x;;; WD)(A;; FRFW;;; %s)"
+#define EVERYONE_PIPE_ACCESS_MASK \
+ (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES | READ_CONTROL | \
+ SYNCHRONIZE | FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
+
+#ifndef SECURITY_MAX_SID_STRING_CHARACTERS
+/* Old SDK does not have this constant */
+#define SECURITY_MAX_SID_STRING_CHARACTERS 187
+#endif
+
+ /*
+ Figure out SID of the user that runs the server, then create SDDL string
+ for pipe permissions, and convert it to the security descriptor.
+ */
+ char sddl_string[sizeof(SDDL_FMT) + 8 + SECURITY_MAX_SID_STRING_CHARACTERS];
+ struct
+ {
+ TOKEN_USER token_user;
+ BYTE buffer[SECURITY_MAX_SID_SIZE];
+ } token_buffer;
+ HANDLE token;
+ DWORD tmp;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
+ goto fail;
+
+ if (!GetTokenInformation(token, TokenUser, &token_buffer,
+ (DWORD) sizeof(token_buffer), &tmp))
+ goto fail;
+
+ CloseHandle(token);
+
+ char *current_user_string_sid;
+ if (!ConvertSidToStringSid(token_buffer.token_user.User.Sid,
+ &current_user_string_sid))
+ goto fail;
+
+ snprintf(sddl_string, sizeof(sddl_string), SDDL_FMT,
+ EVERYONE_PIPE_ACCESS_MASK, current_user_string_sid);
+ LocalFree(current_user_string_sid);
+
+ if (ConvertStringSecurityDescriptorToSecurityDescriptor(sddl_string,
+ SDDL_REVISION_1, &pipe_security.lpSecurityDescriptor, 0))
+ return;
+
+fail:
+ sql_perror("Can't start server : Initialize security descriptor");
+ unireg_abort(1);
+}
/**
Pipe Listener.
@@ -338,13 +396,7 @@ struct Pipe_Listener : public Listener
{
snprintf(pipe_name, sizeof(pipe_name), "\\\\.\\pipe\\%s", mysqld_unix_port);
open_mode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
- if (!ConvertStringSecurityDescriptorToSecurityDescriptorA(
- "S:(ML;; NW;;; LW) D:(A;; FRFW;;; WD)",
- 1, &pipe_security.lpSecurityDescriptor, NULL))
- {
- sql_perror("Can't start server : Initialize security descriptor");
- unireg_abort(1);
- }
+ init_pipe_security_descriptor();
pipe_security.nLength= sizeof(SECURITY_ATTRIBUTES);
pipe_security.bInheritHandle= FALSE;
}
diff --git a/sql/item.h b/sql/item.h
index 19b7b5d03e9..fb480b4c578 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -120,20 +120,19 @@ enum precedence {
XOR_PRECEDENCE, // XOR
AND_PRECEDENCE, // AND, &&
NOT_PRECEDENCE, // NOT (unless HIGH_NOT_PRECEDENCE)
- BETWEEN_PRECEDENCE, // BETWEEN, CASE, WHEN, THEN, ELSE
- CMP_PRECEDENCE, // =, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
+ CMP_PRECEDENCE, // =, <=>, >=, >, <=, <, <>, !=, IS
+ BETWEEN_PRECEDENCE, // BETWEEN
+ IN_PRECEDENCE, // IN, LIKE, REGEXP
BITOR_PRECEDENCE, // |
BITAND_PRECEDENCE, // &
SHIFT_PRECEDENCE, // <<, >>
- ADDINTERVAL_PRECEDENCE, // first argument in +INTERVAL
+ INTERVAL_PRECEDENCE, // first argument in +INTERVAL
ADD_PRECEDENCE, // +, -
MUL_PRECEDENCE, // *, /, DIV, %, MOD
BITXOR_PRECEDENCE, // ^
PIPES_PRECEDENCE, // || (if PIPES_AS_CONCAT)
- NEG_PRECEDENCE, // unary -, ~
- BANG_PRECEDENCE, // !, NOT (if HIGH_NOT_PRECEDENCE)
+ NEG_PRECEDENCE, // unary -, ~, !, NOT (if HIGH_NOT_PRECEDENCE)
COLLATE_PRECEDENCE, // BINARY, COLLATE
- INTERVAL_PRECEDENCE, // INTERVAL
DEFAULT_PRECEDENCE,
HIGHEST_PRECEDENCE
};
@@ -1716,6 +1715,8 @@ public:
mysql_register_view().
*/
virtual enum precedence precedence() const { return DEFAULT_PRECEDENCE; }
+ enum precedence higher_precedence() const
+ { return (enum precedence)(precedence() + 1); }
void print_parenthesised(String *str, enum_query_type query_type,
enum precedence parent_prec);
/**
@@ -5439,7 +5440,11 @@ public:
{
(*ref)->restore_to_before_no_rows_in_result();
}
- virtual void print(String *str, enum_query_type query_type);
+ void print(String *str, enum_query_type query_type);
+ enum precedence precedence() const
+ {
+ return ref ? (*ref)->precedence() : DEFAULT_PRECEDENCE;
+ }
void cleanup();
Item_field *field_for_view_update()
{ return (*ref)->field_for_view_update(); }
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index c753b963fd4..2b662c4de7d 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2331,7 +2331,7 @@ longlong Item_func_between::val_int_cmp_real()
void Item_func_between::print(String *str, enum_query_type query_type)
{
- args[0]->print_parenthesised(str, query_type, precedence());
+ args[0]->print_parenthesised(str, query_type, higher_precedence());
if (negated)
str->append(STRING_WITH_LEN(" not"));
str->append(STRING_WITH_LEN(" between "));
@@ -3348,27 +3348,28 @@ Item* Item_func_case_simple::propagate_equal_fields(THD *thd,
}
-void Item_func_case::print_when_then_arguments(String *str,
- enum_query_type query_type,
- Item **items, uint count)
+inline void Item_func_case::print_when_then_arguments(String *str,
+ enum_query_type
+ query_type,
+ Item **items, uint count)
{
- for (uint i=0 ; i < count ; i++)
+ for (uint i= 0; i < count; i++)
{
str->append(STRING_WITH_LEN("when "));
- items[i]->print_parenthesised(str, query_type, precedence());
+ items[i]->print(str, query_type);
str->append(STRING_WITH_LEN(" then "));
- items[i + count]->print_parenthesised(str, query_type, precedence());
+ items[i + count]->print(str, query_type);
str->append(' ');
}
}
-void Item_func_case::print_else_argument(String *str,
- enum_query_type query_type,
- Item *item)
+inline void Item_func_case::print_else_argument(String *str,
+ enum_query_type query_type,
+ Item *item)
{
str->append(STRING_WITH_LEN("else "));
- item->print_parenthesised(str, query_type, precedence());
+ item->print(str, query_type);
str->append(' ');
}
@@ -5600,12 +5601,14 @@ void Item_func_like::print(String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN(" not "));
str->append(func_name());
str->append(' ');
- args[1]->print_parenthesised(str, query_type, precedence());
if (escape_used_in_parsing)
{
+ args[1]->print_parenthesised(str, query_type, precedence());
str->append(STRING_WITH_LEN(" escape "));
- escape_item->print(str, query_type);
+ escape_item->print_parenthesised(str, query_type, higher_precedence());
}
+ else
+ args[1]->print_parenthesised(str, query_type, higher_precedence());
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index fe6cba607a7..fa715badfc7 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1,7 +1,7 @@
#ifndef ITEM_CMPFUNC_INCLUDED
#define ITEM_CMPFUNC_INCLUDED
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2009, 2016, MariaDB
+ Copyright (c) 2009, 2020, MariaDB
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
@@ -608,7 +608,7 @@ public:
enum Functype functype() const override { return NOT_FUNC; }
const char *func_name() const override { return "not"; }
bool find_not_null_fields(table_map allowed) override { return false; }
- enum precedence precedence() const override { return BANG_PRECEDENCE; }
+ enum precedence precedence() const override { return NEG_PRECEDENCE; }
Item *neg_transformer(THD *thd) override;
bool fix_fields(THD *, Item **) override;
void print(String *str, enum_query_type query_type) override;
@@ -2184,9 +2184,11 @@ protected:
bool aggregate_then_and_else_arguments(THD *thd, uint count);
virtual Item **else_expr_addr() const= 0;
virtual Item *find_item()= 0;
- void print_when_then_arguments(String *str, enum_query_type query_type,
- Item **items, uint count);
- void print_else_argument(String *str, enum_query_type query_type, Item *item);
+ inline void print_when_then_arguments(String *str,
+ enum_query_type query_type,
+ Item **items, uint count);
+ inline void print_else_argument(String *str, enum_query_type query_type,
+ Item *item);
void reorder_args(uint start);
public:
Item_func_case(THD *thd, List<Item> &list)
@@ -2202,7 +2204,6 @@ public:
bool fix_fields(THD *thd, Item **ref);
table_map not_null_tables() const { return 0; }
const char *func_name() const { return "case"; }
- enum precedence precedence() const { return BETWEEN_PRECEDENCE; }
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
bool need_parentheses_in_default() { return true; }
};
@@ -2467,7 +2468,7 @@ public:
virtual void print(String *str, enum_query_type query_type);
enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return "in"; }
- enum precedence precedence() const { return CMP_PRECEDENCE; }
+ enum precedence precedence() const { return IN_PRECEDENCE; }
bool eval_not_null_tables(void *opt_arg);
bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
@@ -2793,7 +2794,7 @@ public:
return this;
}
const char *func_name() const { return "like"; }
- enum precedence precedence() const { return CMP_PRECEDENCE; }
+ enum precedence precedence() const { return IN_PRECEDENCE; }
bool fix_fields(THD *thd, Item **ref);
bool fix_length_and_dec()
{
@@ -2902,7 +2903,7 @@ public:
longlong val_int();
bool fix_length_and_dec();
const char *func_name() const { return "regexp"; }
- enum precedence precedence() const { return CMP_PRECEDENCE; }
+ enum precedence precedence() const { return IN_PRECEDENCE; }
Item *get_copy(THD *) { return 0; }
void print(String *str, enum_query_type query_type)
{
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 8a75d2c9946..c0714bc263f 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -640,8 +640,7 @@ void Item_func::print_op(String *str, enum_query_type query_type)
str->append(func_name());
str->append(' ');
}
- args[arg_count-1]->print_parenthesised(str, query_type,
- (enum precedence)(precedence() + 1));
+ args[arg_count-1]->print_parenthesised(str, query_type, higher_precedence());
}
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index 0299adf42bc..032ecb1bb91 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -2464,6 +2464,8 @@ String *Item_func_json_merge_patch::val_str(String *str)
uint n_arg;
bool empty_result, merge_to_null;
+ /* To report errors properly if some JSON is invalid. */
+ je1.s.error= je2.s.error= 0;
merge_to_null= args[0]->null_value;
for (n_arg=1; n_arg < arg_count; n_arg++)
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 334fec2e048..cbde9599073 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -3357,7 +3357,7 @@ void Item_in_subselect::print(String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN("<exists>"));
else
{
- left_expr->print(str, query_type);
+ left_expr->print_parenthesised(str, query_type, precedence());
str->append(STRING_WITH_LEN(" in "));
}
Item_subselect::print(str, query_type);
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 7e504d09565..ec4398b9a76 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -640,7 +640,7 @@ public:
bool val_bool() override;
bool test_limit(st_select_lex_unit *unit);
void print(String *str, enum_query_type query_type) override;
- enum precedence precedence() const override { return CMP_PRECEDENCE; }
+ enum precedence precedence() const override { return IN_PRECEDENCE; }
bool fix_fields(THD *thd, Item **ref) override;
bool fix_length_and_dec() override;
void fix_after_pullout(st_select_lex *new_parent, Item **ref,
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 6b5c6fa323c..b8650a5c7e9 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2095,9 +2095,9 @@ static const char *interval_names[]=
void Item_date_add_interval::print(String *str, enum_query_type query_type)
{
- args[0]->print_parenthesised(str, query_type, ADDINTERVAL_PRECEDENCE);
+ args[0]->print_parenthesised(str, query_type, INTERVAL_PRECEDENCE);
str->append(date_sub_interval?" - interval ":" + interval ");
- args[1]->print_parenthesised(str, query_type, INTERVAL_PRECEDENCE);
+ args[1]->print(str, query_type);
str->append(' ');
str->append(interval_names[int_type]);
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 35c9df533c4..a910b2cb723 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -948,7 +948,7 @@ public:
bool fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const;
void print(String *str, enum_query_type query_type);
- enum precedence precedence() const { return ADDINTERVAL_PRECEDENCE; }
+ enum precedence precedence() const { return INTERVAL_PRECEDENCE; }
bool need_parentheses_in_default() { return true; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_date_add_interval>(thd, this); }
diff --git a/sql/mf_iocache_encr.cc b/sql/mf_iocache_encr.cc
index b27f10c7d72..072c0a48269 100644
--- a/sql/mf_iocache_encr.cc
+++ b/sql/mf_iocache_encr.cc
@@ -71,6 +71,16 @@ static int my_b_encr_read(IO_CACHE *info, uchar *Buffer, size_t Count)
DBUG_RETURN(1);
}
info->seek_not_done= 0;
+ if (info->next_file_user)
+ {
+ IO_CACHE *c;
+ for (c= info->next_file_user;
+ c!= info;
+ c= c->next_file_user)
+ {
+ c->seek_not_done= 1;
+ }
+ }
}
do
diff --git a/sql/session_tracker.cc b/sql/session_tracker.cc
index 1e5e356a5ba..de82d8be90c 100644
--- a/sql/session_tracker.cc
+++ b/sql/session_tracker.cc
@@ -445,8 +445,11 @@ bool Session_sysvars_tracker::vars_list::store(THD *thd, String *buf)
show.name= svar->name.str;
show.value= (char *) svar;
+ mysql_mutex_lock(&LOCK_global_system_variables);
const char *value= get_one_variable(thd, &show, OPT_SESSION, SHOW_SYS, NULL,
&charset, val_buf, &val_length);
+ mysql_mutex_unlock(&LOCK_global_system_variables);
+
if (is_plugin)
mysql_mutex_unlock(&LOCK_plugin);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 38c8d1f1775..fe98d98fbd4 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -1084,7 +1084,6 @@ static void store_var(Field *field, sys_var *var, enum_var_type scope,
int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond)
{
char name_buffer[NAME_CHAR_LEN];
- enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
bool res= 1;
CHARSET_INFO *scs= system_charset_info;
StringBuffer<STRING_BUFFER_USUAL_SIZE> strbuf(scs);
@@ -1095,7 +1094,6 @@ int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_ASSERT(tables->table->in_use == thd);
cond= make_cond_for_info_schema(thd, cond, tables);
- thd->count_cuted_fields= CHECK_FIELD_WARN;
mysql_prlock_rdlock(&LOCK_system_variables_hash);
for (uint i= 0; i < system_variable_hash.records; i++)
@@ -1269,7 +1267,6 @@ int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond)
res= 0;
end:
mysql_prlock_unlock(&LOCK_system_variables_hash);
- thd->count_cuted_fields= save_count_cuted_fields;
return res;
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 3958cb3fba7..2c96e0e9ff2 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -304,8 +304,9 @@ ulong role_global_merges= 0, role_db_merges= 0, role_table_merges= 0,
static void update_hostname(acl_host_and_ip *host, const char *hostname);
static bool show_proxy_grants (THD *, const char *, const char *,
char *, size_t);
-static bool show_role_grants(THD *, const char *, const char *,
+static bool show_role_grants(THD *, const char *,
ACL_USER_BASE *, char *, size_t);
+static bool show_default_role(THD *, ACL_USER *, char *, size_t);
static bool show_global_privileges(THD *, ACL_USER_BASE *,
bool, char *, size_t);
static bool show_database_privileges(THD *, const char *, const char *,
@@ -9000,7 +9001,7 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role)
{
char buff[1024];
- if (show_role_grants(thd, role->user.str, "", role, buff, sizeof(buff)))
+ if (show_role_grants(thd, "", role, buff, sizeof(buff)))
return TRUE;
if (show_global_privileges(thd, role, TRUE, buff, sizeof(buff)))
@@ -9245,7 +9246,7 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
}
/* Show granted roles to acl_user */
- if (show_role_grants(thd, username, hostname, acl_user, buff, sizeof(buff)))
+ if (show_role_grants(thd, hostname, acl_user, buff, sizeof(buff)))
goto end;
/* Add first global access grants */
@@ -9302,6 +9303,14 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
}
}
+ if (username)
+ {
+ /* Show default role to acl_user */
+ if (show_default_role(thd, acl_user, buff, sizeof(buff)))
+ goto end;
+ }
+
+
error= 0;
end:
mysql_mutex_unlock(&acl_cache->lock);
@@ -9328,15 +9337,44 @@ static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_CSTRING *u,
my_hash_search(&acl_roles_mappings, (uchar*)pair_key.ptr(), key_length);
}
-static bool show_role_grants(THD *thd, const char *username,
- const char *hostname, ACL_USER_BASE *acl_entry,
+static bool show_default_role(THD *thd, ACL_USER *acl_entry,
+ char *buff, size_t buffsize)
+{
+ Protocol *protocol= thd->protocol;
+ LEX_CSTRING def_rolename= acl_entry->default_rolename;
+
+ if (def_rolename.length)
+ {
+ String def_str(buff, buffsize, system_charset_info);
+ def_str.length(0);
+ def_str.append(STRING_WITH_LEN("SET DEFAULT ROLE "));
+ def_str.append(&def_rolename);
+ def_str.append(" FOR '");
+ def_str.append(&acl_entry->user);
+ DBUG_ASSERT(!(acl_entry->flags & IS_ROLE));
+ def_str.append(STRING_WITH_LEN("'@'"));
+ def_str.append(acl_entry->host.hostname, acl_entry->hostname_length,
+ system_charset_info);
+ def_str.append('\'');
+ protocol->prepare_for_resend();
+ protocol->store(def_str.ptr(),def_str.length(),def_str.charset());
+ if (protocol->write())
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static bool show_role_grants(THD *thd, const char *hostname,
+ ACL_USER_BASE *acl_entry,
char *buff, size_t buffsize)
{
uint counter;
Protocol *protocol= thd->protocol;
LEX_CSTRING host= {const_cast<char*>(hostname), strlen(hostname)};
- String grant(buff,sizeof(buff),system_charset_info);
+ String grant(buff, buffsize, system_charset_info);
for (counter= 0; counter < acl_entry->role_grants.elements; counter++)
{
grant.length(0);
@@ -9377,7 +9415,7 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry,
privilege_t want_access(NO_ACL);
Protocol *protocol= thd->protocol;
- String global(buff,sizeof(buff),system_charset_info);
+ String global(buff, buffsize, system_charset_info);
global.length(0);
global.append(STRING_WITH_LEN("GRANT "));
@@ -9471,7 +9509,7 @@ static bool show_database_privileges(THD *thd, const char *username,
want_access=acl_db->initial_access;
if (want_access)
{
- String db(buff,sizeof(buff),system_charset_info);
+ String db(buff, buffsize, system_charset_info);
db.length(0);
db.append(STRING_WITH_LEN("GRANT "));
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 20f1fb356a3..2769575f2cb 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1918,7 +1918,12 @@ retry_share:
DBUG_RETURN(FALSE);
}
+#ifdef WITH_WSREP
+ if (!((flags & MYSQL_OPEN_IGNORE_FLUSH) ||
+ (wsrep_on(thd) && thd->wsrep_applier)))
+#else
if (!(flags & MYSQL_OPEN_IGNORE_FLUSH))
+#endif
{
if (share->tdc->flushed)
{
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 592b53ceecf..61e3b89c9a3 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -3997,21 +3997,21 @@ bool LEX::can_not_use_merged()
}
}
-/*
- Detect that we need only table structure of derived table/view
+/**
+ Detect that we need only table structure of derived table/view.
- SYNOPSIS
- only_view_structure()
+ Also used by I_S tables (@see create_schema_table) to detect that
+ they need a full table structure and cannot optimize unused columns away
- RETURN
- TRUE yes, we need only structure
- FALSE no, we need data
+ @retval TRUE yes, we need only structure
+ @retval FALSE no, we need data
*/
bool LEX::only_view_structure()
{
switch (sql_command) {
case SQLCOM_SHOW_CREATE:
+ case SQLCOM_CHECKSUM:
case SQLCOM_SHOW_TABLES:
case SQLCOM_SHOW_FIELDS:
case SQLCOM_REVOKE_ALL:
@@ -4019,6 +4019,8 @@ bool LEX::only_view_structure()
case SQLCOM_GRANT:
case SQLCOM_CREATE_VIEW:
return TRUE;
+ case SQLCOM_CREATE_TABLE:
+ return create_info.like();
default:
return FALSE;
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 3eb28d960b3..3d43305431b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3835,6 +3835,7 @@ mysql_execute_command(THD *thd)
lex->sql_command != SQLCOM_BEGIN &&
lex->sql_command != SQLCOM_CALL &&
lex->sql_command != SQLCOM_EXECUTE &&
+ lex->sql_command != SQLCOM_EXECUTE_IMMEDIATE &&
!(sql_command_flags[lex->sql_command] & CF_AUTO_COMMIT_TRANS))
{
wsrep_start_trx_if_not_started(thd);
@@ -4407,6 +4408,11 @@ mysql_execute_command(THD *thd)
/* mysql_update return 2 if we need to switch to multi-update */
if (up_result != 2)
break;
+ if (thd->lex->period_conditions.is_set())
+ {
+ DBUG_ASSERT(0); // Should never happen
+ goto error;
+ }
}
/* fall through */
case SQLCOM_UPDATE_MULTI:
@@ -7926,7 +7932,6 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
bool is_com_multi,
bool is_next_command)
{
- int error __attribute__((unused));
DBUG_ENTER("mysql_parse");
DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on_MYSQLparse(););
DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on_ORAparse(););
@@ -8007,6 +8012,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
(char *) thd->security_ctx->host_or_ip,
0);
+ int error __attribute__((unused));
error= mysql_execute_command(thd);
MYSQL_QUERY_EXEC_DONE(error);
}
@@ -9105,8 +9111,6 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
SELECT_LEX *lex)
{
b->natural_join= a;
- a->part_of_natural_join= TRUE;
- b->part_of_natural_join= TRUE;
lex->prev_join_using= using_fields;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c54f8902976..2a856a0d51f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2785,6 +2785,10 @@ int JOIN::optimize_stage2()
(select_options & (SELECT_DESCRIBE | SELECT_NO_JOIN_CACHE)) |
(select_lex->ftfunc_list->elements ? SELECT_NO_JOIN_CACHE : 0);
+ if (select_lex->options & OPTION_SCHEMA_TABLE &&
+ optimize_schema_tables_reads(this))
+ DBUG_RETURN(1);
+
if (make_join_readinfo(this, select_opts_for_readinfo, no_jbuf_after))
DBUG_RETURN(1);
@@ -2961,10 +2965,6 @@ int JOIN::optimize_stage2()
having_is_correlated= MY_TEST(having->used_tables() & OUTER_REF_TABLE_BIT);
tmp_having= having;
- if ((select_lex->options & OPTION_SCHEMA_TABLE) &&
- optimize_schema_tables_reads(this))
- DBUG_RETURN(TRUE);
-
if (unlikely(thd->is_error()))
DBUG_RETURN(TRUE);
@@ -18172,8 +18172,7 @@ public:
bool add_schema_fields(THD *thd, TABLE *table,
TMP_TABLE_PARAM *param,
- const ST_SCHEMA_TABLE &schema_table,
- const MY_BITMAP &bitmap);
+ const ST_SCHEMA_TABLE &schema_table);
bool finalize(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
bool do_not_open, bool keep_row_order);
@@ -18282,8 +18281,7 @@ TABLE *Create_tmp_table::start(THD *thd,
No need to change table name to lower case as we are only creating
MyISAM, Aria or HEAP tables here
*/
- fn_format(path, path, mysql_tmpdir, "",
- MY_REPLACE_EXT|MY_UNPACK_FILENAME);
+ fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME);
if (m_group)
{
@@ -19105,8 +19103,7 @@ err:
bool Create_tmp_table::add_schema_fields(THD *thd, TABLE *table,
TMP_TABLE_PARAM *param,
- const ST_SCHEMA_TABLE &schema_table,
- const MY_BITMAP &bitmap)
+ const ST_SCHEMA_TABLE &schema_table)
{
DBUG_ENTER("Create_tmp_table::add_schema_fields");
DBUG_ASSERT(table);
@@ -19125,11 +19122,9 @@ bool Create_tmp_table::add_schema_fields(THD *thd, TABLE *table,
for (fieldnr= 0; !defs[fieldnr].end_marker(); fieldnr++)
{
const ST_FIELD_INFO &def= defs[fieldnr];
- bool visible= bitmap_is_set(&bitmap, fieldnr);
Record_addr addr(def.nullable());
const Type_handler *h= def.type_handler();
- Field *field= h->make_schema_field(&table->mem_root, table,
- addr, def, visible);
+ Field *field= h->make_schema_field(&table->mem_root, table, addr, def);
if (!field)
{
thd->mem_root= mem_root_save;
@@ -19192,17 +19187,16 @@ TABLE *create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
TABLE *create_tmp_table_for_schema(THD *thd, TMP_TABLE_PARAM *param,
const ST_SCHEMA_TABLE &schema_table,
- const MY_BITMAP &bitmap,
longlong select_options,
const LEX_CSTRING &table_alias,
- bool keep_row_order)
+ bool do_not_open, bool keep_row_order)
{
TABLE *table;
Create_tmp_table maker(param, (ORDER *) NULL, false, false,
select_options, HA_POS_ERROR);
if (!(table= maker.start(thd, param, &table_alias)) ||
- maker.add_schema_fields(thd, table, param, schema_table, bitmap) ||
- maker.finalize(thd, table, param, false, keep_row_order))
+ maker.add_schema_fields(thd, table, param, schema_table) ||
+ maker.finalize(thd, table, param, do_not_open, keep_row_order))
{
maker.cleanup_on_failure(thd, table);
return NULL;
@@ -19583,14 +19577,10 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
}
}
- if (unlikely((error= maria_create(share->path.str,
- file_type,
- share->keys, &keydef,
- (uint) (*recinfo-start_recinfo),
- start_recinfo,
- share->uniques, &uniquedef,
- &create_info,
- create_flags))))
+ if (unlikely((error= maria_create(share->path.str, file_type, share->keys,
+ &keydef, (uint) (*recinfo-start_recinfo),
+ start_recinfo, share->uniques, &uniquedef,
+ &create_info, create_flags))))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
table->db_stat=0;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 947863bc2d9..bb9ecf88df0 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -2436,10 +2436,9 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
bool keep_row_order= FALSE);
TABLE *create_tmp_table_for_schema(THD *thd, TMP_TABLE_PARAM *param,
const ST_SCHEMA_TABLE &schema_table,
- const MY_BITMAP &bitmap,
longlong select_options,
const LEX_CSTRING &alias,
- bool keep_row_order);
+ bool do_not_open, bool keep_row_order);
void free_tmp_table(THD *thd, TABLE *entry);
bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 794589b234c..c00476871e4 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -3675,8 +3675,6 @@ static bool show_status_array(THD *thd, const char *wild,
CHARSET_INFO *charset= system_charset_info;
DBUG_ENTER("show_status_array");
- thd->count_cuted_fields= CHECK_FIELD_WARN;
-
prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
if (*prefix)
*prefix_end++= '_';
@@ -3776,6 +3774,8 @@ static bool show_status_array(THD *thd, const char *wild,
pos= get_one_variable(thd, var, scope, show_type, status_var,
&charset, buff, &length);
+ if (table->field[1]->field_length)
+ thd->count_cuted_fields= CHECK_FIELD_WARN;
table->field[1]->store(pos, (uint32) length, charset);
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
table->field[1]->set_notnull();
@@ -8046,51 +8046,6 @@ ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx)
return &schema_tables[schema_table_idx];
}
-static void
-mark_all_fields_used_in_query(THD *thd,
- ST_FIELD_INFO *schema_fields,
- MY_BITMAP *bitmap,
- Item *all_items)
-{
- Item *item;
- DBUG_ENTER("mark_all_fields_used_in_query");
-
- /* If not SELECT command, return all columns */
- if (thd->lex->sql_command != SQLCOM_SELECT &&
- thd->lex->sql_command != SQLCOM_SET_OPTION)
- {
- bitmap_set_all(bitmap);
- DBUG_VOID_RETURN;
- }
-
- for (item= all_items ; item ; item= item->next)
- {
- if (item->type() == Item::FIELD_ITEM)
- {
- ST_FIELD_INFO *fields= schema_fields;
- uint count;
- Item_field *item_field= (Item_field*) item;
-
- /* item_field can be '*' as this function is called before fix_fields */
- if (item_field->field_name.str == star_clex_str.str)
- {
- bitmap_set_all(bitmap);
- break;
- }
- for (count=0; !fields->end_marker(); fields++, count++)
- {
- if (!my_strcasecmp(system_charset_info, fields->name().str,
- item_field->field_name.str))
- {
- bitmap_set_bit(bitmap, count);
- break;
- }
- }
- }
- }
- DBUG_VOID_RETURN;
-}
-
/**
Create information_schema table using schema_table data.
@@ -8103,7 +8058,7 @@ mark_all_fields_used_in_query(THD *thd,
0<decimals<10 and 0<=length<100 .
@param
- thd thread handler
+ thd thread handler
@param table_list Used to pass I_S table information(fields info, tables
parameters etc) and table name.
@@ -8114,32 +8069,16 @@ mark_all_fields_used_in_query(THD *thd,
TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
{
- uint field_count;
- Item *all_items;
+ uint field_count= 0;
TABLE *table;
ST_SCHEMA_TABLE *schema_table= table_list->schema_table;
- ST_FIELD_INFO *fields_info= schema_table->fields_info;
- ST_FIELD_INFO *fields;
- MY_BITMAP bitmap;
- my_bitmap_map *buf;
+ ST_FIELD_INFO *fields= schema_table->fields_info;
+ bool need_all_fieds= table_list->schema_table_reformed || // SHOW command
+ thd->lex->only_view_structure(); // need table structure
DBUG_ENTER("create_schema_table");
- for (field_count= 0, fields= fields_info; !fields->end_marker(); fields++)
+ for (; !fields->end_marker(); fields++)
field_count++;
- if (!(buf= (my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count))))
- DBUG_RETURN(NULL);
- my_bitmap_init(&bitmap, buf, field_count, 0);
-
- if (!thd->stmt_arena->is_conventional() &&
- thd->mem_root != thd->stmt_arena->mem_root)
- all_items= thd->stmt_arena->free_list;
- else
- all_items= thd->free_list;
-
- if (table_list->part_of_natural_join)
- bitmap_set_all(&bitmap);
- else
- mark_all_fields_used_in_query(thd, fields_info, &bitmap, all_items);
TMP_TABLE_PARAM *tmp_table_param = new (thd->mem_root) TMP_TABLE_PARAM;
tmp_table_param->init();
@@ -8148,13 +8087,9 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
tmp_table_param->schema_table= 1;
SELECT_LEX *select_lex= table_list->select_lex;
bool keep_row_order= is_show_command(thd);
- if (!(table= create_tmp_table_for_schema(thd, tmp_table_param,
- *schema_table, bitmap,
- (select_lex->options |
- thd->variables.option_bits |
- TMP_TABLE_ALL_COLUMNS),
- table_list->alias,
- keep_row_order)))
+ if (!(table= create_tmp_table_for_schema(thd, tmp_table_param, *schema_table,
+ (select_lex->options | thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS),
+ table_list->alias, !need_all_fieds, keep_row_order)))
DBUG_RETURN(0);
my_bitmap_map* bitmaps=
(my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count));
@@ -8546,6 +8481,68 @@ end:
}
+static int optimize_schema_tables_memory_usage(TABLE_LIST *table_list)
+{
+ TABLE *table= table_list->table;
+ THD *thd=table->in_use;
+ if (!table->is_created())
+ {
+ TMP_TABLE_PARAM *p= table_list->schema_table_param;
+ TMP_ENGINE_COLUMNDEF *from_recinfo, *to_recinfo;
+ DBUG_ASSERT(table->s->keys == 0);
+ DBUG_ASSERT(table->s->uniques == 0);
+
+ // XXX HACK HACK HACK: in a stored function, RETURN (SELECT ...)
+ // enables warnings (in THD::sp_eval_expr) for the whole val_xxx/store pair,
+ // while the intention is to warn only for store(). Until this is
+ // fixed let's avoid data truncation warnings in I_S->fill_table()
+ if (thd->count_cuted_fields == CHECK_FIELD_IGNORE)
+ {
+
+ uchar *cur= table->field[0]->ptr;
+ /* first recinfo could be a NULL bitmap, not an actual Field */
+ from_recinfo= to_recinfo= p->start_recinfo + (cur != table->record[0]);
+ for (uint i=0; i < table->s->fields; i++, from_recinfo++)
+ {
+ Field *field= table->field[i];
+ DBUG_ASSERT(field->vcol_info == 0);
+ DBUG_ASSERT(from_recinfo->length);
+ DBUG_ASSERT(from_recinfo->length == field->pack_length_in_rec());
+ if (bitmap_is_set(table->read_set, i))
+ {
+ field->move_field(cur);
+ *to_recinfo++= *from_recinfo;
+ cur+= from_recinfo->length;
+ }
+ else
+ {
+ field= new (thd->mem_root) Field_string(cur, 0, field->null_ptr,
+ field->null_bit, Field::NONE,
+ &field->field_name, field->dtcollation());
+ field->init(table);
+ field->field_index= i;
+ DBUG_ASSERT(field->pack_length_in_rec() == 0);
+ table->field[i]= field;
+ }
+ }
+ if ((table->s->reclength= (ulong)(cur - table->record[0])) == 0)
+ {
+ /* all fields were optimized away. Force a non-0-length row */
+ table->s->reclength= to_recinfo->length= 1;
+ to_recinfo++;
+ }
+ p->recinfo= to_recinfo;
+ } // XXX end of HACK HACK HACK
+
+ // TODO switch from Aria to Memory if all blobs were optimized away?
+ if (instantiate_tmp_table(table, p->keyinfo, p->start_recinfo, &p->recinfo,
+ table_list->select_lex->options | thd->variables.option_bits))
+ return 1;
+ }
+ return 0;
+}
+
+
/*
This is the optimizer part of get_schema_tables_result().
*/
@@ -8566,6 +8563,9 @@ bool optimize_schema_tables_reads(JOIN *join)
TABLE_LIST *table_list= tab->table->pos_in_table_list;
if (table_list->schema_table && thd->fill_information_schema_tables())
{
+ if (optimize_schema_tables_memory_usage(table_list))
+ DBUG_RETURN(1);
+
/* A value of 0 indicates a dummy implementation */
if (table_list->schema_table->fill_table == 0)
continue;
@@ -8588,10 +8588,10 @@ bool optimize_schema_tables_reads(JOIN *join)
cond= tab->cache_select->cond;
}
if (optimize_for_get_all_tables(thd, table_list, cond))
- DBUG_RETURN(TRUE); // Handle OOM
+ DBUG_RETURN(1); // Handle OOM
}
}
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(0);
}
@@ -8656,13 +8656,10 @@ bool get_schema_tables_result(JOIN *join,
continue;
/*
- If schema table is already processed and
- the statement is not a subselect then
- we don't need to fill this table again.
- If schema table is already processed and
- schema_table_state != executed_place then
- table is already processed and
- we should skip second data processing.
+ If schema table is already processed and the statement is not a
+ subselect then we don't need to fill this table again. If schema table
+ is already processed and schema_table_state != executed_place then
+ table is already processed and we should skip second data processing.
*/
if (table_list->schema_table_state &&
(!is_subselect || table_list->schema_table_state != executed_place))
@@ -8724,8 +8721,7 @@ bool get_schema_tables_result(JOIN *join,
It also means that an audit plugin cannot process the error correctly
either. See also thd->clear_error()
*/
- thd->get_stmt_da()->push_warning(thd,
- thd->get_stmt_da()->sql_errno(),
+ thd->get_stmt_da()->push_warning(thd, thd->get_stmt_da()->sql_errno(),
thd->get_stmt_da()->get_sqlstate(),
Sql_condition::WARN_LEVEL_ERROR,
thd->get_stmt_da()->message());
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 32bb7c4cbf7..00b9c71cc37 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -2655,8 +2655,7 @@ Field *Type_handler_set::make_conversion_table_field(MEM_ROOT *root,
Field *Type_handler_enum::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
const Typelib *typelib= def.typelib();
@@ -3861,8 +3860,7 @@ Field *Type_handler_set::make_table_field(MEM_ROOT *root,
Field *Type_handler_float::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
return new (root)
@@ -3876,8 +3874,7 @@ Field *Type_handler_float::make_schema_field(MEM_ROOT *root, TABLE *table,
Field *Type_handler_double::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
return new (root)
@@ -3892,8 +3889,7 @@ Field *Type_handler_double::make_schema_field(MEM_ROOT *root, TABLE *table,
Field *Type_handler_decimal_result::make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
uint dec= def.decimal_scale();
@@ -3909,28 +3905,20 @@ Field *Type_handler_decimal_result::make_schema_field(MEM_ROOT *root,
Field *Type_handler_blob_common::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
- if (show_field)
- {
- return new (root)
- Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(),
- Field::NONE, &name, table->s,
- length_bytes(),
- &my_charset_bin);
- }
- else
- return new (root)
- Field_null(addr.ptr(), 0, Field::NONE, &name, &my_charset_bin);
+ return new (root)
+ Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(),
+ Field::NONE, &name, table->s,
+ length_bytes(),
+ &my_charset_bin);
}
Field *Type_handler_varchar::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
DBUG_ASSERT(def.char_length());
LEX_CSTRING name= def.name();
@@ -3944,7 +3932,7 @@ Field *Type_handler_varchar::make_schema_field(MEM_ROOT *root, TABLE *table,
field->field_length= octet_length;
return field;
}
- else if (show_field)
+ else
{
return new (root)
Field_varstring(addr.ptr(), octet_length,
@@ -3953,16 +3941,12 @@ Field *Type_handler_varchar::make_schema_field(MEM_ROOT *root, TABLE *table,
Field::NONE, &name,
table->s, system_charset_info);
}
- else
- return new (root)
- Field_null(addr.ptr(), 0, Field::NONE, &name, system_charset_info);
}
Field *Type_handler_tiny::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
return new (root)
@@ -3974,8 +3958,7 @@ Field *Type_handler_tiny::make_schema_field(MEM_ROOT *root, TABLE *table,
Field *Type_handler_short::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
return new (root)
@@ -3987,8 +3970,7 @@ Field *Type_handler_short::make_schema_field(MEM_ROOT *root, TABLE *table,
Field *Type_handler_long::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
return new (root)
@@ -4000,8 +3982,7 @@ Field *Type_handler_long::make_schema_field(MEM_ROOT *root, TABLE *table,
Field *Type_handler_longlong::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
return new (root)
@@ -4013,8 +3994,7 @@ Field *Type_handler_longlong::make_schema_field(MEM_ROOT *root, TABLE *table,
Field *Type_handler_date_common::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
return new (root)
@@ -4025,8 +4005,7 @@ Field *Type_handler_date_common::make_schema_field(MEM_ROOT *root, TABLE *table,
Field *Type_handler_time_common::make_schema_field(MEM_ROOT *root, TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
return new_Field_time(root,
@@ -4038,8 +4017,7 @@ Field *Type_handler_time_common::make_schema_field(MEM_ROOT *root, TABLE *table,
Field *Type_handler_datetime_common::make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
LEX_CSTRING name= def.name();
return new (root) Field_datetimef(addr.ptr(),
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 7b541962bac..1db503b926e 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -3934,8 +3934,7 @@ public:
virtual Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const
+ const ST_FIELD_INFO &def) const
{
DBUG_ASSERT(0);
return NULL;
@@ -4817,8 +4816,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *)
const override;
void make_sort_key_part(uchar *to, Item *item,
@@ -5477,8 +5475,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
@@ -5529,8 +5526,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
@@ -5581,8 +5577,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
@@ -5648,8 +5643,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
@@ -5879,8 +5873,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
@@ -5935,8 +5928,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
@@ -5991,8 +5983,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Item_literal *create_literal_item(THD *thd, const char *str, size_t length,
CHARSET_INFO *cs, bool send_error)
const override;
@@ -6202,8 +6193,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Item_literal *create_literal_item(THD *thd, const char *str, size_t length,
CHARSET_INFO *cs, bool send_error)
const override;
@@ -6333,8 +6323,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const override;
bool validate_implicit_default_value(THD *thd, const Column_definition &def)
@@ -6909,8 +6898,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
@@ -7030,8 +7018,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
@@ -7214,8 +7201,7 @@ public:
Field *make_schema_field(MEM_ROOT *root,
TABLE *table,
const Record_addr &addr,
- const ST_FIELD_INFO &def,
- bool show_field) const override;
+ const ST_FIELD_INFO &def) const override;
};
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 2d360849928..9e6a1cd3bb4 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -189,6 +189,13 @@ static bool check_fields(THD *thd, TABLE_LIST *table, List<Item> &items,
my_error(ER_IT_IS_A_VIEW, MYF(0), table->table_name.str);
return TRUE;
}
+ if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "updating and querying the same temporal periods table");
+
+ return true;
+ }
DBUG_ASSERT(thd->lex->sql_command == SQLCOM_UPDATE);
for (List_iterator_fast<Item> it(items); (item=it++);)
{
@@ -419,6 +426,14 @@ int mysql_update(THD *thd,
DBUG_PRINT("info", ("Switch to multi-update"));
/* pass counter value */
thd->lex->table_count= table_count;
+ if (thd->lex->period_conditions.is_set())
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "updating and querying the same temporal periods table");
+
+ DBUG_RETURN(1);
+ }
+
/* convert to multiupdate */
DBUG_RETURN(2);
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ed361ed5df4..1b37896f18b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -115,6 +115,14 @@ int yylex(void *yylval, void *yythd);
#endif
+static Item* escape(THD *thd)
+{
+ thd->lex->escape_used= false;
+ const char *esc= thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES ? "" : "\\";
+ return new (thd->mem_root) Item_string_ascii(thd, esc, MY_TEST(esc[0]));
+}
+
+
/**
@brief Bison callback to report a syntax/OOM error
@@ -325,16 +333,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
- We should not introduce new conflicts any more.
+ We should not introduce any further shift/reduce conflicts.
*/
/* Start SQL_MODE_DEFAULT_SPECIFIC */
-%expect 37
+%expect 53
/* End SQL_MODE_DEFAULT_SPECIFIC */
/* Start SQL_MODE_ORACLE_SPECIFIC
-%expect 40
+%expect 56
End SQL_MODE_ORACLE_SPECIFIC */
@@ -1142,16 +1150,6 @@ End SQL_MODE_ORACLE_SPECIFIC */
%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
@@ -1162,10 +1160,12 @@ End SQL_MODE_ORACLE_SPECIFIC */
%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
+%nonassoc NOT_SYM
+%left '=' EQUAL_SYM GE '>' LE '<' NE
+%nonassoc IS
+%right BETWEEN_SYM
+%left LIKE SOUNDS_SYM REGEXP IN_SYM
%left '|'
%left '&'
%left SHIFT_LEFT SHIFT_RIGHT
@@ -1173,9 +1173,9 @@ End SQL_MODE_ORACLE_SPECIFIC */
%left '*' '/' '%' DIV_SYM MOD_SYM
%left '^'
%left MYSQL_CONCAT_SYM
-%left NEG '~' NOT2_SYM BINARY
-%left COLLATE_SYM
-%left SUBQUERY_AS_EXPR
+%nonassoc NEG '~' NOT2_SYM BINARY
+%nonassoc COLLATE_SYM
+%nonassoc SUBQUERY_AS_EXPR
/*
Tokens that can change their meaning from identifier to something else
@@ -1448,7 +1448,6 @@ End SQL_MODE_ORACLE_SPECIFIC */
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
@@ -9301,59 +9300,59 @@ expr:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bool_pri IS TRUE_SYM %prec IS
+ | expr 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
+ | expr 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
+ | expr 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
+ | expr 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
+ | expr 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
+ | expr 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
+ | expr IS NULL_SYM %prec PREC_BELOW_NOT
{
$$= new (thd->mem_root) Item_func_isnull(thd, $1);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bool_pri IS not NULL_SYM %prec IS
+ | expr 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
+ | bool_pri
+ ;
+
+bool_pri:
+ bool_pri EQUAL_SYM predicate %prec EQUAL_SYM
{
$$= new (thd->mem_root) Item_func_equal(thd, $1, $3);
if (unlikely($$ == NULL))
@@ -9375,42 +9374,42 @@ bool_pri:
;
predicate:
- bit_expr IN_SYM subquery
+ predicate IN_SYM subquery
{
$$= new (thd->mem_root) Item_in_subselect(thd, $1, $3);
- if (unlikely($$ == NULL))
+ if (unlikely(!$$))
MYSQL_YYABORT;
}
- | bit_expr not IN_SYM subquery
+ | predicate not IN_SYM subquery
{
Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $4);
- if (unlikely(item == NULL))
+ if (unlikely(!item))
MYSQL_YYABORT;
$$= negate_expression(thd, item);
- if (unlikely($$ == NULL))
+ if (unlikely(!$$))
MYSQL_YYABORT;
}
- | bit_expr IN_SYM '(' expr ')'
+ | predicate IN_SYM '(' expr ')'
{
$$= handle_sql2003_note184_exception(thd, $1, true, $4);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bit_expr IN_SYM '(' expr ',' expr_list ')'
- {
+ | predicate 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 ')'
+ | predicate 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 ')'
+ | predicate not IN_SYM '(' expr ',' expr_list ')'
{
$7->push_front($5, thd->mem_root);
$7->push_front($1, thd->mem_root);
@@ -9419,13 +9418,13 @@ predicate:
MYSQL_YYABORT;
$$= item->neg_transformer(thd);
}
- | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
+ | predicate BETWEEN_SYM predicate AND_SYM predicate %prec BETWEEN_SYM
{
$$= 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
+ | predicate not BETWEEN_SYM predicate AND_SYM predicate %prec BETWEEN_SYM
{
Item_func_between *item;
item= new (thd->mem_root) Item_func_between(thd, $1, $4, $6);
@@ -9433,7 +9432,7 @@ predicate:
MYSQL_YYABORT;
$$= item->neg_transformer(thd);
}
- | bit_expr SOUNDS_SYM LIKE bit_expr
+ | predicate SOUNDS_SYM LIKE predicate
{
Item *item1= new (thd->mem_root) Item_func_soundex(thd, $1);
Item *item4= new (thd->mem_root) Item_func_soundex(thd, $4);
@@ -9443,28 +9442,41 @@ predicate:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bit_expr LIKE bit_expr opt_escape
+ | predicate LIKE predicate
{
- $$= new (thd->mem_root) Item_func_like(thd, $1, $3, $4,
- Lex->escape_used);
- if (unlikely($$ == NULL))
+ $$= new (thd->mem_root) Item_func_like(thd, $1, $3, escape(thd), false);
+ if (unlikely(!$$))
MYSQL_YYABORT;
}
- | bit_expr not LIKE bit_expr opt_escape
+ | predicate LIKE predicate ESCAPE_SYM predicate %prec LIKE
{
- Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $5,
- Lex->escape_used);
- if (unlikely(item == NULL))
+ Lex->escape_used= true;
+ $$= new (thd->mem_root) Item_func_like(thd, $1, $3, $5, true);
+ if (unlikely(!$$))
+ MYSQL_YYABORT;
+ }
+ | predicate not LIKE predicate
+ {
+ Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, escape(thd), false);
+ if (unlikely(!item))
+ MYSQL_YYABORT;
+ $$= item->neg_transformer(thd);
+ }
+ | predicate not LIKE predicate ESCAPE_SYM predicate %prec LIKE
+ {
+ Lex->escape_used= true;
+ Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $6, true);
+ if (unlikely(!item))
MYSQL_YYABORT;
$$= item->neg_transformer(thd);
}
- | bit_expr REGEXP bit_expr
+ | predicate REGEXP predicate
{
$$= new (thd->mem_root) Item_func_regex(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bit_expr not REGEXP bit_expr
+ | predicate not REGEXP predicate
{
Item *item= new (thd->mem_root) Item_func_regex(thd, $1, $4);
if (unlikely(item == NULL))
@@ -11907,23 +11919,6 @@ opt_having_clause:
}
;
-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
*/
diff --git a/sql/table.h b/sql/table.h
index 7edf1e68a0b..ec865f2e3ce 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -2244,7 +2244,6 @@ struct TABLE_LIST
parsing 'this' is a NATURAL/USING join iff (natural_join != NULL).
*/
TABLE_LIST *natural_join;
- bool part_of_natural_join;
/*
True if 'this' represents a nested join that is a NATURAL JOIN.
For one of the operands of 'this', the member 'natural_join' points