LCOV - code coverage report
Current view: top level - src/ctlib/unittests - ct_dynamic.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 140 167 83.8 %
Date: 2025-10-13 15:16:19 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : 
       3             : #include <stdarg.h>
       4             : 
       5             : static int verbose = 0;
       6             : 
       7             : static CS_CONTEXT *ctx;
       8             : static CS_CONNECTION *conn;
       9             : static CS_COMMAND *cmd;
      10             : static CS_COMMAND *cmd2;
      11             : 
      12             : static void
      13           8 : cleanup(void)
      14             : {
      15           8 :         if (verbose) {
      16           0 :                 printf("Trying logout\n");
      17             :         }
      18             : 
      19           8 :         if (cmd2)
      20           8 :                 ct_cmd_drop(cmd2);
      21             : 
      22           8 :         check_call(try_ctlogout, (ctx, conn, cmd, verbose));
      23           8 : }
      24             : 
      25             : static void
      26         232 : chk(int check, const char *fmt, ...)
      27             : {
      28             :         va_list ap;
      29             : 
      30         232 :         if (check)
      31         232 :                 return;
      32             : 
      33           0 :         va_start(ap, fmt);
      34           0 :         vfprintf(stderr, fmt, ap);
      35           0 :         va_end(ap);
      36             : 
      37           0 :         cleanup();
      38           0 :         exit(1);
      39             : }
      40             : 
      41          10 : TEST_MAIN()
      42             : {
      43             :         CS_RETCODE ret;
      44             :         CS_RETCODE results_ret;
      45             :         CS_CHAR cmdbuf[4096];
      46             :         CS_CHAR name[257];
      47             :         CS_INT datalength;
      48             :         CS_SMALLINT ind;
      49             :         CS_INT count;
      50             :         CS_INT num_cols;
      51          10 :         CS_INT row_count = 0;
      52             :         CS_DATAFMT datafmt;
      53             :         CS_DATAFMT descfmt;
      54             :         CS_INT intvar;
      55             :         CS_INT intvarsize;
      56             :         CS_SMALLINT intvarind;
      57             :         CS_INT res_type;
      58             : 
      59             :         int i;
      60             : 
      61          10 :         if (argc > 1 && (0 == strcmp(argv[1], "-v")))
      62           0 :                 verbose = 1;
      63             : 
      64          10 :         printf("%s: use ct_dynamic to prepare and execute  a statement\n", __FILE__);
      65          10 :         if (verbose) {
      66           0 :                 printf("Trying login\n");
      67             :         }
      68          10 :         check_call(try_ctlogin, (&ctx, &conn, &cmd, verbose));
      69           8 :         error_to_stdout = true;
      70             : 
      71           8 :         check_call(ct_cmd_alloc, (conn, &cmd2));
      72             : 
      73             :         /* do not test error */
      74           8 :         run_command(cmd, "IF OBJECT_ID('tempdb..#ct_dynamic') IS NOT NULL DROP table #ct_dynamic");
      75             : 
      76           8 :         strcpy(cmdbuf, "create table #ct_dynamic (id numeric identity not null, \
      77             :         name varchar(30), age int, cost money, bdate datetime, fval float) ");
      78             : 
      79           8 :         check_call(run_command, (cmd, cmdbuf));
      80             : 
      81           8 :         strcpy(cmdbuf, "insert into #ct_dynamic ( name , age , cost , bdate , fval ) ");
      82           8 :         strcat(cmdbuf, "values ('Bill', 44, 2000.00, 'May 21 1960', 60.97 ) ");
      83             : 
      84           8 :         check_call(run_command, (cmd, cmdbuf));
      85             : 
      86           8 :         strcpy(cmdbuf, "insert into #ct_dynamic ( name , age , cost , bdate , fval ) ");
      87           8 :         strcat(cmdbuf, "values ('Freddy', 32, 1000.00, 'Jan 21 1972', 70.97 ) ");
      88             : 
      89           8 :         check_call(run_command, (cmd, cmdbuf));
      90             : 
      91           8 :         strcpy(cmdbuf, "insert into #ct_dynamic ( name , age , cost , bdate , fval ) ");
      92           8 :         strcat(cmdbuf, "values ('James', 42, 5000.00, 'May 21 1962', 80.97 ) ");
      93             : 
      94           8 :         check_call(run_command, (cmd, cmdbuf));
      95             : 
      96           8 :         strcpy(cmdbuf, "select name from #ct_dynamic where age = ?");
      97             : 
      98           8 :         check_call(ct_dynamic, (cmd, CS_PREPARE, "age", CS_NULLTERM, cmdbuf, CS_NULLTERM));
      99             : 
     100           8 :         check_call(ct_send, (cmd));
     101             : 
     102          32 :         while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
     103          16 :                 switch ((int) res_type) {
     104             : 
     105             :                 case CS_CMD_SUCCEED:
     106             :                 case CS_CMD_DONE:
     107             :                         break;
     108             : 
     109             :                 case CS_CMD_FAIL:
     110             :                         break;
     111             : 
     112           0 :                 default:
     113           0 :                         chk(0, "invalid ct_results result type: %d\n", res_type);
     114             :                 }
     115             :         }
     116           8 :         chk(ret == CS_END_RESULTS, "ct_results() unexpected return.\n", (int) ret);
     117             : 
     118           8 :         check_call(ct_dynamic, (cmd, CS_DESCRIBE_INPUT, "age", CS_NULLTERM, NULL, CS_UNUSED));
     119             : 
     120           8 :         check_call(ct_send, (cmd));
     121             : 
     122          32 :         while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
     123          16 :                 switch ((int) res_type) {
     124             : 
     125           8 :                 case CS_DESCRIBE_RESULT:
     126           8 :                         check_call(ct_res_info, (cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL));
     127             : 
     128          10 :                         for (i = 1; i <= num_cols; i++) {
     129           2 :                                 check_call(ct_describe, (cmd, i, &descfmt));
     130           2 :                                 fprintf(stderr, "CS_DESCRIBE_INPUT parameter %d :\n", i);
     131           2 :                                 if (descfmt.namelen == 0)
     132           2 :                                         fprintf(stderr, "\t\tNo name...\n");
     133             :                                 else
     134           0 :                                         fprintf(stderr, "\t\tName = %*.*s\n", descfmt.namelen, descfmt.namelen, descfmt.name);
     135           2 :                                 fprintf(stderr, "\t\tType   = %d\n", descfmt.datatype);
     136           2 :                                 fprintf(stderr, "\t\tLength = %d\n", descfmt.maxlength);
     137             :                         }
     138             :                         break;
     139             : 
     140             :                 case CS_CMD_SUCCEED:
     141             :                 case CS_CMD_DONE:
     142             :                         break;
     143             : 
     144             :                 case CS_CMD_FAIL:
     145             :                         break;
     146             : 
     147           0 :                 default:
     148           0 :                         chk(0, "invalid ct_results result type: %d\n", res_type);
     149             :                 }
     150             :         }
     151             : 
     152           8 :         check_call(ct_dynamic, (cmd, CS_DESCRIBE_OUTPUT, "age", CS_NULLTERM, NULL, CS_UNUSED));
     153             : 
     154           8 :         check_call(ct_send, (cmd));
     155             : 
     156          32 :         while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
     157          16 :                 switch ((int) res_type) {
     158             : 
     159           8 :                 case CS_DESCRIBE_RESULT:
     160           8 :                         check_call(ct_res_info, (cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL));
     161           8 :                         chk(num_cols == 1, "CS_DESCRIBE_OUTPUT showed %d columns , expected 1\n", num_cols);
     162             : 
     163          16 :                         for (i = 1; i <= num_cols; i++) {
     164           8 :                                 check_call(ct_describe, (cmd, i, &descfmt));
     165             : 
     166           8 :                                 if (descfmt.namelen == 0)
     167           0 :                                         fprintf(stderr, "\t\tNo name...\n");
     168             :                                 else
     169           8 :                                         fprintf(stderr, "\t\tName = %*.*s\n", descfmt.namelen, descfmt.namelen, descfmt.name);
     170           8 :                                 fprintf(stderr, "\t\tType   = %d\n", descfmt.datatype);
     171           8 :                                 fprintf(stderr, "\t\tLength = %d\n", descfmt.maxlength);
     172             :                         }
     173             :                         break;
     174             : 
     175             :                 case CS_CMD_SUCCEED:
     176             :                 case CS_CMD_DONE:
     177             :                         break;
     178             : 
     179             :                 case CS_CMD_FAIL:
     180             :                         break;
     181             : 
     182           0 :                 default:
     183           0 :                         chk(0, "invalid ct_results result type: %d\n", res_type);
     184             :                 }
     185             :         }
     186             : 
     187             :         /* execute dynamic on a second command to check it still works */
     188           8 :         check_call(ct_dynamic, (cmd2, CS_EXECUTE, "age", CS_NULLTERM, NULL, CS_UNUSED));
     189             : 
     190           8 :         intvar = 44;
     191           8 :         intvarsize = 4;
     192           8 :         intvarind = 0;
     193             : 
     194           8 :         datafmt.name[0] = 0;
     195           8 :         datafmt.namelen = 0;
     196           8 :         datafmt.datatype = CS_INT_TYPE;
     197           8 :         datafmt.status = CS_INPUTVALUE;
     198             : 
     199           8 :         check_call(ct_setparam, (cmd2, &datafmt, (CS_VOID *) & intvar, &intvarsize, &intvarind));
     200             : 
     201           8 :         check_call(ct_send, (cmd2));
     202             : 
     203           8 :         while ((results_ret = ct_results(cmd2, &res_type)) == CS_SUCCEED) {
     204          32 :                 chk(res_type != CS_CMD_FAIL, "1: ct_results() result_type CS_CMD_FAIL.\n");
     205          32 :                 chk(res_type != CS_COMPUTE_RESULT, "ct_results() unexpected CS_COMPUTE_RESULT.\n");
     206             : 
     207          32 :                 switch ((int) res_type) {
     208             :                 case CS_CMD_SUCCEED:
     209             :                         break;
     210             :                 case CS_CMD_DONE:
     211             :                         break;
     212           8 :                 case CS_ROW_RESULT:
     213           8 :                         datafmt.datatype = CS_CHAR_TYPE;
     214           8 :                         datafmt.format = CS_FMT_NULLTERM;
     215           8 :                         datafmt.maxlength = 256;
     216           8 :                         datafmt.count = 1;
     217           8 :                         datafmt.locale = NULL;
     218           8 :                         check_call(ct_bind, (cmd2, 1, &datafmt, name, &datalength, &ind));
     219             : 
     220          24 :                         while (((ret = ct_fetch(cmd2, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count)) == CS_SUCCEED)
     221           8 :                                || (ret == CS_ROW_FAIL)) {
     222           8 :                                 row_count += count;
     223           8 :                                 chk(ret != CS_ROW_FAIL, "ct_fetch() CS_ROW_FAIL on row %d.\n", row_count);
     224           8 :                                 if (ret == CS_SUCCEED) {
     225           8 :                                         chk(!strcmp(name, "Bill"), "fetched value '%s' expected 'Bill'\n", name);
     226             :                                 } else {
     227             :                                         break;
     228             :                                 }
     229             :                         }
     230           8 :                         chk(ret == CS_END_DATA, "ct_fetch() unexpected return %d.\n", (int) ret);
     231           8 :                         break;
     232           0 :                 default:
     233           0 :                         fprintf(stderr, "ct_results() unexpected result_type.\n");
     234           0 :                         return 1;
     235             :                 }
     236             :         }
     237           8 :         chk(results_ret == CS_END_RESULTS, "ct_results() unexpected return.\n", (int) results_ret);
     238             : 
     239           8 :         intvar = 32;
     240             : 
     241           8 :         check_call(ct_send, (cmd2));
     242             : 
     243           8 :         while ((results_ret = ct_results(cmd2, &res_type)) == CS_SUCCEED) {
     244          32 :                 chk(res_type != CS_CMD_FAIL, "2: ct_results() result_type CS_CMD_FAIL.\n");
     245          32 :                 chk(res_type != CS_COMPUTE_RESULT, "ct_results() unexpected CS_COMPUTE_RESULT.\n");
     246             : 
     247          32 :                 switch ((int) res_type) {
     248             :                 case CS_CMD_SUCCEED:
     249             :                         break;
     250             :                 case CS_CMD_DONE:
     251             :                         break;
     252           8 :                 case CS_ROW_RESULT:
     253           8 :                         datafmt.datatype = CS_CHAR_TYPE;
     254           8 :                         datafmt.format = CS_FMT_NULLTERM;
     255           8 :                         datafmt.maxlength = 256;
     256           8 :                         datafmt.count = 1;
     257           8 :                         datafmt.locale = NULL;
     258           8 :                         check_call(ct_bind, (cmd2, 1, &datafmt, name, &datalength, &ind));
     259             : 
     260          24 :                         while (((ret = ct_fetch(cmd2, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count)) == CS_SUCCEED)
     261           8 :                                || (ret == CS_ROW_FAIL)) {
     262           8 :                                 row_count += count;
     263           8 :                                 chk(ret != CS_ROW_FAIL, "ct_fetch() CS_ROW_FAIL on row %d.\n", row_count);
     264             : 
     265           8 :                                 if (ret == CS_SUCCEED) {
     266           8 :                                         chk(!strcmp(name, "Freddy"), "fetched value '%s' expected 'Freddy'\n", name);
     267             :                                 } else {
     268             :                                         break;
     269             :                                 }
     270             :                         }
     271           8 :                         chk(ret == CS_END_DATA, "ct_fetch() unexpected return %d.\n", (int) ret);
     272           8 :                         break;
     273           0 :                 default:
     274           0 :                         fprintf(stderr, "ct_results() unexpected result_type.\n");
     275           0 :                         return 1;
     276             :                 }
     277             :         }
     278           8 :         chk(results_ret == CS_END_RESULTS, "ct_results() unexpected return.\n", (int) results_ret);
     279             : 
     280           8 :         check_call(ct_dynamic, (cmd, CS_DEALLOC, "age", CS_NULLTERM, NULL, CS_UNUSED));
     281             : 
     282           8 :         check_call(ct_send, (cmd));
     283             : 
     284          20 :         while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
     285           4 :                 switch ((int) res_type) {
     286             : 
     287             :                 case CS_CMD_SUCCEED:
     288             :                 case CS_CMD_DONE:
     289             :                         break;
     290             : 
     291             :                 case CS_CMD_FAIL:
     292             :                         break;
     293             : 
     294           0 :                 default:
     295           0 :                         chk(0, "invalid ct_results result type: %d\n", res_type);
     296             :                 }
     297             :         }
     298           8 :         chk(ret == CS_END_RESULTS, "ct_results() unexpected return.\n", (int) ret);
     299             : 
     300             :         /*
     301             :          * check we can prepare again dynamic with same name after deallocation
     302             :          */
     303           8 :         strcpy(cmdbuf, "select name from #ct_dynamic where age = ?");
     304           8 :         check_call(ct_dynamic, (cmd, CS_PREPARE, "age", CS_NULLTERM, cmdbuf, CS_NULLTERM));
     305             : 
     306           8 :         check_call(ct_send, (cmd));
     307             : 
     308          32 :         while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
     309          16 :                 switch ((int) res_type) {
     310             : 
     311             :                 case CS_CMD_SUCCEED:
     312             :                 case CS_CMD_DONE:
     313             :                         break;
     314             : 
     315             :                 case CS_CMD_FAIL:
     316             :                         break;
     317             : 
     318           0 :                 default:
     319           0 :                         chk(0, "invalid ct_results result type: %d\n", res_type);
     320             :                 }
     321             :         }
     322           8 :         chk(ret == CS_END_RESULTS, "ct_results() unexpected return.\n", (int) ret);
     323             : 
     324           8 :         ct_dynamic(cmd, CS_DEALLOC, "invalid", CS_NULLTERM, NULL, CS_UNUSED);
     325           8 :         ct_send(cmd);
     326          16 :         while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED)
     327           0 :                 chk(res_type != CS_ROW_RESULT, "Rows not expected\n");
     328           8 :         chk(ret == CS_END_RESULTS, "ct_results() unexpected return.\n", (int) ret);
     329             : 
     330           8 :         check_call(ct_dynamic, (cmd2, CS_EXECUTE, "age", CS_NULLTERM, NULL, CS_UNUSED));
     331             : 
     332           8 :         intvar = 32;
     333           8 :         intvarsize = 4;
     334           8 :         intvarind = 0;
     335             : 
     336           8 :         datafmt.name[0] = 0;
     337           8 :         datafmt.namelen = 0;
     338           8 :         datafmt.datatype = CS_INT_TYPE;
     339           8 :         datafmt.status = CS_INPUTVALUE;
     340             : 
     341           8 :         check_call(ct_setparam, (cmd2, &datafmt, (CS_VOID *) & intvar, &intvarsize, &intvarind));
     342           8 :         check_call(ct_send, (cmd2));
     343             : 
     344             :         /* all tests succeeded */
     345             : 
     346           8 :         cleanup();
     347           8 :         return 0;
     348             : }

Generated by: LCOV version 1.13