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