[ODBC-377] Timeouts set via ODBC do nothing Created: 2022-12-22  Updated: 2023-03-24  Resolved: 2023-03-12

Status: Closed
Project: MariaDB Connector/ODBC
Component/s: General
Affects Version/s: None
Fix Version/s: 3.2.0, 3.1.18

Type: Bug Priority: Major
Reporter: markus makela Assignee: Lawrin Novitsky
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Duplicate
is duplicated by ODBC-382 Connect timeout is not working Closed

 Description   

Looking at the source code, I see that SQL_ATTR_LOGIN_TIMEOUT is set but it does nothing. The SQL_ATTR_CONNECTION_TIMEOUT and SQL_ATTR_QUERY_TIMEOUT values are also either handled but ignored or not handled at all. Since the timeouts can be controlled via the connection string, I would expect that they are controllable with the ODBC attributes as well.

Here's a patch that I think should make it work like I described:

diff --git a/ma_statement.c b/ma_statement.c
--- ma_statement.c
+++ ma_statement.c
@@ -2771,11 +2771,17 @@
     break;
   case SQL_ATTR_QUERY_TIMEOUT:
     if ((SQLULEN)ValuePtr != 0)
     {
-       MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default (no timeout)", 0);
-       ret= SQL_SUCCESS_WITH_INFO;
+       mysql_optionsv(Stmt->Connection->mariadb, MYSQL_OPT_READ_TIMEOUT, ValuePtr);
+       mysql_optionsv(Stmt->Connection->mariadb, MYSQL_OPT_WRITE_TIMEOUT, ValuePtr);
     }
+    else
+    {
+       int Timeout = INT_MAX;
+       mysql_optionsv(Stmt->Connection->mariadb, MYSQL_OPT_READ_TIMEOUT, &Timeout);
+       mysql_optionsv(Stmt->Connection->mariadb, MYSQL_OPT_WRITE_TIMEOUT, &Timeout);
+    }
     break;
   case SQL_ATTR_RETRIEVE_DATA:
     if ((SQLULEN)ValuePtr != SQL_RD_ON)
     {
diff --git a/ma_connection.c b/ma_connection.c
--- ma_connection.c
+++ ma_connection.c
@@ -263,8 +263,11 @@
       }
       MADB_RESET(Dbc->CurrentSchema, Dbc->CatalogName);
     }
     break;
+  case SQL_ATTR_CONNECTION_TIMEOUT:
+    Dbc->ConnectionTimeout= (SQLUINTEGER)(SQLULEN)ValuePtr;
+    break;
   case SQL_ATTR_LOGIN_TIMEOUT:
     Dbc->LoginTimeout= (SQLUINTEGER)(SQLULEN)ValuePtr;
     break;
   case SQL_ATTR_METADATA_ID:
@@ -400,9 +403,9 @@
   case SQL_ATTR_LOGIN_TIMEOUT:
     *(SQLUINTEGER *)ValuePtr= Dbc->LoginTimeout;
     break;
   case SQL_ATTR_CONNECTION_TIMEOUT:
-    *(SQLUINTEGER *)ValuePtr= 0;
+    *(SQLUINTEGER *)ValuePtr= Dbc->ConnectionTimeout;
     break;
   case SQL_ATTR_METADATA_ID:
     /* SQL_ATTR_METADATA_ID is SQLUINTEGER attribute on connection level, but SQLULEN on statement level :/ */
     *(SQLUINTEGER *)ValuePtr= Dbc->MetadataId;
@@ -806,14 +809,26 @@
   {
     mysql_optionsv(Connection->mariadb, MYSQL_INIT_COMMAND, InitCmd.str);
   }
 
+  if (Connection->LoginTimeout)
+    mysql_optionsv(Connection->mariadb, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&Connection->LoginTimeout);
+
+  if (Connection->ConnectionTimeout)
+    mysql_optionsv(Connection->mariadb, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&Connection->ConnectionTimeout);
+
   if (Dsn->ConnectionTimeout)
     mysql_optionsv(Connection->mariadb, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&Dsn->ConnectionTimeout);
 
+  if (Connection->ReadTimeout)
+    mysql_optionsv(Connection->mariadb, MYSQL_OPT_READ_TIMEOUT, (const char *)&Connection->ReadTimeout);
+
   if (Dsn->ReadTimeout)
     mysql_optionsv(Connection->mariadb, MYSQL_OPT_READ_TIMEOUT, (const char *)&Dsn->ReadTimeout);
 
+  if (Connection->WriteTimeout)
+    mysql_optionsv(Connection->mariadb, MYSQL_OPT_WRITE_TIMEOUT, (const char *)&Connection->WriteTimeout);
+
   if (Dsn->WriteTimeout)
     mysql_optionsv(Connection->mariadb, MYSQL_OPT_WRITE_TIMEOUT, (const char *)&Dsn->WriteTimeout);
 
   if (DSN_OPTION(Connection, MADB_OPT_FLAG_AUTO_RECONNECT))



 Comments   
Comment by Lawrin Novitsky [ 2023-03-12 ]

Spect define SQL_ATTR_CONNECTION_TIMEOUT attribute as:
"An SQLUINTEGER value corresponding to the number of seconds to wait for any request on the connection to complete before returning to the application. The driver should return SQLSTATE HYT00 (Timeout expired) anytime that it is possible to time out in a situation not associated with query execution or login."
As I read it - we can't support this, thus it stays 0 adn we report warning on attempts to set it.

Comment by Lawrin Novitsky [ 2023-03-12 ]

Attribute SQL_ATTR_LOGIN_TIMEOUT was not considered during connect.
CONN_TIMEOUT connstring option value will still take precedence over SQL_ATTR_LOGIN_TIMEOUT value, though.

SQL_ATTR_CONNECTION_TIMEOUT we did not support, and are not going to so far.

Adding support of SQL_ATTR_QUERY_TIMEOUT statement attribute. It is done using "SET STATEMENT max_statement_time= FOR " construction and only works for MariaDB servers.

Generated at Thu Feb 08 03:28:15 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.