From 3e423f49ddc7ad823d86e8dbb592fd4210f55dd0 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 17 Jul 2026 18:05:04 +0000 Subject: [PATCH] Expose MySQL connection state --- site/doc/areas/mysql.txt | 1 + site/doc/pages/mysql_connect.txt | 4 ++-- site/doc/pages/mysql_connected.txt | 20 ++++++++++++++++++++ site/tests/services.uce | 5 +++++ src/lib/mysql-connector.h | 8 ++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 site/doc/pages/mysql_connected.txt diff --git a/site/doc/areas/mysql.txt b/site/doc/areas/mysql.txt index 8d90ca2..5280616 100644 --- a/site/doc/areas/mysql.txt +++ b/site/doc/areas/mysql.txt @@ -1,6 +1,7 @@ MySQL Functions mysql_connect +mysql_connected mysql_disconnect mysql_error mysql_escape diff --git a/site/doc/pages/mysql_connect.txt b/site/doc/pages/mysql_connect.txt index 709f094..b69222a 100644 --- a/site/doc/pages/mysql_connect.txt +++ b/site/doc/pages/mysql_connect.txt @@ -11,7 +11,7 @@ return value : pointer to the MySQL connection struct >mysql :content -Establishes a connection to a MySQL server and returns a pointer to the connection struct. +Establishes a connection to a MySQL server and returns a request-owned pointer to the connection struct. A failed connection also returns a wrapper so that `mysql_error()` can report the failure; use `mysql_connected()` before issuing optional work that requires a live server handle. This connection handle is then used with helpers such as `mysql_query()`, `mysql_error()`, and `mysql_disconnect()`. @@ -19,5 +19,5 @@ MySQL handles are request-scoped framework resources. Repeated `mysql_connect()` :example MySQL* db = mysql_connect(); -print(db != 0 ? "connected to MySQL" : "no MySQL server reachable with these credentials", "\n"); +print(mysql_connected(db) ? "connected to MySQL" : "no MySQL server reachable with these credentials", "\n"); if(db != 0) mysql_disconnect(db); diff --git a/site/doc/pages/mysql_connected.txt b/site/doc/pages/mysql_connected.txt new file mode 100644 index 0000000..fe36669 --- /dev/null +++ b/site/doc/pages/mysql_connected.txt @@ -0,0 +1,20 @@ +:sig +bool mysql_connected(MySQL* m) + +:params +m : pointer returned by mysql_connect() +return value : true only when the wrapper owns a live server connection + +:see +>mysql + +:content +Tests whether a MySQL wrapper has a usable server connection. `mysql_connect()` retains a failed wrapper so that callers can retrieve its diagnostic through `mysql_error()`; this helper distinguishes that state from a live handle without consuming the diagnostic. + +:example +MySQL* db = mysql_connect(); +if(!mysql_connected(db)) +{ + print("database unavailable: ", mysql_error(db), "\n"); +} +if(db != 0) mysql_disconnect(db); diff --git a/site/tests/services.uce b/site/tests/services.uce index a59b2bf..6af1104 100644 --- a/site/tests/services.uce +++ b/site/tests/services.uce @@ -117,6 +117,11 @@ RENDER(Request& context) ); MySQL unavailable_mysql; unavailable_mysql.connect("127.0.0.1", "__uce_intentionally_missing__", "not-a-real-password"); + mark( + "mysql_connected() distinguishes a failed connection wrapper", + !mysql_connected(&unavailable_mysql) ? "pass" : "fail", + mysql_connected(&unavailable_mysql) ? "unexpected live handle" : "no live handle" + ); unavailable_mysql.query("SELECT 1"); String unavailable_mysql_error = unavailable_mysql.error(); mark( diff --git a/src/lib/mysql-connector.h b/src/lib/mysql-connector.h index 2767a88..87ab875 100644 --- a/src/lib/mysql-connector.h +++ b/src/lib/mysql-connector.h @@ -71,6 +71,14 @@ inline MySQL* mysql_connect(String host = "localhost", String username = "root", return(db); } +// A failed connection retains a request-owned wrapper so mysql_error() remains +// available. Callers that need to decide whether to issue work must test the +// connection state rather than only the wrapper pointer. +inline bool mysql_connected(MySQL* m) +{ + return(m != 0 && m->connection != 0); +} + inline void mysql_disconnect(MySQL* m) { if(!m)