summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc187
1 files changed, 111 insertions, 76 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index af62e1a199f..6576324c16e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2,8 +2,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -381,9 +380,9 @@ int check_user(THD *thd, enum enum_server_command command,
NO_ACCESS)) // authentication is OK
{
DBUG_PRINT("info",
- ("Capabilities: %d packet_length: %ld Host: '%s' "
+ ("Capabilities: %lu packet_length: %ld Host: '%s' "
"Login user: '%s' Priv_user: '%s' Using password: %s "
- "Access: %u db: '%s'",
+ "Access: %lu db: '%s'",
thd->client_capabilities,
thd->max_client_packet_length,
thd->main_security_ctx.host_or_ip,
@@ -956,7 +955,7 @@ static int check_connection(THD *thd)
if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
thd->variables.sql_mode|= MODE_IGNORE_SPACE;
#ifdef HAVE_OPENSSL
- DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities));
+ DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
if (thd->client_capabilities & CLIENT_SSL)
{
/* Do the SSL layering. */
@@ -1112,7 +1111,7 @@ pthread_handler_t handle_one_connection(void *arg)
of handle_one_connection, which is thd. We need to know the
start of the stack so that we could check for stack overruns.
*/
- DBUG_PRINT("info", ("handle_one_connection called by thread %d\n",
+ DBUG_PRINT("info", ("handle_one_connection called by thread %lu\n",
thd->thread_id));
/* now that we've called my_thread_init(), it is safe to call DBUG_* */
@@ -1764,7 +1763,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (alloc_query(thd, packet, packet_length))
break; // fatal error is set
char *packet_end= thd->query + thd->query_length;
- mysql_log.write(thd,command, "%.*b", thd->query_length, thd->query);
+ /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
+ const char *format= "%.*b";
+ mysql_log.write(thd,command, format, thd->query_length, thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query));
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -2503,7 +2504,23 @@ mysql_execute_command(THD *thd)
{
/* we warn the slave SQL thread */
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
- reset_one_shot_variables(thd);
+ if (thd->one_shot_set)
+ {
+ /*
+ It's ok to check thd->one_shot_set here:
+
+ The charsets in a MySQL 5.0 slave can change by both a binlogged
+ SET ONE_SHOT statement and the event-internal charset setting,
+ and these two ways to change charsets do not seems to work
+ together.
+
+ At least there seems to be problems in the rli cache for
+ charsets if we are using ONE_SHOT. Note that this is normally no
+ problem because either the >= 5.0 slave reads a 4.1 binlog (with
+ ONE_SHOT) *or* or 5.0 binlog (without ONE_SHOT) but never both."
+ */
+ reset_one_shot_variables(thd);
+ }
DBUG_RETURN(0);
}
}
@@ -2882,6 +2899,12 @@ mysql_execute_command(THD *thd)
goto end_with_restore_list;
#ifndef HAVE_READLINK
+ if (lex->create_info.data_file_name)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "DATA DIRECTORY option ignored");
+ if (lex->create_info.index_file_name)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "INDEX DIRECTORY option ignored");
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
#else
/* Fix names if symlinked tables */
@@ -3436,8 +3459,12 @@ end_with_restore_list:
if (first_table->lock_type == TL_WRITE_CONCURRENT_INSERT &&
thd->lock)
{
+ /* INSERT ... SELECT should invalidate only the very first table */
+ TABLE_LIST *save_table= first_table->next_local;
+ first_table->next_local= 0;
mysql_unlock_tables(thd, thd->lock);
query_cache_invalidate3(thd, first_table, 1);
+ first_table->next_local= save_table;
thd->lock=0;
}
delete result;
@@ -4018,8 +4045,9 @@ end_with_restore_list:
case SQLCOM_FLUSH:
{
bool write_to_binlog;
- if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, all_tables))
+ if (check_global_access(thd,RELOAD_ACL))
goto error;
+
/*
reload_acl_and_cache() will tell us if we are allowed to write to the
binlog or not.
@@ -4040,7 +4068,8 @@ end_with_restore_list:
}
}
send_ok(thd);
- }
+ }
+
break;
}
case SQLCOM_KILL:
@@ -4222,26 +4251,38 @@ end_with_restore_list:
{
uint namelen;
char *name;
- int result;
+ int result= SP_INTERNAL_ERROR;
DBUG_ASSERT(lex->sphead != 0);
DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
-
- if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
- is_schema_db(lex->sphead->m_db.str)))
+ /*
+ Verify that the database name is allowed, optionally
+ lowercase it.
+ */
+ if (check_db_name(lex->sphead->m_db.str))
{
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
+ goto create_sp_error;
}
- if (end_active_trans(thd))
+ /*
+ Check that a database directory with this name
+ exists. Design note: This won't work on virtual databases
+ like information_schema.
+ */
+ if (check_db_dir_existence(lex->sphead->m_db.str))
{
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
+ my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
+ goto create_sp_error;
}
+ if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
+ is_schema_db(lex->sphead->m_db.str)))
+ goto create_sp_error;
+
+ if (end_active_trans(thd))
+ goto create_sp_error;
+
name= lex->sphead->name(&namelen);
#ifdef HAVE_DLOPEN
if (lex->sphead->m_type == TYPE_ENUM_FUNCTION)
@@ -4250,10 +4291,8 @@ end_with_restore_list:
if (udf)
{
- my_error(ER_UDF_EXISTS, MYF(0), name);
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
+ my_error(ER_UDF_EXISTS, MYF(0), name);
+ goto create_sp_error;
}
}
#endif
@@ -4261,7 +4300,7 @@ end_with_restore_list:
/*
If the definer is not specified, this means that CREATE-statement missed
DEFINER-clause. DEFINER-clause can be missed in two cases:
-
+
- The user submitted a statement w/o the clause. This is a normal
case, we should assign CURRENT_USER as definer.
@@ -4270,7 +4309,7 @@ end_with_restore_list:
CURRENT_USER as definer here, but also we should mark this routine
as NON-SUID. This is essential for the sake of backward
compatibility.
-
+
The problem is the slave thread is running under "special" user (@),
that actually does not exist. In the older versions we do not fail
execution of a stored routine if its definer does not exist and
@@ -4295,13 +4334,9 @@ end_with_restore_list:
if (ps_arena)
thd->restore_active_arena(ps_arena, &original_arena);
+ /* Error has been already reported. */
if (res)
- {
- /* Error has been already reported. */
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- }
+ goto create_sp_error;
if (thd->slave_thread)
lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
@@ -4312,7 +4347,7 @@ end_with_restore_list:
that the current user has SUPER privilege (in order to create a stored
routine under another user one must have SUPER privilege).
*/
-
+
else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
my_strcasecmp(system_charset_info,
lex->definer->host.str,
@@ -4321,9 +4356,7 @@ end_with_restore_list:
if (check_global_access(thd, SUPER_ACL))
{
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
+ goto create_sp_error;
}
}
@@ -4343,54 +4376,51 @@ end_with_restore_list:
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
res= (result= lex->sphead->create(thd));
- if (result == SP_OK)
- {
+ switch (result) {
+ case SP_OK:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* only add privileges if really neccessary */
if (sp_automatic_privileges && !opt_noacl &&
check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
- lex->sphead->m_db.str, name,
+ lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
{
- close_thread_tables(thd);
if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE))
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_PROC_AUTO_GRANT_FAIL,
- ER(ER_PROC_AUTO_GRANT_FAIL));
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_PROC_AUTO_GRANT_FAIL,
+ ER(ER_PROC_AUTO_GRANT_FAIL));
+ close_thread_tables(thd);
}
#endif
- lex->unit.cleanup();
- delete lex->sphead;
- lex->sphead= 0;
- send_ok(thd);
- }
- else
- {
- switch (result) {
- case SP_WRITE_ROW_FAILED:
- my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
- break;
- case SP_NO_DB_ERROR:
- my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
- break;
- case SP_BAD_IDENTIFIER:
- my_error(ER_TOO_LONG_IDENT, MYF(0), name);
- break;
- case SP_BODY_TOO_LONG:
- my_error(ER_TOO_LONG_BODY, MYF(0), name);
- break;
- default:
- my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
- break;
- }
- lex->unit.cleanup();
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- }
break;
- }
+ case SP_WRITE_ROW_FAILED:
+ my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
+ break;
+ case SP_BAD_IDENTIFIER:
+ my_error(ER_TOO_LONG_IDENT, MYF(0), name);
+ break;
+ case SP_BODY_TOO_LONG:
+ my_error(ER_TOO_LONG_BODY, MYF(0), name);
+ break;
+ default:
+ my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
+ break;
+ } /* end switch */
+
+ /*
+ Capture all errors within this CASE and
+ clean up the environment.
+ */
+create_sp_error:
+ lex->unit.cleanup();
+ delete lex->sphead;
+ lex->sphead= 0;
+ if (result != SP_OK )
+ goto error;
+ send_ok(thd);
+ break; /* break super switch */
+ } /* end case group bracket */
case SQLCOM_CALL:
{
sp_head *sp;
@@ -6120,7 +6150,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->alias= alias_str;
if (lower_case_table_names && table->table.length)
- my_casedn_str(files_charset_info, table->table.str);
+ table->table.length= my_casedn_str(files_charset_info, table->table.str);
ptr->table_name=table->table.str;
ptr->table_name_length=table->table.length;
ptr->lock_type= lock_type;
@@ -6709,7 +6739,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
tmp_write_to_binlog= 0;
mysql_log.new_file(1);
mysql_slow_log.new_file(1);
- mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+ if( mysql_bin_log.is_open() )
+ {
+ mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+ }
#ifdef HAVE_REPLICATION
pthread_mutex_lock(&LOCK_active_mi);
rotate_relay_log(active_mi);
@@ -7011,6 +7044,7 @@ bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
+ create_info.row_type= ROW_TYPE_NOT_USED;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
&create_info, table_list,
fields, keys, 0, (ORDER*)0,
@@ -7027,6 +7061,7 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
+ create_info.row_type= ROW_TYPE_NOT_USED;
alter_info->clear();
alter_info->flags= ALTER_DROP_INDEX;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,