LCOV - code coverage report
Current view: top level - src/odbc/unittests - blob1.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 182 209 87.1 %
Date: 2024-04-18 20:40:06 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /* Testing large objects */
       2             : /* Test from Sebastien Flaesch */
       3             : 
       4             : #include "common.h"
       5             : #include <ctype.h>
       6             : #include <assert.h>
       7             : 
       8             : #define NBYTES 10000u
       9             : 
      10             : static int failed = 0;
      11             : 
      12             : static void
      13             : fill_chars(char *buf, size_t len, unsigned int start, unsigned int step)
      14             : {
      15             :         size_t n;
      16             : 
      17      220022 :         for (n = 0; n < len; ++n)
      18      220000 :                 buf[n] = 'a' + ((start+n) * step % ('z' - 'a' + 1));
      19             : }
      20             : 
      21             : static void
      22          88 : fill_hex(char *buf, size_t len, unsigned int start, unsigned int step)
      23             : {
      24             :         size_t n;
      25             : 
      26      880088 :         for (n = 0; n < len; ++n)
      27      880000 :                 sprintf(buf + 2*n, "%2x", (unsigned int)('a' + ((start+n) * step % ('z' - 'a' + 1))));
      28          88 : }
      29             : 
      30             : 
      31             : static int
      32             : check_chars(const char *buf, size_t len, unsigned int start, unsigned int step)
      33             : {
      34             :         size_t n;
      35             : 
      36      880264 :         for (n = 0; n < len; ++n)
      37      880000 :                 if (buf[n] != 'a' + ((start+n) * step % ('z' - 'a' + 1)))
      38             :                         return 0;
      39             : 
      40             :         return 1;
      41             : }
      42             : 
      43             : static int
      44         704 : check_hex(const char *buf, size_t len, unsigned int start, unsigned int step)
      45             : {
      46             :         size_t n;
      47             :         char symbol[3];
      48             : 
      49     3520704 :         for (n = 0; n < len; ++n) {
      50     3520000 :                 sprintf(symbol, "%2x", (unsigned int)('a' + ((start+n) / 2 * step % ('z' - 'a' + 1))));
      51     3520000 :                 if (tolower((unsigned char) buf[n]) != symbol[(start+n) % 2])
      52             :                         return 0;
      53             :         }
      54             : 
      55             :         return 1;
      56             : }
      57             : 
      58             : #define MAX_TESTS 10
      59             : typedef struct {
      60             :         unsigned num;
      61             :         SQLSMALLINT c_type, sql_type;
      62             :         const char *db_type;
      63             :         unsigned gen1, gen2;
      64             :         SQLLEN vind;
      65             :         char *buf;
      66             : } test_info;
      67             : 
      68             : static test_info test_infos[MAX_TESTS];
      69             : static unsigned num_tests = 0;
      70             : 
      71             : static void
      72           0 : dump(FILE* out, const char* start, void* buf, unsigned len)
      73             : {
      74             :         unsigned n;
      75             :         char s[17];
      76           0 :         if (len >= 16)
      77           0 :                 len = 16;
      78           0 :         fprintf(out, "%s", start);
      79           0 :         for (n = 0; n < len; ++n) {
      80           0 :                 unsigned char c = ((unsigned char*)buf)[n];
      81           0 :                 fprintf(out, " %02X", c);
      82           0 :                 s[n] = (c >= 0x20 && c < 127) ? (char) c : '.';
      83             :         }
      84           0 :         s[len] = 0;
      85           0 :         fprintf(out, " - %s\n", s);
      86           0 : }
      87             : 
      88             : static void
      89          88 : readBlob(test_info *t)
      90             : {
      91             :         SQLRETURN rc;
      92             :         char buf[4096];
      93          88 :         SQLLEN len, total = 0;
      94          88 :         int i = 0;
      95             :         int check;
      96             : 
      97          88 :         printf(">> readBlob field %d\n", t->num);
      98             :         while (1) {
      99         616 :                 i++;
     100         352 :                 rc = CHKGetData(t->num, SQL_C_BINARY, (SQLPOINTER) buf, (SQLINTEGER) sizeof(buf), &len, "SINo");
     101         352 :                 if (rc == SQL_NO_DATA || len <= 0)
     102             :                         break;
     103         264 :                 if (len > (SQLLEN) sizeof(buf))
     104         176 :                         len = (SQLLEN) sizeof(buf);
     105         264 :                 printf(">>     step %d: %d bytes readed\n", i, (int) len);
     106         528 :                 check = check_chars(buf, len, t->gen1 + total, t->gen2);
     107         264 :                 if (!check) {
     108           0 :                         fprintf(stderr, "Wrong buffer content\n");
     109           0 :                         dump(stderr, " buf ", buf, len);
     110           0 :                         failed = 1;
     111             :                 }
     112         264 :                 total += len;
     113             :         }
     114          88 :         printf(">>   total bytes read = %d \n", (int) total);
     115          88 :         if (total != 10000) {
     116           0 :                 fprintf(stderr, "Wrong buffer length, expected 20000\n");
     117           0 :                 failed = 1;
     118             :         }
     119          88 : }
     120             : 
     121             : static void
     122         176 : readBlobAsChar(test_info *t, int step, int wide)
     123             : {
     124         176 :         SQLRETURN rc = SQL_SUCCESS_WITH_INFO;
     125             :         char buf[8192];
     126         176 :         SQLLEN len, total = 0, len2;
     127         176 :         int i = 0;
     128             :         int check;
     129             :         int bufsize;
     130             : 
     131         176 :         SQLSMALLINT type = SQL_C_CHAR;
     132         176 :         unsigned int char_len = 1;
     133         176 :         if (wide) {
     134          88 :                 char_len = sizeof(SQLWCHAR);
     135          88 :                 type = SQL_C_WCHAR;
     136             :         }
     137             :         
     138         176 :         if (step%2) bufsize = sizeof(buf) - char_len;
     139             :         else bufsize = sizeof(buf);
     140             : 
     141         176 :         printf(">> readBlobAsChar field %d\n", t->num);
     142        1056 :         while (rc == SQL_SUCCESS_WITH_INFO) {
     143         704 :                 i++;
     144         704 :                 rc = CHKGetData(t->num, type, (SQLPOINTER) buf, (SQLINTEGER) bufsize, &len, "SINo");
     145         704 :                 if (rc == SQL_SUCCESS_WITH_INFO && len == SQL_NO_TOTAL) {
     146         176 :                         len = bufsize - char_len;
     147         176 :                         rc = SQL_SUCCESS;
     148             :                 }
     149         528 :                 if (rc == SQL_NO_DATA || len <= 0)
     150             :                         break;
     151         704 :                 rc = CHKGetData(t->num, type, (SQLPOINTER) buf, 0, &len2, "SINo");
     152         704 :                 if (rc == SQL_SUCCESS_WITH_INFO && len2 != SQL_NO_TOTAL)
     153         352 :                         len = len - len2;
     154             : #if 0
     155             :                 if (len > (SQLLEN) (bufsize - char_len))
     156             :                         len = (SQLLEN) (bufsize - char_len);
     157             :                 len -= len % (2u * char_len);
     158             : #endif
     159         704 :                 printf(">>     step %d: %d bytes readed\n", i, (int) len);
     160             : 
     161         704 :                 if (wide) {
     162         440 :                         len /= sizeof(SQLWCHAR);
     163         440 :                         odbc_from_sqlwchar((char *) buf, (SQLWCHAR *) buf, len + 1);
     164             :                 }
     165             : 
     166         704 :                 check = check_hex(buf, len, 2*t->gen1 + total, t->gen2);
     167         704 :                 if (!check) {
     168           0 :                         fprintf(stderr, "Wrong buffer content\n");
     169           0 :                         dump(stderr, " buf ", buf, len);
     170           0 :                         failed = 1;
     171             :                 }
     172         704 :                 total += len;
     173             :         }
     174         176 :         printf(">>   total bytes read = %d \n", (int) total);
     175         176 :         if (total != 20000) {
     176           0 :                 fprintf(stderr, "Wrong buffer length, expected 20000\n");
     177           0 :                 failed = 1;
     178             :         }
     179         176 : }
     180             : 
     181             : static void
     182          66 : add_test(SQLSMALLINT c_type, SQLSMALLINT sql_type, const char *db_type, unsigned gen1, unsigned gen2)
     183             : {
     184          66 :         test_info *t = NULL;
     185             :         size_t buf_len;
     186             : 
     187          66 :         if (num_tests >= MAX_TESTS) {
     188           0 :                 fprintf(stderr, "too max tests\n");
     189           0 :                 exit(1);
     190             :         }
     191             : 
     192          66 :         t = &test_infos[num_tests++];
     193          66 :         t->num = num_tests;
     194          66 :         t->c_type = c_type;
     195          66 :         t->sql_type = sql_type;
     196          66 :         t->db_type = db_type;
     197          66 :         t->gen1 = gen1;
     198          66 :         t->gen2 = gen2;
     199          66 :         t->vind = 0;
     200          66 :         switch (c_type) {
     201             :         case SQL_C_CHAR:
     202             :                 buf_len =  NBYTES*2+1;
     203             :                 break;
     204          22 :         case SQL_C_WCHAR:
     205          22 :                 buf_len = (NBYTES*2+1) * sizeof(SQLWCHAR);
     206          22 :                 break;
     207          22 :         default:
     208          22 :                 buf_len = NBYTES;
     209             :         }
     210          66 :         t->buf = (char*) malloc(buf_len);
     211          66 :         if (!t->buf) {
     212           0 :                 fprintf(stderr, "memory error\n");
     213           0 :                 exit(1);
     214             :         }
     215          66 :         if (c_type != SQL_C_CHAR && c_type != SQL_C_WCHAR)
     216          22 :                 fill_chars(t->buf, NBYTES, t->gen1, t->gen2);
     217             :         else
     218          44 :                 memset(t->buf, 0, buf_len);
     219          66 :         t->vind = SQL_LEN_DATA_AT_EXEC((SQLLEN) buf_len);
     220          66 : }
     221             : 
     222             : static void
     223           8 : free_tests(void)
     224             : {
     225          82 :         while (num_tests > 0) {
     226          66 :                 test_info *t = &test_infos[--num_tests];
     227          66 :                 free(t->buf);
     228          66 :                 t->buf = NULL;
     229             :         }
     230           8 : }
     231             : 
     232             : int
     233           8 : main(void)
     234             : {
     235             :         SQLRETURN RetCode;
     236           8 :         SQLHSTMT old_odbc_stmt = SQL_NULL_HSTMT;
     237             :         int i;
     238             : 
     239             :         int key;
     240             :         SQLLEN vind0;
     241           8 :         int cnt = 2, wide;
     242             :         char sql[256];
     243           8 :         test_info *t = NULL;
     244             : 
     245           8 :         odbc_use_version3 = 1;
     246           8 :         odbc_connect();
     247             : 
     248             :         /* tests (W)CHAR/BINARY -> (W)CHAR/BINARY (9 cases) */
     249           8 :         add_test(SQL_C_BINARY, SQL_LONGVARCHAR,   "TEXT",  123, 1 );
     250           8 :         add_test(SQL_C_BINARY, SQL_LONGVARBINARY, "IMAGE", 987, 25);
     251           8 :         add_test(SQL_C_CHAR,   SQL_LONGVARBINARY, "IMAGE", 987, 25);
     252           8 :         add_test(SQL_C_CHAR,   SQL_LONGVARCHAR,   "TEXT",  343, 47);
     253           8 :         add_test(SQL_C_WCHAR,  SQL_LONGVARBINARY, "IMAGE", 561, 29);
     254           8 :         add_test(SQL_C_WCHAR,  SQL_LONGVARCHAR,   "TEXT",  698, 24);
     255           8 :         if (odbc_db_is_microsoft()) {
     256           6 :                 add_test(SQL_C_BINARY, SQL_WLONGVARCHAR, "NTEXT", 765, 12);
     257           6 :                 add_test(SQL_C_CHAR,   SQL_WLONGVARCHAR, "NTEXT", 237, 71);
     258           6 :                 add_test(SQL_C_WCHAR,  SQL_WLONGVARCHAR, "NTEXT", 687, 68);
     259             :         }
     260             : 
     261           8 :         strcpy(sql, "CREATE TABLE #tt(k INT");
     262          74 :         for (t = test_infos; t < test_infos+num_tests; ++t)
     263          66 :                 sprintf(strchr(sql, 0), ",f%u %s", t->num, t->db_type);
     264           8 :         strcat(sql, ",v INT)");
     265           8 :         odbc_command(sql);
     266             : 
     267           8 :         old_odbc_stmt = odbc_stmt;
     268           8 :         odbc_stmt = SQL_NULL_HSTMT;
     269             : 
     270             :         /* Insert rows ... */
     271             : 
     272          24 :         for (i = 0; i < cnt; i++) {
     273             :                 /* MS do not save correctly char -> binary */
     274          16 :                 if (!odbc_driver_is_freetds() && i)
     275           0 :                         continue;
     276             : 
     277          16 :                 CHKAllocHandle(SQL_HANDLE_STMT, odbc_conn, &odbc_stmt, "S");
     278             : 
     279          16 :                 strcpy(sql, "INSERT INTO #tt VALUES(?");
     280         148 :                 for (t = test_infos; t < test_infos+num_tests; ++t)
     281         132 :                         strcat(sql, ",?");
     282          16 :                 strcat(sql, ",?)");
     283          16 :                 CHKPrepare(T(sql), SQL_NTS, "S");
     284             : 
     285          16 :                 CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0, "S");
     286         148 :                 for (t = test_infos; t < test_infos+num_tests; ++t)
     287         132 :                         CHKBindParameter(t->num+1, SQL_PARAM_INPUT, t->c_type, t->sql_type, 0x10000000, 0, t->buf, 0, &t->vind, "S");
     288             : 
     289          16 :                 CHKBindParameter(num_tests+2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0, "S");
     290             : 
     291          16 :                 key = i;
     292          16 :                 vind0 = 0;
     293             : 
     294          16 :                 printf(">> insert... %d\n", i);
     295          16 :                 RetCode = CHKExecute("SINe");
     296         180 :                 while (RetCode == SQL_NEED_DATA) {
     297             :                         char *p;
     298             : 
     299         148 :                         RetCode = CHKParamData((SQLPOINTER *) & p, "SINe");
     300         148 :                         printf(">> SQLParamData: ptr = %p  RetCode = %d\n", (void *) p, RetCode);
     301         148 :                         if (RetCode == SQL_NEED_DATA) {
     302         492 :                                 for (t = test_infos; t < test_infos+num_tests && t->buf != p; ++t)
     303             :                                         ;
     304         132 :                                 assert(t < test_infos+num_tests);
     305         132 :                                 if (t->c_type == SQL_C_CHAR || t->c_type == SQL_C_WCHAR) {
     306          88 :                                         unsigned char_len = 1;
     307             : 
     308          88 :                                         fill_hex(p, NBYTES, t->gen1, t->gen2);
     309          88 :                                         if (t->c_type == SQL_C_WCHAR) {
     310          44 :                                                 char_len = sizeof(SQLWCHAR);
     311          44 :                                                 odbc_to_sqlwchar((SQLWCHAR*) p, p, NBYTES * 2);
     312             :                                         }
     313             : 
     314          88 :                                         CHKPutData(p, (NBYTES - (i&1)) * char_len, "S");
     315             : 
     316          88 :                                         printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES - (i&1));
     317             : 
     318          88 :                                         CHKPutData(p + (NBYTES - (i&1)) * char_len, (NBYTES + (i&1)) * char_len, "S");
     319             : 
     320          88 :                                         printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES + (i&1));
     321             :                                 } else {
     322          44 :                                         CHKPutData(p, NBYTES, "S");
     323             : 
     324          44 :                                         printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES);
     325             :                                 }
     326             :                         }
     327             :                 }
     328             : 
     329          16 :                 CHKFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) odbc_stmt, "S");
     330          16 :                 odbc_stmt = SQL_NULL_HSTMT;
     331             :         }
     332             : 
     333             :         /* Now fetch rows ... */
     334             : 
     335          16 :         for (wide = 0; wide < 2; ++wide)
     336          48 :         for (i = 0; i < cnt; i++) {
     337             :                 /* MS do not save correctly char -> binary */
     338          32 :                 if (!odbc_driver_is_freetds() && i)
     339           0 :                         continue;
     340             : 
     341             : 
     342          32 :                 CHKAllocHandle(SQL_HANDLE_STMT, odbc_conn, &odbc_stmt, "S");
     343             : 
     344          32 :                 if (odbc_db_is_microsoft()) {
     345          24 :                         CHKSetStmtAttr(SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_NONSCROLLABLE, SQL_IS_UINTEGER, "S");
     346          24 :                         CHKSetStmtAttr(SQL_ATTR_CURSOR_SENSITIVITY, (SQLPOINTER) SQL_SENSITIVE, SQL_IS_UINTEGER, "S");
     347             :                 }
     348             : 
     349          32 :                 strcpy(sql, "SELECT ");
     350         296 :                 for (t = test_infos; t < test_infos+num_tests; ++t)
     351         264 :                         sprintf(strchr(sql, 0), "f%u,", t->num);
     352          32 :                 strcat(sql, "v FROM #tt WHERE k = ?");
     353          32 :                 CHKPrepare(T(sql), SQL_NTS, "S");
     354             : 
     355          32 :                 CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &i, 0, &vind0, "S");
     356             : 
     357         296 :                 for (t = test_infos; t < test_infos+num_tests; ++t) {
     358         264 :                         t->vind = SQL_DATA_AT_EXEC;
     359         264 :                         CHKBindCol(t->num, SQL_C_BINARY, NULL, 0, &t->vind, "S");
     360             :                 }
     361          32 :                 CHKBindCol(num_tests+1, SQL_C_LONG, &key, 0, &vind0, "S");
     362             : 
     363          32 :                 vind0 = 0;
     364             : 
     365          32 :                 CHKExecute("S");
     366             : 
     367          32 :                 CHKFetchScroll(SQL_FETCH_NEXT, 0, "S");
     368          32 :                 printf(">> fetch... %d\n", i);
     369             : 
     370         296 :                 for (t = test_infos; t < test_infos+num_tests; ++t) {
     371         264 :                         if (t->c_type == SQL_C_CHAR || t->c_type == SQL_C_WCHAR)
     372         176 :                                 readBlobAsChar(t, i, wide);
     373             :                         else
     374          88 :                                 readBlob(t);
     375             :                 }
     376             : 
     377          32 :                 CHKCloseCursor("S");
     378          32 :                 CHKFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) odbc_stmt, "S");
     379          32 :                 odbc_stmt = SQL_NULL_HSTMT;
     380             :         }
     381             : 
     382           8 :         odbc_stmt = old_odbc_stmt;
     383             : 
     384           8 :         free_tests();
     385           8 :         odbc_disconnect();
     386             : 
     387           8 :         if (!failed)
     388           8 :                 printf("ok!\n");
     389             : 
     390           8 :         return failed ? 1 : 0;
     391             : }
     392             : 

Generated by: LCOV version 1.13