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