LCOV - code coverage report
Current view: top level - src/dblib/unittests - rpc.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 213 292 72.9 %
Date: 2025-04-21 16:22:06 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* 
       2             :  * Purpose: Test remote procedure calls
       3             :  * Functions:  dbretdata dbretlen dbretname dbretstatus dbrettype dbrpcinit dbrpcparam dbrpcsend 
       4             :  */
       5             : 
       6             : #include "common.h"
       7             : 
       8             : #include <freetds/bool.h>
       9             : 
      10             : static RETCODE init_proc(DBPROCESS * dbproc, const char *name);
      11             : 
      12             : typedef struct {
      13             :         char *name, *value;
      14             :         int type, len;
      15             : } RETPARAM;
      16             : 
      17             : static RETPARAM* save_retparam(RETPARAM *param, char *name, char *value, int type, int len);
      18             : 
      19             : static RETCODE
      20          12 : init_proc(DBPROCESS * dbproc, const char *name)
      21             : {
      22          12 :         RETCODE ret = FAIL;
      23             : 
      24          12 :         if (name[0] != '#') {
      25           2 :                 printf("Dropping procedure %s\n", name);
      26           2 :                 sql_cmd(dbproc);
      27           2 :                 dbsqlexec(dbproc);
      28           2 :                 while (dbresults(dbproc) != NO_MORE_RESULTS) {
      29             :                         /* nop */
      30             :                 }
      31             :         }
      32             : 
      33          12 :         printf("Creating procedure %s\n", name);
      34          12 :         sql_cmd(dbproc);
      35          12 :         if ((ret = dbsqlexec(dbproc)) == FAIL) {
      36           2 :                 if (name[0] == '#')
      37           2 :                         printf("Failed to create procedure %s. Wrong permission or not MSSQL.\n", name);
      38             :                 else
      39           0 :                         printf("Failed to create procedure %s. Wrong permission.\n", name);
      40             :         }
      41          22 :         while (dbresults(dbproc) != NO_MORE_RESULTS) {
      42             :                 /* nop */
      43             :         }
      44          12 :         return ret;
      45             : }
      46             : 
      47             : static RETPARAM*
      48          74 : save_retparam(RETPARAM *param, char *name, char *value, int type, int len)
      49             : {
      50          74 :         free(param->name);
      51          74 :         free(param->value);
      52             :         
      53          74 :         param->name = strdup(name);
      54          74 :         param->value = strdup(value);
      55             :         
      56          74 :         param->type = type;
      57          74 :         param->len = len;
      58             :         
      59          74 :         return param;
      60             : }
      61             : 
      62             : static void
      63             : free_retparam(RETPARAM *param)
      64             : {
      65          30 :         free(param->name);
      66          30 :         free(param->value);
      67             :         param->name = param->value = NULL;
      68             : }
      69             : 
      70             : static bool failed = false;
      71             : 
      72             : static int
      73          28 : ignore_msg_handler(DBPROCESS * dbproc, DBINT msgno, int state, int severity, char *text, char *server, char *proc, int line)
      74             : {
      75             :         int ret;
      76             : 
      77          28 :         dbsetuserdata(dbproc, (BYTE*) &msgno);
      78             :         /* printf("(ignoring message %d)\n", msgno); */
      79          28 :         ret = syb_msg_handler(dbproc, msgno, state, severity, text, server, proc, line);
      80          28 :         dbsetuserdata(dbproc, NULL);
      81          28 :         return ret;
      82             : }
      83             : /*
      84             :  * The bad procedure name message has severity 15, causing db-lib to call the error handler after calling the message handler.
      85             :  * This wrapper anticipates that behavior, and again sets the userdata, telling the handler this error is expected. 
      86             :  */
      87             : static int
      88          38 : ignore_err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
      89             : {       
      90             :         int erc;
      91             :         static int recursion_depth = 0;
      92             :         
      93          38 :         if (dbproc == NULL) {   
      94          10 :                 printf("expected error %d: \"%s\"\n", dberr, dberrstr? dberrstr : "");
      95          10 :                 return INT_CANCEL;
      96             :         }
      97             :         
      98          28 :         if (recursion_depth++) {
      99           0 :                 printf("error %d: \"%s\"\n", dberr, dberrstr? dberrstr : "");
     100           0 :                 printf("logic error: recursive call to ignore_err_handler\n");
     101           0 :                 exit(1);
     102             :         }
     103          28 :         dbsetuserdata(dbproc, (BYTE*) &dberr);
     104             :         /* printf("(ignoring error %d)\n", dberr); */
     105          28 :         erc = syb_err_handler(dbproc, severity, dberr, oserr, dberrstr, oserrstr);
     106          28 :         dbsetuserdata(dbproc, NULL);
     107          28 :         recursion_depth--;
     108          28 :         return erc;
     109             : }
     110             : 
     111             : static int 
     112         860 : colwidth( DBPROCESS * dbproc, int icol ) 
     113             : {
     114         860 :         int width = dbwillconvert(dbcoltype(dbproc, icol), SYBCHAR);
     115         860 :         return 255 == width? dbcollen(dbproc, icol) : width;
     116             : }
     117             : 
     118             : static char param_data1[64], param_data3[8000+1], param_data4[2 * 4000 + 1];
     119             : static int param_data2, param_data5;
     120             : 
     121             : struct parameters_t {
     122             :         const char   *name;
     123             :         BYTE         status;
     124             :         int          type;
     125             :         DBINT        maxlen;
     126             :         DBINT        datalen;
     127             :         BYTE         *value;
     128             : };
     129             : 
     130             : static struct parameters_t bindings[] = {
     131             :           { "@null_input", DBRPCRETURN, SYBCHAR,  -1,   0, NULL }
     132             :         , { "@first_type", DBRPCRETURN, SYBCHAR,  sizeof(param_data1), 0, (BYTE *) &param_data1 }
     133             :         , { "@nullout",    DBRPCRETURN, SYBINT4,  -1,   0, (BYTE *) &param_data2 }
     134             :         , { "@varchar_tds7_out", DBRPCRETURN, SYBVARCHAR,  sizeof(param_data3),   0, (BYTE *) &param_data3 }
     135             :         , { "@nvarchar_tds7_out", DBRPCRETURN, 231,  sizeof(param_data4),   0, (BYTE *) &param_data4 }
     136             :         , { "@nrows",      DBRPCRETURN, SYBINT4,  -1,  -1, (BYTE *) &param_data5 }
     137             :         , { "@c_this_name_is_way_more_than_thirty_characters_charlie",
     138             :                            0,        SYBVARCHAR,   0,   0, NULL }
     139             :         , { "@nv",         0,        SYBVARCHAR,  -1,   2, (BYTE *) "OK:" }
     140             :         , { NULL, 0, 0, 0, 0, NULL }
     141             : };
     142             : 
     143             : #define PARAM_STR(s) sizeof(s)-1, (BYTE*) s
     144             : static struct parameters_t bindings_mssql1[] = {
     145             :           { "", 0, SYBVARCHAR,  -1,  PARAM_STR("set @a='test123'") }
     146             :         , { "", 0, SYBVARCHAR,  -1,  PARAM_STR("@a varchar(max) out") }
     147             :         , { "", DBRPCRETURN, SYBTEXT,  sizeof(param_data3), 0, (BYTE *) &param_data3 }
     148             :         , { NULL, 0, 0, 0, 0, NULL }
     149             : };
     150             : 
     151             : static struct parameters_t bindings_mssql2[] = {
     152             :           { "", 0, SYBVARCHAR,  -1,  PARAM_STR("set @a=null") }
     153             :         , { "", 0, SYBVARCHAR,  -1,  PARAM_STR("@a bit out") }
     154             :         , { "", DBRPCRETURN, SYBBIT,  sizeof(param_data3), 0, (BYTE *) &param_data3 }
     155             :         , { NULL, 0, 0, 0, 0, NULL }
     156             : };
     157             : 
     158             : static void
     159         100 : bind_param(DBPROCESS *dbproc, struct parameters_t *pb)
     160             : {
     161             :         RETCODE erc;
     162         100 :         const char *name = pb->name[0] ? pb->name : NULL;
     163             : 
     164         100 :         if ((erc = dbrpcparam(dbproc, name, pb->status, pb->type, pb->maxlen, pb->datalen, pb->value)) == FAIL) {
     165           0 :                 fprintf(stderr, "Failed line %d: dbrpcparam\n", __LINE__);
     166           0 :                 failed = true;
     167             :         }
     168         100 : }
     169             : 
     170          10 : TEST_MAIN()
     171             : {
     172             :         LOGINREC *login;
     173             :         DBPROCESS *dbproc;
     174             :         RETPARAM save_param, save_varchar_tds7_param, save_nvarchar_tds7_param;
     175             :         
     176             :         char teststr[8000+1], abbrev_data[10+3+1], *output;
     177          10 :         char *retname = NULL;
     178             :         int i;
     179          10 :         int rettype = 0, retlen = 0, return_status = 0;
     180          10 :         char proc[] = "#t0022";
     181          10 :         char *proc_name = proc;
     182             : 
     183          10 :         int num_resultset = 0, num_empty_resultset = 0;
     184          10 :         int num_params = 6;
     185             : 
     186             :         struct parameters_t *pb;
     187             : 
     188             :         static const char dashes30[] = "------------------------------";
     189             :         static const char  *dashes5 = dashes30 + (sizeof(dashes30) - 5), 
     190             :                           *dashes20 = dashes30 + (sizeof(dashes30) - 20);
     191             : 
     192             :         RETCODE erc, row_code;
     193             : 
     194          10 :         set_malloc_options();
     195             :         
     196          10 :         memset(&save_param, 0, sizeof(save_param));
     197          10 :         memset(&save_varchar_tds7_param, 0, sizeof(save_varchar_tds7_param));
     198          10 :         memset(&save_nvarchar_tds7_param, 0, sizeof(save_nvarchar_tds7_param));
     199             : 
     200          10 :         read_login_info(argc, argv);
     201             : 
     202          10 :         printf("Starting %s\n", argv[0]);
     203             : 
     204          10 :         dbinit();
     205             : 
     206          10 :         dberrhandle(syb_err_handler);
     207          10 :         dbmsghandle(syb_msg_handler);
     208             : 
     209          10 :         printf("About to logon\n");
     210             : 
     211          10 :         login = dblogin();
     212          10 :         DBSETLPWD(login, PASSWORD);
     213          10 :         DBSETLUSER(login, USER);
     214          10 :         DBSETLAPP(login, "rpc");
     215          10 :         dberrhandle(ignore_err_handler);
     216          10 :         DBSETLPACKET(login, -1);
     217          10 :         dberrhandle(syb_err_handler);
     218             : 
     219             : 
     220          10 :         printf("About to open %s.%s\n", SERVER, DATABASE);
     221             : 
     222          10 :         dbproc = dbopen(login, SERVER);
     223          10 :         if (strlen(DATABASE))
     224          10 :                 dbuse(dbproc, DATABASE);
     225          10 :         dbloginfree(login);
     226             : 
     227          10 :         printf("Check if server support long identifiers\n");
     228          10 :         sql_cmd(dbproc);
     229          10 :         i = 103;
     230          10 :         dbsetuserdata(dbproc, (BYTE*) &i);
     231          10 :         dbsqlexec(dbproc);
     232          30 :         while (dbresults(dbproc) != NO_MORE_RESULTS)
     233          20 :                 while (dbnextrow(dbproc) != NO_MORE_ROWS)
     234          10 :                         continue;
     235          10 :         dbsetuserdata(dbproc, NULL);
     236          10 :         if (i == 0) {
     237           0 :                 fprintf(stderr, "This server does not support long identifiers\n");
     238           0 :                 dbexit();
     239           0 :                 return 0;
     240             :         }
     241             : 
     242          10 :         dberrhandle(ignore_err_handler);
     243          10 :         dbmsghandle(ignore_msg_handler);
     244             : 
     245          10 :         printf("trying to create a temporary stored procedure\n");
     246          10 :         if (FAIL == init_proc(dbproc, proc_name)) {
     247           2 :                 num_params = 4;
     248           2 :                 printf("trying to create a permanent stored procedure\n");
     249           2 :                 if (FAIL == init_proc(dbproc, ++proc_name))
     250           0 :                         exit(EXIT_FAILURE);
     251             :         }
     252             : 
     253          10 :         dberrhandle(syb_err_handler);
     254          10 :         dbmsghandle(syb_msg_handler);
     255             : 
     256          10 :         printf("Created procedure %s\n", proc_name);
     257             : 
     258             :         /* set up and send the rpc */
     259          10 :         printf("executing dbrpcinit\n");
     260          10 :         erc = dbrpcinit(dbproc, proc_name, 0);  /* no options */
     261          10 :         if (erc == FAIL) {
     262           0 :                 fprintf(stderr, "Failed line %d: dbrpcinit\n", __LINE__);
     263           0 :                 failed = true;
     264             :         }
     265             : 
     266          90 :         for (pb = bindings, i = 0; pb->name != NULL; pb++, i++) {
     267          80 :                 printf("executing dbrpcparam for %s\n", pb->name);
     268          80 :                 if (num_params == 4 && (i == 3 || i == 4))
     269           4 :                         continue;
     270          76 :                 bind_param(dbproc, pb);
     271             :         }
     272          10 :         printf("executing dbrpcsend\n");
     273          10 :         param_data5 = 0x11223344;
     274          10 :         erc = dbrpcsend(dbproc);
     275          10 :         if (erc == FAIL) {
     276           0 :                 fprintf(stderr, "Failed line %d: dbrpcsend\n", __LINE__);
     277           0 :                 exit(1);
     278             :         }
     279             : 
     280             :         /* wait for it to execute */
     281          10 :         printf("executing dbsqlok\n");
     282          10 :         erc = dbsqlok(dbproc);
     283          10 :         if (erc == FAIL) {
     284           0 :                 fprintf(stderr, "Failed line %d: dbsqlok\n", __LINE__);
     285           0 :                 exit(1);
     286             :         }
     287             : 
     288             :         /* retrieve outputs per usual */
     289          10 :         printf("fetching results\n");
     290          10 :         while ((erc = dbresults(dbproc)) != NO_MORE_RESULTS) {
     291          40 :                 printf("fetched resultset %d %s:\n", 1+num_resultset, erc==SUCCEED? "successfully":"unsuccessfully");
     292          40 :                 if (erc == SUCCEED) { 
     293          40 :                         const int ncol = dbnumcols(dbproc);
     294          40 :                         int empty_resultset = 1, c;
     295             :                         enum {buflen=1024, nbuf=5};
     296          40 :                         char bound_buffers[nbuf][buflen] = { "one", "two", "three", "four", "five" };
     297             : 
     298          40 :                         ++num_resultset;
     299             :                         
     300         130 :                         for( c=0; c < ncol && c < nbuf; c++ ) {
     301          90 :                                 printf("column %d (%s) is %d wide, ", c+1, dbcolname(dbproc, c+1), colwidth(dbproc, c+1));
     302          90 :                                 printf("buffer initialized to '%s'\n", bound_buffers[c]);
     303             :                         }
     304          90 :                         for( c=0; c < ncol && c < nbuf; c++ ) {
     305          90 :                                 erc = dbbind(dbproc, c+1, STRINGBIND, 0, (BYTE *) bound_buffers[c]);
     306          90 :                                 if (erc == FAIL) {
     307           0 :                                         fprintf(stderr, "Failed line %d: dbbind\n", __LINE__);
     308           0 :                                         exit(1);
     309             :                                 }
     310             : 
     311          90 :                                 printf("%-*s ", colwidth(dbproc, c+1), dbcolname(dbproc, c+1));
     312             :                         }
     313          40 :                         printf("\n");
     314             : 
     315          40 :                         while ((row_code = dbnextrow(dbproc)) != NO_MORE_ROWS) {
     316         340 :                                 empty_resultset = 0;
     317         340 :                                 if (row_code == REG_ROW) {
     318             :                                         int c;
     319         680 :                                         for( c=0; c < ncol && c < nbuf; c++ ) {
     320         680 :                                                 printf("%-*s ", colwidth(dbproc, c+1), bound_buffers[c]);
     321             :                                         }
     322         340 :                                         printf("\n");
     323             :                                 } else {
     324             :                                         /* not supporting computed rows in this unit test */
     325           0 :                                         failed = true;
     326           0 :                                         fprintf(stderr, "Failed.  Expected a row\n");
     327           0 :                                         exit(1);
     328             :                                 }
     329             :                         }
     330          40 :                         printf("row count %d\n", (int) dbcount(dbproc));
     331          40 :                         printf("hasretstatus %d\n", dbhasretstat(dbproc));
     332          40 :                         if (num_resultset == 4 && !dbhasretstat(dbproc)) {
     333           0 :                                 fprintf(stderr, "dbnextrow should have set hasretstatus after last recordset\n");
     334           0 :                                 exit(1);
     335             :                         }
     336          40 :                         if (empty_resultset)
     337          10 :                                 ++num_empty_resultset;
     338             :                 } else {
     339           0 :                         fprintf(stderr, "Expected a result set.\n");
     340           0 :                         exit(1);
     341             :                 }
     342             :         } /* while dbresults */
     343             :         
     344             :         /* check return status */
     345          10 :         printf("retrieving return status...\n");
     346          10 :         if (dbhasretstat(dbproc) == TRUE) {
     347          10 :                 printf("%d\n", return_status = dbretstatus(dbproc));
     348             :         } else {
     349           0 :                 printf("none\n");
     350             :         }
     351             : 
     352             :         /* 
     353             :          * Check output parameter values 
     354             :          */
     355          10 :         if (dbnumrets(dbproc) != num_params) {  /* dbnumrets missed something */
     356           0 :                 fprintf(stderr, "Expected %d output parameters.\n", num_params);
     357           0 :                 exit(1);
     358             :         }
     359          10 :         printf("retrieving output parameters...\n");
     360          10 :         printf("%-5s %-20s %5s %6s  %-30s\n", "param", "name", "type", "length", "data");
     361          10 :         printf("%-5s %-20s %5s %5s- %-30s\n", dashes5, dashes20, dashes5, dashes5, dashes30);
     362          66 :         for (i = 1; i <= dbnumrets(dbproc); i++) {
     363          56 :                 retname = dbretname(dbproc, i);
     364          56 :                 rettype = dbrettype(dbproc, i);
     365          56 :                 retlen = dbretlen(dbproc, i);
     366          56 :                 dbconvert(dbproc, rettype, dbretdata(dbproc, i), retlen, SYBVARCHAR, (BYTE*) teststr, -1);
     367          56 :                 if(retlen <= 10) {
     368             :                         output = teststr;
     369             :                 } else {
     370          16 :                         memcpy(abbrev_data, teststr, 10);
     371          16 :                         sprintf(&abbrev_data[10], "...");
     372          16 :                         output = abbrev_data;
     373             :                 }
     374          56 :                 printf("%-5d %-20s %5d %6d  %-30s\n", i, retname, rettype, retlen, output);
     375             : 
     376          56 :                 save_retparam(&save_param, retname, teststr, rettype, retlen);
     377          56 :                 if (i == 4) {
     378          10 :                         save_retparam(&save_varchar_tds7_param, retname, teststr, rettype, retlen);
     379             :                 }
     380          56 :                 if (i == 5) {
     381           8 :                         save_retparam(&save_nvarchar_tds7_param, retname, teststr, rettype, retlen);
     382             :                 }
     383             :         }
     384             : 
     385             :         /* 
     386             :          * Test the last parameter for expected outcome 
     387             :          */
     388          10 :         if ((save_param.name == NULL) || strcmp(save_param.name, bindings[5].name)) {
     389           0 :                 fprintf(stderr, "Expected retname to be '%s', got ", bindings[5].name);
     390           0 :                 if (save_param.name == NULL) 
     391           0 :                         fprintf(stderr, "<NULL> instead.\n");
     392             :                 else
     393           0 :                         fprintf(stderr, "'%s' instead.\n", save_param.name);
     394           0 :                 exit(1);
     395             :         }
     396          10 :         if (strcmp(save_param.value, "3")) {
     397           0 :                 fprintf(stderr, "Expected retdata to be 3.\n");
     398           0 :                 exit(1);
     399             :         }
     400          10 :         if (save_param.type != SYBINT4) {
     401           0 :                 fprintf(stderr, "Expected rettype to be SYBINT4 was %d.\n", save_param.type);
     402           0 :                 exit(1);
     403             :         }
     404          10 :         if (save_param.len != 4) {
     405           0 :                 fprintf(stderr, "Expected retlen to be 4.\n");
     406           0 :                 exit(1);
     407             :         }
     408             : 
     409          10 :         if (num_params == 6) {
     410             :                 /*
     411             :                  * Test name, size, contents of the VARCHAR(8000) output parameter
     412             :                  */
     413           8 :                 if ((save_varchar_tds7_param.name == NULL) || strcmp(save_varchar_tds7_param.name, bindings[3].name)) {
     414           0 :                         fprintf(stderr, "Expected retname to be '%s', got ", bindings[3].name);
     415           0 :                         if (save_varchar_tds7_param.name == NULL)
     416           0 :                                 fprintf(stderr, "<NULL> instead.\n");
     417             :                         else
     418           0 :                                 fprintf(stderr, "'%s' instead.\n", save_varchar_tds7_param.name);
     419           0 :                         exit(1);
     420             :                 }
     421           8 :                 if (save_varchar_tds7_param.type != SYBVARCHAR) {
     422           0 :                         fprintf(stderr, "Expected rettype to be SYBVARCHAR was %d.\n", save_varchar_tds7_param.type);
     423           0 :                         exit(1);
     424             :                 }
     425           8 :                 if (save_varchar_tds7_param.len != 8000) {
     426           0 :                         fprintf(stderr, "Expected retlen to be 8000 was %d.\n", save_varchar_tds7_param.len);
     427           0 :                         exit(1);
     428             :                 }
     429             : 
     430             :                 /*
     431             :                  * Test name, size, contents of the NVARCHAR(4000) output parameter
     432             :                  */
     433           8 :                 if ((save_nvarchar_tds7_param.name == NULL) || strcmp(save_nvarchar_tds7_param.name, bindings[4].name)) {
     434           0 :                         fprintf(stderr, "Expected retname to be '%s', got ", bindings[4].name);
     435           0 :                         if (save_varchar_tds7_param.name == NULL)
     436           0 :                                 fprintf(stderr, "<NULL> instead.\n");
     437             :                         else
     438           0 :                                 fprintf(stderr, "'%s' instead.\n", save_nvarchar_tds7_param.name);
     439           0 :                         exit(1);
     440             :                 }
     441           8 :                 if (save_nvarchar_tds7_param.len != 4000) {
     442           0 :                         fprintf(stderr, "Expected retlen to be 4000 was %d.\n", save_nvarchar_tds7_param.len);
     443           0 :                         exit(1);
     444             :                 }
     445             :         }
     446             : 
     447          10 :         if(42 != return_status) {
     448           0 :                 fprintf(stderr, "Expected status to be 42.\n");
     449           0 :                 exit(1);
     450             :         }
     451             : 
     452          10 :         printf("Good: Got 6 output parameters and 1 return status of %d.\n", return_status);
     453             : 
     454             : 
     455             :         /* Test number of result sets */
     456          10 :         if (num_resultset != 4) {
     457           0 :                 fprintf(stderr, "Expected 4 resultset got %d.\n", num_resultset);
     458           0 :                 exit(1);
     459             :         }
     460          10 :         if (num_empty_resultset != 1) {
     461           0 :                 fprintf(stderr, "Expected an empty resultset got %d.\n", num_empty_resultset);
     462           0 :                 exit(1);
     463             :         }
     464          10 :         printf("Good: Got %d resultsets and %d empty resultset.\n", num_resultset, num_empty_resultset);
     465             : 
     466             : 
     467             : 
     468          10 :         printf("Dropping procedure\n");
     469          10 :         sql_cmd(dbproc);
     470          10 :         dbsqlexec(dbproc);
     471          10 :         while (dbresults(dbproc) != NO_MORE_RESULTS) {
     472             :                 /* nop */
     473             :         }
     474             : 
     475             :         /* additional tests for mssql */
     476             : #if defined(DBTDS_7_2)
     477          10 :         if (num_params == 6 && dbtds(dbproc) >= DBTDS_7_2) {
     478           4 :                 erc = dbrpcinit(dbproc, "sp_executesql", 0);  /* no options */
     479           4 :                 if (erc == FAIL) {
     480           0 :                         fprintf(stderr, "Failed line %d: dbrpcinit\n", __LINE__);
     481           0 :                         failed = true;
     482             :                 }
     483          12 :                 for (pb = bindings_mssql1; pb->name != NULL; pb++)
     484          12 :                         bind_param(dbproc, pb);
     485           4 :                 erc = dbrpcsend(dbproc);
     486           4 :                 if (erc == FAIL) {
     487           0 :                         fprintf(stderr, "Failed line %d: dbrpcsend\n", __LINE__);
     488           0 :                         exit(1);
     489             :                 }
     490           4 :                 while (dbresults(dbproc) != NO_MORE_RESULTS)
     491           0 :                         continue;
     492           4 :                 if (dbnumrets(dbproc) != 1) {   /* dbnumrets missed something */
     493           0 :                         fprintf(stderr, "Expected 1 output parameters.\n");
     494           0 :                         exit(1);
     495             :                 }
     496           4 :                 i = 1;
     497           4 :                 retname = dbretname(dbproc, i);
     498           4 :                 rettype = dbrettype(dbproc, i);
     499           4 :                 retlen = dbretlen(dbproc, i);
     500           4 :                 dbconvert(dbproc, rettype, dbretdata(dbproc, i), retlen, SYBVARCHAR, (BYTE*) teststr, -1);
     501           4 :                 if (strcmp(teststr, "test123") != 0) {
     502           0 :                         fprintf(stderr, "Unexpected '%s' results.\n", teststr);
     503           0 :                         exit(1);
     504             :                 }
     505             : 
     506           4 :                 erc = dbrpcinit(dbproc, "sp_executesql", 0);  /* no options */
     507           4 :                 if (erc == FAIL) {
     508           0 :                         fprintf(stderr, "Failed line %d: dbrpcinit\n", __LINE__);
     509           0 :                         failed = true;
     510             :                 }
     511          12 :                 for (pb = bindings_mssql2; pb->name != NULL; pb++)
     512          12 :                         bind_param(dbproc, pb);
     513           4 :                 erc = dbrpcsend(dbproc);
     514           4 :                 if (erc == FAIL) {
     515           0 :                         fprintf(stderr, "Failed line %d: dbrpcsend\n", __LINE__);
     516           0 :                         exit(1);
     517             :                 }
     518           4 :                 while (dbresults(dbproc) != NO_MORE_RESULTS)
     519           0 :                         continue;
     520           4 :                 if (dbnumrets(dbproc) != 1) {   /* dbnumrets missed something */
     521           0 :                         fprintf(stderr, "Expected 1 output parameters.\n");
     522           0 :                         exit(1);
     523             :                 }
     524           4 :                 i = 1;
     525           4 :                 retname = dbretname(dbproc, i);
     526           4 :                 rettype = dbrettype(dbproc, i);
     527           4 :                 retlen = dbretlen(dbproc, i);
     528           4 :                 dbconvert(dbproc, rettype, dbretdata(dbproc, i), retlen, SYBVARCHAR, (BYTE*) teststr, -1);
     529           4 :                 if (dbretdata(dbproc, i) != NULL || rettype != SYBBIT || retlen != 0) {
     530           0 :                         fprintf(stderr, "Unexpected '%s' results.\n", teststr);
     531           0 :                         exit(1);
     532             :                 }
     533             :         }
     534             : #endif
     535             : 
     536          10 :         dbexit();
     537             : 
     538          10 :         printf("%s %s\n", __FILE__, (failed ? "failed!" : "OK"));
     539             : 
     540          10 :         free_retparam(&save_param);
     541          10 :         free_retparam(&save_varchar_tds7_param);
     542          10 :         free_retparam(&save_nvarchar_tds7_param);
     543             : 
     544          10 :         return failed ? 1 : 0;
     545             : }

Generated by: LCOV version 1.13