LCOV - code coverage report
Current view: top level - src/ctlib/unittests - row_count.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 72 123 58.5 %
Date: 2025-01-18 12:13:41 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /*
       2             :  * Tests rows count
       3             :  *
       4             :  * These are the results using Sybase CT-Library. This test check that ct_results returns the same results.
       5             :  *
       6             :  *
       7             :  *                      "insert into #tmp1 values(1) "
       8             :  *                      "insert into #tmp1 values(2) "
       9             :  *                      "insert into #tmp1 values(3) "
      10             :  *                      "select * from #tmp1 "
      11             :  *
      12             :  * Open Client Message:
      13             :  * number 16843050 layer 1 origin 1 severity 1 number 42
      14             :  * msgstring: ct_res_info(ROWCOUNT): user api layer: external error: This routine cannot be called after ct_results() returns a result type of CS_ROW_RESULT.
      15             :  * osstring: (null)
      16             :  * ct_results returned CS_ROW_RESULT type and -1 rows
      17             :  * All done processing rows.
      18             :  * ct_results returned CS_CMD_DONE type and 3 rows
      19             :  *
      20             :  * Open Client Message:
      21             :  * number 16843051 layer 1 origin 1 severity 1 number 43
      22             :  * msgstring: ct_res_info(ROWCOUNT): user api layer: external error: This routine cannot be called after ct_results() returns a result type of CS_STATUS_RESULT.
      23             :  * osstring: (null)
      24             :  * ct_results returned CS_STATUS_RESULT type and -1 rows
      25             :  * All done processing rows.
      26             :  * ct_results returned CS_CMD_SUCCEED type and -1 rows
      27             :  * ct_results returned CS_CMD_DONE type and -1 rows
      28             :  *
      29             :  *
      30             :  *                      "insert into #tmp1 values(1) "
      31             :  *                      "insert into #tmp1 values(2) "
      32             :  *                      "insert into #tmp1 values(3) "
      33             :  *                      "select * from #tmp1 "
      34             :  *                      "insert into #tmp1 values(4) "
      35             :  *                      "delete from #tmp1 where i <= 2 "
      36             :  *
      37             :  * Open Client Message:
      38             :  * number 16843050 layer 1 origin 1 severity 1 number 42
      39             :  * msgstring: ct_res_info(ROWCOUNT): user api layer: external error: This routine cannot be called after ct_results() returns a result type of CS_ROW_RESULT.
      40             :  * osstring: (null)
      41             :  * ct_results returned CS_ROW_RESULT type and -1 rows
      42             :  * All done processing rows.
      43             :  * ct_results returned CS_CMD_DONE type and 3 rows
      44             :  *
      45             :  * Open Client Message:
      46             :  * number 16843051 layer 1 origin 1 severity 1 number 43
      47             :  * msgstring: ct_res_info(ROWCOUNT): user api layer: external error: This routine cannot be called after ct_results() returns a result type of CS_STATUS_RESULT.
      48             :  * osstring: (null)
      49             :  * ct_results returned CS_STATUS_RESULT type and -1 rows
      50             :  * All done processing rows.
      51             :  * ct_results returned CS_CMD_SUCCEED type and 2 rows
      52             :  * ct_results returned CS_CMD_DONE type and 2 rows
      53             :  */
      54             : 
      55             : #undef NDEBUG
      56             : #include <config.h>
      57             : 
      58             : #include <stdio.h>
      59             : 
      60             : #if HAVE_STDLIB_H
      61             : #include <stdlib.h>
      62             : #endif /* HAVE_STDLIB_H */
      63             : 
      64             : #if HAVE_STRING_H
      65             : #include <string.h>
      66             : #endif /* HAVE_STRING_H */
      67             : 
      68             : #include <assert.h>
      69             : #include <ctpublic.h>
      70             : #include "common.h"
      71             : #include <freetds/replacements.h>
      72             : 
      73             : static CS_CONTEXT *ctx;
      74             : static CS_CONNECTION *conn;
      75             : static CS_COMMAND *cmd;
      76             : 
      77             : static CS_RETCODE ex_clientmsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_CLIENTMSG * errmsg);
      78             : static CS_RETCODE ex_servermsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_SERVERMSG * errmsg);
      79             : static CS_INT ex_display_results(CS_COMMAND * cmd, char *results);
      80             : 
      81             : static int test(int final_rows, int no_rows);
      82             : 
      83             : int
      84           8 : main(int argc, char *argv[])
      85             : {
      86             :         CS_RETCODE ret;
      87             : 
      88           8 :         printf("%s: check row count returned\n", __FILE__);
      89           8 :         ret = try_ctlogin(&ctx, &conn, &cmd, 0);
      90           8 :         if (ret != CS_SUCCEED) {
      91           0 :                 fprintf(stderr, "Login failed\n");
      92           0 :                 return 1;
      93             :         }
      94             : 
      95           8 :         ct_callback(ctx, NULL, CS_SET, CS_CLIENTMSG_CB, (CS_VOID *) ex_clientmsg_cb);
      96           8 :         ct_callback(ctx, NULL, CS_SET, CS_SERVERMSG_CB, (CS_VOID *) ex_servermsg_cb);
      97             : 
      98             :         /* do not test error */
      99           8 :         run_command(cmd, "DROP PROCEDURE sample_rpc");
     100           8 :         run_command(cmd, "drop table #tmp1");
     101             : 
     102             :         /* test with rows from select */
     103           8 :         if (test(0, 0) || test(1, 0))
     104             :                 return 1;
     105             : 
     106             :         /* test with empty select */
     107           8 :         if (test(0, 1) || test(1, 1))
     108             :                 return 1;
     109             : 
     110           8 :         ret = try_ctlogout(ctx, conn, cmd, 0);
     111           8 :         if (ret != CS_SUCCEED) {
     112           0 :                 fprintf(stderr, "Logout failed\n");
     113           0 :                 return 1;
     114             :         }
     115             : 
     116             :         return 0;
     117             : }
     118             : 
     119             : static int
     120          32 : test(int final_rows, int no_rows)
     121             : {
     122             :         CS_RETCODE ret;
     123             :         CS_CHAR cmdbuf[4096];
     124             :         char results[1024];
     125             : 
     126          32 :         run_command(cmd, "create table #tmp1 (i int not null)");
     127             : 
     128          32 :         strlcpy(cmdbuf, "create proc sample_rpc as ", sizeof(cmdbuf));
     129             : 
     130          32 :         strlcpy(results, "CS_ROW_RESULT -1\n", sizeof(results));
     131          32 :         strlcat(cmdbuf, "insert into #tmp1 values(1) "
     132             :                         "insert into #tmp1 values(2) "
     133             :                         "insert into #tmp1 values(3) ", sizeof(cmdbuf)
     134             :         );
     135             : 
     136          32 :         if (no_rows) {
     137          16 :                 strlcat(cmdbuf,  "select * from #tmp1 where i > 10 ",
     138             :                         sizeof(cmdbuf));
     139          16 :                 strlcat(results, "CS_CMD_DONE 0\n", sizeof(results));
     140             :         } else {
     141          16 :                 strlcat(cmdbuf,  "select * from #tmp1 ", sizeof(cmdbuf));
     142          16 :                 strlcat(results, "CS_CMD_DONE 3\n", sizeof(results));
     143             :         }
     144             : 
     145          32 :         strlcat(results, "CS_STATUS_RESULT -1\n", sizeof(results));
     146             : 
     147          32 :         if (final_rows) {
     148          16 :                 strlcat(cmdbuf,  "insert into #tmp1 values(4) "
     149             :                                  "delete from #tmp1 where i <= 2 ",
     150             :                         sizeof(cmdbuf)
     151             :                 );
     152          16 :                 strlcat(results, "CS_CMD_SUCCEED 2\n"
     153             :                                  "CS_CMD_DONE 2\n", sizeof(results));
     154             :         } else {
     155          16 :                 strlcat(results, "CS_CMD_SUCCEED -1\n"
     156             :                                 "CS_CMD_DONE -1\n", sizeof(results));
     157             :         }
     158             : 
     159          32 :         printf("testing query:\n----\n%s\n----\n", cmdbuf);
     160             : 
     161          32 :         ret = run_command(cmd, cmdbuf);
     162          32 :         if (ret != CS_SUCCEED) {
     163           0 :                 fprintf(stderr, "create proc failed\n");
     164           0 :                 return 1;
     165             :         }
     166             : 
     167          32 :         printf("----------\n");
     168          32 :         if ((ret = ct_command(cmd, CS_RPC_CMD, "sample_rpc", CS_NULLTERM, CS_NO_RECOMPILE)) != CS_SUCCEED) {
     169           0 :                 fprintf(stderr, "ct_command(CS_RPC_CMD) failed");
     170           0 :                 return 1;
     171             :         }
     172             : 
     173          32 :         if (ct_send(cmd) != CS_SUCCEED) {
     174           0 :                 fprintf(stderr, "ct_send(RPC) failed");
     175           0 :                 return 1;
     176             :         }
     177          32 :         ex_display_results(cmd, results);
     178             : 
     179             :         /* cleanup */
     180          32 :         run_command(cmd, "DROP PROCEDURE sample_rpc");
     181          32 :         run_command(cmd, "drop table #tmp1");
     182             : 
     183          32 :         return 0;
     184             : }
     185             : 
     186             : static CS_INT
     187          32 : ex_display_results(CS_COMMAND * cmd, char *results)
     188             : {
     189             :         CS_RETCODE ret;
     190             :         CS_INT res_type;
     191             :         CS_INT num_cols;
     192          32 :         CS_INT row_count = 0;
     193             :         CS_INT rows_read;
     194             :         CS_SMALLINT msg_id;
     195             : 
     196             :         /*
     197             :          * Process the results of the RPC.
     198             :          */
     199         224 :         while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
     200             :                 char res[32];
     201             :                 int rows, pos;
     202             : 
     203         160 :                 CS_INT rowsAffected = -1;
     204         160 :                 ct_res_info(cmd, CS_ROW_COUNT, &rowsAffected, CS_UNUSED, NULL);
     205         160 :                 printf("ct_results returned %s type and %d rows\n", res_type_str(res_type), (int) rowsAffected);
     206             : 
     207             :                 /* check expected results are the same as got ones */
     208         160 :                 pos = -1;
     209         160 :                 assert(sscanf(results, "%30s %d %n", res, &rows, &pos) >= 2 && pos > 0);
     210         160 :                 results += pos;
     211         160 :                 if (strcmp(res_type_str(res_type), res) != 0 || rowsAffected != rows) {
     212           0 :                         fprintf(stderr, "Expected ct_results %s rows %d\n", res, rows);
     213           0 :                         exit(1);
     214             :                 }
     215             : 
     216         160 :                 switch (res_type) {
     217          64 :                 case CS_ROW_RESULT:
     218             :                 case CS_PARAM_RESULT:
     219             :                 case CS_STATUS_RESULT:
     220             : 
     221             :                         /*
     222             :                          * All three of these result types are fetchable.
     223             :                          * Since the result model for rpcs and rows have
     224             :                          * been unified in the New Client-Library, we
     225             :                          * will use the same routine to display them
     226             :                          */
     227             : 
     228             :                         /*
     229             :                          * Find out how many columns there are in this result set.
     230             :                          */
     231          64 :                         ret = ct_res_info(cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL);
     232          64 :                         if (ret != CS_SUCCEED) {
     233           0 :                                 fprintf(stderr, "ct_res_info(CS_NUMDATA) failed");
     234           0 :                                 return 1;
     235             :                         }
     236             : 
     237             :                         /*
     238             :                          * Make sure we have at least one column
     239             :                          */
     240          64 :                         if (num_cols <= 0) {
     241           0 :                                 fprintf(stderr, "ct_res_info(CS_NUMDATA) returned zero columns");
     242           0 :                                 return 1;
     243             :                         }
     244             : 
     245         144 :                         while (((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
     246          64 :                                                 &rows_read)) == CS_SUCCEED) || (ret == CS_ROW_FAIL)) {
     247             :                                 /*
     248             :                                  * Increment our row count by the number of rows just fetched.
     249             :                                  */
     250          80 :                                 row_count = row_count + rows_read;
     251             : 
     252             :                                 /*
     253             :                                  * Check if we hit a recoverable error.
     254             :                                  */
     255          80 :                                 if (ret == CS_ROW_FAIL) {
     256           0 :                                         printf("Error on row %d.\n", row_count);
     257           0 :                                         fflush(stdout);
     258             :                                 }
     259             :                         }
     260             : 
     261             :                         /*
     262             :                          * We're done processing rows.  Let's check the final return
     263             :                          * value of ct_fetch().
     264             :                          */
     265          64 :                         switch ((int) ret) {
     266          64 :                         case CS_END_DATA:
     267             :                                 /*
     268             :                                  * Everything went fine.
     269             :                                  */
     270          64 :                                 printf("All done processing rows.\n");
     271          64 :                                 fflush(stdout);
     272             :                                 break;
     273             : 
     274           0 :                         case CS_FAIL:
     275             :                                 /*
     276             :                                  * Something terrible happened.
     277             :                                  */
     278           0 :                                 fprintf(stderr, "ct_fetch returned CS_FAIL\n");
     279           0 :                                 return 1;
     280             :                                 break;
     281             : 
     282           0 :                         default:
     283             :                                 /*
     284             :                                  * We got an unexpected return value.
     285             :                                  */
     286           0 :                                 fprintf(stderr, "ct_fetch returned %d\n", ret);
     287           0 :                                 return 1;
     288             :                                 break;
     289             : 
     290             :                         }
     291          64 :                         break;
     292             : 
     293           0 :                 case CS_MSG_RESULT:
     294           0 :                         ret = ct_res_info(cmd, CS_MSGTYPE, (CS_VOID *) & msg_id, CS_UNUSED, NULL);
     295           0 :                         if (ret != CS_SUCCEED) {
     296           0 :                                 fprintf(stderr, "ct_res_info(msg_id) failed");
     297           0 :                                 return 1;
     298             :                         }
     299           0 :                         printf("ct_result returned CS_MSG_RESULT where msg id = %d.\n", msg_id);
     300           0 :                         fflush(stdout);
     301           0 :                         break;
     302             : 
     303             :                 case CS_CMD_SUCCEED:
     304             :                 case CS_CMD_DONE:
     305             :                 case CS_CMD_FAIL:
     306             :                         break;
     307             : 
     308           0 :                 default:
     309             :                         /*
     310             :                          * We got something unexpected.
     311             :                          */
     312           0 :                         fprintf(stderr, "ct_results returned unexpected result type.");
     313           0 :                         return CS_FAIL;
     314             :                 }
     315             :         }
     316             : 
     317             :         /*
     318             :          * We're done processing results. Let's check the
     319             :          * return value of ct_results() to see if everything
     320             :          * went ok.
     321             :          */
     322          32 :         switch ((int) ret) {
     323             :         case CS_END_RESULTS:
     324             :                 /*
     325             :                  * Everything went fine.
     326             :                  */
     327             :                 break;
     328             : 
     329           0 :         case CS_FAIL:
     330             :                 /*
     331             :                  * Something failed happened.
     332             :                  */
     333           0 :                 fprintf(stderr, "ct_results failed.");
     334           0 :                 break;
     335             : 
     336           0 :         default:
     337             :                 /*
     338             :                  * We got an unexpected return value.
     339             :                  */
     340           0 :                 fprintf(stderr, "ct_results returned unexpected result type.");
     341           0 :                 break;
     342             :         }
     343             : 
     344             :         return CS_SUCCEED;
     345             : }
     346             : 
     347             : static CS_RETCODE
     348           0 : ex_clientmsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_CLIENTMSG * errmsg)
     349             : {
     350           0 :         printf("\nOpen Client Message:\n");
     351           0 :         printf("Message number: LAYER = (%ld) ORIGIN = (%ld) ", (long) CS_LAYER(errmsg->msgnumber), (long) CS_ORIGIN(errmsg->msgnumber));
     352           0 :         printf("SEVERITY = (%ld) NUMBER = (%ld)\n", (long) CS_SEVERITY(errmsg->msgnumber), (long) CS_NUMBER(errmsg->msgnumber));
     353           0 :         printf("Message String: %s\n", errmsg->msgstring);
     354           0 :         if (errmsg->osstringlen > 0) {
     355           0 :                 printf("Operating System Error: %s\n", errmsg->osstring);
     356             :         }
     357           0 :         fflush(stdout);
     358             : 
     359           0 :         return CS_SUCCEED;
     360             : }
     361             : 
     362             : static CS_RETCODE
     363          14 : ex_servermsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_SERVERMSG * srvmsg)
     364             : {
     365          14 :         printf("\nServer message:\n");
     366          14 :         printf("Message number: %ld, Severity %ld, ", (long) srvmsg->msgnumber, (long) srvmsg->severity);
     367          14 :         printf("State %ld, Line %ld\n", (long) srvmsg->state, (long) srvmsg->line);
     368             : 
     369          14 :         if (srvmsg->svrnlen > 0) {
     370          14 :                 printf("Server '%s'\n", srvmsg->svrname);
     371             :         }
     372             : 
     373          14 :         if (srvmsg->proclen > 0) {
     374           0 :                 printf(" Procedure '%s'\n", srvmsg->proc);
     375             :         }
     376             : 
     377          14 :         printf("Message String: %s\n", srvmsg->text);
     378          14 :         fflush(stdout);
     379             : 
     380          14 :         return CS_SUCCEED;
     381             : }

Generated by: LCOV version 1.13