LCOV - code coverage report
Current view: top level - src/ctlib/unittests - row_count.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 58 84 69.0 %
Date: 2025-01-18 11:50:39 Functions: 3 3 100.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             : #include "common.h"
      56             : 
      57             : #include <freetds/replacements.h>
      58             : 
      59             : static CS_CONTEXT *ctx;
      60             : static CS_CONNECTION *conn;
      61             : static CS_COMMAND *cmd;
      62             : 
      63             : static CS_INT ex_display_results(CS_COMMAND * cmd, char *results);
      64             : 
      65             : static int test(int final_rows, int no_rows);
      66             : 
      67             : int
      68           8 : main(void)
      69             : {
      70           8 :         printf("%s: check row count returned\n", __FILE__);
      71           8 :         check_call(try_ctlogin, (&ctx, &conn, &cmd, 0));
      72           8 :         error_to_stdout = true;
      73             : 
      74             :         /* do not test error */
      75           8 :         run_command(cmd, "DROP PROCEDURE sample_rpc");
      76           8 :         run_command(cmd, "drop table #tmp1");
      77             : 
      78             :         /* test with rows from select */
      79           8 :         if (test(0, 0) || test(1, 0))
      80             :                 return 1;
      81             : 
      82             :         /* test with empty select */
      83           8 :         if (test(0, 1) || test(1, 1))
      84             :                 return 1;
      85             : 
      86           8 :         check_call(try_ctlogout, (ctx, conn, cmd, 0));
      87             : 
      88           8 :         return 0;
      89             : }
      90             : 
      91             : static int
      92          32 : test(int final_rows, int no_rows)
      93             : {
      94             :         CS_CHAR cmdbuf[4096];
      95             :         char results[1024];
      96             : 
      97          32 :         run_command(cmd, "create table #tmp1 (i int not null)");
      98             : 
      99          32 :         strlcpy(cmdbuf, "create proc sample_rpc as ", sizeof(cmdbuf));
     100             : 
     101          32 :         strlcpy(results, "CS_ROW_RESULT -1\n", sizeof(results));
     102          32 :         strlcat(cmdbuf, "insert into #tmp1 values(1) "
     103             :                         "insert into #tmp1 values(2) "
     104             :                         "insert into #tmp1 values(3) ", sizeof(cmdbuf)
     105             :         );
     106             : 
     107          32 :         if (no_rows) {
     108          16 :                 strlcat(cmdbuf,  "select * from #tmp1 where i > 10 ",
     109             :                         sizeof(cmdbuf));
     110          16 :                 strlcat(results, "CS_CMD_DONE 0\n", sizeof(results));
     111             :         } else {
     112          16 :                 strlcat(cmdbuf,  "select * from #tmp1 ", sizeof(cmdbuf));
     113          16 :                 strlcat(results, "CS_CMD_DONE 3\n", sizeof(results));
     114             :         }
     115             : 
     116          32 :         strlcat(results, "CS_STATUS_RESULT -1\n", sizeof(results));
     117             : 
     118          32 :         if (final_rows) {
     119          16 :                 strlcat(cmdbuf,  "insert into #tmp1 values(4) "
     120             :                                  "delete from #tmp1 where i <= 2 ",
     121             :                         sizeof(cmdbuf)
     122             :                 );
     123          16 :                 strlcat(results, "CS_CMD_SUCCEED 2\n"
     124             :                                  "CS_CMD_DONE 2\n", sizeof(results));
     125             :         } else {
     126          16 :                 strlcat(results, "CS_CMD_SUCCEED -1\n"
     127             :                                 "CS_CMD_DONE -1\n", sizeof(results));
     128             :         }
     129             : 
     130          32 :         printf("testing query:\n----\n%s\n----\n", cmdbuf);
     131             : 
     132          32 :         check_call(run_command, (cmd, cmdbuf));
     133             : 
     134          32 :         printf("----------\n");
     135          32 :         check_call(ct_command, (cmd, CS_RPC_CMD, "sample_rpc", CS_NULLTERM, CS_NO_RECOMPILE));
     136             : 
     137          32 :         check_call(ct_send, (cmd));
     138          32 :         ex_display_results(cmd, results);
     139             : 
     140             :         /* cleanup */
     141          32 :         run_command(cmd, "DROP PROCEDURE sample_rpc");
     142          32 :         run_command(cmd, "drop table #tmp1");
     143             : 
     144          32 :         return 0;
     145             : }
     146             : 
     147             : static CS_INT
     148          32 : ex_display_results(CS_COMMAND * cmd, char *results)
     149             : {
     150             :         CS_RETCODE ret;
     151             :         CS_INT res_type;
     152             :         CS_INT num_cols;
     153          32 :         CS_INT row_count = 0;
     154             :         CS_INT rows_read;
     155             :         CS_SMALLINT msg_id;
     156             : 
     157             :         /*
     158             :          * Process the results of the RPC.
     159             :          */
     160         224 :         while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
     161             :                 char res[32];
     162             :                 int rows, pos;
     163             : 
     164         160 :                 CS_INT rowsAffected = -1;
     165         160 :                 ct_res_info(cmd, CS_ROW_COUNT, &rowsAffected, CS_UNUSED, NULL);
     166         160 :                 printf("ct_results returned %s type and %d rows\n", res_type_str(res_type), (int) rowsAffected);
     167             : 
     168             :                 /* check expected results are the same as got ones */
     169         160 :                 pos = -1;
     170         160 :                 assert(sscanf(results, "%30s %d %n", res, &rows, &pos) >= 2 && pos > 0);
     171         160 :                 results += pos;
     172         160 :                 if (strcmp(res_type_str(res_type), res) != 0 || rowsAffected != rows) {
     173           0 :                         fprintf(stderr, "Expected ct_results %s rows %d\n", res, rows);
     174           0 :                         exit(1);
     175             :                 }
     176             : 
     177         160 :                 switch (res_type) {
     178          64 :                 case CS_ROW_RESULT:
     179             :                 case CS_PARAM_RESULT:
     180             :                 case CS_STATUS_RESULT:
     181             : 
     182             :                         /*
     183             :                          * All three of these result types are fetchable.
     184             :                          * Since the result model for rpcs and rows have
     185             :                          * been unified in the New Client-Library, we
     186             :                          * will use the same routine to display them
     187             :                          */
     188             : 
     189             :                         /*
     190             :                          * Find out how many columns there are in this result set.
     191             :                          */
     192          64 :                         check_call(ct_res_info, (cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL));
     193             : 
     194             :                         /*
     195             :                          * Make sure we have at least one column
     196             :                          */
     197          64 :                         if (num_cols <= 0) {
     198           0 :                                 fprintf(stderr, "ct_res_info(CS_NUMDATA) returned zero columns");
     199           0 :                                 return 1;
     200             :                         }
     201             : 
     202         144 :                         while (((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
     203          64 :                                                 &rows_read)) == CS_SUCCEED) || (ret == CS_ROW_FAIL)) {
     204             :                                 /*
     205             :                                  * Increment our row count by the number of rows just fetched.
     206             :                                  */
     207          80 :                                 row_count = row_count + rows_read;
     208             : 
     209             :                                 /*
     210             :                                  * Check if we hit a recoverable error.
     211             :                                  */
     212          80 :                                 if (ret == CS_ROW_FAIL) {
     213           0 :                                         printf("Error on row %d.\n", row_count);
     214           0 :                                         fflush(stdout);
     215             :                                 }
     216             :                         }
     217             : 
     218             :                         /*
     219             :                          * We're done processing rows.  Let's check the final return
     220             :                          * value of ct_fetch().
     221             :                          */
     222          64 :                         switch ((int) ret) {
     223          64 :                         case CS_END_DATA:
     224             :                                 /*
     225             :                                  * Everything went fine.
     226             :                                  */
     227          64 :                                 printf("All done processing rows.\n");
     228          64 :                                 fflush(stdout);
     229             :                                 break;
     230             : 
     231           0 :                         case CS_FAIL:
     232             :                                 /*
     233             :                                  * Something terrible happened.
     234             :                                  */
     235           0 :                                 fprintf(stderr, "ct_fetch returned CS_FAIL\n");
     236           0 :                                 return 1;
     237             :                                 break;
     238             : 
     239           0 :                         default:
     240             :                                 /*
     241             :                                  * We got an unexpected return value.
     242             :                                  */
     243           0 :                                 fprintf(stderr, "ct_fetch returned %d\n", ret);
     244           0 :                                 return 1;
     245             :                                 break;
     246             : 
     247             :                         }
     248          64 :                         break;
     249             : 
     250           0 :                 case CS_MSG_RESULT:
     251           0 :                         check_call(ct_res_info, (cmd, CS_MSGTYPE, (CS_VOID *) & msg_id, CS_UNUSED, NULL));
     252           0 :                         printf("ct_result returned CS_MSG_RESULT where msg id = %d.\n", msg_id);
     253           0 :                         fflush(stdout);
     254           0 :                         break;
     255             : 
     256             :                 case CS_CMD_SUCCEED:
     257             :                 case CS_CMD_DONE:
     258             :                 case CS_CMD_FAIL:
     259             :                         break;
     260             : 
     261           0 :                 default:
     262             :                         /*
     263             :                          * We got something unexpected.
     264             :                          */
     265           0 :                         fprintf(stderr, "ct_results returned unexpected result type.");
     266           0 :                         return CS_FAIL;
     267             :                 }
     268             :         }
     269             : 
     270             :         /*
     271             :          * We're done processing results. Let's check the
     272             :          * return value of ct_results() to see if everything
     273             :          * went ok.
     274             :          */
     275          32 :         switch ((int) ret) {
     276             :         case CS_END_RESULTS:
     277             :                 /*
     278             :                  * Everything went fine.
     279             :                  */
     280             :                 break;
     281             : 
     282           0 :         case CS_FAIL:
     283             :                 /*
     284             :                  * Something failed happened.
     285             :                  */
     286           0 :                 fprintf(stderr, "ct_results failed.");
     287           0 :                 break;
     288             : 
     289           0 :         default:
     290             :                 /*
     291             :                  * We got an unexpected return value.
     292             :                  */
     293           0 :                 fprintf(stderr, "ct_results returned unexpected result type.");
     294           0 :                 break;
     295             :         }
     296             : 
     297             :         return CS_SUCCEED;
     298             : }

Generated by: LCOV version 1.13