LCOV - code coverage report
Current view: top level - src/odbc/unittests - qn.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 60 63 95.2 %
Date: 2025-01-18 12:13:41 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : 
       3             : #include <assert.h>
       4             : #include "odbcss.h"
       5             : #include <freetds/thread.h>
       6             : #include <freetds/replacements.h>
       7             : 
       8             : /* test query notifications */
       9             : 
      10             : #define SWAP(t,a,b) do { t xyz = a; a = b; b = xyz; } while(0)
      11             : #define SWAP_CONN() do { SWAP(HENV,env,odbc_env); SWAP(HDBC,dbc,odbc_conn); SWAP(HSTMT,stmt,odbc_stmt);} while(0)
      12             : 
      13             : static HENV env = SQL_NULL_HENV;
      14             : static HDBC dbc = SQL_NULL_HDBC;
      15             : static HSTMT stmt = SQL_NULL_HSTMT;
      16             : 
      17           2 : static TDS_THREAD_PROC_DECLARE(change_thread_proc, arg)
      18             : {
      19           2 :         SQLHSTMT odbc_stmt = stmt;
      20             : 
      21           2 :         odbc_command("UPDATE ftds_test SET v = 'hi!'");
      22           2 :         CHKMoreResults("No");
      23           2 :         CHKMoreResults("SNo");
      24             : 
      25           2 :         return TDS_THREAD_RESULT(0);
      26             : }
      27             : 
      28             : int
      29           8 : main(int argc, char *argv[])
      30             : {
      31           8 :         char *sql = NULL;
      32             :         tds_thread th;
      33             :         SQLSMALLINT cols, col;
      34             :         char message[1024];
      35             : 
      36           8 :         odbc_use_version3 = 1;
      37           8 :         odbc_connect();
      38             : 
      39           8 :         if (!odbc_db_is_microsoft() || odbc_tds_version() < 0x702) {
      40           6 :                 odbc_disconnect();
      41           6 :                 printf("Query notifications available only using TDS 7.2 or newer\n");
      42           6 :                 odbc_test_skipped();
      43           0 :                 return 0;
      44             :         }
      45             : 
      46           2 :         sql = odbc_buf_asprintf(&odbc_buf, "ALTER DATABASE %s SET ENABLE_BROKER", odbc_database);
      47           2 :         odbc_command(sql);
      48             : 
      49           2 :         odbc_command2("DROP SERVICE FTDS_Service", "SENo");
      50           2 :         odbc_command2("DROP QUEUE FTDS_Queue", "SENo");
      51           2 :         odbc_command2("DROP TABLE ftds_test", "SENo");
      52             : 
      53           2 :         odbc_command("CREATE TABLE ftds_test(i int PRIMARY KEY, v varchar(100))");
      54           2 :         odbc_command("INSERT INTO ftds_test VALUES(1, 'hello')");
      55             : 
      56           2 :         odbc_command("CREATE QUEUE FTDS_Queue\n"
      57             :                      "CREATE SERVICE FTDS_Service ON QUEUE FTDS_Queue\n"
      58             :                      "([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]);");
      59             : 
      60             :         /* clear queue */
      61             :         for (;;) {
      62           2 :                 odbc_command("RECEIVE * FROM FTDS_Queue");
      63           2 :                 if (CHKFetch("SNo") == SQL_NO_DATA)
      64             :                         break;
      65           0 :                 CHKMoreResults("SNo");
      66           0 :                 CHKMoreResults("SNo");
      67             :         }
      68           2 :         odbc_reset_statement();
      69             : 
      70             :         /* connect another time for thread */
      71           2 :         SWAP_CONN();
      72           2 :         odbc_connect();
      73           2 :         SWAP_CONN();
      74             : 
      75           2 :         sql = odbc_buf_asprintf(&odbc_buf, "service=FTDS_Service;local database=%s", odbc_database);
      76           2 :         CHKSetStmtAttr(SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS, T(sql), SQL_NTS, "S");
      77           2 :         CHKSetStmtAttr(SQL_SOPT_SS_QUERYNOTIFICATION_MSGTEXT, T("Table has changed"), SQL_NTS, "S");
      78           2 :         CHKSetStmtAttr(SQL_SOPT_SS_QUERYNOTIFICATION_TIMEOUT, TDS_INT2PTR(60), SQL_IS_UINTEGER, "S");
      79             : 
      80           2 :         odbc_command("SELECT v FROM dbo.ftds_test");
      81             : 
      82           2 :         odbc_reset_statement();
      83             : 
      84             :         /* launch another thread to update the table we are looking to */
      85           2 :         assert(tds_thread_create(&th, change_thread_proc, NULL) == 0);
      86             : 
      87           2 :         odbc_command("WAITFOR (RECEIVE * FROM FTDS_Queue)");
      88             : 
      89           2 :         memset(message, 0, sizeof(message));
      90           2 :         CHKNumResultCols(&cols, "S");
      91           6 :         while (CHKFetch("SNo") == SQL_SUCCESS) {
      92          28 :                 for (col = 0; col < cols; ++col) {
      93             :                         char buf[1024];
      94             :                         SQLLEN len;
      95             :                         SQLTCHAR name[128];
      96             :                         SQLSMALLINT namelen, type, digits, nullable;
      97             :                         SQLULEN size;
      98             : 
      99          28 :                         CHKDescribeCol(col + 1, name, TDS_VECTOR_SIZE(name), &namelen, &type, &size, &digits, &nullable, "S");
     100          28 :                         if (col == 13) {
     101           2 :                                 CHKGetData(col + 1, SQL_C_BINARY, buf, sizeof(buf), &len, "S");
     102             :                         } else {
     103          26 :                                 CHKGetData(col + 1, SQL_C_CHAR, buf, sizeof(buf), &len, "S");
     104             :                         }
     105          28 :                         if (col == 13) {
     106             :                                 int i;
     107         586 :                                 for (i = 2; i < len; i+= 2)
     108         586 :                                         buf[i / 2 - 1] = buf[i];
     109           2 :                                 buf[len / 2 - 1] = 0;
     110           2 :                                 strcpy(message, buf);
     111             :                         }
     112          28 :                         printf("%s: %s\n", C(name), buf);
     113             :                 }
     114             :         }
     115             : 
     116           4 :         tds_thread_join(th, NULL);
     117             : 
     118           2 :         SWAP_CONN();
     119           2 :         odbc_disconnect();
     120           2 :         SWAP_CONN();
     121             : 
     122             :         /* cleanup */
     123           2 :         odbc_command2("DROP SERVICE FTDS_Service", "SENo");
     124           2 :         odbc_command2("DROP QUEUE FTDS_Queue", "SENo");
     125           2 :         odbc_command2("DROP TABLE ftds_test", "SENo");
     126             : 
     127           2 :         odbc_disconnect();
     128             : 
     129           2 :         assert(strstr(message, "Table has changed") != NULL);
     130           2 :         assert(strstr(message, "info=\"update\"") != NULL);
     131             : 
     132             :         return 0;
     133             : }
     134             : 

Generated by: LCOV version 1.13