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 : | Authors: Stig Sæther Bakken <ssb@php.net> |
16 : | Thies C. Arntzen <thies@thieso.net> |
17 : | |
18 : | Collection support by Andy Sautins <asautins@veripost.net> |
19 : | Temporary LOB support by David Benson <dbenson@mancala.com> |
20 : | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
21 : | |
22 : | Redesigned by: Antony Dovgal <antony@zend.com> |
23 : | Andi Gutmans <andi@zend.com> |
24 : | Wez Furlong <wez@omniti.com> |
25 : +----------------------------------------------------------------------+
26 : */
27 :
28 : /* $Id: oci8_statement.c 289264 2009-10-06 22:36:32Z sixd $ */
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 : /* {{{ php_oci_statement_create()
45 : Create statemend handle and allocate necessary resources */
46 : php_oci_statement *php_oci_statement_create (php_oci_connection *connection, zstr query, int query_len, zend_uchar type TSRMLS_DC)
47 34041 : {
48 : php_oci_statement *statement;
49 :
50 34041 : statement = ecalloc(1,sizeof(php_oci_statement));
51 :
52 34041 : if (!query_len) {
53 : /* do not allocate stmt handle for refcursors, we'll get it from OCIStmtPrepare2() */
54 1424 : PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->stmt), OCI_HTYPE_STMT, 0, NULL));
55 : }
56 :
57 34041 : PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->err), OCI_HTYPE_ERROR, 0, NULL));
58 :
59 34041 : if (query_len > 0) {
60 32617 : PHP_OCI_CALL_RETURN(connection->errcode, OCIStmtPrepare2,
61 : (
62 : connection->svc,
63 : &(statement->stmt),
64 : connection->err,
65 : (text *)query.s,
66 : USTR_BYTES(type, query_len),
67 : NULL,
68 : 0,
69 : OCI_NTV_SYNTAX,
70 : OCI_DEFAULT
71 : )
72 : );
73 32617 : if (connection->errcode != OCI_SUCCESS) {
74 3 : connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
75 :
76 3 : PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
77 3 : PHP_OCI_CALL(OCIHandleFree,(statement->err, OCI_HTYPE_ERROR));
78 :
79 3 : efree(statement);
80 3 : PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
81 3 : return NULL;
82 : }
83 : }
84 :
85 66652 : if (query.s && query_len) {
86 32614 : statement->last_query = safe_emalloc(1, USTR_BYTES(type, query_len + 1), 0);
87 32614 : memcpy(statement->last_query, query.s, USTR_BYTES(type, query_len));
88 32614 : statement->last_query[USTR_BYTES(type, query_len)] = '\0';
89 32614 : statement->last_query_len = query_len;
90 : }
91 : else {
92 1424 : statement->last_query = NULL;
93 1424 : statement->last_query_len = 0;
94 : }
95 :
96 34038 : statement->connection = connection;
97 34038 : statement->has_data = 0;
98 34038 : statement->parent_stmtid = 0;
99 34038 : zend_list_addref(statement->connection->rsrc_id);
100 :
101 34038 : if (OCI_G(default_prefetch) >= 0) {
102 34038 : php_oci_statement_set_prefetch(statement, OCI_G(default_prefetch) TSRMLS_CC);
103 : }
104 :
105 34038 : PHP_OCI_REGISTER_RESOURCE(statement, le_statement);
106 :
107 34038 : OCI_G(num_statements)++;
108 :
109 34038 : return statement;
110 : }
111 : /* }}} */
112 :
113 : /* {{{ php_oci_statement_set_prefetch()
114 : Set prefetch buffer size for the statement (we're assuming that one row is ~1K sized) */
115 : int php_oci_statement_set_prefetch(php_oci_statement *statement, long size TSRMLS_DC)
116 34041 : {
117 34041 : ub4 prefetch = size;
118 :
119 34041 : if (size < 0) {
120 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows to be prefetched has to be greater than or equal to 0");
121 0 : return 1;
122 : }
123 :
124 34041 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_ROWS, statement->err));
125 :
126 34041 : if (statement->errcode != OCI_SUCCESS) {
127 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
128 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
129 0 : return 1;
130 : }
131 :
132 34041 : return 0;
133 : }
134 : /* }}} */
135 :
136 : /* {{{ php_oci_statement_fetch()
137 : Fetch a row from the statement */
138 : int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC)
139 131686 : {
140 : int i;
141 : void *handlepp;
142 : ub4 typep, iterp, idxp;
143 : ub1 in_outp, piecep;
144 131686 : zend_bool piecewisecols = 0;
145 : php_oci_out_column *column;
146 : zstr zstr_data;
147 :
148 131686 : PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
149 :
150 131686 : if ( statement->errcode == OCI_NO_DATA || nrows == 0 ) {
151 30216 : if (statement->last_query == NULL) {
152 : /* reset define-list for refcursors */
153 15 : if (statement->columns) {
154 13 : zend_hash_destroy(statement->columns);
155 13 : efree(statement->columns);
156 13 : statement->columns = NULL;
157 13 : statement->ncolumns = 0;
158 : }
159 15 : statement->executed = 0;
160 : }
161 :
162 30216 : statement->errcode = 0; /* OCI_NO_DATA is NO error for us!!! */
163 30216 : statement->has_data = 0;
164 :
165 30216 : if (nrows == 0) {
166 : /* this is exactly what we requested */
167 8 : return 0;
168 : }
169 30208 : return 1;
170 : }
171 :
172 : /* reset length for all piecewise columns */
173 293823 : for (i = 0; i < statement->ncolumns; i++) {
174 192353 : column = php_oci_statement_get_column(statement, i + 1, NULL_ZSTR, 0 TSRMLS_CC);
175 192353 : if (column->piecewise) {
176 12 : column->retlen4 = 0;
177 12 : piecewisecols = 1;
178 : }
179 : }
180 :
181 202952 : while (statement->errcode == OCI_NEED_DATA) {
182 12 : if (piecewisecols) {
183 12 : PHP_OCI_CALL_RETURN(statement->errcode,
184 : OCIStmtGetPieceInfo,
185 : (
186 : statement->stmt,
187 : statement->err,
188 : &handlepp,
189 : &typep,
190 : &in_outp,
191 : &iterp,
192 : &idxp,
193 : &piecep
194 : )
195 : );
196 :
197 : /* scan through our columns for a piecewise column with a matching handle */
198 34 : for (i = 0; i < statement->ncolumns; i++) {
199 22 : column = php_oci_statement_get_column(statement, i + 1, NULL_ZSTR, 0 TSRMLS_CC);
200 22 : if (column->piecewise && handlepp == column->oci_define) {
201 12 : if (!column->data) {
202 4 : zstr_data.v = ecalloc(1, PHP_OCI_PIECE_SIZE + 1);
203 4 : column->data = zstr_data.v;
204 : } else {
205 8 : zstr_data.v = erealloc(column->data, column->retlen4 + PHP_OCI_PIECE_SIZE + 1);
206 8 : column->data = zstr_data.v;
207 : }
208 12 : column->cb_retlen = PHP_OCI_PIECE_SIZE;
209 :
210 : /* and instruct fetch to fetch waiting piece into our buffer */
211 12 : PHP_OCI_CALL(OCIStmtSetPieceInfo,
212 : (
213 : (void *) column->oci_define,
214 : OCI_HTYPE_DEFINE,
215 : statement->err,
216 : ((char *)zstr_data.s) + column->retlen4,
217 : &(column->cb_retlen),
218 : piecep,
219 : &column->indicator,
220 : &column->retcode
221 : )
222 : );
223 : }
224 : }
225 : }
226 :
227 12 : PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
228 :
229 12 : if (piecewisecols) {
230 34 : for (i = 0; i < statement->ncolumns; i++) {
231 22 : column = php_oci_statement_get_column(statement, i + 1, NULL_ZSTR, 0 TSRMLS_CC);
232 22 : if (column && column->piecewise && handlepp == column->oci_define) {
233 12 : column->retlen4 += column->cb_retlen;
234 : }
235 : }
236 : }
237 : }
238 :
239 101470 : if (statement->errcode == OCI_SUCCESS_WITH_INFO || statement->errcode == OCI_SUCCESS) {
240 101462 : statement->has_data = 1;
241 :
242 : /* do the stuff needed for OCIDefineByName */
243 293808 : for (i = 0; i < statement->ncolumns; i++) {
244 192346 : column = php_oci_statement_get_column(statement, i + 1, NULL_ZSTR, 0 TSRMLS_CC);
245 192346 : if (column == NULL) {
246 0 : continue;
247 : }
248 :
249 192346 : if (!column->define) {
250 102330 : continue;
251 : }
252 :
253 90016 : zval_dtor(column->define->zval);
254 90016 : php_oci_column_to_zval(column, column->define->zval, 0 TSRMLS_CC);
255 : }
256 :
257 101462 : return 0;
258 : }
259 :
260 8 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
261 8 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
262 :
263 8 : statement->has_data = 0;
264 :
265 8 : return 1;
266 : }
267 : /* }}} */
268 :
269 : /* {{{ php_oci_statement_get_column()
270 : Get column from the result set */
271 : php_oci_out_column *php_oci_statement_get_column(php_oci_statement *statement, long column_index, zstr column_name, int column_name_len TSRMLS_DC)
272 577359 : {
273 577359 : php_oci_out_column *column = NULL;
274 : int i;
275 :
276 577359 : if (statement->columns == NULL) { /* we release the columns at the end of a fetch */
277 0 : return NULL;
278 : }
279 :
280 577359 : if (column_name.v != NULL) {
281 344 : for (i = 0; i < statement->ncolumns; i++) {
282 337 : column = php_oci_statement_get_column(statement, i + 1, NULL_ZSTR, 0 TSRMLS_CC);
283 337 : if (column == NULL) {
284 0 : continue;
285 337 : } else if ((int) column->name_len == column_name_len) {
286 321 : if (!u_strncmp(column->name.u, column_name.u, column_name_len)) {
287 69 : return column;
288 : }
289 : }
290 : }
291 577283 : } else if (column_index != -1) {
292 577276 : if (zend_hash_index_find(statement->columns, column_index, (void **)&column) == FAILURE) {
293 7 : return NULL;
294 : }
295 577269 : return column;
296 : }
297 :
298 14 : return NULL;
299 : }
300 : /* }}} */
301 :
302 : /* php_oci_define_callback() {{{ */
303 : sb4 php_oci_define_callback(dvoid *ctx, OCIDefine *define, ub4 iter, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcpp)
304 184853 : {
305 184853 : php_oci_out_column *outcol = (php_oci_out_column *)ctx;
306 :
307 184853 : if (!outcol) {
308 : TSRMLS_FETCH();
309 :
310 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid context pointer value");
311 0 : return OCI_ERROR;
312 : }
313 :
314 184853 : switch(outcol->data_type) {
315 : case SQLT_RSET: {
316 : php_oci_statement *nested_stmt;
317 : TSRMLS_FETCH();
318 :
319 1416 : nested_stmt = php_oci_statement_create(outcol->statement->connection, NULL_ZSTR, 0, 0 TSRMLS_CC);
320 1416 : if (!nested_stmt) {
321 0 : return OCI_ERROR;
322 : }
323 1416 : nested_stmt->parent_stmtid = outcol->statement->id;
324 1416 : zend_list_addref(outcol->statement->id);
325 1416 : outcol->nested_statement = nested_stmt;
326 1416 : outcol->stmtid = nested_stmt->id;
327 :
328 1416 : *bufpp = nested_stmt->stmt;
329 1416 : *alenpp = &(outcol->retlen4);
330 1416 : *piecep = OCI_ONE_PIECE;
331 1416 : *indpp = &(outcol->indicator);
332 1416 : *rcpp = &(outcol->retcode);
333 1416 : return OCI_CONTINUE;
334 : }
335 : break;
336 : case SQLT_RDD:
337 : case SQLT_BLOB:
338 : case SQLT_CLOB:
339 : case SQLT_BFILE: {
340 : php_oci_descriptor *descr;
341 : int dtype;
342 : TSRMLS_FETCH();
343 :
344 183437 : if (outcol->data_type == SQLT_BFILE) {
345 3 : dtype = OCI_DTYPE_FILE;
346 183434 : } else if (outcol->data_type == SQLT_RDD ) {
347 1 : dtype = OCI_DTYPE_ROWID;
348 : } else {
349 183433 : dtype = OCI_DTYPE_LOB;
350 : }
351 :
352 183437 : descr = php_oci_lob_create(outcol->statement->connection, dtype TSRMLS_CC);
353 183437 : if (!descr) {
354 0 : return OCI_ERROR;
355 : }
356 183437 : outcol->descid = descr->id;
357 183437 : descr->charset_form = outcol->charset_form;
358 :
359 183437 : *bufpp = descr->descriptor;
360 183437 : *alenpp = &(outcol->retlen4);
361 183437 : *piecep = OCI_ONE_PIECE;
362 183437 : *indpp = &(outcol->indicator);
363 183437 : *rcpp = &(outcol->retcode);
364 :
365 183437 : return OCI_CONTINUE;
366 : }
367 : break;
368 : }
369 0 : return OCI_ERROR;
370 : }
371 : /* }}} */
372 :
373 : /* {{{ php_oci_statement_execute()
374 : Execute statement */
375 : int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC)
376 34120 : {
377 : php_oci_out_column *outcol;
378 : php_oci_out_column column;
379 34120 : OCIParam *param = NULL;
380 : text *colname;
381 : ub4 counter;
382 : ub2 define_type;
383 : ub4 iters;
384 : ub4 colcount;
385 : ub2 dynamic;
386 : dvoid *buf;
387 :
388 34120 : switch (mode) {
389 : case OCI_COMMIT_ON_SUCCESS:
390 : case OCI_DESCRIBE_ONLY:
391 : case OCI_DEFAULT:
392 : /* only these are allowed */
393 : break;
394 : default:
395 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid execute mode given: %d", mode);
396 1 : return 1;
397 : break;
398 : }
399 :
400 34119 : if (!statement->stmttype) {
401 : /* get statement type */
402 34007 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement->stmttype, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
403 :
404 34007 : if (statement->errcode != OCI_SUCCESS) {
405 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
406 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
407 0 : return 1;
408 : }
409 : }
410 :
411 34119 : if (statement->stmttype == OCI_STMT_SELECT) {
412 32742 : iters = 0;
413 : } else {
414 1377 : iters = 1;
415 : }
416 :
417 34119 : if (statement->last_query) {
418 : /* if we execute refcursors we don't have a query and
419 : we don't want to execute!!! */
420 :
421 32700 : if (statement->binds) {
422 236 : int result = 0;
423 236 : zend_hash_apply_with_argument(statement->binds, (apply_func_arg_t) php_oci_bind_pre_exec, (void *)&result TSRMLS_CC);
424 236 : if (result) {
425 2 : return 1;
426 : }
427 : }
428 :
429 : /* execute statement */
430 32698 : PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtExecute, (statement->connection->svc, statement->stmt, statement->err, iters, 0, NULL, NULL, mode));
431 :
432 32698 : if (statement->errcode != OCI_SUCCESS) {
433 192 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
434 192 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
435 192 : return 1;
436 : }
437 :
438 32506 : if (statement->binds) {
439 226 : zend_hash_apply(statement->binds, (apply_func_t) php_oci_bind_post_exec TSRMLS_CC);
440 : }
441 :
442 32506 : if (mode & OCI_COMMIT_ON_SUCCESS) {
443 31657 : statement->connection->needs_commit = 0;
444 : } else {
445 849 : statement->connection->needs_commit = 1;
446 : }
447 : }
448 :
449 33925 : if (statement->stmttype == OCI_STMT_SELECT && statement->executed == 0) {
450 : /* we only need to do the define step is this very statement is executed the first time! */
451 32712 : statement->executed = 1;
452 :
453 32712 : ALLOC_HASHTABLE(statement->columns);
454 32712 : zend_hash_init(statement->columns, 13, NULL, php_oci_column_hash_dtor, 0);
455 :
456 32712 : counter = 1;
457 :
458 : /* get number of columns */
459 32712 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *)&colcount, (ub4 *)0, OCI_ATTR_PARAM_COUNT, statement->err));
460 :
461 32712 : if (statement->errcode != OCI_SUCCESS) {
462 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
463 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
464 0 : return 1;
465 : }
466 :
467 32712 : statement->ncolumns = colcount;
468 :
469 95962 : for (counter = 1; counter <= colcount; counter++) {
470 63250 : memset(&column,0,sizeof(php_oci_out_column));
471 :
472 63250 : if (zend_hash_index_update(statement->columns, counter, &column, sizeof(php_oci_out_column), (void**) &outcol) == FAILURE) {
473 0 : efree(statement->columns);
474 : /* out of memory */
475 0 : return 1;
476 : }
477 :
478 : /* get column */
479 63250 : PHP_OCI_CALL_RETURN(statement->errcode, OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)¶m, counter));
480 :
481 63250 : if (statement->errcode != OCI_SUCCESS) {
482 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
483 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
484 0 : return 1;
485 : }
486 :
487 : /* get column datatype */
488 63250 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_type, (ub4 *)0, OCI_ATTR_DATA_TYPE, statement->err));
489 :
490 63250 : if (statement->errcode != OCI_SUCCESS) {
491 0 : PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
492 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
493 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
494 0 : return 1;
495 : }
496 :
497 : /* get character set form */
498 63250 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_form, (ub4 *)0, OCI_ATTR_CHARSET_FORM, statement->err));
499 :
500 63250 : if (statement->errcode != OCI_SUCCESS) {
501 0 : PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
502 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
503 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
504 0 : return 1;
505 : }
506 :
507 : /* get character set id */
508 63250 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_id, (ub4 *)0, OCI_ATTR_CHARSET_ID, statement->err));
509 :
510 63250 : if (statement->errcode != OCI_SUCCESS) {
511 0 : PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
512 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
513 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
514 0 : return 1;
515 : }
516 :
517 : /* get size of the column */
518 63250 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_size, (dvoid *)0, OCI_ATTR_DATA_SIZE, statement->err));
519 :
520 63250 : if (statement->errcode != OCI_SUCCESS) {
521 0 : PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
522 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
523 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
524 0 : return 1;
525 : }
526 :
527 63250 : outcol->storage_size4 = outcol->data_size;
528 63250 : outcol->retlen = TEXT_CHARS(outcol->data_size);
529 :
530 : /* get scale of the column */
531 63250 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->scale, (dvoid *)0, OCI_ATTR_SCALE, statement->err));
532 :
533 63250 : if (statement->errcode != OCI_SUCCESS) {
534 0 : PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
535 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
536 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
537 0 : return 1;
538 : }
539 :
540 : /* get precision of the column */
541 63250 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->precision, (dvoid *)0, OCI_ATTR_PRECISION, statement->err));
542 :
543 63250 : if (statement->errcode != OCI_SUCCESS) {
544 0 : PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
545 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
546 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
547 0 : return 1;
548 : }
549 :
550 : /* get name of the column */
551 63250 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid **)&colname, (ub4 *)&outcol->name_len, (ub4)OCI_ATTR_NAME, statement->err));
552 :
553 63250 : if (statement->errcode != OCI_SUCCESS) {
554 0 : PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
555 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
556 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
557 0 : return 1;
558 : }
559 63250 : PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
560 :
561 63250 : outcol->name_len = TEXT_CHARS(outcol->name_len);
562 63250 : outcol->name.u = eustrndup((UChar*) colname, outcol->name_len);
563 :
564 : /* find a user-setted define */
565 63250 : if (statement->defines) {
566 30020 : if (zend_hash_find(statement->defines, outcol->name.s, TEXT_BYTES(outcol->name_len + 1),(void **) &outcol->define) == SUCCESS) {
567 30015 : if (outcol->define->type) {
568 7 : outcol->data_type = outcol->define->type;
569 : }
570 : }
571 : }
572 :
573 63250 : buf = 0;
574 63250 : switch (outcol->data_type) {
575 : case SQLT_RSET:
576 1410 : outcol->statement = statement; /* parent handle */
577 :
578 1410 : define_type = SQLT_RSET;
579 1410 : outcol->is_cursor = 1;
580 1410 : outcol->storage_size4 = -1;
581 1410 : outcol->retlen = -1;
582 1410 : dynamic = OCI_DYNAMIC_FETCH;
583 1410 : break;
584 :
585 : case SQLT_RDD: /* ROWID */
586 : case SQLT_BLOB: /* binary LOB */
587 : case SQLT_CLOB: /* character LOB */
588 : case SQLT_BFILE: /* binary file LOB */
589 60134 : outcol->statement = statement; /* parent handle */
590 :
591 60134 : define_type = outcol->data_type;
592 60134 : outcol->is_descr = 1;
593 60134 : outcol->storage_size4 = -1;
594 60134 : dynamic = OCI_DYNAMIC_FETCH;
595 60134 : break;
596 :
597 : case SQLT_LNG:
598 : case SQLT_LBI:
599 4 : if (outcol->data_type == SQLT_LBI) {
600 1 : define_type = SQLT_BIN;
601 : } else {
602 3 : define_type = SQLT_CHR;
603 : }
604 4 : outcol->storage_size4 = PHP_OCI_MAX_DATA_SIZE;
605 4 : outcol->piecewise = 1;
606 4 : dynamic = OCI_DYNAMIC_FETCH;
607 4 : break;
608 :
609 : case SQLT_BIN:
610 : default:
611 1702 : define_type = SQLT_CHR;
612 1702 : if (outcol->data_type == SQLT_BIN) {
613 4 : define_type = SQLT_BIN;
614 : }
615 2676 : if ((outcol->data_type == SQLT_DAT) || (outcol->data_type == SQLT_NUM)
616 : #ifdef SQLT_TIMESTAMP
617 : || (outcol->data_type == SQLT_TIMESTAMP)
618 : #endif
619 : #ifdef SQLT_TIMESTAMP_TZ
620 : || (outcol->data_type == SQLT_TIMESTAMP_TZ)
621 : #endif
622 : #ifdef SQLT_TIMESTAMP_LTZ
623 : || (outcol->data_type == SQLT_TIMESTAMP_LTZ)
624 : #endif
625 : #ifdef SQLT_INTERVAL_YM
626 : || (outcol->data_type == SQLT_INTERVAL_YM)
627 : #endif
628 : #ifdef SQLT_INTERVAL_DS
629 : || (outcol->data_type == SQLT_INTERVAL_DS)
630 : #endif
631 : ) {
632 974 : outcol->storage_size4 = 512; /* XXX this should fit "most" NLS date-formats and Numbers */
633 : #if defined(SQLT_IBFLOAT) && defined(SQLT_IBDOUBLE)
634 728 : } else if (outcol->data_type == SQLT_IBFLOAT || outcol->data_type == SQLT_IBDOUBLE) {
635 0 : outcol->storage_size4 = 1024;
636 : #endif
637 : } else {
638 728 : outcol->storage_size4++; /* add one for string terminator */
639 : }
640 :
641 1702 : outcol->storage_size4 *= 3;
642 :
643 1702 : dynamic = OCI_DEFAULT;
644 1702 : buf = outcol->data = (text *) safe_emalloc(1, outcol->storage_size4, 0);
645 1702 : memset(buf, 0, outcol->storage_size4);
646 : break;
647 : }
648 :
649 63250 : if (dynamic == OCI_DYNAMIC_FETCH) {
650 61548 : PHP_OCI_CALL_RETURN(statement->errcode,
651 : OCIDefineByPos,
652 : (
653 : statement->stmt, /* IN/OUT handle to the requested SQL query */
654 : (OCIDefine **)&outcol->oci_define, /* IN/OUT pointer to a pointer to a define handle */
655 : statement->err, /* IN/OUT An error handle */
656 : counter, /* IN position in the select list */
657 : (dvoid *)NULL, /* IN/OUT pointer to a buffer */
658 : outcol->storage_size4, /* IN The size of each valuep buffer in bytes */
659 : define_type, /* IN The data type */
660 : (dvoid *)&outcol->indicator, /* IN pointer to an indicator variable or arr */
661 : (ub2 *)NULL, /* IN/OUT Pointer to array of length of data fetched */
662 : (ub2 *)NULL, /* OUT Pointer to array of column-level return codes */
663 : OCI_DYNAMIC_FETCH /* IN mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
664 : )
665 : );
666 :
667 : } else {
668 1702 : PHP_OCI_CALL_RETURN(statement->errcode,
669 : OCIDefineByPos,
670 : (
671 : statement->stmt, /* IN/OUT handle to the requested SQL query */
672 : (OCIDefine **)&outcol->oci_define, /* IN/OUT pointer to a pointer to a define handle */
673 : statement->err, /* IN/OUT An error handle */
674 : counter, /* IN position in the select list */
675 : (dvoid *)buf, /* IN/OUT pointer to a buffer */
676 : outcol->storage_size4, /* IN The size of each valuep buffer in bytes */
677 : define_type, /* IN The data type */
678 : (dvoid *)&outcol->indicator, /* IN pointer to an indicator variable or arr */
679 : (ub2 *)&outcol->retlen, /* IN/OUT Pointer to array of length of data fetched */
680 : (ub2 *)&outcol->retcode, /* OUT Pointer to array of column-level return codes */
681 : OCI_DEFAULT /* IN mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
682 : )
683 : );
684 :
685 : }
686 :
687 63250 : if (statement->errcode != OCI_SUCCESS) {
688 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
689 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
690 0 : return 0;
691 : }
692 :
693 : /* additional OCIDefineDynamic() call */
694 63250 : switch (outcol->data_type) {
695 : case SQLT_RSET:
696 : case SQLT_RDD:
697 : case SQLT_BLOB:
698 : case SQLT_CLOB:
699 : case SQLT_BFILE:
700 61544 : PHP_OCI_CALL_RETURN(statement->errcode,
701 : OCIDefineDynamic,
702 : (
703 : outcol->oci_define,
704 : statement->err,
705 : (dvoid *)outcol,
706 : php_oci_define_callback
707 : )
708 : );
709 :
710 : break;
711 : }
712 : }
713 : }
714 :
715 33925 : return 0;
716 : }
717 : /* }}} */
718 :
719 : /* {{{ php_oci_statement_cancel()
720 : Cancel statement */
721 : int php_oci_statement_cancel(php_oci_statement *statement TSRMLS_DC)
722 8 : {
723 :
724 8 : return php_oci_statement_fetch(statement, 0 TSRMLS_CC);
725 :
726 : } /* }}} */
727 :
728 : /* {{{ php_oci_statement_free()
729 : Destroy statement handle and free associated resources */
730 : void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC)
731 34038 : {
732 34038 : if (statement->stmt) {
733 34038 : if (statement->last_query_len) { /* FIXME: magical */
734 32614 : PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
735 : } else {
736 1424 : PHP_OCI_CALL(OCIHandleFree, (statement->stmt, OCI_HTYPE_STMT));
737 : }
738 34038 : statement->stmt = 0;
739 : }
740 :
741 34038 : if (statement->err) {
742 34038 : PHP_OCI_CALL(OCIHandleFree, (statement->err, OCI_HTYPE_ERROR));
743 34038 : statement->err = 0;
744 : }
745 :
746 34038 : if (statement->last_query) {
747 32614 : efree(statement->last_query);
748 : }
749 :
750 34038 : if (statement->columns) {
751 32699 : zend_hash_destroy(statement->columns);
752 32699 : efree(statement->columns);
753 : }
754 :
755 34038 : if (statement->binds) {
756 222 : zend_hash_destroy(statement->binds);
757 222 : efree(statement->binds);
758 : }
759 :
760 34038 : if (statement->defines) {
761 15020 : zend_hash_destroy(statement->defines);
762 15020 : efree(statement->defines);
763 : }
764 :
765 34038 : if (statement->parent_stmtid) {
766 1416 : zend_list_delete(statement->parent_stmtid);
767 : }
768 :
769 34038 : zend_list_delete(statement->connection->rsrc_id);
770 34038 : efree(statement);
771 :
772 34038 : OCI_G(num_statements)--;
773 34038 : } /* }}} */
774 :
775 : /* {{{ php_oci_bind_pre_exec()
776 : Helper function */
777 : int php_oci_bind_pre_exec(void *data, void *result TSRMLS_DC)
778 351 : {
779 351 : php_oci_bind *bind = (php_oci_bind *) data;
780 351 : *(int *)result = 0;
781 :
782 351 : switch (bind->type) {
783 : case SQLT_NTY:
784 : case SQLT_BFILEE:
785 : case SQLT_CFILEE:
786 : case SQLT_CLOB:
787 : case SQLT_BLOB:
788 : case SQLT_RDD:
789 189 : if (Z_TYPE_P(bind->zval) != IS_OBJECT) {
790 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
791 0 : *(int *)result = 1;
792 : }
793 189 : break;
794 :
795 : case SQLT_INT:
796 : case SQLT_NUM:
797 2 : if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
798 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
799 0 : *(int *)result = 1;
800 : }
801 2 : break;
802 :
803 : case SQLT_LBI:
804 : case SQLT_BIN:
805 : case SQLT_LNG:
806 : case SQLT_AFC:
807 : case SQLT_CHR:
808 136 : if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
809 2 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
810 2 : *(int *)result = 1;
811 : }
812 136 : break;
813 :
814 : case SQLT_RSET:
815 6 : if (Z_TYPE_P(bind->zval) != IS_RESOURCE) {
816 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
817 0 : *(int *)result = 1;
818 : }
819 : break;
820 : }
821 :
822 : /* reset all bind stuff to a normal state..-. */
823 :
824 351 : bind->indicator = 0;
825 :
826 351 : return 0;
827 : }
828 : /* }}} */
829 :
830 : /* {{{ php_oci_bind_post_exec()
831 : Helper function */
832 : int php_oci_bind_post_exec(void *data TSRMLS_DC)
833 340 : {
834 340 : php_oci_bind *bind = (php_oci_bind *) data;
835 340 : php_oci_connection *connection = bind->parent_statement->connection;
836 :
837 340 : if (bind->indicator == -1) { /* NULL */
838 3 : zval *val = bind->zval;
839 3 : if (Z_TYPE_P(val) == IS_STRING) {
840 0 : *Z_STRVAL_P(val) = '\0'; /* XXX avoid warning in debug mode */
841 : }
842 3 : zval_dtor(val);
843 3 : ZVAL_NULL(val);
844 337 : } else if (Z_TYPE_P(bind->zval) == IS_STRING && Z_STRLEN_P(bind->zval) > 0) {
845 0 : Z_STRVAL_P(bind->zval) = erealloc(Z_STRVAL_P(bind->zval), Z_STRLEN_P(bind->zval)+1);
846 0 : Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] = '\0';
847 464 : } else if (Z_TYPE_P(bind->zval) == IS_UNICODE && Z_UNILEN_P(bind->zval) > 0) {
848 127 : if (bind->out) {
849 : /* OCI returns _bytes_ as data length for OUT binds */
850 2 : Z_UNILEN_P(bind->zval) = TEXT_CHARS(Z_UNILEN_P(bind->zval));
851 : }
852 127 : Z_UNIVAL_P(bind->zval).u = eurealloc(Z_UNIVAL_P(bind->zval).u, Z_UNILEN_P(bind->zval)+1);
853 127 : Z_UNIVAL_P(bind->zval).s[ TEXT_BYTES(Z_UNILEN_P(bind->zval)) - 1 ] = '\0';
854 127 : Z_UNIVAL_P(bind->zval).s[ TEXT_BYTES(Z_UNILEN_P(bind->zval)) ] = '\0';
855 210 : } else if (Z_TYPE_P(bind->zval) == IS_ARRAY) {
856 : int i;
857 : zval **entry;
858 15 : HashTable *hash = HASH_OF(bind->zval);
859 :
860 15 : zend_hash_internal_pointer_reset(hash);
861 :
862 15 : switch (bind->array.type) {
863 : case SQLT_NUM:
864 : case SQLT_INT:
865 : case SQLT_LNG:
866 18 : for (i = 0; i < bind->array.current_length; i++) {
867 25 : if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
868 10 : zval_dtor(*entry);
869 10 : ZVAL_LONG(*entry, ((ub4 *)(bind->array.elements))[i]);
870 10 : zend_hash_move_forward(hash);
871 : } else {
872 5 : add_next_index_long(bind->zval, ((ub4 *)(bind->array.elements))[i]);
873 : }
874 : }
875 3 : break;
876 : case SQLT_FLT:
877 12 : for (i = 0; i < bind->array.current_length; i++) {
878 20 : if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
879 10 : zval_dtor(*entry);
880 10 : ZVAL_DOUBLE(*entry, ((double *)(bind->array.elements))[i]);
881 10 : zend_hash_move_forward(hash);
882 : } else {
883 0 : add_next_index_double(bind->zval, ((double *)(bind->array.elements))[i]);
884 : }
885 : }
886 2 : break;
887 : case SQLT_ODT:
888 12 : for (i = 0; i < bind->array.current_length; i++) {
889 : oratext buff[1024];
890 10 : ub4 buff_len = 1024;
891 :
892 10 : memset((void*)buff,0,sizeof(buff));
893 :
894 20 : if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
895 10 : PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
896 10 : zval_dtor(*entry);
897 :
898 10 : if (connection->errcode != OCI_SUCCESS) {
899 0 : connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
900 0 : PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
901 0 : ZVAL_NULL(*entry);
902 : } else {
903 : zstr tmp;
904 10 : tmp.s = (char *)buff;
905 10 : ZVAL_UNICODEL(*entry, tmp.u, TEXT_CHARS(buff_len), 1);
906 : }
907 10 : zend_hash_move_forward(hash);
908 : } else {
909 : zstr tmp;
910 0 : PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
911 0 : tmp.s = (char *)buff;
912 0 : if (connection->errcode != OCI_SUCCESS) {
913 0 : connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
914 0 : PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
915 0 : add_next_index_null(bind->zval);
916 : } else {
917 0 : add_next_index_unicodel(bind->zval, tmp.u, TEXT_CHARS(buff_len), 1);
918 : }
919 : }
920 : }
921 2 : break;
922 :
923 : case SQLT_AFC:
924 : case SQLT_CHR:
925 : case SQLT_VCS:
926 : case SQLT_AVC:
927 : case SQLT_STR:
928 : case SQLT_LVC:
929 : {
930 : zstr tmp;
931 48 : for (i = 0; i < bind->array.current_length; i++) {
932 : /* int curr_element_length = strlen(((text *)bind->array.elements)+i*bind->array.max_length); */
933 40 : ub2 curr_element_length = TEXT_CHARS(bind->array.element_lengths[i]);
934 75 : if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
935 35 : zval_dtor(*entry);
936 35 : tmp.u = ((UChar *)bind->array.elements)+TEXT_CHARS(i*bind->array.max_length);
937 :
938 35 : ZVAL_UNICODEL(*entry, tmp.u, curr_element_length, 1);
939 35 : zend_hash_move_forward(hash);
940 : } else {
941 5 : tmp.s = (char *)(((text *)bind->array.elements)+(i*bind->array.max_length));
942 5 : add_next_index_unicodel(bind->zval, tmp.u, curr_element_length, 1);
943 : }
944 : }
945 : }
946 : break;
947 : }
948 : }
949 :
950 340 : return 0;
951 : }
952 : /* }}} */
953 :
954 : /* {{{ php_oci_bind_by_name()
955 : Bind zval to the given placeholder */
956 : int php_oci_bind_by_name(php_oci_statement *statement, zstr name, int name_len, zval* var, long maxlength, ub2 type, zend_uchar uni_type TSRMLS_DC)
957 319 : {
958 319 : php_oci_collection *bind_collection = NULL;
959 319 : php_oci_descriptor *bind_descriptor = NULL;
960 319 : php_oci_statement *bind_statement = NULL;
961 319 : dvoid *oci_desc = NULL;
962 : /* dvoid *php_oci_collection = NULL; */
963 319 : OCIStmt *oci_stmt = NULL;
964 319 : dvoid *bind_data = NULL;
965 : php_oci_bind bind, *old_bind, *bindp;
966 319 : int mode = OCI_DATA_AT_EXEC;
967 319 : sb4 value_sz = -1;
968 :
969 319 : switch (type) {
970 : case SQLT_NTY:
971 : {
972 : zval **tmp;
973 :
974 1 : if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
975 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
976 0 : return 1;
977 : }
978 :
979 1 : PHP_OCI_ZVAL_TO_COLLECTION_EX(*tmp, bind_collection);
980 1 : value_sz = sizeof(void*);
981 1 : mode = OCI_DEFAULT;
982 :
983 1 : if (!bind_collection->collection) {
984 0 : return 1;
985 : }
986 : }
987 1 : break;
988 : case SQLT_BFILEE:
989 : case SQLT_CFILEE:
990 : case SQLT_CLOB:
991 : case SQLT_BLOB:
992 : case SQLT_RDD:
993 : {
994 : zval **tmp;
995 :
996 181 : if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
997 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
998 0 : return 1;
999 : }
1000 :
1001 181 : PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, bind_descriptor);
1002 :
1003 181 : value_sz = sizeof(void*);
1004 :
1005 181 : oci_desc = bind_descriptor->descriptor;
1006 :
1007 181 : if (!oci_desc) {
1008 0 : return 1;
1009 : }
1010 : }
1011 181 : break;
1012 :
1013 : case SQLT_INT:
1014 : case SQLT_NUM:
1015 2 : if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
1016 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
1017 0 : return 1;
1018 : }
1019 2 : convert_to_long(var);
1020 2 : bind_data = (ub4 *)&Z_LVAL_P(var);
1021 2 : value_sz = sizeof(ub4);
1022 2 : mode = OCI_DEFAULT;
1023 2 : break;
1024 :
1025 : case SQLT_LBI:
1026 : case SQLT_BIN:
1027 : case SQLT_LNG:
1028 : case SQLT_AFC:
1029 : case SQLT_CHR: /* SQLT_CHR is the default value when type was not specified */
1030 129 : if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
1031 2 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
1032 2 : return 1;
1033 : }
1034 127 : if (Z_TYPE_P(var) != IS_NULL) {
1035 120 : convert_to_unicode(var);
1036 : }
1037 127 : if (maxlength == -1) {
1038 122 : switch (Z_TYPE_P(var)) {
1039 : case IS_STRING:
1040 0 : value_sz = Z_STRLEN_P(var);
1041 0 : break;
1042 : case IS_UNICODE:
1043 119 : value_sz = Z_UNILEN_P(var);
1044 119 : break;
1045 : default:
1046 3 : value_sz = 0;
1047 : break;
1048 : }
1049 : } else {
1050 5 : value_sz = maxlength;
1051 : }
1052 127 : break;
1053 :
1054 : case SQLT_RSET:
1055 6 : if (Z_TYPE_P(var) != IS_RESOURCE) {
1056 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
1057 0 : return 1;
1058 : }
1059 6 : PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement);
1060 6 : value_sz = sizeof(void*);
1061 :
1062 6 : oci_stmt = bind_statement->stmt;
1063 :
1064 6 : if (!oci_stmt) {
1065 0 : return 1;
1066 : }
1067 6 : break;
1068 :
1069 : default:
1070 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %d", (int) type);
1071 0 : return 1;
1072 : break;
1073 : }
1074 :
1075 317 : if (value_sz == 0) {
1076 5 : value_sz = 1;
1077 : }
1078 :
1079 317 : if (!statement->binds) {
1080 205 : ALLOC_HASHTABLE(statement->binds);
1081 205 : zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
1082 : }
1083 :
1084 317 : memset((void*)&bind,0,sizeof(php_oci_bind));
1085 317 : if (zend_hash_find(statement->binds, name.s, USTR_BYTES(uni_type, name_len + 1), (void **)&old_bind) == SUCCESS) {
1086 2 : bindp = old_bind;
1087 2 : if (bindp->zval) {
1088 2 : zval_ptr_dtor(&bindp->zval);
1089 : }
1090 : } else {
1091 315 : zend_hash_update(statement->binds, name.s, USTR_BYTES(uni_type, name_len + 1), &bind, sizeof(php_oci_bind), (void **)&bindp);
1092 : }
1093 :
1094 317 : bindp->descriptor = oci_desc;
1095 317 : bindp->statement = oci_stmt;
1096 317 : bindp->parent_statement = statement;
1097 317 : bindp->zval = var;
1098 317 : bindp->type = type;
1099 317 : zval_add_ref(&var);
1100 :
1101 317 : PHP_OCI_CALL_RETURN(statement->errcode,
1102 : OCIBindByName,
1103 : (
1104 : statement->stmt, /* statement handle */
1105 : (OCIBind **)&bindp->bind, /* bind hdl (will alloc) */
1106 : statement->err, /* error handle */
1107 : (text*) name.s, /* placeholder name */
1108 : USTR_BYTES(uni_type, name_len), /* placeholder length */
1109 : (dvoid *)bind_data, /* in/out data */
1110 : TEXT_BYTES(value_sz), /* PHP_OCI_MAX_DATA_SIZE, */ /* max size of input/output data */
1111 : type, /* in/out data type */
1112 : (dvoid *)&bindp->indicator, /* indicator (ignored) */
1113 : (ub2 *)0, /* size array (ignored) */
1114 : (ub2 *)&bindp->retcode, /* return code (ignored) */
1115 : (ub4)0, /* maxarr_len (PL/SQL only?) */
1116 : (ub4 *)0, /* actual array size (PL/SQL only?) */
1117 : mode /* mode */
1118 : )
1119 : );
1120 :
1121 317 : if (statement->errcode != OCI_SUCCESS) {
1122 1 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
1123 1 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1124 1 : return 1;
1125 : }
1126 :
1127 316 : if (mode == OCI_DATA_AT_EXEC) {
1128 313 : PHP_OCI_CALL_RETURN(statement->errcode, OCIBindDynamic,
1129 : (
1130 : bindp->bind,
1131 : statement->err,
1132 : (dvoid *)bindp,
1133 : php_oci_bind_in_callback,
1134 : (dvoid *)bindp,
1135 : php_oci_bind_out_callback
1136 : )
1137 : );
1138 :
1139 313 : if (statement->errcode != OCI_SUCCESS) {
1140 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
1141 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1142 0 : return 1;
1143 : }
1144 : }
1145 :
1146 316 : if (type == SQLT_NTY) {
1147 : /* Bind object */
1148 1 : PHP_OCI_CALL_RETURN(statement->errcode, OCIBindObject,
1149 : (
1150 : bindp->bind,
1151 : statement->err,
1152 : bind_collection->tdo,
1153 : (dvoid **) &(bind_collection->collection),
1154 : (ub4 *) 0,
1155 : (dvoid **) 0,
1156 : (ub4 *) 0
1157 : )
1158 : );
1159 :
1160 1 : if (statement->errcode) {
1161 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
1162 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1163 0 : return 1;
1164 : }
1165 : }
1166 :
1167 316 : return 0;
1168 : } /* }}} */
1169 :
1170 : /* {{{ php_oci_bind_in_callback()
1171 : Callback used when binding LOBs and VARCHARs */
1172 : sb4 php_oci_bind_in_callback(
1173 : dvoid *ictxp, /* context pointer */
1174 : OCIBind *bindp, /* bind handle */
1175 : ub4 iter, /* 0-based execute iteration value */
1176 : ub4 index, /* index of current array for PL/SQL or row index for SQL */
1177 : dvoid **bufpp, /* pointer to data */
1178 : ub4 *alenp, /* size after value/piece has been read */
1179 : ub1 *piecep, /* which piece */
1180 : dvoid **indpp) /* indicator value */
1181 315 : {
1182 : php_oci_bind *phpbind;
1183 : zval *val;
1184 : TSRMLS_FETCH();
1185 :
1186 315 : if (!(phpbind=(php_oci_bind *)ictxp) || !(val = phpbind->zval)) {
1187 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
1188 0 : return OCI_ERROR;
1189 : }
1190 :
1191 315 : if (ZVAL_IS_NULL(val)) {
1192 : /* we're going to insert a NULL column */
1193 4 : phpbind->indicator = -1;
1194 4 : *bufpp = 0;
1195 4 : *alenp = -1;
1196 4 : *indpp = (dvoid *)&phpbind->indicator;
1197 440 : } else if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
1198 : /* "normal string bind */
1199 129 : convert_to_unicode(val);
1200 :
1201 129 : *bufpp = Z_UNIVAL_P(val).v;
1202 129 : *alenp = UBYTES(Z_UNILEN_P(val));
1203 129 : *indpp = (dvoid *)&phpbind->indicator;
1204 182 : } else if (phpbind->statement != 0) {
1205 : /* RSET */
1206 3 : *bufpp = phpbind->statement;
1207 3 : *alenp = -1; /* seems to be allright */
1208 3 : *indpp = (dvoid *)&phpbind->indicator;
1209 : } else {
1210 : /* descriptor bind */
1211 179 : *bufpp = phpbind->descriptor;
1212 179 : *alenp = -1; /* seems to be allright */
1213 179 : *indpp = (dvoid *)&phpbind->indicator;
1214 : }
1215 :
1216 315 : *piecep = OCI_ONE_PIECE; /* pass all data in one go */
1217 :
1218 315 : return OCI_CONTINUE;
1219 : }/* }}} */
1220 :
1221 : /* {{{ php_oci_bind_out_callback()
1222 : Callback used when binding LOBs and VARCHARs */
1223 : sb4 php_oci_bind_out_callback(
1224 : dvoid *octxp, /* context pointer */
1225 : OCIBind *bindp, /* bind handle */
1226 : ub4 iter, /* 0-based execute iteration value */
1227 : ub4 index, /* index of current array for PL/SQL or row index for SQL */
1228 : dvoid **bufpp, /* pointer to data */
1229 : ub4 **alenpp, /* size after value/piece has been read */
1230 : ub1 *piecep, /* which piece */
1231 : dvoid **indpp, /* indicator value */
1232 : ub2 **rcodepp) /* return code */
1233 85 : {
1234 : php_oci_bind *phpbind;
1235 : zval *val;
1236 85 : sb4 retval = OCI_ERROR;
1237 : TSRMLS_FETCH();
1238 :
1239 85 : if (!(phpbind=(php_oci_bind *)octxp) || !(val = phpbind->zval)) {
1240 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
1241 0 : return retval;
1242 : }
1243 :
1244 85 : phpbind->out = 1; /* mark as OUT bind */
1245 :
1246 85 : if (Z_TYPE_P(val) == IS_RESOURCE) {
1247 : /* Processing for ref-cursor out binds */
1248 5 : if (phpbind->statement != NULL) {
1249 5 : *bufpp = phpbind->statement;
1250 5 : *alenpp = &phpbind->dummy_len;
1251 5 : *piecep = OCI_ONE_PIECE;
1252 5 : *rcodepp = &phpbind->retcode;
1253 5 : *indpp = &phpbind->indicator;
1254 : }
1255 5 : retval = OCI_CONTINUE;
1256 80 : } else if (Z_TYPE_P(val) == IS_OBJECT) {
1257 : zval **tmp;
1258 : php_oci_descriptor *desc;
1259 :
1260 77 : if (!phpbind->descriptor) {
1261 0 : return OCI_ERROR;
1262 : }
1263 :
1264 : /* Do not use the cached lob size if the descriptor is an
1265 : * out-bind as the contents would have been changed for in/out
1266 : * binds (Bug #46994).
1267 : */
1268 77 : if (zend_hash_find(Z_OBJPROP_P(val), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
1269 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find object outbind descriptor property");
1270 0 : return OCI_ERROR;
1271 : }
1272 77 : PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, desc);
1273 77 : desc->lob_size = -1; /* force OCI8 to update cached size */
1274 :
1275 77 : *alenpp = &phpbind->dummy_len;
1276 77 : *bufpp = phpbind->descriptor;
1277 77 : *piecep = OCI_ONE_PIECE;
1278 77 : *rcodepp = &phpbind->retcode;
1279 77 : *indpp = &phpbind->indicator;
1280 77 : retval = OCI_CONTINUE;
1281 : } else {
1282 3 : convert_to_unicode(val);
1283 3 : zval_dtor(val);
1284 :
1285 3 : Z_UNILEN_P(val) = PHP_OCI_PIECE_SIZE; /* 64K-1 is max XXX */
1286 3 : Z_UNIVAL_P(val).v = ecalloc(1, UBYTES(Z_UNILEN_P(phpbind->zval) + 1));
1287 :
1288 3 : *alenpp = (ub4*) &Z_UNILEN_P(phpbind->zval);
1289 3 : *bufpp = Z_UNIVAL_P(phpbind->zval).v;
1290 3 : *piecep = OCI_ONE_PIECE;
1291 3 : *rcodepp = &phpbind->retcode;
1292 3 : *indpp = &phpbind->indicator;
1293 3 : retval = OCI_CONTINUE;
1294 : }
1295 85 : return retval;
1296 : }
1297 : /* }}} */
1298 :
1299 : /* {{{ php_oci_statement_get_column_helper()
1300 : Helper function to get column by name and index */
1301 : php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAMETERS, int need_data)
1302 329 : {
1303 : zval *z_statement, **column_index;
1304 : php_oci_statement *statement;
1305 : php_oci_out_column *column;
1306 :
1307 329 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &z_statement, &column_index) == FAILURE) {
1308 9 : return NULL;
1309 : }
1310 :
1311 320 : statement = (php_oci_statement *) zend_fetch_resource(&z_statement TSRMLS_CC, -1, "oci8 statement", NULL, 1, le_statement);
1312 :
1313 320 : if (!statement) {
1314 8 : return NULL;
1315 : }
1316 :
1317 312 : if (need_data && !statement->has_data) {
1318 1 : return NULL;
1319 : }
1320 :
1321 380 : if (Z_TYPE_PP(column_index) == IS_STRING || Z_TYPE_PP(column_index) == IS_UNICODE) {
1322 76 : column = php_oci_statement_get_column(statement, -1, Z_UNIVAL_PP(column_index), Z_UNILEN_PP(column_index) TSRMLS_CC);
1323 76 : if (!column) {
1324 7 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column name \"%v\"", Z_UNIVAL_PP(column_index));
1325 7 : return NULL;
1326 : }
1327 : } else {
1328 235 : convert_to_long_ex(column_index);
1329 235 : column = php_oci_statement_get_column(statement, Z_LVAL_PP(column_index), NULL_ZSTR, 0 TSRMLS_CC);
1330 235 : if (!column) {
1331 14 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column index \"%ld\"", Z_LVAL_PP(column_index));
1332 14 : return NULL;
1333 : }
1334 : }
1335 290 : return column;
1336 : } /* }}} */
1337 :
1338 : /* {{{ php_oci_statement_get_type()
1339 : Return type of the statement */
1340 : int php_oci_statement_get_type(php_oci_statement *statement, ub2 *type TSRMLS_DC)
1341 26 : {
1342 : ub2 statement_type;
1343 :
1344 26 : *type = 0;
1345 :
1346 26 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement_type, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
1347 :
1348 26 : if (statement->errcode != OCI_SUCCESS) {
1349 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
1350 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1351 0 : return 1;
1352 : }
1353 :
1354 26 : *type = statement_type;
1355 :
1356 26 : return 0;
1357 : } /* }}} */
1358 :
1359 : /* {{{ php_oci_statement_get_numrows()
1360 : Get the number of rows fetched to the clientside (NOT the number of rows in the result set) */
1361 : int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows TSRMLS_DC)
1362 25 : {
1363 : ub4 statement_numrows;
1364 :
1365 25 : *numrows = 0;
1366 :
1367 25 : PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub4 *)&statement_numrows, (ub4 *)0, OCI_ATTR_ROW_COUNT, statement->err));
1368 :
1369 25 : if (statement->errcode != OCI_SUCCESS) {
1370 0 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
1371 0 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1372 0 : return 1;
1373 : }
1374 :
1375 25 : *numrows = statement_numrows;
1376 :
1377 25 : return 0;
1378 : } /* }}} */
1379 :
1380 : /* {{{ php_oci_bind_array_by_name()
1381 : Bind arrays to PL/SQL types */
1382 : int php_oci_bind_array_by_name(php_oci_statement *statement, zstr name, int name_len, zval* var, long max_table_length, long maxlength, long type, zend_uchar uni_type TSRMLS_DC)
1383 24 : {
1384 : php_oci_bind *bind, *bindp;
1385 :
1386 24 : convert_to_array(var);
1387 :
1388 24 : if (maxlength < -1) {
1389 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid max length value (%ld)", maxlength);
1390 1 : return 1;
1391 : }
1392 :
1393 23 : switch(type) {
1394 : case SQLT_NUM:
1395 : case SQLT_INT:
1396 : case SQLT_LNG:
1397 3 : bind = php_oci_bind_array_helper_number(var, max_table_length TSRMLS_CC);
1398 3 : break;
1399 :
1400 : case SQLT_FLT:
1401 2 : bind = php_oci_bind_array_helper_double(var, max_table_length TSRMLS_CC);
1402 2 : break;
1403 :
1404 : case SQLT_AFC:
1405 : case SQLT_CHR:
1406 : case SQLT_VCS:
1407 : case SQLT_AVC:
1408 : case SQLT_STR:
1409 : case SQLT_LVC:
1410 12 : if (maxlength == -1 && zend_hash_num_elements(Z_ARRVAL_P(var)) == 0) {
1411 4 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must provide max length value for empty arrays");
1412 4 : return 1;
1413 : }
1414 8 : bind = php_oci_bind_array_helper_string(var, max_table_length, maxlength TSRMLS_CC);
1415 8 : break;
1416 : case SQLT_ODT:
1417 5 : bind = php_oci_bind_array_helper_date(var, max_table_length, statement->connection TSRMLS_CC);
1418 5 : break;
1419 : default:
1420 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %ld", type);
1421 1 : return 1;
1422 : break;
1423 : }
1424 :
1425 18 : if (bind == NULL) {
1426 : /* failed to generate bind struct */
1427 1 : return 1;
1428 : }
1429 :
1430 17 : if (!statement->binds) {
1431 17 : ALLOC_HASHTABLE(statement->binds);
1432 17 : zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
1433 : }
1434 :
1435 17 : zend_hash_update(statement->binds, name.s, USTR_BYTES(uni_type, name_len + 1), bind, sizeof(php_oci_bind), (void **)&bindp);
1436 :
1437 17 : bindp->descriptor = NULL;
1438 17 : bindp->statement = NULL;
1439 17 : bindp->parent_statement = statement;
1440 17 : bindp->bind = NULL;
1441 17 : bindp->zval = var;
1442 17 : bindp->array.type = type;
1443 17 : zval_add_ref(&var);
1444 :
1445 17 : PHP_OCI_CALL_RETURN(statement->errcode,
1446 : OCIBindByName,
1447 : (
1448 : statement->stmt,
1449 : (OCIBind **)&bindp->bind,
1450 : statement->err,
1451 : (text *)name.s,
1452 : USTR_BYTES(uni_type, name_len),
1453 : (dvoid *) bindp->array.elements,
1454 : (sb4) bind->array.max_length,
1455 : type,
1456 : (dvoid *)bindp->array.indicators,
1457 : (ub2 *)bind->array.element_lengths,
1458 : (ub2 *)0, /* bindp->array.retcodes, */
1459 : (ub4) max_table_length,
1460 : (ub4 *) &(bindp->array.current_length),
1461 : (ub4) OCI_DEFAULT
1462 : )
1463 : );
1464 :
1465 :
1466 17 : if (statement->errcode != OCI_SUCCESS) {
1467 1 : efree(bind);
1468 1 : statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
1469 1 : PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1470 1 : return 1;
1471 : }
1472 16 : efree(bind);
1473 16 : return 0;
1474 : } /* }}} */
1475 :
1476 : /* {{{ php_oci_bind_array_helper_string()
1477 : Bind arrays to PL/SQL types */
1478 : php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length, long maxlength TSRMLS_DC)
1479 8 : {
1480 : php_oci_bind *bind;
1481 : ub4 i;
1482 : HashTable *hash;
1483 : zval **entry;
1484 :
1485 8 : hash = HASH_OF(var);
1486 :
1487 8 : if (maxlength == -1) {
1488 1 : zend_hash_internal_pointer_reset(hash);
1489 7 : while (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
1490 5 : convert_to_unicode_ex(entry);
1491 5 : if (Z_UNILEN_PP(entry) > maxlength) {
1492 2 : maxlength = Z_UNILEN_PP(entry) + 1;
1493 : }
1494 5 : zend_hash_move_forward(hash);
1495 : }
1496 : }
1497 :
1498 8 : bind = emalloc(sizeof(php_oci_bind));
1499 8 : bind->array.elements = (UChar *)safe_emalloc(max_table_length * (maxlength + 1), sizeof(UChar), 0);
1500 8 : memset(bind->array.elements, 0, max_table_length * sizeof(UChar) * (maxlength + 1));
1501 :
1502 8 : bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
1503 8 : bind->array.old_length = bind->array.current_length;
1504 8 : bind->array.max_length = TEXT_BYTES(maxlength);
1505 8 : bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
1506 8 : memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1507 8 : bind->array.indicators = safe_emalloc(max_table_length, sizeof(sb2), 0);
1508 8 : memset(bind->array.indicators, 0, max_table_length*sizeof(sb2));
1509 :
1510 8 : zend_hash_internal_pointer_reset(hash);
1511 :
1512 43 : for (i = 0; i < bind->array.current_length; i++) {
1513 35 : if (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
1514 35 : convert_to_unicode_ex(entry);
1515 35 : bind->array.element_lengths[i] = TEXT_BYTES(Z_UNILEN_PP(entry));
1516 35 : if (Z_UNILEN_PP(entry) == 0) {
1517 5 : bind->array.indicators[i] = -1;
1518 : }
1519 35 : zend_hash_move_forward(hash);
1520 : } else {
1521 0 : break;
1522 : }
1523 : }
1524 :
1525 8 : zend_hash_internal_pointer_reset(hash);
1526 43 : for (i = 0; i < max_table_length; i++) {
1527 37 : if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1528 : int element_length;
1529 :
1530 35 : convert_to_unicode_ex(entry);
1531 35 : element_length = (maxlength > Z_UNILEN_PP(entry)) ? Z_UNILEN_PP(entry) : maxlength;
1532 :
1533 35 : memcpy((UChar *)bind->array.elements + i*maxlength, Z_UNIVAL_PP(entry).u, TEXT_BYTES(element_length));
1534 35 : ((UChar *)bind->array.elements)[i*maxlength + element_length] = '\0';
1535 :
1536 35 : zend_hash_move_forward(hash);
1537 : } else {
1538 : break;
1539 : }
1540 : }
1541 8 : zend_hash_internal_pointer_reset(hash);
1542 :
1543 8 : return bind;
1544 : } /* }}} */
1545 :
1546 : /* {{{ php_oci_bind_array_helper_number()
1547 : Bind arrays to PL/SQL types */
1548 : php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length TSRMLS_DC)
1549 3 : {
1550 : php_oci_bind *bind;
1551 : ub4 i;
1552 : HashTable *hash;
1553 : zval **entry;
1554 :
1555 3 : hash = HASH_OF(var);
1556 :
1557 3 : bind = emalloc(sizeof(php_oci_bind));
1558 3 : bind->array.elements = (ub4 *)safe_emalloc(max_table_length, sizeof(ub4), 0);
1559 3 : bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
1560 3 : bind->array.old_length = bind->array.current_length;
1561 3 : bind->array.max_length = sizeof(ub4);
1562 3 : bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
1563 3 : memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1564 3 : bind->array.indicators = NULL;
1565 :
1566 3 : zend_hash_internal_pointer_reset(hash);
1567 23 : for (i = 0; i < max_table_length; i++) {
1568 20 : if (i < bind->array.current_length) {
1569 10 : bind->array.element_lengths[i] = sizeof(ub4);
1570 : }
1571 30 : if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1572 10 : convert_to_long_ex(entry);
1573 10 : ((ub4 *)bind->array.elements)[i] = (ub4) Z_LVAL_PP(entry);
1574 10 : zend_hash_move_forward(hash);
1575 : } else {
1576 10 : ((ub4 *)bind->array.elements)[i] = 0;
1577 : }
1578 : }
1579 3 : zend_hash_internal_pointer_reset(hash);
1580 :
1581 3 : return bind;
1582 : } /* }}} */
1583 :
1584 : /* {{{ php_oci_bind_array_helper_double()
1585 : Bind arrays to PL/SQL types */
1586 : php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length TSRMLS_DC)
1587 2 : {
1588 : php_oci_bind *bind;
1589 : ub4 i;
1590 : HashTable *hash;
1591 : zval **entry;
1592 :
1593 2 : hash = HASH_OF(var);
1594 :
1595 2 : bind = emalloc(sizeof(php_oci_bind));
1596 2 : bind->array.elements = (double *)safe_emalloc(max_table_length, sizeof(double), 0);
1597 2 : bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
1598 2 : bind->array.old_length = bind->array.current_length;
1599 2 : bind->array.max_length = sizeof(double);
1600 2 : bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
1601 2 : memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1602 2 : bind->array.indicators = NULL;
1603 :
1604 2 : zend_hash_internal_pointer_reset(hash);
1605 17 : for (i = 0; i < max_table_length; i++) {
1606 15 : if (i < bind->array.current_length) {
1607 10 : bind->array.element_lengths[i] = sizeof(double);
1608 : }
1609 25 : if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1610 10 : convert_to_double_ex(entry);
1611 10 : ((double *)bind->array.elements)[i] = (double) Z_DVAL_PP(entry);
1612 10 : zend_hash_move_forward(hash);
1613 : } else {
1614 5 : ((double *)bind->array.elements)[i] = 0;
1615 : }
1616 : }
1617 2 : zend_hash_internal_pointer_reset(hash);
1618 :
1619 2 : return bind;
1620 : } /* }}} */
1621 :
1622 : /* {{{ php_oci_bind_array_helper_date()
1623 : Bind arrays to PL/SQL types */
1624 : php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, php_oci_connection *connection TSRMLS_DC)
1625 5 : {
1626 : php_oci_bind *bind;
1627 : ub4 i;
1628 : HashTable *hash;
1629 : zval **entry;
1630 :
1631 5 : hash = HASH_OF(var);
1632 :
1633 5 : bind = emalloc(sizeof(php_oci_bind));
1634 5 : bind->array.elements = (OCIDate *)safe_emalloc(max_table_length, sizeof(OCIDate), 0);
1635 5 : bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
1636 5 : bind->array.old_length = bind->array.current_length;
1637 5 : bind->array.max_length = sizeof(OCIDate);
1638 5 : bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
1639 5 : memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
1640 5 : bind->array.indicators = NULL;
1641 :
1642 5 : zend_hash_internal_pointer_reset(hash);
1643 30 : for (i = 0; i < max_table_length; i++) {
1644 : OCIDate oci_date;
1645 26 : if (i < bind->array.current_length) {
1646 15 : bind->array.element_lengths[i] = sizeof(OCIDate);
1647 : }
1648 40 : if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
1649 :
1650 15 : convert_to_unicode_ex(entry);
1651 15 : PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)Z_UNIVAL_PP(entry).s, UBYTES(Z_UNILEN_PP(entry)), NULL, 0, NULL, 0, &oci_date));
1652 :
1653 15 : if (connection->errcode != OCI_SUCCESS) {
1654 : /* failed to convert string to date */
1655 1 : efree(bind->array.element_lengths);
1656 1 : efree(bind->array.elements);
1657 1 : efree(bind);
1658 1 : connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
1659 1 : PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
1660 1 : return NULL;
1661 : }
1662 :
1663 14 : ((OCIDate *)bind->array.elements)[i] = oci_date;
1664 14 : zend_hash_move_forward(hash);
1665 : } else {
1666 :
1667 11 : UChar *tmp = USTR_MAKE("01-JAN-00");
1668 11 : PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)tmp, UBYTES(sizeof("01-JAN-00")-1), NULL, 0, NULL, 0, &oci_date));
1669 11 : efree(tmp);
1670 :
1671 11 : if (connection->errcode != OCI_SUCCESS) {
1672 : /* failed to convert string to date */
1673 0 : efree(bind->array.element_lengths);
1674 0 : efree(bind->array.elements);
1675 0 : efree(bind);
1676 0 : connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
1677 0 : PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
1678 0 : return NULL;
1679 : }
1680 :
1681 11 : ((OCIDate *)bind->array.elements)[i] = oci_date;
1682 : }
1683 : }
1684 4 : zend_hash_internal_pointer_reset(hash);
1685 :
1686 4 : return bind;
1687 : } /* }}} */
1688 :
1689 : #endif /* HAVE_OCI8 */
1690 :
1691 : /*
1692 : * Local variables:
1693 : * tab-width: 4
1694 : * c-basic-offset: 4
1695 : * End:
1696 : * vim600: noet sw=4 ts=4 fdm=marker
1697 : * vim<600: noet sw=4 ts=4
1698 : */
|