LCOV - code coverage report
Current view: top level - src/dblib/unittests - numeric.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 110 132 83.3 %
Date: 2024-03-23 09:12:27 Functions: 4 5 80.0 %

          Line data    Source code
       1             : #define MSDBLIB 1
       2             : #include "common.h"
       3             : 
       4             : static void
       5           0 : dump_addr(FILE *out, const char *msg, const void *p, size_t len)
       6             : {
       7             :         size_t n;
       8           0 :         if (msg)
       9           0 :                 fprintf(out, "%s", msg);
      10           0 :         for (n = 0; n < len; ++n)
      11           0 :                 fprintf(out, " %02X", ((unsigned char*) p)[n]);
      12           0 :         fprintf(out, "\n");
      13           0 : }
      14             : 
      15             : static void
      16        1784 : chk(RETCODE ret, const char *msg)
      17             : {
      18        1784 :         printf("%s: res %d\n", msg, ret);
      19        1784 :         if (ret == SUCCEED)
      20        1784 :                 return;
      21           0 :         fprintf(stderr, "error: %s\n", msg);
      22           0 :         exit(1);
      23             : }
      24             : 
      25             : static void
      26         384 : zero_end(DBNUMERIC *num)
      27             : {
      28             :         /* 27213 == math.floor(math.log(10,256)*65536) */
      29         384 :         unsigned len = 4u+num->precision*27213u/65536u;
      30         384 :         if (num->precision < 1 || num->precision > 77)
      31             :                 return;
      32         384 :         assert(len >= 4 && len <= sizeof(*num));
      33         384 :         memset(((char*) num) + len, 0, sizeof(*num) - len);
      34             : }
      35             : 
      36             : static int msdblib;
      37             : 
      38             : static void
      39         192 : test(int bind_type, const char *bind_name, int override_prec, int override_scale, int out_prec, int out_scale, int line)
      40             : {
      41             :         LOGINREC *login;
      42             :         DBPROCESS *dbproc;
      43         192 :         DBNUMERIC *num = NULL, *num2 = NULL;
      44             :         RETCODE ret;
      45             :         DBTYPEINFO ti;
      46             :         int i;
      47             : 
      48         192 :         printf("*** Starting test msdblib %d bind %s prec %d scale %d out prec %d out scale %d line %d\n",
      49             :                 msdblib, bind_name, override_prec, override_scale, out_prec, out_scale, line);
      50         192 :         chk(sql_rewind(), "sql_rewind");
      51         192 :         login = dblogin();
      52             : 
      53         192 :         DBSETLUSER(login, USER);
      54         192 :         DBSETLPWD(login, PASSWORD);
      55         192 :         DBSETLAPP(login, "numeric");
      56         192 :         dbsetmaxprocs(25);
      57         192 :         DBSETLHOST(login, SERVER);
      58             : 
      59         192 :         dbproc = tdsdbopen(login, SERVER, msdblib);
      60         192 :         dbloginfree(login);
      61         192 :         login = NULL;
      62         192 :         if (strlen(DATABASE))
      63         192 :                 dbuse(dbproc, DATABASE);
      64             : 
      65         192 :         sql_cmd(dbproc);
      66         192 :         dbsqlexec(dbproc);
      67         192 :         while (dbresults(dbproc) != NO_MORE_RESULTS) {
      68             :                 /* nop */
      69             :         }
      70             : 
      71         192 :         sql_cmd(dbproc);
      72         192 :         dbsqlexec(dbproc);
      73         192 :         while (dbresults(dbproc) != NO_MORE_RESULTS) {
      74             :                 /* nop */
      75             :         }
      76             : 
      77         192 :         if (DBTDS_5_0 < DBTDS(dbproc)) {
      78         144 :                 ret = dbcmd(dbproc,
      79             :                             "SET ARITHABORT ON;"
      80             :                             "SET CONCAT_NULL_YIELDS_NULL ON;"
      81             :                             "SET ANSI_NULLS ON;"
      82             :                             "SET ANSI_NULL_DFLT_ON ON;"
      83             :                             "SET ANSI_PADDING ON;"
      84             :                             "SET ANSI_WARNINGS ON;"
      85             :                             "SET ANSI_NULL_DFLT_ON ON;"
      86             :                             "SET CURSOR_CLOSE_ON_COMMIT ON;"
      87             :                             "SET QUOTED_IDENTIFIER ON");
      88         144 :                 chk(ret, "dbcmd");
      89         144 :                 ret = dbsqlexec(dbproc);
      90         144 :                 chk(ret, "dbsqlexec");
      91             : 
      92         144 :                 ret = dbcancel(dbproc);
      93         144 :                 chk(ret, "dbcancel");
      94             :         }
      95             : 
      96         192 :         ret = dbrpcinit(dbproc, "testDecimal", 0);
      97         192 :         chk(ret, "dbrpcinit");
      98             : 
      99         192 :         num = (DBDECIMAL *) calloc(1, sizeof(DBDECIMAL));
     100         192 :         ti.scale = 5;
     101         192 :         ti.precision = 16;
     102         192 :         ret = dbconvert_ps(dbproc, SYBVARCHAR, (const BYTE *) "123.45", -1, SYBDECIMAL, (BYTE *) num, sizeof(*num), &ti);
     103         192 :         chk(ret > 0, "dbconvert_ps");
     104             : 
     105         192 :         ret = dbrpcparam(dbproc, "@idecimal", 0, SYBDECIMAL, -1, sizeof(DBDECIMAL), (BYTE *) num);
     106         192 :         chk(ret, "dbrpcparam");
     107         192 :         ret = dbrpcsend(dbproc);
     108         192 :         chk(ret, "dbrpcsend");
     109         192 :         ret = dbsqlok(dbproc);
     110         192 :         chk(ret, "dbsqlok");
     111             : 
     112             :         /* TODO check MS/Sybase format */
     113         192 :         num2 = (DBDECIMAL *) calloc(1, sizeof(DBDECIMAL));
     114         192 :         ti.precision = override_prec;
     115         192 :         ti.scale     = override_scale;
     116         192 :         ret = dbconvert_ps(dbproc, SYBVARCHAR, (const BYTE *) "246.9", -1, SYBDECIMAL, (BYTE *) num2, sizeof(*num2), &ti);
     117         192 :         chk(ret > 0, "dbconvert_ps");
     118             : 
     119         384 :         for (i=0; (ret = dbresults(dbproc)) != NO_MORE_RESULTS; ++i) {
     120             :                 RETCODE row_code;
     121             : 
     122         192 :                 switch (ret) {
     123         192 :                 case SUCCEED:
     124         192 :                         if (DBROWS(dbproc) == FAIL)
     125           0 :                                 continue;
     126         192 :                         assert(DBROWS(dbproc) == SUCCEED);
     127         192 :                         printf("dbrows() returned SUCCEED, processing rows\n");
     128             : 
     129         192 :                         memset(num, 0, sizeof(*num));
     130         192 :                         num->precision = out_prec  ? out_prec  : num2->precision;
     131         192 :                         num->scale     = out_scale ? out_scale : num2->scale;
     132         192 :                         dbbind(dbproc, 1, bind_type, 0, (BYTE *) num);
     133             : 
     134         192 :                         while ((row_code = dbnextrow(dbproc)) != NO_MORE_ROWS) {
     135         192 :                                 if (row_code == REG_ROW) {
     136         192 :                                         zero_end(num);
     137         192 :                                         zero_end(num2);
     138         192 :                                         if (memcmp(num, num2, sizeof(*num)) != 0) {
     139           0 :                                                 fprintf(stderr, "Failed. Output results does not match\n");
     140           0 :                                                 dump_addr(stderr, "got:      ", num, sizeof(*num));
     141           0 :                                                 dump_addr(stderr, "expected: ", num2, sizeof(*num2));
     142           0 :                                                 exit(1);
     143             :                                         }
     144             :                                 } else {
     145             :                                         /* not supporting computed rows in this unit test */
     146           0 :                                         fprintf(stderr, "Failed.  Expected a row\n");
     147           0 :                                         exit(1);
     148             :                                 }
     149             :                         }
     150             :                         break;
     151           0 :                 case FAIL:
     152           0 :                         fprintf(stderr, "dbresults returned FAIL\n");
     153           0 :                         exit(1);
     154           0 :                 default:
     155           0 :                         fprintf(stderr, "unexpected return code %d from dbresults\n", ret);
     156           0 :                         exit(1);
     157             :                 }
     158             :         } /* while dbresults */
     159             : 
     160         192 :         sql_cmd(dbproc);
     161             : 
     162         192 :         free(num2);
     163         192 :         free(num);
     164             : 
     165         192 :         dbclose(dbproc);
     166         192 : }
     167             : 
     168             : #define test(a,b,c,d,e) test(a, #a, b, c, d, e, __LINE__)
     169             : 
     170             : int
     171           8 : main(int argc, char **argv)
     172             : {
     173           8 :         read_login_info(argc, argv);
     174             : 
     175           8 :         dbsetversion(DBVERSION_100);
     176           8 :         dbinit();
     177             : 
     178             :         /* tests with MS behaviour */
     179           8 :         msdblib = 1;
     180           8 :         test(DECIMALBIND,    20, 10, 0, 0);
     181           8 :         test(NUMERICBIND,    20, 10, 0, 0);
     182           8 :         test(SRCDECIMALBIND, 20, 10, 0, 0);
     183           8 :         test(SRCNUMERICBIND, 20, 10, 0, 0);
     184             :         /* in these 2 case MS override what server returns */
     185           8 :         test(DECIMALBIND,    10,  4, 10, 4);
     186           8 :         test(NUMERICBIND,    10,  4, 10, 4);
     187           8 :         test(SRCDECIMALBIND, 20, 10, 10, 4);
     188           8 :         test(SRCNUMERICBIND, 20, 10, 10, 4);
     189             : 
     190             :         /* tests with Sybase behaviour */
     191           8 :         msdblib = 0;
     192           8 :         test(DECIMALBIND,    20, 10, 0, 0);
     193           8 :         test(NUMERICBIND,    20, 10, 0, 0);
     194           8 :         test(SRCDECIMALBIND, 20, 10, 0, 0);
     195           8 :         test(SRCNUMERICBIND, 20, 10, 0, 0);
     196             :         /* no matter what Sybase return always according to source */
     197           8 :         test(DECIMALBIND,    20, 10, 10, 4);
     198           8 :         test(NUMERICBIND,    20, 10, 10, 4);
     199           8 :         test(SRCDECIMALBIND, 20, 10, 10, 4);
     200           8 :         test(SRCNUMERICBIND, 20, 10, 10, 4);
     201             : 
     202           8 :         chk(sql_reopen("numeric_2"), "sql_reopen");
     203             : 
     204           8 :         msdblib = 1;
     205             :         /* on MS use always output */
     206           8 :         test(DECIMALBIND,    20,  0, 20, 0);
     207           8 :         test(NUMERICBIND,    19,  0, 19, 0);
     208           8 :         test(SRCDECIMALBIND, 18,  0, 18, 0);
     209           8 :         test(SRCNUMERICBIND, 17,  0, 17, 0);
     210             : 
     211           8 :         msdblib = 0;
     212           8 :         test(DECIMALBIND,    18,  0, 20, 0);
     213           8 :         test(NUMERICBIND,    18,  0, 19, 0);
     214             :         /* this is MS only and behave like MS */
     215           8 :         test(SRCDECIMALBIND, 18,  0, 18, 0);
     216           8 :         test(SRCNUMERICBIND, 17,  0, 17, 0);
     217             : 
     218           8 :         dbexit();
     219             : 
     220           8 :         printf("Succeed\n");
     221             :         return 0;
     222             : }
     223             : 

Generated by: LCOV version 1.13