LCOV - code coverage report
Current view: top level - src/odbc/unittests - funccall.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 113 126 89.7 %
Date: 2024-03-23 08:24:27 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : 
       3             : /* Test for {?=call store(?)} syntax and run */
       4             : 
       5             : static void test_with_conversions(void);
       6             : static void test_with_dbname(void);
       7             : 
       8             : int
       9           8 : main(void)
      10             : {
      11             :         SQLINTEGER input, output;
      12             :         SQLLEN ind, ind2, ind3, ind4;
      13             :         SQLINTEGER out1;
      14             :         char out2[30];
      15             : 
      16           8 :         odbc_connect();
      17             : 
      18           8 :         odbc_command("IF OBJECT_ID('simpleresult') IS NOT NULL DROP PROC simpleresult");
      19             : 
      20           8 :         odbc_command("create proc simpleresult @i int as begin return @i end");
      21             : 
      22           8 :         CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &input, 0, &ind2, "S");
      23           8 :         CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S");
      24             : 
      25           8 :         CHKPrepare(T("{ \n?\t\r= call simpleresult(?)}"), SQL_NTS, "S");
      26             : 
      27           8 :         input = 123;
      28           8 :         ind2 = sizeof(input);
      29           8 :         output = 0xdeadbeef;
      30           8 :         CHKExecute("S");
      31             : 
      32           8 :         if (output != 123) {
      33           0 :                 printf("Invalid result\n");
      34           0 :                 exit(1);
      35             :         }
      36             : 
      37             :         /* should return "Invalid cursor state" */
      38           8 :         if (SQLFetch(odbc_stmt) != SQL_ERROR) {
      39           0 :                 printf("Data not expected\n");
      40           0 :                 exit(1);
      41             :         }
      42           8 :         ODBC_CHECK_COLS(0);
      43             : 
      44             :         /* just to reset some possible buffers */
      45           8 :         odbc_command("DECLARE @i INT");
      46             : 
      47             :         /* same test but with SQLExecDirect and same bindings */
      48           8 :         input = 567;
      49           8 :         ind2 = sizeof(input);
      50           8 :         output = 0xdeadbeef;
      51           8 :         CHKExecDirect(T("{?=call simpleresult(?)}"), SQL_NTS, "S");
      52             : 
      53           8 :         if (output != 567) {
      54           0 :                 fprintf(stderr, "Invalid result\n");
      55           0 :                 exit(1);
      56             :         }
      57             : 
      58             :         /* should return "Invalid cursor state" */
      59           8 :         CHKFetch("E");
      60             : 
      61           8 :         odbc_command("drop proc simpleresult");
      62             : 
      63           8 :         odbc_command("IF OBJECT_ID('simpleresult2') IS NOT NULL DROP PROC simpleresult2");
      64             : 
      65             :         /* force cursor close */
      66           8 :         SQLCloseCursor(odbc_stmt);
      67             : 
      68             :         /* test output parameter */
      69           8 :         odbc_command("create proc simpleresult2 @i int, @x int output, @y varchar(20) output as begin select @x = 6789 select @y = 'test foo' return @i end");
      70             : 
      71           8 :         CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0,  0, &output, 0,            &ind,  "S");
      72           8 :         CHKBindParameter(2, SQL_PARAM_INPUT,  SQL_C_SLONG, SQL_INTEGER, 0,  0, &input,  0,            &ind2, "S");
      73           8 :         CHKBindParameter(3, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0,  0, &out1,   0,            &ind3, "S");
      74           8 :         CHKBindParameter(4, SQL_PARAM_OUTPUT, SQL_C_CHAR,  SQL_VARCHAR, 20, 0, out2,    sizeof(out2), &ind4, "S");
      75             : 
      76           8 :         CHKPrepare(T("{ \n?\t\r= call simpleresult2(?,?,?)}"), SQL_NTS, "S");
      77             : 
      78           8 :         input = 987;
      79           8 :         ind2 = sizeof(input);
      80           8 :         out1 = 888;
      81           8 :         output = 0xdeadbeef;
      82           8 :         ind3 = SQL_DATA_AT_EXEC;
      83           8 :         ind4 = SQL_DEFAULT_PARAM;
      84           8 :         strcpy(out2, "bad!");
      85           8 :         CHKExecute("S");
      86             : 
      87           8 :         if (output != 987 || ind3 <= 0 || ind4 <= 0 || out1 != 6789 || strcmp(out2, "test foo") != 0) {
      88           0 :                 printf("ouput = %d ind3 = %d ind4 = %d out1 = %d out2 = %s\n", (int) output, (int) ind3, (int) ind4, (int) out1,
      89             :                        out2);
      90           0 :                 printf("Invalid result\n");
      91           0 :                 exit(1);
      92             :         }
      93             : 
      94             :         /* should return "Invalid cursor state" */
      95           8 :         CHKFetch("E");
      96             : 
      97           8 :         ODBC_CHECK_COLS(0);
      98             : 
      99           8 :         odbc_command("drop proc simpleresult2");
     100             : 
     101             :         /*
     102             :          * test from shiv kumar
     103             :          * Cfr ML 2006-11-21 "specifying a 0 for the StrLen_or_IndPtr in the
     104             :          * SQLBindParameter call is not working on AIX"
     105             :          */
     106           8 :         odbc_command("IF OBJECT_ID('rpc_read') IS NOT NULL DROP PROC rpc_read");
     107             : 
     108           8 :         odbc_reset_statement();
     109             : 
     110           8 :         odbc_command("create proc rpc_read @i int, @x timestamp as begin select 1 return 1234 end");
     111           8 :         SQLCloseCursor(odbc_stmt);
     112             : 
     113           8 :         CHKPrepare(T("{ ? = CALL rpc_read ( ?, ? ) }"), SQL_NTS, "S");
     114             : 
     115           8 :         ind = 0;
     116           8 :         CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S");
     117             : 
     118           8 :         ind2 = 0;
     119           8 :         CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &input, 0, &ind2, "S");
     120             : 
     121           8 :         ind3 = 8;
     122           8 :         CHKBindParameter(3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, 8, 0, out2, 8, &ind3, "S");
     123             : 
     124           8 :         CHKExecute("S");
     125             : 
     126           8 :         CHKFetch("S");
     127             : 
     128           8 :         CHKFetch("No");
     129             : 
     130           8 :         odbc_reset_statement();
     131           8 :         odbc_command("drop proc rpc_read");
     132             : 
     133             :         /*
     134             :          * Test from Joao Amaral
     135             :          * This test SQLExecute where a store procedure returns no result
     136             :          * This seems similar to a previous one but use set instead of select
     137             :          * (with is supported only by mssql and do not return all stuff as 
     138             :          * select does)
     139             :          */
     140           8 :         if (odbc_db_is_microsoft()) {
     141             : 
     142           6 :                 odbc_reset_statement();
     143             : 
     144           6 :                 odbc_command("IF OBJECT_ID('sp_test') IS NOT NULL DROP PROC sp_test");
     145           6 :                 odbc_command("create proc sp_test @res int output as set @res = 456");
     146             : 
     147           6 :                 odbc_reset_statement();
     148             : 
     149           6 :                 CHKPrepare(T("{ call sp_test(?)}"), SQL_NTS, "S");
     150           6 :                 CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S");
     151             : 
     152           6 :                 output = 0xdeadbeef;
     153           6 :                 CHKExecute("S");
     154             : 
     155           6 :                 if (output != 456) {
     156           0 :                         fprintf(stderr, "Invalid result %d(%x)\n", (int) output, (int) output);
     157           0 :                         return 1;
     158             :                 }
     159           6 :                 odbc_command("drop proc sp_test");
     160             :         }
     161           8 :         odbc_disconnect();
     162             : 
     163           8 :         if (odbc_db_is_microsoft()) {
     164           6 :                 odbc_use_version3 = 1;
     165           6 :                 odbc_connect();
     166             : 
     167           6 :                 test_with_conversions();
     168           6 :                 test_with_dbname();
     169           6 :                 odbc_disconnect();
     170             :         }
     171             : 
     172           8 :         printf("Done.\n");
     173           8 :         return 0;
     174             : }
     175             : 
     176             : static void
     177           6 : test_with_conversions(void)
     178             : {
     179             :         SQLLEN ind, ind2, ind3;
     180             :         char out2[30];
     181             : 
     182             :         /*
     183             :          * test from Bower, Wayne
     184             :          * Cfr ML 2012-03-02 "[freetds] [unixODBC][Driver Manager]Function sequence error (SQL-HY010)"
     185             :          */
     186           6 :         odbc_command("IF OBJECT_ID('TMP_SP_Test_ODBC') IS NOT NULL DROP PROC TMP_SP_Test_ODBC");
     187           6 :         odbc_command("create proc TMP_SP_Test_ODBC @i int,\n@o int output\nas\nset nocount on\nselect @o = 55\nreturn 9\n");
     188           6 :         odbc_reset_statement();
     189             : 
     190           6 :         CHKPrepare(T("{ ? = call TMP_SP_Test_ODBC (?, ?) }"), SQL_NTS, "S");
     191             : 
     192           6 :         ind2 = 2;
     193           6 :         CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 80, 0, "10", 2, &ind2, "S");
     194           6 :         ind3 = SQL_NULL_DATA;
     195           6 :         strcpy(out2, " ");
     196           6 :         CHKBindParameter(3, SQL_PARAM_INPUT_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 1, out2, 29, &ind3, "S");
     197           6 :         ind = 1;
     198           6 :         CHKBindParameter(1, SQL_PARAM_INPUT_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 1, out2, 29, &ind, "S");
     199             : 
     200             :         /* mssql returns SUCCESS */
     201           6 :         CHKExecute("No");
     202             : 
     203           6 :         ODBC_CHECK_COLS(0);
     204             : 
     205           6 :         odbc_reset_statement();
     206           6 :         odbc_command("drop proc TMP_SP_Test_ODBC");
     207           6 : }
     208             : 
     209             : static void
     210           6 : test_with_dbname(void)
     211             : {
     212             :         SQLINTEGER len;
     213             :         SQLTCHAR out[512];
     214             :         char sql[1024];
     215             :         SQLINTEGER output;
     216             :         SQLLEN ind;
     217           6 :         ODBC_BUF *odbc_buf = NULL;
     218             : 
     219           6 :         len = sizeof(out);
     220           6 :         CHKGetConnectAttr(SQL_ATTR_CURRENT_CATALOG, (SQLPOINTER) out, sizeof(out), &len, "SI");
     221             : 
     222           6 :         odbc_command("IF OBJECT_ID('TMP_SP_Test_ODBC') IS NOT NULL DROP PROC TMP_SP_Test_ODBC");
     223           6 :         odbc_command("create proc TMP_SP_Test_ODBC @o int output\nas\nset @o=55\nreturn 3\n");
     224           6 :         odbc_reset_statement();
     225             : 
     226           6 :         sprintf(sql, "{call [%s]..TMP_SP_Test_ODBC(?)}", C(out));
     227           6 :         CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S");
     228           6 :         CHKPrepare(T(sql), SQL_NTS, "S");
     229             : 
     230           6 :         output = 123;
     231           6 :         ind = sizeof(output);
     232           6 :         CHKExecute("S");
     233             : 
     234           6 :         if (output != 55) {
     235           0 :                 printf("Invalid result\n");
     236           0 :                 exit(1);
     237             :         }
     238             : 
     239           6 :         odbc_reset_statement();
     240           6 :         odbc_command("drop proc TMP_SP_Test_ODBC");
     241           6 :         ODBC_FREE();
     242           6 : }

Generated by: LCOV version 1.13