Modify odbc-escapes-test case. SQLExecDirect cases were added as well as SQLExecute...
authorHiroshi Inoue <h-inoue@dream.email.ne.jp>
Wed, 22 Feb 2017 05:13:56 +0000 (14:13 +0900)
committerHiroshi Inoue <h-inoue@dream.email.ne.jp>
Fri, 24 Feb 2017 05:38:11 +0000 (14:38 +0900)
1. newly added {call a_b_c_d_e( .. fails in SQLExecDirect test case.
2. { = call concat( .. fails in both test cases.

It would be fixed by the next commit.

test/expected/odbc-escapes.out
test/src/odbc-escapes-test.c

index 7c3ffb4900396faf9a4e0150019c738bc7998c2e..0f8a4db125e6dfdf503c9127854457c2394cd239 100644 (file)
@@ -1,5 +1,7 @@
 connected
 
+-- TEST using SQLExecute after SQLPrepare
+
 Query: SELECT {fn CONCAT(?, ?) }
 Param 1: foo
 Param 2: bar
@@ -33,6 +35,14 @@ Result set:
 
 OUT param: 3
 
+Query: { ? = call concat(?::text, ?::text) }
+Param 1 is an OUT parameter
+Param 2: foo
+Param 3: bar
+Result set:
+
+OUT param: foobar
+
 Query: SELECT {d '2014-12-21' } + '1 day'::interval
 Result set:
 2014-12-22 00:00:00
@@ -44,4 +54,79 @@ Result set:
 Query: SELECT {ts '2014-12-21 20:30:40' } + '1 day 1 hour 1 minute 1 second'::interval
 Result set:
 2014-12-22 21:31:41
+
+Query: {call a_b_c_d_e(?, ?::timestamp, ?, ?, ?)}
+Param 1 is an OUT parameter
+Param 2: 2017-02-23 11:34:46
+Param 3 is an I-O parameter
+Param 4: 3.4
+Param 5 is an OUT parameter
+Result set:
+6.7999999999999998 7   2017-02-24 11:34:46
+OUT params: 6.7999999999999998 : 7 : 2017-02-24 11:34:46
+
+-- TEST using SQLExecDirect
+
+Query: SELECT {fn CONCAT(?, ?) }
+Param 1: foo
+Param 2: bar
+Result set:
+foobar
+
+Query: SELECT {fn LOCATE(?, ?, 2) }
+Param 1: needle
+Param 2: this is a needle in an ol' haystack
+Result set:
+11
+
+Query: SELECT 'x' || {fn SPACE(10) } || 'x'
+Result set:
+x          x
+
+Query: { call length(?) }
+Param 1: foobar
+Result set:
+6
+
+Query: { call right(?, ?) }
+Param 1: foobar
+Param 2: 3
+Result set:
+bar
+
+Query: { ? = call length('foo') }
+Param 1 is an OUT parameter
+Result set:
+
+OUT param: 3
+
+Query: { ? = call concat(?::text, ?::text) }
+Param 1 is an OUT parameter
+Param 2: foo
+Param 3: bar
+Result set:
+
+OUT param: foobar
+
+Query: SELECT {d '2014-12-21' } + '1 day'::interval
+Result set:
+2014-12-22 00:00:00
+
+Query: SELECT {t '20:30:40' } + '1 hour 1 minute 1 second'::interval
+Result set:
+21:31:41
+
+Query: SELECT {ts '2014-12-21 20:30:40' } + '1 day 1 hour 1 minute 1 second'::interval
+Result set:
+2014-12-22 21:31:41
+
+Query: {call a_b_c_d_e(?, ?::timestamp, ?, ?, ?)}
+Param 1 is an OUT parameter
+Param 2: 2017-02-23 11:34:46
+Param 3 is an I-O parameter
+Param 4: 3.4
+Param 5 is an OUT parameter
+Result set:
+6.7999999999999998 7   2017-02-24 11:34:46
+OUT params: 6.7999999999999998 : 7 : 2017-02-24 11:34:46
 disconnecting
index d6e504c02de267950d7ff50ab8babb585c554295..4cd448ee7c3c9ef261ce478336c0461b77a1715f 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "common.h"
 
@@ -29,12 +30,13 @@ bindParamString(HSTMT hstmt, int paramno, char *str)
 }
 
 static void
-bindOutParamString(HSTMT hstmt, int paramno, char *outbuf, int outbuflen)
+bindOutParamString(HSTMT hstmt, int paramno, char *outbuf, int outbuflen, BOOL inout)
 {
    SQLRETURN   rc;
    static SQLLEN       cbParams[10];
 
-    rc = SQLBindParameter(hstmt, paramno, SQL_PARAM_OUTPUT,
+   cbParams[paramno] = SQL_NTS;
+   rc = SQLBindParameter(hstmt, paramno, inout ? SQL_PARAM_INPUT_OUTPUT : SQL_PARAM_OUTPUT,
                          SQL_C_CHAR,   /* value type */
                          SQL_CHAR,     /* param type */
                          20,           /* column size */
@@ -43,15 +45,21 @@ bindOutParamString(HSTMT hstmt, int paramno, char *outbuf, int outbuflen)
                          outbuflen,    /* buffer len */
                          &cbParams[paramno]        /* StrLen_or_IndPtr */);
    CHECK_STMT_RESULT(rc, "SQLBindParameter failed", hstmt);
-   printf("Param %d is an OUT parameter\n", paramno);
+   printf("Param %d is an %s parameter\n", paramno, inout ? "I-O": "OUT");
 }
 
+static BOOL    execDirectMode = FALSE;
+static SQLCHAR saveQuery[128];
+
 static void
 executeQuery(HSTMT hstmt)
 {
    SQLRETURN   rc;
 
-   rc = SQLExecute(hstmt);
+   if (execDirectMode)
+       rc = SQLExecDirect(hstmt, saveQuery, SQL_NTS);
+   else
+       rc = SQLExecute(hstmt);
    CHECK_STMT_RESULT(rc, "SQLExecute failed", hstmt);
    print_result(hstmt);
    rc = SQLFreeStmt(hstmt, SQL_CLOSE);
@@ -63,25 +71,20 @@ prepareQuery(HSTMT hstmt, char *str)
 {
    SQLRETURN   rc;
 
-   rc = SQLPrepare(hstmt, (SQLCHAR *) str, SQL_NTS);
-   CHECK_STMT_RESULT(rc, "SQLPrepare failed", hstmt);
+   if (execDirectMode)
+       strcpy(saveQuery, str);
+   else
+   {
+       rc = SQLPrepare(hstmt, (SQLCHAR *) str, SQL_NTS);
+       CHECK_STMT_RESULT(rc, "SQLPrepare failed", hstmt);
+   }
    printf("\nQuery: %s\n", str);
 }
 
-int main(int argc, char **argv)
+static void    escape_test(HSTMT hstmt)
 {
-   SQLRETURN   rc;
-   HSTMT       hstmt = SQL_NULL_HSTMT;
-   char        outbuf[10];
-
-   test_connect();
-
-   rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
-   if (!SQL_SUCCEEDED(rc))
-   {
-       print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn);
-       exit(1);
-   }
+   char    outbuf1[64], outbuf3[64], outbuf5[64];
+   BOOL    variadic_test_success = FALSE;
 
    /**** Function escapes ****/
 
@@ -113,20 +116,22 @@ int main(int argc, char **argv)
    executeQuery(hstmt);
 
    prepareQuery(hstmt, "{ ? = call length('foo') }");
-   memset(outbuf, 0, sizeof(outbuf));
-   bindOutParamString(hstmt, 1, outbuf, sizeof(outbuf) - 1);
+   memset(outbuf1, 0, sizeof(outbuf1));
+   bindOutParamString(hstmt, 1, outbuf1, sizeof(outbuf1) - 1, FALSE);
    executeQuery(hstmt);
-   printf("OUT param: %s\n", outbuf);
+   printf("OUT param: %s\n", outbuf1);
 
-   /* TODO: This doesn't currently work.
-   prepareQuery(hstmt, "{ ? = call concat(?, ?) }");
-   memset(outbuf, 0, sizeof(outbuf));
-   bindOutParamString(hstmt, 1, outbuf, sizeof(outbuf) - 1);
+   /* It's preferable to cast VARIADIC any fields */
+   prepareQuery(hstmt, "{ ? = call concat(?::text, ?::text) }");
+   memset(outbuf1, 0, sizeof(outbuf1));
+   bindOutParamString(hstmt, 1, outbuf1, sizeof(outbuf1) - 1, FALSE);
    bindParamString(hstmt, 2, "foo");
    bindParamString(hstmt, 3, "bar");
-   executeQuery(hstmt);
-   printf("OUT param: %s\n", outbuf);
-   */
+   if (variadic_test_success)
+       executeQuery(hstmt);
+   else
+       printf("skip this test because it fails\n");
+   printf("OUT param: %s\n", outbuf1);
 
    /**** Date, Time, and Timestamp literals ****/
 
@@ -139,6 +144,56 @@ int main(int argc, char **argv)
    prepareQuery(hstmt, "SELECT {ts '2014-12-21 20:30:40' } + '1 day 1 hour 1 minute 1 second'::interval");
    executeQuery(hstmt);
 
+   /**** call procedure with out and i-o parameters ****/
+   prepareQuery(hstmt, "{call a_b_c_d_e(?, ?::timestamp, ?, ?, ?)}");
+   memset(outbuf1, 0, sizeof(outbuf1));
+   bindOutParamString(hstmt, 1, outbuf1, sizeof(outbuf1) - 1, FALSE);
+   bindParamString(hstmt, 2, "2017-02-23 11:34:46");
+   strcpy(outbuf3, "4");
+   bindOutParamString(hstmt, 3, outbuf3, sizeof(outbuf3) - 1, TRUE);
+   bindParamString(hstmt, 4, "3.4");
+   memset(outbuf5, 0, sizeof(outbuf5));
+   bindOutParamString(hstmt, 5, outbuf5, sizeof(outbuf5) - 1, FALSE);
+   executeQuery(hstmt);
+   printf("OUT params: %s : %s : %s\n", outbuf1, outbuf3, outbuf5);
+}
+
+int main(int argc, char **argv)
+{
+   SQLRETURN   rc;
+   HSTMT       hstmt = SQL_NULL_HSTMT;
+
+   test_connect();
+
+   rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
+   if (!SQL_SUCCEEDED(rc))
+   {
+       print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn);
+       exit(1);
+   }
+
+   rc = SQLExecDirect(hstmt, "create or replace function a_b_c_d_e"
+           "(out a float8, in b timestamp, inout c integer, "
+           "in d numeric, out e timestamp) returns record as "
+           "$function$ \n"
+           "DECLARE \n"
+           "BEGIN \n"
+           "a := 2 * d; \n"
+           "e := b + '1 day'::interval; \n"
+           "c := c + 3; \n"
+           "END; \n"
+           "$function$ \n"
+           "LANGUAGE plpgsql\n"
+           , SQL_NTS);
+   CHECK_STMT_RESULT(rc, "create function a_b_c_d_e failed", hstmt);
+
+   execDirectMode = FALSE;
+   printf("\n-- TEST using SQLExecute after SQLPrepare\n");
+   escape_test(hstmt);
+   execDirectMode = TRUE;
+   printf("\n-- TEST using SQLExecDirect\n");
+   escape_test(hstmt);
+
    /* Clean up */
    test_disconnect();