1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-comeng-unification

into  zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-recentcommmerge


BitKeeper/deleted/.del-ha_berkeley.cc:
  Auto merged
BitKeeper/deleted/.del-mysqld.vcproj~6aa7b3f9c3e28fcb:
  Auto merged
BitKeeper/triggers/post-commit:
  Auto merged
client/mysqlcheck.c:
  Auto merged
include/config-win.h:
  Auto merged
include/my_dbug.h:
  Auto merged
libmysqld/Makefile.am:
  Auto merged
mysql-test/r/func_in.result:
  Auto merged
mysql-test/r/information_schema.result:
  Auto merged
mysql-test/r/information_schema_db.result:
  Auto merged
mysql-test/t/func_in.test:
  Auto merged
mysql-test/t/information_schema.test:
  Auto merged
sql/Makefile.am:
  Auto merged
sql/ha_ndbcluster.cc:
  Auto merged
sql/item_cmpfunc.cc:
  Auto merged
sql/item_func.cc:
  Auto merged
sql/lock.cc:
  Auto merged
sql/log_event.cc:
  Auto merged
sql/repl_failsafe.cc:
  Auto merged
sql/set_var.h:
  Auto merged
sql/sp_head.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_delete.cc:
  Auto merged
sql/sql_insert.cc:
  Auto merged
sql/sql_lex.cc:
  Auto merged
sql/sql_prepare.cc:
  Auto merged
sql/sql_repl.cc:
  Auto merged
sql/sql_view.cc:
  Auto merged
sql/structs.h:
  Auto merged
sql/table.h:
  Auto merged
storage/archive/ha_archive.cc:
  Auto merged
storage/myisam/ha_myisam.cc:
  Auto merged
storage/myisam/mi_open.c:
  Auto merged
storage/myisammrg/ha_myisammrg.cc:
  Auto merged
storage/ndb/src/common/util/File.cpp:
  Auto merged
configure.in:
  Manual merge.
sql/CMakeLists.txt:
  Manual merge.
sql/mysql_priv.h:
  Manual merge.
sql/mysqld.cc:
  Manual merge.
sql/set_var.cc:
  Manual merge.
sql/slave.cc:
  Manual merge.
sql/sql_cache.cc:
  Manual merge.
sql/sql_class.cc:
  Manual merge.
sql/sql_lex.h:
  Manual merge.
sql/sql_parse.cc:
  Manual merge.
sql/sql_select.cc:
  Manual merge.
sql/sql_show.cc:
  Manual merge.
sql/sql_table.cc:
  Manual merge.
sql/sql_update.cc:
  Manual merge.
sql/sql_yacc.yy:
  Manual merge.
This commit is contained in:
unknown
2007-10-17 14:05:43 -04:00
2610 changed files with 159083 additions and 65835 deletions

View File

@@ -112,7 +112,6 @@ public:
/****************************************************************************/
/**
@class Prepared_statement
@brief Prepared_statement: a statement that can contain placeholders
*/
@@ -229,7 +228,7 @@ find_prepared_statement(THD *thd, ulong id, const char *where)
static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
{
NET *net= &stmt->thd->net;
char buff[12];
uchar buff[12];
uint tmp;
DBUG_ENTER("send_prep_stmt");
@@ -572,6 +571,8 @@ void set_param_date(Item_param *param, uchar **pos, ulong len)
static void set_param_str(Item_param *param, uchar **pos, ulong len)
{
ulong length= get_param_length(pos, len);
if (length > len)
length= len;
param->set_str((const char *)*pos, length);
*pos+= length;
}
@@ -742,6 +743,8 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array,
if (read_pos >= data_end)
DBUG_RETURN(1);
param->set_param_func(param, &read_pos, data_end - read_pos);
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
}
}
res= param->query_val_str(&str);
@@ -778,6 +781,8 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
if (read_pos >= data_end)
DBUG_RETURN(1);
param->set_param_func(param, &read_pos, data_end - read_pos);
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
}
}
if (param->convert_str_value(stmt->thd))
@@ -860,6 +865,8 @@ static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query)
client_param->length ?
*client_param->length :
client_param->buffer_length);
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
}
}
if (param->convert_str_value(thd))
@@ -902,6 +909,8 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt,
client_param->length ?
*client_param->length :
client_param->buffer_length);
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
}
}
res= param->query_val_str(&str);
@@ -946,7 +955,7 @@ static bool insert_params_from_vars(Prepared_statement *stmt,
Item_param *param= *it;
varname= var_it++;
entry= (user_var_entry*)hash_search(&stmt->thd->user_vars,
(byte*) varname->str,
(uchar*) varname->str,
varname->length);
if (param->set_from_user_var(stmt->thd, entry) ||
param->convert_str_value(stmt->thd))
@@ -981,6 +990,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
String buf;
const String *val;
uint32 length= 0;
THD *thd= stmt->thd;
DBUG_ENTER("insert_params_from_vars");
@@ -991,34 +1001,20 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
{
Item_param *param= *it;
varname= var_it++;
if (get_var_with_binlog(stmt->thd, stmt->lex->sql_command,
*varname, &entry))
DBUG_RETURN(1);
if (param->set_from_user_var(stmt->thd, entry))
entry= (user_var_entry *) hash_search(&thd->user_vars, (uchar*) varname->str,
varname->length);
/*
We have to call the setup_one_conversion_function() here to set
the parameter's members that might be needed further
(e.g. value.cs_info.character_set_client is used in the query_val_str()).
*/
setup_one_conversion_function(thd, param, param->param_type);
if (param->set_from_user_var(thd, entry))
DBUG_RETURN(1);
/* Insert @'escaped-varname' instead of parameter in the query */
if (entry)
{
char *start, *ptr;
buf.length(0);
if (buf.reserve(entry->name.length*2+3))
DBUG_RETURN(1);
val= param->query_val_str(&buf);
start= ptr= buf.c_ptr_quick();
*ptr++= '@';
*ptr++= '\'';
ptr+= escape_string_for_mysql(&my_charset_utf8_general_ci,
ptr, 0, entry->name.str,
entry->name.length);
*ptr++= '\'';
buf.length(ptr - start);
val= &buf;
}
else
val= &my_null_string;
if (param->convert_str_value(stmt->thd))
if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */
if (query->replace(param->pos_in_query+length, 1, *val))
@@ -1077,7 +1073,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
if (table_list->table)
{
// don't allocate insert_values
table_list->table->insert_values=(byte *)1;
table_list->table->insert_values=(uchar *)1;
}
if (mysql_prepare_insert(thd, table_list, table_list->table,
@@ -1164,8 +1160,9 @@ static int mysql_test_update(Prepared_statement *stmt,
goto error;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* TABLE_LIST contain right privilages request */
want_privilege= table_list->grant.want_privilege;
/* Force privilege re-checking for views after they have been opened. */
want_privilege= (table_list->view ? UPDATE_ACL :
table_list->grant.want_privilege);
#endif
if (mysql_prepare_update(thd, table_list, &select->where,
@@ -1492,8 +1489,21 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
if (select_lex->item_list.elements)
{
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
lex->link_first_table_back(create_table, link_to_local);
create_table->create= TRUE;
}
if (open_normal_and_derived_tables(stmt->thd, lex->query_tables, 0))
DBUG_RETURN(TRUE);
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
create_table= lex->unlink_first_table(&link_to_local);
select_lex->context.resolve_in_select_list= TRUE;
res= select_like_stmt_test_with_open(stmt, tables, 0, 0);
res= select_like_stmt_test(stmt, 0, 0);
}
/* put tables back for PS rexecuting */
@@ -1590,7 +1600,7 @@ static bool mysql_insert_select_prepare_tester(THD *thd)
next_local;
/* Skip first table, which is the table we are inserting in */
first_select->table_list.first= (byte *) second_table;
first_select->table_list.first= (uchar *) second_table;
thd->lex->select_lex.context.table_list=
thd->lex->select_lex.context.first_name_resolution_table= second_table;
@@ -1621,7 +1631,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt,
if (tables->table)
{
// don't allocate insert_values
tables->table->insert_values=(byte *)1;
tables->table->insert_values=(uchar *)1;
}
if (insert_precheck(stmt->thd, tables))
@@ -1636,7 +1646,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt,
&mysql_insert_select_prepare_tester,
OPTION_SETUP_TABLES_DONE);
/* revert changes made by mysql_insert_select_prepare_tester */
lex->select_lex.table_list.first= (byte*) first_local_table;
lex->select_lex.table_list.first= (uchar*) first_local_table;
return res;
}
@@ -1715,6 +1725,13 @@ static bool check_prepared_statement(Prepared_statement *stmt,
res= mysql_test_create_table(stmt);
break;
case SQLCOM_CREATE_VIEW:
if (lex->create_view_mode == VIEW_ALTER)
{
my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0));
goto error;
}
break;
case SQLCOM_DO:
res= mysql_test_do_fields(stmt, tables, lex->insert_list);
break;
@@ -1751,6 +1768,7 @@ static bool check_prepared_statement(Prepared_statement *stmt,
case SQLCOM_SHOW_CREATE_PROC:
case SQLCOM_SHOW_CREATE_FUNC:
case SQLCOM_SHOW_CREATE_EVENT:
case SQLCOM_SHOW_CREATE_TRIGGER:
case SQLCOM_SHOW_CREATE:
case SQLCOM_SHOW_PROC_CODE:
case SQLCOM_SHOW_FUNC_CODE:
@@ -1768,7 +1786,6 @@ static bool check_prepared_statement(Prepared_statement *stmt,
case SQLCOM_ROLLBACK:
case SQLCOM_TRUNCATE:
case SQLCOM_CALL:
case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_VIEW:
case SQLCOM_REPAIR:
case SQLCOM_ANALYZE:
@@ -1794,6 +1811,9 @@ static bool check_prepared_statement(Prepared_statement *stmt,
case SQLCOM_KILL:
break;
case SQLCOM_PREPARE:
case SQLCOM_EXECUTE:
case SQLCOM_DEALLOCATE_PREPARE:
default:
/*
Trivial check of all status commands. This is easier than having
@@ -1920,13 +1940,6 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length)
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
}
else
{
const char *format= "[%lu] %.*b";
general_log_print(thd, COM_STMT_PREPARE, format, stmt->id,
stmt->query_length, stmt->query);
}
/* check_prepared_statemnt sends the metadata packet in case of success */
DBUG_VOID_RETURN;
}
@@ -1970,7 +1983,7 @@ static const char *get_dynamic_sql_string(LEX *lex, uint *query_len)
*/
if ((entry=
(user_var_entry*)hash_search(&thd->user_vars,
(byte*)lex->prepared_stmt_code.str,
(uchar*)lex->prepared_stmt_code.str,
lex->prepared_stmt_code.length))
&& entry->value)
{
@@ -1999,7 +2012,7 @@ static const char *get_dynamic_sql_string(LEX *lex, uint *query_len)
len= (needs_conversion ? var_value->length() * to_cs->mbmaxlen :
var_value->length());
if (!(query_str= alloc_root(thd->mem_root, len+1)))
if (!(query_str= (char*) alloc_root(thd->mem_root, len+1)))
goto end;
if (needs_conversion)
@@ -2312,12 +2325,6 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
test(flags & (ulong) CURSOR_TYPE_READ_ONLY));
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
if (error == 0)
{
const char *format= "[%lu] %.*b";
general_log_print(thd, COM_STMT_EXECUTE, format, stmt->id,
thd->query_length, thd->query);
}
DBUG_VOID_RETURN;
set_params_data_err:
@@ -2355,7 +2362,7 @@ void mysql_sql_stmt_execute(THD *thd)
/* Query text for binary, general or slow log, if any of them is open */
String expanded_query;
DBUG_ENTER("mysql_sql_stmt_execute");
DBUG_PRINT("info", ("EXECUTE: %.*s\n", name->length, name->str));
DBUG_PRINT("info", ("EXECUTE: %.*s\n", (int) name->length, name->str));
if (!(stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
{
@@ -2416,7 +2423,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
/* First of all clear possible warnings from the previous command */
mysql_reset_thd_for_next_command(thd);
statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status);
status_var_increment(thd->status_var.com_stmt_fetch);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch")))
DBUG_VOID_RETURN;
@@ -2480,7 +2487,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
/* First of all clear possible warnings from the previous command */
mysql_reset_thd_for_next_command(thd);
statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status);
status_var_increment(thd->status_var.com_stmt_reset);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset")))
DBUG_VOID_RETURN;
@@ -2543,7 +2550,8 @@ void mysql_sql_stmt_close(THD *thd)
{
Prepared_statement* stmt;
LEX_STRING *name= &thd->lex->prepared_stmt_name;
DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", name->length, name->str));
DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", (int) name->length,
name->str));
if (! (stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
{
@@ -2584,7 +2592,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
#endif
DBUG_ENTER("mysql_stmt_get_longdata");
statistic_increment(thd->status_var.com_stmt_send_long_data, &LOCK_status);
status_var_increment(thd->status_var.com_stmt_send_long_data);
#ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */
if (packet_length <= MYSQL_LONG_DATA_HEADER)
@@ -2788,7 +2796,7 @@ void Prepared_statement::cleanup_stmt()
bool Prepared_statement::set_name(LEX_STRING *name_arg)
{
name.length= name_arg->length;
name.str= memdup_root(mem_root, (char*) name_arg->str, name_arg->length);
name.str= (char*) memdup_root(mem_root, name_arg->str, name_arg->length);
return name.str == 0;
}
@@ -2835,7 +2843,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
However, it seems handy if com_stmt_prepare is increased always,
no matter what kind of prepare is processed.
*/
statistic_increment(thd->status_var.com_stmt_prepare, &LOCK_status);
status_var_increment(thd->status_var.com_stmt_prepare);
/*
alloc_query() uses thd->memroot && thd->query, so we should call
@@ -2853,11 +2861,28 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
old_stmt_arena= thd->stmt_arena;
thd->stmt_arena= this;
lex_start(thd, thd->query, thd->query_length);
lex->stmt_prepare_mode= TRUE;
error= MYSQLparse((void *)thd) || thd->is_fatal_error ||
thd->net.report_error || init_param_array(this);
Lex_input_stream lip(thd, thd->query, thd->query_length);
lip.stmt_prepare_mode= TRUE;
lex_start(thd);
error= parse_sql(thd, &lip, NULL) ||
thd->net.report_error ||
init_param_array(this);
lex->set_trg_event_type_for_tables();
/* Remember the current database. */
if (thd->db && thd->db_length)
{
db= this->strmake(thd->db, thd->db_length);
db_length= thd->db_length;
}
else
{
db= NULL;
db_length= 0;
}
/*
While doing context analysis of the query (in check_prepared_statement)
@@ -2901,24 +2926,35 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
thd->restore_backup_statement(this, &stmt_backup);
thd->stmt_arena= old_stmt_arena;
if ((protocol->type() == Protocol::PROTOCOL_TEXT) && (param_count > 0))
{
/*
This is a mysql_sql_stmt_prepare(); query expansion will insert user
variable references, and user variables are uncacheable, thus we have to
mark this statement as uncacheable.
This has to be done before setup_set_params(), as it may make expansion
unneeded.
*/
lex->safe_to_cache_query= FALSE;
}
if (error == 0)
{
setup_set_params();
init_stmt_after_parse(lex);
state= Query_arena::PREPARED;
flags&= ~ (uint) IS_IN_USE;
/*
Log COM_EXECUTE to the general log. Note, that in case of SQL
prepared statements this causes two records to be output:
Query PREPARE stmt from @user_variable
Prepare <statement SQL text>
This is considered user-friendly, since in the
second log entry we output the actual statement text.
Do not print anything if this is an SQL prepared statement and
we're inside a stored procedure (also called Dynamic SQL) --
sub-statements inside stored procedures are not logged into
the general log.
*/
if (thd->spcont == NULL)
{
const char *format= "[%lu] %.*b";
general_log_print(thd, COM_STMT_PREPARE, format, id,
query_length, query);
}
}
DBUG_RETURN(error);
}
@@ -2954,7 +2990,14 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
Query_arena *old_stmt_arena;
bool error= TRUE;
statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status);
char saved_cur_db_name_buf[NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
bool cur_db_changed;
LEX_STRING stmt_db_name= { db, db_length };
status_var_increment(thd->status_var.com_stmt_execute);
/* Check if we got an error when sending long data */
if (state == Query_arena::ERROR)
@@ -3002,6 +3045,21 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
*/
thd->set_n_backup_statement(this, &stmt_backup);
/*
Change the current database (if needed).
Force switching, because the database of the prepared statement may be
NULL (prepared statements can be created while no current database
selected).
*/
if (mysql_opt_change_db(thd, &stmt_db_name, &saved_cur_db_name, TRUE,
&cur_db_changed))
goto error;
/* Allocate query. */
if (expanded_query->length() &&
alloc_query(thd, (char*) expanded_query->ptr(),
expanded_query->length()+1))
@@ -3030,6 +3088,8 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
thd->protocol= protocol; /* activate stmt protocol */
/* Go! */
if (open_cursor)
error= mysql_open_cursor(thd, (uint) ALWAYS_MATERIALIZED_CURSOR,
&result, &cursor);
@@ -3048,6 +3108,17 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
}
}
/*
Restore the current database (if changed).
Force switching back to the saved current database (if changed),
because it may be NULL. In this case, mysql_change_db() would generate
an error.
*/
if (cur_db_changed)
mysql_change_db(thd, &saved_cur_db_name, TRUE);
thd->protocol= &thd->protocol_text; /* use normal protocol */
/* Assert that if an error, no cursor is open */
@@ -3065,6 +3136,28 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
if (state == Query_arena::PREPARED)
state= Query_arena::EXECUTED;
/*
Log COM_EXECUTE to the general log. Note, that in case of SQL
prepared statements this causes two records to be output:
Query EXECUTE <statement name>
Execute <statement SQL text>
This is considered user-friendly, since in the
second log entry we output values of parameter markers.
Do not print anything if this is an SQL prepared statement and
we're inside a stored procedure (also called Dynamic SQL) --
sub-statements inside stored procedures are not logged into
the general log.
*/
if (error == 0 && thd->spcont == NULL)
{
const char *format= "[%lu] %.*b";
general_log_print(thd, COM_STMT_EXECUTE, format, id,
thd->query_length, thd->query);
}
error:
flags&= ~ (uint) IS_IN_USE;
return error;
@@ -3076,7 +3169,7 @@ error:
bool Prepared_statement::deallocate()
{
/* We account deallocate in the same manner as mysql_stmt_close */
statistic_increment(thd->status_var.com_stmt_close, &LOCK_status);
status_var_increment(thd->status_var.com_stmt_close);
if (flags & (uint) IS_IN_USE)
{
my_error(ER_PS_NO_RECURSION, MYF(0));