1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge bb-10.2-ext into 10.3

This commit is contained in:
Marko Mäkelä
2017-06-19 17:28:08 +03:00
725 changed files with 17193 additions and 16743 deletions

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
Copyright (c) 2008, 2016, MariaDB
Copyright (c) 2008, 2017, 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
@ -164,7 +164,6 @@ public:
Server_side_cursor *cursor;
uchar *packet;
uchar *packet_end;
ulong iterations;
uint param_count;
uint last_errno;
uint flags;
@ -183,7 +182,9 @@ public:
*/
uint select_number_after_prepare;
char last_error[MYSQL_ERRMSG_SIZE];
my_bool iterations;
my_bool start_param;
my_bool read_types;
#ifndef EMBEDDED_LIBRARY
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
uchar *read_pos, String *expanded_query);
@ -213,11 +214,10 @@ public:
uchar *packet_arg, uchar *packet_end_arg);
bool execute_bulk_loop(String *expanded_query,
bool open_cursor,
uchar *packet_arg, uchar *packet_end_arg,
ulong iterations);
uchar *packet_arg, uchar *packet_end_arg);
bool execute_server_runnable(Server_runnable *server_runnable);
my_bool set_bulk_parameters(bool reset);
ulong bulk_iterations();
bool bulk_iterations() { return iterations; };
/* Destroy this statement */
void deallocate();
bool execute_immediate(const char *query, uint query_length);
@ -923,6 +923,7 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
for (Item_param **it= begin; it < end; ++it)
{
Item_param *param= *it;
param->indicator= STMT_INDICATOR_NONE; // only for bulk parameters
if (!param->has_long_data_value())
{
if (is_param_null(null_array, (uint) (it - begin)))
@ -967,10 +968,7 @@ static bool insert_bulk_params(Prepared_statement *stmt,
param->reset();
if (!param->has_long_data_value())
{
if (param->indicators)
param->indicator= (enum_indicator_type) *((*read_pos)++);
else
param->indicator= STMT_INDICATOR_NONE;
param->indicator= (enum_indicator_type) *((*read_pos)++);
if ((*read_pos) > data_end)
DBUG_RETURN(1);
switch (param->indicator)
@ -981,6 +979,8 @@ static bool insert_bulk_params(Prepared_statement *stmt,
param->set_param_func(param, read_pos, (uint) (data_end - (*read_pos)));
if (param->has_no_value())
DBUG_RETURN(1);
if (param->convert_str_value(stmt->thd))
DBUG_RETURN(1); /* out of memory */
break;
case STMT_INDICATOR_NULL:
param->set_null();
@ -999,6 +999,36 @@ static bool insert_bulk_params(Prepared_statement *stmt,
DBUG_RETURN(0);
}
static bool set_conversion_functions(Prepared_statement *stmt,
uchar **data, uchar *data_end)
{
uchar *read_pos= *data;
const uint signed_bit= 1 << 15;
DBUG_ENTER("set_conversion_functions");
/*
First execute or types altered by the client, setup the
conversion routines for all parameters (one time)
*/
Item_param **it= stmt->param_array;
Item_param **end= it + stmt->param_count;
THD *thd= stmt->thd;
for (; it < end; ++it)
{
ushort typecode;
if (read_pos >= data_end)
DBUG_RETURN(1);
typecode= sint2korr(read_pos);
read_pos+= 2;
(**it).unsigned_flag= MY_TEST(typecode & signed_bit);
setup_one_conversion_function(thd, *it, (uchar) (typecode & 0xff));
}
*data= read_pos;
DBUG_RETURN(0);
}
static bool setup_conversion_functions(Prepared_statement *stmt,
uchar **data, uchar *data_end,
bool bulk_protocol= 0)
@ -1012,30 +1042,9 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
if (*read_pos++) //types supplied / first execute
{
/*
First execute or types altered by the client, setup the
conversion routines for all parameters (one time)
*/
Item_param **it= stmt->param_array;
Item_param **end= it + stmt->param_count;
THD *thd= stmt->thd;
for (; it < end; ++it)
{
ushort typecode;
const uint signed_bit= 1 << 15;
const uint indicators_bit= 1 << 14;
if (read_pos >= data_end)
DBUG_RETURN(1);
typecode= sint2korr(read_pos);
read_pos+= 2;
(**it).unsigned_flag= MY_TEST(typecode & signed_bit);
if (bulk_protocol)
(**it).indicators= MY_TEST(typecode & indicators_bit);
setup_one_conversion_function(thd, *it,
(uchar) (typecode & 0xff));
}
*data= read_pos;
bool res= set_conversion_functions(stmt, data, data_end);
DBUG_RETURN(res);
}
*data= read_pos;
DBUG_RETURN(0);
@ -2343,7 +2352,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
/* mysql_test_update returns 2 if we need to switch to multi-update */
if (res != 2)
break;
/* fall through */
case SQLCOM_UPDATE_MULTI:
res= mysql_test_multiupdate(stmt, tables, res == 2);
break;
@ -3022,6 +3031,14 @@ static void reset_stmt_params(Prepared_statement *stmt)
}
static void mysql_stmt_execute_common(THD *thd,
ulong stmt_id,
uchar *packet,
uchar *packet_end,
ulong cursor_flags,
bool iteration,
bool types);
/**
COM_STMT_EXECUTE handler: execute a previously prepared statement.
@ -3044,21 +3061,92 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround
ulong stmt_id= uint4korr(packet);
ulong flags= (ulong) packet[4];
#ifndef EMBEDDED_LIBRARY
ulong iterations= uint4korr(packet + 5);
#else
ulong iterations= 0; // no support
#endif
/* Query text for binary, general or slow log, if any of them is open */
String expanded_query;
uchar *packet_end= packet + packet_length;
Prepared_statement *stmt;
Protocol *save_protocol= thd->protocol;
bool open_cursor;
DBUG_ENTER("mysqld_stmt_execute");
packet+= 9; /* stmt_id + 5 bytes of flags */
mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, flags, FALSE,
FALSE);
DBUG_VOID_RETURN;
}
/**
COM_STMT_BULK_EXECUTE handler: execute a previously prepared statement.
If there are any parameters, then replace parameter markers with the
data supplied from the client, and then execute the statement.
This function uses binary protocol to send a possible result set
to the client.
@param thd current thread
@param packet_arg parameter types and data, if any
@param packet_length packet length, including the terminator character.
@return
none: in case of success OK packet or a result set is sent to the
client, otherwise an error message is set in THD.
*/
void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length)
{
uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround
ulong stmt_id= uint4korr(packet);
uint flags= (uint) uint2korr(packet + 4);
uchar *packet_end= packet + packet_length;
DBUG_ENTER("mysqld_stmt_execute_bulk");
if (!(thd->client_capabilities &
MARIADB_CLIENT_STMT_BULK_OPERATIONS))
{
DBUG_PRINT("error",
("An attempt to execute bulk operation without support"));
my_error(ER_UNSUPPORTED_PS, MYF(0));
}
/* Check for implemented parameters */
if (flags & (~STMT_BULK_FLAG_CLIENT_SEND_TYPES))
{
DBUG_PRINT("error", ("unsupported bulk execute flags %x", flags));
my_error(ER_UNSUPPORTED_PS, MYF(0));
}
/* stmt id and two bytes of flags */
packet+= 4 + 2;
mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, 0, TRUE,
(flags & STMT_BULK_FLAG_CLIENT_SEND_TYPES));
DBUG_VOID_RETURN;
}
/**
Common part of prepared statement execution
@param thd THD handle
@param stmt_id id of the prepared statement
@param paket packet with parameters to bind
@param packet_end pointer to the byte after parameters end
@param cursor_flags cursor flags
@param bulk_op id it bulk operation
@param read_types flag say that types muast been read
*/
static void mysql_stmt_execute_common(THD *thd,
ulong stmt_id,
uchar *packet,
uchar *packet_end,
ulong cursor_flags,
bool bulk_op,
bool read_types)
{
/* Query text for binary, general or slow log, if any of them is open */
String expanded_query;
Prepared_statement *stmt;
Protocol *save_protocol= thd->protocol;
bool open_cursor;
DBUG_ENTER("mysqld_stmt_execute_common");
DBUG_ASSERT((!read_types) || (read_types && bulk_op));
/* First of all clear possible warnings from the previous command */
thd->reset_for_next_command();
@ -3069,21 +3157,21 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
llstr(stmt_id, llbuf), "mysqld_stmt_execute");
DBUG_VOID_RETURN;
}
stmt->read_types= read_types;
#if defined(ENABLED_PROFILING)
thd->profiling.set_query_source(stmt->query(), stmt->query_length());
#endif
DBUG_PRINT("exec_query", ("%s", stmt->query()));
DBUG_PRINT("info",("stmt: %p iterations: %lu", stmt, iterations));
DBUG_PRINT("info",("stmt: %p bulk_op %d", stmt, bulk_op));
open_cursor= MY_TEST(flags & (ulong) CURSOR_TYPE_READ_ONLY);
open_cursor= MY_TEST(cursor_flags & (ulong) CURSOR_TYPE_READ_ONLY);
thd->protocol= &thd->protocol_binary;
if (iterations <= 1)
if (!bulk_op)
stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end);
else
stmt->execute_bulk_loop(&expanded_query, open_cursor, packet, packet_end,
iterations);
stmt->execute_bulk_loop(&expanded_query, open_cursor, packet, packet_end);
thd->protocol= save_protocol;
sp_cache_enforce_limit(thd->sp_proc_cache, stored_program_cache_size);
@ -3426,7 +3514,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
{
stmt->state= Query_arena::STMT_ERROR;
stmt->last_errno= thd->get_stmt_da()->sql_errno();
strncpy(stmt->last_error, thd->get_stmt_da()->message(), MYSQL_ERRMSG_SIZE);
strmake_buf(stmt->last_error, thd->get_stmt_da()->message());
}
thd->set_stmt_da(save_stmt_da);
@ -3590,11 +3678,12 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
cursor(0),
packet(0),
packet_end(0),
iterations(0),
param_count(0),
last_errno(0),
flags((uint) IS_IN_USE),
iterations(0),
start_param(0),
read_types(0),
m_sql_mode(thd->variables.sql_mode)
{
init_sql_alloc(&main_mem_root, thd_arg->variables.query_alloc_block_size,
@ -3631,7 +3720,7 @@ void Prepared_statement::setup_set_params()
set_params_from_actual_params= insert_params_from_actual_params_with_log;
#ifndef EMBEDDED_LIBRARY
set_params= insert_params_with_log;
set_bulk_params= insert_bulk_params; // TODO: add binlog support
set_bulk_params= insert_bulk_params; // RBR is on for bulk operation
#else
//TODO: add bulk support for bulk parameters
set_params_data= emb_insert_params_with_log;
@ -4013,7 +4102,7 @@ Prepared_statement::execute_loop(String *expanded_query,
Reprepare_observer reprepare_observer;
bool error;
int reprepare_attempt= 0;
iterations= 0;
iterations= FALSE;
/*
- In mysql_sql_stmt_execute() we hide all "external" Items
@ -4116,11 +4205,11 @@ my_bool bulk_parameters_set(THD *thd)
DBUG_RETURN(FALSE);
}
ulong bulk_parameters_iterations(THD *thd)
my_bool bulk_parameters_iterations(THD *thd)
{
Prepared_statement *stmt= (Prepared_statement *) thd->bulk_param;
if (!stmt)
return 1;
return FALSE;
return stmt->bulk_iterations();
}
@ -4128,7 +4217,8 @@ ulong bulk_parameters_iterations(THD *thd)
my_bool Prepared_statement::set_bulk_parameters(bool reset)
{
DBUG_ENTER("Prepared_statement::set_bulk_parameters");
DBUG_PRINT("info", ("iteration: %lu", iterations));
DBUG_PRINT("info", ("iteration: %d", iterations));
if (iterations)
{
#ifndef EMBEDDED_LIBRARY
@ -4142,31 +4232,24 @@ my_bool Prepared_statement::set_bulk_parameters(bool reset)
reset_stmt_params(this);
DBUG_RETURN(true);
}
iterations--;
if (packet >= packet_end)
iterations= FALSE;
}
start_param= 0;
DBUG_RETURN(false);
}
ulong Prepared_statement::bulk_iterations()
{
if (iterations)
return iterations;
return start_param ? 1 : 0;
}
bool
Prepared_statement::execute_bulk_loop(String *expanded_query,
bool open_cursor,
uchar *packet_arg,
uchar *packet_end_arg,
ulong iterations_arg)
uchar *packet_end_arg)
{
Reprepare_observer reprepare_observer;
bool error= 0;
packet= packet_arg;
packet_end= packet_end_arg;
iterations= iterations_arg;
iterations= TRUE;
start_param= true;
#ifndef DBUG_OFF
Item *free_list_state= thd->free_list;
@ -4180,16 +4263,26 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
thd->set_bulk_execution(0);
return TRUE;
}
/* Check for non zero parameter count*/
if (param_count == 0)
{
DBUG_PRINT("error", ("Statement with no parameters for bulk execution."));
my_error(ER_UNSUPPORTED_PS, MYF(0));
thd->set_bulk_execution(0);
return TRUE;
}
if (!(sql_command_flags[lex->sql_command] & CF_SP_BULK_SAFE))
{
DBUG_PRINT("error", ("Command is not supported in bulk execution."));
my_error(ER_UNSUPPORTED_PS, MYF(0));
thd->set_bulk_execution(0);
return TRUE;
}
#ifndef EMBEDDED_LIBRARY
if (setup_conversion_functions(this, &packet, packet_end, TRUE))
if (read_types &&
set_conversion_functions(this, &packet, packet_end))
#else
// bulk parameters are not supported for embedded, so it will an error
#endif
@ -4200,6 +4293,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
thd->set_bulk_execution(0);
return true;
}
read_types= FALSE;
#ifdef NOT_YET_FROM_MYSQL_5_6
if (unlikely(thd->security_ctx->password_expired &&