diff options
Diffstat (limited to 'ext/mssql')
-rw-r--r-- | ext/mssql/CREDITS | 2 | ||||
-rw-r--r-- | ext/mssql/config.m4 | 56 | ||||
-rw-r--r-- | ext/mssql/config.w32 | 28 | ||||
-rw-r--r-- | ext/mssql/mssql.dsp | 117 | ||||
-rw-r--r-- | ext/mssql/mssql_win32_howto.txt | 35 | ||||
-rw-r--r-- | ext/mssql/php_mssql.c | 2279 | ||||
-rw-r--r-- | ext/mssql/php_mssql.h | 214 |
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, ¶m_name, ¶m_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 */ |