LCOV - code coverage report
Current view: top level - src/odbc/unittests - bcp.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 192 207 92.8 %
Date: 2026-11-10 08:16:44 Functions: 10 10 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : #define TDSODBC_BCP
       3             : #include <odbcss.h>
       4             : #include <assert.h>
       5             : 
       6             : #ifdef UNICODE
       7             : typedef SQLWCHAR bcp_init_char_t;
       8             : #else
       9             : typedef char bcp_init_char_t;
      10             : #endif
      11             : 
      12             : struct prefixed_int {
      13             :         ODBCINT64 prefix;
      14             :         int value;
      15             : };
      16             : struct prefixed_str {
      17             :         ODBCINT64 prefix;
      18             :         char value[64];
      19             : };
      20             : 
      21             : /*
      22             :  * Static data for insertion
      23             :  */
      24             : static struct prefixed_int not_null_bit           = {4, 1};
      25             : static struct prefixed_str not_null_char          = {64, "a char"};
      26             : static struct prefixed_str not_null_varchar       = {64, "a varchar"};
      27             : static struct prefixed_str not_null_datetime      = {64, "2003-12-17 15:44:00.000"};
      28             : static struct prefixed_str not_null_smalldatetime = {64, "2003-12-17 15:44:00"};
      29             : static struct prefixed_str not_null_money         = {64, "12.341"};
      30             : static struct prefixed_str not_null_smallmoney    = {64, "12.34"};
      31             : static struct prefixed_str not_null_float         = {64, "12.34"};
      32             : static struct prefixed_str not_null_real          = {64, "12.34"};
      33             : static struct prefixed_str not_null_decimal       = {64, "12.34"};
      34             : static struct prefixed_str not_null_numeric       = {64, "12.34"};
      35             : static struct prefixed_int not_null_int           = {4, 1234};
      36             : static struct prefixed_int not_null_smallint      = {4, 1234};
      37             : static struct prefixed_int not_null_tinyint       = {4, 123};
      38             : static struct prefixed_str not_null_nvarchar      = {64, "a wide var"};
      39             : static ODBCINT64 null_prefix = -1;
      40             : 
      41             : static const char *expected[] = {
      42             :         "1",
      43             :         "a char    ","a varchar","2003-12-17 15:44:00.000","2003-12-17 15:44:00",
      44             :         "12.3410","12.3400","12.34","12.3400002","12.34","12.34",
      45             :         "1234","1234","123",
      46             :         "a wide var",
      47             : };
      48             : static const int total_cols = 29;
      49             : 
      50             : static const char *expected_special[] = {
      51             :         "2015-03-14 15:26:53.000",
      52             :         "2015-03-14 15:26:53.589793",
      53             :         "3.141593000",
      54             :         "3.141593",           /* MS driver has "3141593" here. Bug? Should we be bug-compatible? */
      55             :         "hello",
      56             :         "",
      57             :         "\xd3\xd4"
      58             : };
      59             : 
      60             : static int tds_version;
      61             : 
      62             : static void
      63             : cleanup(void)
      64             : {
      65          20 :         odbc_command("if object_id('all_types_bcp_unittest') is not null drop table all_types_bcp_unittest\n"
      66             :                      "if object_id('special_types_bcp_unittest') is not null drop table special_types_bcp_unittest");
      67             : }
      68             : 
      69             : static void
      70          10 : init(void)
      71             : {
      72             :         cleanup();
      73             : 
      74          10 :         odbc_command("CREATE TABLE all_types_bcp_unittest ("
      75             :                 "  not_null_bit                  bit NOT NULL"
      76             :                 ""
      77             :                 ", not_null_char                 char(10) NOT NULL"
      78             :                 ", not_null_varchar              varchar(10) NOT NULL"
      79             :                 ""
      80             :                 ", not_null_datetime             datetime NOT NULL"
      81             :                 ", not_null_smalldatetime        smalldatetime NOT NULL"
      82             :                 ""
      83             :                 ", not_null_money                money NOT NULL"
      84             :                 ", not_null_smallmoney           smallmoney NOT NULL"
      85             :                 ""
      86             :                 ", not_null_float                float NOT NULL"
      87             :                 ", not_null_real                 real NOT NULL"
      88             :                 ""
      89             :                 ", not_null_decimal              decimal(5,2) NOT NULL"
      90             :                 ", not_null_numeric              numeric(5,2) NOT NULL"
      91             :                 ""
      92             :                 ", not_null_int                  int NOT NULL"
      93             :                 ", not_null_smallint             smallint NOT NULL"
      94             :                 ", not_null_tinyint              tinyint NOT NULL"
      95             :                 ", not_null_nvarchar             nvarchar(10) NOT NULL"
      96             :                 ""
      97             :                 ", nullable_char                 char(10)  NULL"
      98             :                 ", nullable_varchar              varchar(10)  NULL"
      99             :                 ""
     100             :                 ", nullable_datetime             datetime  NULL"
     101             :                 ", nullable_smalldatetime        smalldatetime  NULL"
     102             :                 ""
     103             :                 ", nullable_money                money  NULL"
     104             :                 ", nullable_smallmoney           smallmoney  NULL"
     105             :                 ""
     106             :                 ", nullable_float                float  NULL"
     107             :                 ", nullable_real                 real  NULL"
     108             :                 ""
     109             :                 ", nullable_decimal              decimal(5,2)  NULL"
     110             :                 ", nullable_numeric              numeric(5,2)  NULL"
     111             :                 ""
     112             :                 ", nullable_int                  int  NULL"
     113             :                 ", nullable_smallint             smallint  NULL"
     114             :                 ", nullable_tinyint              tinyint  NULL"
     115             :                 ", nullable_nvarchar             nvarchar(10)  NULL"
     116             :                 ")");
     117             : 
     118          10 :         if (tds_version < 0x703)
     119             :                 return;
     120             : 
     121             :                 /* Excludes:
     122             :                  * binary
     123             :                  * image
     124             :                  * uniqueidentifier
     125             :                  * varbinary
     126             :                  * text
     127             :                  * timestamp
     128             :                  * nchar
     129             :                  * ntext
     130             :                  * nvarchar
     131             :                  */
     132           4 :         odbc_command("CREATE TABLE special_types_bcp_unittest ("
     133             :                 "dt datetime not null,"
     134             :                 "dt2 datetime2(6) not null,"
     135             :                 "num decimal(19,9) not null,"
     136             :                 "numstr varchar(64) not null,"
     137             :                 "str nvarchar(6) not null,"
     138             :                 "empty varchar(64) not null,"
     139             :                 "cp varchar(64) collate SQL_Latin1_General_CP850_CI_AS not null,"
     140             :                 "bitnull bit null"
     141             :                 ")");
     142             : }
     143             : 
     144             : #define VARCHAR_BIND(x) \
     145             :         bcp_bind( odbc_conn, \
     146             :                   (prefixlen == 0 ? (void*)&x.value : (void*)&x.prefix), \
     147             :                   prefixlen, (SQLINTEGER) strlen(x.value), NULL, termlen, \
     148             :                   BCP_TYPE_SQLVARCHAR, col++ )
     149             : 
     150             : #define INT_BIND(x) \
     151             :         bcp_bind( odbc_conn, (prefixlen == 0 ? (void*)&x.value : (void*)&x.prefix), prefixlen, \
     152             :                 SQL_VARLEN_DATA, NULL, termlen, BCP_TYPE_SQLINT4,    col++ )
     153             : 
     154             : #define NULL_BIND(x, type) \
     155             :         bcp_bind( odbc_conn, (prefixlen == 0 ? (void*)&x.value : (void*)&null_prefix), prefixlen, \
     156             :                 prefixlen == 0 ? SQL_NULL_DATA : SQL_VARLEN_DATA, NULL, termlen, type,    col++ )
     157             : 
     158             : static void
     159          20 : test_bind(int prefixlen)
     160             : {
     161             :         enum { termlen = 0 };
     162             : 
     163             :         RETCODE fOK;
     164          20 :         int col=1;
     165             : 
     166             :         /* non nulls */
     167          40 :         fOK = INT_BIND(not_null_bit);
     168          20 :         assert(fOK == SUCCEED);
     169             : 
     170          40 :         fOK = VARCHAR_BIND(not_null_char);
     171          20 :         assert(fOK == SUCCEED);
     172          40 :         fOK = VARCHAR_BIND(not_null_varchar);
     173          20 :         assert(fOK == SUCCEED);
     174             : 
     175          40 :         fOK = VARCHAR_BIND(not_null_datetime);
     176          20 :         assert(fOK == SUCCEED);
     177          40 :         fOK = VARCHAR_BIND(not_null_smalldatetime);
     178          20 :         assert(fOK == SUCCEED);
     179             : 
     180          40 :         fOK = VARCHAR_BIND(not_null_money);
     181          20 :         assert(fOK == SUCCEED);
     182          40 :         fOK = VARCHAR_BIND(not_null_smallmoney);
     183          20 :         assert(fOK == SUCCEED);
     184             : 
     185          40 :         fOK = VARCHAR_BIND(not_null_float);
     186          20 :         assert(fOK == SUCCEED);
     187          40 :         fOK = VARCHAR_BIND(not_null_real);
     188          20 :         assert(fOK == SUCCEED);
     189             : 
     190          40 :         fOK = VARCHAR_BIND(not_null_decimal);
     191          20 :         assert(fOK == SUCCEED);
     192          40 :         fOK = VARCHAR_BIND(not_null_numeric);
     193          20 :         assert(fOK == SUCCEED);
     194             : 
     195          40 :         fOK = INT_BIND(not_null_int);
     196          20 :         assert(fOK == SUCCEED);
     197          40 :         fOK = INT_BIND(not_null_smallint);
     198          20 :         assert(fOK == SUCCEED);
     199          40 :         fOK = INT_BIND(not_null_tinyint);
     200          20 :         assert(fOK == SUCCEED);
     201          40 :         fOK = VARCHAR_BIND(not_null_nvarchar);
     202          20 :         assert(fOK == SUCCEED);
     203             : 
     204             :         /* nulls */
     205             :         assert(fOK == SUCCEED);
     206          40 :         fOK = NULL_BIND(not_null_char, BCP_TYPE_SQLVARCHAR);
     207          20 :         assert(fOK == SUCCEED);
     208          40 :         fOK = NULL_BIND(not_null_varchar, BCP_TYPE_SQLVARCHAR);
     209          20 :         assert(fOK == SUCCEED);
     210             : 
     211          40 :         fOK = NULL_BIND(not_null_datetime, BCP_TYPE_SQLVARCHAR);
     212          20 :         assert(fOK == SUCCEED);
     213          40 :         fOK = NULL_BIND(not_null_smalldatetime, BCP_TYPE_SQLVARCHAR);
     214          20 :         assert(fOK == SUCCEED);
     215             : 
     216          40 :         fOK = NULL_BIND(not_null_money, BCP_TYPE_SQLVARCHAR);
     217          20 :         assert(fOK == SUCCEED);
     218          40 :         fOK = NULL_BIND(not_null_smallmoney, BCP_TYPE_SQLVARCHAR);
     219          20 :         assert(fOK == SUCCEED);
     220             : 
     221          40 :         fOK = NULL_BIND(not_null_float, BCP_TYPE_SQLVARCHAR);
     222          20 :         assert(fOK == SUCCEED);
     223          40 :         fOK = NULL_BIND(not_null_real, BCP_TYPE_SQLVARCHAR);
     224          20 :         assert(fOK == SUCCEED);
     225             : 
     226          40 :         fOK = NULL_BIND(not_null_decimal, BCP_TYPE_SQLVARCHAR);
     227          20 :         assert(fOK == SUCCEED);
     228          40 :         fOK = NULL_BIND(not_null_numeric, BCP_TYPE_SQLVARCHAR);
     229          20 :         assert(fOK == SUCCEED);
     230             : 
     231          40 :         fOK = NULL_BIND(not_null_int, BCP_TYPE_SQLINT4);
     232          20 :         assert(fOK == SUCCEED);
     233          40 :         fOK = NULL_BIND(not_null_smallint, BCP_TYPE_SQLINT4);
     234          20 :         assert(fOK == SUCCEED);
     235          40 :         fOK = NULL_BIND(not_null_tinyint, BCP_TYPE_SQLINT4);
     236          20 :         assert(fOK == SUCCEED);
     237          40 :         fOK = NULL_BIND(not_null_nvarchar, BCP_TYPE_SQLVARCHAR);
     238          20 :         assert(fOK == SUCCEED);
     239             : 
     240          20 : }
     241             : 
     242             : static void
     243          10 : set_attr(void)
     244             : {
     245          10 :         CHKSetConnectAttr(SQL_COPT_SS_BCP, (SQLPOINTER)SQL_BCP_ON, 0, "S");
     246          10 : }
     247             : 
     248             : static void
     249             : report_bcp_error(const char *errmsg, int line, const char *file)
     250             : {
     251           0 :         odbc_stmt = NULL;
     252           0 :         odbc_report_error(errmsg, line, file);
     253             : }
     254             : 
     255             : static void normal_inserts(int prefixlen);
     256             : static void normal_select(void);
     257             : static void special_inserts(void);
     258             : static void special_select(void);
     259             : 
     260             : static const char table_name[] = "all_types_bcp_unittest";
     261             : 
     262             : static void
     263          80 : check_bind(int line, const void *varaddr, int varlen, const void *terminator, int termlen, int vartype, int table_column,
     264             :            const char *sqlstate)
     265             : {
     266             :         RETCODE rc;
     267          80 :         SQLHSTMT stmt = odbc_stmt;
     268             : 
     269         160 :         rc = bcp_bind(odbc_conn, (const unsigned char *) varaddr, 0, varlen, (const unsigned char *) terminator, termlen,
     270             :                       vartype, table_column);
     271          80 :         if (!sqlstate) {
     272          20 :                 if (rc != SUCCEED)
     273             :                         report_bcp_error("bcp_bind", line, __FILE__);
     274             :                 return;
     275             :         }
     276          60 :         if (rc != FAIL) {
     277           0 :                 fprintf(stderr, "line %d: bcp_bind succeeded unexpectedly\n", line);
     278           0 :                 exit(1);
     279             :         }
     280          60 :         odbc_stmt = NULL;
     281          60 :         odbc_read_error();
     282          60 :         odbc_stmt = stmt;
     283          60 :         if (strcmp(odbc_sqlstate, sqlstate) != 0) {
     284           0 :                 fprintf(stderr, "line %d: wrong SQLSTATE %s, expected %s\n", line, odbc_sqlstate, sqlstate);
     285           0 :                 exit(1);
     286             :         }
     287             : }
     288             : 
     289             : /* bindings rejected as data size cannot be computed (used to crash) */
     290             : static void
     291          10 : bind_errors(void)
     292             : {
     293             :         static const char str[] = "hello";
     294             :         static const int num = 1234;
     295             : 
     296          20 :         if (bcp_init(odbc_conn, (bcp_init_char_t *) T(table_name), NULL, NULL, BCP_DIRECTION_IN) == FAIL)
     297             :                 report_bcp_error("bcp_init", __LINE__, __FILE__);
     298             : 
     299             :         /* NULL terminator */
     300          10 :         check_bind(__LINE__, &num, SQL_VARLEN_DATA, NULL, 1, BCP_TYPE_SQLINT4, 12, "HY009");
     301          10 :         check_bind(__LINE__, str, SQL_VARLEN_DATA, NULL, 1, BCP_TYPE_SQLVARCHAR, 3, "HY009");
     302             : 
     303             :         /* no length, prefix or terminator */
     304          10 :         check_bind(__LINE__, str, SQL_VARLEN_DATA, NULL, 0, BCP_TYPE_SQLVARCHAR, 3, "HY009");
     305          10 :         check_bind(__LINE__, str, SQL_VARLEN_DATA, "", 0, BCP_TYPE_SQLVARCHAR, 3, "HY009");
     306          10 :         check_bind(__LINE__, str, SQL_VARLEN_DATA, NULL, -1, BCP_TYPE_SQLVARCHAR, 3, "HY009");
     307          10 :         check_bind(__LINE__, str, SQL_VARLEN_DATA, NULL, 0, BCP_TYPE_SQLDECIMAL, 10, "HY009");
     308             : 
     309             :         /* fixed types do not need it */
     310          10 :         check_bind(__LINE__, &num, SQL_VARLEN_DATA, NULL, 0, BCP_TYPE_SQLINT4, 12, NULL);
     311          10 :         check_bind(__LINE__, &num, SQL_VARLEN_DATA, NULL, 0, 0, 12, NULL);
     312             : 
     313          10 :         bcp_done(odbc_conn);
     314          10 : }
     315             : 
     316          10 : TEST_MAIN()
     317             : {
     318             :         const char *s;
     319             : 
     320          10 :         odbc_set_conn_attr = set_attr;
     321          10 :         odbc_conn_additional_params = "ClientCharset=ISO-8859-1;";
     322          10 :         odbc_connect();
     323             : 
     324          10 :         tds_version = odbc_tds_version();
     325             : 
     326          10 :         init();
     327             : 
     328          10 :         bind_errors();
     329             : 
     330          10 :         normal_inserts(0);
     331          10 :         if (tds_version >= 0x703)
     332           4 :                 special_inserts();
     333          10 :         normal_select();
     334          10 :         if (tds_version >= 0x703)
     335           4 :                 special_select();
     336             : 
     337          10 :         odbc_command("delete from all_types_bcp_unittest");
     338          10 :         normal_inserts(8);
     339          10 :         normal_select();
     340             : 
     341          10 :         if ((s = getenv("BCP")) != NULL && 0 == strcmp(s, "nodrop")) {
     342           0 :                 printf("BCP=nodrop: tables kept\n");
     343             :         } else {
     344          10 :                 printf("Dropping tables\n");
     345             :                 cleanup();
     346             :         }
     347             : 
     348          10 :         odbc_disconnect();
     349             : 
     350          10 :         printf("Done.\n");
     351          10 :         return 0;
     352             : }
     353             : 
     354             : static void
     355          20 : normal_inserts(int prefixlen)
     356             : {
     357             :         int i;
     358             :         int rows_sent;
     359             : 
     360             :         /* set up and send the bcp */
     361          20 :         printf("preparing to insert into %s ... ", table_name);
     362          40 :         if (bcp_init(odbc_conn, (bcp_init_char_t *) T(table_name), NULL, NULL, BCP_DIRECTION_IN) == FAIL)
     363             :                 report_bcp_error("bcp_init", __LINE__, __FILE__);
     364          20 :         printf("OK\n");
     365             : 
     366          20 :         test_bind(prefixlen);
     367             : 
     368          20 :         printf("Sending same row 10 times... \n");
     369         220 :         for (i=0; i<10; i++)
     370         400 :                 if (bcp_sendrow(odbc_conn) == FAIL)
     371             :                         report_bcp_error("bcp_sendrow", __LINE__, __FILE__);
     372             : 
     373             : #if 1
     374          20 :         rows_sent = bcp_batch(odbc_conn);
     375          20 :         if (rows_sent == -1)
     376             :                 report_bcp_error("bcp_batch", __LINE__, __FILE__);
     377             : #endif
     378             : 
     379          20 :         printf("OK\n");
     380             : 
     381             :         /* end bcp.  */
     382          20 :         rows_sent = bcp_done(odbc_conn);
     383          20 :         if (rows_sent != 0)
     384             :                 report_bcp_error("bcp_done", __LINE__, __FILE__);
     385             :         else
     386          20 :                 printf("%d rows copied.\n", rows_sent);
     387             : 
     388          20 :         printf("done\n");
     389          20 : }
     390             : 
     391             : static void
     392           4 : special_inserts(void)
     393             : {
     394             :         int rows_sent;
     395             :         SQL_TIMESTAMP_STRUCT timestamp;
     396             :         DBDATETIME datetime;
     397             :         SQL_NUMERIC_STRUCT numeric;
     398             :         SQLWCHAR hello[6], oo[3];
     399             : 
     400           4 :         printf("sending special types\n");
     401           4 :         rows_sent = 0;
     402             : 
     403           8 :         if (bcp_init(odbc_conn, (bcp_init_char_t *) T("special_types_bcp_unittest"), NULL, NULL, BCP_DIRECTION_IN) == FAIL)
     404             :                 report_bcp_error("bcp_init", __LINE__, __FILE__);
     405           4 :         printf("OK\n");
     406             : 
     407           8 :         if (bcp_control(odbc_conn, BCPHINTSA, (void *) "TABLOCK") != SUCCEED)
     408             :                 report_bcp_error("bcp_init", __LINE__, __FILE__);
     409             : 
     410           4 :         datetime.dtdays = 42075;
     411           4 :         datetime.dttime = 16683900;
     412           4 :         timestamp.year = 2015;
     413           4 :         timestamp.month = 3;
     414           4 :         timestamp.day = 14;
     415           4 :         timestamp.hour = 15;
     416           4 :         timestamp.minute = 26;
     417           4 :         timestamp.second = 53;
     418           4 :         timestamp.fraction = 589793000;
     419           4 :         memset(&numeric, 0, sizeof(numeric));
     420           4 :         numeric.precision = 19;
     421           4 :         numeric.scale = 6;
     422           4 :         numeric.sign = 1;
     423           4 :         numeric.val[0] = 0xd9;
     424           4 :         numeric.val[1] = 0xef;
     425           4 :         numeric.val[2] = 0x2f;
     426           4 :         odbc_to_sqlwchar(hello, "hello", 6);
     427           4 :         odbc_to_sqlwchar(oo, "\xd3\xd4", 3);
     428           8 :         bcp_bind(odbc_conn, (unsigned char *) &datetime, 0, sizeof(datetime), NULL, 0, BCP_TYPE_SQLDATETIME, 1);
     429           8 :         bcp_bind(odbc_conn, (unsigned char *) &timestamp, 0, sizeof(timestamp), NULL, 0, BCP_TYPE_SQLDATETIME2, 2);
     430           8 :         bcp_bind(odbc_conn, (unsigned char *) &numeric, 0, sizeof(numeric), NULL, 0, BCP_TYPE_SQLDECIMAL, 3);
     431           8 :         bcp_bind(odbc_conn, (unsigned char *) &numeric, 0, sizeof(numeric), NULL, 0, BCP_TYPE_SQLDECIMAL, 4);
     432           8 :         bcp_bind(odbc_conn, (unsigned char *) hello, 0, 10, NULL, 0, BCP_TYPE_SQLNVARCHAR, 5);
     433           8 :         bcp_bind(odbc_conn, (unsigned char *) "", 0, 0, NULL, 0, BCP_TYPE_SQLVARCHAR, 6);
     434           8 :         bcp_bind(odbc_conn, (unsigned char *) oo, 0, 4, NULL, 0, BCP_TYPE_SQLNVARCHAR, 7);
     435           8 :         bcp_bind(odbc_conn, (unsigned char *) &not_null_bit, 0, SQL_NULL_DATA, NULL, 0, BCP_TYPE_SQLINT4, 8);
     436             : 
     437           8 :         if (bcp_sendrow(odbc_conn) == FAIL)
     438             :                 report_bcp_error("bcp_sendrow", __LINE__, __FILE__);
     439             : 
     440           4 :         rows_sent = bcp_batch(odbc_conn);
     441           4 :         if (rows_sent != 1)
     442             :                 report_bcp_error("bcp_batch", __LINE__, __FILE__);
     443             : 
     444           4 :         printf("OK\n");
     445             : 
     446             :         /* end bcp.  */
     447             : 
     448           4 :         rows_sent = bcp_done(odbc_conn);
     449           4 :         if (rows_sent != 0)
     450             :                 report_bcp_error("bcp_done", __LINE__, __FILE__);
     451             :         else
     452           4 :                 printf("%d rows copied.\n", rows_sent);
     453             : 
     454           4 :         printf("done\n");
     455           4 : }
     456             : 
     457             : static void
     458          20 : normal_select(void)
     459             : {
     460          20 :         int ok = 1, i;
     461             : 
     462          20 :         odbc_command("select * from all_types_bcp_unittest");
     463          20 :         CHKFetch("SI");
     464             : 
     465             :         /* first columns have values */
     466         320 :         for (i = 0; i < TDS_VECTOR_SIZE(expected); ++i) {
     467             :                 char output[128];
     468             :                 SQLLEN dataSize;
     469         300 :                 CHKGetData(i + 1, SQL_C_CHAR, output, sizeof(output), &dataSize, "S");
     470         300 :                 if (strcmp(output, expected[i]) || dataSize <= 0) {
     471           0 :                         fprintf(stderr, "Invalid returned col %d: '%s'!='%s'\n", i, expected[i], output);
     472           0 :                         ok = 0;
     473             :                 }
     474             :         }
     475             :         /* others are NULL */
     476         280 :         for (; i < total_cols; ++i) {
     477             :                 char output[128];
     478             :                 SQLLEN dataSize;
     479         280 :                 CHKGetData(i + 1, SQL_C_CHAR, output, sizeof(output), &dataSize, "S");
     480         280 :                 if (dataSize != SQL_NULL_DATA) {
     481           0 :                         fprintf(stderr, "Invalid returned col %d: should be NULL'\n", i);
     482           0 :                         ok = 0;
     483             :                 }
     484             :         }
     485          20 :         if (!ok)
     486           0 :                 exit(1);
     487          20 :         CHKCloseCursor("SI");
     488          20 : }
     489             : 
     490             : static void
     491           4 : special_select(void)
     492             : {
     493           4 :         int ok = 1, i;
     494             : 
     495           4 :         odbc_command("select top 1 * from special_types_bcp_unittest");
     496           4 :         CHKFetch("SI");
     497          32 :         for (i = 0; i < TDS_VECTOR_SIZE(expected_special); ++i) {
     498             :                 char output[128];
     499             :                 SQLLEN dataSize;
     500          28 :                 CHKGetData(i + 1, SQL_C_CHAR, output, sizeof(output), &dataSize, "S");
     501          28 :                 if (strcmp(output, expected_special[i]) || (dataSize <= 0 && expected_special[i][0] != '\0')) {
     502           0 :                         fprintf(stderr, "Invalid returned col %d: '%s'!='%s'\n", i, expected_special[i], output);
     503           0 :                         ok = 0;
     504             :                 }
     505             :         }
     506           4 :         if (!ok)
     507           0 :                 exit(1);
     508           4 :         CHKCloseCursor("SI");
     509           4 : }

Generated by: LCOV version 1.13