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