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

Generated by: LCOV version 1.13