summaryrefslogtreecommitdiffstats
path: root/src/interfaces/ecpg/test/compat_informix
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:15:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:15:05 +0000
commit46651ce6fe013220ed397add242004d764fc0153 (patch)
tree6e5299f990f88e60174a1d3ae6e48eedd2688b2b /src/interfaces/ecpg/test/compat_informix
parentInitial commit. (diff)
downloadpostgresql-14-upstream.tar.xz
postgresql-14-upstream.zip
Adding upstream version 14.5.upstream/14.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/interfaces/ecpg/test/compat_informix')
-rw-r--r--src/interfaces/ecpg/test/compat_informix/.gitignore18
-rw-r--r--src/interfaces/ecpg/test/compat_informix/Makefile24
-rw-r--r--src/interfaces/ecpg/test/compat_informix/charfuncs.pgc31
-rw-r--r--src/interfaces/ecpg/test/compat_informix/dec_test.pgc238
-rw-r--r--src/interfaces/ecpg/test/compat_informix/describe.pgc199
-rw-r--r--src/interfaces/ecpg/test/compat_informix/rfmtdate.pgc175
-rw-r--r--src/interfaces/ecpg/test/compat_informix/rfmtlong.pgc73
-rw-r--r--src/interfaces/ecpg/test/compat_informix/rnull.pgc97
-rw-r--r--src/interfaces/ecpg/test/compat_informix/sqlda.pgc250
-rw-r--r--src/interfaces/ecpg/test/compat_informix/test_informix.pgc95
-rw-r--r--src/interfaces/ecpg/test/compat_informix/test_informix2.pgc122
11 files changed, 1322 insertions, 0 deletions
diff --git a/src/interfaces/ecpg/test/compat_informix/.gitignore b/src/interfaces/ecpg/test/compat_informix/.gitignore
new file mode 100644
index 0000000..f97706b
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/.gitignore
@@ -0,0 +1,18 @@
+/charfuncs
+/charfuncs.c
+/dec_test
+/dec_test.c
+/describe
+/describe.c
+/rfmtdate
+/rfmtdate.c
+/rfmtlong
+/rfmtlong.c
+/rnull
+/rnull.c
+/sqlda
+/sqlda.c
+/test_informix
+/test_informix.c
+/test_informix2
+/test_informix2.c
diff --git a/src/interfaces/ecpg/test/compat_informix/Makefile b/src/interfaces/ecpg/test/compat_informix/Makefile
new file mode 100644
index 0000000..d50fdc2
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/Makefile
@@ -0,0 +1,24 @@
+subdir = src/interfaces/ecpg/test/compat_informix
+top_builddir = ../../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/$(subdir)/../Makefile.regress
+
+# Use special informix compatibility switch for all tests in this directory
+ECPG += -C INFORMIX
+
+LDFLAGS_INTERNAL += -L../../compatlib -lecpg_compat
+
+TESTS = test_informix test_informix.c \
+ test_informix2 test_informix2.c \
+ dec_test dec_test.c \
+ rfmtdate rfmtdate.c \
+ rfmtlong rfmtlong.c \
+ rnull rnull.c \
+ sqlda sqlda.c \
+ describe describe.c \
+ charfuncs charfuncs.c
+
+all: $(TESTS)
+
+rnull.c: rnull.pgc $(ECPG_TEST_DEPENDENCIES)
+ $(ECPG) -r no_indicator -o $@ $<
diff --git a/src/interfaces/ecpg/test/compat_informix/charfuncs.pgc b/src/interfaces/ecpg/test/compat_informix/charfuncs.pgc
new file mode 100644
index 0000000..3605c9d
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/charfuncs.pgc
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sqltypes.h>
+
+int main(void)
+{
+ char t1[] = "abc def ghi ";
+ /* 123456789012345 */
+ char buf[50];
+ int k;
+
+ printf("t1: _%s_\n", t1);
+ rupshift(t1);
+ printf("t1: _%s_\n", t1);
+
+ k = 2;
+ ldchar(t1, k, buf);
+ printf("byleng(t1, %d): %d, ldchar: _%s_\n", k, byleng(t1, k), buf);
+ k = 5;
+ ldchar(t1, k, buf);
+ printf("byleng(t1, %d): %d, ldchar: _%s_\n", k, byleng(t1, k), buf);
+ k = 9;
+ ldchar(t1, k, buf);
+ printf("byleng(t1, %d): %d, ldchar: _%s_\n", k, byleng(t1, k), buf);
+ k = 15;
+ ldchar(t1, k, buf);
+ printf("byleng(t1, %d): %d, ldchar: _%s_\n", k, byleng(t1, k), buf);
+
+
+ return 0;
+}
diff --git a/src/interfaces/ecpg/test/compat_informix/dec_test.pgc b/src/interfaces/ecpg/test/compat_informix/dec_test.pgc
new file mode 100644
index 0000000..f6a9f42
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/dec_test.pgc
@@ -0,0 +1,238 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <pgtypes_numeric.h>
+#include <pgtypes_error.h>
+#include <decimal.h>
+#include <sqltypes.h>
+
+exec sql include ../regression;
+
+exec sql include ../printf_hack;
+
+
+/*
+TODO:
+ deccmp => DECUNKNOWN
+ decimal point: , and/or . ?
+ ECPG_INFORMIX_BAD_EXPONENT ?
+*/
+
+char* decs[] = { "2E394", "-2", ".794", "3.44", "592.49E21", "-32.84e4",
+ "2E-394", ".1E-2", "+.0", "-592.49E-07", "+32.84e-4",
+ ".500001", "-.5000001",
+ "1234567890123456789012345678.91", /* 30 digits should fit
+ into decimal */
+ "1234567890123456789012345678.921", /* 31 digits should NOT
+ fit into decimal */
+ "not a number",
+ NULL};
+
+
+static void
+check_errno(void);
+
+#define BUFSIZE 200
+
+int
+main(void)
+{
+ decimal *dec, *din;
+ char buf[BUFSIZE];
+ long l;
+ int i, j, k, q, r, count = 0;
+ double dbl;
+ decimal **decarr = (decimal **) calloc(1, sizeof(decimal));
+
+ ECPGdebug(1, stderr);
+
+ for (i = 0; decs[i]; i++)
+ {
+ dec = PGTYPESdecimal_new();
+ r = deccvasc(decs[i], strlen(decs[i]), dec);
+ if (r)
+ {
+ check_errno();
+ printf("dec[%d,0]: r: %d\n", i, r);
+ PGTYPESdecimal_free(dec);
+ continue;
+ }
+ decarr = realloc(decarr, sizeof(decimal *) * (count + 1));
+ decarr[count++] = dec;
+
+ r = dectoasc(dec, buf, BUFSIZE-1, -1);
+ if (r < 0) check_errno();
+ printf("dec[%d,1]: r: %d, %s\n", i, r, buf);
+
+ r = dectoasc(dec, buf, BUFSIZE-1, 0);
+ if (r < 0) check_errno();
+ printf("dec[%d,2]: r: %d, %s\n", i, r, buf);
+ r = dectoasc(dec, buf, BUFSIZE-1, 1);
+ if (r < 0) check_errno();
+ printf("dec[%d,3]: r: %d, %s\n", i, r, buf);
+ r = dectoasc(dec, buf, BUFSIZE-1, 2);
+ if (r < 0) check_errno();
+ printf("dec[%d,4]: r: %d, %s\n", i, r, buf);
+
+ din = PGTYPESdecimal_new();
+ r = dectoasc(din, buf, BUFSIZE-1, 2);
+ if (r < 0) check_errno();
+ printf("dec[%d,5]: r: %d, %s\n", i, r, buf);
+
+ r = dectolong(dec, &l);
+ if (r) check_errno();
+ printf("dec[%d,6]: %ld (r: %d)\n", i, r?0L:l, r);
+ if (r == 0)
+ {
+ r = deccvlong(l, din);
+ if (r) check_errno();
+ dectoasc(din, buf, BUFSIZE-1, 2);
+ q = deccmp(dec, din);
+ printf("dec[%d,7]: %s (r: %d - cmp: %d)\n", i, buf, r, q);
+ }
+
+ r = dectoint(dec, &k);
+ if (r) check_errno();
+ printf("dec[%d,8]: %d (r: %d)\n", i, r?0:k, r);
+ if (r == 0)
+ {
+ r = deccvint(k, din);
+ if (r) check_errno();
+ dectoasc(din, buf, BUFSIZE-1, 2);
+ q = deccmp(dec, din);
+ printf("dec[%d,9]: %s (r: %d - cmp: %d)\n", i, buf, r, q);
+ }
+
+ if (i != 6)
+ {
+ /* underflow does not work reliable on several archs, so not testing it here */
+ /* this is a libc problem since we only call strtod() */
+ r = dectodbl(dec, &dbl);
+ if (r) check_errno();
+ printf("dec[%d,10]: ", i);
+ print_double(r ? 0.0 : dbl);
+ printf(" (r: %d)\n", r);
+ }
+
+ PGTYPESdecimal_free(din);
+ printf("\n");
+ }
+
+ /* add a NULL value */
+ dec = PGTYPESdecimal_new();
+ decarr = realloc(decarr, sizeof(decimal *) * (count + 1));
+ decarr[count++] = dec;
+
+ rsetnull(CDECIMALTYPE, (char *) decarr[count-1]);
+ printf("dec[%d]: %sNULL\n", count-1,
+ risnull(CDECIMALTYPE, (char *) decarr[count-1]) ? "" : "NOT ");
+ printf("dec[0]: %sNULL\n",
+ risnull(CDECIMALTYPE, (char *) decarr[0]) ? "" : "NOT ");
+
+ r = dectoasc(decarr[3], buf, -1, -1);
+ check_errno(); printf("dectoasc with len == -1: r: %d\n", r);
+ r = dectoasc(decarr[3], buf, 0, -1);
+ check_errno(); printf("dectoasc with len == 0: r: %d\n", r);
+
+ for (i = 0; i < count; i++)
+ {
+ for (j = 0; j < count; j++)
+ {
+ decimal a, s, m, d;
+ int c;
+ c = deccmp(decarr[i], decarr[j]);
+ printf("dec[c,%d,%d]: %d\n", i, j, c);
+
+ r = decadd(decarr[i], decarr[j], &a);
+ if (r)
+ {
+ check_errno();
+ printf("r: %d\n", r);
+ }
+ else
+ {
+ dectoasc(&a, buf, BUFSIZE-1, -1);
+ printf("dec[a,%d,%d]: %s\n", i, j, buf);
+ }
+
+ r = decsub(decarr[i], decarr[j], &s);
+ if (r)
+ {
+ check_errno();
+ printf("r: %d\n", r);
+ }
+ else
+ {
+ dectoasc(&s, buf, BUFSIZE-1, -1);
+ printf("dec[s,%d,%d]: %s\n", i, j, buf);
+ }
+
+ r = decmul(decarr[i], decarr[j], &m);
+ if (r)
+ {
+ check_errno();
+ printf("r: %d\n", r);
+ }
+ else
+ {
+ dectoasc(&m, buf, BUFSIZE-1, -1);
+ printf("dec[m,%d,%d]: %s\n", i, j, buf);
+ }
+
+ r = decdiv(decarr[i], decarr[j], &d);
+ if (r)
+ {
+ check_errno();
+ printf("r: %d\n", r);
+ }
+ else
+ {
+ dectoasc(&d, buf, BUFSIZE-1, -1);
+ printf("dec[d,%d,%d]: %s\n", i, j, buf);
+ }
+ }
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ dectoasc(decarr[i], buf, BUFSIZE-1, -1);
+ printf("%d: %s\n", i, buf);
+
+ PGTYPESdecimal_free(decarr[i]);
+ }
+ free(decarr);
+
+ return 0;
+}
+
+static void
+check_errno(void)
+{
+ switch(errno)
+ {
+ case 0:
+ printf("(no errno set) - ");
+ break;
+ case ECPG_INFORMIX_NUM_OVERFLOW:
+ printf("(errno == ECPG_INFORMIX_NUM_OVERFLOW) - ");
+ break;
+ case ECPG_INFORMIX_NUM_UNDERFLOW:
+ printf("(errno == ECPG_INFORMIX_NUM_UNDERFLOW) - ");
+ break;
+ case PGTYPES_NUM_OVERFLOW:
+ printf("(errno == PGTYPES_NUM_OVERFLOW) - ");
+ break;
+ case PGTYPES_NUM_UNDERFLOW:
+ printf("(errno == PGTYPES_NUM_UNDERFLOW) - ");
+ break;
+ case PGTYPES_NUM_BAD_NUMERIC:
+ printf("(errno == PGTYPES_NUM_BAD_NUMERIC) - ");
+ break;
+ case PGTYPES_NUM_DIVIDE_ZERO:
+ printf("(errno == PGTYPES_NUM_DIVIDE_ZERO) - ");
+ break;
+ default:
+ printf("(unknown errno (%d))\n", errno);
+ printf("(libc: (%s)) ", strerror(errno));
+ break;
+ }
+}
diff --git a/src/interfaces/ecpg/test/compat_informix/describe.pgc b/src/interfaces/ecpg/test/compat_informix/describe.pgc
new file mode 100644
index 0000000..4ee7254
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/describe.pgc
@@ -0,0 +1,199 @@
+#include <stdlib.h>
+#include <string.h>
+
+exec sql include ../regression;
+exec sql include sqlda.h;
+
+exec sql whenever sqlerror stop;
+
+sqlda_t *sqlda1, *sqlda2, *sqlda3;
+
+int
+main (void)
+{
+exec sql begin declare section;
+ char *stmt1 = "SELECT id, t FROM descr_t1";
+ char *stmt2 = "SELECT id, t FROM descr_t1 WHERE id = -1";
+ int i, count1, count2;
+ char field_name1[30] = "not set";
+ char field_name2[30] = "not set";
+exec sql end declare section;
+
+ char msg[128];
+
+ ECPGdebug(1, stderr);
+
+ strcpy(msg, "connect");
+ exec sql connect to REGRESSDB1;
+
+ strcpy(msg, "set");
+ exec sql set datestyle to iso;
+
+ strcpy(msg, "create");
+ exec sql create table descr_t1(id serial primary key, t text);
+
+ strcpy(msg, "insert");
+ exec sql insert into descr_t1(id, t) values (default, 'a');
+ exec sql insert into descr_t1(id, t) values (default, 'b');
+ exec sql insert into descr_t1(id, t) values (default, 'c');
+ exec sql insert into descr_t1(id, t) values (default, 'd');
+
+ strcpy(msg, "commit");
+ exec sql commit;
+
+ /*
+ * Test DESCRIBE with a query producing tuples.
+ * DESCRIPTOR and SQL DESCRIPTOR are NOT the same in
+ * Informix-compat mode.
+ */
+
+ strcpy(msg, "allocate");
+ exec sql allocate descriptor desc1;
+ exec sql allocate descriptor desc2;
+
+ strcpy(msg, "prepare");
+ exec sql prepare st_id1 FROM :stmt1;
+
+ sqlda1 = sqlda2 = sqlda3 = NULL;
+
+ strcpy(msg, "describe");
+ exec sql describe st_id1 into sql descriptor desc1;
+ exec sql describe st_id1 using sql descriptor desc2;
+
+ exec sql describe st_id1 into descriptor sqlda1;
+ exec sql describe st_id1 using descriptor sqlda2;
+ exec sql describe st_id1 into sqlda3;
+
+ if (sqlda1 == NULL)
+ {
+ printf("sqlda1 NULL\n");
+ exit(1);
+ }
+
+ if (sqlda2 == NULL)
+ {
+ printf("sqlda2 NULL\n");
+ exit(1);
+ }
+
+ if (sqlda3 == NULL)
+ {
+ printf("sqlda3 NULL\n");
+ exit(1);
+ }
+
+ strcpy(msg, "get descriptor");
+ exec sql get descriptor desc1 :count1 = count;
+ exec sql get descriptor desc1 :count2 = count;
+
+ if (count1 != count2)
+ {
+ printf("count1 (%d) != count2 (%d)\n", count1, count2);
+ exit(1);
+ }
+
+ if (count1 != sqlda1->sqld)
+ {
+ printf("count1 (%d) != sqlda1->sqld (%d)\n", count1, sqlda1->sqld);
+ exit(1);
+ }
+
+ if (count1 != sqlda2->sqld)
+ {
+ printf("count1 (%d) != sqlda2->sqld (%d)\n", count1, sqlda2->sqld);
+ exit(1);
+ }
+
+ if (count1 != sqlda3->sqld)
+ {
+ printf("count1 (%d) != sqlda3->sqld (%d)\n", count1, sqlda3->sqld);
+ exit(1);
+ }
+
+ for (i = 1; i <= count1; i++)
+ {
+ exec sql get descriptor desc1 value :i :field_name1 = name;
+ exec sql get descriptor desc2 value :i :field_name2 = name;
+ printf("%d\n\tfield_name1 '%s'\n\tfield_name2 '%s'\n\t"
+ "sqlda1 '%s'\n\tsqlda2 '%s'\n\tsqlda3 '%s'\n",
+ i, field_name1, field_name2,
+ sqlda1->sqlvar[i-1].sqlname,
+ sqlda2->sqlvar[i-1].sqlname,
+ sqlda3->sqlvar[i-1].sqlname);
+ }
+
+ strcpy(msg, "deallocate");
+ exec sql deallocate descriptor desc1;
+ exec sql deallocate descriptor desc2;
+ free(sqlda1);
+ free(sqlda2);
+ free(sqlda3);
+
+ exec sql deallocate prepare st_id1;
+
+ /* Test DESCRIBE with a query not producing tuples */
+
+ strcpy(msg, "allocate");
+ exec sql allocate descriptor desc1;
+ exec sql allocate descriptor desc2;
+
+ strcpy(msg, "prepare");
+ exec sql prepare st_id2 FROM :stmt2;
+
+ sqlda1 = sqlda2 = sqlda3 = NULL;
+
+ strcpy(msg, "describe");
+ exec sql describe st_id2 into sql descriptor desc1;
+ exec sql describe st_id2 using sql descriptor desc2;
+
+ exec sql describe st_id2 into descriptor sqlda1;
+ exec sql describe st_id2 using descriptor sqlda2;
+ exec sql describe st_id2 into sqlda3;
+
+ if (sqlda1 == NULL || sqlda2 == NULL || sqlda3 == NULL)
+ exit(1);
+
+ strcpy(msg, "get descriptor");
+ exec sql get descriptor desc1 :count1 = count;
+ exec sql get descriptor desc1 :count2 = count;
+
+ if (!( count1 == count2 &&
+ count1 == sqlda1->sqld &&
+ count1 == sqlda2->sqld &&
+ count1 == sqlda3->sqld))
+ exit(1);
+
+ for (i = 1; i <= count1; i++)
+ {
+ exec sql get descriptor desc1 value :i :field_name1 = name;
+ exec sql get descriptor desc2 value :i :field_name2 = name;
+ printf("%d\n\tfield_name1 '%s'\n\tfield_name2 '%s'\n\t"
+ "sqlda1 '%s'\n\tsqlda2 '%s'\n\tsqlda3 '%s'\n",
+ i, field_name1, field_name2,
+ sqlda1->sqlvar[i-1].sqlname,
+ sqlda2->sqlvar[i-1].sqlname,
+ sqlda3->sqlvar[i-1].sqlname);
+ }
+
+ strcpy(msg, "deallocate");
+ exec sql deallocate descriptor desc1;
+ exec sql deallocate descriptor desc2;
+ free(sqlda1);
+ free(sqlda2);
+ free(sqlda3);
+
+ exec sql deallocate prepare st_id2;
+
+ /* End test */
+
+ strcpy(msg, "drop");
+ exec sql drop table descr_t1;
+
+ strcpy(msg, "commit");
+ exec sql commit;
+
+ strcpy(msg, "disconnect");
+ exec sql disconnect;
+
+ return 0;
+}
diff --git a/src/interfaces/ecpg/test/compat_informix/rfmtdate.pgc b/src/interfaces/ecpg/test/compat_informix/rfmtdate.pgc
new file mode 100644
index 0000000..a147f40
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/rfmtdate.pgc
@@ -0,0 +1,175 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <pgtypes_error.h>
+#include <sqltypes.h>
+
+/*
+ * This file tests various forms of date-input/output by means of
+ * rfmtdate / rdefmtdate / rstrdate
+ */
+
+
+static void
+check_return(int ret);
+
+static void
+date_test_strdate(const char *input)
+{
+ static int i;
+ date d;
+ int r, q;
+ char dbuf[11];
+
+ r = rstrdate(input, &d);
+ printf("r: %d ", r);
+ if (r == 0)
+ {
+ q = rdatestr(d, dbuf);
+ printf("q: %d ", q);
+ if (q == 0)
+ {
+ printf("date %d: %s\n", i++, dbuf);
+ }
+ else
+ printf("\n");
+ }
+ else
+ check_return(r);
+}
+
+static void
+date_test_defmt(const char *fmt, const char *input)
+{
+ static int i;
+ char dbuf[11];
+ date d;
+ int q, r;
+
+ r = rdefmtdate(&d, fmt, input);
+ printf("r: %d ", r);
+ if (r == 0)
+ {
+ q = rdatestr(d, dbuf);
+ printf("q: %d ", q);
+ if (q == 0)
+ {
+ printf("date %d: %s\n", i++, dbuf);
+ }
+ else
+ printf("\n");
+ }
+ else
+ check_return(r);
+}
+
+static void
+date_test_fmt(date d, const char *fmt)
+{
+ static int i;
+ char buf[200];
+ int r;
+
+ r = rfmtdate(d, fmt, buf);
+ printf("r: %d ", r);
+ if (r != 0)
+ check_return(r);
+ else
+ printf("date: %d: %s\n", i++, buf);
+}
+
+
+int
+main(void)
+{
+ short mdy[3] = { 11, 23, 1959 };
+ char dbuf[11];
+ date d;
+ int r;
+
+ ECPGdebug(1, stderr);
+
+ r = rmdyjul(mdy, &d);
+ printf("create: r: %d\n", r);
+ if (r == 0)
+ {
+ rdatestr(d, dbuf);
+ printf("date: %s\n", dbuf);
+ }
+
+ /* input mask is mmddyyyy */
+ date_test_strdate("12031994");
+ date_test_strdate("9.6.1994");
+
+ date_test_fmt(d, "mmddyy");
+ date_test_fmt(d, "ddmmyy");
+ date_test_fmt(d, "yymmdd");
+ date_test_fmt(d, "yy/mm/dd");
+ date_test_fmt(d, "yy mm dd");
+ date_test_fmt(d, "yy.mm.dd");
+ date_test_fmt(d, ".mm.yyyy.dd.");
+ date_test_fmt(d, "mmm. dd, yyyy");
+ date_test_fmt(d, "mmm dd yyyy");
+ date_test_fmt(d, "yyyy dd mm");
+ date_test_fmt(d, "ddd, mmm. dd, yyyy");
+ date_test_fmt(d, "(ddd) mmm. dd, yyyy");
+
+ date_test_defmt("ddmmyy", "21-2-54");
+ date_test_defmt("ddmmyy", "2-12-54");
+ date_test_defmt("ddmmyy", "20111954");
+ date_test_defmt("ddmmyy", "130464");
+ date_test_defmt("mmm.dd.yyyy", "MAR-12-1967");
+ date_test_defmt("yy/mm/dd", "1954, February 3rd");
+ date_test_defmt("mmm.dd.yyyy", "041269");
+ date_test_defmt("yy/mm/dd", "In the year 2525, in the month of July, mankind will be alive on the 28th day");
+ date_test_defmt("dd-mm-yy", "I said on the 28th of July in the year 2525");
+ date_test_defmt("mmm.dd.yyyy", "9/14/58");
+ date_test_defmt("yy/mm/dd", "47/03/29");
+ date_test_defmt("mmm.dd.yyyy", "oct 28 1975");
+ date_test_defmt("mmddyy", "Nov 14th, 1985");
+ /* ok: still contains dd mm yy */
+ date_test_defmt("bladdfoommbaryybong", "20/11/1954");
+ /* 1994 is not a leap year, it accepts the date as 01-03-1994 */
+ date_test_defmt("ddmmyy", "29-02-1994");
+
+ /* ECPG_INFORMIX_ENOTDMY, need "dd", "mm" and "yy" */
+ date_test_defmt("dmy", "20/11/1954");
+
+ /* ECPG_INFORMIX_ENOSHORTDATE */
+ date_test_defmt("ddmmyy", "21254");
+ date_test_defmt("ddmmyy", " 21254 ");
+
+ /* ECPG_INFORMIX_BAD_DAY */
+ date_test_defmt("ddmmyy", "320494");
+
+ /* ECPG_INFORMIX_BAD_MONTH */
+ date_test_defmt("mm-yyyy-dd", "13-1993-21");
+
+ /* ECPG_INFORMIX_BAD_YEAR */
+ /* ??? */
+
+ return 0;
+}
+
+static void
+check_return(int ret)
+{
+ switch(ret)
+ {
+ case ECPG_INFORMIX_ENOTDMY:
+ printf("(ECPG_INFORMIX_ENOTDMY)");
+ break;
+ case ECPG_INFORMIX_ENOSHORTDATE:
+ printf("(ECPG_INFORMIX_ENOSHORTDATE)");
+ break;
+ case ECPG_INFORMIX_BAD_DAY:
+ printf("(ECPG_INFORMIX_BAD_DAY)");
+ break;
+ case ECPG_INFORMIX_BAD_MONTH:
+ printf("(ECPG_INFORMIX_BAD_MONTH)");
+ break;
+ default:
+ printf("(unknown ret: %d)", ret);
+ break;
+ }
+ printf("\n");
+}
diff --git a/src/interfaces/ecpg/test/compat_informix/rfmtlong.pgc b/src/interfaces/ecpg/test/compat_informix/rfmtlong.pgc
new file mode 100644
index 0000000..2ecf09c
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/rfmtlong.pgc
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <pgtypes_error.h>
+#include <sqltypes.h>
+
+/*
+ * This file tests various forms of long-input/output by means of
+ * rfmtlong
+ */
+
+
+static void
+check_return(int ret);
+
+static void
+fmtlong(long lng, const char *fmt)
+{
+ static int i;
+ int r;
+ char buf[30];
+
+ r = rfmtlong(lng, fmt, buf);
+ printf("r: %d ", r);
+ if (r == 0)
+ {
+ printf("%d: %s (fmt was: %s)\n", i++, buf, fmt);
+ }
+ else
+ check_return(r);
+}
+
+int
+main(void)
+{
+ ECPGdebug(1, stderr);
+
+ fmtlong(-8494493, "-<<<<,<<<,<<<,<<<");
+ fmtlong(-8494493, "################");
+ fmtlong(-8494493, "+++$$$$$$$$$$$$$.##");
+ fmtlong(-8494493, "(&,&&&,&&&,&&&.)");
+ fmtlong(-8494493, "<<<<,<<<,<<<,<<<");
+ fmtlong(-8494493, "$************.**");
+ fmtlong(-8494493, "---$************.**");
+ fmtlong(-8494493, "+-+################");
+ fmtlong(-8494493, "abc: ################+-+");
+ fmtlong(-8494493, "+<<<<,<<<,<<<,<<<");
+
+ return 0;
+}
+
+static void
+check_return(int ret)
+{
+ switch(ret)
+ {
+ case ECPG_INFORMIX_ENOTDMY:
+ printf("(ECPG_INFORMIX_ENOTDMY)");
+ break;
+ case ECPG_INFORMIX_ENOSHORTDATE:
+ printf("(ECPG_INFORMIX_ENOSHORTDATE)");
+ break;
+ case ECPG_INFORMIX_BAD_DAY:
+ printf("(ECPG_INFORMIX_BAD_DAY)");
+ break;
+ case ECPG_INFORMIX_BAD_MONTH:
+ printf("(ECPG_INFORMIX_BAD_MONTH)");
+ break;
+ default:
+ printf("(unknown ret: %d)", ret);
+ break;
+ }
+ printf("\n");
+}
diff --git a/src/interfaces/ecpg/test/compat_informix/rnull.pgc b/src/interfaces/ecpg/test/compat_informix/rnull.pgc
new file mode 100644
index 0000000..a6ad35e
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/rnull.pgc
@@ -0,0 +1,97 @@
+#include "sqltypes.h"
+#include <stdlib.h>
+
+$include ../regression;
+$define NUMBER 12;
+
+static void
+test_null(int type, char *ptr)
+{
+ printf("null: %d\n", risnull(type, ptr));
+}
+
+int main(void)
+{
+ $char c[] = "abc";
+ $short s = 17;
+ $int i = -74874;
+ $bool b = 1;
+ $float f = 3.71;
+ $long l = 487444;
+ $double dbl = 404.404;
+ $decimal dec;
+ $date dat;
+ $timestamp tmp;
+
+ ECPGdebug(1, stderr);
+ $whenever sqlerror do sqlprint();
+
+ $connect to REGRESSDB1;
+
+ $create table test(id int, c char(10), s smallint, i int, b bool,
+ f float, l bigint, dbl double precision,
+ dec decimal, dat date, tmp timestamptz);
+ $commit;
+
+ $insert into test (id, c, s, i, b, f, l, dbl) values (
+ 1, :c, :s, :i, :b, :f, :l, :dbl
+ );
+ $commit;
+
+ rsetnull(CCHARTYPE, (char *) c);
+ rsetnull(CSHORTTYPE, (char *) &s);
+ rsetnull(CINTTYPE, (char *) &i);
+ rsetnull(CBOOLTYPE, (char *) &b);
+ rsetnull(CFLOATTYPE, (char *) &f);
+ rsetnull(CLONGTYPE, (char *) &l);
+ rsetnull(CDOUBLETYPE, (char *) &dbl);
+ rsetnull(CDECIMALTYPE, (char *) &dec);
+ rsetnull(CDATETYPE, (char *) &dat);
+ rsetnull(CDTIMETYPE, (char *) &tmp);
+
+ $insert into test (id, c, s, i, b, f, l, dbl, dec, dat, tmp) values (
+ 2, :c, :s, :i, :b, :f, :l, :dbl, :dec, :dat, :tmp
+ );
+ $commit;
+
+ printf("first select\n");
+
+ $select c, s, i, b, f, l, dbl, dec, dat, tmp
+ into :c, :s, :i, :b, :f, :l, :dbl, :dec, :dat, :tmp
+ from test where id = 1;
+
+ test_null(CCHARTYPE, (char *) c);
+ test_null(CSHORTTYPE, (char *) &s);
+ test_null(CINTTYPE, (char *) &i);
+ test_null(CBOOLTYPE, (char *) &b);
+ test_null(CFLOATTYPE, (char *) &f);
+ test_null(CLONGTYPE, (char *) &l);
+ test_null(CDOUBLETYPE, (char *) &dbl);
+ test_null(CDECIMALTYPE, (char *) &dec);
+ test_null(CDATETYPE, (char *) &dat);
+ test_null(CDTIMETYPE, (char *) &tmp);
+
+ printf("second select\n");
+
+ $select c, s, i, b, f, l, dbl, dec, dat, tmp
+ into :c, :s, :i, :b, :f, :l, :dbl, :dec, :dat, :tmp
+ from test where id = 2;
+
+ test_null(CCHARTYPE, (char *) c);
+ test_null(CSHORTTYPE, (char *) &s);
+ test_null(CINTTYPE, (char *) &i);
+ test_null(CBOOLTYPE, (char *) &b);
+ test_null(CFLOATTYPE, (char *) &f);
+ test_null(CLONGTYPE, (char *) &l);
+ test_null(CDOUBLETYPE, (char *) &dbl);
+ test_null(CDECIMALTYPE, (char *) &dec);
+ test_null(CDATETYPE, (char *) &dat);
+ test_null(CDTIMETYPE, (char *) &tmp);
+
+ $drop table test;
+ $commit;
+
+ $close database;
+
+ return 0;
+}
diff --git a/src/interfaces/ecpg/test/compat_informix/sqlda.pgc b/src/interfaces/ecpg/test/compat_informix/sqlda.pgc
new file mode 100644
index 0000000..87e0110
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/sqlda.pgc
@@ -0,0 +1,250 @@
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+exec sql include ../regression;
+
+exec sql include sqlda.h;
+exec sql include sqltypes.h;
+
+exec sql whenever sqlerror stop;
+
+/* These shouldn't be under DECLARE SECTION */
+sqlda_t *inp_sqlda, *outp_sqlda;
+
+static void
+dump_sqlda(sqlda_t *sqlda)
+{
+ int i;
+
+ if (sqlda == NULL)
+ {
+ printf("dump_sqlda called with NULL sqlda\n");
+ return;
+ }
+
+ for (i = 0; i < sqlda->sqld; i++)
+ {
+ if (sqlda->sqlvar[i].sqlind && *(sqlda->sqlvar[i].sqlind) == -1)
+ printf("name sqlda descriptor: '%s' value NULL'\n", sqlda->sqlvar[i].sqlname);
+ else
+ switch (sqlda->sqlvar[i].sqltype)
+ {
+ case SQLCHAR:
+ printf("name sqlda descriptor: '%s' value '%s'\n", sqlda->sqlvar[i].sqlname, sqlda->sqlvar[i].sqldata);
+ break;
+ case SQLINT:
+ printf("name sqlda descriptor: '%s' value %d\n", sqlda->sqlvar[i].sqlname, *(int *)sqlda->sqlvar[i].sqldata);
+ break;
+ case SQLFLOAT:
+ printf("name sqlda descriptor: '%s' value %f\n", sqlda->sqlvar[i].sqlname, *(double *)sqlda->sqlvar[i].sqldata);
+ break;
+ case SQLDECIMAL:
+ {
+ char val[64];
+ dectoasc((dec_t *)sqlda->sqlvar[i].sqldata, val, 64, -1);
+ printf("name sqlda descriptor: '%s' value DECIMAL '%s'\n", sqlda->sqlvar[i].sqlname, val);
+ break;
+ }
+ }
+ }
+}
+
+int
+main (void)
+{
+exec sql begin declare section;
+ char *stmt1 = "SELECT * FROM t1";
+ char *stmt2 = "SELECT * FROM t1 WHERE id = ?";
+ int rec;
+ int id;
+exec sql end declare section;
+
+ char msg[128];
+
+ ECPGdebug(1, stderr);
+
+ strcpy(msg, "connect");
+ exec sql connect to REGRESSDB1 as regress1;
+
+ strcpy(msg, "set");
+ exec sql set datestyle to iso;
+
+ strcpy(msg, "create");
+ exec sql create table t1(
+ id integer,
+ t text,
+ d1 numeric,
+ d2 float8,
+ c char(10));
+
+ strcpy(msg, "insert");
+ exec sql insert into t1 values
+ (1, 'a', 1.0, 1, 'a'),
+ (2, null, null, null, null),
+ (4, 'd', 4.0, 4, 'd');
+
+ strcpy(msg, "commit");
+ exec sql commit;
+
+ /* SQLDA test for getting all records from a table */
+
+ outp_sqlda = NULL;
+
+ strcpy(msg, "prepare");
+ exec sql prepare st_id1 from :stmt1;
+
+ strcpy(msg, "declare");
+ exec sql declare mycur1 cursor for st_id1;
+
+ strcpy(msg, "open");
+ exec sql open mycur1;
+
+ exec sql whenever not found do break;
+
+ rec = 0;
+ while (1)
+ {
+ strcpy(msg, "fetch");
+ exec sql fetch 1 from mycur1 into descriptor outp_sqlda;
+
+ printf("FETCH RECORD %d\n", ++rec);
+ dump_sqlda(outp_sqlda);
+ }
+
+ exec sql whenever not found continue;
+
+ strcpy(msg, "close");
+ exec sql close mycur1;
+
+ strcpy(msg, "deallocate");
+ exec sql deallocate prepare st_id1;
+
+ free(outp_sqlda);
+
+ /* SQLDA test for getting all records from a table
+ using the Informix-specific FETCH ... USING DESCRIPTOR
+ */
+
+ outp_sqlda = NULL;
+
+ strcpy(msg, "prepare");
+ exec sql prepare st_id2 from :stmt1;
+
+ strcpy(msg, "declare");
+ exec sql declare mycur2 cursor for st_id2;
+
+ strcpy(msg, "open");
+ exec sql open mycur2;
+
+ exec sql whenever not found do break;
+
+ rec = 0;
+ while (1)
+ {
+ strcpy(msg, "fetch");
+ exec sql fetch from mycur2 using descriptor outp_sqlda;
+
+ printf("FETCH RECORD %d\n", ++rec);
+ dump_sqlda(outp_sqlda);
+ }
+
+ exec sql whenever not found continue;
+
+ strcpy(msg, "close");
+ exec sql close mycur2;
+
+ strcpy(msg, "deallocate");
+ exec sql deallocate prepare st_id2;
+
+ free(outp_sqlda);
+
+ /* SQLDA test for getting one record using an input descriptor */
+
+ /* Input sqlda has to be built manually */
+ inp_sqlda = (sqlda_t *)malloc(sizeof(sqlda_t));
+ memset(inp_sqlda, 0, sizeof(sqlda_t));
+ inp_sqlda->sqld = 1;
+ inp_sqlda->sqlvar = malloc(sizeof(sqlvar_t));
+ memset(inp_sqlda->sqlvar, 0, sizeof(sqlvar_t));
+
+ inp_sqlda->sqlvar[0].sqltype = SQLINT;
+ inp_sqlda->sqlvar[0].sqldata = (char *)&id;
+
+ printf("EXECUTE RECORD 4\n");
+
+ id = 4;
+
+ outp_sqlda = NULL;
+
+ strcpy(msg, "prepare");
+ exec sql prepare st_id3 FROM :stmt2;
+
+ strcpy(msg, "execute");
+ exec sql execute st_id3 using descriptor inp_sqlda into descriptor outp_sqlda;
+
+ dump_sqlda(outp_sqlda);
+
+ strcpy(msg, "deallocate");
+ exec sql deallocate prepare st_id3;
+
+ free(inp_sqlda->sqlvar);
+ free(inp_sqlda);
+ free(outp_sqlda);
+
+ /* SQLDA test for getting one record using an input descriptor
+ * on a named connection
+ */
+
+ exec sql connect to REGRESSDB1 as con2;
+
+ /* Input sqlda has to be built manually */
+ inp_sqlda = (sqlda_t *)malloc(sizeof(sqlda_t));
+ memset(inp_sqlda, 0, sizeof(sqlda_t));
+ inp_sqlda->sqld = 1;
+ inp_sqlda->sqlvar = malloc(sizeof(sqlvar_t));
+ memset(inp_sqlda->sqlvar, 0, sizeof(sqlvar_t));
+
+ inp_sqlda->sqlvar[0].sqltype = SQLINT;
+ inp_sqlda->sqlvar[0].sqldata = (char *)&id;
+
+ printf("EXECUTE RECORD 4\n");
+
+ id = 4;
+
+ outp_sqlda = NULL;
+
+ strcpy(msg, "prepare");
+ exec sql at con2 prepare st_id4 FROM :stmt2;
+
+ strcpy(msg, "execute");
+ exec sql at con2 execute st_id4 using descriptor inp_sqlda into descriptor outp_sqlda;
+
+ dump_sqlda(outp_sqlda);
+
+ strcpy(msg, "commit");
+ exec sql at con2 commit;
+
+ strcpy(msg, "deallocate");
+ exec sql deallocate prepare st_id4;
+
+ free(inp_sqlda->sqlvar);
+ free(inp_sqlda);
+ free(outp_sqlda);
+
+ strcpy(msg, "disconnect");
+ exec sql disconnect con2;
+
+ /* End test */
+
+ strcpy(msg, "drop");
+ exec sql drop table t1;
+
+ strcpy(msg, "commit");
+ exec sql commit;
+
+ strcpy(msg, "disconnect");
+ exec sql disconnect;
+
+ return 0;
+}
diff --git a/src/interfaces/ecpg/test/compat_informix/test_informix.pgc b/src/interfaces/ecpg/test/compat_informix/test_informix.pgc
new file mode 100644
index 0000000..0911efe
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/test_informix.pgc
@@ -0,0 +1,95 @@
+#include "sqltypes.h"
+#include <stdlib.h>
+
+$include ../regression;
+$define NUMBER 12;
+
+static void openit(void);
+static void dosqlprint(void) {
+ printf("doSQLprint: Error: %s\n", sqlca.sqlerrm.sqlerrmc);
+}
+
+int main(void)
+{
+ $int i = 14, loopcount;
+ $decimal j, m, n;
+ $string c[10];
+
+ ECPGdebug(1, stderr);
+ $whenever sqlerror do dosqlprint();
+
+ $connect to REGRESSDB1;
+ if (sqlca.sqlcode != 0) exit(1);
+
+ $create table test(i int primary key, j int, c text);
+
+ /* this INSERT works */
+ rsetnull(CDECIMALTYPE, (char *)&j);
+ $insert into test (i, j, c) values (7, :j, 'test ');
+ $commit;
+
+ /* this INSERT should fail because i is a unique column */
+ $insert into test (i, j, c) values (7, NUMBER, 'a');
+ printf("INSERT: %ld=%s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
+ if (sqlca.sqlcode != 0) $rollback;
+
+ $insert into test (i, j, c) values (:i, 1, 'a ');
+ $commit;
+
+ /* this will fail (more than one row in subquery) */
+ $select i from test where j=(select j from test);
+ $rollback;
+
+ /* this however should be ok */
+ $select i from test where j=(select j from test order by i limit 1);
+ printf("SELECT: %ld=%s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
+ if (sqlca.sqlcode != 0) $rollback;
+
+ sqlca.sqlcode = 100;
+ $declare c cursor for select * from test where i <= :i;
+ printf ("%ld\n", sqlca.sqlcode);
+ openit();
+
+ deccvint(0, &j);
+
+ for (loopcount = 0; loopcount < 100; loopcount++)
+ {
+ $fetch forward c into :i, :j, :c;
+ if (sqlca.sqlcode == 100) break;
+
+ if (risnull(CDECIMALTYPE, (char *)&j))
+ printf("%d NULL\n", i);
+ else
+ {
+ int a;
+
+ dectoint(&j, &a);
+ printf("%d %d \"%s\"\n", i, a, c);
+ }
+ }
+
+ deccvint(7, &j);
+ deccvint(14, &m);
+ decadd(&j, &m, &n);
+ $delete from test where i= :n::decimal;
+ printf("DELETE: %ld\n", sqlca.sqlcode);
+
+ $select 1 from test where i=14;
+ printf("Exists: %ld\n", sqlca.sqlcode);
+
+ $select 1 from test where i=147;
+ printf("Does not exist: %ld\n", sqlca.sqlcode);
+
+ $commit;
+ $drop table test;
+ $commit;
+
+ $close database;
+
+ return 0;
+}
+
+static void openit(void)
+{
+ $open c;
+}
diff --git a/src/interfaces/ecpg/test/compat_informix/test_informix2.pgc b/src/interfaces/ecpg/test/compat_informix/test_informix2.pgc
new file mode 100644
index 0000000..224f2da
--- /dev/null
+++ b/src/interfaces/ecpg/test/compat_informix/test_informix2.pgc
@@ -0,0 +1,122 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "sqltypes.h"
+
+EXEC SQL include sqlca.h;
+EXEC SQL include ../regression;
+EXEC SQL DEFINE MAXDBLEN 30;
+
+/* Check SQLCODE, and produce a "standard error" if it's wrong! */
+static void sql_check(const char *fn, const char *caller, int ignore)
+{
+ char errorstring[255];
+
+ if (SQLCODE == ignore)
+ return;
+ else
+ {
+ if (SQLCODE != 0)
+ {
+
+ sprintf(errorstring, "**SQL error %ld doing '%s' in function '%s'. [%s]",
+ SQLCODE, caller, fn, sqlca.sqlerrm.sqlerrmc);
+ fprintf(stderr, "%s", errorstring);
+ printf("%s\n", errorstring);
+
+ /* attempt a ROLLBACK */
+ EXEC SQL rollback;
+
+ if (SQLCODE == 0)
+ {
+ sprintf(errorstring, "Rollback successful.\n");
+ } else {
+ sprintf(errorstring, "Rollback failed with code %ld.\n", SQLCODE);
+ }
+
+ fprintf(stderr, "%s", errorstring);
+ printf("%s\n", errorstring);
+
+ exit(1);
+ }
+ }
+}
+
+int main(void)
+{
+ EXEC SQL BEGIN DECLARE SECTION;
+ int c;
+ timestamp d;
+ timestamp e;
+ timestamp maxd;
+ char dbname[30];
+ EXEC SQL END DECLARE SECTION;
+
+ interval *intvl;
+
+ EXEC SQL whenever sqlerror stop;
+
+ ECPGdebug(1, stderr);
+
+ strcpy(dbname, "ecpg1_regression");
+ EXEC SQL connect to :dbname;
+ sql_check("main", "connect", 0);
+
+ EXEC SQL SET DateStyle TO 'DMY';
+
+ EXEC SQL create table history (customerid integer, timestamp timestamp without time zone, action_taken char(5), narrative varchar(100));
+ sql_check("main", "create", 0);
+
+ EXEC SQL insert into history
+ (customerid, timestamp, action_taken, narrative)
+ values(1, '2003-05-07 13:28:34 CEST', 'test', 'test');
+ sql_check("main", "insert", 0);
+
+ EXEC SQL select max(timestamp)
+ into :maxd
+ from history;
+ sql_check("main", "select max", 100);
+
+ EXEC SQL select customerid, timestamp
+ into :c, :d
+ from history
+ where timestamp = :maxd
+ limit 1;
+ sql_check("main", "select", 0);
+
+ printf("Read in customer %d\n", c);
+
+ intvl = PGTYPESinterval_from_asc("1 day 2 hours 24 minutes 65 seconds", NULL);
+ PGTYPEStimestamp_add_interval(&d, intvl, &e);
+ free(intvl);
+ c++;
+
+ EXEC SQL insert into history
+ (customerid, timestamp, action_taken, narrative)
+ values(:c, :e, 'test', 'test');
+ sql_check("main", "update", 0);
+
+ EXEC SQL commit;
+
+ EXEC SQL drop table history;
+ sql_check("main", "drop", 0);
+
+ EXEC SQL commit;
+
+ EXEC SQL disconnect;
+ sql_check("main", "disconnect", 0);
+
+ printf("All OK!\n");
+
+ exit(0);
+
+/*
+ Table "public.history"
+ Column | Type | Nullable
+--------------+-----------------------------+----------
+ customerid | integer | not null
+ timestamp | timestamp without time zone | not null
+ action_taken | character(5) | not null
+ narrative | character varying(100) |
+*/
+
+}