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