1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 The PHP Group | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 3.01 of the PHP license, | 8 | that is bundled with this package in the file LICENSE, and is | 9 | available through the world-wide-web at the following url: | 10 | http://www.php.net/license/3_01.txt | 11 | If you did not receive a copy of the PHP license and are unable to | 12 | obtain it through the world-wide-web, please send a note to | 13 | license@php.net so we can mail you a copy immediately. | 14 +----------------------------------------------------------------------+ 15 | 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 23/* $Id$ */ 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 63void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent); 64 65static int le_result, le_conn, le_pconn; 66 67#define SAFE_SQL_NTS(n) ((SQLSMALLINT) ((n)?(SQL_NTS):0)) 68 69/* {{{ arginfo */ 70ZEND_BEGIN_ARG_INFO(arginfo_odbc_close_all, 0) 71ZEND_END_ARG_INFO() 72 73ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_binmode, 0, 0, 2) 74 ZEND_ARG_INFO(0, result_id) 75 ZEND_ARG_INFO(0, mode) 76ZEND_END_ARG_INFO() 77 78ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_longreadlen, 0, 0, 2) 79 ZEND_ARG_INFO(0, result_id) 80 ZEND_ARG_INFO(0, length) 81ZEND_END_ARG_INFO() 82 83ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_prepare, 0, 0, 2) 84 ZEND_ARG_INFO(0, connection_id) 85 ZEND_ARG_INFO(0, query) 86ZEND_END_ARG_INFO() 87 88ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_execute, 0, 0, 1) 89 ZEND_ARG_INFO(0, result_id) 90 ZEND_ARG_INFO(0, parameters_array) 91ZEND_END_ARG_INFO() 92 93ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_cursor, 0, 0, 1) 94 ZEND_ARG_INFO(0, result_id) 95ZEND_END_ARG_INFO() 96 97#ifdef HAVE_SQLDATASOURCES 98ZEND_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) 101ZEND_END_ARG_INFO() 102#endif 103 104ZEND_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) 108ZEND_END_ARG_INFO() 109 110#ifdef PHP_ODBC_HAVE_FETCH_HASH 111ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_object, 0, 0, 1) 112 ZEND_ARG_INFO(0, result) 113 ZEND_ARG_INFO(0, rownumber) 114ZEND_END_ARG_INFO() 115 116ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_array, 0, 0, 1) 117 ZEND_ARG_INFO(0, result) 118 ZEND_ARG_INFO(0, rownumber) 119ZEND_END_ARG_INFO() 120#endif 121 122ZEND_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) 126ZEND_END_ARG_INFO() 127 128ZEND_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) 131ZEND_END_ARG_INFO() 132 133ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_result, 0, 0, 2) 134 ZEND_ARG_INFO(0, result_id) 135 ZEND_ARG_INFO(0, field) 136ZEND_END_ARG_INFO() 137 138ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_result_all, 0, 0, 1) 139 ZEND_ARG_INFO(0, result_id) 140 ZEND_ARG_INFO(0, format) 141ZEND_END_ARG_INFO() 142 143ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_free_result, 0, 0, 1) 144 ZEND_ARG_INFO(0, result_id) 145ZEND_END_ARG_INFO() 146 147ZEND_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) 152ZEND_END_ARG_INFO() 153 154ZEND_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) 159ZEND_END_ARG_INFO() 160 161ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_close, 0, 0, 1) 162 ZEND_ARG_INFO(0, connection_id) 163ZEND_END_ARG_INFO() 164 165ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_num_rows, 0, 0, 1) 166 ZEND_ARG_INFO(0, result_id) 167ZEND_END_ARG_INFO() 168 169#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) 170ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_next_result, 0, 0, 1) 171 ZEND_ARG_INFO(0, result_id) 172ZEND_END_ARG_INFO() 173#endif 174 175ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_num_fields, 0, 0, 1) 176 ZEND_ARG_INFO(0, result_id) 177ZEND_END_ARG_INFO() 178 179ZEND_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) 182ZEND_END_ARG_INFO() 183 184ZEND_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) 187ZEND_END_ARG_INFO() 188 189ZEND_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) 192ZEND_END_ARG_INFO() 193 194ZEND_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) 197ZEND_END_ARG_INFO() 198 199ZEND_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) 202ZEND_END_ARG_INFO() 203 204ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_autocommit, 0, 0, 1) 205 ZEND_ARG_INFO(0, connection_id) 206 ZEND_ARG_INFO(0, onoff) 207ZEND_END_ARG_INFO() 208 209ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_commit, 0, 0, 1) 210 ZEND_ARG_INFO(0, connection_id) 211ZEND_END_ARG_INFO() 212 213ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_rollback, 0, 0, 1) 214 ZEND_ARG_INFO(0, connection_id) 215ZEND_END_ARG_INFO() 216 217ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_error, 0, 0, 0) 218 ZEND_ARG_INFO(0, connection_id) 219ZEND_END_ARG_INFO() 220 221ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_errormsg, 0, 0, 0) 222 ZEND_ARG_INFO(0, connection_id) 223ZEND_END_ARG_INFO() 224 225ZEND_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) 230ZEND_END_ARG_INFO() 231 232ZEND_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) 238ZEND_END_ARG_INFO() 239 240ZEND_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) 246ZEND_END_ARG_INFO() 247 248ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_gettypeinfo, 0, 0, 1) 249 ZEND_ARG_INFO(0, connection_id) 250 ZEND_ARG_INFO(0, data_type) 251ZEND_END_ARG_INFO() 252 253ZEND_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) 258ZEND_END_ARG_INFO() 259 260#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) 261#if !defined(HAVE_BIRDSTEP) 262ZEND_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) 268ZEND_END_ARG_INFO() 269#endif 270 271ZEND_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) 276ZEND_END_ARG_INFO() 277 278ZEND_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) 286ZEND_END_ARG_INFO() 287#endif 288 289ZEND_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) 297ZEND_END_ARG_INFO() 298 299ZEND_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) 306ZEND_END_ARG_INFO() 307 308#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP) 309ZEND_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) 314ZEND_END_ARG_INFO() 315 316ZEND_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) 322ZEND_END_ARG_INFO() 323#endif 324/* }}} */ 325 326/* {{{ odbc_functions[] 327 */ 328const 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 390ZEND_DECLARE_MODULE_GLOBALS(odbc) 391static PHP_GINIT_FUNCTION(odbc); 392 393/* {{{ odbc_module_entry 394 */ 395zend_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 414ZEND_GET_MODULE(odbc) 415#endif 416 417/* {{{ _free_odbc_result 418 */ 419static 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 */ 453static 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 */ 468static 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 */ 497static 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 */ 527static 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 */ 552static 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 */ 583static 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 */ 614static 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 */ 640static 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 */ 683PHP_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) 704PHP_INI_END() 705/* }}} */ 706 707static PHP_GINIT_FUNCTION(odbc) 708{ 709 odbc_globals->num_persistent = 0; 710} 711 712/* {{{ PHP_MINIT_FUNCTION */ 713PHP_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 */ 815PHP_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 */ 826PHP_RSHUTDOWN_FUNCTION(odbc) 827{ 828 return SUCCESS; 829} 830/* }}} */ 831 832/* {{{ PHP_MSHUTDOWN_FUNCTION */ 833PHP_MSHUTDOWN_FUNCTION(odbc) 834{ 835 UNREGISTER_INI_ENTRIES(); 836 return SUCCESS; 837} 838/* }}} */ 839 840/* {{{ PHP_MINFO_FUNCTION */ 841PHP_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 */ 865void 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 */ 913void 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 */ 942int 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 */ 999void 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 */ 1022static 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 */ 1033void 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 */ 1081PHP_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 */ 1123PHP_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 */ 1131PHP_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 */ 1139PHP_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 */ 1226PHP_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] == '\'') { 1320 if (strlen(tmp) != Z_STRLEN_PP(tmp)) { 1321 RETURN_FALSE; 1322 } 1323 1324 filename = estrndup(&Z_STRVAL_PP(tmp)[1], Z_STRLEN_PP(tmp) - 2); 1325 1326 /* Check for safe mode. */ 1327 if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { 1328 efree(filename); 1329 efree(params); 1330 RETURN_FALSE; 1331 } 1332 1333 /* Check the basedir */ 1334 if (php_check_open_basedir(filename TSRMLS_CC)) { 1335 efree(filename); 1336 SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); 1337 for (i = 0; i < result->numparams; i++) { 1338 if (params[i].fp != -1) { 1339 close(params[i].fp); 1340 } 1341 } 1342 efree(params); 1343 RETURN_FALSE; 1344 } 1345 1346 if ((params[i-1].fp = open(filename,O_RDONLY)) == -1) { 1347 php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't open file %s", filename); 1348 SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); 1349 for (i = 0; i < result->numparams; i++) { 1350 if (params[i].fp != -1) { 1351 close(params[i].fp); 1352 } 1353 } 1354 efree(params); 1355 efree(filename); 1356 RETURN_FALSE; 1357 } 1358 1359 efree(filename); 1360 1361 params[i-1].vallen = SQL_LEN_DATA_AT_EXEC(0); 1362 1363 rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT, 1364 ctype, sqltype, precision, scale, 1365 (void *)params[i-1].fp, 0, 1366 ¶ms[i-1].vallen); 1367 } else { 1368#ifdef HAVE_DBMAKER 1369 precision = params[i-1].vallen; 1370#endif 1371 if (otype == IS_NULL) { 1372 params[i-1].vallen = SQL_NULL_DATA; 1373 } 1374 1375 rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT, 1376 ctype, sqltype, precision, scale, 1377 Z_STRVAL_PP(tmp), 0, 1378 ¶ms[i-1].vallen); 1379 } 1380 if (rc == SQL_ERROR) { 1381 odbc_sql_error(result->conn_ptr, result->stmt, "SQLBindParameter"); 1382 SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); 1383 for (i = 0; i < result->numparams; i++) { 1384 if (params[i].fp != -1) { 1385 close(params[i].fp); 1386 } 1387 } 1388 efree(params); 1389 RETURN_FALSE; 1390 } 1391 zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr)); 1392 } 1393 } 1394 /* Close cursor, needed for doing multiple selects */ 1395 rc = SQLFreeStmt(result->stmt, SQL_CLOSE); 1396 1397 if (rc == SQL_ERROR) { 1398 odbc_sql_error(result->conn_ptr, result->stmt, "SQLFreeStmt"); 1399 } 1400 1401 rc = SQLExecute(result->stmt); 1402 1403 result->fetched = 0; 1404 if (rc == SQL_NEED_DATA) { 1405 char buf[4096]; 1406 int fp, nbytes; 1407 while (rc == SQL_NEED_DATA) { 1408 rc = SQLParamData(result->stmt, (void*)&fp); 1409 if (rc == SQL_NEED_DATA) { 1410 while ((nbytes = read(fp, &buf, 4096)) > 0) { 1411 SQLPutData(result->stmt, (void*)&buf, nbytes); 1412 } 1413 } 1414 } 1415 } else { 1416 switch (rc) { 1417 case SQL_SUCCESS: 1418 break; 1419 case SQL_NO_DATA_FOUND: 1420 case SQL_SUCCESS_WITH_INFO: 1421 odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute"); 1422 break; 1423 default: 1424 odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute"); 1425 RETVAL_FALSE; 1426 } 1427 } 1428 1429 if (result->numparams > 0) { 1430 SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); 1431 for(i = 0; i < result->numparams; i++) { 1432 if (params[i].fp != -1) { 1433 close(params[i].fp); 1434 } 1435 } 1436 efree(params); 1437 } 1438 1439 if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO || rc == SQL_NO_DATA_FOUND) { 1440 RETVAL_TRUE; 1441 } 1442 1443 if (result->numcols == 0) { 1444 SQLNumResultCols(result->stmt, &(result->numcols)); 1445 1446 if (result->numcols > 0) { 1447 if (!odbc_bindcols(result TSRMLS_CC)) { 1448 efree(result); 1449 RETVAL_FALSE; 1450 } 1451 } else { 1452 result->values = NULL; 1453 } 1454 } 1455} 1456/* }}} */ 1457 1458/* {{{ proto string odbc_cursor(resource result_id) 1459 Get cursor name */ 1460PHP_FUNCTION(odbc_cursor) 1461{ 1462 zval *pv_res; 1463 SQLUSMALLINT max_len; 1464 SQLSMALLINT len; 1465 char *cursorname; 1466 odbc_result *result; 1467 RETCODE rc; 1468 1469 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) { 1470 return; 1471 } 1472 1473 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 1474 1475 rc = SQLGetInfo(result->conn_ptr->hdbc,SQL_MAX_CURSOR_NAME_LEN, (void *)&max_len,sizeof(max_len),&len); 1476 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 1477 RETURN_FALSE; 1478 } 1479 1480 if (max_len > 0) { 1481 cursorname = emalloc(max_len + 1); 1482 rc = SQLGetCursorName(result->stmt,cursorname,(SQLSMALLINT)max_len,&len); 1483 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 1484 char state[6]; /* Not used */ 1485 SQLINTEGER error; /* Not used */ 1486 char errormsg[SQL_MAX_MESSAGE_LENGTH]; 1487 SQLSMALLINT errormsgsize; /* Not used */ 1488 1489 SQLError( result->conn_ptr->henv, result->conn_ptr->hdbc, 1490 result->stmt, state, &error, errormsg, 1491 sizeof(errormsg)-1, &errormsgsize); 1492 if (!strncmp(state,"S1015",5)) { 1493 snprintf(cursorname, max_len+1, "php_curs_%d", (int)result->stmt); 1494 if (SQLSetCursorName(result->stmt,cursorname,SQL_NTS) != SQL_SUCCESS) { 1495 odbc_sql_error(result->conn_ptr, result->stmt, "SQLSetCursorName"); 1496 RETVAL_FALSE; 1497 } else { 1498 RETVAL_STRING(cursorname,1); 1499 } 1500 } else { 1501 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL error: %s, SQL state %s", errormsg, state); 1502 RETVAL_FALSE; 1503 } 1504 } else { 1505 RETVAL_STRING(cursorname,1); 1506 } 1507 efree(cursorname); 1508 } else { 1509 RETVAL_FALSE; 1510 } 1511} 1512/* }}} */ 1513 1514#ifdef HAVE_SQLDATASOURCES 1515/* {{{ proto array odbc_data_source(resource connection_id, int fetch_type) 1516 Return information about the currently connected data source */ 1517PHP_FUNCTION(odbc_data_source) 1518{ 1519 zval *zv_conn; 1520 long zv_fetch_type; 1521 RETCODE rc = 0; /* assume all is good */ 1522 odbc_connection *conn; 1523 UCHAR server_name[100], desc[200]; 1524 SQLSMALLINT len1=0, len2=0, fetch_type; 1525 1526 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zv_conn, &zv_fetch_type) == FAILURE) { 1527 return; 1528 } 1529 1530 fetch_type = (SQLSMALLINT) zv_fetch_type; 1531 1532 if (!(fetch_type == SQL_FETCH_FIRST || fetch_type == SQL_FETCH_NEXT)) { 1533 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fetch type (%d)", fetch_type); 1534 RETURN_FALSE; 1535 } 1536 1537 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &zv_conn, -1, "ODBC-Link", le_conn, le_pconn); 1538 1539 /* now we have the "connection" lets call the DataSource object */ 1540 rc = SQLDataSources(conn->henv, 1541 fetch_type, 1542 server_name, 1543 (SQLSMALLINT)sizeof(server_name), 1544 &len1, 1545 desc, 1546 (SQLSMALLINT)sizeof(desc), 1547 &len2); 1548 1549 if (rc != SQL_SUCCESS) { 1550 /* ummm.... he did it */ 1551 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLDataSources"); 1552 RETURN_FALSE; 1553 } 1554 1555 if (len1 == 0 || len2 == 0) { 1556 /* we have a non-valid entry... so stop the looping */ 1557 RETURN_FALSE; 1558 } 1559 1560 array_init(return_value); 1561 1562 add_assoc_string_ex(return_value, "server", sizeof("server"), server_name, 1); 1563 add_assoc_string_ex(return_value, "description", sizeof("description"), desc, 1); 1564 1565} 1566/* }}} */ 1567#endif /* HAVE_SQLDATASOURCES */ 1568 1569/* {{{ proto resource odbc_exec(resource connection_id, string query [, int flags]) 1570 Prepare and execute an SQL statement */ 1571/* XXX Use flags */ 1572PHP_FUNCTION(odbc_exec) 1573{ 1574 zval *pv_conn; 1575 long pv_flags; 1576 char *query; 1577 int numArgs, query_len; 1578 odbc_result *result = NULL; 1579 odbc_connection *conn; 1580 RETCODE rc; 1581#ifdef HAVE_SQL_EXTENDED_FETCH 1582 SQLUINTEGER scrollopts; 1583#endif 1584 1585 numArgs = ZEND_NUM_ARGS(); 1586 1587 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &pv_conn, &query, &query_len, &pv_flags) == FAILURE) { 1588 return; 1589 } 1590 1591 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 1592 1593 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 1594 1595 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 1596 if (rc == SQL_INVALID_HANDLE) { 1597 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 1598 efree(result); 1599 RETURN_FALSE; 1600 } 1601 1602 if (rc == SQL_ERROR) { 1603 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 1604 efree(result); 1605 RETURN_FALSE; 1606 } 1607 1608#ifdef HAVE_SQL_EXTENDED_FETCH 1609 /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info, 1610 whether Driver supports ExtendedFetch */ 1611 rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL); 1612 if (rc == SQL_SUCCESS) { 1613 if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) { 1614 /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other 1615 type if not possible. 1616 */ 1617 SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype)); 1618 } 1619 } else { 1620 result->fetch_abs = 0; 1621 } 1622#endif 1623 1624 rc = SQLExecDirect(result->stmt, query, SQL_NTS); 1625 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA_FOUND) { 1626 /* XXX FIXME we should really check out SQLSTATE with SQLError 1627 * in case rc is SQL_SUCCESS_WITH_INFO here. 1628 */ 1629 odbc_sql_error(conn, result->stmt, "SQLExecDirect"); 1630 SQLFreeStmt(result->stmt, SQL_DROP); 1631 efree(result); 1632 RETURN_FALSE; 1633 } 1634 1635 SQLNumResultCols(result->stmt, &(result->numcols)); 1636 1637 /* For insert, update etc. cols == 0 */ 1638 if (result->numcols > 0) { 1639 if (!odbc_bindcols(result TSRMLS_CC)) { 1640 efree(result); 1641 RETURN_FALSE; 1642 } 1643 } else { 1644 result->values = NULL; 1645 } 1646 zend_list_addref(conn->id); 1647 result->conn_ptr = conn; 1648 result->fetched = 0; 1649 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 1650} 1651/* }}} */ 1652 1653#ifdef PHP_ODBC_HAVE_FETCH_HASH 1654#define ODBC_NUM 1 1655#define ODBC_OBJECT 2 1656 1657/* {{{ php_odbc_fetch_hash */ 1658static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) 1659{ 1660 int i; 1661 odbc_result *result; 1662 RETCODE rc; 1663 SQLSMALLINT sql_c_type; 1664 char *buf = NULL; 1665#ifdef HAVE_SQL_EXTENDED_FETCH 1666 SQLULEN crow; 1667 SQLUSMALLINT RowStatus[1]; 1668 SQLLEN rownum; 1669 zval *pv_res, *tmp; 1670 long pv_row = -1; 1671 1672 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_res, &pv_row) == FAILURE) { 1673 return; 1674 } 1675 1676 rownum = pv_row; 1677#else 1678 zval *pv_res, *tmp; 1679 1680 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) { 1681 return; 1682 } 1683#endif 1684 1685 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 1686 1687 if (result->numcols == 0) { 1688 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); 1689 RETURN_FALSE; 1690 } 1691 1692#ifdef HAVE_SQL_EXTENDED_FETCH 1693 if (result->fetch_abs) { 1694 if (rownum > 0) { 1695 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus); 1696 } else { 1697 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); 1698 } 1699 } else 1700#endif 1701 rc = SQLFetch(result->stmt); 1702 1703 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 1704 RETURN_FALSE; 1705 } 1706 1707 array_init(return_value); 1708 1709#ifdef HAVE_SQL_EXTENDED_FETCH 1710 if (rownum > 0 && result->fetch_abs) 1711 result->fetched = rownum; 1712 else 1713#endif 1714 result->fetched++; 1715 1716 for(i = 0; i < result->numcols; i++) { 1717 ALLOC_INIT_ZVAL(tmp); 1718 Z_TYPE_P(tmp) = IS_STRING; 1719 Z_STRLEN_P(tmp) = 0; 1720 sql_c_type = SQL_C_CHAR; 1721 1722 switch(result->values[i].coltype) { 1723 case SQL_BINARY: 1724 case SQL_VARBINARY: 1725 case SQL_LONGVARBINARY: 1726 if (result->binmode <= 0) { 1727 Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC(); 1728 break; 1729 } 1730 if (result->binmode == 1) { 1731 sql_c_type = SQL_C_BINARY; 1732 } 1733 case SQL_LONGVARCHAR: 1734 if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) { 1735 Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC(); 1736 break; 1737 } 1738 if (buf == NULL) { 1739 buf = emalloc(result->longreadlen + 1); 1740 } 1741 1742 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1), sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen); 1743 1744 if (rc == SQL_ERROR) { 1745 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData"); 1746 efree(buf); 1747 RETURN_FALSE; 1748 } 1749 1750 if (rc == SQL_SUCCESS_WITH_INFO) { 1751 Z_STRLEN_P(tmp) = result->longreadlen; 1752 } else if (result->values[i].vallen == SQL_NULL_DATA) { 1753 ZVAL_NULL(tmp); 1754 break; 1755 } else { 1756 Z_STRLEN_P(tmp) = result->values[i].vallen; 1757 } 1758 Z_STRVAL_P(tmp) = estrndup(buf, Z_STRLEN_P(tmp)); 1759 break; 1760 1761 default: 1762 if (result->values[i].vallen == SQL_NULL_DATA) { 1763 ZVAL_NULL(tmp); 1764 break; 1765 } 1766 Z_STRLEN_P(tmp) = result->values[i].vallen; 1767 Z_STRVAL_P(tmp) = estrndup(result->values[i].value,Z_STRLEN_P(tmp)); 1768 break; 1769 } 1770 1771 if (result_type & ODBC_NUM) { 1772 zend_hash_index_update(Z_ARRVAL_P(return_value), i, &tmp, sizeof(zval *), NULL); 1773 } else { 1774 if (!*(result->values[i].name)) { 1775 zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)+1, &tmp, sizeof(zval *), NULL); 1776 } else { 1777 zend_hash_update(Z_ARRVAL_P(return_value), result->values[i].name, strlen(result->values[i].name)+1, &tmp, sizeof(zval *), NULL); 1778 } 1779 } 1780 } 1781 if (buf) { 1782 efree(buf); 1783 } 1784} 1785/* }}} */ 1786 1787 1788/* {{{ proto object odbc_fetch_object(int result [, int rownumber]) 1789 Fetch a result row as an object */ 1790PHP_FUNCTION(odbc_fetch_object) 1791{ 1792 php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT); 1793 if (Z_TYPE_P(return_value) == IS_ARRAY) { 1794 object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value)); 1795 } 1796} 1797/* }}} */ 1798 1799/* {{{ proto array odbc_fetch_array(int result [, int rownumber]) 1800 Fetch a result row as an associative array */ 1801PHP_FUNCTION(odbc_fetch_array) 1802{ 1803 php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT); 1804} 1805/* }}} */ 1806#endif 1807 1808/* {{{ proto int odbc_fetch_into(resource result_id, array &result_array, [, int rownumber]) 1809 Fetch one result row into an array */ 1810PHP_FUNCTION(odbc_fetch_into) 1811{ 1812 int i; 1813 odbc_result *result; 1814 RETCODE rc; 1815 SQLSMALLINT sql_c_type; 1816 char *buf = NULL; 1817 zval *pv_res, **pv_res_arr, *tmp; 1818#ifdef HAVE_SQL_EXTENDED_FETCH 1819 long pv_row = 0; 1820 SQLULEN crow; 1821 SQLUSMALLINT RowStatus[1]; 1822 SQLLEN rownum = -1; 1823#endif /* HAVE_SQL_EXTENDED_FETCH */ 1824 1825#ifdef HAVE_SQL_EXTENDED_FETCH 1826 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ|l", &pv_res, &pv_res_arr, &pv_row) == FAILURE) { 1827 return; 1828 } 1829 1830 rownum = pv_row; 1831#else 1832 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pv_res, &pv_res_arr) == FAILURE) { 1833 return; 1834 } 1835#endif /* HAVE_SQL_EXTENDED_FETCH */ 1836 1837 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 1838 1839 if (result->numcols == 0) { 1840 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); 1841 RETURN_FALSE; 1842 } 1843 1844 if (Z_TYPE_PP(pv_res_arr) != IS_ARRAY) { 1845 array_init(*pv_res_arr); 1846 } 1847 1848#ifdef HAVE_SQL_EXTENDED_FETCH 1849 if (result->fetch_abs) { 1850 if (rownum > 0) { 1851 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus); 1852 } else { 1853 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); 1854 } 1855 } else 1856#endif 1857 rc = SQLFetch(result->stmt); 1858 1859 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 1860 RETURN_FALSE; 1861 } 1862 1863#ifdef HAVE_SQL_EXTENDED_FETCH 1864 if (rownum > 0 && result->fetch_abs) 1865 result->fetched = rownum; 1866 else 1867#endif 1868 result->fetched++; 1869 1870 for(i = 0; i < result->numcols; i++) { 1871 MAKE_STD_ZVAL(tmp); 1872 Z_TYPE_P(tmp) = IS_STRING; 1873 Z_STRLEN_P(tmp) = 0; 1874 sql_c_type = SQL_C_CHAR; 1875 1876 switch(result->values[i].coltype) { 1877 case SQL_BINARY: 1878 case SQL_VARBINARY: 1879 case SQL_LONGVARBINARY: 1880 if (result->binmode <= 0) { 1881 Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC(); 1882 break; 1883 } 1884 if (result->binmode == 1) sql_c_type = SQL_C_BINARY; 1885 case SQL_LONGVARCHAR: 1886 if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) { 1887 Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC(); 1888 break; 1889 } 1890 1891 if (buf == NULL) { 1892 buf = emalloc(result->longreadlen + 1); 1893 } 1894 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen); 1895 1896 if (rc == SQL_ERROR) { 1897 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData"); 1898 efree(buf); 1899 RETURN_FALSE; 1900 } 1901 if (rc == SQL_SUCCESS_WITH_INFO) { 1902 Z_STRLEN_P(tmp) = result->longreadlen; 1903 } else if (result->values[i].vallen == SQL_NULL_DATA) { 1904 ZVAL_NULL(tmp); 1905 break; 1906 } else { 1907 Z_STRLEN_P(tmp) = result->values[i].vallen; 1908 } 1909 Z_STRVAL_P(tmp) = estrndup(buf, Z_STRLEN_P(tmp)); 1910 break; 1911 1912 default: 1913 if (result->values[i].vallen == SQL_NULL_DATA) { 1914 ZVAL_NULL(tmp); 1915 break; 1916 } 1917 Z_STRLEN_P(tmp) = result->values[i].vallen; 1918 Z_STRVAL_P(tmp) = estrndup(result->values[i].value,Z_STRLEN_P(tmp)); 1919 break; 1920 } 1921 zend_hash_index_update(Z_ARRVAL_PP(pv_res_arr), i, &tmp, sizeof(zval *), NULL); 1922 } 1923 if (buf) efree(buf); 1924 RETURN_LONG(result->numcols); 1925} 1926/* }}} */ 1927 1928/* {{{ proto bool solid_fetch_prev(resource result_id) 1929 */ 1930#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35) 1931PHP_FUNCTION(solid_fetch_prev) 1932{ 1933 odbc_result *result; 1934 RETCODE rc; 1935 zval *pv_res; 1936 1937 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) { 1938 return; 1939 } 1940 1941 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 1942 if (result->numcols == 0) { 1943 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); 1944 RETURN_FALSE; 1945 } 1946 rc = SQLFetchPrev(result->stmt); 1947 1948 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 1949 RETURN_FALSE; 1950 } 1951 1952 if (result->fetched > 1) { 1953 result->fetched--; 1954 } 1955 1956 RETURN_TRUE; 1957} 1958#endif 1959/* }}} */ 1960 1961/* {{{ proto bool odbc_fetch_row(resource result_id [, int row_number]) 1962 Fetch a row */ 1963PHP_FUNCTION(odbc_fetch_row) 1964{ 1965 SQLLEN rownum; 1966 odbc_result *result; 1967 RETCODE rc; 1968 zval *pv_res; 1969 long pv_row = 1; 1970#ifdef HAVE_SQL_EXTENDED_FETCH 1971 SQLULEN crow; 1972 SQLUSMALLINT RowStatus[1]; 1973#endif 1974 1975 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_res, &pv_row) == FAILURE) { 1976 return; 1977 } 1978 1979 rownum = pv_row; 1980 1981 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 1982 1983 if (result->numcols == 0) { 1984 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); 1985 RETURN_FALSE; 1986 } 1987 1988#ifdef HAVE_SQL_EXTENDED_FETCH 1989 if (result->fetch_abs) { 1990 if (ZEND_NUM_ARGS() > 1) { 1991 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus); 1992 } else { 1993 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); 1994 } 1995 } else 1996#endif 1997 rc = SQLFetch(result->stmt); 1998 1999 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 2000 RETURN_FALSE; 2001 } 2002 2003 if (ZEND_NUM_ARGS() > 1) { 2004 result->fetched = rownum; 2005 } else { 2006 result->fetched++; 2007 } 2008 2009 RETURN_TRUE; 2010} 2011/* }}} */ 2012 2013/* {{{ proto mixed odbc_result(resource result_id, mixed field) 2014 Get result data */ 2015PHP_FUNCTION(odbc_result) 2016{ 2017 char *field; 2018 int field_ind; 2019 SQLSMALLINT sql_c_type = SQL_C_CHAR; 2020 odbc_result *result; 2021 int i = 0; 2022 RETCODE rc; 2023 SQLLEN fieldsize; 2024 zval *pv_res, **pv_field; 2025#ifdef HAVE_SQL_EXTENDED_FETCH 2026 SQLULEN crow; 2027 SQLUSMALLINT RowStatus[1]; 2028#endif 2029 2030 field_ind = -1; 2031 field = NULL; 2032 2033 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pv_res, &pv_field) == FAILURE) { 2034 return; 2035 } 2036 2037 if (Z_TYPE_PP(pv_field) == IS_STRING) { 2038 field = Z_STRVAL_PP(pv_field); 2039 } else { 2040 convert_to_long_ex(pv_field); 2041 field_ind = Z_LVAL_PP(pv_field) - 1; 2042 } 2043 2044 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 2045 2046 if ((result->numcols == 0)) { 2047 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); 2048 RETURN_FALSE; 2049 } 2050 2051 /* get field index if the field parameter was a string */ 2052 if (field != NULL) { 2053 if (result->values == NULL) { 2054 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result set contains no data"); 2055 RETURN_FALSE; 2056 } 2057 2058 for(i = 0; i < result->numcols; i++) { 2059 if (!strcasecmp(result->values[i].name, field)) { 2060 field_ind = i; 2061 break; 2062 } 2063 } 2064 2065 if (field_ind < 0) { 2066 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field %s not found", field); 2067 RETURN_FALSE; 2068 } 2069 } else { 2070 /* check for limits of field_ind if the field parameter was an int */ 2071 if (field_ind >= result->numcols || field_ind < 0) { 2072 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index is larger than the number of fields"); 2073 RETURN_FALSE; 2074 } 2075 } 2076 2077 if (result->fetched == 0) { 2078 /* User forgot to call odbc_fetch_row(), or wants to reload the results, do it now */ 2079#ifdef HAVE_SQL_EXTENDED_FETCH 2080 if (result->fetch_abs) 2081 rc = SQLExtendedFetch(result->stmt, SQL_FETCH_NEXT, 1, &crow,RowStatus); 2082 else 2083#endif 2084 rc = SQLFetch(result->stmt); 2085 2086 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 2087 RETURN_FALSE; 2088 } 2089 2090 result->fetched++; 2091 } 2092 2093 switch(result->values[field_ind].coltype) { 2094 case SQL_BINARY: 2095 case SQL_VARBINARY: 2096 case SQL_LONGVARBINARY: 2097 if (result->binmode <= 1) { 2098 sql_c_type = SQL_C_BINARY; 2099 } 2100 if (result->binmode <= 0) { 2101 break; 2102 } 2103 case SQL_LONGVARCHAR: 2104 if (IS_SQL_LONG(result->values[field_ind].coltype)) { 2105 if (result->longreadlen <= 0) { 2106 break; 2107 } else { 2108 fieldsize = result->longreadlen; 2109 } 2110 } else { 2111 SQLColAttributes(result->stmt, (SQLUSMALLINT)(field_ind + 1), 2112 (SQLUSMALLINT)((sql_c_type == SQL_C_BINARY) ? SQL_COLUMN_LENGTH : 2113 SQL_COLUMN_DISPLAY_SIZE), 2114 NULL, 0, NULL, &fieldsize); 2115 } 2116 /* For char data, the length of the returned string will be longreadlen - 1 */ 2117 fieldsize = (result->longreadlen <= 0) ? 4096 : result->longreadlen; 2118 field = emalloc(fieldsize); 2119 2120 /* SQLGetData will truncate CHAR data to fieldsize - 1 bytes and append \0. 2121 * For binary data it is truncated to fieldsize bytes. 2122 */ 2123 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1), sql_c_type, 2124 field, fieldsize, &result->values[field_ind].vallen); 2125 2126 if (rc == SQL_ERROR) { 2127 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData"); 2128 efree(field); 2129 RETURN_FALSE; 2130 } 2131 2132 if (result->values[field_ind].vallen == SQL_NULL_DATA) { 2133 efree(field); 2134 RETURN_NULL(); 2135 } else if (rc == SQL_NO_DATA_FOUND) { 2136 efree(field); 2137 RETURN_FALSE; 2138 } 2139 /* Reduce fieldlen by 1 if we have char data. One day we might 2140 have binary strings... */ 2141 if (result->values[field_ind].coltype == SQL_LONGVARCHAR) { 2142 fieldsize -= 1; 2143 } 2144 /* Don't duplicate result, saves one emalloc. 2145 For SQL_SUCCESS, the length is in vallen. 2146 */ 2147 RETURN_STRINGL(field, (rc == SQL_SUCCESS_WITH_INFO) ? fieldsize : result->values[field_ind].vallen, 0); 2148 break; 2149 2150 default: 2151 if (result->values[field_ind].vallen == SQL_NULL_DATA) { 2152 RETURN_NULL(); 2153 } else { 2154 RETURN_STRINGL(result->values[field_ind].value, result->values[field_ind].vallen, 1); 2155 } 2156 break; 2157 } 2158 2159/* If we come here, output unbound LONG and/or BINARY column data to the client */ 2160 2161 /* We emalloc 1 byte more for SQL_C_CHAR (trailing \0) */ 2162 fieldsize = (sql_c_type == SQL_C_CHAR) ? 4096 : 4095; 2163 field = emalloc(fieldsize); 2164 2165 /* Call SQLGetData() until SQL_SUCCESS is returned */ 2166 while(1) { 2167 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1),sql_c_type, field, fieldsize, &result->values[field_ind].vallen); 2168 2169 if (rc == SQL_ERROR) { 2170 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData"); 2171 efree(field); 2172 RETURN_FALSE; 2173 } 2174 2175 if (result->values[field_ind].vallen == SQL_NULL_DATA) { 2176 efree(field); 2177 RETURN_NULL(); 2178 } 2179 /* chop the trailing \0 by outputing only 4095 bytes */ 2180 PHPWRITE(field,(rc == SQL_SUCCESS_WITH_INFO) ? 4095 : result->values[field_ind].vallen); 2181 2182 if (rc == SQL_SUCCESS) { /* no more data avail */ 2183 efree(field); 2184 RETURN_TRUE; 2185 } 2186 } 2187 RETURN_TRUE; 2188} 2189/* }}} */ 2190 2191/* {{{ proto int odbc_result_all(resource result_id [, string format]) 2192 Print result as HTML table */ 2193PHP_FUNCTION(odbc_result_all) 2194{ 2195 char *buf = NULL; 2196 odbc_result *result; 2197 RETCODE rc; 2198 zval *pv_res; 2199 char *pv_format = NULL; 2200 int i, pv_format_len = 0; 2201 SQLSMALLINT sql_c_type; 2202#ifdef HAVE_SQL_EXTENDED_FETCH 2203 SQLULEN crow; 2204 SQLUSMALLINT RowStatus[1]; 2205#endif 2206 2207 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s", &pv_res, &pv_format, &pv_format_len) == FAILURE) { 2208 return; 2209 } 2210 2211 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 2212 2213 if (result->numcols == 0) { 2214 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); 2215 RETURN_FALSE; 2216 } 2217#ifdef HAVE_SQL_EXTENDED_FETCH 2218 if (result->fetch_abs) 2219 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); 2220 else 2221#endif 2222 rc = SQLFetch(result->stmt); 2223 2224 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 2225 php_printf("<h2>No rows found</h2>\n"); 2226 RETURN_LONG(0); 2227 } 2228 2229 /* Start table tag */ 2230 if (ZEND_NUM_ARGS() == 1) { 2231 php_printf("<table><tr>"); 2232 } else { 2233 php_printf("<table %s ><tr>", pv_format); 2234 } 2235 2236 for (i = 0; i < result->numcols; i++) { 2237 php_printf("<th>%s</th>", result->values[i].name); 2238 } 2239 2240 php_printf("</tr>\n"); 2241 2242 while(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { 2243 result->fetched++; 2244 php_printf("<tr>"); 2245 for(i = 0; i < result->numcols; i++) { 2246 sql_c_type = SQL_C_CHAR; 2247 switch(result->values[i].coltype) { 2248 case SQL_BINARY: 2249 case SQL_VARBINARY: 2250 case SQL_LONGVARBINARY: 2251 if (result->binmode <= 0) { 2252 php_printf("<td>Not printable</td>"); 2253 break; 2254 } 2255 if (result->binmode <= 1) sql_c_type = SQL_C_BINARY; 2256 case SQL_LONGVARCHAR: 2257 if (IS_SQL_LONG(result->values[i].coltype) && 2258 result->longreadlen <= 0) { 2259 php_printf("<td>Not printable</td>"); 2260 break; 2261 } 2262 2263 if (buf == NULL) { 2264 buf = emalloc(result->longreadlen); 2265 } 2266 2267 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen, &result->values[i].vallen); 2268 2269 php_printf("<td>"); 2270 2271 if (rc == SQL_ERROR) { 2272 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData"); 2273 php_printf("</td></tr></table>"); 2274 efree(buf); 2275 RETURN_FALSE; 2276 } 2277 if (rc == SQL_SUCCESS_WITH_INFO) { 2278 PHPWRITE(buf, result->longreadlen); 2279 } else if (result->values[i].vallen == SQL_NULL_DATA) { 2280 php_printf("<td>NULL</td>"); 2281 break; 2282 } else { 2283 PHPWRITE(buf, result->values[i].vallen); 2284 } 2285 php_printf("</td>"); 2286 break; 2287 default: 2288 if (result->values[i].vallen == SQL_NULL_DATA) { 2289 php_printf("<td>NULL</td>"); 2290 } else { 2291 php_printf("<td>%s</td>", result->values[i].value); 2292 } 2293 break; 2294 } 2295 } 2296 php_printf("</tr>\n"); 2297 2298#ifdef HAVE_SQL_EXTENDED_FETCH 2299 if (result->fetch_abs) 2300 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); 2301 else 2302#endif 2303 rc = SQLFetch(result->stmt); 2304 } 2305 php_printf("</table>\n"); 2306 if (buf) efree(buf); 2307 RETURN_LONG(result->fetched); 2308} 2309/* }}} */ 2310 2311/* {{{ proto bool odbc_free_result(resource result_id) 2312 Free resources associated with a result */ 2313PHP_FUNCTION(odbc_free_result) 2314{ 2315 zval *pv_res; 2316 odbc_result *result; 2317 int i; 2318 2319 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) { 2320 return; 2321 } 2322 2323 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 2324 if (result->values) { 2325 for (i = 0; i < result->numcols; i++) { 2326 if (result->values[i].value) { 2327 efree(result->values[i].value); 2328 } 2329 } 2330 efree(result->values); 2331 result->values = NULL; 2332 } 2333 2334 zend_list_delete(Z_LVAL_P(pv_res)); 2335 2336 RETURN_TRUE; 2337} 2338/* }}} */ 2339 2340/* {{{ proto resource odbc_connect(string DSN, string user, string password [, int cursor_option]) 2341 Connect to a datasource */ 2342PHP_FUNCTION(odbc_connect) 2343{ 2344 odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); 2345} 2346/* }}} */ 2347 2348/* {{{ proto resource odbc_pconnect(string DSN, string user, string password [, int cursor_option]) 2349 Establish a persistent connection to a datasource */ 2350PHP_FUNCTION(odbc_pconnect) 2351{ 2352 odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); 2353} 2354/* }}} */ 2355 2356/* {{{ odbc_sqlconnect */ 2357int odbc_sqlconnect(odbc_connection **conn, char *db, char *uid, char *pwd, int cur_opt, int persistent TSRMLS_DC) 2358{ 2359 RETCODE rc; 2360 2361 *conn = (odbc_connection *)pemalloc(sizeof(odbc_connection), persistent); 2362 (*conn)->persistent = persistent; 2363 SQLAllocEnv(&((*conn)->henv)); 2364 SQLAllocConnect((*conn)->henv, &((*conn)->hdbc)); 2365 2366#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) 2367 SQLSetConnectOption((*conn)->hdbc, SQL_TRANSLATE_OPTION, 2368 SQL_SOLID_XLATOPT_NOCNV); 2369#endif 2370#ifdef HAVE_ODBC_ROUTER 2371 { 2372#define CONNSTRSIZE 2048 2373 char *lpszConnStr = emalloc(CONNSTRSIZE); 2374 if (lpszConnStr && db) { 2375 short cbszConnStr; 2376 if (strstr(db, ";")) { 2377 /* the caller has apparently passed a connection-string */ 2378 if (strstr(db, "uid") || strstr(db, "UID")) { 2379 uid = NULL; 2380 } 2381 if (strstr(db, "pwd") || strstr(db, "PWD")) { 2382 pwd = NULL; 2383 } 2384 strlcpy( lpszConnStr, db, CONNSTRSIZE); 2385 } 2386 else { 2387 strcpy(lpszConnStr, "DSN="); 2388 strlcat(lpszConnStr, db, CONNSTRSIZE); 2389 } 2390 if (uid) { 2391 if (uid[0]) { 2392 strlcat(lpszConnStr, ";UID=", CONNSTRSIZE); 2393 strlcat(lpszConnStr, uid, CONNSTRSIZE); 2394 strlcat(lpszConnStr, ";", CONNSTRSIZE); 2395 } 2396 if (pwd) { 2397 if (pwd[0]) { 2398 strlcat(lpszConnStr, "PWD=", CONNSTRSIZE); 2399 strlcat(lpszConnStr, pwd, CONNSTRSIZE); 2400 strlcat(lpszConnStr, ";", CONNSTRSIZE); 2401 } 2402 } 2403 } 2404 rc = SQLDriverConnect((*conn)->hdbc, NULL, lpszConnStr, SQL_NTS, lpszConnStr, CONNSTRSIZE, &cbszConnStr, SQL_DRIVER_NOPROMPT); 2405 efree(lpszConnStr); 2406 } 2407 } 2408#else 2409#ifdef HAVE_OPENLINK 2410 { 2411 char dsnbuf[1024]; 2412 short dsnbuflen; 2413 2414 rc = SQLDriverConnect((*conn)->hdbc, NULL, db, SQL_NTS, dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT); 2415 } 2416#else 2417 if (cur_opt != SQL_CUR_DEFAULT) { 2418 rc = SQLSetConnectOption((*conn)->hdbc, SQL_ODBC_CURSORS, cur_opt); 2419 if (rc != SQL_SUCCESS) { /* && rc != SQL_SUCCESS_WITH_INFO ? */ 2420 odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLSetConnectOption"); 2421 SQLFreeConnect((*conn)->hdbc); 2422 pefree(*conn, persistent); 2423 return FALSE; 2424 } 2425 } 2426/* Possible fix for bug #10250 2427 * Needs testing on UnixODBC < 2.0.5 though. */ 2428#if defined(HAVE_EMPRESS) || defined(HAVE_UNIXODBC) || defined(PHP_WIN32) || defined (HAVE_IODBC) 2429/* * Uncomment the line above, and comment line below to fully test 2430 * #ifdef HAVE_EMPRESS */ 2431 { 2432 int direct = 0; 2433 char dsnbuf[1024]; 2434 short dsnbuflen; 2435 char *ldb = 0; 2436 int ldb_len = 0; 2437 2438 if (strstr((char*)db, ";")) { 2439 direct = 1; 2440 if (uid && !strstr ((char*)db, "uid") && !strstr((char*)db, "UID")) { 2441 spprintf(&ldb, 0, "%s;UID=%s;PWD=%s", db, uid, pwd); 2442 } else { 2443 ldb_len = strlen(db)+1; 2444 ldb = (char*) emalloc(ldb_len); 2445 memcpy(ldb, db, ldb_len); 2446 } 2447 } 2448 2449 if (direct) { 2450 rc = SQLDriverConnect((*conn)->hdbc, NULL, ldb, strlen(ldb), dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT); 2451 } else { 2452 rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS); 2453 } 2454 2455 if (ldb) { 2456 efree(ldb); 2457 } 2458 } 2459#else 2460 rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS); 2461#endif 2462#endif 2463#endif 2464 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 2465 odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLConnect"); 2466 SQLFreeConnect((*conn)->hdbc); 2467 pefree((*conn), persistent); 2468 return FALSE; 2469 } 2470/* (*conn)->open = 1;*/ 2471 return TRUE; 2472} 2473/* }}} */ 2474 2475/* Persistent connections: two list-types le_pconn, le_conn and a plist 2476 * where hashed connection info is stored together with index pointer to 2477 * the actual link of type le_pconn in the list. Only persistent 2478 * connections get hashed up. Normal connections use existing pconnections. 2479 * Maybe this has to change with regard to transactions on pconnections? 2480 * Possibly set autocommit to on on request shutdown. 2481 * 2482 * We do have to hash non-persistent connections, and reuse connections. 2483 * In the case where two connects were being made, without closing the first 2484 * connect, access violations were occuring. This is because some of the 2485 * "globals" in this module should actualy be per-connection variables. I 2486 * simply fixed things to get them working for now. Shane 2487 */ 2488/* {{{ odbc_do_connect */ 2489void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) 2490{ 2491 char *db, *uid, *pwd; 2492 int db_len, uid_len, pwd_len; 2493 long pv_opt = SQL_CUR_DEFAULT; 2494 odbc_connection *db_conn; 2495 char *hashed_details; 2496 int hashed_len, cur_opt; 2497 2498 /* Now an optional 4th parameter specifying the cursor type 2499 * defaulting to the cursors default 2500 */ 2501 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|l", &db, &db_len, &uid, &uid_len, &pwd, &pwd_len, &pv_opt) == FAILURE) { 2502 return; 2503 } 2504 2505 cur_opt = pv_opt; 2506 2507 if (ZEND_NUM_ARGS() > 3) { 2508 /* Confirm the cur_opt range */ 2509 if (! (cur_opt == SQL_CUR_USE_IF_NEEDED || 2510 cur_opt == SQL_CUR_USE_ODBC || 2511 cur_opt == SQL_CUR_USE_DRIVER || 2512 cur_opt == SQL_CUR_DEFAULT) ) { 2513 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Cursor type (%d)", cur_opt); 2514 RETURN_FALSE; 2515 } 2516 } 2517 2518 if (ODBCG(allow_persistent) <= 0) { 2519 persistent = 0; 2520 } 2521 2522 hashed_len = spprintf(&hashed_details, 0, "%s_%s_%s_%s_%d", ODBC_TYPE, db, uid, pwd, cur_opt); 2523 2524 /* FIXME the idea of checking to see if our connection is already persistent 2525 is good, but it adds a lot of overhead to non-persistent connections. We 2526 should look and see if we can fix that somehow */ 2527 /* try to find if we already have this link in our persistent list, 2528 * no matter if it is to be persistent or not 2529 */ 2530 2531try_and_get_another_connection: 2532 2533 if (persistent) { 2534 zend_rsrc_list_entry *le; 2535 2536 /* the link is not in the persistent list */ 2537 if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_len + 1, (void **) &le) == FAILURE) { 2538 zend_rsrc_list_entry new_le; 2539 2540 if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) { 2541 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", ODBCG(num_links)); 2542 efree(hashed_details); 2543 RETURN_FALSE; 2544 } 2545 if (ODBCG(max_persistent) != -1 && ODBCG(num_persistent) >= ODBCG(max_persistent)) { 2546 php_error_docref(NULL TSRMLS_CC, E_WARNING,"Too many open persistent links (%ld)", ODBCG(num_persistent)); 2547 efree(hashed_details); 2548 RETURN_FALSE; 2549 } 2550 2551 if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 1 TSRMLS_CC)) { 2552 efree(hashed_details); 2553 RETURN_FALSE; 2554 } 2555 2556 Z_TYPE(new_le) = le_pconn; 2557 new_le.ptr = db_conn; 2558 if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_len + 1, &new_le, 2559 sizeof(zend_rsrc_list_entry), NULL) == FAILURE) { 2560 free(db_conn); 2561 efree(hashed_details); 2562 RETURN_FALSE; 2563 } 2564 ODBCG(num_persistent)++; 2565 ODBCG(num_links)++; 2566 db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_pconn); 2567 } else { /* found connection */ 2568 if (Z_TYPE_P(le) != le_pconn) { 2569 RETURN_FALSE; 2570 } 2571 /* 2572 * check to see if the connection is still valid 2573 */ 2574 db_conn = (odbc_connection *)le->ptr; 2575 2576 /* 2577 * check to see if the connection is still in place (lurcher) 2578 */ 2579 if(ODBCG(check_persistent)){ 2580 RETCODE ret; 2581 UCHAR d_name[32]; 2582 SQLSMALLINT len; 2583 2584 ret = SQLGetInfo(db_conn->hdbc, 2585 SQL_DATA_SOURCE_READ_ONLY, 2586 d_name, sizeof(d_name), &len); 2587 2588 if(ret != SQL_SUCCESS || len == 0) { 2589 zend_hash_del(&EG(persistent_list), hashed_details, hashed_len + 1); 2590 /* Commented out to fix a possible double closure error 2591 * when working with persistent connections as submitted by 2592 * bug #15758 2593 * 2594 * safe_odbc_disconnect(db_conn->hdbc); 2595 * SQLFreeConnect(db_conn->hdbc); 2596 */ 2597 goto try_and_get_another_connection; 2598 } 2599 } 2600 } 2601 db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_pconn); 2602 } else { /* non persistent */ 2603 zend_rsrc_list_entry *index_ptr, new_index_ptr; 2604 2605 if (zend_hash_find(&EG(regular_list), hashed_details, hashed_len + 1, (void **) &index_ptr) == SUCCESS) { 2606 int type, conn_id; 2607 void *ptr; 2608 2609 if (Z_TYPE_P(index_ptr) != le_index_ptr) { 2610 RETURN_FALSE; 2611 } 2612 conn_id = (int)index_ptr->ptr; 2613 ptr = zend_list_find(conn_id, &type); /* check if the connection is still there */ 2614 2615 if (ptr && (type == le_conn || type == le_pconn)) { 2616 zend_list_addref(conn_id); 2617 Z_LVAL_P(return_value) = conn_id; 2618 Z_TYPE_P(return_value) = IS_RESOURCE; 2619 efree(hashed_details); 2620 return; 2621 } else { 2622 zend_hash_del(&EG(regular_list), hashed_details, hashed_len + 1); 2623 } 2624 } 2625 if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) { 2626 php_error_docref(NULL TSRMLS_CC, E_WARNING,"Too many open connections (%ld)",ODBCG(num_links)); 2627 efree(hashed_details); 2628 RETURN_FALSE; 2629 } 2630 2631 if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 0 TSRMLS_CC)) { 2632 efree(hashed_details); 2633 RETURN_FALSE; 2634 } 2635 db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_conn); 2636 new_index_ptr.ptr = (void *) Z_LVAL_P(return_value); 2637 Z_TYPE(new_index_ptr) = le_index_ptr; 2638 2639 if (zend_hash_update(&EG(regular_list), hashed_details, hashed_len + 1, (void *) &new_index_ptr, 2640 sizeof(zend_rsrc_list_entry), NULL) == FAILURE) { 2641 efree(hashed_details); 2642 RETURN_FALSE; 2643 /* XXX Free Connection */ 2644 } 2645 ODBCG(num_links)++; 2646 } 2647 efree(hashed_details); 2648} 2649/* }}} */ 2650 2651/* {{{ proto void odbc_close(resource connection_id) 2652 Close an ODBC connection */ 2653PHP_FUNCTION(odbc_close) 2654{ 2655 zval *pv_conn; 2656 void *ptr; 2657 odbc_connection *conn; 2658 odbc_result *res; 2659 int nument; 2660 int i; 2661 int type; 2662 int is_pconn = 0; 2663 int found_resource_type = le_conn; 2664 2665 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_conn) == FAILURE) { 2666 return; 2667 } 2668 2669 conn = (odbc_connection *) zend_fetch_resource(&pv_conn TSRMLS_CC, -1, "ODBC-Link", &found_resource_type, 2, le_conn, le_pconn); 2670 if (found_resource_type==le_pconn) { 2671 is_pconn = 1; 2672 } 2673 2674 nument = zend_hash_next_free_element(&EG(regular_list)); 2675 2676 for(i = 1; i < nument; i++){ 2677 ptr = zend_list_find(i, &type); 2678 if(ptr && (type == le_result)){ 2679 res = (odbc_result *)ptr; 2680 if(res->conn_ptr == conn){ 2681 zend_list_delete(i); 2682 } 2683 } 2684 } 2685 2686 zend_list_delete(Z_LVAL_P(pv_conn)); 2687 2688 if(is_pconn){ 2689 zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) _close_pconn_with_id, (void *) &(Z_LVAL_P(pv_conn)) TSRMLS_CC); 2690 } 2691} 2692/* }}} */ 2693 2694/* {{{ proto int odbc_num_rows(resource result_id) 2695 Get number of rows in a result */ 2696PHP_FUNCTION(odbc_num_rows) 2697{ 2698 odbc_result *result; 2699 SQLLEN rows; 2700 zval *pv_res; 2701 2702 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) { 2703 return; 2704 } 2705 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 2706 SQLRowCount(result->stmt, &rows); 2707 RETURN_LONG(rows); 2708} 2709/* }}} */ 2710 2711#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) 2712/* {{{ proto bool odbc_next_result(resource result_id) 2713 Checks if multiple results are avaiable */ 2714PHP_FUNCTION(odbc_next_result) 2715{ 2716 odbc_result *result; 2717 zval *pv_res; 2718 int rc, i; 2719 2720 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) { 2721 return; 2722 } 2723 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 2724 2725 if (result->values) { 2726 for(i = 0; i < result->numcols; i++) { 2727 if (result->values[i].value) { 2728 efree(result->values[i].value); 2729 } 2730 } 2731 efree(result->values); 2732 result->values = NULL; 2733 } 2734 2735 result->fetched = 0; 2736 rc = SQLMoreResults(result->stmt); 2737 if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS) { 2738 rc = SQLFreeStmt(result->stmt, SQL_UNBIND); 2739 SQLNumParams(result->stmt, &(result->numparams)); 2740 SQLNumResultCols(result->stmt, &(result->numcols)); 2741 2742 if (result->numcols > 0) { 2743 if (!odbc_bindcols(result TSRMLS_CC)) { 2744 efree(result); 2745 RETVAL_FALSE; 2746 } 2747 } else { 2748 result->values = NULL; 2749 } 2750 RETURN_TRUE; 2751 } else if (rc == SQL_NO_DATA_FOUND) { 2752 RETURN_FALSE; 2753 } else { 2754 odbc_sql_error(result->conn_ptr, result->stmt, "SQLMoreResults"); 2755 RETURN_FALSE; 2756 } 2757} 2758/* }}} */ 2759#endif 2760 2761/* {{{ proto int odbc_num_fields(resource result_id) 2762 Get number of columns in a result */ 2763PHP_FUNCTION(odbc_num_fields) 2764{ 2765 odbc_result *result; 2766 zval *pv_res; 2767 2768 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) { 2769 return; 2770 } 2771 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 2772 RETURN_LONG(result->numcols); 2773} 2774/* }}} */ 2775 2776/* {{{ proto string odbc_field_name(resource result_id, int field_number) 2777 Get a column name */ 2778PHP_FUNCTION(odbc_field_name) 2779{ 2780 odbc_result *result; 2781 zval *pv_res; 2782 long pv_num; 2783 2784 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &pv_num) == FAILURE) { 2785 return; 2786 } 2787 2788 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 2789 2790 if (result->numcols == 0) { 2791 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); 2792 RETURN_FALSE; 2793 } 2794 2795 if (pv_num > result->numcols) { 2796 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index larger than number of fields"); 2797 RETURN_FALSE; 2798 } 2799 2800 if (pv_num < 1) { 2801 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field numbering starts at 1"); 2802 RETURN_FALSE; 2803 } 2804 2805 RETURN_STRING(result->values[pv_num - 1].name, 1); 2806} 2807/* }}} */ 2808 2809/* {{{ proto string odbc_field_type(resource result_id, int field_number) 2810 Get the datatype of a column */ 2811PHP_FUNCTION(odbc_field_type) 2812{ 2813 odbc_result *result; 2814 char tmp[32]; 2815 SQLSMALLINT tmplen; 2816 zval *pv_res; 2817 long pv_num; 2818 2819 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &pv_num) == FAILURE) { 2820 return; 2821 } 2822 2823 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 2824 2825 if (result->numcols == 0) { 2826 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); 2827 RETURN_FALSE; 2828 } 2829 2830 if (pv_num > result->numcols) { 2831 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index larger than number of fields"); 2832 RETURN_FALSE; 2833 } 2834 2835 if (pv_num < 1) { 2836 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field numbering starts at 1"); 2837 RETURN_FALSE; 2838 } 2839 2840 SQLColAttributes(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL); 2841 RETURN_STRING(tmp,1) 2842} 2843/* }}} */ 2844 2845/* {{{ proto int odbc_field_len(resource result_id, int field_number) 2846 Get the length (precision) of a column */ 2847PHP_FUNCTION(odbc_field_len) 2848{ 2849 odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); 2850} 2851/* }}} */ 2852 2853/* {{{ proto int odbc_field_scale(resource result_id, int field_number) 2854 Get the scale of a column */ 2855PHP_FUNCTION(odbc_field_scale) 2856{ 2857 odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); 2858} 2859/* }}} */ 2860 2861/* {{{ proto int odbc_field_num(resource result_id, string field_name) 2862 Return column number */ 2863PHP_FUNCTION(odbc_field_num) 2864{ 2865 char *fname; 2866 int i, field_ind, fname_len; 2867 odbc_result *result; 2868 zval *pv_res; 2869 2870 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pv_res, &fname, &fname_len) == FAILURE) { 2871 return; 2872 } 2873 2874 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result); 2875 2876 if (result->numcols == 0) { 2877 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index"); 2878 RETURN_FALSE; 2879 } 2880 2881 field_ind = -1; 2882 for(i = 0; i < result->numcols; i++) { 2883 if (strcasecmp(result->values[i].name, fname) == 0) { 2884 field_ind = i + 1; 2885 } 2886 } 2887 2888 if (field_ind == -1) { 2889 RETURN_FALSE; 2890 } 2891 RETURN_LONG(field_ind); 2892} 2893/* }}} */ 2894 2895/* {{{ proto mixed odbc_autocommit(resource connection_id [, int OnOff]) 2896 Toggle autocommit mode or get status */ 2897/* There can be problems with pconnections!*/ 2898PHP_FUNCTION(odbc_autocommit) 2899{ 2900 odbc_connection *conn; 2901 RETCODE rc; 2902 zval *pv_conn; 2903 long pv_onoff = 0; 2904 2905 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_conn, &pv_onoff) == FAILURE) { 2906 return; 2907 } 2908 2909 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 2910 2911 if (ZEND_NUM_ARGS() > 1) { 2912 rc = SQLSetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (pv_onoff) ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF); 2913 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 2914 odbc_sql_error(conn, SQL_NULL_HSTMT, "Set autocommit"); 2915 RETURN_FALSE; 2916 } 2917 RETVAL_TRUE; 2918 } else { 2919 SQLINTEGER status; 2920 2921 rc = SQLGetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (PTR)&status); 2922 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 2923 odbc_sql_error(conn, SQL_NULL_HSTMT, "Get commit status"); 2924 RETURN_FALSE; 2925 } 2926 RETVAL_LONG((long)status); 2927 } 2928} 2929/* }}} */ 2930 2931/* {{{ proto bool odbc_commit(resource connection_id) 2932 Commit an ODBC transaction */ 2933PHP_FUNCTION(odbc_commit) 2934{ 2935 odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); 2936} 2937/* }}} */ 2938 2939/* {{{ proto bool odbc_rollback(resource connection_id) 2940 Rollback a transaction */ 2941PHP_FUNCTION(odbc_rollback) 2942{ 2943 odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); 2944} 2945/* }}} */ 2946 2947/* {{{ php_odbc_lasterror */ 2948static void php_odbc_lasterror(INTERNAL_FUNCTION_PARAMETERS, int mode) 2949{ 2950 odbc_connection *conn; 2951 zval *pv_handle; 2952 char *ptr; 2953 int len; 2954 2955 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &pv_handle) == FAILURE) { 2956 return; 2957 } 2958 2959 if (mode == 0) { /* last state */ 2960 len = 6; 2961 } else { /* last error message */ 2962 len = SQL_MAX_MESSAGE_LENGTH; 2963 } 2964 2965 if (ZEND_NUM_ARGS() == 1) { 2966 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_handle, -1, "ODBC-Link", le_conn, le_pconn); 2967 ptr = ecalloc(len + 1, 1); 2968 if (mode == 0) { 2969 strlcpy(ptr, conn->laststate, len+1); 2970 } else { 2971 strlcpy(ptr, conn->lasterrormsg, len+1); 2972 } 2973 } else { 2974 ptr = ecalloc(len + 1, 1); 2975 if (mode == 0) { 2976 strlcpy(ptr, ODBCG(laststate), len+1); 2977 } else { 2978 strlcpy(ptr, ODBCG(lasterrormsg), len+1); 2979 } 2980 } 2981 RETVAL_STRING(ptr, 0); 2982} 2983/* }}} */ 2984 2985/* {{{ proto string odbc_error([resource connection_id]) 2986 Get the last error code */ 2987PHP_FUNCTION(odbc_error) 2988{ 2989 php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); 2990} 2991/* }}} */ 2992 2993/* {{{ proto string odbc_errormsg([resource connection_id]) 2994 Get the last error message */ 2995PHP_FUNCTION(odbc_errormsg) 2996{ 2997 php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); 2998} 2999/* }}} */ 3000 3001/* {{{ proto bool odbc_setoption(resource conn_id|result_id, int which, int option, int value) 3002 Sets connection or statement options */ 3003/* This one has to be used carefully. We can't allow to set connection options for 3004 persistent connections. I think that SetStmtOption is of little use, since most 3005 of those can only be specified before preparing/executing statements. 3006 On the other hand, they can be made connection wide default through SetConnectOption 3007 - but will be overidden by calls to SetStmtOption() in odbc_prepare/odbc_do 3008*/ 3009PHP_FUNCTION(odbc_setoption) 3010{ 3011 odbc_connection *conn; 3012 odbc_result *result; 3013 RETCODE rc; 3014 zval *pv_handle; 3015 long pv_which, pv_opt, pv_val; 3016 3017 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlll", &pv_handle, &pv_which, &pv_opt, &pv_val) == FAILURE) { 3018 return; 3019 } 3020 3021 switch (pv_which) { 3022 case 1: /* SQLSetConnectOption */ 3023 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_handle, -1, "ODBC-Link", le_conn, le_pconn); 3024 3025 if (conn->persistent) { 3026 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set option for persistent connection"); 3027 RETURN_FALSE; 3028 } 3029 rc = SQLSetConnectOption(conn->hdbc, (unsigned short) pv_opt, pv_val); 3030 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 3031 odbc_sql_error(conn, SQL_NULL_HSTMT, "SetConnectOption"); 3032 RETURN_FALSE; 3033 } 3034 break; 3035 case 2: /* SQLSetStmtOption */ 3036 ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_handle, -1, "ODBC result", le_result); 3037 3038 rc = SQLSetStmtOption(result->stmt, (unsigned short) pv_opt, pv_val); 3039 3040 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 3041 odbc_sql_error(result->conn_ptr, result->stmt, "SetStmtOption"); 3042 RETURN_FALSE; 3043 } 3044 break; 3045 default: 3046 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option type"); 3047 RETURN_FALSE; 3048 break; 3049 } 3050 3051 RETURN_TRUE; 3052} 3053/* }}} */ 3054 3055/* 3056 * metadata functions 3057 */ 3058 3059/* {{{ proto resource odbc_tables(resource connection_id [, string qualifier [, string owner [, string name [, string table_types]]]]) 3060 Call the SQLTables function */ 3061PHP_FUNCTION(odbc_tables) 3062{ 3063 zval *pv_conn; 3064 odbc_result *result = NULL; 3065 odbc_connection *conn; 3066 char *cat = NULL, *schema = NULL, *table = NULL, *type = NULL; 3067 int cat_len = 0, schema_len = 0, table_len = 0, type_len = 0; 3068 RETCODE rc; 3069 3070 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len, 3071 &table, &table_len, &type, &type_len) == FAILURE) { 3072 return; 3073 } 3074 3075 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3076 3077 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3078 3079 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3080 if (rc == SQL_INVALID_HANDLE) { 3081 efree(result); 3082 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3083 RETURN_FALSE; 3084 } 3085 3086 if (rc == SQL_ERROR) { 3087 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3088 efree(result); 3089 RETURN_FALSE; 3090 } 3091 3092 /* This hack is needed to access table information in Access databases (fmk) */ 3093 if (table && table_len && schema && schema_len == 0) { 3094 schema = NULL; 3095 } 3096 3097 rc = SQLTables(result->stmt, 3098 cat, SAFE_SQL_NTS(cat), 3099 schema, SAFE_SQL_NTS(schema), 3100 table, SAFE_SQL_NTS(table), 3101 type, SAFE_SQL_NTS(type)); 3102 3103 if (rc == SQL_ERROR) { 3104 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTables"); 3105 efree(result); 3106 RETURN_FALSE; 3107 } 3108 3109 result->numparams = 0; 3110 SQLNumResultCols(result->stmt, &(result->numcols)); 3111 3112 if (result->numcols > 0) { 3113 if (!odbc_bindcols(result TSRMLS_CC)) { 3114 efree(result); 3115 RETURN_FALSE; 3116 } 3117 } else { 3118 result->values = NULL; 3119 } 3120 result->conn_ptr = conn; 3121 result->fetched = 0; 3122 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3123} 3124/* }}} */ 3125 3126/* {{{ proto resource odbc_columns(resource connection_id [, string qualifier [, string owner [, string table_name [, string column_name]]]]) 3127 Returns a result identifier that can be used to fetch a list of column names in specified tables */ 3128PHP_FUNCTION(odbc_columns) 3129{ 3130 zval *pv_conn; 3131 odbc_result *result = NULL; 3132 odbc_connection *conn; 3133 char *cat = NULL, *schema = NULL, *table = NULL, *column = NULL; 3134 int cat_len = 0, schema_len = 0, table_len = 0, column_len = 0; 3135 RETCODE rc; 3136 3137 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len, 3138 &table, &table_len, &column, &column_len) == FAILURE) { 3139 return; 3140 } 3141 3142 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3143 3144 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3145 3146 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3147 if (rc == SQL_INVALID_HANDLE) { 3148 efree(result); 3149 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3150 RETURN_FALSE; 3151 } 3152 3153 if (rc == SQL_ERROR) { 3154 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3155 efree(result); 3156 RETURN_FALSE; 3157 } 3158 3159 /* 3160 * Needed to make MS Access happy 3161 */ 3162 if (table && table_len && schema && schema_len == 0) { 3163 schema = NULL; 3164 } 3165 3166 rc = SQLColumns(result->stmt, 3167 cat, (SQLSMALLINT) cat_len, 3168 schema, (SQLSMALLINT) schema_len, 3169 table, (SQLSMALLINT) table_len, 3170 column, (SQLSMALLINT) column_len); 3171 3172 if (rc == SQL_ERROR) { 3173 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLColumns"); 3174 efree(result); 3175 RETURN_FALSE; 3176 } 3177 3178 result->numparams = 0; 3179 SQLNumResultCols(result->stmt, &(result->numcols)); 3180 3181 if (result->numcols > 0) { 3182 if (!odbc_bindcols(result TSRMLS_CC)) { 3183 efree(result); 3184 RETURN_FALSE; 3185 } 3186 } else { 3187 result->values = NULL; 3188 } 3189 result->conn_ptr = conn; 3190 result->fetched = 0; 3191 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3192} 3193/* }}} */ 3194 3195#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP) 3196/* {{{ proto resource odbc_columnprivileges(resource connection_id, string catalog, string schema, string table, string column) 3197 Returns a result identifier that can be used to fetch a list of columns and associated privileges for the specified table */ 3198PHP_FUNCTION(odbc_columnprivileges) 3199{ 3200 zval *pv_conn; 3201 odbc_result *result = NULL; 3202 odbc_connection *conn; 3203 char *cat = NULL, *schema, *table, *column; 3204 int cat_len = 0, schema_len, table_len, column_len; 3205 RETCODE rc; 3206 3207 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len, 3208 &table, &table_len, &column, &column_len) == FAILURE) { 3209 return; 3210 } 3211 3212 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3213 3214 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3215 3216 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3217 if (rc == SQL_INVALID_HANDLE) { 3218 efree(result); 3219 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3220 RETURN_FALSE; 3221 } 3222 3223 if (rc == SQL_ERROR) { 3224 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3225 efree(result); 3226 RETURN_FALSE; 3227 } 3228 3229 rc = SQLColumnPrivileges(result->stmt, 3230 cat, SAFE_SQL_NTS(cat), 3231 schema, SAFE_SQL_NTS(schema), 3232 table, SAFE_SQL_NTS(table), 3233 column, SAFE_SQL_NTS(column)); 3234 3235 if (rc == SQL_ERROR) { 3236 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLColumnPrivileges"); 3237 efree(result); 3238 RETURN_FALSE; 3239 } 3240 3241 result->numparams = 0; 3242 SQLNumResultCols(result->stmt, &(result->numcols)); 3243 3244 if (result->numcols > 0) { 3245 if (!odbc_bindcols(result TSRMLS_CC)) { 3246 efree(result); 3247 RETURN_FALSE; 3248 } 3249 } else { 3250 result->values = NULL; 3251 } 3252 result->conn_ptr = conn; 3253 result->fetched = 0; 3254 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3255} 3256/* }}} */ 3257#endif /* HAVE_DBMAKER || HAVE_SOLID*/ 3258 3259#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) 3260/* {{{ 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) 3261 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 */ 3262PHP_FUNCTION(odbc_foreignkeys) 3263{ 3264 zval *pv_conn; 3265 odbc_result *result = NULL; 3266 odbc_connection *conn; 3267 char *pcat = NULL, *pschema, *ptable, *fcat, *fschema, *ftable; 3268 int pcat_len = 0, pschema_len, ptable_len, fcat_len, fschema_len, ftable_len; 3269 RETCODE rc; 3270 3271 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!sssss", &pv_conn, &pcat, &pcat_len, &pschema, &pschema_len, 3272 &ptable, &ptable_len, &fcat, &fcat_len, &fschema, &fschema_len, &ftable, &ftable_len) == FAILURE) { 3273 return; 3274 } 3275 3276#if defined(HAVE_DBMAKER) || defined(HAVE_IBMDB2) 3277#define EMPTY_TO_NULL(xstr) \ 3278 if ((int)strlen((xstr)) == 0) (xstr) = NULL 3279 3280 EMPTY_TO_NULL(pcat); 3281 EMPTY_TO_NULL(pschema); 3282 EMPTY_TO_NULL(ptable); 3283 EMPTY_TO_NULL(fcat); 3284 EMPTY_TO_NULL(fschema); 3285 EMPTY_TO_NULL(ftable); 3286#endif 3287 3288 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3289 3290 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3291 3292 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3293 if (rc == SQL_INVALID_HANDLE) { 3294 efree(result); 3295 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3296 RETURN_FALSE; 3297 } 3298 3299 if (rc == SQL_ERROR) { 3300 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3301 efree(result); 3302 RETURN_FALSE; 3303 } 3304 3305 rc = SQLForeignKeys(result->stmt, 3306 pcat, SAFE_SQL_NTS(pcat), 3307 pschema, SAFE_SQL_NTS(pschema), 3308 ptable, SAFE_SQL_NTS(ptable), 3309 fcat, SAFE_SQL_NTS(fcat), 3310 fschema, SAFE_SQL_NTS(fschema), 3311 ftable, SAFE_SQL_NTS(ftable) ); 3312 3313 if (rc == SQL_ERROR) { 3314 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLForeignKeys"); 3315 efree(result); 3316 RETURN_FALSE; 3317 } 3318 3319 result->numparams = 0; 3320 SQLNumResultCols(result->stmt, &(result->numcols)); 3321 3322 if (result->numcols > 0) { 3323 if (!odbc_bindcols(result TSRMLS_CC)) { 3324 efree(result); 3325 RETURN_FALSE; 3326 } 3327 } else { 3328 result->values = NULL; 3329 } 3330 result->conn_ptr = conn; 3331 result->fetched = 0; 3332 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3333} 3334/* }}} */ 3335#endif /* HAVE_SOLID */ 3336 3337/* {{{ proto resource odbc_gettypeinfo(resource connection_id [, int data_type]) 3338 Returns a result identifier containing information about data types supported by the data source */ 3339PHP_FUNCTION(odbc_gettypeinfo) 3340{ 3341 zval *pv_conn; 3342 long pv_data_type = SQL_ALL_TYPES; 3343 odbc_result *result = NULL; 3344 odbc_connection *conn; 3345 RETCODE rc; 3346 SQLSMALLINT data_type; 3347 3348 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_conn, &pv_data_type) == FAILURE) { 3349 return; 3350 } 3351 3352 data_type = (SQLSMALLINT) pv_data_type; 3353 3354 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3355 3356 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3357 3358 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3359 if (rc == SQL_INVALID_HANDLE) { 3360 efree(result); 3361 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3362 RETURN_FALSE; 3363 } 3364 3365 if (rc == SQL_ERROR) { 3366 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3367 efree(result); 3368 RETURN_FALSE; 3369 } 3370 3371 rc = SQLGetTypeInfo(result->stmt, data_type ); 3372 3373 if (rc == SQL_ERROR) { 3374 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLGetTypeInfo"); 3375 efree(result); 3376 RETURN_FALSE; 3377 } 3378 3379 result->numparams = 0; 3380 SQLNumResultCols(result->stmt, &(result->numcols)); 3381 3382 if (result->numcols > 0) { 3383 if (!odbc_bindcols(result TSRMLS_CC)) { 3384 efree(result); 3385 RETURN_FALSE; 3386 } 3387 } else { 3388 result->values = NULL; 3389 } 3390 result->conn_ptr = conn; 3391 result->fetched = 0; 3392 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3393} 3394/* }}} */ 3395 3396/* {{{ proto resource odbc_primarykeys(resource connection_id, string qualifier, string owner, string table) 3397 Returns a result identifier listing the column names that comprise the primary key for a table */ 3398PHP_FUNCTION(odbc_primarykeys) 3399{ 3400 zval *pv_conn; 3401 odbc_result *result = NULL; 3402 odbc_connection *conn; 3403 char *cat = NULL, *schema = NULL, *table = NULL; 3404 int cat_len = 0, schema_len, table_len; 3405 RETCODE rc; 3406 3407 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) { 3408 return; 3409 } 3410 3411 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3412 3413 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3414 3415 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3416 if (rc == SQL_INVALID_HANDLE) { 3417 efree(result); 3418 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3419 RETURN_FALSE; 3420 } 3421 3422 if (rc == SQL_ERROR) { 3423 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3424 efree(result); 3425 RETURN_FALSE; 3426 } 3427 3428 rc = SQLPrimaryKeys(result->stmt, 3429 cat, SAFE_SQL_NTS(cat), 3430 schema, SAFE_SQL_NTS(schema), 3431 table, SAFE_SQL_NTS(table) ); 3432 3433 if (rc == SQL_ERROR) { 3434 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLPrimaryKeys"); 3435 efree(result); 3436 RETURN_FALSE; 3437 } 3438 3439 result->numparams = 0; 3440 SQLNumResultCols(result->stmt, &(result->numcols)); 3441 3442 if (result->numcols > 0) { 3443 if (!odbc_bindcols(result TSRMLS_CC)) { 3444 efree(result); 3445 RETURN_FALSE; 3446 } 3447 } else { 3448 result->values = NULL; 3449 } 3450 result->conn_ptr = conn; 3451 result->fetched = 0; 3452 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3453} 3454/* }}} */ 3455 3456#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP) 3457/* {{{ proto resource odbc_procedurecolumns(resource connection_id [, string qualifier, string owner, string proc, string column]) 3458 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 */ 3459PHP_FUNCTION(odbc_procedurecolumns) 3460{ 3461 zval *pv_conn; 3462 odbc_result *result = NULL; 3463 odbc_connection *conn; 3464 char *cat = NULL, *schema = NULL, *proc = NULL, *col = NULL; 3465 int cat_len = 0, schema_len = 0, proc_len = 0, col_len = 0; 3466 RETCODE rc; 3467 3468 if (ZEND_NUM_ARGS() != 1 && ZEND_NUM_ARGS() != 5) { 3469 WRONG_PARAM_COUNT; 3470 } 3471 3472 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len, 3473 &proc, &proc_len, &col, &col_len) == FAILURE) { 3474 return; 3475 } 3476 3477 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3478 3479 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3480 3481 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3482 if (rc == SQL_INVALID_HANDLE) { 3483 efree(result); 3484 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3485 RETURN_FALSE; 3486 } 3487 3488 if (rc == SQL_ERROR) { 3489 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3490 efree(result); 3491 RETURN_FALSE; 3492 } 3493 3494 rc = SQLProcedureColumns(result->stmt, 3495 cat, SAFE_SQL_NTS(cat), 3496 schema, SAFE_SQL_NTS(schema), 3497 proc, SAFE_SQL_NTS(proc), 3498 col, SAFE_SQL_NTS(col) ); 3499 3500 if (rc == SQL_ERROR) { 3501 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLProcedureColumns"); 3502 efree(result); 3503 RETURN_FALSE; 3504 } 3505 3506 result->numparams = 0; 3507 SQLNumResultCols(result->stmt, &(result->numcols)); 3508 3509 if (result->numcols > 0) { 3510 if (!odbc_bindcols(result TSRMLS_CC)) { 3511 efree(result); 3512 RETURN_FALSE; 3513 } 3514 } else { 3515 result->values = NULL; 3516 } 3517 result->conn_ptr = conn; 3518 result->fetched = 0; 3519 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3520} 3521/* }}} */ 3522#endif /* HAVE_SOLID */ 3523 3524#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) 3525/* {{{ proto resource odbc_procedures(resource connection_id [, string qualifier, string owner, string name]) 3526 Returns a result identifier containg the list of procedure names in a datasource */ 3527PHP_FUNCTION(odbc_procedures) 3528{ 3529 zval *pv_conn; 3530 odbc_result *result = NULL; 3531 odbc_connection *conn; 3532 char *cat = NULL, *schema = NULL, *proc = NULL; 3533 int cat_len = 0, schema_len = 0, proc_len = 0; 3534 RETCODE rc; 3535 3536 if (ZEND_NUM_ARGS() != 1 && ZEND_NUM_ARGS() != 4) { 3537 WRONG_PARAM_COUNT; 3538 } 3539 3540 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &proc, &proc_len) == FAILURE) { 3541 return; 3542 } 3543 3544 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3545 3546 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3547 3548 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3549 if (rc == SQL_INVALID_HANDLE) { 3550 efree(result); 3551 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3552 RETURN_FALSE; 3553 } 3554 3555 if (rc == SQL_ERROR) { 3556 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3557 efree(result); 3558 RETURN_FALSE; 3559 } 3560 3561 rc = SQLProcedures(result->stmt, 3562 cat, SAFE_SQL_NTS(cat), 3563 schema, SAFE_SQL_NTS(schema), 3564 proc, SAFE_SQL_NTS(proc) ); 3565 3566 if (rc == SQL_ERROR) { 3567 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLProcedures"); 3568 efree(result); 3569 RETURN_FALSE; 3570 } 3571 3572 result->numparams = 0; 3573 SQLNumResultCols(result->stmt, &(result->numcols)); 3574 3575 if (result->numcols > 0) { 3576 if (!odbc_bindcols(result TSRMLS_CC)) { 3577 efree(result); 3578 RETURN_FALSE; 3579 } 3580 } else { 3581 result->values = NULL; 3582 } 3583 result->conn_ptr = conn; 3584 result->fetched = 0; 3585 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3586} 3587/* }}} */ 3588#endif /* HAVE_SOLID */ 3589 3590/* {{{ proto resource odbc_specialcolumns(resource connection_id, int type, string qualifier, string owner, string table, int scope, int nullable) 3591 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 */ 3592PHP_FUNCTION(odbc_specialcolumns) 3593{ 3594 zval *pv_conn; 3595 long vtype, vscope, vnullable; 3596 odbc_result *result = NULL; 3597 odbc_connection *conn; 3598 char *cat = NULL, *schema = NULL, *name = NULL; 3599 int cat_len = 0, schema_len, name_len; 3600 SQLUSMALLINT type, scope, nullable; 3601 RETCODE rc; 3602 3603 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls!ssll", &pv_conn, &vtype, &cat, &cat_len, &schema, &schema_len, 3604 &name, &name_len, &vscope, &vnullable) == FAILURE) { 3605 return; 3606 } 3607 3608 type = (SQLUSMALLINT) vtype; 3609 scope = (SQLUSMALLINT) vscope; 3610 nullable = (SQLUSMALLINT) vnullable; 3611 3612 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3613 3614 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3615 3616 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3617 if (rc == SQL_INVALID_HANDLE) { 3618 efree(result); 3619 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3620 RETURN_FALSE; 3621 } 3622 3623 if (rc == SQL_ERROR) { 3624 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3625 efree(result); 3626 RETURN_FALSE; 3627 } 3628 3629 rc = SQLSpecialColumns(result->stmt, 3630 type, 3631 cat, SAFE_SQL_NTS(cat), 3632 schema, SAFE_SQL_NTS(schema), 3633 name, SAFE_SQL_NTS(name), 3634 scope, 3635 nullable); 3636 3637 if (rc == SQL_ERROR) { 3638 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLSpecialColumns"); 3639 efree(result); 3640 RETURN_FALSE; 3641 } 3642 3643 result->numparams = 0; 3644 SQLNumResultCols(result->stmt, &(result->numcols)); 3645 3646 if (result->numcols > 0) { 3647 if (!odbc_bindcols(result TSRMLS_CC)) { 3648 efree(result); 3649 RETURN_FALSE; 3650 } 3651 } else { 3652 result->values = NULL; 3653 } 3654 result->conn_ptr = conn; 3655 result->fetched = 0; 3656 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3657} 3658/* }}} */ 3659 3660/* {{{ proto resource odbc_statistics(resource connection_id, string qualifier, string owner, string name, int unique, int accuracy) 3661 Returns a result identifier that contains statistics about a single table and the indexes associated with the table */ 3662PHP_FUNCTION(odbc_statistics) 3663{ 3664 zval *pv_conn; 3665 long vunique, vreserved; 3666 odbc_result *result = NULL; 3667 odbc_connection *conn; 3668 char *cat = NULL, *schema, *name; 3669 int cat_len = 0, schema_len, name_len; 3670 SQLUSMALLINT unique, reserved; 3671 RETCODE rc; 3672 3673 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!ssll", &pv_conn, &cat, &cat_len, &schema, &schema_len, 3674 &name, &name_len, &vunique, &vreserved) == FAILURE) { 3675 return; 3676 } 3677 3678 unique = (SQLUSMALLINT) vunique; 3679 reserved = (SQLUSMALLINT) vreserved; 3680 3681 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3682 3683 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3684 3685 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3686 if (rc == SQL_INVALID_HANDLE) { 3687 efree(result); 3688 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3689 RETURN_FALSE; 3690 } 3691 3692 if (rc == SQL_ERROR) { 3693 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3694 efree(result); 3695 RETURN_FALSE; 3696 } 3697 3698 rc = SQLStatistics(result->stmt, 3699 cat, SAFE_SQL_NTS(cat), 3700 schema, SAFE_SQL_NTS(schema), 3701 name, SAFE_SQL_NTS(name), 3702 unique, 3703 reserved); 3704 3705 if (rc == SQL_ERROR) { 3706 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLStatistics"); 3707 efree(result); 3708 RETURN_FALSE; 3709 } 3710 3711 result->numparams = 0; 3712 SQLNumResultCols(result->stmt, &(result->numcols)); 3713 3714 if (result->numcols > 0) { 3715 if (!odbc_bindcols(result TSRMLS_CC)) { 3716 efree(result); 3717 RETURN_FALSE; 3718 } 3719 } else { 3720 result->values = NULL; 3721 } 3722 result->conn_ptr = conn; 3723 result->fetched = 0; 3724 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3725} 3726/* }}} */ 3727 3728#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP) 3729/* {{{ proto resource odbc_tableprivileges(resource connection_id, string qualifier, string owner, string name) 3730 Returns a result identifier containing a list of tables and the privileges associated with each table */ 3731PHP_FUNCTION(odbc_tableprivileges) 3732{ 3733 zval *pv_conn; 3734 odbc_result *result = NULL; 3735 odbc_connection *conn; 3736 char *cat = NULL, *schema = NULL, *table = NULL; 3737 int cat_len = 0, schema_len, table_len; 3738 RETCODE rc; 3739 3740 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) { 3741 return; 3742 } 3743 3744 ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn); 3745 3746 result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); 3747 3748 rc = SQLAllocStmt(conn->hdbc, &(result->stmt)); 3749 if (rc == SQL_INVALID_HANDLE) { 3750 efree(result); 3751 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); 3752 RETURN_FALSE; 3753 } 3754 3755 if (rc == SQL_ERROR) { 3756 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt"); 3757 efree(result); 3758 RETURN_FALSE; 3759 } 3760 3761 rc = SQLTablePrivileges(result->stmt, 3762 cat, SAFE_SQL_NTS(cat), 3763 schema, SAFE_SQL_NTS(schema), 3764 table, SAFE_SQL_NTS(table)); 3765 3766 if (rc == SQL_ERROR) { 3767 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTablePrivileges"); 3768 efree(result); 3769 RETURN_FALSE; 3770 } 3771 3772 result->numparams = 0; 3773 SQLNumResultCols(result->stmt, &(result->numcols)); 3774 3775 if (result->numcols > 0) { 3776 if (!odbc_bindcols(result TSRMLS_CC)) { 3777 efree(result); 3778 RETURN_FALSE; 3779 } 3780 } else { 3781 result->values = NULL; 3782 } 3783 result->conn_ptr = conn; 3784 result->fetched = 0; 3785 ZEND_REGISTER_RESOURCE(return_value, result, le_result); 3786} 3787/* }}} */ 3788#endif /* HAVE_DBMAKER */ 3789 3790#endif /* HAVE_UODBC */ 3791 3792/* 3793 * Local variables: 3794 * tab-width: 4 3795 * c-basic-offset: 4 3796 * End: 3797 * vim600: sw=4 ts=4 fdm=marker 3798 * vim<600: sw=4 ts=4 3799 */ 3800