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