Commit 1b1ff549 authored by Matthias Leich's avatar Matthias Leich

Merge latest changes into GCA tree, no conflicts

parents b09ebad9 7c6ed98f
...@@ -79,4 +79,4 @@ public: ...@@ -79,4 +79,4 @@ public:
uint emb_count_querycache_size(THD *thd); uint emb_count_querycache_size(THD *thd);
int emb_load_querycache_result(THD *thd, Querycache_stream *src); int emb_load_querycache_result(THD *thd, Querycache_stream *src);
void emb_store_querycache_result(Querycache_stream *dst, THD* thd); void emb_store_querycache_result(Querycache_stream *dst, THD* thd);
void net_send_eof(THD *thd, uint server_status, uint total_warn_count); bool net_send_eof(THD *thd, uint server_status, uint total_warn_count);
...@@ -803,11 +803,11 @@ MYSQL_DATA *THD::alloc_new_dataset() ...@@ -803,11 +803,11 @@ MYSQL_DATA *THD::alloc_new_dataset()
*/ */
static static
void bool
write_eof_packet(THD *thd, uint server_status, uint total_warn_count) write_eof_packet(THD *thd, uint server_status, uint total_warn_count)
{ {
if (!thd->mysql) // bootstrap file handling if (!thd->mysql) // bootstrap file handling
return; return FALSE;
/* /*
The following test should never be true, but it's better to do it The following test should never be true, but it's better to do it
because if 'is_fatal_error' is set the server is not going to execute because if 'is_fatal_error' is set the server is not going to execute
...@@ -822,6 +822,7 @@ write_eof_packet(THD *thd, uint server_status, uint total_warn_count) ...@@ -822,6 +822,7 @@ write_eof_packet(THD *thd, uint server_status, uint total_warn_count)
*/ */
thd->cur_data->embedded_info->warning_count= thd->cur_data->embedded_info->warning_count=
(thd->spcont ? 0 : min(total_warn_count, 65535)); (thd->spcont ? 0 : min(total_warn_count, 65535));
return FALSE;
} }
...@@ -1032,31 +1033,34 @@ bool Protocol_binary::write() ...@@ -1032,31 +1033,34 @@ bool Protocol_binary::write()
@sa Server implementation of net_send_ok in protocol.cc for @sa Server implementation of net_send_ok in protocol.cc for
description of the arguments. description of the arguments.
@return The function does not return errors. @return
@retval TRUE An error occurred
@retval FALSE Success
*/ */
void bool
net_send_ok(THD *thd, net_send_ok(THD *thd,
uint server_status, uint total_warn_count, uint server_status, uint total_warn_count,
ha_rows affected_rows, ulonglong id, const char *message) ha_rows affected_rows, ulonglong id, const char *message)
{ {
DBUG_ENTER("emb_net_send_ok"); DBUG_ENTER("emb_net_send_ok");
MYSQL_DATA *data; MYSQL_DATA *data;
bool error;
MYSQL *mysql= thd->mysql; MYSQL *mysql= thd->mysql;
if (!mysql) // bootstrap file handling if (!mysql) // bootstrap file handling
DBUG_VOID_RETURN; DBUG_RETURN(FALSE);
if (!(data= thd->alloc_new_dataset())) if (!(data= thd->alloc_new_dataset()))
return; return TRUE;
data->embedded_info->affected_rows= affected_rows; data->embedded_info->affected_rows= affected_rows;
data->embedded_info->insert_id= id; data->embedded_info->insert_id= id;
if (message) if (message)
strmake(data->embedded_info->info, message, strmake(data->embedded_info->info, message,
sizeof(data->embedded_info->info)-1); sizeof(data->embedded_info->info)-1);
write_eof_packet(thd, server_status, total_warn_count); error= write_eof_packet(thd, server_status, total_warn_count);
thd->cur_data= 0; thd->cur_data= 0;
DBUG_VOID_RETURN; DBUG_RETURN(error);
} }
...@@ -1065,18 +1069,21 @@ net_send_ok(THD *thd, ...@@ -1065,18 +1069,21 @@ net_send_ok(THD *thd,
@sa net_send_ok @sa net_send_ok
@return This function does not return errors. @return
@retval TRUE An error occurred
@retval FALSE Success
*/ */
void bool
net_send_eof(THD *thd, uint server_status, uint total_warn_count) net_send_eof(THD *thd, uint server_status, uint total_warn_count)
{ {
write_eof_packet(thd, server_status, total_warn_count); bool error= write_eof_packet(thd, server_status, total_warn_count);
thd->cur_data= 0; thd->cur_data= 0;
return error;
} }
void net_send_error_packet(THD *thd, uint sql_errno, const char *err) bool net_send_error_packet(THD *thd, uint sql_errno, const char *err)
{ {
MYSQL_DATA *data= thd->cur_data; MYSQL_DATA *data= thd->cur_data;
struct embedded_query_result *ei; struct embedded_query_result *ei;
...@@ -1084,7 +1091,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) ...@@ -1084,7 +1091,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
if (!thd->mysql) // bootstrap file handling if (!thd->mysql) // bootstrap file handling
{ {
fprintf(stderr, "ERROR: %d %s\n", sql_errno, err); fprintf(stderr, "ERROR: %d %s\n", sql_errno, err);
return; return TRUE;
} }
if (!data) if (!data)
...@@ -1096,6 +1103,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) ...@@ -1096,6 +1103,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
strmov(ei->sqlstate, mysql_errno_to_sqlstate(sql_errno)); strmov(ei->sqlstate, mysql_errno_to_sqlstate(sql_errno));
ei->server_status= thd->server_status; ei->server_status= thd->server_status;
thd->cur_data= 0; thd->cur_data= 0;
return FALSE;
} }
......
...@@ -1068,7 +1068,13 @@ partition by range (a) ...@@ -1068,7 +1068,13 @@ partition by range (a)
subpartition by hash(a) subpartition by hash(a)
(partition p0 values less than (0), (partition p0 values less than (0),
partition p1 values less than (1) (subpartition sp0)); partition p1 values less than (1) (subpartition sp0));
ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near '))' at line 5 ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near 'subpartition sp0))' at line 5
create table t1 (a int, b int)
partition by list (a)
subpartition by hash(a)
(partition p0 values in (0),
partition p1 values in (1) (subpartition sp0));
ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near 'subpartition sp0))' at line 5
create table t1 (a int) create table t1 (a int)
partition by hash (a) partition by hash (a)
(partition p0 (subpartition sp0)); (partition p0 (subpartition sp0));
......
...@@ -249,3 +249,25 @@ DROP PROCEDURE p1; ...@@ -249,3 +249,25 @@ DROP PROCEDURE p1;
DELETE FROM mysql.user WHERE User='mysqltest_1'; DELETE FROM mysql.user WHERE User='mysqltest_1';
FLUSH PRIVILEGES; FLUSH PRIVILEGES;
set @@global.concurrent_insert= @old_concurrent_insert; set @@global.concurrent_insert= @old_concurrent_insert;
#
# Bug#44521 Prepared Statement: CALL p() - crashes: `! thd->main_da.is_sent' failed et.al.
#
SELECT GET_LOCK('Bug44521', 0);
GET_LOCK('Bug44521', 0)
1
** Connection con1
CREATE PROCEDURE p()
BEGIN
SELECT 1;
SELECT GET_LOCK('Bug44521', 100);
SELECT 2;
END$
CALL p();;
** Default connection
SELECT RELEASE_LOCK('Bug44521');
RELEASE_LOCK('Bug44521')
1
DROP PROCEDURE p;
# ------------------------------------------------------------------
# -- End of 5.1 tests
# ------------------------------------------------------------------
...@@ -1019,6 +1019,17 @@ subpartition by hash(a) ...@@ -1019,6 +1019,17 @@ subpartition by hash(a)
(partition p0 values less than (0), (partition p0 values less than (0),
partition p1 values less than (1) (subpartition sp0)); partition p1 values less than (1) (subpartition sp0));
#
# Bug 46354 Crash with subpartition
#
--error ER_PARSE_ERROR
create table t1 (a int, b int)
partition by list (a)
subpartition by hash(a)
(partition p0 values in (0),
partition p1 values in (1) (subpartition sp0));
# #
# BUG 15961 No error when subpartition defined without subpartition by clause # BUG 15961 No error when subpartition defined without subpartition by clause
# #
......
...@@ -380,3 +380,39 @@ set @@global.concurrent_insert= @old_concurrent_insert; ...@@ -380,3 +380,39 @@ set @@global.concurrent_insert= @old_concurrent_insert;
# Wait till all disconnects are completed # Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc --source include/wait_until_count_sessions.inc
--echo #
--echo # Bug#44521 Prepared Statement: CALL p() - crashes: `! thd->main_da.is_sent' failed et.al.
--echo #
SELECT GET_LOCK('Bug44521', 0);
--connect (con1,localhost,root,,)
--echo ** Connection con1
delimiter $;
CREATE PROCEDURE p()
BEGIN
SELECT 1;
SELECT GET_LOCK('Bug44521', 100);
SELECT 2;
END$
delimiter ;$
--send CALL p();
--connection default
--echo ** Default connection
let $wait_condition=
SELECT count(*) = 1 FROM information_schema.processlist
WHERE state = "User lock" AND info = "SELECT GET_LOCK('Bug44521', 100)";
--source include/wait_condition.inc
let $conid =
`SELECT id FROM information_schema.processlist
WHERE state = "User lock" AND info = "SELECT GET_LOCK('Bug44521', 100)"`;
dirty_close con1;
SELECT RELEASE_LOCK('Bug44521');
let $wait_condition=
SELECT count(*) = 0 FROM information_schema.processlist
WHERE id = $conid;
--source include/wait_condition.inc
DROP PROCEDURE p;
--echo # ------------------------------------------------------------------
--echo # -- End of 5.1 tests
--echo # ------------------------------------------------------------------
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024; static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
/* Declared non-static only because of the embedded library. */ /* Declared non-static only because of the embedded library. */
void net_send_error_packet(THD *thd, uint sql_errno, const char *err); bool net_send_error_packet(THD *thd, uint sql_errno, const char *err);
void net_send_ok(THD *, uint, uint, ha_rows, ulonglong, const char *); bool net_send_ok(THD *, uint, uint, ha_rows, ulonglong, const char *);
void net_send_eof(THD *thd, uint server_status, uint total_warn_count); bool net_send_eof(THD *thd, uint server_status, uint total_warn_count);
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
static void write_eof_packet(THD *thd, NET *net, static bool write_eof_packet(THD *thd, NET *net,
uint server_status, uint total_warn_count); uint server_status, uint total_warn_count);
#endif #endif
...@@ -70,8 +70,17 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length) ...@@ -70,8 +70,17 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length)
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
critical that every error that can be intercepted is issued in one critical that every error that can be intercepted is issued in one
place only, my_message_sql. place only, my_message_sql.
@param thd Thread handler
@param sql_errno The error code to send
@param err A pointer to the error message
@return
@retval FALSE The message was sent to the client
@retval TRUE An error occurred and the message wasn't sent properly
*/ */
void net_send_error(THD *thd, uint sql_errno, const char *err)
bool net_send_error(THD *thd, uint sql_errno, const char *err)
{ {
DBUG_ENTER("net_send_error"); DBUG_ENTER("net_send_error");
...@@ -80,6 +89,7 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) ...@@ -80,6 +89,7 @@ void net_send_error(THD *thd, uint sql_errno, const char *err)
DBUG_ASSERT(err && err[0]); DBUG_ASSERT(err && err[0]);
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err)); DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err));
bool error;
/* /*
It's one case when we can push an error even though there It's one case when we can push an error even though there
...@@ -90,11 +100,11 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) ...@@ -90,11 +100,11 @@ void net_send_error(THD *thd, uint sql_errno, const char *err)
/* Abort multi-result sets */ /* Abort multi-result sets */
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
net_send_error_packet(thd, sql_errno, err); error= net_send_error_packet(thd, sql_errno, err);
thd->main_da.can_overwrite_status= FALSE; thd->main_da.can_overwrite_status= FALSE;
DBUG_VOID_RETURN; DBUG_RETURN(error);
} }
/** /**
...@@ -113,25 +123,33 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) ...@@ -113,25 +123,33 @@ void net_send_error(THD *thd, uint sql_errno, const char *err)
Is not stored if no message. Is not stored if no message.
@param thd Thread handler @param thd Thread handler
@param server_status The server status
@param total_warn_count Total number of warnings
@param affected_rows Number of rows changed by statement @param affected_rows Number of rows changed by statement
@param id Auto_increment id for first row (if used) @param id Auto_increment id for first row (if used)
@param message Message to send to the client (Used by mysql_status) @param message Message to send to the client (Used by mysql_status)
@return
@retval FALSE The message was successfully sent
@retval TRUE An error occurred and the messages wasn't sent properly
*/ */
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
void bool
net_send_ok(THD *thd, net_send_ok(THD *thd,
uint server_status, uint total_warn_count, uint server_status, uint total_warn_count,
ha_rows affected_rows, ulonglong id, const char *message) ha_rows affected_rows, ulonglong id, const char *message)
{ {
NET *net= &thd->net; NET *net= &thd->net;
uchar buff[MYSQL_ERRMSG_SIZE+10],*pos; uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
bool error= FALSE;
DBUG_ENTER("my_ok"); DBUG_ENTER("my_ok");
if (! net->vio) // hack for re-parsing queries if (! net->vio) // hack for re-parsing queries
{ {
DBUG_PRINT("info", ("vio present: NO")); DBUG_PRINT("info", ("vio present: NO"));
DBUG_VOID_RETURN; DBUG_RETURN(FALSE);
} }
buff[0]=0; // No fields buff[0]=0; // No fields
...@@ -162,13 +180,14 @@ net_send_ok(THD *thd, ...@@ -162,13 +180,14 @@ net_send_ok(THD *thd,
if (message && message[0]) if (message && message[0])
pos= net_store_data(pos, (uchar*) message, strlen(message)); pos= net_store_data(pos, (uchar*) message, strlen(message));
VOID(my_net_write(net, buff, (size_t) (pos-buff))); error= my_net_write(net, buff, (size_t) (pos-buff));
VOID(net_flush(net)); if (!error)
error= net_flush(net);
thd->main_da.can_overwrite_status= FALSE; thd->main_da.can_overwrite_status= FALSE;
DBUG_PRINT("info", ("OK sent, so no more error sending allowed")); DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
DBUG_VOID_RETURN; DBUG_RETURN(error);
} }
static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
...@@ -188,37 +207,54 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */ ...@@ -188,37 +207,54 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
client. client.
@param thd Thread handler @param thd Thread handler
@param no_flush Set to 1 if there will be more data to the client, @param server_status The server status
like in send_fields(). @param total_warn_count Total number of warnings
@return
@retval FALSE The message was successfully sent
@retval TRUE An error occurred and the message wasn't sent properly
*/ */
void bool
net_send_eof(THD *thd, uint server_status, uint total_warn_count) net_send_eof(THD *thd, uint server_status, uint total_warn_count)
{ {
NET *net= &thd->net; NET *net= &thd->net;
bool error= FALSE;
DBUG_ENTER("net_send_eof"); DBUG_ENTER("net_send_eof");
/* Set to TRUE if no active vio, to work well in case of --init-file */ /* Set to TRUE if no active vio, to work well in case of --init-file */
if (net->vio != 0) if (net->vio != 0)
{ {
thd->main_da.can_overwrite_status= TRUE; thd->main_da.can_overwrite_status= TRUE;
write_eof_packet(thd, net, server_status, total_warn_count); error= write_eof_packet(thd, net, server_status, total_warn_count);
VOID(net_flush(net)); if (!error)
error= net_flush(net);
thd->main_da.can_overwrite_status= FALSE; thd->main_da.can_overwrite_status= FALSE;
DBUG_PRINT("info", ("EOF sent, so no more error sending allowed")); DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
} }
DBUG_VOID_RETURN; DBUG_RETURN(error);
} }
/** /**
Format EOF packet according to the current protocol and Format EOF packet according to the current protocol and
write it to the network output buffer. write it to the network output buffer.
@param thd The thread handler
@param net The network handler
@param server_status The server status
@param total_warn_count The number of warnings
@return
@retval FALSE The message was sent successfully
@retval TRUE An error occurred and the messages wasn't sent properly
*/ */
static void write_eof_packet(THD *thd, NET *net, static bool write_eof_packet(THD *thd, NET *net,
uint server_status, uint server_status,
uint total_warn_count) uint total_warn_count)
{ {
bool error;
if (thd->client_capabilities & CLIENT_PROTOCOL_41) if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{ {
uchar buff[5]; uchar buff[5];
...@@ -237,10 +273,12 @@ static void write_eof_packet(THD *thd, NET *net, ...@@ -237,10 +273,12 @@ static void write_eof_packet(THD *thd, NET *net,
if (thd->is_fatal_error) if (thd->is_fatal_error)
server_status&= ~SERVER_MORE_RESULTS_EXISTS; server_status&= ~SERVER_MORE_RESULTS_EXISTS;
int2store(buff + 3, server_status); int2store(buff + 3, server_status);
VOID(my_net_write(net, buff, 5)); error= my_net_write(net, buff, 5);
} }
else else
VOID(my_net_write(net, eof_buff, 1)); error= my_net_write(net, eof_buff, 1);
return error;
} }
/** /**
...@@ -261,7 +299,17 @@ bool send_old_password_request(THD *thd) ...@@ -261,7 +299,17 @@ bool send_old_password_request(THD *thd)
} }
void net_send_error_packet(THD *thd, uint sql_errno, const char *err) /**
@param thd Thread handler
@param sql_errno The error code to send
@param err A pointer to the error message
@return
@retval FALSE The message was successfully sent
@retval TRUE An error occurred and the messages wasn't sent properly
*/
bool net_send_error_packet(THD *thd, uint sql_errno, const char *err)
{ {
NET *net= &thd->net; NET *net= &thd->net;
uint length; uint length;
...@@ -279,7 +327,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) ...@@ -279,7 +327,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
/* In bootstrap it's ok to print on stderr */ /* In bootstrap it's ok to print on stderr */
fprintf(stderr,"ERROR: %d %s\n",sql_errno,err); fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
} }
DBUG_VOID_RETURN; DBUG_RETURN(FALSE);
} }
if (net->return_errno) if (net->return_errno)
...@@ -301,9 +349,8 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) ...@@ -301,9 +349,8 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
length=(uint) strlen(err); length=(uint) strlen(err);
set_if_smaller(length,MYSQL_ERRMSG_SIZE-1); set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
} }
VOID(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err, DBUG_RETURN(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
length)); length));
DBUG_VOID_RETURN;
} }
#endif /* EMBEDDED_LIBRARY */ #endif /* EMBEDDED_LIBRARY */
...@@ -389,36 +436,39 @@ void net_end_statement(THD *thd) ...@@ -389,36 +436,39 @@ void net_end_statement(THD *thd)
if (thd->main_da.is_sent) if (thd->main_da.is_sent)
return; return;
bool error= FALSE;
switch (thd->main_da.status()) { switch (thd->main_da.status()) {
case Diagnostics_area::DA_ERROR: case Diagnostics_area::DA_ERROR:
/* The query failed, send error to log and abort bootstrap. */ /* The query failed, send error to log and abort bootstrap. */
net_send_error(thd, error= net_send_error(thd,
thd->main_da.sql_errno(), thd->main_da.sql_errno(),
thd->main_da.message()); thd->main_da.message());
break; break;
case Diagnostics_area::DA_EOF: case Diagnostics_area::DA_EOF:
net_send_eof(thd, error= net_send_eof(thd,
thd->main_da.server_status(), thd->main_da.server_status(),
thd->main_da.total_warn_count()); thd->main_da.total_warn_count());
break; break;
case Diagnostics_area::DA_OK: case Diagnostics_area::DA_OK:
net_send_ok(thd, error= net_send_ok(thd,
thd->main_da.server_status(), thd->main_da.server_status(),
thd->main_da.total_warn_count(), thd->main_da.total_warn_count(),
thd->main_da.affected_rows(), thd->main_da.affected_rows(),
thd->main_da.last_insert_id(), thd->main_da.last_insert_id(),
thd->main_da.message()); thd->main_da.message());
break; break;
case Diagnostics_area::DA_DISABLED: case Diagnostics_area::DA_DISABLED:
break; break;
case Diagnostics_area::DA_EMPTY: case Diagnostics_area::DA_EMPTY:
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
net_send_ok(thd, thd->server_status, thd->total_warn_count, error= net_send_ok(thd, thd->server_status, thd->total_warn_count,
0, 0, NULL); 0, 0, NULL);
break; break;
} }
thd->main_da.is_sent= TRUE; if (!error)
thd->main_da.is_sent= TRUE;
} }
......
...@@ -173,7 +173,7 @@ public: ...@@ -173,7 +173,7 @@ public:
}; };
void send_warning(THD *thd, uint sql_errno, const char *err=0); void send_warning(THD *thd, uint sql_errno, const char *err=0);
void net_send_error(THD *thd, uint sql_errno=0, const char *err=0); bool net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
void net_end_statement(THD *thd); void net_end_statement(THD *thd);
bool send_old_password_request(THD *thd); bool send_old_password_request(THD *thd);
uchar *net_store_data(uchar *to,const uchar *from, size_t length); uchar *net_store_data(uchar *to,const uchar *from, size_t length);
......
...@@ -1248,7 +1248,7 @@ sp_head::execute(THD *thd) ...@@ -1248,7 +1248,7 @@ sp_head::execute(THD *thd)
*/ */
if (thd->prelocked_mode == NON_PRELOCKED) if (thd->prelocked_mode == NON_PRELOCKED)
thd->user_var_events_alloc= thd->mem_root; thd->user_var_events_alloc= thd->mem_root;
err_status= i->execute(thd, &ip); err_status= i->execute(thd, &ip);
if (i->free_list) if (i->free_list)
...@@ -2863,7 +2863,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) ...@@ -2863,7 +2863,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
if (!thd->is_error()) if (!thd->is_error())
thd->main_da.reset_diagnostics_area(); thd->main_da.reset_diagnostics_area();
} }
DBUG_RETURN(res); DBUG_RETURN(res || thd->is_error());
} }
......
...@@ -4206,6 +4206,10 @@ opt_sub_partition: ...@@ -4206,6 +4206,10 @@ opt_sub_partition:
if (Lex->part_info->no_subparts != 0 && if (Lex->part_info->no_subparts != 0 &&
!Lex->part_info->use_default_subpartitions) !Lex->part_info->use_default_subpartitions)
{ {
/*
We come here when we have defined subpartitions on the first
partition but not on all the subsequent partitions.
*/
my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR)); my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -4248,6 +4252,23 @@ sub_part_definition: ...@@ -4248,6 +4252,23 @@ sub_part_definition:
partition_info *part_info= lex->part_info; partition_info *part_info= lex->part_info;
partition_element *curr_part= part_info->current_partition; partition_element *curr_part= part_info->current_partition;
partition_element *sub_p_elem= new partition_element(curr_part); partition_element *sub_p_elem= new partition_element(curr_part);
if (part_info->use_default_subpartitions &&
part_info->partitions.elements >= 2)
{
/*
create table t1 (a int)
partition by list (a) subpartition by hash (a)
(partition p0 values in (1),
partition p1 values in (2) subpartition sp11);
causes use to arrive since we are on the second
partition, but still use_default_subpartitions
is set. When we come here we're processing at least
the second partition (the current partition processed
have already been put into the partitions list.
*/
my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
MYSQL_YYABORT;
}
if (!sub_p_elem || if (!sub_p_elem ||
curr_part->subpartitions.push_back(sub_p_elem)) curr_part->subpartitions.push_back(sub_p_elem))
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment