1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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 : | Author: Ard Biesheuvel <abies@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: firebird_statement.c 284404 2009-07-20 00:17:24Z felipe $ */
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include "php.h"
26 : #include "php_ini.h"
27 : #include "ext/standard/info.h"
28 : #include "pdo/php_pdo.h"
29 : #include "pdo/php_pdo_driver.h"
30 : #include "php_pdo_firebird.h"
31 : #include "php_pdo_firebird_int.h"
32 :
33 : #include <time.h>
34 :
35 : #define RECORD_ERROR(stmt) _firebird_error(NULL, stmt, __FILE__, __LINE__ TSRMLS_CC)
36 :
37 : /* free the allocated space for passing field values to the db and back */
38 : static void free_sqlda(XSQLDA const *sqlda) /* {{{ */
39 76 : {
40 : int i;
41 :
42 196 : for (i = 0; i < sqlda->sqld; ++i) {
43 120 : XSQLVAR const *var = &sqlda->sqlvar[i];
44 :
45 120 : if (var->sqlind) {
46 91 : efree(var->sqlind);
47 : }
48 : }
49 76 : }
50 : /* }}} */
51 :
52 : /* called by PDO to clean up a statement handle */
53 : static int firebird_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
54 63 : {
55 63 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
56 63 : int result = 1, i;
57 :
58 : /* release the statement */
59 63 : if (isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_drop)) {
60 0 : RECORD_ERROR(stmt);
61 0 : result = 0;
62 : }
63 :
64 : /* clean up the fetch buffers if they have been used */
65 160 : for (i = 0; i < S->out_sqlda.sqld; ++i) {
66 97 : if (S->fetch_buf[i]) {
67 24 : efree(S->fetch_buf[i]);
68 : }
69 : }
70 63 : efree(S->fetch_buf);
71 :
72 63 : zend_hash_destroy(S->named_params);
73 63 : FREE_HASHTABLE(S->named_params);
74 :
75 : /* clean up the input descriptor */
76 63 : if (S->in_sqlda) {
77 13 : free_sqlda(S->in_sqlda);
78 13 : efree(S->in_sqlda);
79 : }
80 :
81 63 : free_sqlda(&S->out_sqlda);
82 63 : efree(S);
83 :
84 63 : return result;
85 : }
86 : /* }}} */
87 :
88 : /* called by PDO to execute a prepared query */
89 : static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
90 101 : {
91 101 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
92 101 : pdo_firebird_db_handle *H = S->H;
93 :
94 : do {
95 : /* named cursors should be closed first */
96 101 : if (*S->name && isc_dsql_free_statement(H->isc_status, &S->stmt, DSQL_close)) {
97 0 : break;
98 : }
99 :
100 : /* assume all params have been bound */
101 :
102 101 : if ((S->statement_type == isc_info_sql_stmt_exec_procedure &&
103 : isc_dsql_execute2(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION,
104 : S->in_sqlda, &S->out_sqlda))
105 : || isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION,
106 : S->in_sqlda)) {
107 : break;
108 : }
109 :
110 : /* commit? */
111 53 : if (stmt->dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
112 0 : break;
113 : }
114 :
115 53 : *S->name = 0;
116 53 : S->exhausted = 0;
117 :
118 53 : return 1;
119 : } while (0);
120 :
121 48 : RECORD_ERROR(stmt);
122 :
123 48 : return 0;
124 : }
125 : /* }}} */
126 :
127 : /* called by PDO to fetch the next row from a statement */
128 : static int firebird_stmt_fetch(pdo_stmt_t *stmt, /* {{{ */
129 : enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
130 156 : {
131 156 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
132 156 : pdo_firebird_db_handle *H = S->H;
133 :
134 156 : if (!stmt->executed) {
135 24 : strcpy(stmt->error_code, "HY000");
136 24 : H->last_app_error = "Cannot fetch from a closed cursor";
137 132 : } else if (!S->exhausted) {
138 :
139 : /* an EXECUTE PROCEDURE statement can be fetched from once, without calling the API, because
140 : * the result was returned in the execute call */
141 112 : if (S->statement_type == isc_info_sql_stmt_exec_procedure) {
142 0 : S->exhausted = 1;
143 : } else {
144 112 : if (isc_dsql_fetch(H->isc_status, &S->stmt, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
145 31 : if (H->isc_status[0] && H->isc_status[1]) {
146 0 : RECORD_ERROR(stmt);
147 : }
148 31 : S->exhausted = 1;
149 31 : return 0;
150 : }
151 : }
152 81 : return 1;
153 : }
154 44 : return 0;
155 : }
156 : /* }}} */
157 :
158 : /* called by PDO to retrieve information about the fields being returned */
159 : static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{ */
160 78 : {
161 78 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
162 78 : struct pdo_column_data *col = &stmt->columns[colno];
163 78 : XSQLVAR *var = &S->out_sqlda.sqlvar[colno];
164 :
165 : /* allocate storage for the column */
166 78 : var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short));
167 78 : var->sqldata = &((char*)var->sqlind)[sizeof(short)];
168 :
169 78 : col->precision = -var->sqlscale;
170 78 : col->maxlen = var->sqllen;
171 78 : col->namelen = var->aliasname_length;
172 78 : col->name = estrndup(var->aliasname,var->aliasname_length);
173 78 : col->param_type = PDO_PARAM_STR;
174 :
175 78 : return 1;
176 : }
177 : /* }}} */
178 :
179 : #define FETCH_BUF(buf,type,len,lenvar) ((buf) = (buf) ? (buf) : \
180 : emalloc((len) ? (len * sizeof(type)) : ((*(unsigned long*)lenvar) = sizeof(type))))
181 :
182 : #define CHAR_BUF_LEN 24
183 :
184 : /* fetch a blob into a fetch buffer */
185 : static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */
186 : unsigned long *len, ISC_QUAD *blob_id TSRMLS_DC)
187 0 : {
188 0 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
189 0 : pdo_firebird_db_handle *H = S->H;
190 0 : isc_blob_handle blobh = NULL;
191 0 : char const bl_item = isc_info_blob_total_length;
192 : char bl_info[20];
193 : unsigned short i;
194 0 : int result = *len = 0;
195 :
196 0 : if (isc_open_blob(H->isc_status, &H->db, &H->tr, &blobh, blob_id)) {
197 0 : RECORD_ERROR(stmt);
198 0 : return 0;
199 : }
200 :
201 0 : if (isc_blob_info(H->isc_status, &blobh, 1, const_cast(&bl_item),
202 : sizeof(bl_info), bl_info)) {
203 0 : RECORD_ERROR(stmt);
204 0 : goto fetch_blob_end;
205 : }
206 :
207 : /* find total length of blob's data */
208 0 : for (i = 0; i < sizeof(bl_info); ) {
209 : unsigned short item_len;
210 0 : char item = bl_info[i++];
211 :
212 0 : if (item == isc_info_end || item == isc_info_truncated || item == isc_info_error
213 : || i >= sizeof(bl_info)) {
214 0 : H->last_app_error = "Couldn't determine BLOB size";
215 0 : goto fetch_blob_end;
216 : }
217 :
218 0 : item_len = (unsigned short) isc_vax_integer(&bl_info[i], 2);
219 :
220 0 : if (item == isc_info_blob_total_length) {
221 0 : *len = isc_vax_integer(&bl_info[i+2], item_len);
222 0 : break;
223 : }
224 0 : i += item_len+2;
225 : }
226 :
227 : /* we've found the blob's length, now fetch! */
228 :
229 0 : if (*len) {
230 : unsigned long cur_len;
231 : unsigned short seg_len;
232 : ISC_STATUS stat;
233 :
234 0 : *ptr = S->fetch_buf[colno] = erealloc(*ptr, *len+1);
235 :
236 0 : for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) {
237 :
238 : unsigned short chunk_size = (*len-cur_len) > USHRT_MAX ? USHRT_MAX
239 0 : : (unsigned short)(*len-cur_len);
240 :
241 0 : stat = isc_get_segment(H->isc_status, &blobh, &seg_len, chunk_size, &(*ptr)[cur_len]);
242 : }
243 :
244 0 : (*ptr)[*len++] = '\0';
245 :
246 0 : if (H->isc_status[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) {
247 0 : H->last_app_error = "Error reading from BLOB";
248 0 : goto fetch_blob_end;
249 : }
250 : }
251 0 : result = 1;
252 :
253 0 : fetch_blob_end:
254 0 : if (isc_close_blob(H->isc_status, &blobh)) {
255 0 : RECORD_ERROR(stmt);
256 0 : return 0;
257 : }
258 0 : return result;
259 : }
260 : /* }}} */
261 :
262 : static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */
263 : unsigned long *len, int *caller_frees TSRMLS_DC)
264 182 : {
265 182 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
266 182 : XSQLVAR const *var = &S->out_sqlda.sqlvar[colno];
267 :
268 182 : if (*var->sqlind == -1) {
269 : /* A NULL value */
270 2 : *ptr = NULL;
271 2 : *len = 0;
272 : } else {
273 180 : if (var->sqlscale < 0) {
274 : static ISC_INT64 const scales[] = { 1, 10, 100, 1000,
275 : 10000,
276 : 100000,
277 : 1000000,
278 : 10000000,
279 : 100000000,
280 : 1000000000,
281 : LL_LIT(10000000000),
282 : LL_LIT(100000000000),
283 : LL_LIT(1000000000000),
284 : LL_LIT(10000000000000),
285 : LL_LIT(100000000000000),
286 : LL_LIT(1000000000000000),
287 : LL_LIT(10000000000000000),
288 : LL_LIT(100000000000000000),
289 : LL_LIT(1000000000000000000)
290 : };
291 0 : ISC_INT64 n, f = scales[-var->sqlscale];
292 :
293 0 : switch (var->sqltype & ~1) {
294 : case SQL_SHORT:
295 0 : n = *(short*)var->sqldata;
296 0 : break;
297 : case SQL_LONG:
298 0 : n = *(ISC_LONG*)var->sqldata;
299 0 : break;
300 : case SQL_INT64:
301 0 : n = *(ISC_INT64*)var->sqldata;
302 : }
303 :
304 0 : *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
305 :
306 0 : if (n >= 0) {
307 0 : *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
308 : n / f, -var->sqlscale, n % f);
309 0 : } else if (n < -f) {
310 0 : *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
311 : n / f, -var->sqlscale, -n % f);
312 : } else {
313 0 : *len = slprintf(*ptr, CHAR_BUF_LEN, "-0.%0*" LL_MASK "d", -var->sqlscale, -n % f);
314 : }
315 : } else {
316 180 : switch (var->sqltype & ~1) {
317 : struct tm t;
318 : char *fmt;
319 :
320 : case SQL_VARYING:
321 107 : *ptr = &var->sqldata[2];
322 107 : *len = *(short*)var->sqldata;
323 107 : break;
324 : case SQL_TEXT:
325 7 : *ptr = var->sqldata;
326 7 : *len = var->sqllen;
327 7 : break;
328 : case SQL_SHORT:
329 0 : *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
330 0 : *len = slprintf(*ptr, CHAR_BUF_LEN, "%d", *(short*)var->sqldata);
331 0 : break;
332 : case SQL_LONG:
333 66 : *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
334 66 : *len = slprintf(*ptr, CHAR_BUF_LEN, "%ld", *(ISC_LONG*)var->sqldata);
335 66 : break;
336 : case SQL_INT64:
337 0 : *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
338 0 : *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata);
339 0 : break;
340 : case SQL_FLOAT:
341 0 : *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
342 0 : *len = slprintf(*ptr, CHAR_BUF_LEN, "%F", *(float*)var->sqldata);
343 0 : break;
344 : case SQL_DOUBLE:
345 0 : *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
346 0 : *len = slprintf(*ptr, CHAR_BUF_LEN, "%F" , *(double*)var->sqldata);
347 0 : break;
348 : case SQL_TYPE_DATE:
349 0 : isc_decode_sql_date((ISC_DATE*)var->sqldata, &t);
350 0 : fmt = S->H->date_format ? S->H->date_format : PDO_FB_DEF_DATE_FMT;
351 : if (0) {
352 : case SQL_TYPE_TIME:
353 0 : isc_decode_sql_time((ISC_TIME*)var->sqldata, &t);
354 0 : fmt = S->H->time_format ? S->H->time_format : PDO_FB_DEF_TIME_FMT;
355 : } else if (0) {
356 : case SQL_TIMESTAMP:
357 0 : isc_decode_timestamp((ISC_TIMESTAMP*)var->sqldata, &t);
358 0 : fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT;
359 : }
360 :
361 : /* convert the timestamp into a string */
362 0 : *len = 80;
363 0 : *ptr = FETCH_BUF(S->fetch_buf[colno], char, *len, NULL);
364 0 : *len = strftime(*ptr, *len, fmt, &t);
365 0 : break;
366 : case SQL_BLOB:
367 0 : return firebird_fetch_blob(stmt,colno,ptr,len,
368 : (ISC_QUAD*)var->sqldata TSRMLS_CC);
369 : }
370 : }
371 : }
372 182 : return 1;
373 : }
374 : /* }}} */
375 :
376 : static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param TSRMLS_DC)
377 0 : {
378 0 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
379 0 : pdo_firebird_db_handle *H = S->H;
380 0 : isc_blob_handle h = NULL;
381 0 : unsigned long put_cnt = 0, rem_cnt;
382 : unsigned short chunk_size;
383 0 : int result = 1;
384 :
385 0 : if (isc_create_blob(H->isc_status, &H->db, &H->tr, &h, blob_id)) {
386 0 : RECORD_ERROR(stmt);
387 0 : return 0;
388 : }
389 :
390 0 : SEPARATE_ZVAL(¶m);
391 :
392 0 : convert_to_string_ex(¶m);
393 :
394 0 : for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size) {
395 :
396 0 : chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;
397 :
398 0 : if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL_P(param)[put_cnt])) {
399 0 : RECORD_ERROR(stmt);
400 0 : result = 0;
401 0 : break;
402 : }
403 0 : put_cnt += chunk_size;
404 : }
405 :
406 0 : zval_dtor(param);
407 :
408 0 : if (isc_close_blob(H->isc_status, &h)) {
409 0 : RECORD_ERROR(stmt);
410 0 : return 0;
411 : }
412 0 : return result;
413 : }
414 :
415 : static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, /* {{{ */
416 : enum pdo_param_event event_type TSRMLS_DC)
417 327 : {
418 327 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
419 327 : XSQLDA *sqlda = param->is_param ? S->in_sqlda : &S->out_sqlda;
420 : XSQLVAR *var;
421 :
422 327 : if (event_type == PDO_PARAM_EVT_FREE) { /* not used */
423 66 : return 1;
424 : }
425 :
426 261 : if (!sqlda || param->paramno >= sqlda->sqld) {
427 0 : strcpy(stmt->error_code, "HY093");
428 0 : S->H->last_app_error = "Invalid parameter index";
429 0 : return 0;
430 : }
431 261 : if (param->is_param && param->paramno == -1) {
432 : long *index;
433 :
434 : /* try to determine the index by looking in the named_params hash */
435 7 : if (SUCCESS == zend_hash_find(S->named_params, param->name, param->namelen+1, (void*)&index)) {
436 0 : param->paramno = *index;
437 : } else {
438 : /* ... or by looking in the input descriptor */
439 : int i;
440 :
441 14 : for (i = 0; i < sqlda->sqld; ++i) {
442 7 : XSQLVAR *var = &sqlda->sqlvar[i];
443 :
444 7 : if ((var->aliasname_length && !strncasecmp(param->name, var->aliasname,
445 : min(param->namelen, var->aliasname_length)))
446 : || (var->sqlname_length && !strncasecmp(param->name, var->sqlname,
447 : min(param->namelen, var->sqlname_length)))) {
448 0 : param->paramno = i;
449 0 : break;
450 : }
451 : }
452 7 : if (i >= sqlda->sqld) {
453 7 : strcpy(stmt->error_code, "HY093");
454 7 : S->H->last_app_error = "Invalid parameter name";
455 7 : return 0;
456 : }
457 : }
458 : }
459 :
460 254 : var = &sqlda->sqlvar[param->paramno];
461 :
462 254 : switch (event_type) {
463 : char *value;
464 : unsigned long value_len;
465 : int caller_frees;
466 :
467 : case PDO_PARAM_EVT_ALLOC:
468 66 : if (param->is_param) {
469 : /* allocate the parameter */
470 50 : if (var->sqlind) {
471 37 : efree(var->sqlind);
472 : }
473 50 : var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short));
474 50 : var->sqldata = &((char*)var->sqlind)[sizeof(short)];
475 : }
476 66 : break;
477 :
478 : case PDO_PARAM_EVT_EXEC_PRE:
479 73 : if (!param->is_param) {
480 30 : break;
481 : }
482 :
483 43 : *var->sqlind = 0;
484 :
485 43 : switch (var->sqltype & ~1) {
486 : case SQL_ARRAY:
487 0 : strcpy(stmt->error_code, "HY000");
488 0 : S->H->last_app_error = "Cannot bind to array field";
489 0 : return 0;
490 :
491 : case SQL_BLOB:
492 0 : return firebird_bind_blob(stmt, (ISC_QUAD*)var->sqldata,
493 : param->parameter TSRMLS_CC);
494 : }
495 :
496 : /* check if a NULL should be inserted */
497 43 : switch (Z_TYPE_P(param->parameter)) {
498 : int force_null;
499 :
500 : case IS_LONG:
501 0 : var->sqltype = sizeof(long) == 8 ? SQL_INT64 : SQL_LONG;
502 0 : var->sqldata = (void*)&Z_LVAL_P(param->parameter);
503 0 : var->sqllen = sizeof(long);
504 0 : break;
505 : case IS_DOUBLE:
506 0 : var->sqltype = SQL_DOUBLE;
507 0 : var->sqldata = (void*)&Z_DVAL_P(param->parameter);
508 0 : var->sqllen = sizeof(double);
509 0 : break;
510 : case IS_STRING:
511 42 : force_null = 0;
512 :
513 : /* for these types, an empty string can be handled like a NULL value */
514 42 : switch (var->sqltype & ~1) {
515 : case SQL_SHORT:
516 : case SQL_LONG:
517 : case SQL_INT64:
518 : case SQL_FLOAT:
519 : case SQL_DOUBLE:
520 : case SQL_TIMESTAMP:
521 : case SQL_TYPE_DATE:
522 : case SQL_TYPE_TIME:
523 3 : force_null = (Z_STRLEN_P(param->parameter) == 0);
524 : }
525 42 : if (!force_null) {
526 42 : var->sqltype = SQL_TEXT;
527 42 : var->sqldata = Z_STRVAL_P(param->parameter);
528 42 : var->sqllen = Z_STRLEN_P(param->parameter);
529 42 : break;
530 : }
531 : case IS_NULL:
532 : /* complain if this field doesn't allow NULL values */
533 0 : if (~var->sqltype & 1) {
534 0 : strcpy(stmt->error_code, "HY105");
535 0 : S->H->last_app_error = "Parameter requires non-null value";
536 0 : return 0;
537 : }
538 0 : *var->sqlind = -1;
539 0 : break;
540 : default:
541 1 : strcpy(stmt->error_code, "HY105");
542 1 : S->H->last_app_error = "Binding arrays/objects is not supported";
543 1 : return 0;
544 : }
545 42 : break;
546 :
547 : case PDO_PARAM_EVT_FETCH_POST:
548 0 : value = NULL;
549 0 : value_len = 0;
550 0 : caller_frees = 0;
551 :
552 0 : if (firebird_stmt_get_col(stmt, param->paramno, &value, &value_len, &caller_frees TSRMLS_CC)) {
553 0 : switch (PDO_PARAM_TYPE(param->param_type)) {
554 : case PDO_PARAM_STR:
555 0 : if (value) {
556 0 : ZVAL_STRINGL(param->parameter, value, value_len, 1);
557 0 : break;
558 : }
559 : case PDO_PARAM_INT:
560 0 : if (value) {
561 0 : ZVAL_LONG(param->parameter, *(long*)value);
562 0 : break;
563 : }
564 : default:
565 0 : ZVAL_NULL(param->parameter);
566 : }
567 0 : if (value && caller_frees) {
568 0 : efree(value);
569 : }
570 0 : return 1;
571 : }
572 0 : return 0;
573 : default:
574 : ;
575 : }
576 253 : return 1;
577 : }
578 : /* }}} */
579 :
580 : static int firebird_stmt_set_attribute(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC) /* {{{ */
581 0 : {
582 0 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
583 :
584 0 : switch (attr) {
585 : default:
586 0 : return 0;
587 : case PDO_ATTR_CURSOR_NAME:
588 0 : convert_to_string(val);
589 :
590 0 : if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, Z_STRVAL_P(val),0)) {
591 0 : RECORD_ERROR(stmt);
592 0 : return 0;
593 : }
594 0 : strlcpy(S->name, Z_STRVAL_P(val), sizeof(S->name));
595 : break;
596 : }
597 0 : return 1;
598 : }
599 : /* }}} */
600 :
601 : static int firebird_stmt_get_attribute(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC) /* {{{ */
602 0 : {
603 0 : pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
604 :
605 0 : switch (attr) {
606 : default:
607 0 : return 0;
608 : case PDO_ATTR_CURSOR_NAME:
609 0 : if (*S->name) {
610 0 : ZVAL_STRING(val,S->name,1);
611 : } else {
612 0 : ZVAL_NULL(val);
613 : }
614 : break;
615 : }
616 0 : return 1;
617 : }
618 : /* }}} */
619 :
620 : struct pdo_stmt_methods firebird_stmt_methods = { /* {{{ */
621 : firebird_stmt_dtor,
622 : firebird_stmt_execute,
623 : firebird_stmt_fetch,
624 : firebird_stmt_describe,
625 : firebird_stmt_get_col,
626 : firebird_stmt_param_hook,
627 : firebird_stmt_set_attribute,
628 : firebird_stmt_get_attribute
629 : };
630 : /* }}} */
631 :
632 : /*
633 : * Local variables:
634 : * tab-width: 4
635 : * c-basic-offset: 4
636 : * End:
637 : * vim600: noet sw=4 ts=4 fdm=marker
638 : * vim<600: noet sw=4 ts=4
639 : */
|