Back to index

php5  5.3.10
php_mssql.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Frank M. Kromann <frank@kromann.info>                        |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: php_mssql.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #ifdef COMPILE_DL_MSSQL
00022 #define HAVE_MSSQL 1
00023 #endif
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #include "php.h"
00030 #include "php_globals.h"
00031 #include "ext/standard/php_standard.h"
00032 #include "ext/standard/info.h"
00033 #include "php_mssql.h"
00034 #include "php_ini.h"
00035 
00036 #if HAVE_MSSQL
00037 #define SAFE_STRING(s) ((s)?(s):"")
00038 
00039 #define MSSQL_ASSOC         1<<0
00040 #define MSSQL_NUM           1<<1
00041 #define MSSQL_BOTH          (MSSQL_ASSOC|MSSQL_NUM)
00042 
00043 static int le_result, le_link, le_plink, le_statement;
00044 
00045 static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC);
00046 static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC);
00047 
00048 static void _mssql_bind_hash_dtor(void *data);
00049 
00050 /* {{{ arginfo */
00051 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_connect, 0, 0, 0)
00052        ZEND_ARG_INFO(0, servername)
00053        ZEND_ARG_INFO(0, username)
00054        ZEND_ARG_INFO(0, password)
00055        ZEND_ARG_INFO(0, newlink)
00056 ZEND_END_ARG_INFO()
00057 
00058 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_close, 0, 0, 0)
00059        ZEND_ARG_INFO(0, link_identifier)
00060 ZEND_END_ARG_INFO()
00061 
00062 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_select_db, 0, 0, 1)
00063        ZEND_ARG_INFO(0, database_name)
00064        ZEND_ARG_INFO(0, link_identifier)
00065 ZEND_END_ARG_INFO()
00066 
00067 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_query, 0, 0, 1)
00068        ZEND_ARG_INFO(0, query)
00069        ZEND_ARG_INFO(0, link_identifier)
00070        ZEND_ARG_INFO(0, batch_size)
00071 ZEND_END_ARG_INFO()
00072 
00073 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_batch, 0, 0, 1)
00074        ZEND_ARG_INFO(0, result)
00075 ZEND_END_ARG_INFO()
00076 
00077 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_rows_affected, 0, 0, 1)
00078        ZEND_ARG_INFO(0, link_identifier)
00079 ZEND_END_ARG_INFO()
00080 
00081 ZEND_BEGIN_ARG_INFO(arginfo_mssql_get_last_message, 0)
00082 ZEND_END_ARG_INFO()
00083 
00084 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_field, 0, 0, 1)
00085        ZEND_ARG_INFO(0, result)
00086        ZEND_ARG_INFO(0, field_offset)
00087 ZEND_END_ARG_INFO()
00088 
00089 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_array, 0, 0, 1)
00090        ZEND_ARG_INFO(0, result)
00091        ZEND_ARG_INFO(0, result_type)
00092 ZEND_END_ARG_INFO()
00093 
00094 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_assoc, 0, 0, 1)
00095        ZEND_ARG_INFO(0, result_id)
00096 ZEND_END_ARG_INFO()
00097 
00098 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_field_length, 0, 0, 1)
00099        ZEND_ARG_INFO(0, result)
00100        ZEND_ARG_INFO(0, offset)
00101 ZEND_END_ARG_INFO()
00102 
00103 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_data_seek, 0, 0, 2)
00104        ZEND_ARG_INFO(0, result_identifier)
00105        ZEND_ARG_INFO(0, row_number)
00106 ZEND_END_ARG_INFO()
00107 
00108 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_result, 0, 0, 3)
00109        ZEND_ARG_INFO(0, result)
00110        ZEND_ARG_INFO(0, row)
00111        ZEND_ARG_INFO(0, field)
00112 ZEND_END_ARG_INFO()
00113 
00114 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_min_error_severity, 0, 0, 1)
00115        ZEND_ARG_INFO(0, severity)
00116 ZEND_END_ARG_INFO()
00117 
00118 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_init, 0, 0, 1)
00119        ZEND_ARG_INFO(0, sp_name)
00120        ZEND_ARG_INFO(0, link_identifier)
00121 ZEND_END_ARG_INFO()
00122 
00123 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_bind, 0, 0, 4)
00124        ZEND_ARG_INFO(0, stmt)
00125        ZEND_ARG_INFO(0, param_name)
00126        ZEND_ARG_INFO(1, var)
00127        ZEND_ARG_INFO(0, type)
00128        ZEND_ARG_INFO(0, is_output)
00129        ZEND_ARG_INFO(0, is_null)
00130        ZEND_ARG_INFO(0, maxlen)
00131 ZEND_END_ARG_INFO()
00132 
00133 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_execute, 0, 0, 1)
00134        ZEND_ARG_INFO(0, stmt)
00135        ZEND_ARG_INFO(0, skip_results)
00136 ZEND_END_ARG_INFO()
00137 
00138 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_free_statement, 0, 0, 1)
00139        ZEND_ARG_INFO(0, stmt)
00140 ZEND_END_ARG_INFO()
00141 
00142 ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_guid_string, 0, 0, 1)
00143        ZEND_ARG_INFO(0, binary)
00144        ZEND_ARG_INFO(0, short_format)
00145 ZEND_END_ARG_INFO()
00146 /* }}} */
00147 
00148 /* {{{ mssql_functions
00149 */
00150 const zend_function_entry mssql_functions[] = {
00151        PHP_FE(mssql_connect,                            arginfo_mssql_connect)
00152        PHP_FE(mssql_pconnect,                           arginfo_mssql_connect)
00153        PHP_FE(mssql_close,                              arginfo_mssql_close)
00154        PHP_FE(mssql_select_db,                          arginfo_mssql_select_db)
00155        PHP_FE(mssql_query,                              arginfo_mssql_query)
00156        PHP_FE(mssql_fetch_batch,                 arginfo_mssql_fetch_batch)
00157        PHP_FE(mssql_rows_affected,               arginfo_mssql_rows_affected)
00158        PHP_FE(mssql_free_result,                 arginfo_mssql_fetch_batch)
00159        PHP_FE(mssql_get_last_message,            arginfo_mssql_get_last_message)
00160        PHP_FE(mssql_num_rows,                           arginfo_mssql_fetch_batch)
00161        PHP_FE(mssql_num_fields,                  arginfo_mssql_fetch_batch)
00162        PHP_FE(mssql_fetch_field,                 arginfo_mssql_fetch_field)
00163        PHP_FE(mssql_fetch_row,                          arginfo_mssql_fetch_batch)
00164        PHP_FE(mssql_fetch_array,                 arginfo_mssql_fetch_array)
00165        PHP_FE(mssql_fetch_assoc,                 arginfo_mssql_fetch_assoc)
00166        PHP_FE(mssql_fetch_object,                arginfo_mssql_fetch_batch)
00167        PHP_FE(mssql_field_length,                arginfo_mssql_field_length)
00168        PHP_FE(mssql_field_name,                  arginfo_mssql_field_length)
00169        PHP_FE(mssql_field_type,                  arginfo_mssql_field_length)
00170        PHP_FE(mssql_data_seek,                          arginfo_mssql_data_seek)
00171        PHP_FE(mssql_field_seek,                  arginfo_mssql_fetch_field)
00172        PHP_FE(mssql_result,                      arginfo_mssql_result)
00173        PHP_FE(mssql_next_result,                 arginfo_mssql_fetch_assoc)
00174        PHP_FE(mssql_min_error_severity,   arginfo_mssql_min_error_severity)
00175        PHP_FE(mssql_min_message_severity, arginfo_mssql_min_error_severity)
00176        PHP_FE(mssql_init,                               arginfo_mssql_init)
00177        PHP_FE(mssql_bind,                               arginfo_mssql_bind)
00178        PHP_FE(mssql_execute,                            arginfo_mssql_execute)
00179        PHP_FE(mssql_free_statement,              arginfo_mssql_free_statement)
00180        PHP_FE(mssql_guid_string,                 arginfo_mssql_guid_string)
00181        PHP_FE_END
00182 };
00183 /* }}} */
00184 
00185 ZEND_DECLARE_MODULE_GLOBALS(mssql)
00186 static PHP_GINIT_FUNCTION(mssql);
00187 
00188 /* {{{ mssql_module_entry
00189 */
00190 zend_module_entry mssql_module_entry = 
00191 {
00192        STANDARD_MODULE_HEADER,
00193        "mssql", 
00194        mssql_functions, 
00195        PHP_MINIT(mssql), 
00196        PHP_MSHUTDOWN(mssql), 
00197        PHP_RINIT(mssql), 
00198        PHP_RSHUTDOWN(mssql), 
00199        PHP_MINFO(mssql), 
00200        NO_VERSION_YET,
00201        PHP_MODULE_GLOBALS(mssql),
00202        PHP_GINIT(mssql),
00203        NULL,
00204        NULL,
00205        STANDARD_MODULE_PROPERTIES_EX
00206 };
00207 /* }}} */
00208 
00209 #ifdef COMPILE_DL_MSSQL
00210 ZEND_GET_MODULE(mssql)
00211 #endif
00212 
00213 #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; } }
00214 
00215 /* {{{ PHP_INI_DISP
00216 */
00217 static PHP_INI_DISP(display_text_size)
00218 {
00219        char *value;
00220        TSRMLS_FETCH();
00221        
00222     if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
00223               value = ini_entry->orig_value;
00224        } else if (ini_entry->value) {
00225               value = ini_entry->value;
00226        } else {
00227               value = NULL;
00228        }
00229 
00230        if (atoi(value) == -1) {
00231               PUTS("Server default");
00232        } else {
00233               php_printf("%s", value);
00234        }
00235 }
00236 /* }}} */
00237 
00238 /* {{{ PHP_INI
00239 */
00240 PHP_INI_BEGIN()
00241        STD_PHP_INI_BOOLEAN("mssql.allow_persistent",           "1",   PHP_INI_SYSTEM,      OnUpdateBool, allow_persistent,                  zend_mssql_globals,         mssql_globals)
00242        STD_PHP_INI_ENTRY_EX("mssql.max_persistent",            "-1",  PHP_INI_SYSTEM,      OnUpdateLong, max_persistent,                           zend_mssql_globals,         mssql_globals,       display_link_numbers)
00243        STD_PHP_INI_ENTRY_EX("mssql.max_links",                        "-1",  PHP_INI_SYSTEM,      OnUpdateLong, max_links,                                zend_mssql_globals,         mssql_globals,       display_link_numbers)
00244        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)
00245        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)
00246        STD_PHP_INI_BOOLEAN("mssql.compatability_mode",         "0",   PHP_INI_ALL,  OnUpdateBool, compatability_mode,                zend_mssql_globals,         mssql_globals)
00247        STD_PHP_INI_ENTRY_EX("mssql.connect_timeout",           "5",   PHP_INI_ALL,  OnUpdateLong, connect_timeout,                   zend_mssql_globals,         mssql_globals,       display_link_numbers)
00248        STD_PHP_INI_ENTRY_EX("mssql.timeout",                          "60",  PHP_INI_ALL,  OnUpdateLong, timeout,                                  zend_mssql_globals,         mssql_globals,       display_link_numbers)
00249        STD_PHP_INI_ENTRY_EX("mssql.textsize",                  "-1",  PHP_INI_ALL,  OnUpdateLong, textsize,                                 zend_mssql_globals,         mssql_globals,       display_text_size)
00250        STD_PHP_INI_ENTRY_EX("mssql.textlimit",                        "-1",  PHP_INI_ALL,  OnUpdateLong, textlimit,                                zend_mssql_globals,         mssql_globals,       display_text_size)
00251        STD_PHP_INI_ENTRY_EX("mssql.batchsize",                        "0",   PHP_INI_ALL,  OnUpdateLong, batchsize,                                zend_mssql_globals,         mssql_globals,       display_link_numbers)
00252        STD_PHP_INI_BOOLEAN("mssql.datetimeconvert",            "1",   PHP_INI_ALL,  OnUpdateBool, datetimeconvert,                   zend_mssql_globals,         mssql_globals)
00253        STD_PHP_INI_BOOLEAN("mssql.secure_connection",          "0",   PHP_INI_SYSTEM, OnUpdateBool,      secure_connection,                 zend_mssql_globals,         mssql_globals)
00254        STD_PHP_INI_ENTRY_EX("mssql.max_procs",                        "-1",  PHP_INI_ALL,  OnUpdateLong, max_procs,                                zend_mssql_globals,         mssql_globals,       display_link_numbers)
00255 #ifdef HAVE_FREETDS
00256        STD_PHP_INI_ENTRY("mssql.charset",                             "",           PHP_INI_ALL,  OnUpdateString,      charset,                                  zend_mssql_globals,         mssql_globals)
00257 #endif
00258 PHP_INI_END()
00259 /* }}} */
00260 
00261 /* error handler */
00262 static int php_mssql_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
00263 {
00264        TSRMLS_FETCH();
00265 
00266        if (severity >= MS_SQL_G(min_error_severity)) {
00267               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (severity %d)", dberrstr, severity);
00268        }
00269        return INT_CANCEL;  
00270 }
00271 
00272 /* {{{ php_mssql_message_handler
00273 */
00274 /* message handler */
00275 static int php_mssql_message_handler(DBPROCESS *dbproc, DBINT msgno,int msgstate, int severity,char *msgtext,char *srvname, char *procname,DBUSMALLINT line)
00276 {
00277        TSRMLS_FETCH();
00278 
00279        if (severity >= MS_SQL_G(min_message_severity)) {
00280               php_error_docref(NULL TSRMLS_CC, E_WARNING, "message: %s (severity %d)", msgtext, severity);
00281        }
00282        if (MS_SQL_G(server_message)) {
00283               STR_FREE(MS_SQL_G(server_message));
00284               MS_SQL_G(server_message) = NULL;
00285        }
00286        MS_SQL_G(server_message) = estrdup(msgtext);
00287        return 0;
00288 }
00289 /* }}} */
00290 
00291 /* {{{ _clean_invalid_results
00292 */
00293 static int _clean_invalid_results(zend_rsrc_list_entry *le TSRMLS_DC)
00294 {
00295        if (Z_TYPE_P(le) == le_result) {
00296               mssql_link *mssql_ptr = ((mssql_result *) le->ptr)->mssql_ptr;
00297               
00298               if (!mssql_ptr->valid) {
00299                      return 1;
00300               }
00301        }
00302        return 0;
00303 }
00304 /* }}} */
00305 
00306 /* {{{ _free_result
00307 */
00308 static void _free_result(mssql_result *result, int free_fields) 
00309 {
00310        int i,j;
00311 
00312        if (result->data) {
00313               for (i=0; i<result->num_rows; i++) {
00314                      if (result->data[i]) {
00315                             for (j=0; j<result->num_fields; j++) {
00316                                    zval_dtor(&result->data[i][j]);
00317                             }
00318                             efree(result->data[i]);
00319                      }
00320               }
00321               efree(result->data);
00322               result->data = NULL;
00323               result->blocks_initialized = 0;
00324        }
00325        
00326        if (free_fields && result->fields) {
00327               for (i=0; i<result->num_fields; i++) {
00328                      STR_FREE(result->fields[i].name);
00329                      STR_FREE(result->fields[i].column_source);
00330               }
00331               efree(result->fields);
00332        }
00333 }
00334 /* }}} */
00335 
00336 /* {{{ _free_mssql_statement
00337 */
00338 static void _free_mssql_statement(zend_rsrc_list_entry *rsrc TSRMLS_DC)
00339 {
00340        mssql_statement *statement = (mssql_statement *)rsrc->ptr;
00341 
00342        if (statement->binds) {
00343               zend_hash_destroy(statement->binds);
00344               efree(statement->binds);
00345        }
00346        
00347        efree(statement);
00348 }
00349 /* }}} */
00350 
00351 /* {{{ _free_mssql_result
00352 */
00353 static void _free_mssql_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
00354 {
00355        mssql_result *result = (mssql_result *)rsrc->ptr;
00356 
00357        _free_result(result, 1);
00358        dbcancel(result->mssql_ptr->link);
00359        efree(result);
00360 }
00361 /* }}} */
00362 
00363 /* {{{ php_mssql_set_defaullt_link
00364 */
00365 static void php_mssql_set_default_link(int id TSRMLS_DC)
00366 {
00367        if (MS_SQL_G(default_link)!=-1) {
00368               zend_list_delete(MS_SQL_G(default_link));
00369        }
00370        MS_SQL_G(default_link) = id;
00371        zend_list_addref(id);
00372 }
00373 /* }}} */
00374 
00375 /* {{{ _close_mssql_link
00376 */
00377 static void _close_mssql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
00378 {
00379        mssql_link *mssql_ptr = (mssql_link *)rsrc->ptr;
00380 
00381        mssql_ptr->valid = 0;
00382        zend_hash_apply(&EG(regular_list),(apply_func_t) _clean_invalid_results TSRMLS_CC);
00383        dbclose(mssql_ptr->link);
00384        dbfreelogin(mssql_ptr->login);
00385        efree(mssql_ptr);
00386        MS_SQL_G(num_links)--;
00387 }
00388 /* }}} */
00389 
00390 /* {{{ _close_mssql_plink
00391 */
00392 static void _close_mssql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
00393 {
00394        mssql_link *mssql_ptr = (mssql_link *)rsrc->ptr;
00395 
00396        dbclose(mssql_ptr->link);
00397        dbfreelogin(mssql_ptr->login);
00398        free(mssql_ptr);
00399        MS_SQL_G(num_persistent)--;
00400        MS_SQL_G(num_links)--;
00401 }
00402 /* }}} */
00403 
00404 /* {{{ _mssql_bind_hash_dtor
00405 */
00406 static void _mssql_bind_hash_dtor(void *data)
00407 {
00408        mssql_bind *bind= (mssql_bind *) data;
00409 
00410        zval_ptr_dtor(&(bind->zval));
00411 }
00412 /* }}} */
00413 
00414 /* {{{ PHP_GINIT_FUNCTION
00415 */
00416 static PHP_GINIT_FUNCTION(mssql)
00417 {
00418        long compatability_mode;
00419 
00420        mssql_globals->num_persistent = 0;
00421        mssql_globals->get_column_content = php_mssql_get_column_content_with_type;
00422        if (cfg_get_long("mssql.compatability_mode", &compatability_mode) == SUCCESS) {
00423               if (compatability_mode) {
00424                      mssql_globals->get_column_content = php_mssql_get_column_content_without_type;      
00425               }
00426        }
00427 }
00428 /* }}} */
00429 
00430 /* {{{ PHP_MINIT_FUNCTION
00431 */
00432 PHP_MINIT_FUNCTION(mssql)
00433 {
00434        REGISTER_INI_ENTRIES();
00435 
00436        le_statement = zend_register_list_destructors_ex(_free_mssql_statement, NULL, "mssql statement", module_number);
00437        le_result = zend_register_list_destructors_ex(_free_mssql_result, NULL, "mssql result", module_number);
00438        le_link = zend_register_list_destructors_ex(_close_mssql_link, NULL, "mssql link", module_number);
00439        le_plink = zend_register_list_destructors_ex(NULL, _close_mssql_plink, "mssql link persistent", module_number);
00440        Z_TYPE(mssql_module_entry) = type;
00441 
00442        if (dbinit()==FAIL) {
00443               return FAILURE;
00444        }
00445 
00446        /* BEGIN MSSQL data types for mssql_bind */
00447        REGISTER_LONG_CONSTANT("MSSQL_ASSOC", MSSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
00448        REGISTER_LONG_CONSTANT("MSSQL_NUM", MSSQL_NUM, CONST_CS | CONST_PERSISTENT);
00449        REGISTER_LONG_CONSTANT("MSSQL_BOTH", MSSQL_BOTH, CONST_CS | CONST_PERSISTENT);
00450 
00451        REGISTER_LONG_CONSTANT("SQLTEXT",SQLTEXT, CONST_CS | CONST_PERSISTENT);
00452        REGISTER_LONG_CONSTANT("SQLVARCHAR",SQLVARCHAR, CONST_CS | CONST_PERSISTENT);
00453        REGISTER_LONG_CONSTANT("SQLCHAR",SQLCHAR, CONST_CS | CONST_PERSISTENT);
00454        REGISTER_LONG_CONSTANT("SQLINT1",SQLINT1, CONST_CS | CONST_PERSISTENT);
00455        REGISTER_LONG_CONSTANT("SQLINT2",SQLINT2, CONST_CS | CONST_PERSISTENT);
00456        REGISTER_LONG_CONSTANT("SQLINT4",SQLINT4, CONST_CS | CONST_PERSISTENT);
00457        REGISTER_LONG_CONSTANT("SQLBIT",SQLBIT, CONST_CS | CONST_PERSISTENT);
00458        REGISTER_LONG_CONSTANT("SQLFLT4",SQLFLT4, CONST_CS | CONST_PERSISTENT);
00459        REGISTER_LONG_CONSTANT("SQLFLT8",SQLFLT8, CONST_CS | CONST_PERSISTENT);
00460        REGISTER_LONG_CONSTANT("SQLFLTN",SQLFLTN, CONST_CS | CONST_PERSISTENT);
00461        /* END MSSQL data types for mssql_bind */
00462 
00463        return SUCCESS;
00464 }
00465 /* }}} */
00466 
00467 /* {{{ PHP_MSHUTDOWN_FUNCTION
00468 */
00469 PHP_MSHUTDOWN_FUNCTION(mssql)
00470 {
00471        UNREGISTER_INI_ENTRIES();
00472 #ifndef HAVE_FREETDS
00473        dbwinexit();
00474 #else
00475        dbexit();
00476 #endif
00477        return SUCCESS;
00478 }
00479 /* }}} */
00480 
00481 /* {{{ PHP_RINIT_FUNCTION
00482 */
00483 PHP_RINIT_FUNCTION(mssql)
00484 {
00485        MS_SQL_G(default_link) = -1;
00486        MS_SQL_G(num_links) = MS_SQL_G(num_persistent);
00487        MS_SQL_G(appname) = estrndup("PHP 5", 5);
00488        MS_SQL_G(server_message) = NULL;
00489        MS_SQL_G(min_error_severity) = MS_SQL_G(cfg_min_error_severity);
00490        MS_SQL_G(min_message_severity) = MS_SQL_G(cfg_min_message_severity);
00491        if (MS_SQL_G(connect_timeout) < 1) MS_SQL_G(connect_timeout) = 1;
00492        if (MS_SQL_G(timeout) < 0) MS_SQL_G(timeout) = 60;
00493        if (MS_SQL_G(max_procs) != -1) {
00494               dbsetmaxprocs((TDS_SHORT)MS_SQL_G(max_procs));
00495        }
00496 
00497        return SUCCESS;
00498 }
00499 /* }}} */
00500 
00501 /* {{{ PHP_RSHUTDOWN_FUNCTION
00502 */
00503 PHP_RSHUTDOWN_FUNCTION(mssql)
00504 {
00505        STR_FREE(MS_SQL_G(appname));
00506        MS_SQL_G(appname) = NULL;
00507        if (MS_SQL_G(server_message)) {
00508               STR_FREE(MS_SQL_G(server_message));
00509               MS_SQL_G(server_message) = NULL;
00510        }
00511        return SUCCESS;
00512 }
00513 /* }}} */
00514 
00515 /* {{{ PHP_MINFO_FUNCTION
00516 */
00517 PHP_MINFO_FUNCTION(mssql)
00518 {
00519        char buf[32];
00520 
00521        php_info_print_table_start();
00522        php_info_print_table_header(2, "MSSQL Support", "enabled");
00523 
00524        snprintf(buf, sizeof(buf), "%ld", MS_SQL_G(num_persistent));
00525        php_info_print_table_row(2, "Active Persistent Links", buf);
00526        snprintf(buf, sizeof(buf), "%ld", MS_SQL_G(num_links));
00527        php_info_print_table_row(2, "Active Links", buf);
00528 
00529        php_info_print_table_row(2, "Library version", MSSQL_VERSION);
00530        php_info_print_table_end();
00531 
00532        DISPLAY_INI_ENTRIES();
00533 
00534 }
00535 /* }}} */
00536 
00537 /* {{{ php_mssql_do_connect
00538 */
00539 static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
00540 {
00541        char *host = NULL, *user = NULL, *passwd = NULL;
00542        int host_len = 0, user_len = 0, passwd_len = 0;
00543        zend_bool new_link = 0;
00544        char *hashed_details;
00545        int hashed_details_length;
00546        mssql_link mssql, *mssql_ptr;
00547        char buffer[40];
00548 
00549        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sssb", &host, &host_len, &user, &user_len, &passwd, &passwd_len, &new_link) == FAILURE) {
00550               return;
00551        }
00552 
00553        /* Limit strings to 255 chars to prevent overflow issues in underlying libraries */
00554        if(host_len>255) {
00555               host[255] = '\0';
00556        }
00557        if(user_len>255) {
00558               user[255] = '\0';
00559        }
00560        if(passwd_len>255) {
00561               passwd[255] = '\0';
00562        }
00563 
00564        switch(ZEND_NUM_ARGS())
00565        {
00566               case 0:
00567                      /* defaults */
00568                      hashed_details_length=5+3;
00569                      hashed_details = (char *) emalloc(hashed_details_length+1);
00570                      strcpy(hashed_details, "mssql___");
00571                      break;
00572               case 1:
00573                      hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s__", host);
00574                      break;
00575               case 2:
00576                      hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s_%s_", host, user);
00577                      break;
00578               case 3:
00579               case 4:
00580                      hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s_%s_%s", host, user, passwd);
00581                      break;
00582        }
00583 
00584        if (hashed_details == NULL) {
00585               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Out of memory");
00586               RETURN_FALSE;
00587        }
00588 
00589        dbsetlogintime(MS_SQL_G(connect_timeout));
00590        dbsettime(MS_SQL_G(timeout));
00591 
00592        /* set a DBLOGIN record */  
00593        if ((mssql.login = dblogin()) == NULL) {
00594               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate login record");
00595               RETURN_FALSE;
00596        }
00597        
00598        DBERRHANDLE(mssql.login, (EHANDLEFUNC) php_mssql_error_handler);
00599        DBMSGHANDLE(mssql.login, (MHANDLEFUNC) php_mssql_message_handler);
00600 
00601 #ifndef HAVE_FREETDS
00602        if (MS_SQL_G(secure_connection)){
00603               DBSETLSECURE(mssql.login);
00604        }
00605        else {
00606 #endif
00607               if (user) {
00608                      DBSETLUSER(mssql.login,user);
00609               }
00610               if (passwd) {
00611                      DBSETLPWD(mssql.login,passwd);
00612               }
00613 #ifndef HAVE_FREETDS
00614        }
00615 #endif
00616 
00617 #ifdef HAVE_FREETDS
00618               if (MS_SQL_G(charset) && strlen(MS_SQL_G(charset))) {
00619                      DBSETLCHARSET(mssql.login, MS_SQL_G(charset));
00620               }
00621 #endif
00622 
00623        DBSETLAPP(mssql.login,MS_SQL_G(appname));
00624        mssql.valid = 1;
00625 
00626 #ifndef HAVE_FREETDS
00627        DBSETLVERSION(mssql.login, DBVER60);
00628 #endif
00629 /*     DBSETLTIME(mssql.login, TIMEOUT_INFINITE); */
00630 
00631        if (!MS_SQL_G(allow_persistent)) {
00632               persistent=0;
00633        }
00634        if (persistent) {
00635               zend_rsrc_list_entry *le;
00636 
00637               /* try to find if we already have this link in our persistent list */
00638               if (new_link || zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length + 1, (void **) &le)==FAILURE) {  /* we don't */
00639                      zend_rsrc_list_entry new_le;
00640 
00641                      if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) {
00642                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links));
00643                             efree(hashed_details);
00644                             dbfreelogin(mssql.login);
00645                             RETURN_FALSE;
00646                      }
00647                      if (MS_SQL_G(max_persistent) != -1 && MS_SQL_G(num_persistent) >= MS_SQL_G(max_persistent)) {
00648                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)", MS_SQL_G(num_persistent));
00649                             efree(hashed_details);
00650                             dbfreelogin(mssql.login);
00651                             RETURN_FALSE;
00652                      }
00653                      /* create the link */
00654                      if ((mssql.link = dbopen(mssql.login, host)) == FAIL) {
00655                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", (host == NULL ? "" : host));
00656                             efree(hashed_details);
00657                             dbfreelogin(mssql.login);
00658                             RETURN_FALSE;
00659                      }
00660 
00661                      if (DBSETOPT(mssql.link, DBBUFFER, "2")==FAIL) {
00662                             efree(hashed_details);
00663                             dbfreelogin(mssql.login);
00664                             dbclose(mssql.link);
00665                             RETURN_FALSE;
00666                      }
00667 
00668 #ifndef HAVE_FREETDS
00669                      if (MS_SQL_G(textlimit) != -1) {
00670                             snprintf(buffer, sizeof(buffer), "%li", MS_SQL_G(textlimit));
00671                             if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) {
00672                                    efree(hashed_details);
00673                                    dbfreelogin(mssql.login);
00674                                    dbclose(mssql.link);
00675                                    RETURN_FALSE;
00676                             }
00677                      }
00678 #endif
00679                      if (MS_SQL_G(textsize) != -1) {
00680                             snprintf(buffer, sizeof(buffer), "SET TEXTSIZE %li", MS_SQL_G(textsize));
00681                             dbcmd(mssql.link, buffer);
00682                             dbsqlexec(mssql.link);
00683                             dbresults(mssql.link);
00684                      }
00685 
00686                      /* hash it up */
00687                      mssql_ptr = (mssql_link *) malloc(sizeof(mssql_link));
00688                      if (!mssql_ptr) {
00689                             efree(hashed_details);
00690                             dbfreelogin(mssql.login);
00691                             dbclose(mssql.link);
00692                             RETURN_FALSE;
00693                      }
00694 
00695                      memcpy(mssql_ptr, &mssql, sizeof(mssql_link));
00696                      Z_TYPE(new_le) = le_plink;
00697                      new_le.ptr = mssql_ptr;
00698                      if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length + 1, &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
00699                             free(mssql_ptr);
00700                             efree(hashed_details);
00701                             dbfreelogin(mssql.login);
00702                             dbclose(mssql.link);
00703                             RETURN_FALSE;
00704                      }
00705                      MS_SQL_G(num_persistent)++;
00706                      MS_SQL_G(num_links)++;
00707               } else {  /* we do */
00708                      if (Z_TYPE_P(le) != le_plink) {
00709 #if BROKEN_MSSQL_PCONNECTS
00710                             log_error("PHP/MS SQL: Hashed persistent link is not a MS SQL link!",php_rqst->server);
00711 #endif
00712                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Hashed persistent link is not a MS SQL link!");
00713                             efree(hashed_details);
00714                             RETURN_FALSE;
00715                      }
00716                      
00717                      mssql_ptr = (mssql_link *) le->ptr;
00718                      /* test that the link hasn't died */
00719                      if (DBDEAD(mssql_ptr->link) == TRUE) {
00720                             dbclose(mssql_ptr->link);
00721 #if BROKEN_MSSQL_PCONNECTS
00722                             log_error("PHP/MS SQL: Persistent link died, trying to reconnect...",php_rqst->server);
00723 #endif
00724                             if ((mssql_ptr->link=dbopen(mssql_ptr->login,host))==NULL) {
00725 #if BROKEN_MSSQL_PCONNECTS
00726                                    log_error("PHP/MS SQL: Unable to reconnect!",php_rqst->server);
00727 #endif
00728                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
00729                                    zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1);
00730                                    efree(hashed_details);
00731                                    dbfreelogin(mssql_ptr->login);
00732                                    RETURN_FALSE;
00733                             }
00734 #if BROKEN_MSSQL_PCONNECTS
00735                             log_error("PHP/MS SQL: Reconnect successful!",php_rqst->server);
00736 #endif
00737                             if (DBSETOPT(mssql_ptr->link, DBBUFFER, "2")==FAIL) {
00738 #if BROKEN_MSSQL_PCONNECTS
00739                                    log_error("PHP/MS SQL: Unable to set required options",php_rqst->server);
00740 #endif
00741                                    zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length + 1);
00742                                    efree(hashed_details);
00743                                    dbfreelogin(mssql_ptr->login);
00744                                    dbclose(mssql_ptr->link);
00745                                    RETURN_FALSE;
00746                             }
00747                      }
00748               }
00749               ZEND_REGISTER_RESOURCE(return_value, mssql_ptr, le_plink);
00750        } else { /* non persistent */
00751               zend_rsrc_list_entry *index_ptr, new_index_ptr;
00752               
00753               /* first we check the hash for the hashed_details key.  if it exists,
00754                * it should point us to the right offset where the actual mssql link sits.
00755                * if it doesn't, open a new mssql link, add it to the resource list,
00756                * and add a pointer to it with hashed_details as the key.
00757                */
00758               if (!new_link && zend_hash_find(&EG(regular_list), hashed_details, hashed_details_length + 1,(void **) &index_ptr)==SUCCESS) {
00759                      int type,link;
00760                      void *ptr;
00761 
00762                      if (Z_TYPE_P(index_ptr) != le_index_ptr) {
00763                             efree(hashed_details);
00764                             dbfreelogin(mssql.login);
00765                             RETURN_FALSE;
00766                      }
00767                      link = (int) index_ptr->ptr;
00768                      ptr = zend_list_find(link,&type);   /* check if the link is still there */
00769                      if (ptr && (type==le_link || type==le_plink)) {
00770                             zend_list_addref(link);
00771                             Z_LVAL_P(return_value) = link;
00772                             php_mssql_set_default_link(link TSRMLS_CC);
00773                             Z_TYPE_P(return_value) = IS_RESOURCE;
00774                             dbfreelogin(mssql.login);
00775                             efree(hashed_details);
00776                             return;
00777                      } else {
00778                             zend_hash_del(&EG(regular_list), hashed_details, hashed_details_length + 1);
00779                      }
00780               }
00781               if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) {
00782                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links));
00783                      efree(hashed_details);
00784                      dbfreelogin(mssql.login);
00785                      RETURN_FALSE;
00786               }
00787               
00788               if ((mssql.link=dbopen(mssql.login, host))==NULL) {
00789                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", (host == NULL ? "" : host));
00790                      efree(hashed_details);
00791                      dbfreelogin(mssql.login);
00792                      RETURN_FALSE;
00793               }
00794 
00795               if (DBSETOPT(mssql.link, DBBUFFER,"2")==FAIL) {
00796                      efree(hashed_details);
00797                      dbfreelogin(mssql.login);
00798                      dbclose(mssql.link);
00799                      RETURN_FALSE;
00800               }
00801 
00802 #ifndef HAVE_FREETDS
00803               if (MS_SQL_G(textlimit) != -1) {
00804                      snprintf(buffer, sizeof(buffer), "%li", MS_SQL_G(textlimit));
00805                      if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) {
00806                             efree(hashed_details);
00807                             dbfreelogin(mssql.login);
00808                             dbclose(mssql.link);
00809                             RETURN_FALSE;
00810                      }
00811               }
00812 #endif
00813               if (MS_SQL_G(textsize) != -1) {
00814                      snprintf(buffer, sizeof(buffer), "SET TEXTSIZE %li", MS_SQL_G(textsize));
00815                      dbcmd(mssql.link, buffer);
00816                      dbsqlexec(mssql.link);
00817                      dbresults(mssql.link);
00818               }
00819 
00820               /* add it to the list */
00821               mssql_ptr = (mssql_link *) emalloc(sizeof(mssql_link));
00822               memcpy(mssql_ptr, &mssql, sizeof(mssql_link));
00823               ZEND_REGISTER_RESOURCE(return_value, mssql_ptr, le_link);
00824               
00825               /* add it to the hash */
00826               new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
00827               Z_TYPE(new_index_ptr) = le_index_ptr;
00828               if (zend_hash_update(&EG(regular_list), hashed_details, hashed_details_length + 1,(void *) &new_index_ptr, sizeof(zend_rsrc_list_entry),NULL)==FAILURE) {
00829                      efree(hashed_details);
00830                      RETURN_FALSE;
00831               }
00832               MS_SQL_G(num_links)++;
00833        }
00834        efree(hashed_details);
00835        php_mssql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC);
00836 }
00837 /* }}} */
00838 
00839 /* {{{ php_mssql_get_default_link
00840 */
00841 static int php_mssql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
00842 {
00843        if (MS_SQL_G(default_link)==-1) { /* no link opened yet, implicitly open one */
00844               ht = 0;
00845               php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
00846        }
00847        return MS_SQL_G(default_link);
00848 }
00849 /* }}} */
00850 
00851 /* {{{ proto int mssql_connect([string servername [, string username [, string password [, bool new_link]]]])
00852    Establishes a connection to a MS-SQL server */
00853 PHP_FUNCTION(mssql_connect)
00854 {
00855        php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
00856 }
00857 /* }}} */
00858 
00859 /* {{{ proto int mssql_pconnect([string servername [, string username [, string password [, bool new_link]]]])
00860    Establishes a persistent connection to a MS-SQL server */
00861 PHP_FUNCTION(mssql_pconnect)
00862 {
00863        php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
00864 }
00865 /* }}} */
00866 
00867 /* {{{ proto bool mssql_close([resource conn_id])
00868    Closes a connection to a MS-SQL server */
00869 PHP_FUNCTION(mssql_close)
00870 {
00871        zval *mssql_link_index = NULL;
00872        int id = -1;
00873        mssql_link *mssql_ptr;
00874        
00875        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mssql_link_index) == FAILURE) {
00876               return;
00877        }
00878 
00879        if (mssql_link_index == NULL) {
00880               id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00881               CHECK_LINK(id);
00882        }
00883 
00884        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
00885 
00886        if (mssql_link_index) {
00887               zend_list_delete(Z_RESVAL_P(mssql_link_index));
00888        } else {
00889               zend_list_delete(id);
00890        }
00891 
00892        RETURN_TRUE;
00893 }
00894 /* }}} */
00895 
00896 /* {{{ proto bool mssql_select_db(string database_name [, resource conn_id])
00897    Select a MS-SQL database */
00898 PHP_FUNCTION(mssql_select_db)
00899 {
00900        char *db;
00901        zval *mssql_link_index = NULL;
00902        int db_len;
00903        int id = -1;
00904        mssql_link  *mssql_ptr;
00905 
00906        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &db, &db_len, &mssql_link_index) == FAILURE) {
00907               return;
00908        }
00909 
00910        if (mssql_link_index == NULL) {
00911               id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
00912               CHECK_LINK(id);
00913        }
00914 
00915        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
00916        
00917        if (dbuse(mssql_ptr->link, db)==FAIL) {
00918               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to select database:  %s", db);
00919               RETURN_FALSE;
00920        } else {
00921               RETURN_TRUE;
00922        }
00923 }
00924 /* }}} */
00925 
00926 /* {{{ php_mssql_get_column_content_with_type
00927 */
00928 static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type  TSRMLS_DC)
00929 {
00930        if (dbdata(mssql_ptr->link,offset) == NULL && dbdatlen(mssql_ptr->link,offset) == 0) {
00931               ZVAL_NULL(result);
00932               return;
00933        }
00934 
00935        switch (column_type)
00936        {
00937               case SQLBIT:
00938               case SQLINT1:
00939               case SQLINT2:
00940               case SQLINT4:
00941               case SQLINTN: {      
00942                      ZVAL_LONG(result, (long) anyintcol(offset));
00943                      break;
00944               } 
00945               case SQLCHAR:
00946               case SQLVARCHAR:
00947               case SQLTEXT: {
00948                      int length;
00949                      char *data = charcol(offset);
00950 
00951                      length=dbdatlen(mssql_ptr->link,offset);
00952 #if ilia_0
00953                      while (length>0 && data[length-1] == ' ') { /* nuke trailing whitespace */
00954                             length--;
00955                      }
00956 #endif
00957                      ZVAL_STRINGL(result, data, length, 1); 
00958                      break;
00959               }
00960               case SQLFLT4:
00961                      ZVAL_DOUBLE(result, (double) floatcol4(offset));
00962                      break;
00963               case SQLMONEY:
00964               case SQLMONEY4:
00965               case SQLMONEYN: {
00966                      DBFLT8 res_buf;
00967                      dbconvert(NULL, column_type, dbdata(mssql_ptr->link,offset), 8, SQLFLT8, (LPBYTE)&res_buf, -1);
00968                      ZVAL_DOUBLE(result, res_buf);
00969                      }
00970                      break;
00971               case SQLFLT8:
00972                      ZVAL_DOUBLE(result, (double) floatcol8(offset));
00973                      break;
00974 #ifdef SQLUNIQUE
00975               case SQLUNIQUE: {
00976 #else
00977               case 36: {                  /* FreeTDS hack */
00978 #endif
00979                      char *data = charcol(offset);
00980 
00981                      /* uniqueidentifier is a 16-byte binary number */
00982                      ZVAL_STRINGL(result, data, 16, 1);
00983                      }
00984                      break;
00985               case SQLVARBINARY:
00986               case SQLBINARY:
00987               case SQLIMAGE: {
00988                      int res_length = dbdatlen(mssql_ptr->link, offset);
00989 
00990                      if (!res_length) {
00991                             ZVAL_NULL(result);
00992                      } else {
00993                             ZVAL_STRINGL(result, (char *)dbdata(mssql_ptr->link, offset), res_length, 1);
00994                      }
00995               }
00996                      break;
00997               case SQLNUMERIC:
00998               default: {
00999                      if (dbwillconvert(column_type,SQLCHAR)) {
01000                             char *res_buf;
01001                             DBDATEREC dateinfo;  
01002                             int res_length = dbdatlen(mssql_ptr->link,offset);
01003 
01004                             if (res_length == -1) {
01005                                    res_length = 255;
01006                             }
01007 
01008                             if ((column_type != SQLDATETIME && column_type != SQLDATETIM4) || MS_SQL_G(datetimeconvert)) {
01009 
01010                                    switch (column_type) {
01011                                           case SQLDATETIME :
01012                                           case SQLDATETIM4 :
01013                                                  res_length += 20;
01014                                                  break;
01015                                           case SQLMONEY :
01016                                           case SQLMONEY4 :
01017                                           case SQLMONEYN :
01018                                           case SQLDECIMAL :
01019                                           case SQLNUMERIC :
01020                                                  res_length += 5;
01021                                           case 127 :
01022                                                  res_length += 20;
01023                                                  break;
01024                                    }
01025 
01026                                    res_buf = (unsigned char *) emalloc(res_length+1);
01027                                    res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR,res_buf,-1);
01028                                    res_buf[res_length] = '\0';
01029                             } else {
01030                                    if (column_type == SQLDATETIM4) {
01031                                           DBDATETIME temp;
01032 
01033                                           dbconvert(NULL, SQLDATETIM4, dbdata(mssql_ptr->link,offset), -1, SQLDATETIME, (LPBYTE) &temp, -1);
01034                                           dbdatecrack(mssql_ptr->link, &dateinfo, &temp);
01035                                    } else {
01036                                           dbdatecrack(mssql_ptr->link, &dateinfo, (DBDATETIME *) dbdata(mssql_ptr->link,offset));
01037                                    }
01038                      
01039                                    res_length = 19;
01040                                    spprintf(&res_buf, 0, "%d-%02d-%02d %02d:%02d:%02d" , dateinfo.year, dateinfo.month, dateinfo.day, dateinfo.hour, dateinfo.minute, dateinfo.second);
01041                             }
01042               
01043                             ZVAL_STRINGL(result, res_buf, res_length, 0);
01044                      } else {
01045                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d has unknown data type (%d)", offset, coltype(offset));
01046                             ZVAL_FALSE(result);
01047                      }
01048               }
01049        }
01050 }
01051 /* }}} */
01052 
01053 /* {{{ php_mssql_get_column_content_without_type
01054 */
01055 static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC)
01056 {
01057        if (dbdatlen(mssql_ptr->link,offset) == 0) {
01058               ZVAL_NULL(result);
01059               return;
01060        }
01061 
01062        if (column_type == SQLVARBINARY ||
01063               column_type == SQLBINARY ||
01064               column_type == SQLIMAGE) {
01065               DBBINARY *bin;
01066               unsigned char *res_buf;
01067               int res_length = dbdatlen(mssql_ptr->link, offset);
01068 
01069               if (res_length == 0) {
01070                      ZVAL_NULL(result);
01071                      return;
01072               } else if (res_length < 0) {
01073                      ZVAL_FALSE(result);
01074                      return;
01075               }
01076 
01077               res_buf = (unsigned char *) emalloc(res_length+1);
01078               bin = ((DBBINARY *)dbdata(mssql_ptr->link, offset));
01079               res_buf[res_length] = '\0';
01080               memcpy(res_buf, bin, res_length);
01081               ZVAL_STRINGL(result, res_buf, res_length, 0);
01082        }
01083        else if  (dbwillconvert(coltype(offset),SQLCHAR)) {
01084               unsigned char *res_buf;
01085               DBDATEREC dateinfo;  
01086               int res_length = dbdatlen(mssql_ptr->link,offset);
01087 
01088               if ((column_type != SQLDATETIME && column_type != SQLDATETIM4) || MS_SQL_G(datetimeconvert)) {
01089 
01090                      switch (column_type) {
01091                             case SQLDATETIME :
01092                             case SQLDATETIM4 :
01093                                    res_length += 20;
01094                                    break;
01095                             case SQLMONEY :
01096                             case SQLMONEY4 :
01097                             case SQLMONEYN :
01098                             case SQLDECIMAL :
01099                             case SQLNUMERIC :
01100                                    res_length += 5;
01101                             case 127 :
01102                                    res_length += 20;
01103                                    break;
01104                      }
01105                      
01106                      res_buf = (unsigned char *) emalloc(res_length+1);
01107                      res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR, res_buf, -1);
01108                      res_buf[res_length] = '\0';
01109               } else {
01110                      if (column_type == SQLDATETIM4) {
01111                             DBDATETIME temp;
01112 
01113                             dbconvert(NULL, SQLDATETIM4, dbdata(mssql_ptr->link,offset), -1, SQLDATETIME, (LPBYTE) &temp, -1);
01114                             dbdatecrack(mssql_ptr->link, &dateinfo, &temp);
01115                      } else {
01116                             dbdatecrack(mssql_ptr->link, &dateinfo, (DBDATETIME *) dbdata(mssql_ptr->link,offset));
01117                      }
01118                      
01119                      res_length = 19;
01120                      spprintf(&res_buf, 0, "%d-%02d-%02d %02d:%02d:%02d" , dateinfo.year, dateinfo.month, dateinfo.day, dateinfo.hour, dateinfo.minute, dateinfo.second);
01121               }
01122 
01123               ZVAL_STRINGL(result, res_buf, res_length, 0);
01124        } else {
01125               php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d has unknown data type (%d)", offset, coltype(offset));
01126               ZVAL_FALSE(result);
01127        }
01128 }
01129 /* }}} */
01130 
01131 /* {{{ _mssql_get_sp_result
01132 */
01133 static void _mssql_get_sp_result(mssql_link *mssql_ptr, mssql_statement *statement TSRMLS_DC) 
01134 {
01135        int i, num_rets, type;
01136        char *parameter;
01137        mssql_bind *bind;
01138 
01139        /* Now to fetch RETVAL and OUTPUT values*/
01140        num_rets = dbnumrets(mssql_ptr->link);
01141 
01142        if (num_rets!=0) {
01143               for (i = 1; i <= num_rets; i++) {
01144                      parameter = (char*)dbretname(mssql_ptr->link, i);
01145                      type = dbrettype(mssql_ptr->link, i);
01146                                           
01147                      if (statement->binds != NULL) {    /*     Maybe a non-parameter sp    */
01148                             if (zend_hash_find(statement->binds, parameter, strlen(parameter), (void**)&bind)==SUCCESS) {
01149                                    if (!dbretlen(mssql_ptr->link,i)) {
01150                                           ZVAL_NULL(bind->zval);
01151                                    }
01152                                    else {
01153                                           switch (type) {
01154                                                  case SQLBIT:
01155                                                  case SQLINT1:
01156                                                  case SQLINT2:
01157                                                  case SQLINT4:
01158                                                         convert_to_long_ex(&bind->zval);
01159                                                         /* FIXME this works only on little endian machine !!! */
01160                                                         Z_LVAL_P(bind->zval) = *((int *)(dbretdata(mssql_ptr->link,i)));
01161                                                         break;
01162                             
01163                                                  case SQLFLT4:
01164                                                  case SQLFLT8:
01165                                                  case SQLFLTN:
01166                                                  case SQLMONEY4:
01167                                                  case SQLMONEY:
01168                                                  case SQLMONEYN:
01169                                                         convert_to_double_ex(&bind->zval);
01170                                                         Z_DVAL_P(bind->zval) = *((double *)(dbretdata(mssql_ptr->link,i)));
01171                                                         break;
01172        
01173                                                  case SQLCHAR:
01174                                                  case SQLVARCHAR:
01175                                                  case SQLTEXT:
01176                                                         convert_to_string_ex(&bind->zval);
01177                                                         Z_STRLEN_P(bind->zval) = dbretlen(mssql_ptr->link,i);
01178                                                         Z_STRVAL_P(bind->zval) = estrndup(dbretdata(mssql_ptr->link,i),Z_STRLEN_P(bind->zval));
01179                                                         break;
01180                                                  /* TODO binary */
01181                                           }
01182                                    }
01183                             }
01184                             else {
01185                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "An output parameter variable was not provided");
01186                             }
01187                      }
01188               }
01189        }
01190        if (statement->binds != NULL) {    /*     Maybe a non-parameter sp    */
01191               if (zend_hash_find(statement->binds, "RETVAL", 6, (void**)&bind)==SUCCESS) {
01192                      if (dbhasretstat(mssql_ptr->link)) {
01193                             convert_to_long_ex(&bind->zval);
01194                             Z_LVAL_P(bind->zval)=dbretstatus(mssql_ptr->link);
01195                      }
01196                      else {
01197                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "stored procedure has no return value. Nothing was returned into RETVAL");
01198                      }
01199               }
01200        }
01201 }
01202 /* }}} */
01203 
01204 /* {{{ _mssql_fetch_batch
01205 */
01206 static int _mssql_fetch_batch(mssql_link *mssql_ptr, mssql_result *result, int retvalue TSRMLS_DC) 
01207 {
01208        int i, j = 0;
01209        char computed_buf[16];
01210 
01211        if (!result->have_fields) {
01212               for (i=0; i<result->num_fields; i++) {
01213                      char *source = NULL;
01214                      char *fname = (char *)dbcolname(mssql_ptr->link,i+1);
01215        
01216                      if (*fname) {
01217                             result->fields[i].name = estrdup(fname);
01218                      } else {
01219                             if (j>0) {
01220                                    snprintf(computed_buf,16,"computed%d",j);
01221                             } else {
01222                                    strcpy(computed_buf,"computed");
01223                             }
01224                             result->fields[i].name = estrdup(computed_buf);
01225                             j++;
01226                      }
01227                      result->fields[i].max_length = dbcollen(mssql_ptr->link,i+1);
01228                      source = (char *)dbcolsource(mssql_ptr->link,i+1);
01229                      if (source) {
01230                             result->fields[i].column_source = estrdup(source);
01231                      }
01232                      else {
01233                             result->fields[i].column_source = STR_EMPTY_ALLOC();
01234                      }
01235        
01236                      result->fields[i].type = coltype(i+1);
01237                      /* set numeric flag */
01238                      switch (result->fields[i].type) {
01239                             case SQLINT1:
01240                             case SQLINT2:
01241                             case SQLINT4:
01242                             case SQLINTN:
01243                             case SQLFLT4:
01244                             case SQLFLT8:
01245                             case SQLNUMERIC:
01246                             case SQLDECIMAL:
01247                                    result->fields[i].numeric = 1;
01248                                    break;
01249                             case SQLCHAR:
01250                             case SQLVARCHAR:
01251                             case SQLTEXT:
01252                             default:
01253                                    result->fields[i].numeric = 0;
01254                                    break;
01255                      }
01256               }
01257               result->have_fields = 1;
01258        }
01259 
01260        i=0;
01261        if (!result->data) {
01262               result->data = (zval **) safe_emalloc(sizeof(zval *), MSSQL_ROWS_BLOCK*(++result->blocks_initialized), 0);
01263        }
01264        while (retvalue!=FAIL && retvalue!=NO_MORE_ROWS) {
01265               result->num_rows++;
01266               if (result->num_rows > result->blocks_initialized*MSSQL_ROWS_BLOCK) {
01267                      result->data = (zval **) erealloc(result->data,sizeof(zval *)*MSSQL_ROWS_BLOCK*(++result->blocks_initialized));
01268               }
01269               result->data[i] = (zval *) safe_emalloc(sizeof(zval), result->num_fields, 0);
01270               for (j=0; j<result->num_fields; j++) {
01271                      INIT_ZVAL(result->data[i][j]);
01272                      MS_SQL_G(get_column_content(mssql_ptr, j+1, &result->data[i][j], result->fields[j].type TSRMLS_CC));
01273               }
01274               if (i<result->batchsize || result->batchsize==0) {
01275                      i++;
01276                      dbclrbuf(mssql_ptr->link,DBLASTROW(mssql_ptr->link)); 
01277                      retvalue=dbnextrow(mssql_ptr->link);
01278               }
01279               else
01280                      break;
01281               result->lastresult = retvalue;
01282        }
01283        if (result->statement && (retvalue == NO_MORE_RESULTS || retvalue == NO_MORE_RPC_RESULTS)) {
01284               _mssql_get_sp_result(mssql_ptr, result->statement TSRMLS_CC);
01285        }
01286        return i;
01287 }
01288 /* }}} */
01289 
01290 /* {{{ proto int mssql_fetch_batch(resource result_index)
01291    Returns the next batch of records */
01292 PHP_FUNCTION(mssql_fetch_batch)
01293 {
01294        zval *mssql_result_index;
01295        mssql_result *result;
01296        mssql_link *mssql_ptr;
01297 
01298        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
01299               return;
01300        }
01301        
01302        if (Z_RESVAL_P(mssql_result_index) == 0) {
01303               RETURN_FALSE;
01304        }
01305 
01306        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
01307 
01308        mssql_ptr = result->mssql_ptr;
01309        _free_result(result, 0);
01310        result->cur_row=result->num_rows=0;
01311        result->num_rows = _mssql_fetch_batch(mssql_ptr, result, result->lastresult TSRMLS_CC);
01312 
01313        RETURN_LONG(result->num_rows);
01314 }
01315 /* }}} */
01316 
01317 /* {{{ proto resource mssql_query(string query [, resource conn_id [, int batch_size]])
01318    Perform an SQL query on a MS-SQL server database */
01319 PHP_FUNCTION(mssql_query)
01320 {
01321        char *query;
01322        zval *mssql_link_index = NULL;
01323        int query_len, retvalue, batchsize, num_fields;
01324        long zbatchsize = 0;
01325        mssql_link *mssql_ptr;
01326        mssql_result *result;
01327        int id = -1;
01328 
01329        dbsettime(MS_SQL_G(timeout));
01330        batchsize = MS_SQL_G(batchsize);
01331 
01332        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|rl", &query, &query_len, &mssql_link_index, &zbatchsize) == FAILURE) {
01333               return;
01334        }
01335 
01336        switch(ZEND_NUM_ARGS()) {
01337               case 1:
01338                      id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01339                      CHECK_LINK(id);
01340                      break;
01341               case 3:
01342                      batchsize = (int) zbatchsize;
01343                      break;
01344        }
01345 
01346        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
01347        
01348        if (dbcmd(mssql_ptr->link, query)==FAIL) {
01349               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set query");
01350               RETURN_FALSE;
01351        }
01352        if (dbsqlexec(mssql_ptr->link)==FAIL || (retvalue = dbresults(mssql_ptr->link))==FAIL) {
01353               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed");
01354               dbcancel(mssql_ptr->link);
01355               RETURN_FALSE;
01356        }
01357        
01358        /* Skip results not returning any columns */
01359        while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retvalue == SUCCEED) {
01360               retvalue = dbresults(mssql_ptr->link);
01361        }
01362 
01363        if (num_fields <= 0) {
01364               RETURN_TRUE;
01365        }
01366 
01367        retvalue=dbnextrow(mssql_ptr->link);      
01368        if (retvalue==FAIL) {
01369               dbcancel(mssql_ptr->link);
01370               RETURN_FALSE;
01371        }
01372 
01373        result = (mssql_result *) emalloc(sizeof(mssql_result));
01374        result->statement = NULL;
01375        result->num_fields = num_fields;
01376        result->blocks_initialized = 1;
01377        
01378        result->batchsize = batchsize;
01379        result->data = NULL;
01380        result->blocks_initialized = 0;
01381        result->mssql_ptr = mssql_ptr;
01382        result->cur_field=result->cur_row=result->num_rows=0;
01383        result->have_fields = 0;
01384 
01385        result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), result->num_fields, 0);
01386        result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
01387        
01388        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
01389 }
01390 /* }}} */
01391 
01392 /* {{{ proto int mssql_rows_affected(resource conn_id)
01393    Returns the number of records affected by the query */
01394 PHP_FUNCTION(mssql_rows_affected)
01395 {
01396        zval *mssql_link_index;
01397        mssql_link *mssql_ptr;
01398 
01399        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_link_index) == FAILURE) {
01400               return;
01401        }
01402        
01403        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, -1, "MS SQL-Link", le_link, le_plink);
01404 
01405        RETURN_LONG(DBCOUNT(mssql_ptr->link));
01406 }
01407 /* }}} */
01408 
01409 /* {{{ proto bool mssql_free_result(resource result_index)
01410    Free a MS-SQL result index */
01411 PHP_FUNCTION(mssql_free_result)
01412 {
01413        zval *mssql_result_index;
01414        mssql_result *result;
01415        int retvalue;
01416        
01417        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
01418               return;
01419        }
01420        
01421        if (Z_RESVAL_P(mssql_result_index) == 0) {
01422               RETURN_FALSE;
01423        }
01424 
01425        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01426        /* Release remaining results */
01427        do {
01428               dbcanquery(result->mssql_ptr->link);
01429               retvalue = dbresults(result->mssql_ptr->link);
01430        } while (retvalue == SUCCEED);
01431 
01432        zend_list_delete(Z_RESVAL_P(mssql_result_index));
01433        RETURN_TRUE;
01434 }
01435 /* }}} */
01436 
01437 /* {{{ proto string mssql_get_last_message(void)
01438    Gets the last message from the MS-SQL server */
01439 PHP_FUNCTION(mssql_get_last_message)
01440 {
01441        if (zend_parse_parameters_none() == FAILURE) {
01442               return;
01443        }
01444 
01445        if (MS_SQL_G(server_message)) {
01446               RETURN_STRING(MS_SQL_G(server_message),1);
01447        } else {
01448               RETURN_STRING("",1);
01449        }
01450 }
01451 /* }}} */
01452 
01453 /* {{{ proto int mssql_num_rows(resource mssql_result_index)
01454    Returns the number of rows fetched in from the result id specified */
01455 PHP_FUNCTION(mssql_num_rows)
01456 {
01457        zval *mssql_result_index;
01458        mssql_result *result;
01459 
01460        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
01461               return;
01462        }
01463 
01464        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01465 
01466        RETURN_LONG(result->num_rows);
01467 }
01468 /* }}} */
01469 
01470 /* {{{ proto int mssql_num_fields(resource mssql_result_index)
01471    Returns the number of fields fetched in from the result id specified */
01472 PHP_FUNCTION(mssql_num_fields)
01473 {
01474        zval *mssql_result_index;
01475        mssql_result *result;
01476        
01477        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
01478               return;
01479        }
01480        
01481        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01482 
01483        RETURN_LONG(result->num_fields);
01484 }
01485 /* }}} */
01486 
01487 /* {{{ php_mssql_fetch_hash
01488 */
01489 static void php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
01490 {
01491        zval *mssql_result_index;
01492        mssql_result *result;
01493        int i;
01494        long resulttype = 0;
01495 
01496        switch (result_type) {
01497               case MSSQL_NUM:
01498               case MSSQL_ASSOC:
01499                      if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
01500                             return;
01501                      }
01502                      break;
01503               case MSSQL_BOTH:
01504                      if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &resulttype) == FAILURE) {
01505                             return;
01506                      }
01507                      result_type = (resulttype > 0 && (resulttype & MSSQL_BOTH)) ? resulttype : result_type;
01508                      break;
01509               default:
01510                      return;
01511        }
01512 
01513        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01514 
01515        if (MS_SQL_G(server_message)) {
01516               STR_FREE(MS_SQL_G(server_message));
01517               MS_SQL_G(server_message) = NULL;
01518        }
01519 
01520        if (result->cur_row >= result->num_rows) {
01521               RETURN_FALSE;
01522        }
01523        
01524        array_init(return_value);
01525        
01526        for (i=0; i<result->num_fields; i++) {
01527               if (Z_TYPE(result->data[result->cur_row][i]) != IS_NULL) {
01528                      char *data;
01529                      int data_len;
01530                      int should_copy;
01531 
01532                      if (Z_TYPE(result->data[result->cur_row][i]) == IS_STRING) {
01533                             if (PG(magic_quotes_runtime)) {
01534                                    data = php_addslashes(Z_STRVAL(result->data[result->cur_row][i]), Z_STRLEN(result->data[result->cur_row][i]), &data_len, 0 TSRMLS_CC);
01535                                    should_copy = 0;
01536                             }
01537                             else
01538                             {
01539                                    data = Z_STRVAL(result->data[result->cur_row][i]);
01540                                    data_len = Z_STRLEN(result->data[result->cur_row][i]);
01541                                    should_copy = 1;
01542                             }
01543 
01544                             if (result_type & MSSQL_NUM) {
01545                                    add_index_stringl(return_value, i, data, data_len, should_copy);
01546                                    should_copy = 1;
01547                             }
01548                             
01549                             if (result_type & MSSQL_ASSOC) {
01550                                    add_assoc_stringl(return_value, result->fields[i].name, data, data_len, should_copy);
01551                             }
01552                      }
01553                      else if (Z_TYPE(result->data[result->cur_row][i]) == IS_LONG) {
01554                             if (result_type & MSSQL_NUM)
01555                                    add_index_long(return_value, i, Z_LVAL(result->data[result->cur_row][i]));
01556                             
01557                             if (result_type & MSSQL_ASSOC)
01558                                    add_assoc_long(return_value, result->fields[i].name, Z_LVAL(result->data[result->cur_row][i]));
01559                      }
01560                      else if (Z_TYPE(result->data[result->cur_row][i]) == IS_DOUBLE) {
01561                             if (result_type & MSSQL_NUM)
01562                                    add_index_double(return_value, i, Z_DVAL(result->data[result->cur_row][i]));
01563                             
01564                             if (result_type & MSSQL_ASSOC)
01565                                    add_assoc_double(return_value, result->fields[i].name, Z_DVAL(result->data[result->cur_row][i]));
01566                      }
01567               }
01568               else
01569               {
01570                      if (result_type & MSSQL_NUM)
01571                             add_index_null(return_value, i);
01572                      if (result_type & MSSQL_ASSOC)
01573                             add_assoc_null(return_value, result->fields[i].name);
01574               }
01575        }
01576        result->cur_row++;
01577 }
01578 /* }}} */
01579 
01580 /* {{{ proto array mssql_fetch_row(resource result_id)
01581    Returns an array of the current row in the result set specified by result_id */
01582 PHP_FUNCTION(mssql_fetch_row)
01583 {
01584        php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_NUM);
01585 }
01586 /* }}} */
01587 
01588 /* {{{ proto object mssql_fetch_object(resource result_id)
01589    Returns a pseudo-object of the current row in the result set specified by result_id */
01590 PHP_FUNCTION(mssql_fetch_object)
01591 {
01592        php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_ASSOC);
01593        if (Z_TYPE_P(return_value)==IS_ARRAY) {
01594               object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
01595        }
01596 }
01597 /* }}} */
01598 
01599 /* {{{ proto array mssql_fetch_array(resource result_id [, int result_type])
01600    Returns an associative array of the current row in the result set specified by result_id */
01601 PHP_FUNCTION(mssql_fetch_array)
01602 {
01603        php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_BOTH);
01604 }
01605 /* }}} */
01606 
01607 /* {{{ proto array mssql_fetch_assoc(resource result_id)
01608    Returns an associative array of the current row in the result set specified by result_id */
01609 PHP_FUNCTION(mssql_fetch_assoc)
01610 {
01611        php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_ASSOC);
01612 }
01613 /* }}} */
01614 
01615 /* {{{ proto bool mssql_data_seek(resource result_id, int offset)
01616    Moves the internal row pointer of the MS-SQL result associated with the specified result identifier to pointer to the specified row number */
01617 PHP_FUNCTION(mssql_data_seek)
01618 {
01619        zval *mssql_result_index;
01620        long offset;
01621        mssql_result *result;
01622 
01623        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &mssql_result_index, &offset) == FAILURE) {
01624               return;
01625        }
01626        
01627        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01628 
01629        if (offset < 0 || offset >= result->num_rows) {
01630               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad row offset");
01631               RETURN_FALSE;
01632        }
01633        
01634        result->cur_row = offset;
01635        RETURN_TRUE;
01636 }
01637 /* }}} */
01638 
01639 /* {{{ php_mssql_get_field_name
01640 */
01641 static char *php_mssql_get_field_name(int type)
01642 {
01643        switch (type) {
01644               case SQLBINARY:
01645               case SQLVARBINARY:
01646                      return "blob";
01647                      break;
01648               case SQLCHAR:
01649               case SQLVARCHAR:
01650                      return "char";
01651                      break;
01652               case SQLTEXT:
01653                      return "text";
01654                      break;
01655               case SQLDATETIME:
01656               case SQLDATETIM4:
01657               case SQLDATETIMN:
01658                      return "datetime";
01659                      break;
01660               case SQLDECIMAL:
01661               case SQLFLT4:
01662               case SQLFLT8:
01663               case SQLFLTN:
01664                      return "real";
01665                      break;
01666               case SQLINT1:
01667               case SQLINT2:
01668               case SQLINT4:
01669               case SQLINTN:
01670                      return "int";
01671                      break;
01672               case SQLNUMERIC:
01673                      return "numeric";
01674                      break;
01675               case SQLMONEY:
01676               case SQLMONEY4:
01677               case SQLMONEYN:
01678                      return "money";
01679                      break;
01680               case SQLBIT:
01681                      return "bit";
01682                      break;
01683               case SQLIMAGE:
01684                      return "image";
01685                      break;
01686 #ifdef SQLUNIQUE
01687               case SQLUNIQUE:
01688                      return "uniqueidentifier";
01689                      break;
01690 #endif
01691               default:
01692                      return "unknown";
01693                      break;
01694        }
01695 }
01696 /* }}} */
01697 
01698 /* {{{ proto object mssql_fetch_field(resource result_id [, int offset])
01699    Gets information about certain fields in a query result */
01700 PHP_FUNCTION(mssql_fetch_field)
01701 {
01702        zval *mssql_result_index;
01703        long field_offset = -1;
01704        mssql_result *result;
01705 
01706        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
01707               return;
01708        }
01709 
01710        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01711        
01712        if (field_offset==-1) {
01713               field_offset = result->cur_field;
01714               result->cur_field++;
01715        }
01716        
01717        if (field_offset<0 || field_offset >= result->num_fields) {
01718               if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
01719                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
01720               }
01721               RETURN_FALSE;
01722        }
01723 
01724        object_init(return_value);
01725 
01726        add_property_string(return_value, "name",result->fields[field_offset].name, 1);
01727        add_property_long(return_value, "max_length",result->fields[field_offset].max_length);
01728        add_property_string(return_value, "column_source",result->fields[field_offset].column_source, 1);
01729        add_property_long(return_value, "numeric", result->fields[field_offset].numeric);
01730        add_property_string(return_value, "type", php_mssql_get_field_name(Z_TYPE(result->fields[field_offset])), 1);
01731 }
01732 /* }}} */
01733 
01734 /* {{{ proto int mssql_field_length(resource result_id [, int offset])
01735    Get the length of a MS-SQL field */
01736 PHP_FUNCTION(mssql_field_length)
01737 {
01738        zval *mssql_result_index;
01739        long field_offset = -1;
01740        mssql_result *result;
01741 
01742        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
01743               return;
01744        }
01745        
01746        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01747        
01748        if (field_offset==-1) {
01749               field_offset = result->cur_field;
01750               result->cur_field++;
01751        }
01752        
01753        if (field_offset<0 || field_offset >= result->num_fields) {
01754               if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
01755                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
01756               }
01757               RETURN_FALSE;
01758        }
01759 
01760        RETURN_LONG(result->fields[field_offset].max_length);
01761 }
01762 /* }}} */
01763 
01764 /* {{{ proto string mssql_field_name(resource result_id [, int offset])
01765    Returns the name of the field given by offset in the result set given by result_id */
01766 PHP_FUNCTION(mssql_field_name)
01767 {
01768        zval *mssql_result_index;
01769        long field_offset = -1;
01770        mssql_result *result;
01771 
01772        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
01773               return;
01774        }
01775        
01776        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01777        
01778        if (field_offset==-1) {
01779               field_offset = result->cur_field;
01780               result->cur_field++;
01781        }
01782        
01783        if (field_offset<0 || field_offset >= result->num_fields) {
01784               if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
01785                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
01786               }
01787               RETURN_FALSE;
01788        }
01789 
01790        RETURN_STRINGL(result->fields[field_offset].name, strlen(result->fields[field_offset].name), 1);
01791 }
01792 /* }}} */
01793 
01794 /* {{{ proto string mssql_field_type(resource result_id [, int offset])
01795    Returns the type of a field */
01796 PHP_FUNCTION(mssql_field_type)
01797 {
01798        zval *mssql_result_index;
01799        long field_offset = -1;
01800        mssql_result *result;
01801 
01802        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
01803               return;
01804        }
01805        
01806        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01807        
01808        if (field_offset==-1) {
01809               field_offset = result->cur_field;
01810               result->cur_field++;
01811        }
01812        
01813        if (field_offset<0 || field_offset >= result->num_fields) {
01814               if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
01815                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
01816               }
01817               RETURN_FALSE;
01818        }
01819 
01820        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);
01821 }
01822 /* }}} */
01823 
01824 /* {{{ proto bool mssql_field_seek(resource result_id, int offset)
01825    Seeks to the specified field offset */
01826 PHP_FUNCTION(mssql_field_seek)
01827 {
01828        zval *mssql_result_index;
01829        long field_offset;
01830        mssql_result *result;
01831 
01832        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &mssql_result_index, &field_offset) == FAILURE) {
01833               return;
01834        }
01835        
01836        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01837        
01838        if (field_offset<0 || field_offset >= result->num_fields) {
01839               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
01840               RETURN_FALSE;
01841        }
01842 
01843        result->cur_field = field_offset;
01844        RETURN_TRUE;
01845 }
01846 /* }}} */
01847 
01848 /* {{{ proto string mssql_result(resource result_id, int row, mixed field)
01849    Returns the contents of one cell from a MS-SQL result set */
01850 PHP_FUNCTION(mssql_result)
01851 {
01852        zval **field, *mssql_result_index;
01853        long row;
01854        int field_offset=0;
01855        mssql_result *result;
01856 
01857        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlZ", &mssql_result_index, &row, &field) == FAILURE) {
01858               return;
01859        }
01860 
01861        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01862 
01863        if (row < 0 || row >= result->num_rows) {
01864               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad row offset (%ld)", row);
01865               RETURN_FALSE;
01866        }
01867 
01868        switch(Z_TYPE_PP(field)) {
01869               case IS_STRING: {
01870                      int i;
01871 
01872                      for (i=0; i<result->num_fields; i++) {
01873                             if (!strcasecmp(result->fields[i].name, Z_STRVAL_PP(field))) {
01874                                    field_offset = i;
01875                                    break;
01876                             }
01877                      }
01878                      if (i>=result->num_fields) { /* no match found */
01879                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s field not found in result", Z_STRVAL_PP(field));
01880                             RETURN_FALSE;
01881                      }
01882                      break;
01883               }
01884               default:
01885                      convert_to_long_ex(field);
01886                      field_offset = Z_LVAL_PP(field);
01887                      if (field_offset<0 || field_offset>=result->num_fields) {
01888                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
01889                             RETURN_FALSE;
01890                      }
01891                      break;
01892        }
01893 
01894        *return_value = result->data[row][field_offset];
01895        zval_copy_ctor(return_value);
01896 }
01897 /* }}} */
01898 
01899 /* {{{ proto bool mssql_next_result(resource result_id)
01900    Move the internal result pointer to the next result */
01901 PHP_FUNCTION(mssql_next_result)
01902 {
01903        zval *mssql_result_index;
01904        int retvalue;
01905        mssql_result *result;
01906        mssql_link *mssql_ptr;
01907 
01908        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
01909               return;
01910        }
01911 
01912        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result); 
01913 
01914        mssql_ptr = result->mssql_ptr;
01915        retvalue = dbresults(mssql_ptr->link);
01916 
01917        while (dbnumcols(mssql_ptr->link) <= 0 && retvalue == SUCCEED) {
01918               retvalue = dbresults(mssql_ptr->link);
01919        }
01920 
01921        if (retvalue == FAIL) {
01922               RETURN_FALSE;
01923        }
01924        else if (retvalue == NO_MORE_RESULTS || retvalue == NO_MORE_RPC_RESULTS) {
01925               if (result->statement) {
01926                      _mssql_get_sp_result(mssql_ptr, result->statement TSRMLS_CC);
01927               }
01928               RETURN_FALSE;
01929        }
01930        else {
01931               _free_result(result, 1);
01932               result->cur_row=result->num_fields=result->num_rows=0;
01933               dbclrbuf(mssql_ptr->link,DBLASTROW(mssql_ptr->link));
01934               retvalue = dbnextrow(mssql_ptr->link);
01935 
01936               result->num_fields = dbnumcols(mssql_ptr->link);
01937               result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), result->num_fields, 0);
01938               result->have_fields = 0;
01939               result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
01940               RETURN_TRUE;
01941        }
01942 
01943 }
01944 /* }}} */
01945 
01946 
01947 /* {{{ proto void mssql_min_error_severity(int severity)
01948    Sets the lower error severity */
01949 PHP_FUNCTION(mssql_min_error_severity)
01950 {
01951        long severity;
01952 
01953        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &severity) == FAILURE) {
01954               return;
01955        }
01956 
01957        MS_SQL_G(min_error_severity) = severity;
01958 }
01959 
01960 /* }}} */
01961 
01962 /* {{{ proto void mssql_min_message_severity(int severity)
01963    Sets the lower message severity */
01964 PHP_FUNCTION(mssql_min_message_severity)
01965 {
01966        long severity;
01967        
01968        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &severity) == FAILURE) {
01969               return;
01970        }
01971 
01972        MS_SQL_G(min_message_severity) = severity;
01973 }
01974 /* }}} */
01975 
01976 /* {{{ proto int mssql_init(string sp_name [, resource conn_id])
01977    Initializes a stored procedure or a remote stored procedure  */
01978 PHP_FUNCTION(mssql_init)
01979 {
01980        char *sp_name;
01981        int sp_name_len;
01982        zval *mssql_link_index = NULL;
01983        mssql_link *mssql_ptr;
01984        mssql_statement *statement;
01985        int id = -1;
01986        
01987        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &sp_name, &sp_name_len, &mssql_link_index) == FAILURE) {
01988               return;
01989        }
01990 
01991        if (mssql_link_index == NULL) {
01992               id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
01993               CHECK_LINK(id);
01994        }
01995 
01996        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
01997        
01998        if (dbrpcinit(mssql_ptr->link, sp_name,0)==FAIL) {
01999               php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to init stored procedure");
02000               RETURN_FALSE;
02001        }
02002 
02003        statement=NULL;
02004        statement = ecalloc(1,sizeof(mssql_statement));
02005        statement->link = mssql_ptr;
02006        statement->executed=FALSE;
02007 
02008        statement->id = zend_list_insert(statement,le_statement);
02009        
02010        RETURN_RESOURCE(statement->id);
02011 }
02012 /* }}} */
02013 
02014 /* {{{ proto bool mssql_bind(resource stmt, string param_name, mixed var, int type [, bool is_output [, bool is_null [, int maxlen]]])
02015    Adds a parameter to a stored procedure or a remote stored procedure  */
02016 PHP_FUNCTION(mssql_bind)
02017 {
02018        char *param_name;
02019        int param_name_len, datalen;
02020        int status = 0;
02021        long type = 0, maxlen = -1;
02022        zval *stmt, **var;
02023        zend_bool is_output = 0, is_null = 0;
02024        mssql_link *mssql_ptr;
02025        mssql_statement *statement;
02026        mssql_bind bind,*bindp;
02027        LPBYTE value = NULL;
02028 
02029        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZl|bbl", &stmt, &param_name, &param_name_len, &var, &type, &is_output, &is_null, &maxlen) == FAILURE) {
02030               return;
02031        }
02032 
02033        if (ZEND_NUM_ARGS() == 7 && !is_output) {
02034               maxlen = -1;
02035        }
02036        
02037        ZEND_FETCH_RESOURCE(statement, mssql_statement *, &stmt, -1, "MS SQL-Statement", le_statement);
02038 
02039        if (statement==NULL) {
02040               RETURN_FALSE;
02041        }
02042        mssql_ptr=statement->link;
02043 
02044        /* modify datalen and maxlen according to dbrpcparam documentation */
02045        if ( (type==SQLVARCHAR) || (type==SQLCHAR) || (type==SQLTEXT) )       {      /* variable-length type */
02046               if (is_null) {
02047                      maxlen=0;
02048                      datalen=0;
02049               } else {
02050                      convert_to_string_ex(var);
02051                      datalen=Z_STRLEN_PP(var);
02052                      value=(LPBYTE)Z_STRVAL_PP(var);
02053               }
02054        } else {
02055               /* fixed-length type */
02056               if (is_null)  {
02057                      datalen=0;
02058               } else {
02059                      datalen=-1;
02060               }
02061               maxlen=-1;
02062 
02063               switch (type) {
02064                      case SQLFLT4:
02065                      case SQLFLT8:
02066                      case SQLFLTN:
02067                             convert_to_double_ex(var);
02068                             value=(LPBYTE)(&Z_DVAL_PP(var));
02069                             break;
02070 
02071                      case SQLBIT:
02072                      case SQLINT1:
02073                      case SQLINT2:
02074                      case SQLINT4:
02075                             convert_to_long_ex(var);
02076                             value=(LPBYTE)(&Z_LVAL_PP(var));
02077                             break;
02078 
02079                      default:
02080                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported type");
02081                             RETURN_FALSE;
02082                             break;
02083               }
02084        }
02085        
02086        if (is_output) {
02087               status=DBRPCRETURN;
02088        }
02089        
02090        /* hashtable of binds */
02091        if (! statement->binds) {
02092               ALLOC_HASHTABLE(statement->binds);
02093               zend_hash_init(statement->binds, 13, NULL, _mssql_bind_hash_dtor, 0);
02094        }
02095 
02096        if (zend_hash_exists(statement->binds, param_name, param_name_len)) {
02097               RETURN_FALSE;
02098        }
02099        else {
02100               memset((void*)&bind,0,sizeof(mssql_bind));
02101               zend_hash_add(statement->binds, param_name, param_name_len, &bind, sizeof(mssql_bind), (void **)&bindp);
02102               if( NULL == bindp ) RETURN_FALSE;
02103               bindp->zval=*var;
02104               zval_add_ref(var);
02105        
02106               /* no call to dbrpcparam if RETVAL */
02107               if ( strcmp("RETVAL", param_name)!=0 ) {                                     
02108                      if (dbrpcparam(mssql_ptr->link, param_name, (BYTE)status, type, maxlen, datalen, (LPBYTE)value)==FAIL) {
02109                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set parameter");
02110                             RETURN_FALSE;
02111                      }
02112               }
02113        }
02114 
02115        RETURN_TRUE;
02116 }
02117 /* }}} */
02118 
02119 /* {{{ proto mixed mssql_execute(resource stmt [, bool skip_results = false])
02120    Executes a stored procedure on a MS-SQL server database */
02121 PHP_FUNCTION(mssql_execute)
02122 {
02123        zval *stmt;
02124        zend_bool skip_results = 0;
02125        int retvalue, retval_results;
02126        mssql_link *mssql_ptr;
02127        mssql_statement *statement;
02128        mssql_result *result;
02129        int num_fields;
02130        int batchsize;
02131        int exec_retval;
02132 
02133        batchsize = MS_SQL_G(batchsize);
02134 
02135        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &stmt, &skip_results) == FAILURE) {
02136               return;
02137        }
02138 
02139        ZEND_FETCH_RESOURCE(statement, mssql_statement *, &stmt, -1, "MS SQL-Statement", le_statement);
02140 
02141        mssql_ptr=statement->link;
02142        exec_retval = dbrpcexec(mssql_ptr->link);
02143 
02144        if (exec_retval == FAIL || dbsqlok(mssql_ptr->link) == FAIL) {
02145               php_error_docref(NULL TSRMLS_CC, E_WARNING, "stored procedure execution failed");
02146 
02147               if (exec_retval == FAIL) {
02148                      dbcancel(mssql_ptr->link);
02149               }
02150 
02151               RETURN_FALSE;
02152        }
02153 
02154        retval_results=dbresults(mssql_ptr->link);
02155 
02156        if (retval_results==FAIL) {
02157               php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not retrieve results");
02158               dbcancel(mssql_ptr->link);
02159               RETURN_FALSE;
02160        }
02161 
02162        /* The following is just like mssql_query, fetch all rows from the first result 
02163         *     set into the row buffer. 
02164         */
02165        result=NULL;
02166        if (retval_results == SUCCEED) {
02167               if (skip_results) {
02168                      do {
02169                             dbcanquery(mssql_ptr->link);
02170                             retval_results = dbresults(mssql_ptr->link);
02171                      } while (retval_results == SUCCEED);
02172               }
02173               else {
02174                      /* Skip results not returning any columns */
02175                      while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retval_results == SUCCEED) {
02176                             retval_results = dbresults(mssql_ptr->link);
02177                      }
02178                      if ((num_fields = dbnumcols(mssql_ptr->link)) > 0) {
02179                             retvalue = dbnextrow(mssql_ptr->link);
02180                             result = (mssql_result *) emalloc(sizeof(mssql_result));
02181                             result->batchsize = batchsize;
02182                             result->blocks_initialized = 1;
02183                             result->data = (zval **) safe_emalloc(sizeof(zval *), MSSQL_ROWS_BLOCK, 0);
02184                             result->mssql_ptr = mssql_ptr;
02185                             result->cur_field=result->cur_row=result->num_rows=0;
02186                             result->num_fields = num_fields;
02187                             result->have_fields = 0;
02188 
02189                             result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), num_fields, 0);
02190                             result->statement = statement;
02191                             result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
02192                      }
02193               }
02194        }
02195        if (retval_results == NO_MORE_RESULTS || retval_results == NO_MORE_RPC_RESULTS) {
02196               _mssql_get_sp_result(mssql_ptr, statement TSRMLS_CC);
02197        }
02198        
02199        if (result==NULL) {
02200               RETURN_TRUE;  /* no recordset returned ...*/
02201        }
02202        else {
02203               ZEND_REGISTER_RESOURCE(return_value, result, le_result);
02204        }
02205 }
02206 /* }}} */
02207 
02208 /* {{{ proto bool mssql_free_statement(resource result_index)
02209    Free a MS-SQL statement index */
02210 PHP_FUNCTION(mssql_free_statement)
02211 {
02212        zval *mssql_statement_index;
02213        mssql_statement *statement;
02214        int retvalue;
02215 
02216        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_statement_index) == FAILURE) {
02217               return;
02218        }
02219        
02220        if (Z_RESVAL_P(mssql_statement_index) == 0) {
02221               RETURN_FALSE;
02222        }
02223 
02224        ZEND_FETCH_RESOURCE(statement, mssql_statement *, &mssql_statement_index, -1, "MS SQL-statement", le_statement);       
02225        /* Release remaining results */
02226        do {
02227               dbcanquery(statement->link->link);
02228               retvalue = dbresults(statement->link->link);
02229        } while (retvalue == SUCCEED);
02230 
02231        zend_list_delete(Z_RESVAL_P(mssql_statement_index));
02232        RETURN_TRUE;
02233 }
02234 /* }}} */
02235 
02236 /* {{{ proto string mssql_guid_string(string binary [,bool short_format])
02237    Converts a 16 byte binary GUID to a string  */
02238 PHP_FUNCTION(mssql_guid_string)
02239 {
02240        char *binary;
02241        int binary_len;
02242        zend_bool sf = 0;
02243        char buffer[32+1];
02244        char buffer2[36+1];
02245 
02246        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &binary, &binary_len, &sf) == FAILURE) {
02247               return;
02248        }
02249 
02250        dbconvert(NULL, SQLBINARY, (BYTE*) binary, MIN(16, binary_len), SQLCHAR, buffer, -1);
02251 
02252        if (sf) {
02253               php_strtoupper(buffer, 32);
02254               RETURN_STRING(buffer, 1);
02255        }
02256        else {
02257               int i;
02258               /* FIXME this works only on little endian machine */
02259               for (i=0; i<4; i++) {
02260                      buffer2[2*i] = buffer[6-2*i];
02261                      buffer2[2*i+1] = buffer[7-2*i];
02262               }
02263               buffer2[8] = '-';
02264               for (i=0; i<2; i++) {
02265                      buffer2[9+2*i] = buffer[10-2*i];
02266                      buffer2[10+2*i] = buffer[11-2*i];
02267               }
02268               buffer2[13] = '-';
02269               for (i=0; i<2; i++) {
02270                      buffer2[14+2*i] = buffer[14-2*i];
02271                      buffer2[15+2*i] = buffer[15-2*i];
02272               }
02273               buffer2[18] = '-';
02274               for (i=0; i<4; i++) {
02275                      buffer2[19+i] = buffer[16+i];
02276               }
02277               buffer2[23] = '-';
02278               for (i=0; i<12; i++) {
02279                      buffer2[24+i] = buffer[20+i];
02280               }
02281               buffer2[36] = 0;
02282 
02283               php_strtoupper(buffer2, 36);
02284               RETURN_STRING(buffer2, 1);
02285        }
02286 }
02287 /* }}} */
02288 
02289 #endif