Annotation of embedaddon/php/ext/odbc/php_odbc.c, revision 1.1.1.5

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.5 ! misho       5:    | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       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:    | Authors: Stig Sæther Bakken <ssb@php.net>                            |
                     16:    |          Andreas Karajannis <Andreas.Karajannis@gmd.de>              |
                     17:    |          Frank M. Kromann <frank@kromann.info>  Support for DB/2 CLI |
                     18:    |          Kevin N. Shallow <kshallow@tampabay.rr.com> Birdstep Support|
                     19:    |          Daniel R. Kalowsky <kalowsky@php.net>                       |
                     20:    +----------------------------------------------------------------------+
                     21: */
                     22: 
1.1.1.2   misho      23: /* $Id$ */
1.1       misho      24: 
                     25: #ifdef HAVE_CONFIG_H
                     26: #include "config.h"
                     27: #endif
                     28:  
                     29: #include "php.h"
                     30: #include "php_globals.h"
                     31: 
                     32: #include "ext/standard/info.h"
                     33: #include "ext/standard/php_string.h"
                     34: #include "ext/standard/php_standard.h"
                     35: 
                     36: #include "php_odbc.h"
                     37: #include "php_odbc_includes.h"
                     38: #include "php_globals.h"
                     39: 
                     40: #if HAVE_UODBC
                     41: 
                     42: #include <fcntl.h>
                     43: #include "ext/standard/head.h"
                     44: #include "php_ini.h"
                     45: 
                     46: #ifdef PHP_WIN32
                     47: #include <winsock2.h>
                     48: 
                     49: #define ODBC_TYPE "Win32"
                     50: #define PHP_ODBC_TYPE ODBC_TYPE
                     51: 
                     52: #endif
                     53: 
                     54: /*
                     55:  * not defined elsewhere
                     56:  */
                     57: 
                     58: #ifndef TRUE
                     59: #define TRUE 1
                     60: #define FALSE 0
                     61: #endif
                     62: 
                     63: void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent);
                     64: 
                     65: static int le_result, le_conn, le_pconn;
                     66: 
                     67: #define SAFE_SQL_NTS(n) ((SQLSMALLINT) ((n)?(SQL_NTS):0))
                     68: 
                     69: /* {{{ arginfo */
                     70: ZEND_BEGIN_ARG_INFO(arginfo_odbc_close_all, 0)
                     71: ZEND_END_ARG_INFO()
                     72: 
                     73: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_binmode, 0, 0, 2)
                     74:        ZEND_ARG_INFO(0, result_id)
                     75:        ZEND_ARG_INFO(0, mode)
                     76: ZEND_END_ARG_INFO()
                     77: 
                     78: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_longreadlen, 0, 0, 2)
                     79:        ZEND_ARG_INFO(0, result_id)
                     80:        ZEND_ARG_INFO(0, length)
                     81: ZEND_END_ARG_INFO()
                     82: 
                     83: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_prepare, 0, 0, 2)
                     84:        ZEND_ARG_INFO(0, connection_id)
                     85:        ZEND_ARG_INFO(0, query)
                     86: ZEND_END_ARG_INFO()
                     87: 
                     88: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_execute, 0, 0, 1)
                     89:        ZEND_ARG_INFO(0, result_id)
                     90:        ZEND_ARG_INFO(0, parameters_array)
                     91: ZEND_END_ARG_INFO()
                     92: 
                     93: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_cursor, 0, 0, 1)
                     94:        ZEND_ARG_INFO(0, result_id)
                     95: ZEND_END_ARG_INFO()
                     96: 
                     97: #ifdef HAVE_SQLDATASOURCES
                     98: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_data_source, 0, 0, 2)
                     99:        ZEND_ARG_INFO(0, connection_id)
                    100:        ZEND_ARG_INFO(0, fetch_type)
                    101: ZEND_END_ARG_INFO()
                    102: #endif
                    103: 
                    104: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_exec, 0, 0, 2)
                    105:        ZEND_ARG_INFO(0, connection_id)
                    106:        ZEND_ARG_INFO(0, query)
                    107:        ZEND_ARG_INFO(0, flags)
                    108: ZEND_END_ARG_INFO()
                    109: 
                    110: #ifdef PHP_ODBC_HAVE_FETCH_HASH
                    111: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_object, 0, 0, 1)
                    112:        ZEND_ARG_INFO(0, result)
                    113:        ZEND_ARG_INFO(0, rownumber)
                    114: ZEND_END_ARG_INFO()
                    115: 
                    116: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_array, 0, 0, 1)
                    117:        ZEND_ARG_INFO(0, result)
                    118:        ZEND_ARG_INFO(0, rownumber)
                    119: ZEND_END_ARG_INFO()
                    120: #endif
                    121: 
                    122: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_into, 0, 0, 2)
                    123:        ZEND_ARG_INFO(0, result_id)
                    124:        ZEND_ARG_INFO(1, result_array)
                    125:        ZEND_ARG_INFO(0, rownumber)
                    126: ZEND_END_ARG_INFO()
                    127: 
                    128: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_row, 0, 0, 1)
                    129:        ZEND_ARG_INFO(0, result_id)
                    130:        ZEND_ARG_INFO(0, row_number)
                    131: ZEND_END_ARG_INFO()
                    132: 
                    133: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_result, 0, 0, 2)
                    134:        ZEND_ARG_INFO(0, result_id)
                    135:        ZEND_ARG_INFO(0, field)
                    136: ZEND_END_ARG_INFO()
                    137: 
                    138: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_result_all, 0, 0, 1)
                    139:        ZEND_ARG_INFO(0, result_id)
                    140:        ZEND_ARG_INFO(0, format)
                    141: ZEND_END_ARG_INFO()
                    142: 
                    143: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_free_result, 0, 0, 1)
                    144:        ZEND_ARG_INFO(0, result_id)
                    145: ZEND_END_ARG_INFO()
                    146: 
                    147: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_connect, 0, 0, 3)
                    148:        ZEND_ARG_INFO(0, dsn)
                    149:        ZEND_ARG_INFO(0, user)
                    150:        ZEND_ARG_INFO(0, password)
                    151:        ZEND_ARG_INFO(0, cursor_option)
                    152: ZEND_END_ARG_INFO()
                    153: 
                    154: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_pconnect, 0, 0, 3)
                    155:        ZEND_ARG_INFO(0, dsn)
                    156:        ZEND_ARG_INFO(0, user)
                    157:        ZEND_ARG_INFO(0, password)
                    158:        ZEND_ARG_INFO(0, cursor_option)
                    159: ZEND_END_ARG_INFO()
                    160: 
                    161: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_close, 0, 0, 1)
                    162:        ZEND_ARG_INFO(0, connection_id)
                    163: ZEND_END_ARG_INFO()
                    164: 
                    165: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_num_rows, 0, 0, 1)
                    166:        ZEND_ARG_INFO(0, result_id)
                    167: ZEND_END_ARG_INFO()
                    168: 
                    169: #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
                    170: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_next_result, 0, 0, 1)
                    171:        ZEND_ARG_INFO(0, result_id)
                    172: ZEND_END_ARG_INFO()
                    173: #endif
                    174: 
                    175: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_num_fields, 0, 0, 1)
                    176:        ZEND_ARG_INFO(0, result_id)
                    177: ZEND_END_ARG_INFO()
                    178: 
                    179: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_name, 0, 0, 2)
                    180:        ZEND_ARG_INFO(0, result_id)
                    181:        ZEND_ARG_INFO(0, field_number)
                    182: ZEND_END_ARG_INFO()
                    183: 
                    184: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_type, 0, 0, 2)
                    185:        ZEND_ARG_INFO(0, result_id)
                    186:        ZEND_ARG_INFO(0, field_number)
                    187: ZEND_END_ARG_INFO()
                    188: 
                    189: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_len, 0, 0, 2)
                    190:        ZEND_ARG_INFO(0, result_id)
                    191:        ZEND_ARG_INFO(0, field_number)
                    192: ZEND_END_ARG_INFO()
                    193: 
                    194: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_scale, 0, 0, 2)
                    195:        ZEND_ARG_INFO(0, result_id)
                    196:        ZEND_ARG_INFO(0, field_number)
                    197: ZEND_END_ARG_INFO()
                    198: 
                    199: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_num, 0, 0, 2)
                    200:        ZEND_ARG_INFO(0, result_id)
                    201:        ZEND_ARG_INFO(0, field_name)
                    202: ZEND_END_ARG_INFO()
                    203: 
                    204: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_autocommit, 0, 0, 1)
                    205:        ZEND_ARG_INFO(0, connection_id)
                    206:        ZEND_ARG_INFO(0, onoff)
                    207: ZEND_END_ARG_INFO()
                    208: 
                    209: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_commit, 0, 0, 1)
                    210:        ZEND_ARG_INFO(0, connection_id)
                    211: ZEND_END_ARG_INFO()
                    212: 
                    213: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_rollback, 0, 0, 1)
                    214:        ZEND_ARG_INFO(0, connection_id)
                    215: ZEND_END_ARG_INFO()
                    216: 
                    217: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_error, 0, 0, 0)
                    218:        ZEND_ARG_INFO(0, connection_id)
                    219: ZEND_END_ARG_INFO()
                    220: 
                    221: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_errormsg, 0, 0, 0)
                    222:        ZEND_ARG_INFO(0, connection_id)
                    223: ZEND_END_ARG_INFO()
                    224: 
                    225: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_setoption, 0, 0, 4)
                    226:        ZEND_ARG_INFO(0, conn_id)
                    227:        ZEND_ARG_INFO(0, which)
                    228:        ZEND_ARG_INFO(0, option)
                    229:        ZEND_ARG_INFO(0, value)
                    230: ZEND_END_ARG_INFO()
                    231: 
                    232: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_tables, 0, 0, 1)
                    233:        ZEND_ARG_INFO(0, connection_id)
                    234:        ZEND_ARG_INFO(0, qualifier)
                    235:        ZEND_ARG_INFO(0, owner)
                    236:        ZEND_ARG_INFO(0, name)
                    237:        ZEND_ARG_INFO(0, table_types)
                    238: ZEND_END_ARG_INFO()
                    239: 
                    240: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_columns, 0, 0, 1)
                    241:        ZEND_ARG_INFO(0, connection_id)
                    242:        ZEND_ARG_INFO(0, qualifier)
                    243:        ZEND_ARG_INFO(0, owner)
                    244:        ZEND_ARG_INFO(0, table_name)
                    245:        ZEND_ARG_INFO(0, column_name)
                    246: ZEND_END_ARG_INFO()
                    247: 
                    248: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_gettypeinfo, 0, 0, 1)
                    249:        ZEND_ARG_INFO(0, connection_id)
                    250:        ZEND_ARG_INFO(0, data_type)
                    251: ZEND_END_ARG_INFO()
                    252: 
                    253: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_primarykeys, 0, 0, 4)
                    254:        ZEND_ARG_INFO(0, connection_id)
                    255:        ZEND_ARG_INFO(0, qualifier)
                    256:        ZEND_ARG_INFO(0, owner)
                    257:        ZEND_ARG_INFO(0, table)
                    258: ZEND_END_ARG_INFO()
                    259: 
                    260: #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
                    261: #if !defined(HAVE_BIRDSTEP)
                    262: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_procedurecolumns, 0, 0, 1)
                    263:        ZEND_ARG_INFO(0, connection_id)
                    264:        ZEND_ARG_INFO(0, qualifier)
                    265:        ZEND_ARG_INFO(0, owner)
                    266:        ZEND_ARG_INFO(0, proc)
                    267:        ZEND_ARG_INFO(0, column)
                    268: ZEND_END_ARG_INFO()
                    269: #endif
                    270: 
                    271: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_procedures, 0, 0, 1)
                    272:        ZEND_ARG_INFO(0, connection_id)
                    273:        ZEND_ARG_INFO(0, qualifier)
                    274:        ZEND_ARG_INFO(0, owner)
                    275:        ZEND_ARG_INFO(0, name)
                    276: ZEND_END_ARG_INFO()
                    277: 
                    278: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_foreignkeys, 0, 0, 7)
                    279:        ZEND_ARG_INFO(0, connection_id)
                    280:        ZEND_ARG_INFO(0, pk_qualifier)
                    281:        ZEND_ARG_INFO(0, pk_owner)
                    282:        ZEND_ARG_INFO(0, pk_table)
                    283:        ZEND_ARG_INFO(0, fk_qualifier)
                    284:        ZEND_ARG_INFO(0, fk_owner)
                    285:        ZEND_ARG_INFO(0, fk_table)
                    286: ZEND_END_ARG_INFO()
                    287: #endif
                    288: 
                    289: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_specialcolumns, 0, 0, 7)
                    290:        ZEND_ARG_INFO(0, connection_id)
                    291:        ZEND_ARG_INFO(0, type)
                    292:        ZEND_ARG_INFO(0, qualifier)
                    293:        ZEND_ARG_INFO(0, owner)
                    294:        ZEND_ARG_INFO(0, table)
                    295:        ZEND_ARG_INFO(0, scope)
                    296:        ZEND_ARG_INFO(0, nullable)
                    297: ZEND_END_ARG_INFO()
                    298: 
                    299: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_statistics, 0, 0, 6)
                    300:        ZEND_ARG_INFO(0, connection_id)
                    301:        ZEND_ARG_INFO(0, qualifier)
                    302:        ZEND_ARG_INFO(0, owner)
                    303:        ZEND_ARG_INFO(0, name)
                    304:        ZEND_ARG_INFO(0, unique)
                    305:        ZEND_ARG_INFO(0, accuracy)
                    306: ZEND_END_ARG_INFO()
                    307: 
                    308: #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP)
                    309: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_tableprivileges, 0, 0, 4)
                    310:        ZEND_ARG_INFO(0, connection_id)
                    311:        ZEND_ARG_INFO(0, qualifier)
                    312:        ZEND_ARG_INFO(0, owner)
                    313:        ZEND_ARG_INFO(0, name)
                    314: ZEND_END_ARG_INFO()
                    315: 
                    316: ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_columnprivileges, 0, 0, 5)
                    317:        ZEND_ARG_INFO(0, connection_id)
                    318:        ZEND_ARG_INFO(0, catalog)
                    319:        ZEND_ARG_INFO(0, schema)
                    320:        ZEND_ARG_INFO(0, table)
                    321:        ZEND_ARG_INFO(0, column)
                    322: ZEND_END_ARG_INFO()
                    323: #endif
                    324: /* }}} */
                    325: 
                    326: /* {{{ odbc_functions[]
                    327:  */
                    328: const zend_function_entry odbc_functions[] = {
                    329:        PHP_FE(odbc_autocommit, arginfo_odbc_autocommit)
                    330:        PHP_FE(odbc_binmode, arginfo_odbc_binmode)
                    331:        PHP_FE(odbc_close, arginfo_odbc_close)
                    332:        PHP_FE(odbc_close_all, arginfo_odbc_close_all)
                    333:        PHP_FE(odbc_columns, arginfo_odbc_columns)
                    334:        PHP_FE(odbc_commit, arginfo_odbc_commit)
                    335:        PHP_FE(odbc_connect, arginfo_odbc_connect)
                    336:        PHP_FE(odbc_cursor, arginfo_odbc_cursor)
                    337: #ifdef HAVE_SQLDATASOURCES
                    338:        PHP_FE(odbc_data_source, arginfo_odbc_data_source)
                    339: #endif
                    340:        PHP_FE(odbc_execute, arginfo_odbc_execute)
                    341:        PHP_FE(odbc_error, arginfo_odbc_error)
                    342:        PHP_FE(odbc_errormsg, arginfo_odbc_errormsg)
                    343:        PHP_FE(odbc_exec, arginfo_odbc_exec)
                    344: #ifdef PHP_ODBC_HAVE_FETCH_HASH
                    345:        PHP_FE(odbc_fetch_array, arginfo_odbc_fetch_array)
                    346:        PHP_FE(odbc_fetch_object, arginfo_odbc_fetch_object)
                    347: #endif
                    348:        PHP_FE(odbc_fetch_row, arginfo_odbc_fetch_row)
                    349:        PHP_FE(odbc_fetch_into, arginfo_odbc_fetch_into)
                    350:        PHP_FE(odbc_field_len, arginfo_odbc_field_len)
                    351:        PHP_FE(odbc_field_scale, arginfo_odbc_field_scale)
                    352:        PHP_FE(odbc_field_name, arginfo_odbc_field_name)
                    353:        PHP_FE(odbc_field_type, arginfo_odbc_field_type)
                    354:        PHP_FE(odbc_field_num, arginfo_odbc_field_num)
                    355:        PHP_FE(odbc_free_result, arginfo_odbc_free_result)
                    356:        PHP_FE(odbc_gettypeinfo, arginfo_odbc_gettypeinfo)
                    357:        PHP_FE(odbc_longreadlen, arginfo_odbc_longreadlen)
                    358: #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
                    359:        PHP_FE(odbc_next_result, arginfo_odbc_next_result)
                    360: #endif
                    361:        PHP_FE(odbc_num_fields, arginfo_odbc_num_fields)
                    362:        PHP_FE(odbc_num_rows, arginfo_odbc_num_rows)
                    363:        PHP_FE(odbc_pconnect, arginfo_odbc_pconnect)
                    364:        PHP_FE(odbc_prepare, arginfo_odbc_prepare)
                    365:        PHP_FE(odbc_result, arginfo_odbc_result)
                    366:        PHP_FE(odbc_result_all, arginfo_odbc_result_all)
                    367:        PHP_FE(odbc_rollback, arginfo_odbc_rollback)
                    368:        PHP_FE(odbc_setoption, arginfo_odbc_setoption)
                    369:        PHP_FE(odbc_specialcolumns, arginfo_odbc_specialcolumns)
                    370:        PHP_FE(odbc_statistics, arginfo_odbc_statistics)
                    371:        PHP_FE(odbc_tables, arginfo_odbc_tables)
                    372:        PHP_FE(odbc_primarykeys, arginfo_odbc_primarykeys)
                    373: #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP)    /* not supported now */
                    374:        PHP_FE(odbc_columnprivileges, arginfo_odbc_columnprivileges)
                    375:        PHP_FE(odbc_tableprivileges, arginfo_odbc_tableprivileges)
                    376: #endif
                    377: #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) /* not supported */
                    378:        PHP_FE(odbc_foreignkeys, arginfo_odbc_foreignkeys)
                    379:        PHP_FE(odbc_procedures, arginfo_odbc_procedures)
                    380: #if !defined(HAVE_BIRDSTEP)
                    381:        PHP_FE(odbc_procedurecolumns, arginfo_odbc_procedurecolumns)
                    382: #endif
                    383: #endif
                    384:        PHP_FALIAS(odbc_do, odbc_exec, arginfo_odbc_exec)
                    385:        PHP_FALIAS(odbc_field_precision, odbc_field_len, arginfo_odbc_field_len)
                    386:        PHP_FE_END
                    387: };
                    388: /* }}} */
                    389: 
1.1.1.3   misho     390: ZEND_DECLARE_MODULE_GLOBALS(odbc)
1.1       misho     391: static PHP_GINIT_FUNCTION(odbc);
                    392: 
                    393: /* {{{ odbc_module_entry
                    394:  */
                    395: zend_module_entry odbc_module_entry = {
                    396:        STANDARD_MODULE_HEADER,
                    397:        "odbc", 
                    398:        odbc_functions, 
                    399:        PHP_MINIT(odbc), 
                    400:        PHP_MSHUTDOWN(odbc),
                    401:        PHP_RINIT(odbc), 
                    402:        PHP_RSHUTDOWN(odbc), 
                    403:        PHP_MINFO(odbc), 
                    404:        "1.0",
                    405:        PHP_MODULE_GLOBALS(odbc),
                    406:        PHP_GINIT(odbc),
                    407:        NULL,
                    408:        NULL,
                    409:        STANDARD_MODULE_PROPERTIES_EX
                    410: };
                    411: /* }}} */
                    412: 
                    413: #ifdef COMPILE_DL_ODBC
                    414: ZEND_GET_MODULE(odbc)
                    415: #endif
                    416: 
                    417: /* {{{ _free_odbc_result
                    418:  */
                    419: static void _free_odbc_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                    420: {
                    421:        odbc_result *res = (odbc_result *)rsrc->ptr;
                    422:        int i;
                    423:        RETCODE rc;
                    424:        
                    425:        if (res) {
                    426:                if (res->values) {
                    427:                        for(i = 0; i < res->numcols; i++) {
                    428:                                if (res->values[i].value)
                    429:                                        efree(res->values[i].value);
                    430:                        }
                    431:                        efree(res->values);
                    432:                        res->values = NULL;
                    433:                }
                    434:                if (res->stmt) {
                    435: #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35)
                    436:                        SQLTransact(res->conn_ptr->henv, res->conn_ptr->hdbc,
                    437:                                                (SQLUSMALLINT) SQL_COMMIT);
                    438: #endif
                    439:                        rc = SQLFreeStmt(res->stmt,SQL_DROP);
                    440:                        /* We don't want the connection to be closed after the last statment has been closed
                    441:                         * Connections will be closed on shutdown
                    442:                         * zend_list_delete(res->conn_ptr->id);
                    443:                         */
                    444:                }
                    445:                efree(res);
                    446:        }
                    447: }
                    448: /* }}} */
                    449: 
                    450: /* {{{ safe_odbc_disconnect
                    451:  * disconnect, and if it fails, then issue a rollback for any pending transaction (lurcher)
                    452:  */
                    453: static void safe_odbc_disconnect( void *handle )
                    454: {
                    455:        int ret;
                    456: 
                    457:        ret = SQLDisconnect( handle );
                    458:        if ( ret == SQL_ERROR )
                    459:        {
                    460:                SQLTransact( NULL, handle, SQL_ROLLBACK );
                    461:                SQLDisconnect( handle );
                    462:        }
                    463: }
                    464: /* }}} */
                    465: 
                    466: /* {{{ _close_odbc_conn
                    467:  */
                    468: static void _close_odbc_conn(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                    469: {
                    470:        int i, nument, type;
                    471:        void *ptr;
                    472:        odbc_result *res;
                    473: 
                    474:        odbc_connection *conn = (odbc_connection *)rsrc->ptr;
                    475: 
                    476:        nument = zend_hash_next_free_element(&EG(regular_list));
                    477:        for(i = 1; i < nument; i++) {
                    478:                ptr = zend_list_find(i, &type);
                    479:                if (ptr && (type == le_result)) {
                    480:                        res = (odbc_result *)ptr;
                    481:                        if (res->conn_ptr == conn) {
                    482:                                zend_list_delete(i);
                    483:                        }
                    484:                }
                    485:        }
                    486: 
                    487:        safe_odbc_disconnect(conn->hdbc);
                    488:        SQLFreeConnect(conn->hdbc);
                    489:        SQLFreeEnv(conn->henv);
                    490:        efree(conn);
                    491:        ODBCG(num_links)--;
                    492: }
                    493: /* }}} */
                    494: 
                    495: /* {{{ void _close_odbc_pconn
                    496:  */
                    497: static void _close_odbc_pconn(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                    498: {
                    499:        int i, nument, type;
                    500:        void *ptr;
                    501:        odbc_result *res;
                    502:        odbc_connection *conn = (odbc_connection *)rsrc->ptr;
                    503: 
                    504:        nument = zend_hash_next_free_element(&EG(persistent_list));
                    505:        for(i = 1; i < nument; i++) {
                    506:                ptr = zend_list_find(i, &type);
                    507:                if (ptr && (type == le_result)) {
                    508:                        res = (odbc_result *)ptr;
                    509:                        if (res->conn_ptr == conn) {
                    510:                                zend_list_delete(i);
                    511:                        }
                    512:                }
                    513:        }
                    514:        
                    515:        safe_odbc_disconnect(conn->hdbc);
                    516:        SQLFreeConnect(conn->hdbc);
                    517:        SQLFreeEnv(conn->henv);
                    518:        free(conn);
                    519: 
                    520:        ODBCG(num_links)--;
                    521:        ODBCG(num_persistent)--;
                    522: }
                    523: /* }}} */
                    524: 
                    525: /* {{{ PHP_INI_DISP(display_link_nums)
                    526:  */
                    527: static PHP_INI_DISP(display_link_nums)
                    528: {
                    529:        char *value;
                    530:        TSRMLS_FETCH();
                    531: 
                    532:        if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
                    533:                value = ini_entry->orig_value;
                    534:        } else if (ini_entry->value) {
                    535:                value = ini_entry->value;
                    536:        } else {
                    537:                value = NULL;
                    538:        }
                    539: 
                    540:        if (value) {
                    541:                if (atoi(value) == -1) {
                    542:                        PUTS("Unlimited");
                    543:                } else {
                    544:                        php_printf("%s", value);
                    545:                }
                    546:        }
                    547: }
                    548: /* }}} */
                    549: 
                    550: /* {{{ PHP_INI_DISP(display_defPW)
                    551:  */
                    552: static PHP_INI_DISP(display_defPW)
                    553: {
                    554:        char *value;
                    555:        TSRMLS_FETCH();
                    556: 
                    557:        if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
                    558:                value = ini_entry->orig_value;
                    559:        } else if (ini_entry->value) {
                    560:                value = ini_entry->value;
                    561:        } else {
                    562:                value = NULL;
                    563:        }
                    564: 
                    565:        if (value) {
                    566: #if PHP_DEBUG
                    567:                php_printf("%s", value);
                    568: #else
                    569:                PUTS("********");
                    570: #endif
                    571:        } else {
                    572:                if (PG(html_errors)) {
                    573:                        PUTS("<i>no value</i>");
                    574:                } else {
                    575:                        PUTS("no value");
                    576:                }
                    577:        }
                    578: }
                    579: /* }}} */
                    580: 
                    581: /* {{{ PHP_INI_DISP(display_binmode)
                    582:  */
                    583: static PHP_INI_DISP(display_binmode)
                    584: {
                    585:        char *value;
                    586:        TSRMLS_FETCH();
                    587:        
                    588:        if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
                    589:                value = ini_entry->orig_value;
                    590:        } else if (ini_entry->value) {
                    591:                value = ini_entry->value;
                    592:        } else {
                    593:                value = NULL;
                    594:        }
                    595: 
                    596:        if (value) {
                    597:                switch(atoi(value)) {
                    598:                        case 0:
                    599:                                PUTS("passthru");
                    600:                                break;
                    601:                        case 1:
                    602:                                PUTS("return as is");
                    603:                                break;
                    604:                        case 2:
                    605:                                PUTS("return as char");
                    606:                                break;
                    607:                }
                    608:        }
                    609: }
                    610: /* }}} */
                    611: 
                    612: /* {{{ PHP_INI_DISP(display_lrl)
                    613:  */
                    614: static PHP_INI_DISP(display_lrl)
                    615: {
                    616:        char *value;
                    617:        TSRMLS_FETCH();
                    618: 
                    619:        if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
                    620:                value = ini_entry->orig_value;
                    621:        } else if (ini_entry->value) {
                    622:                value = ini_entry->value;
                    623:        } else {
                    624:                value = NULL;
                    625:        }
                    626: 
                    627:        if (value) {
                    628:                if (atoi(value) <= 0) {
                    629:                        PUTS("Passthru");
                    630:                } else {
                    631:                        php_printf("return up to %s bytes", value);
                    632:                }
                    633:        }
                    634: }
                    635: /* }}} */
                    636: 
                    637: 
                    638: /* {{{ PHP_INI_DISP(display_cursortype)
                    639:  */
                    640: static PHP_INI_DISP(display_cursortype)
                    641: {
                    642:        char *value;
                    643:        TSRMLS_FETCH();
                    644: 
                    645:        if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
                    646:                value = ini_entry->orig_value;
                    647:        } else if (ini_entry->value) {
                    648:                value = ini_entry->value;
                    649:        } else {
                    650:                value = NULL;
                    651:        }
                    652: 
                    653:        if (value) {
                    654:                switch (atoi (value))
                    655:                  {
                    656:                    case SQL_CURSOR_FORWARD_ONLY:
                    657:                                PUTS ("Forward Only cursor");
                    658:                                break;
                    659: 
                    660:                        case SQL_CURSOR_STATIC:
                    661:                            PUTS ("Static cursor");
                    662:                                break;
                    663: 
                    664:                        case SQL_CURSOR_KEYSET_DRIVEN:
                    665:                                PUTS ("Keyset driven cursor");
                    666:                                break;
                    667: 
                    668:                        case SQL_CURSOR_DYNAMIC:
                    669:                                PUTS ("Dynamic cursor");
                    670:                                break;
                    671: 
                    672:                        default:
                    673:                                php_printf("Unknown cursor model %s", value);
                    674:                                break;
                    675:                  }
                    676:        }
                    677: }
                    678: 
                    679: /* }}} */
                    680: 
                    681: /* {{{ PHP_INI_BEGIN 
                    682:  */
                    683: PHP_INI_BEGIN()
                    684:        STD_PHP_INI_BOOLEAN("odbc.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong,
                    685:                        allow_persistent, zend_odbc_globals, odbc_globals)
                    686:        STD_PHP_INI_ENTRY_EX("odbc.max_persistent",  "-1", PHP_INI_SYSTEM, OnUpdateLong,
                    687:                        max_persistent, zend_odbc_globals, odbc_globals, display_link_nums)
                    688:        STD_PHP_INI_ENTRY_EX("odbc.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong,
                    689:                        max_links, zend_odbc_globals, odbc_globals, display_link_nums)
                    690:        STD_PHP_INI_ENTRY("odbc.default_db", NULL, PHP_INI_ALL, OnUpdateString,
                    691:                        defDB, zend_odbc_globals, odbc_globals)
                    692:        STD_PHP_INI_ENTRY("odbc.default_user", NULL, PHP_INI_ALL, OnUpdateString,
                    693:                        defUser, zend_odbc_globals, odbc_globals)
                    694:        STD_PHP_INI_ENTRY_EX("odbc.default_pw", NULL, PHP_INI_ALL, OnUpdateString,
                    695:                        defPW, zend_odbc_globals, odbc_globals, display_defPW)
                    696:        STD_PHP_INI_ENTRY_EX("odbc.defaultlrl", "4096", PHP_INI_ALL, OnUpdateLong,
                    697:                        defaultlrl, zend_odbc_globals, odbc_globals, display_lrl)
                    698:        STD_PHP_INI_ENTRY_EX("odbc.defaultbinmode", "1", PHP_INI_ALL, OnUpdateLong,
                    699:                        defaultbinmode, zend_odbc_globals, odbc_globals, display_binmode)
                    700:        STD_PHP_INI_BOOLEAN("odbc.check_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong,
                    701:                        check_persistent, zend_odbc_globals, odbc_globals)
                    702:        STD_PHP_INI_ENTRY_EX("odbc.default_cursortype", "3", PHP_INI_ALL, OnUpdateLong, 
                    703:                        default_cursortype, zend_odbc_globals, odbc_globals, display_cursortype)
                    704: PHP_INI_END()
                    705: /* }}} */
                    706: 
                    707: static PHP_GINIT_FUNCTION(odbc)
                    708: {
                    709:        odbc_globals->num_persistent = 0;
                    710: }
                    711: 
                    712: /* {{{ PHP_MINIT_FUNCTION */
                    713: PHP_MINIT_FUNCTION(odbc)
                    714: {
                    715: #ifdef SQLANY_BUG
                    716:        ODBC_SQL_CONN_T foobar;
                    717:        RETCODE rc;
                    718: #endif
                    719: 
                    720:        REGISTER_INI_ENTRIES();
                    721:        le_result = zend_register_list_destructors_ex(_free_odbc_result, NULL, "odbc result", module_number);
                    722:        le_conn = zend_register_list_destructors_ex(_close_odbc_conn, NULL, "odbc link", module_number);
                    723:        le_pconn = zend_register_list_destructors_ex(NULL, _close_odbc_pconn, "odbc link persistent", module_number);
                    724:        Z_TYPE(odbc_module_entry) = type;
                    725:        
                    726:        REGISTER_STRING_CONSTANT("ODBC_TYPE", PHP_ODBC_TYPE, CONST_CS | CONST_PERSISTENT);
                    727:        REGISTER_LONG_CONSTANT("ODBC_BINMODE_PASSTHRU", 0, CONST_CS | CONST_PERSISTENT);
                    728:        REGISTER_LONG_CONSTANT("ODBC_BINMODE_RETURN", 1, CONST_CS | CONST_PERSISTENT);
                    729:        REGISTER_LONG_CONSTANT("ODBC_BINMODE_CONVERT", 2, CONST_CS | CONST_PERSISTENT);
                    730:        /* Define Constants for options
                    731:           these Constants are defined in <sqlext.h>
                    732:        */
                    733:        REGISTER_LONG_CONSTANT("SQL_ODBC_CURSORS", SQL_ODBC_CURSORS, CONST_PERSISTENT | CONST_CS);
                    734:        REGISTER_LONG_CONSTANT("SQL_CUR_USE_DRIVER", SQL_CUR_USE_DRIVER, CONST_PERSISTENT | CONST_CS);
                    735:        REGISTER_LONG_CONSTANT("SQL_CUR_USE_IF_NEEDED", SQL_CUR_USE_IF_NEEDED, CONST_PERSISTENT | CONST_CS);
                    736:        REGISTER_LONG_CONSTANT("SQL_CUR_USE_ODBC", SQL_CUR_USE_ODBC, CONST_PERSISTENT | CONST_CS);
                    737: 
                    738: 
                    739:        REGISTER_LONG_CONSTANT("SQL_CONCURRENCY", SQL_CONCURRENCY, CONST_PERSISTENT | CONST_CS);
                    740:        REGISTER_LONG_CONSTANT("SQL_CONCUR_READ_ONLY", SQL_CONCUR_READ_ONLY, CONST_PERSISTENT | CONST_CS);
                    741:        REGISTER_LONG_CONSTANT("SQL_CONCUR_LOCK", SQL_CONCUR_LOCK, CONST_PERSISTENT | CONST_CS);
                    742:        REGISTER_LONG_CONSTANT("SQL_CONCUR_ROWVER", SQL_CONCUR_ROWVER, CONST_PERSISTENT | CONST_CS);
                    743:        REGISTER_LONG_CONSTANT("SQL_CONCUR_VALUES", SQL_CONCUR_VALUES, CONST_PERSISTENT | CONST_CS);
                    744: 
                    745:        REGISTER_LONG_CONSTANT("SQL_CURSOR_TYPE", SQL_CURSOR_TYPE, CONST_PERSISTENT | CONST_CS);
                    746:        REGISTER_LONG_CONSTANT("SQL_CURSOR_FORWARD_ONLY", SQL_CURSOR_FORWARD_ONLY, CONST_PERSISTENT | CONST_CS);
                    747:        REGISTER_LONG_CONSTANT("SQL_CURSOR_KEYSET_DRIVEN", SQL_CURSOR_KEYSET_DRIVEN, CONST_PERSISTENT | CONST_CS);
                    748:        REGISTER_LONG_CONSTANT("SQL_CURSOR_DYNAMIC", SQL_CURSOR_DYNAMIC, CONST_PERSISTENT | CONST_CS);
                    749:        REGISTER_LONG_CONSTANT("SQL_CURSOR_STATIC", SQL_CURSOR_STATIC, CONST_PERSISTENT | CONST_CS);
                    750:        
                    751:        REGISTER_LONG_CONSTANT("SQL_KEYSET_SIZE", SQL_KEYSET_SIZE, CONST_PERSISTENT | CONST_CS);
                    752: 
                    753:        /* these are for the Data Source type */
                    754:        REGISTER_LONG_CONSTANT("SQL_FETCH_FIRST", SQL_FETCH_FIRST, CONST_PERSISTENT | CONST_CS);
                    755:        REGISTER_LONG_CONSTANT("SQL_FETCH_NEXT", SQL_FETCH_NEXT, CONST_PERSISTENT | CONST_CS);
                    756: 
                    757:        /*
                    758:         * register the standard data types
                    759:         */
                    760:        REGISTER_LONG_CONSTANT("SQL_CHAR", SQL_CHAR, CONST_PERSISTENT | CONST_CS);
                    761:        REGISTER_LONG_CONSTANT("SQL_VARCHAR", SQL_VARCHAR, CONST_PERSISTENT | CONST_CS);
                    762:        REGISTER_LONG_CONSTANT("SQL_LONGVARCHAR", SQL_LONGVARCHAR, CONST_PERSISTENT | CONST_CS);
                    763:        REGISTER_LONG_CONSTANT("SQL_DECIMAL", SQL_DECIMAL, CONST_PERSISTENT | CONST_CS);
                    764:        REGISTER_LONG_CONSTANT("SQL_NUMERIC", SQL_NUMERIC, CONST_PERSISTENT | CONST_CS);
                    765:        REGISTER_LONG_CONSTANT("SQL_BIT", SQL_BIT, CONST_PERSISTENT | CONST_CS);
                    766:        REGISTER_LONG_CONSTANT("SQL_TINYINT", SQL_TINYINT, CONST_PERSISTENT | CONST_CS);
                    767:        REGISTER_LONG_CONSTANT("SQL_SMALLINT", SQL_SMALLINT, CONST_PERSISTENT | CONST_CS);
                    768:        REGISTER_LONG_CONSTANT("SQL_INTEGER", SQL_INTEGER, CONST_PERSISTENT | CONST_CS);
                    769:        REGISTER_LONG_CONSTANT("SQL_BIGINT", SQL_BIGINT, CONST_PERSISTENT | CONST_CS);
                    770:        REGISTER_LONG_CONSTANT("SQL_REAL", SQL_REAL, CONST_PERSISTENT | CONST_CS);
                    771:        REGISTER_LONG_CONSTANT("SQL_FLOAT", SQL_FLOAT, CONST_PERSISTENT | CONST_CS);
                    772:        REGISTER_LONG_CONSTANT("SQL_DOUBLE", SQL_DOUBLE, CONST_PERSISTENT | CONST_CS);
                    773:        REGISTER_LONG_CONSTANT("SQL_BINARY", SQL_BINARY, CONST_PERSISTENT | CONST_CS);
                    774:        REGISTER_LONG_CONSTANT("SQL_VARBINARY", SQL_VARBINARY, CONST_PERSISTENT | CONST_CS);
                    775:        REGISTER_LONG_CONSTANT("SQL_LONGVARBINARY", SQL_LONGVARBINARY, CONST_PERSISTENT | CONST_CS);
                    776:        REGISTER_LONG_CONSTANT("SQL_DATE", SQL_DATE, CONST_PERSISTENT | CONST_CS);
                    777:        REGISTER_LONG_CONSTANT("SQL_TIME", SQL_TIME, CONST_PERSISTENT | CONST_CS);
                    778:        REGISTER_LONG_CONSTANT("SQL_TIMESTAMP", SQL_TIMESTAMP, CONST_PERSISTENT | CONST_CS);
                    779: #if defined(ODBCVER) && (ODBCVER >= 0x0300)
                    780:        REGISTER_LONG_CONSTANT("SQL_TYPE_DATE", SQL_TYPE_DATE, CONST_PERSISTENT | CONST_CS);
                    781:        REGISTER_LONG_CONSTANT("SQL_TYPE_TIME", SQL_TYPE_TIME, CONST_PERSISTENT | CONST_CS);
                    782:        REGISTER_LONG_CONSTANT("SQL_TYPE_TIMESTAMP", SQL_TYPE_TIMESTAMP, CONST_PERSISTENT | CONST_CS);
                    783: 
                    784:        /*
                    785:         * SQLSpecialColumns values
                    786:         */
                    787:        REGISTER_LONG_CONSTANT("SQL_BEST_ROWID", SQL_BEST_ROWID, CONST_PERSISTENT | CONST_CS);
                    788:        REGISTER_LONG_CONSTANT("SQL_ROWVER", SQL_ROWVER, CONST_PERSISTENT | CONST_CS);
                    789:        REGISTER_LONG_CONSTANT("SQL_SCOPE_CURROW", SQL_SCOPE_CURROW, CONST_PERSISTENT | CONST_CS);
                    790:        REGISTER_LONG_CONSTANT("SQL_SCOPE_TRANSACTION", SQL_SCOPE_TRANSACTION, CONST_PERSISTENT | CONST_CS);
                    791:        REGISTER_LONG_CONSTANT("SQL_SCOPE_SESSION", SQL_SCOPE_SESSION, CONST_PERSISTENT | CONST_CS);
                    792:        REGISTER_LONG_CONSTANT("SQL_NO_NULLS", SQL_NO_NULLS, CONST_PERSISTENT | CONST_CS);
                    793:        REGISTER_LONG_CONSTANT("SQL_NULLABLE", SQL_NULLABLE, CONST_PERSISTENT | CONST_CS);
                    794: 
                    795:        /*
                    796:         * SQLStatistics values
                    797:         */
                    798:        REGISTER_LONG_CONSTANT("SQL_INDEX_UNIQUE", SQL_INDEX_UNIQUE, CONST_PERSISTENT | CONST_CS);
                    799:        REGISTER_LONG_CONSTANT("SQL_INDEX_ALL", SQL_INDEX_ALL, CONST_PERSISTENT | CONST_CS);
                    800:        REGISTER_LONG_CONSTANT("SQL_ENSURE", SQL_ENSURE, CONST_PERSISTENT | CONST_CS);
                    801:        REGISTER_LONG_CONSTANT("SQL_QUICK", SQL_QUICK, CONST_PERSISTENT | CONST_CS);
                    802: #endif
                    803: 
                    804: #if defined(HAVE_IBMDB2) && defined(_AIX)
                    805:        /* atexit() handler in the DB2/AIX library segfaults in PHP CLI */
                    806:        /* DB2NOEXITLIST env variable prevents DB2 from invoking atexit() */
                    807:        putenv("DB2NOEXITLIST=TRUE");
                    808: #endif
                    809: 
                    810:        return SUCCESS;
                    811: }
                    812: /* }}} */
                    813: 
                    814: /* {{{ PHP_RINIT_FUNCTION */
                    815: PHP_RINIT_FUNCTION(odbc)
                    816: {
                    817:        ODBCG(defConn) = -1;
                    818:        ODBCG(num_links) = ODBCG(num_persistent);
                    819:        memset(ODBCG(laststate), '\0', 6);
                    820:        memset(ODBCG(lasterrormsg), '\0', SQL_MAX_MESSAGE_LENGTH);
                    821:        return SUCCESS;
                    822: }
                    823: /* }}} */
                    824: 
                    825: /* {{{ PHP_RSHUTDOWN_FUNCTION */
                    826: PHP_RSHUTDOWN_FUNCTION(odbc)
                    827: {
                    828:        return SUCCESS;
                    829: }
                    830: /* }}} */
                    831: 
                    832: /* {{{ PHP_MSHUTDOWN_FUNCTION */
                    833: PHP_MSHUTDOWN_FUNCTION(odbc)
                    834: {
                    835:        UNREGISTER_INI_ENTRIES();
                    836:        return SUCCESS;
                    837: }
                    838: /* }}} */
                    839: 
                    840: /* {{{ PHP_MINFO_FUNCTION */
                    841: PHP_MINFO_FUNCTION(odbc)
                    842: {
                    843:        char buf[32];
                    844: 
                    845:        php_info_print_table_start();
                    846:        php_info_print_table_header(2, "ODBC Support", "enabled");
                    847:        snprintf(buf, sizeof(buf), "%ld", ODBCG(num_persistent));
                    848:        php_info_print_table_row(2, "Active Persistent Links", buf);
                    849:        snprintf(buf, sizeof(buf), "%ld", ODBCG(num_links));
                    850:        php_info_print_table_row(2, "Active Links", buf);
                    851:        php_info_print_table_row(2, "ODBC library", PHP_ODBC_TYPE);
                    852: #ifndef PHP_WIN32
                    853:        php_info_print_table_row(2, "ODBC_INCLUDE", PHP_ODBC_INCLUDE);
                    854:        php_info_print_table_row(2, "ODBC_LFLAGS", PHP_ODBC_LFLAGS);
                    855:        php_info_print_table_row(2, "ODBC_LIBS", PHP_ODBC_LIBS);
                    856: #endif
                    857:        php_info_print_table_end();
                    858: 
                    859:        DISPLAY_INI_ENTRIES();
                    860: 
                    861: }       
                    862: /* }}} */
                    863: 
                    864: /* {{{ odbc_sql_error */
                    865: void odbc_sql_error(ODBC_SQL_ERROR_PARAMS)
                    866: {
                    867:        char        state[6];
                    868:        SQLINTEGER      error;        /* Not used */
                    869:        char        errormsg[SQL_MAX_MESSAGE_LENGTH];
                    870:        SQLSMALLINT     errormsgsize; /* Not used */
                    871:        RETCODE rc;
                    872:        ODBC_SQL_ENV_T henv;
                    873:        ODBC_SQL_CONN_T conn;
                    874:        TSRMLS_FETCH();
                    875: 
                    876:        if (conn_resource) {
                    877:                henv = conn_resource->henv;
                    878:                conn = conn_resource->hdbc;
                    879:        } else {
                    880:                henv = SQL_NULL_HENV;
                    881:                conn = SQL_NULL_HDBC;
                    882:        }
                    883: 
                    884:        /* This leads to an endless loop in many drivers! 
                    885:         *
                    886:           while(henv != SQL_NULL_HENV){
                    887:                do {
                    888:         */
                    889:        rc = SQLError(henv, conn, stmt, state, &error, errormsg, sizeof(errormsg)-1, &errormsgsize);
                    890:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                    891:                snprintf(state, sizeof(state), "HY000");
                    892:                snprintf(errormsg, sizeof(errormsg), "Failed to fetch error message");
                    893:        }
                    894:        if (conn_resource) {
                    895:                memcpy(conn_resource->laststate, state, sizeof(state));
                    896:                memcpy(conn_resource->lasterrormsg, errormsg, sizeof(errormsg));
                    897:        }
                    898:        memcpy(ODBCG(laststate), state, sizeof(state));
                    899:        memcpy(ODBCG(lasterrormsg), errormsg, sizeof(errormsg));
                    900:        if (func) {
                    901:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL error: %s, SQL state %s in %s", errormsg, state, func);
                    902:        } else {
                    903:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL error: %s, SQL state %s", errormsg, state);
                    904:        }
                    905:        /*              
                    906:                } while (SQL_SUCCEEDED(rc));
                    907:        }
                    908:        */
                    909: }
                    910: /* }}} */
                    911: 
                    912: /* {{{ php_odbc_fetch_attribs */
                    913: void php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAMETERS, int mode)
                    914: {
                    915:        odbc_result *result;
                    916:        zval *pv_res;
                    917:        long flag;
                    918: 
                    919:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &flag) == FAILURE) {
                    920:                return;
                    921:        }
                    922:        
                    923:        if (Z_LVAL_P(pv_res)) {
                    924:                ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                    925:         if (mode) {
                    926:             result->longreadlen = flag;
                    927:         } else {
                    928:             result->binmode = flag;
                    929:                }
                    930:        } else {
                    931:         if (mode) {
                    932:             ODBCG(defaultlrl) = flag;
                    933:         } else {
                    934:             ODBCG(defaultbinmode) = flag;
                    935:                }
                    936:        }
                    937:        RETURN_TRUE;
                    938: }
                    939: /* }}} */
                    940: 
                    941: /* {{{ odbc_bindcols */
                    942: int odbc_bindcols(odbc_result *result TSRMLS_DC)
                    943: {
                    944:        RETCODE rc;
                    945:        int i;
                    946:        SQLSMALLINT colnamelen; /* Not used */
                    947:        SQLLEN      displaysize;
                    948: 
                    949:        result->values = (odbc_result_value *) safe_emalloc(sizeof(odbc_result_value), result->numcols, 0);
                    950: 
                    951:        result->longreadlen = ODBCG(defaultlrl);
                    952:        result->binmode = ODBCG(defaultbinmode);
                    953: 
                    954:        for(i = 0; i < result->numcols; i++) {
                    955:                rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_NAME, 
                    956:                                result->values[i].name, sizeof(result->values[i].name), &colnamelen, 0);
                    957:                rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_TYPE, 
                    958:                                NULL, 0, NULL, &result->values[i].coltype);
                    959:                
                    960:                /* Don't bind LONG / BINARY columns, so that fetch behaviour can
                    961:                 * be controlled by odbc_binmode() / odbc_longreadlen()
                    962:                 */
                    963:                
                    964:                switch(result->values[i].coltype) {
                    965:                        case SQL_BINARY:
                    966:                        case SQL_VARBINARY:
                    967:                        case SQL_LONGVARBINARY:
                    968:                        case SQL_LONGVARCHAR:
                    969:                                result->values[i].value = NULL;
                    970:                                break;
                    971:                                
                    972: #ifdef HAVE_ADABAS
                    973:                        case SQL_TIMESTAMP:
                    974:                                result->values[i].value = (char *)emalloc(27);
                    975:                                SQLBindCol(result->stmt, (SQLUSMALLINT)(i+1), SQL_C_CHAR, result->values[i].value,
                    976:                                                        27, &result->values[i].vallen);
                    977:                                break;
                    978: #endif /* HAVE_ADABAS */
                    979:                        default:
                    980:                                rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_DISPLAY_SIZE,
                    981:                                                                        NULL, 0, NULL, &displaysize);
                    982:                                displaysize = displaysize <= result->longreadlen ? displaysize : 
                    983:                                                                result->longreadlen;
                    984:                                /* Workaround for Oracle ODBC Driver bug (#50162) when fetching TIMESTAMP column */
                    985:                                if (result->values[i].coltype == SQL_TIMESTAMP) {
                    986:                                        displaysize += 3;
                    987:                                }
                    988:                                result->values[i].value = (char *)emalloc(displaysize + 1);
                    989:                                rc = SQLBindCol(result->stmt, (SQLUSMALLINT)(i+1), SQL_C_CHAR, result->values[i].value,
                    990:                                                        displaysize + 1, &result->values[i].vallen);
                    991:                                break;
                    992:                }
                    993:        }
                    994:        return 1;
                    995: }
                    996: /* }}} */
                    997: 
                    998: /* {{{ odbc_transact */
                    999: void odbc_transact(INTERNAL_FUNCTION_PARAMETERS, int type)
                   1000: {
                   1001:        odbc_connection *conn;
                   1002:        RETCODE rc;
                   1003:        zval *pv_conn;
                   1004:        
                   1005:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_conn) == FAILURE) {
                   1006:                return;
                   1007:        }
                   1008: 
                   1009:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   1010:        
                   1011:        rc = SQLTransact(conn->henv, conn->hdbc, (SQLUSMALLINT)((type)?SQL_COMMIT:SQL_ROLLBACK));
                   1012:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   1013:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTransact");
                   1014:                RETURN_FALSE;
                   1015:        }
                   1016: 
                   1017:        RETURN_TRUE;
                   1018: }
                   1019: /* }}} */
                   1020: 
                   1021: /* {{{ _close_pconn_with_id */
                   1022: static int _close_pconn_with_id(zend_rsrc_list_entry *le, int *id TSRMLS_DC)
                   1023: {
                   1024:        if(Z_TYPE_P(le) == le_pconn && (((odbc_connection *)(le->ptr))->id == *id)){
                   1025:                return 1;
                   1026:        }else{
                   1027:                return 0;
                   1028:        }
                   1029: }
                   1030: /* }}} */
                   1031: 
                   1032: /* {{{ odbc_column_lengths */
                   1033: void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type)
                   1034: {
                   1035:        odbc_result *result;
                   1036: #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30)
                   1037:        /* this seems to be necessary for Solid2.3 ( tested by 
                   1038:         * tammy@synchronis.com) and Solid 3.0 (tested by eric@terra.telemediair.nl)
                   1039:         * Solid does not seem to declare a SQLINTEGER, but it does declare a
                   1040:         * SQL_INTEGER which does not work (despite being the same type as a SDWORD.
                   1041:         * Solid 3.5 does not have this issue.
                   1042:         */
                   1043:        SDWORD len;
                   1044: #else
                   1045:        SQLLEN len;
                   1046: #endif
                   1047:        zval *pv_res;
                   1048:        long pv_num;
                   1049: 
                   1050:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &pv_num) == FAILURE) {
                   1051:                return;
                   1052:        }
                   1053: 
                   1054:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   1055: 
                   1056:        if (result->numcols == 0) {
                   1057:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   1058:                RETURN_FALSE;
                   1059:        }
                   1060: 
                   1061:        if (pv_num > result->numcols) {
                   1062:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index larger than number of fields");
                   1063:                RETURN_FALSE;
                   1064:        }
                   1065: 
                   1066:        if (pv_num < 1) {
                   1067:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field numbering starts at 1");
                   1068:                RETURN_FALSE;
                   1069:        }
                   1070: 
                   1071:        SQLColAttributes(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len);
                   1072: 
                   1073:        RETURN_LONG(len);
                   1074: }
                   1075: /* }}} */
                   1076: 
                   1077: /* Main User Functions */
                   1078: 
                   1079: /* {{{ proto void odbc_close_all(void)
                   1080:    Close all ODBC connections */
                   1081: PHP_FUNCTION(odbc_close_all)
                   1082: {
                   1083:        void *ptr;
                   1084:        int type;
                   1085:        int i;
                   1086:        int nument;
                   1087: 
                   1088:        if (zend_parse_parameters_none() == FAILURE) {
                   1089:                return;
                   1090:        }
                   1091: 
                   1092:        nument = zend_hash_next_free_element(&EG(regular_list));
                   1093:        
                   1094:        /* Loop through list and close all statements */
                   1095:        for(i = 1; i < nument; i++) {
                   1096:                ptr = zend_list_find(i, &type);
                   1097:                if (ptr && (type == le_result)){
                   1098:                        zend_list_delete(i);
                   1099:                }
                   1100:        }
                   1101: 
                   1102:        /* Second loop through list, now close all connections */
                   1103:        nument = zend_hash_next_free_element(&EG(regular_list));
                   1104:        
                   1105:        for(i = 1; i < nument; i++) {
                   1106:                ptr = zend_list_find(i, &type);
                   1107:                if (ptr){
                   1108:                        if(type == le_conn){
                   1109:                                zend_list_delete(i);
                   1110:                        }else if(type == le_pconn){
                   1111:                                zend_list_delete(i);
                   1112:                                /* Delete the persistent connection */
                   1113:                                zend_hash_apply_with_argument(&EG(persistent_list), 
                   1114:                                        (apply_func_arg_t) _close_pconn_with_id, (void *) &i TSRMLS_CC);
                   1115:                        }
                   1116:                }
                   1117:        }
                   1118: }
                   1119: /* }}} */
                   1120: 
                   1121: /* {{{ proto bool odbc_binmode(int result_id, int mode)
                   1122:    Handle binary column data */
                   1123: PHP_FUNCTION(odbc_binmode)
                   1124: {
                   1125:        php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                   1126: }
                   1127: /* }}} */
                   1128: 
                   1129: /* {{{ proto bool odbc_longreadlen(int result_id, int length)
                   1130:    Handle LONG columns */
                   1131: PHP_FUNCTION(odbc_longreadlen)
                   1132: {
                   1133:        php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                   1134: }
                   1135: /* }}} */
                   1136: 
                   1137: /* {{{ proto resource odbc_prepare(resource connection_id, string query)
                   1138:    Prepares a statement for execution */
                   1139: PHP_FUNCTION(odbc_prepare)
                   1140: {
                   1141:        zval *pv_conn;
                   1142:        char *query;
                   1143:        int query_len;
                   1144:        odbc_result *result = NULL;
                   1145:        odbc_connection *conn;
                   1146:        RETCODE rc;
                   1147: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1148:        SQLUINTEGER      scrollopts;
                   1149: #endif
                   1150: 
                   1151:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pv_conn, &query, &query_len) == FAILURE) {
                   1152:                return;
                   1153:        }
                   1154: 
                   1155:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   1156: 
                   1157:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   1158:        
                   1159:        result->numparams = 0;
                   1160:        
                   1161:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   1162:        if (rc == SQL_INVALID_HANDLE) {
                   1163:                efree(result);
                   1164:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   1165:                RETURN_FALSE;
                   1166:        }
                   1167: 
                   1168:        if (rc == SQL_ERROR) {
                   1169:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   1170:                efree(result);
                   1171:                RETURN_FALSE;
                   1172:        }
                   1173: 
                   1174: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1175:        /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info,
                   1176:           whether Driver supports ExtendedFetch */
                   1177:        rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL);
                   1178:        if (rc == SQL_SUCCESS) {
                   1179:                if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) {
                   1180:                        /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other
                   1181:                           type if not possible.
                   1182:                        */
                   1183:                        SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype));
                   1184:                }
                   1185:        } else {
                   1186:                result->fetch_abs = 0;
                   1187:        }
                   1188: #endif
                   1189: 
                   1190:        rc = SQLPrepare(result->stmt, query, SQL_NTS);
                   1191:        switch (rc) {
                   1192:                case SQL_SUCCESS:
                   1193:                        break;
                   1194:                case SQL_SUCCESS_WITH_INFO:
                   1195:                        odbc_sql_error(conn, result->stmt, "SQLPrepare");
                   1196:                        break;
                   1197:                default:
                   1198:                        odbc_sql_error(conn, result->stmt, "SQLPrepare");
                   1199:                        RETURN_FALSE;
                   1200:        }
                   1201:        
                   1202:        SQLNumParams(result->stmt, &(result->numparams));
                   1203:        SQLNumResultCols(result->stmt, &(result->numcols));
                   1204: 
                   1205:        if (result->numcols > 0) {
                   1206:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   1207:                        efree(result);
                   1208:                        RETURN_FALSE;
                   1209:                }
                   1210:        } else {
                   1211:                result->values = NULL;
                   1212:        }
                   1213:        zend_list_addref(conn->id);
                   1214:        result->conn_ptr = conn;
                   1215:        result->fetched = 0;
                   1216:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);  
                   1217: }
                   1218: /* }}} */
                   1219: 
                   1220: /*
                   1221:  * Execute prepared SQL statement. Supports only input parameters.
                   1222:  */
                   1223: 
                   1224: /* {{{ proto bool odbc_execute(resource result_id [, array parameters_array])
                   1225:    Execute a prepared statement */
                   1226: PHP_FUNCTION(odbc_execute)
                   1227: { 
                   1228:        zval *pv_res, *pv_param_arr, **tmp;
                   1229:        typedef struct params_t {
                   1230:                SQLLEN vallen;
                   1231:                int fp;
                   1232:        } params_t;
                   1233:        params_t *params = NULL;
                   1234:        char *filename;
                   1235:        unsigned char otype;
                   1236:        SQLSMALLINT sqltype, ctype, scale;
                   1237:        SQLSMALLINT nullable;
                   1238:        SQLULEN precision;
                   1239:        odbc_result *result;
                   1240:        int numArgs, i, ne;
                   1241:        RETCODE rc;
                   1242:        
                   1243:        numArgs = ZEND_NUM_ARGS();
                   1244:        
                   1245:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|a", &pv_res, &pv_param_arr) == FAILURE) {
                   1246:                return;
                   1247:        }
                   1248: 
                   1249:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   1250:        
                   1251:        /* XXX check for already bound parameters*/
                   1252:        if (result->numparams > 0 && numArgs == 1) {
                   1253:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No parameters to SQL statement given");
                   1254:                RETURN_FALSE;
                   1255:        }
                   1256: 
                   1257:        if (result->numparams > 0) {
                   1258:                if ((ne = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr))) < result->numparams) {
                   1259:                        php_error_docref(NULL TSRMLS_CC, E_WARNING,"Not enough parameters (%d should be %d) given", ne, result->numparams);
                   1260:                        RETURN_FALSE;
                   1261:                }
                   1262: 
                   1263:                zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
                   1264:                params = (params_t *)safe_emalloc(sizeof(params_t), result->numparams, 0);
                   1265:                for(i = 0; i < result->numparams; i++) {
                   1266:                        params[i].fp = -1;
                   1267:                }
                   1268:                
                   1269:                for(i = 1; i <= result->numparams; i++) {
                   1270:                        if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
                   1271:                                php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
                   1272:                                SQLFreeStmt(result->stmt,SQL_RESET_PARAMS);
                   1273:                                for (i = 0; i < result->numparams; i++) {
                   1274:                                        if (params[i].fp != -1) {
                   1275:                                                close(params[i].fp);
                   1276:                                        }
                   1277:                                }
                   1278:                                efree(params);
                   1279:                                RETURN_FALSE;
                   1280:                        }
                   1281: 
                   1282:                        otype = (*tmp)->type;
                   1283:                        convert_to_string_ex(tmp);
                   1284:                        if (Z_TYPE_PP(tmp) != IS_STRING) {
                   1285:                                php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
                   1286:                                SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
                   1287:                                for (i = 0; i < result->numparams; i++) {
                   1288:                                        if (params[i].fp != -1) {
                   1289:                                                close(params[i].fp);
                   1290:                                        }
                   1291:                                }
                   1292:                                efree(params);
                   1293:                                RETURN_FALSE;
                   1294:                        }
                   1295:                        
                   1296:                        rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)i, &sqltype, &precision, &scale, &nullable);
                   1297:                        params[i-1].vallen = Z_STRLEN_PP(tmp);
                   1298:                        params[i-1].fp = -1;
                   1299:                        if (rc == SQL_ERROR) {
                   1300:                                odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParameter"); 
                   1301:                                SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
                   1302:                                for (i = 0; i < result->numparams; i++) {
                   1303:                                        if (params[i].fp != -1) {
                   1304:                                                close(params[i].fp);
                   1305:                                        }
                   1306:                                }
                   1307:                                efree(params);
                   1308:                                RETURN_FALSE;
                   1309:                        }
                   1310: 
                   1311:                        if (IS_SQL_BINARY(sqltype)) {
                   1312:                                ctype = SQL_C_BINARY;
                   1313:                        } else {
                   1314:                                ctype = SQL_C_CHAR;
                   1315:                        }
                   1316: 
                   1317:                        if (Z_STRLEN_PP(tmp) > 2 &&
                   1318:                                Z_STRVAL_PP(tmp)[0] == '\'' &&
                   1319:                                Z_STRVAL_PP(tmp)[Z_STRLEN_PP(tmp) - 1] == '\'') {
1.1.1.2   misho    1320:                                        
                   1321:                                if (CHECK_ZVAL_NULL_PATH(*tmp)) {
1.1       misho    1322:                                        RETURN_FALSE;
                   1323:                                }
                   1324:                                filename = estrndup(&Z_STRVAL_PP(tmp)[1], Z_STRLEN_PP(tmp) - 2);
1.1.1.2   misho    1325:                                filename[strlen(filename)] = '\0';
1.1       misho    1326: 
                   1327:                                /* Check the basedir */
                   1328:                                if (php_check_open_basedir(filename TSRMLS_CC)) {
                   1329:                                        efree(filename);
                   1330:                                        SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
                   1331:                                        for (i = 0; i < result->numparams; i++) {
                   1332:                                                if (params[i].fp != -1) {
                   1333:                                                        close(params[i].fp);
                   1334:                                                }
                   1335:                                        }
                   1336:                                        efree(params);
                   1337:                                        RETURN_FALSE;
                   1338:                                }
                   1339: 
                   1340:                                if ((params[i-1].fp = open(filename,O_RDONLY)) == -1) {
                   1341:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't open file %s", filename);
                   1342:                                        SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
                   1343:                                        for (i = 0; i < result->numparams; i++) {
                   1344:                                                if (params[i].fp != -1) {
                   1345:                                                        close(params[i].fp);
                   1346:                                                }
                   1347:                                        }
                   1348:                                        efree(params);
                   1349:                                        efree(filename);
                   1350:                                        RETURN_FALSE;
                   1351:                                }
                   1352: 
                   1353:                                efree(filename);
                   1354: 
                   1355:                                params[i-1].vallen = SQL_LEN_DATA_AT_EXEC(0);
                   1356: 
                   1357:                                rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
                   1358:                                                                          ctype, sqltype, precision, scale,
                   1359:                                                                          (void *)params[i-1].fp, 0,
                   1360:                                                                          &params[i-1].vallen);
                   1361:                        } else {
                   1362: #ifdef HAVE_DBMAKER
                   1363:                                precision = params[i-1].vallen;
                   1364: #endif
                   1365:                                if (otype == IS_NULL) {
                   1366:                                        params[i-1].vallen = SQL_NULL_DATA;
                   1367:                                }
                   1368: 
                   1369:                                rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
                   1370:                                                                          ctype, sqltype, precision, scale,
                   1371:                                                                          Z_STRVAL_PP(tmp), 0,
                   1372:                                                                          &params[i-1].vallen);
                   1373:                        }
                   1374:                        if (rc == SQL_ERROR) {
                   1375:                                odbc_sql_error(result->conn_ptr, result->stmt, "SQLBindParameter");     
                   1376:                                SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
                   1377:                                for (i = 0; i < result->numparams; i++) {
                   1378:                                        if (params[i].fp != -1) {
                   1379:                                                close(params[i].fp);
                   1380:                                        }
                   1381:                                }
                   1382:                                efree(params);
                   1383:                                RETURN_FALSE;
                   1384:                        }
                   1385:                        zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
                   1386:                }
                   1387:        }
                   1388:        /* Close cursor, needed for doing multiple selects */
                   1389:        rc = SQLFreeStmt(result->stmt, SQL_CLOSE);
                   1390: 
                   1391:        if (rc == SQL_ERROR) {
                   1392:                odbc_sql_error(result->conn_ptr, result->stmt, "SQLFreeStmt");  
                   1393:        }
                   1394: 
                   1395:        rc = SQLExecute(result->stmt);
                   1396: 
                   1397:        result->fetched = 0;
                   1398:        if (rc == SQL_NEED_DATA) {
                   1399:                char buf[4096];
                   1400:                int fp, nbytes;
                   1401:                while (rc == SQL_NEED_DATA) {
                   1402:                        rc = SQLParamData(result->stmt, (void*)&fp);
                   1403:                        if (rc == SQL_NEED_DATA) {
                   1404:                                while ((nbytes = read(fp, &buf, 4096)) > 0) {
                   1405:                                        SQLPutData(result->stmt, (void*)&buf, nbytes);
                   1406:                                }
                   1407:                        }
                   1408:                }
                   1409:        } else {
                   1410:                switch (rc) {
                   1411:                        case SQL_SUCCESS:
                   1412:                                break;
                   1413:                        case SQL_NO_DATA_FOUND:
                   1414:                        case SQL_SUCCESS_WITH_INFO:
                   1415:                                odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute");
                   1416:                                break;
                   1417:                        default:
                   1418:                                odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute");
                   1419:                                RETVAL_FALSE;
                   1420:                }
                   1421:        }       
                   1422:        
                   1423:        if (result->numparams > 0) {
                   1424:                SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
                   1425:                for(i = 0; i < result->numparams; i++) {
                   1426:                        if (params[i].fp != -1) {
                   1427:                                close(params[i].fp);
                   1428:                        }
                   1429:                }
                   1430:                efree(params);
                   1431:        }
                   1432: 
                   1433:        if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO || rc == SQL_NO_DATA_FOUND) {
                   1434:                RETVAL_TRUE;
                   1435:        }
                   1436: 
                   1437:        if (result->numcols == 0) {
                   1438:                SQLNumResultCols(result->stmt, &(result->numcols));
                   1439: 
                   1440:                if (result->numcols > 0) {
                   1441:                        if (!odbc_bindcols(result TSRMLS_CC)) {
                   1442:                                efree(result);
                   1443:                                RETVAL_FALSE;
                   1444:                        }
                   1445:                } else {
                   1446:                        result->values = NULL;
                   1447:                }
                   1448:        }
                   1449: }
                   1450: /* }}} */
                   1451: 
                   1452: /* {{{ proto string odbc_cursor(resource result_id)
                   1453:    Get cursor name */
                   1454: PHP_FUNCTION(odbc_cursor)
                   1455: {
                   1456:        zval *pv_res;
                   1457:        SQLUSMALLINT max_len;
                   1458:        SQLSMALLINT len;
                   1459:        char *cursorname;
                   1460:        odbc_result *result;
                   1461:        RETCODE rc;
                   1462:        
                   1463:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
                   1464:                return;
                   1465:        }
                   1466: 
                   1467:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   1468: 
                   1469:        rc = SQLGetInfo(result->conn_ptr->hdbc,SQL_MAX_CURSOR_NAME_LEN, (void *)&max_len,sizeof(max_len),&len);
                   1470:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   1471:                RETURN_FALSE;
                   1472:        }
                   1473:        
                   1474:        if (max_len > 0) {
                   1475:                cursorname = emalloc(max_len + 1);
                   1476:                rc = SQLGetCursorName(result->stmt,cursorname,(SQLSMALLINT)max_len,&len);
                   1477:                if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   1478:                        char        state[6];     /* Not used */
                   1479:                        SQLINTEGER  error;        /* Not used */
                   1480:                        char        errormsg[SQL_MAX_MESSAGE_LENGTH];
                   1481:                        SQLSMALLINT errormsgsize; /* Not used */
                   1482: 
                   1483:                        SQLError( result->conn_ptr->henv, result->conn_ptr->hdbc,
                   1484:                                                result->stmt, state, &error, errormsg,
                   1485:                                                sizeof(errormsg)-1, &errormsgsize);
                   1486:                        if (!strncmp(state,"S1015",5)) {
                   1487:                                snprintf(cursorname, max_len+1, "php_curs_%d", (int)result->stmt);
                   1488:                                if (SQLSetCursorName(result->stmt,cursorname,SQL_NTS) != SQL_SUCCESS) {
                   1489:                                        odbc_sql_error(result->conn_ptr, result->stmt, "SQLSetCursorName");
                   1490:                                        RETVAL_FALSE;
                   1491:                                } else {
                   1492:                                        RETVAL_STRING(cursorname,1);
                   1493:                                }
                   1494:                        } else {
                   1495:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL error: %s, SQL state %s", errormsg, state);
                   1496:                                RETVAL_FALSE;
                   1497:                        }
                   1498:                } else {
                   1499:                        RETVAL_STRING(cursorname,1);
                   1500:                }
                   1501:                efree(cursorname);
                   1502:        } else {
                   1503:                RETVAL_FALSE;
                   1504:        }
                   1505: }
                   1506: /* }}} */
                   1507: 
                   1508: #ifdef HAVE_SQLDATASOURCES
                   1509: /* {{{ proto array odbc_data_source(resource connection_id, int fetch_type)
                   1510:    Return information about the currently connected data source */
                   1511: PHP_FUNCTION(odbc_data_source)
                   1512: {
                   1513:        zval *zv_conn;
                   1514:        long zv_fetch_type;
                   1515:        RETCODE rc = 0; /* assume all is good */
                   1516:        odbc_connection *conn;
                   1517:        UCHAR server_name[100], desc[200];
                   1518:        SQLSMALLINT len1=0, len2=0, fetch_type;
                   1519: 
                   1520:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zv_conn, &zv_fetch_type) == FAILURE) {
                   1521:                return;
                   1522:        }
                   1523: 
                   1524:        fetch_type = (SQLSMALLINT) zv_fetch_type;
                   1525: 
                   1526:        if (!(fetch_type == SQL_FETCH_FIRST || fetch_type == SQL_FETCH_NEXT)) {
                   1527:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fetch type (%d)", fetch_type);
                   1528:                RETURN_FALSE;
                   1529:        }
                   1530: 
                   1531:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &zv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   1532: 
                   1533:        /* now we have the "connection" lets call the DataSource object */
                   1534:        rc = SQLDataSources(conn->henv, 
                   1535:                        fetch_type,
                   1536:                        server_name,
                   1537:                        (SQLSMALLINT)sizeof(server_name),
                   1538:                        &len1,
                   1539:                        desc, 
                   1540:                        (SQLSMALLINT)sizeof(desc),
                   1541:                        &len2);
                   1542: 
                   1543:        if (rc != SQL_SUCCESS) {
                   1544:                /* ummm.... he did it */
                   1545:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLDataSources");
                   1546:                RETURN_FALSE;
                   1547:        }
                   1548: 
                   1549:        if (len1 == 0 || len2 == 0) {
                   1550:                /* we have a non-valid entry... so stop the looping */
                   1551:                RETURN_FALSE;
                   1552:        }
                   1553: 
                   1554:        array_init(return_value);
                   1555: 
                   1556:        add_assoc_string_ex(return_value, "server", sizeof("server"), server_name, 1);
                   1557:        add_assoc_string_ex(return_value, "description", sizeof("description"), desc, 1);
                   1558: 
                   1559: }
                   1560: /* }}} */
                   1561: #endif /* HAVE_SQLDATASOURCES */
                   1562: 
                   1563: /* {{{ proto resource odbc_exec(resource connection_id, string query [, int flags])
                   1564:    Prepare and execute an SQL statement */
                   1565: /* XXX Use flags */
                   1566: PHP_FUNCTION(odbc_exec)
                   1567: {
                   1568:        zval *pv_conn;
                   1569:        long pv_flags;
                   1570:        char *query;
                   1571:        int numArgs, query_len;
                   1572:        odbc_result *result = NULL;
                   1573:        odbc_connection *conn;
                   1574:        RETCODE rc;
                   1575: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1576:        SQLUINTEGER      scrollopts;
                   1577: #endif
                   1578: 
                   1579:        numArgs = ZEND_NUM_ARGS();
                   1580:        
                   1581:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &pv_conn, &query, &query_len, &pv_flags) == FAILURE) {
                   1582:                return;
                   1583:        }
                   1584: 
                   1585:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   1586:                
                   1587:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   1588: 
                   1589:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   1590:        if (rc == SQL_INVALID_HANDLE) {
                   1591:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   1592:                efree(result);
                   1593:                RETURN_FALSE;
                   1594:        }
                   1595: 
                   1596:        if (rc == SQL_ERROR) {
                   1597:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   1598:                efree(result);
                   1599:                RETURN_FALSE;
                   1600:        }
                   1601:        
                   1602: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1603:        /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info,
                   1604:           whether Driver supports ExtendedFetch */
                   1605:        rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL);
                   1606:        if (rc == SQL_SUCCESS) {
                   1607:                if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) {
                   1608:                        /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other
                   1609:                           type if not possible.
                   1610:                         */
                   1611:                        SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype));
                   1612:                }
                   1613:        } else {
                   1614:                result->fetch_abs = 0;
                   1615:        }
                   1616: #endif
                   1617: 
                   1618:        rc = SQLExecDirect(result->stmt, query, SQL_NTS);
                   1619:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA_FOUND) { 
                   1620:                /* XXX FIXME we should really check out SQLSTATE with SQLError
                   1621:                 * in case rc is SQL_SUCCESS_WITH_INFO here.
                   1622:                 */
                   1623:                odbc_sql_error(conn, result->stmt, "SQLExecDirect"); 
                   1624:                SQLFreeStmt(result->stmt, SQL_DROP);
                   1625:                efree(result);
                   1626:                RETURN_FALSE;
                   1627:        }
                   1628: 
                   1629:        SQLNumResultCols(result->stmt, &(result->numcols));
                   1630:        
                   1631:        /* For insert, update etc. cols == 0 */
                   1632:        if (result->numcols > 0) {
                   1633:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   1634:                        efree(result);
                   1635:                        RETURN_FALSE;
                   1636:                }
                   1637:        } else {
                   1638:                result->values = NULL;
                   1639:        }
                   1640:        zend_list_addref(conn->id);
                   1641:        result->conn_ptr = conn;
                   1642:        result->fetched = 0;
                   1643:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   1644: }
                   1645: /* }}} */
                   1646: 
                   1647: #ifdef PHP_ODBC_HAVE_FETCH_HASH
                   1648: #define ODBC_NUM  1
                   1649: #define ODBC_OBJECT  2
                   1650: 
                   1651: /* {{{ php_odbc_fetch_hash */
                   1652: static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
                   1653: {
                   1654:        int i;
                   1655:        odbc_result *result;
                   1656:        RETCODE rc;
                   1657:        SQLSMALLINT sql_c_type;
                   1658:        char *buf = NULL;
                   1659: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1660:        SQLULEN crow;
                   1661:        SQLUSMALLINT RowStatus[1];
                   1662:        SQLLEN rownum;
                   1663:        zval *pv_res, *tmp;
                   1664:        long pv_row = -1;
                   1665: 
                   1666:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_res, &pv_row) == FAILURE) {
                   1667:                return;
                   1668:        }
                   1669:        
                   1670:        rownum = pv_row;
                   1671: #else
                   1672:        zval *pv_res, *tmp;
                   1673: 
                   1674:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
                   1675:                return;
                   1676:        }
                   1677: #endif
                   1678: 
                   1679:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   1680: 
                   1681:        if (result->numcols == 0) {
                   1682:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   1683:                RETURN_FALSE;
                   1684:        }
                   1685: 
                   1686: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1687:        if (result->fetch_abs) {
                   1688:                if (rownum > 0) {
                   1689:                        rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
                   1690:                } else {
                   1691:                        rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
                   1692:                }
                   1693:        } else
                   1694: #endif
                   1695:        rc = SQLFetch(result->stmt);
                   1696: 
                   1697:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   1698:                RETURN_FALSE;
                   1699:        }
                   1700:        
                   1701:        array_init(return_value);
                   1702:        
                   1703: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1704:        if (rownum > 0 && result->fetch_abs)
                   1705:                result->fetched = rownum;
                   1706:        else
                   1707: #endif
                   1708:                result->fetched++;
                   1709: 
                   1710:        for(i = 0; i < result->numcols; i++) {
                   1711:                ALLOC_INIT_ZVAL(tmp);
                   1712:                Z_TYPE_P(tmp) = IS_STRING;
                   1713:                Z_STRLEN_P(tmp) = 0;
                   1714:                sql_c_type = SQL_C_CHAR;
                   1715: 
                   1716:                switch(result->values[i].coltype) {
                   1717:                        case SQL_BINARY:
                   1718:                        case SQL_VARBINARY:
                   1719:                        case SQL_LONGVARBINARY:
                   1720:                                if (result->binmode <= 0) {
                   1721:                                        Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
                   1722:                                        break;
                   1723:                                }
                   1724:                                if (result->binmode == 1) {
                   1725:                                        sql_c_type = SQL_C_BINARY;
                   1726:                                }
                   1727:                        case SQL_LONGVARCHAR:
                   1728:                                if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
                   1729:                                        Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
                   1730:                                        break;
                   1731:                                }                               
                   1732:                                if (buf == NULL) {
                   1733:                                        buf = emalloc(result->longreadlen + 1);
                   1734:                                }
                   1735:                                
                   1736:                                rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1), sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen);
                   1737: 
                   1738:                                if (rc == SQL_ERROR) {
                   1739:                                        odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
                   1740:                                        efree(buf);
                   1741:                                        RETURN_FALSE;
                   1742:                                }
                   1743: 
                   1744:                                if (rc == SQL_SUCCESS_WITH_INFO) {
                   1745:                                        Z_STRLEN_P(tmp) = result->longreadlen;
                   1746:                                } else if (result->values[i].vallen == SQL_NULL_DATA) {
                   1747:                                        ZVAL_NULL(tmp);
                   1748:                                        break;
                   1749:                                } else {
                   1750:                                        Z_STRLEN_P(tmp) = result->values[i].vallen;
                   1751:                                }
                   1752:                                Z_STRVAL_P(tmp) = estrndup(buf, Z_STRLEN_P(tmp));
                   1753:                                break;
                   1754: 
                   1755:                        default:
                   1756:                                if (result->values[i].vallen == SQL_NULL_DATA) {
                   1757:                                        ZVAL_NULL(tmp);
                   1758:                                        break;
                   1759:                                }
                   1760:                                Z_STRLEN_P(tmp) = result->values[i].vallen;
                   1761:                                Z_STRVAL_P(tmp) = estrndup(result->values[i].value,Z_STRLEN_P(tmp));
                   1762:                                break;
                   1763:                }
                   1764: 
                   1765:                if (result_type & ODBC_NUM) {
                   1766:                        zend_hash_index_update(Z_ARRVAL_P(return_value), i, &tmp, sizeof(zval *), NULL);
                   1767:                } else {
1.1.1.4   misho    1768:                        if (!*(result->values[i].name) && Z_TYPE_P(tmp) == IS_STRING) {
1.1       misho    1769:                                zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(tmp),     Z_STRLEN_P(tmp)+1, &tmp, sizeof(zval *), NULL);
                   1770:                        } else {
                   1771:                                zend_hash_update(Z_ARRVAL_P(return_value), result->values[i].name, strlen(result->values[i].name)+1, &tmp, sizeof(zval *), NULL);
                   1772:                        }
                   1773:                }
                   1774:        }
                   1775:        if (buf) {
                   1776:                efree(buf);
                   1777:        }
                   1778: }
                   1779: /* }}} */
                   1780: 
                   1781: 
                   1782: /* {{{ proto object odbc_fetch_object(int result [, int rownumber])
                   1783:    Fetch a result row as an object */
                   1784: PHP_FUNCTION(odbc_fetch_object)
                   1785: {
                   1786:        php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT);
                   1787:        if (Z_TYPE_P(return_value) == IS_ARRAY) {
                   1788:                object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
                   1789:        }
                   1790: }
                   1791: /* }}} */
                   1792: 
                   1793: /* {{{ proto array odbc_fetch_array(int result [, int rownumber])
                   1794:    Fetch a result row as an associative array */
                   1795: PHP_FUNCTION(odbc_fetch_array)
                   1796: {
                   1797:        php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT);
                   1798: }
                   1799: /* }}} */
                   1800: #endif
                   1801: 
                   1802: /* {{{ proto int odbc_fetch_into(resource result_id, array &result_array, [, int rownumber])
                   1803:    Fetch one result row into an array */ 
                   1804: PHP_FUNCTION(odbc_fetch_into)
                   1805: {
                   1806:        int i;
                   1807:        odbc_result *result;
                   1808:        RETCODE rc;
                   1809:        SQLSMALLINT sql_c_type;
                   1810:        char *buf = NULL;
                   1811:        zval *pv_res, **pv_res_arr, *tmp;
                   1812: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1813:        long pv_row = 0;
                   1814:        SQLULEN crow;
                   1815:        SQLUSMALLINT RowStatus[1];
                   1816:        SQLLEN rownum = -1;
                   1817: #endif /* HAVE_SQL_EXTENDED_FETCH */
                   1818: 
                   1819: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1820:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ|l", &pv_res, &pv_res_arr, &pv_row) == FAILURE) {
                   1821:                return;
                   1822:        }
                   1823:        
                   1824:        rownum = pv_row;
                   1825: #else
                   1826:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pv_res, &pv_res_arr) == FAILURE) {
                   1827:                return;
                   1828:        }
                   1829: #endif /* HAVE_SQL_EXTENDED_FETCH */
                   1830: 
                   1831:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   1832:        
                   1833:        if (result->numcols == 0) {
                   1834:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   1835:                RETURN_FALSE;
                   1836:        }
                   1837:        
                   1838:        if (Z_TYPE_PP(pv_res_arr) != IS_ARRAY) {
                   1839:                array_init(*pv_res_arr);
                   1840:        }
                   1841: 
                   1842: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1843:        if (result->fetch_abs) {
                   1844:                if (rownum > 0) {
                   1845:                        rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
                   1846:                } else {
                   1847:                        rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
                   1848:                }
                   1849:        } else
                   1850: #endif
                   1851:                rc = SQLFetch(result->stmt);
                   1852: 
                   1853:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   1854:                RETURN_FALSE;
                   1855:        }
                   1856: 
                   1857: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1858:        if (rownum > 0 && result->fetch_abs)
                   1859:                result->fetched = rownum;
                   1860:        else
                   1861: #endif
                   1862:                result->fetched++;
                   1863: 
                   1864:        for(i = 0; i < result->numcols; i++) {
                   1865:                MAKE_STD_ZVAL(tmp);
                   1866:                Z_TYPE_P(tmp) = IS_STRING;
                   1867:                Z_STRLEN_P(tmp) = 0;
                   1868:                sql_c_type = SQL_C_CHAR;
                   1869: 
                   1870:                switch(result->values[i].coltype) {
                   1871:                        case SQL_BINARY:
                   1872:                        case SQL_VARBINARY:
                   1873:                        case SQL_LONGVARBINARY:
                   1874:                                if (result->binmode <= 0) {
                   1875:                                        Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
                   1876:                                        break;
                   1877:                                }
                   1878:                                if (result->binmode == 1) sql_c_type = SQL_C_BINARY; 
                   1879:                        case SQL_LONGVARCHAR:
                   1880:                                if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
                   1881:                                        Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
                   1882:                                        break;
                   1883:                                }
                   1884: 
                   1885:                                if (buf == NULL) {
                   1886:                                        buf = emalloc(result->longreadlen + 1);
                   1887:                                }
                   1888:                                rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen);
                   1889: 
                   1890:                                if (rc == SQL_ERROR) {
                   1891:                                        odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
                   1892:                                        efree(buf);
                   1893:                                        RETURN_FALSE;
                   1894:                                }
                   1895:                                if (rc == SQL_SUCCESS_WITH_INFO) {
                   1896:                                        Z_STRLEN_P(tmp) = result->longreadlen;
                   1897:                                } else if (result->values[i].vallen == SQL_NULL_DATA) {
                   1898:                                        ZVAL_NULL(tmp);
                   1899:                                        break;
                   1900:                                } else {
                   1901:                                        Z_STRLEN_P(tmp) = result->values[i].vallen;
                   1902:                                }
                   1903:                                Z_STRVAL_P(tmp) = estrndup(buf, Z_STRLEN_P(tmp));
                   1904:                                break;
                   1905: 
                   1906:                        default:
                   1907:                                if (result->values[i].vallen == SQL_NULL_DATA) {
                   1908:                                        ZVAL_NULL(tmp);
                   1909:                                        break;
                   1910:                                }
                   1911:                                Z_STRLEN_P(tmp) = result->values[i].vallen;
                   1912:                                Z_STRVAL_P(tmp) = estrndup(result->values[i].value,Z_STRLEN_P(tmp));
                   1913:                                break;
                   1914:                }
                   1915:                zend_hash_index_update(Z_ARRVAL_PP(pv_res_arr), i, &tmp, sizeof(zval *), NULL);
                   1916:        }
                   1917:        if (buf) efree(buf);
                   1918:        RETURN_LONG(result->numcols);   
                   1919: }
                   1920: /* }}} */
                   1921: 
                   1922: /* {{{ proto bool solid_fetch_prev(resource result_id)
                   1923:    */ 
                   1924: #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35)
                   1925: PHP_FUNCTION(solid_fetch_prev)
                   1926: {
                   1927:        odbc_result *result;
                   1928:        RETCODE rc;
                   1929:        zval *pv_res;
                   1930:        
                   1931:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
                   1932:                return;
                   1933:        }
                   1934:        
                   1935:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   1936:        if (result->numcols == 0) {
                   1937:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   1938:                RETURN_FALSE;
                   1939:        }
                   1940:        rc = SQLFetchPrev(result->stmt);
                   1941: 
                   1942:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   1943:                RETURN_FALSE;
                   1944:        }
                   1945: 
                   1946:        if (result->fetched > 1) {
                   1947:                result->fetched--;
                   1948:        }
                   1949: 
                   1950:        RETURN_TRUE;
                   1951: }
                   1952: #endif
                   1953: /* }}} */
                   1954: 
                   1955: /* {{{ proto bool odbc_fetch_row(resource result_id [, int row_number])
                   1956:    Fetch a row */
                   1957: PHP_FUNCTION(odbc_fetch_row)
                   1958: {
                   1959:        SQLLEN rownum;
                   1960:        odbc_result *result;
                   1961:        RETCODE rc;
                   1962:        zval *pv_res;
                   1963:        long pv_row = 1;
                   1964: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1965:        SQLULEN crow;
                   1966:        SQLUSMALLINT RowStatus[1];
                   1967: #endif
                   1968: 
                   1969:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_res, &pv_row) == FAILURE) {
                   1970:                return;
                   1971:        }
                   1972:        
                   1973:        rownum = pv_row;
                   1974:        
                   1975:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   1976:        
                   1977:        if (result->numcols == 0) {
                   1978:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   1979:                RETURN_FALSE;
                   1980:        }
                   1981: 
                   1982: #ifdef HAVE_SQL_EXTENDED_FETCH
                   1983:        if (result->fetch_abs) {
                   1984:                if (ZEND_NUM_ARGS() > 1) {
                   1985:                        rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
                   1986:                } else {
                   1987:                        rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
                   1988:                }
                   1989:        } else
                   1990: #endif
                   1991:                rc = SQLFetch(result->stmt);
                   1992: 
                   1993:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   1994:                RETURN_FALSE;
                   1995:        }
                   1996:        
                   1997:        if (ZEND_NUM_ARGS() > 1) {
                   1998:                result->fetched = rownum;
                   1999:        } else {
                   2000:                result->fetched++;
                   2001:        }
                   2002:        
                   2003:        RETURN_TRUE;
                   2004: }      
                   2005: /* }}} */
                   2006: 
                   2007: /* {{{ proto mixed odbc_result(resource result_id, mixed field)
                   2008:    Get result data */ 
                   2009: PHP_FUNCTION(odbc_result)
                   2010: {
                   2011:        char *field;
                   2012:        int field_ind;
                   2013:        SQLSMALLINT sql_c_type = SQL_C_CHAR;
                   2014:        odbc_result *result;
                   2015:        int i = 0;
                   2016:        RETCODE rc;
                   2017:        SQLLEN  fieldsize;
                   2018:        zval *pv_res, **pv_field;
                   2019: #ifdef HAVE_SQL_EXTENDED_FETCH
                   2020:        SQLULEN crow;
                   2021:        SQLUSMALLINT RowStatus[1];
                   2022: #endif
                   2023: 
                   2024:        field_ind = -1;
                   2025:        field = NULL;
                   2026: 
                   2027:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pv_res, &pv_field) == FAILURE) {
                   2028:                return;
                   2029:        }
                   2030:        
                   2031:        if (Z_TYPE_PP(pv_field) == IS_STRING) {
                   2032:                field = Z_STRVAL_PP(pv_field);
                   2033:        } else {
                   2034:                convert_to_long_ex(pv_field);
                   2035:                field_ind = Z_LVAL_PP(pv_field) - 1;
                   2036:        }
                   2037:        
                   2038:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   2039:        
                   2040:        if ((result->numcols == 0)) {
                   2041:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   2042:                RETURN_FALSE;
                   2043:        }
                   2044:        
                   2045:        /* get field index if the field parameter was a string */
                   2046:        if (field != NULL) {
                   2047:                if (result->values == NULL) {
                   2048:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result set contains no data");
                   2049:                        RETURN_FALSE;
                   2050:                }
                   2051: 
                   2052:                for(i = 0; i < result->numcols; i++) {
                   2053:                        if (!strcasecmp(result->values[i].name, field)) {
                   2054:                                field_ind = i;
                   2055:                                break;
                   2056:                        }
                   2057:                }
                   2058: 
                   2059:                if (field_ind < 0) {
                   2060:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field %s not found", field);
                   2061:                        RETURN_FALSE;
                   2062:                }
                   2063:        } else {
                   2064:                /* check for limits of field_ind if the field parameter was an int */
                   2065:                if (field_ind >= result->numcols || field_ind < 0) {
                   2066:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index is larger than the number of fields");
                   2067:                        RETURN_FALSE;
                   2068:                }
                   2069:        }
                   2070: 
                   2071:        if (result->fetched == 0) {
                   2072:                /* User forgot to call odbc_fetch_row(), or wants to reload the results, do it now */
                   2073: #ifdef HAVE_SQL_EXTENDED_FETCH
                   2074:                if (result->fetch_abs)
                   2075:                        rc = SQLExtendedFetch(result->stmt, SQL_FETCH_NEXT, 1, &crow,RowStatus);
                   2076:                else
                   2077: #endif
                   2078:                        rc = SQLFetch(result->stmt);
                   2079: 
                   2080:                if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   2081:                        RETURN_FALSE;
                   2082:                }
                   2083:                
                   2084:                result->fetched++;
                   2085:        }
                   2086: 
                   2087:        switch(result->values[field_ind].coltype) {
                   2088:                case SQL_BINARY:
                   2089:                case SQL_VARBINARY:
                   2090:                case SQL_LONGVARBINARY:
                   2091:                        if (result->binmode <= 1) {
                   2092:                                sql_c_type = SQL_C_BINARY;
                   2093:                        }
                   2094:                        if (result->binmode <= 0) {
                   2095:                                break; 
                   2096:                        }
                   2097:                case SQL_LONGVARCHAR:
                   2098:                        if (IS_SQL_LONG(result->values[field_ind].coltype)) {
                   2099:                                if (result->longreadlen <= 0) {
                   2100:                                   break;
                   2101:                                } else {
                   2102:                                   fieldsize = result->longreadlen;
                   2103:                                }
                   2104:                        } else {
                   2105:                           SQLColAttributes(result->stmt, (SQLUSMALLINT)(field_ind + 1), 
                   2106:                                                                (SQLUSMALLINT)((sql_c_type == SQL_C_BINARY) ? SQL_COLUMN_LENGTH :
                   2107:                                                                SQL_COLUMN_DISPLAY_SIZE),
                   2108:                                                                NULL, 0, NULL, &fieldsize);
                   2109:                        }
                   2110:                        /* For char data, the length of the returned string will be longreadlen - 1 */
                   2111:                        fieldsize = (result->longreadlen <= 0) ? 4096 : result->longreadlen;
                   2112:                        field = emalloc(fieldsize);
                   2113: 
                   2114:                /* SQLGetData will truncate CHAR data to fieldsize - 1 bytes and append \0.
                   2115:                 * For binary data it is truncated to fieldsize bytes. 
                   2116:                 */
                   2117:                        rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1), sql_c_type,
                   2118:                                                        field, fieldsize, &result->values[field_ind].vallen);
                   2119: 
                   2120:                        if (rc == SQL_ERROR) {
                   2121:                                odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
                   2122:                                efree(field);
                   2123:                                RETURN_FALSE;
                   2124:                        }
                   2125: 
                   2126:                        if (result->values[field_ind].vallen == SQL_NULL_DATA) {
                   2127:                                efree(field);
                   2128:                                RETURN_NULL();
                   2129:                        } else if (rc == SQL_NO_DATA_FOUND) {
                   2130:                                efree(field);
                   2131:                                RETURN_FALSE;
                   2132:                        }
                   2133:                        /* Reduce fieldlen by 1 if we have char data. One day we might 
                   2134:                           have binary strings... */
                   2135:                        if (result->values[field_ind].coltype == SQL_LONGVARCHAR) {
                   2136:                                fieldsize -= 1;
                   2137:                        }
                   2138:                        /* Don't duplicate result, saves one emalloc.
                   2139:                           For SQL_SUCCESS, the length is in vallen.
                   2140:                         */
                   2141:                        RETURN_STRINGL(field, (rc == SQL_SUCCESS_WITH_INFO) ? fieldsize : result->values[field_ind].vallen, 0);
                   2142:                        break;
                   2143:                        
                   2144:                default:
                   2145:                        if (result->values[field_ind].vallen == SQL_NULL_DATA) {
                   2146:                                RETURN_NULL();
                   2147:                        } else {
                   2148:                                RETURN_STRINGL(result->values[field_ind].value, result->values[field_ind].vallen, 1);
                   2149:                        }
                   2150:                        break;
                   2151:        }
                   2152: 
                   2153: /* If we come here, output unbound LONG and/or BINARY column data to the client */
                   2154:        
                   2155:        /* We emalloc 1 byte more for SQL_C_CHAR (trailing \0) */
                   2156:        fieldsize = (sql_c_type == SQL_C_CHAR) ? 4096 : 4095;
                   2157:        field = emalloc(fieldsize);
                   2158:        
                   2159:        /* Call SQLGetData() until SQL_SUCCESS is returned */
                   2160:        while(1) {
                   2161:                rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1),sql_c_type, field, fieldsize, &result->values[field_ind].vallen);
                   2162: 
                   2163:                if (rc == SQL_ERROR) {
                   2164:                        odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
                   2165:                        efree(field);
                   2166:                        RETURN_FALSE;
                   2167:                }
                   2168:                
                   2169:                if (result->values[field_ind].vallen == SQL_NULL_DATA) {
                   2170:                        efree(field);
                   2171:                        RETURN_NULL();
                   2172:                }
                   2173:                /* chop the trailing \0 by outputing only 4095 bytes */
                   2174:                PHPWRITE(field,(rc == SQL_SUCCESS_WITH_INFO) ? 4095 : result->values[field_ind].vallen);
                   2175: 
                   2176:                if (rc == SQL_SUCCESS) { /* no more data avail */
                   2177:                        efree(field);
                   2178:                        RETURN_TRUE;
                   2179:                }
                   2180:        }
                   2181:        RETURN_TRUE;
                   2182: }
                   2183: /* }}} */
                   2184: 
                   2185: /* {{{ proto int odbc_result_all(resource result_id [, string format])
                   2186:    Print result as HTML table */
                   2187: PHP_FUNCTION(odbc_result_all)
                   2188: {
                   2189:        char *buf = NULL;
                   2190:        odbc_result *result;
                   2191:        RETCODE rc;
                   2192:        zval *pv_res;
                   2193:        char *pv_format = NULL;
                   2194:        int i, pv_format_len = 0;
                   2195:        SQLSMALLINT sql_c_type;
                   2196: #ifdef HAVE_SQL_EXTENDED_FETCH
                   2197:        SQLULEN crow;
                   2198:        SQLUSMALLINT RowStatus[1];
                   2199: #endif
                   2200: 
                   2201:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s", &pv_res, &pv_format, &pv_format_len) == FAILURE) {
                   2202:                return;
                   2203:        }
                   2204:                                
                   2205:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   2206:        
                   2207:        if (result->numcols == 0) {
                   2208:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   2209:                RETURN_FALSE;
                   2210:        }
                   2211: #ifdef HAVE_SQL_EXTENDED_FETCH
                   2212:        if (result->fetch_abs)
                   2213:                rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
                   2214:        else
                   2215: #endif 
                   2216:                rc = SQLFetch(result->stmt);
                   2217: 
                   2218:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   2219:                php_printf("<h2>No rows found</h2>\n");
                   2220:                RETURN_LONG(0);
                   2221:        }
                   2222:        
                   2223:        /* Start table tag */
                   2224:        if (ZEND_NUM_ARGS() == 1) {
                   2225:                php_printf("<table><tr>");
                   2226:        } else {
                   2227:                php_printf("<table %s ><tr>", pv_format);
                   2228:        }
                   2229:        
                   2230:        for (i = 0; i < result->numcols; i++) {
                   2231:                php_printf("<th>%s</th>", result->values[i].name);
                   2232:        }
                   2233: 
                   2234:        php_printf("</tr>\n");
                   2235: 
                   2236:        while(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
                   2237:                result->fetched++;
                   2238:                php_printf("<tr>");
                   2239:                for(i = 0; i < result->numcols; i++) {
                   2240:                        sql_c_type = SQL_C_CHAR;
                   2241:                        switch(result->values[i].coltype) {
                   2242:                                case SQL_BINARY:
                   2243:                                case SQL_VARBINARY:
                   2244:                                case SQL_LONGVARBINARY:
                   2245:                                        if (result->binmode <= 0) {
                   2246:                                                php_printf("<td>Not printable</td>");
                   2247:                                                break;
                   2248:                                        }
                   2249:                                        if (result->binmode <= 1) sql_c_type = SQL_C_BINARY; 
                   2250:                                case SQL_LONGVARCHAR:
                   2251:                                        if (IS_SQL_LONG(result->values[i].coltype) && 
                   2252:                                                result->longreadlen <= 0) {
                   2253:                                                php_printf("<td>Not printable</td>"); 
                   2254:                                                break;
                   2255:                                        }
                   2256: 
                   2257:                                        if (buf == NULL) {
                   2258:                                                buf = emalloc(result->longreadlen);
                   2259:                                        }
                   2260: 
                   2261:                                        rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen, &result->values[i].vallen);
                   2262:  
                   2263:                                        php_printf("<td>");
                   2264: 
                   2265:                                        if (rc == SQL_ERROR) {
                   2266:                                                odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
                   2267:                                                php_printf("</td></tr></table>");
                   2268:                                                efree(buf);
                   2269:                                                RETURN_FALSE;
                   2270:                                        }
                   2271:                                        if (rc == SQL_SUCCESS_WITH_INFO) {
                   2272:                                                PHPWRITE(buf, result->longreadlen);
                   2273:                                        } else if (result->values[i].vallen == SQL_NULL_DATA) {
                   2274:                                                php_printf("<td>NULL</td>");
                   2275:                                                break;
                   2276:                                        } else {
                   2277:                                                PHPWRITE(buf, result->values[i].vallen);
                   2278:                                        }
                   2279:                                        php_printf("</td>");
                   2280:                                        break;
                   2281:                                default:
                   2282:                                        if (result->values[i].vallen == SQL_NULL_DATA) {
                   2283:                                                php_printf("<td>NULL</td>");
                   2284:                                        } else {
                   2285:                                                php_printf("<td>%s</td>", result->values[i].value);
                   2286:                                        }
                   2287:                                        break;
                   2288:                        }
                   2289:                }
                   2290:                php_printf("</tr>\n");
                   2291: 
                   2292: #ifdef HAVE_SQL_EXTENDED_FETCH
                   2293:                if (result->fetch_abs)
                   2294:                        rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
                   2295:                else
                   2296: #endif
                   2297:                        rc = SQLFetch(result->stmt);            
                   2298:        }
                   2299:        php_printf("</table>\n");
                   2300:        if (buf) efree(buf);
                   2301:        RETURN_LONG(result->fetched);
                   2302: }
                   2303: /* }}} */
                   2304: 
                   2305: /* {{{ proto bool odbc_free_result(resource result_id)
                   2306:    Free resources associated with a result */
                   2307: PHP_FUNCTION(odbc_free_result)
                   2308: {
                   2309:        zval *pv_res;
                   2310:        odbc_result *result;
                   2311:        int i;
                   2312: 
                   2313:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
                   2314:                return;
                   2315:        }
                   2316: 
                   2317:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   2318:        if (result->values) {
                   2319:                for (i = 0; i < result->numcols; i++) {
                   2320:                        if (result->values[i].value) {
                   2321:                                efree(result->values[i].value);
                   2322:                        }
                   2323:                }
                   2324:                efree(result->values);
                   2325:                result->values = NULL;
                   2326:        }
                   2327:                        
                   2328:        zend_list_delete(Z_LVAL_P(pv_res));
                   2329:        
                   2330:        RETURN_TRUE;
                   2331: }
                   2332: /* }}} */
                   2333: 
                   2334: /* {{{ proto resource odbc_connect(string DSN, string user, string password [, int cursor_option])
                   2335:    Connect to a datasource */
                   2336: PHP_FUNCTION(odbc_connect)
                   2337: {
                   2338:        odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                   2339: }
                   2340: /* }}} */
                   2341: 
                   2342: /* {{{ proto resource odbc_pconnect(string DSN, string user, string password [, int cursor_option])
                   2343:    Establish a persistent connection to a datasource */
                   2344: PHP_FUNCTION(odbc_pconnect)
                   2345: {
                   2346:        odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                   2347: }
                   2348: /* }}} */
                   2349: 
                   2350: /* {{{ odbc_sqlconnect */
                   2351: int odbc_sqlconnect(odbc_connection **conn, char *db, char *uid, char *pwd, int cur_opt, int persistent TSRMLS_DC)
                   2352: {
                   2353:        RETCODE rc;
                   2354:        
                   2355:        *conn = (odbc_connection *)pemalloc(sizeof(odbc_connection), persistent);
                   2356:        (*conn)->persistent = persistent;
                   2357:        SQLAllocEnv(&((*conn)->henv));
                   2358:        SQLAllocConnect((*conn)->henv, &((*conn)->hdbc));
                   2359:        
                   2360: #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) 
                   2361:        SQLSetConnectOption((*conn)->hdbc, SQL_TRANSLATE_OPTION,
                   2362:                        SQL_SOLID_XLATOPT_NOCNV);
                   2363: #endif
                   2364: #ifdef HAVE_ODBC_ROUTER
                   2365:        {
                   2366: #define CONNSTRSIZE 2048
                   2367:         char *lpszConnStr = emalloc(CONNSTRSIZE);
                   2368:         if (lpszConnStr && db) {
                   2369:                 short cbszConnStr;
                   2370:                 if (strstr(db, ";")) {
                   2371:                         /* the caller has apparently passed a connection-string */
                   2372:                         if (strstr(db, "uid") || strstr(db, "UID")) {
                   2373:                                 uid = NULL;
                   2374:                         }
                   2375:                         if (strstr(db, "pwd") || strstr(db, "PWD")) {
                   2376:                                 pwd = NULL;
                   2377:                         }
                   2378:                         strlcpy( lpszConnStr, db, CONNSTRSIZE);
                   2379:                 }
                   2380:                 else {
                   2381:                         strcpy(lpszConnStr, "DSN=");
                   2382:                         strlcat(lpszConnStr, db, CONNSTRSIZE);
                   2383:                 }
                   2384:                 if (uid) {
                   2385:                         if (uid[0]) {
                   2386:                                 strlcat(lpszConnStr, ";UID=", CONNSTRSIZE);
                   2387:                                 strlcat(lpszConnStr, uid, CONNSTRSIZE);
                   2388:                                 strlcat(lpszConnStr, ";", CONNSTRSIZE);
                   2389:                         }
                   2390:                         if (pwd) {
                   2391:                                 if (pwd[0]) {
                   2392:                                         strlcat(lpszConnStr, "PWD=", CONNSTRSIZE);
                   2393:                                         strlcat(lpszConnStr, pwd, CONNSTRSIZE);
                   2394:                                         strlcat(lpszConnStr, ";", CONNSTRSIZE);
                   2395:                                 }
                   2396:                         }
                   2397:                 }
                   2398:                 rc = SQLDriverConnect((*conn)->hdbc, NULL, lpszConnStr, SQL_NTS, lpszConnStr, CONNSTRSIZE, &cbszConnStr, SQL_DRIVER_NOPROMPT);
                   2399:                 efree(lpszConnStr);
                   2400:         }
                   2401:        }
                   2402: #else
                   2403: #ifdef HAVE_OPENLINK
                   2404:        {
                   2405:                char dsnbuf[1024];
                   2406:                short dsnbuflen;
                   2407: 
                   2408:                rc = SQLDriverConnect((*conn)->hdbc, NULL, db, SQL_NTS, dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
                   2409:        }
                   2410: #else
                   2411:        if (cur_opt != SQL_CUR_DEFAULT) {
                   2412:                rc = SQLSetConnectOption((*conn)->hdbc, SQL_ODBC_CURSORS, cur_opt);
                   2413:                if (rc != SQL_SUCCESS) {  /* && rc != SQL_SUCCESS_WITH_INFO ? */
                   2414:                        odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLSetConnectOption");
                   2415:                        SQLFreeConnect((*conn)->hdbc);
                   2416:                        pefree(*conn, persistent);
                   2417:                        return FALSE;
                   2418:                }
                   2419:        }
                   2420: /*  Possible fix for bug #10250
                   2421:  *  Needs testing on UnixODBC < 2.0.5 though. */
                   2422: #if defined(HAVE_EMPRESS) || defined(HAVE_UNIXODBC) || defined(PHP_WIN32) || defined (HAVE_IODBC)
                   2423: /* *  Uncomment the line above, and comment line below to fully test 
                   2424:  * #ifdef HAVE_EMPRESS */
                   2425:        {
                   2426:                int     direct = 0;
                   2427:                char    dsnbuf[1024];
                   2428:                short   dsnbuflen;
                   2429:                char    *ldb = 0;
                   2430:                int             ldb_len = 0;
                   2431: 
                   2432:                if (strstr((char*)db, ";")) {
                   2433:                        direct = 1;
                   2434:                        if (uid && !strstr ((char*)db, "uid") && !strstr((char*)db, "UID")) {
                   2435:                                spprintf(&ldb, 0, "%s;UID=%s;PWD=%s", db, uid, pwd);
                   2436:                        } else {
                   2437:                                ldb_len = strlen(db)+1;
                   2438:                                ldb = (char*) emalloc(ldb_len);
                   2439:                                memcpy(ldb, db, ldb_len);
                   2440:                        }
                   2441:                }
                   2442: 
                   2443:                if (direct) {
                   2444:                        rc = SQLDriverConnect((*conn)->hdbc, NULL, ldb, strlen(ldb), dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
                   2445:                } else {
                   2446:                        rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
                   2447:                }
                   2448: 
                   2449:                if (ldb) {
                   2450:                        efree(ldb);
                   2451:                }
                   2452:        }
                   2453: #else
                   2454:        rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
                   2455: #endif
                   2456: #endif
                   2457: #endif
                   2458:        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   2459:                odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLConnect");
                   2460:                SQLFreeConnect((*conn)->hdbc);
                   2461:                pefree((*conn), persistent);
                   2462:                return FALSE;
                   2463:        }
                   2464: /*     (*conn)->open = 1;*/
                   2465:        return TRUE;
                   2466: }
                   2467: /* }}} */
                   2468: 
                   2469: /* Persistent connections: two list-types le_pconn, le_conn and a plist
                   2470:  * where hashed connection info is stored together with index pointer to
                   2471:  * the actual link of type le_pconn in the list. Only persistent 
                   2472:  * connections get hashed up. Normal connections use existing pconnections.
                   2473:  * Maybe this has to change with regard to transactions on pconnections?
                   2474:  * Possibly set autocommit to on on request shutdown.
                   2475:  *
                   2476:  * We do have to hash non-persistent connections, and reuse connections.
                   2477:  * In the case where two connects were being made, without closing the first
                   2478:  * connect, access violations were occuring.  This is because some of the
                   2479:  * "globals" in this module should actualy be per-connection variables.  I
                   2480:  * simply fixed things to get them working for now.  Shane
                   2481:  */
                   2482: /* {{{ odbc_do_connect */
                   2483: void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                   2484: {
                   2485:        char *db, *uid, *pwd;
                   2486:        int db_len, uid_len, pwd_len;
                   2487:        long pv_opt = SQL_CUR_DEFAULT;
                   2488:        odbc_connection *db_conn;
                   2489:        char *hashed_details;
                   2490:        int hashed_len, cur_opt;
                   2491: 
                   2492:        /*  Now an optional 4th parameter specifying the cursor type
                   2493:         *  defaulting to the cursors default
                   2494:         */
                   2495:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|l", &db, &db_len, &uid, &uid_len, &pwd, &pwd_len, &pv_opt) == FAILURE) {
                   2496:                return;
                   2497:        }
                   2498:        
                   2499:        cur_opt = pv_opt;
                   2500:        
                   2501:        if (ZEND_NUM_ARGS() > 3) {
                   2502:                /* Confirm the cur_opt range */
                   2503:                if (! (cur_opt == SQL_CUR_USE_IF_NEEDED || 
                   2504:                        cur_opt == SQL_CUR_USE_ODBC || 
                   2505:                        cur_opt == SQL_CUR_USE_DRIVER || 
                   2506:                        cur_opt == SQL_CUR_DEFAULT) ) {
                   2507:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Cursor type (%d)", cur_opt);
                   2508:                        RETURN_FALSE;
                   2509:                }
                   2510:        }
                   2511: 
                   2512:        if (ODBCG(allow_persistent) <= 0) {
                   2513:                persistent = 0;
                   2514:        }
                   2515: 
                   2516:        hashed_len = spprintf(&hashed_details, 0, "%s_%s_%s_%s_%d", ODBC_TYPE, db, uid, pwd, cur_opt);
                   2517: 
                   2518:        /* FIXME the idea of checking to see if our connection is already persistent
                   2519:                is good, but it adds a lot of overhead to non-persistent connections.  We
                   2520:                should look and see if we can fix that somehow */
                   2521:        /* try to find if we already have this link in our persistent list,
                   2522:         * no matter if it is to be persistent or not
                   2523:         */
                   2524: 
                   2525: try_and_get_another_connection:
                   2526: 
                   2527:        if (persistent) {
                   2528:                zend_rsrc_list_entry *le;
                   2529:                
                   2530:                /* the link is not in the persistent list */
                   2531:                if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_len + 1, (void **) &le) == FAILURE) {
                   2532:                        zend_rsrc_list_entry new_le;
                   2533:                        
                   2534:                        if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) {
                   2535:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", ODBCG(num_links));
                   2536:                                efree(hashed_details);
                   2537:                                RETURN_FALSE;
                   2538:                        }
                   2539:                        if (ODBCG(max_persistent) != -1 && ODBCG(num_persistent) >= ODBCG(max_persistent)) {
                   2540:                                php_error_docref(NULL TSRMLS_CC, E_WARNING,"Too many open persistent links (%ld)", ODBCG(num_persistent));
                   2541:                                efree(hashed_details);
                   2542:                                RETURN_FALSE;
                   2543:                        }
                   2544:                        
                   2545:                        if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 1 TSRMLS_CC)) {
                   2546:                                efree(hashed_details);
                   2547:                                RETURN_FALSE;
                   2548:                        }
                   2549:                        
                   2550:                        Z_TYPE(new_le) = le_pconn;
                   2551:                        new_le.ptr = db_conn;
                   2552:                        if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_len + 1, &new_le,
                   2553:                                                sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
                   2554:                                free(db_conn);
                   2555:                                efree(hashed_details);
                   2556:                                RETURN_FALSE;
                   2557:                        }
                   2558:                        ODBCG(num_persistent)++;
                   2559:                        ODBCG(num_links)++;
                   2560:                        db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_pconn);
                   2561:                } else { /* found connection */
                   2562:                        if (Z_TYPE_P(le) != le_pconn) {
                   2563:                                RETURN_FALSE;
                   2564:                        }
                   2565:                        /*
                   2566:                         * check to see if the connection is still valid
                   2567:                         */
                   2568:                        db_conn = (odbc_connection *)le->ptr;
                   2569: 
                   2570:                        /*
                   2571:                         * check to see if the connection is still in place (lurcher)
                   2572:                         */
                   2573:                        if(ODBCG(check_persistent)){
                   2574:                                RETCODE ret;
                   2575:                                UCHAR d_name[32];
                   2576:                                SQLSMALLINT len;
                   2577: 
                   2578:                                ret = SQLGetInfo(db_conn->hdbc, 
                   2579:                                        SQL_DATA_SOURCE_READ_ONLY, 
                   2580:                                        d_name, sizeof(d_name), &len);
                   2581: 
                   2582:                                if(ret != SQL_SUCCESS || len == 0) {
                   2583:                                        zend_hash_del(&EG(persistent_list), hashed_details, hashed_len + 1);
                   2584:                                        /* Commented out to fix a possible double closure error 
                   2585:                                         * when working with persistent connections as submitted by
                   2586:                                         * bug #15758
                   2587:                                         *
                   2588:                                         * safe_odbc_disconnect(db_conn->hdbc);
                   2589:                                         * SQLFreeConnect(db_conn->hdbc);
                   2590:                                         */
                   2591:                                        goto try_and_get_another_connection;
                   2592:                                }
                   2593:                        }
                   2594:                }
                   2595:                db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_pconn);
                   2596:        } else { /* non persistent */
                   2597:                zend_rsrc_list_entry *index_ptr, new_index_ptr;
                   2598:                
                   2599:                if (zend_hash_find(&EG(regular_list), hashed_details, hashed_len + 1, (void **) &index_ptr) == SUCCESS) {
                   2600:                        int type, conn_id;
                   2601:                        void *ptr;
                   2602: 
                   2603:                        if (Z_TYPE_P(index_ptr) != le_index_ptr) {
                   2604:                                RETURN_FALSE;
                   2605:                        }
                   2606:                        conn_id = (int)index_ptr->ptr;
                   2607:                        ptr = zend_list_find(conn_id, &type);   /* check if the connection is still there */
                   2608: 
                   2609:                        if (ptr && (type == le_conn || type == le_pconn)) {
                   2610:                                zend_list_addref(conn_id);
                   2611:                                Z_LVAL_P(return_value) = conn_id;
                   2612:                                Z_TYPE_P(return_value) = IS_RESOURCE;
                   2613:                                efree(hashed_details);
                   2614:                                return;
                   2615:                        } else {
                   2616:                                zend_hash_del(&EG(regular_list), hashed_details, hashed_len + 1);
                   2617:                        }
                   2618:                }
                   2619:                if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) {
                   2620:                        php_error_docref(NULL TSRMLS_CC, E_WARNING,"Too many open connections (%ld)",ODBCG(num_links));
                   2621:                        efree(hashed_details);
                   2622:                        RETURN_FALSE;
                   2623:                }
                   2624: 
                   2625:                if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 0 TSRMLS_CC)) {
                   2626:                        efree(hashed_details);
                   2627:                        RETURN_FALSE;
                   2628:                }
                   2629:                db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_conn);
                   2630:                new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
                   2631:                Z_TYPE(new_index_ptr) = le_index_ptr;
                   2632: 
                   2633:                if (zend_hash_update(&EG(regular_list), hashed_details, hashed_len + 1, (void *) &new_index_ptr,
                   2634:                                   sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
                   2635:                        efree(hashed_details);
                   2636:                        RETURN_FALSE;
                   2637:                        /* XXX Free Connection */
                   2638:                }
                   2639:                ODBCG(num_links)++;
                   2640:        }
                   2641:        efree(hashed_details);
                   2642: }
                   2643: /* }}} */
                   2644: 
                   2645: /* {{{ proto void odbc_close(resource connection_id)
                   2646:    Close an ODBC connection */
                   2647: PHP_FUNCTION(odbc_close)
                   2648: {
                   2649:        zval *pv_conn;
                   2650:        void *ptr;
                   2651:        odbc_connection *conn;
                   2652:        odbc_result *res;
                   2653:        int nument;
                   2654:        int i;
                   2655:        int type;
                   2656:        int is_pconn = 0;
                   2657:        int found_resource_type = le_conn;
                   2658: 
                   2659:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_conn) == FAILURE) {
                   2660:                return;
                   2661:        }
                   2662: 
                   2663:        conn = (odbc_connection *) zend_fetch_resource(&pv_conn TSRMLS_CC, -1, "ODBC-Link", &found_resource_type, 2, le_conn, le_pconn);
                   2664:        if (found_resource_type==le_pconn) {
                   2665:                is_pconn = 1;
                   2666:        }
                   2667: 
                   2668:        nument = zend_hash_next_free_element(&EG(regular_list));
                   2669: 
                   2670:        for(i = 1; i < nument; i++){
                   2671:                ptr = zend_list_find(i, &type);
                   2672:                if(ptr && (type == le_result)){
                   2673:                        res = (odbc_result *)ptr;
                   2674:                        if(res->conn_ptr == conn){
                   2675:                                zend_list_delete(i);
                   2676:                        }
                   2677:                }
                   2678:        }
                   2679:        
                   2680:        zend_list_delete(Z_LVAL_P(pv_conn));
                   2681:        
                   2682:        if(is_pconn){
                   2683:                zend_hash_apply_with_argument(&EG(persistent_list),     (apply_func_arg_t) _close_pconn_with_id, (void *) &(Z_LVAL_P(pv_conn)) TSRMLS_CC);      
                   2684:        }
                   2685: }
                   2686: /* }}} */
                   2687: 
                   2688: /* {{{ proto int odbc_num_rows(resource result_id)
                   2689:    Get number of rows in a result */
                   2690: PHP_FUNCTION(odbc_num_rows)
                   2691: {
                   2692:        odbc_result *result;
                   2693:        SQLLEN rows;
                   2694:        zval *pv_res;
                   2695:        
                   2696:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
                   2697:                return;
                   2698:        }
                   2699:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   2700:        SQLRowCount(result->stmt, &rows);
                   2701:        RETURN_LONG(rows);
                   2702: }
                   2703: /* }}} */
                   2704: 
                   2705: #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
                   2706: /* {{{ proto bool odbc_next_result(resource result_id)
1.1.1.4   misho    2707:    Checks if multiple results are available */
1.1       misho    2708: PHP_FUNCTION(odbc_next_result)
                   2709: {
                   2710:        odbc_result *result;
                   2711:        zval *pv_res;
                   2712:        int rc, i;
                   2713: 
                   2714:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
                   2715:                return;
                   2716:        }
                   2717:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 
                   2718: 
                   2719:        if (result->values) {
                   2720:                for(i = 0; i < result->numcols; i++) {
                   2721:                        if (result->values[i].value) {
                   2722:                                efree(result->values[i].value);
                   2723:                        }
                   2724:                }
                   2725:                efree(result->values);
                   2726:                result->values = NULL;
                   2727:        }
                   2728: 
                   2729:        result->fetched = 0;
                   2730:        rc = SQLMoreResults(result->stmt);
                   2731:        if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS) {
                   2732:                rc = SQLFreeStmt(result->stmt, SQL_UNBIND);
                   2733:                SQLNumParams(result->stmt, &(result->numparams));
                   2734:                SQLNumResultCols(result->stmt, &(result->numcols));
                   2735: 
                   2736:                if (result->numcols > 0) {
                   2737:                        if (!odbc_bindcols(result TSRMLS_CC)) {
                   2738:                                efree(result);
                   2739:                                RETVAL_FALSE;
                   2740:                        }
                   2741:                } else {
                   2742:                        result->values = NULL;
                   2743:                }
                   2744:                RETURN_TRUE;
                   2745:        } else if (rc == SQL_NO_DATA_FOUND) {
                   2746:                RETURN_FALSE;
                   2747:        } else {
                   2748:                odbc_sql_error(result->conn_ptr, result->stmt, "SQLMoreResults");
                   2749:                RETURN_FALSE;
                   2750:        }
                   2751: }
                   2752: /* }}} */
                   2753: #endif
                   2754: 
                   2755: /* {{{ proto int odbc_num_fields(resource result_id)
                   2756:    Get number of columns in a result */
                   2757: PHP_FUNCTION(odbc_num_fields)
                   2758: {
                   2759:        odbc_result *result;
                   2760:        zval *pv_res;
                   2761: 
                   2762:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
                   2763:                return;
                   2764:        }
                   2765:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   2766:        RETURN_LONG(result->numcols);
                   2767: }
                   2768: /* }}} */
                   2769: 
                   2770: /* {{{ proto string odbc_field_name(resource result_id, int field_number)
                   2771:    Get a column name */
                   2772: PHP_FUNCTION(odbc_field_name)
                   2773: {
                   2774:        odbc_result *result;
                   2775:        zval *pv_res;
                   2776:        long pv_num;
                   2777:        
                   2778:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &pv_num) == FAILURE) {
                   2779:                return;
                   2780:        }
                   2781:        
                   2782:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   2783:        
                   2784:        if (result->numcols == 0) {
                   2785:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   2786:                RETURN_FALSE;
                   2787:        }
                   2788:        
                   2789:        if (pv_num > result->numcols) {
                   2790:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index larger than number of fields");
                   2791:                RETURN_FALSE;
                   2792:        }
                   2793:        
                   2794:        if (pv_num < 1) {
                   2795:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field numbering starts at 1");
                   2796:                RETURN_FALSE;
                   2797:        }
                   2798:        
                   2799:        RETURN_STRING(result->values[pv_num - 1].name, 1);
                   2800: }
                   2801: /* }}} */
                   2802: 
                   2803: /* {{{ proto string odbc_field_type(resource result_id, int field_number)
                   2804:    Get the datatype of a column */
                   2805: PHP_FUNCTION(odbc_field_type)
                   2806: {
                   2807:        odbc_result     *result;
                   2808:        char            tmp[32];
                   2809:        SQLSMALLINT     tmplen;
                   2810:        zval            *pv_res;
                   2811:        long            pv_num;
                   2812: 
                   2813:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &pv_num) == FAILURE) {
                   2814:                return;
                   2815:        }
                   2816: 
                   2817:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   2818: 
                   2819:        if (result->numcols == 0) {
                   2820:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   2821:                RETURN_FALSE;
                   2822:        }
                   2823:        
                   2824:        if (pv_num > result->numcols) {
                   2825:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index larger than number of fields");
                   2826:                RETURN_FALSE;
                   2827:        }
                   2828: 
                   2829:        if (pv_num < 1) {
                   2830:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field numbering starts at 1");
                   2831:                RETURN_FALSE;
                   2832:        }
                   2833: 
                   2834:        SQLColAttributes(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL);
                   2835:        RETURN_STRING(tmp,1)
                   2836: }
                   2837: /* }}} */
                   2838: 
                   2839: /* {{{ proto int odbc_field_len(resource result_id, int field_number)
                   2840:    Get the length (precision) of a column */
                   2841: PHP_FUNCTION(odbc_field_len)
                   2842: {
                   2843:        odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                   2844: }
                   2845: /* }}} */
                   2846: 
                   2847: /* {{{ proto int odbc_field_scale(resource result_id, int field_number)
                   2848:    Get the scale of a column */
                   2849: PHP_FUNCTION(odbc_field_scale)
                   2850: {
                   2851:        odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);       
                   2852: }
                   2853: /* }}} */
                   2854: 
                   2855: /* {{{ proto int odbc_field_num(resource result_id, string field_name)
                   2856:    Return column number */
                   2857: PHP_FUNCTION(odbc_field_num)
                   2858: {
                   2859:        char *fname;
                   2860:        int i, field_ind, fname_len;
                   2861:        odbc_result *result;
                   2862:        zval *pv_res;
                   2863: 
                   2864:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pv_res, &fname, &fname_len) == FAILURE) {
                   2865:                return;
                   2866:        }
                   2867:        
                   2868:        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
                   2869:        
                   2870:        if (result->numcols == 0) {
                   2871:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
                   2872:                RETURN_FALSE;
                   2873:        }
                   2874: 
                   2875:        field_ind = -1;
                   2876:        for(i = 0; i < result->numcols; i++) {
                   2877:                if (strcasecmp(result->values[i].name, fname) == 0) {
                   2878:                        field_ind = i + 1;
                   2879:                }
                   2880:        }
                   2881: 
                   2882:        if (field_ind == -1) {
                   2883:                RETURN_FALSE;
                   2884:        }
                   2885:        RETURN_LONG(field_ind);
                   2886: }
                   2887: /* }}} */
                   2888: 
                   2889: /* {{{ proto mixed odbc_autocommit(resource connection_id [, int OnOff])
                   2890:    Toggle autocommit mode or get status */
                   2891: /* There can be problems with pconnections!*/
                   2892: PHP_FUNCTION(odbc_autocommit)
                   2893: {
                   2894:        odbc_connection *conn;
                   2895:        RETCODE rc;
                   2896:        zval *pv_conn;
                   2897:        long pv_onoff = 0;
                   2898: 
                   2899:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_conn, &pv_onoff) == FAILURE) {
                   2900:                return;
                   2901:        }
                   2902: 
                   2903:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   2904:        
                   2905:        if (ZEND_NUM_ARGS() > 1) {
                   2906:                rc = SQLSetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (pv_onoff) ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
                   2907:                if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   2908:                        odbc_sql_error(conn, SQL_NULL_HSTMT, "Set autocommit");
                   2909:                        RETURN_FALSE;
                   2910:                }
                   2911:                RETVAL_TRUE;
                   2912:        } else {
                   2913:                SQLINTEGER status;
                   2914: 
                   2915:                rc = SQLGetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (PTR)&status);
                   2916:                if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   2917:                        odbc_sql_error(conn, SQL_NULL_HSTMT, "Get commit status");
                   2918:                        RETURN_FALSE;
                   2919:                }
                   2920:                RETVAL_LONG((long)status);
                   2921:        }
                   2922: }
                   2923: /* }}} */
                   2924: 
                   2925: /* {{{ proto bool odbc_commit(resource connection_id)
                   2926:    Commit an ODBC transaction */
                   2927: PHP_FUNCTION(odbc_commit)
                   2928: {
                   2929:        odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                   2930: }
                   2931: /* }}} */
                   2932: 
                   2933: /* {{{ proto bool odbc_rollback(resource connection_id)
                   2934:    Rollback a transaction */
                   2935: PHP_FUNCTION(odbc_rollback)
                   2936: {
                   2937:        odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                   2938: }
                   2939: /* }}} */
                   2940: 
                   2941: /* {{{ php_odbc_lasterror */
                   2942: static void php_odbc_lasterror(INTERNAL_FUNCTION_PARAMETERS, int mode)
                   2943: {
                   2944:        odbc_connection *conn;
                   2945:        zval *pv_handle;
                   2946:        char *ptr;
                   2947:        int len;
                   2948: 
                   2949:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &pv_handle) == FAILURE) {
                   2950:                return;
                   2951:        }
                   2952: 
                   2953:        if (mode == 0) {  /* last state */
                   2954:                len = 6;
                   2955:        } else { /* last error message */
                   2956:                len = SQL_MAX_MESSAGE_LENGTH;
                   2957:        }
                   2958: 
                   2959:        if (ZEND_NUM_ARGS() == 1) {
                   2960:                ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_handle, -1, "ODBC-Link", le_conn, le_pconn);
                   2961:                ptr = ecalloc(len + 1, 1);
                   2962:                if (mode == 0) {
                   2963:                        strlcpy(ptr, conn->laststate, len+1);
                   2964:                } else {
                   2965:                        strlcpy(ptr, conn->lasterrormsg, len+1);
                   2966:                }
                   2967:        } else {
                   2968:                ptr = ecalloc(len + 1, 1);
                   2969:                if (mode == 0) {
                   2970:                        strlcpy(ptr, ODBCG(laststate), len+1);
                   2971:                } else {
                   2972:                        strlcpy(ptr, ODBCG(lasterrormsg), len+1);
                   2973:                }
                   2974:        }
                   2975:        RETVAL_STRING(ptr, 0);
                   2976: }
                   2977: /* }}} */
                   2978: 
                   2979: /* {{{ proto string odbc_error([resource connection_id])
                   2980:    Get the last error code */
                   2981: PHP_FUNCTION(odbc_error)
                   2982: {
                   2983:        php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                   2984: }
                   2985: /* }}} */
                   2986: 
                   2987: /* {{{ proto string odbc_errormsg([resource connection_id])
                   2988:    Get the last error message */
                   2989: PHP_FUNCTION(odbc_errormsg)
                   2990: {
                   2991:        php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                   2992: }
                   2993: /* }}} */
                   2994: 
                   2995: /* {{{ proto bool odbc_setoption(resource conn_id|result_id, int which, int option, int value)
                   2996:    Sets connection or statement options */
                   2997: /* This one has to be used carefully. We can't allow to set connection options for
                   2998:    persistent connections. I think that SetStmtOption is of little use, since most
                   2999:    of those can only be specified before preparing/executing statements.
                   3000:    On the other hand, they can be made connection wide default through SetConnectOption
                   3001:    - but will be overidden by calls to SetStmtOption() in odbc_prepare/odbc_do
                   3002: */
                   3003: PHP_FUNCTION(odbc_setoption)
                   3004: {
                   3005:        odbc_connection *conn;
                   3006:        odbc_result     *result;
                   3007:        RETCODE rc;
                   3008:        zval *pv_handle;
                   3009:        long pv_which, pv_opt, pv_val;
                   3010: 
                   3011:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlll", &pv_handle, &pv_which, &pv_opt, &pv_val) == FAILURE) {
                   3012:                return;
                   3013:        }
                   3014: 
                   3015:        switch (pv_which) {
                   3016:                case 1:         /* SQLSetConnectOption */
                   3017:                        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_handle, -1, "ODBC-Link", le_conn, le_pconn);
                   3018: 
                   3019:                        if (conn->persistent) {
                   3020:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set option for persistent connection");
                   3021:                                RETURN_FALSE;
                   3022:                        }
                   3023:                        rc = SQLSetConnectOption(conn->hdbc, (unsigned short) pv_opt, pv_val);
                   3024:                        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   3025:                                odbc_sql_error(conn, SQL_NULL_HSTMT, "SetConnectOption");
                   3026:                                RETURN_FALSE;
                   3027:                        }
                   3028:                        break;
                   3029:                case 2:         /* SQLSetStmtOption */
                   3030:                        ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_handle, -1, "ODBC result", le_result);
                   3031:                        
                   3032:                        rc = SQLSetStmtOption(result->stmt, (unsigned short) pv_opt, pv_val);
                   3033: 
                   3034:                        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
                   3035:                                odbc_sql_error(result->conn_ptr, result->stmt, "SetStmtOption");
                   3036:                                RETURN_FALSE;
                   3037:                        }
                   3038:                        break;
                   3039:                default:
                   3040:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option type");
                   3041:                        RETURN_FALSE;
                   3042:                        break;
                   3043:        }
                   3044: 
                   3045:        RETURN_TRUE;
                   3046: }
                   3047: /* }}} */
                   3048: 
                   3049: /*
                   3050:  * metadata functions
                   3051:  */
                   3052: 
                   3053: /* {{{ proto resource odbc_tables(resource connection_id [, string qualifier [, string owner [, string name [, string table_types]]]])
                   3054:    Call the SQLTables function */
                   3055: PHP_FUNCTION(odbc_tables)
                   3056: {
                   3057:        zval *pv_conn;
                   3058:        odbc_result   *result = NULL;
                   3059:        odbc_connection *conn;
                   3060:        char *cat = NULL, *schema = NULL, *table = NULL, *type = NULL;
                   3061:        int cat_len = 0, schema_len = 0, table_len = 0, type_len = 0;
                   3062:        RETCODE rc;
                   3063: 
                   3064:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len, 
                   3065:                &table, &table_len, &type, &type_len) == FAILURE) {
                   3066:                return;
                   3067:        }
                   3068: 
                   3069:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3070: 
                   3071:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3072:        
                   3073:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3074:        if (rc == SQL_INVALID_HANDLE) {
                   3075:                efree(result);
                   3076:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3077:                RETURN_FALSE;
                   3078:        }
                   3079: 
                   3080:        if (rc == SQL_ERROR) {
                   3081:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3082:                efree(result);
                   3083:                RETURN_FALSE;
                   3084:        }
                   3085: 
                   3086:        /* This hack is needed to access table information in Access databases (fmk) */
                   3087:        if (table && table_len && schema && schema_len == 0) {
                   3088:                schema = NULL;
                   3089:        }
                   3090: 
                   3091:        rc = SQLTables(result->stmt, 
                   3092:                        cat, SAFE_SQL_NTS(cat), 
                   3093:                        schema, SAFE_SQL_NTS(schema), 
                   3094:                        table, SAFE_SQL_NTS(table),
                   3095:                        type, SAFE_SQL_NTS(type));
                   3096: 
                   3097:        if (rc == SQL_ERROR) {
                   3098:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTables");
                   3099:                efree(result);
                   3100:                RETURN_FALSE;
                   3101:        }
                   3102: 
                   3103:        result->numparams = 0;
                   3104:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3105: 
                   3106:        if (result->numcols > 0) {
                   3107:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3108:                        efree(result);
                   3109:                        RETURN_FALSE;
                   3110:                }
                   3111:        } else {
                   3112:                result->values = NULL;
                   3113:        }
                   3114:        result->conn_ptr = conn;
                   3115:        result->fetched = 0;
                   3116:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3117: }
                   3118: /* }}} */
                   3119: 
                   3120: /* {{{ proto resource odbc_columns(resource connection_id [, string qualifier [, string owner [, string table_name [, string column_name]]]])
                   3121:    Returns a result identifier that can be used to fetch a list of column names in specified tables */
                   3122: PHP_FUNCTION(odbc_columns)
                   3123: {
                   3124:        zval *pv_conn;
                   3125:        odbc_result *result = NULL;
                   3126:        odbc_connection *conn;
                   3127:        char *cat = NULL, *schema = NULL, *table = NULL, *column = NULL;
                   3128:        int cat_len = 0, schema_len = 0, table_len = 0, column_len = 0;
                   3129:        RETCODE rc;
                   3130: 
                   3131:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
                   3132:                &table, &table_len, &column, &column_len) == FAILURE) {
                   3133:                return;
                   3134:        }
                   3135: 
                   3136:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3137: 
                   3138:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3139:        
                   3140:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3141:        if (rc == SQL_INVALID_HANDLE) {
                   3142:                efree(result);
                   3143:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3144:                RETURN_FALSE;
                   3145:        }
                   3146: 
                   3147:        if (rc == SQL_ERROR) {
                   3148:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3149:                efree(result);
                   3150:                RETURN_FALSE;
                   3151:        }
                   3152: 
                   3153:        /* 
                   3154:         * Needed to make MS Access happy
                   3155:         */
                   3156:        if (table && table_len && schema && schema_len == 0) {
                   3157:                schema = NULL;
                   3158:        }
                   3159: 
                   3160:        rc = SQLColumns(result->stmt, 
                   3161:                        cat, (SQLSMALLINT) cat_len,
                   3162:                        schema, (SQLSMALLINT) schema_len,
                   3163:                        table, (SQLSMALLINT) table_len,
                   3164:                        column, (SQLSMALLINT) column_len);
                   3165: 
                   3166:        if (rc == SQL_ERROR) {
                   3167:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLColumns");
                   3168:                efree(result);
                   3169:                RETURN_FALSE;
                   3170:        }
                   3171: 
                   3172:        result->numparams = 0;
                   3173:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3174: 
                   3175:        if (result->numcols > 0) {
                   3176:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3177:                        efree(result);
                   3178:                        RETURN_FALSE;
                   3179:                }
                   3180:        } else {
                   3181:                result->values = NULL;
                   3182:        }
                   3183:        result->conn_ptr = conn;
                   3184:        result->fetched = 0;
                   3185:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3186: }
                   3187: /* }}} */
                   3188: 
                   3189: #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP)
                   3190: /* {{{ proto resource odbc_columnprivileges(resource connection_id, string catalog, string schema, string table, string column)
                   3191:    Returns a result identifier that can be used to fetch a list of columns and associated privileges for the specified table */
                   3192: PHP_FUNCTION(odbc_columnprivileges)
                   3193: {
                   3194:        zval *pv_conn;
                   3195:        odbc_result *result = NULL;
                   3196:        odbc_connection *conn;
                   3197:        char *cat = NULL, *schema, *table, *column;
                   3198:        int cat_len = 0, schema_len, table_len, column_len;
                   3199:        RETCODE rc;
                   3200:        
                   3201:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
                   3202:                &table, &table_len, &column, &column_len) == FAILURE) {
                   3203:                return;
                   3204:        }
                   3205: 
                   3206:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3207: 
                   3208:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3209:        
                   3210:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3211:        if (rc == SQL_INVALID_HANDLE) {
                   3212:                efree(result);
                   3213:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3214:                RETURN_FALSE;
                   3215:        }
                   3216: 
                   3217:        if (rc == SQL_ERROR) {
                   3218:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3219:                efree(result);
                   3220:                RETURN_FALSE;
                   3221:        }
                   3222: 
                   3223:        rc = SQLColumnPrivileges(result->stmt, 
                   3224:                        cat, SAFE_SQL_NTS(cat),
                   3225:                        schema, SAFE_SQL_NTS(schema),
                   3226:                        table, SAFE_SQL_NTS(table),
                   3227:                        column, SAFE_SQL_NTS(column));
                   3228: 
                   3229:        if (rc == SQL_ERROR) {
                   3230:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLColumnPrivileges");
                   3231:                efree(result);
                   3232:                RETURN_FALSE;
                   3233:        }
                   3234: 
                   3235:        result->numparams = 0;
                   3236:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3237: 
                   3238:        if (result->numcols > 0) {
                   3239:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3240:                        efree(result);
                   3241:                        RETURN_FALSE;
                   3242:                }
                   3243:        } else {
                   3244:                result->values = NULL;
                   3245:        }
                   3246:        result->conn_ptr = conn;
                   3247:        result->fetched = 0;
                   3248:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3249: }
                   3250: /* }}} */
                   3251: #endif /* HAVE_DBMAKER || HAVE_SOLID*/
                   3252: 
                   3253: #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
                   3254: /* {{{ proto resource odbc_foreignkeys(resource connection_id, string pk_qualifier, string pk_owner, string pk_table, string fk_qualifier, string fk_owner, string fk_table)
                   3255:    Returns a result identifier to either a list of foreign keys in the specified table or a list of foreign keys in other tables that refer to the primary key in the specified table */
                   3256: PHP_FUNCTION(odbc_foreignkeys)
                   3257: {
                   3258:        zval *pv_conn;
                   3259:        odbc_result *result = NULL;
                   3260:        odbc_connection *conn;
                   3261:        char *pcat = NULL, *pschema, *ptable, *fcat, *fschema, *ftable;
                   3262:        int pcat_len = 0, pschema_len, ptable_len, fcat_len, fschema_len, ftable_len;
                   3263:        RETCODE rc;
                   3264: 
                   3265:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!sssss", &pv_conn, &pcat, &pcat_len, &pschema, &pschema_len, 
                   3266:                &ptable, &ptable_len, &fcat, &fcat_len, &fschema, &fschema_len, &ftable, &ftable_len) == FAILURE) {
                   3267:                return;
                   3268:        }
                   3269: 
                   3270: #if defined(HAVE_DBMAKER) || defined(HAVE_IBMDB2)
                   3271: #define EMPTY_TO_NULL(xstr) \
                   3272:        if ((int)strlen((xstr)) == 0) (xstr) = NULL
                   3273: 
                   3274:                EMPTY_TO_NULL(pcat);
                   3275:                EMPTY_TO_NULL(pschema);
                   3276:                EMPTY_TO_NULL(ptable);
                   3277:                EMPTY_TO_NULL(fcat);
                   3278:                EMPTY_TO_NULL(fschema);
                   3279:                EMPTY_TO_NULL(ftable);
                   3280: #endif
                   3281: 
                   3282:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3283: 
                   3284:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3285:        
                   3286:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3287:        if (rc == SQL_INVALID_HANDLE) {
                   3288:                efree(result);
                   3289:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3290:                RETURN_FALSE;
                   3291:        }
                   3292: 
                   3293:        if (rc == SQL_ERROR) {
                   3294:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3295:                efree(result);
                   3296:                RETURN_FALSE;
                   3297:        }
                   3298: 
                   3299:        rc = SQLForeignKeys(result->stmt, 
                   3300:                        pcat, SAFE_SQL_NTS(pcat), 
                   3301:                        pschema, SAFE_SQL_NTS(pschema), 
                   3302:                        ptable, SAFE_SQL_NTS(ptable), 
                   3303:                        fcat, SAFE_SQL_NTS(fcat), 
                   3304:                        fschema, SAFE_SQL_NTS(fschema), 
                   3305:                        ftable, SAFE_SQL_NTS(ftable) );
                   3306: 
                   3307:        if (rc == SQL_ERROR) {
                   3308:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLForeignKeys");
                   3309:                efree(result);
                   3310:                RETURN_FALSE;
                   3311:        }
                   3312: 
                   3313:        result->numparams = 0;
                   3314:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3315: 
                   3316:        if (result->numcols > 0) {
                   3317:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3318:                        efree(result);
                   3319:                        RETURN_FALSE;
                   3320:                }
                   3321:        } else {
                   3322:                result->values = NULL;
                   3323:        }
                   3324:        result->conn_ptr = conn;
                   3325:        result->fetched = 0;
                   3326:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3327: }
                   3328: /* }}} */
                   3329: #endif /* HAVE_SOLID */
                   3330: 
                   3331: /* {{{ proto resource odbc_gettypeinfo(resource connection_id [, int data_type])
                   3332:    Returns a result identifier containing information about data types supported by the data source */
                   3333: PHP_FUNCTION(odbc_gettypeinfo)
                   3334: {
                   3335:        zval *pv_conn;
                   3336:        long pv_data_type = SQL_ALL_TYPES;
                   3337:        odbc_result *result = NULL;
                   3338:        odbc_connection *conn;
                   3339:        RETCODE rc;
                   3340:        SQLSMALLINT data_type;
                   3341: 
                   3342:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_conn, &pv_data_type) == FAILURE) {
                   3343:                return;
                   3344:        }
                   3345:        
                   3346:        data_type = (SQLSMALLINT) pv_data_type;
                   3347: 
                   3348:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3349: 
                   3350:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3351:        
                   3352:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3353:        if (rc == SQL_INVALID_HANDLE) {
                   3354:                efree(result);
                   3355:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3356:                RETURN_FALSE;
                   3357:        }
                   3358: 
                   3359:        if (rc == SQL_ERROR) {
                   3360:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3361:                efree(result);
                   3362:                RETURN_FALSE;
                   3363:        }
                   3364: 
                   3365:        rc = SQLGetTypeInfo(result->stmt, data_type );
                   3366: 
                   3367:        if (rc == SQL_ERROR) {
                   3368:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLGetTypeInfo");
                   3369:                efree(result);
                   3370:                RETURN_FALSE;
                   3371:        }
                   3372: 
                   3373:        result->numparams = 0;
                   3374:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3375: 
                   3376:        if (result->numcols > 0) {
                   3377:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3378:                        efree(result);
                   3379:                        RETURN_FALSE;
                   3380:                }
                   3381:        } else {
                   3382:                result->values = NULL;
                   3383:        }
                   3384:        result->conn_ptr = conn;
                   3385:        result->fetched = 0;
                   3386:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3387: }
                   3388: /* }}} */
                   3389: 
                   3390: /* {{{ proto resource odbc_primarykeys(resource connection_id, string qualifier, string owner, string table)
                   3391:    Returns a result identifier listing the column names that comprise the primary key for a table */
                   3392: PHP_FUNCTION(odbc_primarykeys)
                   3393: {
                   3394:        zval *pv_conn;
                   3395:        odbc_result   *result = NULL;
                   3396:        odbc_connection *conn;
                   3397:        char *cat = NULL, *schema = NULL, *table = NULL;
                   3398:        int cat_len = 0, schema_len, table_len;
                   3399:        RETCODE rc;
                   3400: 
                   3401:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
                   3402:                return;
                   3403:        }
                   3404: 
                   3405:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3406: 
                   3407:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3408:        
                   3409:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3410:        if (rc == SQL_INVALID_HANDLE) {
                   3411:                efree(result);
                   3412:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3413:                RETURN_FALSE;
                   3414:        }
                   3415: 
                   3416:        if (rc == SQL_ERROR) {
                   3417:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3418:                efree(result);
                   3419:                RETURN_FALSE;
                   3420:        }
                   3421: 
                   3422:        rc = SQLPrimaryKeys(result->stmt, 
                   3423:                        cat, SAFE_SQL_NTS(cat), 
                   3424:                        schema, SAFE_SQL_NTS(schema), 
                   3425:                        table, SAFE_SQL_NTS(table) );
                   3426: 
                   3427:        if (rc == SQL_ERROR) {
                   3428:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLPrimaryKeys");
                   3429:                efree(result);
                   3430:                RETURN_FALSE;
                   3431:        }
                   3432: 
                   3433:        result->numparams = 0;
                   3434:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3435: 
                   3436:        if (result->numcols > 0) {
                   3437:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3438:                        efree(result);
                   3439:                        RETURN_FALSE;
                   3440:                }
                   3441:        } else {
                   3442:                result->values = NULL;
                   3443:        }
                   3444:        result->conn_ptr = conn;
                   3445:        result->fetched = 0;
                   3446:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3447: }
                   3448: /* }}} */
                   3449: 
                   3450: #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP)
                   3451: /* {{{ proto resource odbc_procedurecolumns(resource connection_id [, string qualifier, string owner, string proc, string column])
                   3452:    Returns a result identifier containing the list of input and output parameters, as well as the columns that make up the result set for the specified procedures */
                   3453: PHP_FUNCTION(odbc_procedurecolumns)
                   3454: {
                   3455:        zval *pv_conn;
                   3456:        odbc_result *result = NULL;
                   3457:        odbc_connection *conn;
                   3458:        char *cat = NULL, *schema = NULL, *proc = NULL, *col = NULL;
                   3459:        int cat_len = 0, schema_len = 0, proc_len = 0, col_len = 0;
                   3460:        RETCODE rc;
                   3461:        
                   3462:        if (ZEND_NUM_ARGS() != 1 && ZEND_NUM_ARGS() != 5) {
                   3463:                WRONG_PARAM_COUNT;
                   3464:        }
                   3465: 
                   3466:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len, 
                   3467:                &proc, &proc_len, &col, &col_len) == FAILURE) {
                   3468:                return;
                   3469:        }
                   3470: 
                   3471:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3472: 
                   3473:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3474:        
                   3475:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3476:        if (rc == SQL_INVALID_HANDLE) {
                   3477:                efree(result);
                   3478:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3479:                RETURN_FALSE;
                   3480:        }
                   3481: 
                   3482:        if (rc == SQL_ERROR) {
                   3483:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3484:                efree(result);
                   3485:                RETURN_FALSE;
                   3486:        }
                   3487: 
                   3488:        rc = SQLProcedureColumns(result->stmt, 
                   3489:                        cat, SAFE_SQL_NTS(cat), 
                   3490:                        schema, SAFE_SQL_NTS(schema), 
                   3491:                        proc, SAFE_SQL_NTS(proc), 
                   3492:                        col, SAFE_SQL_NTS(col) );
                   3493: 
                   3494:        if (rc == SQL_ERROR) {
                   3495:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLProcedureColumns");
                   3496:                efree(result);
                   3497:                RETURN_FALSE;
                   3498:        }
                   3499: 
                   3500:        result->numparams = 0;
                   3501:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3502: 
                   3503:        if (result->numcols > 0) {
                   3504:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3505:                        efree(result);
                   3506:                        RETURN_FALSE;
                   3507:                }
                   3508:        } else {
                   3509:                result->values = NULL;
                   3510:        }
                   3511:        result->conn_ptr = conn;
                   3512:        result->fetched = 0;
                   3513:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3514: }
                   3515: /* }}} */
                   3516: #endif /* HAVE_SOLID */
                   3517: 
                   3518: #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
                   3519: /* {{{ proto resource odbc_procedures(resource connection_id [, string qualifier, string owner, string name])
                   3520:    Returns a result identifier containg the list of procedure names in a datasource */
                   3521: PHP_FUNCTION(odbc_procedures)
                   3522: {
                   3523:        zval *pv_conn;
                   3524:        odbc_result   *result = NULL;
                   3525:        odbc_connection *conn;
                   3526:        char *cat = NULL, *schema = NULL, *proc = NULL;
                   3527:        int cat_len = 0, schema_len = 0, proc_len = 0;
                   3528:        RETCODE rc;
                   3529: 
                   3530:        if (ZEND_NUM_ARGS() != 1 && ZEND_NUM_ARGS() != 4) {
                   3531:                WRONG_PARAM_COUNT;
                   3532:        }
                   3533:        
                   3534:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &proc, &proc_len) == FAILURE) {
                   3535:                return;
                   3536:        }
                   3537: 
                   3538:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3539: 
                   3540:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3541:        
                   3542:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3543:        if (rc == SQL_INVALID_HANDLE) {
                   3544:                efree(result);
                   3545:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3546:                RETURN_FALSE;
                   3547:        }
                   3548: 
                   3549:        if (rc == SQL_ERROR) {
                   3550:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3551:                efree(result);
                   3552:                RETURN_FALSE;
                   3553:        }
                   3554: 
                   3555:        rc = SQLProcedures(result->stmt, 
                   3556:                        cat, SAFE_SQL_NTS(cat), 
                   3557:                        schema, SAFE_SQL_NTS(schema), 
                   3558:                        proc, SAFE_SQL_NTS(proc) );
                   3559: 
                   3560:        if (rc == SQL_ERROR) {
                   3561:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLProcedures");
                   3562:                efree(result);
                   3563:                RETURN_FALSE;
                   3564:        }
                   3565: 
                   3566:        result->numparams = 0;
                   3567:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3568: 
                   3569:        if (result->numcols > 0) {
                   3570:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3571:                        efree(result);
                   3572:                        RETURN_FALSE;
                   3573:                }
                   3574:        } else {
                   3575:                result->values = NULL;
                   3576:        }
                   3577:        result->conn_ptr = conn;
                   3578:        result->fetched = 0;
                   3579:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3580: }
                   3581: /* }}} */
                   3582: #endif /* HAVE_SOLID */
                   3583: 
                   3584: /* {{{ proto resource odbc_specialcolumns(resource connection_id, int type, string qualifier, string owner, string table, int scope, int nullable)
                   3585:    Returns a result identifier containing either the optimal set of columns that uniquely identifies a row in the table or columns that are automatically updated when any value in the row is updated by a transaction */
                   3586: PHP_FUNCTION(odbc_specialcolumns)
                   3587: {
                   3588:        zval *pv_conn;
                   3589:        long vtype, vscope, vnullable;
                   3590:        odbc_result *result = NULL;
                   3591:        odbc_connection *conn;
                   3592:        char *cat = NULL, *schema = NULL, *name = NULL;
                   3593:        int cat_len = 0, schema_len, name_len;
                   3594:        SQLUSMALLINT type, scope, nullable;
                   3595:        RETCODE rc;
                   3596: 
                   3597:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls!ssll", &pv_conn, &vtype, &cat, &cat_len, &schema, &schema_len,
                   3598:                &name, &name_len, &vscope, &vnullable) == FAILURE) {
                   3599:                return;
                   3600:        }
                   3601:        
                   3602:        type = (SQLUSMALLINT) vtype;
                   3603:        scope = (SQLUSMALLINT) vscope;
                   3604:        nullable = (SQLUSMALLINT) vnullable;
                   3605: 
                   3606:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3607: 
                   3608:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3609:        
                   3610:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3611:        if (rc == SQL_INVALID_HANDLE) {
                   3612:                efree(result);
                   3613:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3614:                RETURN_FALSE;
                   3615:        }
                   3616: 
                   3617:        if (rc == SQL_ERROR) {
                   3618:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3619:                efree(result);
                   3620:                RETURN_FALSE;
                   3621:        }
                   3622: 
                   3623:        rc = SQLSpecialColumns(result->stmt, 
                   3624:                        type,
                   3625:                        cat, SAFE_SQL_NTS(cat), 
                   3626:                        schema, SAFE_SQL_NTS(schema), 
                   3627:                        name, SAFE_SQL_NTS(name),
                   3628:                        scope,
                   3629:                        nullable);
                   3630: 
                   3631:        if (rc == SQL_ERROR) {
                   3632:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLSpecialColumns");
                   3633:                efree(result);
                   3634:                RETURN_FALSE;
                   3635:        }
                   3636: 
                   3637:        result->numparams = 0;
                   3638:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3639: 
                   3640:        if (result->numcols > 0) {
                   3641:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3642:                        efree(result);
                   3643:                        RETURN_FALSE;
                   3644:                }
                   3645:        } else {
                   3646:                result->values = NULL;
                   3647:        }
                   3648:        result->conn_ptr = conn;
                   3649:        result->fetched = 0;
                   3650:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3651: }
                   3652: /* }}} */
                   3653: 
                   3654: /* {{{ proto resource odbc_statistics(resource connection_id, string qualifier, string owner, string name, int unique, int accuracy)
                   3655:    Returns a result identifier that contains statistics about a single table and the indexes associated with the table */
                   3656: PHP_FUNCTION(odbc_statistics)
                   3657: {
                   3658:        zval *pv_conn;
                   3659:        long vunique, vreserved;
                   3660:        odbc_result *result = NULL;
                   3661:        odbc_connection *conn;
                   3662:        char *cat = NULL, *schema, *name;
                   3663:        int cat_len = 0, schema_len, name_len;
                   3664:        SQLUSMALLINT unique, reserved;
                   3665:        RETCODE rc;
                   3666: 
                   3667:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!ssll", &pv_conn, &cat, &cat_len, &schema, &schema_len,
                   3668:                &name, &name_len, &vunique, &vreserved) == FAILURE) {
                   3669:                return;
                   3670:        }
                   3671:        
                   3672:        unique = (SQLUSMALLINT) vunique;
                   3673:        reserved = (SQLUSMALLINT) vreserved;
                   3674: 
                   3675:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3676: 
                   3677:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3678:        
                   3679:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3680:        if (rc == SQL_INVALID_HANDLE) {
                   3681:                efree(result);
                   3682:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3683:                RETURN_FALSE;
                   3684:        }
                   3685: 
                   3686:        if (rc == SQL_ERROR) {
                   3687:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3688:                efree(result);
                   3689:                RETURN_FALSE;
                   3690:        }
                   3691: 
                   3692:        rc = SQLStatistics(result->stmt, 
                   3693:                        cat, SAFE_SQL_NTS(cat),
                   3694:                        schema, SAFE_SQL_NTS(schema), 
                   3695:                        name, SAFE_SQL_NTS(name),
                   3696:                        unique,
                   3697:                        reserved);
                   3698: 
                   3699:        if (rc == SQL_ERROR) {
                   3700:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLStatistics");
                   3701:                efree(result);
                   3702:                RETURN_FALSE;
                   3703:        }
                   3704: 
                   3705:        result->numparams = 0;
                   3706:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3707: 
                   3708:        if (result->numcols > 0) {
                   3709:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3710:                        efree(result);
                   3711:                        RETURN_FALSE;
                   3712:                }
                   3713:        } else {
                   3714:                result->values = NULL;
                   3715:        }
                   3716:        result->conn_ptr = conn;
                   3717:        result->fetched = 0;
                   3718:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3719: }
                   3720: /* }}} */
                   3721: 
                   3722: #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP)
                   3723: /* {{{ proto resource odbc_tableprivileges(resource connection_id, string qualifier, string owner, string name)
                   3724:    Returns a result identifier containing a list of tables and the privileges associated with each table */
                   3725: PHP_FUNCTION(odbc_tableprivileges)
                   3726: {
                   3727:        zval *pv_conn;
                   3728:        odbc_result   *result = NULL;
                   3729:        odbc_connection *conn;
                   3730:        char *cat = NULL, *schema = NULL, *table = NULL;
                   3731:        int cat_len = 0, schema_len, table_len;
                   3732:        RETCODE rc;
                   3733: 
                   3734:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
                   3735:                return;
                   3736:        }
                   3737: 
                   3738:        ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
                   3739: 
                   3740:        result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
                   3741:        
                   3742:        rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
                   3743:        if (rc == SQL_INVALID_HANDLE) {
                   3744:                efree(result);
                   3745:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
                   3746:                RETURN_FALSE;
                   3747:        }
                   3748: 
                   3749:        if (rc == SQL_ERROR) {
                   3750:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
                   3751:                efree(result);
                   3752:                RETURN_FALSE;
                   3753:        }
                   3754: 
                   3755:        rc = SQLTablePrivileges(result->stmt, 
                   3756:                        cat, SAFE_SQL_NTS(cat), 
                   3757:                        schema, SAFE_SQL_NTS(schema), 
                   3758:                        table, SAFE_SQL_NTS(table));
                   3759: 
                   3760:        if (rc == SQL_ERROR) {
                   3761:                odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTablePrivileges");
                   3762:                efree(result);
                   3763:                RETURN_FALSE;
                   3764:        }
                   3765: 
                   3766:        result->numparams = 0;
                   3767:        SQLNumResultCols(result->stmt, &(result->numcols));
                   3768: 
                   3769:        if (result->numcols > 0) {
                   3770:                if (!odbc_bindcols(result TSRMLS_CC)) {
                   3771:                        efree(result);
                   3772:                        RETURN_FALSE;
                   3773:                }
                   3774:        } else {
                   3775:                result->values = NULL;
                   3776:        }
                   3777:        result->conn_ptr = conn;
                   3778:        result->fetched = 0;
                   3779:        ZEND_REGISTER_RESOURCE(return_value, result, le_result);
                   3780: }
                   3781: /* }}} */
                   3782: #endif /* HAVE_DBMAKER */
                   3783: 
                   3784: #endif /* HAVE_UODBC */
                   3785: 
                   3786: /*
                   3787:  * Local variables:
                   3788:  * tab-width: 4
                   3789:  * c-basic-offset: 4
                   3790:  * End:
                   3791:  * vim600: sw=4 ts=4 fdm=marker
                   3792:  * vim<600: sw=4 ts=4
                   3793:  */

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