diff options
author | Frank M. Kromann <fmk@php.net> | 1999-11-03 20:35:58 +0000 |
---|---|---|
committer | Frank M. Kromann <fmk@php.net> | 1999-11-03 20:35:58 +0000 |
commit | e5ca107a3d8cc5df344d894331436d141609f31a (patch) | |
tree | 45bc387686e2a63a25facd82b8d45c011f1e2e98 | |
parent | a79bdcc28f147629af1aa510c95dce510bfa1d19 (diff) | |
download | php-git-e5ca107a3d8cc5df344d894331436d141609f31a.tar.gz |
Adding MS SQL Server module for Win32
-rw-r--r-- | ext/mssql/Readme_w32.txt | 10 | ||||
-rw-r--r-- | ext/mssql/mssql.dsp | 118 | ||||
-rw-r--r-- | ext/mssql/php_mssql.c | 1429 | ||||
-rw-r--r-- | ext/mssql/php_mssql.h | 150 |
4 files changed, 1707 insertions, 0 deletions
diff --git a/ext/mssql/Readme_w32.txt b/ext/mssql/Readme_w32.txt new file mode 100644 index 0000000000..7ae22dc578 --- /dev/null +++ b/ext/mssql/Readme_w32.txt @@ -0,0 +1,10 @@ +MS SQL Extension for PHP 4.0 - Win32 README +------------------------------------------- + +In order to compile this extension, copy sqlfront.h, sqldb.h and ntwdblib.lib to mssql-65 or mssql-70. +These files are optaind from the MS SQL Server distribution CD + +You can change the file location by changing include and lib paths in the project. + + +[03/11/1999 fmk@swwwing.com]
\ No newline at end of file diff --git a/ext/mssql/mssql.dsp b/ext/mssql/mssql.dsp new file mode 100644 index 0000000000..7ae86e6610 --- /dev/null +++ b/ext/mssql/mssql.dsp @@ -0,0 +1,118 @@ +# 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 Debug
+!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 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mssql - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mssql - Win32 Debug" (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"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "mssql___Win32_Release"
+# PROP BASE Intermediate_Dir "mssql___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "MSSQL_65_Release"
+# PROP Intermediate_Dir "MSSQL_65_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MSSQL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\libzend" /I "..\..\..\bindlib_w32" /I "..\..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MSSQL_EXPORTS" /D "COMPILE_DL" /D "DBNTWIN32" /D ZTS=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 /nologo /dll /machine:I386
+# 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 php4ts.lib ntwdblib.lib /nologo /dll /machine:I386 /out:"MSSQL_65_Release/php_mssql.dll" /libpath:"..\..\Release_TS"
+
+!ELSEIF "$(CFG)" == "mssql - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MSSQL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MSSQL_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "_DEBUG"
+# ADD RSC /l 0x406 /d "_DEBUG"
+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 /nologo /dll /debug /machine:I386 /pdbtype:sept
+# 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 /nologo /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "mssql - Win32 Release"
+# Name "mssql - Win32 Debug"
+# 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
+# Begin Source File
+
+SOURCE=.\sqldb.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqlfront.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
+# End Target
+# End Project
diff --git a/ext/mssql/php_mssql.c b/ext/mssql/php_mssql.c new file mode 100644 index 0000000000..9ab6d241f2 --- /dev/null +++ b/ext/mssql/php_mssql.c @@ -0,0 +1,1429 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_0.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. | + +----------------------------------------------------------------------+ + | Authors: Frank M. Kromann <fmk@businesnet.dk> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#if COMPILE_DL +#include "dl/phpdl.h" +#define HAVE_MSSQL 1 +#endif + +#include "php.h" +#include "php_globals.h" +#include "ext/standard/php3_standard.h" +#include "php_mssql.h" +#include "php_ini.h" + +#if HAVE_MSSQL +#define SAFE_STRING(s) ((s)?(s):"") + +static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,pval *result, int column_type); +static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,pval *result, int column_type); + +function_entry mssql_functions[] = { + PHP_FE(mssql_connect, NULL) + PHP_FE(mssql_pconnect, NULL) + PHP_FE(mssql_close, NULL) + PHP_FE(mssql_select_db, NULL) + PHP_FE(mssql_query, NULL) + PHP_FE(mssql_free_result, NULL) + PHP_FE(mssql_get_last_message, NULL) + PHP_FE(mssql_num_rows, NULL) + PHP_FE(mssql_num_fields, NULL) + PHP_FE(mssql_fetch_field, NULL) + PHP_FE(mssql_fetch_row, NULL) + PHP_FE(mssql_fetch_array, NULL) + PHP_FE(mssql_fetch_object, NULL) + PHP_FE(mssql_field_length, NULL) + PHP_FE(mssql_field_name, NULL) + PHP_FE(mssql_field_type, NULL) + PHP_FE(mssql_data_seek, NULL) + PHP_FE(mssql_field_seek, NULL) + PHP_FE(mssql_result, NULL) + PHP_FE(mssql_min_error_severity, NULL) + PHP_FE(mssql_min_message_severity, NULL) + {NULL, NULL, NULL} +}; + +zend_module_entry mssql_module_entry = { + "Microsoft SQL Server", + mssql_functions, + PHP_MINIT(mssql), + PHP_MSHUTDOWN(mssql), + PHP_RINIT(mssql), + PHP_RSHUTDOWN(mssql), + PHP_MINFO(mssql), + STANDARD_MODULE_PROPERTIES +}; + +#ifdef ZTS +int mssql_globals_id; +#else +ZEND_API php_mssql_globals mssql_globals; +#endif + +#ifdef COMPILE_DL +DLEXPORT zend_module_entry *get_module(void) { return &mssql_module_entry; }; +#endif + +#define CHECK_LINK(link) { if (link==-1) { php_error(E_WARNING,"MS SQL: A link to the server could not be established"); RETURN_FALSE; } } + +static PHP_INI_DISP(display_link_numbers) +{ + char *value; + + 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 (value) { + if (atoi(value)==-1) { + PUTS("Unlimited"); + } else { + php_printf("%s", value); + } + } +} + +PHP_INI_BEGIN() + STD_PHP_INI_BOOLEAN("mssql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_persistent, php_mssql_globals, mssql_globals) + STD_PHP_INI_ENTRY_EX("mssql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_persistent, php_mssql_globals, mssql_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("mssql.max_links", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_links, php_mssql_globals, mssql_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("mssql.min_error_severity", "10", PHP_INI_ALL, OnUpdateInt, cfg_min_error_severity, php_mssql_globals, mssql_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("mssql.min_message_severity", "10", PHP_INI_ALL, OnUpdateInt, cfg_min_message_severity, php_mssql_globals, mssql_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("mssql.compatability_mode", "0", PHP_INI_ALL, OnUpdateInt, compatability_mode, php_mssql_globals, mssql_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("mssql.connect_timeout", "5", PHP_INI_ALL, OnUpdateInt, connect_timeout, php_mssql_globals, mssql_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("mssql.textsize", "-1", PHP_INI_ALL, OnUpdateInt, textsize, php_mssql_globals, mssql_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("mssql.textlimit", "-1", PHP_INI_ALL, OnUpdateInt, textlimit, php_mssql_globals, mssql_globals, display_link_numbers) +PHP_INI_END() + +/* error handler */ +static int php_mssql_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr) +{ + MSSQLLS_FETCH(); + if (severity >= MS_SQL_G(min_error_severity)) { + php_error(E_WARNING,"MS SQL error: %s (severity %d)", dberrstr, severity); + } + return INT_CANCEL; +} + +/* message handler */ +static int php_mssql_message_handler(DBPROCESS *dbproc, DBINT msgno,int msgstate, int severity,char *msgtext,char *srvname, char *procname,DBUSMALLINT line) +{ + MSSQLLS_FETCH(); + if (severity >= MS_SQL_G(min_message_severity)) { + php_error(E_WARNING,"MS SQL message: %s (severity %d)", msgtext, severity); + } + STR_FREE(MS_SQL_G(server_message)); + MS_SQL_G(server_message) = estrdup(msgtext); + return 0; +} + +static int _clean_invalid_results(list_entry *le) +{ + MSSQLLS_FETCH(); + + if (le->type == MS_SQL_G(le_result)) { + mssql_link *mssql_ptr = ((mssql_result *) le->ptr)->mssql_ptr; + + if (!mssql_ptr->valid) { + return 1; + } + } + return 0; +} + +static void _free_mssql_result(mssql_result *result) +{ + int i,j; + + if (result->data) { + for (i=0; i<result->num_rows; i++) { + for (j=0; j<result->num_fields; j++) { + pval_destructor(&result->data[i][j]); + } + efree(result->data[i]); + } + efree(result->data); + } + + if (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); + } + efree(result); +} + + +static void _close_mssql_link(mssql_link *mssql_ptr) +{ + MSSQLLS_FETCH(); + + mssql_ptr->valid = 0; + zend_hash_apply(MS_SQL_G(resource_list),(int (*)(void *))_clean_invalid_results); + dbclose(mssql_ptr->link); + dbfreelogin(mssql_ptr->login); + efree(mssql_ptr); + MS_SQL_G(num_links)--; +} + + +static void _close_mssql_plink(mssql_link *mssql_ptr) +{ + MSSQLLS_FETCH(); + + dbclose(mssql_ptr->link); + dbfreelogin(mssql_ptr->login); + free(mssql_ptr); + MS_SQL_G(num_persistent)--; + MS_SQL_G(num_links)--; +} + +#ifdef ZTS +static void php_mssql_init_globals(php_mssql_globals *mssql_globals) +{ + MS_SQL_G(num_persistent) = 0; +} +#endif + +PHP_MINIT_FUNCTION(mssql) +{ + ELS_FETCH(); + MSSQLLS_D; + +#ifdef ZTS + mssql_globals_id = ts_allocate_id(sizeof(php_mssql_globals), php_mssql_init_globals, NULL); + mssql_globals = ts_resource(mssql_globals_id); +#else + MS_SQL_G(num_persistent) = 0; +#endif + REGISTER_INI_ENTRIES(); + + MS_SQL_G(le_result) = register_list_destructors(_free_mssql_result, NULL); + MS_SQL_G(le_link) = register_list_destructors(_close_mssql_link, NULL); + MS_SQL_G(le_plink) = register_list_destructors(NULL, _close_mssql_plink); + mssql_module_entry.type = type; + + if (dbinit()==FAIL) { + return FAILURE; + } + dberrhandle((DBERRHANDLE_PROC) php_mssql_error_handler); + dbmsghandle((DBMSGHANDLE_PROC) php_mssql_message_handler); + if (MS_SQL_G(compatability_mode)) { + MS_SQL_G(get_column_content) = php_mssql_get_column_content_with_type; + } else { + MS_SQL_G(get_column_content) = php_mssql_get_column_content_without_type; + } +// if (MS_SQL_G(connecttimeout) < 1) MS_SQL_G(connecttimeout) = 1; +// dbsetlogintime(MS_SQL_G(connecttimeout)); + + return SUCCESS; +} + +PHP_MSHUTDOWN_FUNCTION(mssql) +{ + MSSQLLS_FETCH(); + + UNREGISTER_INI_ENTRIES(); + dbexit(); + return SUCCESS; +} + + +PHP_RINIT_FUNCTION(mssql) +{ + MSSQLLS_FETCH(); + + MS_SQL_G(default_link) = -1; + MS_SQL_G(num_links) = MS_SQL_G(num_persistent); + MS_SQL_G(appname) = "PHP"; + MS_SQL_G(server_message) = empty_string; + 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); + + return SUCCESS; +} + +PHP_RSHUTDOWN_FUNCTION(mssql) +{ + MSSQLLS_FETCH(); + STR_FREE(MS_SQL_G(server_message)); + return SUCCESS; +} + +PHP_MINFO_FUNCTION(mssql) +{ + char buf[32]; + MSSQLLS_FETCH(); + + DISPLAY_INI_ENTRIES(); + + php_printf("<table border=5 width=\"600\">"); + php_info_print_table_header(2, "Key", "Value"); + + sprintf(buf, "%ld", MS_SQL_G(num_persistent)); + php_info_print_table_row(2, "Active Persistent Links", buf); + sprintf(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_printf("</table>\n"); +} + +void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) +{ + char *user, *passwd, *host; + char *hashed_details; + int hashed_details_length; + mssql_link mssql, *mssql_ptr; + char buffer[32]; + MSSQLLS_FETCH(); +// PLS_FETCH(); + + MS_SQL_G(resource_list) = list; + MS_SQL_G(resource_plist) = plist; + + switch(ARG_COUNT(ht)) { + case 0: /* defaults */ + host=user=passwd=NULL; + break; + case 1: { + pval **yyhost; + + if (getParametersEx(1, &yyhost)==FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(yyhost); + host = (*yyhost)->value.str.val; + user=passwd=NULL; + } + break; + case 2: { + pval **yyhost,**yyuser; + + if (getParametersEx(2, &yyhost, &yyuser)==FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(yyhost); + convert_to_string_ex(yyuser); + host = (*yyhost)->value.str.val; + user = (*yyuser)->value.str.val; + passwd=NULL; + } + break; + case 3: { + pval **yyhost,**yyuser,**yypasswd; + + if (getParametersEx(3, &yyhost, &yyuser, &yypasswd) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(yyhost); + convert_to_string_ex(yyuser); + convert_to_string_ex(yypasswd); + host = (*yyhost)->value.str.val; + user = (*yyuser)->value.str.val; + passwd = (*yypasswd)->value.str.val; + } + break; + default: + WRONG_PARAM_COUNT; + break; + } + + hashed_details_length = sizeof("mssql___")-1 + strlen(SAFE_STRING(host))+strlen(SAFE_STRING(user))+strlen(SAFE_STRING(passwd)); + hashed_details = (char *) emalloc(hashed_details_length+1); + + if (hashed_details == NULL) { + php_error(E_WARNING, "Out of memory"); + RETURN_FALSE; + } + + sprintf(hashed_details,"mssql_%s_%s_%s", SAFE_STRING(host), SAFE_STRING(user), SAFE_STRING(passwd)); + +// return_value->value.lval = 0; +// return_value->type = IS_RESOURCE; + + /* set a DBLOGIN record */ + if ((mssql.login = dblogin()) == NULL) { + php_error(E_WARNING,"MS SQL: Unable to allocate login record"); + RETURN_FALSE; + } + + if (user) { + DBSETLUSER(mssql.login,user); + } + if (passwd) { + DBSETLPWD(mssql.login,passwd); + } + DBSETLAPP(mssql.login,MS_SQL_G(appname)); + mssql.valid = 1; + + DBSETLVERSION(mssql.login, DBVER60); +// DBSETLTIME(mssql.login, TIMEOUT_INFINITE); + + if (!MS_SQL_G(allow_persistent)) { + persistent=0; + } + if (persistent) { + list_entry *le; + + /* try to find if we already have this link in our persistent list */ + if (zend_hash_find(plist, hashed_details, hashed_details_length + 1, + (void **) &le)==FAILURE) { /* we don't */ + list_entry new_le; + + if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) { + php_error(E_WARNING,"MS SQL: Too many open links (%d)",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(E_WARNING,"MS SQL: Too many open persistent links (%d)",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(E_WARNING,"MS SQL: Unable to connect to server: %s", 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; + } + + if (MS_SQL_G(textsize) != -1) { + sprintf(buffer, "%li", MS_SQL_G(textsize)); + if (dbsetopt(mssql.link, DBTEXTSIZE, buffer)==FAIL) { + efree(hashed_details); + dbfreelogin(mssql.login); + RETURN_FALSE; + } + } + if (MS_SQL_G(textlimit) != -1) { + sprintf(buffer, "%li", MS_SQL_G(textlimit)); + if (dbsetopt(mssql.link, DBTEXTLIMIT, buffer)==FAIL) { + efree(hashed_details); + dbfreelogin(mssql.login); + RETURN_FALSE; + } + } + + /* hash it up */ + mssql_ptr = (mssql_link *) emalloc(sizeof(mssql_link)); + memcpy(mssql_ptr, &mssql, sizeof(mssql_link)); + new_le.type = MS_SQL_G(le_plink); + new_le.ptr = mssql_ptr; + if (zend_hash_update(plist, hashed_details, hashed_details_length + 1, &new_le, sizeof(list_entry), NULL)==FAILURE) { + efree(mssql_ptr); + efree(hashed_details); + dbfreelogin(mssql.login); + RETURN_FALSE; + } + MS_SQL_G(num_persistent)++; + MS_SQL_G(num_links)++; + } else { /* we do */ + if (le->type != MS_SQL_G(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(E_WARNING,"MS SQL: Hashed persistent link is not a MS SQL link!"); + RETURN_FALSE; + } + + mssql_ptr = (mssql_link *) le->ptr; + /* test that the link hasn't died */ + if (DBDEAD(mssql_ptr->link) == TRUE) { +#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))==FAIL) { +#if BROKEN_MSSQL_PCONNECTS + log_error("PHP/MS SQL: Unable to reconnect!",php_rqst->server); +#endif + php_error(E_WARNING,"MS SQL: Link to server lost, unable to reconnect"); + zend_hash_del(plist, hashed_details, hashed_details_length+1); + efree(hashed_details); + 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(plist, hashed_details, hashed_details_length + 1); + efree(hashed_details); + RETURN_FALSE; + } + } + } + ZEND_REGISTER_RESOURCE(return_value, mssql_ptr, MS_SQL_G(le_plink)); + } else { /* non persistent */ + 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 (zend_hash_find(list, hashed_details, hashed_details_length + 1,(void **) &index_ptr)==SUCCESS) { + int type,link; + void *ptr; + + if (index_ptr->type != le_index_ptr) { + RETURN_FALSE; + } + link = (int) index_ptr->ptr; + ptr = zend_list_find(link,&type); /* check if the link is still there */ + if (ptr && (type==MS_SQL_G(le_link) || type==MS_SQL_G(le_plink))) { + zend_list_addref(link); + return_value->value.lval = MS_SQL_G(default_link) = link; + return_value->type = IS_RESOURCE; + efree(hashed_details); + return; + } else { + zend_hash_del(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(E_WARNING,"MS SQL: Too many open links (%d)",MS_SQL_G(num_links)); + efree(hashed_details); + RETURN_FALSE; + } + + if ((mssql.link=dbopen(mssql.login, host))==NULL) { + php_error(E_WARNING,"MS SQL: Unable to connect to server: %s", host); + efree(hashed_details); + RETURN_FALSE; + } + + if (dbsetopt(mssql.link, DBBUFFER,"2")==FAIL) { + efree(hashed_details); + dbfreelogin(mssql.login); + dbclose(mssql.link); + RETURN_FALSE; + } + + if (MS_SQL_G(textlimit) != -1) { + sprintf(buffer, "%li", MS_SQL_G(textlimit)); + if (dbsetopt(mssql.link, DBTEXTLIMIT, buffer)==FAIL) { + efree(hashed_details); + dbfreelogin(mssql.login); + RETURN_FALSE; + } + } + if (MS_SQL_G(textsize) != -1) { + sprintf(buffer, "SET TEXTSIZE %li", MS_SQL_G(textsize)); + + dbcmd(mssql.link, buffer); + dbsqlexec(mssql.link); + dbresults(mssql.link); +// if (dbsetopt(mssql.link, DBTEXTSIZE, buffer)==FAIL) { +// efree(hashed_details); +// dbfreelogin(mssql.login); +// RETURN_FALSE; +// } + } + + /* 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, MS_SQL_G(le_link)); + + /* add it to the hash */ + new_index_ptr.ptr = (void *) return_value->value.lval; + new_index_ptr.type = le_index_ptr; + if (zend_hash_update(list, hashed_details, hashed_details_length + 1,(void *) &new_index_ptr, sizeof(list_entry),NULL)==FAILURE) { + efree(hashed_details); + RETURN_FALSE; + } + MS_SQL_G(num_links)++; + } + efree(hashed_details); +// MS_SQL_G(default_link)=return_value->value.lval; +} + + +static int php_mssql_get_default_link(INTERNAL_FUNCTION_PARAMETERS) +{ + MSSQLLS_FETCH(); + + 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); +} + + +PHP_FUNCTION(mssql_connect) +{ + php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0); +} + +PHP_FUNCTION(mssql_pconnect) +{ + php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1); +} + +PHP_FUNCTION(mssql_close) +{ + pval **mssql_link_index; + int id; + mssql_link *mssql_ptr; + MSSQLLS_FETCH(); + + + switch (ARG_COUNT(ht)) { + case 0: + id = MS_SQL_G(default_link); + break; + case 1: + if (getParametersEx(1, &mssql_link_index)==FAILURE) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, mssql_link_index, -1, "MS SQL-Link", MS_SQL_G(le_link), MS_SQL_G(le_plink)); + id = (*mssql_link_index)->value.lval; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + zend_list_delete(id); + + RETURN_TRUE; +} + +PHP_FUNCTION(mssql_select_db) +{ + pval **db, **mssql_link_index; + int id; + mssql_link *mssql_ptr; + MSSQLLS_FETCH(); + + + switch(ARG_COUNT(ht)) { + case 1: + if (getParametersEx(1, &db)==FAILURE) { + RETURN_FALSE; + } + id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + break; + case 2: + if (getParametersEx(2, &db, &mssql_link_index)==FAILURE) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, mssql_link_index, -1, "MS SQL-Link", MS_SQL_G(le_link), MS_SQL_G(le_plink)); + id = (*mssql_link_index)->value.lval; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + CHECK_LINK(id); + + convert_to_string_ex(db); + + if (dbuse(mssql_ptr->link, (*db)->value.str.val)==FAIL) { + php_error(E_WARNING,"MS SQL: Unable to select database: %s", (*db)->value.str.val); + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} + +static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,pval *result, int column_type) +{ + if (dbdatlen(mssql_ptr->link,offset) == 0) { + var_reset(result); + return; + } + + switch (column_type) + { + case SQLINT1: + case SQLINT2: + case SQLINT4: + case SQLINTN: { + result->value.lval = (long) anyintcol(offset); + result->type = IS_LONG; + break; + } + case SQLCHAR: + case SQLVARCHAR: + case SQLTEXT: { + int length; + char *data = charcol(offset); + + length=dbdatlen(mssql_ptr->link,offset); + while (length>0 && charcol(offset)[length-1] == ' ') { /* nuke trailing whitespace */ + length--; + } + result->value.str.val = estrndup(data,length); + result->value.str.len = length; + result->type = IS_STRING; + break; + } + case SQLFLT8: { + result->value.dval = (double) floatcol(offset); + result->type = IS_DOUBLE; + break; + } + case SQLNUMERIC: + default: { + if (dbwillconvert(coltype(offset),SQLCHAR)) { + char *res_buf; + int res_length = dbdatlen(mssql_ptr->link,offset); + + res_buf = (char *) emalloc(res_length+1); + memset(res_buf, 0, res_length+1); + dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length,SQLCHAR,res_buf,-1); + + result->value.str.len = res_length; + result->value.str.val = res_buf; + result->type = IS_STRING; + } else { + php_error(E_WARNING,"MS SQL: column %d has unknown data type (%d)", offset, coltype(offset)); + var_reset(result); + } + } + } +} + +static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,pval *result, int column_type) +{ + if (dbdatlen(mssql_ptr->link,offset) == 0) { + var_reset(result); + return; + } + if (dbwillconvert(coltype(offset),SQLCHAR)) { + unsigned char *res_buf; + int res_length = dbdatlen(mssql_ptr->link,offset); + + res_buf = (unsigned char *) emalloc(res_length+1 + 19); + memset(res_buf, 0, res_length+1 + 10); + dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR,res_buf,-1); + + result->value.str.len = strlen(res_buf); + result->value.str.val = res_buf; + result->type = IS_STRING; + } else { + php_error(E_WARNING,"MS SQL: column %d has unknown data type (%d)", offset, coltype(offset)); + var_reset(result); + } +} + +PHP_FUNCTION(mssql_query) +{ + pval **query, **mssql_link_index; + int retvalue; + mssql_link *mssql_ptr; + mssql_result *result; + int num_fields; + int blocks_initialized=1; + int i,j; + int *column_types; + MSSQLLS_FETCH(); + + + switch(ARG_COUNT(ht)) { + case 1: + if (getParametersEx(1, &query)==FAILURE) { + RETURN_FALSE; + } +// id = MS_SQL_G(default_link); + break; + case 2: + if (getParametersEx(2, &query, &mssql_link_index)==FAILURE) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, mssql_link_index, -1, "MS SQL-Link", MS_SQL_G(le_link), MS_SQL_G(le_plink)); + break; + default: + WRONG_PARAM_COUNT; + break; + } + + convert_to_string_ex(query); + + if (dbcmd(mssql_ptr->link, (*query)->value.str.val)==FAIL) { + php_error(E_WARNING,"MS SQL: Unable to set query"); + RETURN_FALSE; + } + if (dbsqlexec(mssql_ptr->link)==FAIL || dbresults(mssql_ptr->link)==FAIL) { + php_error(E_WARNING,"MS SQL: Query failed"); + RETURN_FALSE; + } + + /* The following is more or less the equivalent of mysql_store_result(). + * fetch all rows from the server into the row buffer, thus: + * 1) Being able to fire up another query without explicitly reading all rows + * 2) Having numrows accessible + */ + retvalue=dbnextrow(mssql_ptr->link); + + if (retvalue==FAIL) { + RETURN_FALSE; + } + + num_fields = dbnumcols(mssql_ptr->link); + if (num_fields <= 0) { + RETURN_TRUE; + } + + column_types = (int *) emalloc(sizeof(int) * num_fields); + for (i=0; i<num_fields; i++) { + column_types[i] = coltype(i+1); + } + + result = (mssql_result *) emalloc(sizeof(mssql_result)); + result->data = (pval **) emalloc(sizeof(pval *)*MSSQL_ROWS_BLOCK); + result->mssql_ptr = mssql_ptr; + result->cur_field=result->cur_row=result->num_rows=0; + result->num_fields = num_fields; + + i=0; + while (retvalue!=FAIL && retvalue!=NO_MORE_ROWS) { + result->num_rows++; + if (result->num_rows > blocks_initialized*MSSQL_ROWS_BLOCK) { + result->data = (pval **) erealloc(result->data,sizeof(pval *)*MSSQL_ROWS_BLOCK*(++blocks_initialized)); + } + result->data[i] = (pval *) emalloc(sizeof(pval)*num_fields); + for (j=1; j<=num_fields; j++) { + MS_SQL_G(get_column_content(mssql_ptr, j, &result->data[i][j-1], column_types[j-1])); + } + retvalue=dbnextrow(mssql_ptr->link); + dbclrbuf(mssql_ptr->link,DBLASTROW(mssql_ptr->link)-1); + i++; + } + result->num_rows = DBCOUNT(mssql_ptr->link); + + result->fields = (mssql_field *) emalloc(sizeof(mssql_field)*num_fields); + j=0; + for (i=0; i<num_fields; i++) { + char *fname = (char *)dbcolname(mssql_ptr->link,i+1); + char computed_buf[16]; + + 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); + result->fields[i].column_source = estrdup(dbcolsource(mssql_ptr->link,i+1)); + if (!result->fields[i].column_source) { + result->fields[i].column_source = empty_string; + } + result->fields[i].type = column_types[i]; + /* set numeric flag */ + switch (column_types[i]) { + case SQLINT1: + case SQLINT2: + case SQLINT4: + 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; + } + } + efree(column_types); + + ZEND_REGISTER_RESOURCE(return_value, result, MS_SQL_G(le_result)); +} + +PHP_FUNCTION(mssql_free_result) +{ + pval **mssql_result_index; + mssql_result *result; + MSSQLLS_FETCH(); + + + if (ARG_COUNT(ht)!=1 || getParametersEx(1, &mssql_result_index)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(result, mssql_result *, mssql_result_index, -1, "MS SQL-result", MS_SQL_G(le_result)); + zend_list_delete((*mssql_result_index)->value.lval); + RETURN_TRUE; +} + +PHP_FUNCTION(mssql_get_last_message) +{ + MSSQLLS_FETCH(); + + RETURN_STRING(MS_SQL_G(server_message),1); +} + +PHP_FUNCTION(mssql_num_rows) +{ + pval **mssql_result_index; + mssql_result *result; + MSSQLLS_FETCH(); + + + if (ARG_COUNT(ht)!=1 || getParametersEx(1, &mssql_result_index)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(result, mssql_result *, mssql_result_index, -1, "MS SQL-result", MS_SQL_G(le_result)); + + return_value->value.lval = result->num_rows; + return_value->type = IS_LONG; +} + +PHP_FUNCTION(mssql_num_fields) +{ + pval **mssql_result_index; + mssql_result *result; + MSSQLLS_FETCH(); + + + if (ARG_COUNT(ht)!=1 || getParametersEx(1, &mssql_result_index)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(result, mssql_result *, mssql_result_index, -1, "MS SQL-result", MS_SQL_G(le_result)); + + return_value->value.lval = result->num_fields; + return_value->type = IS_LONG; +} + +PHP_FUNCTION(mssql_fetch_row) +{ + pval **mssql_result_index; + int i; + mssql_result *result; + pval *field_content; + MSSQLLS_FETCH(); + + if (ARG_COUNT(ht)!=1 || getParametersEx(1, &mssql_result_index)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(result, mssql_result *, mssql_result_index, -1, "MS SQL-result", MS_SQL_G(le_result)); + + if (result->cur_row >= result->num_rows) { + RETURN_FALSE; + } + + array_init(return_value); + for (i=0; i<result->num_fields; i++) { + MAKE_STD_ZVAL(field_content); + *field_content = result->data[result->cur_row][i]; + pval_copy_constructor(field_content); + zend_hash_index_update(return_value->value.ht, i, (void *) &field_content, sizeof(pval), NULL); + } + result->cur_row++; +} + +static void php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS) +{ + pval **mssql_result_index; + mssql_result *result; + int i; + pval *pvalue_ptr,tmp; + MSSQLLS_FETCH(); + PLS_FETCH(); + + + if (ARG_COUNT(ht)!=1 || getParametersEx(1, &mssql_result_index)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(result, mssql_result *, mssql_result_index, -1, "MS SQL-result", MS_SQL_G(le_result)); + + if (result->cur_row >= result->num_rows) { + RETURN_FALSE; + } + + if (array_init(return_value)==FAILURE) { + RETURN_FALSE; + } + + for (i=0; i<result->num_fields; i++) { + tmp = result->data[result->cur_row][i]; + pval_copy_constructor(&tmp); + if (PG(magic_quotes_runtime) && tmp.type == IS_STRING) { + tmp.value.str.val = _php3_addslashes(tmp.value.str.val,tmp.value.str.len,&tmp.value.str.len,1); + } + zend_hash_index_update(return_value->value.ht, i, (void *) &tmp, sizeof(pval), (void **) &pvalue_ptr); + zend_hash_pointer_update(return_value->value.ht, result->fields[i].name, strlen(result->fields[i].name)+1, pvalue_ptr); + } + result->cur_row++; +} + +PHP_FUNCTION(mssql_fetch_object) +{ + php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (return_value->type==IS_ARRAY) { + return_value->type=IS_OBJECT; + } +} + +PHP_FUNCTION(mssql_fetch_array) +{ + php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +PHP_FUNCTION(mssql_data_seek) +{ + pval *mssql_result_index, *offset; + int type,id; + mssql_result *result; + MSSQLLS_FETCH(); + + + if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &mssql_result_index, &offset)==FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long(mssql_result_index); + id = mssql_result_index->value.lval; + + result = (mssql_result *) zend_list_find(id,&type); + if (type!=MS_SQL_G(le_result)) { + php_error(E_WARNING,"%d is not a MS SQL result index",id); + RETURN_FALSE; + } + + convert_to_long(offset); + if (offset->value.lval<0 || offset->value.lval>=result->num_rows) { + php_error(E_WARNING,"MS SQL: Bad row offset"); + RETURN_FALSE; + } + + result->cur_row = offset->value.lval; + RETURN_TRUE; +} + +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 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; + default: + return "unknown"; + break; + } +} + +PHP_FUNCTION(mssql_fetch_field) +{ + pval *mssql_result_index,*offset; + int type,id,field_offset; + mssql_result *result; + MSSQLLS_FETCH(); + + + switch (ARG_COUNT(ht)) { + case 1: + if (getParameters(ht, 1, &mssql_result_index)==FAILURE) { + RETURN_FALSE; + } + field_offset=-1; + break; + case 2: + if (getParameters(ht, 2, &mssql_result_index, &offset)==FAILURE) { + RETURN_FALSE; + } + convert_to_long(offset); + field_offset = offset->value.lval; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + convert_to_long(mssql_result_index); + id = mssql_result_index->value.lval; + + result = (mssql_result *) zend_list_find(id,&type); + if (type!=MS_SQL_G(le_result)) { + php_error(E_WARNING,"%d is not a MS SQL result index",id); + RETURN_FALSE; + } + + if (field_offset==-1) { + field_offset = result->cur_field; + result->cur_field++; + } + + if (field_offset<0 || field_offset >= result->num_fields) { + if (ARG_COUNT(ht)==2) { /* field specified explicitly */ + php_error(E_WARNING,"MS SQL: Bad column offset"); + } + RETURN_FALSE; + } + + if (object_init(return_value)==FAILURE) { + RETURN_FALSE; + } + 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(result->fields[field_offset].type), 1); +} + +PHP_FUNCTION(mssql_field_length) +{ + pval *mssql_result_index,*offset; + int type,id,field_offset; + mssql_result *result; + MSSQLLS_FETCH(); + + + switch (ARG_COUNT(ht)) { + case 1: + if (getParameters(ht, 1, &mssql_result_index)==FAILURE) { + RETURN_FALSE; + } + field_offset=-1; + break; + case 2: + if (getParameters(ht, 2, &mssql_result_index, &offset)==FAILURE) { + RETURN_FALSE; + } + convert_to_long(offset); + field_offset = offset->value.lval; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + convert_to_long(mssql_result_index); + id = mssql_result_index->value.lval; + + result = (mssql_result *) zend_list_find(id,&type); + if (type!=MS_SQL_G(le_result)) { + php_error(E_WARNING,"%d is not a MS SQL result index",id); + RETURN_FALSE; + } + + if (field_offset==-1) { + field_offset = result->cur_field; + result->cur_field++; + } + + if (field_offset<0 || field_offset >= result->num_fields) { + if (ARG_COUNT(ht)==2) { /* field specified explicitly */ + php_error(E_WARNING,"MS SQL: Bad column offset"); + } + RETURN_FALSE; + } + + return_value->value.lval = result->fields[field_offset].max_length; + return_value->type = IS_LONG; +} + +PHP_FUNCTION(mssql_field_name) +{ + pval *mssql_result_index,*offset; + int type,id,field_offset; + mssql_result *result; + MSSQLLS_FETCH(); + + + switch (ARG_COUNT(ht)) { + case 1: + if (getParameters(ht, 1, &mssql_result_index)==FAILURE) { + RETURN_FALSE; + } + field_offset=-1; + break; + case 2: + if (getParameters(ht, 2, &mssql_result_index, &offset)==FAILURE) { + RETURN_FALSE; + } + convert_to_long(offset); + field_offset = offset->value.lval; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + convert_to_long(mssql_result_index); + id = mssql_result_index->value.lval; + + result = (mssql_result *) zend_list_find(id,&type); + if (type!=MS_SQL_G(le_result)) { + php_error(E_WARNING,"%d is not a MS SQL result index",id); + RETURN_FALSE; + } + + if (field_offset==-1) { + field_offset = result->cur_field; + result->cur_field++; + } + + if (field_offset<0 || field_offset >= result->num_fields) { + if (ARG_COUNT(ht)==2) { /* field specified explicitly */ + php_error(E_WARNING,"MS SQL: Bad column offset"); + } + RETURN_FALSE; + } + + return_value->value.str.val = estrdup(result->fields[field_offset].name); + return_value->value.str.len = strlen(result->fields[field_offset].name); + return_value->type = IS_STRING; +} + +PHP_FUNCTION(mssql_field_type) +{ + pval *mssql_result_index,*offset; + int type,id,field_offset; + mssql_result *result; + MSSQLLS_FETCH(); + + + switch (ARG_COUNT(ht)) { + case 1: + if (getParameters(ht, 1, &mssql_result_index)==FAILURE) { + RETURN_FALSE; + } + field_offset=-1; + break; + case 2: + if (getParameters(ht, 2, &mssql_result_index, &offset)==FAILURE) { + RETURN_FALSE; + } + convert_to_long(offset); + field_offset = offset->value.lval; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + convert_to_long(mssql_result_index); + id = mssql_result_index->value.lval; + + result = (mssql_result *) zend_list_find(id,&type); + if (type!=MS_SQL_G(le_result)) { + php_error(E_WARNING,"%d is not a MS SQL result index",id); + RETURN_FALSE; + } + + if (field_offset==-1) { + field_offset = result->cur_field; + result->cur_field++; + } + + if (field_offset<0 || field_offset >= result->num_fields) { + if (ARG_COUNT(ht)==2) { /* field specified explicitly */ + php_error(E_WARNING,"MS SQL: Bad column offset"); + } + RETURN_FALSE; + } + + return_value->value.str.val = estrdup(php_mssql_get_field_name(result->fields[field_offset].type)); + return_value->value.str.len = strlen(php_mssql_get_field_name(result->fields[field_offset].type)); + return_value->type = IS_STRING; +} + +PHP_FUNCTION(mssql_field_seek) +{ + pval *mssql_result_index,*offset; + int type,id,field_offset; + mssql_result *result; + MSSQLLS_FETCH(); + + + if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &mssql_result_index, &offset)==FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long(mssql_result_index); + id = mssql_result_index->value.lval; + + result = (mssql_result *) zend_list_find(id,&type); + if (type!=MS_SQL_G(le_result)) { + php_error(E_WARNING,"%d is not a MS SQL result index",id); + RETURN_FALSE; + } + + convert_to_long(offset); + field_offset = offset->value.lval; + + if (field_offset<0 || field_offset >= result->num_fields) { + php_error(E_WARNING,"MS SQL: Bad column offset"); + RETURN_FALSE; + } + + result->cur_field = field_offset; + RETURN_TRUE; +} + +PHP_FUNCTION(mssql_result) +{ + pval *row, *field, *mssql_result_index; + int id,type,field_offset=0; + mssql_result *result; + MSSQLLS_FETCH(); + + + if (ARG_COUNT(ht)!=3 || getParameters(ht, 3, &mssql_result_index, &row, &field)==FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long(mssql_result_index); + id = mssql_result_index->value.lval; + + result = (mssql_result *) zend_list_find(id,&type); + if (type!=MS_SQL_G(le_result)) { + php_error(E_WARNING,"%d is not a MS SQL result index",id); + RETURN_FALSE; + } + + convert_to_long(row); + if (row->value.lval<0 || row->value.lval>=result->num_rows) { + php_error(E_WARNING,"MS SQL: Bad row offset (%d)",row->value.lval); + RETURN_FALSE; + } + + switch(field->type) { + case IS_STRING: { + int i; + + for (i=0; i<result->num_fields; i++) { + if (!strcasecmp(result->fields[i].name,field->value.str.val)) { + field_offset = i; + break; + } + } + if (i>=result->num_fields) { /* no match found */ + php_error(E_WARNING,"MS SQL: %s field not found in result",field->value.str.val); + RETURN_FALSE; + } + break; + } + default: + convert_to_long(field); + field_offset = field->value.lval; + if (field_offset<0 || field_offset>=result->num_fields) { + php_error(E_WARNING,"MS SQL: Bad column offset specified"); + RETURN_FALSE; + } + break; + } + + *return_value = result->data[row->value.lval][field_offset]; + pval_copy_constructor(return_value); +} + +PHP_FUNCTION(mssql_min_error_severity) +{ + pval *severity; + MSSQLLS_FETCH(); + + + if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &severity)==FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(severity); + MS_SQL_G(min_error_severity) = severity->value.lval; +} + +PHP_FUNCTION(mssql_min_message_severity) +{ + pval *severity; + MSSQLLS_FETCH(); + + + if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &severity)==FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(severity); + MS_SQL_G(min_message_severity) = severity->value.lval; +} +/* }}} */ + + +#endif diff --git a/ext/mssql/php_mssql.h b/ext/mssql/php_mssql.h new file mode 100644 index 0000000000..a292745adc --- /dev/null +++ b/ext/mssql/php_mssql.h @@ -0,0 +1,150 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_0.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. | + +----------------------------------------------------------------------+ + | Authors: Frank M. Kromann <fmk@swwwing.com> | + +----------------------------------------------------------------------+ + */ + + +/* $Id$ */ + +#ifndef _PHP_MSSQL_H +#define _PHP_MSSQL_H + + +#if HAVE_MSSQL +#include "sqlfront.h" +#include "sqldb.h" + +#if MSSQL65 +#define MSSQL_VERSION "6.5" +#elif MSSQL70 +#define MSSQL_VERSION "7.0" +#else +#define MSSQL_VERSION "Unknown" +#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 floatcol(i) ((float) *(DBFLT8 *) dbdata(mssql_ptr->link,i)) + +#ifndef DLEXPORT +#define DLEXPORT +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +extern zend_module_entry mssql_module_entry; +#define mssql_module_ptr &mssql_module_entry + +extern PHP_MINIT_FUNCTION(mssql); +extern PHP_MSHUTDOWN_FUNCTION(mssql); +extern PHP_RINIT_FUNCTION(mssql); +extern 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_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_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_min_error_severity); +PHP_FUNCTION(mssql_min_message_severity); + +typedef struct mssql_link { + LOGINREC *login; + DBPROCESS *link; + int valid; +} mssql_link; + +typedef struct { + long default_link; + long num_links,num_persistent; + long max_links,max_persistent; + long allow_persistent; + char *appname; + char *server_message; + int le_link,le_plink,le_result; + long min_error_severity, min_message_severity; + long cfg_min_error_severity, cfg_min_message_severity; + long compatability_mode, connect_timeout; + void (*get_column_content)(mssql_link *mssql_ptr,int offset,pval *result,int column_type); + long textsize, textlimit; + HashTable *resource_list, *resource_plist; +} php_mssql_globals; + +#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 { + pval **data; + mssql_field *fields; + mssql_link *mssql_ptr; + int cur_row,cur_field; + int num_rows,num_fields; +} mssql_result; + + +#ifdef ZTS +# define MSSQLLS_D php_mssql_globals *mssql_globals +# define MSSQLLS_DC , MSSQLLS_D +# define MSSQLLS_C mssql_globals +# define MSSQLLS_CC , MSSQLLS_C +# define MS_SQL_G(v) (mssql_globals->v) +# define MSSQLLS_FETCH() php_mssql_globals *mssql_globals = ts_resource(mssql_globals_id) +#else +# define MSSQLLS_D +# define MSSQLLS_DC +# define MSSQLLS_C +# define MSSQLLS_CC +# define MS_SQL_G(v) (mssql_globals.v) +# define MSSQLLS_FETCH() +extern ZEND_API php_mssql_globals mssql_globals; +#endif + +#else + +#define mssql_module_ptr NULL + +#endif /* HAVE_MSSQL */ + +#define phpext_mssql_ptr mssql_module_ptr + +#endif /* _PHP_MSSQL_H */ |