php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
php_odbc.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Stig Sæther Bakken <ssb@php.net> |
14 | Andreas Karajannis <Andreas.Karajannis@gmd.de> |
15 | Frank M. Kromann <frank@kromann.info> Support for DB/2 CLI |
16 | Kevin N. Shallow <kshallow@tampabay.rr.com> |
17 | Daniel R. Kalowsky <kalowsky@php.net> |
18 +----------------------------------------------------------------------+
19*/
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25#include "php.h"
26#include "php_globals.h"
27#include "zend_attributes.h"
28
29#include "ext/standard/info.h"
31#include "zend_smart_str.h"
32
33#include "php_odbc.h"
34#include "php_odbc_includes.h"
35
36/* actually lives in main/ */
37#include "php_odbc_utils.h"
38
39#ifdef HAVE_UODBC
40
41#include <fcntl.h>
42#include "php_ini.h"
43
44#define PHP_ODBC_BINMODE_PASSTHRU 0
45#define PHP_ODBC_BINMODE_RETURN 1
46#define PHP_ODBC_BINMODE_CONVERT 2
47
48#include "odbc_arginfo.h"
49
50#define CHECK_ODBC_CONNECTION(conn) \
51 if (conn == NULL) { \
52 zend_throw_error(NULL, "ODBC connection has already been closed"); \
53 RETURN_THROWS(); \
54 }
55
56#define CHECK_ODBC_RESULT(result) \
57 if (result->conn_ptr == NULL) { \
58 zend_throw_error(NULL, "ODBC result has already been closed"); \
59 RETURN_THROWS(); \
60 }
61
62void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent);
63static void safe_odbc_disconnect(void *handle);
64static void close_results_with_connection(odbc_connection *conn);
65static inline odbc_result *odbc_result_from_obj(zend_object *obj);
66
67static int le_pconn;
68
69static zend_class_entry *odbc_connection_ce, *odbc_result_ce;
70static zend_object_handlers odbc_connection_object_handlers, odbc_result_object_handlers;
71
72#define Z_ODBC_LINK_P(zv) odbc_link_from_obj(Z_OBJ_P(zv))
73#define Z_ODBC_CONNECTION_P(zv) Z_ODBC_LINK_P(zv)->connection
74#define Z_ODBC_RESULT_P(zv) odbc_result_from_obj(Z_OBJ_P(zv))
75
76static void odbc_insert_new_result(odbc_connection *connection, zval *result)
77{
79#if ZEND_DEBUG
80 ZEND_ASSERT(instanceof_function(Z_OBJCE_P(result), odbc_result_ce));
81#endif
82
83 odbc_result *res = Z_ODBC_RESULT_P(result);
84
85 res->index = connection->results.nNextFreeElement;
86 zend_hash_index_add_new(&connection->results, res->index, result);
88}
89
90static inline odbc_link *odbc_link_from_obj(zend_object *obj)
91{
92 return (odbc_link *)((char *)(obj) - XtOffsetOf(odbc_link, std));
93}
94
95static int _close_pconn_with_res(zval *zv, void *p)
96{
98
99 if (le->ptr == p) {
101 }
102
104}
105
106static int _close_pconn(zval *zv)
107{
108 zend_resource *le = Z_RES_P(zv);
109 if (le->type == le_pconn) {
111 } else {
113 }
114}
115
116/* disconnect, and if it fails, then issue a rollback for any pending transaction (lurcher) */
117static void safe_odbc_disconnect( void *handle )
118{
119 int ret = SQLDisconnect( handle );
120
121 if ( ret == SQL_ERROR )
122 {
123 SQLTransact( NULL, handle, SQL_ROLLBACK );
124 SQLDisconnect( handle );
125 }
126}
127
128static void free_connection(odbc_connection *conn, bool persistent)
129{
130 /* If aborted via timer expiration, don't try to call any unixODBC function */
132 safe_odbc_disconnect(conn->hdbc);
133 SQLFreeConnect(conn->hdbc);
134 SQLFreeEnv(conn->henv);
135 }
136
137 conn->hdbc = NULL;
138 conn->henv = NULL;
139
140 zend_hash_destroy(&conn->results);
141
142 pefree(conn, persistent);
143
144 ODBCG(num_links)--;
145 if (persistent) {
146 ODBCG(num_persistent)--;
147 }
148}
149
150static void odbc_link_free(odbc_link *link)
151{
152 ZEND_ASSERT(link->connection && "link has already been closed");
153
154 close_results_with_connection(link->connection);
155
156 if (!link->persistent) {
157 free_connection(link->connection, link->persistent);
158 }
159
160 link->connection = NULL;
161
162 if (link->hash) {
163 zend_hash_del(&ODBCG(connections), link->hash);
164 zend_string_release_ex(link->hash, link->persistent);
165 link->hash = NULL;
166 }
167}
168
169static zend_object *odbc_connection_create_object(zend_class_entry *class_type)
170{
171 odbc_link *intern = zend_object_alloc(sizeof(odbc_link), class_type);
172
173 zend_object_std_init(&intern->std, class_type);
174 object_properties_init(&intern->std, class_type);
175
176 return &intern->std;
177}
178
179static zend_function *odbc_connection_get_constructor(zend_object *object)
180{
181 zend_throw_error(NULL, "Cannot directly construct Odbc\\Connection, use odbc_connect() or odbc_pconnect() instead");
182 return NULL;
183}
184
185static zend_result odbc_connection_cast_object(zend_object *obj, zval *result, int type)
186{
187 if (type == IS_LONG) {
188 ZVAL_LONG(result, obj->handle);
189
190 return SUCCESS;
191 }
192
194}
195
196static void odbc_connection_free_obj(zend_object *obj)
197{
198 odbc_link *link = odbc_link_from_obj(obj);
199
200 if (link->connection) {
201 odbc_link_free(link);
202 }
203
205}
206
207static inline odbc_result *odbc_result_from_obj(zend_object *obj)
208{
209 return (odbc_result *)((char *)(obj) - XtOffsetOf(odbc_result, std));
210}
211
212static zend_object *odbc_result_create_object(zend_class_entry *class_type)
213{
214 odbc_result *intern = zend_object_alloc(sizeof(odbc_result), class_type);
215
216 zend_object_std_init(&intern->std, class_type);
217 object_properties_init(&intern->std, class_type);
218
219 return &intern->std;
220}
221
222static zend_function *odbc_result_get_constructor(zend_object *object)
223{
224 zend_throw_error(NULL, "Cannot directly construct Odbc\\Result, use an appropriate odbc_* function instead");
225 return NULL;
226}
227
228static zend_result odbc_result_cast_object(zend_object *obj, zval *result, int type)
229{
230 if (type == IS_LONG) {
231 ZVAL_LONG(result, obj->handle);
232
233 return SUCCESS;
234 }
235
237}
238
239static void odbc_result_free(odbc_result *res)
240{
241 ZEND_ASSERT(res->conn_ptr && "result has already been closed");
242
243 if (res->values) {
244 for (int i = 0; i < res->numcols; i++) {
245 if (res->values[i].value) {
246 efree(res->values[i].value);
247 }
248 }
249 efree(res->values);
250 res->values = NULL;
251 res->numcols = 0;
252 }
253
254 /* If aborted via timer expiration, don't try to call any unixODBC function */
255 if (res->stmt && !(PG(connection_status) & PHP_CONNECTION_TIMEOUT)) {
256#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35)
257 SQLTransact(res->conn_ptr->henv, res->conn_ptr->hdbc,
258 (SQLUSMALLINT) SQL_COMMIT);
259#endif
260 SQLFreeStmt(res->stmt,SQL_DROP);
261 /* We don't want the connection to be closed after the last statement has been closed
262 * Connections will be closed on shutdown
263 */
264 res->stmt = NULL;
265 }
266 if (res->param_info) {
267 efree(res->param_info);
268 res->param_info = NULL;
269 }
270
271 HashTable *results = &res->conn_ptr->results;
272 res->conn_ptr = NULL;
273 zend_result status = zend_hash_index_del(results, res->index);
275}
276
277static void odbc_result_free_obj(zend_object *obj)
278{
279 odbc_result *result = odbc_result_from_obj(obj);
280
281 if (result->conn_ptr) {
282 odbc_result_free(result);
283 }
284
286}
287
288#define SAFE_SQL_NTS(n) ((SQLSMALLINT) ((n)?(SQL_NTS):0))
289
290PHP_ODBC_API ZEND_DECLARE_MODULE_GLOBALS(odbc)
291static PHP_GINIT_FUNCTION(odbc);
292static PHP_GSHUTDOWN_FUNCTION(odbc);
293
294/* {{{ odbc_module_entry */
295zend_module_entry odbc_module_entry = {
297 "odbc",
298 ext_functions,
299 PHP_MINIT(odbc),
300 PHP_MSHUTDOWN(odbc),
301 PHP_RINIT(odbc),
302 PHP_RSHUTDOWN(odbc),
303 PHP_MINFO(odbc),
304 PHP_ODBC_VERSION,
305 PHP_MODULE_GLOBALS(odbc),
306 PHP_GINIT(odbc),
307 PHP_GSHUTDOWN(odbc),
308 NULL,
310};
311/* }}} */
312
313#ifdef COMPILE_DL_ODBC
314#ifdef ZTS
316#endif
317ZEND_GET_MODULE(odbc)
318#endif
319
320static void close_results_with_connection(odbc_connection *conn)
321{
322 zval *p;
323
324 ZEND_HASH_FOREACH_VAL(&conn->results, p) {
325 odbc_result *result = Z_ODBC_RESULT_P(p);
326 if (result->conn_ptr) {
327 odbc_result_free(result);
328 }
330
331 zend_hash_clean(&conn->results);
332}
333
334/* {{{ void _close_odbc_pconn */
335static void _close_odbc_pconn(zend_resource *rsrc)
336{
337 odbc_connection *conn = (odbc_connection *)rsrc->ptr;
338
339 close_results_with_connection(conn);
340 free_connection(conn, true);
341
342 rsrc->ptr = NULL;
343}
344/* }}} */
345
346/* {{{ PHP_INI_DISP(display_link_nums) */
347static PHP_INI_DISP(display_link_nums)
348{
349 char *value;
350
351 if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
352 value = ZSTR_VAL(ini_entry->orig_value);
353 } else if (ini_entry->value) {
354 value = ZSTR_VAL(ini_entry->value);
355 } else {
356 value = NULL;
357 }
358
359 if (value) {
360 if (atoi(value) == -1) {
361 PUTS("Unlimited");
362 } else {
363 php_printf("%s", value);
364 }
365 }
366}
367/* }}} */
368
369/* {{{ PHP_INI_DISP(display_binmode) */
370static PHP_INI_DISP(display_binmode)
371{
372 char *value;
373
374 if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
375 value = ZSTR_VAL(ini_entry->orig_value);
376 } else if (ini_entry->value) {
377 value = ZSTR_VAL(ini_entry->value);
378 } else {
379 value = NULL;
380 }
381
382 if (value) {
383 switch(atoi(value)) {
384 case 0:
385 PUTS("passthru");
386 break;
387 case 1:
388 PUTS("return as is");
389 break;
390 case 2:
391 PUTS("return as char");
392 break;
393 }
394 }
395}
396/* }}} */
397
398/* {{{ PHP_INI_DISP(display_lrl) */
399static PHP_INI_DISP(display_lrl)
400{
401 char *value;
402
403 if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
404 value = ZSTR_VAL(ini_entry->orig_value);
405 } else if (ini_entry->value) {
406 value = ZSTR_VAL(ini_entry->value);
407 } else {
408 value = NULL;
409 }
410
411 if (value) {
412 if (atoi(value) <= 0) {
413 PUTS("Passthru");
414 } else {
415 php_printf("return up to %s bytes", value);
416 }
417 }
418}
419/* }}} */
420
421
422/* {{{ PHP_INI_DISP(display_cursortype) */
423static PHP_INI_DISP(display_cursortype)
424{
425 char *value;
426
427 if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
428 value = ZSTR_VAL(ini_entry->orig_value);
429 } else if (ini_entry->value) {
430 value = ZSTR_VAL(ini_entry->value);
431 } else {
432 value = NULL;
433 }
434
435 if (value) {
436 switch (atoi (value))
437 {
439 PUTS ("Forward Only cursor");
440 break;
441
443 PUTS ("Static cursor");
444 break;
445
447 PUTS ("Keyset driven cursor");
448 break;
449
451 PUTS ("Dynamic cursor");
452 break;
453
454 default:
455 php_printf("Unknown cursor model %s", value);
456 break;
457 }
458 }
459}
460
461/* }}} */
462
463/* {{{ PHP_INI_BEGIN */
465 STD_PHP_INI_BOOLEAN("odbc.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool,
466 allow_persistent, zend_odbc_globals, odbc_globals)
467 STD_PHP_INI_ENTRY_EX("odbc.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong,
468 max_persistent, zend_odbc_globals, odbc_globals, display_link_nums)
469 STD_PHP_INI_ENTRY_EX("odbc.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong,
470 max_links, zend_odbc_globals, odbc_globals, display_link_nums)
471 STD_PHP_INI_ENTRY_EX("odbc.defaultlrl", "4096", PHP_INI_ALL, OnUpdateLong,
472 defaultlrl, zend_odbc_globals, odbc_globals, display_lrl)
473 STD_PHP_INI_ENTRY_EX("odbc.defaultbinmode", "1", PHP_INI_ALL, OnUpdateLong,
474 defaultbinmode, zend_odbc_globals, odbc_globals, display_binmode)
475 STD_PHP_INI_BOOLEAN("odbc.check_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool,
476 check_persistent, zend_odbc_globals, odbc_globals)
477 STD_PHP_INI_ENTRY_EX("odbc.default_cursortype", "3", PHP_INI_ALL, OnUpdateLong,
478 default_cursortype, zend_odbc_globals, odbc_globals, display_cursortype)
480/* }}} */
481
482static PHP_GINIT_FUNCTION(odbc)
483{
484#if defined(COMPILE_DL_ODBC) && defined(ZTS)
486#endif
487 odbc_globals->num_persistent = 0;
488 zend_hash_init(&odbc_globals->connections, 0, NULL, NULL, true);
489 GC_MAKE_PERSISTENT_LOCAL(&odbc_globals->connections);
490}
491
492static PHP_GSHUTDOWN_FUNCTION(odbc)
493{
494 zend_hash_destroy(&odbc_globals->connections);
495}
496
497/* {{{ PHP_MINIT_FUNCTION */
499{
500#ifdef SQLANY_BUG
501 ODBC_SQL_CONN_T foobar;
502 RETCODE rc;
503#endif
504
506 le_pconn = zend_register_list_destructors_ex(NULL, _close_odbc_pconn, "odbc link persistent", module_number);
507 odbc_module_entry.type = type;
508
509 register_odbc_symbols(module_number);
510
511 odbc_connection_ce = register_class_Odbc_Connection();
512 odbc_connection_ce->create_object = odbc_connection_create_object;
513 odbc_connection_ce->default_object_handlers = &odbc_connection_object_handlers;
514
515 memcpy(&odbc_connection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
516 odbc_connection_object_handlers.offset = XtOffsetOf(odbc_link, std);
517 odbc_connection_object_handlers.free_obj = odbc_connection_free_obj;
518 odbc_connection_object_handlers.get_constructor = odbc_connection_get_constructor;
519 odbc_connection_object_handlers.clone_obj = NULL;
520 odbc_connection_object_handlers.cast_object = odbc_connection_cast_object;
521 odbc_connection_object_handlers.compare = zend_objects_not_comparable;
522
523 odbc_result_ce = register_class_Odbc_Result();
524 odbc_result_ce->create_object = odbc_result_create_object;
525 odbc_result_ce->default_object_handlers = &odbc_result_object_handlers;
526
527 memcpy(&odbc_result_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
528 odbc_result_object_handlers.offset = XtOffsetOf(odbc_result, std);
529 odbc_result_object_handlers.free_obj = odbc_result_free_obj;
530 odbc_result_object_handlers.get_constructor = odbc_result_get_constructor;
531 odbc_result_object_handlers.clone_obj = NULL;
532 odbc_result_object_handlers.cast_object = odbc_result_cast_object;
533 odbc_result_object_handlers.compare = zend_objects_not_comparable;
534
535#if defined(HAVE_IBMDB2) && defined(_AIX)
536 /* atexit() handler in the DB2/AIX library segfaults in PHP CLI */
537 /* DB2NOEXITLIST env variable prevents DB2 from invoking atexit() */
538 putenv("DB2NOEXITLIST=TRUE");
539#endif
540
541 return SUCCESS;
542}
543/* }}} */
544
545/* {{{ PHP_RINIT_FUNCTION */
547{
548 ODBCG(defConn) = -1;
549 ODBCG(num_links) = ODBCG(num_persistent);
550 memset(ODBCG(laststate), '\0', 6);
551 memset(ODBCG(lasterrormsg), '\0', SQL_MAX_MESSAGE_LENGTH);
552 return SUCCESS;
553}
554/* }}} */
555
556/* {{{ PHP_RSHUTDOWN_FUNCTION */
558{
559 return SUCCESS;
560}
561/* }}} */
562
563/* {{{ PHP_MSHUTDOWN_FUNCTION */
565{
567 return SUCCESS;
568}
569/* }}} */
570
571/* {{{ PHP_MINFO_FUNCTION */
573{
574 char buf[32];
575
577 php_info_print_table_row(2, "ODBC Support", "enabled");
578 snprintf(buf, sizeof(buf), ZEND_LONG_FMT, ODBCG(num_persistent));
579 php_info_print_table_row(2, "Active Persistent Links", buf);
580 snprintf(buf, sizeof(buf), ZEND_LONG_FMT, ODBCG(num_links));
581 php_info_print_table_row(2, "Active Links", buf);
582 php_info_print_table_row(2, "ODBC library", PHP_ODBC_TYPE);
583#ifdef ODBCVER
584 snprintf(buf, sizeof(buf), "0x%.4x", ODBCVER);
585 php_info_print_table_row(2, "ODBCVER", buf);
586#endif
587#ifndef PHP_WIN32
588 php_info_print_table_row(2, "ODBC_CFLAGS", PHP_ODBC_CFLAGS);
589 php_info_print_table_row(2, "ODBC_LFLAGS", PHP_ODBC_LFLAGS);
590 php_info_print_table_row(2, "ODBC_LIBS", PHP_ODBC_LIBS);
591#endif
593
595
596}
597/* }}} */
598
599/* {{{ odbc_sql_error */
600void odbc_sql_error(ODBC_SQL_ERROR_PARAMS)
601{
602 SQLINTEGER error; /* Not used */
603 SQLSMALLINT errormsgsize; /* Not used */
604 RETCODE rc;
605 ODBC_SQL_ENV_T henv;
606 ODBC_SQL_CONN_T conn;
607
608 if (conn_resource) {
609 henv = conn_resource->henv;
610 conn = conn_resource->hdbc;
611 } else {
612 henv = SQL_NULL_HENV;
613 conn = SQL_NULL_HDBC;
614 }
615
616 /* This leads to an endless loop in many drivers!
617 *
618 while(henv != SQL_NULL_HENV){
619 do {
620 */
621 rc = SQLError(henv, conn, stmt, (SQLCHAR *) ODBCG(laststate), &error, (SQLCHAR *) ODBCG(lasterrormsg), sizeof(ODBCG(lasterrormsg))-1, &errormsgsize);
622 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
623 snprintf(ODBCG(laststate), sizeof(ODBCG(laststate)), "HY000");
624 snprintf(ODBCG(lasterrormsg), sizeof(ODBCG(lasterrormsg)), "Failed to fetch error message");
625 }
626 if (conn_resource) {
627 memcpy(conn_resource->laststate, ODBCG(laststate), sizeof(ODBCG(laststate)));
628 memcpy(conn_resource->lasterrormsg, ODBCG(lasterrormsg), sizeof(ODBCG(lasterrormsg)));
629 }
630 if (func) {
631 php_error_docref(NULL, E_WARNING, "SQL error: %s, SQL state %s in %s", ODBCG(lasterrormsg), ODBCG(laststate), func);
632 } else {
633 php_error_docref(NULL, E_WARNING, "SQL error: %s, SQL state %s", ODBCG(lasterrormsg), ODBCG(laststate));
634 }
635 /*
636 } while (SQL_SUCCEEDED(rc));
637 }
638 */
639}
640/* }}} */
641
642/* {{{ php_odbc_fetch_attribs */
643void php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAMETERS, int mode)
644{
646 zval *pv_res;
647 zend_long flag;
648
649 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &pv_res, odbc_result_ce, &flag) == FAILURE) {
651 }
652
653 result = Z_ODBC_RESULT_P(pv_res);
654 CHECK_ODBC_RESULT(result);
655
656 if (mode) {
657 result->longreadlen = flag;
658 } else {
659 result->binmode = flag;
660 }
661
663}
664/* }}} */
665
666/* {{{ odbc_bindcols */
667void odbc_bindcols(odbc_result *result)
668{
669 RETCODE rc;
670 int i;
671 SQLSMALLINT colnamelen; /* Not used */
672 SQLLEN displaysize;
673 SQLUSMALLINT colfieldid;
674 int charextraalloc;
675
676 result->values = (odbc_result_value *) safe_emalloc(sizeof(odbc_result_value), result->numcols, 0);
677
678 result->longreadlen = ODBCG(defaultlrl);
679 result->binmode = ODBCG(defaultbinmode);
680
681 for(i = 0; i < result->numcols; i++) {
682 charextraalloc = 0;
683 colfieldid = SQL_COLUMN_DISPLAY_SIZE;
684
685 rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), PHP_ODBC_SQL_DESC_NAME,
686 result->values[i].name, sizeof(result->values[i].name), &colnamelen, 0);
687 result->values[i].coltype = 0;
688 rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_TYPE,
689 NULL, 0, NULL, &result->values[i].coltype);
690
691 /* Don't bind LONG / BINARY columns, so that fetch behaviour can
692 * be controlled by odbc_binmode() / odbc_longreadlen()
693 */
694
695 switch(result->values[i].coltype) {
696 case SQL_BINARY:
697 case SQL_VARBINARY:
699 case SQL_LONGVARCHAR:
700#if defined(ODBCVER) && (ODBCVER >= 0x0300)
701 case SQL_WLONGVARCHAR:
702#endif
703 result->values[i].value = NULL;
704 break;
705
706#ifdef HAVE_ADABAS
707 case SQL_TIMESTAMP:
708 result->values[i].value = (char *)emalloc(27);
709 SQLBindCol(result->stmt, (SQLUSMALLINT)(i+1), SQL_C_CHAR, result->values[i].value,
710 27, &result->values[i].vallen);
711 break;
712#endif /* HAVE_ADABAS */
713 case SQL_CHAR:
714 case SQL_VARCHAR:
715#if defined(ODBCVER) && (ODBCVER >= 0x0300)
716 case SQL_WCHAR:
717 case SQL_WVARCHAR:
718 colfieldid = SQL_DESC_OCTET_LENGTH;
719#else
720 charextraalloc = 1;
721#endif
722 /* TODO: Check this is the intended behaviour */
724 default:
725 rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), colfieldid,
726 NULL, 0, NULL, &displaysize);
727 if (rc != SQL_SUCCESS) {
728 displaysize = 0;
729 }
730#if defined(ODBCVER) && (ODBCVER >= 0x0300)
731 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && colfieldid == SQL_DESC_OCTET_LENGTH) {
732 SQLINTEGER err;
733 SQLCHAR errtxt[128];
734 SQLCHAR state[6];
735
736 memset(errtxt, '\0', 128);
737 memset(state, '\0', 6);
738
739 if (SQL_SUCCESS == SQLGetDiagRec(SQL_HANDLE_STMT, result->stmt, 1, state, &err, errtxt, 128, NULL)) {
740 errtxt[127] = '\0';
741 state[5] = '\0';
742 php_error_docref(NULL, E_WARNING, "SQLColAttribute can't handle SQL_DESC_OCTET_LENGTH: [%s] %s", state, errtxt);
743 }
744 /* This is a quirk for ODBC 2.0 compatibility for broken driver implementations.
745 */
746 charextraalloc = 1;
747 rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_DISPLAY_SIZE,
748 NULL, 0, NULL, &displaysize);
749 if (rc != SQL_SUCCESS) {
750 displaysize = 0;
751 }
752 }
753
754 /* Workaround for drivers that report NVARCHAR(MAX) columns as SQL_WVARCHAR with size 0 (bug #69975) */
755 if (result->values[i].coltype == SQL_WVARCHAR && displaysize == 0) {
756 result->values[i].coltype = SQL_WLONGVARCHAR;
757 result->values[i].value = NULL;
758 break;
759 }
760#endif
761 /* Workaround for drivers that report VARCHAR(MAX) columns as SQL_VARCHAR (bug #73725) */
762 if (SQL_VARCHAR == result->values[i].coltype && displaysize == 0) {
763 result->values[i].coltype = SQL_LONGVARCHAR;
764 result->values[i].value = NULL;
765 break;
766 }
767
768 /* Workaround for Oracle ODBC Driver bug (#50162) when fetching TIMESTAMP column */
769 if (result->values[i].coltype == SQL_TIMESTAMP) {
770 displaysize += 3;
771 }
772
773 if (charextraalloc) {
774 /* Since we don't know the exact # of bytes, allocate extra */
775 displaysize *= 4;
776 }
777 result->values[i].value = (char *)emalloc(displaysize + 1);
778 rc = SQLBindCol(result->stmt, (SQLUSMALLINT)(i+1), SQL_C_CHAR, result->values[i].value,
779 displaysize + 1, &result->values[i].vallen);
780 break;
781 }
782 }
783}
784/* }}} */
785
786/* {{{ odbc_transact */
787void odbc_transact(INTERNAL_FUNCTION_PARAMETERS, int type)
788{
789 RETCODE rc;
790 zval *pv_conn;
791
792 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_conn, odbc_connection_ce) == FAILURE) {
794 }
795
796 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
797 CHECK_ODBC_CONNECTION(conn);
798
799 rc = SQLTransact(conn->henv, conn->hdbc, (SQLUSMALLINT)((type)?SQL_COMMIT:SQL_ROLLBACK));
800 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
801 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTransact");
803 }
804
806}
807/* }}} */
808
809/* {{{ odbc_column_lengths */
810void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type)
811{
813#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30)
814 /* this seems to be necessary for Solid2.3 ( tested by
815 * tammy@synchronis.com) and Solid 3.0 (tested by eric@terra.telemediair.nl)
816 * Solid does not seem to declare a SQLINTEGER, but it does declare a
817 * SQL_INTEGER which does not work (despite being the same type as a SDWORD.
818 * Solid 3.5 does not have this issue.
819 */
820 SDWORD len;
821#else
822 SQLLEN len;
823#endif
824 zval *pv_res;
825 zend_long pv_num;
826
827 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &pv_res, odbc_result_ce, &pv_num) == FAILURE) {
829 }
830
831 result = Z_ODBC_RESULT_P(pv_res);
832 CHECK_ODBC_RESULT(result);
833
834 if (pv_num < 1) {
835 zend_argument_value_error(2, "must be greater than 0");
837 }
838
839 if (result->numcols == 0) {
840 php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
842 }
843
844 if (pv_num > result->numcols) {
845 php_error_docref(NULL, E_WARNING, "Field index larger than number of fields");
847 }
848
849 PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len);
850
852}
853/* }}} */
854
855/* Main User Functions */
856
857/* {{{ Close all ODBC connections */
859{
860 zval *zv;
861
864 }
865
866 /* Loop through the link list, now close all links and their results */
867 ZEND_HASH_FOREACH_VAL(&ODBCG(connections), zv) {
868 odbc_link *link = Z_ODBC_LINK_P(zv);
869 if (link->connection) {
870 odbc_link_free(link);
871 }
873
874 zend_hash_clean(&ODBCG(connections));
875
876 zend_hash_apply(&EG(persistent_list), _close_pconn);
877}
878/* }}} */
879
880/* {{{ Handle binary column data */
882{
883 php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
884}
885/* }}} */
886
887/* {{{ Handle LONG columns */
889{
890 php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
891}
892/* }}} */
893
894/* {{{ Prepares a statement for execution */
896{
897 zval *pv_conn;
898 char *query;
899 size_t query_len;
901 RETCODE rc;
902 int i;
903#ifdef HAVE_SQL_EXTENDED_FETCH
904 SQLUINTEGER scrollopts;
905#endif
906
907 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &pv_conn, odbc_connection_ce, &query, &query_len) == FAILURE) {
909 }
910
911 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
912 CHECK_ODBC_CONNECTION(conn);
913
914 object_init_ex(return_value, odbc_result_ce);
915 result = Z_ODBC_RESULT_P(return_value);
916
917 result->numparams = 0;
918 result->param_info = NULL;
919
920 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
921 if (rc == SQL_INVALID_HANDLE) {
922 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
925 }
926
927 if (rc == SQL_ERROR) {
928 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
931 }
932
933#ifdef HAVE_SQL_EXTENDED_FETCH
934 /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info,
935 whether Driver supports ExtendedFetch */
936 rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL);
937 if (rc == SQL_SUCCESS) {
938 if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) {
939 /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other
940 type if not possible.
941 */
942 SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype));
943 }
944 } else {
945 result->fetch_abs = 0;
946 }
947#endif
948
949 rc = SQLPrepare(result->stmt, (SQLCHAR *) query, SQL_NTS);
950 switch (rc) {
951 case SQL_SUCCESS:
952 break;
953 case SQL_SUCCESS_WITH_INFO:
954 odbc_sql_error(conn, result->stmt, "SQLPrepare");
955 break;
956 default:
957 odbc_sql_error(conn, result->stmt, "SQLPrepare");
960 }
961
962 SQLNumParams(result->stmt, &(result->numparams));
963 SQLNumResultCols(result->stmt, &(result->numcols));
964
965 if (result->numcols > 0) {
966 odbc_bindcols(result);
967 } else {
968 result->values = NULL;
969 }
970 result->conn_ptr = conn;
971 result->fetched = 0;
972
973 result->param_info = (odbc_param_info *) safe_emalloc(sizeof(odbc_param_info), result->numparams, 0);
974 for (i=0;i<result->numparams;i++) {
975 rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)(i+1), &result->param_info[i].sqltype, &result->param_info[i].precision,
976 &result->param_info[i].scale, &result->param_info[i].nullable);
977 if (rc == SQL_ERROR) {
978 odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParameter");
979 SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
980 efree(result->param_info);
983 }
984 }
985
986 odbc_insert_new_result(conn, return_value);
987}
988/* }}} */
989
990/*
991 * Execute prepared SQL statement. Supports only input parameters.
992 */
993
994typedef struct odbc_params_t {
995 SQLLEN vallen;
996 int fp;
997 zend_string *zstr;
998} odbc_params_t;
999
1000static void odbc_release_params(odbc_result *result, odbc_params_t *params) {
1001 SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
1002 for (int i = 0; i < result->numparams; i++) {
1003 if (params[i].fp != -1) {
1004 close(params[i].fp);
1005 }
1006 if (params[i].zstr) {
1007 zend_string_release(params[i].zstr);
1008 }
1009 }
1010 efree(params);
1011}
1012
1013/* {{{ Execute a prepared statement */
1015{
1016 zval *pv_res, *tmp;
1017 HashTable *pv_param_ht = (HashTable *) &zend_empty_array;
1018 odbc_params_t *params = NULL;
1019 char *filename;
1020 SQLSMALLINT ctype;
1022 int i, ne;
1023 RETCODE rc;
1024
1025 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|h", &pv_res, odbc_result_ce, &pv_param_ht) == FAILURE) {
1026 RETURN_THROWS();
1027 }
1028
1029 result = Z_ODBC_RESULT_P(pv_res);
1030 CHECK_ODBC_RESULT(result);
1031
1032 if (result->numparams > 0) {
1033 if ((ne = zend_hash_num_elements(pv_param_ht)) < result->numparams) {
1034 php_error_docref(NULL, E_WARNING, "Not enough parameters (%d should be %d) given", ne, result->numparams);
1036 }
1037
1038 params = (odbc_params_t *)safe_emalloc(sizeof(odbc_params_t), result->numparams, 0);
1039 for(i = 0; i < result->numparams; i++) {
1040 params[i].fp = -1;
1041 params[i].zstr = NULL;
1042 }
1043
1044 i = 1;
1045 ZEND_HASH_FOREACH_VAL(pv_param_ht, tmp) {
1046 unsigned char otype = Z_TYPE_P(tmp);
1047 zend_string *tmpstr = zval_try_get_string(tmp);
1048 if (!tmpstr) {
1049 odbc_release_params(result, params);
1050 RETURN_THROWS();
1051 }
1052
1053 params[i-1].vallen = ZSTR_LEN(tmpstr);
1054 params[i-1].fp = -1;
1055 params[i-1].zstr = tmpstr;
1056
1057 if (IS_SQL_BINARY(result->param_info[i-1].sqltype)) {
1058 ctype = SQL_C_BINARY;
1059 } else {
1060 ctype = SQL_C_CHAR;
1061 }
1062
1063 if (ZSTR_LEN(tmpstr) > 2 &&
1064 ZSTR_VAL(tmpstr)[0] == '\'' &&
1065 ZSTR_VAL(tmpstr)[ZSTR_LEN(tmpstr) - 1] == '\'') {
1066
1067 if (ZSTR_LEN(tmpstr) != strlen(ZSTR_VAL(tmpstr))) {
1068 odbc_release_params(result, params);
1070 }
1071 filename = estrndup(&ZSTR_VAL(tmpstr)[1], ZSTR_LEN(tmpstr) - 2);
1072 filename[strlen(filename)] = '\0';
1073
1074 /* Check the basedir */
1075 if (php_check_open_basedir(filename)) {
1076 efree(filename);
1077 odbc_release_params(result, params);
1079 }
1080
1081 if ((params[i-1].fp = open(filename,O_RDONLY)) == -1) {
1082 php_error_docref(NULL, E_WARNING,"Can't open file %s", filename);
1083 odbc_release_params(result, params);
1084 efree(filename);
1086 }
1087
1088 efree(filename);
1089
1090 params[i-1].vallen = SQL_LEN_DATA_AT_EXEC(0);
1091
1092 rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
1093 ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale,
1094 (void *)(intptr_t)params[i-1].fp, 0,
1095 &params[i-1].vallen);
1096 } else {
1097#ifdef HAVE_DBMAKER
1098 precision = params[i-1].vallen;
1099#endif
1100 if (otype == IS_NULL) {
1101 params[i-1].vallen = SQL_NULL_DATA;
1102 }
1103
1104 rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
1105 ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale,
1106 ZSTR_VAL(tmpstr), 0,
1107 &params[i-1].vallen);
1108 }
1109 if (rc == SQL_ERROR) {
1110 odbc_sql_error(result->conn_ptr, result->stmt, "SQLBindParameter");
1111 odbc_release_params(result, params);
1113 }
1114 if (++i > result->numparams) break;
1116 }
1117 /* Close cursor, needed for doing multiple selects */
1118 rc = SQLFreeStmt(result->stmt, SQL_CLOSE);
1119
1120 if (rc == SQL_ERROR) {
1121 odbc_sql_error(result->conn_ptr, result->stmt, "SQLFreeStmt");
1122 }
1123
1124 result->fetched = 0;
1125 rc = SQLExecute(result->stmt);
1126 switch (rc) {
1127 case SQL_NEED_DATA: {
1128 char buf[4096];
1129 int fp, nbytes;
1130 while (rc == SQL_NEED_DATA) {
1131 rc = SQLParamData(result->stmt, (void*)&fp);
1132 if (rc == SQL_NEED_DATA) {
1133 while ((nbytes = read(fp, &buf, 4096)) > 0) {
1134 SQLPutData(result->stmt, (void*)&buf, nbytes);
1135 }
1136 }
1137 }
1138 break;
1139 }
1140 case SQL_SUCCESS:
1141 break;
1142 case SQL_NO_DATA_FOUND:
1143 case SQL_SUCCESS_WITH_INFO:
1144 odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute");
1145 break;
1146 default:
1147 odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute");
1149 }
1150
1151 if (result->numparams > 0) {
1152 odbc_release_params(result, params);
1153 }
1154
1155 if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO || rc == SQL_NO_DATA_FOUND) {
1157 }
1158
1159 if (result->numcols == 0) {
1160 SQLNumResultCols(result->stmt, &(result->numcols));
1161
1162 if (result->numcols > 0) {
1163 odbc_bindcols(result);
1164 } else {
1165 result->values = NULL;
1166 }
1167 }
1168}
1169/* }}} */
1170
1171/* {{{ Get cursor name */
1173{
1174 zval *pv_res;
1175 SQLUSMALLINT max_len;
1176 SQLSMALLINT len;
1177 char *cursorname;
1179 RETCODE rc;
1180
1181 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
1182 RETURN_THROWS();
1183 }
1184
1185 result = Z_ODBC_RESULT_P(pv_res);
1186 CHECK_ODBC_RESULT(result);
1187
1188 rc = SQLGetInfo(result->conn_ptr->hdbc,SQL_MAX_CURSOR_NAME_LEN, (void *)&max_len,sizeof(max_len),&len);
1189 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1191 }
1192
1193 if (max_len > 0) {
1194 cursorname = emalloc(max_len + 1);
1195 rc = SQLGetCursorName(result->stmt, (SQLCHAR *) cursorname, (SQLSMALLINT)max_len, &len);
1196 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1197 char state[6]; /* Not used */
1198 SQLINTEGER error; /* Not used */
1199 char errormsg[SQL_MAX_MESSAGE_LENGTH];
1200 SQLSMALLINT errormsgsize; /* Not used */
1201
1202 SQLError( result->conn_ptr->henv, result->conn_ptr->hdbc,
1203 result->stmt, (SQLCHAR *) state, &error, (SQLCHAR *) errormsg,
1204 sizeof(errormsg)-1, &errormsgsize);
1205 if (!strncmp(state,"S1015",5)) {
1206 snprintf(cursorname, max_len+1, "php_curs_" ZEND_ULONG_FMT, (zend_ulong)result->stmt);
1207 if (SQLSetCursorName(result->stmt, (SQLCHAR *) cursorname, SQL_NTS) != SQL_SUCCESS) {
1208 odbc_sql_error(result->conn_ptr, result->stmt, "SQLSetCursorName");
1210 } else {
1211 RETVAL_STRING(cursorname);
1212 }
1213 } else {
1214 php_error_docref(NULL, E_WARNING, "SQL error: %s, SQL state %s", errormsg, state);
1216 }
1217 } else {
1218 RETVAL_STRING(cursorname);
1219 }
1220 efree(cursorname);
1221 } else {
1223 }
1224}
1225/* }}} */
1226
1227#ifdef HAVE_SQLDATASOURCES
1228/* {{{ Return information about the currently connected data source */
1230{
1231 zval *zv_conn;
1232 zend_long zv_fetch_type;
1233 RETCODE rc = 0; /* assume all is good */
1234 UCHAR server_name[100], desc[200];
1235 SQLSMALLINT len1=0, len2=0, fetch_type;
1236
1237 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &zv_conn, odbc_connection_ce, &zv_fetch_type) == FAILURE) {
1238 RETURN_THROWS();
1239 }
1240
1241 fetch_type = (SQLSMALLINT) zv_fetch_type;
1242
1243 if (!(fetch_type == SQL_FETCH_FIRST || fetch_type == SQL_FETCH_NEXT)) {
1244 zend_argument_value_error(2, "must be either SQL_FETCH_FIRST or SQL_FETCH_NEXT");
1245 RETURN_THROWS();
1246 }
1247
1248 odbc_connection *conn = Z_ODBC_CONNECTION_P(zv_conn);
1249 CHECK_ODBC_CONNECTION(conn);
1250
1251 /* now we have the "connection" lets call the DataSource object */
1252 rc = SQLDataSources(conn->henv,
1253 fetch_type,
1254 server_name,
1255 (SQLSMALLINT)sizeof(server_name),
1256 &len1,
1257 desc,
1258 (SQLSMALLINT)sizeof(desc),
1259 &len2);
1260
1261 if (SQL_NO_DATA == rc) {
1262 /* System has no data sources, no error. Signal it by returning NULL,
1263 not false. */
1264 RETURN_NULL();
1265 } else if (rc != SQL_SUCCESS) {
1266 /* ummm.... he did it */
1267 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLDataSources");
1269 }
1270
1271 if (len1 == 0 || len2 == 0) {
1272 /* we have a non-valid entry... so stop the looping */
1274 }
1275
1277
1278 add_assoc_string_ex(return_value, "server", sizeof("server")-1, (char *) server_name);
1279 add_assoc_string_ex(return_value, "description", sizeof("description")-1, (char *) desc);
1280
1281}
1282/* }}} */
1283#endif /* HAVE_SQLDATASOURCES */
1284
1285/* {{{ Prepare and execute an SQL statement */
1286/* XXX Use flags */
1288{
1289 zval *pv_conn;
1290 char *query;
1291 size_t query_len;
1293 RETCODE rc;
1294#ifdef HAVE_SQL_EXTENDED_FETCH
1295 SQLUINTEGER scrollopts;
1296#endif
1297
1298 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &pv_conn, odbc_connection_ce, &query, &query_len) == FAILURE) {
1299 RETURN_THROWS();
1300 }
1301
1302 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
1303 CHECK_ODBC_CONNECTION(conn);
1304
1305 object_init_ex(return_value, odbc_result_ce);
1306 result = Z_ODBC_RESULT_P(return_value);
1307
1308 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
1309 if (rc == SQL_INVALID_HANDLE) {
1310 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
1313 }
1314
1315 if (rc == SQL_ERROR) {
1316 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
1319 }
1320
1321#ifdef HAVE_SQL_EXTENDED_FETCH
1322 /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info,
1323 whether Driver supports ExtendedFetch */
1324 rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL);
1325 if (rc == SQL_SUCCESS) {
1326 if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) {
1327 /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other
1328 type if not possible.
1329 */
1330 SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype));
1331 }
1332 } else {
1333 result->fetch_abs = 0;
1334 }
1335#endif
1336
1337 rc = SQLExecDirect(result->stmt, (SQLCHAR *) query, SQL_NTS);
1338 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA_FOUND) {
1339 /* XXX FIXME we should really check out SQLSTATE with SQLError
1340 * in case rc is SQL_SUCCESS_WITH_INFO here.
1341 */
1342 odbc_sql_error(conn, result->stmt, "SQLExecDirect");
1343 SQLFreeStmt(result->stmt, SQL_DROP);
1346 }
1347
1348 SQLNumResultCols(result->stmt, &(result->numcols));
1349
1350 /* For insert, update etc. cols == 0 */
1351 if (result->numcols > 0) {
1352 odbc_bindcols(result);
1353 } else {
1354 result->values = NULL;
1355 }
1356 result->conn_ptr = conn;
1357 result->fetched = 0;
1358
1359 odbc_insert_new_result(conn, return_value);
1360}
1361/* }}} */
1362
1363#ifdef PHP_ODBC_HAVE_FETCH_HASH
1364#define ODBC_NUM 1
1365#define ODBC_OBJECT 2
1366
1367/* {{{ php_odbc_fetch_hash */
1368static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
1369{
1370 int i;
1372 RETCODE rc;
1373 SQLSMALLINT sql_c_type;
1374 char *buf = NULL;
1375 zend_long pv_row = 0;
1376 bool pv_row_is_null = true;
1377 zval *pv_res, tmp;
1378#ifdef HAVE_SQL_EXTENDED_FETCH
1379 SQLULEN crow;
1380 SQLUSMALLINT RowStatus[1];
1381#endif
1382
1383 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l!", &pv_res, odbc_result_ce, &pv_row, &pv_row_is_null) == FAILURE) {
1384 RETURN_THROWS();
1385 }
1386
1387 result = Z_ODBC_RESULT_P(pv_res);
1388 CHECK_ODBC_RESULT(result);
1389
1390 /* TODO deprecate $row argument values less than 1 after PHP 8.4 */
1391
1392#ifndef HAVE_SQL_EXTENDED_FETCH
1393 if (!pv_row_is_null && pv_row > 0) {
1394 php_error_docref(NULL, E_WARNING, "Extended fetch functionality is not available, argument #3 ($row) is ignored");
1395 }
1396#endif
1397
1398 if (result->numcols == 0) {
1399 php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
1401 }
1402
1403#ifdef HAVE_SQL_EXTENDED_FETCH
1404 if (result->fetch_abs) {
1405 if (!pv_row_is_null && pv_row > 0) {
1406 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,(SQLLEN)pv_row,&crow,RowStatus);
1407 } else {
1408 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
1409 }
1410 } else
1411#endif
1412 rc = SQLFetch(result->stmt);
1413
1414 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1415 if (rc == SQL_ERROR) {
1416#ifdef HAVE_SQL_EXTENDED_FETCH
1417 odbc_sql_error(result->conn_ptr, result->stmt, "SQLExtendedFetch");
1418#else
1419 odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetch");
1420#endif
1421 }
1423 }
1424
1426
1427#ifdef HAVE_SQL_EXTENDED_FETCH
1428 if (!pv_row_is_null && pv_row > 0 && result->fetch_abs)
1429 result->fetched = (SQLLEN)pv_row;
1430 else
1431#endif
1432 result->fetched++;
1433
1434 for(i = 0; i < result->numcols; i++) {
1435 sql_c_type = SQL_C_CHAR;
1436
1437 switch(result->values[i].coltype) {
1438 case SQL_BINARY:
1439 case SQL_VARBINARY:
1440 case SQL_LONGVARBINARY:
1441 if (result->binmode <= 0) {
1442 ZVAL_EMPTY_STRING(&tmp);
1443 break;
1444 }
1445 if (result->binmode == 1) {
1446 sql_c_type = SQL_C_BINARY;
1447 }
1449 case SQL_LONGVARCHAR:
1450#if defined(ODBCVER) && (ODBCVER >= 0x0300)
1451 case SQL_WLONGVARCHAR:
1452#endif
1453 if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
1454 ZVAL_EMPTY_STRING(&tmp);
1455 break;
1456 }
1457 if (buf == NULL) {
1458 buf = emalloc(result->longreadlen + 1);
1459 }
1460
1461 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1), sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen);
1462
1463 if (rc == SQL_ERROR) {
1464 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
1465 efree(buf);
1467 }
1468
1469 if (rc == SQL_SUCCESS_WITH_INFO) {
1470 ZVAL_STRINGL(&tmp, buf, result->longreadlen);
1471 } else if (rc != SQL_SUCCESS) {
1472 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc);
1473 ZVAL_FALSE(&tmp);
1474 } else if (result->values[i].vallen == SQL_NULL_DATA) {
1475 ZVAL_NULL(&tmp);
1476 break;
1477 } else if (result->values[i].vallen == SQL_NO_TOTAL) {
1478 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1);
1479 ZVAL_FALSE(&tmp);
1480 } else {
1481 ZVAL_STRINGL(&tmp, buf, result->values[i].vallen);
1482 }
1483 break;
1484
1485 default:
1486 if (result->values[i].vallen == SQL_NULL_DATA) {
1487 ZVAL_NULL(&tmp);
1488 break;
1489 } else if (result->values[i].vallen == SQL_NO_TOTAL) {
1490 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1);
1491 ZVAL_FALSE(&tmp);
1492 break;
1493 }
1494 ZVAL_STRINGL(&tmp, result->values[i].value, result->values[i].vallen);
1495 break;
1496 }
1497
1498 if (result_type & ODBC_NUM) {
1500 } else {
1501 if (!*(result->values[i].name) && Z_TYPE(tmp) == IS_STRING) {
1503 } else {
1504 zend_hash_str_update(Z_ARRVAL_P(return_value), result->values[i].name, strlen(result->values[i].name), &tmp);
1505 }
1506 }
1507 }
1508 if (buf) {
1509 efree(buf);
1510 }
1511}
1512/* }}} */
1513
1514
1515/* {{{ Fetch a result row as an object */
1517{
1518 php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT);
1519 if (Z_TYPE_P(return_value) == IS_ARRAY) {
1521 }
1522}
1523/* }}} */
1524
1525/* {{{ Fetch a result row as an associative array */
1527{
1528 php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT);
1529}
1530/* }}} */
1531#endif
1532
1533/* {{{ Fetch one result row into an array */
1535{
1536 int i;
1538 RETCODE rc;
1539 SQLSMALLINT sql_c_type;
1540 char *buf = NULL;
1541 zval *pv_res, *pv_res_arr, tmp;
1542 zend_long pv_row = 0;
1543 bool pv_row_is_null = true;
1544#ifdef HAVE_SQL_EXTENDED_FETCH
1545 SQLULEN crow;
1546 SQLUSMALLINT RowStatus[1];
1547#endif /* HAVE_SQL_EXTENDED_FETCH */
1548
1549 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oz|l!", &pv_res, odbc_result_ce, &pv_res_arr, &pv_row, &pv_row_is_null) == FAILURE) {
1550 RETURN_THROWS();
1551 }
1552
1553 result = Z_ODBC_RESULT_P(pv_res);
1554 CHECK_ODBC_RESULT(result);
1555
1556 /* TODO deprecate $row argument values less than 1 after PHP 8.4 */
1557
1558#ifndef HAVE_SQL_EXTENDED_FETCH
1559 if (!pv_row_is_null && pv_row > 0) {
1560 php_error_docref(NULL, E_WARNING, "Extended fetch functionality is not available, argument #3 ($row) is ignored");
1561 }
1562#endif
1563
1564 if (result->numcols == 0) {
1565 php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
1567 }
1568
1569 pv_res_arr = zend_try_array_init(pv_res_arr);
1570 if (!pv_res_arr) {
1571 RETURN_THROWS();
1572 }
1573
1574#ifdef HAVE_SQL_EXTENDED_FETCH
1575 if (result->fetch_abs) {
1576 if (!pv_row_is_null && pv_row > 0) {
1577 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,(SQLLEN)pv_row,&crow,RowStatus);
1578 } else {
1579 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
1580 }
1581 } else
1582#endif
1583 rc = SQLFetch(result->stmt);
1584
1585 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1586 if (rc == SQL_ERROR) {
1587#ifdef HAVE_SQL_EXTENDED_FETCH
1588 odbc_sql_error(result->conn_ptr, result->stmt, "SQLExtendedFetch");
1589#else
1590 odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetch");
1591#endif
1592 }
1594 }
1595
1596#ifdef HAVE_SQL_EXTENDED_FETCH
1597 if (!pv_row_is_null && pv_row > 0 && result->fetch_abs)
1598 result->fetched = (SQLLEN)pv_row;
1599 else
1600#endif
1601 result->fetched++;
1602
1603 for(i = 0; i < result->numcols; i++) {
1604 sql_c_type = SQL_C_CHAR;
1605
1606 switch(result->values[i].coltype) {
1607 case SQL_BINARY:
1608 case SQL_VARBINARY:
1609 case SQL_LONGVARBINARY:
1610 if (result->binmode <= 0) {
1611 ZVAL_EMPTY_STRING(&tmp);
1612 break;
1613 }
1614 if (result->binmode == 1) sql_c_type = SQL_C_BINARY;
1615
1616 /* TODO: Check this is the intended behaviour */
1618 case SQL_LONGVARCHAR:
1619#if defined(ODBCVER) && (ODBCVER >= 0x0300)
1620 case SQL_WLONGVARCHAR:
1621#endif
1622 if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
1623 ZVAL_EMPTY_STRING(&tmp);
1624 break;
1625 }
1626
1627 if (buf == NULL) {
1628 buf = emalloc(result->longreadlen + 1);
1629 }
1630 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen);
1631
1632 if (rc == SQL_ERROR) {
1633 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
1634 efree(buf);
1636 }
1637 if (rc == SQL_SUCCESS_WITH_INFO) {
1638 ZVAL_STRINGL(&tmp, buf, result->longreadlen);
1639 } else if (rc != SQL_SUCCESS) {
1640 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc);
1641 ZVAL_FALSE(&tmp);
1642 } else if (result->values[i].vallen == SQL_NULL_DATA) {
1643 ZVAL_NULL(&tmp);
1644 break;
1645 } else if (result->values[i].vallen == SQL_NO_TOTAL) {
1646 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1);
1647 ZVAL_FALSE(&tmp);
1648 } else {
1649 ZVAL_STRINGL(&tmp, buf, result->values[i].vallen);
1650 }
1651 break;
1652
1653 default:
1654 if (result->values[i].vallen == SQL_NULL_DATA) {
1655 ZVAL_NULL(&tmp);
1656 break;
1657 } else if (result->values[i].vallen == SQL_NO_TOTAL) {
1658 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1);
1659 ZVAL_FALSE(&tmp);
1660 break;
1661 }
1662 ZVAL_STRINGL(&tmp, result->values[i].value, result->values[i].vallen);
1663 break;
1664 }
1665 zend_hash_index_update(Z_ARRVAL_P(pv_res_arr), i, &tmp);
1666 }
1667 if (buf) efree(buf);
1668 RETURN_LONG(result->numcols);
1669}
1670/* }}} */
1671
1672/* {{{ Fetch a row */
1674{
1676 RETCODE rc;
1677 zval *pv_res;
1678 zend_long pv_row = 0;
1679 bool pv_row_is_null = true;
1680#ifdef HAVE_SQL_EXTENDED_FETCH
1681 SQLULEN crow;
1682 SQLUSMALLINT RowStatus[1];
1683#endif
1684
1685 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l!", &pv_res, odbc_result_ce, &pv_row, &pv_row_is_null) == FAILURE) {
1686 RETURN_THROWS();
1687 }
1688
1689 result = Z_ODBC_RESULT_P(pv_res);
1690 CHECK_ODBC_RESULT(result);
1691
1692#ifndef HAVE_SQL_EXTENDED_FETCH
1693 if (!pv_row_is_null) {
1694 php_error_docref(NULL, E_WARNING, "Extended fetch functionality is not available, argument #3 ($row) is ignored");
1695 }
1696#else
1697 if (!pv_row_is_null && pv_row < 1) {
1698 php_error_docref(NULL, E_WARNING, "Argument #3 ($row) must be greater than or equal to 1");
1700 }
1701#endif
1702
1703 if (result->numcols == 0) {
1704 php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
1706 }
1707
1708#ifdef HAVE_SQL_EXTENDED_FETCH
1709 if (result->fetch_abs) {
1710 if (!pv_row_is_null) {
1711 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,(SQLLEN)pv_row,&crow,RowStatus);
1712 } else {
1713 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
1714 }
1715 } else
1716#endif
1717 rc = SQLFetch(result->stmt);
1718
1719 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1720 if (rc == SQL_ERROR) {
1721#ifdef HAVE_SQL_EXTENDED_FETCH
1722 odbc_sql_error(result->conn_ptr, result->stmt, "SQLExtendedFetch");
1723#else
1724 odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetch");
1725#endif
1726 }
1728 }
1729
1730#ifdef HAVE_SQL_EXTENDED_FETCH
1731 if (!pv_row_is_null) {
1732 result->fetched = (SQLLEN)pv_row;
1733 } else
1734#endif
1735 result->fetched++;
1736
1738}
1739/* }}} */
1740
1741/* {{{ Get result data */
1743{
1744 char *field;
1745 zend_string *field_str, *pv_field_str;
1746 zend_long pv_field_long;
1747 int field_ind;
1748 SQLSMALLINT sql_c_type = SQL_C_CHAR;
1750 int i = 0;
1751 RETCODE rc;
1752 SQLLEN fieldsize;
1753 zval *pv_res;
1754#ifdef HAVE_SQL_EXTENDED_FETCH
1755 SQLULEN crow;
1756 SQLUSMALLINT RowStatus[1];
1757#endif
1758
1760 Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce)
1761 Z_PARAM_STR_OR_LONG(pv_field_str, pv_field_long)
1763
1764 if (pv_field_str) {
1765 field = ZSTR_VAL(pv_field_str);
1766 field_ind = -1;
1767 } else {
1768 field = NULL;
1769 field_ind = (int) pv_field_long - 1;
1770 }
1771
1772 result = Z_ODBC_RESULT_P(pv_res);
1773 CHECK_ODBC_RESULT(result);
1774
1775 if (result->numcols == 0) {
1776 php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
1778 }
1779
1780 /* get field index if the field parameter was a string */
1781 if (field != NULL) {
1782 if (result->values == NULL) {
1783 php_error_docref(NULL, E_WARNING, "Result set contains no data");
1785 }
1786
1787 for(i = 0; i < result->numcols; i++) {
1788 if (!strcasecmp(result->values[i].name, field)) {
1789 field_ind = i;
1790 break;
1791 }
1792 }
1793
1794 if (field_ind < 0) {
1795 php_error_docref(NULL, E_WARNING, "Field %s not found", field);
1797 }
1798 } else {
1799 /* check for limits of field_ind if the field parameter was an int */
1800 if (field_ind >= result->numcols || field_ind < 0) {
1801 php_error_docref(NULL, E_WARNING, "Field index is larger than the number of fields");
1803 }
1804 }
1805
1806 if (result->fetched == 0) {
1807 /* User forgot to call odbc_fetch_row(), or wants to reload the results, do it now */
1808#ifdef HAVE_SQL_EXTENDED_FETCH
1809 if (result->fetch_abs)
1810 rc = SQLExtendedFetch(result->stmt, SQL_FETCH_NEXT, 1, &crow,RowStatus);
1811 else
1812#endif
1813 rc = SQLFetch(result->stmt);
1814
1815 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1816 if (rc == SQL_ERROR) {
1817#ifdef HAVE_SQL_EXTENDED_FETCH
1818 odbc_sql_error(result->conn_ptr, result->stmt, "SQLExtendedFetch");
1819#else
1820 odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetch");
1821#endif
1822 }
1824 }
1825
1826 result->fetched++;
1827 }
1828
1829 switch(result->values[field_ind].coltype) {
1830 case SQL_BINARY:
1831 case SQL_VARBINARY:
1832 case SQL_LONGVARBINARY:
1833 if (result->binmode <= 1) {
1834 sql_c_type = SQL_C_BINARY;
1835 }
1836 if (result->binmode <= 0) {
1837 break;
1838 }
1839 /* TODO: Check this is the intended behaviour */
1841
1842 case SQL_LONGVARCHAR:
1843#if defined(ODBCVER) && (ODBCVER >= 0x0300)
1844 case SQL_WLONGVARCHAR:
1845#endif
1846 if (IS_SQL_LONG(result->values[field_ind].coltype)) {
1847 if (result->longreadlen <= 0) {
1848 break;
1849 } else {
1850 fieldsize = result->longreadlen;
1851 }
1852 } else {
1853 PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(field_ind + 1),
1854 (SQLUSMALLINT)((sql_c_type == SQL_C_BINARY) ? SQL_COLUMN_LENGTH :
1855 SQL_COLUMN_DISPLAY_SIZE),
1856 NULL, 0, NULL, &fieldsize);
1857 }
1858 /* For char data, the length of the returned string will be longreadlen - 1 */
1859 fieldsize = (result->longreadlen <= 0) ? 4096 : result->longreadlen;
1860 field_str = zend_string_alloc(fieldsize, 0);
1861
1862 /* SQLGetData will truncate CHAR data to fieldsize - 1 bytes and append \0.
1863 * For binary data it is truncated to fieldsize bytes.
1864 */
1865 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1), sql_c_type,
1866 ZSTR_VAL(field_str), fieldsize, &result->values[field_ind].vallen);
1867
1868 if (rc == SQL_ERROR) {
1869 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
1870 zend_string_efree(field_str);
1872 }
1873
1874 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1875 zend_string_efree(field_str);
1876 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", field_ind + 1, rc);
1878 } else if (result->values[field_ind].vallen == SQL_NULL_DATA) {
1879 zend_string_efree(field_str);
1880 RETURN_NULL();
1881 } else if (result->values[field_ind].vallen == SQL_NO_TOTAL) {
1882 zend_string_efree(field_str);
1883 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", field_ind + 1);
1885 }
1886 /* Reduce fieldlen by 1 if we have char data. One day we might
1887 have binary strings... */
1888 if ((result->values[field_ind].coltype == SQL_LONGVARCHAR)
1889#if defined(ODBCVER) && (ODBCVER >= 0x0300)
1890 || (result->values[field_ind].coltype == SQL_WLONGVARCHAR)
1891#endif
1892 ) {
1893 fieldsize -= 1;
1894 }
1895 /* Don't duplicate result, saves one emalloc.
1896 For SQL_SUCCESS, the length is in vallen.
1897 */
1898 if (rc != SQL_SUCCESS_WITH_INFO) {
1899 field_str = zend_string_truncate(field_str, result->values[field_ind].vallen, 0);
1900 }
1901 ZSTR_VAL(field_str)[ZSTR_LEN(field_str)] = '\0';
1902 RETURN_NEW_STR(field_str);
1903 break;
1904
1905 default:
1906 if (result->values[field_ind].vallen == SQL_NULL_DATA) {
1907 RETURN_NULL();
1908 } else if (result->values[field_ind].vallen == SQL_NO_TOTAL) {
1909 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", field_ind + 1);
1911 } else {
1912 RETURN_STRINGL(result->values[field_ind].value, result->values[field_ind].vallen);
1913 }
1914 break;
1915 }
1916
1917/* If we come here, output unbound LONG and/or BINARY column data to the client */
1918
1919 /* We emalloc 1 byte more for SQL_C_CHAR (trailing \0) */
1920 fieldsize = (sql_c_type == SQL_C_CHAR) ? 4096 : 4095;
1921 field = emalloc(fieldsize);
1922
1923 /* Call SQLGetData() until SQL_SUCCESS is returned */
1924 while(1) {
1925 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1),sql_c_type, field, fieldsize, &result->values[field_ind].vallen);
1926
1927 if (rc == SQL_ERROR) {
1928 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
1929 efree(field);
1931 }
1932
1933 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1934 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", field_ind + 1, rc);
1935 efree(field);
1937 }
1938
1939 if (result->values[field_ind].vallen == SQL_NULL_DATA) {
1940 efree(field);
1941 RETURN_NULL();
1942 } else if (result->values[field_ind].vallen == SQL_NO_TOTAL) {
1943 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", field_ind + 1);
1944 efree(field);
1946 }
1947 /* chop the trailing \0 by outputting only 4095 bytes */
1948 PHPWRITE(field,(rc == SQL_SUCCESS_WITH_INFO) ? 4095 : result->values[field_ind].vallen);
1949
1950 if (rc == SQL_SUCCESS) { /* no more data avail */
1951 efree(field);
1953 }
1954 }
1956}
1957/* }}} */
1958
1959/* {{{ Print result as HTML table */
1961{
1962 char *buf = NULL;
1964 RETCODE rc;
1965 zval *pv_res;
1966 char *pv_format = NULL;
1967 size_t i, pv_format_len = 0;
1968 SQLSMALLINT sql_c_type;
1969#ifdef HAVE_SQL_EXTENDED_FETCH
1970 SQLULEN crow;
1971 SQLUSMALLINT RowStatus[1];
1972#endif
1973
1974 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s", &pv_res, odbc_result_ce, &pv_format, &pv_format_len) == FAILURE) {
1975 RETURN_THROWS();
1976 }
1977
1978 result = Z_ODBC_RESULT_P(pv_res);
1979 CHECK_ODBC_RESULT(result);
1980
1981 if (result->numcols == 0) {
1982 php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
1984 }
1985#ifdef HAVE_SQL_EXTENDED_FETCH
1986 if (result->fetch_abs)
1987 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
1988 else
1989#endif
1990 rc = SQLFetch(result->stmt);
1991
1992 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1993 php_printf("<h2>No rows found</h2>\n");
1994 RETURN_LONG(0);
1995 }
1996
1997 /* Start table tag */
1998 if (ZEND_NUM_ARGS() == 1) {
1999 php_printf("<table><tr>");
2000 } else {
2001 php_printf("<table %s ><tr>", pv_format);
2002 }
2003
2004 for (i = 0; i < result->numcols; i++) {
2005 php_printf("<th>%s</th>", result->values[i].name);
2006 }
2007
2008 php_printf("</tr>\n");
2009
2010 while(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
2011 result->fetched++;
2012 php_printf("<tr>");
2013 for(i = 0; i < result->numcols; i++) {
2014 sql_c_type = SQL_C_CHAR;
2015 switch(result->values[i].coltype) {
2016 case SQL_BINARY:
2017 case SQL_VARBINARY:
2018 case SQL_LONGVARBINARY:
2019 if (result->binmode <= 0) {
2020 php_printf("<td>Not printable</td>");
2021 break;
2022 }
2023 if (result->binmode <= 1) sql_c_type = SQL_C_BINARY;
2024
2025 /* TODO: Check this is the intended behaviour */
2027 case SQL_LONGVARCHAR:
2028#if defined(ODBCVER) && (ODBCVER >= 0x0300)
2029 case SQL_WLONGVARCHAR:
2030#endif
2031 if (IS_SQL_LONG(result->values[i].coltype) &&
2032 result->longreadlen <= 0) {
2033 php_printf("<td>Not printable</td>");
2034 break;
2035 }
2036
2037 if (buf == NULL) {
2038 buf = emalloc(result->longreadlen);
2039 }
2040
2041 rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen, &result->values[i].vallen);
2042
2043 php_printf("<td>");
2044
2045 if (rc == SQL_ERROR) {
2046 odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
2047 php_printf("</td></tr></table>");
2048 efree(buf);
2050 }
2051 if (rc == SQL_SUCCESS_WITH_INFO) {
2052 if (result->values[i].vallen == SQL_NO_TOTAL) {
2053 php_printf("</td></tr></table>");
2054 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%zu (driver cannot determine length)", i + 1);
2055 efree(buf);
2057 } else {
2058 PHPWRITE(buf, result->longreadlen);
2059 }
2060 } else if (rc != SQL_SUCCESS) {
2061 php_printf("</td></tr></table>");
2062 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%zu (retcode %u)", i + 1, rc);
2063 efree(buf);
2065 } else if (result->values[i].vallen == SQL_NULL_DATA) {
2066 php_printf("<td>NULL</td>");
2067 break;
2068 } else {
2069 PHPWRITE(buf, result->values[i].vallen);
2070 }
2071 php_printf("</td>");
2072 break;
2073 default:
2074 if (result->values[i].vallen == SQL_NULL_DATA) {
2075 php_printf("<td>NULL</td>");
2076 } else if (result->values[i].vallen == SQL_NO_TOTAL) {
2077 php_error_docref(NULL, E_WARNING, "Cannot get data of column #%zu (driver cannot determine length)", i + 1);
2078 php_printf("<td>FALSE</td>");
2079 } else {
2080 php_printf("<td>%s</td>", result->values[i].value);
2081 }
2082 break;
2083 }
2084 }
2085 php_printf("</tr>\n");
2086
2087#ifdef HAVE_SQL_EXTENDED_FETCH
2088 if (result->fetch_abs)
2089 rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
2090 else
2091#endif
2092 rc = SQLFetch(result->stmt);
2093 }
2094 php_printf("</table>\n");
2095 if (buf) efree(buf);
2096 RETURN_LONG(result->fetched);
2097}
2098/* }}} */
2099
2100/* {{{ Free resources associated with a result */
2102{
2103 zval *pv_res;
2105
2106 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
2107 RETURN_THROWS();
2108 }
2109
2110 result = Z_ODBC_RESULT_P(pv_res);
2111 CHECK_ODBC_RESULT(result);
2112
2113 odbc_result_free(result);
2114
2116}
2117/* }}} */
2118
2119/* {{{ Connect to a datasource */
2121{
2122 odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2123}
2124/* }}} */
2125
2126/* {{{ Establish a persistent connection to a datasource */
2128{
2129 odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2130}
2131/* }}} */
2132
2133/* {{{ odbc_sqlconnect */
2134bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool persistent, char *hash, int hash_len)
2135{
2136 RETCODE rc;
2137 SQLRETURN ret;
2138 odbc_link *link;
2139
2140 object_init_ex(zv, odbc_connection_ce);
2141 link = Z_ODBC_LINK_P(zv);
2142 link->connection = pecalloc(1, sizeof(odbc_connection), persistent);
2143 zend_hash_init(&link->connection->results, 0, NULL, ZVAL_PTR_DTOR, true);
2144 link->persistent = persistent;
2145 link->hash = zend_string_init(hash, hash_len, persistent);
2146 if (persistent) {
2148 }
2149 ret = SQLAllocEnv(&link->connection->henv);
2150 if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
2151 odbc_sql_error(link->connection, SQL_NULL_HSTMT, "SQLAllocEnv");
2152 return false;
2153 }
2154
2155 ret = SQLAllocConnect(link->connection->henv, &link->connection->hdbc);
2156 if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
2157 odbc_sql_error(link->connection, SQL_NULL_HSTMT, "SQLAllocConnect");
2158 return false;
2159 }
2160
2161#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30)
2162 SQLSetConnectOption((link->connection->hdbc, SQL_TRANSLATE_OPTION,
2163 SQL_SOLID_XLATOPT_NOCNV);
2164#endif
2165#ifdef HAVE_OPENLINK
2166 {
2167 char dsnbuf[1024];
2168 short dsnbuflen;
2169
2170 rc = SQLDriverConnect(link->connection->hdbc, NULL, db, SQL_NTS, dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
2171 }
2172#else
2173 if (cur_opt != SQL_CUR_DEFAULT) {
2174 rc = SQLSetConnectOption(link->connection->hdbc, SQL_ODBC_CURSORS, cur_opt);
2175 if (rc != SQL_SUCCESS) { /* && rc != SQL_SUCCESS_WITH_INFO ? */
2176 odbc_sql_error(link->connection, SQL_NULL_HSTMT, "SQLSetConnectOption");
2177 return false;
2178 }
2179 }
2180/* Possible fix for bug #10250
2181 * Needs testing on UnixODBC < 2.0.5 though. */
2182#if defined(HAVE_EMPRESS) || defined(HAVE_UNIXODBC) || defined(PHP_WIN32) || defined (HAVE_IODBC)
2183/* * Uncomment the line above, and comment line below to fully test
2184 * #ifdef HAVE_EMPRESS */
2185 {
2186 int direct = 0;
2187 SQLCHAR dsnbuf[1024];
2188 short dsnbuflen;
2189 char *ldb = 0;
2190 int ldb_len = 0;
2191
2192 /* a connection string may have = but not ; - i.e. "DSN=PHP" */
2193 if (strstr((char*)db, "=")) {
2194 direct = 1;
2195
2196 /* This should be identical to the code in the PDO driver and vice versa. */
2197 size_t db_len = strlen(db);
2198 char *db_end = db + db_len;
2199 bool use_uid_arg = uid != NULL && !php_memnistr(db, "uid=", strlen("uid="), db_end);
2200 bool use_pwd_arg = pwd != NULL && !php_memnistr(db, "pwd=", strlen("pwd="), db_end);
2201
2202 /* Force UID and PWD to be set in the DSN */
2203 if (use_uid_arg || use_pwd_arg) {
2204 db_end--;
2205 if ((unsigned char)*(db_end) == ';') {
2206 *db_end = '\0';
2207 }
2208
2209 char *uid_quoted = NULL, *pwd_quoted = NULL;
2210 bool should_quote_uid, should_quote_pwd;
2211 if (use_uid_arg) {
2212 should_quote_uid = !php_odbc_connstr_is_quoted(uid) && php_odbc_connstr_should_quote(uid);
2213 if (should_quote_uid) {
2214 size_t estimated_length = php_odbc_connstr_estimate_quote_length(uid);
2215 uid_quoted = emalloc(estimated_length);
2216 php_odbc_connstr_quote(uid_quoted, uid, estimated_length);
2217 } else {
2218 uid_quoted = uid;
2219 }
2220
2221 if (!use_pwd_arg) {
2222 spprintf(&ldb, 0, "%s;UID=%s;", db, uid_quoted);
2223 }
2224 }
2225
2226 if (use_pwd_arg) {
2227 should_quote_pwd = !php_odbc_connstr_is_quoted(pwd) && php_odbc_connstr_should_quote(pwd);
2228 if (should_quote_pwd) {
2229 size_t estimated_length = php_odbc_connstr_estimate_quote_length(pwd);
2230 pwd_quoted = emalloc(estimated_length);
2231 php_odbc_connstr_quote(pwd_quoted, pwd, estimated_length);
2232 } else {
2233 pwd_quoted = pwd;
2234 }
2235
2236 if (!use_uid_arg) {
2237 spprintf(&ldb, 0, "%s;PWD=%s;", db, pwd_quoted);
2238 }
2239 }
2240
2241 if (use_uid_arg && use_pwd_arg) {
2242 spprintf(&ldb, 0, "%s;UID=%s;PWD=%s;", db, uid_quoted, pwd_quoted);
2243 }
2244
2245 if (uid_quoted && should_quote_uid) {
2246 efree(uid_quoted);
2247 }
2248 if (pwd_quoted && should_quote_pwd) {
2249 efree(pwd_quoted);
2250 }
2251 } else {
2252 ldb_len = strlen(db)+1;
2253 ldb = (char*) emalloc(ldb_len);
2254 memcpy(ldb, db, ldb_len);
2255 }
2256 }
2257
2258 if (direct) {
2259 rc = SQLDriverConnect(link->connection->hdbc, NULL, (SQLCHAR *) ldb, strlen(ldb), dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
2260 } else {
2261 rc = SQLConnect(link->connection->hdbc, (SQLCHAR *) db, SQL_NTS, (SQLCHAR *) uid, SQL_NTS, (SQLCHAR *) pwd, SQL_NTS);
2262 }
2263
2264 if (ldb) {
2265 efree(ldb);
2266 }
2267 }
2268#else
2269 rc = SQLConnect(link->connection->hdbc, (SQLCHAR *) db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
2270#endif
2271#endif
2272 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
2273 odbc_sql_error(link->connection, SQL_NULL_HSTMT, "SQLConnect");
2274 return false;
2275 }
2276 return true;
2277}
2278/* }}} */
2279
2280/* {{{ odbc_do_connect */
2281void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
2282{
2283 char *db, *uid=NULL, *pwd=NULL;
2284 size_t db_len, uid_len, pwd_len;
2285 zend_long pv_opt = SQL_CUR_DEFAULT;
2286 odbc_connection *db_conn;
2287 int cur_opt;
2288
2290 Z_PARAM_STRING(db, db_len)
2292 Z_PARAM_STRING_OR_NULL(uid, uid_len)
2293 Z_PARAM_STRING_OR_NULL(pwd, pwd_len)
2294 Z_PARAM_LONG(pv_opt)
2296
2297 cur_opt = pv_opt;
2298
2299 if (ZEND_NUM_ARGS() > 3) {
2300 /* Confirm the cur_opt range */
2301 if (! (cur_opt == SQL_CUR_USE_IF_NEEDED ||
2302 cur_opt == SQL_CUR_USE_ODBC ||
2303 cur_opt == SQL_CUR_USE_DRIVER ||
2304 cur_opt == SQL_CUR_DEFAULT) ) {
2305 zend_argument_value_error(4, "must be one of SQL_CUR_USE_IF_NEEDED, "
2306 "SQL_CUR_USE_ODBC, or SQL_CUR_USE_DRIVER");
2307 RETURN_THROWS();
2308 }
2309 }
2310
2311 if (!ODBCG(allow_persistent)) {
2312 persistent = 0;
2313 }
2314
2315 char *hashed_details;
2316 size_t hashed_details_len = spprintf(&hashed_details, 0, "odbc_%d_%s_%s_%s_%s_%d", persistent, ODBC_TYPE, db, uid, pwd, cur_opt);
2317
2318try_and_get_another_connection:
2319
2320 if (persistent) {
2321 zend_resource *le;
2322
2323 /* the link is not in the persistent list */
2324 if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashed_details, hashed_details_len)) == NULL) {
2325 if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) {
2326 php_error_docref(NULL, E_WARNING, "Too many open links (" ZEND_LONG_FMT ")", ODBCG(num_links));
2327 efree(hashed_details);
2329 }
2330 if (ODBCG(max_persistent) != -1 && ODBCG(num_persistent) >= ODBCG(max_persistent)) {
2331 php_error_docref(NULL, E_WARNING,"Too many open persistent links (" ZEND_LONG_FMT ")", ODBCG(num_persistent));
2332 efree(hashed_details);
2334 }
2335
2336 if (!odbc_sqlconnect(return_value, db, uid, pwd, cur_opt, true, hashed_details, hashed_details_len)) {
2337 efree(hashed_details);
2340 }
2341
2342 db_conn = Z_ODBC_CONNECTION_P(return_value);
2343
2344 if (zend_register_persistent_resource(hashed_details, hashed_details_len, db_conn, le_pconn) == NULL) {
2345 efree(hashed_details);
2348 }
2349
2350 zend_hash_str_add_new(&ODBCG(connections), hashed_details, hashed_details_len, return_value);
2351
2352 ODBCG(num_persistent)++;
2353 ODBCG(num_links)++;
2354 } else { /* found connection */
2355 ZEND_ASSERT(le->type == le_pconn);
2356
2357 /*
2358 * check to see if the connection is still valid
2359 */
2360 db_conn = (odbc_connection *)le->ptr;
2361
2362 /*
2363 * check to see if the connection is still in place (lurcher)
2364 */
2365 if(ODBCG(check_persistent)){
2366 RETCODE ret;
2367 UCHAR d_name[32];
2368 SQLSMALLINT len;
2369 SQLUINTEGER dead = SQL_CD_FALSE;
2370
2371 ret = SQLGetConnectAttr(db_conn->hdbc,
2372 SQL_ATTR_CONNECTION_DEAD,
2373 &dead, 0, NULL);
2374 if (ret == SQL_SUCCESS && dead == SQL_CD_TRUE) {
2375 /* Bail early here, since we know it's gone */
2376 zend_hash_str_del(&EG(persistent_list), hashed_details, hashed_details_len);
2377 goto try_and_get_another_connection;
2378 }
2379 /* If the driver doesn't support it, or returns
2380 * false (could be a false positive), fall back
2381 * to the old heuristic.
2382 */
2383 ret = SQLGetInfo(db_conn->hdbc,
2384 SQL_DATA_SOURCE_READ_ONLY,
2385 d_name, sizeof(d_name), &len);
2386
2387 if(ret != SQL_SUCCESS || len == 0) {
2388 zend_hash_str_del(&EG(persistent_list), hashed_details, hashed_details_len);
2389 /* Commented out to fix a possible double closure error
2390 * when working with persistent connections as submitted by
2391 * bug #15758
2392 *
2393 * safe_odbc_disconnect(db_conn->hdbc);
2394 * SQLFreeConnect(db_conn->hdbc);
2395 */
2396 goto try_and_get_another_connection;
2397 }
2398 }
2399
2400 zval *link_zval;
2401 if ((link_zval = zend_hash_str_find(&ODBCG(connections), hashed_details, hashed_details_len)) == NULL) {
2402 object_init_ex(return_value, odbc_connection_ce);
2403 odbc_link *link = Z_ODBC_LINK_P(return_value);
2404 link->connection = db_conn;
2405 link->hash = zend_string_init(hashed_details, hashed_details_len, persistent);
2406 link->persistent = true;
2407 } else {
2408 ZVAL_COPY(return_value, link_zval);
2409
2410 ZEND_ASSERT(Z_ODBC_CONNECTION_P(return_value) == db_conn && "Persistent connection has changed");
2411 }
2412 }
2413 } else { /* non-persistent */
2414 zval *link_zval;
2415 if ((link_zval = zend_hash_str_find(&ODBCG(connections), hashed_details, hashed_details_len)) == NULL) { /* non-persistent, new */
2416 if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) {
2417 php_error_docref(NULL, E_WARNING, "Too many open connections (" ZEND_LONG_FMT ")", ODBCG(num_links));
2418 efree(hashed_details);
2420 }
2421
2422 if (!odbc_sqlconnect(return_value, db, uid, pwd, cur_opt, false, hashed_details, hashed_details_len)) {
2423 efree(hashed_details);
2426 }
2427 ODBCG(num_links)++;
2428
2429 zend_hash_str_add_new(&ODBCG(connections), hashed_details, hashed_details_len, return_value);
2430 } else { /* non-persistent, pre-existing */
2431 ZVAL_COPY(return_value, link_zval);
2432 }
2433 }
2434 efree(hashed_details);
2435}
2436/* }}} */
2437
2438/* {{{ Close an ODBC connection */
2440{
2441 zval *pv_conn;
2442 odbc_link *link;
2443
2444 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_conn, odbc_connection_ce) == FAILURE) {
2445 RETURN_THROWS();
2446 }
2447
2448 link = Z_ODBC_LINK_P(pv_conn);
2449 odbc_connection *connection = Z_ODBC_CONNECTION_P(pv_conn);
2450 CHECK_ODBC_CONNECTION(connection);
2451
2452 odbc_link_free(link);
2453
2454 if (link->persistent) {
2455 zend_hash_apply_with_argument(&EG(persistent_list), _close_pconn_with_res, (void *) connection);
2456 }
2457}
2458/* }}} */
2459
2460/* {{{ Get number of rows in a result */
2462{
2464 SQLLEN rows;
2465 zval *pv_res;
2466
2467 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
2468 RETURN_THROWS();
2469 }
2470
2471 result = Z_ODBC_RESULT_P(pv_res);
2472 CHECK_ODBC_RESULT(result);
2473
2474 SQLRowCount(result->stmt, &rows);
2475 RETURN_LONG(rows);
2476}
2477/* }}} */
2478
2479#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
2480/* {{{ Checks if multiple results are available */
2482{
2484 zval *pv_res;
2485 int rc, i;
2486
2487 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
2488 RETURN_THROWS();
2489 }
2490
2491 result = Z_ODBC_RESULT_P(pv_res);
2492 CHECK_ODBC_RESULT(result);
2493
2494 if (result->values) {
2495 for(i = 0; i < result->numcols; i++) {
2496 if (result->values[i].value) {
2497 efree(result->values[i].value);
2498 }
2499 }
2500 efree(result->values);
2501 result->values = NULL;
2502 result->numcols = 0;
2503 }
2504
2505 result->fetched = 0;
2506 rc = SQLMoreResults(result->stmt);
2507 if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS) {
2508 rc = SQLFreeStmt(result->stmt, SQL_UNBIND);
2509 SQLNumParams(result->stmt, &(result->numparams));
2510 SQLNumResultCols(result->stmt, &(result->numcols));
2511
2512 if (result->numcols > 0) {
2513 odbc_bindcols(result);
2514 } else {
2515 result->values = NULL;
2516 }
2518 } else if (rc == SQL_NO_DATA_FOUND) {
2520 } else {
2521 odbc_sql_error(result->conn_ptr, result->stmt, "SQLMoreResults");
2523 }
2524}
2525/* }}} */
2526#endif
2527
2528/* {{{ Get number of columns in a result */
2530{
2532 zval *pv_res;
2533
2534 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &pv_res, odbc_result_ce) == FAILURE) {
2535 RETURN_THROWS();
2536 }
2537
2538 result = Z_ODBC_RESULT_P(pv_res);
2539 CHECK_ODBC_RESULT(result);
2540
2541 RETURN_LONG(result->numcols);
2542}
2543/* }}} */
2544
2545/* {{{ Get a column name */
2547{
2549 zval *pv_res;
2550 zend_long pv_num;
2551
2552 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &pv_res, odbc_result_ce, &pv_num) == FAILURE) {
2553 RETURN_THROWS();
2554 }
2555
2556 result = Z_ODBC_RESULT_P(pv_res);
2557 CHECK_ODBC_RESULT(result);
2558
2559 if (pv_num < 1) {
2560 zend_argument_value_error(2, "must be greater than 0");
2561 RETURN_THROWS();
2562 }
2563
2564 if (result->numcols == 0) {
2565 php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
2567 }
2568
2569 if (pv_num > result->numcols) {
2570 php_error_docref(NULL, E_WARNING, "Field index larger than number of fields");
2572 }
2573
2574 RETURN_STRING(result->values[pv_num - 1].name);
2575}
2576/* }}} */
2577
2578/* {{{ Get the datatype of a column */
2580{
2582 char tmp[32];
2583 SQLSMALLINT tmplen;
2584 zval *pv_res;
2585 zend_long pv_num;
2586
2587 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &pv_res, odbc_result_ce, &pv_num) == FAILURE) {
2588 RETURN_THROWS();
2589 }
2590
2591 result = Z_ODBC_RESULT_P(pv_res);
2592 CHECK_ODBC_RESULT(result);
2593
2594 if (pv_num < 1) {
2595 zend_argument_value_error(2, "must be greater than 0");
2596 RETURN_THROWS();
2597 }
2598
2599 if (result->numcols == 0) {
2600 php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
2602 }
2603
2604 if (pv_num > result->numcols) {
2605 php_error_docref(NULL, E_WARNING, "Field index larger than number of fields");
2607 }
2608
2609 PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL);
2610 RETURN_STRING(tmp);
2611}
2612/* }}} */
2613
2614/* {{{ Get the length (precision) of a column */
2616{
2617 odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2618}
2619/* }}} */
2620
2621/* {{{ Get the scale of a column */
2623{
2624 odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2625}
2626/* }}} */
2627
2628/* {{{ Return column number */
2630{
2631 char *fname;
2632 size_t i, field_ind, fname_len;
2634 zval *pv_res;
2635
2636 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &pv_res, odbc_result_ce, &fname, &fname_len) == FAILURE) {
2637 RETURN_THROWS();
2638 }
2639
2640 result = Z_ODBC_RESULT_P(pv_res);
2641 CHECK_ODBC_RESULT(result);
2642
2643 if (result->numcols == 0) {
2644 php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
2646 }
2647
2648 field_ind = -1;
2649 for(i = 0; i < result->numcols; i++) {
2650 if (strcasecmp(result->values[i].name, fname) == 0) {
2651 field_ind = i + 1;
2652 }
2653 }
2654
2655 if (field_ind == -1) {
2657 }
2658 RETURN_LONG(field_ind);
2659}
2660/* }}} */
2661
2662/* {{{ Toggle autocommit mode or get status */
2663/* There can be problems with pconnections!*/
2665{
2666 RETCODE rc;
2667 zval *pv_conn;
2668 bool pv_onoff = 0;
2669 bool pv_onoff_is_null = true;
2670
2671 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b!", &pv_conn, odbc_connection_ce, &pv_onoff, &pv_onoff_is_null) == FAILURE) {
2672 RETURN_THROWS();
2673 }
2674
2675 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
2676 CHECK_ODBC_CONNECTION(conn);
2677
2678 if (!pv_onoff_is_null) {
2679 rc = SQLSetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, pv_onoff ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
2680 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
2681 odbc_sql_error(conn, SQL_NULL_HSTMT, "Set autocommit");
2683 }
2685 } else {
2686 SQLINTEGER status;
2687
2688 rc = SQLGetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (PTR)&status);
2689 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
2690 odbc_sql_error(conn, SQL_NULL_HSTMT, "Get commit status");
2692 }
2694 }
2695}
2696/* }}} */
2697
2698/* {{{ Commit an ODBC transaction */
2700{
2701 odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2702}
2703/* }}} */
2704
2705/* {{{ Rollback a transaction */
2707{
2708 odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2709}
2710/* }}} */
2711
2712/* {{{ php_odbc_lasterror */
2713static void php_odbc_lasterror(INTERNAL_FUNCTION_PARAMETERS, int mode)
2714{
2715 odbc_connection *conn;
2716 zval *pv_handle = NULL;
2717 char *ret;
2718
2719 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|O!", &pv_handle, odbc_connection_ce) == FAILURE) {
2720 RETURN_THROWS();
2721 }
2722
2723 if (pv_handle) {
2724 conn = Z_ODBC_CONNECTION_P(pv_handle);
2725 CHECK_ODBC_CONNECTION(conn);
2726
2727 if (mode == 0) {
2728 ret = conn->laststate;
2729 } else {
2730 ret = conn->lasterrormsg;
2731 }
2732 } else {
2733 if (mode == 0) {
2734 ret = ODBCG(laststate);
2735 } else {
2736 ret = ODBCG(lasterrormsg);
2737 }
2738 }
2739
2741}
2742/* }}} */
2743
2744/* {{{ Get the last error code */
2746{
2747 php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2748}
2749/* }}} */
2750
2751/* {{{ Get the last error message */
2753{
2754 php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2755}
2756/* }}} */
2757
2758/* {{{ Sets connection or statement options */
2759/* This one has to be used carefully. We can't allow to set connection options for
2760 persistent connections. I think that SetStmtOption is of little use, since most
2761 of those can only be specified before preparing/executing statements.
2762 On the other hand, they can be made connection wide default through SetConnectOption
2763 - but will be overridden by calls to SetStmtOption() in odbc_prepare/odbc_do
2764*/
2766{
2767 odbc_link *link;
2769 RETCODE rc;
2770 zval *pv_handle;
2771 zend_long pv_which, pv_opt, pv_val;
2772
2773 if (zend_parse_parameters(ZEND_NUM_ARGS(), "olll", &pv_handle, &pv_which, &pv_opt, &pv_val) == FAILURE) {
2774 RETURN_THROWS();
2775 }
2776
2777 switch (pv_which) {
2778 case 1: /* SQLSetConnectOption */
2779 if (!instanceof_function(Z_OBJCE_P(pv_handle), odbc_connection_ce)) {
2780 zend_argument_type_error(1, "must be of type Odbc\\Connection for SQLSetConnectOption()");
2781 RETURN_THROWS();
2782 }
2783 link = Z_ODBC_LINK_P(pv_handle);
2784 CHECK_ODBC_CONNECTION(link->connection);
2785
2786 if (link->persistent) {
2787 php_error_docref(NULL, E_WARNING, "Unable to set option for persistent connection");
2789 }
2790 rc = SQLSetConnectOption(link->connection->hdbc, (unsigned short) pv_opt, pv_val);
2791 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
2792 odbc_sql_error(link->connection, SQL_NULL_HSTMT, "SetConnectOption");
2794 }
2795 break;
2796 case 2: /* SQLSetStmtOption */
2797 if (!instanceof_function(Z_OBJCE_P(pv_handle), odbc_result_ce)) {
2798 zend_argument_type_error(1, "must be of type Odbc\\Result for SQLSetStmtOption()");
2799 RETURN_THROWS();
2800 }
2801 result = Z_ODBC_RESULT_P(pv_handle);
2802 CHECK_ODBC_RESULT(result);
2803
2804 rc = SQLSetStmtOption(result->stmt, (unsigned short) pv_opt, pv_val);
2805
2806 if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
2807 odbc_sql_error(result->conn_ptr, result->stmt, "SetStmtOption");
2809 }
2810 break;
2811 default:
2812 zend_argument_value_error(2, "must be 1 for SQLSetConnectOption(), or 2 for SQLSetStmtOption()");
2813 RETURN_THROWS();
2814 }
2815
2817}
2818/* }}} */
2819
2820/*
2821 * metadata functions
2822 */
2823
2824/* {{{ Call the SQLTables function */
2826{
2827 zval *pv_conn;
2829 char *cat = NULL, *schema = NULL, *table = NULL, *type = NULL;
2830 size_t cat_len = 0, schema_len = 0, table_len = 0, type_len = 0;
2831 RETCODE rc;
2832
2833 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!s!", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
2834 &table, &table_len, &type, &type_len) == FAILURE) {
2835 RETURN_THROWS();
2836 }
2837
2838 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
2839 CHECK_ODBC_CONNECTION(conn);
2840
2841 object_init_ex(return_value, odbc_result_ce);
2842 result = Z_ODBC_RESULT_P(return_value);
2843
2844 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
2845 if (rc == SQL_INVALID_HANDLE) {
2846 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
2849 }
2850
2851 if (rc == SQL_ERROR) {
2852 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
2855 }
2856
2857 /* This hack is needed to access table information in Access databases (fmk) */
2858 if (schema && schema_len == 0 && table && table_len) {
2859 schema = NULL;
2860 }
2861
2862 rc = SQLTables(result->stmt,
2863 (SQLCHAR *) cat, SAFE_SQL_NTS(cat),
2864 (SQLCHAR *) schema, SAFE_SQL_NTS(schema),
2865 (SQLCHAR *) table, SAFE_SQL_NTS(table),
2866 (SQLCHAR *) type, SAFE_SQL_NTS(type));
2867
2868 if (rc == SQL_ERROR) {
2869 odbc_sql_error(conn, result->stmt, "SQLTables");
2872 }
2873
2874 result->numparams = 0;
2875 SQLNumResultCols(result->stmt, &(result->numcols));
2876
2877 if (result->numcols > 0) {
2878 odbc_bindcols(result);
2879 } else {
2880 result->values = NULL;
2881 }
2882 result->conn_ptr = conn;
2883 result->fetched = 0;
2884
2885 odbc_insert_new_result(conn, return_value);
2886}
2887/* }}} */
2888
2889/* {{{ Returns a result identifier that can be used to fetch a list of column names in specified tables */
2891{
2892 zval *pv_conn;
2894 char *cat = NULL, *schema = NULL, *table = NULL, *column = NULL;
2895 size_t cat_len = 0, schema_len = 0, table_len = 0, column_len = 0;
2896 RETCODE rc;
2897
2898 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!s!", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
2899 &table, &table_len, &column, &column_len) == FAILURE) {
2900 RETURN_THROWS();
2901 }
2902
2903 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
2904 CHECK_ODBC_CONNECTION(conn);
2905
2906 object_init_ex(return_value, odbc_result_ce);
2907 result = Z_ODBC_RESULT_P(return_value);
2908
2909 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
2910 if (rc == SQL_INVALID_HANDLE) {
2911 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
2914 }
2915
2916 if (rc == SQL_ERROR) {
2917 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
2920 }
2921
2922 /*
2923 * Needed to make MS Access happy
2924 */
2925 if (table && table_len && schema && schema_len == 0) {
2926 schema = NULL;
2927 }
2928
2929 rc = SQLColumns(result->stmt,
2930 (SQLCHAR *) cat, (SQLSMALLINT) cat_len,
2931 (SQLCHAR *) schema, (SQLSMALLINT) schema_len,
2932 (SQLCHAR *) table, (SQLSMALLINT) table_len,
2933 (SQLCHAR *) column, (SQLSMALLINT) column_len);
2934
2935 if (rc == SQL_ERROR) {
2936 odbc_sql_error(conn, result->stmt, "SQLColumns");
2939 }
2940
2941 result->numparams = 0;
2942 SQLNumResultCols(result->stmt, &(result->numcols));
2943
2944 if (result->numcols > 0) {
2945 odbc_bindcols(result);
2946 } else {
2947 result->values = NULL;
2948 }
2949 result->conn_ptr = conn;
2950 result->fetched = 0;
2951
2952 odbc_insert_new_result(conn, return_value);
2953}
2954/* }}} */
2955
2956#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
2957/* {{{ Returns a result identifier that can be used to fetch a list of columns and associated privileges for the specified table */
2959{
2960 zval *pv_conn;
2962 char *cat = NULL, *schema, *table, *column;
2963 size_t cat_len = 0, schema_len, table_len, column_len;
2964 RETCODE rc;
2965
2966 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!sss", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
2967 &table, &table_len, &column, &column_len) == FAILURE) {
2968 RETURN_THROWS();
2969 }
2970
2971 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
2972 CHECK_ODBC_CONNECTION(conn);
2973
2974 object_init_ex(return_value, odbc_result_ce);
2975 result = Z_ODBC_RESULT_P(return_value);
2976
2977 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
2978 if (rc == SQL_INVALID_HANDLE) {
2979 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
2982 }
2983
2984 if (rc == SQL_ERROR) {
2985 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
2988 }
2989
2990 rc = SQLColumnPrivileges(result->stmt,
2991 (SQLCHAR *) cat, SAFE_SQL_NTS(cat),
2992 (SQLCHAR *) schema, SAFE_SQL_NTS(schema),
2993 (SQLCHAR *) table, SAFE_SQL_NTS(table),
2994 (SQLCHAR *) column, SAFE_SQL_NTS(column));
2995
2996 if (rc == SQL_ERROR) {
2997 odbc_sql_error(conn, result->stmt, "SQLColumnPrivileges");
3000 }
3001
3002 result->numparams = 0;
3003 SQLNumResultCols(result->stmt, &(result->numcols));
3004
3005 if (result->numcols > 0) {
3006 odbc_bindcols(result);
3007 } else {
3008 result->values = NULL;
3009 }
3010 result->conn_ptr = conn;
3011 result->fetched = 0;
3012
3013 odbc_insert_new_result(conn, return_value);
3014}
3015/* }}} */
3016#endif /* HAVE_DBMAKER || HAVE_SOLID*/
3017
3018#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
3019/* {{{ 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 */
3021{
3022 zval *pv_conn;
3024 char *pcat = NULL, *pschema, *ptable, *fcat, *fschema, *ftable;
3025 size_t pcat_len = 0, pschema_len, ptable_len, fcat_len, fschema_len, ftable_len;
3026 RETCODE rc;
3027
3028 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!sssss", &pv_conn, odbc_connection_ce, &pcat, &pcat_len, &pschema, &pschema_len,
3029 &ptable, &ptable_len, &fcat, &fcat_len, &fschema, &fschema_len, &ftable, &ftable_len) == FAILURE) {
3030 RETURN_THROWS();
3031 }
3032
3033#if defined(HAVE_DBMAKER) || defined(HAVE_IBMDB2)
3034#define EMPTY_TO_NULL(xstr) \
3035 if ((int)strlen((xstr)) == 0) (xstr) = NULL
3036
3037 EMPTY_TO_NULL(pcat);
3038 EMPTY_TO_NULL(pschema);
3039 EMPTY_TO_NULL(ptable);
3040 EMPTY_TO_NULL(fcat);
3041 EMPTY_TO_NULL(fschema);
3042 EMPTY_TO_NULL(ftable);
3043#endif
3044
3045 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
3046 CHECK_ODBC_CONNECTION(conn);
3047
3048 object_init_ex(return_value, odbc_result_ce);
3049 result = Z_ODBC_RESULT_P(return_value);
3050
3051 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
3052 if (rc == SQL_INVALID_HANDLE) {
3053 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
3056 }
3057
3058 if (rc == SQL_ERROR) {
3059 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
3062 }
3063
3064 rc = SQLForeignKeys(result->stmt,
3065 (SQLCHAR *) pcat, SAFE_SQL_NTS(pcat),
3066 (SQLCHAR *) pschema, SAFE_SQL_NTS(pschema),
3067 (SQLCHAR *) ptable, SAFE_SQL_NTS(ptable),
3068 (SQLCHAR *) fcat, SAFE_SQL_NTS(fcat),
3069 (SQLCHAR *) fschema, SAFE_SQL_NTS(fschema),
3070 (SQLCHAR *) ftable, SAFE_SQL_NTS(ftable) );
3071
3072 if (rc == SQL_ERROR) {
3073 odbc_sql_error(conn, result->stmt, "SQLForeignKeys");
3076 }
3077
3078 result->numparams = 0;
3079 SQLNumResultCols(result->stmt, &(result->numcols));
3080
3081 if (result->numcols > 0) {
3082 odbc_bindcols(result);
3083 } else {
3084 result->values = NULL;
3085 }
3086 result->conn_ptr = conn;
3087 result->fetched = 0;
3088
3089 odbc_insert_new_result(conn, return_value);
3090}
3091/* }}} */
3092#endif /* HAVE_SOLID */
3093
3094/* {{{ Returns a result identifier containing information about data types supported by the data source */
3096{
3097 zval *pv_conn;
3098 zend_long pv_data_type = SQL_ALL_TYPES;
3100 RETCODE rc;
3101 SQLSMALLINT data_type;
3102
3103 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &pv_conn, odbc_connection_ce, &pv_data_type) == FAILURE) {
3104 RETURN_THROWS();
3105 }
3106
3107 data_type = (SQLSMALLINT) pv_data_type;
3108
3109 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
3110 CHECK_ODBC_CONNECTION(conn);
3111
3112 object_init_ex(return_value, odbc_result_ce);
3113 result = Z_ODBC_RESULT_P(return_value);
3114
3115 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
3116 if (rc == SQL_INVALID_HANDLE) {
3117 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
3120 }
3121
3122 if (rc == SQL_ERROR) {
3123 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
3126 }
3127
3128 rc = SQLGetTypeInfo(result->stmt, data_type );
3129
3130 if (rc == SQL_ERROR) {
3131 odbc_sql_error(conn, result->stmt, "SQLGetTypeInfo");
3134 }
3135
3136 result->numparams = 0;
3137 SQLNumResultCols(result->stmt, &(result->numcols));
3138
3139 if (result->numcols > 0) {
3140 odbc_bindcols(result);
3141 } else {
3142 result->values = NULL;
3143 }
3144 result->conn_ptr = conn;
3145 result->fetched = 0;
3146
3147 odbc_insert_new_result(conn, return_value);
3148}
3149/* }}} */
3150
3151/* {{{ Returns a result identifier listing the column names that comprise the primary key for a table */
3153{
3154 zval *pv_conn;
3156 char *cat = NULL, *schema = NULL, *table = NULL;
3157 size_t cat_len = 0, schema_len, table_len;
3158 RETCODE rc;
3159
3160 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!ss", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
3161 RETURN_THROWS();
3162 }
3163
3164 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
3165 CHECK_ODBC_CONNECTION(conn);
3166
3167 object_init_ex(return_value, odbc_result_ce);
3168 result = Z_ODBC_RESULT_P(return_value);
3169
3170 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
3171 if (rc == SQL_INVALID_HANDLE) {
3172 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
3175 }
3176
3177 if (rc == SQL_ERROR) {
3178 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
3181 }
3182
3183 rc = SQLPrimaryKeys(result->stmt,
3184 (SQLCHAR *) cat, SAFE_SQL_NTS(cat),
3185 (SQLCHAR *) schema, SAFE_SQL_NTS(schema),
3186 (SQLCHAR *) table, SAFE_SQL_NTS(table) );
3187
3188 if (rc == SQL_ERROR) {
3189 odbc_sql_error(conn, result->stmt, "SQLPrimaryKeys");
3192 }
3193
3194 result->numparams = 0;
3195 SQLNumResultCols(result->stmt, &(result->numcols));
3196
3197 if (result->numcols > 0) {
3198 odbc_bindcols(result);
3199 } else {
3200 result->values = NULL;
3201 }
3202 result->conn_ptr = conn;
3203 result->fetched = 0;
3204
3205 odbc_insert_new_result(conn, return_value);
3206}
3207/* }}} */
3208
3209#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
3210/* {{{ 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 */
3212{
3213 zval *pv_conn;
3215 char *cat = NULL, *schema = NULL, *proc = NULL, *col = NULL;
3216 size_t cat_len = 0, schema_len = 0, proc_len = 0, col_len = 0;
3217 RETCODE rc;
3218
3219 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!s!", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
3220 &proc, &proc_len, &col, &col_len) == FAILURE) {
3221 RETURN_THROWS();
3222 }
3223
3224 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
3225 CHECK_ODBC_CONNECTION(conn);
3226
3227 object_init_ex(return_value, odbc_result_ce);
3228 result = Z_ODBC_RESULT_P(return_value);
3229
3230 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
3231 if (rc == SQL_INVALID_HANDLE) {
3232 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
3235 }
3236
3237 if (rc == SQL_ERROR) {
3238 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
3241 }
3242
3243 rc = SQLProcedureColumns(result->stmt,
3244 (SQLCHAR *) cat, SAFE_SQL_NTS(cat),
3245 (SQLCHAR *) schema, SAFE_SQL_NTS(schema),
3246 (SQLCHAR *) proc, SAFE_SQL_NTS(proc),
3247 (SQLCHAR *) col, SAFE_SQL_NTS(col) );
3248
3249 if (rc == SQL_ERROR) {
3250 odbc_sql_error(conn, result->stmt, "SQLProcedureColumns");
3253 }
3254
3255 result->numparams = 0;
3256 SQLNumResultCols(result->stmt, &(result->numcols));
3257
3258 if (result->numcols > 0) {
3259 odbc_bindcols(result);
3260 } else {
3261 result->values = NULL;
3262 }
3263 result->conn_ptr = conn;
3264 result->fetched = 0;
3265
3266 odbc_insert_new_result(conn, return_value);
3267}
3268/* }}} */
3269#endif /* HAVE_SOLID */
3270
3271#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
3272/* {{{ Returns a result identifier containing the list of procedure names in a datasource */
3274{
3275 zval *pv_conn;
3277 char *cat = NULL, *schema = NULL, *proc = NULL;
3278 size_t cat_len = 0, schema_len = 0, proc_len = 0;
3279 RETCODE rc;
3280
3281 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len, &proc, &proc_len) == FAILURE) {
3282 RETURN_THROWS();
3283 }
3284
3285 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
3286 CHECK_ODBC_CONNECTION(conn);
3287
3288 object_init_ex(return_value, odbc_result_ce);
3289 result = Z_ODBC_RESULT_P(return_value);
3290
3291 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
3292 if (rc == SQL_INVALID_HANDLE) {
3293 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
3296 }
3297
3298 if (rc == SQL_ERROR) {
3299 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
3302 }
3303
3304 rc = SQLProcedures(result->stmt,
3305 (SQLCHAR *) cat, SAFE_SQL_NTS(cat),
3306 (SQLCHAR *) schema, SAFE_SQL_NTS(schema),
3307 (SQLCHAR *) proc, SAFE_SQL_NTS(proc) );
3308
3309 if (rc == SQL_ERROR) {
3310 odbc_sql_error(conn, result->stmt, "SQLProcedures");
3313 }
3314
3315 result->numparams = 0;
3316 SQLNumResultCols(result->stmt, &(result->numcols));
3317
3318 if (result->numcols > 0) {
3319 odbc_bindcols(result);
3320 } else {
3321 result->values = NULL;
3322 }
3323 result->conn_ptr = conn;
3324 result->fetched = 0;
3325
3326 odbc_insert_new_result(conn, return_value);
3327}
3328/* }}} */
3329#endif /* HAVE_SOLID */
3330
3331/* {{{ 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 */
3333{
3334 zval *pv_conn;
3335 zend_long vtype, vscope, vnullable;
3337 char *cat = NULL, *schema = NULL, *name = NULL;
3338 size_t cat_len = 0, schema_len, name_len;
3339 SQLUSMALLINT type, scope, nullable;
3340 RETCODE rc;
3341
3342 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ols!ssll", &pv_conn, odbc_connection_ce, &vtype, &cat, &cat_len, &schema, &schema_len,
3343 &name, &name_len, &vscope, &vnullable) == FAILURE) {
3344 RETURN_THROWS();
3345 }
3346
3347 type = (SQLUSMALLINT) vtype;
3348 scope = (SQLUSMALLINT) vscope;
3349 nullable = (SQLUSMALLINT) vnullable;
3350
3351 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
3352 CHECK_ODBC_CONNECTION(conn);
3353
3354 object_init_ex(return_value, odbc_result_ce);
3355 result = Z_ODBC_RESULT_P(return_value);
3356
3357 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
3358 if (rc == SQL_INVALID_HANDLE) {
3359 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
3362 }
3363
3364 if (rc == SQL_ERROR) {
3365 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
3368 }
3369
3370 rc = SQLSpecialColumns(result->stmt, type,
3371 (SQLCHAR *) cat, SAFE_SQL_NTS(cat),
3372 (SQLCHAR *) schema, SAFE_SQL_NTS(schema),
3373 (SQLCHAR *) name, SAFE_SQL_NTS(name),
3374 scope,
3375 nullable);
3376
3377 if (rc == SQL_ERROR) {
3378 odbc_sql_error(conn, result->stmt, "SQLSpecialColumns");
3381 }
3382
3383 result->numparams = 0;
3384 SQLNumResultCols(result->stmt, &(result->numcols));
3385
3386 if (result->numcols > 0) {
3387 odbc_bindcols(result);
3388 } else {
3389 result->values = NULL;
3390 }
3391 result->conn_ptr = conn;
3392 result->fetched = 0;
3393
3394 odbc_insert_new_result(conn, return_value);
3395}
3396/* }}} */
3397
3398/* {{{ Returns a result identifier that contains statistics about a single table and the indexes associated with the table */
3400{
3401 zval *pv_conn;
3402 zend_long vunique, vreserved;
3404 char *cat = NULL, *schema, *name;
3405 size_t cat_len = 0, schema_len, name_len;
3406 SQLUSMALLINT unique, reserved;
3407 RETCODE rc;
3408
3409 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!ssll", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len,
3410 &name, &name_len, &vunique, &vreserved) == FAILURE) {
3411 RETURN_THROWS();
3412 }
3413
3414 unique = (SQLUSMALLINT) vunique;
3415 reserved = (SQLUSMALLINT) vreserved;
3416
3417 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
3418 CHECK_ODBC_CONNECTION(conn);
3419
3420 object_init_ex(return_value, odbc_result_ce);
3421 result = Z_ODBC_RESULT_P(return_value);
3422
3423 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
3424 if (rc == SQL_INVALID_HANDLE) {
3425 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
3428 }
3429
3430 if (rc == SQL_ERROR) {
3431 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
3434 }
3435
3436 rc = SQLStatistics(result->stmt,
3437 (SQLCHAR *) cat, SAFE_SQL_NTS(cat),
3438 (SQLCHAR *) schema, SAFE_SQL_NTS(schema),
3439 (SQLCHAR *) name, SAFE_SQL_NTS(name),
3440 unique,
3441 reserved);
3442
3443 if (rc == SQL_ERROR) {
3444 odbc_sql_error(conn, result->stmt, "SQLStatistics");
3447 }
3448
3449 result->numparams = 0;
3450 SQLNumResultCols(result->stmt, &(result->numcols));
3451
3452 if (result->numcols > 0) {
3453 odbc_bindcols(result);
3454 } else {
3455 result->values = NULL;
3456 }
3457 result->conn_ptr = conn;
3458 result->fetched = 0;
3459
3460 odbc_insert_new_result(conn, return_value);
3461}
3462/* }}} */
3463
3464#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
3465/* {{{ Returns a result identifier containing a list of tables and the privileges associated with each table */
3467{
3468 zval *pv_conn;
3470 char *cat = NULL, *schema = NULL, *table = NULL;
3471 size_t cat_len = 0, schema_len, table_len;
3472 RETCODE rc;
3473
3474 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os!ss", &pv_conn, odbc_connection_ce, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
3475 RETURN_THROWS();
3476 }
3477
3478 odbc_connection *conn = Z_ODBC_CONNECTION_P(pv_conn);
3479 CHECK_ODBC_CONNECTION(conn);
3480
3481 object_init_ex(return_value, odbc_result_ce);
3482 result = Z_ODBC_RESULT_P(return_value);
3483
3484 rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
3485 if (rc == SQL_INVALID_HANDLE) {
3486 php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
3489 }
3490
3491 if (rc == SQL_ERROR) {
3492 odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
3495 }
3496
3497 rc = SQLTablePrivileges(result->stmt,
3498 (SQLCHAR *) cat, SAFE_SQL_NTS(cat),
3499 (SQLCHAR *) schema, SAFE_SQL_NTS(schema),
3500 (SQLCHAR *) table, SAFE_SQL_NTS(table));
3501
3502 if (rc == SQL_ERROR) {
3503 odbc_sql_error(conn, result->stmt, "SQLTablePrivileges");
3506 }
3507
3508 result->numparams = 0;
3509 SQLNumResultCols(result->stmt, &(result->numcols));
3510
3511 if (result->numcols > 0) {
3512 odbc_bindcols(result);
3513 } else {
3514 result->values = NULL;
3515 }
3516 result->conn_ptr = conn;
3517 result->fetched = 0;
3518
3519 odbc_insert_new_result(conn, return_value);
3520}
3521/* }}} */
3522#endif /* HAVE_DBMAKER */
3523
3524#endif /* HAVE_UODBC */
size_t len
Definition apprentice.c:174
putenv(string $assignment)
strstr(string $haystack, string $needle, bool $before_needle=false)
link(string $target, string $link)
DNS_STATUS status
Definition dns_win32.c:49
error($message)
Definition ext_skel.php:22
zend_ffi_type * type
Definition ffi.c:3812
zval * zv
Definition ffi.c:3975
DL_HANDLE handle
Definition ffi.c:3028
ctype
Definition ffi.c:4208
zend_string * res
Definition ffi.c:4692
memcpy(ptr1, ptr2, size)
char * err
Definition ffi.c:3029
memset(ptr, 0, type->size)
ffi persistent
Definition ffi.c:3633
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
PHPAPI int php_check_open_basedir(const char *path)
char * mode
#define NULL
Definition gdcache.h:45
hash(string $algo, string $data, bool $binary=false, array $options=[])
Definition hash.stub.php:12
#define SUCCESS
Definition hash_sha3.c:261
foreach($dp as $el) foreach( $dp as $el) if( $pass2< 2) echo ""
PHPAPI size_t php_printf(const char *format,...)
Definition main.c:938
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
const SQL_CURSOR_DYNAMIC
odbc_longreadlen(Odbc\Result $statement, int $length)
odbc_field_len(Odbc\Result $statement, int $field)
odbc_foreignkeys(Odbc\Connection $odbc, ?string $pk_catalog, string $pk_schema, string $pk_table, string $fk_catalog, string $fk_schema, string $fk_table)
odbc_error(?Odbc\Connection $odbc=null)
const SQL_CURSOR_TYPE
Definition odbc.stub.php:98
odbc_specialcolumns(Odbc\Connection $odbc, int $type, ?string $catalog, string $schema, string $table, int $scope, int $nullable)
const SQL_WLONGVARCHAR
const SQL_WCHAR
const SQL_LONGVARCHAR
odbc_gettypeinfo(Odbc\Connection $odbc, int $data_type=0)
odbc_free_result(Odbc\Result $statement)
odbc_commit(Odbc\Connection $odbc)
const SQL_FETCH_FIRST
const SQL_TIMESTAMP
const ODBC_TYPE
Definition odbc.stub.php:28
const SQL_CURSOR_KEYSET_DRIVEN
odbc_data_source(Odbc\Connection $odbc, int $fetch_type)
const SQL_CUR_USE_IF_NEEDED
Definition odbc.stub.php:61
odbc_rollback(Odbc\Connection $odbc)
odbc_setoption(Odbc\Connection|Odbc\Result $odbc, int $which, int $option, int $value)
odbc_field_scale(Odbc\Result $statement, int $field)
odbc_pconnect(string $dsn, ?string $user=null, #[\SensitiveParameter] ?string $password=null, int $cursor_option=SQL_CUR_USE_DRIVER)
odbc_autocommit(Odbc\Connection $odbc, ?bool $enable=null)
odbc_field_type(Odbc\Result $statement, int $field)
odbc_tableprivileges(Odbc\Connection $odbc, ?string $catalog, string $schema, string $table)
odbc_connect(string $dsn, ?string $user=null, #[\SensitiveParameter] ?string $password=null, int $cursor_option=SQL_CUR_USE_DRIVER)
const SQL_VARBINARY
const SQL_WVARCHAR
const SQL_CUR_USE_DRIVER
Definition odbc.stub.php:56
odbc_columnprivileges(Odbc\Connection $odbc, ?string $catalog, string $schema, string $table, string $column)
odbc_num_fields(Odbc\Result $statement)
odbc_fetch_object(Odbc\Result $statement, ?int $row=null)
odbc_close(Odbc\Connection $odbc)
odbc_procedures(Odbc\Connection $odbc, ?string $catalog=null, ?string $schema=null, ?string $procedure=null)
odbc_procedurecolumns(Odbc\Connection $odbc, ?string $catalog=null, ?string $schema=null, ?string $procedure=null, ?string $column=null)
const SQL_VARCHAR
odbc_close_all()
odbc_fetch_into(Odbc\Result $statement, &$array, ?int $row=null)
odbc_result(Odbc\Result $statement, string|int $field)
odbc_result_all(Odbc\Result $statement, string $format="")
odbc_num_rows(Odbc\Result $statement)
odbc_statistics(Odbc\Connection $odbc, ?string $catalog, string $schema, string $table, int $unique, int $accuracy)
odbc_fetch_array(Odbc\Result $statement, ?int $row=null)
odbc_columns(Odbc\Connection $odbc, ?string $catalog=null, ?string $schema=null, ?string $table=null, ?string $column=null)
const SQL_CURSOR_STATIC
odbc_field_name(Odbc\Result $statement, int $field)
const SQL_BINARY
odbc_tables(Odbc\Connection $odbc, ?string $catalog=null, ?string $schema=null, ?string $table=null, ?string $types=null)
odbc_execute(Odbc\Result $statement, array $params=[])
const SQL_CURSOR_FORWARD_ONLY
odbc_cursor(Odbc\Result $statement)
odbc_binmode(Odbc\Result $statement, int $mode)
odbc_prepare(Odbc\Connection $odbc, string $query)
odbc_exec(Odbc\Connection $odbc, string $query)
const SQL_CHAR
const SQL_FETCH_NEXT
odbc_primarykeys(Odbc\Connection $odbc, ?string $catalog, string $schema, string $table)
const SQL_CUR_USE_ODBC
Definition odbc.stub.php:66
const SQL_LONGVARBINARY
const SQL_ODBC_CURSORS
Definition odbc.stub.php:51
odbc_fetch_row(Odbc\Result $statement, ?int $row=null)
odbc_field_num(Odbc\Result $statement, string $field)
odbc_errormsg(?Odbc\Connection $odbc=null)
odbc_next_result(Odbc\Result $statement)
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_GINIT
Definition php.h:397
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MSHUTDOWN_FUNCTION
Definition php.h:401
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_CONNECTION_TIMEOUT
Definition php.h:428
#define php_memnistr
Definition php.h:344
#define PHP_RINIT
Definition php.h:394
#define PHP_MSHUTDOWN
Definition php.h:393
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_GINIT_FUNCTION
Definition php.h:405
#define PHP_RSHUTDOWN
Definition php.h:395
#define PHP_RINIT_FUNCTION
Definition php.h:402
#define PHP_RSHUTDOWN_FUNCTION
Definition php.h:403
#define PHP_GSHUTDOWN_FUNCTION
Definition php.h:406
#define PHP_MINIT
Definition php.h:392
#define PHP_MODULE_GLOBALS
Definition php.h:408
#define PHP_GSHUTDOWN
Definition php.h:398
#define PG(v)
Definition php_globals.h:31
#define STD_PHP_INI_ENTRY_EX
Definition php_ini.h:65
#define PHP_INI_ALL
Definition php_ini.h:45
#define PHP_INI_BEGIN
Definition php_ini.h:52
#define STD_PHP_INI_BOOLEAN
Definition php_ini.h:66
#define PHP_INI_SYSTEM
Definition php_ini.h:43
#define PHP_INI_DISP
Definition php_ini.h:50
#define PHP_INI_DISPLAY_ORIG
Definition php_ini.h:68
#define PHP_INI_END
Definition php_ini.h:53
zend_long num_links
Definition php_ldap.h:40
zend_long max_links
Definition php_ldap.h:41
zend_long max_persistent
bool allow_persistent
PHPAPI size_t php_odbc_connstr_estimate_quote_length(const char *in_str)
PHPAPI bool php_odbc_connstr_is_quoted(const char *str)
PHPAPI size_t php_odbc_connstr_quote(char *out_str, const char *in_str, size_t out_str_size)
PHPAPI bool php_odbc_connstr_should_quote(const char *str)
#define PHPWRITE(str, str_len)
#define PUTS(str)
#define SQLCHAR
#define UCHAR(x)
Definition scanf.c:92
p
Definition session.c:1105
#define spprintf
Definition spprintf.h:29
zend_object *(* create_object)(zend_class_entry *class_type)
Definition zend.h:195
const zend_object_handlers * default_object_handlers
Definition zend.h:186
unsigned char type
zend_object_compare_t compare
zend_object_free_obj_t free_obj
zend_object_cast_t cast_object
zend_object_get_constructor_t get_constructor
zend_object_clone_obj_t clone_obj
uint32_t handle
Definition zend_types.h:558
#define close(a)
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
#define ZEND_TSRMLS_CACHE_UPDATE()
Definition zend.h:69
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
#define ZEND_TSRMLS_CACHE_DEFINE()
Definition zend.h:68
#define ZEND_STANDARD_CLASS_DEF_PTR
Definition zend.h:406
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties)
Definition zend_API.c:1843
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
ZEND_API void add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str)
Definition zend_API.c:1982
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:423
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define RETURN_STRINGL(s, l)
Definition zend_API.h:1044
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define RETVAL_STRING(s)
Definition zend_API.h:1017
#define RETURN_NULL()
Definition zend_API.h:1036
#define ZEND_DECLARE_MODULE_GLOBALS(module_name)
Definition zend_API.h:268
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define ZEND_GET_MODULE(name)
Definition zend_API.h:241
#define zend_parse_parameters_none()
Definition zend_API.h:353
#define Z_PARAM_STRING(dest, dest_len)
Definition zend_API.h:2071
#define Z_PARAM_STRING_OR_NULL(dest, dest_len)
Definition zend_API.h:2074
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define Z_PARAM_LONG(dest)
Definition zend_API.h:1896
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_NEW_STR(s)
Definition zend_API.h:1041
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETVAL_TRUE
Definition zend_API.h:1033
#define Z_PARAM_STR_OR_LONG(dest_str, dest_long)
Definition zend_API.h:2165
#define Z_PARAM_OBJECT_OF_CLASS(dest, _ce)
Definition zend_API.h:1976
#define ZVAL_STRINGL(z, s, l)
Definition zend_API.h:952
#define RETVAL_FALSE
Definition zend_API.h:1032
#define RETURN_TRUE
Definition zend_API.h:1059
#define array_init(arg)
Definition zend_API.h:537
#define ZVAL_EMPTY_STRING(z)
Definition zend_API.h:961
#define estrndup(s, length)
Definition zend_alloc.h:165
#define efree(ptr)
Definition zend_alloc.h:155
#define pefree(ptr, persistent)
Definition zend_alloc.h:191
#define safe_emalloc(nmemb, size, offset)
Definition zend_alloc.h:154
#define pecalloc(nmemb, size, persistent)
Definition zend_alloc.h:200
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
strncmp(string $string1, string $string2, int $length)
defined(string $constant_name)
zend_string_release_ex(func->internal_function.function_name, 0)
execute_data func
#define strcasecmp(s1, s2)
#define snprintf
#define E_WARNING
Definition zend_errors.h:24
union _zend_function zend_function
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_func)
Definition zend_hash.c:2059
ZEND_API zval *ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:2689
ZEND_API zval *ZEND_FASTCALL zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData)
Definition zend_hash.c:1214
ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
Definition zend_hash.c:2099
ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
Definition zend_hash.c:1869
ZEND_API zend_result ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h)
Definition zend_hash.c:1692
ZEND_API zval *ZEND_FASTCALL zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData)
Definition zend_hash.c:1219
ZEND_API zval *ZEND_FASTCALL zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData)
Definition zend_hash.c:1031
ZEND_API zval *ZEND_FASTCALL zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData)
Definition zend_hash.c:1052
ZEND_API zval *ZEND_FASTCALL zend_hash_update(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:997
ZEND_API zend_result ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
Definition zend_hash.c:1534
ZEND_API zend_result ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:1661
ZEND_API const HashTable zend_empty_array
Definition zend_hash.c:248
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HASH_APPLY_REMOVE
Definition zend_hash.h:147
#define ZEND_HASH_APPLY_KEEP
Definition zend_hash.h:146
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
#define ZEND_HASH_FOREACH_VAL(ht, _val)
Definition zend_hash.h:1102
#define UNREGISTER_INI_ENTRIES()
Definition zend_ini.h:204
#define REGISTER_INI_ENTRIES()
Definition zend_ini.h:203
#define DISPLAY_INI_ENTRIES()
Definition zend_ini.h:205
ZEND_API zend_resource * zend_register_persistent_resource(const char *key, size_t key_len, void *rsrc_pointer, int rsrc_type)
Definition zend_list.c:342
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number)
Definition zend_list.c:265
#define ZEND_ULONG_FMT
Definition zend_long.h:88
int32_t zend_long
Definition zend_long.h:42
uint32_t zend_ulong
Definition zend_long.h:43
#define ZEND_LONG_FMT
Definition zend_long.h:87
struct _zend_string zend_string
#define STANDARD_MODULE_HEADER
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES_EX
ZEND_API zend_result zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type)
ZEND_API int zend_objects_not_comparable(zval *o1, zval *o2)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
#define ZEND_FALLTHROUGH
#define XtOffsetOf(s_type, field)
#define ZEND_ASSERT(c)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define ZVAL_FALSE(z)
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_NULL(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
struct _zend_resource zend_resource
Definition zend_types.h:99
struct _zend_array HashTable
Definition zend_types.h:386
#define IS_ARRAY
Definition zend_types.h:607
#define Z_STR(zval)
Definition zend_types.h:971
#define GC_MAKE_PERSISTENT_LOCAL(p)
#define Z_ADDREF_P(pz)
#define IS_NULL
Definition zend_types.h:601
#define Z_OBJCE_P(zval_p)
@ FAILURE
Definition zend_types.h:61
#define IS_OBJECT
Definition zend_types.h:608
#define IS_LONG
Definition zend_types.h:604
#define ZVAL_COPY(z, v)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define Z_RES_P(zval_p)
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define Z_TYPE(zval)
Definition zend_types.h:659
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
#define ZVAL_PTR_DTOR
zval * return_value
zend_string * name
bool result
zval * ret
value
new_op_array scope