LCOV - code coverage report
Current view: top level - src/ctlib/unittests - blk_in_array.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 70 77 90.9 %
Date: 2026-11-07 23:58:45 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Test bulk copy in using array binding and blk_rowxfer_mult.
       3             :  * Check the row count passed to blk_rowxfer_mult, behaviour taken
       4             :  * from Sybase/SAP library.
       5             :  */
       6             : 
       7             : #include "common.h"
       8             : 
       9             : #include <bkpublic.h>
      10             : 
      11             : static const char table_name[] = "blk_in_array_test";
      12             : 
      13             : static CS_CONNECTION *conn;
      14             : static CS_COMMAND *cmd;
      15             : 
      16             : /* check rows in table and their sum, also checks connection is usable */
      17             : static void
      18          70 : check_table(CS_INT expected_count, CS_INT expected_sum)
      19             : {
      20             :         char sql[128];
      21             :         CS_DATAFMT fmt;
      22             :         CS_INT values[2], result_type, count;
      23             :         CS_RETCODE ret;
      24             :         int i;
      25             : 
      26          70 :         sprintf(sql, "select count(*), coalesce(sum(id), 0) from %s", table_name);
      27          70 :         check_call(ct_command, (cmd, CS_LANG_CMD, sql, CS_NULLTERM, CS_UNUSED));
      28          70 :         check_call(ct_send, (cmd));
      29         280 :         while ((ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
      30         140 :                 if (result_type != CS_ROW_RESULT)
      31          70 :                         continue;
      32         140 :                 for (i = 0; i < 2; i++) {
      33         140 :                         memset(&fmt, 0, sizeof(fmt));
      34         140 :                         fmt.datatype = CS_INT_TYPE;
      35         140 :                         fmt.maxlength = sizeof(CS_INT);
      36         140 :                         fmt.count = 1;
      37         140 :                         check_call(ct_bind, (cmd, i + 1, &fmt, &values[i], NULL, NULL));
      38             :                 }
      39         140 :                 while ((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count)) == CS_SUCCEED)
      40          70 :                         continue;
      41          70 :                 assert(ret == CS_END_DATA);
      42             :         }
      43          70 :         assert(ret == CS_END_RESULTS);
      44             : 
      45          70 :         if (values[0] != expected_count || values[1] != expected_sum) {
      46           0 :                 fprintf(stderr, "wrong table content, got %d rows sum %d, expected %d rows sum %d\n",
      47           0 :                         (int) values[0], (int) values[1], (int) expected_count, (int) expected_sum);
      48           0 :                 exit(1);
      49             :         }
      50          70 : }
      51             : 
      52             : /*
      53             :  * Bulk copy 3 bound rows (ids 1, 2 and 3) calling blk_rowxfer_mult
      54             :  * with given row count (NULL if row_count is NULL).
      55             :  */
      56             : static void
      57          70 : test(const CS_INT *row_count, CS_RETCODE expected_ret, CS_INT expected_rows)
      58             : {
      59             :         CS_BLKDESC *blkdesc;
      60             :         CS_DATAFMT fmt;
      61          70 :         CS_INT ids[3] = { 1, 2, 3 }, lens[3] = { 4, 4, 4 };
      62          70 :         CS_INT count = 0, rows = -1;
      63             :         CS_RETCODE ret;
      64             :         char sql[128];
      65             : 
      66          70 :         printf("row count %s%d\n", row_count ? "" : "NULL ", row_count ? (int) *row_count : 0);
      67             : 
      68          70 :         sprintf(sql, "delete from %s", table_name);
      69          70 :         check_call(run_command, (cmd, sql));
      70             : 
      71          70 :         check_call(blk_alloc, (conn, BLK_VERSION_100, &blkdesc));
      72          70 :         check_call(blk_init, (blkdesc, CS_BLK_IN, (char *) table_name, CS_NULLTERM));
      73             : 
      74          70 :         memset(&fmt, 0, sizeof(fmt));
      75          70 :         fmt.datatype = CS_INT_TYPE;
      76          70 :         fmt.maxlength = sizeof(CS_INT);
      77          70 :         fmt.count = 3;
      78          70 :         check_call(blk_bind, (blkdesc, 1, &fmt, ids, lens, NULL));
      79             : 
      80          70 :         if (row_count)
      81          60 :                 count = *row_count;
      82          70 :         ct_reset_last_message();
      83          70 :         ret = blk_rowxfer_mult(blkdesc, row_count ? &count : NULL);
      84          70 :         if (ret != expected_ret) {
      85           0 :                 fprintf(stderr, "blk_rowxfer_mult returned %d, expected %d\n", (int) ret, (int) expected_ret);
      86           0 :                 exit(1);
      87             :         }
      88          70 :         if (expected_ret == CS_FAIL)
      89          10 :                 check_last_message(CTMSG_CLIENT, 0x01010121, "row count greater than the array bind count");
      90             : 
      91          70 :         check_call(blk_done, (blkdesc, CS_BLK_ALL, &rows));
      92          70 :         if (rows != expected_rows) {
      93           0 :                 fprintf(stderr, "blk_done returned %d rows, expected %d\n", (int) rows, (int) expected_rows);
      94           0 :                 exit(1);
      95             :         }
      96          70 :         blk_drop(blkdesc);
      97             : 
      98          70 :         check_table(expected_rows, expected_rows * (expected_rows + 1) / 2);
      99          70 : }
     100             : 
     101          10 : TEST_MAIN()
     102             : {
     103             :         CS_CONTEXT *ctx;
     104          10 :         bool verbose = false;
     105             :         char sql[256];
     106             :         CS_INT row_count;
     107             : 
     108          10 :         printf("%s: Testing bulk copy in using array binding\n", __FILE__);
     109          10 :         check_call(try_ctlogin, (&ctx, &conn, &cmd, verbose));
     110             : 
     111          10 :         sprintf(sql, "if exists (select 1 from sysobjects where type = 'U' and name = '%s') drop table %s", table_name, table_name);
     112          10 :         check_call(run_command, (cmd, sql));
     113          10 :         sprintf(sql, "create table %s (id int not null)", table_name);
     114          10 :         check_call(run_command, (cmd, sql));
     115             : 
     116             :         /* NULL, zero or negative values send all bound rows */
     117          10 :         test(NULL, CS_SUCCEED, 3);
     118          10 :         row_count = 0;
     119          10 :         test(&row_count, CS_SUCCEED, 3);
     120          10 :         row_count = -1;
     121          10 :         test(&row_count, CS_SUCCEED, 3);
     122             : 
     123             :         /* positive values limit rows sent */
     124          10 :         row_count = 1;
     125          10 :         test(&row_count, CS_SUCCEED, 1);
     126          10 :         row_count = 2;
     127          10 :         test(&row_count, CS_SUCCEED, 2);
     128          10 :         row_count = 3;
     129          10 :         test(&row_count, CS_SUCCEED, 3);
     130             : 
     131             :         /* cannot send more rows than bound */
     132          10 :         row_count = 4;
     133          10 :         test(&row_count, CS_FAIL, 0);
     134             : 
     135          10 :         sprintf(sql, "drop table %s", table_name);
     136          10 :         check_call(run_command, (cmd, sql));
     137             : 
     138          10 :         printf("done\n");
     139             : 
     140          10 :         check_call(try_ctlogout, (ctx, conn, cmd, verbose));
     141             : 
     142          10 :         return 0;
     143             : }

Generated by: LCOV version 1.13