diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-10-30 11:15:30 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-10-30 11:15:30 +0200 |
commit | 898521e2dd8a4a6706cba01b6ef0a7cea4114fd0 (patch) | |
tree | 4ef9a6ddc4298574bb75db673c2412f83c107c5b /sql | |
parent | 571bcf9aaaf59b84e24bbfb809738dea25495d78 (diff) | |
parent | 199863d72b7cccaa4c75641c50c45a83b568ab8c (diff) | |
download | mariadb-git-898521e2dd8a4a6706cba01b6ef0a7cea4114fd0.tar.gz |
Merge 10.4 into 10.5
Diffstat (limited to 'sql')
-rw-r--r-- | sql/CMakeLists.txt | 2 | ||||
-rw-r--r-- | sql/handle_connections_win.cc | 66 | ||||
-rw-r--r-- | sql/item.h | 19 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 29 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 19 | ||||
-rw-r--r-- | sql/item_func.cc | 3 | ||||
-rw-r--r-- | sql/item_jsonfunc.cc | 2 | ||||
-rw-r--r-- | sql/item_subselect.cc | 2 | ||||
-rw-r--r-- | sql/item_subselect.h | 2 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 4 | ||||
-rw-r--r-- | sql/item_timefunc.h | 2 | ||||
-rw-r--r-- | sql/mf_iocache_encr.cc | 10 | ||||
-rw-r--r-- | sql/session_tracker.cc | 3 | ||||
-rw-r--r-- | sql/set_var.cc | 3 | ||||
-rw-r--r-- | sql/sql_acl.cc | 54 | ||||
-rw-r--r-- | sql/sql_base.cc | 5 | ||||
-rw-r--r-- | sql/sql_lex.cc | 16 | ||||
-rw-r--r-- | sql/sql_parse.cc | 10 | ||||
-rw-r--r-- | sql/sql_select.cc | 40 | ||||
-rw-r--r-- | sql/sql_select.h | 3 | ||||
-rw-r--r-- | sql/sql_show.cc | 170 | ||||
-rw-r--r-- | sql/sql_type.cc | 60 | ||||
-rw-r--r-- | sql/sql_type.h | 42 | ||||
-rw-r--r-- | sql/sql_update.cc | 15 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 141 | ||||
-rw-r--r-- | sql/table.h | 1 |
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, + ¤t_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 |