Expose MySQL affected row counts

This commit is contained in:
udo 2026-07-13 07:10:03 +00:00
parent 7281302287
commit d857930ceb
8 changed files with 50 additions and 1 deletions

View File

@ -47,6 +47,7 @@ PUBLIC_APIS = [
("cli_arg", True, "public"), ("unit_compile", True, "public"), ("cli_arg", True, "public"), ("unit_compile", True, "public"),
("cleanup_sqlite_connections", False, "internal"), ("cleanup_mysql_connections", False, "internal"), ("cleanup_sqlite_connections", False, "internal"), ("cleanup_mysql_connections", False, "internal"),
("mysql_connect", True, "integration"), ("mysql_query", True, "integration"), ("mysql_connect", True, "integration"), ("mysql_query", True, "integration"),
("mysql_affected_rows", True, "integration"),
] ]
REMOVED_APIS = ["unit_load", "concat"] REMOVED_APIS = ["unit_load", "concat"]

View File

@ -5,4 +5,5 @@ mysql_disconnect
mysql_error mysql_error
mysql_escape mysql_escape
mysql_insert_id mysql_insert_id
mysql_affected_rows
mysql_query mysql_query

View File

@ -0,0 +1,24 @@
:sig
u32 mysql_affected_rows(MySQL* m)
:params
m : pointer to an active MySQL connection
return value : number of rows changed by the most recent statement
:see
>mysql
mysql_query
mysql_insert_id
:content
Returns the number of rows changed by the most recent insert, update, or delete on the connection. A successful statement that returns rows, a rejected query, or a null connection returns `0` rather than retaining an earlier statement's count.
:example
MySQL* db = mysql_connect();
if(db != 0)
{
mysql_query(db, "update users set active=1 where active=0");
print("rows updated: ", mysql_affected_rows(db), "\n");
mysql_disconnect(db);
}
else print("(requires a reachable MySQL server)\n");

View File

@ -9,6 +9,7 @@ return value : a list of rows returned from executing the query
:see :see
>mysql >mysql
mysql_affected_rows
:content :content
Executes a MySQL query and returns the resulting data, if any. Executes a MySQL query and returns the resulting data, if any.
@ -17,6 +18,8 @@ Executes a MySQL query and returns the resulting data, if any.
The result is returned as a `DValue`, which makes it easy to iterate through rows and read fields with the usual `DValue` accessors. The result is returned as a `DValue`, which makes it easy to iterate through rows and read fields with the usual `DValue` accessors.
After an insert, update, or delete, use `mysql_affected_rows()` to inspect how many rows changed.
:example :example
MySQL* db = mysql_connect(); MySQL* db = mysql_connect();
if(db != 0) if(db != 0)

View File

@ -131,8 +131,21 @@ RENDER(Request& context)
(dbs.find("information_schema") != String::npos || dbs.find("mysql") != String::npos) ? "pass" : "fail", (dbs.find("information_schema") != String::npos || dbs.find("mysql") != String::npos) ? "pass" : "fail",
dbs.substr(0, dbs.length() > 220 ? 220 : dbs.length()) dbs.substr(0, dbs.length() > 220 ? 220 : dbs.length())
); );
mysql.query("USE mysql");
mysql.query("CREATE TEMPORARY TABLE uce_affected_rows_test (id INT PRIMARY KEY, value INT NOT NULL)");
mysql.query("INSERT INTO uce_affected_rows_test VALUES (1,10),(2,20)");
u32 inserted = mysql_affected_rows(&mysql);
mysql.query("UPDATE uce_affected_rows_test SET value=value+1 WHERE id=1");
u32 updated = mysql_affected_rows(&mysql);
mysql.query("SELECT * FROM uce_affected_rows_test");
u32 selected = mysql_affected_rows(&mysql);
mark(
"mysql_affected_rows()",
inserted == 2 && updated == 1 && selected == 0 ? "pass" : "fail",
"inserted=" + std::to_string((u64)inserted) + " updated=" + std::to_string((u64)updated) + " selected=" + std::to_string((u64)selected)
);
} }
site_tests_summary(passed, failed, skipped, "Memcache or MySQL checks are allowed to skip cleanly when the corresponding service is not available on the development host."); site_tests_summary(passed, failed, skipped, "Memcache or MySQL checks are allowed to skip cleanly when the corresponding service is not available on the development host.");
site_tests_page_end(); site_tests_page_end();
} }

View File

@ -202,6 +202,7 @@ static bool mysql_has_unquoted_positional_placeholder(String query);
DValue MySQL::query(String q) DValue MySQL::query(String q)
{ {
affected_rows = 0;
if(mysql_has_unquoted_positional_placeholder(q)) if(mysql_has_unquoted_positional_placeholder(q))
{ {
_preload_next_error_code = CR_UNKNOWN_ERROR; _preload_next_error_code = CR_UNKNOWN_ERROR;

View File

@ -104,3 +104,8 @@ inline u64 mysql_insert_id(MySQL* m)
{ {
return(m->insert_id); return(m->insert_id);
} }
inline u32 mysql_affected_rows(MySQL* m)
{
return(m ? m->affected_rows : 0);
}

View File

@ -280,6 +280,7 @@ static bool wasm_mysql_has_unquoted_positional_placeholder(String query)
DValue MySQL::query(String q) DValue MySQL::query(String q)
{ {
affected_rows = 0;
if(wasm_mysql_has_unquoted_positional_placeholder(q)) if(wasm_mysql_has_unquoted_positional_placeholder(q))
{ {
_preload_next_error_code = 2000; _preload_next_error_code = 2000;