summaryrefslogtreecommitdiff
path: root/ext/mssql
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-03-14 05:42:27 +0000
committer <>2013-04-03 16:25:08 +0000
commitc4dd7a1a684490673e25aaf4fabec5df138854c4 (patch)
tree4d57c44caae4480efff02b90b9be86f44bf25409 /ext/mssql
downloadphp2-master.tar.gz
Imported from /home/lorry/working-area/delta_php2/php-5.4.13.tar.bz2.HEADphp-5.4.13master
Diffstat (limited to 'ext/mssql')
-rw-r--r--ext/mssql/CREDITS2
-rw-r--r--ext/mssql/config.m456
-rw-r--r--ext/mssql/config.w3228
-rw-r--r--ext/mssql/mssql.dsp117
-rw-r--r--ext/mssql/mssql_win32_howto.txt35
-rw-r--r--ext/mssql/php_mssql.c2279
-rw-r--r--ext/mssql/php_mssql.h214
7 files changed, 2731 insertions, 0 deletions
diff --git a/ext/mssql/CREDITS b/ext/mssql/CREDITS
new file mode 100644
index 0000000..548684a
--- /dev/null
+++ b/ext/mssql/CREDITS
@@ -0,0 +1,2 @@
+MS SQL
+Frank M. Kromann
diff --git a/ext/mssql/config.m4 b/ext/mssql/config.m4
new file mode 100644
index 0000000..4231bb3
--- /dev/null
+++ b/ext/mssql/config.m4
@@ -0,0 +1,56 @@
+dnl
+dnl $Id$
+dnl
+
+PHP_ARG_WITH(mssql,for MSSQL support via FreeTDS,
+[ --with-mssql[=DIR] Include MSSQL-DB support. DIR is the FreeTDS home
+ directory [/usr/local/freetds]])
+
+if test "$PHP_MSSQL" != "no"; then
+
+ if test "$PHP_MSSQL" = "yes"; then
+ for i in /usr/local /usr; do
+ if test -f $i/include/sybdb.h; then
+ FREETDS_INSTALLATION_DIR=$i
+ FREETDS_INCLUDE_DIR=$i/include
+ break
+ elif test -f $i/include/freetds/sybdb.h; then
+ FREETDS_INSTALLATION_DIR=$i
+ FREETDS_INCLUDE_DIR=$i/include/freetds
+ break
+ fi
+ done
+
+ if test -z "$FREETDS_INSTALLATION_DIR"; then
+ AC_MSG_ERROR(Cannot find FreeTDS in known installation directories)
+ fi
+
+ elif test "$PHP_MSSQL" != "no"; then
+
+ if test -f $PHP_MSSQL/include/sybdb.h; then
+ FREETDS_INSTALLATION_DIR=$PHP_MSSQL
+ FREETDS_INCLUDE_DIR=$PHP_MSSQL/include
+ elif test -f $PHP_MSSQL/include/freetds/sybdb.h; then
+ FREETDS_INSTALLATION_DIR=$PHP_MSSQL
+ FREETDS_INCLUDE_DIR=$PHP_MSSQL/include/freetds
+ else
+ AC_MSG_ERROR(Directory $PHP_MSSQL is not a FreeTDS installation directory)
+ fi
+ fi
+
+ if test ! -r "$FREETDS_INSTALLATION_DIR/$PHP_LIBDIR/libsybdb.a" && test ! -r "$FREETDS_INSTALLATION_DIR/$PHP_LIBDIR/libsybdb.so"; then
+ AC_MSG_ERROR(Could not find $FREETDS_INSTALLATION_DIR/$PHP_LIBDIR/libsybdb.[a|so])
+ fi
+
+ PHP_ADD_INCLUDE($FREETDS_INCLUDE_DIR)
+ PHP_ADD_LIBRARY_WITH_PATH(sybdb, $FREETDS_INSTALLATION_DIR/$PHP_LIBDIR, MSSQL_SHARED_LIBADD)
+
+ PHP_NEW_EXTENSION(mssql, php_mssql.c, $ext_shared)
+ AC_CHECK_LIB(dnet_stub, dnet_addr,
+ [ PHP_ADD_LIBRARY_WITH_PATH(dnet_stub,,MSSQL_SHARED_LIBADD)
+ AC_DEFINE(HAVE_LIBDNET_STUB,1,[ ])
+ ])
+ AC_DEFINE(HAVE_MSSQL,1,[ ])
+ AC_DEFINE(HAVE_FREETDS,1,[ ])
+ PHP_SUBST(MSSQL_SHARED_LIBADD)
+fi
diff --git a/ext/mssql/config.w32 b/ext/mssql/config.w32
new file mode 100644
index 0000000..bd1f686
--- /dev/null
+++ b/ext/mssql/config.w32
@@ -0,0 +1,28 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_WITH("mssql", "mssql support", "no");
+
+if (PHP_MSSQL != "no") {
+ if (CHECK_LIB("ntwdblib.lib", "mssql", "\\MSSQL7\\DevTools\\Lib;\\MSSQL7\\DevTools\\Lib;" + PHP_MSSQL) &&
+ CHECK_HEADER_ADD_INCLUDE("sqlfront.h", "CFLAGS_MSSQL", "\\MSSQL7\\DevTools\\Include;\\MSSQL7\\DevTools\\Include" + PHP_MSSQL)) {
+ EXTENSION("mssql", "php_mssql.c");
+ AC_DEFINE('HAVE_MSSQL', 1, 'Have MSSQL support');
+ ADD_FLAG("CFLAGS_MSSQL", "/D DBNTWIN32=1 /D MSSQL70=1");
+ } else {
+ WARNING("mssql not enabled; libraries and headers not found");
+ }
+}
+
+ARG_WITH("dblib", "mssql support with freetds", "no");
+
+if (PHP_DBLIB != "no") {
+ if (CHECK_LIB("dblib.lib", "dblib", PHP_PHP_BUILD + "\\freetds") &&
+ CHECK_HEADER_ADD_INCLUDE("sybfront.h", "CFLAGS_DBLIB", PHP_PHP_BUILD + "\\freetds;" + PHP_DBLIB)) {
+ EXTENSION("dblib", "php_mssql.c", null, null, null, "ext\\dblib");
+ AC_DEFINE('HAVE_MSSQL', 1, 'Have MSSQL support');
+ ADD_FLAG("CFLAGS_DBLIB", "/D HAVE_FREETDS=1 /D DBNTWIN32=1 /D MSSQL70=1 /D MSSQL_EXPORTS /D COMPILE_DL_MSSQL");
+ } else {
+ WARNING("dblib not enabled; libraries and headers not found");
+ }
+}
diff --git a/ext/mssql/mssql.dsp b/ext/mssql/mssql.dsp
new file mode 100644
index 0000000..4329428
--- /dev/null
+++ b/ext/mssql/mssql.dsp
@@ -0,0 +1,117 @@
+# Microsoft Developer Studio Project File - Name="mssql" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mssql - Win32 Release_TS
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mssql.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mssql.mak" CFG="mssql - Win32 Release_TS"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mssql - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mssql - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mssql - Win32 Release_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_TS"
+# PROP BASE Intermediate_Dir "Release_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_TS"
+# PROP Intermediate_Dir "Release_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D MSSQL70=1 /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MSSQL_EXPORTS" /D "COMPILE_DL_MSSQL" /D "DBNTWIN32" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_MSSQL=1 /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D MSSQL70=1 /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MSSQL_EXPORTS" /D "COMPILE_DL_MSSQL" /D "DBNTWIN32" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_MSSQL=1 /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib ntwdblib.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_mssql70.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\..\php_build\mssql-70\lib" /libpath:"..\..\Release_TS_Inline"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib ntwdblib.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_mssql.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\..\php_build\mssql-70\lib" /libpath:"..\..\Release_TS_Inline"
+
+!ELSEIF "$(CFG)" == "mssql - Win32 Debug_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Debug_TS"
+# PROP BASE Intermediate_Dir "Debug_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Debug_TS"
+# PROP Intermediate_Dir "Debug_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D MSSQL70=1 /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MSSQL_EXPORTS" /D "COMPILE_DL_MSSQL" /D "DBNTWIN32" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_MSSQL=1 /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D MSSQL70=1 /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MSSQL_EXPORTS" /D "COMPILE_DL_MSSQL" /D "DBNTWIN32" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_MSSQL=1 /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts_debug.lib ntwdblib.lib /nologo /dll /machine:I386 /out:"..\..\Debug_TS/php_mssql70.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\php_build\mssql-70\lib"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts_debug.lib ntwdblib.lib /nologo /dll /incremental:yes /debug /machine:I386 /out:"..\..\Debug_TS/php_mssql.dll" /pdbtype:sept /libpath:"..\..\Debug_TS" /libpath:"..\..\..\php_build\mssql-70\lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mssql - Win32 Release_TS"
+# Name "mssql - Win32 Debug_TS"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\php_mssql.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\php_mssql.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=.\mssql_win32_howto.txt
+# End Source File
+# End Target
+# End Project
diff --git a/ext/mssql/mssql_win32_howto.txt b/ext/mssql/mssql_win32_howto.txt
new file mode 100644
index 0000000..d42bc25
--- /dev/null
+++ b/ext/mssql/mssql_win32_howto.txt
@@ -0,0 +1,35 @@
+Rules for building MSSQL
+------------------------
+
+The MSSQL project contains 2 configurations.
+
+The files needed for each configurations are:
+
+Win32 Release_TS
+Win32 Debug_TS
+
+ php_build\mssql-70\include\sqldb.h
+ php_build\mssql-70\include\sqlfront.h
+ php_build\mssql-70\lib\ntwdblib.lib
+
+php_build is a directory at the same level as php5.
+
+Start Visual Studio, load php_modules.dsw, select the MSSQL projects,
+configuration and build it.
+
+This module requires ntwdblib.dll and one or more of the following dll's
+
+dbmsadsn.dll
+dbmsrpcn.dll
+dbmsshrn.dll
+dbmssocn.dll for tcp/ip connections
+dbmsspxn.dll for ipx/spx connections
+dbmsvinn.dll
+dbnmpntw.dll for netbios connections
+
+All these files are installed while installing MS SQL Server. If the SQL Server
+is installed on another maschine you need to install the client tools on
+the web server as well.
+
+
+ \ No newline at end of file
diff --git a/ext/mssql/php_mssql.c b/ext/mssql/php_mssql.c
new file mode 100644
index 0000000..fbeaa60
--- /dev/null
+++ b/ext/mssql/php_mssql.c
@@ -0,0 +1,2279 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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: Frank M. Kromann <frank@kromann.info> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef COMPILE_DL_MSSQL
+#define HAVE_MSSQL 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_globals.h"
+#include "ext/standard/php_standard.h"
+#include "ext/standard/info.h"
+#include "php_mssql.h"
+#include "php_ini.h"
+
+#if HAVE_MSSQL
+#define SAFE_STRING(s) ((s)?(s):"")
+
+#define MSSQL_ASSOC 1<<0
+#define MSSQL_NUM 1<<1
+#define MSSQL_BOTH (MSSQL_ASSOC|MSSQL_NUM)
+
+static int le_result, le_link, le_plink, le_statement;
+
+static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC);
+static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC);
+
+static void _mssql_bind_hash_dtor(void *data);
+
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_connect, 0, 0, 0)
+ ZEND_ARG_INFO(0, servername)
+ ZEND_ARG_INFO(0, username)
+ ZEND_ARG_INFO(0, password)
+ ZEND_ARG_INFO(0, newlink)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_close, 0, 0, 0)
+ ZEND_ARG_INFO(0, link_identifier)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_select_db, 0, 0, 1)
+ ZEND_ARG_INFO(0, database_name)
+ ZEND_ARG_INFO(0, link_identifier)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_query, 0, 0, 1)
+ ZEND_ARG_INFO(0, query)
+ ZEND_ARG_INFO(0, link_identifier)
+ ZEND_ARG_INFO(0, batch_size)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_batch, 0, 0, 1)
+ ZEND_ARG_INFO(0, result)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_rows_affected, 0, 0, 1)
+ ZEND_ARG_INFO(0, link_identifier)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_mssql_get_last_message, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_field, 0, 0, 1)
+ ZEND_ARG_INFO(0, result)
+ ZEND_ARG_INFO(0, field_offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_array, 0, 0, 1)
+ ZEND_ARG_INFO(0, result)
+ ZEND_ARG_INFO(0, result_type)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_assoc, 0, 0, 1)
+ ZEND_ARG_INFO(0, result_id)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_field_length, 0, 0, 1)
+ ZEND_ARG_INFO(0, result)
+ ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_data_seek, 0, 0, 2)
+ ZEND_ARG_INFO(0, result_identifier)
+ ZEND_ARG_INFO(0, row_number)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_result, 0, 0, 3)
+ ZEND_ARG_INFO(0, result)
+ ZEND_ARG_INFO(0, row)
+ ZEND_ARG_INFO(0, field)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_min_error_severity, 0, 0, 1)
+ ZEND_ARG_INFO(0, severity)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_init, 0, 0, 1)
+ ZEND_ARG_INFO(0, sp_name)
+ ZEND_ARG_INFO(0, link_identifier)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_bind, 0, 0, 4)
+ ZEND_ARG_INFO(0, stmt)
+ ZEND_ARG_INFO(0, param_name)
+ ZEND_ARG_INFO(1, var)
+ ZEND_ARG_INFO(0, type)
+ ZEND_ARG_INFO(0, is_output)
+ ZEND_ARG_INFO(0, is_null)
+ ZEND_ARG_INFO(0, maxlen)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_execute, 0, 0, 1)
+ ZEND_ARG_INFO(0, stmt)
+ ZEND_ARG_INFO(0, skip_results)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_free_statement, 0, 0, 1)
+ ZEND_ARG_INFO(0, stmt)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_guid_string, 0, 0, 1)
+ ZEND_ARG_INFO(0, binary)
+ ZEND_ARG_INFO(0, short_format)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ mssql_functions
+*/
+const zend_function_entry mssql_functions[] = {
+ PHP_FE(mssql_connect, arginfo_mssql_connect)
+ PHP_FE(mssql_pconnect, arginfo_mssql_connect)
+ PHP_FE(mssql_close, arginfo_mssql_close)
+ PHP_FE(mssql_select_db, arginfo_mssql_select_db)
+ PHP_FE(mssql_query, arginfo_mssql_query)
+ PHP_FE(mssql_fetch_batch, arginfo_mssql_fetch_batch)
+ PHP_FE(mssql_rows_affected, arginfo_mssql_rows_affected)
+ PHP_FE(mssql_free_result, arginfo_mssql_fetch_batch)
+ PHP_FE(mssql_get_last_message, arginfo_mssql_get_last_message)
+ PHP_FE(mssql_num_rows, arginfo_mssql_fetch_batch)
+ PHP_FE(mssql_num_fields, arginfo_mssql_fetch_batch)
+ PHP_FE(mssql_fetch_field, arginfo_mssql_fetch_field)
+ PHP_FE(mssql_fetch_row, arginfo_mssql_fetch_batch)
+ PHP_FE(mssql_fetch_array, arginfo_mssql_fetch_array)
+ PHP_FE(mssql_fetch_assoc, arginfo_mssql_fetch_assoc)
+ PHP_FE(mssql_fetch_object, arginfo_mssql_fetch_batch)
+ PHP_FE(mssql_field_length, arginfo_mssql_field_length)
+ PHP_FE(mssql_field_name, arginfo_mssql_field_length)
+ PHP_FE(mssql_field_type, arginfo_mssql_field_length)
+ PHP_FE(mssql_data_seek, arginfo_mssql_data_seek)
+ PHP_FE(mssql_field_seek, arginfo_mssql_fetch_field)
+ PHP_FE(mssql_result, arginfo_mssql_result)
+ PHP_FE(mssql_next_result, arginfo_mssql_fetch_assoc)
+ PHP_FE(mssql_min_error_severity, arginfo_mssql_min_error_severity)
+ PHP_FE(mssql_min_message_severity, arginfo_mssql_min_error_severity)
+ PHP_FE(mssql_init, arginfo_mssql_init)
+ PHP_FE(mssql_bind, arginfo_mssql_bind)
+ PHP_FE(mssql_execute, arginfo_mssql_execute)
+ PHP_FE(mssql_free_statement, arginfo_mssql_free_statement)
+ PHP_FE(mssql_guid_string, arginfo_mssql_guid_string)
+ PHP_FE_END
+};
+/* }}} */
+
+ZEND_DECLARE_MODULE_GLOBALS(mssql)
+static PHP_GINIT_FUNCTION(mssql);
+
+/* {{{ mssql_module_entry
+*/
+zend_module_entry mssql_module_entry =
+{
+ STANDARD_MODULE_HEADER,
+ "mssql",
+ mssql_functions,
+ PHP_MINIT(mssql),
+ PHP_MSHUTDOWN(mssql),
+ PHP_RINIT(mssql),
+ PHP_RSHUTDOWN(mssql),
+ PHP_MINFO(mssql),
+ NO_VERSION_YET,
+ PHP_MODULE_GLOBALS(mssql),
+ PHP_GINIT(mssql),
+ NULL,
+ NULL,
+ STANDARD_MODULE_PROPERTIES_EX
+};
+/* }}} */
+
+#ifdef COMPILE_DL_MSSQL
+ZEND_GET_MODULE(mssql)
+#endif
+
+#define CHECK_LINK(link) { if (link==-1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } }
+
+/* {{{ PHP_INI_DISP
+*/
+static PHP_INI_DISP(display_text_size)
+{
+ char *value;
+ TSRMLS_FETCH();
+
+ if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
+ value = ini_entry->orig_value;
+ } else if (ini_entry->value) {
+ value = ini_entry->value;
+ } else {
+ value = NULL;
+ }
+
+ if (atoi(value) == -1) {
+ PUTS("Server default");
+ } else {
+ php_printf("%s", value);
+ }
+}
+/* }}} */
+
+/* {{{ PHP_INI
+*/
+PHP_INI_BEGIN()
+ STD_PHP_INI_BOOLEAN("mssql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_persistent, zend_mssql_globals, mssql_globals)
+ STD_PHP_INI_ENTRY_EX("mssql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_mssql_globals, mssql_globals, display_link_numbers)
+ STD_PHP_INI_ENTRY_EX("mssql.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_mssql_globals, mssql_globals, display_link_numbers)
+ STD_PHP_INI_ENTRY_EX("mssql.min_error_severity", "10", PHP_INI_ALL, OnUpdateLong, cfg_min_error_severity, zend_mssql_globals, mssql_globals, display_link_numbers)
+ STD_PHP_INI_ENTRY_EX("mssql.min_message_severity", "10", PHP_INI_ALL, OnUpdateLong, cfg_min_message_severity, zend_mssql_globals, mssql_globals, display_link_numbers)
+ STD_PHP_INI_BOOLEAN("mssql.compatability_mode", "0", PHP_INI_ALL, OnUpdateBool, compatability_mode, zend_mssql_globals, mssql_globals)
+ STD_PHP_INI_ENTRY_EX("mssql.connect_timeout", "5", PHP_INI_ALL, OnUpdateLong, connect_timeout, zend_mssql_globals, mssql_globals, display_link_numbers)
+ STD_PHP_INI_ENTRY_EX("mssql.timeout", "60", PHP_INI_ALL, OnUpdateLong, timeout, zend_mssql_globals, mssql_globals, display_link_numbers)
+ STD_PHP_INI_ENTRY_EX("mssql.textsize", "-1", PHP_INI_ALL, OnUpdateLong, textsize, zend_mssql_globals, mssql_globals, display_text_size)
+ STD_PHP_INI_ENTRY_EX("mssql.textlimit", "-1", PHP_INI_ALL, OnUpdateLong, textlimit, zend_mssql_globals, mssql_globals, display_text_size)
+ STD_PHP_INI_ENTRY_EX("mssql.batchsize", "0", PHP_INI_ALL, OnUpdateLong, batchsize, zend_mssql_globals, mssql_globals, display_link_numbers)
+ STD_PHP_INI_BOOLEAN("mssql.datetimeconvert", "1", PHP_INI_ALL, OnUpdateBool, datetimeconvert, zend_mssql_globals, mssql_globals)
+ STD_PHP_INI_BOOLEAN("mssql.secure_connection", "0", PHP_INI_SYSTEM, OnUpdateBool, secure_connection, zend_mssql_globals, mssql_globals)
+ STD_PHP_INI_ENTRY_EX("mssql.max_procs", "-1", PHP_INI_ALL, OnUpdateLong, max_procs, zend_mssql_globals, mssql_globals, display_link_numbers)
+#ifdef HAVE_FREETDS
+ STD_PHP_INI_ENTRY("mssql.charset", "", PHP_INI_ALL, OnUpdateString, charset, zend_mssql_globals, mssql_globals)
+#endif
+PHP_INI_END()
+/* }}} */
+
+/* error handler */
+static int php_mssql_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
+{
+ TSRMLS_FETCH();
+
+ if (severity >= MS_SQL_G(min_error_severity)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (severity %d)", dberrstr, severity);
+ }
+ return INT_CANCEL;
+}
+
+/* {{{ php_mssql_message_handler
+*/
+/* message handler */
+static int php_mssql_message_handler(DBPROCESS *dbproc, DBINT msgno,int msgstate, int severity,char *msgtext,char *srvname, char *procname,DBUSMALLINT line)
+{
+ TSRMLS_FETCH();
+
+ if (severity >= MS_SQL_G(min_message_severity)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "message: %s (severity %d)", msgtext, severity);
+ }
+ if (MS_SQL_G(server_message)) {
+ STR_FREE(MS_SQL_G(server_message));
+ MS_SQL_G(server_message) = NULL;
+ }
+ MS_SQL_G(server_message) = estrdup(msgtext);
+ return 0;
+}
+/* }}} */
+
+/* {{{ _clean_invalid_results
+*/
+static int _clean_invalid_results(zend_rsrc_list_entry *le TSRMLS_DC)
+{
+ if (Z_TYPE_P(le) == le_result) {
+ mssql_link *mssql_ptr = ((mssql_result *) le->ptr)->mssql_ptr;
+
+ if (!mssql_ptr->valid) {
+ return 1;
+ }
+ }
+ return 0;
+}
+/* }}} */
+
+/* {{{ _free_result
+*/
+static void _free_result(mssql_result *result, int free_fields)
+{
+ int i,j;
+
+ if (result->data) {
+ for (i=0; i<result->num_rows; i++) {
+ if (result->data[i]) {
+ for (j=0; j<result->num_fields; j++) {
+ zval_dtor(&result->data[i][j]);
+ }
+ efree(result->data[i]);
+ }
+ }
+ efree(result->data);
+ result->data = NULL;
+ result->blocks_initialized = 0;
+ }
+
+ if (free_fields && result->fields) {
+ for (i=0; i<result->num_fields; i++) {
+ STR_FREE(result->fields[i].name);
+ STR_FREE(result->fields[i].column_source);
+ }
+ efree(result->fields);
+ }
+}
+/* }}} */
+
+/* {{{ _free_mssql_statement
+*/
+static void _free_mssql_statement(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ mssql_statement *statement = (mssql_statement *)rsrc->ptr;
+
+ if (statement->binds) {
+ zend_hash_destroy(statement->binds);
+ efree(statement->binds);
+ }
+
+ efree(statement);
+}
+/* }}} */
+
+/* {{{ _free_mssql_result
+*/
+static void _free_mssql_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ mssql_result *result = (mssql_result *)rsrc->ptr;
+
+ _free_result(result, 1);
+ dbcancel(result->mssql_ptr->link);
+ efree(result);
+}
+/* }}} */
+
+/* {{{ php_mssql_set_defaullt_link
+*/
+static void php_mssql_set_default_link(int id TSRMLS_DC)
+{
+ if (MS_SQL_G(default_link)!=-1) {
+ zend_list_delete(MS_SQL_G(default_link));
+ }
+ MS_SQL_G(default_link) = id;
+ zend_list_addref(id);
+}
+/* }}} */
+
+/* {{{ _close_mssql_link
+*/
+static void _close_mssql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ mssql_link *mssql_ptr = (mssql_link *)rsrc->ptr;
+
+ mssql_ptr->valid = 0;
+ zend_hash_apply(&EG(regular_list),(apply_func_t) _clean_invalid_results TSRMLS_CC);
+ dbclose(mssql_ptr->link);
+ dbfreelogin(mssql_ptr->login);
+ efree(mssql_ptr);
+ MS_SQL_G(num_links)--;
+}
+/* }}} */
+
+/* {{{ _close_mssql_plink
+*/
+static void _close_mssql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ mssql_link *mssql_ptr = (mssql_link *)rsrc->ptr;
+
+ dbclose(mssql_ptr->link);
+ dbfreelogin(mssql_ptr->login);
+ free(mssql_ptr);
+ MS_SQL_G(num_persistent)--;
+ MS_SQL_G(num_links)--;
+}
+/* }}} */
+
+/* {{{ _mssql_bind_hash_dtor
+*/
+static void _mssql_bind_hash_dtor(void *data)
+{
+ mssql_bind *bind= (mssql_bind *) data;
+
+ zval_ptr_dtor(&(bind->zval));
+}
+/* }}} */
+
+/* {{{ PHP_GINIT_FUNCTION
+*/
+static PHP_GINIT_FUNCTION(mssql)
+{
+ long compatability_mode;
+
+ mssql_globals->num_persistent = 0;
+ mssql_globals->get_column_content = php_mssql_get_column_content_with_type;
+ if (cfg_get_long("mssql.compatability_mode", &compatability_mode) == SUCCESS) {
+ if (compatability_mode) {
+ mssql_globals->get_column_content = php_mssql_get_column_content_without_type;
+ }
+ }
+}
+/* }}} */
+
+/* {{{ PHP_MINIT_FUNCTION
+*/
+PHP_MINIT_FUNCTION(mssql)
+{
+ REGISTER_INI_ENTRIES();
+
+ le_statement = zend_register_list_destructors_ex(_free_mssql_statement, NULL, "mssql statement", module_number);
+ le_result = zend_register_list_destructors_ex(_free_mssql_result, NULL, "mssql result", module_number);
+ le_link = zend_register_list_destructors_ex(_close_mssql_link, NULL, "mssql link", module_number);
+ le_plink = zend_register_list_destructors_ex(NULL, _close_mssql_plink, "mssql link persistent", module_number);
+ Z_TYPE(mssql_module_entry) = type;
+
+ if (dbinit()==FAIL) {
+ return FAILURE;
+ }
+
+ /* BEGIN MSSQL data types for mssql_bind */
+ REGISTER_LONG_CONSTANT("MSSQL_ASSOC", MSSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("MSSQL_NUM", MSSQL_NUM, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("MSSQL_BOTH", MSSQL_BOTH, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("SQLTEXT",SQLTEXT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLVARCHAR",SQLVARCHAR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLCHAR",SQLCHAR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLINT1",SQLINT1, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLINT2",SQLINT2, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLINT4",SQLINT4, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLBIT",SQLBIT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLFLT4",SQLFLT4, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLFLT8",SQLFLT8, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLFLTN",SQLFLTN, CONST_CS | CONST_PERSISTENT);
+ /* END MSSQL data types for mssql_bind */
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+*/
+PHP_MSHUTDOWN_FUNCTION(mssql)
+{
+ UNREGISTER_INI_ENTRIES();
+#ifndef HAVE_FREETDS
+ dbwinexit();
+#else
+ dbexit();
+#endif
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_RINIT_FUNCTION
+*/
+PHP_RINIT_FUNCTION(mssql)
+{
+ MS_SQL_G(default_link) = -1;
+ MS_SQL_G(num_links) = MS_SQL_G(num_persistent);
+ MS_SQL_G(appname) = estrndup("PHP 5", 5);
+ MS_SQL_G(server_message) = NULL;
+ MS_SQL_G(min_error_severity) = MS_SQL_G(cfg_min_error_severity);
+ MS_SQL_G(min_message_severity) = MS_SQL_G(cfg_min_message_severity);
+ if (MS_SQL_G(connect_timeout) < 1) MS_SQL_G(connect_timeout) = 1;
+ if (MS_SQL_G(timeout) < 0) MS_SQL_G(timeout) = 60;
+ if (MS_SQL_G(max_procs) != -1) {
+ dbsetmaxprocs((TDS_SHORT)MS_SQL_G(max_procs));
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_RSHUTDOWN_FUNCTION
+*/
+PHP_RSHUTDOWN_FUNCTION(mssql)
+{
+ STR_FREE(MS_SQL_G(appname));
+ MS_SQL_G(appname) = NULL;
+ if (MS_SQL_G(server_message)) {
+ STR_FREE(MS_SQL_G(server_message));
+ MS_SQL_G(server_message) = NULL;
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+*/
+PHP_MINFO_FUNCTION(mssql)
+{
+ char buf[32];
+
+ php_info_print_table_start();
+ php_info_print_table_header(2, "MSSQL Support", "enabled");
+
+ snprintf(buf, sizeof(buf), "%ld", MS_SQL_G(num_persistent));
+ php_info_print_table_row(2, "Active Persistent Links", buf);
+ snprintf(buf, sizeof(buf), "%ld", MS_SQL_G(num_links));
+ php_info_print_table_row(2, "Active Links", buf);
+
+ php_info_print_table_row(2, "Library version", MSSQL_VERSION);
+ php_info_print_table_end();
+
+ DISPLAY_INI_ENTRIES();
+
+}
+/* }}} */
+
+/* {{{ php_mssql_do_connect
+*/
+static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
+{
+ char *host = NULL, *user = NULL, *passwd = NULL;
+ int host_len = 0, user_len = 0, passwd_len = 0;
+ zend_bool new_link = 0;
+ char *hashed_details;
+ int hashed_details_length;
+ mssql_link mssql, *mssql_ptr;
+ char buffer[40];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sssb", &host, &host_len, &user, &user_len, &passwd, &passwd_len, &new_link) == FAILURE) {
+ return;
+ }
+
+ /* Limit strings to 255 chars to prevent overflow issues in underlying libraries */
+ if(host_len>255) {
+ host[255] = '\0';
+ }
+ if(user_len>255) {
+ user[255] = '\0';
+ }
+ if(passwd_len>255) {
+ passwd[255] = '\0';
+ }
+
+ switch(ZEND_NUM_ARGS())
+ {
+ case 0:
+ /* defaults */
+ hashed_details_length=5+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ strcpy(hashed_details, "mssql___");
+ break;
+ case 1:
+ hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s__", host);
+ break;
+ case 2:
+ hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s_%s_", host, user);
+ break;
+ case 3:
+ case 4:
+ hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s_%s_%s", host, user, passwd);
+ break;
+ }
+
+ if (hashed_details == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Out of memory");
+ RETURN_FALSE;
+ }
+
+ dbsetlogintime(MS_SQL_G(connect_timeout));
+ dbsettime(MS_SQL_G(timeout));
+
+ /* set a DBLOGIN record */
+ if ((mssql.login = dblogin()) == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate login record");
+ RETURN_FALSE;
+ }
+
+ DBERRHANDLE(mssql.login, (EHANDLEFUNC) php_mssql_error_handler);
+ DBMSGHANDLE(mssql.login, (MHANDLEFUNC) php_mssql_message_handler);
+
+#ifndef HAVE_FREETDS
+ if (MS_SQL_G(secure_connection)){
+ DBSETLSECURE(mssql.login);
+ }
+ else {
+#endif
+ if (user) {
+ DBSETLUSER(mssql.login,user);
+ }
+ if (passwd) {
+ DBSETLPWD(mssql.login,passwd);
+ }
+#ifndef HAVE_FREETDS
+ }
+#endif
+
+#ifdef HAVE_FREETDS
+ if (MS_SQL_G(charset) && strlen(MS_SQL_G(charset))) {
+ DBSETLCHARSET(mssql.login, MS_SQL_G(charset));
+ }
+#endif
+
+ DBSETLAPP(mssql.login,MS_SQL_G(appname));
+ mssql.valid = 1;
+
+#ifndef HAVE_FREETDS
+ DBSETLVERSION(mssql.login, DBVER60);
+#endif
+/* DBSETLTIME(mssql.login, TIMEOUT_INFINITE); */
+
+ if (!MS_SQL_G(allow_persistent)) {
+ persistent=0;
+ }
+ if (persistent) {
+ zend_rsrc_list_entry *le;
+
+ /* try to find if we already have this link in our persistent list */
+ if (new_link || zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length + 1, (void **) &le)==FAILURE) { /* we don't */
+ zend_rsrc_list_entry new_le;
+
+ if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links));
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ RETURN_FALSE;
+ }
+ if (MS_SQL_G(max_persistent) != -1 && MS_SQL_G(num_persistent) >= MS_SQL_G(max_persistent)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)", MS_SQL_G(num_persistent));
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ RETURN_FALSE;
+ }
+ /* create the link */
+ if ((mssql.link = dbopen(mssql.login, host)) == FAIL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", (host == NULL ? "" : host));
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ RETURN_FALSE;
+ }
+
+ if (DBSETOPT(mssql.link, DBBUFFER, "2")==FAIL) {
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ dbclose(mssql.link);
+ RETURN_FALSE;
+ }
+
+#ifndef HAVE_FREETDS
+ if (MS_SQL_G(textlimit) != -1) {
+ snprintf(buffer, sizeof(buffer), "%li", MS_SQL_G(textlimit));
+ if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) {
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ dbclose(mssql.link);
+ RETURN_FALSE;
+ }
+ }
+#endif
+ if (MS_SQL_G(textsize) != -1) {
+ snprintf(buffer, sizeof(buffer), "SET TEXTSIZE %li", MS_SQL_G(textsize));
+ dbcmd(mssql.link, buffer);
+ dbsqlexec(mssql.link);
+ dbresults(mssql.link);
+ }
+
+ /* hash it up */
+ mssql_ptr = (mssql_link *) malloc(sizeof(mssql_link));
+ if (!mssql_ptr) {
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ dbclose(mssql.link);
+ RETURN_FALSE;
+ }
+
+ memcpy(mssql_ptr, &mssql, sizeof(mssql_link));
+ Z_TYPE(new_le) = le_plink;
+ new_le.ptr = mssql_ptr;
+ if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length + 1, &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
+ free(mssql_ptr);
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ dbclose(mssql.link);
+ RETURN_FALSE;
+ }
+ MS_SQL_G(num_persistent)++;
+ MS_SQL_G(num_links)++;
+ } else { /* we do */
+ if (Z_TYPE_P(le) != le_plink) {
+#if BROKEN_MSSQL_PCONNECTS
+ log_error("PHP/MS SQL: Hashed persistent link is not a MS SQL link!",php_rqst->server);
+#endif
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Hashed persistent link is not a MS SQL link!");
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ mssql_ptr = (mssql_link *) le->ptr;
+ /* test that the link hasn't died */
+ if (DBDEAD(mssql_ptr->link) == TRUE) {
+ dbclose(mssql_ptr->link);
+#if BROKEN_MSSQL_PCONNECTS
+ log_error("PHP/MS SQL: Persistent link died, trying to reconnect...",php_rqst->server);
+#endif
+ if ((mssql_ptr->link=dbopen(mssql_ptr->login,host))==NULL) {
+#if BROKEN_MSSQL_PCONNECTS
+ log_error("PHP/MS SQL: Unable to reconnect!",php_rqst->server);
+#endif
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
+ zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1);
+ efree(hashed_details);
+ dbfreelogin(mssql_ptr->login);
+ RETURN_FALSE;
+ }
+#if BROKEN_MSSQL_PCONNECTS
+ log_error("PHP/MS SQL: Reconnect successful!",php_rqst->server);
+#endif
+ if (DBSETOPT(mssql_ptr->link, DBBUFFER, "2")==FAIL) {
+#if BROKEN_MSSQL_PCONNECTS
+ log_error("PHP/MS SQL: Unable to set required options",php_rqst->server);
+#endif
+ zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length + 1);
+ efree(hashed_details);
+ dbfreelogin(mssql_ptr->login);
+ dbclose(mssql_ptr->link);
+ RETURN_FALSE;
+ }
+ }
+ }
+ ZEND_REGISTER_RESOURCE(return_value, mssql_ptr, le_plink);
+ } else { /* non persistent */
+ zend_rsrc_list_entry *index_ptr, new_index_ptr;
+
+ /* first we check the hash for the hashed_details key. if it exists,
+ * it should point us to the right offset where the actual mssql link sits.
+ * if it doesn't, open a new mssql link, add it to the resource list,
+ * and add a pointer to it with hashed_details as the key.
+ */
+ if (!new_link && zend_hash_find(&EG(regular_list), hashed_details, hashed_details_length + 1,(void **) &index_ptr)==SUCCESS) {
+ int type,link;
+ void *ptr;
+
+ if (Z_TYPE_P(index_ptr) != le_index_ptr) {
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ RETURN_FALSE;
+ }
+ link = (int) index_ptr->ptr;
+ ptr = zend_list_find(link,&type); /* check if the link is still there */
+ if (ptr && (type==le_link || type==le_plink)) {
+ zend_list_addref(link);
+ Z_LVAL_P(return_value) = link;
+ php_mssql_set_default_link(link TSRMLS_CC);
+ Z_TYPE_P(return_value) = IS_RESOURCE;
+ dbfreelogin(mssql.login);
+ efree(hashed_details);
+ return;
+ } else {
+ zend_hash_del(&EG(regular_list), hashed_details, hashed_details_length + 1);
+ }
+ }
+ if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links));
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ RETURN_FALSE;
+ }
+
+ if ((mssql.link=dbopen(mssql.login, host))==NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", (host == NULL ? "" : host));
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ RETURN_FALSE;
+ }
+
+ if (DBSETOPT(mssql.link, DBBUFFER,"2")==FAIL) {
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ dbclose(mssql.link);
+ RETURN_FALSE;
+ }
+
+#ifndef HAVE_FREETDS
+ if (MS_SQL_G(textlimit) != -1) {
+ snprintf(buffer, sizeof(buffer), "%li", MS_SQL_G(textlimit));
+ if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) {
+ efree(hashed_details);
+ dbfreelogin(mssql.login);
+ dbclose(mssql.link);
+ RETURN_FALSE;
+ }
+ }
+#endif
+ if (MS_SQL_G(textsize) != -1) {
+ snprintf(buffer, sizeof(buffer), "SET TEXTSIZE %li", MS_SQL_G(textsize));
+ dbcmd(mssql.link, buffer);
+ dbsqlexec(mssql.link);
+ dbresults(mssql.link);
+ }
+
+ /* add it to the list */
+ mssql_ptr = (mssql_link *) emalloc(sizeof(mssql_link));
+ memcpy(mssql_ptr, &mssql, sizeof(mssql_link));
+ ZEND_REGISTER_RESOURCE(return_value, mssql_ptr, le_link);
+
+ /* add it to the hash */
+ new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
+ Z_TYPE(new_index_ptr) = le_index_ptr;
+ if (zend_hash_update(&EG(regular_list), hashed_details, hashed_details_length + 1,(void *) &new_index_ptr, sizeof(zend_rsrc_list_entry),NULL)==FAILURE) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ MS_SQL_G(num_links)++;
+ }
+ efree(hashed_details);
+ php_mssql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ php_mssql_get_default_link
+*/
+static int php_mssql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
+{
+ if (MS_SQL_G(default_link)==-1) { /* no link opened yet, implicitly open one */
+ ht = 0;
+ php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
+ }
+ return MS_SQL_G(default_link);
+}
+/* }}} */
+
+/* {{{ proto int mssql_connect([string servername [, string username [, string password [, bool new_link]]]])
+ Establishes a connection to a MS-SQL server */
+PHP_FUNCTION(mssql_connect)
+{
+ php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
+}
+/* }}} */
+
+/* {{{ proto int mssql_pconnect([string servername [, string username [, string password [, bool new_link]]]])
+ Establishes a persistent connection to a MS-SQL server */
+PHP_FUNCTION(mssql_pconnect)
+{
+ php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
+}
+/* }}} */
+
+/* {{{ proto bool mssql_close([resource conn_id])
+ Closes a connection to a MS-SQL server */
+PHP_FUNCTION(mssql_close)
+{
+ zval *mssql_link_index = NULL;
+ int id = -1;
+ mssql_link *mssql_ptr;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mssql_link_index) == FAILURE) {
+ return;
+ }
+
+ if (mssql_link_index == NULL) {
+ id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ CHECK_LINK(id);
+ }
+
+ ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
+
+ if (mssql_link_index) {
+ zend_list_delete(Z_RESVAL_P(mssql_link_index));
+ } else {
+ zend_list_delete(id);
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool mssql_select_db(string database_name [, resource conn_id])
+ Select a MS-SQL database */
+PHP_FUNCTION(mssql_select_db)
+{
+ char *db;
+ zval *mssql_link_index = NULL;
+ int db_len;
+ int id = -1;
+ mssql_link *mssql_ptr;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &db, &db_len, &mssql_link_index) == FAILURE) {
+ return;
+ }
+
+ if (mssql_link_index == NULL) {
+ id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ CHECK_LINK(id);
+ }
+
+ ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
+
+ if (dbuse(mssql_ptr->link, db)==FAIL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to select database: %s", db);
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* {{{ php_mssql_get_column_content_with_type
+*/
+static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC)
+{
+ if (dbdata(mssql_ptr->link,offset) == NULL && dbdatlen(mssql_ptr->link,offset) == 0) {
+ ZVAL_NULL(result);
+ return;
+ }
+
+ switch (column_type)
+ {
+ case SQLBIT:
+ case SQLINT1:
+ case SQLINT2:
+ case SQLINT4:
+ case SQLINTN: {
+ ZVAL_LONG(result, (long) anyintcol(offset));
+ break;
+ }
+ case SQLCHAR:
+ case SQLVARCHAR:
+ case SQLTEXT: {
+ int length;
+ char *data = charcol(offset);
+
+ length=dbdatlen(mssql_ptr->link,offset);
+#if ilia_0
+ while (length>0 && data[length-1] == ' ') { /* nuke trailing whitespace */
+ length--;
+ }
+#endif
+ ZVAL_STRINGL(result, data, length, 1);
+ break;
+ }
+ case SQLFLT4:
+ ZVAL_DOUBLE(result, (double) floatcol4(offset));
+ break;
+ case SQLMONEY:
+ case SQLMONEY4:
+ case SQLMONEYN: {
+ DBFLT8 res_buf;
+ dbconvert(NULL, column_type, dbdata(mssql_ptr->link,offset), 8, SQLFLT8, (LPBYTE)&res_buf, -1);
+ ZVAL_DOUBLE(result, res_buf);
+ }
+ break;
+ case SQLFLT8:
+ ZVAL_DOUBLE(result, (double) floatcol8(offset));
+ break;
+#ifdef SQLUNIQUE
+ case SQLUNIQUE: {
+#else
+ case 36: { /* FreeTDS hack */
+#endif
+ char *data = charcol(offset);
+
+ /* uniqueidentifier is a 16-byte binary number */
+ ZVAL_STRINGL(result, data, 16, 1);
+ }
+ break;
+ case SQLVARBINARY:
+ case SQLBINARY:
+ case SQLIMAGE: {
+ int res_length = dbdatlen(mssql_ptr->link, offset);
+
+ if (!res_length) {
+ ZVAL_NULL(result);
+ } else {
+ ZVAL_STRINGL(result, (char *)dbdata(mssql_ptr->link, offset), res_length, 1);
+ }
+ }
+ break;
+ case SQLNUMERIC:
+ default: {
+ if (dbwillconvert(column_type,SQLCHAR)) {
+ char *res_buf;
+ DBDATEREC dateinfo;
+ int res_length = dbdatlen(mssql_ptr->link,offset);
+
+ if (res_length == -1) {
+ res_length = 255;
+ }
+
+ if ((column_type != SQLDATETIME && column_type != SQLDATETIM4) || MS_SQL_G(datetimeconvert)) {
+
+ switch (column_type) {
+ case SQLDATETIME :
+ case SQLDATETIM4 :
+ res_length += 20;
+ break;
+ case SQLMONEY :
+ case SQLMONEY4 :
+ case SQLMONEYN :
+ case SQLDECIMAL :
+ case SQLNUMERIC :
+ res_length += 5;
+ case 127 :
+ res_length += 20;
+ break;
+ }
+
+ res_buf = (unsigned char *) emalloc(res_length+1);
+ res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR,res_buf,-1);
+ res_buf[res_length] = '\0';
+ } else {
+ if (column_type == SQLDATETIM4) {
+ DBDATETIME temp;
+
+ dbconvert(NULL, SQLDATETIM4, dbdata(mssql_ptr->link,offset), -1, SQLDATETIME, (LPBYTE) &temp, -1);
+ dbdatecrack(mssql_ptr->link, &dateinfo, &temp);
+ } else {
+ dbdatecrack(mssql_ptr->link, &dateinfo, (DBDATETIME *) dbdata(mssql_ptr->link,offset));
+ }
+
+ res_length = 19;
+ spprintf(&res_buf, 0, "%d-%02d-%02d %02d:%02d:%02d" , dateinfo.year, dateinfo.month, dateinfo.day, dateinfo.hour, dateinfo.minute, dateinfo.second);
+ }
+
+ ZVAL_STRINGL(result, res_buf, res_length, 0);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d has unknown data type (%d)", offset, coltype(offset));
+ ZVAL_FALSE(result);
+ }
+ }
+ }
+}
+/* }}} */
+
+/* {{{ php_mssql_get_column_content_without_type
+*/
+static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC)
+{
+ if (dbdatlen(mssql_ptr->link,offset) == 0) {
+ ZVAL_NULL(result);
+ return;
+ }
+
+ if (column_type == SQLVARBINARY ||
+ column_type == SQLBINARY ||
+ column_type == SQLIMAGE) {
+ DBBINARY *bin;
+ unsigned char *res_buf;
+ int res_length = dbdatlen(mssql_ptr->link, offset);
+
+ if (res_length == 0) {
+ ZVAL_NULL(result);
+ return;
+ } else if (res_length < 0) {
+ ZVAL_FALSE(result);
+ return;
+ }
+
+ res_buf = (unsigned char *) emalloc(res_length+1);
+ bin = ((DBBINARY *)dbdata(mssql_ptr->link, offset));
+ res_buf[res_length] = '\0';
+ memcpy(res_buf, bin, res_length);
+ ZVAL_STRINGL(result, res_buf, res_length, 0);
+ }
+ else if (dbwillconvert(coltype(offset),SQLCHAR)) {
+ unsigned char *res_buf;
+ DBDATEREC dateinfo;
+ int res_length = dbdatlen(mssql_ptr->link,offset);
+
+ if ((column_type != SQLDATETIME && column_type != SQLDATETIM4) || MS_SQL_G(datetimeconvert)) {
+
+ switch (column_type) {
+ case SQLDATETIME :
+ case SQLDATETIM4 :
+ res_length += 20;
+ break;
+ case SQLMONEY :
+ case SQLMONEY4 :
+ case SQLMONEYN :
+ case SQLDECIMAL :
+ case SQLNUMERIC :
+ res_length += 5;
+ case 127 :
+ res_length += 20;
+ break;
+ }
+
+ res_buf = (unsigned char *) emalloc(res_length+1);
+ res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR, res_buf, -1);
+ res_buf[res_length] = '\0';
+ } else {
+ if (column_type == SQLDATETIM4) {
+ DBDATETIME temp;
+
+ dbconvert(NULL, SQLDATETIM4, dbdata(mssql_ptr->link,offset), -1, SQLDATETIME, (LPBYTE) &temp, -1);
+ dbdatecrack(mssql_ptr->link, &dateinfo, &temp);
+ } else {
+ dbdatecrack(mssql_ptr->link, &dateinfo, (DBDATETIME *) dbdata(mssql_ptr->link,offset));
+ }
+
+ res_length = 19;
+ spprintf(&res_buf, 0, "%d-%02d-%02d %02d:%02d:%02d" , dateinfo.year, dateinfo.month, dateinfo.day, dateinfo.hour, dateinfo.minute, dateinfo.second);
+ }
+
+ ZVAL_STRINGL(result, res_buf, res_length, 0);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d has unknown data type (%d)", offset, coltype(offset));
+ ZVAL_FALSE(result);
+ }
+}
+/* }}} */
+
+/* {{{ _mssql_get_sp_result
+*/
+static void _mssql_get_sp_result(mssql_link *mssql_ptr, mssql_statement *statement TSRMLS_DC)
+{
+ int i, num_rets, type;
+ char *parameter;
+ mssql_bind *bind;
+
+ /* Now to fetch RETVAL and OUTPUT values*/
+ num_rets = dbnumrets(mssql_ptr->link);
+
+ if (num_rets!=0) {
+ for (i = 1; i <= num_rets; i++) {
+ parameter = (char*)dbretname(mssql_ptr->link, i);
+ type = dbrettype(mssql_ptr->link, i);
+
+ if (statement->binds != NULL) { /* Maybe a non-parameter sp */
+ if (zend_hash_find(statement->binds, parameter, strlen(parameter), (void**)&bind)==SUCCESS) {
+ if (!dbretlen(mssql_ptr->link,i)) {
+ ZVAL_NULL(bind->zval);
+ }
+ else {
+ switch (type) {
+ case SQLBIT:
+ case SQLINT1:
+ case SQLINT2:
+ case SQLINT4:
+ convert_to_long_ex(&bind->zval);
+ /* FIXME this works only on little endian machine !!! */
+ Z_LVAL_P(bind->zval) = *((int *)(dbretdata(mssql_ptr->link,i)));
+ break;
+
+ case SQLFLT4:
+ case SQLFLT8:
+ case SQLFLTN:
+ case SQLMONEY4:
+ case SQLMONEY:
+ case SQLMONEYN:
+ convert_to_double_ex(&bind->zval);
+ Z_DVAL_P(bind->zval) = *((double *)(dbretdata(mssql_ptr->link,i)));
+ break;
+
+ case SQLCHAR:
+ case SQLVARCHAR:
+ case SQLTEXT:
+ convert_to_string_ex(&bind->zval);
+ Z_STRLEN_P(bind->zval) = dbretlen(mssql_ptr->link,i);
+ Z_STRVAL_P(bind->zval) = estrndup(dbretdata(mssql_ptr->link,i),Z_STRLEN_P(bind->zval));
+ break;
+ /* TODO binary */
+ }
+ }
+ }
+ else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "An output parameter variable was not provided");
+ }
+ }
+ }
+ }
+ if (statement->binds != NULL) { /* Maybe a non-parameter sp */
+ if (zend_hash_find(statement->binds, "RETVAL", 6, (void**)&bind)==SUCCESS) {
+ if (dbhasretstat(mssql_ptr->link)) {
+ convert_to_long_ex(&bind->zval);
+ Z_LVAL_P(bind->zval)=dbretstatus(mssql_ptr->link);
+ }
+ else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "stored procedure has no return value. Nothing was returned into RETVAL");
+ }
+ }
+ }
+}
+/* }}} */
+
+/* {{{ _mssql_fetch_batch
+*/
+static int _mssql_fetch_batch(mssql_link *mssql_ptr, mssql_result *result, int retvalue TSRMLS_DC)
+{
+ int i, j = 0;
+ char computed_buf[16];
+
+ if (!result->have_fields) {
+ for (i=0; i<result->num_fields; i++) {
+ char *source = NULL;
+ char *fname = (char *)dbcolname(mssql_ptr->link,i+1);
+
+ if (*fname) {
+ result->fields[i].name = estrdup(fname);
+ } else {
+ if (j>0) {
+ snprintf(computed_buf,16,"computed%d",j);
+ } else {
+ strcpy(computed_buf,"computed");
+ }
+ result->fields[i].name = estrdup(computed_buf);
+ j++;
+ }
+ result->fields[i].max_length = dbcollen(mssql_ptr->link,i+1);
+ source = (char *)dbcolsource(mssql_ptr->link,i+1);
+ if (source) {
+ result->fields[i].column_source = estrdup(source);
+ }
+ else {
+ result->fields[i].column_source = STR_EMPTY_ALLOC();
+ }
+
+ result->fields[i].type = coltype(i+1);
+ /* set numeric flag */
+ switch (result->fields[i].type) {
+ case SQLINT1:
+ case SQLINT2:
+ case SQLINT4:
+ case SQLINTN:
+ case SQLFLT4:
+ case SQLFLT8:
+ case SQLNUMERIC:
+ case SQLDECIMAL:
+ result->fields[i].numeric = 1;
+ break;
+ case SQLCHAR:
+ case SQLVARCHAR:
+ case SQLTEXT:
+ default:
+ result->fields[i].numeric = 0;
+ break;
+ }
+ }
+ result->have_fields = 1;
+ }
+
+ i=0;
+ if (!result->data) {
+ result->data = (zval **) safe_emalloc(sizeof(zval *), MSSQL_ROWS_BLOCK*(++result->blocks_initialized), 0);
+ }
+ while (retvalue!=FAIL && retvalue!=NO_MORE_ROWS) {
+ result->num_rows++;
+ if (result->num_rows > result->blocks_initialized*MSSQL_ROWS_BLOCK) {
+ result->data = (zval **) erealloc(result->data,sizeof(zval *)*MSSQL_ROWS_BLOCK*(++result->blocks_initialized));
+ }
+ result->data[i] = (zval *) safe_emalloc(sizeof(zval), result->num_fields, 0);
+ for (j=0; j<result->num_fields; j++) {
+ INIT_ZVAL(result->data[i][j]);
+ MS_SQL_G(get_column_content(mssql_ptr, j+1, &result->data[i][j], result->fields[j].type TSRMLS_CC));
+ }
+ if (i<result->batchsize || result->batchsize==0) {
+ i++;
+ dbclrbuf(mssql_ptr->link,DBLASTROW(mssql_ptr->link));
+ retvalue=dbnextrow(mssql_ptr->link);
+ }
+ else
+ break;
+ result->lastresult = retvalue;
+ }
+ if (result->statement && (retvalue == NO_MORE_RESULTS || retvalue == NO_MORE_RPC_RESULTS)) {
+ _mssql_get_sp_result(mssql_ptr, result->statement TSRMLS_CC);
+ }
+ return i;
+}
+/* }}} */
+
+/* {{{ proto int mssql_fetch_batch(resource result_index)
+ Returns the next batch of records */
+PHP_FUNCTION(mssql_fetch_batch)
+{
+ zval *mssql_result_index;
+ mssql_result *result;
+ mssql_link *mssql_ptr;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
+ return;
+ }
+
+ if (Z_RESVAL_P(mssql_result_index) == 0) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ mssql_ptr = result->mssql_ptr;
+ _free_result(result, 0);
+ result->cur_row=result->num_rows=0;
+ result->num_rows = _mssql_fetch_batch(mssql_ptr, result, result->lastresult TSRMLS_CC);
+
+ RETURN_LONG(result->num_rows);
+}
+/* }}} */
+
+/* {{{ proto resource mssql_query(string query [, resource conn_id [, int batch_size]])
+ Perform an SQL query on a MS-SQL server database */
+PHP_FUNCTION(mssql_query)
+{
+ char *query;
+ zval *mssql_link_index = NULL;
+ int query_len, retvalue, batchsize, num_fields;
+ long zbatchsize = 0;
+ mssql_link *mssql_ptr;
+ mssql_result *result;
+ int id = -1;
+
+ dbsettime(MS_SQL_G(timeout));
+ batchsize = MS_SQL_G(batchsize);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|rl", &query, &query_len, &mssql_link_index, &zbatchsize) == FAILURE) {
+ return;
+ }
+
+ switch(ZEND_NUM_ARGS()) {
+ case 1:
+ id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ CHECK_LINK(id);
+ break;
+ case 3:
+ batchsize = (int) zbatchsize;
+ break;
+ }
+
+ ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
+
+ if (dbcmd(mssql_ptr->link, query)==FAIL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set query");
+ RETURN_FALSE;
+ }
+ if (dbsqlexec(mssql_ptr->link)==FAIL || (retvalue = dbresults(mssql_ptr->link))==FAIL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed");
+ dbcancel(mssql_ptr->link);
+ RETURN_FALSE;
+ }
+
+ /* Skip results not returning any columns */
+ while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retvalue == SUCCEED) {
+ retvalue = dbresults(mssql_ptr->link);
+ }
+
+ if (num_fields <= 0) {
+ RETURN_TRUE;
+ }
+
+ retvalue=dbnextrow(mssql_ptr->link);
+ if (retvalue==FAIL) {
+ dbcancel(mssql_ptr->link);
+ RETURN_FALSE;
+ }
+
+ result = (mssql_result *) emalloc(sizeof(mssql_result));
+ result->statement = NULL;
+ result->num_fields = num_fields;
+ result->blocks_initialized = 1;
+
+ result->batchsize = batchsize;
+ result->data = NULL;
+ result->blocks_initialized = 0;
+ result->mssql_ptr = mssql_ptr;
+ result->cur_field=result->cur_row=result->num_rows=0;
+ result->have_fields = 0;
+
+ result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), result->num_fields, 0);
+ result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
+
+ ZEND_REGISTER_RESOURCE(return_value, result, le_result);
+}
+/* }}} */
+
+/* {{{ proto int mssql_rows_affected(resource conn_id)
+ Returns the number of records affected by the query */
+PHP_FUNCTION(mssql_rows_affected)
+{
+ zval *mssql_link_index;
+ mssql_link *mssql_ptr;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_link_index) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, -1, "MS SQL-Link", le_link, le_plink);
+
+ RETURN_LONG(DBCOUNT(mssql_ptr->link));
+}
+/* }}} */
+
+/* {{{ proto bool mssql_free_result(resource result_index)
+ Free a MS-SQL result index */
+PHP_FUNCTION(mssql_free_result)
+{
+ zval *mssql_result_index;
+ mssql_result *result;
+ int retvalue;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
+ return;
+ }
+
+ if (Z_RESVAL_P(mssql_result_index) == 0) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+ /* Release remaining results */
+ do {
+ dbcanquery(result->mssql_ptr->link);
+ retvalue = dbresults(result->mssql_ptr->link);
+ } while (retvalue == SUCCEED);
+
+ zend_list_delete(Z_RESVAL_P(mssql_result_index));
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string mssql_get_last_message(void)
+ Gets the last message from the MS-SQL server */
+PHP_FUNCTION(mssql_get_last_message)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ if (MS_SQL_G(server_message)) {
+ RETURN_STRING(MS_SQL_G(server_message),1);
+ } else {
+ RETURN_STRING("",1);
+ }
+}
+/* }}} */
+
+/* {{{ proto int mssql_num_rows(resource mssql_result_index)
+ Returns the number of rows fetched in from the result id specified */
+PHP_FUNCTION(mssql_num_rows)
+{
+ zval *mssql_result_index;
+ mssql_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ RETURN_LONG(result->num_rows);
+}
+/* }}} */
+
+/* {{{ proto int mssql_num_fields(resource mssql_result_index)
+ Returns the number of fields fetched in from the result id specified */
+PHP_FUNCTION(mssql_num_fields)
+{
+ zval *mssql_result_index;
+ mssql_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ RETURN_LONG(result->num_fields);
+}
+/* }}} */
+
+/* {{{ php_mssql_fetch_hash
+*/
+static void php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
+{
+ zval *mssql_result_index;
+ mssql_result *result;
+ int i;
+ long resulttype = 0;
+
+ switch (result_type) {
+ case MSSQL_NUM:
+ case MSSQL_ASSOC:
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
+ return;
+ }
+ break;
+ case MSSQL_BOTH:
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &resulttype) == FAILURE) {
+ return;
+ }
+ result_type = (resulttype > 0 && (resulttype & MSSQL_BOTH)) ? resulttype : result_type;
+ break;
+ default:
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ if (MS_SQL_G(server_message)) {
+ STR_FREE(MS_SQL_G(server_message));
+ MS_SQL_G(server_message) = NULL;
+ }
+
+ if (result->cur_row >= result->num_rows) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+
+ for (i=0; i<result->num_fields; i++) {
+ if (Z_TYPE(result->data[result->cur_row][i]) != IS_NULL) {
+ char *data;
+ int data_len;
+
+ if (Z_TYPE(result->data[result->cur_row][i]) == IS_STRING) {
+ data = Z_STRVAL(result->data[result->cur_row][i]);
+ data_len = Z_STRLEN(result->data[result->cur_row][i]);
+
+ if (result_type & MSSQL_NUM) {
+ add_index_stringl(return_value, i, data, data_len, 1);
+ }
+
+ if (result_type & MSSQL_ASSOC) {
+ add_assoc_stringl(return_value, result->fields[i].name, data, data_len, 1);
+ }
+ }
+ else if (Z_TYPE(result->data[result->cur_row][i]) == IS_LONG) {
+ if (result_type & MSSQL_NUM)
+ add_index_long(return_value, i, Z_LVAL(result->data[result->cur_row][i]));
+
+ if (result_type & MSSQL_ASSOC)
+ add_assoc_long(return_value, result->fields[i].name, Z_LVAL(result->data[result->cur_row][i]));
+ }
+ else if (Z_TYPE(result->data[result->cur_row][i]) == IS_DOUBLE) {
+ if (result_type & MSSQL_NUM)
+ add_index_double(return_value, i, Z_DVAL(result->data[result->cur_row][i]));
+
+ if (result_type & MSSQL_ASSOC)
+ add_assoc_double(return_value, result->fields[i].name, Z_DVAL(result->data[result->cur_row][i]));
+ }
+ }
+ else
+ {
+ if (result_type & MSSQL_NUM)
+ add_index_null(return_value, i);
+ if (result_type & MSSQL_ASSOC)
+ add_assoc_null(return_value, result->fields[i].name);
+ }
+ }
+ result->cur_row++;
+}
+/* }}} */
+
+/* {{{ proto array mssql_fetch_row(resource result_id)
+ Returns an array of the current row in the result set specified by result_id */
+PHP_FUNCTION(mssql_fetch_row)
+{
+ php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_NUM);
+}
+/* }}} */
+
+/* {{{ proto object mssql_fetch_object(resource result_id)
+ Returns a pseudo-object of the current row in the result set specified by result_id */
+PHP_FUNCTION(mssql_fetch_object)
+{
+ php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_ASSOC);
+ if (Z_TYPE_P(return_value)==IS_ARRAY) {
+ object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
+ }
+}
+/* }}} */
+
+/* {{{ proto array mssql_fetch_array(resource result_id [, int result_type])
+ Returns an associative array of the current row in the result set specified by result_id */
+PHP_FUNCTION(mssql_fetch_array)
+{
+ php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_BOTH);
+}
+/* }}} */
+
+/* {{{ proto array mssql_fetch_assoc(resource result_id)
+ Returns an associative array of the current row in the result set specified by result_id */
+PHP_FUNCTION(mssql_fetch_assoc)
+{
+ php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_ASSOC);
+}
+/* }}} */
+
+/* {{{ proto bool mssql_data_seek(resource result_id, int offset)
+ Moves the internal row pointer of the MS-SQL result associated with the specified result identifier to pointer to the specified row number */
+PHP_FUNCTION(mssql_data_seek)
+{
+ zval *mssql_result_index;
+ long offset;
+ mssql_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &mssql_result_index, &offset) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ if (offset < 0 || offset >= result->num_rows) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad row offset");
+ RETURN_FALSE;
+ }
+
+ result->cur_row = offset;
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ php_mssql_get_field_name
+*/
+static char *php_mssql_get_field_name(int type)
+{
+ switch (type) {
+ case SQLBINARY:
+ case SQLVARBINARY:
+ return "blob";
+ break;
+ case SQLCHAR:
+ case SQLVARCHAR:
+ return "char";
+ break;
+ case SQLTEXT:
+ return "text";
+ break;
+ case SQLDATETIME:
+ case SQLDATETIM4:
+ case SQLDATETIMN:
+ return "datetime";
+ break;
+ case SQLDECIMAL:
+ case SQLFLT4:
+ case SQLFLT8:
+ case SQLFLTN:
+ return "real";
+ break;
+ case SQLINT1:
+ case SQLINT2:
+ case SQLINT4:
+ case SQLINTN:
+ return "int";
+ break;
+ case SQLNUMERIC:
+ return "numeric";
+ break;
+ case SQLMONEY:
+ case SQLMONEY4:
+ case SQLMONEYN:
+ return "money";
+ break;
+ case SQLBIT:
+ return "bit";
+ break;
+ case SQLIMAGE:
+ return "image";
+ break;
+#ifdef SQLUNIQUE
+ case SQLUNIQUE:
+ return "uniqueidentifier";
+ break;
+#endif
+ default:
+ return "unknown";
+ break;
+ }
+}
+/* }}} */
+
+/* {{{ proto object mssql_fetch_field(resource result_id [, int offset])
+ Gets information about certain fields in a query result */
+PHP_FUNCTION(mssql_fetch_field)
+{
+ zval *mssql_result_index;
+ long field_offset = -1;
+ mssql_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ if (field_offset==-1) {
+ field_offset = result->cur_field;
+ result->cur_field++;
+ }
+
+ if (field_offset<0 || field_offset >= result->num_fields) {
+ if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
+ }
+ RETURN_FALSE;
+ }
+
+ object_init(return_value);
+
+ add_property_string(return_value, "name",result->fields[field_offset].name, 1);
+ add_property_long(return_value, "max_length",result->fields[field_offset].max_length);
+ add_property_string(return_value, "column_source",result->fields[field_offset].column_source, 1);
+ add_property_long(return_value, "numeric", result->fields[field_offset].numeric);
+ add_property_string(return_value, "type", php_mssql_get_field_name(Z_TYPE(result->fields[field_offset])), 1);
+}
+/* }}} */
+
+/* {{{ proto int mssql_field_length(resource result_id [, int offset])
+ Get the length of a MS-SQL field */
+PHP_FUNCTION(mssql_field_length)
+{
+ zval *mssql_result_index;
+ long field_offset = -1;
+ mssql_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ if (field_offset==-1) {
+ field_offset = result->cur_field;
+ result->cur_field++;
+ }
+
+ if (field_offset<0 || field_offset >= result->num_fields) {
+ if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
+ }
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(result->fields[field_offset].max_length);
+}
+/* }}} */
+
+/* {{{ proto string mssql_field_name(resource result_id [, int offset])
+ Returns the name of the field given by offset in the result set given by result_id */
+PHP_FUNCTION(mssql_field_name)
+{
+ zval *mssql_result_index;
+ long field_offset = -1;
+ mssql_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ if (field_offset==-1) {
+ field_offset = result->cur_field;
+ result->cur_field++;
+ }
+
+ if (field_offset<0 || field_offset >= result->num_fields) {
+ if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
+ }
+ RETURN_FALSE;
+ }
+
+ RETURN_STRINGL(result->fields[field_offset].name, strlen(result->fields[field_offset].name), 1);
+}
+/* }}} */
+
+/* {{{ proto string mssql_field_type(resource result_id [, int offset])
+ Returns the type of a field */
+PHP_FUNCTION(mssql_field_type)
+{
+ zval *mssql_result_index;
+ long field_offset = -1;
+ mssql_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ if (field_offset==-1) {
+ field_offset = result->cur_field;
+ result->cur_field++;
+ }
+
+ if (field_offset<0 || field_offset >= result->num_fields) {
+ if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
+ }
+ RETURN_FALSE;
+ }
+
+ RETURN_STRINGL(php_mssql_get_field_name(Z_TYPE(result->fields[field_offset])), strlen(php_mssql_get_field_name(Z_TYPE(result->fields[field_offset]))), 1);
+}
+/* }}} */
+
+/* {{{ proto bool mssql_field_seek(resource result_id, int offset)
+ Seeks to the specified field offset */
+PHP_FUNCTION(mssql_field_seek)
+{
+ zval *mssql_result_index;
+ long field_offset;
+ mssql_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &mssql_result_index, &field_offset) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ if (field_offset<0 || field_offset >= result->num_fields) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
+ RETURN_FALSE;
+ }
+
+ result->cur_field = field_offset;
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string mssql_result(resource result_id, int row, mixed field)
+ Returns the contents of one cell from a MS-SQL result set */
+PHP_FUNCTION(mssql_result)
+{
+ zval **field, *mssql_result_index;
+ long row;
+ int field_offset=0;
+ mssql_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlZ", &mssql_result_index, &row, &field) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ if (row < 0 || row >= result->num_rows) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad row offset (%ld)", row);
+ RETURN_FALSE;
+ }
+
+ switch(Z_TYPE_PP(field)) {
+ case IS_STRING: {
+ int i;
+
+ for (i=0; i<result->num_fields; i++) {
+ if (!strcasecmp(result->fields[i].name, Z_STRVAL_PP(field))) {
+ field_offset = i;
+ break;
+ }
+ }
+ if (i>=result->num_fields) { /* no match found */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s field not found in result", Z_STRVAL_PP(field));
+ RETURN_FALSE;
+ }
+ break;
+ }
+ default:
+ convert_to_long_ex(field);
+ field_offset = Z_LVAL_PP(field);
+ if (field_offset<0 || field_offset>=result->num_fields) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
+ RETURN_FALSE;
+ }
+ break;
+ }
+
+ *return_value = result->data[row][field_offset];
+ zval_copy_ctor(return_value);
+}
+/* }}} */
+
+/* {{{ proto bool mssql_next_result(resource result_id)
+ Move the internal result pointer to the next result */
+PHP_FUNCTION(mssql_next_result)
+{
+ zval *mssql_result_index;
+ int retvalue;
+ mssql_result *result;
+ mssql_link *mssql_ptr;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
+
+ mssql_ptr = result->mssql_ptr;
+ retvalue = dbresults(mssql_ptr->link);
+
+ while (dbnumcols(mssql_ptr->link) <= 0 && retvalue == SUCCEED) {
+ retvalue = dbresults(mssql_ptr->link);
+ }
+
+ if (retvalue == FAIL) {
+ RETURN_FALSE;
+ }
+ else if (retvalue == NO_MORE_RESULTS || retvalue == NO_MORE_RPC_RESULTS) {
+ if (result->statement) {
+ _mssql_get_sp_result(mssql_ptr, result->statement TSRMLS_CC);
+ }
+ RETURN_FALSE;
+ }
+ else {
+ _free_result(result, 1);
+ result->cur_row=result->num_fields=result->num_rows=0;
+ dbclrbuf(mssql_ptr->link,DBLASTROW(mssql_ptr->link));
+ retvalue = dbnextrow(mssql_ptr->link);
+
+ result->num_fields = dbnumcols(mssql_ptr->link);
+ result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), result->num_fields, 0);
+ result->have_fields = 0;
+ result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
+ RETURN_TRUE;
+ }
+
+}
+/* }}} */
+
+
+/* {{{ proto void mssql_min_error_severity(int severity)
+ Sets the lower error severity */
+PHP_FUNCTION(mssql_min_error_severity)
+{
+ long severity;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &severity) == FAILURE) {
+ return;
+ }
+
+ MS_SQL_G(min_error_severity) = severity;
+}
+
+/* }}} */
+
+/* {{{ proto void mssql_min_message_severity(int severity)
+ Sets the lower message severity */
+PHP_FUNCTION(mssql_min_message_severity)
+{
+ long severity;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &severity) == FAILURE) {
+ return;
+ }
+
+ MS_SQL_G(min_message_severity) = severity;
+}
+/* }}} */
+
+/* {{{ proto int mssql_init(string sp_name [, resource conn_id])
+ Initializes a stored procedure or a remote stored procedure */
+PHP_FUNCTION(mssql_init)
+{
+ char *sp_name;
+ int sp_name_len;
+ zval *mssql_link_index = NULL;
+ mssql_link *mssql_ptr;
+ mssql_statement *statement;
+ int id = -1;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &sp_name, &sp_name_len, &mssql_link_index) == FAILURE) {
+ return;
+ }
+
+ if (mssql_link_index == NULL) {
+ id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ CHECK_LINK(id);
+ }
+
+ ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
+
+ if (dbrpcinit(mssql_ptr->link, sp_name,0)==FAIL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to init stored procedure");
+ RETURN_FALSE;
+ }
+
+ statement=NULL;
+ statement = ecalloc(1,sizeof(mssql_statement));
+ statement->link = mssql_ptr;
+ statement->executed=FALSE;
+
+ statement->id = zend_list_insert(statement,le_statement TSRMLS_CC);
+
+ RETURN_RESOURCE(statement->id);
+}
+/* }}} */
+
+/* {{{ proto bool mssql_bind(resource stmt, string param_name, mixed var, int type [, bool is_output [, bool is_null [, int maxlen]]])
+ Adds a parameter to a stored procedure or a remote stored procedure */
+PHP_FUNCTION(mssql_bind)
+{
+ char *param_name;
+ int param_name_len, datalen;
+ int status = 0;
+ long type = 0, maxlen = -1;
+ zval *stmt, **var;
+ zend_bool is_output = 0, is_null = 0;
+ mssql_link *mssql_ptr;
+ mssql_statement *statement;
+ mssql_bind bind,*bindp;
+ LPBYTE value = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZl|bbl", &stmt, &param_name, &param_name_len, &var, &type, &is_output, &is_null, &maxlen) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() == 7 && !is_output) {
+ maxlen = -1;
+ }
+
+ ZEND_FETCH_RESOURCE(statement, mssql_statement *, &stmt, -1, "MS SQL-Statement", le_statement);
+
+ if (statement==NULL) {
+ RETURN_FALSE;
+ }
+ mssql_ptr=statement->link;
+
+ /* modify datalen and maxlen according to dbrpcparam documentation */
+ if ( (type==SQLVARCHAR) || (type==SQLCHAR) || (type==SQLTEXT) ) { /* variable-length type */
+ if (is_null) {
+ maxlen=0;
+ datalen=0;
+ } else {
+ convert_to_string_ex(var);
+ datalen=Z_STRLEN_PP(var);
+ value=(LPBYTE)Z_STRVAL_PP(var);
+ }
+ } else {
+ /* fixed-length type */
+ if (is_null) {
+ datalen=0;
+ } else {
+ datalen=-1;
+ }
+ maxlen=-1;
+
+ switch (type) {
+ case SQLFLT4:
+ case SQLFLT8:
+ case SQLFLTN:
+ convert_to_double_ex(var);
+ value=(LPBYTE)(&Z_DVAL_PP(var));
+ break;
+
+ case SQLBIT:
+ case SQLINT1:
+ case SQLINT2:
+ case SQLINT4:
+ convert_to_long_ex(var);
+ value=(LPBYTE)(&Z_LVAL_PP(var));
+ break;
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported type");
+ RETURN_FALSE;
+ break;
+ }
+ }
+
+ if (is_output) {
+ status=DBRPCRETURN;
+ }
+
+ /* hashtable of binds */
+ if (! statement->binds) {
+ ALLOC_HASHTABLE(statement->binds);
+ zend_hash_init(statement->binds, 13, NULL, _mssql_bind_hash_dtor, 0);
+ }
+
+ if (zend_hash_exists(statement->binds, param_name, param_name_len)) {
+ RETURN_FALSE;
+ }
+ else {
+ memset((void*)&bind,0,sizeof(mssql_bind));
+ zend_hash_add(statement->binds, param_name, param_name_len, &bind, sizeof(mssql_bind), (void **)&bindp);
+ if( NULL == bindp ) RETURN_FALSE;
+ bindp->zval=*var;
+ zval_add_ref(var);
+
+ /* no call to dbrpcparam if RETVAL */
+ if ( strcmp("RETVAL", param_name)!=0 ) {
+ if (dbrpcparam(mssql_ptr->link, param_name, (BYTE)status, type, maxlen, datalen, (LPBYTE)value)==FAIL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set parameter");
+ RETURN_FALSE;
+ }
+ }
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto mixed mssql_execute(resource stmt [, bool skip_results = false])
+ Executes a stored procedure on a MS-SQL server database */
+PHP_FUNCTION(mssql_execute)
+{
+ zval *stmt;
+ zend_bool skip_results = 0;
+ int retvalue, retval_results;
+ mssql_link *mssql_ptr;
+ mssql_statement *statement;
+ mssql_result *result;
+ int num_fields;
+ int batchsize;
+ int exec_retval;
+
+ batchsize = MS_SQL_G(batchsize);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &stmt, &skip_results) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(statement, mssql_statement *, &stmt, -1, "MS SQL-Statement", le_statement);
+
+ mssql_ptr=statement->link;
+ exec_retval = dbrpcexec(mssql_ptr->link);
+
+ if (exec_retval == FAIL || dbsqlok(mssql_ptr->link) == FAIL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "stored procedure execution failed");
+
+ if (exec_retval == FAIL) {
+ dbcancel(mssql_ptr->link);
+ }
+
+ RETURN_FALSE;
+ }
+
+ retval_results=dbresults(mssql_ptr->link);
+
+ if (retval_results==FAIL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not retrieve results");
+ dbcancel(mssql_ptr->link);
+ RETURN_FALSE;
+ }
+
+ /* The following is just like mssql_query, fetch all rows from the first result
+ * set into the row buffer.
+ */
+ result=NULL;
+ if (retval_results == SUCCEED) {
+ if (skip_results) {
+ do {
+ dbcanquery(mssql_ptr->link);
+ retval_results = dbresults(mssql_ptr->link);
+ } while (retval_results == SUCCEED);
+ }
+ else {
+ /* Skip results not returning any columns */
+ while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retval_results == SUCCEED) {
+ retval_results = dbresults(mssql_ptr->link);
+ }
+ if ((num_fields = dbnumcols(mssql_ptr->link)) > 0) {
+ retvalue = dbnextrow(mssql_ptr->link);
+ result = (mssql_result *) emalloc(sizeof(mssql_result));
+ result->batchsize = batchsize;
+ result->blocks_initialized = 1;
+ result->data = (zval **) safe_emalloc(sizeof(zval *), MSSQL_ROWS_BLOCK, 0);
+ result->mssql_ptr = mssql_ptr;
+ result->cur_field=result->cur_row=result->num_rows=0;
+ result->num_fields = num_fields;
+ result->have_fields = 0;
+
+ result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), num_fields, 0);
+ result->statement = statement;
+ result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
+ }
+ }
+ }
+ if (retval_results == NO_MORE_RESULTS || retval_results == NO_MORE_RPC_RESULTS) {
+ _mssql_get_sp_result(mssql_ptr, statement TSRMLS_CC);
+ }
+
+ if (result==NULL) {
+ RETURN_TRUE; /* no recordset returned ...*/
+ }
+ else {
+ ZEND_REGISTER_RESOURCE(return_value, result, le_result);
+ }
+}
+/* }}} */
+
+/* {{{ proto bool mssql_free_statement(resource result_index)
+ Free a MS-SQL statement index */
+PHP_FUNCTION(mssql_free_statement)
+{
+ zval *mssql_statement_index;
+ mssql_statement *statement;
+ int retvalue;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_statement_index) == FAILURE) {
+ return;
+ }
+
+ if (Z_RESVAL_P(mssql_statement_index) == 0) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(statement, mssql_statement *, &mssql_statement_index, -1, "MS SQL-statement", le_statement);
+ /* Release remaining results */
+ do {
+ dbcanquery(statement->link->link);
+ retvalue = dbresults(statement->link->link);
+ } while (retvalue == SUCCEED);
+
+ zend_list_delete(Z_RESVAL_P(mssql_statement_index));
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string mssql_guid_string(string binary [,bool short_format])
+ Converts a 16 byte binary GUID to a string */
+PHP_FUNCTION(mssql_guid_string)
+{
+ char *binary;
+ int binary_len;
+ zend_bool sf = 0;
+ char buffer[32+1];
+ char buffer2[36+1];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &binary, &binary_len, &sf) == FAILURE) {
+ return;
+ }
+
+ dbconvert(NULL, SQLBINARY, (BYTE*) binary, MIN(16, binary_len), SQLCHAR, buffer, -1);
+
+ if (sf) {
+ php_strtoupper(buffer, 32);
+ RETURN_STRING(buffer, 1);
+ }
+ else {
+ int i;
+ /* FIXME this works only on little endian machine */
+ for (i=0; i<4; i++) {
+ buffer2[2*i] = buffer[6-2*i];
+ buffer2[2*i+1] = buffer[7-2*i];
+ }
+ buffer2[8] = '-';
+ for (i=0; i<2; i++) {
+ buffer2[9+2*i] = buffer[10-2*i];
+ buffer2[10+2*i] = buffer[11-2*i];
+ }
+ buffer2[13] = '-';
+ for (i=0; i<2; i++) {
+ buffer2[14+2*i] = buffer[14-2*i];
+ buffer2[15+2*i] = buffer[15-2*i];
+ }
+ buffer2[18] = '-';
+ for (i=0; i<4; i++) {
+ buffer2[19+i] = buffer[16+i];
+ }
+ buffer2[23] = '-';
+ for (i=0; i<12; i++) {
+ buffer2[24+i] = buffer[20+i];
+ }
+ buffer2[36] = 0;
+
+ php_strtoupper(buffer2, 36);
+ RETURN_STRING(buffer2, 1);
+ }
+}
+/* }}} */
+
+#endif
diff --git a/ext/mssql/php_mssql.h b/ext/mssql/php_mssql.h
new file mode 100644
index 0000000..b73c842
--- /dev/null
+++ b/ext/mssql/php_mssql.h
@@ -0,0 +1,214 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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: Frank M. Kromann <frank@kromann.info> |
+ +----------------------------------------------------------------------+
+ */
+
+
+/* $Id$ */
+
+#ifndef PHP_MSSQL_H
+#define PHP_MSSQL_H
+
+
+#if HAVE_MSSQL
+#define MSDBLIB
+
+/* FreeTDS checks for PHP_MSSQL_API for avoid type redefinition */
+#ifdef HAVE_FREETDS
+#define PHP_MSSQL_API
+#endif
+
+#include <sqlfront.h>
+#include <sqldb.h>
+
+typedef short TDS_SHORT;
+#ifdef HAVE_FREETDS
+#define MSSQL_VERSION "FreeTDS"
+#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 SQLUNIQUE /* FreeTSD 0.61+ */
+#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
+#ifndef dbfreelogin
+#define dbfreelogin dbloginfree
+#endif
+#define dbrpcexec dbrpcsend
+typedef unsigned char *LPBYTE;
+typedef float DBFLT4;
+#else
+#define MSSQL_VERSION "7.0"
+#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)
+#endif
+
+#define coltype(j) dbcoltype(mssql_ptr->link,j)
+#define intcol(i) ((int) *(DBINT *) dbdata(mssql_ptr->link,i))
+#define smallintcol(i) ((int) *(DBSMALLINT *) dbdata(mssql_ptr->link,i))
+#define tinyintcol(i) ((int) *(DBTINYINT *) dbdata(mssql_ptr->link,i))
+#define anyintcol(j) (coltype(j)==SQLINT4?intcol(j):(coltype(j)==SQLINT2?smallintcol(j):tinyintcol(j)))
+#define charcol(i) ((DBCHAR *) dbdata(mssql_ptr->link,i))
+#define floatcol4(i) (*(DBFLT4 *) dbdata(mssql_ptr->link,i))
+#define floatcol8(i) (*(DBFLT8 *) dbdata(mssql_ptr->link,i))
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+extern zend_module_entry mssql_module_entry;
+#define mssql_module_ptr &mssql_module_entry
+
+PHP_MINIT_FUNCTION(mssql);
+PHP_MSHUTDOWN_FUNCTION(mssql);
+PHP_RINIT_FUNCTION(mssql);
+PHP_RSHUTDOWN_FUNCTION(mssql);
+PHP_MINFO_FUNCTION(mssql);
+
+PHP_FUNCTION(mssql_connect);
+PHP_FUNCTION(mssql_pconnect);
+PHP_FUNCTION(mssql_close);
+PHP_FUNCTION(mssql_select_db);
+PHP_FUNCTION(mssql_query);
+PHP_FUNCTION(mssql_fetch_batch);
+PHP_FUNCTION(mssql_rows_affected);
+PHP_FUNCTION(mssql_free_result);
+PHP_FUNCTION(mssql_get_last_message);
+PHP_FUNCTION(mssql_num_rows);
+PHP_FUNCTION(mssql_num_fields);
+PHP_FUNCTION(mssql_fetch_field);
+PHP_FUNCTION(mssql_fetch_row);
+PHP_FUNCTION(mssql_fetch_array);
+PHP_FUNCTION(mssql_fetch_assoc);
+PHP_FUNCTION(mssql_fetch_object);
+PHP_FUNCTION(mssql_field_length);
+PHP_FUNCTION(mssql_field_name);
+PHP_FUNCTION(mssql_field_type);
+PHP_FUNCTION(mssql_data_seek);
+PHP_FUNCTION(mssql_field_seek);
+PHP_FUNCTION(mssql_result);
+PHP_FUNCTION(mssql_next_result);
+PHP_FUNCTION(mssql_min_error_severity);
+PHP_FUNCTION(mssql_min_message_severity);
+PHP_FUNCTION(mssql_init);
+PHP_FUNCTION(mssql_bind);
+PHP_FUNCTION(mssql_execute);
+PHP_FUNCTION(mssql_free_statement);
+PHP_FUNCTION(mssql_guid_string);
+
+typedef struct mssql_link {
+ LOGINREC *login;
+ DBPROCESS *link;
+ int valid;
+} mssql_link;
+
+typedef struct mssql_statement {
+ int id;
+ mssql_link *link;
+ HashTable *binds;
+ int executed;
+} mssql_statement;
+
+typedef struct {
+
+ zval *zval;
+ /* TODO: more data for special types (BLOBS, NUMERIC...) */
+} mssql_bind;
+
+ZEND_BEGIN_MODULE_GLOBALS(mssql)
+ long default_link;
+ long num_links,num_persistent;
+ long max_links,max_persistent;
+ zend_bool allow_persistent;
+ char *appname;
+ char *server_message;
+#ifdef HAVE_FREETDS
+ char *charset;
+#endif
+ long min_error_severity, min_message_severity;
+ long cfg_min_error_severity, cfg_min_message_severity;
+ long connect_timeout, timeout;
+ zend_bool compatability_mode;
+ void (*get_column_content)(mssql_link *mssql_ptr,int offset,zval *result,int column_type TSRMLS_DC);
+ long textsize, textlimit, batchsize;
+ zend_bool datetimeconvert;
+ HashTable *resource_list, *resource_plist;
+ zend_bool secure_connection;
+ long max_procs;
+ZEND_END_MODULE_GLOBALS(mssql)
+
+#define MSSQL_ROWS_BLOCK 128
+
+typedef struct mssql_field {
+ char *name,*column_source;
+ long max_length;
+ int numeric;
+ int type;
+} mssql_field;
+
+typedef struct mssql_result {
+ zval **data;
+ mssql_field *fields;
+ mssql_link *mssql_ptr;
+ mssql_statement * statement;
+ int batchsize;
+ int lastresult;
+ int blocks_initialized;
+ int cur_row,cur_field;
+ int num_rows,num_fields,have_fields;
+} mssql_result;
+
+
+#ifdef ZTS
+# define MS_SQL_G(v) TSRMG(mssql_globals_id, zend_mssql_globals *, v)
+#else
+# define MS_SQL_G(v) (mssql_globals.v)
+#endif
+
+#else
+
+#define mssql_module_ptr NULL
+
+#endif /* HAVE_MSSQL */
+
+#define phpext_mssql_ptr mssql_module_ptr
+
+#endif /* PHP_MSSQL_H */