This source file includes following definitions.
- php_oci_statement_create
- php_oci_get_implicit_resultset
- php_oci_statement_set_prefetch
- php_oci_cleanup_pre_fetch
- php_oci_statement_fetch
- php_oci_statement_get_column
- php_oci_define_callback
- php_oci_statement_execute
- php_oci_statement_cancel
- php_oci_statement_free
- php_oci_bind_pre_exec
- php_oci_bind_post_exec
- php_oci_bind_by_name
- php_oci_bind_in_callback
- php_oci_bind_out_callback
- php_oci_statement_get_column_helper
- php_oci_statement_get_type
- php_oci_statement_get_numrows
- php_oci_bind_array_by_name
- php_oci_bind_array_helper_string
- php_oci_bind_array_helper_number
- php_oci_bind_array_helper_double
- php_oci_bind_array_helper_date
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "php.h"
36 #include "ext/standard/info.h"
37 #include "php_ini.h"
38
39 #if HAVE_OCI8
40
41 #include "php_oci8.h"
42 #include "php_oci8_int.h"
43
44
45
46 php_oci_statement *php_oci_statement_create(php_oci_connection *connection, char *query, int query_len TSRMLS_DC)
47 {
48 php_oci_statement *statement;
49 sword errstatus;
50
51 connection->errcode = 0;
52
53 statement = ecalloc(1,sizeof(php_oci_statement));
54
55 if (!query_len) {
56
57 PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->stmt), OCI_HTYPE_STMT, 0, NULL));
58 }
59
60 PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->err), OCI_HTYPE_ERROR, 0, NULL));
61
62 if (query_len > 0) {
63 PHP_OCI_CALL_RETURN(errstatus, OCIStmtPrepare2,
64 (
65 connection->svc,
66 &(statement->stmt),
67 connection->err,
68 (text *)query,
69 query_len,
70 NULL,
71 0,
72 OCI_NTV_SYNTAX,
73 OCI_DEFAULT
74 )
75 );
76 #ifdef HAVE_OCI8_DTRACE
77 if (DTRACE_OCI8_SQLTEXT_ENABLED()) {
78 DTRACE_OCI8_SQLTEXT(connection, connection->client_id, statement, query);
79 }
80 #endif
81
82 if (errstatus != OCI_SUCCESS) {
83 connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
84
85 PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, OCI_STRLS_CACHE_DELETE));
86 PHP_OCI_CALL(OCIHandleFree,(statement->err, OCI_HTYPE_ERROR));
87 PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
88 efree(statement);
89 return NULL;
90 }
91 }
92
93 if (query && query_len) {
94 statement->last_query = estrndup(query, query_len);
95 statement->last_query_len = query_len;
96 }
97 else {
98 statement->last_query = NULL;
99 statement->last_query_len = 0;
100 }
101
102 statement->connection = connection;
103 statement->has_data = 0;
104 statement->has_descr = 0;
105 statement->parent_stmtid = 0;
106 statement->impres_child_stmt = NULL;
107 statement->impres_count = 0;
108 statement->impres_flag = PHP_OCI_IMPRES_UNKNOWN;
109 zend_list_addref(statement->connection->id);
110
111 if (OCI_G(default_prefetch) >= 0) {
112 php_oci_statement_set_prefetch(statement, (ub4)OCI_G(default_prefetch) TSRMLS_CC);
113 } else {
114 php_oci_statement_set_prefetch(statement, (ub4)100 TSRMLS_CC);
115 }
116
117 PHP_OCI_REGISTER_RESOURCE(statement, le_statement);
118
119 OCI_G(num_statements)++;
120
121 return statement;
122 }
123
124
125
126
127 php_oci_statement *php_oci_get_implicit_resultset(php_oci_statement *statement TSRMLS_DC)
128 {
129 #if (OCI_MAJOR_VERSION < 12)
130 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Implicit results are available in Oracle Database 12c onwards");
131 return NULL;
132 #else
133 void *result;
134 ub4 rtype;
135 php_oci_statement *statement2;
136 sword errstatus;
137
138 PHP_OCI_CALL_RETURN(errstatus, OCIStmtGetNextResult, (statement->stmt, statement->err, &result, &rtype, OCI_DEFAULT));
139 if (errstatus == OCI_NO_DATA) {
140 return NULL;
141 }
142
143 if (rtype != OCI_RESULT_TYPE_SELECT) {
144
145 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected implicit result type returned from Oracle Database");
146 return NULL;
147 } else {
148 statement2 = ecalloc(1,sizeof(php_oci_statement));
149
150 PHP_OCI_CALL(OCIHandleAlloc, (statement->connection->env, (dvoid **)&(statement2->err), OCI_HTYPE_ERROR, 0, NULL));
151 statement2->stmt = (OCIStmt *)result;
152 statement2->parent_stmtid = statement->id;
153 statement2->impres_child_stmt = NULL;
154 statement2->impres_count = 0;
155 statement2->impres_flag = PHP_OCI_IMPRES_IS_CHILD;
156 statement2->connection = statement->connection;
157 statement2->errcode = 0;
158 statement2->last_query = NULL;
159 statement2->last_query_len = 0;
160 statement2->columns = NULL;
161 statement2->binds = NULL;
162 statement2->defines = NULL;
163 statement2->ncolumns = 0;
164 statement2->executed = 0;
165 statement2->has_data = 0;
166 statement2->has_descr = 0;
167 statement2->stmttype = 0;
168
169 zend_list_addref(statement->id);
170 zend_list_addref(statement2->connection->id);
171
172 php_oci_statement_set_prefetch(statement2, statement->prefetch_count TSRMLS_CC);
173
174 PHP_OCI_REGISTER_RESOURCE(statement2, le_statement);
175
176 OCI_G(num_statements)++;
177
178 return statement2;
179 }
180 #endif
181 }
182
183
184
185
186 int php_oci_statement_set_prefetch(php_oci_statement *statement, ub4 prefetch TSRMLS_DC)
187 {
188 sword errstatus;
189
190 if (prefetch > 20000) {
191 prefetch = 20000;
192 }
193
194 PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_ROWS, statement->err));
195
196 if (errstatus != OCI_SUCCESS) {
197 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
198 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
199 statement->prefetch_count = 0;
200 return 1;
201 }
202 statement->prefetch_count = prefetch;
203 statement->errcode = 0;
204 return 0;
205 }
206
207
208
209
210 int php_oci_cleanup_pre_fetch(void *data TSRMLS_DC)
211 {
212 php_oci_out_column *outcol = data;
213
214 if (!outcol->is_descr && !outcol->is_cursor)
215 return ZEND_HASH_APPLY_KEEP;
216
217 switch(outcol->data_type) {
218 case SQLT_CLOB:
219 case SQLT_BLOB:
220 case SQLT_RDD:
221 case SQLT_BFILE:
222 if (outcol->descid) {
223 zend_list_delete(outcol->descid);
224 outcol->descid = 0;
225 }
226 break;
227 case SQLT_RSET:
228 if (outcol->stmtid) {
229 zend_list_delete(outcol->stmtid);
230 outcol->stmtid = 0;
231 outcol->nested_statement = NULL;
232 }
233 break;
234 default:
235 break;
236 }
237 return ZEND_HASH_APPLY_KEEP;
238
239 }
240
241
242
243
244 int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC)
245 {
246 int i;
247 void *handlepp;
248 ub4 typep, iterp, idxp;
249 ub1 in_outp, piecep;
250 zend_bool piecewisecols = 0;
251 php_oci_out_column *column;
252 sword errstatus;
253
254 statement->errcode = 0;
255
256 if (statement->has_descr && statement->columns) {
257 zend_hash_apply(statement->columns, (apply_func_t) php_oci_cleanup_pre_fetch TSRMLS_CC);
258 }
259
260 PHP_OCI_CALL_RETURN(errstatus, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
261
262 if (errstatus == OCI_NO_DATA || nrows == 0) {
263 if (statement->last_query == NULL) {
264
265 if (statement->columns) {
266 zend_hash_destroy(statement->columns);
267 efree(statement->columns);
268 statement->columns = NULL;
269 statement->ncolumns = 0;
270 }
271 statement->executed = 0;
272 }
273
274 statement->has_data = 0;
275
276 if (nrows == 0) {
277
278 return 0;
279 }
280 return 1;
281 }
282
283
284 for (i = 0; i < statement->ncolumns; i++) {
285 column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
286 if (column && column->piecewise) {
287 column->retlen4 = 0;
288 piecewisecols = 1;
289 }
290 }
291
292 while (errstatus == OCI_NEED_DATA) {
293 if (piecewisecols) {
294 PHP_OCI_CALL_RETURN(errstatus,
295 OCIStmtGetPieceInfo,
296 (
297 statement->stmt,
298 statement->err,
299 &handlepp,
300 &typep,
301 &in_outp,
302 &iterp,
303 &idxp,
304 &piecep
305 )
306 );
307
308
309 for (i = 0; i < statement->ncolumns; i++) {
310 column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
311 if (column && column->piecewise && handlepp == column->oci_define) {
312 if (!column->data) {
313 column->data = (text *) ecalloc(1, PHP_OCI_PIECE_SIZE + 1);
314 } else {
315 column->data = erealloc(column->data, column->retlen4 + PHP_OCI_PIECE_SIZE + 1);
316 }
317 column->cb_retlen = PHP_OCI_PIECE_SIZE;
318
319
320 PHP_OCI_CALL(OCIStmtSetPieceInfo,
321 (
322 (void *) column->oci_define,
323 OCI_HTYPE_DEFINE,
324 statement->err,
325 ((char*)column->data) + column->retlen4,
326 &(column->cb_retlen),
327 piecep,
328 &column->indicator,
329 &column->retcode
330 )
331 );
332 }
333 }
334 }
335
336 PHP_OCI_CALL_RETURN(errstatus, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
337
338 if (piecewisecols) {
339 for (i = 0; i < statement->ncolumns; i++) {
340 column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
341 if (column && column->piecewise && handlepp == column->oci_define) {
342 column->retlen4 += column->cb_retlen;
343 }
344 }
345 }
346 }
347
348 if (errstatus == OCI_SUCCESS_WITH_INFO || errstatus == OCI_SUCCESS) {
349 statement->has_data = 1;
350
351
352 for (i = 0; i < statement->ncolumns; i++) {
353 column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
354 if (column == NULL) {
355 continue;
356 }
357
358 if (!column->define) {
359 continue;
360 }
361
362 zval_dtor(column->define->zval);
363 php_oci_column_to_zval(column, column->define->zval, 0 TSRMLS_CC);
364 }
365
366 return 0;
367 }
368
369 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
370 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
371
372 statement->has_data = 0;
373
374 return 1;
375 }
376
377
378
379
380 php_oci_out_column *php_oci_statement_get_column(php_oci_statement *statement, long column_index, char *column_name, int column_name_len TSRMLS_DC)
381 {
382 php_oci_out_column *column = NULL;
383 int i;
384
385 if (statement->columns == NULL) {
386 return NULL;
387 }
388
389 if (column_name) {
390 for (i = 0; i < statement->ncolumns; i++) {
391 column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
392 if (column == NULL) {
393 continue;
394 } else if (((int) column->name_len == column_name_len) && (!strncmp(column->name, column_name, column_name_len))) {
395 return column;
396 }
397 }
398 } else if (column_index != -1) {
399 if (zend_hash_index_find(statement->columns, column_index, (void **)&column) == FAILURE) {
400 return NULL;
401 }
402 return column;
403 }
404
405 return NULL;
406 }
407
408
409
410 sb4 php_oci_define_callback(dvoid *ctx, OCIDefine *define, ub4 iter, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcpp)
411 {
412 php_oci_out_column *outcol = (php_oci_out_column *)ctx;
413 TSRMLS_FETCH();
414
415 if (!outcol) {
416
417 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid context pointer value");
418 return OCI_ERROR;
419 }
420
421 switch(outcol->data_type) {
422 case SQLT_RSET: {
423 php_oci_statement *nested_stmt;
424
425 nested_stmt = php_oci_statement_create(outcol->statement->connection, NULL, 0 TSRMLS_CC);
426 if (!nested_stmt) {
427 return OCI_ERROR;
428 }
429 nested_stmt->parent_stmtid = outcol->statement->id;
430 zend_list_addref(outcol->statement->id);
431 outcol->nested_statement = nested_stmt;
432 outcol->stmtid = nested_stmt->id;
433
434 *bufpp = nested_stmt->stmt;
435 *alenpp = &(outcol->retlen4);
436 *piecep = OCI_ONE_PIECE;
437 *indpp = &(outcol->indicator);
438 *rcpp = &(outcol->retcode);
439 return OCI_CONTINUE;
440 }
441 break;
442 case SQLT_RDD:
443 case SQLT_BLOB:
444 case SQLT_CLOB:
445 case SQLT_BFILE: {
446 php_oci_descriptor *descr;
447 int dtype;
448
449 if (outcol->data_type == SQLT_BFILE) {
450 dtype = OCI_DTYPE_FILE;
451 } else if (outcol->data_type == SQLT_RDD ) {
452 dtype = OCI_DTYPE_ROWID;
453 } else {
454 dtype = OCI_DTYPE_LOB;
455 }
456
457 descr = php_oci_lob_create(outcol->statement->connection, dtype TSRMLS_CC);
458 if (!descr) {
459 return OCI_ERROR;
460 }
461 outcol->descid = descr->id;
462 descr->charset_form = outcol->charset_form;
463
464 *bufpp = descr->descriptor;
465 *alenpp = &(outcol->retlen4);
466 *piecep = OCI_ONE_PIECE;
467 *indpp = &(outcol->indicator);
468 *rcpp = &(outcol->retcode);
469
470 return OCI_CONTINUE;
471 }
472 break;
473 }
474 return OCI_ERROR;
475 }
476
477
478
479
480 int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC)
481 {
482 php_oci_out_column *outcol;
483 php_oci_out_column column;
484 OCIParam *param = NULL;
485 text *colname;
486 ub4 counter;
487 ub2 define_type;
488 ub4 iters;
489 ub4 colcount;
490 ub2 dynamic;
491 dvoid *buf;
492 sword errstatus;
493
494 switch (mode) {
495 case OCI_COMMIT_ON_SUCCESS:
496 case OCI_DESCRIBE_ONLY:
497 case OCI_DEFAULT:
498
499 #ifdef HAVE_OCI8_DTRACE
500 if (DTRACE_OCI8_EXECUTE_MODE_ENABLED()) {
501 DTRACE_OCI8_EXECUTE_MODE(statement->connection, statement->connection->client_id, statement, mode);
502 }
503 #endif
504 break;
505 default:
506 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid execute mode given: %d", mode);
507 return 1;
508 break;
509 }
510
511 if (!statement->stmttype) {
512
513 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement->stmttype, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
514
515 if (errstatus != OCI_SUCCESS) {
516 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
517 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
518 return 1;
519 } else {
520 statement->errcode = 0;
521 }
522 }
523
524 if (statement->stmttype == OCI_STMT_SELECT) {
525 iters = 0;
526 } else {
527 iters = 1;
528 }
529
530 if (statement->last_query) {
531
532 if (statement->binds) {
533 int result = 0;
534 zend_hash_apply_with_argument(statement->binds, (apply_func_arg_t) php_oci_bind_pre_exec, (void *)&result TSRMLS_CC);
535 if (result) {
536 return 1;
537 }
538 }
539
540
541 PHP_OCI_CALL_RETURN(errstatus, OCIStmtExecute, (statement->connection->svc, statement->stmt, statement->err, iters, 0, NULL, NULL, mode));
542
543 if (errstatus != OCI_SUCCESS) {
544 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
545 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
546 return 1;
547 }
548
549 if (statement->binds) {
550 zend_hash_apply(statement->binds, (apply_func_t) php_oci_bind_post_exec TSRMLS_CC);
551 }
552
553 if (mode & OCI_COMMIT_ON_SUCCESS) {
554
555 statement->connection->rb_on_disconnect = 0;
556 } else if (statement->stmttype != OCI_STMT_SELECT) {
557
558 statement->connection->rb_on_disconnect = 1;
559 }
560
561
562
563
564
565
566
567 statement->errcode = 0;
568 }
569
570 if (statement->stmttype == OCI_STMT_SELECT && statement->executed == 0) {
571
572 statement->executed = 1;
573
574 ALLOC_HASHTABLE(statement->columns);
575 zend_hash_init(statement->columns, 13, NULL, php_oci_column_hash_dtor, 0);
576
577 counter = 1;
578
579
580 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *)&colcount, (ub4 *)0, OCI_ATTR_PARAM_COUNT, statement->err));
581
582 if (errstatus != OCI_SUCCESS) {
583 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
584 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
585 return 1;
586 }
587
588 statement->ncolumns = colcount;
589
590 for (counter = 1; counter <= colcount; counter++) {
591 memset(&column,0,sizeof(php_oci_out_column));
592
593 if (zend_hash_index_update(statement->columns, counter, &column, sizeof(php_oci_out_column), (void**) &outcol) == FAILURE) {
594 efree(statement->columns);
595
596 return 1;
597 }
598
599
600 PHP_OCI_CALL_RETURN(errstatus, OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)¶m, counter));
601
602 if (errstatus != OCI_SUCCESS) {
603 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
604 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
605 return 1;
606 }
607
608
609 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_type, (ub4 *)0, OCI_ATTR_DATA_TYPE, statement->err));
610
611 if (errstatus != OCI_SUCCESS) {
612 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
613 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
614 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
615 return 1;
616 }
617
618
619 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_form, (ub4 *)0, OCI_ATTR_CHARSET_FORM, statement->err));
620
621 if (errstatus != OCI_SUCCESS) {
622 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
623 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
624 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
625 return 1;
626 }
627
628
629 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_id, (ub4 *)0, OCI_ATTR_CHARSET_ID, statement->err));
630
631 if (errstatus != OCI_SUCCESS) {
632 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
633 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
634 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
635 return 1;
636 }
637
638
639 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_size, (dvoid *)0, OCI_ATTR_DATA_SIZE, statement->err));
640
641 if (errstatus != OCI_SUCCESS) {
642 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
643 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
644 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
645 return 1;
646 }
647
648 outcol->storage_size4 = outcol->data_size;
649 outcol->retlen = outcol->data_size;
650
651
652 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->scale, (dvoid *)0, OCI_ATTR_SCALE, statement->err));
653
654 if (errstatus != OCI_SUCCESS) {
655 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
656 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
657 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
658 return 1;
659 }
660
661
662 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->precision, (dvoid *)0, OCI_ATTR_PRECISION, statement->err));
663
664 if (errstatus != OCI_SUCCESS) {
665 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
666 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
667 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
668 return 1;
669 }
670
671
672 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid **)&colname, (ub4 *)&outcol->name_len, (ub4)OCI_ATTR_NAME, statement->err));
673
674 if (errstatus != OCI_SUCCESS) {
675 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
676 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
677 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
678 return 1;
679 }
680 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
681
682 outcol->name = estrndup((char*) colname, outcol->name_len);
683
684
685 if (statement->defines) {
686 if (zend_hash_find(statement->defines,outcol->name,outcol->name_len,(void **) &outcol->define) == SUCCESS) {
687 if (outcol->define->type) {
688 outcol->data_type = outcol->define->type;
689 }
690 }
691 }
692
693 buf = 0;
694 switch (outcol->data_type) {
695 case SQLT_RSET:
696 outcol->statement = statement;
697
698 define_type = SQLT_RSET;
699 outcol->is_cursor = 1;
700 outcol->statement->has_descr = 1;
701 outcol->storage_size4 = -1;
702 outcol->retlen = -1;
703 dynamic = OCI_DYNAMIC_FETCH;
704 break;
705
706 case SQLT_RDD:
707 case SQLT_BLOB:
708 case SQLT_CLOB:
709 case SQLT_BFILE:
710 outcol->statement = statement;
711
712 define_type = outcol->data_type;
713 outcol->is_descr = 1;
714 outcol->statement->has_descr = 1;
715 outcol->storage_size4 = -1;
716 outcol->chunk_size = 0;
717 dynamic = OCI_DYNAMIC_FETCH;
718 break;
719
720 case SQLT_LNG:
721 case SQLT_LBI:
722 if (outcol->data_type == SQLT_LBI) {
723 define_type = SQLT_BIN;
724 } else {
725 define_type = SQLT_CHR;
726 }
727 outcol->storage_size4 = PHP_OCI_MAX_DATA_SIZE;
728 outcol->piecewise = 1;
729 dynamic = OCI_DYNAMIC_FETCH;
730 break;
731
732 case SQLT_BIN:
733 default:
734 define_type = SQLT_CHR;
735 if (outcol->data_type == SQLT_BIN) {
736 define_type = SQLT_BIN;
737 }
738 if ((outcol->data_type == SQLT_DAT) || (outcol->data_type == SQLT_NUM)
739 #ifdef SQLT_TIMESTAMP
740 || (outcol->data_type == SQLT_TIMESTAMP)
741 #endif
742 #ifdef SQLT_TIMESTAMP_TZ
743 || (outcol->data_type == SQLT_TIMESTAMP_TZ)
744 #endif
745 #ifdef SQLT_TIMESTAMP_LTZ
746 || (outcol->data_type == SQLT_TIMESTAMP_LTZ)
747 #endif
748 #ifdef SQLT_INTERVAL_YM
749 || (outcol->data_type == SQLT_INTERVAL_YM)
750 #endif
751 #ifdef SQLT_INTERVAL_DS
752 || (outcol->data_type == SQLT_INTERVAL_DS)
753 #endif
754 ) {
755 outcol->storage_size4 = 512;
756 #if defined(SQLT_IBFLOAT) && defined(SQLT_IBDOUBLE)
757 } else if (outcol->data_type == SQLT_IBFLOAT || outcol->data_type == SQLT_IBDOUBLE) {
758 outcol->storage_size4 = 1024;
759 #endif
760 } else {
761 outcol->storage_size4++;
762 }
763
764 outcol->storage_size4 *= 3;
765
766 dynamic = OCI_DEFAULT;
767 buf = outcol->data = (text *) safe_emalloc(1, outcol->storage_size4, 0);
768 memset(buf, 0, outcol->storage_size4);
769 break;
770 }
771
772 if (dynamic == OCI_DYNAMIC_FETCH) {
773 PHP_OCI_CALL_RETURN(errstatus,
774 OCIDefineByPos,
775 (
776 statement->stmt,
777 (OCIDefine **)&outcol->oci_define,
778 statement->err,
779 counter,
780 (dvoid *)NULL,
781 outcol->storage_size4,
782 define_type,
783 (dvoid *)&outcol->indicator,
784 (ub2 *)NULL,
785 (ub2 *)NULL,
786 OCI_DYNAMIC_FETCH
787 )
788 );
789
790 } else {
791 PHP_OCI_CALL_RETURN(errstatus,
792 OCIDefineByPos,
793 (
794 statement->stmt,
795 (OCIDefine **)&outcol->oci_define,
796 statement->err,
797 counter,
798 (dvoid *)buf,
799 outcol->storage_size4,
800 define_type,
801 (dvoid *)&outcol->indicator,
802 (ub2 *)&outcol->retlen,
803 (ub2 *)&outcol->retcode,
804 OCI_DEFAULT
805 )
806 );
807
808 }
809
810 if (errstatus != OCI_SUCCESS) {
811 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
812 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
813 return 1;
814 }
815
816
817 switch (outcol->data_type) {
818 case SQLT_RSET:
819 case SQLT_RDD:
820 case SQLT_BLOB:
821 case SQLT_CLOB:
822 case SQLT_BFILE:
823 PHP_OCI_CALL_RETURN(errstatus,
824 OCIDefineDynamic,
825 (
826 outcol->oci_define,
827 statement->err,
828 (dvoid *)outcol,
829 php_oci_define_callback
830 )
831 );
832
833 if (errstatus != OCI_SUCCESS) {
834 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
835 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
836 return 1;
837 }
838 break;
839 }
840 }
841 statement->errcode = 0;
842 }
843
844 return 0;
845 }
846
847
848
849
850 int php_oci_statement_cancel(php_oci_statement *statement TSRMLS_DC)
851 {
852 return php_oci_statement_fetch(statement, 0 TSRMLS_CC);
853 }
854
855
856
857
858 void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC)
859 {
860 if (statement->stmt) {
861 if (statement->last_query_len) {
862 PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
863 } else if (statement->impres_flag != PHP_OCI_IMPRES_IS_CHILD) {
864 PHP_OCI_CALL(OCIHandleFree, (statement->stmt, OCI_HTYPE_STMT));
865 }
866 statement->stmt = NULL;
867 }
868
869 if (statement->err) {
870 PHP_OCI_CALL(OCIHandleFree, (statement->err, OCI_HTYPE_ERROR));
871 statement->err = NULL;
872 }
873
874 if (statement->last_query) {
875 efree(statement->last_query);
876 }
877
878 if (statement->columns) {
879 zend_hash_destroy(statement->columns);
880 efree(statement->columns);
881 }
882
883 if (statement->binds) {
884 zend_hash_destroy(statement->binds);
885 efree(statement->binds);
886 }
887
888 if (statement->defines) {
889 zend_hash_destroy(statement->defines);
890 efree(statement->defines);
891 }
892
893 if (statement->parent_stmtid) {
894 zend_list_delete(statement->parent_stmtid);
895 }
896
897 zend_list_delete(statement->connection->id);
898 efree(statement);
899
900 OCI_G(num_statements)--;
901 }
902
903
904
905
906 int php_oci_bind_pre_exec(void *data, void *result TSRMLS_DC)
907 {
908 php_oci_bind *bind = (php_oci_bind *) data;
909
910 *(int *)result = 0;
911
912 if (Z_TYPE_P(bind->zval) == IS_ARRAY) {
913
914
915
916
917 return 0;
918 }
919 switch (bind->type) {
920 case SQLT_NTY:
921 case SQLT_BFILEE:
922 case SQLT_CFILEE:
923 case SQLT_CLOB:
924 case SQLT_BLOB:
925 case SQLT_RDD:
926 if (Z_TYPE_P(bind->zval) != IS_OBJECT) {
927 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
928 *(int *)result = 1;
929 }
930 break;
931
932 case SQLT_CHR:
933 case SQLT_AFC:
934 case SQLT_INT:
935 case SQLT_NUM:
936 #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
937 case SQLT_BOL:
938 #endif
939 case SQLT_LBI:
940 case SQLT_BIN:
941 case SQLT_LNG:
942 if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
943 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
944 *(int *)result = 1;
945 }
946 break;
947
948 case SQLT_RSET:
949 if (Z_TYPE_P(bind->zval) != IS_RESOURCE) {
950 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
951 *(int *)result = 1;
952 }
953 break;
954 }
955
956
957 bind->indicator = 0;
958
959 return 0;
960 }
961
962
963
964
965 int php_oci_bind_post_exec(void *data TSRMLS_DC)
966 {
967 php_oci_bind *bind = (php_oci_bind *) data;
968 php_oci_connection *connection = bind->parent_statement->connection;
969 sword errstatus;
970
971 if (bind->indicator == -1) {
972 zval *val = bind->zval;
973 if (Z_TYPE_P(val) == IS_STRING) {
974 *Z_STRVAL_P(val) = '\0';
975 }
976 zval_dtor(val);
977 ZVAL_NULL(val);
978 } else if (Z_TYPE_P(bind->zval) == IS_STRING
979 && Z_STRLEN_P(bind->zval) > 0
980 && Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] != '\0') {
981
982
983
984
985
986
987 Z_STRVAL_P(bind->zval) = erealloc(Z_STRVAL_P(bind->zval), Z_STRLEN_P(bind->zval)+1);
988 Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] = '\0';
989 } else if (Z_TYPE_P(bind->zval) == IS_ARRAY) {
990 int i;
991 zval **entry;
992 HashTable *hash = HASH_OF(bind->zval);
993
994 zend_hash_internal_pointer_reset(hash);
995
996 switch (bind->array.type) {
997 case SQLT_NUM:
998 case SQLT_INT:
999 case SQLT_LNG:
1000 for (i = 0; i < bind->array.current_length; i++) {
1001 if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1002 zval_dtor(*entry);
1003 ZVAL_LONG(*entry, ((ub4 *)(bind->array.elements))[i]);
1004 zend_hash_move_forward(hash);
1005 } else {
1006 add_next_index_long(bind->zval, ((ub4 *)(bind->array.elements))[i]);
1007 }
1008 }
1009 break;
1010 case SQLT_FLT:
1011 for (i = 0; i < bind->array.current_length; i++) {
1012 if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1013 zval_dtor(*entry);
1014 ZVAL_DOUBLE(*entry, ((double *)(bind->array.elements))[i]);
1015 zend_hash_move_forward(hash);
1016 } else {
1017 add_next_index_double(bind->zval, ((double *)(bind->array.elements))[i]);
1018 }
1019 }
1020 break;
1021 case SQLT_ODT:
1022 for (i = 0; i < bind->array.current_length; i++) {
1023 oratext buff[1024];
1024 ub4 buff_len = 1024;
1025
1026 memset((void*)buff,0,sizeof(buff));
1027
1028 if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1029 PHP_OCI_CALL_RETURN(errstatus, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
1030 zval_dtor(*entry);
1031
1032 if (errstatus != OCI_SUCCESS) {
1033 connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
1034 PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
1035 ZVAL_NULL(*entry);
1036 } else {
1037 connection->errcode = 0;
1038 ZVAL_STRINGL(*entry, (char *)buff, buff_len, 1);
1039 }
1040 zend_hash_move_forward(hash);
1041 } else {
1042 PHP_OCI_CALL_RETURN(errstatus, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
1043 if (errstatus != OCI_SUCCESS) {
1044 connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
1045 PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
1046 add_next_index_null(bind->zval);
1047 } else {
1048 connection->errcode = 0;
1049 add_next_index_stringl(bind->zval, (char *)buff, buff_len, 1);
1050 }
1051 }
1052 }
1053 break;
1054
1055 case SQLT_AFC:
1056 case SQLT_CHR:
1057 case SQLT_VCS:
1058 case SQLT_AVC:
1059 case SQLT_STR:
1060 case SQLT_LVC:
1061 for (i = 0; i < bind->array.current_length; i++) {
1062
1063 int curr_element_length = bind->array.element_lengths[i];
1064 if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1065 zval_dtor(*entry);
1066 ZVAL_STRINGL(*entry, (char *)(((text *)bind->array.elements)+i*bind->array.max_length), curr_element_length, 1);
1067 zend_hash_move_forward(hash);
1068 } else {
1069 add_next_index_stringl(bind->zval, (char *)(((text *)bind->array.elements)+i*bind->array.max_length), curr_element_length, 1);
1070 }
1071 }
1072 break;
1073 }
1074 }
1075
1076 return 0;
1077 }
1078
1079
1080
1081
1082 int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, zval *var, long maxlength, ub2 type TSRMLS_DC)
1083 {
1084 php_oci_collection *bind_collection = NULL;
1085 php_oci_descriptor *bind_descriptor = NULL;
1086 php_oci_statement *bind_statement = NULL;
1087 dvoid *oci_desc = NULL;
1088
1089 OCIStmt *oci_stmt = NULL;
1090 dvoid *bind_data = NULL;
1091 php_oci_bind bind, *old_bind, *bindp;
1092 int mode = OCI_DATA_AT_EXEC;
1093 sb4 value_sz = -1;
1094 sword errstatus;
1095
1096 switch (type) {
1097 case SQLT_NTY:
1098 {
1099 zval **tmp;
1100
1101 if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
1102 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
1103 return 1;
1104 }
1105
1106 PHP_OCI_ZVAL_TO_COLLECTION_EX(*tmp, bind_collection);
1107 value_sz = sizeof(void*);
1108 mode = OCI_DEFAULT;
1109
1110 if (!bind_collection->collection) {
1111 return 1;
1112 }
1113 }
1114 break;
1115 case SQLT_BFILEE:
1116 case SQLT_CFILEE:
1117 case SQLT_CLOB:
1118 case SQLT_BLOB:
1119 case SQLT_RDD:
1120 {
1121 zval **tmp;
1122
1123 if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
1124 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
1125 return 1;
1126 }
1127
1128 PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, bind_descriptor);
1129
1130 value_sz = sizeof(void*);
1131
1132 oci_desc = bind_descriptor->descriptor;
1133
1134 if (!oci_desc) {
1135 return 1;
1136 }
1137 }
1138 break;
1139
1140 case SQLT_INT:
1141 case SQLT_NUM:
1142 {
1143 if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
1144 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
1145 return 1;
1146 }
1147 convert_to_long(var);
1148 #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION > 10
1149 bind_data = (ub8 *)&Z_LVAL_P(var);
1150 value_sz = sizeof(ub8);
1151 #else
1152 bind_data = (ub4 *)&Z_LVAL_P(var);
1153 value_sz = sizeof(ub4);
1154 #endif
1155 mode = OCI_DEFAULT;
1156 }
1157 break;
1158
1159 case SQLT_LBI:
1160 case SQLT_BIN:
1161 case SQLT_LNG:
1162 case SQLT_AFC:
1163 case SQLT_CHR:
1164 if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
1165 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
1166 return 1;
1167 }
1168 if (Z_TYPE_P(var) != IS_NULL) {
1169 convert_to_string(var);
1170 }
1171 if (maxlength == -1) {
1172 value_sz = (Z_TYPE_P(var) == IS_STRING) ? Z_STRLEN_P(var) : 0;
1173 } else {
1174 value_sz = maxlength;
1175 }
1176 break;
1177
1178 case SQLT_RSET:
1179 if (Z_TYPE_P(var) != IS_RESOURCE) {
1180 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
1181 return 1;
1182 }
1183 PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement);
1184 value_sz = sizeof(void*);
1185
1186 oci_stmt = bind_statement->stmt;
1187
1188 if (!oci_stmt) {
1189 return 1;
1190 }
1191 break;
1192
1193 #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
1194 case SQLT_BOL:
1195 if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
1196 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
1197 return 1;
1198 }
1199 convert_to_boolean(var);
1200 bind_data = (int *)&Z_LVAL_P(var);
1201 value_sz = sizeof(int);
1202
1203 mode = OCI_DEFAULT;
1204 break;
1205 #endif
1206
1207 default:
1208 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %d", (int)type);
1209 return 1;
1210 break;
1211 }
1212
1213 if (value_sz == 0) {
1214 value_sz = 1;
1215 }
1216
1217 if (!statement->binds) {
1218 ALLOC_HASHTABLE(statement->binds);
1219 zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
1220 }
1221
1222 memset((void*)&bind,0,sizeof(php_oci_bind));
1223 if (zend_hash_find(statement->binds, name, name_len + 1, (void **)&old_bind) == SUCCESS) {
1224 bindp = old_bind;
1225 if (bindp->zval) {
1226 zval_ptr_dtor(&bindp->zval);
1227 }
1228 } else {
1229 zend_hash_update(statement->binds, name, name_len + 1, &bind, sizeof(php_oci_bind), (void **)&bindp);
1230 }
1231
1232 bindp->descriptor = oci_desc;
1233 bindp->statement = oci_stmt;
1234 bindp->parent_statement = statement;
1235 bindp->zval = var;
1236 bindp->type = type;
1237 zval_add_ref(&var);
1238
1239 PHP_OCI_CALL_RETURN(errstatus,
1240 OCIBindByName,
1241 (
1242 statement->stmt,
1243 (OCIBind **)&bindp->bind,
1244 statement->err,
1245 (text*) name,
1246 name_len,
1247 (dvoid *)bind_data,
1248 value_sz,
1249 type,
1250 (dvoid *)&bindp->indicator,
1251 (ub2 *)0,
1252 (ub2 *)&bindp->retcode,
1253 (ub4)0,
1254 (ub4 *)0,
1255 mode
1256 )
1257 );
1258
1259 if (errstatus != OCI_SUCCESS) {
1260 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
1261 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1262 return 1;
1263 }
1264
1265 if (mode == OCI_DATA_AT_EXEC) {
1266 PHP_OCI_CALL_RETURN(errstatus, OCIBindDynamic,
1267 (
1268 bindp->bind,
1269 statement->err,
1270 (dvoid *)bindp,
1271 php_oci_bind_in_callback,
1272 (dvoid *)bindp,
1273 php_oci_bind_out_callback
1274 )
1275 );
1276
1277 if (errstatus != OCI_SUCCESS) {
1278 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
1279 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1280 return 1;
1281 }
1282 }
1283
1284 if (type == SQLT_NTY) {
1285
1286 PHP_OCI_CALL_RETURN(errstatus, OCIBindObject,
1287 (
1288 bindp->bind,
1289 statement->err,
1290 bind_collection->tdo,
1291 (dvoid **) &(bind_collection->collection),
1292 (ub4 *) 0,
1293 (dvoid **) 0,
1294 (ub4 *) 0
1295 )
1296 );
1297
1298 if (errstatus) {
1299 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
1300 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1301 return 1;
1302 }
1303 }
1304
1305 statement->errcode = 0;
1306 return 0;
1307 }
1308
1309
1310
1311
1312 sb4 php_oci_bind_in_callback(
1313 dvoid *ictxp,
1314 OCIBind *bindp,
1315 ub4 iter,
1316 ub4 index,
1317 dvoid **bufpp,
1318 ub4 *alenp,
1319 ub1 *piecep,
1320 dvoid **indpp)
1321 {
1322 php_oci_bind *phpbind;
1323 zval *val;
1324 TSRMLS_FETCH();
1325
1326 if (!(phpbind=(php_oci_bind *)ictxp) || !(val = phpbind->zval)) {
1327 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
1328 return OCI_ERROR;
1329 }
1330
1331 if (ZVAL_IS_NULL(val)) {
1332
1333 phpbind->indicator = -1;
1334 *bufpp = 0;
1335 *alenp = -1;
1336 *indpp = (dvoid *)&phpbind->indicator;
1337 } else if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
1338
1339 convert_to_string(val);
1340
1341 *bufpp = Z_STRVAL_P(val);
1342 *alenp = Z_STRLEN_P(val);
1343 *indpp = (dvoid *)&phpbind->indicator;
1344 } else if (phpbind->statement != 0) {
1345
1346 *bufpp = phpbind->statement;
1347 *alenp = -1;
1348 *indpp = (dvoid *)&phpbind->indicator;
1349 } else {
1350
1351 *bufpp = phpbind->descriptor;
1352 *alenp = -1;
1353 *indpp = (dvoid *)&phpbind->indicator;
1354 }
1355
1356 *piecep = OCI_ONE_PIECE;
1357
1358 return OCI_CONTINUE;
1359 }
1360
1361
1362
1363
1364 sb4 php_oci_bind_out_callback(
1365 dvoid *octxp,
1366 OCIBind *bindp,
1367 ub4 iter,
1368 ub4 index,
1369 dvoid **bufpp,
1370 ub4 **alenpp,
1371 ub1 *piecep,
1372 dvoid **indpp,
1373 ub2 **rcodepp)
1374 {
1375 php_oci_bind *phpbind;
1376 zval *val;
1377 sb4 retval = OCI_ERROR;
1378 TSRMLS_FETCH();
1379
1380 if (!(phpbind=(php_oci_bind *)octxp) || !(val = phpbind->zval)) {
1381 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
1382 return retval;
1383 }
1384
1385 if (Z_TYPE_P(val) == IS_RESOURCE) {
1386
1387 if (phpbind->statement != NULL) {
1388 *bufpp = phpbind->statement;
1389 *alenpp = &phpbind->dummy_len;
1390 *piecep = OCI_ONE_PIECE;
1391 *rcodepp = &phpbind->retcode;
1392 *indpp = &phpbind->indicator;
1393 }
1394 retval = OCI_CONTINUE;
1395 } else if (Z_TYPE_P(val) == IS_OBJECT) {
1396 zval **tmp;
1397 php_oci_descriptor *desc;
1398
1399 if (!phpbind->descriptor) {
1400 return OCI_ERROR;
1401 }
1402
1403
1404
1405
1406
1407 if (zend_hash_find(Z_OBJPROP_P(val), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
1408 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find object outbind descriptor property");
1409 return OCI_ERROR;
1410 }
1411 PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, desc);
1412 desc->lob_size = -1;
1413
1414 *alenpp = &phpbind->dummy_len;
1415 *bufpp = phpbind->descriptor;
1416 *piecep = OCI_ONE_PIECE;
1417 *rcodepp = &phpbind->retcode;
1418 *indpp = &phpbind->indicator;
1419 retval = OCI_CONTINUE;
1420 } else {
1421 convert_to_string(val);
1422 zval_dtor(val);
1423
1424 Z_STRLEN_P(val) = PHP_OCI_PIECE_SIZE;
1425 Z_STRVAL_P(val) = ecalloc(1, Z_STRLEN_P(phpbind->zval) + 1);
1426
1427
1428 *alenpp = (ub4*) &Z_STRLEN_P(phpbind->zval);
1429 *bufpp = Z_STRVAL_P(phpbind->zval);
1430 *piecep = OCI_ONE_PIECE;
1431 *rcodepp = &phpbind->retcode;
1432 *indpp = &phpbind->indicator;
1433 retval = OCI_CONTINUE;
1434 }
1435
1436 return retval;
1437 }
1438
1439
1440
1441
1442 php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAMETERS, int need_data)
1443 {
1444 zval *z_statement, *column_index;
1445 php_oci_statement *statement;
1446 php_oci_out_column *column;
1447
1448 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &z_statement, &column_index) == FAILURE) {
1449 return NULL;
1450 }
1451
1452 statement = (php_oci_statement *) zend_fetch_resource(&z_statement TSRMLS_CC, -1, "oci8 statement", NULL, 1, le_statement);
1453
1454 if (!statement) {
1455 return NULL;
1456 }
1457
1458 if (need_data && !statement->has_data) {
1459 return NULL;
1460 }
1461
1462 if (Z_TYPE_P(column_index) == IS_STRING) {
1463 column = php_oci_statement_get_column(statement, -1, Z_STRVAL_P(column_index), Z_STRLEN_P(column_index) TSRMLS_CC);
1464 if (!column) {
1465 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column name \"%s\"", Z_STRVAL_P(column_index));
1466 return NULL;
1467 }
1468 } else {
1469 zval tmp;
1470
1471 tmp = *column_index;
1472 zval_copy_ctor(&tmp);
1473 convert_to_long(&tmp);
1474 column = php_oci_statement_get_column(statement, Z_LVAL(tmp), NULL, 0 TSRMLS_CC);
1475 if (!column) {
1476 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column index \"%ld\"", Z_LVAL(tmp));
1477 zval_dtor(&tmp);
1478 return NULL;
1479 }
1480 zval_dtor(&tmp);
1481 }
1482 return column;
1483 }
1484
1485
1486
1487
1488 int php_oci_statement_get_type(php_oci_statement *statement, ub2 *type TSRMLS_DC)
1489 {
1490 ub2 statement_type;
1491 sword errstatus;
1492
1493 *type = 0;
1494
1495 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement_type, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
1496
1497 if (errstatus != OCI_SUCCESS) {
1498 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
1499 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1500 return 1;
1501 }
1502 statement->errcode = 0;
1503 *type = statement_type;
1504
1505 return 0;
1506 }
1507
1508
1509
1510
1511 int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows TSRMLS_DC)
1512 {
1513 ub4 statement_numrows;
1514 sword errstatus;
1515
1516 *numrows = 0;
1517
1518 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub4 *)&statement_numrows, (ub4 *)0, OCI_ATTR_ROW_COUNT, statement->err));
1519
1520 if (errstatus != OCI_SUCCESS) {
1521 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
1522 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1523 return 1;
1524 }
1525 statement->errcode = 0;
1526 *numrows = statement_numrows;
1527
1528 return 0;
1529 }
1530
1531
1532
1533
1534 int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval *var, long max_table_length, long maxlength, long type TSRMLS_DC)
1535 {
1536 php_oci_bind *bind, *bindp;
1537 sword errstatus;
1538
1539 convert_to_array(var);
1540
1541 if (maxlength < -1) {
1542 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid max length value (%ld)", maxlength);
1543 return 1;
1544 }
1545
1546 switch(type) {
1547 case SQLT_NUM:
1548 case SQLT_INT:
1549 case SQLT_LNG:
1550 bind = php_oci_bind_array_helper_number(var, max_table_length TSRMLS_CC);
1551 break;
1552
1553 case SQLT_FLT:
1554 bind = php_oci_bind_array_helper_double(var, max_table_length TSRMLS_CC);
1555 break;
1556
1557 case SQLT_AFC:
1558 case SQLT_CHR:
1559 case SQLT_VCS:
1560 case SQLT_AVC:
1561 case SQLT_STR:
1562 case SQLT_LVC:
1563 if (maxlength == -1 && zend_hash_num_elements(Z_ARRVAL_P(var)) == 0) {
1564 php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must provide max length value for empty arrays");
1565 return 1;
1566 }
1567 bind = php_oci_bind_array_helper_string(var, max_table_length, maxlength TSRMLS_CC);
1568 break;
1569 case SQLT_ODT:
1570 bind = php_oci_bind_array_helper_date(var, max_table_length, statement->connection TSRMLS_CC);
1571 break;
1572 default:
1573 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %ld", type);
1574 return 1;
1575 break;
1576 }
1577
1578 if (bind == NULL) {
1579
1580 return 1;
1581 }
1582
1583 if (!statement->binds) {
1584 ALLOC_HASHTABLE(statement->binds);
1585 zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
1586 }
1587
1588 zend_hash_update(statement->binds, name, name_len + 1, bind, sizeof(php_oci_bind), (void **)&bindp);
1589
1590 bindp->descriptor = NULL;
1591 bindp->statement = NULL;
1592 bindp->parent_statement = statement;
1593 bindp->bind = NULL;
1594 bindp->zval = var;
1595 bindp->array.type = type;
1596 bindp->indicator = 0;
1597 bindp->type = 0;
1598
1599 zval_add_ref(&var);
1600
1601 PHP_OCI_CALL_RETURN(errstatus,
1602 OCIBindByName,
1603 (
1604 statement->stmt,
1605 (OCIBind **)&bindp->bind,
1606 statement->err,
1607 (text *)name,
1608 name_len,
1609 (dvoid *) bindp->array.elements,
1610 (sb4) bind->array.max_length,
1611 (ub2)type,
1612 (dvoid *)bindp->array.indicators,
1613 (ub2 *)bind->array.element_lengths,
1614 (ub2 *)0,
1615 (ub4) max_table_length,
1616 (ub4 *) &(bindp->array.current_length),
1617 (ub4) OCI_DEFAULT
1618 )
1619 );
1620
1621
1622 if (errstatus != OCI_SUCCESS) {
1623 efree(bind);
1624 statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
1625 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1626 return 1;
1627 }
1628 statement->errcode = 0;
1629 efree(bind);
1630 return 0;
1631 }
1632
1633
1634
1635
1636 php_oci_bind *php_oci_bind_array_helper_string(zval *var, long max_table_length, long maxlength TSRMLS_DC)
1637 {
1638 php_oci_bind *bind;
1639 ub4 i;
1640 HashTable *hash;
1641 zval **entry;
1642
1643 hash = HASH_OF(var);
1644
1645 if (maxlength == -1) {
1646 zend_hash_internal_pointer_reset(hash);
1647 while (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
1648 convert_to_string_ex(entry);
1649 if (Z_STRLEN_PP(entry) > maxlength) {
1650 maxlength = Z_STRLEN_PP(entry) + 1;
1651 }
1652 zend_hash_move_forward(hash);
1653 }
1654 }
1655
1656 bind = emalloc(sizeof(php_oci_bind));
1657 bind->array.elements = (text *)safe_emalloc(max_table_length * (maxlength + 1), sizeof(text), 0);
1658 memset(bind->array.elements, 0, max_table_length * (maxlength + 1) * sizeof(text));
1659 bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
1660 bind->array.old_length = bind->array.current_length;
1661 bind->array.max_length = maxlength;
1662 bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
1663 memset(bind->array.element_lengths, 0, max_table_length*sizeof(ub2));
1664 bind->array.indicators = safe_emalloc(max_table_length, sizeof(sb2), 0);
1665 memset(bind->array.indicators, 0, max_table_length*sizeof(sb2));
1666
1667 zend_hash_internal_pointer_reset(hash);
1668
1669 for (i = 0; i < bind->array.current_length; i++) {
1670 if (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
1671 convert_to_string_ex(entry);
1672 bind->array.element_lengths[i] = Z_STRLEN_PP(entry);
1673 if (Z_STRLEN_PP(entry) == 0) {
1674 bind->array.indicators[i] = -1;
1675 }
1676 zend_hash_move_forward(hash);
1677 } else {
1678 break;
1679 }
1680 }
1681
1682 zend_hash_internal_pointer_reset(hash);
1683 for (i = 0; i < max_table_length; i++) {
1684 if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1685 int element_length;
1686
1687 convert_to_string_ex(entry);
1688 element_length = (maxlength > Z_STRLEN_PP(entry)) ? Z_STRLEN_PP(entry) : maxlength;
1689
1690 memcpy((text *)bind->array.elements + i*maxlength, Z_STRVAL_PP(entry), element_length);
1691 ((text *)bind->array.elements)[i*maxlength + element_length] = '\0';
1692
1693 zend_hash_move_forward(hash);
1694 } else {
1695 ((text *)bind->array.elements)[i*maxlength] = '\0';
1696 }
1697 }
1698 zend_hash_internal_pointer_reset(hash);
1699
1700 return bind;
1701 }
1702
1703
1704
1705
1706 php_oci_bind *php_oci_bind_array_helper_number(zval *var, long max_table_length TSRMLS_DC)
1707 {
1708 php_oci_bind *bind;
1709 ub4 i;
1710 HashTable *hash;
1711 zval **entry;
1712
1713 hash = HASH_OF(var);
1714
1715 bind = emalloc(sizeof(php_oci_bind));
1716 bind->array.elements = (ub4 *)safe_emalloc(max_table_length, sizeof(ub4), 0);
1717 bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
1718 bind->array.old_length = bind->array.current_length;
1719 bind->array.max_length = sizeof(ub4);
1720 bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
1721 memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1722 bind->array.indicators = NULL;
1723
1724 zend_hash_internal_pointer_reset(hash);
1725 for (i = 0; i < max_table_length; i++) {
1726 if (i < bind->array.current_length) {
1727 bind->array.element_lengths[i] = sizeof(ub4);
1728 }
1729 if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1730 convert_to_long_ex(entry);
1731 ((ub4 *)bind->array.elements)[i] = (ub4) Z_LVAL_PP(entry);
1732 zend_hash_move_forward(hash);
1733 } else {
1734 ((ub4 *)bind->array.elements)[i] = 0;
1735 }
1736 }
1737 zend_hash_internal_pointer_reset(hash);
1738
1739 return bind;
1740 }
1741
1742
1743
1744
1745 php_oci_bind *php_oci_bind_array_helper_double(zval *var, long max_table_length TSRMLS_DC)
1746 {
1747 php_oci_bind *bind;
1748 ub4 i;
1749 HashTable *hash;
1750 zval **entry;
1751
1752 hash = HASH_OF(var);
1753
1754 bind = emalloc(sizeof(php_oci_bind));
1755 bind->array.elements = (double *)safe_emalloc(max_table_length, sizeof(double), 0);
1756 bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
1757 bind->array.old_length = bind->array.current_length;
1758 bind->array.max_length = sizeof(double);
1759 bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
1760 memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1761 bind->array.indicators = NULL;
1762
1763 zend_hash_internal_pointer_reset(hash);
1764 for (i = 0; i < max_table_length; i++) {
1765 if (i < bind->array.current_length) {
1766 bind->array.element_lengths[i] = sizeof(double);
1767 }
1768 if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1769 convert_to_double_ex(entry);
1770 ((double *)bind->array.elements)[i] = (double) Z_DVAL_PP(entry);
1771 zend_hash_move_forward(hash);
1772 } else {
1773 ((double *)bind->array.elements)[i] = 0;
1774 }
1775 }
1776 zend_hash_internal_pointer_reset(hash);
1777
1778 return bind;
1779 }
1780
1781
1782
1783
1784 php_oci_bind *php_oci_bind_array_helper_date(zval *var, long max_table_length, php_oci_connection *connection TSRMLS_DC)
1785 {
1786 php_oci_bind *bind;
1787 ub4 i;
1788 HashTable *hash;
1789 zval **entry;
1790 sword errstatus;
1791
1792 hash = HASH_OF(var);
1793
1794 bind = emalloc(sizeof(php_oci_bind));
1795 bind->array.elements = (OCIDate *)safe_emalloc(max_table_length, sizeof(OCIDate), 0);
1796 bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
1797 bind->array.old_length = bind->array.current_length;
1798 bind->array.max_length = sizeof(OCIDate);
1799 bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
1800 memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1801 bind->array.indicators = NULL;
1802
1803 zend_hash_internal_pointer_reset(hash);
1804 for (i = 0; i < max_table_length; i++) {
1805 OCIDate oci_date;
1806 if (i < bind->array.current_length) {
1807 bind->array.element_lengths[i] = sizeof(OCIDate);
1808 }
1809 if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1810
1811 convert_to_string_ex(entry);
1812 PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), NULL, 0, NULL, 0, &oci_date));
1813
1814 if (errstatus != OCI_SUCCESS) {
1815
1816 efree(bind->array.element_lengths);
1817 efree(bind->array.elements);
1818 efree(bind);
1819 connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
1820 PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
1821 return NULL;
1822 }
1823
1824 ((OCIDate *)bind->array.elements)[i] = oci_date;
1825 zend_hash_move_forward(hash);
1826 } else {
1827 PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)"01-JAN-00", sizeof("01-JAN-00")-1, NULL, 0, NULL, 0, &oci_date));
1828
1829 if (errstatus != OCI_SUCCESS) {
1830
1831 efree(bind->array.element_lengths);
1832 efree(bind->array.elements);
1833 efree(bind);
1834 connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
1835 PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
1836 return NULL;
1837 }
1838
1839 ((OCIDate *)bind->array.elements)[i] = oci_date;
1840 }
1841 connection->errcode = 0;
1842 }
1843 zend_hash_internal_pointer_reset(hash);
1844
1845 return bind;
1846 }
1847
1848
1849 #endif
1850
1851
1852
1853
1854
1855
1856
1857
1858