]> granicus.if.org Git - php/commitdiff
moved odbc into ext/
authorStig Bakken <ssb@php.net>
Mon, 19 Apr 1999 15:04:11 +0000 (15:04 +0000)
committerStig Bakken <ssb@php.net>
Mon, 19 Apr 1999 15:04:11 +0000 (15:04 +0000)
Makefile.in
configure.in.in
ext/odbc/Makefile.am [new file with mode: 0644]
ext/odbc/config.m4 [new file with mode: 0644]
ext/odbc/odbc.c [new file with mode: 0644]
ext/odbc/php3_odbc.h [new file with mode: 0644]
ext/odbc/php3_velocis.h [new file with mode: 0644]
ext/odbc/setup.stub [new file with mode: 0644]
ext/odbc/velocis.c [new file with mode: 0644]
internal_functions.c
setup

index 526b8cd2cf67ccfbb0c5b0e43ca115cef97bcf4b..07dd3f56874bea7ec5c90eb572f30adbc18a8b18 100644 (file)
@@ -68,22 +68,21 @@ OBJS = main.o internal_functions.o snprintf.o php3_sprintf.o \
        safe_mode.o fopen-wrappers.o php3_realpath.o alloca.o output.o \
        php_ini.o
 
-FUNCTIONS_SOURCE = functions/adabasd.c functions/apache.c functions/fhttpd.c \
+FUNCTIONS_SOURCE = functions/apache.c functions/fhttpd.c \
        functions/crypt.c functions/db.c functions/dl.c functions/filepro.c \
        functions/head.c functions/imap.c functions/mime.c \
        functions/msql.c functions/mysql.c \
        functions/oracle.c functions/oci8.c functions/pgsql.c \
-       functions/post.c functions/solid.c functions/sybase.c \
+       functions/post.c functions/sybase.c \
        functions/sybase-ct.c @BCMATH_SRC@ functions/xml.c \
-       functions/unified_odbc.c functions/ldap.c functions/velocis.c \
-       functions/zlib.c functions/COM.c functions/ifx.c \
+       functions/ldap.c functions/zlib.c functions/COM.c functions/ifx.c \
        functions/pdf.c functions/hw.c functions/hg_comm.c functions/dlist.c \
        functions/fdf.c functions/snmp.c functions/interbase.c \
        functions/sysvsem.c functions/sysvshm.c functions/dav.c
 
 FUNCTIONS = $(FUNCTIONS_SOURCE:.c=.o)
 PHPLIBS = -L@top_srcdir@/libzend -lzend -Lext -lphpext
-LIBS = $(PHPLIBS) $(EXTRA_LIBS) @SYBASE_CT_LFLAGS@ @SYBASE_CT_LIBS@ @FHTTPD_LIB@ @REGEX_LIB@ @DBM_LIB@ @ORACLE_LFLAGS@ @ORACLE_LIBS@ @IODBC_LFLAGS@ @IODBC_LIBS@ @SYBASE_LFLAGS@ @SYBASE_LIBS@ @SYBASE_CT_LFLAGS@ @SYBASE_CT_LIBS@ @MYSQL_LFLAGS@ @MYSQL_LIBS@ @MSQL_LFLAGS@ @MSQL_LIBS@ @ADA_LFLAGS@ @ADA_LIBS@ @SOLID_LIBS@ @EMPRESS_LIBS@ @OPENLINK_LFLAGS@ @OPENLINK_LIBS@ @PGSQL_LFLAGS@ @PGSQL_LIBS@ @LDAP_LFLAGS@ @LDAP_LIBS@ @VELOCIS_LIBS@ @CODBC_LFLAGS@ @CODBC_LIBS@ @IMAP_LIBS@ @ZLIB_LIBS@ @PDFLIB_LIBS@ @FDFLIB_LIBS@ @IFX_LFLAGS@ @IFX_LIBS@ @SNMP_LFLAGS@ @SNMP_LIBS@ @IBASE_LFLAGS@ @IBASE_LIBS@ @XML_LIBS@ @LIBS@
+LIBS = $(PHPLIBS) $(EXTRA_LIBS) @SYBASE_CT_LFLAGS@ @SYBASE_CT_LIBS@ @FHTTPD_LIB@ @REGEX_LIB@ @DBM_LIB@ @ORACLE_LFLAGS@ @ORACLE_LIBS@ @SYBASE_LFLAGS@ @SYBASE_LIBS@ @SYBASE_CT_LFLAGS@ @SYBASE_CT_LIBS@ @MYSQL_LFLAGS@ @MYSQL_LIBS@ @MSQL_LFLAGS@ @MSQL_LIBS@ @PGSQL_LFLAGS@ @PGSQL_LIBS@ @LDAP_LFLAGS@ @LDAP_LIBS@ @IMAP_LIBS@ @ZLIB_LIBS@ @PDFLIB_LIBS@ @FDFLIB_LIBS@ @IFX_LFLAGS@ @IFX_LIBS@ @SNMP_LFLAGS@ @SNMP_LIBS@ @IBASE_LFLAGS@ @IBASE_LIBS@ @XML_LIBS@ @LIBS@
 
 all: $(BINNAME)
 
index af10ae83c47f7bc1074fbd2d2a97dead35a46f11..40c409180c2e01c856f89dfe6010cac4704f0951 100644 (file)
@@ -1023,99 +1023,6 @@ AC_SUBST(ORACLE_HOME)
 AC_SUBST(ORACLE_VERSION)
 
 
-AC_MSG_CHECKING(for iODBC support)
-AC_ARG_WITH(iodbc,
-[  --with-iodbc[=DIR]      Include iODBC support.  DIR is the iODBC base
-                          install directory, defaults to /usr/local.],
-[
-       if test "$withval" = "yes"; then
-         withval=/usr/local
-       fi
-       if test "$withval" != "no"; then
-
-         IODBC_INCDIR=$withval/include
-         IODBC_LIBDIR=$withval/lib
-         IODBC_LFLAGS=-L$IODBC_LIBDIR
-         IODBC_INCLUDE=-I$IODBC_INCDIR
-         IODBC_LIBS=-liodbc
-      UODBC_DEFAULT=yes
-
-         AC_DEFINE(HAVE_IODBC)
-
-         AC_MSG_RESULT(yes)
-
-       fi
-],[
-       AC_MSG_RESULT(no)
-])
-AC_SUBST(IODBC_LIBS)
-AC_SUBST(IODBC_LFLAGS)
-dnl## AC_SUBST(IODBC_INCLUDE)
-INCLUDES="$INCLUDES $IODBC_INCLUDE"
-
-
-AC_MSG_CHECKING(for OpenLink ODBC support)
-AC_ARG_WITH(openlink,
-[  --with-openlink[=DIR]   Include OpenLink ODBC support.  DIR is the
-                          OpenLink base install directory, defaults to
-                          /usr/local/openlink.],
-[
-       if test "$withval" = "yes"; then
-         withval=/usr/local/openlink
-       fi
-       if test "$withval" != "no"; then
-
-         OPENLINK_INCDIR=$withval/odbcsdk/include
-         OPENLINK_LIBDIR=$withval/odbcsdk/lib
-         OPENLINK_LFLAGS=-L$OPENLINK_LIBDIR
-         OPENLINK_INCLUDE=-I$OPENLINK_INCDIR
-         OPENLINK_LIBS=-liodbc
-      UODBC_DEFAULT=yes
-
-         AC_DEFINE(HAVE_OPENLINK)
-
-         AC_MSG_RESULT(yes)
-
-       fi
-],[
-       AC_MSG_RESULT(no)
-])
-AC_SUBST(OPENLINK_LIBS)
-AC_SUBST(OPENLINK_LFLAGS)
-dnl## AC_SUBST(OPENLINK_INCLUDE)
-INCLUDES="$INCLUDES $OPENLINK_INCLUDE"
-
-
-AC_MSG_CHECKING(for Adabas support)
-AC_ARG_WITH(adabas,
-[  --with-adabas[=DIR]     Include Adabas D support.  DIR is the Adabas base
-                          install directory, defaults to /usr/local.],
-[
-  if test "$withval" = "yes"; then
-    withval=/usr/local
-  fi
-  if test "$withval" != "no"; then
-    ADA_INCDIR=$withval/incl
-    ADA_LIBDIR=$withval/lib
-    ADA_LFLAGS=-L$ADA_LIBDIR
-    ADA_INCLUDE=-I$ADA_INCDIR
-    ADA_LIBS="${ADA_LIBDIR}/odbclib.a -lsqlrte -lsqlptc"
-    UODBC_DEFAULT=yes
-
-    AC_DEFINE(HAVE_ADABAS)
-    AC_MSG_RESULT(yes)
-  else
-    AC_MSG_RESULT(no)
-  fi
-],[
-  AC_MSG_RESULT(no)
-])
-AC_SUBST(ADA_LIBS)
-AC_SUBST(ADA_LFLAGS)
-dnl## AC_SUBST(ADA_INCLUDE)
-INCLUDES="$INCLUDES $ADA_INCLUDE"
-
-
 AC_MSG_CHECKING(for Sybase support)
 AC_ARG_WITH(sybase,
 [  --with-sybase[=DIR]     Include Sybase-DB support.  DIR is the Sybase home
@@ -1309,72 +1216,6 @@ dnl## AC_SUBST(PGSQL_INCLUDE)
 INCLUDES="$INCLUDES $PGSQL_INCLUDE"
 
 
-AC_MSG_CHECKING(for Solid support)
-AC_ARG_WITH(solid,
-[  --with-solid[=DIR]      Include Solid support.  DIR is the Solid base
-                          install directory, defaults to /usr/local/solid],
-[
-  if test "$withval" != "no"; then
-       if test "$withval" = "yes"; then
-           SOLID_INCDIR=/usr/local/solid/include
-               SOLID_LIBDIR=/usr/local/solid/lib
-       else
-               SOLID_INCDIR=$withval/include
-               SOLID_LIBDIR=$withval/lib
-       fi
-    SOLID_INCLUDE=-I$SOLID_INCDIR
-    UODBC_DEFAULT=yes
-
-    AC_DEFINE(HAVE_SOLID)
-
-    AC_MSG_RESULT(yes)
-  else
-       AC_MSG_RESULT(no)
-  fi
-],[
-  AC_MSG_RESULT(no)
-])
-if test "$SOLID_LIBDIR" != ""; then
-  AC_FIND_SOLID_LIBS($SOLID_LIBDIR)
-fi
-dnl## AC_SUBST(SOLID_INCLUDE)
-AC_SUBST(SOLID_LIBS)
-INCLUDES="$INCLUDES $SOLID_INCLUDE"
-
-
-AC_MSG_CHECKING(for Empress support)
-AC_ARG_WITH(empress,
-[  --with-empress[=DIR]    Include Empress support.  DIR is the Empress base
-                          install directory, defaults to \$EMPRESSPATH],
-[
-  if test "$withval" != "no"; then
-        if test "$withval" = "yes"; then
-                EMPRESS_INCDIR=$EMPRESSPATH/odbccl/include
-                EMPRESS_LIBDIR=$EMPRESSPATH/odbccl/lib
-        else
-                EMPRESS_INCDIR=$withval/include
-                EMPRESS_LIBDIR=$withval/lib
-        fi
-    EMPRESS_INCLUDE=-I$EMPRESS_INCDIR
-    UODBC_DEFAULT=yes
-
-    AC_DEFINE(HAVE_EMPRESS)
-
-    AC_MSG_RESULT(yes)
-  else
-        AC_MSG_RESULT(no)
-  fi
-],[
-  AC_MSG_RESULT(no)
-])
-if test "$EMPRESS_LIBDIR" != ""; then
-  AC_FIND_EMPRESS_LIBS($EMPRESS_LIBDIR)
-fi
-AC_SUBST(EMPRESS_LIBS)
-dnl## AC_SUBST(EMPRESS_INCLUDE)
-INCLUDES="$INCLUDES $EMPRESS_INCLUDE"
-
-
 AC_MSG_CHECKING(for LDAP support)
 AC_ARG_WITH(ldap,
 [  --with-ldap[=DIR]       Include LDAP support.  DIR is the LDAP base
@@ -1441,48 +1282,6 @@ dnl## AC_SUBST(SNMP_INCLUDE)
 INCLUDES="$INCLUDES $SNMP_INCLUDE"
 
 
-AC_MSG_CHECKING(for Velocis support)
-AC_ARG_WITH(velocis,
-[  --with-velocis[=DIR]    Include Velocis support.  DIR is the Velocis
-                         base install directory, defaults to /usr/local/velocis.],
-[
-  if test "$withval" != "no"; then
-    VELOCIS_OS=`uname`
-       if test "$withval" = "yes"; then
-           VELOCIS_INCDIR=/usr/local/velocis/include
-               VELOCIS_LIBDIR=/usr/local/velocis
-       else
-               VELOCIS_INCDIR=$withval/include
-               VELOCIS_LIBDIR=$withval
-       fi
-    VELOCIS_INCLUDE=-I$VELOCIS_INCDIR
-    VELOCIS_LIBDIR="$VELOCIS_LIBDIR/bin"
-    VELOCIS_LIBS="-l_rdbc -l_sql"
-    if test $VELOCIS_OS = "FreeBSD"; then
-       VELOCIS_LIBS="$VELOCIS_LIBDIR/../lib/rdscli.a -lcompat"
-    fi
-    if test $VELOCIS_OS = "BSD/OS"; then
-       VELOCIS_LIBS="$VELOCIS_LIBDIR/../lib/rdscli.a -lcompat"
-    fi
-    old_CFLAGS=$CFLAGS; old_LDFLAGS=$LDFLAGS
-       CFLAGS="$CFLAGS $VELOCIS_INCLUDE"
-       LDFLAGS="$LDFLAGS $VELOCIS_LIBS"
-    UODBC_DEFAULT=yes
-
-    AC_DEFINE(HAVE_VELOCIS)
-    AC_MSG_RESULT(yes)
-  else
-       AC_MSG_RESULT(no)
-  fi
-],[
-  AC_MSG_RESULT(no)
-])
-AC_SUBST(VELOCIS_LIBS)
-AC_SUBST(VELOCIS_LFLAGS)
-dnl## AC_SUBST(VELOCIS_INCLUDE)
-INCLUDES="$INCLUDES $VELOCIS_INCLUDE"
-
-
 AC_MSG_CHECKING(for Informix support)
 AC_ARG_WITH(informix,
 [  --with-informix[=DIR]   Include Informix support.  DIR is the Informix base
@@ -1587,46 +1386,6 @@ dnl## AC_SUBST(IBASE_INCLUDE)
 INCLUDES="$INCLUDES $IBASE_INCLUDE"
 
 
-AC_MSG_CHECKING(for a custom ODBC support)
-AC_ARG_WITH(custom-odbc,
-[  --with-custom-odbc[=DIR]      Include a user defined ODBC support.
-                          The DIR is ODBC install base directory, 
-                          which defaults to /usr/local.
-                          Make sure to define CUSTOM_ODBC_LIBS and
-                          have some odbc.h in your include dirs.
-                          E.g., you should define following for 
-                          Sybase SQL Anywhere 5.5.00 on QNX, prior to
-                          run configure script:
-                              CFLAGS=\"-DODBC_QNX -DSQLANY_BUG\"
-                              LDFLAGS=-lunix
-                              CUSTOM_ODBC_LIBS=\"-ldblib -lodbc\".],
-[
-       if test "$withval" = "yes"; then
-         withval=/usr/local
-       fi
-       if test "$withval" != "no"; then
-
-         CODBC_INCDIR=$withval/include
-         CODBC_LIBDIR=$withval/lib
-         CODBC_LFLAGS=-L$CODBC_LIBDIR
-         CODBC_INCLUDE=-I$CODBC_INCDIR
-         CODBC_LIBS=$CUSTOM_ODBC_LIBS
-      UODBC_DEFAULT=yes
-
-         AC_DEFINE(HAVE_CODBC)
-
-         AC_MSG_RESULT(yes)
-
-       fi
-],[
-       AC_MSG_RESULT(no)
-])
-AC_SUBST(CODBC_LIBS)
-AC_SUBST(CODBC_LFLAGS)
-dnl## AC_SUBST(CODBC_INCLUDE)
-INCLUDES="$INCLUDES $CODBC_INCLUDE"
-
-
 AC_MSG_CHECKING(for Hyperwave support)
 AC_ARG_WITH(hyperwave,
 [  --with-hyperwave        Include Hyperwave support],
@@ -1805,43 +1564,6 @@ AC_ARG_WITH(mod-dav,
 AC_SUBST(MOD_DAV_CFLAGS)
 
 
-AC_MSG_CHECKING(whether to enable unified ODBC support)
-AC_ARG_ENABLE(unified-odbc,
-[  --disable-unified-odbc  Disable unified ODBC support. Only applicable if
-                          iODBC, Adabas, Solid, Velocis or a custom ODBC
-                          interface is enabled.],
-[
-  if test "$enableval" = "no"; then
-    AC_DEFINE(HAVE_UODBC, 0)
-    AC_MSG_RESULT(no)
-  else
-    if test "$with_solid" != ""; then
-      UODBC_TYPE=solid
-    elif test "$with_iodbc" != ""; then
-      UODBC_TYPE=iodbc
-    elif test "$with_adabas" != ""; then
-      UODBC_TYPE=adabas
-    elif test "$with_velocis" != ""; then
-      UODBC_TYPE=velocis
-    elif test "$with_custom_odbc" != ""; then
-      UODBC_TYPE=custom
-    else
-      AC_MSG_ERROR([no ODBC library!  Include Solid, iODBC, Velocis, Adabas D or a custom ODBC support.])
-    fi
-    AC_DEFINE(HAVE_UODBC, 1)
-    AC_MSG_RESULT([yes, using $UODBC_TYPE])
-  fi
-],[
-  if test "$UODBC_DEFAULT" = "yes"; then
-       AC_DEFINE(HAVE_UODBC, 1)
-       AC_MSG_RESULT(yes)
-  else
-       AC_DEFINE(HAVE_UODBC, 0)
-       AC_MSG_RESULT(no)
-  fi
-])
-
-
 AC_MSG_CHECKING(whether to enable System V semaphore support)
 AC_ARG_ENABLE(sysvsem,
 [  --enable-sysvsem        Enable System V semaphore support.],
diff --git a/ext/odbc/Makefile.am b/ext/odbc/Makefile.am
new file mode 100644 (file)
index 0000000..9f78717
--- /dev/null
@@ -0,0 +1,4 @@
+## Process this file with automake to produce Makefile.in
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_odbc.a
+libphpext_odbc_a_SOURCES=odbc.c velocis.c
diff --git a/ext/odbc/config.m4 b/ext/odbc/config.m4
new file mode 100644 (file)
index 0000000..8fee81c
--- /dev/null
@@ -0,0 +1,217 @@
+dnl ODBC_INCDIR
+dnl ODBC_INCLUDE
+dnl ODBC_LIBDIR
+dnl ODBC_LIBS
+dnl ODBC_LFLAGS
+
+if test -z "$ODBC_TYPE"; then
+AC_MSG_CHECKING(for Adabas support)
+AC_ARG_WITH(adabas,
+[  --with-adabas[=DIR]     Include Adabas D support.  DIR is the Adabas base
+                          install directory, defaults to /usr/local.],
+[
+  if test "$withval" = "yes"; then
+    withval=/usr/local
+  fi
+  if test "$withval" != "no"; then
+    ODBC_INCDIR=$withval/incl
+    ODBC_LIBDIR=$withval/lib
+    ODBC_LFLAGS=-L$ADA_LIBDIR
+    ODBC_INCLUDE=-I$ADA_INCDIR
+    ODBC_LIBS="${ADA_LIBDIR}/odbclib.a -lsqlrte -lsqlptc"
+    ODBC_TYPE=adabas
+    AC_DEFINE(HAVE_ADABAS)
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+  fi
+],[
+  AC_MSG_RESULT(no)
+])
+fi
+
+if test -z "$ODBC_TYPE"; then
+AC_MSG_CHECKING(for Solid support)
+AC_ARG_WITH(solid,
+[  --with-solid[=DIR]      Include Solid support.  DIR is the Solid base
+                         install directory, defaults to /usr/local/solid],
+[
+  if test "$withval" = "yes"; then
+    withval=/usr/local/solid
+  fi
+  if test "$withval" != "no"; then
+    ODBC_INCDIR=$withval/include
+    ODBC_LIBDIR=$withval/lib
+         ODBC_INCLUDE=-I$ODBC_INCDIR
+         ODBC_TYPE=solid
+         AC_DEFINE(HAVE_SOLID)
+         AC_MSG_RESULT(yes)
+         AC_FIND_SOLID_LIBS($SOLID_LIBDIR)
+  else
+         AC_MSG_RESULT(no)
+  fi
+],[
+  AC_MSG_RESULT(no)
+])
+fi
+
+if test -z "$ODBC_TYPE"; then
+AC_MSG_CHECKING(for Empress support)
+AC_ARG_WITH(empress,
+[  --with-empress[=DIR]    Include Empress support.  DIR is the Empress base
+                          install directory, defaults to \$EMPRESSPATH],
+[
+  if test "$withval" != "no"; then
+    if test "$withval" = "yes"; then
+      ODBC_INCDIR=$EMPRESSPATH/odbccl/include
+      ODBC_LIBDIR=$EMPRESSPATH/odbccl/lib
+    else
+      ODBC_INCDIR=$withval/include
+      ODBC_LIBDIR=$withval/lib
+    fi
+    ODBC_INCLUDE=-I$ODBC_INCDIR
+    ODBC_TYPE=empress
+    AC_DEFINE(HAVE_EMPRESS)
+    AC_MSG_RESULT(yes)
+    AC_FIND_EMPRESS_LIBS($ODBC_LIBDIR)
+  else
+    AC_MSG_RESULT(no)
+  fi
+],[
+  AC_MSG_RESULT(no)
+])
+fi
+
+if test -z "$ODBC_TYPE"; then
+AC_MSG_CHECKING(for Velocis support)
+AC_ARG_WITH(velocis,
+[  --with-velocis[=DIR]    Include Velocis support.  DIR is the Velocis
+                          base install directory, defaults to /usr/local/velocis.],
+[
+  if test "$withval" != "no"; then
+    if test "$withval" = "yes"; then
+      ODBC_INCDIR=/usr/local/velocis/include
+      ODBC_LIBDIR=/usr/local/velocis
+    else
+      ODBC_INCDIR=$withval/include
+      ODBC_LIBDIR=$withval
+    fi
+    ODBC_INCLUDE=-I$ODBC_INCDIR
+    ODBC_LIBDIR="$ODBC_LIBDIR/bin"
+    case `uname` in
+      FreeBSD|BSD/OS)
+        ODBC_LIBS="$ODBC_LIBDIR/../lib/rdscli.a -lcompat";;
+      *)
+        ODBC_LIBS="-l_rdbc -l_sql";;
+    esac
+    ODBC_TYPE=velocis
+    AC_DEFINE(HAVE_VELOCIS)
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+  fi
+],[
+  AC_MSG_RESULT(no)
+])
+fi
+
+if test -z "$ODBC_TYPE"; then
+AC_MSG_CHECKING(for a custom ODBC support)
+AC_ARG_WITH(custom-odbc,
+[  --with-custom-odbc[=DIR]      Include a user defined ODBC support.
+                          The DIR is ODBC install base directory, 
+                          which defaults to /usr/local.
+                          Make sure to define CUSTOM_ODBC_LIBS and
+                          have some odbc.h in your include dirs.
+                          E.g., you should define following for 
+                          Sybase SQL Anywhere 5.5.00 on QNX, prior to
+                          run configure script:
+                              CFLAGS=\"-DODBC_QNX -DSQLANY_BUG\"
+                              LDFLAGS=-lunix
+                              CUSTOM_ODBC_LIBS=\"-ldblib -lodbc\".],
+[
+  if test "$withval" = "yes"; then
+    withval=/usr/local
+  fi
+  if test "$withval" != "no"; then
+    ODBC_INCDIR=$withval/include
+    ODBC_LIBDIR=$withval/lib
+    ODBC_LFLAGS=-L$CODBC_LIBDIR
+    ODBC_INCLUDE=-I$CODBC_INCDIR
+    ODBC_LIBS=$CUSTOM_ODBC_LIBS
+    ODBC_TYPE=custom
+    AC_DEFINE(HAVE_CODBC)
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+  fi
+],[
+  AC_MSG_RESULT(no)
+])
+fi
+
+if test -z "$ODBC_TYPE"; then
+AC_MSG_CHECKING(for iODBC support)
+AC_ARG_WITH(iodbc,
+[  --with-iodbc[=DIR]      Include iODBC support.  DIR is the iODBC base
+                          install directory, defaults to /usr/local.],
+[
+  if test "$withval" = "yes"; then
+    withval=/usr/local
+  fi
+  if test "$withval" != "no"; then
+    ODBC_INCDIR=$withval/include
+    ODBC_LIBDIR=$withval/lib
+    ODBC_LFLAGS=-L$IODBC_LIBDIR
+    ODBC_INCLUDE=-I$IODBC_INCDIR
+    ODBC_LIBS=-liodbc
+    ODBC_TYPE=iodbc
+    AC_DEFINE(HAVE_IODBC)
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+  fi
+],[
+  AC_MSG_RESULT(no)
+])
+fi
+
+if test -z "$ODBC_TYPE"; then
+AC_MSG_CHECKING(for OpenLink ODBC support)
+AC_ARG_WITH(openlink,
+[  --with-openlink[=DIR]   Include OpenLink ODBC support.  DIR is the
+                          OpenLink base install directory, defaults to
+                          /usr/local/openlink.],
+[
+  if test "$withval" = "yes"; then
+    withval=/usr/local/openlink
+  fi
+  if test "$withval" != "no"; then
+    ODBC_INCDIR=$withval/odbcsdk/include
+    ODBC_LIBDIR=$withval/odbcsdk/lib
+    ODBC_LFLAGS=-L$OPENLINK_LIBDIR
+    ODBC_INCLUDE=-I$OPENLINK_INCDIR
+    ODBC_LIBS=-liodbc
+    ODBC_TYPE=openlink
+    AC_DEFINE(HAVE_OPENLINK)
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+  fi
+],[
+  AC_MSG_RESULT(no)
+])
+fi
+
+if test -n "$ODBC_TYPE"; then
+  INCLUDES="$INCLUDES $ODBC_INCLUDE"
+  EXTRA_LIBS="$EXTRA_LIBS $ODBC_LFLAGS $ODBC_LIBS"
+  AC_DEFINE(HAVE_UODBC, 1)
+  AC_SUBST(ODBC_INCDIR)
+  AC_SUBST(ODBC_INCLUDE)
+  AC_SUBST(ODBC_LIBDIR)
+  AC_SUBST(ODBC_LIBS)
+  AC_SUBST(ODBC_LFLAGS)
+  AC_SUBST(ODBC_TYPE)
+  PHP_EXTENSION(odbc)
+fi
diff --git a/ext/odbc/odbc.c b/ext/odbc/odbc.c
new file mode 100644 (file)
index 0000000..df42879
--- /dev/null
@@ -0,0 +1,2312 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP HTML Embedded Scripting Language Version 3.0                     |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997,1998 PHP Development Team (See Credits file)      |
+   +----------------------------------------------------------------------+
+   | This program is free software; you can redistribute it and/or modify |
+   | it under the terms of one of the following licenses:                 |
+   |                                                                      |
+   |  A) the GNU General Public License as published by the Free Software |
+   |     Foundation; either version 2 of the License, or (at your option) |
+   |     any later version.                                               |
+   |                                                                      |
+   |  B) the PHP License as published by the PHP Development Team and     |
+   |     included in the distribution in the file: LICENSE                |
+   |                                                                      |
+   | This program is distributed in the hope that it will be useful,      |
+   | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
+   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
+   | GNU General Public License for more details.                         |
+   |                                                                      |
+   | You should have received a copy of both licenses referred to here.   |
+   | If you did not, or have any questions about PHP licensing, please    |
+   | contact core@php.net.                                                |
+   +----------------------------------------------------------------------+
+   | Authors: Stig Sæther Bakken <ssb@guardian.no>                        |
+   |          Andreas Karajannis <Andreas.Karajannis@gmd.de>              |
+   |          Frank M. Kromann <fmk@businessnet.dk> Support for DB/2 CLI  |
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/* This file is based on the Adabas D extension.
+ * Adabas D will no longer be supported as separate module.
+ */
+#define IS_EXT_MODULE
+#if !PHP_31
+#undef THREAD_SAFE
+#endif
+#ifdef THREAD_SAFE
+#include "tls.h"
+#endif
+#if !(WIN32|WINNT)
+#include "config.h"
+#include "build-defs.h"
+#endif
+#include <fcntl.h>
+
+#include "php.h"
+#include "dl/phpdl.h"
+#include "ext/standard/php3_standard.h"
+#include "php3_unified_odbc.h"
+#include "head.h"
+#include "snprintf.h"
+
+#if HAVE_UODBC
+
+#ifdef THREAD_SAFE
+
+void *UODBC_MUTEX;
+DWORD UODBC_TLS;
+static int numthreads=0;
+
+typedef struct UODBC_GLOBAL_STRUCT {
+       UODBC_MODULE PHP3_UODBC_MODULE;
+} UODBC_GLOBAL_STRUCT;
+
+#define UODBC_GLOBAL(a) UODBC_GLOBALS->a
+
+#define UODBC_TLS_VARS UODBC_GLOBAL_STRUCT *UODBC_GLOBALS = TlsGetValue(UODBC_TLS); 
+
+#else
+UODBC_MODULE PHP3_UODBC_MODULE;
+#define UODBC_GLOBAL(a) a
+#define UODBC_TLS_VARS
+#endif
+
+function_entry UODBC_FUNCTIONS[] = {
+       UODBC_FE(setoption, NULL),
+       UODBC_FE(autocommit, NULL),
+       UODBC_FE(close, NULL),
+       UODBC_FE(close_all, NULL),
+       UODBC_FE(commit, NULL),
+       UODBC_FE(connect, NULL),
+       UODBC_FE(pconnect, NULL),
+       UODBC_FE(cursor, NULL),
+       UODBC_FE_ALIAS(do, exec, NULL),
+       UODBC_FE(exec, NULL),
+       UODBC_FE(prepare, NULL),
+       UODBC_FE(execute, NULL),
+       UODBC_FE(fetch_row, NULL),
+       UODBC_FE(fetch_into, NULL),
+       UODBC_FE(field_len, NULL),
+       UODBC_FE(field_name, NULL),
+       UODBC_FE(field_type, NULL),
+       UODBC_FE(field_num, NULL),
+       UODBC_FE(free_result, NULL),
+       UODBC_FE(num_fields, NULL),
+       UODBC_FE(num_rows, NULL),
+       UODBC_FE(result, NULL),
+       UODBC_FE(result_all, NULL),
+       UODBC_FE(rollback, NULL),
+       UODBC_FE(binmode, NULL),
+       UODBC_FE(longreadlen, NULL),
+#if defined(USE_ODBC_ALIAS) && defined(UODBC_UNIQUE_NAMES)
+       UODBC_ALIAS(setoption, NULL),
+       UODBC_ALIAS(autocommit, NULL),
+       UODBC_ALIAS(close, NULL),
+       UODBC_ALIAS(close_all, NULL),
+       UODBC_ALIAS(commit, NULL),
+       UODBC_ALIAS(connect, NULL),
+       UODBC_ALIAS(pconnect, NULL),
+       UODBC_ALIAS(cursor, NULL),
+       UODBC_ALIAS_FE(do, exec, NULL),
+       UODBC_ALIAS(exec, NULL),
+       UODBC_ALIAS(prepare, NULL),
+       UODBC_ALIAS(execute, NULL),
+       UODBC_ALIAS(fetch_row, NULL),
+       UODBC_ALIAS(fetch_into, NULL),
+       UODBC_ALIAS(field_len, NULL),
+       UODBC_ALIAS(field_name, NULL),
+       UODBC_ALIAS(field_type, NULL),
+       UODBC_ALIAS(field_num, NULL),
+       UODBC_ALIAS(free_result, NULL),
+       UODBC_ALIAS(num_fields, NULL),
+       UODBC_ALIAS(num_rows, NULL),
+       UODBC_ALIAS(result, NULL),
+       UODBC_ALIAS(result_all, NULL),
+       UODBC_ALIAS(rollback, NULL),
+       UODBC_ALIAS(binmode, NULL),
+       UODBC_ALIAS(longreadlen, NULL),
+#endif
+#if HAVE_SOLID
+       {"solid_fetch_prev",php3_solid_fetch_prev,      NULL},
+#endif
+#if 0 && HAVE_IODBC /* this won't work with the new system */
+/* for backwards compatibility with the older odbc module*/
+       {"sqlconnect",          php3_uodbc_connect,             NULL},
+       {"sqldisconnect",       php3_uodbc_close,               NULL},
+       {"sqlfetch",            php3_uodbc_fetch_row,   NULL},
+       {"sqlexecdirect",       php3_uodbc_do,                  NULL},
+       {"sqlgetdata",          php3_uodbc_result,              NULL},
+       {"sqlfree",                     php3_uodbc_free_result, NULL},
+       {"sqlrowcount",         php3_uodbc_num_rows,    NULL},
+#endif
+       { NULL, NULL, NULL }
+};
+
+php3_module_entry UODBC_MODULE_ENTRY = {
+    UODBC_MODULE_NAME, 
+       UODBC_FUNCTIONS, 
+       PHP3_MINIT_UODBC, 
+       PHP3_MSHUTDOWN_UODBC,
+    PHP3_RINIT_UODBC, 
+       NULL, 
+       PHP3_INFO_UODBC, 
+       STANDARD_MODULE_PROPERTIES
+};
+
+
+#if COMPILE_DL
+DLEXPORT php3_module_entry *get_module() { return &UODBC_MODULE_ENTRY; };
+#endif
+
+
+static void _free_result(UODBC_RESULT *res)
+{
+       int i;
+       
+       if (res){
+               if (res->values) {
+                       for(i = 0; i < res->numcols; i++){
+                               if (res->values[i].value)
+                                       efree(res->values[i].value);
+                       }
+                       efree(res->values);
+                       res->values = NULL;
+               }
+               if (res->stmt){
+#if HAVE_SOLID
+                       SQLTransact(UODBC_GLOBAL(PHP3_UODBC_MODULE).henv, res->conn_ptr->hdbc,
+                                               (UWORD)SQL_COMMIT);
+#endif
+                       SQLFreeStmt(res->stmt,SQL_DROP);
+#if !HAVE_DB2
+                       res->stmt = NULL;
+#endif
+               }
+               efree(res);
+       }
+}
+
+static int _results_cleanup(list_entry *le)
+{
+       UODBC_TLS_VARS;
+
+       if (le->type == UODBC_GLOBAL(PHP3_UODBC_MODULE).le_result){
+               UODBC_CONNECTION *conn = ((UODBC_RESULT *) le->ptr)->conn_ptr;
+               if (!conn->open && ((UODBC_RESULT *) le->ptr)->stmt){
+                       SQLFreeStmt(((UODBC_RESULT *) le->ptr)->stmt,SQL_DROP);
+#if !HAVE_DB2
+                       ((UODBC_RESULT *) le->ptr)->stmt = NULL;
+#endif
+               }
+       }
+       return 0;
+}
+
+static void _close_connection(UODBC_CONNECTION *conn)
+{
+       /* FIXME
+        * Closing a connection will fail if there are
+        * pending transactions
+        */
+       UODBC_TLS_VARS;
+
+       conn->open = 0;
+       _php3_hash_apply(UODBC_GLOBAL(PHP3_UODBC_MODULE).resource_list,
+                               (int (*)(void *))_results_cleanup);
+       SQLDisconnect(conn->hdbc);
+       SQLFreeConnect(conn->hdbc);
+       efree(conn);
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).num_links--;
+}
+
+
+static void _close_pconnection(UODBC_CONNECTION *conn)
+{
+       UODBC_TLS_VARS;
+
+
+       conn->open = 0;
+       _php3_hash_apply(UODBC_GLOBAL(PHP3_UODBC_MODULE).resource_plist,
+                               (int (*)(void *))_results_cleanup);
+
+       SQLDisconnect(conn->hdbc);
+       SQLFreeConnect(conn->hdbc);
+       free(conn);
+
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).num_links--;
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).num_persistent--;
+}
+
+
+int PHP3_MINIT_UODBC(INIT_FUNC_ARGS) 
+{
+#ifdef SQLANY_BUG
+       HDBC    foobar;
+       RETCODE rc;
+#endif
+
+#if defined(THREAD_SAFE)
+       UODBC_GLOBAL_STRUCT *UODBC_GLOBALS;
+
+       PHP3_MUTEX_ALLOC(UODBC_MUTEX);
+       PHP3_MUTEX_LOCK(UODBC_MUTEX);
+       numthreads++;
+       if (numthreads==1){
+               if (!PHP3_TLS_PROC_STARTUP(UODBC_TLS)){
+                       PHP3_MUTEX_UNLOCK(UODBC_MUTEX);
+                       PHP3_MUTEX_FREE(UODBC_MUTEX);
+                       return FAILURE;
+               }
+       }
+       PHP3_MUTEX_UNLOCK(UODBC_MUTEX);
+       if(!PHP3_TLS_THREAD_INIT(UODBC_TLS,UODBC_GLOBALS,UODBC_GLOBAL_STRUCT)){
+               PHP3_MUTEX_FREE(UODBC_MUTEX);
+               return FAILURE;
+       }
+#endif
+
+       SQLAllocEnv(&UODBC_GLOBAL(PHP3_UODBC_MODULE).henv);
+       
+#if !PHP_31
+       cfg_get_string(ODBC_INI_VAR(default_db),
+                                  &UODBC_GLOBAL(PHP3_UODBC_MODULE).defDB);
+       cfg_get_string(ODBC_INI_VAR(default_user),
+                                  &UODBC_GLOBAL(PHP3_UODBC_MODULE).defUser);
+       cfg_get_string(ODBC_INI_VAR(default_pw),
+                                  &UODBC_GLOBAL(PHP3_UODBC_MODULE).defPW);
+       if (cfg_get_long(ODBC_INI_VAR(allow_persistent),
+                                        &UODBC_GLOBAL(PHP3_UODBC_MODULE).allow_persistent)
+               == FAILURE) {
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).allow_persistent = -1;
+       }
+       if (cfg_get_long(ODBC_INI_VAR(max_persistent),
+                                        &UODBC_GLOBAL(PHP3_UODBC_MODULE).max_persistent)
+               == FAILURE) {
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).max_persistent = -1;
+       }
+       if (cfg_get_long(ODBC_INI_VAR(max_links),
+                                        &UODBC_GLOBAL(PHP3_UODBC_MODULE).max_links)
+               == FAILURE) {
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).max_links = -1;
+       }
+#else
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).allow_persistent = -1;
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).max_persistent = -1;
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).max_links = -1;
+#endif
+
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).num_persistent = 0;
+
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).le_result =
+               register_list_destructors(_free_result, NULL);
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).le_conn =
+               register_list_destructors(_close_connection, NULL);
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).le_pconn =
+               register_list_destructors(NULL, _close_pconnection);
+
+#ifdef SQLANY_BUG
+/* Make a dumb connection to avoid crash on SQLFreeEnv(),
+ * then release it immediately.
+ * This is required for SQL Anywhere 5.5.00 on QNX 4.24 at least.
+ * The SQLANY_BUG should be defined in CFLAGS.
+ */
+       if ( SQLAllocConnect(UODBC_GLOBAL(PHP3_UODBC_MODULE).henv, &foobar) != SQL_SUCCESS )
+                       UODBC_SQL_ERROR(SQL_NULL_HDBC, SQL_NULL_HSTMT, "SQLAllocConnect");
+       else
+       {
+               rc = SQLConnect(foobar, UODBC_GLOBAL(PHP3_UODBC_MODULE).defDB, SQL_NTS, UODBC_GLOBAL(PHP3_UODBC_MODULE).defUser, 
+                                               SQL_NTS, UODBC_GLOBAL(PHP3_UODBC_MODULE).defPW, SQL_NTS);
+               if(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
+                       SQLDisconnect( foobar );
+               SQLFreeConnect( foobar );
+       }
+#endif
+
+       REGISTER_LONG_CONSTANT("ODBC_BINMODE_PASSTHRU", 0, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ODBC_BINMODE_RETURN", 1, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("ODBC_BINMODE_CONVERT", 2, CONST_CS | CONST_PERSISTENT);
+       /* Define Constants for different cursor options
+          these Constants are are defined in <sqlext.h>
+       */
+       REGISTER_MAIN_LONG_CONSTANT("SQL_CUR_USE_IF_NEEDED", SQL_CUR_USE_IF_NEEDED, CONST_PERSISTENT | CONST_CS);
+       REGISTER_MAIN_LONG_CONSTANT("SQL_CUR_USE_ODBC", SQL_CUR_USE_ODBC, CONST_PERSISTENT | CONST_CS);
+       REGISTER_MAIN_LONG_CONSTANT("SQL_CUR_USE_DRIVER", SQL_CUR_USE_DRIVER, CONST_PERSISTENT | CONST_CS);
+       REGISTER_MAIN_LONG_CONSTANT("SQL_CUR_DEFAULT", SQL_CUR_DEFAULT, CONST_PERSISTENT | CONST_CS);
+       return SUCCESS;
+}
+
+
+int PHP3_RINIT_UODBC(INIT_FUNC_ARGS)
+{
+       UODBC_TLS_VARS;
+
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).defConn = -1;
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).num_links = 
+                       UODBC_GLOBAL(PHP3_UODBC_MODULE).num_persistent;
+#if PHP_31
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultlrl = 4096;
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultbinmode = 1;
+#else
+       if (cfg_get_long(ODBC_INI_VAR(defaultlrl), &UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultlrl)
+               == FAILURE){
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultlrl = 4096;
+       }
+       if (cfg_get_long(ODBC_INI_VAR(defaultbinmode), &UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultbinmode) == FAILURE){
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultbinmode = 1;
+       }
+#endif
+       return SUCCESS;
+}
+
+int PHP3_MSHUTDOWN_UODBC(SHUTDOWN_FUNC_ARGS)
+{
+       UODBC_TLS_VARS;
+
+       SQLFreeEnv(UODBC_GLOBAL(PHP3_UODBC_MODULE).henv);
+#ifdef THREAD_SAFE
+       PHP3_TLS_THREAD_FREE(UODBC_GLOBALS);
+       PHP3_MUTEX_LOCK(UODBC_MUTEX);
+       numthreads--;
+       if (!numthreads) {
+               PHP3_TLS_PROC_SHUTDOWN(UODBC_TLS);
+               PHP3_MUTEX_UNLOCK(UODBC_MUTEX);
+               PHP3_MUTEX_FREE(UODBC_MUTEX);
+               return SUCCESS;
+       }
+       PHP3_MUTEX_UNLOCK(UODBC_MUTEX);
+#endif
+       return SUCCESS;
+}
+
+
+void PHP3_INFO_UODBC(void)
+{
+       UODBC_TLS_VARS;
+
+#if HAVE_SOLID
+       php3_printf("Unified ODBC Support active (compiled with Solid)");
+#elif HAVE_ADABAS
+       php3_printf("Unified ODBC Support active (compiled with Adabas D)");
+#elif HAVE_IODBC && !(WIN32|WINNT)
+       php3_printf("Unified ODBC Support active (compiled with iODBC)");
+#elif HAVE_VELOCIS
+       php3_printf("Unified ODBC Support active (compiled with Velocis)");
+#elif HAVE_DB2
+       php3_printf("Unified ODBC Support active (compiled with IBM DB2)");
+#elif WIN32|WINNT
+       php3_printf("Unified ODBC Support active (compiled with win32 ODBC)");
+#elif HAVE_EMPRESS
+        PUTS("Unified ODBC Support active (compiled with Empress)");
+#else
+       php3_printf("Unified ODBC Support active (compiled with unknown library)");
+#endif
+       php3_printf("<BR>");
+#if DEBUG
+       php3_printf("default_db: %s<br>\n",UODBC_GLOBAL(PHP3_UODBC_MODULE).defDB);
+       php3_printf("default_user: %s<br>\n",UODBC_GLOBAL(PHP3_UODBC_MODULE).defUser);
+       php3_printf("default_pw: %s<br>\n",UODBC_GLOBAL(PHP3_UODBC_MODULE).defPW);
+#endif
+       php3_printf("allow_persistent: %d<br>\n",UODBC_GLOBAL(PHP3_UODBC_MODULE).allow_persistent);
+       php3_printf("max_persistent: %d<br>\n",UODBC_GLOBAL(PHP3_UODBC_MODULE).max_persistent);
+       php3_printf("max_links: %d<br>\n",UODBC_GLOBAL(PHP3_UODBC_MODULE).max_links);
+}       
+        
+        
+
+/*
+ * List management functions
+ */
+
+int UODBC_ADD_RESULT(HashTable *list,UODBC_RESULT *result)
+{
+       UODBC_TLS_VARS;
+       return php3_list_insert(result, UODBC_GLOBAL(PHP3_UODBC_MODULE).le_result);
+}
+
+UODBC_RESULT *UODBC_GET_RESULT(HashTable *list, int ind)
+{
+       UODBC_RESULT *res;
+       int type;
+       UODBC_TLS_VARS;
+
+       res = (UODBC_RESULT*)php3_list_find(ind, &type);
+       if (!res || type != UODBC_GLOBAL(PHP3_UODBC_MODULE).le_result) {
+               php3_error(E_WARNING, "Bad result index %d", ind);
+               return NULL;
+       }
+       return res;
+}
+
+void UODBC_DEL_RESULT(HashTable *list, int ind)
+{
+       UODBC_RESULT *res;
+       int type;
+       UODBC_TLS_VARS;
+
+       res = (UODBC_RESULT *)php3_list_find(ind, &type);
+       if (!res || type != UODBC_GLOBAL(PHP3_UODBC_MODULE).le_result) {
+               php3_error(E_WARNING,"Can't find result %d", ind);
+               return;
+       }
+       php3_list_delete(ind);
+}
+
+#if 0
+int UODBC_ADD_CONN(HashTable *list, HDBC conn)
+{
+       UODBC_TLS_VARS;
+       return php3_list_insert(conn, UODBC_GLOBAL(PHP3_UODBC_MODULE).le_conn);
+}
+
+void uodbc_make_def_conn(HashTable *list)
+{
+       HDBC    new_conn;
+       RETCODE rc;
+       UODBC_TLS_VARS;
+
+       SQLAllocConnect(UODBC_GLOBAL(PHP3_UODBC_MODULE).henv, &new_conn);
+       rc = SQLConnect(new_conn, UODBC_GLOBAL(PHP3_UODBC_MODULE).defDB,
+                                       SQL_NTS, UODBC_GLOBAL(PHP3_UODBC_MODULE).defUser, 
+                                       SQL_NTS, UODBC_GLOBAL(PHP3_UODBC_MODULE).defPW, SQL_NTS);
+
+       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
+               UODBC_SQL_ERROR(new_conn, SQL_NULL_HSTMT, "SQLConnect"); 
+       } else {
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).defConn = uodbc_add_conn(list, new_conn);
+       }
+}
+#endif
+
+UODBC_CONNECTION *UODBC_GET_CONN(HashTable *list, int ind)
+{
+       UODBC_CONNECTION *conn = NULL;
+       int type;
+       HashTable *plist;
+       UODBC_TLS_VARS;
+       
+       plist = UODBC_GLOBAL(PHP3_UODBC_MODULE).resource_plist;
+
+       conn = (UODBC_CONNECTION *)php3_list_find(ind, &type);
+       if (conn && (type == UODBC_GLOBAL(PHP3_UODBC_MODULE).le_conn ||
+                               type == UODBC_GLOBAL(PHP3_UODBC_MODULE).le_pconn))
+               return conn;
+
+       conn = (UODBC_CONNECTION *)php3_plist_find(ind, &type);
+       if (conn && (type == UODBC_GLOBAL(PHP3_UODBC_MODULE).le_conn ||
+                               type == UODBC_GLOBAL(PHP3_UODBC_MODULE).le_pconn))
+               return conn;
+
+       php3_error(E_WARNING,"Bad ODBC connection number (%d)", ind);
+       return NULL;
+}
+
+#if HAVE_DB2
+void UODBC_SQL_ERROR(SQLHANDLE conn, SQLHANDLE stmt, char *func)
+#else
+void UODBC_SQL_ERROR(HDBC conn, HSTMT stmt, char *func)
+#endif
+{
+    char       state[6];     /* Not used */
+       SDWORD  error;        /* Not used */
+       char    errormsg[255];
+       SWORD   errormsgsize; /* Not used */
+       UODBC_TLS_VARS;
+       
+       SQLError(UODBC_GLOBAL(PHP3_UODBC_MODULE).henv, conn, stmt, state,
+                        &error, errormsg, sizeof(errormsg)-1, &errormsgsize);
+       if (func) {
+               php3_error(E_WARNING, "SQL error: %s, SQL state %s in %s",
+                                  errormsg, state, func);
+       } else {
+               php3_error(E_WARNING, "SQL error: %s, SQL state %s",
+                                  errormsg, state);
+       }
+}
+
+/* Main User Functions */
+/* {{{ proto odbc_close_all(void)
+   Close all ODBC connections */
+UODBC_FUNCTION(close_all)
+{
+       void *ptr;
+       int type;
+       int i, nument = _php3_hash_next_free_element(list);
+       UODBC_TLS_VARS;
+
+       for (i = 1; i < nument; i++) {
+               ptr = php3_list_find(i, &type);
+               if (ptr && (type == UODBC_GLOBAL(PHP3_UODBC_MODULE).le_conn ||
+                                  type == UODBC_GLOBAL(PHP3_UODBC_MODULE).le_pconn)){
+                       php3_list_delete(i);
+               }
+       }
+}
+/* }}} */
+
+void php3_uodbc_fetch_attribs(INTERNAL_FUNCTION_PARAMETERS, int mode)
+{
+       int         res_ind;
+       UODBC_RESULT   *result;
+       pval     *arg1, *arg2;
+       UODBC_TLS_VARS;
+
+       if (getParameters(ht, 2, &arg1, &arg2) == FAILURE)
+               WRONG_PARAM_COUNT;
+
+       convert_to_long(arg1);
+    convert_to_long(arg2);
+    
+       res_ind = arg1->value.lval;
+
+    if (res_ind){           
+        if ((result = UODBC_GET_RESULT(list, res_ind)) == NULL){
+            RETURN_FALSE;
+        }
+        if (mode)
+            result->longreadlen = arg2->value.lval;    
+        else
+            result->binmode = arg2->value.lval;
+       } else {
+        if (mode)
+            UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultlrl = arg2->value.lval;
+        else
+            UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultbinmode = arg2->value.lval;
+    }
+    
+       RETURN_TRUE
+}
+
+/* {{{ proto odbc_binmode(int result_id, int mode)
+   Handle binary column data */
+UODBC_FUNCTION(binmode)
+{
+       php3_uodbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
+}
+/* }}} */
+
+/* {{{ proto odbc_longreadlen(int result_id, int length)
+   Handle LONG columns */
+UODBC_FUNCTION(longreadlen)
+{
+       php3_uodbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
+}
+/* }}} */
+
+int UODBC_BINDCOLS(UODBC_RESULT *result)
+{
+    int i;
+    SWORD       colnamelen; /* Not used */
+       SDWORD      displaysize;
+       UODBC_TLS_VARS;
+       
+    result->values = (UODBC_RESULT_VALUE *)
+               emalloc(sizeof(UODBC_RESULT_VALUE)*result->numcols);
+
+    if (result->values == NULL){
+        php3_error(E_WARNING, "Out of memory");
+        SQLFreeStmt(result->stmt, SQL_DROP);
+        return 0;
+    }
+
+    result->longreadlen = UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultlrl;
+    result->binmode = UODBC_GLOBAL(PHP3_UODBC_MODULE).defaultbinmode;
+        
+    for(i = 0; i < result->numcols; i++){
+        SQLColAttributes(result->stmt, (UWORD)(i+1), SQL_COLUMN_NAME,
+                         result->values[i].name,
+                         sizeof(result->values[i].name),
+                         &colnamelen,
+                         0);
+               SQLColAttributes(result->stmt, (UWORD)(i+1), SQL_COLUMN_TYPE,
+                                                       NULL, 0, NULL, &result->values[i].coltype);
+               
+               /* Don't bind LONG / BINARY columns, so that fetch behaviour can
+           be controlled by odbc_binmode() / odbc_longreadlen()
+                */
+               
+               switch(result->values[i].coltype){
+            case SQL_BINARY:
+            case SQL_VARBINARY:
+                       case SQL_LONGVARBINARY:
+                       case SQL_LONGVARCHAR:
+                               result->values[i].value = NULL;
+                               break;
+                               
+#if HAVE_ADABAS
+                       case SQL_TIMESTAMP:
+                               result->values[i].value = (char *)emalloc(27);
+                               SQLBindCol(result->stmt, (UWORD)(i+1), SQL_C_CHAR, result->values[i].value,
+                                                       27, &result->values[i].vallen);
+                               break;
+#endif /* HAVE_ADABAS */
+                       default:
+                               SQLColAttributes(result->stmt, (UWORD)(i+1), SQL_COLUMN_DISPLAY_SIZE,
+                                                                       NULL, 0, NULL, &displaysize);
+                               result->values[i].value = (char *)emalloc(displaysize + 1);
+                               SQLBindCol(result->stmt, (UWORD)(i+1), SQL_C_CHAR, result->values[i].value,
+                                                       displaysize + 1, &result->values[i].vallen);
+                               break;
+               }
+    }
+    return 1;
+}
+
+/* {{{ proto odbc_prepare(int connection_id, string query)
+   Prepares a statement for execution */
+UODBC_FUNCTION(prepare)
+{
+       pval     *arg1, *arg2;
+       int         conn;
+       char        *query;
+       UODBC_RESULT   *result=NULL;
+       UODBC_CONNECTION *curr_conn=NULL;
+       RETCODE rc;
+
+       if (getParameters(ht, 2, &arg1, &arg2) == FAILURE){
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(arg1);
+       convert_to_string(arg2);
+       conn = arg1->value.lval;
+       query = arg2->value.str.val;
+
+       if ((curr_conn = UODBC_GET_CONN(list, conn)) == NULL){
+               RETURN_FALSE;
+       }
+
+#if 0
+       _php3_stripslashes(query,NULL);
+#endif
+
+       result = (UODBC_RESULT *)emalloc(sizeof(UODBC_RESULT));
+       if (result == NULL){
+               php3_error(E_WARNING, "Out of memory");
+               RETURN_FALSE;
+       }
+       
+       result->numparams = 0;
+       
+       rc = SQLAllocStmt(curr_conn->hdbc, &(result->stmt));
+       if (rc == SQL_INVALID_HANDLE){
+               efree(result);
+               php3_error(E_WARNING, "SQLAllocStmt error 'Invalid Handle' in php3_uodbc_prepare");
+               RETURN_FALSE;
+       }
+
+       if (rc == SQL_ERROR){
+               UODBC_SQL_ERROR(curr_conn->hdbc, SQL_NULL_HSTMT, "SQLAllocStmt");
+               efree(result);
+               RETURN_FALSE;
+       }
+
+       if ((rc = SQLPrepare(result->stmt, query, SQL_NTS)) != SQL_SUCCESS){
+               UODBC_SQL_ERROR(curr_conn->hdbc, result->stmt, "SQLPrepare");
+               SQLFreeStmt(result->stmt, SQL_DROP);
+               RETURN_FALSE;
+       }
+       
+       SQLNumParams(result->stmt, &(result->numparams));
+    SQLNumResultCols(result->stmt, &(result->numcols));
+
+       if (result->numcols > 0){
+        if (!UODBC_BINDCOLS(result)){
+                       efree(result);
+            RETURN_FALSE;
+               }
+       } else {
+               result->values = NULL;
+       }
+       result->conn_ptr = curr_conn;
+       result->fetched = 0;
+       RETURN_LONG(UODBC_ADD_RESULT(list, result));    
+}
+/* }}} */
+
+/*
+ * Execute prepared SQL statement. Supports only input parameters.
+ */
+/* {{{ proto odbc_execute(int result_id [, array parameters_array])
+   Execute a prepared statement */
+extern UODBC_FUNCTION(execute)
+{ 
+    pval *arg1, *arg2, arr, *tmp;
+    typedef struct params_t {
+               SDWORD vallen;
+               int fp;
+       } params_t;
+       params_t *params = NULL;
+       char *filename;
+       SWORD sqltype, scale, nullable;
+       UDWORD precision;
+       UODBC_RESULT   *result=NULL;
+       int res_ind, numArgs, i, ne;
+       RETCODE rc;
+       
+       numArgs = ARG_COUNT(ht);
+       if (numArgs == 1){
+               if (getParameters(ht, 1, &arg1) == FAILURE)
+                       WRONG_PARAM_COUNT;
+       } else {
+               if (getParameters(ht, 2, &arg1, &arg2) == FAILURE)
+                       WRONG_PARAM_COUNT;
+
+        arr = *arg2;
+        if (arr.type != IS_ARRAY) {
+            php3_error(E_WARNING, "No array passed to odbc_execute()");
+            return;
+        }
+    }
+    
+       convert_to_long(arg1);
+       res_ind = arg1->value.lval;
+       
+       /* check result */
+       if ((result = UODBC_GET_RESULT(list, res_ind)) == NULL){
+               RETURN_FALSE;
+       }
+       
+       if (result->numparams > 0 && numArgs == 1) {
+               php3_error(E_WARNING, "No parameters to SQL statement given");
+               RETURN_FALSE;
+       }
+
+    if (result->numparams > 0){
+               if ((ne = _php3_hash_num_elements(arr.value.ht)) < result->numparams){
+                       php3_error(E_WARNING,"Not enough parameters (%d should be %d) given",
+                                          ne, result->numparams);
+                       RETURN_FALSE;
+               }
+
+        pval_copy_constructor(arg2);
+        _php3_hash_internal_pointer_reset(arr.value.ht);
+        params = (params_t *)emalloc(sizeof(params_t) * result->numparams);
+               
+               for (i = 1; i <= result->numparams; i++) {
+            if (_php3_hash_get_current_data(arr.value.ht, (void **) &tmp) == FAILURE) {
+                php3_error(E_WARNING,"Error getting parameter");
+                SQLFreeStmt(result->stmt,SQL_RESET_PARAMS);
+                               efree(params);
+                RETURN_FALSE;
+            }
+            convert_to_string(tmp);
+                       if (tmp->type != IS_STRING) {
+                               php3_error(E_WARNING,"Error converting parameter");
+                               SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
+                               _php3_hash_destroy(arr.value.ht);
+                               efree(arr.value.ht);
+                               efree(params);
+                               RETURN_FALSE;
+                       }
+                       
+            SQLDescribeParam(result->stmt, (UWORD)i, &sqltype, &precision,
+                                                        &scale, &nullable);
+                       params[i-1].vallen = tmp->value.str.len;
+                       params[i-1].fp = -1;
+
+
+                       if (tmp->value.str.val[0] == '\'') {
+                               filename = &tmp->value.str.val[1];
+                               filename[tmp->value.str.len - 2] = '\0';
+
+                if ((params[i-1].fp = open(filename,O_RDONLY)) == -1) {
+                                       php3_error(E_WARNING,"Can't open file %s", filename);
+                                       SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
+                                       for (i = 0; i < result->numparams; i++) {
+                                               if (params[i].fp != -1) {
+                                                       close(params[i].fp);
+                                               }
+                                       }
+                                       _php3_hash_destroy(arr.value.ht);
+                                       efree(arr.value.ht);
+                                       efree(params);
+                                       RETURN_FALSE;
+                               }
+
+                               params[i-1].vallen = SQL_LEN_DATA_AT_EXEC(0);
+
+                               rc = SQLBindParameter(result->stmt, (UWORD)i, SQL_PARAM_INPUT,
+                                                                         SQL_C_BINARY, sqltype, precision, scale,
+                                                                         (void *)params[i-1].fp, 0,
+                                                                         &params[i-1].vallen);
+                       } else {
+                               /*if (IS_SQL_BINARY(sqltype)){
+                                       php3_error(E_WARNING,"No Filename for binary parameter");
+                                       SQLFreeStmt(result->stmt,SQL_RESET_PARAMS);
+                                       _php3_hash_destroy(arr.value.ht);
+                                       efree(arr.value.ht);
+                                       efree(params);
+                                       RETURN_FALSE;
+                               }
+*/
+                               rc = SQLBindParameter(result->stmt, (UWORD)i, SQL_PARAM_INPUT,
+                                                                         SQL_C_CHAR, sqltype, precision, scale,
+                                                                         tmp->value.str.val, 0,
+                                                                         &params[i-1].vallen);
+                       }
+                       _php3_hash_move_forward(arr.value.ht);
+               }
+       }
+       /* Close cursor, needed for doing multiple selects */
+       rc = SQLFreeStmt(result->stmt, SQL_CLOSE);
+
+       if (rc == SQL_ERROR){
+               UODBC_SQL_ERROR(result->conn_ptr->hdbc, result->stmt, "SQLFreeStmt");   
+       }
+
+       rc = SQLExecute(result->stmt);
+
+       result->fetched = 0;
+       if (rc == SQL_NEED_DATA){
+               char buf[4096];
+               int fp, nbytes;
+               while(rc == SQL_NEED_DATA){
+                       rc = SQLParamData(result->stmt, (PTR FAR *)&fp);
+                       if (rc == SQL_NEED_DATA){
+                               while((nbytes = read(fp, &buf, 4096)) > 0)
+                                       SQLPutData(result->stmt,(UCHAR FAR*) &buf, nbytes);
+                       }
+               }
+       } else {
+               if (rc != SQL_SUCCESS){
+                       UODBC_SQL_ERROR(result->conn_ptr->hdbc, result->stmt, "SQLExecute");
+                       RETVAL_FALSE;
+               }
+       }       
+       
+       if (result->numparams > 0){
+               SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
+               for(i = 0; i < result->numparams; i++){
+                       if (params[i].fp != -1)
+                               close(params[i].fp);
+               }
+               _php3_hash_destroy(arr.value.ht);
+               efree(arr.value.ht);
+               efree(params);
+       }
+
+       if (rc == SQL_SUCCESS){
+               RETVAL_TRUE;
+       }
+}
+/* }}} */
+
+/* odbc_cursor simply returns a cursor name for the given stmt
+ * Adabas automagically generates cursor names, other drivers may not
+ */
+/* {{{ proto odbc_cursor(int result_id)
+   Get cursor name */
+UODBC_FUNCTION(cursor)
+{
+       pval     *arg1;
+       int                     res_ind;
+       SWORD           len, max_len;
+       char            *cursorname;
+       UODBC_RESULT *result;
+       RETCODE         rc;
+
+       if (getParameters(ht, 1, &arg1) == FAILURE){
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(arg1);
+       res_ind = arg1->value.lval;
+       
+       /* check result */
+       if ((result = UODBC_GET_RESULT(list, res_ind)) == NULL) {
+               RETURN_FALSE;
+       }
+       rc = SQLGetInfo(result->conn_ptr->hdbc,SQL_MAX_CURSOR_NAME_LEN,
+                                       (void *)&max_len,0,&len);
+       if (rc != SQL_SUCCESS){
+               RETURN_FALSE;
+       }
+       
+       if (max_len > 0){
+               cursorname = emalloc(max_len + 1);
+               if (cursorname == NULL){
+                       php3_error(E_WARNING,"Out of memory");
+                       RETURN_FALSE;
+               }
+               rc = SQLGetCursorName(result->stmt,cursorname,(SWORD)max_len,&len);
+               if (rc != SQL_SUCCESS){
+                       char    state[6];     /* Not used */
+                       SDWORD  error;        /* Not used */
+                       char    errormsg[255];
+                       SWORD   errormsgsize; /* Not used */
+                       UODBC_TLS_VARS;
+
+                       SQLError(UODBC_GLOBAL(PHP3_UODBC_MODULE).henv, result->conn_ptr->hdbc,
+                                               result->stmt, state, &error, errormsg,
+                                               sizeof(errormsg)-1, &errormsgsize);
+                       if (!strncmp(state,"S1015",5)){
+                               sprintf(cursorname,"php3_curs_%d", (int)result->stmt);
+                               if (SQLSetCursorName(result->stmt,cursorname,SQL_NTS) != SQL_SUCCESS){
+                                       UODBC_SQL_ERROR(result->conn_ptr->hdbc,result->stmt,
+                                                                               "SQLSetCursorName");
+                                       RETVAL_FALSE;
+                               } else {
+                                       RETVAL_STRING(cursorname,1);
+                               }
+                       } else {
+                               php3_error(E_WARNING, "SQL error: %s, SQL state %s", errormsg, state);
+                               RETVAL_FALSE;
+                       }
+               } else {
+                       RETVAL_STRING(cursorname,1);
+               }
+               efree(cursorname);
+       } else {
+               RETVAL_FALSE;
+       }
+}
+/* }}} */
+
+/* {{{ proto odbc_exec(int connection_id, string query)
+   Prepare and execute an SQL statement */
+UODBC_FUNCTION(exec)
+{
+       pval    *arg1, *arg2;
+       int         conn;
+       char        *query;
+       UODBC_RESULT   *result=NULL;
+       UODBC_CONNECTION *curr_conn=NULL;
+       RETCODE     rc;
+#if HAVE_SQL_EXTENDED_FETCH
+       UDWORD      scrollopts;
+#endif
+
+       if (getParameters(ht, 2, &arg1, &arg2) == FAILURE){
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(arg1);
+       convert_to_string(arg2);
+       conn = arg1->value.lval;
+       query = arg2->value.str.val;
+       
+       if ((curr_conn = UODBC_GET_CONN(list, conn)) == NULL){
+               RETURN_FALSE;
+       }
+
+#if 0
+       _php3_stripslashes(query,NULL);
+#endif
+       
+       result = (UODBC_RESULT *)emalloc(sizeof(UODBC_RESULT));
+       if (result == NULL){
+               php3_error(E_WARNING, "Out of memory");
+               RETURN_FALSE;
+       }
+
+       rc = SQLAllocStmt(curr_conn->hdbc, &(result->stmt));
+       if (rc == SQL_INVALID_HANDLE){
+               php3_error(E_WARNING, "SQLAllocStmt error 'Invalid Handle' in PHP3_UODBC_DO");
+               efree(result);
+               RETURN_FALSE;
+       }
+
+       if (rc == SQL_ERROR){
+               UODBC_SQL_ERROR(curr_conn->hdbc, SQL_NULL_HSTMT, "SQLAllocStmt");
+               efree(result);
+               RETURN_FALSE;
+       }
+       
+#if HAVE_SQL_EXTENDED_FETCH
+       /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info,
+          whether Driver supports ExtendedFetch */
+       rc = SQLGetInfo(curr_conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL);
+       if (rc == SQL_SUCCESS){
+               if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))){
+                       /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other
+                          type if not possible.
+                        */
+                       if (SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, SQL_CURSOR_DYNAMIC)
+                               == SQL_ERROR){
+                               UODBC_SQL_ERROR(curr_conn->hdbc, result->stmt, " SQLSetStmtOption");
+                               SQLFreeStmt(result->stmt, SQL_DROP);
+                               efree(result);
+                               RETURN_FALSE;
+                       }
+               }
+       } else {
+               result->fetch_abs = 0;
+       }
+#endif
+
+       rc = SQLExecDirect(result->stmt, query, SQL_NTS);
+       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
+               /* XXX FIXME we should really check out SQLSTATE with SQLError
+                * in case rc is SQL_SUCCESS_WITH_INFO here.
+                */
+               UODBC_SQL_ERROR(curr_conn->hdbc, result->stmt, "SQLExecDirect"); 
+               SQLFreeStmt(result->stmt, SQL_DROP);
+               efree(result);
+               RETURN_FALSE;
+       }
+
+       SQLNumResultCols(result->stmt, &(result->numcols));
+       
+       /* For insert, update etc. cols == 0 */
+       if (result->numcols > 0){
+        if (!UODBC_BINDCOLS(result)){
+                       efree(result);
+            RETURN_FALSE;
+               }
+       } else {
+               result->values = NULL;
+       }
+       result->conn_ptr = curr_conn;
+       result->fetched = 0;
+       RETURN_LONG(UODBC_ADD_RESULT(list, result));
+}
+/* }}} */
+
+/* {{{ proto odbc_fetch_into(int result_id [, int rownumber], array result_array)
+   Fetch one result row into an array */ 
+UODBC_FUNCTION(fetch_into)
+{
+       int         res_ind, numArgs, i;
+       UODBC_RESULT   *result;
+       RETCODE     rc;
+    SWORD sql_c_type;
+       char *buf = NULL;
+#if HAVE_SQL_EXTENDED_FETCH
+       UDWORD      crow;
+       UWORD       RowStatus[1];
+       SDWORD      rownum = -1;
+       pval     *arg1, *arg2, *arr, tmp;
+       
+       numArgs = ARG_COUNT(ht);
+
+       switch(numArgs){
+               case 2:
+                       if (getParameters(ht, 2, &arg1, &arr) == FAILURE)
+                               WRONG_PARAM_COUNT;
+                       break;
+               case 3:
+                       if (getParameters(ht, 3, &arg1, &arg2, &arr) == FAILURE)
+                               WRONG_PARAM_COUNT;
+                       convert_to_long(arg2);
+                       rownum = arg2->value.lval;
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       if (!ParameterPassedByReference(ht, numArgs)){
+               php3_error(E_WARNING, "Array not passed by reference in call to odbc_fetch_into()");
+               RETURN_FALSE;
+       }
+#else
+       pval     *arg1, *arr, tmp;
+
+       numArgs = ARG_COUNT(ht);
+
+       if (numArgs != 2 || getParameters(ht, 2, &arg1, &arr) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       if (!ParameterPassedByReference(ht, numArgs)){
+               php3_error(E_WARNING, "Array not passed by reference in call to odbc_fetch_into()");
+               RETURN_FALSE;
+       }
+#endif                         
+       
+       convert_to_long(arg1);
+       res_ind = arg1->value.lval;
+
+       /* check result */
+       if ((result = UODBC_GET_RESULT(list, res_ind)) == NULL){
+               RETURN_FALSE;
+       }
+
+       if (result->numcols == 0) {
+               php3_error(E_WARNING, "No tuples available at this result index");
+               RETURN_FALSE;
+       }
+       
+       if (arr->type != IS_ARRAY){
+               if (array_init(arr) == FAILURE){
+                       php3_error(E_WARNING, "Can't convert to type Array");
+                       RETURN_FALSE;
+               }
+       }
+
+#if HAVE_SQL_EXTENDED_FETCH
+       if (result->fetch_abs){
+               if (rownum > 0)
+                       rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
+               else
+                       rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
+       }else
+#endif
+               
+               rc = SQLFetch(result->stmt);
+
+       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
+               RETURN_FALSE;
+
+#if HAVE_SQL_EXTENDED_FETCH
+       if (rownum > 0 && result->fetch_abs)
+               result->fetched = rownum;
+       else
+#endif
+               result->fetched++;
+
+       for (i = 0; i < result->numcols; i++) {
+               tmp.type = IS_STRING;
+               tmp.value.str.len = 0;
+        sql_c_type = SQL_C_CHAR;
+       
+        switch(result->values[i].coltype){
+            case SQL_BINARY:
+            case SQL_VARBINARY:
+            case SQL_LONGVARBINARY:
+                if (result->binmode <= 0){
+                    tmp.value.str.val = empty_string;
+                    break;
+                }
+                if (result->binmode == 1) sql_c_type = SQL_C_BINARY; 
+            case SQL_LONGVARCHAR:
+                if (IS_SQL_LONG(result->values[i].coltype) && 
+                   result->longreadlen <= 0){
+                    tmp.value.str.val = empty_string;
+                    break;
+                }
+        
+                if (buf == NULL) buf = emalloc(result->longreadlen + 1);
+                rc = SQLGetData(result->stmt, (UWORD)(i + 1),sql_c_type,
+                                                               buf, result->longreadlen + 1, &result->values[i].vallen);
+
+                if (rc == SQL_ERROR) {
+                                       UODBC_SQL_ERROR(result->conn_ptr->hdbc, result->stmt, "SQLGetData");
+                                       efree(buf);
+                                       RETURN_FALSE;
+                               }
+                               if (rc == SQL_SUCCESS_WITH_INFO){
+                                       tmp.value.str.len = result->longreadlen;
+                               } else if (result->values[i].vallen == SQL_NULL_DATA){
+                                       tmp.value.str.val = empty_string;
+                                       break;
+                               } else {
+                                       tmp.value.str.len = result->values[i].vallen;
+                               }
+                               tmp.value.str.val = estrndup(buf, tmp.value.str.len);
+                               break;
+
+                       default:
+                               if (result->values[i].vallen == SQL_NULL_DATA){
+                                       tmp.value.str.val = empty_string;
+                                       break;
+                               }
+                               tmp.value.str.len = result->values[i].vallen;
+                               tmp.value.str.val = estrndup(result->values[i].value,tmp.value.str.len);
+                               break;
+               }
+               _php3_hash_index_update(arr->value.ht, i, (void *) &tmp, sizeof(pval), NULL);
+       }
+       if (buf) efree(buf);
+       RETURN_LONG(result->numcols);   
+}
+/* }}} */
+
+#if HAVE_SOLID
+void php3_solid_fetch_prev(INTERNAL_FUNCTION_PARAMETERS)
+{
+       int         res_ind;
+       UODBC_RESULT   *result;
+       RETCODE     rc;
+       pval     *arg1;
+       
+       if (getParameters(ht, 1, &arg1) == FAILURE)
+                           WRONG_PARAM_COUNT;
+       
+       convert_to_long(arg1);
+       res_ind = arg1->value.lval;
+
+       /* check result */
+       if ((result = UODBC_GET_RESULT(list, res_ind)) == NULL) {
+               RETURN_FALSE;
+       }
+
+       if (result->numcols == 0) {
+               php3_error(E_WARNING, "No tuples available at this result index");
+               RETURN_FALSE;
+       }
+       rc = SQLFetchPrev(result->stmt);
+
+       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
+               RETURN_FALSE;
+       }
+
+       if (result->fetched > 1) result->fetched--;
+
+       RETURN_TRUE;
+}
+#endif
+
+/* {{{ proto odbc_fetch_row(int result_id [, int row_number])
+   Fetch a row */
+UODBC_FUNCTION(fetch_row)
+{
+       int         res_ind, numArgs;
+       SDWORD      rownum = 1;
+       UODBC_RESULT   *result;
+       RETCODE     rc;
+       pval            *arg1, *arg2;
+#if HAVE_SQL_EXTENDED_FETCH
+       UDWORD      crow;
+       UWORD       RowStatus[1];
+#endif
+
+       numArgs = ARG_COUNT(ht);
+       if (numArgs ==  1){
+               if (getParameters(ht, 1, &arg1) == FAILURE)
+                       WRONG_PARAM_COUNT;
+       } else {
+               if (getParameters(ht, 2, &arg1, &arg2) == FAILURE)
+                       WRONG_PARAM_COUNT;
+               convert_to_long(arg2);
+               rownum = arg2->value.lval;
+       }
+       
+       convert_to_long(arg1);
+       res_ind = arg1->value.lval;
+       
+       /* check result */
+       if ((result = UODBC_GET_RESULT(list, res_ind)) == NULL) {
+               RETURN_FALSE;
+       }
+       
+       if (result->numcols == 0) {
+               php3_error(E_WARNING, "No tuples available at this result index");
+               RETURN_FALSE;
+       }
+
+#if HAVE_SQL_EXTENDED_FETCH
+    if (result->fetch_abs){
+               if (numArgs > 1)
+                       rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
+               else
+                       rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
+       }else
+#endif
+               rc = SQLFetch(result->stmt);
+
+       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
+               RETURN_FALSE;
+       }
+       
+       if (numArgs > 1) {
+               result->fetched = rownum;
+       } else {
+               result->fetched++;
+       }
+       
+       RETURN_TRUE;
+}      
+/* }}} */
+
+/* {{{ proto odbc_result(int result_id, mixed field)
+   Get result data */ 
+UODBC_FUNCTION(result)
+{
+       char        *field;
+       int         res_ind;
+       int         field_ind;
+       SWORD           sql_c_type = SQL_C_CHAR;
+       UODBC_RESULT   *result;
+       int         i = 0;
+       RETCODE     rc;
+       SDWORD          fieldsize;
+       pval            *arg1, *arg2;
+#if HAVE_SQL_EXTENDED_FETCH
+       UDWORD      crow;
+       UWORD       RowStatus[1];
+#endif
+#if !defined(COMPILE_DL) && defined(THREAD_SAFE)
+       TLS_VARS;
+#endif
+
+       field_ind = -1;
+       field = NULL;
+
+       if (ARG_COUNT(ht) != 2 || getParameters(ht, 2 , &arg1, &arg2) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       
+       convert_to_long(arg1);
+       res_ind = arg1->value.lval;
+
+       if (arg2->type == IS_STRING){
+               field = arg2->value.str.val;
+       } else {
+               convert_to_long(arg2);
+               field_ind = arg2->value.lval - 1;
+       }
+       
+       /* check result */
+       if ((result = UODBC_GET_RESULT(list, res_ind)) == NULL) {
+               RETURN_FALSE;
+       }
+       
+       if ((result->numcols == 0)){
+               php3_error(E_WARNING, "No tuples available at this result index");
+               RETURN_FALSE;
+       }
+       
+       /* get field index if the field parameter was a string */
+       if (field != NULL){
+               for(i = 0; i < result->numcols; i++){
+                       if (!strcasecmp(result->values[i].name, field)){
+                               field_ind = i;
+                               break;
+                       }
+               }
+
+               if (field_ind < 0){
+                       php3_error(E_WARNING, "Field %s not found", field);
+                       RETURN_FALSE;
+               }
+       } else {
+               /* check for limits of field_ind if the field parameter was an int */
+               if (field_ind >= result->numcols || field_ind < 0){
+                       php3_error(E_WARNING, "Field index is larger than the number of fields");
+                       RETURN_FALSE;
+               }
+       }
+
+       if (result->fetched == 0){
+               /* User forgot to call odbc_fetchrow(), let's do it here */
+#if HAVE_SQL_EXTENDED_FETCH
+               if (result->fetch_abs)
+                       rc = SQLExtendedFetch(result->stmt, SQL_FETCH_NEXT, 1, &crow,RowStatus);
+               else
+#endif
+                       rc = SQLFetch(result->stmt);
+
+               if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
+                       RETURN_FALSE;
+               
+               result->fetched++;
+       }
+
+       switch(result->values[field_ind].coltype){
+        case SQL_BINARY:
+        case SQL_VARBINARY:
+        case SQL_LONGVARBINARY:
+            if (result->binmode <= 1) sql_c_type = SQL_C_BINARY;
+            if (result->binmode <= 0) break; 
+        case SQL_LONGVARCHAR:
+            if (IS_SQL_LONG(result->values[field_ind].coltype)){
+               if (result->longreadlen <= 0) 
+                                  break;
+                          else 
+                                  fieldsize = result->longreadlen;
+                       } else {
+                       
+                          SQLColAttributes(result->stmt, (UWORD)(field_ind + 1), 
+                                                               (UWORD)((sql_c_type == SQL_C_BINARY) ? SQL_COLUMN_LENGTH :
+                                                               SQL_COLUMN_DISPLAY_SIZE),
+                                                               NULL, 0, NULL, &fieldsize);
+                       }
+                       /* For char data, the length of the returned string will be longreadlen - 1 */
+                       fieldsize = (result->longreadlen <= 0) ? 4096 : result->longreadlen;
+            field = emalloc(fieldsize);
+            if (!field){
+                php3_error(E_WARNING, "Out of memory");
+                RETURN_FALSE;
+            }
+               /* SQLGetData will truncate CHAR data to fieldsize - 1 bytes and append \0.
+                  For binary data it is truncated to fieldsize bytes. 
+                */
+            rc = SQLGetData(result->stmt, (UWORD)(field_ind + 1), sql_c_type,
+                            field, fieldsize, &result->values[field_ind].vallen);
+            
+            if (rc == SQL_ERROR) {
+                UODBC_SQL_ERROR(result->conn_ptr->hdbc, result->stmt, "SQLGetData");
+                efree(field);
+                RETURN_FALSE;
+            }
+            
+            if (result->values[field_ind].vallen == SQL_NULL_DATA || rc == SQL_NO_DATA_FOUND){
+                efree(field);
+                               RETURN_FALSE;
+            }
+                       /* Reduce fieldlen by 1 if we have char data. One day we might 
+                          have binary strings... */
+                       if (result->values[field_ind].coltype == SQL_LONGVARCHAR) fieldsize -= 1;
+            /* Don't duplicate result, saves one emalloc.
+                          For SQL_SUCCESS, the length is in vallen.
+                        */
+            RETURN_STRINGL(field, (rc == SQL_SUCCESS_WITH_INFO) ? fieldsize :
+                           result->values[field_ind].vallen, 0);
+            break;
+                       
+               default:
+                       if (result->values[field_ind].vallen == SQL_NULL_DATA){
+                               RETURN_FALSE;
+                       } else {
+                               RETURN_STRINGL(result->values[field_ind].value, result->values[field_ind].vallen, 1);
+                       }
+                       break;
+       }
+
+/* If we come here, output unbound LONG and/or BINARY column data to the client */
+
+       
+       /* We emalloc 1 byte more for SQL_C_CHAR (trailing \0) */
+       fieldsize = (sql_c_type == SQL_C_CHAR) ? 4096 : 4095;
+    if ((field = emalloc(fieldsize)) == NULL){
+        php3_error(E_WARNING,"Out of memory");
+        RETURN_FALSE;
+    }
+    
+       /* Call SQLGetData() until SQL_SUCCESS is returned */
+       while (1) {
+        rc = SQLGetData(result->stmt, (UWORD)(field_ind + 1),sql_c_type,
+                            field, fieldsize, &result->values[field_ind].vallen);
+
+               if (rc == SQL_ERROR) {
+                       UODBC_SQL_ERROR(result->conn_ptr->hdbc, result->stmt, "SQLGetData");
+            efree(field);
+                       RETURN_FALSE;
+               }
+        
+        if (result->values[field_ind].vallen == SQL_NULL_DATA){
+            efree(field);
+            RETURN_FALSE;
+        }
+        /* chop the trailing \0 by outputing only 4095 bytes */
+               PHPWRITE(field,(rc == SQL_SUCCESS_WITH_INFO) ? 4095 :
+                           result->values[field_ind].vallen);
+
+               if (rc == SQL_SUCCESS) { /* no more data avail */
+            efree(field);
+                       RETURN_TRUE;
+               }
+       }
+       RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto odbc_result_all(int result_id [, string format])
+   Print result as HTML table */
+UODBC_FUNCTION(result_all)
+{
+       char *buf = NULL;
+       int         res_ind, numArgs;
+       UODBC_RESULT   *result;
+       int         i;
+       RETCODE     rc;
+       pval     *arg1, *arg2;
+       SWORD sql_c_type;
+#if HAVE_SQL_EXTENDED_FETCH
+       UDWORD      crow;
+       UWORD       RowStatus[1];
+#endif
+#if !defined(COMPILE_DL) && defined(THREAD_SAFE)
+       TLS_VARS
+#endif
+
+       numArgs = ARG_COUNT(ht);
+       if (numArgs ==  1){
+               if (getParameters(ht, 1, &arg1) == FAILURE)
+                       WRONG_PARAM_COUNT;
+       } else {
+               if (getParameters(ht, 2, &arg1, &arg2) == FAILURE)
+                       WRONG_PARAM_COUNT;
+       }
+                               
+       convert_to_long(arg1);
+       res_ind = arg1->value.lval;
+       
+       /* check result */
+       if ((result = UODBC_GET_RESULT(list, res_ind)) == NULL) {
+               RETURN_FALSE;
+       }
+       
+       if (result->numcols == 0){
+               php3_error(E_WARNING, "No tuples available at this result index");
+               RETURN_FALSE;
+       }
+#if HAVE_SQL_EXTENDED_FETCH
+       if (result->fetch_abs)
+               rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
+       else
+#endif 
+               rc = SQLFetch(result->stmt);
+
+       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
+               php3_printf("<h2>No rows found</h2>\n");
+               RETURN_LONG(0);
+       }
+       
+       /* Start table tag */
+       if (numArgs == 1){
+               php3_printf("<table><tr>");
+       } else {
+               convert_to_string(arg2);        
+               php3_printf("<table %s ><tr>",arg2->value.str.val); 
+       }
+       
+       for(i = 0; i < result->numcols; i++)
+               php3_printf("<th>%s</th>", result->values[i].name);
+
+       php3_printf("</tr>\n");
+
+       while(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO){
+               result->fetched++;
+               php3_printf("<tr>");
+               for(i = 0; i < result->numcols; i++){
+            sql_c_type = SQL_C_CHAR;
+            switch(result->values[i].coltype){
+                case SQL_BINARY:
+                case SQL_VARBINARY:
+                case SQL_LONGVARBINARY:
+                    if (result->binmode <= 0){
+                        php3_printf("<td>Not printable</td>");
+                        break;
+                    }
+                    if (result->binmode <= 1) sql_c_type = SQL_C_BINARY; 
+                case SQL_LONGVARCHAR:
+                    if (IS_SQL_LONG(result->values[i].coltype) && 
+                       result->longreadlen <= 0){
+                        php3_printf("<td>Not printable</td>"); 
+                        break;
+                    }
+        
+                    if (buf == NULL) buf = emalloc(result->longreadlen);
+                    
+                    rc = SQLGetData(result->stmt, (UWORD)(i + 1),sql_c_type,
+                                    buf, result->longreadlen, &result->values[i].vallen);
+                    
+                    php3_printf("<td>");
+
+                    if (rc == SQL_ERROR) {
+                        UODBC_SQL_ERROR(result->conn_ptr->hdbc, result->stmt, "SQLGetData");
+                        php3_printf("</td></tr></table>");
+                        efree(buf);
+                        RETURN_FALSE;
+                    }
+                    if (rc == SQL_SUCCESS_WITH_INFO)
+                        php3_printf(buf,result->longreadlen);
+                    else if (result->values[i].vallen == SQL_NULL_DATA){
+                                               php3_printf("&nbsp;</td>");
+                                               break;
+                    }
+                   else
+                   {
+                       php3_printf(buf, result->values[i].vallen);
+                   }
+                    php3_printf("</td>");
+                    break;
+
+                default:
+                    if (result->values[i].vallen == SQL_NULL_DATA){
+                        php3_printf("<td>&nbsp;</td>");
+                    } else {
+                        php3_printf("<td>%s</td>", result->values[i].value);
+                    }
+                    break;
+            }
+               }
+               php3_printf("</tr>\n");
+
+#if HAVE_SQL_EXTENDED_FETCH
+               if (result->fetch_abs)
+                       rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
+               else
+#endif
+                       rc = SQLFetch(result->stmt);            
+       }
+       php3_printf("</table>\n");
+    if (buf) efree(buf);
+       RETURN_LONG(result->fetched);
+}
+/* }}} */
+
+/* {{{ proto odbc_free_result(int result_id)
+   Free resources associated with a result */
+UODBC_FUNCTION(free_result)
+{
+       pval *arg1;
+       
+       if ( getParameters(ht, 1, &arg1) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(arg1);
+       UODBC_DEL_RESULT(list, arg1->value.lval);
+       RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto odbc_connect(string DSN, string user, string password [, int cursor_option])
+   Connect to a datasource */
+UODBC_FUNCTION(connect)
+{
+       PHP3_UODBC_DO_CONNECT(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto odbc_connect(string DSN, string user, string password [, int cursor_option])
+   Establish a persistant connection to a datasource */
+UODBC_FUNCTION(pconnect)
+{
+       PHP3_UODBC_DO_CONNECT(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* Persistent connections: two list-types le_pconn, le_conn and a plist
+ * where hashed connection info is stored together with index pointer to
+ * the actual link of type le_pconn in the list. Only persistent 
+ * connections get hashed up. Normal connections use existing pconnections.
+ * Maybe this has to change with regard to transactions on pconnections?
+ * Possibly set autocommit to on on request shutdown.
+ *
+ * We do have to hash non-persistent connections, and reuse connections.
+ * In the case where two connects were being made, without closing the first
+ * connect, access violations were occuring.  This is because some of the
+ * "globals" in this module should actualy be per-connection variables.  I
+ * simply fixed things to get them working for now.  Shane
+ */
+void PHP3_UODBC_DO_CONNECT(INTERNAL_FUNCTION_PARAMETERS, int persistent)
+{
+       char    *db = NULL;
+       char    *uid = NULL;
+       char    *pwd = NULL;
+       pval *arg1, *arg2, *arg3, *arg4;
+       UODBC_CONNECTION *db_conn;
+       RETCODE rc;
+       list_entry *index_ptr;
+       char *hashed_details;
+       int hashed_len, len, id, cur_opt;
+       int type;
+       UODBC_TLS_VARS;
+
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).resource_list = list;
+       UODBC_GLOBAL(PHP3_UODBC_MODULE).resource_plist = plist;
+
+       /*  Now an optional 4th parameter specifying the cursor type
+        *  defaulting to the cursors default
+        */
+       switch(ARG_COUNT(ht)) {
+               case 3: 
+                       if (getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       /* Use Default: Probably a better way to do this */
+                       cur_opt = SQL_CUR_DEFAULT;
+                       break;
+               case 4:
+                       if (getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_long(arg4);
+                       cur_opt = arg4->value.lval;
+
+                       /* Confirm the cur_opt range */
+                       if (! (cur_opt == SQL_CUR_USE_IF_NEEDED || 
+                               cur_opt == SQL_CUR_USE_ODBC || 
+                               cur_opt == SQL_CUR_USE_DRIVER || 
+                               cur_opt == SQL_CUR_DEFAULT) ) {
+                               php3_error(E_WARNING, "uODBC: Invalid Cursor type (%d)", cur_opt);
+                               RETURN_FALSE;
+                       }
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+                       break;
+       }
+
+       convert_to_string(arg1);
+       convert_to_string(arg2);
+       convert_to_string(arg3);
+
+       db = arg1->value.str.val;
+       uid = arg2->value.str.val;
+       pwd = arg3->value.str.val;
+
+       if (UODBC_GLOBAL(PHP3_UODBC_MODULE).allow_persistent <= 0) {
+               persistent = 0;
+       }
+
+       if (UODBC_GLOBAL(PHP3_UODBC_MODULE).max_links != -1 &&
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).num_links >=
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).max_links) {
+               php3_error(E_WARNING, "uODBC: Too many open links (%d)",
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).num_links);
+               RETURN_FALSE;
+       }
+
+       /* the user requested a persistent connection */
+       if (persistent && 
+                       UODBC_GLOBAL(PHP3_UODBC_MODULE).max_persistent != -1 &&
+                       UODBC_GLOBAL(PHP3_UODBC_MODULE).num_persistent >=
+                       UODBC_GLOBAL(PHP3_UODBC_MODULE).max_persistent) {
+               php3_error(E_WARNING,"uODBC: Too many open persistent links (%d)",
+                                       UODBC_GLOBAL(PHP3_UODBC_MODULE).num_persistent);
+               RETURN_FALSE;
+       }
+
+       len = strlen(db) + strlen(uid) + strlen(pwd) + strlen(UODBC_NAME) + 5; 
+       hashed_details = emalloc(len);
+
+       if (hashed_details == NULL) {
+               php3_error(E_WARNING, "Out of memory");
+               RETURN_FALSE;
+       }
+
+       hashed_len = _php3_sprintf(hashed_details, "%s_%s_%s_%s_%d", UODBC_NAME, db, uid, pwd, cur_opt);
+
+       /* FIXME the idea of checking to see if our connection is already persistent
+               is good, but it adds a lot of overhead to non-persistent connections.  We
+               should look and see if we can fix that somehow */
+       /* try to find if we already have this link in our persistent list,
+        * no matter if it is to be persistent or not
+        */
+
+       if ((persistent || (_php3_hash_find(list, hashed_details, hashed_len + 1,
+                 (void **) &index_ptr) == FAILURE || !php3_list_find((int) index_ptr->ptr, &type))) &&
+                 _php3_hash_find(plist, hashed_details, hashed_len + 1,
+                 (void **) &index_ptr) == FAILURE) {
+               /* the link is not in the persistent list */
+               list_entry new_le, new_index_ptr;
+
+               if (persistent) {
+                       db_conn = (UODBC_CONNECTION *)malloc(sizeof(UODBC_CONNECTION));
+               } else {
+                       db_conn = (UODBC_CONNECTION *)emalloc(sizeof(UODBC_CONNECTION));
+               }
+
+               SQLAllocConnect(UODBC_GLOBAL(PHP3_UODBC_MODULE).henv, &db_conn->hdbc);
+#if HAVE_SOLID
+               SQLSetConnectOption(db_conn->hdbc, SQL_TRANSLATE_OPTION,
+                                                       SQL_SOLID_XLATOPT_NOCNV);
+#endif
+#if HAVE_OPENLINK
+               {
+                       char dsnbuf[300];
+                       short dsnbuflen;
+
+                       rc = SQLDriverConnect(db_conn->hdbc, NULL, db, SQL_NTS,
+                                                                 dsnbuf, sizeof(dsnbuf)-1, &dsnbuflen,
+                                                                 SQL_DRIVER_COMPLETE);
+               }
+#else
+               if(cur_opt != SQL_CUR_DEFAULT){
+                       rc = SQLSetConnectOption(db_conn->hdbc, SQL_ODBC_CURSORS, cur_opt);
+                       if (rc != SQL_SUCCESS ) {  /* && rc != SQL_SUCCESS_WITH_INFO ? */
+                               UODBC_SQL_ERROR(db_conn->hdbc, SQL_NULL_HSTMT, "SQLSetConnectOption");
+                               SQLFreeConnect(db_conn->hdbc);
+                               if (persistent)
+                                       free(db_conn);
+                               else
+                                       efree(db_conn);
+                               RETURN_FALSE;
+                       }
+               }
+
+#if HAVE_EMPRESS
+                {
+                        int     direct = 0;
+                        char    dsnbuf[300];
+                        short   dsnbuflen;
+                        char    *ldb = 0;
+
+                        if (strstr ((char*)db, ";"))
+                        {
+                                direct = 1;
+                                if (uid && !strstr ((char*)db, "uid") &&
+                                                !strstr ((char*)db, "UID"))
+                                {
+                                        ldb = (char*) emalloc (strlen(db) +
+                                                        strlen (uid) +
+                                                        strlen (pwd) + 12);
+                                        sprintf (ldb, "%s;UID=%s;PWD=%s",
+                                                                db, uid, pwd);
+                                }
+                                else
+                                {
+                                        ldb = (char*) emalloc (strlen (db) + 1);
+                                        strcat (ldb, db);
+                                }
+                        }
+
+                        if (direct)
+                                rc = SQLDriverConnect (db_conn->hdbc, NULL,
+                                        ldb, strlen (ldb), dsnbuf, 300,
+                                        &dsnbuflen, SQL_DRIVER_NOPROMPT);
+
+                        else
+                                rc = SQLConnect(db_conn->hdbc, db, SQL_NTS,
+                                                uid, SQL_NTS, pwd, SQL_NTS);
+
+                        if (ldb)
+                                efree (ldb);
+                }
+#else
+               rc = SQLConnect(db_conn->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
+
+#endif
+
+#endif
+               if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
+                       UODBC_SQL_ERROR(db_conn->hdbc, SQL_NULL_HSTMT, "SQLConnect");
+                       SQLFreeConnect(db_conn->hdbc);
+                       if (persistent)
+                               free(db_conn);
+                       else
+                               efree(db_conn);
+                       RETURN_FALSE;
+               }
+               db_conn->open = 1;
+               if (persistent){
+                       new_le.type = UODBC_GLOBAL(PHP3_UODBC_MODULE).le_pconn;
+                       new_le.ptr = db_conn;
+                       return_value->value.lval = 
+                               php3_plist_insert(db_conn, UODBC_GLOBAL(PHP3_UODBC_MODULE).le_pconn);
+                       new_index_ptr.ptr = (void *) return_value->value.lval;
+#ifdef THREAD_SAFE
+                       new_index_ptr.type = _php3_le_index_ptr();
+#else
+                       new_index_ptr.type = le_index_ptr;
+#endif
+                       if (_php3_hash_update(plist,hashed_details,hashed_len + 1,(void *) &new_index_ptr,
+                                       sizeof(list_entry),NULL)==FAILURE) {
+                               SQLDisconnect(db_conn->hdbc);
+                               SQLFreeConnect(db_conn->hdbc);
+                               free(db_conn);
+                               efree(hashed_details);
+                               RETURN_FALSE;
+                       }
+                       UODBC_GLOBAL(PHP3_UODBC_MODULE).num_persistent++;
+               } else {
+                       new_le.type = UODBC_GLOBAL(PHP3_UODBC_MODULE).le_conn;
+                       new_le.ptr = db_conn;
+                       return_value->value.lval = 
+                               php3_list_insert(db_conn, UODBC_GLOBAL(PHP3_UODBC_MODULE).le_conn);
+                       new_index_ptr.ptr = (void *) return_value->value.lval;
+#ifdef THREAD_SAFE
+                       new_index_ptr.type = _php3_le_index_ptr();
+#else
+                       new_index_ptr.type = le_index_ptr;
+#endif
+                       if (_php3_hash_update(list,hashed_details,hashed_len + 1,(void *) &new_index_ptr,
+                                       sizeof(list_entry),NULL)==FAILURE) {
+                               SQLDisconnect(db_conn->hdbc);
+                               SQLFreeConnect(db_conn->hdbc);
+                               efree(db_conn);
+                               efree(hashed_details);
+                               RETURN_FALSE;
+                       }
+               }
+
+               UODBC_GLOBAL(PHP3_UODBC_MODULE).num_links++;
+
+       } else {
+               /* we are already connected */
+#ifdef THREAD_SAFE
+               if (index_ptr->type != _php3_le_index_ptr()) {
+#else
+               if (index_ptr->type != le_index_ptr) {
+#endif
+                       efree(hashed_details);
+                       RETURN_FALSE;
+               }
+               id = (int) index_ptr->ptr;
+
+               /* first see if there is a persistent connection and use it,
+                       else, if we are making a non-persistent connect, check our
+                       non-persistent list */
+               db_conn = (UODBC_CONNECTION *)php3_plist_find(id, &type);
+               if(!db_conn && !persistent)
+                       db_conn = (UODBC_CONNECTION *)php3_list_find(id, &type);
+
+
+               /* FIXME test if the connection is dead */
+               /* For Adabas D and local db connections, a reconnect is performed
+                * implicitly when needed. Cool.
+                */
+
+               if (db_conn && (type ==  UODBC_GLOBAL(PHP3_UODBC_MODULE).le_conn ||
+                                       type == UODBC_GLOBAL(PHP3_UODBC_MODULE).le_pconn)){
+                       return_value->value.lval = id;
+               } else {
+                       efree(hashed_details);
+                       RETURN_FALSE;
+               }
+       }
+       efree(hashed_details);
+       return_value->type = IS_LONG;
+}
+
+/* {{{ proto odbc_close(int connection_id)
+   Close an ODBC connection */
+UODBC_FUNCTION(close)
+{
+       pval *arg1;
+       HDBC conn;
+       int type, ind;
+       UODBC_TLS_VARS;
+
+    if (getParameters(ht, 1, &arg1) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(arg1);
+       ind = (int)arg1->value.lval;
+       conn = (HDBC)php3_list_find(ind, &type);
+       if (!conn ||
+               (type != UODBC_GLOBAL(PHP3_UODBC_MODULE).le_conn &&
+                type != UODBC_GLOBAL(PHP3_UODBC_MODULE).le_pconn)) {
+               return;
+       }
+       php3_list_delete(ind);
+}
+/* }}} */
+
+/* {{{ proto odbc_num_rows(int result_id)
+   Get number of rows in a result */
+UODBC_FUNCTION(num_rows)
+{
+       UODBC_RESULT   *result;
+       SDWORD      rows;
+       pval    *arg1;
+       
+       if ( getParameters(ht, 1, &arg1) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }            
+
+       convert_to_long(arg1);
+
+       if ((result = UODBC_GET_RESULT(list, arg1->value.lval)) == NULL) {
+               RETURN_FALSE;
+       }
+
+       SQLRowCount(result->stmt, &rows);
+       RETURN_LONG(rows);
+}
+/* }}} */
+
+/* {{{ proto odbc_num_fields(int result_id)
+   Get number of columns in a result */
+UODBC_FUNCTION(num_fields)
+{
+       UODBC_RESULT   *result;
+       pval     *arg1;
+
+       if ( getParameters(ht, 1, &arg1) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }                            
+    convert_to_long(arg1);
+        
+       if ((result = UODBC_GET_RESULT(list, arg1->value.lval)) == NULL) {
+               RETURN_FALSE;
+       }
+       RETURN_LONG(result->numcols);
+}
+/* }}} */
+
+/* {{{ proto odbc_field_name(int result_id, int field_number)
+   Get a column name */
+UODBC_FUNCTION(field_name)
+{
+       UODBC_RESULT       *result;
+       pval     *arg1, *arg2;
+       
+       if (getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       convert_to_long(arg1);
+       convert_to_long(arg2);
+       
+    if ((result = UODBC_GET_RESULT(list, arg1->value.lval)) == NULL) {
+               RETURN_FALSE;
+       }
+       
+       if (result->numcols == 0){
+               php3_error(E_WARNING, "No tuples available at this result index");
+               RETURN_FALSE;
+       }
+       
+       if (arg2->value.lval > result->numcols){
+               php3_error(E_WARNING, "Field index larger than number of fields");
+               RETURN_FALSE;
+       }
+       
+       if (arg2->value.lval < 1){
+               php3_error(E_WARNING, "Field numbering starts at 1");
+               RETURN_FALSE;
+       }
+       
+       RETURN_STRING(result->values[arg2->value.lval - 1].name,1)
+}
+/* }}} */
+
+/* {{{ proto odbc_field_type(int result_id, int field_number)
+   Get the datatype of a column */
+UODBC_FUNCTION(field_type)
+{
+       UODBC_RESULT    *result;
+       char            tmp[32];
+       SWORD           tmplen;
+       pval     *arg1, *arg2;
+
+       if (getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long(arg1);
+       convert_to_long(arg2);
+
+       if ((result = UODBC_GET_RESULT(list, arg1->value.lval)) == NULL) {
+               RETURN_FALSE;
+       }               
+
+       if (result->numcols == 0){
+               php3_error(E_WARNING, "No tuples available at this result index");
+               RETURN_FALSE;
+       }
+
+       if (arg2->value.lval > result->numcols){
+               php3_error(E_WARNING, "Field index larger than number of fields");
+               RETURN_FALSE;
+       }
+
+       SQLColAttributes(result->stmt, (UWORD)arg2->value.lval,
+                                        SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL);
+       RETURN_STRING(tmp,1)
+}
+/* }}} */
+
+/* {{{ proto odbc_field_len(int result_id, int field_number)
+   Get the length of a column */   
+UODBC_FUNCTION(field_len)
+{
+       UODBC_RESULT       *result;
+       SDWORD  len;
+       pval     *arg1, *arg2;
+
+       if (getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long(arg1);
+       convert_to_long(arg2);
+       
+       if ((result = UODBC_GET_RESULT(list, arg1->value.lval)) == NULL) {
+               RETURN_FALSE;
+       }                                                                
+
+       if (result->numcols == 0){
+               php3_error(E_WARNING, "No tuples available at this result index");
+               RETURN_FALSE;
+       }
+       
+       if (arg2->value.lval > result->numcols){
+               php3_error(E_WARNING, "Field index larger than number of fields");
+               RETURN_FALSE;
+       }
+       SQLColAttributes(result->stmt, (UWORD)arg2->value.lval, 
+                                        SQL_COLUMN_PRECISION, NULL, 0, NULL, &len);
+       
+       RETURN_LONG(len);
+}
+/* }}} */
+
+/* {{{ proto odbc_field_num(int result_id, string field_name)
+   Return column number */
+UODBC_FUNCTION(field_num)
+{
+       int         field_ind;
+       char        *fname;
+       UODBC_RESULT *result;
+       int         i;
+       pval     *arg1, *arg2;
+
+       if (getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long(arg1);
+       convert_to_string(arg2);
+       fname = arg2->value.str.val;
+       
+       if (arg1->value.lval == 1){
+               php3_error(E_WARNING, "No tuples available at this result index");
+               RETURN_FALSE;
+       }
+       if ((result = UODBC_GET_RESULT(list, arg1->value.lval)) == NULL) {
+               RETURN_FALSE;
+       }
+       
+       field_ind = -1;
+       for(i = 0; i < result->numcols; i++){
+               if (strcasecmp(result->values[i].name, fname) == 0)
+                       field_ind = i + 1;
+               }
+       if (field_ind == -1)
+               RETURN_FALSE;
+       RETURN_LONG(field_ind);
+}
+/* }}} */
+
+/* {{{ proto odbc_autocommit(int connection_id, int OnOff)
+   Toggle autocommit mode */
+UODBC_FUNCTION(autocommit)
+{
+       UODBC_CONNECTION *curr_conn;
+       RETCODE rc;
+       pval *arg1, *arg2 = NULL;
+       int argc;
+
+       argc = ARG_COUNT(ht);
+       if (argc == 2) {
+               if (getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+                       WRONG_PARAM_COUNT;
+               }
+       } else if (argc == 1) {
+               if (getParameters(ht, 1, &arg1) == FAILURE) {
+                       WRONG_PARAM_COUNT;
+               }
+       } else {
+               WRONG_PARAM_COUNT;
+       }
+    convert_to_long(arg1);
+       if (arg2) {
+               convert_to_long(arg2);
+       }
+
+       if ((curr_conn = UODBC_GET_CONN(list, arg1->value.lval)) == NULL) {
+               RETURN_FALSE;
+       }
+
+       if (arg2) {
+               rc = SQLSetConnectOption(curr_conn->hdbc, SQL_AUTOCOMMIT,
+                                                                (arg2->value.lval) ?
+                                                                SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
+               if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
+                       UODBC_SQL_ERROR(curr_conn->hdbc, SQL_NULL_HSTMT, "Set autocommit");
+                       RETURN_FALSE;
+               }
+               RETVAL_TRUE;
+       } else {
+               SDWORD status;
+
+               rc = SQLGetConnectOption(curr_conn->hdbc, SQL_AUTOCOMMIT, (PTR)&status);
+               if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
+                       UODBC_SQL_ERROR(curr_conn->hdbc, SQL_NULL_HSTMT, "Test autocommit");
+                       RETURN_FALSE;
+               }
+               RETVAL_LONG((long)status);
+       }
+}
+/* }}} */
+
+void PHP3_UODBC_TRANSACT(INTERNAL_FUNCTION_PARAMETERS, int type)
+{
+       UODBC_CONNECTION *curr_conn;
+       RETCODE rc;
+       pval *arg1;
+       UODBC_TLS_VARS;
+
+       if ( getParameters(ht, 1, &arg1) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }                            
+    convert_to_long(arg1);
+
+       if ((curr_conn = UODBC_GET_CONN(list, arg1->value.lval)) == NULL){
+               RETURN_FALSE;
+       }
+
+       rc = SQLTransact(UODBC_GLOBAL(PHP3_UODBC_MODULE).henv, curr_conn->hdbc, (UWORD)((type)?SQL_COMMIT:SQL_ROLLBACK));
+       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
+               UODBC_SQL_ERROR(curr_conn->hdbc, SQL_NULL_HSTMT, "SQLTransact");
+               RETURN_FALSE;
+       }
+
+       RETURN_TRUE;
+}
+
+/* {{{ proto odbc_commit(int connection_id)
+   Commit an ODBC transaction */
+UODBC_FUNCTION(commit)
+{
+       PHP3_UODBC_TRANSACT(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto odbc_rollback(int connection_id)
+   Rollback a transaction */
+UODBC_FUNCTION(rollback)
+{
+       PHP3_UODBC_TRANSACT(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto odbc_setoption(??)
+   ?? */
+UODBC_FUNCTION(setoption)
+{
+       UODBC_CONNECTION *curr_conn;
+       UODBC_RESULT    *result;
+       RETCODE rc;
+       pval *arg1, *arg2, *arg3, *arg4;
+
+       if ( getParameters(ht, 3, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }                            
+       convert_to_long(arg1);
+       convert_to_long(arg2);
+       convert_to_long(arg3);
+       convert_to_long(arg4);
+
+       switch (arg2->value.lval) {
+               case 1:         /* SQLSetConnectOption */
+                       if ((curr_conn = UODBC_GET_CONN(list, arg1->value.lval)) == NULL){
+                               RETURN_FALSE;
+                       }
+                       rc = SQLSetConnectOption(curr_conn->hdbc, (unsigned short)(arg3->value.lval), (arg4->value.lval));
+                       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
+                               UODBC_SQL_ERROR(curr_conn->hdbc, SQL_NULL_HSTMT, "SetConnectOption");
+                               RETURN_FALSE;
+                       }
+                       break;
+               case 2:         /* SQLSetStmtOption */
+                       if ((result = UODBC_GET_RESULT(list, arg1->value.lval)) == NULL) {
+                               RETURN_FALSE;
+                       }
+                       rc = SQLSetStmtOption(result->stmt, (unsigned short)(arg3->value.lval), (arg4->value.lval));
+                       if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){
+                               UODBC_SQL_ERROR(result->conn_ptr->hdbc, result->stmt, "SetStmtOption");
+                               RETURN_FALSE;
+                       }
+                       break;
+               default:
+                       php3_error(E_WARNING, "Unknown option type");
+                       RETURN_FALSE;
+                       break;
+       }
+
+       RETURN_TRUE;
+}
+/* }}} */
+
+#endif /* HAVE_UODBC */
+
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/odbc/php3_odbc.h b/ext/odbc/php3_odbc.h
new file mode 100644 (file)
index 0000000..1357553
--- /dev/null
@@ -0,0 +1,729 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP HTML Embedded Scripting Language Version 3.0                     |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997,1998 PHP Development Team (See Credits file)      |
+   +----------------------------------------------------------------------+
+   | This program is free software; you can redistribute it and/or modify |
+   | it under the terms of one of the following licenses:                 |
+   |                                                                      |
+   |  A) the GNU General Public License as published by the Free Software |
+   |     Foundation; either version 2 of the License, or (at your option) |
+   |     any later version.                                               |
+   |                                                                      |
+   |  B) the PHP License as published by the PHP Development Team and     |
+   |     included in the distribution in the file: LICENSE                |
+   |                                                                      |
+   | This program is distributed in the hope that it will be useful,      |
+   | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
+   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
+   | GNU General Public License for more details.                         |
+   |                                                                      |
+   | You should have received a copy of both licenses referred to here.   |
+   | If you did not, or have any questions about PHP licensing, please    |
+   | contact core@php.net.                                                |
+   +----------------------------------------------------------------------+
+   | Authors: Stig Sæther Bakken <ssb@guardian.no>                        |
+   |          Andreas Karajannis <Andreas.Karajannis@gmd.de>              |
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef _UNIFIED_ODBC_H
+#define _UNIFIED_ODBC_H
+
+#if HAVE_UODBC
+
+/*these defines are used to seperate the different
+database modules that use the uodbc interface so that
+two or more of them can be compiled into the same
+php binary*/
+
+/*
+*
+*  Defines for ODBC
+*
+*/
+#if HAVE_UODBC
+/* win32 vars for thread local storage */
+#define UODBC_MUTEX uodbc_mutex
+#define UODBC_TLS UODBCTls
+#define UODBC_GLOBAL_STRUCT uodbc_global_struct
+#define UODBC_GLOBALS uodbc_globals
+/* defines for variables, structs, etc */
+#define UODBC_MODULE_NAME "ODBC (uODBC)"
+#define UODBC_FUNCTIONS uodbc_functions
+#define UODBC_MODULE_ENTRY uodbc_module_entry
+#define UODBC_CONNECTION uodbc_connection
+#define UODBC_RESULT_VALUE uodbc_result_value
+#define UODBC_RESULT uodbc_result
+#define UODBC_MODULE uodbc_module
+#define PHP3_UODBC_MODULE php3_uodbc_module
+
+/* function defines */
+#define PHP3_MINIT_UODBC php3_minit_uodbc
+#define PHP3_MSHUTDOWN_UODBC php3_mshutdown_uodbc
+#define PHP3_RINIT_UODBC php3_rinit_uodbc
+#define PHP3_INFO_UODBC php3_info_uodbc
+#define PHP3_UODBC_SETOPTION php3_uodbc_setoption
+#define PHP3_UODBC_AUTOCOMMIT php3_uodbc_autocommit
+#define PHP3_UODBC_CLOSE php3_uodbc_close
+#define PHP3_UDOBC_CLOSE_ALL php3_uodbc_close_all
+#define PHP3_UODBC_COMMIT php3_uodbc_commit
+#define PHP3_UODBC_CONNECT php3_uodbc_connect
+#define PHP3_UODBC_PCONNECT php3_uodbc_pconnect
+#define PHP3_UODBC_DO_CONNECT php3_uodbc_do_connect
+#define PHP3_UODBC_CURSOR php3_uodbc_cursor
+#define PHP3_UODBC_DO php3_uodbc_do
+#define PHP3_UODBC_EXECUTE php3_uodbc_execute
+#define PHP3_UODBC_FETCH_INTO php3_uodbc_fetch_into
+#define PHP3_UODBC_FETCH_ROW php3_uodbc_fetch_row
+#define PHP3_UODBC_FIELD_LEN php3_uodbc_field_len
+#define PHP3_UODBC_FIELD_NAME php3_uodbc_field_name
+#define PHP3_UODBC_FIELD_TYPE php3_uodbc_field_type
+#define PHP3_UODBC_FIELD_NUM php3_uodbc_field_num
+#define PHP3_UODBC_FREE_RESULT php3_uodbc_free_result
+#define PHP3_UODBC_NUM_FIELDS php3_uodbc_num_fields
+#define PHP3_UODBC_NUM_ROWS php3_uodbc_num_rows
+#define PHP3_UODBC_PREPARE php3_uodbc_prepare
+#define PHP3_UODBC_RESULT php3_uodbc_result
+#define PHP3_UODBC_RESULT_ALL php3_uodbc_result_all
+#define PHP3_UODBC_ROLLBACK php3_uodbc_rollback
+#define PHP3_UODBC_TRANSACT php3_uodbc_transact
+#define PHP3_UODBC_BINMODE php3_uodbc_binmode
+#define PHP3_UODBC_LONGREADLEN php3_uodbc_longreadlen
+
+/* internal function defines */
+#define UODBC_ADD_RESULT uodbc_add_result
+#define UODBC_GET_RESULT uodbc_get_result
+#define UODBC_DEL_RESULT uodbc_del_result
+#define UODBC_ADD_CONN uodbc_add_conn
+#define UODBC_GET_CONN uodbc_get_conn
+#define UODBC_DEL_CONN uodbc_del_conn
+#define UODBC_SQL_ERROR uodbc_sql_error
+#define UODBC_BINDCOLS uodbc_bindcols
+#define _FREE_UODBC_RESULT _free_uodbc_result
+#define _CLOSE_UODBC_CONNECTION _close_uodbc_connection
+#define _CLOSE_UODBC_PCONNECTION _close_uodbc_pconnection
+/* function name defines */
+#define ODBC_SETOPTION "odbc_setoption"
+#define ODBC_AUTOCOMMIT "odbc_autocommit"
+#define ODBC_CLOSE "odbc_close"
+#define ODBC_CLOSE_ALL "odbc_close_all"
+#define ODBC_COMMIT "odbc_commit"
+#define ODBC_CONNECT "odbc_connect"
+#define ODBC_PCONNECT "odbc_pconnect"
+#define ODBC_CURSOR "odbc_cursor"
+#define ODBC_DO "odbc_do"
+#define ODBC_EXEC "odbc_exec"
+#define ODBC_PREPARE "odbc_prepare"
+#define ODBC_EXECUTE "odbc_execute"
+#define ODBC_FETCH_ROW "odbc_fetch_row"
+#define ODBC_FETCH_INTO "odbc_fetch_into"
+#define ODBC_FIELD_LEN "odbc_field_len"
+#define ODBC_FIELD_NAME "odbc_field_name"
+#define ODBC_FIELD_TYPE "odbc_field_type"
+#define ODBC_FIELD_NUM "odbc_field_num"
+#define ODBC_FREE_RESULT "odbc_free_result"
+#define ODBC_NUM_FIELDS "odbc_num_fields"
+#define ODBC_NUM_ROWS "odbc_num_rows"
+#define ODBC_RESULT "odbc_result"
+#define ODBC_RESULT_ALL "odbc_result_all"
+#define ODBC_ROLLBACK "odbc_rollback"
+#define ODBC_TRANSACT "odbc_transact"
+#define ODBC_DO_CONNECT "odbc_do_connect"
+#define ODBC_LONGREADLEN "odbc_longreadlen"
+#define ODBC_BINMODE "odbc_binmode"
+
+/* ini variable defines */
+#define ODBC_INI_DEFAULTDB "uodbc.default_db"
+#define ODBC_INI_DEFAULTUSER "uodbc.default_user"
+#define ODBC_INI_DEFAULTPW "uodbc.default_pw"
+#define ODBC_INI_ALLOWPERSISTENT "uodbc.allow_persistent"
+#define ODBC_INI_MAXPERSISTENT "uodbc.max_persistent"
+#define ODBC_INI_MAXLINKS "uodbc.max_links"
+#define ODBC_INI_DEFAULTLRL "uodbc.defaultlrl"
+#define ODBC_INI_DEFAULTBINMODE "uodbc.defaultbinmode"
+#endif
+
+/*
+*
+*  Defines for SOLID
+*
+*/
+
+
+#if 0 /* HAVE_SOLID turned off for now,
+               will use above uodbc defines for now */
+/* win32 vars for thread local storage */
+#define UODBC_MUTEX solid_mutex
+#define UODBC_TLS SOLIDTls
+#define UODBC_GLOBAL_STRUCT solid_global_struct
+#define UODBC_GLOBALS solid_globals
+/* defines for variables, structs, etc */
+#define UODBC_MODULE_NAME "SOLID (uODBC)"
+#define UODBC_FUNCTIONS solid_functions
+#define UODBC_MODULE_ENTRY solid_module_entry
+#define UODBC_CONNECTION solid_connection
+#define UODBC_RESULT_VALUE solid_result_value
+#define UODBC_RESULT solid_result
+#define UODBC_MODULE solid_module
+#define PHP3_UODBC_MODULE php3_solid_module
+
+/* function defines */
+#define PHP3_MINIT_UODBC php3_minit_solid
+#define PHP3_MSHUTDOWN_UODBC php3_mshutdown_solid
+#define PHP3_RINIT_UODBC php3_rinit_solid
+#define PHP3_INFO_UODBC php3_info_solid
+#define PHP3_UODBC_SETOPTION php3_solid_setoption
+#define PHP3_UODBC_AUTOCOMMIT php3_solid_autocommit
+#define PHP3_UODBC_CLOSE php3_solid_close
+#define PHP3_UDOBC_CLOSE_ALL php3_solid_close_all
+#define PHP3_UODBC_COMMIT php3_solid_commit
+#define PHP3_UODBC_CONNECT php3_solid_connect
+#define PHP3_UODBC_PCONNECT php3_solid_pconnect
+#define PHP3_UODBC_DO_CONNECT php3_solid_do_connect
+#define PHP3_UODBC_CURSOR php3_solid_cursor
+#define PHP3_UODBC_DO php3_solid_do
+#define PHP3_UODBC_EXECUTE php3_solid_execute
+#define PHP3_UODBC_FETCH_INTO php3_solid_fetch_into
+#define PHP3_UODBC_FETCH_ROW php3_solid_fetch_row
+#define PHP3_UODBC_FIELD_LEN php3_solid_field_len
+#define PHP3_UODBC_FIELD_NAME php3_solid_field_name
+#define PHP3_UODBC_FIELD_TYPE php3_solid_field_type
+#define PHP3_UODBC_FREE_RESULT php3_solid_free_result
+#define PHP3_UODBC_NUM_FIELDS php3_solid_num_fields
+#define PHP3_UODBC_NUM_ROWS php3_solid_num_rows
+#define PHP3_UODBC_PREPARE php3_solid_prepare
+#define PHP3_UODBC_RESULT php3_solid_result
+#define PHP3_UODBC_RESULT_ALL php3_solid_result_all
+#define PHP3_UODBC_ROLLBACK php3_solid_rollback
+#define PHP3_UODBC_TRANSACT php3_solid_transact
+
+/* internal function defines */
+#define UODBC_ADD_RESULT solid_add_result
+#define UODBC_GET_RESULT solid_get_result
+#define UODBC_DEL_RESULT solid_del_result
+#define UODBC_ADD_CONN solid_add_conn
+#define UODBC_GET_CONN solid_get_conn
+#define UODBC_DEL_CONN solid_del_conn
+#define UODBC_SQL_ERROR solid_sql_error
+#define UODBC_BINDCOLS solid_bindcols
+#define _FREE_UODBC_RESULT _free_solid_result
+#define _CLOSE_UODBC_CONNECTION _close_solid_connection
+#define _CLOSE_UODBC_PCONNECTION _close_solid_pconnection
+/* function name defines */
+#define ODBC_SETOPTION "solid_setoption"
+#define ODBC_AUTOCOMMIT "solid_autocommit"
+#define ODBC_CLOSE "solid_close"
+#define ODBC_CLOSE_ALL "solid_close_all"
+#define ODBC_COMMIT "solid_commit"
+#define ODBC_CONNECT "solid_connect"
+#define ODBC_PCONNECT "solid_pconnect"
+#define ODBC_CURSOR "solid_cursor"
+#define ODBC_DO "solid_do"
+#define ODBC_EXEC "solid_exec"
+#define ODBC_PREPARE "solid_prepare"
+#define ODBC_EXECUTE "solid_execute"
+#define ODBC_FETCH_ROW "solid_fetch_row"
+#define ODBC_FETCH_INTO "solid_fetch_into"
+#define ODBC_FIELD_LEN "solid_field_len"
+#define ODBC_FIELD_NAME "solid_field_name"
+#define ODBC_FIELD_TYPE "solid_field_type"
+#define ODBC_FREE_RESULT "solid_free_result"
+#define ODBC_NUM_FIELDS "solid_num_fields"
+#define ODBC_NUM_ROWS "solid_num_rows"
+#define ODBC_RESULT "solid_result"
+#define ODBC_RESULT_ALL "solid_result_all"
+#define ODBC_ROLLBACK "solid_rollback"
+#define ODBC_TRANSACT "solid_transact"
+#define ODBC_DO_CONNECT "solid_do_connect"
+
+/* ini variable defines */
+#define ODBC_INI_DEFAULTDB "solid.default_db"
+#define ODBC_INI_DEFAULTUSER "solid.default_user"
+#define ODBC_INI_DEFAULTPW "solid.default_pw"
+#define ODBC_INI_ALLOWPERSISTENT "solid.allow_persistent"
+#define ODBC_INI_MAXPERSISTENT "solid.max_persistent"
+#define ODBC_INI_MAXLINKS "solid.max_links"
+#endif
+
+
+/*
+*
+*  Defines for ADABAS
+*
+*/
+
+
+#if 0 /* HAVE_ADABAS turned for for now, uses
+      defines from the ODBC section */
+/* win32 vars for thread local storage */
+#define UODBC_MUTEX adabas_mutex
+#define UODBC_TLS ADABASTls
+#define UODBC_GLOBAL_STRUCT adabas_global_struct
+#define UODBC_GLOBALS adabas_globals
+/* defines for variables, structs, etc */
+#define UODBC_MODULE_NAME "ADABAS D (uODBC)"
+#define UODBC_FUNCTIONS adabas_functions
+#define UODBC_MODULE_ENTRY adabas_module_entry
+#define UODBC_CONNECTION adabas_connection
+#define UODBC_RESULT_VALUE adabas_result_value
+#define UODBC_RESULT adabas_result
+#define UODBC_MODULE adabas_module
+#define PHP3_UODBC_MODULE php3_adabas_module
+
+/* function defines */
+#define PHP3_MINIT_UODBC php3_minit_adabas
+#define PHP3_MSHUTDOWN_UODBC php3_mshutdown_adabas
+#define PHP3_RINIT_UODBC php3_rinit_adabas
+#define PHP3_INFO_UODBC php3_info_adabas
+#define PHP3_UODBC_SETOPTION php3_adabas_setoption
+#define PHP3_UODBC_AUTOCOMMIT php3_adabas_autocommit
+#define PHP3_UODBC_CLOSE php3_adabas_close
+#define PHP3_UDOBC_CLOSE_ALL php3_adabas_close_all
+#define PHP3_UODBC_COMMIT php3_adabas_commit
+#define PHP3_UODBC_CONNECT php3_adabas_connect
+#define PHP3_UODBC_PCONNECT php3_adabas_pconnect
+#define PHP3_UODBC_DO_CONNECT php3_adabas_do_connect
+#define PHP3_UODBC_CURSOR php3_adabas_cursor
+#define PHP3_UODBC_DO php3_adabas_do
+#define PHP3_UODBC_EXECUTE php3_adabas_execute
+#define PHP3_UODBC_FETCH_INTO php3_adabas_fetch_into
+#define PHP3_UODBC_FETCH_ROW php3_adabas_fetch_row
+#define PHP3_UODBC_FIELD_LEN php3_adabas_field_len
+#define PHP3_UODBC_FIELD_NAME php3_adabas_field_name
+#define PHP3_UODBC_FIELD_TYPE php3_adabas_field_type
+#define PHP3_UODBC_FREE_RESULT php3_adabas_free_result
+#define PHP3_UODBC_NUM_FIELDS php3_adabas_num_fields
+#define PHP3_UODBC_NUM_ROWS php3_adabas_num_rows
+#define PHP3_UODBC_PREPARE php3_adabas_prepare
+#define PHP3_UODBC_RESULT php3_adabas_result
+#define PHP3_UODBC_RESULT_ALL php3_adabas_result_all
+#define PHP3_UODBC_ROLLBACK php3_adabas_rollback
+#define PHP3_UODBC_TRANSACT php3_adabas_transact
+
+/* internal function defines */
+#define UODBC_ADD_RESULT adabas_add_result
+#define UODBC_GET_RESULT adabas_get_result
+#define UODBC_DEL_RESULT adabas_del_result
+#define UODBC_ADD_CONN adabas_add_conn
+#define UODBC_GET_CONN adabas_get_conn
+#define UODBC_DEL_CONN adabas_del_conn
+#define UODBC_SQL_ERROR adabas_sql_error
+#define UODBC_BINDCOLS adabas_bindcols
+#define _FREE_UODBC_RESULT _free_adabas_result
+#define _CLOSE_UODBC_CONNECTION _close_adabas_connection
+#define _CLOSE_UODBC_PCONNECTION _close_adabas_pconnection
+/* function name defines */
+#define ODBC_SETOPTION "adabas_setoption"
+#define ODBC_AUTOCOMMIT "adabas_autocommit"
+#define ODBC_CLOSE "adabas_close"
+#define ODBC_CLOSE_ALL "adabas_close_all"
+#define ODBC_COMMIT "adabas_commit"
+#define ODBC_CONNECT "adabas_connect"
+#define ODBC_PCONNECT "adabas_pconnect"
+#define ODBC_CURSOR "adabas_cursor"
+#define ODBC_DO "adabas_do"
+#define ODBC_EXEC "adabas_exec"
+#define ODBC_PREPARE "adabas_prepare"
+#define ODBC_EXECUTE "adabas_execute"
+#define ODBC_FETCH_ROW "adabas_fetch_row"
+#define ODBC_FETCH_INTO "adabas_fetch_into"
+#define ODBC_FIELD_LEN "adabas_field_len"
+#define ODBC_FIELD_NAME "adabas_field_name"
+#define ODBC_FIELD_TYPE "adabas_field_type"
+#define ODBC_FREE_RESULT "adabas_free_result"
+#define ODBC_NUM_FIELDS "adabas_num_fields"
+#define ODBC_NUM_ROWS "adabas_num_rows"
+#define ODBC_RESULT "adabas_result"
+#define ODBC_RESULT_ALL "adabas_result_all"
+#define ODBC_ROLLBACK "adabas_rollback"
+#define ODBC_TRANSACT "adabas_transact"
+#define ODBC_DO_CONNECT "adabas_do_connect"
+
+/* ini variable defines */
+#define ODBC_INI_DEFAULTDB "adabas.default_db"
+#define ODBC_INI_DEFAULTUSER "adabas.default_user"
+#define ODBC_INI_DEFAULTPW "adabas.default_pw"
+#define ODBC_INI_ALLOWPERSISTENT "adabas.allow_persistent"
+#define ODBC_INI_MAXPERSISTENT "adabas.max_persistent"
+#define ODBC_INI_MAXLINKS "adabas.max_links"
+#endif
+
+/* checking in the same order as in configure.in */
+# if HAVE_SOLID
+#  include <cli0core.h>
+#  include <cli0ext1.h>
+#  define HAVE_SQL_EXTENDED_FETCH 0
+extern void php3_solid_fetch_prev(INTERNAL_FUNCTION_PARAMETERS);
+#  if defined(UODBC_UNIQUE_NAMES)
+#   define UODBC_TYPE solid
+#   define UODBC_NAME "solid"
+#   define UODBC_FE(name, arg_types) UODBC_NAMED_FE(solid_##name, php3_solid_##name, arg_types)
+#   define UODBC_FE_ALIAS(php_name, name, arg_types) UODBC_NAMED_FE(solid_##php_name, php3_solid_##name, arg_types)
+#   define UODBC_FUNCTION(name) UODBC_NAMED_FUNCTION(php3_solid_##name)
+#   define UODBC_FNAME(name) php3i_solid_##name
+#   define ODBC_INI_VAR_NAME(name) #name
+#   define ODBC_INI_VAR(a) ODBC_INI_VAR_NAME(solid.##a)
+#   define UODBC_VAR_NAME(name) name
+#   define UODBC_VAR(a) UODBC_VAR_NAME(solid_##a)
+#      define PHP3_UODBC_VAR(a) UODBC_VAR_NAME(php3_solid_##a)
+#   define UODBC_MODULE_ENTRY UODBC_VAR(module_entry)
+#   define solid_module_ptr &UODBC_MODULE_ENTRY
+#  endif
+
+#elif HAVE_EMPRESS
+#  include <sql.h>
+#  include <sqlext.h>
+#  define HAVE_SQL_EXTENDED_FETCH 0
+
+#elif HAVE_ADABAS
+#include <WINDOWS.H>
+#include <sql.h>
+#include <sqlext.h>
+#  define HAVE_SQL_EXTENDED_FETCH 1
+#  if defined(UODBC_UNIQUE_NAMES)
+#   define UODBC_TYPE adabas
+#   define UODBC_NAME "adabas"
+#   define UODBC_FE(name, arg_types) UODBC_NAMED_FE(ada_##name, php3_ada_##name, arg_types)
+#   define UODBC_FE_ALIAS(php_name, name, arg_types) UODBC_NAMED_FE(ada_##php_name, php3_ada_##name, arg_types)
+#   define UODBC_FUNCTION(name) UODBC_NAMED_FUNCTION(php3_ada_##name)
+#   define UODBC_FNAME(name) php3i_ada_##name
+#   define ODBC_INI_VAR_NAME(name) #name
+#   define ODBC_INI_VAR(a) ODBC_INI_VAR_NAME(ada.##a)
+#   define UODBC_VAR_NAME(name) name
+#   define UODBC_VAR(a) UODBC_VAR_NAME(ada_##a)
+#       define PHP3_UODBC_VAR(a) UODBC_VAR_NAME(php3_ada_##a)
+#   define UODBC_MODULE_ENTRY UODBC_VAR(module_entry)
+#   define ada_module_ptr &UODBC_MODULE_ENTRY
+#  endif
+
+# elif HAVE_IODBC  && !(WIN32|WINNT)
+#  include <isql.h>
+#  include <isqlext.h>
+#  include <odbc_types.h>
+#  include <odbc_funcs.h>
+#  define HAVE_SQL_EXTENDED_FETCH 1
+#  define SQL_FD_FETCH_ABSOLUTE   0x00000010L
+#  define SQL_CURSOR_DYNAMIC      2UL
+#  define SQL_NO_TOTAL            (-4)
+#  define SQL_SO_DYNAMIC          0x00000004L
+#  define SQL_LEN_DATA_AT_EXEC_OFFSET  (-100)
+#  define SQL_LEN_DATA_AT_EXEC(length) (-(length)+SQL_LEN_DATA_AT_EXEC_OFFSET)
+#  if defined(UODBC_UNIQUE_NAMES)
+#   define UODBC_TYPE iodbc
+#   define UODBC_NAME "iodbc"
+#   define UODBC_FE(name, arg_types) UODBC_NAMED_FE(iodbc_##name, php3_iodbc_##name, arg_types)
+#   define UODBC_FE_ALIAS(php_name, name, arg_types) UODBC_NAMED_FE(iodbc_##php_name, php3_iodbc_##name, arg_types)
+#   define UODBC_FUNCTION(name) UODBC_NAMED_FUNCTION(php3_iodbc_##name)
+#   define UODBC_FNAME(name) php3i_iodbc_##name
+#   define ODBC_INI_VAR_NAME(name) #name
+#   define ODBC_INI_VAR(a) ODBC_INI_VAR_NAME(iodbc.##a)
+#   define UODBC_VAR_NAME(name) name
+#   define UODBC_VAR(a) UODBC_VAR_NAME(iodbc_##a)
+#      define PHP3_UODBC_VAR(a) UODBC_VAR_NAME(php3_iodbc_##a)
+#   define UODBC_MODULE_ENTRY UODBC_VAR(module_entry)
+#   define iodbc_module_ptr &UODBC_MODULE_ENTRY
+#  endif
+
+#elif HAVE_OPENLINK
+
+#  include <iodbc.h>
+#  include <isql.h>
+#  include <isqlext.h>
+#  include <udbcext.h>
+#  define HAVE_SQL_EXTENDED_FETCH 1
+#  if defined(UODBC_UNIQUE_NAMES)
+#   define UODBC_TYPE opnlnk
+#   define UODBC_NAME "opnlnk"
+#   define UODBC_FE(name, arg_types) UODBC_NAMED_FE(opnlnk_##name, php3_opnlnk_##name, arg_types)
+#   define UODBC_FE_ALIAS(php_name, name, arg_types) UODBC_NAMED_FE(opnlnk_##php_name, php3_opnlnk_##name, arg_types)
+#   define UODBC_FUNCTION(name) UODBC_NAMED_FUNCTION(php3_opnlnk_##name)
+#   define UODBC_FNAME(name) php3i_opnlnk_##name
+#   define ODBC_INI_VAR_NAME(name) #name
+#   define ODBC_INI_VAR(a) ODBC_INI_VAR_NAME(opnlnk.##a)
+#   define UODBC_VAR_NAME(name) name
+#   define UODBC_VAR(a) UODBC_VAR_NAME(opnlnk_##a)
+#      define PHP3_UODBC_VAR(a) UODBC_VAR_NAME(php3_opnlnk_##a)
+#   define UODBC_MODULE_ENTRY UODBC_VAR(module_entry)
+#   define opnlnk_module_ptr &UODBC_MODULE_ENTRY
+#  endif
+
+#elif HAVE_VELOCIS
+/* Nothing ??? */
+#  define UNIX
+#  define HAVE_SQL_EXTENDED_FETCH 1
+#  include <sql.h>
+#  include <sqlext.h>
+#  if defined(UODBC_UNIQUE_NAMES)
+#   define UODBC_TYPE velocis
+#   define UODBC_NAME "velocis"
+#   define UODBC_FE(name, arg_types) UODBC_NAMED_FE(velocis_##name, php3_velocis_##name, arg_types)
+#   define UODBC_FE_ALIAS(php_name, name, arg_types) UODBC_NAMED_FE(velocis_##php_name, php3_velocis_##name, arg_types)
+#   define UODBC_FUNCTION(name) UODBC_NAMED_FUNCTION(php3_velocis_##name)
+#   define UODBC_FNAME(name) php3i_velocis_##name
+#   define ODBC_INI_VAR_NAME(name) #name
+#   define ODBC_INI_VAR(a) ODBC_INI_VAR_NAME(velocis.##a)
+#   define UODBC_VAR_NAME(name) name
+#   define UODBC_VAR(a) UODBC_VAR_NAME(velocis_##a)
+#      define PHP3_UODBC_VAR(a) UODBC_VAR_NAME(php3_velocis_##a)
+#   define UODBC_MODULE_ENTRY UODBC_VAR(module_entry)
+#   define velocis_module_ptr &UODBC_MODULE_ENTRY
+#  endif
+
+#elif HAVE_CODBC
+#  define HAVE_SQL_EXTENDED_FETCH 1
+#  include <odbc.h>
+#  if defined(UODBC_UNIQUE_NAMES)
+#   define UODBC_TYPE codbc
+#   define UODBC_NAME "codbc"
+#   define UODBC_FE(name, arg_types) UODBC_NAMED_FE(codbc_##name, php3_codbc_##name, arg_types)
+#   define UODBC_FE_ALIAS(php_name, name, arg_types) UODBC_NAMED_FE(codbc_##php_name, php3_codbc_##name, arg_types)
+#   define UODBC_FUNCTION(name) UODBC_NAMED_FUNCTION(php3_codbc_##name)
+#   define UODBC_FNAME(name) php3i_codbc_##name
+#   define ODBC_INI_VAR_NAME(name) #name
+#   define ODBC_INI_VAR(a) ODBC_INI_VAR_NAME(codbc.##a)
+#   define UODBC_VAR_NAME(name) name
+#   define UODBC_VAR(a) UODBC_VAR_NAME(codbc_##a)
+#      define PHP3_UODBC_VAR(a) UODBC_VAR_NAME(php3_codbc_##a)
+#   define UODBC_MODULE_ENTRY UODBC_VAR(module_entry)
+#   define codbc_module_ptr &UODBC_MODULE_ENTRY
+#  endif
+
+#elif HAVE_DB2
+#  define HAVE_SQL_EXTENDED_FETCH 1
+#  include <sqlcli1.h>
+#  ifdef DB268K
+/* Need to include ASLM for 68K applications */
+#   include <LibraryManager.h>
+#  endif
+#  if defined(UODBC_UNIQUE_NAMES)
+#   define UODBC_TYPE db2
+#   define UODBC_NAME "db2"
+#   define UODBC_FE(name, arg_types) UODBC_NAMED_FE(db2_##name, php3_db2_##name, arg_types)
+#   define UODBC_FE_ALIAS(php_name, name, arg_types) UODBC_NAMED_FE(db2_##php_name, php3_db2_##name, arg_types)
+#   define UODBC_FUNCTION(name) UODBC_NAMED_FUNCTION(php3_db2_##name)
+#   define UODBC_FNAME(name) php3i_db2_##name
+#   define ODBC_INI_VAR_NAME(name) #name
+#   define ODBC_INI_VAR(a) ODBC_INI_VAR_NAME(db2.##a)
+#   define UODBC_VAR_NAME(name) name
+#   define UODBC_VAR(a) UODBC_VAR_NAME(db2_##a)
+#   define PHP3_UODBC_VAR(a) UODBC_VAR_NAME(php3_db2_##a)
+#   define UODBC_MODULE_ENTRY UODBC_VAR(module_entry)
+#   define db2_module_ptr &UODBC_MODULE_ENTRY
+#  endif
+
+# else /* MS ODBC */
+#  define HAVE_SQL_EXTENDED_FETCH 1
+#  include <WINDOWS.H>
+#  include <sql.h>
+#  include <sqlext.h>
+#  if defined(UODBC_UNIQUE_NAMES)
+#   define UODBC_TYPE wodbc
+#   define UODBC_NAME "wodbc"
+#   define UODBC_FE(name, arg_types) UODBC_NAMED_FE(wodbc_##name, php3_wodbc_##name, arg_types)
+#   define UODBC_FE_ALIAS(php_name, name, arg_types) UODBC_NAMED_FE(wodbc_##php_name, php3_wodbc_##name, arg_types)
+#   define UODBC_FUNCTION(name) UODBC_NAMED_FUNCTION(php3_wodbc_##name)
+#   define UODBC_FNAME(name) php3i_wodbc_##name
+#   define ODBC_INI_VAR_NAME(name) #name
+#   define ODBC_INI_VAR(a) ODBC_INI_VAR_NAME(wuodbc.##a)
+#   define UODBC_VAR_NAME(name) name
+#   define UODBC_VAR(a) UODBC_VAR_NAME(wodbc_##a)
+#   define PHP3_UODBC_VAR(a) UODBC_VAR_NAME(php3_wuodbc_##a)
+#   define UODBC_MODULE_ENTRY UODBC_VAR(module_entry)
+#   define wodbc_module_ptr &UODBC_MODULE_ENTRY
+#  endif
+# endif
+
+
+#if !defined(UODBC_UNIQUE_NAMES)
+#define UODBC_TYPE odbc
+#define UODBC_NAME "odbc"
+#define UODBC_FE(name, arg_types) UODBC_NAMED_FE(odbc_##name, php3_odbc_##name, arg_types)
+#define UODBC_FE_ALIAS(php_name, name, arg_types) UODBC_NAMED_FE(odbc_##php_name, php3_odbc_##name, arg_types)
+#define UODBC_FUNCTION(name) UODBC_NAMED_FUNCTION(php3_odbc_##name)
+#define UODBC_FNAME(name) php3i_odbc_##name
+#define ODBC_INI_VAR_NAME(name) #name
+#define ODBC_INI_VAR(a) ODBC_INI_VAR_NAME(uodbc.##a)
+#define UODBC_VAR_NAME(name) name
+#define UODBC_VAR(a) UODBC_VAR_NAME(uodbc_##a)
+#define PHP3_UODBC_VAR(a) UODBC_VAR_NAME(php3_uodbc_##a)
+#define UODBC_MODULE_ENTRY UODBC_VAR(module_entry)
+#define uodbc_module_ptr &UODBC_MODULE_ENTRY
+#else
+#define UODBC_ALIAS(name, arg_types) UODBC_NAMED_FE(odbc_##name, php3_odbc_##name, arg_types)
+#define UODBC_ALIAS_FE(php_name, name, arg_types) UODBC_NAMED_FE(odbc_##php_name, php3_odbc_##name, arg_types)
+#endif
+
+
+
+/*
+*
+*  Defines for ODBC
+*
+*/
+
+/* win32 vars for thread local storage */
+#define UODBC_MUTEX UODBC_VAR(mutex)
+#define UODBC_TLS UODBC_VAR(Tls)
+#define UODBC_GLOBAL_STRUCT UODBC_VAR(global_struct)
+#define UODBC_GLOBALS UODBC_VAR(globals)
+/* defines for variables, structs, etc */
+#define UODBC_MODULE_NAME "ODBC"
+#define UODBC_FUNCTIONS UODBC_VAR(functions)
+#define UODBC_CONNECTION UODBC_VAR(connection)
+#define UODBC_RESULT_VALUE UODBC_VAR(result_value)
+#define UODBC_RESULT UODBC_VAR(result)
+#define UODBC_MODULE UODBC_VAR(module)
+#define UODBC_MODULE_PTR UODBC_VAR(module_ptr)
+#define PHP3_UODBC_MODULE PHP3_UODBC_VAR(module)
+
+/* function defines */
+#define PHP3_MINIT_UODBC UODBC_FNAME(minit)
+#define PHP3_MSHUTDOWN_UODBC UODBC_FNAME(mshutdown)
+#define PHP3_RINIT_UODBC UODBC_FNAME(rinit)
+#define PHP3_INFO_UODBC UODBC_FNAME(info)
+
+/* internal function defines */
+#define UODBC_ADD_RESULT UODBC_FNAME(add_result)
+#define UODBC_GET_RESULT UODBC_FNAME(get_result)
+#define UODBC_DEL_RESULT UODBC_FNAME(del_result)
+#define UODBC_ADD_CONN UODBC_FNAME(add_conn)
+#define UODBC_GET_CONN UODBC_FNAME(get_conn)
+#define UODBC_DEL_CONN UODBC_FNAME(del_conn)
+#define UODBC_SQL_ERROR UODBC_FNAME(sql_error)
+#define UODBC_BINDCOLS UODBC_FNAME(bindcols)
+#define PHP3_UODBC_DO_CONNECT UODBC_FNAME(_do_connect)
+#define PHP3_UODBC_TRANSACT UODBC_FNAME(_do_transact)
+
+# ifndef MSVC5
+#  define FAR
+# endif
+
+extern php3_module_entry UODBC_MODULE_ENTRY;
+
+/* uODBC functions */
+extern int PHP3_MINIT_UODBC(INIT_FUNC_ARGS);
+extern int PHP3_MSHUTDOWN_UODBC(void);
+extern int PHP3_RINIT_UODBC(INIT_FUNC_ARGS);
+extern void PHP3_INFO_UODBC(void);
+extern UODBC_FUNCTION(setoption);
+extern UODBC_FUNCTION(autocommit);
+extern UODBC_FUNCTION(close);
+extern UODBC_FUNCTION(close_all);
+extern UODBC_FUNCTION(commit);
+extern UODBC_FUNCTION(connect);
+extern UODBC_FUNCTION(pconnect);
+extern void PHP3_UODBC_DO_CONNECT(INTERNAL_FUNCTION_PARAMETERS, int);
+extern UODBC_FUNCTION(cursor);
+extern UODBC_FUNCTION(exec);
+/*extern UODBC_FUNCTION(do);*/
+extern UODBC_FUNCTION(execute);
+extern UODBC_FUNCTION(fetch_into);
+extern UODBC_FUNCTION(fetch_row);
+extern UODBC_FUNCTION(field_len);
+extern UODBC_FUNCTION(field_name);
+extern UODBC_FUNCTION(field_type);
+extern UODBC_FUNCTION(field_num);
+extern UODBC_FUNCTION(free_result);
+extern UODBC_FUNCTION(num_fields);
+extern UODBC_FUNCTION(num_rows);
+extern UODBC_FUNCTION(prepare);
+extern UODBC_FUNCTION(result);
+extern UODBC_FUNCTION(result_all);
+extern UODBC_FUNCTION(rollback);
+extern void PHP3_UODBC_TRANSACT(INTERNAL_FUNCTION_PARAMETERS, int);
+extern UODBC_FUNCTION(binmode);
+extern UODBC_FUNCTION(longreadlen);
+
+typedef struct UODBC_CONNECTION {
+#if HAVE_DB2
+       SQLHANDLE hdbc;
+#else
+       HDBC hdbc;
+#endif
+       int open;
+} UODBC_CONNECTION;
+
+typedef struct UODBC_RESULT_VALUE {
+       char name[32];
+       char *value;
+       long int vallen;
+       SDWORD coltype;
+} UODBC_RESULT_VALUE;
+
+typedef struct UODBC_RESULT {
+#if HAVE_DB2
+       SQLHANDLE stmt;
+#else
+       HSTMT stmt;
+#endif
+       UODBC_RESULT_VALUE *values;
+       SWORD numcols;
+       SWORD numparams;
+# if HAVE_SQL_EXTENDED_FETCH
+       int fetch_abs;
+# endif
+    long longreadlen;
+    int binmode;
+       int fetched;
+       UODBC_CONNECTION *conn_ptr;
+} UODBC_RESULT;
+
+typedef struct {
+#if HAVE_DB2
+       SQLHANDLE henv;
+#else
+       HENV henv;
+#endif
+       char *defDB;
+       char *defUser;
+       char *defPW;
+       long allow_persistent;
+       long max_persistent;
+       long max_links;
+       long num_persistent;
+       long num_links;
+       int defConn;
+       int le_result, le_conn, le_pconn;
+    long defaultlrl;
+    long defaultbinmode;
+       HashTable *resource_list;
+       HashTable *resource_plist;
+} UODBC_MODULE;
+
+# ifndef THREAD_SAFE
+extern UODBC_MODULE PHP3_UODBC_MODULE;
+# endif
+
+int UODBC_ADD_RESULT(HashTable *list, UODBC_RESULT *result);
+UODBC_RESULT *UODBC_GET_RESULT(HashTable *list, int count);
+void UODBC_DEL_RESULT(HashTable *list, int count);
+int UODBC_ADD_CONN(HashTable *list, HDBC conn);
+UODBC_CONNECTION *UODBC_GET_CONN(HashTable *list, int count);
+void UODBC_DEL_CONN(HashTable *list, int ind);
+#if HAVE_DB2
+void UODBC_SQL_ERROR(SQLHANDLE conn, SQLHANDLE stmt, char *func);
+#else
+void UODBC_SQL_ERROR(HDBC conn, HSTMT stmt, char *func);
+#endif
+int UODBC_BINDCOLS(UODBC_RESULT *result);
+
+#define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR)
+#define IS_SQL_BINARY(x) (x == SQL_BINARY || x == SQL_VARBINARY || x == SQL_LONGVARBINARY)
+
+#else
+# define uodbc_module_ptr NULL
+
+#endif /* HAVE_UODBC || HAVE_DB2 */
+
+#endif /* _UNIFIED_ODBC_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/odbc/php3_velocis.h b/ext/odbc/php3_velocis.h
new file mode 100644 (file)
index 0000000..19d9f40
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP HTML Embedded Scripting Language Version 3.0                     |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997,1998 PHP Development Team (See Credits file)      |
+   +----------------------------------------------------------------------+
+   | This program is free software; you can redistribute it and/or modify |
+   | it under the terms of one of the following licenses:                 |
+   |                                                                      |
+   |  A) the GNU General Public License as published by the Free Software |
+   |     Foundation; either version 2 of the License, or (at your option) |
+   |     any later version.                                               |
+   |                                                                      |
+   |  B) the PHP License as published by the PHP Development Team and     |
+   |     included in the distribution in the file: LICENSE                |
+   |                                                                      |
+   | This program is distributed in the hope that it will be useful,      |
+   | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
+   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
+   | GNU General Public License for more details.                         |
+   |                                                                      |
+   | You should have received a copy of both licenses referred to here.   |
+   | If you did not, or have any questions about PHP licensing, please    |
+   | contact core@php.net.                                                |
+   +----------------------------------------------------------------------+
+   | Authors: Nikolay P. Romanyuk <mag@redcom.ru>                         |
+   |                                                                      |
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef _PHP3_VELOCIS_H
+#define _PHP3_VELOCIS_H
+
+#if COMPILE_DL
+#undef HAVE_VELOCIS
+#define HAVE_VELOCIS 1
+#endif
+
+#if HAVE_VELOCIS && !HAVE_UODBC
+#define UNIX
+#include <sql.h>
+#include <sqlext.h>
+
+typedef struct VConn {
+       HDBC    hdbc;
+       long    index;
+} VConn;
+
+typedef struct {
+       char name[32];
+       char *value;
+       long vallen;
+       SDWORD valtype;
+} VResVal;
+
+typedef struct Vresult {
+       HSTMT   hstmt;
+       VConn   *conn; 
+       long    index;
+       VResVal *values;
+       long    numcols;
+       int     fetched;
+} Vresult;
+
+typedef struct {
+       long num_links;
+       long max_links;
+       int le_link,le_result;
+} velocis_module;
+
+extern php3_module_entry velocis_module_entry;
+#define velocis_module_ptr &velocis_module_entry
+
+/* velocis.c functions */
+extern int php3_minit_velocis(INIT_FUNC_ARGS);
+extern int php3_rinit_velocis(INIT_FUNC_ARGS);
+extern void php3_info_velocis(void);
+extern int php3_shutdown_velocis(void);
+extern void php3_velocis_connect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_close(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_exec(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_fetch(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_result(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_freeresult(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_autocommit(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_off_autocommit(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_commit(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_rollback(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_fieldnum(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_velocis_fieldname(INTERNAL_FUNCTION_PARAMETERS);
+
+extern velocis_module php3_velocis_module;
+
+#else
+
+#define velocis_module_ptr NULL
+
+#endif /* HAVE_VELOCIS */
+#endif /* _PHP3_VELOCIS_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/odbc/setup.stub b/ext/odbc/setup.stub
new file mode 100644 (file)
index 0000000..8f2b2a9
--- /dev/null
@@ -0,0 +1,76 @@
+# $Id$ -*- sh -*-
+
+# Solid
+define_option with-solid 'Solid support?' yesnodir \
+    'no /usr/local/solid Solid install' \
+'     Whether to build PHP with Solid support.\n
+     More information about Solid can be found at http://www.solidtech.com/.'
+
+# Empress
+if test "$option_value_with_solid" = "no"; then
+define_option with-empress 'Empress support?' yesnodir \
+    "no $EMPRESSPATH Empress home" \
+'    Whether to build PHP with Empress support.  Has been confirmed to
+    work with Empress Version 8.10.  If you have not set up your
+    Empress environment, enter what $EMPRESSPATH is usually set to here.
+    More info about Empress can be found at http://www.empress.com/.'
+fi
+
+# iODBC
+if test "$option_value_with_solid" = "no" -a \
+        "$option_value_with_empress" = "no"; then
+define_option with-iodbc 'iODBC support?' yesnodir \
+    'no /usr/local iODBC install' \
+'    Whether to build PHP with iODBC support.  This feature was first\n
+    developed for iODBC Driver Manager, a freely redistributable ODBC\n
+    driver manager which runs under many flavors of UNIX.\n
+    More info about iODBC can be found on the FreeODBC Pages at \n
+    http://users.ids.net/~bjepson/freeODBC/.'
+fi
+
+# OpenLink
+if test "$option_value_with_solid" = "no" -a \
+        "$option_value_with_empress" = "no" -a \
+        "$option_value_with_iodbc" = "no"; then
+define_option with-openlink 'OpenLink ODBC support?' yesnodir \
+    'no /usr/local/openlink OpenLink install' \
+'    Whether to build PHP with OpenLink ODBC support.  See
+     http://www.openlinksw.com/ for more information.'
+fi
+
+# Adabas D
+if test "$option_value_with_solid" = "no" -a \
+        "$option_value_with_empress" = "no" -a \
+        "$option_value_with_iodbc" = "no" -a \
+        "$option_value_with_openlink" = "no"; then
+define_option with-adabas 'Adabas D support?' yesnodir \
+    'no /usr/local Adabas D install root' \
+'    Whether to build with Adabas D support.\n
+    More info about Adabas D can be found at http://www.adabas.com/.'
+fi
+
+# Velocis
+if test "$option_value_with_solid" = "no" -a \
+        "$option_value_with_empress" = "no" -a \
+        "$option_value_with_iodbc" = "no" -a \
+        "$option_value_with_openlink" = "no" -a \
+        "$option_value_with_adabas" = "no"; then
+define_option with-velocis 'Velocis support?' yesnodir \
+    'no /usr/local/velocis Velocis install' \
+'     Whether to build PHP with Velocis support.\n
+     More information about Velocis can be found at http://www.raima.com/.'
+fi
+
+# Custom ODBC
+if test "$option_value_with_solid" = "no" -a \
+        "$option_value_with_empress" = "no" -a \
+        "$option_value_with_iodbc" = "no" -a \
+        "$option_value_with_openlink" = "no" -a \
+        "$option_value_with_adabas" = "no" -a \
+        "$option_value_with_velocis" = "no"; then
+define_option with-custom-odbc 'custom ODBC support?' yesnodir \
+    'no /usr/local CODBC install' \
+'    Whether to build PHP with CODBC support.  This feature was first
+    developed for Sybase SQL Anywhere 5.5 on QNX, but may be used for
+    any unknown ODBC driver on all flavors of UNIX.'
+fi
diff --git a/ext/odbc/velocis.c b/ext/odbc/velocis.c
new file mode 100644 (file)
index 0000000..0c5b03e
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP HTML Embedded Scripting Language Version 3.0                     |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997,1998 PHP Development Team (See Credits file)      |
+   +----------------------------------------------------------------------+
+   | This program is free software; you can redistribute it and/or modify |
+   | it under the terms of one of the following licenses:                 |
+   |                                                                      |
+   |  A) the GNU General Public License as published by the Free Software |
+   |     Foundation; either version 2 of the License, or (at your option) |
+   |     any later version.                                               |
+   |                                                                      |
+   |  B) the PHP License as published by the PHP Development Team and     |
+   |     included in the distribution in the file: LICENSE                |
+   |                                                                      |
+   | This program is distributed in the hope that it will be useful,      |
+   | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
+   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
+   | GNU General Public License for more details.                         |
+   |                                                                      |
+   | You should have received a copy of both licenses referred to here.   |
+   | If you did not, or have any questions about PHP licensing, please    |
+   | contact core@php.net.                                                |
+   +----------------------------------------------------------------------+
+   | Authors: Nikolay P. Romanyuk <mag@redcom.ru>                         |
+   |                                                                      |
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/*
+ * TODO:
+ * velocis_fetch_into(),
+ * Check all on real life apps.
+ */
+
+#include "php.h"
+#include "php3_velocis.h"
+
+#if HAVE_VELOCIS && !HAVE_UODBC
+
+function_entry velocis_functions[] = {
+       {"velocis_connect",     php3_velocis_connect,           NULL},
+       {"velocis_close",       php3_velocis_close,             NULL},
+       {"velocis_exec",        php3_velocis_exec,              NULL},
+       {"velocis_fetch",       php3_velocis_fetch,             NULL},
+       {"velocis_result",      php3_velocis_result,            NULL},
+       {"velocis_freeresult",  php3_velocis_freeresult,        NULL},
+       {"velocis_autocommit",  php3_velocis_autocommit,        NULL},
+       {"velocis_off_autocommit",      php3_velocis_off_autocommit,    NULL},
+       {"velocis_commit",      php3_velocis_commit,            NULL},
+       {"velocis_rollback",    php3_velocis_rollback,          NULL},
+       {"velocis_fieldnum",    php3_velocis_fieldnum,          NULL},
+       {"velocis_fieldname",   php3_velocis_fieldname,         NULL},
+       {NULL, NULL, NULL}
+};
+
+php3_module_entry velocis_module_entry = {
+       "Velocis", velocis_functions, php3_minit_velocis, php3_shutdown_velocis,
+               php3_rinit_velocis, NULL, php3_info_velocis, STANDARD_MODULE_PROPERTIES
+};
+
+
+#if COMPILE_DL
+php3_module_entry *get_module() { return &velocis_module_entry; }
+#endif
+
+THREAD_LS velocis_module php3_velocis_module;
+THREAD_LS static HENV henv;
+
+static void _close_velocis_link(VConn *conn)
+{
+       if ( conn ) {
+               efree(conn);
+       }
+}
+
+static void _free_velocis_result(Vresult *res)
+{
+       if ( res && res->values ) {
+               register int i;
+               for ( i=0; i < res->numcols; i++ ) {
+                       if ( res->values[i].value )
+                              efree(res->values[i].value);
+               }
+               efree(res->values);
+       }
+       if ( res ) {
+               efree(res);
+       }
+}
+
+int php3_minit_velocis(INIT_FUNC_ARGS)
+{
+       SQLAllocEnv(&henv);
+       if ( cfg_get_long("velocis.max_links",&php3_velocis_module.max_links) == FAILURE ) {
+               php3_velocis_module.max_links = -1;
+       }
+       php3_velocis_module.num_links = 0;
+       php3_velocis_module.le_link   = register_list_destructors(_close_velocis_link,NULL);
+       php3_velocis_module.le_result = register_list_destructors(_free_velocis_result,NULL);
+
+       return SUCCESS;
+}
+
+int php3_rinit_velocis(INIT_FUNC_ARGS)
+{
+       return SUCCESS;
+}
+
+
+void php3_info_velocis(void)
+{
+       php3_printf("RAIMA Velocis Support Active");
+}
+
+int php3_shutdown_velocis(void)
+{
+       SQLFreeEnv(henv);
+       return SUCCESS;
+}
+
+/* Some internal functions. Connections and result manupulate */
+
+static int
+velocis_add_conn(HashTable *list,VConn *conn,HDBC hdbc)
+{
+       int ind;
+
+       ind = php3_list_insert(conn,php3_velocis_module.le_link);
+       conn->hdbc = hdbc;
+       conn->index = ind;
+
+       return(ind);
+}
+
+static VConn *
+velocis_find_conn(HashTable *list,int ind)
+{
+       VConn *conn;
+       int type;
+
+       conn = php3_list_find(ind,&type);
+       if ( !conn || type != php3_velocis_module.le_link ) {
+               return(NULL);
+       }
+       return(conn);
+}
+
+static void
+velocis_del_conn(HashTable *list,int ind)
+{
+       php3_list_delete(ind);
+}
+
+static int
+velocis_add_result(HashTable *list,Vresult *res,VConn *conn)
+{
+       int ind;
+
+       ind = php3_list_insert(res,php3_velocis_module.le_result);
+       res->conn = conn;
+       res->index = ind;
+
+       return(ind);
+}
+
+static Vresult *
+velocis_find_result(HashTable *list,int ind)
+{
+       Vresult *res;
+       int type;
+
+       res = php3_list_find(ind,&type);
+       if ( !res || type != php3_velocis_module.le_result ) {
+               return(NULL);
+       }
+       return(res);
+}
+
+static void
+velocis_del_result(HashTable *list,int ind)
+{
+       php3_list_delete(ind);
+}
+
+/* Users functions */
+
+void php3_velocis_connect(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *serv,*user,*pass;
+       char *Serv = NULL;
+       char *User = NULL;
+       char *Pass = NULL;
+       RETCODE stat;
+       HDBC hdbc;
+       VConn *new;
+       long ind;
+
+       if ( php3_velocis_module.max_links != -1 && php3_velocis_module.num_links == php3_velocis_module.max_links ) {
+               php3_error(E_WARNING,"Velocis: Too many open connections (%d)",php3_velocis_module.num_links);
+               RETURN_FALSE;
+       }
+       if ( ARG_COUNT(ht) != 3 ||
+          getParameters(ht,3,&serv,&user,&pass) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_string(serv);
+       convert_to_string(user);
+       convert_to_string(pass);
+       Serv = serv->value.str.val;
+       User = user->value.str.val;
+       Pass = pass->value.str.val;
+       stat = SQLAllocConnect(henv,&hdbc);
+       if ( stat != SQL_SUCCESS ) {
+               php3_error(E_WARNING,"Velocis: Could not allocate connection handle");
+               RETURN_FALSE;
+       }
+       stat = SQLConnect(hdbc,Serv,SQL_NTS,User,SQL_NTS,Pass,SQL_NTS);
+       if ( stat != SQL_SUCCESS && stat != SQL_SUCCESS_WITH_INFO ) {
+               php3_error(E_WARNING,"Velocis: Could not connect to server \"%s\" for %s",Serv,User);
+               SQLFreeConnect(hdbc);
+               RETURN_FALSE;
+       }
+       new = (VConn *)emalloc(sizeof(VConn));
+       if ( new == NULL ) {
+               php3_error(E_WARNING,"Velocis: Out of memory for store connection");
+               SQLFreeConnect(hdbc);
+               RETURN_FALSE;
+       }
+       ind = velocis_add_conn(list,new,hdbc);
+       php3_velocis_module.num_links++;
+       RETURN_LONG(ind);
+}
+
+void php3_velocis_close(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *id;
+       VConn *conn;
+
+       if ( ARG_COUNT(ht) != 1 || getParameters(ht,1,&id) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(id);
+       conn = velocis_find_conn(list,id->value.lval);
+       if ( !conn ) {
+               php3_error(E_WARNING,"Velocis: Not connection index (%d)",id->value.lval);
+               RETURN_FALSE;
+       }
+       SQLDisconnect(conn->hdbc);
+       SQLFreeConnect(conn->hdbc);
+       velocis_del_conn(list,id->value.lval);
+       php3_velocis_module.num_links--;
+       RETURN_TRUE;
+}
+
+void php3_velocis_exec(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *ind,*exec_str;
+       char *query = NULL;
+       int indx;
+       VConn *conn;
+       Vresult *res;
+       RETCODE stat;
+       SWORD cols,i,colnamelen;
+       SDWORD rows,coldesc;
+
+       if ( ARG_COUNT(ht) != 2 || getParameters(ht,2,&ind,&exec_str) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(ind);
+       conn = velocis_find_conn(list,ind->value.lval);
+       if ( !conn ) {
+               php3_error(E_WARNING,"Velocis: Not connection index (%d)",ind->value.lval);
+               RETURN_FALSE;
+       }
+       convert_to_string(exec_str);
+       query = exec_str->value.str.val;
+
+       res = (Vresult *)emalloc(sizeof(Vresult));
+       if ( res == NULL ) {
+               php3_error(E_WARNING,"Velocis: Out of memory for result");
+               RETURN_FALSE;
+       }
+       stat = SQLAllocStmt(conn->hdbc,&res->hstmt);
+       if ( stat != SQL_SUCCESS && stat != SQL_SUCCESS_WITH_INFO ) {
+               php3_error(E_WARNING,"Velocis: SQLAllocStmt return %d",stat);
+               efree(res);
+               RETURN_FALSE;
+       }
+       stat = SQLExecDirect(res->hstmt,query,SQL_NTS);
+       if ( stat != SQL_SUCCESS && stat != SQL_SUCCESS_WITH_INFO ) {
+               php3_error(E_WARNING,"Velocis: Can not execute \"%s\" query",query);
+               SQLFreeStmt(res->hstmt,SQL_DROP);
+               efree(res);
+               RETURN_FALSE;
+       }
+       /* Success query */
+       stat = SQLNumResultCols(res->hstmt,&cols);
+       if ( stat != SQL_SUCCESS ) {
+               php3_error(E_WARNING,"Velocis: SQLNumResultCols return %d",stat);
+               SQLFreeStmt(res->hstmt,SQL_DROP);
+               efree(res);
+               RETURN_FALSE;
+       }
+       if ( !cols ) { /* Was INSERT, UPDATE, DELETE, etc. query */
+               stat = SQLRowCount(res->hstmt,&rows);
+               if ( stat != SQL_SUCCESS ) {
+                       php3_error(E_WARNING,"Velocis: SQLNumResultCols return %d",stat);
+                       SQLFreeStmt(res->hstmt,SQL_DROP);
+                       efree(res);
+                       RETURN_FALSE;
+               }
+               SQLFreeStmt(res->hstmt,SQL_DROP);
+               efree(res);
+               RETURN_LONG(rows);
+       } else {  /* Was SELECT query */
+               res->values = (VResVal *)emalloc(sizeof(VResVal)*cols);
+               if ( res->values == NULL ) {
+                       php3_error(E_WARNING,"Velocis: Out of memory for result columns");
+                       SQLFreeStmt(res->hstmt,SQL_DROP);
+                       efree(res);
+                       RETURN_FALSE;
+               }
+               res->numcols = cols;
+               for ( i = 0; i < cols; i++ ) {
+                       SQLColAttributes(res->hstmt,i+1,SQL_COLUMN_NAME,
+                          res->values[i].name,sizeof(res->values[i].name),
+                          &colnamelen,NULL);
+                       SQLColAttributes(res->hstmt,i+1,SQL_COLUMN_TYPE,
+                          NULL,0,NULL,&res->values[i].valtype);
+                       switch ( res->values[i].valtype ) {
+                               case SQL_LONGVARBINARY:
+                               case SQL_LONGVARCHAR:
+                                       res->values[i].value = NULL;
+                                       continue;
+                               default:
+                                       break;
+                       }
+                       SQLColAttributes(res->hstmt,i+1,SQL_COLUMN_DISPLAY_SIZE,
+                          NULL,0,NULL,&coldesc);
+                       res->values[i].value = (char *)emalloc(coldesc+1);
+                       if ( res->values[i].value != NULL ) {
+                               SQLBindCol(res->hstmt,i+1,SQL_C_CHAR,
+                                  res->values[i].value,coldesc+1,
+                                  &res->values[i].vallen);
+                       }
+               }
+       }
+       res->fetched = 0;
+       indx = velocis_add_result(list,res,conn);
+       RETURN_LONG(indx);
+}
+
+void php3_velocis_fetch(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *ind;
+       Vresult *res;
+       RETCODE stat;
+       UDWORD  row;
+       UWORD   RowStat[1];
+
+       if ( ARG_COUNT(ht) != 1 || getParameters(ht,1,&ind) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(ind);
+       res = velocis_find_result(list,ind->value.lval);
+       if ( !res ) {
+               php3_error(E_WARNING,"Velocis: Not result index (%d)",ind->value.lval);
+               RETURN_FALSE;
+       }
+       stat = SQLExtendedFetch(res->hstmt,SQL_FETCH_NEXT,1,&row,RowStat);
+       if ( stat == SQL_NO_DATA_FOUND ) {
+               SQLFreeStmt(res->hstmt,SQL_DROP);
+               velocis_del_result(list,ind->value.lval);
+               RETURN_FALSE;
+       }
+       if ( stat != SQL_SUCCESS && stat != SQL_SUCCESS_WITH_INFO ) {
+               php3_error(E_WARNING,"Velocis: SQLFetch return error");
+               SQLFreeStmt(res->hstmt,SQL_DROP);
+               velocis_del_result(list,ind->value.lval);
+               RETURN_FALSE;
+       }
+       res->fetched = 1;
+       RETURN_TRUE;
+}
+
+void php3_velocis_result(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *ind,*col;
+       Vresult *res;
+       RETCODE stat;
+       int i,sql_c_type;
+       UDWORD row;
+       UWORD RowStat[1];
+       SWORD indx = -1;
+       char *field = NULL;
+
+       if ( ARG_COUNT(ht) != 2 || getParameters(ht,2,&ind,&col) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(ind);
+       res = velocis_find_result(list,ind->value.lval);
+       if ( !res ) {
+               php3_error(E_WARNING,"Velocis: Not result index (%d),ind->value.lval");
+               RETURN_FALSE;
+       }
+       if ( col->type == IS_STRING ) {
+               field = col->value.str.val;
+       } else {
+               convert_to_long(col);
+               indx = col->value.lval;
+       }
+       if ( field ) {
+               for ( i = 0; i < res->numcols; i++ ) {
+                       if ( !strcasecmp(res->values[i].name,field)) {
+                               indx = i;
+                               break;
+                       }
+               }
+               if ( indx < 0 ) {
+                       php3_error(E_WARNING, "Field %s not found",field);
+                       RETURN_FALSE;
+               }
+       } else {
+               if ( indx < 0 || indx >= res->numcols ) {
+                       php3_error(E_WARNING,"Velocis: Field index not in range");
+                       RETURN_FALSE;
+               }
+       }
+       if ( !res->fetched ) {
+               stat = SQLExtendedFetch(res->hstmt,SQL_FETCH_NEXT,1,&row,RowStat);
+               if ( stat == SQL_NO_DATA_FOUND ) {
+                       SQLFreeStmt(res->hstmt,SQL_DROP);
+                       velocis_del_result(list,ind->value.lval);
+                       RETURN_FALSE;
+               }
+               if ( stat != SQL_SUCCESS && stat != SQL_SUCCESS_WITH_INFO ) {
+                       php3_error(E_WARNING,"Velocis: SQLFetch return error");
+                       SQLFreeStmt(res->hstmt,SQL_DROP);
+                       velocis_del_result(list,ind->value.lval);
+                       RETURN_FALSE;
+               }
+               res->fetched = 1;
+       }
+       switch ( res->values[indx].valtype ) {
+               case SQL_LONGVARBINARY:
+                       sql_c_type = SQL_C_BINARY;
+                       goto l1;
+               case SQL_LONGVARCHAR:
+                       sql_c_type = SQL_C_CHAR;
+l1:
+                       if ( !res->values[indx].value ) {
+                               res->values[indx].value = emalloc(4096);
+                               if ( !res->values[indx].value ) {
+                                       php3_error(E_WARNING,"Out of memory");
+                                       RETURN_FALSE;
+                               }
+                       }
+                       stat = SQLGetData(res->hstmt,indx+1,sql_c_type,
+                               res->values[indx].value,4095,&res->values[indx].vallen);
+                       if ( stat == SQL_NO_DATA_FOUND ) {
+                               SQLFreeStmt(res->hstmt,SQL_DROP);
+                               velocis_del_result(list,ind->value.lval);
+                               RETURN_FALSE;
+                       }
+                       if ( stat != SQL_SUCCESS && stat != SQL_SUCCESS_WITH_INFO ) {
+                               php3_error(E_WARNING,"Velocis: SQLGetData return error");
+                               SQLFreeStmt(res->hstmt,SQL_DROP);
+                               velocis_del_result(list,ind->value.lval);
+                               RETURN_FALSE;
+                       }
+                       if ( res->values[indx].valtype == SQL_LONGVARCHAR ) {
+                               RETURN_STRING(res->values[indx].value,TRUE);
+                       } else {
+                               RETURN_LONG((long)res->values[indx].value);
+                       }
+               default:
+                       if ( res->values[indx].value != NULL ) {
+                               RETURN_STRING(res->values[indx].value,TRUE);
+                       }
+       }
+}
+
+void php3_velocis_freeresult(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *ind;
+       Vresult *res;
+
+       if ( ARG_COUNT(ht) != 1 || getParameters(ht,1,&ind) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(ind);
+       res = velocis_find_result(list,ind->value.lval);
+       if ( !res ) {
+               php3_error(E_WARNING,"Velocis: Not result index (%d)",ind->value.lval);
+               RETURN_FALSE;
+       }
+       SQLFreeStmt(res->hstmt,SQL_DROP);
+       velocis_del_result(list,ind->value.lval);
+       RETURN_TRUE;
+}
+
+void php3_velocis_autocommit(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *id;
+       RETCODE stat;
+       VConn *conn;
+
+       if ( ARG_COUNT(ht) != 1 || getParameters(ht,1,&id) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(id);
+       conn = velocis_find_conn(list,id->value.lval);
+       if ( !conn ) {
+               php3_error(E_WARNING,"Velocis: Not connection index (%d)",id->value.lval);
+               RETURN_FALSE;
+       }
+       stat = SQLSetConnectOption(conn->hdbc,SQL_AUTOCOMMIT,SQL_AUTOCOMMIT_ON);
+       if ( stat != SQL_SUCCESS && stat != SQL_SUCCESS_WITH_INFO ) {
+               php3_error(E_WARNING,"Velocis: Set autocommit_on option failure");
+               RETURN_FALSE;
+       }
+       RETURN_TRUE;
+}
+
+void php3_velocis_off_autocommit(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *id;
+       RETCODE stat;
+       VConn *conn;
+
+       if ( ARG_COUNT(ht) != 1 || getParameters(ht,1,&id) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(id);
+       conn = velocis_find_conn(list,id->value.lval);
+       if ( !conn ) {
+               php3_error(E_WARNING,"Velocis: Not connection index (%d)",id->value.lval);
+               RETURN_FALSE;
+       }
+       stat = SQLSetConnectOption(conn->hdbc,SQL_AUTOCOMMIT,SQL_AUTOCOMMIT_OFF);
+       if ( stat != SQL_SUCCESS && stat != SQL_SUCCESS_WITH_INFO ) {
+               php3_error(E_WARNING,"Velocis: Set autocommit_off option failure");
+               RETURN_FALSE;
+       }
+       RETURN_TRUE;
+}
+
+void php3_velocis_commit(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *id;
+       RETCODE stat;
+       VConn *conn;
+
+       if ( ARG_COUNT(ht) != 1 || getParameters(ht,1,&id) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(id);
+       conn = velocis_find_conn(list,id->value.lval);
+       if ( !conn ) {
+               php3_error(E_WARNING,"Velocis: Not connection index (%d)",id->value.lval);
+               RETURN_FALSE;
+       }
+       stat = SQLTransact(NULL,conn->hdbc,SQL_COMMIT);
+       if ( stat != SQL_SUCCESS ) {
+               php3_error(E_WARNING,"Velocis: Commit failure");
+               RETURN_FALSE;
+       }
+       RETURN_TRUE;
+}
+
+void php3_velocis_rollback(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *id;
+       RETCODE stat;
+       VConn *conn;
+
+       if ( ARG_COUNT(ht) != 1 || getParameters(ht,1,&id) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(id);
+       conn = velocis_find_conn(list,id->value.lval);
+       if ( !conn ) {
+               php3_error(E_WARNING,"Velocis: Not connection index (%d)",id->value.lval);
+               RETURN_FALSE;
+       }
+       stat = SQLTransact(NULL,conn->hdbc,SQL_ROLLBACK);
+       if ( stat != SQL_SUCCESS ) {
+               php3_error(E_WARNING,"Velocis: Rollback failure");
+               RETURN_FALSE;
+       }
+       RETURN_TRUE;
+}
+
+void php3_velocis_fieldname(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *ind,*col;
+       Vresult *res;
+       SWORD indx;
+
+       if ( ARG_COUNT(ht) != 2 || getParameters(ht,2,&ind,&col) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(ind);
+       res = velocis_find_result(list,ind->value.lval);
+       if ( !res ) {
+               php3_error(E_WARNING,"Velocis: Not result index (%d),ind->value.lval");
+               RETURN_FALSE;
+       }
+       convert_to_long(col);
+       indx = col->value.lval;
+       if ( indx < 0 || indx >= res->numcols ) {
+               php3_error(E_WARNING,"Velocis: Field index not in range");
+               RETURN_FALSE;
+       }
+       RETURN_STRING(res->values[indx].name,TRUE);
+}
+
+void php3_velocis_fieldnum(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *ind;
+       Vresult *res;
+
+       if ( ARG_COUNT(ht) != 1 || getParameters(ht,1,&ind) == FAILURE ) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_long(ind);
+       res = velocis_find_result(list,ind->value.lval);
+       if ( !res ) {
+               php3_error(E_WARNING,"Velocis: Not result index (%d),ind->value.lval");
+               RETURN_FALSE;
+       }
+       RETURN_LONG(res->numcols);
+}
+
+#endif /* HAVE_VELOCIS */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
index bfdaad1d980d40d42c2d5fc58b623aca33438369..b464d8cecdcba5a0d572c7ec2ae002eb501f1494 100644 (file)
@@ -43,6 +43,7 @@
 #include "ext/standard/php3_standard.h"
 #include "ext/gd/php3_gd.h"
 #include "ext/dbase/dbase.h"
+#include "ext/odbc/php3_odbc.h"
 
 #include "functions/php3_ifx.h"
 #include "functions/php3_ldap.h"
 #include "functions/php3_oci8.h"
 #include "functions/oracle.h"
 #include "functions/php3_pgsql.h"
-#include "functions/php3_velocis.h"
 #include "functions/php3_sybase.h"
 #include "functions/php3_sybase-ct.h"
 #include "functions/imap.h"
 #include "functions/dl.h"
 #include "functions/head.h"
 #include "functions/post.h"
-#include "functions/php3_solid.h"
-#include "functions/adabasd.h"
 #include "functions/hw.h"
 #include "functions/filepro.h"
 #include "functions/db.h"
-#include "functions/php3_unified_odbc.h"
 #include "dl/snmp/php3_snmp.h"
 #include "functions/php3_zlib.h"
 #include "functions/php3_COM.h"
@@ -96,7 +93,6 @@ zend_module_entry *php3_builtin_modules[] =
        pgsql_module_ptr,
        ifx_module_ptr,
        ldap_module_ptr,
-       velocis_module_ptr,
        filepro_module_ptr,
        sybase_module_ptr,
        sybct_module_ptr,
@@ -104,8 +100,6 @@ zend_module_entry *php3_builtin_modules[] =
        dbase_module_ptr,
        hw_module_ptr,
        regexp_module_ptr,
-       solid_module_ptr,
-       adabas_module_ptr,
        gd_module_ptr,
        oci8_module_ptr,
        oracle_module_ptr,
diff --git a/setup b/setup
index 0d6bab48e35fb2bbbb03f299d1dc27035c7c7de1..ae87062165aac669bfbc7689a9e9447731a9a49a 100644 (file)
--- a/setup
+++ b/setup
@@ -246,24 +246,6 @@ define_option with-oracle 'Oracle support?' yesnodir \
     Oracle environment, enter what $ORACLE_HOME is usually set to here.\n
     More info about Oracle can be found at http://www.oracle.com/.'
 
-define_option with-iodbc 'iODBC support?' yesnodir \
-    'no /usr/local iODBC install' \
-'    Whether to build PHP with iODBC support.  This feature was first\n
-    developed for iODBC Driver Manager, a freely redistributable ODBC\n
-    driver manager which runs under many flavors of UNIX.\n
-    More info about iODBC can be found on the FreeODBC Pages at \n
-    http://users.ids.net/~bjepson/freeODBC/.'
-
-define_option with-openlink 'OpenLink ODBC support?' yesnodir \
-    'no /usr/local/openlink OpenLink install' \
-'    Whether to build PHP with OpenLink ODBC support.  See
-     http://www.openlinksw.com/ for more information.'
-
-define_option with-adabas 'Adabas D support?' yesnodir \
-    'no /usr/local Adabas D install root' \
-'    Whether to build with Adabas D support.\n
-    More info about Adabas D can be found at http://www.adabas.com/.'
-
 define_option with-sybase 'Sybase support?' yesnodir \
     'no /home/sybase Sybase install' \
 '     Whether to build PHP with Sybase support (DBLib only).\n
@@ -291,18 +273,6 @@ define_option with-pgsql 'PostgreSQL support?' yesnodir \
     More info about PostgreSQL can be found at\n
     http://www.postgreSQL.org/.'
 
-define_option with-solid 'Solid support?' yesnodir \
-    'no /usr/local/solid Solid install' \
-'     Whether to build PHP with Solid support.\n
-     More information about Solid can be found at http://www.solidtech.com/.'
-
-define_option with-empress 'Empress support?' yesnodir \
-    "no $EMPRESSPATH Empress home" \
-'    Whether to build PHP with Empress support.  Has been confirmed to
-    work with Empress Version 8.10.  If you have not set up your
-    Empress environment, enter what $EMPRESSPATH is usually set to here.
-    More info about Empress can be found at http://www.empress.com/.'
-
 define_option with-informix 'Informix support?' yesnodir \
     "no $INFORMIXDIR Informix home" \
 '    Whether to build PHP with Informix support. If you have not set up your\n
@@ -331,32 +301,6 @@ define_option with-imap 'IMAP support?' yesnodir \
      support.\n
      More information about LDAP can be found in RFC1777 and RFC1778.'
 
-define_option with-velocis 'Velocis support?' yesnodir \
-    'no /usr/local/velocis Velocis install' \
-'     Whether to build PHP with Velocis support.\n
-     More information about Velocis can be found at http://www.raima.com/.'
-
-define_option with-custom-odbc 'custom ODBC support?' yesnodir \
-    'no /usr/local CODBC install' \
-'    Whether to build PHP with CODBC support.  This feature was first
-    developed for Sybase SQL Anywhere 5.5 on QNX, but may be used for
-    any unknown ODBC driver on all flavors of UNIX.'
-
-if test "$option_value_with_iodbc" != "no" -o \
-        "$option_value_with_solid" != "no" -o \
-        "$option_value_with_adabas" != "no" -o \
-        "$option_value_with_velocis" != "no" -o \
-        "$option_value_with_custom_odbc" != "no"
-then
-define_option enable-unified-odbc 'Enable unified ODBC support?' yesno yes \
-'    Whether to enabled the unified ODBC support.  This is a database\n
-    module that compiles with the C API of several DBMSes that happen to\n
-    use ODBC as their C-API.  Has been tested with iODBC, Solid, Adabas D,\n
-    Empress, and Sybase SQL Anywhere. Requires that some one (and only one)\n
-    specific ODBC module is enabled, or some custom ODBC library specified\n
-    instead.'
-fi
-
 define_option with-filepro 'filePro support? ' yesno no \
 '    Whether to use the bundled filePro library.  Read-access only.'