Commit 296ba0ea authored by pem@mysql.comhem.se's avatar pem@mysql.comhem.se

WL#1567: Add ROW_COUNT() Function to retrieve count of rows updated/inserted/deleted

parent d42b1458
...@@ -802,6 +802,28 @@ use test| ...@@ -802,6 +802,28 @@ use test|
drop database sp_db3| drop database sp_db3|
select type,db,name from mysql.proc where db = 'sp_db3'| select type,db,name from mysql.proc where db = 'sp_db3'|
type db name type db name
create procedure rc()
begin
delete from t1;
insert into t1 values ("a", 1), ("b", 2), ("c", 3);
end|
call rc()|
select row_count()|
row_count()
3
update t1 set data=42 where id = "b";
select row_count()|
row_count()
1
delete from t1|
select row_count()|
row_count()
3
delete from t1|
select row_count()|
row_count()
0
drop procedure rc|
create procedure bug822(a_id char(16), a_data int) create procedure bug822(a_id char(16), a_data int)
begin begin
declare n int; declare n int;
......
...@@ -931,6 +931,25 @@ drop database sp_db3| ...@@ -931,6 +931,25 @@ drop database sp_db3|
select type,db,name from mysql.proc where db = 'sp_db3'| select type,db,name from mysql.proc where db = 'sp_db3'|
# ROW_COUNT() function after a CALL
# We test the other cases here too, although it's not strictly SP specific
create procedure rc()
begin
delete from t1;
insert into t1 values ("a", 1), ("b", 2), ("c", 3);
end|
call rc()|
select row_count()|
update t1 set data=42 where id = "b";
select row_count()|
delete from t1|
select row_count()|
delete from t1|
select row_count()|
drop procedure rc|
# #
# Test cases for old bugs # Test cases for old bugs
# #
......
...@@ -3206,6 +3206,15 @@ longlong Item_func_is_used_lock::val_int() ...@@ -3206,6 +3206,15 @@ longlong Item_func_is_used_lock::val_int()
} }
longlong Item_func_row_count::val_int()
{
DBUG_ASSERT(fixed == 1);
THD *thd= current_thd;
return thd->row_count_func;
}
Item_func_sp::Item_func_sp(sp_name *name) Item_func_sp::Item_func_sp(sp_name *name)
:Item_func(), m_name(name), m_sp(NULL) :Item_func(), m_name(name), m_sp(NULL)
{ {
......
...@@ -1076,6 +1076,16 @@ enum Cast_target ...@@ -1076,6 +1076,16 @@ enum Cast_target
}; };
class Item_func_row_count :public Item_int_func
{
public:
Item_func_row_count() :Item_int_func() {}
longlong val_int();
const char *func_name() const { return "row_count"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
};
/* /*
* *
* Stored FUNCTIONs * Stored FUNCTIONs
......
...@@ -681,6 +681,7 @@ static SYMBOL sql_functions[] = { ...@@ -681,6 +681,7 @@ static SYMBOL sql_functions[] = {
{ "RELEASE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)}, { "RELEASE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)},
{ "REVERSE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)}, { "REVERSE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)},
{ "ROUND", SYM(ROUND)}, { "ROUND", SYM(ROUND)},
{ "ROW_COUNT", SYM(ROW_COUNT_SYM)},
{ "RPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)}, { "RPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)},
{ "RTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)}, { "RTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)},
{ "SEC_TO_TIME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)}, { "SEC_TO_TIME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)},
......
...@@ -829,6 +829,7 @@ class THD :public ilink, ...@@ -829,6 +829,7 @@ class THD :public ilink,
bool charset_is_system_charset, charset_is_collation_connection; bool charset_is_system_charset, charset_is_collation_connection;
bool slow_command; bool slow_command;
ulong row_count_func; /* For the ROW_COUNT() function */
sp_rcontext *spcont; // SP runtime context sp_rcontext *spcont; // SP runtime context
sp_cache *sp_proc_cache; sp_cache *sp_proc_cache;
sp_cache *sp_func_cache; sp_cache *sp_func_cache;
......
...@@ -96,6 +96,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, ...@@ -96,6 +96,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
{ {
delete select; delete select;
free_underlaid_joins(thd, &thd->lex->select_lex); free_underlaid_joins(thd, &thd->lex->select_lex);
thd->row_count_func= 0;
send_ok(thd,0L); send_ok(thd,0L);
DBUG_RETURN(0); // Nothing to delete DBUG_RETURN(0); // Nothing to delete
} }
...@@ -245,6 +246,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, ...@@ -245,6 +246,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
send_error(thd,thd->killed_errno()); send_error(thd,thd->killed_errno());
else else
{ {
thd->row_count_func= deleted;
send_ok(thd,deleted); send_ok(thd,deleted);
DBUG_PRINT("info",("%d records deleted",deleted)); DBUG_PRINT("info",("%d records deleted",deleted));
} }
...@@ -550,7 +552,10 @@ bool multi_delete::send_eof() ...@@ -550,7 +552,10 @@ bool multi_delete::send_eof()
if (local_error) if (local_error)
::send_error(thd); ::send_error(thd);
else else
{
thd->row_count_func= deleted;
::send_ok(thd, deleted); ::send_ok(thd, deleted);
}
return 0; return 0;
} }
......
...@@ -419,7 +419,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -419,7 +419,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
goto abort; goto abort;
if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) || if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) ||
!thd->cuted_fields)) !thd->cuted_fields))
send_ok(thd,info.copied+info.deleted+info.updated,id); {
thd->row_count_func= info.copied+info.deleted+info.updated;
send_ok(thd, thd->row_count_func, id);
}
else else
{ {
char buff[160]; char buff[160];
...@@ -430,7 +433,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -430,7 +433,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
else else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(ulong) info.deleted+info.updated, (ulong) thd->cuted_fields); (ulong) info.deleted+info.updated, (ulong) thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted+info.updated,(ulonglong)id,buff); thd->row_count_func= info.copied+info.deleted+info.updated;
::send_ok(thd, thd->row_count_func, (ulonglong)id,buff);
} }
free_underlaid_joins(thd, &thd->lex->select_lex); free_underlaid_joins(thd, &thd->lex->select_lex);
table->insert_values=0; table->insert_values=0;
...@@ -1565,7 +1569,8 @@ bool select_insert::send_eof() ...@@ -1565,7 +1569,8 @@ bool select_insert::send_eof()
else else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(ulong) info.deleted+info.updated, (ulong) thd->cuted_fields); (ulong) info.deleted+info.updated, (ulong) thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted+info.updated,last_insert_id,buff); thd->row_count_func= info.copied+info.deleted+info.updated;
::send_ok(thd, thd->row_count_func, last_insert_id, buff);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
...@@ -3582,7 +3582,7 @@ mysql_execute_command(THD *thd) ...@@ -3582,7 +3582,7 @@ mysql_execute_command(THD *thd)
} }
if (res == 0) if (res == 0)
send_ok(thd); send_ok(thd, thd->row_count_func);
else else
goto error; // Substatement should already have sent error goto error; // Substatement should already have sent error
} }
......
...@@ -399,8 +399,9 @@ int mysql_update(THD *thd, ...@@ -399,8 +399,9 @@ int mysql_update(THD *thd,
char buff[80]; char buff[80];
sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
(ulong) thd->cuted_fields); (ulong) thd->cuted_fields);
send_ok(thd, thd->row_count_func=
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
send_ok(thd, thd->row_count_func,
thd->insert_id_used ? thd->insert_id() : 0L,buff); thd->insert_id_used ? thd->insert_id() : 0L,buff);
DBUG_PRINT("info",("%d records updated",updated)); DBUG_PRINT("info",("%d records updated",updated));
} }
...@@ -1124,8 +1125,9 @@ bool multi_update::send_eof() ...@@ -1124,8 +1125,9 @@ bool multi_update::send_eof()
sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
(ulong) thd->cuted_fields); (ulong) thd->cuted_fields);
::send_ok(thd, thd->row_count_func=
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
::send_ok(thd, thd->row_count_func,
thd->insert_id_used ? thd->insert_id() : 0L,buff); thd->insert_id_used ? thd->insert_id() : 0L,buff);
return 0; return 0;
} }
...@@ -436,6 +436,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -436,6 +436,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token X509_SYM %token X509_SYM
%token XOR %token XOR
%token COMPRESSED_SYM %token COMPRESSED_SYM
%token ROW_COUNT_SYM
%token ERRORS %token ERRORS
%token WARNINGS %token WARNINGS
...@@ -3936,6 +3937,11 @@ simple_expr: ...@@ -3936,6 +3937,11 @@ simple_expr:
| ROUND '(' expr ')' | ROUND '(' expr ')'
{ $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); } { $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); }
| ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); } | ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); }
| ROW_COUNT_SYM '(' ')'
{
$$= new Item_func_row_count();
Lex->safe_to_cache_query= 0;
}
| SUBDATE_SYM '(' expr ',' expr ')' | SUBDATE_SYM '(' expr ',' expr ')'
{ $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1);} { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1);}
| SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' | SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
......
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