Annotation of embedaddon/php/ext/mssql/php_mssql.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 The PHP Group                                |
                      6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Author: Frank M. Kromann <frank@kromann.info>                        |
                     16:    +----------------------------------------------------------------------+
                     17:  */
                     18: 
1.1.1.2 ! misho      19: /* $Id$ */
1.1       misho      20: 
                     21: #ifdef COMPILE_DL_MSSQL
                     22: #define HAVE_MSSQL 1
                     23: #endif
                     24: 
                     25: #ifdef HAVE_CONFIG_H
                     26: #include "config.h"
                     27: #endif
                     28: 
                     29: #include "php.h"
                     30: #include "php_globals.h"
                     31: #include "ext/standard/php_standard.h"
                     32: #include "ext/standard/info.h"
                     33: #include "php_mssql.h"
                     34: #include "php_ini.h"
                     35: 
                     36: #if HAVE_MSSQL
                     37: #define SAFE_STRING(s) ((s)?(s):"")
                     38: 
                     39: #define MSSQL_ASSOC            1<<0
                     40: #define MSSQL_NUM              1<<1
                     41: #define MSSQL_BOTH             (MSSQL_ASSOC|MSSQL_NUM)
                     42: 
                     43: static int le_result, le_link, le_plink, le_statement;
                     44: 
                     45: static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC);
                     46: static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC);
                     47: 
                     48: static void _mssql_bind_hash_dtor(void *data);
                     49: 
                     50: /* {{{ arginfo */
                     51: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_connect, 0, 0, 0)
                     52:        ZEND_ARG_INFO(0, servername)
                     53:        ZEND_ARG_INFO(0, username)
                     54:        ZEND_ARG_INFO(0, password)
                     55:        ZEND_ARG_INFO(0, newlink)
                     56: ZEND_END_ARG_INFO()
                     57: 
                     58: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_close, 0, 0, 0)
                     59:        ZEND_ARG_INFO(0, link_identifier)
                     60: ZEND_END_ARG_INFO()
                     61: 
                     62: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_select_db, 0, 0, 1)
                     63:        ZEND_ARG_INFO(0, database_name)
                     64:        ZEND_ARG_INFO(0, link_identifier)
                     65: ZEND_END_ARG_INFO()
                     66: 
                     67: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_query, 0, 0, 1)
                     68:        ZEND_ARG_INFO(0, query)
                     69:        ZEND_ARG_INFO(0, link_identifier)
                     70:        ZEND_ARG_INFO(0, batch_size)
                     71: ZEND_END_ARG_INFO()
                     72: 
                     73: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_batch, 0, 0, 1)
                     74:        ZEND_ARG_INFO(0, result)
                     75: ZEND_END_ARG_INFO()
                     76: 
                     77: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_rows_affected, 0, 0, 1)
                     78:        ZEND_ARG_INFO(0, link_identifier)
                     79: ZEND_END_ARG_INFO()
                     80: 
                     81: ZEND_BEGIN_ARG_INFO(arginfo_mssql_get_last_message, 0)
                     82: ZEND_END_ARG_INFO()
                     83: 
                     84: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_field, 0, 0, 1)
                     85:        ZEND_ARG_INFO(0, result)
                     86:        ZEND_ARG_INFO(0, field_offset)
                     87: ZEND_END_ARG_INFO()
                     88: 
                     89: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_array, 0, 0, 1)
                     90:        ZEND_ARG_INFO(0, result)
                     91:        ZEND_ARG_INFO(0, result_type)
                     92: ZEND_END_ARG_INFO()
                     93: 
                     94: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_assoc, 0, 0, 1)
                     95:        ZEND_ARG_INFO(0, result_id)
                     96: ZEND_END_ARG_INFO()
                     97: 
                     98: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_field_length, 0, 0, 1)
                     99:        ZEND_ARG_INFO(0, result)
                    100:        ZEND_ARG_INFO(0, offset)
                    101: ZEND_END_ARG_INFO()
                    102: 
                    103: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_data_seek, 0, 0, 2)
                    104:        ZEND_ARG_INFO(0, result_identifier)
                    105:        ZEND_ARG_INFO(0, row_number)
                    106: ZEND_END_ARG_INFO()
                    107: 
                    108: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_result, 0, 0, 3)
                    109:        ZEND_ARG_INFO(0, result)
                    110:        ZEND_ARG_INFO(0, row)
                    111:        ZEND_ARG_INFO(0, field)
                    112: ZEND_END_ARG_INFO()
                    113: 
                    114: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_min_error_severity, 0, 0, 1)
                    115:        ZEND_ARG_INFO(0, severity)
                    116: ZEND_END_ARG_INFO()
                    117: 
                    118: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_init, 0, 0, 1)
                    119:        ZEND_ARG_INFO(0, sp_name)
                    120:        ZEND_ARG_INFO(0, link_identifier)
                    121: ZEND_END_ARG_INFO()
                    122: 
                    123: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_bind, 0, 0, 4)
                    124:        ZEND_ARG_INFO(0, stmt)
                    125:        ZEND_ARG_INFO(0, param_name)
                    126:        ZEND_ARG_INFO(1, var)
                    127:        ZEND_ARG_INFO(0, type)
                    128:        ZEND_ARG_INFO(0, is_output)
                    129:        ZEND_ARG_INFO(0, is_null)
                    130:        ZEND_ARG_INFO(0, maxlen)
                    131: ZEND_END_ARG_INFO()
                    132: 
                    133: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_execute, 0, 0, 1)
                    134:        ZEND_ARG_INFO(0, stmt)
                    135:        ZEND_ARG_INFO(0, skip_results)
                    136: ZEND_END_ARG_INFO()
                    137: 
                    138: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_free_statement, 0, 0, 1)
                    139:        ZEND_ARG_INFO(0, stmt)
                    140: ZEND_END_ARG_INFO()
                    141: 
                    142: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_guid_string, 0, 0, 1)
                    143:        ZEND_ARG_INFO(0, binary)
                    144:        ZEND_ARG_INFO(0, short_format)
                    145: ZEND_END_ARG_INFO()
                    146: /* }}} */
                    147: 
                    148: /* {{{ mssql_functions
                    149: */
                    150: const zend_function_entry mssql_functions[] = {
                    151:        PHP_FE(mssql_connect,                           arginfo_mssql_connect)
                    152:        PHP_FE(mssql_pconnect,                          arginfo_mssql_connect)
                    153:        PHP_FE(mssql_close,                                     arginfo_mssql_close)
                    154:        PHP_FE(mssql_select_db,                         arginfo_mssql_select_db)
                    155:        PHP_FE(mssql_query,                                     arginfo_mssql_query)
                    156:        PHP_FE(mssql_fetch_batch,                       arginfo_mssql_fetch_batch)
                    157:        PHP_FE(mssql_rows_affected,                     arginfo_mssql_rows_affected)
                    158:        PHP_FE(mssql_free_result,                       arginfo_mssql_fetch_batch)
                    159:        PHP_FE(mssql_get_last_message,          arginfo_mssql_get_last_message)
                    160:        PHP_FE(mssql_num_rows,                          arginfo_mssql_fetch_batch)
                    161:        PHP_FE(mssql_num_fields,                        arginfo_mssql_fetch_batch)
                    162:        PHP_FE(mssql_fetch_field,                       arginfo_mssql_fetch_field)
                    163:        PHP_FE(mssql_fetch_row,                         arginfo_mssql_fetch_batch)
                    164:        PHP_FE(mssql_fetch_array,                       arginfo_mssql_fetch_array)
                    165:        PHP_FE(mssql_fetch_assoc,                       arginfo_mssql_fetch_assoc)
                    166:        PHP_FE(mssql_fetch_object,                      arginfo_mssql_fetch_batch)
                    167:        PHP_FE(mssql_field_length,                      arginfo_mssql_field_length)
                    168:        PHP_FE(mssql_field_name,                        arginfo_mssql_field_length)
                    169:        PHP_FE(mssql_field_type,                        arginfo_mssql_field_length)
                    170:        PHP_FE(mssql_data_seek,                         arginfo_mssql_data_seek)
                    171:        PHP_FE(mssql_field_seek,                        arginfo_mssql_fetch_field)
                    172:        PHP_FE(mssql_result,                            arginfo_mssql_result)
                    173:        PHP_FE(mssql_next_result,                       arginfo_mssql_fetch_assoc)
                    174:        PHP_FE(mssql_min_error_severity,        arginfo_mssql_min_error_severity)
                    175:        PHP_FE(mssql_min_message_severity,      arginfo_mssql_min_error_severity)
                    176:        PHP_FE(mssql_init,                                      arginfo_mssql_init)
                    177:        PHP_FE(mssql_bind,                                      arginfo_mssql_bind)
                    178:        PHP_FE(mssql_execute,                           arginfo_mssql_execute)
                    179:        PHP_FE(mssql_free_statement,            arginfo_mssql_free_statement)
                    180:        PHP_FE(mssql_guid_string,                       arginfo_mssql_guid_string)
                    181:        PHP_FE_END
                    182: };
                    183: /* }}} */
                    184: 
                    185: ZEND_DECLARE_MODULE_GLOBALS(mssql)
                    186: static PHP_GINIT_FUNCTION(mssql);
                    187: 
                    188: /* {{{ mssql_module_entry
                    189: */
                    190: zend_module_entry mssql_module_entry = 
                    191: {
                    192:        STANDARD_MODULE_HEADER,
                    193:        "mssql", 
                    194:        mssql_functions, 
                    195:        PHP_MINIT(mssql), 
                    196:        PHP_MSHUTDOWN(mssql), 
                    197:        PHP_RINIT(mssql), 
                    198:        PHP_RSHUTDOWN(mssql), 
                    199:        PHP_MINFO(mssql), 
                    200:        NO_VERSION_YET,
                    201:        PHP_MODULE_GLOBALS(mssql),
                    202:        PHP_GINIT(mssql),
                    203:        NULL,
                    204:        NULL,
                    205:        STANDARD_MODULE_PROPERTIES_EX
                    206: };
                    207: /* }}} */
                    208: 
                    209: #ifdef COMPILE_DL_MSSQL
                    210: ZEND_GET_MODULE(mssql)
                    211: #endif
                    212: 
                    213: #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; } }
                    214: 
                    215: /* {{{ PHP_INI_DISP
                    216: */
                    217: static PHP_INI_DISP(display_text_size)
                    218: {
                    219:        char *value;
                    220:        TSRMLS_FETCH();
                    221:        
                    222:     if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
                    223:                value = ini_entry->orig_value;
                    224:        } else if (ini_entry->value) {
                    225:                value = ini_entry->value;
                    226:        } else {
                    227:                value = NULL;
                    228:        }
                    229: 
                    230:        if (atoi(value) == -1) {
                    231:                PUTS("Server default");
                    232:        } else {
                    233:                php_printf("%s", value);
                    234:        }
                    235: }
                    236: /* }}} */
                    237: 
                    238: /* {{{ PHP_INI
                    239: */
                    240: PHP_INI_BEGIN()
                    241:        STD_PHP_INI_BOOLEAN("mssql.allow_persistent",           "1",    PHP_INI_SYSTEM, OnUpdateBool,   allow_persistent,                       zend_mssql_globals,             mssql_globals)
                    242:        STD_PHP_INI_ENTRY_EX("mssql.max_persistent",            "-1",   PHP_INI_SYSTEM, OnUpdateLong,   max_persistent,                         zend_mssql_globals,             mssql_globals,  display_link_numbers)
                    243:        STD_PHP_INI_ENTRY_EX("mssql.max_links",                         "-1",   PHP_INI_SYSTEM, OnUpdateLong,   max_links,                                      zend_mssql_globals,             mssql_globals,  display_link_numbers)
                    244:        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)
                    245:        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)
                    246:        STD_PHP_INI_BOOLEAN("mssql.compatability_mode",         "0",    PHP_INI_ALL,    OnUpdateBool,   compatability_mode,                     zend_mssql_globals,             mssql_globals)
                    247:        STD_PHP_INI_ENTRY_EX("mssql.connect_timeout",           "5",    PHP_INI_ALL,    OnUpdateLong,   connect_timeout,                        zend_mssql_globals,             mssql_globals,  display_link_numbers)
                    248:        STD_PHP_INI_ENTRY_EX("mssql.timeout",                           "60",   PHP_INI_ALL,    OnUpdateLong,   timeout,                                        zend_mssql_globals,             mssql_globals,  display_link_numbers)
                    249:        STD_PHP_INI_ENTRY_EX("mssql.textsize",                          "-1",   PHP_INI_ALL,    OnUpdateLong,   textsize,                                       zend_mssql_globals,             mssql_globals,  display_text_size)
                    250:        STD_PHP_INI_ENTRY_EX("mssql.textlimit",                         "-1",   PHP_INI_ALL,    OnUpdateLong,   textlimit,                                      zend_mssql_globals,             mssql_globals,  display_text_size)
                    251:        STD_PHP_INI_ENTRY_EX("mssql.batchsize",                         "0",    PHP_INI_ALL,    OnUpdateLong,   batchsize,                                      zend_mssql_globals,             mssql_globals,  display_link_numbers)
                    252:        STD_PHP_INI_BOOLEAN("mssql.datetimeconvert",            "1",    PHP_INI_ALL,    OnUpdateBool,   datetimeconvert,                        zend_mssql_globals,             mssql_globals)
                    253:        STD_PHP_INI_BOOLEAN("mssql.secure_connection",          "0",    PHP_INI_SYSTEM, OnUpdateBool,   secure_connection,                      zend_mssql_globals,             mssql_globals)
                    254:        STD_PHP_INI_ENTRY_EX("mssql.max_procs",                         "-1",   PHP_INI_ALL,    OnUpdateLong,   max_procs,                                      zend_mssql_globals,             mssql_globals,  display_link_numbers)
                    255: #ifdef HAVE_FREETDS
                    256:        STD_PHP_INI_ENTRY("mssql.charset",                                      "",             PHP_INI_ALL,    OnUpdateString, charset,                                        zend_mssql_globals,             mssql_globals)
                    257: #endif
                    258: PHP_INI_END()
                    259: /* }}} */
                    260: 
                    261: /* error handler */
                    262: static int php_mssql_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
                    263: {
                    264:        TSRMLS_FETCH();
                    265: 
                    266:        if (severity >= MS_SQL_G(min_error_severity)) {
                    267:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (severity %d)", dberrstr, severity);
                    268:        }
                    269:        return INT_CANCEL;  
                    270: }
                    271: 
                    272: /* {{{ php_mssql_message_handler
                    273: */
                    274: /* message handler */
                    275: static int php_mssql_message_handler(DBPROCESS *dbproc, DBINT msgno,int msgstate, int severity,char *msgtext,char *srvname, char *procname,DBUSMALLINT line)
                    276: {
                    277:        TSRMLS_FETCH();
                    278: 
                    279:        if (severity >= MS_SQL_G(min_message_severity)) {
                    280:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "message: %s (severity %d)", msgtext, severity);
                    281:        }
                    282:        if (MS_SQL_G(server_message)) {
                    283:                STR_FREE(MS_SQL_G(server_message));
                    284:                MS_SQL_G(server_message) = NULL;
                    285:        }
                    286:        MS_SQL_G(server_message) = estrdup(msgtext);
                    287:        return 0;
                    288: }
                    289: /* }}} */
                    290: 
                    291: /* {{{ _clean_invalid_results
                    292: */
                    293: static int _clean_invalid_results(zend_rsrc_list_entry *le TSRMLS_DC)
                    294: {
                    295:        if (Z_TYPE_P(le) == le_result) {
                    296:                mssql_link *mssql_ptr = ((mssql_result *) le->ptr)->mssql_ptr;
                    297:                
                    298:                if (!mssql_ptr->valid) {
                    299:                        return 1;
                    300:                }
                    301:        }
                    302:        return 0;
                    303: }
                    304: /* }}} */
                    305: 
                    306: /* {{{ _free_result
                    307: */
                    308: static void _free_result(mssql_result *result, int free_fields) 
                    309: {
                    310:        int i,j;
                    311: 
                    312:        if (result->data) {
                    313:                for (i=0; i<result->num_rows; i++) {
                    314:                        if (result->data[i]) {
                    315:                                for (j=0; j<result->num_fields; j++) {
                    316:                                        zval_dtor(&result->data[i][j]);
                    317:                                }
                    318:                                efree(result->data[i]);
                    319:                        }
                    320:                }
                    321:                efree(result->data);
                    322:                result->data = NULL;
                    323:                result->blocks_initialized = 0;
                    324:        }
                    325:        
                    326:        if (free_fields && result->fields) {
                    327:                for (i=0; i<result->num_fields; i++) {
                    328:                        STR_FREE(result->fields[i].name);
                    329:                        STR_FREE(result->fields[i].column_source);
                    330:                }
                    331:                efree(result->fields);
                    332:        }
                    333: }
                    334: /* }}} */
                    335: 
                    336: /* {{{ _free_mssql_statement
                    337: */
                    338: static void _free_mssql_statement(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                    339: {
                    340:        mssql_statement *statement = (mssql_statement *)rsrc->ptr;
                    341: 
                    342:        if (statement->binds) {
                    343:                zend_hash_destroy(statement->binds);
                    344:                efree(statement->binds);
                    345:        }
                    346:        
                    347:        efree(statement);
                    348: }
                    349: /* }}} */
                    350: 
                    351: /* {{{ _free_mssql_result
                    352: */
                    353: static void _free_mssql_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                    354: {
                    355:        mssql_result *result = (mssql_result *)rsrc->ptr;
                    356: 
                    357:        _free_result(result, 1);
                    358:        dbcancel(result->mssql_ptr->link);
                    359:        efree(result);
                    360: }
                    361: /* }}} */
                    362: 
                    363: /* {{{ php_mssql_set_defaullt_link
                    364: */
                    365: static void php_mssql_set_default_link(int id TSRMLS_DC)
                    366: {
                    367:        if (MS_SQL_G(default_link)!=-1) {
                    368:                zend_list_delete(MS_SQL_G(default_link));
                    369:        }
                    370:        MS_SQL_G(default_link) = id;
                    371:        zend_list_addref(id);
                    372: }
                    373: /* }}} */
                    374: 
                    375: /* {{{ _close_mssql_link
                    376: */
                    377: static void _close_mssql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                    378: {
                    379:        mssql_link *mssql_ptr = (mssql_link *)rsrc->ptr;
                    380: 
                    381:        mssql_ptr->valid = 0;
                    382:        zend_hash_apply(&EG(regular_list),(apply_func_t) _clean_invalid_results TSRMLS_CC);
                    383:        dbclose(mssql_ptr->link);
                    384:        dbfreelogin(mssql_ptr->login);
                    385:        efree(mssql_ptr);
                    386:        MS_SQL_G(num_links)--;
                    387: }
                    388: /* }}} */
                    389: 
                    390: /* {{{ _close_mssql_plink
                    391: */
                    392: static void _close_mssql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                    393: {
                    394:        mssql_link *mssql_ptr = (mssql_link *)rsrc->ptr;
                    395: 
                    396:        dbclose(mssql_ptr->link);
                    397:        dbfreelogin(mssql_ptr->login);
                    398:        free(mssql_ptr);
                    399:        MS_SQL_G(num_persistent)--;
                    400:        MS_SQL_G(num_links)--;
                    401: }
                    402: /* }}} */
                    403: 
                    404: /* {{{ _mssql_bind_hash_dtor
                    405: */
                    406: static void _mssql_bind_hash_dtor(void *data)
                    407: {
                    408:        mssql_bind *bind= (mssql_bind *) data;
                    409: 
                    410:        zval_ptr_dtor(&(bind->zval));
                    411: }
                    412: /* }}} */
                    413: 
                    414: /* {{{ PHP_GINIT_FUNCTION
                    415: */
                    416: static PHP_GINIT_FUNCTION(mssql)
                    417: {
                    418:        long compatability_mode;
                    419: 
                    420:        mssql_globals->num_persistent = 0;
                    421:        mssql_globals->get_column_content = php_mssql_get_column_content_with_type;
                    422:        if (cfg_get_long("mssql.compatability_mode", &compatability_mode) == SUCCESS) {
                    423:                if (compatability_mode) {
                    424:                        mssql_globals->get_column_content = php_mssql_get_column_content_without_type;  
                    425:                }
                    426:        }
                    427: }
                    428: /* }}} */
                    429: 
                    430: /* {{{ PHP_MINIT_FUNCTION
                    431: */
                    432: PHP_MINIT_FUNCTION(mssql)
                    433: {
                    434:        REGISTER_INI_ENTRIES();
                    435: 
                    436:        le_statement = zend_register_list_destructors_ex(_free_mssql_statement, NULL, "mssql statement", module_number);
                    437:        le_result = zend_register_list_destructors_ex(_free_mssql_result, NULL, "mssql result", module_number);
                    438:        le_link = zend_register_list_destructors_ex(_close_mssql_link, NULL, "mssql link", module_number);
                    439:        le_plink = zend_register_list_destructors_ex(NULL, _close_mssql_plink, "mssql link persistent", module_number);
                    440:        Z_TYPE(mssql_module_entry) = type;
                    441: 
                    442:        if (dbinit()==FAIL) {
                    443:                return FAILURE;
                    444:        }
                    445: 
                    446:        /* BEGIN MSSQL data types for mssql_bind */
                    447:        REGISTER_LONG_CONSTANT("MSSQL_ASSOC", MSSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
                    448:        REGISTER_LONG_CONSTANT("MSSQL_NUM", MSSQL_NUM, CONST_CS | CONST_PERSISTENT);
                    449:        REGISTER_LONG_CONSTANT("MSSQL_BOTH", MSSQL_BOTH, CONST_CS | CONST_PERSISTENT);
                    450: 
                    451:        REGISTER_LONG_CONSTANT("SQLTEXT",SQLTEXT, CONST_CS | CONST_PERSISTENT);
                    452:        REGISTER_LONG_CONSTANT("SQLVARCHAR",SQLVARCHAR, CONST_CS | CONST_PERSISTENT);
                    453:        REGISTER_LONG_CONSTANT("SQLCHAR",SQLCHAR, CONST_CS | CONST_PERSISTENT);
                    454:        REGISTER_LONG_CONSTANT("SQLINT1",SQLINT1, CONST_CS | CONST_PERSISTENT);
                    455:        REGISTER_LONG_CONSTANT("SQLINT2",SQLINT2, CONST_CS | CONST_PERSISTENT);
                    456:        REGISTER_LONG_CONSTANT("SQLINT4",SQLINT4, CONST_CS | CONST_PERSISTENT);
                    457:        REGISTER_LONG_CONSTANT("SQLBIT",SQLBIT, CONST_CS | CONST_PERSISTENT);
                    458:        REGISTER_LONG_CONSTANT("SQLFLT4",SQLFLT4, CONST_CS | CONST_PERSISTENT);
                    459:        REGISTER_LONG_CONSTANT("SQLFLT8",SQLFLT8, CONST_CS | CONST_PERSISTENT);
                    460:        REGISTER_LONG_CONSTANT("SQLFLTN",SQLFLTN, CONST_CS | CONST_PERSISTENT);
                    461:        /* END MSSQL data types for mssql_bind */
                    462: 
                    463:        return SUCCESS;
                    464: }
                    465: /* }}} */
                    466: 
                    467: /* {{{ PHP_MSHUTDOWN_FUNCTION
                    468: */
                    469: PHP_MSHUTDOWN_FUNCTION(mssql)
                    470: {
                    471:        UNREGISTER_INI_ENTRIES();
                    472: #ifndef HAVE_FREETDS
                    473:        dbwinexit();
                    474: #else
                    475:        dbexit();
                    476: #endif
                    477:        return SUCCESS;
                    478: }
                    479: /* }}} */
                    480: 
                    481: /* {{{ PHP_RINIT_FUNCTION
                    482: */
                    483: PHP_RINIT_FUNCTION(mssql)
                    484: {
                    485:        MS_SQL_G(default_link) = -1;
                    486:        MS_SQL_G(num_links) = MS_SQL_G(num_persistent);
                    487:        MS_SQL_G(appname) = estrndup("PHP 5", 5);
                    488:        MS_SQL_G(server_message) = NULL;
                    489:        MS_SQL_G(min_error_severity) = MS_SQL_G(cfg_min_error_severity);
                    490:        MS_SQL_G(min_message_severity) = MS_SQL_G(cfg_min_message_severity);
                    491:        if (MS_SQL_G(connect_timeout) < 1) MS_SQL_G(connect_timeout) = 1;
                    492:        if (MS_SQL_G(timeout) < 0) MS_SQL_G(timeout) = 60;
                    493:        if (MS_SQL_G(max_procs) != -1) {
                    494:                dbsetmaxprocs((TDS_SHORT)MS_SQL_G(max_procs));
                    495:        }
                    496: 
                    497:        return SUCCESS;
                    498: }
                    499: /* }}} */
                    500: 
                    501: /* {{{ PHP_RSHUTDOWN_FUNCTION
                    502: */
                    503: PHP_RSHUTDOWN_FUNCTION(mssql)
                    504: {
                    505:        STR_FREE(MS_SQL_G(appname));
                    506:        MS_SQL_G(appname) = NULL;
                    507:        if (MS_SQL_G(server_message)) {
                    508:                STR_FREE(MS_SQL_G(server_message));
                    509:                MS_SQL_G(server_message) = NULL;
                    510:        }
                    511:        return SUCCESS;
                    512: }
                    513: /* }}} */
                    514: 
                    515: /* {{{ PHP_MINFO_FUNCTION
                    516: */
                    517: PHP_MINFO_FUNCTION(mssql)
                    518: {
                    519:        char buf[32];
                    520: 
                    521:        php_info_print_table_start();
                    522:        php_info_print_table_header(2, "MSSQL Support", "enabled");
                    523: 
                    524:        snprintf(buf, sizeof(buf), "%ld", MS_SQL_G(num_persistent));
                    525:        php_info_print_table_row(2, "Active Persistent Links", buf);
                    526:        snprintf(buf, sizeof(buf), "%ld", MS_SQL_G(num_links));
                    527:        php_info_print_table_row(2, "Active Links", buf);
                    528: 
                    529:        php_info_print_table_row(2, "Library version", MSSQL_VERSION);
                    530:        php_info_print_table_end();
                    531: 
                    532:        DISPLAY_INI_ENTRIES();
                    533: 
                    534: }
                    535: /* }}} */
                    536: 
                    537: /* {{{ php_mssql_do_connect
                    538: */
                    539: static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                    540: {
                    541:        char *host = NULL, *user = NULL, *passwd = NULL;
                    542:        int host_len = 0, user_len = 0, passwd_len = 0;
                    543:        zend_bool new_link = 0;
                    544:        char *hashed_details;
                    545:        int hashed_details_length;
                    546:        mssql_link mssql, *mssql_ptr;
                    547:        char buffer[40];
                    548: 
                    549:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sssb", &host, &host_len, &user, &user_len, &passwd, &passwd_len, &new_link) == FAILURE) {
                    550:                return;
                    551:        }
                    552: 
                    553:        /* Limit strings to 255 chars to prevent overflow issues in underlying libraries */
                    554:        if(host_len>255) {
                    555:                host[255] = '\0';
                    556:        }
                    557:        if(user_len>255) {
                    558:                user[255] = '\0';
                    559:        }
                    560:        if(passwd_len>255) {
                    561:                passwd[255] = '\0';
                    562:        }
                    563: 
                    564:        switch(ZEND_NUM_ARGS())
                    565:        {
                    566:                case 0:
                    567:                        /* defaults */
                    568:                        hashed_details_length=5+3;
                    569:                        hashed_details = (char *) emalloc(hashed_details_length+1);
                    570:                        strcpy(hashed_details, "mssql___");
                    571:                        break;
                    572:                case 1:
                    573:                        hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s__", host);
                    574:                        break;
                    575:                case 2:
                    576:                        hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s_%s_", host, user);
                    577:                        break;
                    578:                case 3:
                    579:                case 4:
                    580:                        hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s_%s_%s", host, user, passwd);
                    581:                        break;
                    582:        }
                    583: 
                    584:        if (hashed_details == NULL) {
                    585:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Out of memory");
                    586:                RETURN_FALSE;
                    587:        }
                    588: 
                    589:        dbsetlogintime(MS_SQL_G(connect_timeout));
                    590:        dbsettime(MS_SQL_G(timeout));
                    591: 
                    592:        /* set a DBLOGIN record */      
                    593:        if ((mssql.login = dblogin()) == NULL) {
                    594:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate login record");
                    595:                RETURN_FALSE;
                    596:        }
                    597:        
                    598:        DBERRHANDLE(mssql.login, (EHANDLEFUNC) php_mssql_error_handler);
                    599:        DBMSGHANDLE(mssql.login, (MHANDLEFUNC) php_mssql_message_handler);
                    600: 
                    601: #ifndef HAVE_FREETDS
                    602:        if (MS_SQL_G(secure_connection)){
                    603:                DBSETLSECURE(mssql.login);
                    604:        }
                    605:        else {
                    606: #endif
                    607:                if (user) {
                    608:                        DBSETLUSER(mssql.login,user);
                    609:                }
                    610:                if (passwd) {
                    611:                        DBSETLPWD(mssql.login,passwd);
                    612:                }
                    613: #ifndef HAVE_FREETDS
                    614:        }
                    615: #endif
                    616: 
                    617: #ifdef HAVE_FREETDS
                    618:                if (MS_SQL_G(charset) && strlen(MS_SQL_G(charset))) {
                    619:                        DBSETLCHARSET(mssql.login, MS_SQL_G(charset));
                    620:                }
                    621: #endif
                    622: 
                    623:        DBSETLAPP(mssql.login,MS_SQL_G(appname));
                    624:        mssql.valid = 1;
                    625: 
                    626: #ifndef HAVE_FREETDS
                    627:        DBSETLVERSION(mssql.login, DBVER60);
                    628: #endif
                    629: /*     DBSETLTIME(mssql.login, TIMEOUT_INFINITE); */
                    630: 
                    631:        if (!MS_SQL_G(allow_persistent)) {
                    632:                persistent=0;
                    633:        }
                    634:        if (persistent) {
                    635:                zend_rsrc_list_entry *le;
                    636: 
                    637:                /* try to find if we already have this link in our persistent list */
                    638:                if (new_link || zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length + 1, (void **) &le)==FAILURE) {  /* we don't */
                    639:                        zend_rsrc_list_entry new_le;
                    640: 
                    641:                        if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) {
                    642:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links));
                    643:                                efree(hashed_details);
                    644:                                dbfreelogin(mssql.login);
                    645:                                RETURN_FALSE;
                    646:                        }
                    647:                        if (MS_SQL_G(max_persistent) != -1 && MS_SQL_G(num_persistent) >= MS_SQL_G(max_persistent)) {
                    648:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)", MS_SQL_G(num_persistent));
                    649:                                efree(hashed_details);
                    650:                                dbfreelogin(mssql.login);
                    651:                                RETURN_FALSE;
                    652:                        }
                    653:                        /* create the link */
                    654:                        if ((mssql.link = dbopen(mssql.login, host)) == FAIL) {
                    655:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", (host == NULL ? "" : host));
                    656:                                efree(hashed_details);
                    657:                                dbfreelogin(mssql.login);
                    658:                                RETURN_FALSE;
                    659:                        }
                    660: 
                    661:                        if (DBSETOPT(mssql.link, DBBUFFER, "2")==FAIL) {
                    662:                                efree(hashed_details);
                    663:                                dbfreelogin(mssql.login);
                    664:                                dbclose(mssql.link);
                    665:                                RETURN_FALSE;
                    666:                        }
                    667: 
                    668: #ifndef HAVE_FREETDS
                    669:                        if (MS_SQL_G(textlimit) != -1) {
                    670:                                snprintf(buffer, sizeof(buffer), "%li", MS_SQL_G(textlimit));
                    671:                                if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) {
                    672:                                        efree(hashed_details);
                    673:                                        dbfreelogin(mssql.login);
                    674:                                        dbclose(mssql.link);
                    675:                                        RETURN_FALSE;
                    676:                                }
                    677:                        }
                    678: #endif
                    679:                        if (MS_SQL_G(textsize) != -1) {
                    680:                                snprintf(buffer, sizeof(buffer), "SET TEXTSIZE %li", MS_SQL_G(textsize));
                    681:                                dbcmd(mssql.link, buffer);
                    682:                                dbsqlexec(mssql.link);
                    683:                                dbresults(mssql.link);
                    684:                        }
                    685: 
                    686:                        /* hash it up */
                    687:                        mssql_ptr = (mssql_link *) malloc(sizeof(mssql_link));
                    688:                        if (!mssql_ptr) {
                    689:                                efree(hashed_details);
                    690:                                dbfreelogin(mssql.login);
                    691:                                dbclose(mssql.link);
                    692:                                RETURN_FALSE;
                    693:                        }
                    694: 
                    695:                        memcpy(mssql_ptr, &mssql, sizeof(mssql_link));
                    696:                        Z_TYPE(new_le) = le_plink;
                    697:                        new_le.ptr = mssql_ptr;
                    698:                        if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length + 1, &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
                    699:                                free(mssql_ptr);
                    700:                                efree(hashed_details);
                    701:                                dbfreelogin(mssql.login);
                    702:                                dbclose(mssql.link);
                    703:                                RETURN_FALSE;
                    704:                        }
                    705:                        MS_SQL_G(num_persistent)++;
                    706:                        MS_SQL_G(num_links)++;
                    707:                } else {  /* we do */
                    708:                        if (Z_TYPE_P(le) != le_plink) {
                    709: #if BROKEN_MSSQL_PCONNECTS
                    710:                                log_error("PHP/MS SQL: Hashed persistent link is not a MS SQL link!",php_rqst->server);
                    711: #endif
                    712:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Hashed persistent link is not a MS SQL link!");
                    713:                                efree(hashed_details);
                    714:                                RETURN_FALSE;
                    715:                        }
                    716:                        
                    717:                        mssql_ptr = (mssql_link *) le->ptr;
                    718:                        /* test that the link hasn't died */
                    719:                        if (DBDEAD(mssql_ptr->link) == TRUE) {
                    720:                                dbclose(mssql_ptr->link);
                    721: #if BROKEN_MSSQL_PCONNECTS
                    722:                                log_error("PHP/MS SQL: Persistent link died, trying to reconnect...",php_rqst->server);
                    723: #endif
                    724:                                if ((mssql_ptr->link=dbopen(mssql_ptr->login,host))==NULL) {
                    725: #if BROKEN_MSSQL_PCONNECTS
                    726:                                        log_error("PHP/MS SQL: Unable to reconnect!",php_rqst->server);
                    727: #endif
                    728:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
                    729:                                        zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1);
                    730:                                        efree(hashed_details);
                    731:                                        dbfreelogin(mssql_ptr->login);
                    732:                                        RETURN_FALSE;
                    733:                                }
                    734: #if BROKEN_MSSQL_PCONNECTS
                    735:                                log_error("PHP/MS SQL: Reconnect successful!",php_rqst->server);
                    736: #endif
                    737:                                if (DBSETOPT(mssql_ptr->link, DBBUFFER, "2")==FAIL) {
                    738: #if BROKEN_MSSQL_PCONNECTS
                    739:                                        log_error("PHP/MS SQL: Unable to set required options",php_rqst->server);
                    740: #endif
                    741:                                        zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length + 1);
                    742:                                        efree(hashed_details);
                    743:                                        dbfreelogin(mssql_ptr->login);
                    744:                                        dbclose(mssql_ptr->link);
                    745:                                        RETURN_FALSE;
                    746:                                }
                    747:                        }
                    748:                }
                    749:                ZEND_REGISTER_RESOURCE(return_value, mssql_ptr, le_plink);
                    750:        } else { /* non persistent */
                    751:                zend_rsrc_list_entry *index_ptr, new_index_ptr;
                    752:                
                    753:                /* first we check the hash for the hashed_details key.  if it exists,
                    754:                 * it should point us to the right offset where the actual mssql link sits.
                    755:                 * if it doesn't, open a new mssql link, add it to the resource list,
                    756:                 * and add a pointer to it with hashed_details as the key.
                    757:                 */
                    758:                if (!new_link && zend_hash_find(&EG(regular_list), hashed_details, hashed_details_length + 1,(void **) &index_ptr)==SUCCESS) {
                    759:                        int type,link;
                    760:                        void *ptr;
                    761: 
                    762:                        if (Z_TYPE_P(index_ptr) != le_index_ptr) {
                    763:                                efree(hashed_details);
                    764:                                dbfreelogin(mssql.login);
                    765:                                RETURN_FALSE;
                    766:                        }
                    767:                        link = (int) index_ptr->ptr;
                    768:                        ptr = zend_list_find(link,&type);   /* check if the link is still there */
                    769:                        if (ptr && (type==le_link || type==le_plink)) {
                    770:                                zend_list_addref(link);
                    771:                                Z_LVAL_P(return_value) = link;
                    772:                                php_mssql_set_default_link(link TSRMLS_CC);
                    773:                                Z_TYPE_P(return_value) = IS_RESOURCE;
                    774:                                dbfreelogin(mssql.login);
                    775:                                efree(hashed_details);
                    776:                                return;
                    777:                        } else {
                    778:                                zend_hash_del(&EG(regular_list), hashed_details, hashed_details_length + 1);
                    779:                        }
                    780:                }
                    781:                if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) {
                    782:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links));
                    783:                        efree(hashed_details);
                    784:                        dbfreelogin(mssql.login);
                    785:                        RETURN_FALSE;
                    786:                }
                    787:                
                    788:                if ((mssql.link=dbopen(mssql.login, host))==NULL) {
                    789:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", (host == NULL ? "" : host));
                    790:                        efree(hashed_details);
                    791:                        dbfreelogin(mssql.login);
                    792:                        RETURN_FALSE;
                    793:                }
                    794: 
                    795:                if (DBSETOPT(mssql.link, DBBUFFER,"2")==FAIL) {
                    796:                        efree(hashed_details);
                    797:                        dbfreelogin(mssql.login);
                    798:                        dbclose(mssql.link);
                    799:                        RETURN_FALSE;
                    800:                }
                    801: 
                    802: #ifndef HAVE_FREETDS
                    803:                if (MS_SQL_G(textlimit) != -1) {
                    804:                        snprintf(buffer, sizeof(buffer), "%li", MS_SQL_G(textlimit));
                    805:                        if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) {
                    806:                                efree(hashed_details);
                    807:                                dbfreelogin(mssql.login);
                    808:                                dbclose(mssql.link);
                    809:                                RETURN_FALSE;
                    810:                        }
                    811:                }
                    812: #endif
                    813:                if (MS_SQL_G(textsize) != -1) {
                    814:                        snprintf(buffer, sizeof(buffer), "SET TEXTSIZE %li", MS_SQL_G(textsize));
                    815:                        dbcmd(mssql.link, buffer);
                    816:                        dbsqlexec(mssql.link);
                    817:                        dbresults(mssql.link);
                    818:                }
                    819: 
                    820:                /* add it to the list */
                    821:                mssql_ptr = (mssql_link *) emalloc(sizeof(mssql_link));
                    822:                memcpy(mssql_ptr, &mssql, sizeof(mssql_link));
                    823:                ZEND_REGISTER_RESOURCE(return_value, mssql_ptr, le_link);
                    824:                
                    825:                /* add it to the hash */
                    826:                new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
                    827:                Z_TYPE(new_index_ptr) = le_index_ptr;
                    828:                if (zend_hash_update(&EG(regular_list), hashed_details, hashed_details_length + 1,(void *) &new_index_ptr, sizeof(zend_rsrc_list_entry),NULL)==FAILURE) {
                    829:                        efree(hashed_details);
                    830:                        RETURN_FALSE;
                    831:                }
                    832:                MS_SQL_G(num_links)++;
                    833:        }
                    834:        efree(hashed_details);
                    835:        php_mssql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC);
                    836: }
                    837: /* }}} */
                    838: 
                    839: /* {{{ php_mssql_get_default_link
                    840: */
                    841: static int php_mssql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
                    842: {
                    843:        if (MS_SQL_G(default_link)==-1) { /* no link opened yet, implicitly open one */
                    844:                ht = 0;
                    845:                php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
                    846:        }
                    847:        return MS_SQL_G(default_link);
                    848: }
                    849: /* }}} */
                    850: 
                    851: /* {{{ proto int mssql_connect([string servername [, string username [, string password [, bool new_link]]]])
                    852:    Establishes a connection to a MS-SQL server */
                    853: PHP_FUNCTION(mssql_connect)
                    854: {
                    855:        php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
                    856: }
                    857: /* }}} */
                    858: 
                    859: /* {{{ proto int mssql_pconnect([string servername [, string username [, string password [, bool new_link]]]])
                    860:    Establishes a persistent connection to a MS-SQL server */
                    861: PHP_FUNCTION(mssql_pconnect)
                    862: {
                    863:        php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
                    864: }
                    865: /* }}} */
                    866: 
                    867: /* {{{ proto bool mssql_close([resource conn_id])
                    868:    Closes a connection to a MS-SQL server */
                    869: PHP_FUNCTION(mssql_close)
                    870: {
                    871:        zval *mssql_link_index = NULL;
                    872:        int id = -1;
                    873:        mssql_link *mssql_ptr;
                    874:        
                    875:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mssql_link_index) == FAILURE) {
                    876:                return;
                    877:        }
                    878: 
                    879:        if (mssql_link_index == NULL) {
                    880:                id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
                    881:                CHECK_LINK(id);
                    882:        }
                    883: 
                    884:        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
                    885: 
                    886:        if (mssql_link_index) {
                    887:                zend_list_delete(Z_RESVAL_P(mssql_link_index));
                    888:        } else {
                    889:                zend_list_delete(id);
                    890:        }
                    891: 
                    892:        RETURN_TRUE;
                    893: }
                    894: /* }}} */
                    895: 
                    896: /* {{{ proto bool mssql_select_db(string database_name [, resource conn_id])
                    897:    Select a MS-SQL database */
                    898: PHP_FUNCTION(mssql_select_db)
                    899: {
                    900:        char *db;
                    901:        zval *mssql_link_index = NULL;
                    902:        int db_len;
                    903:        int id = -1;
                    904:        mssql_link  *mssql_ptr;
                    905: 
                    906:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &db, &db_len, &mssql_link_index) == FAILURE) {
                    907:                return;
                    908:        }
                    909: 
                    910:        if (mssql_link_index == NULL) {
                    911:                id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
                    912:                CHECK_LINK(id);
                    913:        }
                    914: 
                    915:        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
                    916:        
                    917:        if (dbuse(mssql_ptr->link, db)==FAIL) {
                    918:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to select database:  %s", db);
                    919:                RETURN_FALSE;
                    920:        } else {
                    921:                RETURN_TRUE;
                    922:        }
                    923: }
                    924: /* }}} */
                    925: 
                    926: /* {{{ php_mssql_get_column_content_with_type
                    927: */
                    928: static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type  TSRMLS_DC)
                    929: {
                    930:        if (dbdata(mssql_ptr->link,offset) == NULL && dbdatlen(mssql_ptr->link,offset) == 0) {
                    931:                ZVAL_NULL(result);
                    932:                return;
                    933:        }
                    934: 
                    935:        switch (column_type)
                    936:        {
                    937:                case SQLBIT:
                    938:                case SQLINT1:
                    939:                case SQLINT2:
                    940:                case SQLINT4:
                    941:                case SQLINTN: { 
                    942:                        ZVAL_LONG(result, (long) anyintcol(offset));
                    943:                        break;
                    944:                } 
                    945:                case SQLCHAR:
                    946:                case SQLVARCHAR:
                    947:                case SQLTEXT: {
                    948:                        int length;
                    949:                        char *data = charcol(offset);
                    950: 
                    951:                        length=dbdatlen(mssql_ptr->link,offset);
                    952: #if ilia_0
                    953:                        while (length>0 && data[length-1] == ' ') { /* nuke trailing whitespace */
                    954:                                length--;
                    955:                        }
                    956: #endif
                    957:                        ZVAL_STRINGL(result, data, length, 1); 
                    958:                        break;
                    959:                }
                    960:                case SQLFLT4:
                    961:                        ZVAL_DOUBLE(result, (double) floatcol4(offset));
                    962:                        break;
                    963:                case SQLMONEY:
                    964:                case SQLMONEY4:
                    965:                case SQLMONEYN: {
                    966:                        DBFLT8 res_buf;
                    967:                        dbconvert(NULL, column_type, dbdata(mssql_ptr->link,offset), 8, SQLFLT8, (LPBYTE)&res_buf, -1);
                    968:                        ZVAL_DOUBLE(result, res_buf);
                    969:                        }
                    970:                        break;
                    971:                case SQLFLT8:
                    972:                        ZVAL_DOUBLE(result, (double) floatcol8(offset));
                    973:                        break;
                    974: #ifdef SQLUNIQUE
                    975:                case SQLUNIQUE: {
                    976: #else
                    977:                case 36: {                      /* FreeTDS hack */
                    978: #endif
                    979:                        char *data = charcol(offset);
                    980: 
                    981:                        /* uniqueidentifier is a 16-byte binary number */
                    982:                        ZVAL_STRINGL(result, data, 16, 1);
                    983:                        }
                    984:                        break;
                    985:                case SQLVARBINARY:
                    986:                case SQLBINARY:
                    987:                case SQLIMAGE: {
                    988:                        int res_length = dbdatlen(mssql_ptr->link, offset);
                    989: 
                    990:                        if (!res_length) {
                    991:                                ZVAL_NULL(result);
                    992:                        } else {
                    993:                                ZVAL_STRINGL(result, (char *)dbdata(mssql_ptr->link, offset), res_length, 1);
                    994:                        }
                    995:                }
                    996:                        break;
                    997:                case SQLNUMERIC:
                    998:                default: {
                    999:                        if (dbwillconvert(column_type,SQLCHAR)) {
                   1000:                                char *res_buf;
                   1001:                                DBDATEREC dateinfo;     
                   1002:                                int res_length = dbdatlen(mssql_ptr->link,offset);
                   1003: 
                   1004:                                if (res_length == -1) {
                   1005:                                        res_length = 255;
                   1006:                                }
                   1007: 
                   1008:                                if ((column_type != SQLDATETIME && column_type != SQLDATETIM4) || MS_SQL_G(datetimeconvert)) {
                   1009: 
                   1010:                                        switch (column_type) {
                   1011:                                                case SQLDATETIME :
                   1012:                                                case SQLDATETIM4 :
                   1013:                                                        res_length += 20;
                   1014:                                                        break;
                   1015:                                                case SQLMONEY :
                   1016:                                                case SQLMONEY4 :
                   1017:                                                case SQLMONEYN :
                   1018:                                                case SQLDECIMAL :
                   1019:                                                case SQLNUMERIC :
                   1020:                                                        res_length += 5;
                   1021:                                                case 127 :
                   1022:                                                        res_length += 20;
                   1023:                                                        break;
                   1024:                                        }
                   1025: 
                   1026:                                        res_buf = (unsigned char *) emalloc(res_length+1);
                   1027:                                        res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR,res_buf,-1);
                   1028:                                        res_buf[res_length] = '\0';
                   1029:                                } else {
                   1030:                                        if (column_type == SQLDATETIM4) {
                   1031:                                                DBDATETIME temp;
                   1032: 
                   1033:                                                dbconvert(NULL, SQLDATETIM4, dbdata(mssql_ptr->link,offset), -1, SQLDATETIME, (LPBYTE) &temp, -1);
                   1034:                                                dbdatecrack(mssql_ptr->link, &dateinfo, &temp);
                   1035:                                        } else {
                   1036:                                                dbdatecrack(mssql_ptr->link, &dateinfo, (DBDATETIME *) dbdata(mssql_ptr->link,offset));
                   1037:                                        }
                   1038:                        
                   1039:                                        res_length = 19;
                   1040:                                        spprintf(&res_buf, 0, "%d-%02d-%02d %02d:%02d:%02d" , dateinfo.year, dateinfo.month, dateinfo.day, dateinfo.hour, dateinfo.minute, dateinfo.second);
                   1041:                                }
                   1042:                
                   1043:                                ZVAL_STRINGL(result, res_buf, res_length, 0);
                   1044:                        } else {
                   1045:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d has unknown data type (%d)", offset, coltype(offset));
                   1046:                                ZVAL_FALSE(result);
                   1047:                        }
                   1048:                }
                   1049:        }
                   1050: }
                   1051: /* }}} */
                   1052: 
                   1053: /* {{{ php_mssql_get_column_content_without_type
                   1054: */
                   1055: static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC)
                   1056: {
                   1057:        if (dbdatlen(mssql_ptr->link,offset) == 0) {
                   1058:                ZVAL_NULL(result);
                   1059:                return;
                   1060:        }
                   1061: 
                   1062:        if (column_type == SQLVARBINARY ||
                   1063:                column_type == SQLBINARY ||
                   1064:                column_type == SQLIMAGE) {
                   1065:                DBBINARY *bin;
                   1066:                unsigned char *res_buf;
                   1067:                int res_length = dbdatlen(mssql_ptr->link, offset);
                   1068: 
                   1069:                if (res_length == 0) {
                   1070:                        ZVAL_NULL(result);
                   1071:                        return;
                   1072:                } else if (res_length < 0) {
                   1073:                        ZVAL_FALSE(result);
                   1074:                        return;
                   1075:                }
                   1076: 
                   1077:                res_buf = (unsigned char *) emalloc(res_length+1);
                   1078:                bin = ((DBBINARY *)dbdata(mssql_ptr->link, offset));
                   1079:                res_buf[res_length] = '\0';
                   1080:                memcpy(res_buf, bin, res_length);
                   1081:                ZVAL_STRINGL(result, res_buf, res_length, 0);
                   1082:        }
                   1083:        else if  (dbwillconvert(coltype(offset),SQLCHAR)) {
                   1084:                unsigned char *res_buf;
                   1085:                DBDATEREC dateinfo;     
                   1086:                int res_length = dbdatlen(mssql_ptr->link,offset);
                   1087: 
                   1088:                if ((column_type != SQLDATETIME && column_type != SQLDATETIM4) || MS_SQL_G(datetimeconvert)) {
                   1089: 
                   1090:                        switch (column_type) {
                   1091:                                case SQLDATETIME :
                   1092:                                case SQLDATETIM4 :
                   1093:                                        res_length += 20;
                   1094:                                        break;
                   1095:                                case SQLMONEY :
                   1096:                                case SQLMONEY4 :
                   1097:                                case SQLMONEYN :
                   1098:                                case SQLDECIMAL :
                   1099:                                case SQLNUMERIC :
                   1100:                                        res_length += 5;
                   1101:                                case 127 :
                   1102:                                        res_length += 20;
                   1103:                                        break;
                   1104:                        }
                   1105:                        
                   1106:                        res_buf = (unsigned char *) emalloc(res_length+1);
                   1107:                        res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR, res_buf, -1);
                   1108:                        res_buf[res_length] = '\0';
                   1109:                } else {
                   1110:                        if (column_type == SQLDATETIM4) {
                   1111:                                DBDATETIME temp;
                   1112: 
                   1113:                                dbconvert(NULL, SQLDATETIM4, dbdata(mssql_ptr->link,offset), -1, SQLDATETIME, (LPBYTE) &temp, -1);
                   1114:                                dbdatecrack(mssql_ptr->link, &dateinfo, &temp);
                   1115:                        } else {
                   1116:                                dbdatecrack(mssql_ptr->link, &dateinfo, (DBDATETIME *) dbdata(mssql_ptr->link,offset));
                   1117:                        }
                   1118:                        
                   1119:                        res_length = 19;
                   1120:                        spprintf(&res_buf, 0, "%d-%02d-%02d %02d:%02d:%02d" , dateinfo.year, dateinfo.month, dateinfo.day, dateinfo.hour, dateinfo.minute, dateinfo.second);
                   1121:                }
                   1122: 
                   1123:                ZVAL_STRINGL(result, res_buf, res_length, 0);
                   1124:        } else {
                   1125:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d has unknown data type (%d)", offset, coltype(offset));
                   1126:                ZVAL_FALSE(result);
                   1127:        }
                   1128: }
                   1129: /* }}} */
                   1130: 
                   1131: /* {{{ _mssql_get_sp_result
                   1132: */
                   1133: static void _mssql_get_sp_result(mssql_link *mssql_ptr, mssql_statement *statement TSRMLS_DC) 
                   1134: {
                   1135:        int i, num_rets, type;
                   1136:        char *parameter;
                   1137:        mssql_bind *bind;
                   1138: 
                   1139:        /* Now to fetch RETVAL and OUTPUT values*/
                   1140:        num_rets = dbnumrets(mssql_ptr->link);
                   1141: 
                   1142:        if (num_rets!=0) {
                   1143:                for (i = 1; i <= num_rets; i++) {
                   1144:                        parameter = (char*)dbretname(mssql_ptr->link, i);
                   1145:                        type = dbrettype(mssql_ptr->link, i);
                   1146:                                                
                   1147:                        if (statement->binds != NULL) { /*      Maybe a non-parameter sp        */
                   1148:                                if (zend_hash_find(statement->binds, parameter, strlen(parameter), (void**)&bind)==SUCCESS) {
                   1149:                                        if (!dbretlen(mssql_ptr->link,i)) {
                   1150:                                                ZVAL_NULL(bind->zval);
                   1151:                                        }
                   1152:                                        else {
                   1153:                                                switch (type) {
                   1154:                                                        case SQLBIT:
                   1155:                                                        case SQLINT1:
                   1156:                                                        case SQLINT2:
                   1157:                                                        case SQLINT4:
                   1158:                                                                convert_to_long_ex(&bind->zval);
                   1159:                                                                /* FIXME this works only on little endian machine !!! */
                   1160:                                                                Z_LVAL_P(bind->zval) = *((int *)(dbretdata(mssql_ptr->link,i)));
                   1161:                                                                break;
                   1162:                                
                   1163:                                                        case SQLFLT4:
                   1164:                                                        case SQLFLT8:
                   1165:                                                        case SQLFLTN:
                   1166:                                                        case SQLMONEY4:
                   1167:                                                        case SQLMONEY:
                   1168:                                                        case SQLMONEYN:
                   1169:                                                                convert_to_double_ex(&bind->zval);
                   1170:                                                                Z_DVAL_P(bind->zval) = *((double *)(dbretdata(mssql_ptr->link,i)));
                   1171:                                                                break;
                   1172:        
                   1173:                                                        case SQLCHAR:
                   1174:                                                        case SQLVARCHAR:
                   1175:                                                        case SQLTEXT:
                   1176:                                                                convert_to_string_ex(&bind->zval);
                   1177:                                                                Z_STRLEN_P(bind->zval) = dbretlen(mssql_ptr->link,i);
                   1178:                                                                Z_STRVAL_P(bind->zval) = estrndup(dbretdata(mssql_ptr->link,i),Z_STRLEN_P(bind->zval));
                   1179:                                                                break;
                   1180:                                                        /* TODO binary */
                   1181:                                                }
                   1182:                                        }
                   1183:                                }
                   1184:                                else {
                   1185:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "An output parameter variable was not provided");
                   1186:                                }
                   1187:                        }
                   1188:                }
                   1189:        }
                   1190:        if (statement->binds != NULL) { /*      Maybe a non-parameter sp        */
                   1191:                if (zend_hash_find(statement->binds, "RETVAL", 6, (void**)&bind)==SUCCESS) {
                   1192:                        if (dbhasretstat(mssql_ptr->link)) {
                   1193:                                convert_to_long_ex(&bind->zval);
                   1194:                                Z_LVAL_P(bind->zval)=dbretstatus(mssql_ptr->link);
                   1195:                        }
                   1196:                        else {
                   1197:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "stored procedure has no return value. Nothing was returned into RETVAL");
                   1198:                        }
                   1199:                }
                   1200:        }
                   1201: }
                   1202: /* }}} */
                   1203: 
                   1204: /* {{{ _mssql_fetch_batch
                   1205: */
                   1206: static int _mssql_fetch_batch(mssql_link *mssql_ptr, mssql_result *result, int retvalue TSRMLS_DC) 
                   1207: {
                   1208:        int i, j = 0;
                   1209:        char computed_buf[16];
                   1210: 
                   1211:        if (!result->have_fields) {
                   1212:                for (i=0; i<result->num_fields; i++) {
                   1213:                        char *source = NULL;
                   1214:                        char *fname = (char *)dbcolname(mssql_ptr->link,i+1);
                   1215:        
                   1216:                        if (*fname) {
                   1217:                                result->fields[i].name = estrdup(fname);
                   1218:                        } else {
                   1219:                                if (j>0) {
                   1220:                                        snprintf(computed_buf,16,"computed%d",j);
                   1221:                                } else {
                   1222:                                        strcpy(computed_buf,"computed");
                   1223:                                }
                   1224:                                result->fields[i].name = estrdup(computed_buf);
                   1225:                                j++;
                   1226:                        }
                   1227:                        result->fields[i].max_length = dbcollen(mssql_ptr->link,i+1);
                   1228:                        source = (char *)dbcolsource(mssql_ptr->link,i+1);
                   1229:                        if (source) {
                   1230:                                result->fields[i].column_source = estrdup(source);
                   1231:                        }
                   1232:                        else {
                   1233:                                result->fields[i].column_source = STR_EMPTY_ALLOC();
                   1234:                        }
                   1235:        
                   1236:                        result->fields[i].type = coltype(i+1);
                   1237:                        /* set numeric flag */
                   1238:                        switch (result->fields[i].type) {
                   1239:                                case SQLINT1:
                   1240:                                case SQLINT2:
                   1241:                                case SQLINT4:
                   1242:                                case SQLINTN:
                   1243:                                case SQLFLT4:
                   1244:                                case SQLFLT8:
                   1245:                                case SQLNUMERIC:
                   1246:                                case SQLDECIMAL:
                   1247:                                        result->fields[i].numeric = 1;
                   1248:                                        break;
                   1249:                                case SQLCHAR:
                   1250:                                case SQLVARCHAR:
                   1251:                                case SQLTEXT:
                   1252:                                default:
                   1253:                                        result->fields[i].numeric = 0;
                   1254:                                        break;
                   1255:                        }
                   1256:                }
                   1257:                result->have_fields = 1;
                   1258:        }
                   1259: 
                   1260:        i=0;
                   1261:        if (!result->data) {
                   1262:                result->data = (zval **) safe_emalloc(sizeof(zval *), MSSQL_ROWS_BLOCK*(++result->blocks_initialized), 0);
                   1263:        }
                   1264:        while (retvalue!=FAIL && retvalue!=NO_MORE_ROWS) {
                   1265:                result->num_rows++;
                   1266:                if (result->num_rows > result->blocks_initialized*MSSQL_ROWS_BLOCK) {
                   1267:                        result->data = (zval **) erealloc(result->data,sizeof(zval *)*MSSQL_ROWS_BLOCK*(++result->blocks_initialized));
                   1268:                }
                   1269:                result->data[i] = (zval *) safe_emalloc(sizeof(zval), result->num_fields, 0);
                   1270:                for (j=0; j<result->num_fields; j++) {
                   1271:                        INIT_ZVAL(result->data[i][j]);
                   1272:                        MS_SQL_G(get_column_content(mssql_ptr, j+1, &result->data[i][j], result->fields[j].type TSRMLS_CC));
                   1273:                }
                   1274:                if (i<result->batchsize || result->batchsize==0) {
                   1275:                        i++;
                   1276:                        dbclrbuf(mssql_ptr->link,DBLASTROW(mssql_ptr->link)); 
                   1277:                        retvalue=dbnextrow(mssql_ptr->link);
                   1278:                }
                   1279:                else
                   1280:                        break;
                   1281:                result->lastresult = retvalue;
                   1282:        }
                   1283:        if (result->statement && (retvalue == NO_MORE_RESULTS || retvalue == NO_MORE_RPC_RESULTS)) {
                   1284:                _mssql_get_sp_result(mssql_ptr, result->statement TSRMLS_CC);
                   1285:        }
                   1286:        return i;
                   1287: }
                   1288: /* }}} */
                   1289: 
                   1290: /* {{{ proto int mssql_fetch_batch(resource result_index)
                   1291:    Returns the next batch of records */
                   1292: PHP_FUNCTION(mssql_fetch_batch)
                   1293: {
                   1294:        zval *mssql_result_index;
                   1295:        mssql_result *result;
                   1296:        mssql_link *mssql_ptr;
                   1297: 
                   1298:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
                   1299:                return;
                   1300:        }
                   1301:        
                   1302:        if (Z_RESVAL_P(mssql_result_index) == 0) {
                   1303:                RETURN_FALSE;
                   1304:        }
                   1305: 
                   1306:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
                   1307: 
                   1308:        mssql_ptr = result->mssql_ptr;
                   1309:        _free_result(result, 0);
                   1310:        result->cur_row=result->num_rows=0;
                   1311:        result->num_rows = _mssql_fetch_batch(mssql_ptr, result, result->lastresult TSRMLS_CC);
                   1312: 
                   1313:        RETURN_LONG(result->num_rows);
                   1314: }
                   1315: /* }}} */
                   1316: 
                   1317: /* {{{ proto resource mssql_query(string query [, resource conn_id [, int batch_size]])
                   1318:    Perform an SQL query on a MS-SQL server database */
                   1319: PHP_FUNCTION(mssql_query)
                   1320: {
                   1321:        char *query;
                   1322:        zval *mssql_link_index = NULL;
                   1323:        int query_len, retvalue, batchsize, num_fields;
                   1324:        long zbatchsize = 0;
                   1325:        mssql_link *mssql_ptr;
                   1326:        mssql_result *result;
                   1327:        int id = -1;
                   1328: 
                   1329:        dbsettime(MS_SQL_G(timeout));
                   1330:        batchsize = MS_SQL_G(batchsize);
                   1331: 
                   1332:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|rl", &query, &query_len, &mssql_link_index, &zbatchsize) == FAILURE) {
                   1333:                return;
                   1334:        }
                   1335: 
                   1336:        switch(ZEND_NUM_ARGS()) {
                   1337:                case 1:
                   1338:                        id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
                   1339:                        CHECK_LINK(id);
                   1340:                        break;
                   1341:                case 3:
                   1342:                        batchsize = (int) zbatchsize;
                   1343:                        break;
                   1344:        }
                   1345: 
                   1346:        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
                   1347:        
                   1348:        if (dbcmd(mssql_ptr->link, query)==FAIL) {
                   1349:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set query");
                   1350:                RETURN_FALSE;
                   1351:        }
                   1352:        if (dbsqlexec(mssql_ptr->link)==FAIL || (retvalue = dbresults(mssql_ptr->link))==FAIL) {
                   1353:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed");
                   1354:                dbcancel(mssql_ptr->link);
                   1355:                RETURN_FALSE;
                   1356:        }
                   1357:        
                   1358:        /* Skip results not returning any columns */
                   1359:        while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retvalue == SUCCEED) {
                   1360:                retvalue = dbresults(mssql_ptr->link);
                   1361:        }
                   1362: 
                   1363:        if (num_fields <= 0) {
                   1364:                RETURN_TRUE;
                   1365:        }
                   1366: 
                   1367:        retvalue=dbnextrow(mssql_ptr->link);    
                   1368:        if (retvalue==FAIL) {
                   1369:                dbcancel(mssql_ptr->link);
                   1370:                RETURN_FALSE;
                   1371:        }
                   1372: 
                   1373:        result = (mssql_result *) emalloc(sizeof(mssql_result));
                   1374:        result->statement = NULL;
                   1375:        result->num_fields = num_fields;
                   1376:        result->blocks_initialized = 1;
                   1377:        
                   1378:        result->batchsize = batchsize;
                   1379:        result->data = NULL;
                   1380:        result->blocks_initialized = 0;
                   1381:        result->mssql_ptr = mssql_ptr;
                   1382:        result->cur_field=result->cur_row=result->num_rows=0;
                   1383:        result->have_fields = 0;
                   1384: 
                   1385:        result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), result->num_fields, 0);
                   1386:        result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
                   1387:        
                   1388:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   1389: }
                   1390: /* }}} */
                   1391: 
                   1392: /* {{{ proto int mssql_rows_affected(resource conn_id)
                   1393:    Returns the number of records affected by the query */
                   1394: PHP_FUNCTION(mssql_rows_affected)
                   1395: {
                   1396:        zval *mssql_link_index;
                   1397:        mssql_link *mssql_ptr;
                   1398: 
                   1399:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_link_index) == FAILURE) {
                   1400:                return;
                   1401:        }
                   1402:        
                   1403:        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, -1, "MS SQL-Link", le_link, le_plink);
                   1404: 
                   1405:        RETURN_LONG(DBCOUNT(mssql_ptr->link));
                   1406: }
                   1407: /* }}} */
                   1408: 
                   1409: /* {{{ proto bool mssql_free_result(resource result_index)
                   1410:    Free a MS-SQL result index */
                   1411: PHP_FUNCTION(mssql_free_result)
                   1412: {
                   1413:        zval *mssql_result_index;
                   1414:        mssql_result *result;
                   1415:        int retvalue;
                   1416:        
                   1417:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
                   1418:                return;
                   1419:        }
                   1420:        
                   1421:        if (Z_RESVAL_P(mssql_result_index) == 0) {
                   1422:                RETURN_FALSE;
                   1423:        }
                   1424: 
                   1425:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1426:        /* Release remaining results */
                   1427:        do {
                   1428:                dbcanquery(result->mssql_ptr->link);
                   1429:                retvalue = dbresults(result->mssql_ptr->link);
                   1430:        } while (retvalue == SUCCEED);
                   1431: 
                   1432:        zend_list_delete(Z_RESVAL_P(mssql_result_index));
                   1433:        RETURN_TRUE;
                   1434: }
                   1435: /* }}} */
                   1436: 
                   1437: /* {{{ proto string mssql_get_last_message(void)
                   1438:    Gets the last message from the MS-SQL server */
                   1439: PHP_FUNCTION(mssql_get_last_message)
                   1440: {
                   1441:        if (zend_parse_parameters_none() == FAILURE) {
                   1442:                return;
                   1443:        }
                   1444: 
                   1445:        if (MS_SQL_G(server_message)) {
                   1446:                RETURN_STRING(MS_SQL_G(server_message),1);
                   1447:        } else {
                   1448:                RETURN_STRING("",1);
                   1449:        }
                   1450: }
                   1451: /* }}} */
                   1452: 
                   1453: /* {{{ proto int mssql_num_rows(resource mssql_result_index)
                   1454:    Returns the number of rows fetched in from the result id specified */
                   1455: PHP_FUNCTION(mssql_num_rows)
                   1456: {
                   1457:        zval *mssql_result_index;
                   1458:        mssql_result *result;
                   1459: 
                   1460:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
                   1461:                return;
                   1462:        }
                   1463: 
                   1464:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1465: 
                   1466:        RETURN_LONG(result->num_rows);
                   1467: }
                   1468: /* }}} */
                   1469: 
                   1470: /* {{{ proto int mssql_num_fields(resource mssql_result_index)
                   1471:    Returns the number of fields fetched in from the result id specified */
                   1472: PHP_FUNCTION(mssql_num_fields)
                   1473: {
                   1474:        zval *mssql_result_index;
                   1475:        mssql_result *result;
                   1476:        
                   1477:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
                   1478:                return;
                   1479:        }
                   1480:        
                   1481:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1482: 
                   1483:        RETURN_LONG(result->num_fields);
                   1484: }
                   1485: /* }}} */
                   1486: 
                   1487: /* {{{ php_mssql_fetch_hash
                   1488: */
                   1489: static void php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
                   1490: {
                   1491:        zval *mssql_result_index;
                   1492:        mssql_result *result;
                   1493:        int i;
                   1494:        long resulttype = 0;
                   1495: 
                   1496:        switch (result_type) {
                   1497:                case MSSQL_NUM:
                   1498:                case MSSQL_ASSOC:
                   1499:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
                   1500:                                return;
                   1501:                        }
                   1502:                        break;
                   1503:                case MSSQL_BOTH:
                   1504:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &resulttype) == FAILURE) {
                   1505:                                return;
                   1506:                        }
                   1507:                        result_type = (resulttype > 0 && (resulttype & MSSQL_BOTH)) ? resulttype : result_type;
                   1508:                        break;
                   1509:                default:
                   1510:                        return;
                   1511:        }
                   1512: 
                   1513:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1514: 
                   1515:        if (MS_SQL_G(server_message)) {
                   1516:                STR_FREE(MS_SQL_G(server_message));
                   1517:                MS_SQL_G(server_message) = NULL;
                   1518:        }
                   1519: 
                   1520:        if (result->cur_row >= result->num_rows) {
                   1521:                RETURN_FALSE;
                   1522:        }
                   1523:        
                   1524:        array_init(return_value);
                   1525:        
                   1526:        for (i=0; i<result->num_fields; i++) {
                   1527:                if (Z_TYPE(result->data[result->cur_row][i]) != IS_NULL) {
                   1528:                        char *data;
                   1529:                        int data_len;
                   1530: 
                   1531:                        if (Z_TYPE(result->data[result->cur_row][i]) == IS_STRING) {
1.1.1.2 ! misho    1532:                                data = Z_STRVAL(result->data[result->cur_row][i]);
        !          1533:                                data_len = Z_STRLEN(result->data[result->cur_row][i]);
1.1       misho    1534: 
                   1535:                                if (result_type & MSSQL_NUM) {
1.1.1.2 ! misho    1536:                                        add_index_stringl(return_value, i, data, data_len, 1);
1.1       misho    1537:                                }
                   1538:                                
                   1539:                                if (result_type & MSSQL_ASSOC) {
1.1.1.2 ! misho    1540:                                        add_assoc_stringl(return_value, result->fields[i].name, data, data_len, 1);
1.1       misho    1541:                                }
                   1542:                        }
                   1543:                        else if (Z_TYPE(result->data[result->cur_row][i]) == IS_LONG) {
                   1544:                                if (result_type & MSSQL_NUM)
                   1545:                                        add_index_long(return_value, i, Z_LVAL(result->data[result->cur_row][i]));
                   1546:                                
                   1547:                                if (result_type & MSSQL_ASSOC)
                   1548:                                        add_assoc_long(return_value, result->fields[i].name, Z_LVAL(result->data[result->cur_row][i]));
                   1549:                        }
                   1550:                        else if (Z_TYPE(result->data[result->cur_row][i]) == IS_DOUBLE) {
                   1551:                                if (result_type & MSSQL_NUM)
                   1552:                                        add_index_double(return_value, i, Z_DVAL(result->data[result->cur_row][i]));
                   1553:                                
                   1554:                                if (result_type & MSSQL_ASSOC)
                   1555:                                        add_assoc_double(return_value, result->fields[i].name, Z_DVAL(result->data[result->cur_row][i]));
                   1556:                        }
                   1557:                }
                   1558:                else
                   1559:                {
                   1560:                        if (result_type & MSSQL_NUM)
                   1561:                                add_index_null(return_value, i);
                   1562:                        if (result_type & MSSQL_ASSOC)
                   1563:                                add_assoc_null(return_value, result->fields[i].name);
                   1564:                }
                   1565:        }
                   1566:        result->cur_row++;
                   1567: }
                   1568: /* }}} */
                   1569: 
                   1570: /* {{{ proto array mssql_fetch_row(resource result_id)
                   1571:    Returns an array of the current row in the result set specified by result_id */
                   1572: PHP_FUNCTION(mssql_fetch_row)
                   1573: {
                   1574:        php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_NUM);
                   1575: }
                   1576: /* }}} */
                   1577: 
                   1578: /* {{{ proto object mssql_fetch_object(resource result_id)
                   1579:    Returns a pseudo-object of the current row in the result set specified by result_id */
                   1580: PHP_FUNCTION(mssql_fetch_object)
                   1581: {
                   1582:        php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_ASSOC);
                   1583:        if (Z_TYPE_P(return_value)==IS_ARRAY) {
                   1584:                object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
                   1585:        }
                   1586: }
                   1587: /* }}} */
                   1588: 
                   1589: /* {{{ proto array mssql_fetch_array(resource result_id [, int result_type])
                   1590:    Returns an associative array of the current row in the result set specified by result_id */
                   1591: PHP_FUNCTION(mssql_fetch_array)
                   1592: {
                   1593:        php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_BOTH);
                   1594: }
                   1595: /* }}} */
                   1596: 
                   1597: /* {{{ proto array mssql_fetch_assoc(resource result_id)
                   1598:    Returns an associative array of the current row in the result set specified by result_id */
                   1599: PHP_FUNCTION(mssql_fetch_assoc)
                   1600: {
                   1601:        php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_ASSOC);
                   1602: }
                   1603: /* }}} */
                   1604: 
                   1605: /* {{{ proto bool mssql_data_seek(resource result_id, int offset)
                   1606:    Moves the internal row pointer of the MS-SQL result associated with the specified result identifier to pointer to the specified row number */
                   1607: PHP_FUNCTION(mssql_data_seek)
                   1608: {
                   1609:        zval *mssql_result_index;
                   1610:        long offset;
                   1611:        mssql_result *result;
                   1612: 
                   1613:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &mssql_result_index, &offset) == FAILURE) {
                   1614:                return;
                   1615:        }
                   1616:        
                   1617:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1618: 
                   1619:        if (offset < 0 || offset >= result->num_rows) {
                   1620:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad row offset");
                   1621:                RETURN_FALSE;
                   1622:        }
                   1623:        
                   1624:        result->cur_row = offset;
                   1625:        RETURN_TRUE;
                   1626: }
                   1627: /* }}} */
                   1628: 
                   1629: /* {{{ php_mssql_get_field_name
                   1630: */
                   1631: static char *php_mssql_get_field_name(int type)
                   1632: {
                   1633:        switch (type) {
                   1634:                case SQLBINARY:
                   1635:                case SQLVARBINARY:
                   1636:                        return "blob";
                   1637:                        break;
                   1638:                case SQLCHAR:
                   1639:                case SQLVARCHAR:
                   1640:                        return "char";
                   1641:                        break;
                   1642:                case SQLTEXT:
                   1643:                        return "text";
                   1644:                        break;
                   1645:                case SQLDATETIME:
                   1646:                case SQLDATETIM4:
                   1647:                case SQLDATETIMN:
                   1648:                        return "datetime";
                   1649:                        break;
                   1650:                case SQLDECIMAL:
                   1651:                case SQLFLT4:
                   1652:                case SQLFLT8:
                   1653:                case SQLFLTN:
                   1654:                        return "real";
                   1655:                        break;
                   1656:                case SQLINT1:
                   1657:                case SQLINT2:
                   1658:                case SQLINT4:
                   1659:                case SQLINTN:
                   1660:                        return "int";
                   1661:                        break;
                   1662:                case SQLNUMERIC:
                   1663:                        return "numeric";
                   1664:                        break;
                   1665:                case SQLMONEY:
                   1666:                case SQLMONEY4:
                   1667:                case SQLMONEYN:
                   1668:                        return "money";
                   1669:                        break;
                   1670:                case SQLBIT:
                   1671:                        return "bit";
                   1672:                        break;
                   1673:                case SQLIMAGE:
                   1674:                        return "image";
                   1675:                        break;
                   1676: #ifdef SQLUNIQUE
                   1677:                case SQLUNIQUE:
                   1678:                        return "uniqueidentifier";
                   1679:                        break;
                   1680: #endif
                   1681:                default:
                   1682:                        return "unknown";
                   1683:                        break;
                   1684:        }
                   1685: }
                   1686: /* }}} */
                   1687: 
                   1688: /* {{{ proto object mssql_fetch_field(resource result_id [, int offset])
                   1689:    Gets information about certain fields in a query result */
                   1690: PHP_FUNCTION(mssql_fetch_field)
                   1691: {
                   1692:        zval *mssql_result_index;
                   1693:        long field_offset = -1;
                   1694:        mssql_result *result;
                   1695: 
                   1696:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
                   1697:                return;
                   1698:        }
                   1699: 
                   1700:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1701:        
                   1702:        if (field_offset==-1) {
                   1703:                field_offset = result->cur_field;
                   1704:                result->cur_field++;
                   1705:        }
                   1706:        
                   1707:        if (field_offset<0 || field_offset >= result->num_fields) {
                   1708:                if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
                   1709:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
                   1710:                }
                   1711:                RETURN_FALSE;
                   1712:        }
                   1713: 
                   1714:        object_init(return_value);
                   1715: 
                   1716:        add_property_string(return_value, "name",result->fields[field_offset].name, 1);
                   1717:        add_property_long(return_value, "max_length",result->fields[field_offset].max_length);
                   1718:        add_property_string(return_value, "column_source",result->fields[field_offset].column_source, 1);
                   1719:        add_property_long(return_value, "numeric", result->fields[field_offset].numeric);
                   1720:        add_property_string(return_value, "type", php_mssql_get_field_name(Z_TYPE(result->fields[field_offset])), 1);
                   1721: }
                   1722: /* }}} */
                   1723: 
                   1724: /* {{{ proto int mssql_field_length(resource result_id [, int offset])
                   1725:    Get the length of a MS-SQL field */
                   1726: PHP_FUNCTION(mssql_field_length)
                   1727: {
                   1728:        zval *mssql_result_index;
                   1729:        long field_offset = -1;
                   1730:        mssql_result *result;
                   1731: 
                   1732:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
                   1733:                return;
                   1734:        }
                   1735:        
                   1736:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1737:        
                   1738:        if (field_offset==-1) {
                   1739:                field_offset = result->cur_field;
                   1740:                result->cur_field++;
                   1741:        }
                   1742:        
                   1743:        if (field_offset<0 || field_offset >= result->num_fields) {
                   1744:                if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
                   1745:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
                   1746:                }
                   1747:                RETURN_FALSE;
                   1748:        }
                   1749: 
                   1750:        RETURN_LONG(result->fields[field_offset].max_length);
                   1751: }
                   1752: /* }}} */
                   1753: 
                   1754: /* {{{ proto string mssql_field_name(resource result_id [, int offset])
                   1755:    Returns the name of the field given by offset in the result set given by result_id */
                   1756: PHP_FUNCTION(mssql_field_name)
                   1757: {
                   1758:        zval *mssql_result_index;
                   1759:        long field_offset = -1;
                   1760:        mssql_result *result;
                   1761: 
                   1762:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
                   1763:                return;
                   1764:        }
                   1765:        
                   1766:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1767:        
                   1768:        if (field_offset==-1) {
                   1769:                field_offset = result->cur_field;
                   1770:                result->cur_field++;
                   1771:        }
                   1772:        
                   1773:        if (field_offset<0 || field_offset >= result->num_fields) {
                   1774:                if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
                   1775:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
                   1776:                }
                   1777:                RETURN_FALSE;
                   1778:        }
                   1779: 
                   1780:        RETURN_STRINGL(result->fields[field_offset].name, strlen(result->fields[field_offset].name), 1);
                   1781: }
                   1782: /* }}} */
                   1783: 
                   1784: /* {{{ proto string mssql_field_type(resource result_id [, int offset])
                   1785:    Returns the type of a field */
                   1786: PHP_FUNCTION(mssql_field_type)
                   1787: {
                   1788:        zval *mssql_result_index;
                   1789:        long field_offset = -1;
                   1790:        mssql_result *result;
                   1791: 
                   1792:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
                   1793:                return;
                   1794:        }
                   1795:        
                   1796:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1797:        
                   1798:        if (field_offset==-1) {
                   1799:                field_offset = result->cur_field;
                   1800:                result->cur_field++;
                   1801:        }
                   1802:        
                   1803:        if (field_offset<0 || field_offset >= result->num_fields) {
                   1804:                if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
                   1805:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
                   1806:                }
                   1807:                RETURN_FALSE;
                   1808:        }
                   1809: 
                   1810:        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);
                   1811: }
                   1812: /* }}} */
                   1813: 
                   1814: /* {{{ proto bool mssql_field_seek(resource result_id, int offset)
                   1815:    Seeks to the specified field offset */
                   1816: PHP_FUNCTION(mssql_field_seek)
                   1817: {
                   1818:        zval *mssql_result_index;
                   1819:        long field_offset;
                   1820:        mssql_result *result;
                   1821: 
                   1822:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &mssql_result_index, &field_offset) == FAILURE) {
                   1823:                return;
                   1824:        }
                   1825:        
                   1826:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1827:        
                   1828:        if (field_offset<0 || field_offset >= result->num_fields) {
                   1829:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
                   1830:                RETURN_FALSE;
                   1831:        }
                   1832: 
                   1833:        result->cur_field = field_offset;
                   1834:        RETURN_TRUE;
                   1835: }
                   1836: /* }}} */
                   1837: 
                   1838: /* {{{ proto string mssql_result(resource result_id, int row, mixed field)
                   1839:    Returns the contents of one cell from a MS-SQL result set */
                   1840: PHP_FUNCTION(mssql_result)
                   1841: {
                   1842:        zval **field, *mssql_result_index;
                   1843:        long row;
                   1844:        int field_offset=0;
                   1845:        mssql_result *result;
                   1846: 
                   1847:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlZ", &mssql_result_index, &row, &field) == FAILURE) {
                   1848:                return;
                   1849:        }
                   1850: 
                   1851:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1852: 
                   1853:        if (row < 0 || row >= result->num_rows) {
                   1854:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad row offset (%ld)", row);
                   1855:                RETURN_FALSE;
                   1856:        }
                   1857: 
                   1858:        switch(Z_TYPE_PP(field)) {
                   1859:                case IS_STRING: {
                   1860:                        int i;
                   1861: 
                   1862:                        for (i=0; i<result->num_fields; i++) {
                   1863:                                if (!strcasecmp(result->fields[i].name, Z_STRVAL_PP(field))) {
                   1864:                                        field_offset = i;
                   1865:                                        break;
                   1866:                                }
                   1867:                        }
                   1868:                        if (i>=result->num_fields) { /* no match found */
                   1869:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s field not found in result", Z_STRVAL_PP(field));
                   1870:                                RETURN_FALSE;
                   1871:                        }
                   1872:                        break;
                   1873:                }
                   1874:                default:
                   1875:                        convert_to_long_ex(field);
                   1876:                        field_offset = Z_LVAL_PP(field);
                   1877:                        if (field_offset<0 || field_offset>=result->num_fields) {
                   1878:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
                   1879:                                RETURN_FALSE;
                   1880:                        }
                   1881:                        break;
                   1882:        }
                   1883: 
                   1884:        *return_value = result->data[row][field_offset];
                   1885:        zval_copy_ctor(return_value);
                   1886: }
                   1887: /* }}} */
                   1888: 
                   1889: /* {{{ proto bool mssql_next_result(resource result_id)
                   1890:    Move the internal result pointer to the next result */
                   1891: PHP_FUNCTION(mssql_next_result)
                   1892: {
                   1893:        zval *mssql_result_index;
                   1894:        int retvalue;
                   1895:        mssql_result *result;
                   1896:        mssql_link *mssql_ptr;
                   1897: 
                   1898:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
                   1899:                return;
                   1900:        }
                   1901: 
                   1902:        ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);       
                   1903: 
                   1904:        mssql_ptr = result->mssql_ptr;
                   1905:        retvalue = dbresults(mssql_ptr->link);
                   1906: 
                   1907:        while (dbnumcols(mssql_ptr->link) <= 0 && retvalue == SUCCEED) {
                   1908:                retvalue = dbresults(mssql_ptr->link);
                   1909:        }
                   1910: 
                   1911:        if (retvalue == FAIL) {
                   1912:                RETURN_FALSE;
                   1913:        }
                   1914:        else if (retvalue == NO_MORE_RESULTS || retvalue == NO_MORE_RPC_RESULTS) {
                   1915:                if (result->statement) {
                   1916:                        _mssql_get_sp_result(mssql_ptr, result->statement TSRMLS_CC);
                   1917:                }
                   1918:                RETURN_FALSE;
                   1919:        }
                   1920:        else {
                   1921:                _free_result(result, 1);
                   1922:                result->cur_row=result->num_fields=result->num_rows=0;
                   1923:                dbclrbuf(mssql_ptr->link,DBLASTROW(mssql_ptr->link));
                   1924:                retvalue = dbnextrow(mssql_ptr->link);
                   1925: 
                   1926:                result->num_fields = dbnumcols(mssql_ptr->link);
                   1927:                result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), result->num_fields, 0);
                   1928:                result->have_fields = 0;
                   1929:                result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
                   1930:                RETURN_TRUE;
                   1931:        }
                   1932: 
                   1933: }
                   1934: /* }}} */
                   1935: 
                   1936: 
                   1937: /* {{{ proto void mssql_min_error_severity(int severity)
                   1938:    Sets the lower error severity */
                   1939: PHP_FUNCTION(mssql_min_error_severity)
                   1940: {
                   1941:        long severity;
                   1942: 
                   1943:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &severity) == FAILURE) {
                   1944:                return;
                   1945:        }
                   1946: 
                   1947:        MS_SQL_G(min_error_severity) = severity;
                   1948: }
                   1949: 
                   1950: /* }}} */
                   1951: 
                   1952: /* {{{ proto void mssql_min_message_severity(int severity)
                   1953:    Sets the lower message severity */
                   1954: PHP_FUNCTION(mssql_min_message_severity)
                   1955: {
                   1956:        long severity;
                   1957:        
                   1958:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &severity) == FAILURE) {
                   1959:                return;
                   1960:        }
                   1961: 
                   1962:        MS_SQL_G(min_message_severity) = severity;
                   1963: }
                   1964: /* }}} */
                   1965: 
                   1966: /* {{{ proto int mssql_init(string sp_name [, resource conn_id])
                   1967:    Initializes a stored procedure or a remote stored procedure  */
                   1968: PHP_FUNCTION(mssql_init)
                   1969: {
                   1970:        char *sp_name;
                   1971:        int sp_name_len;
                   1972:        zval *mssql_link_index = NULL;
                   1973:        mssql_link *mssql_ptr;
                   1974:        mssql_statement *statement;
                   1975:        int id = -1;
                   1976:        
                   1977:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &sp_name, &sp_name_len, &mssql_link_index) == FAILURE) {
                   1978:                return;
                   1979:        }
                   1980: 
                   1981:        if (mssql_link_index == NULL) {
                   1982:                id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
                   1983:                CHECK_LINK(id);
                   1984:        }
                   1985: 
                   1986:        ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
                   1987:        
                   1988:        if (dbrpcinit(mssql_ptr->link, sp_name,0)==FAIL) {
                   1989:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to init stored procedure");
                   1990:                RETURN_FALSE;
                   1991:        }
                   1992: 
                   1993:        statement=NULL;
                   1994:        statement = ecalloc(1,sizeof(mssql_statement));
                   1995:        statement->link = mssql_ptr;
                   1996:        statement->executed=FALSE;
                   1997: 
1.1.1.2 ! misho    1998:        statement->id = zend_list_insert(statement,le_statement TSRMLS_CC);
1.1       misho    1999:        
                   2000:        RETURN_RESOURCE(statement->id);
                   2001: }
                   2002: /* }}} */
                   2003: 
                   2004: /* {{{ proto bool mssql_bind(resource stmt, string param_name, mixed var, int type [, bool is_output [, bool is_null [, int maxlen]]])
                   2005:    Adds a parameter to a stored procedure or a remote stored procedure  */
                   2006: PHP_FUNCTION(mssql_bind)
                   2007: {
                   2008:        char *param_name;
                   2009:        int param_name_len, datalen;
                   2010:        int status = 0;
                   2011:        long type = 0, maxlen = -1;
                   2012:        zval *stmt, **var;
                   2013:        zend_bool is_output = 0, is_null = 0;
                   2014:        mssql_link *mssql_ptr;
                   2015:        mssql_statement *statement;
                   2016:        mssql_bind bind,*bindp;
                   2017:        LPBYTE value = NULL;
                   2018: 
                   2019:        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) {
                   2020:                return;
                   2021:        }
                   2022: 
                   2023:        if (ZEND_NUM_ARGS() == 7 && !is_output) {
                   2024:                maxlen = -1;
                   2025:        }
                   2026:        
                   2027:        ZEND_FETCH_RESOURCE(statement, mssql_statement *, &stmt, -1, "MS SQL-Statement", le_statement);
                   2028: 
                   2029:        if (statement==NULL) {
                   2030:                RETURN_FALSE;
                   2031:        }
                   2032:        mssql_ptr=statement->link;
                   2033: 
                   2034:        /* modify datalen and maxlen according to dbrpcparam documentation */
                   2035:        if ( (type==SQLVARCHAR) || (type==SQLCHAR) || (type==SQLTEXT) ) {       /* variable-length type */
                   2036:                if (is_null) {
                   2037:                        maxlen=0;
                   2038:                        datalen=0;
                   2039:                } else {
                   2040:                        convert_to_string_ex(var);
                   2041:                        datalen=Z_STRLEN_PP(var);
                   2042:                        value=(LPBYTE)Z_STRVAL_PP(var);
                   2043:                }
                   2044:        } else {
                   2045:                /* fixed-length type */
                   2046:                if (is_null)    {
                   2047:                        datalen=0;
                   2048:                } else {
                   2049:                        datalen=-1;
                   2050:                }
                   2051:                maxlen=-1;
                   2052: 
                   2053:                switch (type) {
                   2054:                        case SQLFLT4:
                   2055:                        case SQLFLT8:
                   2056:                        case SQLFLTN:
                   2057:                                convert_to_double_ex(var);
                   2058:                                value=(LPBYTE)(&Z_DVAL_PP(var));
                   2059:                                break;
                   2060: 
                   2061:                        case SQLBIT:
                   2062:                        case SQLINT1:
                   2063:                        case SQLINT2:
                   2064:                        case SQLINT4:
                   2065:                                convert_to_long_ex(var);
                   2066:                                value=(LPBYTE)(&Z_LVAL_PP(var));
                   2067:                                break;
                   2068: 
                   2069:                        default:
                   2070:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported type");
                   2071:                                RETURN_FALSE;
                   2072:                                break;
                   2073:                }
                   2074:        }
                   2075:        
                   2076:        if (is_output) {
                   2077:                status=DBRPCRETURN;
                   2078:        }
                   2079:        
                   2080:        /* hashtable of binds */
                   2081:        if (! statement->binds) {
                   2082:                ALLOC_HASHTABLE(statement->binds);
                   2083:                zend_hash_init(statement->binds, 13, NULL, _mssql_bind_hash_dtor, 0);
                   2084:        }
                   2085: 
                   2086:        if (zend_hash_exists(statement->binds, param_name, param_name_len)) {
                   2087:                RETURN_FALSE;
                   2088:        }
                   2089:        else {
                   2090:                memset((void*)&bind,0,sizeof(mssql_bind));
                   2091:                zend_hash_add(statement->binds, param_name, param_name_len, &bind, sizeof(mssql_bind), (void **)&bindp);
                   2092:                if( NULL == bindp ) RETURN_FALSE;
                   2093:                bindp->zval=*var;
                   2094:                zval_add_ref(var);
                   2095:        
                   2096:                /* no call to dbrpcparam if RETVAL */
                   2097:                if ( strcmp("RETVAL", param_name)!=0 ) {                                                
                   2098:                        if (dbrpcparam(mssql_ptr->link, param_name, (BYTE)status, type, maxlen, datalen, (LPBYTE)value)==FAIL) {
                   2099:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set parameter");
                   2100:                                RETURN_FALSE;
                   2101:                        }
                   2102:                }
                   2103:        }
                   2104: 
                   2105:        RETURN_TRUE;
                   2106: }
                   2107: /* }}} */
                   2108: 
                   2109: /* {{{ proto mixed mssql_execute(resource stmt [, bool skip_results = false])
                   2110:    Executes a stored procedure on a MS-SQL server database */
                   2111: PHP_FUNCTION(mssql_execute)
                   2112: {
                   2113:        zval *stmt;
                   2114:        zend_bool skip_results = 0;
                   2115:        int retvalue, retval_results;
                   2116:        mssql_link *mssql_ptr;
                   2117:        mssql_statement *statement;
                   2118:        mssql_result *result;
                   2119:        int num_fields;
                   2120:        int batchsize;
                   2121:        int exec_retval;
                   2122: 
                   2123:        batchsize = MS_SQL_G(batchsize);
                   2124: 
                   2125:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &stmt, &skip_results) == FAILURE) {
                   2126:                return;
                   2127:        }
                   2128: 
                   2129:        ZEND_FETCH_RESOURCE(statement, mssql_statement *, &stmt, -1, "MS SQL-Statement", le_statement);
                   2130: 
                   2131:        mssql_ptr=statement->link;
                   2132:        exec_retval = dbrpcexec(mssql_ptr->link);
                   2133: 
                   2134:        if (exec_retval == FAIL || dbsqlok(mssql_ptr->link) == FAIL) {
                   2135:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "stored procedure execution failed");
                   2136: 
                   2137:                if (exec_retval == FAIL) {
                   2138:                        dbcancel(mssql_ptr->link);
                   2139:                }
                   2140: 
                   2141:                RETURN_FALSE;
                   2142:        }
                   2143: 
                   2144:        retval_results=dbresults(mssql_ptr->link);
                   2145: 
                   2146:        if (retval_results==FAIL) {
                   2147:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not retrieve results");
                   2148:                dbcancel(mssql_ptr->link);
                   2149:                RETURN_FALSE;
                   2150:        }
                   2151: 
                   2152:        /* The following is just like mssql_query, fetch all rows from the first result 
                   2153:         *      set into the row buffer. 
                   2154:         */
                   2155:        result=NULL;
                   2156:        if (retval_results == SUCCEED) {
                   2157:                if (skip_results) {
                   2158:                        do {
                   2159:                                dbcanquery(mssql_ptr->link);
                   2160:                                retval_results = dbresults(mssql_ptr->link);
                   2161:                        } while (retval_results == SUCCEED);
                   2162:                }
                   2163:                else {
                   2164:                        /* Skip results not returning any columns */
                   2165:                        while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retval_results == SUCCEED) {
                   2166:                                retval_results = dbresults(mssql_ptr->link);
                   2167:                        }
                   2168:                        if ((num_fields = dbnumcols(mssql_ptr->link)) > 0) {
                   2169:                                retvalue = dbnextrow(mssql_ptr->link);
                   2170:                                result = (mssql_result *) emalloc(sizeof(mssql_result));
                   2171:                                result->batchsize = batchsize;
                   2172:                                result->blocks_initialized = 1;
                   2173:                                result->data = (zval **) safe_emalloc(sizeof(zval *), MSSQL_ROWS_BLOCK, 0);
                   2174:                                result->mssql_ptr = mssql_ptr;
                   2175:                                result->cur_field=result->cur_row=result->num_rows=0;
                   2176:                                result->num_fields = num_fields;
                   2177:                                result->have_fields = 0;
                   2178: 
                   2179:                                result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), num_fields, 0);
                   2180:                                result->statement = statement;
                   2181:                                result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
                   2182:                        }
                   2183:                }
                   2184:        }
                   2185:        if (retval_results == NO_MORE_RESULTS || retval_results == NO_MORE_RPC_RESULTS) {
                   2186:                _mssql_get_sp_result(mssql_ptr, statement TSRMLS_CC);
                   2187:        }
                   2188:        
                   2189:        if (result==NULL) {
                   2190:                RETURN_TRUE;    /* no recordset returned ...*/
                   2191:        }
                   2192:        else {
                   2193:                ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   2194:        }
                   2195: }
                   2196: /* }}} */
                   2197: 
                   2198: /* {{{ proto bool mssql_free_statement(resource result_index)
                   2199:    Free a MS-SQL statement index */
                   2200: PHP_FUNCTION(mssql_free_statement)
                   2201: {
                   2202:        zval *mssql_statement_index;
                   2203:        mssql_statement *statement;
                   2204:        int retvalue;
                   2205: 
                   2206:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_statement_index) == FAILURE) {
                   2207:                return;
                   2208:        }
                   2209:        
                   2210:        if (Z_RESVAL_P(mssql_statement_index) == 0) {
                   2211:                RETURN_FALSE;
                   2212:        }
                   2213: 
                   2214:        ZEND_FETCH_RESOURCE(statement, mssql_statement *, &mssql_statement_index, -1, "MS SQL-statement", le_statement);        
                   2215:        /* Release remaining results */
                   2216:        do {
                   2217:                dbcanquery(statement->link->link);
                   2218:                retvalue = dbresults(statement->link->link);
                   2219:        } while (retvalue == SUCCEED);
                   2220: 
                   2221:        zend_list_delete(Z_RESVAL_P(mssql_statement_index));
                   2222:        RETURN_TRUE;
                   2223: }
                   2224: /* }}} */
                   2225: 
                   2226: /* {{{ proto string mssql_guid_string(string binary [,bool short_format])
                   2227:    Converts a 16 byte binary GUID to a string  */
                   2228: PHP_FUNCTION(mssql_guid_string)
                   2229: {
                   2230:        char *binary;
                   2231:        int binary_len;
                   2232:        zend_bool sf = 0;
                   2233:        char buffer[32+1];
                   2234:        char buffer2[36+1];
                   2235: 
                   2236:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &binary, &binary_len, &sf) == FAILURE) {
                   2237:                return;
                   2238:        }
                   2239: 
                   2240:        dbconvert(NULL, SQLBINARY, (BYTE*) binary, MIN(16, binary_len), SQLCHAR, buffer, -1);
                   2241: 
                   2242:        if (sf) {
                   2243:                php_strtoupper(buffer, 32);
                   2244:                RETURN_STRING(buffer, 1);
                   2245:        }
                   2246:        else {
                   2247:                int i;
                   2248:                /* FIXME this works only on little endian machine */
                   2249:                for (i=0; i<4; i++) {
                   2250:                        buffer2[2*i] = buffer[6-2*i];
                   2251:                        buffer2[2*i+1] = buffer[7-2*i];
                   2252:                }
                   2253:                buffer2[8] = '-';
                   2254:                for (i=0; i<2; i++) {
                   2255:                        buffer2[9+2*i] = buffer[10-2*i];
                   2256:                        buffer2[10+2*i] = buffer[11-2*i];
                   2257:                }
                   2258:                buffer2[13] = '-';
                   2259:                for (i=0; i<2; i++) {
                   2260:                        buffer2[14+2*i] = buffer[14-2*i];
                   2261:                        buffer2[15+2*i] = buffer[15-2*i];
                   2262:                }
                   2263:                buffer2[18] = '-';
                   2264:                for (i=0; i<4; i++) {
                   2265:                        buffer2[19+i] = buffer[16+i];
                   2266:                }
                   2267:                buffer2[23] = '-';
                   2268:                for (i=0; i<12; i++) {
                   2269:                        buffer2[24+i] = buffer[20+i];
                   2270:                }
                   2271:                buffer2[36] = 0;
                   2272: 
                   2273:                php_strtoupper(buffer2, 36);
                   2274:                RETURN_STRING(buffer2, 1);
                   2275:        }
                   2276: }
                   2277: /* }}} */
                   2278: 
                   2279: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>