summaryrefslogtreecommitdiff
path: root/ext/pdo_dblib
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_dblib')
-rw-r--r--ext/pdo_dblib/CREDITS2
-rw-r--r--ext/pdo_dblib/README25
-rw-r--r--ext/pdo_dblib/config.m487
-rwxr-xr-xext/pdo_dblib/config.w3273
-rw-r--r--ext/pdo_dblib/dblib_driver.c360
-rw-r--r--ext/pdo_dblib/dblib_stmt.c302
-rw-r--r--ext/pdo_dblib/package2.xml76
-rw-r--r--ext/pdo_dblib/pdo_dblib.c234
-rw-r--r--ext/pdo_dblib/php_pdo_dblib.h43
-rw-r--r--ext/pdo_dblib/php_pdo_dblib_int.h135
-rw-r--r--ext/pdo_dblib/tests/bug_38955.phpt57
-rw-r--r--ext/pdo_dblib/tests/bug_45876.phpt35
-rw-r--r--ext/pdo_dblib/tests/bug_47588.phpt45
-rw-r--r--ext/pdo_dblib/tests/bug_50755.phpt29
-rw-r--r--ext/pdo_dblib/tests/config.inc26
15 files changed, 1529 insertions, 0 deletions
diff --git a/ext/pdo_dblib/CREDITS b/ext/pdo_dblib/CREDITS
new file mode 100644
index 0000000..91a8057
--- /dev/null
+++ b/ext/pdo_dblib/CREDITS
@@ -0,0 +1,2 @@
+DB-LIB (MS SQL, Sybase)
+Wez Furlong, Frank M. Kromann
diff --git a/ext/pdo_dblib/README b/ext/pdo_dblib/README
new file mode 100644
index 0000000..888ffb6
--- /dev/null
+++ b/ext/pdo_dblib/README
@@ -0,0 +1,25 @@
+This is the unified Sybase-DB style driver for PDO.
+There are three implementations of this library that are known to me:
+
+- The Sybase DB lib itself
+- MSSQL DB lib
+- FreeTDS DB lib
+
+This extension will compile and register itself as 'mssql' when built against
+the mssql libraries (and be named php_pdo_mssql.dll), or 'sybase' otherwise
+(php_pdo_sybase.dll)
+
+If you want to try out the free "desktop" version of SQL Server, known as the MSDE, google to obtain the appropriate download link. Here are some short tips on getting it running:
+
+- Download it and run it to extract it
+- Open up a command prompt
+- cd \MSDERelA
+- setup.exe SQLSECURITY=1 SAPWD=yoursecretpassword
+- cd \Program Files\Microsoft SQL Server\80\Tools\Binn
+- SVRNETCN.exe
+- enable TCP (you MUST do this if you want to access it via FreeTDS/Sybase libs)
+- net start mssqlserver
+
+Consult the MS docs for more information about all this stuff.
+
+
diff --git a/ext/pdo_dblib/config.m4 b/ext/pdo_dblib/config.m4
new file mode 100644
index 0000000..ba8244c
--- /dev/null
+++ b/ext/pdo_dblib/config.m4
@@ -0,0 +1,87 @@
+dnl
+dnl $Id$
+dnl
+
+PHP_ARG_WITH(pdo-dblib, for PDO_DBLIB support via FreeTDS,
+[ --with-pdo-dblib[=DIR] PDO: DBLIB-DB support. DIR is the FreeTDS home directory])
+
+if test "$PHP_PDO_DBLIB" != "no"; then
+
+ if test "$PHP_PDO" = "no" && test "$ext_shared" = "no"; then
+ AC_MSG_ERROR([PDO is not enabled! Add --enable-pdo to your configure line.])
+ fi
+
+ if test "$PHP_PDO_DBLIB" = "yes"; then
+
+ for i in /usr/local /usr; do
+ if test -f $i/include/sybdb.h; then
+ PDO_FREETDS_INSTALLATION_DIR=$i
+ PDO_FREETDS_INCLUDE_DIR=$i/include
+ break
+ elif test -f $i/include/freetds/sybdb.h; then
+ PDO_FREETDS_INSTALLATION_DIR=$i
+ PDO_FREETDS_INCLUDE_DIR=$i/include/freetds
+ break;
+ fi
+ done
+
+ if test -z "$PDO_FREETDS_INSTALLATION_DIR"; then
+ AC_MSG_ERROR(Cannot find FreeTDS in known installation directories)
+ fi
+
+ elif test "$PHP_PDO_DBLIB" != "no"; then
+
+ if test -f $PHP_PDO_DBLIB/include/sybdb.h; then
+ PDO_FREETDS_INSTALLATION_DIR=$PHP_PDO_DBLIB
+ PDO_FREETDS_INCLUDE_DIR=$PHP_PDO_DBLIB/include
+ elif test -f $PHP_PDO_DBLIB/include/freetds/sybdb.h; then
+ PDO_FREETDS_INSTALLATION_DIR=$PHP_PDO_DBLIB
+ PDO_FREETDS_INCLUDE_DIR=$PHP_PDO_DBLIB/include/freetds
+ else
+ AC_MSG_ERROR(Directory $PHP_PDO_DBLIB is not a FreeTDS installation directory)
+ fi
+ fi
+
+ if test "x$PHP_LIBDIR" = "x" ; then
+ PHP_LIBDIR=lib
+ fi
+
+ if test ! -r "$PDO_FREETDS_INSTALLATION_DIR/$PHP_LIBDIR/libsybdb.a" && test ! -r "$PDO_FREETDS_INSTALLATION_DIR/$PHP_LIBDIR/libsybdb.so"; then
+ AC_MSG_ERROR(Could not find $PDO_FREETDS_INSTALLATION_DIR/$PHP_LIBDIR/libsybdb.[a|so])
+ fi
+
+ PHP_ADD_INCLUDE($PDO_FREETDS_INCLUDE_DIR)
+ PHP_ADD_LIBRARY_WITH_PATH(sybdb, $PDO_FREETDS_INSTALLATION_DIR/$PHP_LIBDIR, PDO_DBLIB_SHARED_LIBADD)
+
+ ifdef([PHP_CHECK_PDO_INCLUDES],
+ [
+ PHP_CHECK_PDO_INCLUDES
+ ],[
+ AC_MSG_CHECKING([for PDO includes])
+ if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
+ pdo_cv_inc_path=$abs_srcdir/ext
+ elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then
+ pdo_cv_inc_path=$abs_srcdir/ext
+ elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then
+ pdo_cv_inc_path=$prefix/include/php/ext
+ else
+ AC_MSG_ERROR([Cannot find php_pdo_driver.h.])
+ fi
+ AC_MSG_RESULT($pdo_cv_inc_path)
+ ])
+
+ PDO_DBLIB_DEFS="-DPDO_DBLIB_FLAVOUR=\\\"freetds\\\""
+ PHP_NEW_EXTENSION(pdo_dblib, pdo_dblib.c dblib_driver.c dblib_stmt.c, $ext_shared,,-I$pdo_cv_inc_path $PDO_DBLIB_DEFS)
+ AC_CHECK_LIB(dnet_stub, dnet_addr,
+ [ PHP_ADD_LIBRARY_WITH_PATH(dnet_stub,,PDO_DBLIB_SHARED_LIBADD)
+ AC_DEFINE(HAVE_LIBDNET_STUB,1,[ ])
+ ])
+ AC_DEFINE(HAVE_PDO_DBLIB,1,[ ])
+ AC_DEFINE(HAVE_FREETDS,1,[ ])
+ PHP_SUBST(PDO_DBLIB_SHARED_LIBADD)
+
+ ifdef([PHP_ADD_EXTENSION_DEP],
+ [
+ PHP_ADD_EXTENSION_DEP(pdo_dblib, pdo)
+ ])
+fi
diff --git a/ext/pdo_dblib/config.w32 b/ext/pdo_dblib/config.w32
new file mode 100755
index 0000000..14cbb68
--- /dev/null
+++ b/ext/pdo_dblib/config.w32
@@ -0,0 +1,73 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_WITH("pdo-dblib", "freetds dblib (Sybase, MS-SQL) support for PDO", "no");
+
+if (PHP_PDO_DBLIB != "no") {
+ /* if they pointed us to a freetds dir, pick that up,
+ * otherwise we'll poke around and look for MSSQL libs */
+
+ if (CHECK_LIB("sybdb.lib", "pdo_dblib", PHP_PDO_DBLIB) &&
+ CHECK_HEADER_ADD_INCLUDE("sybfront.h", "CFLAGS_PDO_DBLIB",
+ PHP_PDO_DBLIB, null, null, true))
+ {
+ EXTENSION("pdo_dblib", "pdo_dblib.c dblib_driver.c dblib_stmt.c");
+ ADD_FLAG('CFLAGS_PDO_DBLIB', "/D PDO_DBLIB_FLAVOUR=\\\"freetds\\\"");
+ ADD_EXTENSION_DEP('pdo_dblib', 'pdo');
+ } else {
+ WARNING("pdo_dblib not enabled, libraries or headers not found")
+ }
+}
+
+ARG_WITH("pdo-mssql", "Native MS-SQL support for PDO", "no");
+
+if (PHP_PDO_MSSQL != "no") {
+ /* if they pointed us to a freetds dir, pick that up,
+ * otherwise we'll poke around and look for MSSQL libs */
+
+ pdo_mssql_locations = new Array(
+ PHP_PDO_MSSQL,
+ "\\Program Files\\Microsoft SQL Server\\80",
+ "\\MSSQL8",
+ "\\MSSQL7",
+ PHP_PHP_BUILD + "\\MSSQL80"
+ );
+ PDO_DBLIB_FLAVOUR = 0;
+
+ if (CHECK_LIB("sybdb.lib", "pdo_mssql", PHP_PDO_MSSQL) &&
+ CHECK_HEADER_ADD_INCLUDE("sybfront.h", "CFLAGS_PDO_MSSQL",
+ PHP_PDO_MSSQL, null, null, true)) {
+ /* smells like FreeTDS (or maybe native sybase dblib) */
+ PDO_DBLIB_FLAVOUR = "freetds";
+ } else {
+
+ for (i = 0; i < pdo_mssql_locations.length; i++) {
+ if (CHECK_LIB("ntwdblib.lib", "pdo_mssql",
+ pdo_mssql_locations[i] + "\\DevTools\\Lib") &&
+ CHECK_HEADER_ADD_INCLUDE("sqlfront.h", "CFLAGS_PDO_MSSQL",
+ pdo_mssql_locations[i] + "\\DevTools\\Include",
+ null, null, true)) {
+ if (pdo_mssql_locations[i] == 'yes') {
+ PDO_DBLIB_FLAVOUR = 70;
+ } else {
+ pdo_mssql_locations[i].match(new RegExp("(\\d)"));
+ PDO_DBLIB_FLAVOUR = RegExp.$1 + 0;
+ }
+ break;
+ }
+ }
+ }
+
+ if (PDO_DBLIB_FLAVOUR != 0) {
+ EXTENSION("pdo_mssql", "pdo_dblib.c dblib_driver.c dblib_stmt.c", null, null, null, "ext\\pdo_mssql");
+ if (PDO_DBLIB_FLAVOUR != "freetds") {
+ ADD_FLAG("CFLAGS_PDO_MSSQL", "/DPHP_DBLIB_IS_MSSQL=1 /DDBNTWIN32=1 /DMSSQL" + PDO_DBLIB_FLAVOUR + "0=1 /DMSSQL_VERSION=\\\"" + PDO_DBLIB_FLAVOUR + ".0\\\"");
+ ADD_FLAG("CFLAGS_PDO_MSSQL", "/DPDO_DBLIB_IS_MSSQL=" + PDO_DBLIB_FLAVOUR);
+ PDO_DBLIB_FLAVOUR = "MSSQL_" + PDO_DBLIB_FLAVOUR;
+ }
+ ADD_FLAG('CFLAGS_PDO_MSSQL', "/D PDO_DBLIB_FLAVOUR=\\\"" + PDO_DBLIB_FLAVOUR + "\\\"");
+ ADD_EXTENSION_DEP('pdo_mssql', 'pdo');
+ } else {
+ WARNING("pdo_mssql not enabled, libraries or headers not found")
+ }
+}
diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c
new file mode 100644
index 0000000..ffc9101
--- /dev/null
+++ b/ext/pdo_dblib/dblib_driver.c
@@ -0,0 +1,360 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@php.net> |
+ | Frank M. Kromann <frank@kromann.info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "pdo/php_pdo.h"
+#include "pdo/php_pdo_driver.h"
+#include "php_pdo_dblib.h"
+#include "php_pdo_dblib_int.h"
+#include "zend_exceptions.h"
+
+static int dblib_fetch_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+ pdo_dblib_err *einfo = &H->err;
+ pdo_dblib_stmt *S = NULL;
+ char *message;
+ char *msg;
+
+ if (stmt) {
+ S = (pdo_dblib_stmt*)stmt->driver_data;
+ einfo = &S->err;
+ }
+
+ if (einfo->dberr == SYBESMSG && einfo->lastmsg) {
+ msg = einfo->lastmsg;
+ } else if (einfo->dberr == SYBESMSG && DBLIB_G(err).lastmsg) {
+ msg = DBLIB_G(err).lastmsg;
+ DBLIB_G(err).lastmsg = NULL;
+ } else {
+ msg = einfo->dberrstr;
+ }
+
+ spprintf(&message, 0, "%s [%d] (severity %d) [%s]",
+ msg, einfo->dberr, einfo->severity, stmt ? stmt->active_query_string : "");
+
+ add_next_index_long(info, einfo->dberr);
+ add_next_index_string(info, message, 0);
+ add_next_index_long(info, einfo->oserr);
+ add_next_index_long(info, einfo->severity);
+ if (einfo->oserrstr) {
+ add_next_index_string(info, einfo->oserrstr, 1);
+ }
+
+ return 1;
+}
+
+
+static int dblib_handle_closer(pdo_dbh_t *dbh TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+
+ if (H) {
+ if (H->link) {
+ dbclose(H->link);
+ H->link = NULL;
+ }
+ if (H->login) {
+ dbfreelogin(H->login);
+ H->login = NULL;
+ }
+ pefree(H, dbh->is_persistent);
+ dbh->driver_data = NULL;
+ }
+ return 0;
+}
+
+static int dblib_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+ pdo_dblib_stmt *S = ecalloc(1, sizeof(*S));
+
+ S->H = H;
+ stmt->driver_data = S;
+ stmt->methods = &dblib_stmt_methods;
+ stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
+ S->err.sqlstate = stmt->error_code;
+
+ return 1;
+}
+
+static long dblib_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+ RETCODE ret, resret;
+
+ dbsetuserdata(H->link, (BYTE*)&H->err);
+
+ if (FAIL == dbcmd(H->link, sql)) {
+ return -1;
+ }
+
+ if (FAIL == dbsqlexec(H->link)) {
+ return -1;
+ }
+
+ resret = dbresults(H->link);
+
+ if (resret == FAIL) {
+ return -1;
+ }
+
+ ret = dbnextrow(H->link);
+ if (ret == FAIL) {
+ return -1;
+ }
+
+ if (dbnumcols(H->link) <= 0) {
+ return DBCOUNT(H->link);
+ }
+
+ /* throw away any rows it might have returned */
+ dbcanquery(H->link);
+
+ return DBCOUNT(H->link);
+}
+
+static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+ char *q;
+ int l = 1;
+
+ *quoted = q = safe_emalloc(2, unquotedlen, 3);
+ *q++ = '\'';
+
+ while (unquotedlen--) {
+ if (*unquoted == '\'') {
+ *q++ = '\'';
+ *q++ = '\'';
+ l += 2;
+ } else {
+ *q++ = *unquoted;
+ ++l;
+ }
+ unquoted++;
+ }
+
+ *q++ = '\'';
+ *q++ = '\0';
+ *quotedlen = l+1;
+
+ return 1;
+}
+
+static int pdo_dblib_transaction_cmd(const char *cmd, pdo_dbh_t *dbh TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+ RETCODE ret;
+
+ if (FAIL == dbcmd(H->link, cmd)) {
+ return 0;
+ }
+
+ if (FAIL == dbsqlexec(H->link)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int dblib_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
+{
+ return pdo_dblib_transaction_cmd("BEGIN TRANSACTION", dbh TSRMLS_CC);
+}
+
+static int dblib_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
+{
+ return pdo_dblib_transaction_cmd("COMMIT TRANSACTION", dbh TSRMLS_CC);
+}
+
+static int dblib_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
+{
+ return pdo_dblib_transaction_cmd("ROLLBACK TRANSACTION", dbh TSRMLS_CC);
+}
+
+char *dblib_handle_last_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+
+ RETCODE ret;
+ char *id = NULL;
+
+ /*
+ * Would use scope_identity() but it's not implemented on Sybase
+ */
+
+ if (FAIL == dbcmd(H->link, "SELECT @@IDENTITY")) {
+ return NULL;
+ }
+
+ if (FAIL == dbsqlexec(H->link)) {
+ return NULL;
+ }
+
+ ret = dbresults(H->link);
+ if (ret == FAIL || ret == NO_MORE_RESULTS) {
+ dbcancel(H->link);
+ return NULL;
+ }
+
+ ret = dbnextrow(H->link);
+
+ if (ret == FAIL || ret == NO_MORE_ROWS) {
+ dbcancel(H->link);
+ return NULL;
+ }
+
+ if (dbdatlen(H->link, 1) == 0) {
+ dbcancel(H->link);
+ return NULL;
+ }
+
+ id = emalloc(32);
+ *len = dbconvert(NULL, (dbcoltype(H->link, 1)) , (dbdata(H->link, 1)) , (dbdatlen(H->link, 1)), SQLCHAR, id, (DBINT)-1);
+
+ dbcancel(H->link);
+ return id;
+}
+
+static struct pdo_dbh_methods dblib_methods = {
+ dblib_handle_closer,
+ dblib_handle_preparer,
+ dblib_handle_doer,
+ dblib_handle_quoter,
+ dblib_handle_begin, /* begin */
+ dblib_handle_commit, /* commit */
+ dblib_handle_rollback, /* rollback */
+ NULL, /*set attr */
+ dblib_handle_last_id, /* last insert id */
+ dblib_fetch_error, /* fetch error */
+ NULL, /* get attr */
+ NULL, /* check liveness */
+ NULL, /* get driver methods */
+ NULL, /* request shutdown */
+ NULL /* in transaction */
+};
+
+static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H;
+ int i, ret = 0;
+ struct pdo_data_src_parser vars[] = {
+ { "charset", NULL, 0 },
+ { "appname", "PHP " PDO_DBLIB_FLAVOUR, 0 },
+ { "host", "127.0.0.1", 0 },
+ { "dbname", NULL, 0 },
+ { "secure", NULL, 0 }, /* DBSETLSECURE */
+ /* TODO: DBSETLVERSION ? */
+ };
+
+ php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 5);
+
+ H = pecalloc(1, sizeof(*H), dbh->is_persistent);
+ H->login = dblogin();
+ H->err.sqlstate = dbh->error_code;
+
+ if (!H->login) {
+ goto cleanup;
+ }
+
+ if (dbh->username) {
+ DBSETLUSER(H->login, dbh->username);
+ }
+ if (dbh->password) {
+ DBSETLPWD(H->login, dbh->password);
+ }
+
+#if !PHP_DBLIB_IS_MSSQL
+ if (vars[0].optval) {
+ DBSETLCHARSET(H->login, vars[0].optval);
+ }
+#endif
+
+ DBSETLAPP(H->login, vars[1].optval);
+
+#if PHP_DBLIB_IS_MSSQL
+ dbprocerrhandle(H->login, (EHANDLEFUNC) error_handler);
+ dbprocmsghandle(H->login, (MHANDLEFUNC) msg_handler);
+#endif
+
+ H->link = dbopen(H->login, vars[2].optval);
+
+ if (H->link == NULL) {
+ goto cleanup;
+ }
+
+ /* dblib do not return more than this length from text/image */
+ DBSETOPT(H->link, DBTEXTLIMIT, "2147483647");
+
+ /* limit text/image from network */
+ DBSETOPT(H->link, DBTEXTSIZE, "2147483647");
+
+ /* allow double quoted indentifiers */
+ DBSETOPT(H->link, DBQUOTEDIDENT, NULL);
+
+ if (vars[3].optval && FAIL == dbuse(H->link, vars[3].optval)) {
+ goto cleanup;
+ }
+
+ ret = 1;
+ dbh->max_escaped_char_length = 2;
+ dbh->alloc_own_columns = 1;
+
+cleanup:
+ for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
+ if (vars[i].freeme) {
+ efree(vars[i].optval);
+ }
+ }
+
+ dbh->methods = &dblib_methods;
+ dbh->driver_data = H;
+
+ if (!ret) {
+ zend_throw_exception_ex(php_pdo_get_exception(), DBLIB_G(err).dberr TSRMLS_CC,
+ "SQLSTATE[%s] %s (severity %d)",
+ DBLIB_G(err).sqlstate,
+ DBLIB_G(err).dberrstr,
+ DBLIB_G(err).severity);
+ }
+
+ return ret;
+}
+
+pdo_driver_t pdo_dblib_driver = {
+#if PDO_DBLIB_IS_MSSQL
+ PDO_DRIVER_HEADER(mssql),
+#elif defined(PHP_WIN32)
+#define PDO_DBLIB_IS_SYBASE
+ PDO_DRIVER_HEADER(sybase),
+#else
+ PDO_DRIVER_HEADER(dblib),
+#endif
+ pdo_dblib_handle_factory
+};
+
diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c
new file mode 100644
index 0000000..1a2fefd
--- /dev/null
+++ b/ext/pdo_dblib/dblib_stmt.c
@@ -0,0 +1,302 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@php.net> |
+ | Frank M. Kromann <frank@kromann.info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/php_string.h"
+#include "ext/standard/info.h"
+#include "pdo/php_pdo.h"
+#include "pdo/php_pdo_driver.h"
+#include "php_pdo_dblib.h"
+#include "php_pdo_dblib_int.h"
+#include "zend_exceptions.h"
+
+
+/* {{{ pdo_dblib_get_field_name
+ *
+ * Updated for MSSQL 2008 SR2 extended types
+ *
+ */
+static char *pdo_dblib_get_field_name(int type)
+{
+ switch (type) {
+ case 34: return "image";
+ case 35: return "text";
+ case 36: return "uniqueidentifier";
+ case 40: return "date";
+ case 41: return "time";
+ case 42: return "datetime2";
+ case 43: return "datetimeoffset";
+ case 48: return "tinyint";
+ case 52: return "smallint";
+ case 56: return "int";
+ case 58: return "smalldatetime";
+ case 59: return "real";
+ case 60: return "money";
+ case 61: return "datetime";
+ case 62: return "float";
+ case 98: return "sql_variant";
+ case 99: return "ntext";
+ case 104: return "bit";
+ case 106: return "decimal";
+ case 108: return "numeric";
+ case 122: return "smallmoney";
+ case 127: return "bigint";
+ case 240: return "geometry";
+ case 165: return "varbinary";
+ case 167: return "varchar";
+ case 173: return "binary";
+ case 175: return "char";
+ case 189: return "timestamp";
+ case 231: return "nvarchar";
+ case 239: return "nchar";
+ case 241: return "xml";
+ default:
+ return "unknown";
+ break;
+ }
+}
+/* }}} */
+
+static int dblib_dblib_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ /* Cancel any pending results */
+ dbcancel(H->link);
+
+ efree(stmt->columns);
+ stmt->columns = NULL;
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+
+ dblib_dblib_stmt_cursor_closer(stmt TSRMLS_CC);
+
+ efree(S);
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+ RETCODE ret;
+
+ ret = dbresults(H->link);
+
+ if (ret == FAIL || ret == NO_MORE_RESULTS) {
+ return 0;
+ }
+
+ stmt->row_count = DBCOUNT(H->link);
+ stmt->column_count = dbnumcols(H->link);
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+ RETCODE ret;
+
+ dbsetuserdata(H->link, (BYTE*) &S->err);
+
+ if (FAIL == dbcmd(H->link, stmt->active_query_string)) {
+ return 0;
+ }
+
+ if (FAIL == dbsqlexec(H->link)) {
+ return 0;
+ }
+
+ ret = pdo_dblib_stmt_next_rowset(stmt TSRMLS_CC);
+
+ if (ret == 0) {
+ return 0;
+ }
+
+ stmt->row_count = DBCOUNT(H->link);
+ stmt->column_count = dbnumcols(H->link);
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_fetch(pdo_stmt_t *stmt,
+ enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
+{
+
+ RETCODE ret;
+
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ ret = dbnextrow(H->link);
+
+ if (ret == FAIL || ret == NO_MORE_ROWS) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ struct pdo_column_data *col = &stmt->columns[colno];
+
+ col->name = (char*)dbcolname(H->link, colno+1);
+ col->maxlen = dbcollen(H->link, colno+1);
+ col->namelen = strlen(col->name);
+ col->param_type = PDO_PARAM_STR;
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
+ unsigned long *len, int *caller_frees TSRMLS_DC)
+{
+
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ int coltype;
+ unsigned int tmp_len;
+ char *tmp_ptr = NULL;
+
+ coltype = dbcoltype(H->link, colno+1);
+
+ *len = dbdatlen(H->link, colno+1);
+ *ptr = dbdata(H->link, colno+1);
+
+ if (*len == 0 && *ptr == NULL) {
+ return 1;
+ }
+
+ switch (coltype) {
+ case SQLCHAR:
+ case SQLTEXT:
+ case SQLVARBINARY:
+ case SQLBINARY:
+ case SQLIMAGE:
+ case SQLVARCHAR:
+ tmp_ptr = emalloc(*len + 1);
+ memcpy(tmp_ptr, *ptr, *len);
+ tmp_ptr[*len] = '\0';
+ *ptr = tmp_ptr;
+ break;
+ case SQLMONEY:
+ case SQLMONEY4:
+ case SQLMONEYN: {
+ DBFLT8 money_value;
+ dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
+ *len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
+ *ptr = tmp_ptr;
+ break;
+ }
+#ifdef SQLUNIQUE
+ case SQLUNIQUE: {
+#else
+ case 36: { /* FreeTDS hack, also used by ext/mssql */
+#endif
+ *len = 36+1;
+ tmp_ptr = emalloc(*len + 1);
+
+ /* uniqueidentifier is a 16-byte binary number, convert to 32 char hex string */
+#ifdef SQLUNIQUE
+ *len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
+#else
+ *len = dbconvert(NULL, 36, *ptr, *len, SQLCHAR, tmp_ptr, *len);
+#endif
+ php_strtoupper(tmp_ptr, *len);
+ *ptr = tmp_ptr;
+ break;
+ }
+ default:
+ if (dbwillconvert(coltype, SQLCHAR)) {
+ tmp_len = 32 + (2 * (*len));
+ tmp_ptr = emalloc(tmp_len);
+ *len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
+ *ptr = tmp_ptr;
+ } else {
+ *len = 0;
+ *ptr = NULL;
+ }
+ }
+
+ *caller_frees = 1;
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
+ enum pdo_param_event event_type TSRMLS_DC)
+{
+ return 1;
+}
+
+static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ array_init(return_value);
+
+ DBTYPEINFO* dbtypeinfo;
+ dbtypeinfo = dbcoltypeinfo(H->link, colno+1);
+
+ add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
+ add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
+ add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
+ add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1), 1);
+ add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)), 1);
+
+ return 1;
+}
+
+
+struct pdo_stmt_methods dblib_stmt_methods = {
+ pdo_dblib_stmt_dtor,
+ pdo_dblib_stmt_execute,
+ pdo_dblib_stmt_fetch,
+ pdo_dblib_stmt_describe,
+ pdo_dblib_stmt_get_col,
+ pdo_dblib_stmt_param_hook,
+ NULL, /* set attr */
+ NULL, /* get attr */
+ pdo_dblib_stmt_get_column_meta, /* meta */
+ pdo_dblib_stmt_next_rowset, /* nextrow */
+ dblib_dblib_stmt_cursor_closer
+};
+
diff --git a/ext/pdo_dblib/package2.xml b/ext/pdo_dblib/package2.xml
new file mode 100644
index 0000000..8b72666
--- /dev/null
+++ b/ext/pdo_dblib/package2.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.2" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>PDO_DBLIB</name>
+ <channel>pecl.php.net</channel>
+ <summary>FreeTDS/Sybase/MSSQL driver for PDO</summary>
+ <description>This extension provides a FreeTDS/Sybase/MSSQL driver for PDO.
+ </description>
+ <lead>
+ <name>Wez Furlong</name>
+ <user>wez</user>
+ <email>wez@php.net</email>
+ <active>yes</active>
+ </lead>
+ <lead>
+ <name>Frank M. Kromann</name>
+ <user>fmk</user>
+ <email>fmk@php.net</email>
+ <active>yes</active>
+ </lead>
+ <date>2006-05-01</date>
+ <version>
+ <release>1.0.1</release>
+ <api>1.0.1</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP</license>
+ <notes>
+- Packaging update; no functional changes in this release
+- Fix Bug #34777; segfault when retrieving non-existent error info
+- Fix Bug #35032; didn&apos;t find FreeTDS includes on some systems
+
+Windows binaries can be found at:
+http://pecl4win.php.net/ext.php/php_pdo_mssql.dll,
+
+however: you are *strongly* recommended to use PDO_ODBC instead of this driver on
+Windows platforms.
+
+
+ </notes>
+ <contents>
+ <dir name="/">
+ <file name="config.m4" role="src" />
+ <file name="CREDITS" role="doc" />
+ <file name="dblib_driver.c" role="src" />
+ <file name="dblib_stmt.c" role="src" />
+ <file name="pdo_dblib.c" role="src" />
+ <file name="php_pdo_dblib.h" role="src" />
+ <file name="php_pdo_dblib_int.h" role="src" />
+ <file name="README" role="doc" />
+ </dir> <!-- / -->
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>5.0.3</min>
+ </php>
+ <pearinstaller>
+ <min>1.4.0</min>
+ </pearinstaller>
+ <package>
+ <name>pdo</name>
+ <channel>pecl.php.net</channel>
+ <min>1.0.3</min>
+ <providesextension>PDO</providesextension>
+ </package>
+ </required>
+ </dependencies>
+ <providesextension>PDO_DBLIB</providesextension>
+ <extsrcrelease />
+</package>
diff --git a/ext/pdo_dblib/pdo_dblib.c b/ext/pdo_dblib/pdo_dblib.c
new file mode 100644
index 0000000..ed79aea
--- /dev/null
+++ b/ext/pdo_dblib/pdo_dblib.c
@@ -0,0 +1,234 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@php.net> |
+ | Frank M. Kromann <frank@kromann.info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "pdo/php_pdo.h"
+#include "pdo/php_pdo_driver.h"
+#include "php_pdo_dblib.h"
+#include "php_pdo_dblib_int.h"
+#include "zend_exceptions.h"
+
+ZEND_DECLARE_MODULE_GLOBALS(dblib)
+static PHP_GINIT_FUNCTION(dblib);
+
+const zend_function_entry pdo_dblib_functions[] = {
+ PHP_FE_END
+};
+
+#if ZEND_MODULE_API_NO >= 20050922
+static const zend_module_dep pdo_dblib_deps[] = {
+ ZEND_MOD_REQUIRED("pdo")
+ ZEND_MOD_END
+};
+#endif
+
+#if PDO_DBLIB_IS_MSSQL
+zend_module_entry pdo_mssql_module_entry = {
+#else
+zend_module_entry pdo_dblib_module_entry = {
+#endif
+#if ZEND_MODULE_API_NO >= 20050922
+ STANDARD_MODULE_HEADER_EX, NULL,
+ pdo_dblib_deps,
+#else
+ STANDARD_MODULE_HEADER,
+#endif
+#if PDO_DBLIB_IS_MSSQL
+ "pdo_mssql",
+#elif defined(PHP_WIN32)
+ "pdo_sybase",
+#else
+ "pdo_dblib",
+#endif
+ pdo_dblib_functions,
+ PHP_MINIT(pdo_dblib),
+ PHP_MSHUTDOWN(pdo_dblib),
+ NULL,
+ PHP_RSHUTDOWN(pdo_dblib),
+ PHP_MINFO(pdo_dblib),
+ "1.0.1",
+ PHP_MODULE_GLOBALS(dblib),
+ PHP_GINIT(dblib),
+ NULL,
+ NULL,
+ STANDARD_MODULE_PROPERTIES_EX
+};
+
+#if defined(COMPILE_DL_PDO_DBLIB) || defined(COMPILE_DL_PDO_MSSQL)
+#if PDO_DBLIB_IS_MSSQL
+ZEND_GET_MODULE(pdo_mssql)
+#else
+ZEND_GET_MODULE(pdo_dblib)
+#endif
+#endif
+
+int error_handler(DBPROCESS *dbproc, int severity, int dberr,
+ int oserr, char *dberrstr, char *oserrstr)
+{
+ pdo_dblib_err *einfo;
+ char *state = "HY000";
+ TSRMLS_FETCH();
+
+ einfo = (pdo_dblib_err*)dbgetuserdata(dbproc);
+ if (!einfo) einfo = &DBLIB_G(err);
+
+ einfo->severity = severity;
+ einfo->oserr = oserr;
+ einfo->dberr = dberr;
+ if (einfo->oserrstr) {
+ efree(einfo->oserrstr);
+ }
+ if (einfo->dberrstr) {
+ efree(einfo->dberrstr);
+ }
+ if (oserrstr) {
+ einfo->oserrstr = estrdup(oserrstr);
+ } else {
+ einfo->oserrstr = NULL;
+ }
+ if (dberrstr) {
+ einfo->dberrstr = estrdup(dberrstr);
+ } else {
+ einfo->dberrstr = NULL;
+ }
+
+ switch (dberr) {
+ case SYBESEOF:
+ case SYBEFCON: state = "01002"; break;
+ case SYBEMEM: state = "HY001"; break;
+ case SYBEPWD: state = "28000"; break;
+ }
+ strcpy(einfo->sqlstate, state);
+
+#if 0
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "dblib error: %d %s (severity %d)",
+ dberr, dberrstr, severity);
+#endif
+
+ return INT_CANCEL;
+}
+
+int msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate,
+ int severity, char *msgtext, char *srvname, char *procname, DBUSMALLINT line)
+{
+ pdo_dblib_err *einfo;
+ TSRMLS_FETCH();
+
+ if (severity) {
+ einfo = (pdo_dblib_err*)dbgetuserdata(dbproc);
+ if (!einfo) {
+ einfo = &DBLIB_G(err);
+ }
+
+ if (einfo->lastmsg) {
+ efree(einfo->lastmsg);
+ }
+
+ einfo->lastmsg = estrdup(msgtext);
+ }
+
+#if 0
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "dblib message: %s (severity %d)", msgtext, severity);
+#endif
+
+ return 0;
+}
+
+static PHP_GINIT_FUNCTION(dblib)
+{
+ memset(dblib_globals, 0, sizeof(*dblib_globals));
+ dblib_globals->err.sqlstate = dblib_globals->sqlstate;
+}
+
+PHP_RSHUTDOWN_FUNCTION(pdo_dblib)
+{
+ if (DBLIB_G(err).oserrstr) {
+ efree(DBLIB_G(err).oserrstr);
+ DBLIB_G(err).oserrstr = NULL;
+ }
+ if (DBLIB_G(err).dberrstr) {
+ efree(DBLIB_G(err).dberrstr);
+ DBLIB_G(err).dberrstr = NULL;
+ }
+ if (DBLIB_G(err).lastmsg) {
+ efree(DBLIB_G(err).lastmsg);
+ DBLIB_G(err).lastmsg = NULL;
+ }
+ return SUCCESS;
+}
+
+PHP_MINIT_FUNCTION(pdo_dblib)
+{
+ if (FAIL == dbinit()) {
+ return FAILURE;
+ }
+
+ if (FAILURE == php_pdo_register_driver(&pdo_dblib_driver)) {
+ return FAILURE;
+ }
+
+ /* TODO:
+
+ dbsetifile()
+ dbsetmaxprocs()
+ dbsetlogintime()
+ dbsettime()
+
+ */
+
+#if !PHP_DBLIB_IS_MSSQL
+ dberrhandle(error_handler);
+ dbmsghandle(msg_handler);
+#endif
+
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(pdo_dblib)
+{
+ php_pdo_unregister_driver(&pdo_dblib_driver);
+ dbexit();
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(pdo_dblib)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "PDO Driver for "
+#if PDO_DBLIB_IS_MSSQL
+ "MSSQL"
+#elif defined(PHP_WIN32)
+ "FreeTDS/Sybase/MSSQL"
+#else
+ "FreeTDS/Sybase"
+#endif
+ " DB-lib", "enabled");
+ php_info_print_table_row(2, "Flavour", PDO_DBLIB_FLAVOUR);
+ php_info_print_table_end();
+}
+
diff --git a/ext/pdo_dblib/php_pdo_dblib.h b/ext/pdo_dblib/php_pdo_dblib.h
new file mode 100644
index 0000000..3396f20
--- /dev/null
+++ b/ext/pdo_dblib/php_pdo_dblib.h
@@ -0,0 +1,43 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@php.net> |
+ | Frank M. Kromann <frank@kromann.info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_PDO_DBLIB_H
+#define PHP_PDO_DBLIB_H
+
+#if PDO_DBLIB_IS_MSSQL
+extern zend_module_entry pdo_mssql_module_entry;
+#define phpext_pdo_mssql_ptr &pdo_mssql_module_entry
+#else
+extern zend_module_entry pdo_dblib_module_entry;
+#define phpext_pdo_dblib_ptr &pdo_dblib_module_entry
+#endif
+
+#ifdef ZTS
+# include "TSRM.h"
+#endif
+
+PHP_MINIT_FUNCTION(pdo_dblib);
+PHP_MSHUTDOWN_FUNCTION(pdo_dblib);
+PHP_MINFO_FUNCTION(pdo_dblib);
+PHP_RSHUTDOWN_FUNCTION(pdo_dblib);
+
+#endif
+
diff --git a/ext/pdo_dblib/php_pdo_dblib_int.h b/ext/pdo_dblib/php_pdo_dblib_int.h
new file mode 100644
index 0000000..dd06a1d
--- /dev/null
+++ b/ext/pdo_dblib/php_pdo_dblib_int.h
@@ -0,0 +1,135 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@php.net> |
+ | Frank M. Kromann <frank@kromann.info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_PDO_DBLIB_INT_H
+#define PHP_PDO_DBLIB_INT_H
+
+#ifndef PDO_DBLIB_FLAVOUR
+# define PDO_DBLIB_FLAVOUR "Generic DB-lib"
+#endif
+
+#if PHP_DBLIB_IS_MSSQL
+# include <sqlfront.h>
+# include <sqldb.h>
+
+# define DBERRHANDLE(a, b) dbprocerrhandle(a, b)
+# define DBMSGHANDLE(a, b) dbprocmsghandle(a, b)
+# define EHANDLEFUNC DBERRHANDLE_PROC
+# define MHANDLEFUNC DBMSGHANDLE_PROC
+# define DBSETOPT(a, b, c) dbsetopt(a, b, c)
+# define SYBESMSG SQLESMSG
+# define SYBESEOF SQLESEOF
+# define SYBEFCON SQLECONN // SQLEFCON does not exist in MS SQL Server.
+# define SYBEMEM SQLEMEM
+# define SYBEPWD SQLEPWD
+
+#else
+# include <sybfront.h>
+# include <sybdb.h>
+# include <syberror.h>
+
+/* alias some types */
+# define SQLTEXT SYBTEXT
+# define SQLCHAR SYBCHAR
+# define SQLVARCHAR SYBVARCHAR
+# define SQLINT1 SYBINT1
+# define SQLINT2 SYBINT2
+# define SQLINT4 SYBINT4
+# define SQLINTN SYBINTN
+# define SQLBIT SYBBIT
+# define SQLFLT4 SYBREAL
+# define SQLFLT8 SYBFLT8
+# define SQLFLTN SYBFLTN
+# define SQLDECIMAL SYBDECIMAL
+# define SQLNUMERIC SYBNUMERIC
+# define SQLDATETIME SYBDATETIME
+# define SQLDATETIM4 SYBDATETIME4
+# define SQLDATETIMN SYBDATETIMN
+# define SQLMONEY SYBMONEY
+# define SQLMONEY4 SYBMONEY4
+# define SQLMONEYN SYBMONEYN
+# define SQLIMAGE SYBIMAGE
+# define SQLBINARY SYBBINARY
+# define SQLVARBINARY SYBVARBINARY
+# ifdef SYBUNIQUE
+# define SQLUNIQUE SYBUNIQUE
+# endif
+
+# define DBERRHANDLE(a, b) dberrhandle(b)
+# define DBMSGHANDLE(a, b) dbmsghandle(b)
+# define DBSETOPT(a, b, c) dbsetopt(a, b, c, -1)
+# define NO_MORE_RPC_RESULTS 3
+# define dbfreelogin dbloginfree
+# define dbrpcexec dbrpcsend
+
+typedef short TDS_SHORT;
+# ifndef PHP_WIN32
+typedef unsigned char *LPBYTE;
+# endif
+typedef float DBFLT4;
+#endif
+
+int error_handler(DBPROCESS *dbproc, int severity, int dberr,
+ int oserr, char *dberrstr, char *oserrstr);
+
+int msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate,
+ int severity, char *msgtext, char *srvname, char *procname, DBUSMALLINT line);
+
+extern pdo_driver_t pdo_dblib_driver;
+extern struct pdo_stmt_methods dblib_stmt_methods;
+
+typedef struct {
+ int severity;
+ int oserr;
+ int dberr;
+ char *oserrstr;
+ char *dberrstr;
+ char *sqlstate;
+ char *lastmsg;
+} pdo_dblib_err;
+
+typedef struct {
+ LOGINREC *login;
+ DBPROCESS *link;
+
+ pdo_dblib_err err;
+} pdo_dblib_db_handle;
+
+typedef struct {
+ pdo_dblib_db_handle *H;
+ pdo_dblib_err err;
+} pdo_dblib_stmt;
+
+ZEND_BEGIN_MODULE_GLOBALS(dblib)
+ pdo_dblib_err err;
+ char sqlstate[6];
+ZEND_END_MODULE_GLOBALS(dblib)
+
+#ifdef ZTS
+# define DBLIB_G(v) TSRMG(dblib_globals_id, zend_dblib_globals *, v)
+#else
+# define DBLIB_G(v) (dblib_globals.v)
+#endif
+
+ZEND_EXTERN_MODULE_GLOBALS(dblib);
+
+#endif
+
diff --git a/ext/pdo_dblib/tests/bug_38955.phpt b/ext/pdo_dblib/tests/bug_38955.phpt
new file mode 100644
index 0000000..1954ed4
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_38955.phpt
@@ -0,0 +1,57 @@
+--TEST--
+ PDO_DBLIB driver does not support transactions
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+/*We see these rows */
+$db->query("CREATE table php_test(val int)");
+$db->beginTransaction();
+$db->query("INSERT INTO php_test(val) values(1)");
+$db->query("INSERT INTO php_test(val) values(2)");
+$db->query("INSERT INTO php_test(val) values(3)");
+$db->query("INSERT INTO php_test(val) values(4)");
+$db->commit();
+
+/*We don't see these rows */
+$db->beginTransaction();
+$db->query("INSERT INTO php_test(val) values(5)");
+$db->query("INSERT INTO php_test(val) values(6)");
+$db->query("INSERT INTO php_test(val) values(7)");
+$db->query("INSERT INTO php_test(val) values(8)");
+$db->rollback();
+
+$rs = $db->query("SELECT * FROM php_test");
+$rows = $rs->fetchAll(PDO::FETCH_ASSOC);
+var_dump($rows);
+
+$db->query("DROP table php_test");
+?>
+--EXPECT--
+array(4) {
+ [0]=>
+ array(1) {
+ ["val"]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(1) {
+ ["val"]=>
+ string(1) "2"
+ }
+ [2]=>
+ array(1) {
+ ["val"]=>
+ string(1) "3"
+ }
+ [3]=>
+ array(1) {
+ ["val"]=>
+ string(1) "4"
+ }
+}
diff --git a/ext/pdo_dblib/tests/bug_45876.phpt b/ext/pdo_dblib/tests/bug_45876.phpt
new file mode 100644
index 0000000..9209058
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_45876.phpt
@@ -0,0 +1,35 @@
+--TEST--
+PDO_DBLIB: Does not support get column meta
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+$stmt = $db->prepare("select ic1.* from information_schema.columns ic1");
+$stmt->execute();
+var_dump($stmt->getColumnMeta(0));
+$stmt = null;
+?>
+--EXPECT--
+array(8) {
+ ["max_length"]=>
+ int(255)
+ ["precision"]=>
+ int(0)
+ ["scale"]=>
+ int(0)
+ ["column_source"]=>
+ string(13) "TABLE_CATALOG"
+ ["native_type"]=>
+ string(4) "char"
+ ["name"]=>
+ string(13) "TABLE_CATALOG"
+ ["len"]=>
+ int(255)
+ ["pdo_type"]=>
+ int(2)
+}
diff --git a/ext/pdo_dblib/tests/bug_47588.phpt b/ext/pdo_dblib/tests/bug_47588.phpt
new file mode 100644
index 0000000..d8f424e
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_47588.phpt
@@ -0,0 +1,45 @@
+--TEST--
+PDO_DBLIB: Quoted field names
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+$db->query('CREATE TABLE "Test Table" ("My Field" int, "Another Field" varchar(32) not null default \'test_string\')');
+$db->query('INSERT INTO "Test Table" ("My Field") values(1)');
+$db->query('INSERT INTO "Test Table" ("My Field") values(2)');
+$db->query('INSERT INTO "Test Table" ("My Field") values(3)');
+$rs = $db->query('SELECT * FROM "Test Table"');
+var_dump($rs->fetchAll(PDO::FETCH_ASSOC));
+$db->query('DROP TABLE "Test Table"');
+echo "Done.\n";
+?>
+--EXPECT--
+array(3) {
+ [0]=>
+ array(2) {
+ ["My Field"]=>
+ string(1) "1"
+ ["Another Field"]=>
+ string(11) "test_string"
+ }
+ [1]=>
+ array(2) {
+ ["My Field"]=>
+ string(1) "2"
+ ["Another Field"]=>
+ string(11) "test_string"
+ }
+ [2]=>
+ array(2) {
+ ["My Field"]=>
+ string(1) "3"
+ ["Another Field"]=>
+ string(11) "test_string"
+ }
+}
+Done.
diff --git a/ext/pdo_dblib/tests/bug_50755.phpt b/ext/pdo_dblib/tests/bug_50755.phpt
new file mode 100644
index 0000000..95d1a8b
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_50755.phpt
@@ -0,0 +1,29 @@
+--TEST--
+PDO_DBLIB: Out of memory on large recordsets
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+/* This should be sufficient to overflow any buffers */
+$stmt = $db->prepare("select *
+from information_schema.columns ic1
+cross join information_schema.columns ic2
+cross join information_schema.columns ic3");
+
+$x = $stmt->execute();
+$n = 0;
+while (($r = $stmt->fetch())) {
+ $n++;
+}
+$stmt = null;
+
+echo "OK\n";
+
+?>
+--EXPECT--
+OK
diff --git a/ext/pdo_dblib/tests/config.inc b/ext/pdo_dblib/tests/config.inc
new file mode 100644
index 0000000..5b7b4d4
--- /dev/null
+++ b/ext/pdo_dblib/tests/config.inc
@@ -0,0 +1,26 @@
+<?php
+
+if (false !== getenv('PDO_DBLIB_TEST_DSN'))
+ $dsn = getenv('PDO_DBLIB_TEST_DSN');
+else
+ $dsn = 'dblib:host=localhost;dbname=test';
+
+if (false !== getenv('PDO_DBLIB_TEST_USER'))
+ $user = getenv('PDO_DBLIB_TEST_USER');
+else
+ $user = 'php';
+
+
+if (false !== getenv('PDO_DBLIB_TEST_PASS'))
+ $pass = getenv('PDO_DBLIB_TEST_PASS');
+else
+ $pass = 'password';
+
+try {
+ $db = new PDO($dsn, $user, $pass);
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
+} catch (PDOException $e) {
+ die('skip ' . $e->getMessage());
+}
+?>