mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
Manual merge.
This commit is contained in:
commit
a55e6dda22
3 changed files with 59 additions and 19 deletions
|
@ -1112,6 +1112,13 @@ public:
|
|||
unit= u;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
Because of peculiarities of prepared statements protocol
|
||||
we need to know number of columns in the result set (if
|
||||
there is a result set) apart from sending columns metadata.
|
||||
*/
|
||||
virtual uint field_count(List<Item> &fields) const
|
||||
{ return fields.elements; }
|
||||
virtual bool send_fields(List<Item> &list,uint flag)=0;
|
||||
virtual bool send_data(List<Item> &items)=0;
|
||||
virtual bool initialize_tables (JOIN *join=0) { return 0; }
|
||||
|
@ -1126,6 +1133,20 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
Base class for select_result descendands which intercept and
|
||||
transform result set rows. As the rows are not sent to the client,
|
||||
sending of result set metadata should be suppressed as well.
|
||||
*/
|
||||
|
||||
class select_result_interceptor: public select_result
|
||||
{
|
||||
public:
|
||||
uint field_count(List<Item> &fields) const { return 0; }
|
||||
bool send_fields(List<Item> &fields, uint flag) { return FALSE; }
|
||||
};
|
||||
|
||||
|
||||
class select_send :public select_result {
|
||||
public:
|
||||
select_send() {}
|
||||
|
@ -1135,7 +1156,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class select_to_file :public select_result {
|
||||
class select_to_file :public select_result_interceptor {
|
||||
protected:
|
||||
sql_exchange *exchange;
|
||||
File file;
|
||||
|
@ -1147,7 +1168,6 @@ public:
|
|||
select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L)
|
||||
{ path[0]=0; }
|
||||
~select_to_file();
|
||||
bool send_fields(List<Item> &list, uint flag) { return 0; }
|
||||
void send_error(uint errcode,const char *err);
|
||||
bool send_eof();
|
||||
void cleanup();
|
||||
|
@ -1174,7 +1194,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class select_insert :public select_result {
|
||||
class select_insert :public select_result_interceptor {
|
||||
public:
|
||||
TABLE *table;
|
||||
List<Item> *fields;
|
||||
|
@ -1190,8 +1210,6 @@ class select_insert :public select_result {
|
|||
}
|
||||
~select_insert();
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list, uint flag)
|
||||
{ return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
void send_error(uint errcode,const char *err);
|
||||
bool send_eof();
|
||||
|
@ -1274,7 +1292,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class select_union :public select_result {
|
||||
class select_union :public select_result_interceptor {
|
||||
public:
|
||||
TABLE *table;
|
||||
COPY_INFO info;
|
||||
|
@ -1283,8 +1301,6 @@ class select_union :public select_result {
|
|||
select_union(TABLE *table_par);
|
||||
~select_union();
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list, uint flag)
|
||||
{ return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
bool send_eof();
|
||||
bool flush();
|
||||
|
@ -1292,13 +1308,12 @@ class select_union :public select_result {
|
|||
};
|
||||
|
||||
/* Base subselect interface class */
|
||||
class select_subselect :public select_result
|
||||
class select_subselect :public select_result_interceptor
|
||||
{
|
||||
protected:
|
||||
Item_subselect *item;
|
||||
public:
|
||||
select_subselect(Item_subselect *item);
|
||||
bool send_fields(List<Item> &list, uint flag) { return 0; };
|
||||
bool send_data(List<Item> &items)=0;
|
||||
bool send_eof() { return 0; };
|
||||
};
|
||||
|
@ -1435,7 +1450,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class multi_delete :public select_result
|
||||
class multi_delete :public select_result_interceptor
|
||||
{
|
||||
TABLE_LIST *delete_tables, *table_being_deleted;
|
||||
Unique **tempfiles;
|
||||
|
@ -1448,8 +1463,6 @@ public:
|
|||
multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
|
||||
~multi_delete();
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list,
|
||||
uint flag) { return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
bool initialize_tables (JOIN *join);
|
||||
void send_error(uint errcode,const char *err);
|
||||
|
@ -1458,7 +1471,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class multi_update :public select_result
|
||||
class multi_update :public select_result_interceptor
|
||||
{
|
||||
TABLE_LIST *all_tables, *update_tables, *table_being_updated;
|
||||
THD *thd;
|
||||
|
@ -1477,7 +1490,6 @@ public:
|
|||
List<Item> *values, enum_duplicates handle_duplicates);
|
||||
~multi_update();
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list, uint flag) { return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
bool initialize_tables (JOIN *join);
|
||||
void send_error(uint errcode,const char *err);
|
||||
|
@ -1486,7 +1498,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class select_dumpvar :public select_result {
|
||||
class select_dumpvar :public select_result_interceptor {
|
||||
ha_rows row_count;
|
||||
public:
|
||||
List<LEX_STRING> var_list;
|
||||
|
@ -1494,7 +1506,6 @@ public:
|
|||
select_dumpvar(void) { var_list.empty(); vars.empty(); row_count=0;}
|
||||
~select_dumpvar() {}
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list, uint flag) {return 0;}
|
||||
bool send_data(List<Item> &items);
|
||||
bool send_eof();
|
||||
void cleanup();
|
||||
|
|
|
@ -1064,6 +1064,12 @@ static int mysql_test_select(Prepared_statement *stmt,
|
|||
DBUG_RETURN(1);
|
||||
#endif
|
||||
|
||||
if (!lex->result && !(lex->result= new (&stmt->mem_root) select_send))
|
||||
{
|
||||
send_error(thd);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (open_and_lock_tables(thd, tables))
|
||||
{
|
||||
send_error(thd);
|
||||
|
@ -1087,8 +1093,13 @@ static int mysql_test_select(Prepared_statement *stmt,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (send_prep_stmt(stmt, lex->select_lex.item_list.elements) ||
|
||||
thd->protocol_simple.send_fields(&lex->select_lex.item_list, 0)
|
||||
List<Item> &fields= lex->select_lex.item_list;
|
||||
/*
|
||||
We can use lex->result as it should've been
|
||||
prepared in unit->prepare call above.
|
||||
*/
|
||||
if (send_prep_stmt(stmt, lex->result->field_count(fields)) ||
|
||||
lex->result->send_fields(fields, 0)
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
|| net_flush(&thd->net)
|
||||
#endif
|
||||
|
|
|
@ -10625,6 +10625,23 @@ static void test_bug6058()
|
|||
}
|
||||
|
||||
|
||||
static void test_bug6059()
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
const char *stmt_text;
|
||||
int rc;
|
||||
|
||||
myheader("test_bug6059");
|
||||
|
||||
stmt_text= "SELECT 'foo' INTO OUTFILE 'x.3'";
|
||||
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
|
||||
DIE_UNLESS(mysql_stmt_field_count(stmt) == 0);
|
||||
mysql_stmt_close(stmt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Read and parse arguments and MySQL options from my.cnf
|
||||
|
@ -10938,6 +10955,7 @@ int main(int argc, char **argv)
|
|||
prepared statements */
|
||||
test_bug6049(); /* check support for negative TIME values */
|
||||
test_bug6058(); /* check support for 0000-00-00 dates */
|
||||
test_bug6059(); /* correct metadata for SELECT ... INTO OUTFILE */
|
||||
/*
|
||||
XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
|
||||
DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
|
||||
|
|
Loading…
Reference in a new issue