xref: /PHP-5.6/ext/oci8/oci8_collection.c (revision 49493a2d)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2016 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Stig S�ther Bakken <ssb@php.net>                            |
16    |          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$ */
29 
30 
31 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include "php.h"
37 #include "ext/standard/info.h"
38 #include "php_ini.h"
39 
40 #if HAVE_OCI8
41 
42 #include "php_oci8.h"
43 #include "php_oci8_int.h"
44 
45 /* {{{ php_oci_collection_create()
46  Create and return connection handle */
php_oci_collection_create(php_oci_connection * connection,char * tdo,int tdo_len,char * schema,int schema_len TSRMLS_DC)47 php_oci_collection *php_oci_collection_create(php_oci_connection *connection, char *tdo, int tdo_len, char *schema, int schema_len TSRMLS_DC)
48 {
49 	dvoid *dschp1 = NULL;
50 	dvoid *parmp1;
51 	dvoid *parmp2;
52 	php_oci_collection *collection;
53 	sword errstatus;
54 
55 	collection = emalloc(sizeof(php_oci_collection));
56 
57 	collection->connection = connection;
58 	collection->collection = NULL;
59 	zend_list_addref(collection->connection->id);
60 
61 	/* get type handle by name */
62 	PHP_OCI_CALL_RETURN(errstatus, OCITypeByName,
63 			(
64 			 connection->env,
65 			 connection->err,
66 			 connection->svc,
67 			 (text *) schema,
68 			 (ub4) schema_len,
69 			 (text *) tdo,
70 			 (ub4) tdo_len,
71 			 (CONST text *) 0,
72 			 (ub4) 0,
73 			 OCI_DURATION_SESSION,
74 			 OCI_TYPEGET_ALL,
75 			 &(collection->tdo)
76 			)
77 	);
78 
79 	if (errstatus != OCI_SUCCESS) {
80 		goto CLEANUP;
81 	}
82 
83 	/* allocate describe handle */
84 	PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (connection->env, (dvoid **) &dschp1, (ub4) OCI_HTYPE_DESCRIBE, (size_t) 0, (dvoid **) 0));
85 
86 	if (errstatus != OCI_SUCCESS) {
87 		goto CLEANUP;
88 	}
89 
90 	/* describe TDO */
91 	PHP_OCI_CALL_RETURN(errstatus, OCIDescribeAny,
92 			(
93 			 connection->svc,
94 			 connection->err,
95 			 (dvoid *) collection->tdo,
96 			 (ub4) 0,
97 			 OCI_OTYPE_PTR,
98 			 (ub1) OCI_DEFAULT,
99 			 (ub1) OCI_PTYPE_TYPE,
100 			 dschp1
101 			)
102 	);
103 
104 	if (errstatus != OCI_SUCCESS) {
105 		goto CLEANUP;
106 	}
107 
108 	/* get first parameter handle */
109 	PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *) dschp1, (ub4) OCI_HTYPE_DESCRIBE, (dvoid *)&parmp1, (ub4 *)0, (ub4)OCI_ATTR_PARAM, connection->err));
110 
111 	if (errstatus != OCI_SUCCESS) {
112 		goto CLEANUP;
113 	}
114 
115 	/* get the collection type code of the attribute */
116 	PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet,
117 			(
118 			 (dvoid*) parmp1,
119 			 (ub4) OCI_DTYPE_PARAM,
120 			 (dvoid*) &(collection->coll_typecode),
121 			 (ub4 *) 0,
122 			 (ub4) OCI_ATTR_COLLECTION_TYPECODE,
123 			 connection->err
124 			)
125 	);
126 
127 	if (errstatus != OCI_SUCCESS) {
128 		goto CLEANUP;
129 	}
130 
131 	switch(collection->coll_typecode) {
132 		case OCI_TYPECODE_TABLE:
133 		case OCI_TYPECODE_VARRAY:
134 			/* get collection element handle */
135 			PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet,
136 					(
137 					 (dvoid*) parmp1,
138 					 (ub4) OCI_DTYPE_PARAM,
139 					 (dvoid*) &parmp2,
140 					 (ub4 *) 0,
141 					 (ub4) OCI_ATTR_COLLECTION_ELEMENT,
142 					 connection->err
143 					)
144 			);
145 
146 			if (errstatus != OCI_SUCCESS) {
147 				goto CLEANUP;
148 			}
149 
150 			/* get REF of the TDO for the type */
151 			PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet,
152 					(
153 					 (dvoid*) parmp2,
154 					 (ub4) OCI_DTYPE_PARAM,
155 					 (dvoid*) &(collection->elem_ref),
156 					 (ub4 *) 0,
157 					 (ub4) OCI_ATTR_REF_TDO,
158 					 connection->err
159 					)
160 			);
161 
162 			if (errstatus != OCI_SUCCESS) {
163 				goto CLEANUP;
164 			}
165 
166 			/* get the TDO (only header) */
167 			PHP_OCI_CALL_RETURN(errstatus, OCITypeByRef,
168 					(
169 					 connection->env,
170 					 connection->err,
171 					 collection->elem_ref,
172 					 OCI_DURATION_SESSION,
173 					 OCI_TYPEGET_HEADER,
174 					 &(collection->element_type)
175 					)
176 			);
177 
178 			if (errstatus != OCI_SUCCESS) {
179 				goto CLEANUP;
180 			}
181 
182 			/* get typecode */
183 			PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet,
184 					(
185 					 (dvoid*) parmp2,
186 					 (ub4) OCI_DTYPE_PARAM,
187 					 (dvoid*) &(collection->element_typecode),
188 					 (ub4 *) 0,
189 					 (ub4) OCI_ATTR_TYPECODE,
190 					 connection->err
191 					)
192 			);
193 
194 			if (errstatus != OCI_SUCCESS) {
195 				goto CLEANUP;
196 			}
197 			break;
198 			/* we only support VARRAYs and TABLEs */
199 		default:
200 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown collection type %d", collection->coll_typecode);
201 			break;
202 	}
203 
204 	/* Create object to hold return table */
205 	PHP_OCI_CALL_RETURN(errstatus, OCIObjectNew,
206 		(
207 			connection->env,
208 			connection->err,
209 			connection->svc,
210 			OCI_TYPECODE_TABLE,
211 			collection->tdo,
212 			(dvoid *)0,
213 			OCI_DURATION_DEFAULT,
214 			TRUE,
215 			(dvoid **) &(collection->collection)
216 		)
217 	);
218 
219 	if (errstatus != OCI_SUCCESS) {
220 		goto CLEANUP;
221 	}
222 
223 	/* free the describe handle (Bug #44113) */
224 	PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE));
225 	PHP_OCI_REGISTER_RESOURCE(collection, le_collection);
226 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
227 	return collection;
228 
229 CLEANUP:
230 
231 	if (dschp1) {
232 		/* free the describe handle (Bug #44113) */
233 		PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE));
234 	}
235 	connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
236 	PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
237 	php_oci_collection_close(collection TSRMLS_CC);
238 	return NULL;
239 }
240 /* }}} */
241 
242 /* {{{ php_oci_collection_size()
243  Return size of the collection */
php_oci_collection_size(php_oci_collection * collection,sb4 * size TSRMLS_DC)244 int php_oci_collection_size(php_oci_collection *collection, sb4 *size TSRMLS_DC)
245 {
246 	php_oci_connection *connection = collection->connection;
247 	sword errstatus;
248 
249 	PHP_OCI_CALL_RETURN(errstatus, OCICollSize, (connection->env, connection->err, collection->collection, (sb4 *)size));
250 
251 	if (errstatus != OCI_SUCCESS) {
252 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
253 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
254 		return 1;
255 	}
256 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
257 	return 0;
258 }
259 /* }}} */
260 
261 /* {{{ php_oci_collection_max()
262  Return max number of elements in the collection */
php_oci_collection_max(php_oci_collection * collection,long * max TSRMLS_DC)263 int php_oci_collection_max(php_oci_collection *collection, long *max TSRMLS_DC)
264 {
265 	php_oci_connection *connection = collection->connection;
266 
267 	PHP_OCI_CALL_RETURN(*max, OCICollMax, (connection->env, collection->collection));
268 
269 	/* error handling is not necessary here? */
270 	return 0;
271 }
272 /* }}} */
273 
274 /* {{{ php_oci_collection_trim()
275  Trim collection to the given number of elements */
php_oci_collection_trim(php_oci_collection * collection,long trim_size TSRMLS_DC)276 int php_oci_collection_trim(php_oci_collection *collection, long trim_size TSRMLS_DC)
277 {
278 	php_oci_connection *connection = collection->connection;
279 	sword errstatus;
280 
281 	PHP_OCI_CALL_RETURN(errstatus, OCICollTrim, (connection->env, connection->err, trim_size, collection->collection));
282 
283 	if (errstatus != OCI_SUCCESS) {
284 		errstatus = php_oci_error(connection->err, errstatus TSRMLS_CC);
285 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
286 		return 1;
287 	}
288 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
289 	return 0;
290 }
291 /* }}} */
292 
293 /* {{{ php_oci_collection_append_null()
294  Append NULL element to the end of the collection */
php_oci_collection_append_null(php_oci_collection * collection TSRMLS_DC)295 int php_oci_collection_append_null(php_oci_collection *collection TSRMLS_DC)
296 {
297 	OCIInd null_index = OCI_IND_NULL;
298 	php_oci_connection *connection = collection->connection;
299 	sword errstatus;
300 
301 	/* append NULL element */
302 	PHP_OCI_CALL_RETURN(errstatus, OCICollAppend, (connection->env, connection->err, (dvoid *)0, &null_index, collection->collection));
303 
304 	if (errstatus != OCI_SUCCESS) {
305 		errstatus = php_oci_error(connection->err, errstatus TSRMLS_CC);
306 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
307 		return 1;
308 	}
309 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
310 	return 0;
311 }
312 /* }}} */
313 
314 /* {{{ php_oci_collection_append_date()
315  Append DATE element to the end of the collection (use "DD-MON-YY" format) */
php_oci_collection_append_date(php_oci_collection * collection,char * date,int date_len TSRMLS_DC)316 int php_oci_collection_append_date(php_oci_collection *collection, char *date, int date_len TSRMLS_DC)
317 {
318 	OCIInd new_index = OCI_IND_NOTNULL;
319 	OCIDate oci_date;
320 	php_oci_connection *connection = collection->connection;
321 	sword errstatus;
322 
323 	/* format and language are NULLs, so format is "DD-MON-YY" and language is the default language of the session */
324 	PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date));
325 
326 	if (errstatus != OCI_SUCCESS) {
327 		/* failed to convert string to date */
328 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
329 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
330 		return 1;
331 	}
332 
333 	PHP_OCI_CALL_RETURN(errstatus, OCICollAppend,
334 			(
335 			 connection->env,
336 			 connection->err,
337 			 (dvoid *) &oci_date,
338 			 (dvoid *) &new_index,
339 			 (OCIColl *) collection->collection
340 			)
341 	);
342 
343 	if (errstatus != OCI_SUCCESS) {
344 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
345 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
346 		return 1;
347 	}
348 
349 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
350 	return 0;
351 }
352 /* }}} */
353 
354 /* {{{ php_oci_collection_append_number()
355  Append NUMBER to the end of the collection */
php_oci_collection_append_number(php_oci_collection * collection,char * number,int number_len TSRMLS_DC)356 int php_oci_collection_append_number(php_oci_collection *collection, char *number, int number_len TSRMLS_DC)
357 {
358 	OCIInd new_index = OCI_IND_NOTNULL;
359 	double element_double;
360 	OCINumber oci_number;
361 	php_oci_connection *connection = collection->connection;
362 	sword errstatus;
363 
364 	element_double = zend_strtod(number, NULL);
365 
366 	PHP_OCI_CALL_RETURN(errstatus, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number));
367 
368 	if (errstatus != OCI_SUCCESS) {
369 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
370 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
371 		return 1;
372 	}
373 
374 	PHP_OCI_CALL_RETURN(errstatus, OCICollAppend,
375 			(
376 			 connection->env,
377 			 connection->err,
378 			 (dvoid *) &oci_number,
379 			 (dvoid *) &new_index,
380 			 (OCIColl *) collection->collection
381 			)
382 	);
383 
384 	if (errstatus != OCI_SUCCESS) {
385 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
386 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
387 		return 1;
388 	}
389 
390 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
391 	return 0;
392 }
393 /* }}} */
394 
395 /* {{{ php_oci_collection_append_string()
396  Append STRING to the end of the collection */
php_oci_collection_append_string(php_oci_collection * collection,char * element,int element_len TSRMLS_DC)397 int php_oci_collection_append_string(php_oci_collection *collection, char *element, int element_len TSRMLS_DC)
398 {
399 	OCIInd new_index = OCI_IND_NOTNULL;
400 	OCIString *ocistr = (OCIString *)0;
401 	php_oci_connection *connection = collection->connection;
402 	sword errstatus;
403 
404 	PHP_OCI_CALL_RETURN(errstatus, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr));
405 
406 	if (errstatus != OCI_SUCCESS) {
407 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
408 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
409 		return 1;
410 	}
411 
412 	PHP_OCI_CALL_RETURN(errstatus, OCICollAppend,
413 			(
414 			 connection->env,
415 			 connection->err,
416 			 (dvoid *) ocistr,
417 			 (dvoid *) &new_index,
418 			 (OCIColl *) collection->collection
419 			)
420 	);
421 
422 	if (errstatus != OCI_SUCCESS) {
423 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
424 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
425 		return 1;
426 	}
427 
428 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
429 	return 0;
430 }
431 /* }}} */
432 
433 /* {{{ php_oci_collection_append()
434  Append wrapper. Appends any supported element to the end of the collection */
php_oci_collection_append(php_oci_collection * collection,char * element,int element_len TSRMLS_DC)435 int php_oci_collection_append(php_oci_collection *collection, char *element, int element_len TSRMLS_DC)
436 {
437 	if (element_len == 0) {
438 		return php_oci_collection_append_null(collection TSRMLS_CC);
439 	}
440 
441 	switch(collection->element_typecode) {
442 		case OCI_TYPECODE_DATE:
443 			return php_oci_collection_append_date(collection, element, element_len TSRMLS_CC);
444 			break;
445 
446 		case OCI_TYPECODE_VARCHAR2 :
447 			return php_oci_collection_append_string(collection, element, element_len TSRMLS_CC);
448 			break;
449 
450 		case OCI_TYPECODE_UNSIGNED16 :						 /* UNSIGNED SHORT	*/
451 		case OCI_TYPECODE_UNSIGNED32 :						  /* UNSIGNED LONG	*/
452 		case OCI_TYPECODE_REAL :									 /* REAL	*/
453 		case OCI_TYPECODE_DOUBLE :									 /* DOUBLE	*/
454 		case OCI_TYPECODE_INTEGER :										/* INT	*/
455 		case OCI_TYPECODE_SIGNED16 :								  /* SHORT	*/
456 		case OCI_TYPECODE_SIGNED32 :								   /* LONG	*/
457 		case OCI_TYPECODE_DECIMAL :									/* DECIMAL	*/
458 		case OCI_TYPECODE_FLOAT :									/* FLOAT	*/
459 		case OCI_TYPECODE_NUMBER :									/* NUMBER	*/
460 		case OCI_TYPECODE_SMALLINT :								/* SMALLINT */
461 			return php_oci_collection_append_number(collection, element, element_len TSRMLS_CC);
462 			break;
463 
464 		default:
465 			php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
466 			return 1;
467 			break;
468 	}
469 	/* never reached */
470 	return 1;
471 }
472 /* }}} */
473 
474 /* {{{ php_oci_collection_element_get()
475  Get the element with the given index */
php_oci_collection_element_get(php_oci_collection * collection,long index,zval ** result_element TSRMLS_DC)476 int php_oci_collection_element_get(php_oci_collection *collection, long index, zval **result_element TSRMLS_DC)
477 {
478 	php_oci_connection *connection = collection->connection;
479 	dvoid *element;
480 	OCIInd *element_index;
481 	boolean exists;
482 	oratext buff[1024];
483 	ub4 buff_len = 1024;
484 	sword errstatus;
485 
486 	MAKE_STD_ZVAL(*result_element);
487 	ZVAL_NULL(*result_element);
488 
489 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
490 
491 	PHP_OCI_CALL_RETURN(errstatus, OCICollGetElem,
492 			(
493 			 connection->env,
494 			 connection->err,
495 			 collection->collection,
496 			 (ub4)index,
497 			 &exists,
498 			 &element,
499 			 (dvoid **)&element_index
500 			)
501 	);
502 
503 	if (errstatus != OCI_SUCCESS) {
504 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
505 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
506 		FREE_ZVAL(*result_element);
507 		return 1;
508 	}
509 
510 	if (exists == 0) {
511 		/* element doesn't exist */
512 		FREE_ZVAL(*result_element);
513 		return 1;
514 	}
515 
516 	if (*element_index == OCI_IND_NULL) {
517 		/* this is not an error, we're returning NULL here */
518 		return 0;
519 	}
520 
521 	switch (collection->element_typecode) {
522 		case OCI_TYPECODE_DATE:
523 			PHP_OCI_CALL_RETURN(errstatus, OCIDateToText, (connection->err, element, 0, 0, 0, 0, &buff_len, buff));
524 
525 			if (errstatus != OCI_SUCCESS) {
526 				connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
527 				PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
528 				FREE_ZVAL(*result_element);
529 				return 1;
530 			}
531 
532 			ZVAL_STRINGL(*result_element, (char *)buff, buff_len, 1);
533 			Z_STRVAL_P(*result_element)[buff_len] = '\0';
534 
535 			return 0;
536 			break;
537 
538 		case OCI_TYPECODE_VARCHAR2:
539 		{
540 			OCIString *oci_string = *(OCIString **)element;
541 			text *str;
542 
543 			PHP_OCI_CALL_RETURN(str, OCIStringPtr, (connection->env, oci_string));
544 
545 			if (str) {
546 				ZVAL_STRING(*result_element, (char *)str, 1);
547 			}
548 			return 0;
549 		}
550 			break;
551 
552 		case OCI_TYPECODE_UNSIGNED16:						/* UNSIGNED SHORT  */
553 		case OCI_TYPECODE_UNSIGNED32:						/* UNSIGNED LONG  */
554 		case OCI_TYPECODE_REAL:								/* REAL	   */
555 		case OCI_TYPECODE_DOUBLE:							/* DOUBLE  */
556 		case OCI_TYPECODE_INTEGER:							/* INT	*/
557 		case OCI_TYPECODE_SIGNED16:							/* SHORT  */
558 		case OCI_TYPECODE_SIGNED32:							/* LONG	 */
559 		case OCI_TYPECODE_DECIMAL:							/* DECIMAL	*/
560 		case OCI_TYPECODE_FLOAT:							/* FLOAT	*/
561 		case OCI_TYPECODE_NUMBER:							/* NUMBER	*/
562 		case OCI_TYPECODE_SMALLINT:							/* SMALLINT */
563 		{
564 			double double_number;
565 
566 			PHP_OCI_CALL_RETURN(errstatus, OCINumberToReal, (connection->err, (CONST OCINumber *) element, (uword) sizeof(double), (dvoid *) &double_number));
567 
568 			if (errstatus != OCI_SUCCESS) {
569 				connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
570 				PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
571 				FREE_ZVAL(*result_element);
572 				return 1;
573 			}
574 
575 			ZVAL_DOUBLE(*result_element, double_number);
576 
577 			return 0;
578 		}
579 			break;
580 		default:
581 			php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
582 			FREE_ZVAL(*result_element);
583 			return 1;
584 			break;
585 	}
586 	/* never reached */
587 	return 1;
588 }
589 /* }}} */
590 
591 /* {{{ php_oci_collection_element_set_null()
592  Set the element with the given index to NULL */
php_oci_collection_element_set_null(php_oci_collection * collection,long index TSRMLS_DC)593 int php_oci_collection_element_set_null(php_oci_collection *collection, long index TSRMLS_DC)
594 {
595 	OCIInd null_index = OCI_IND_NULL;
596 	php_oci_connection *connection = collection->connection;
597 	sword errstatus;
598 
599 	/* set NULL element */
600 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem, (connection->env, connection->err, (ub4) index, (dvoid *)"", &null_index, collection->collection));
601 
602 	if (errstatus != OCI_SUCCESS) {
603 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
604 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
605 		return 1;
606 	}
607 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
608 	return 0;
609 }
610 /* }}} */
611 
612 /* {{{ php_oci_collection_element_set_date()
613  Change element's value to the given DATE */
php_oci_collection_element_set_date(php_oci_collection * collection,long index,char * date,int date_len TSRMLS_DC)614 int php_oci_collection_element_set_date(php_oci_collection *collection, long index, char *date, int date_len TSRMLS_DC)
615 {
616 	OCIInd new_index = OCI_IND_NOTNULL;
617 	OCIDate oci_date;
618 	php_oci_connection *connection = collection->connection;
619 	sword errstatus;
620 
621 	/* format and language are NULLs, so format is "DD-MON-YY" and language is the default language of the session */
622 	PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date));
623 
624 	if (errstatus != OCI_SUCCESS) {
625 		/* failed to convert string to date */
626 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
627 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
628 		return 1;
629 	}
630 
631 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem,
632 			(
633 			 connection->env,
634 			 connection->err,
635 			 (ub4)index,
636 			 (dvoid *) &oci_date,
637 			 (dvoid *) &new_index,
638 			 (OCIColl *) collection->collection
639 			 )
640 	);
641 
642 	if (errstatus != OCI_SUCCESS) {
643 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
644 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
645 		return 1;
646 	}
647 
648 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
649 	return 0;
650 }
651 /* }}} */
652 
653 /* {{{ php_oci_collection_element_set_number()
654  Change element's value to the given NUMBER */
php_oci_collection_element_set_number(php_oci_collection * collection,long index,char * number,int number_len TSRMLS_DC)655 int php_oci_collection_element_set_number(php_oci_collection *collection, long index, char *number, int number_len TSRMLS_DC)
656 {
657 	OCIInd new_index = OCI_IND_NOTNULL;
658 	double element_double;
659 	OCINumber oci_number;
660 	php_oci_connection *connection = collection->connection;
661 	sword errstatus;
662 
663 	element_double = zend_strtod(number, NULL);
664 
665 	PHP_OCI_CALL_RETURN(errstatus, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number));
666 
667 	if (errstatus != OCI_SUCCESS) {
668 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
669 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
670 		return 1;
671 	}
672 
673 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem,
674 			(
675 			 connection->env,
676 			 connection->err,
677 			 (ub4) index,
678 			 (dvoid *) &oci_number,
679 			 (dvoid *) &new_index,
680 			 (OCIColl *) collection->collection
681 			 )
682 	);
683 
684 	if (errstatus != OCI_SUCCESS) {
685 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
686 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
687 		return 1;
688 	}
689 
690 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
691 	return 0;
692 }
693 /* }}} */
694 
695 /* {{{ php_oci_collection_element_set_string()
696  Change element's value to the given string */
php_oci_collection_element_set_string(php_oci_collection * collection,long index,char * element,int element_len TSRMLS_DC)697 int php_oci_collection_element_set_string(php_oci_collection *collection, long index, char *element, int element_len TSRMLS_DC)
698 {
699 	OCIInd new_index = OCI_IND_NOTNULL;
700 	OCIString *ocistr = (OCIString *)0;
701 	php_oci_connection *connection = collection->connection;
702 	sword errstatus;
703 
704 	PHP_OCI_CALL_RETURN(errstatus, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr));
705 
706 	if (errstatus != OCI_SUCCESS) {
707 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
708 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
709 		return 1;
710 	}
711 
712 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem,
713 			(
714 			 connection->env,
715 			 connection->err,
716 			 (ub4)index,
717 			 (dvoid *) ocistr,
718 			 (dvoid *) &new_index,
719 			 (OCIColl *) collection->collection
720 			 )
721 	);
722 
723 	if (errstatus != OCI_SUCCESS) {
724 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
725 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
726 		return 1;
727 	}
728 
729 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
730 	return 0;
731 }
732 /* }}} */
733 
734 /* {{{ php_oci_collection_element_set()
735  Collection element setter */
php_oci_collection_element_set(php_oci_collection * collection,long index,char * value,int value_len TSRMLS_DC)736 int php_oci_collection_element_set(php_oci_collection *collection, long index, char *value, int value_len TSRMLS_DC)
737 {
738 	if (value_len == 0) {
739 		return php_oci_collection_element_set_null(collection, index TSRMLS_CC);
740 	}
741 
742 	switch(collection->element_typecode) {
743 		case OCI_TYPECODE_DATE:
744 			return php_oci_collection_element_set_date(collection, index, value, value_len TSRMLS_CC);
745 			break;
746 
747 		case OCI_TYPECODE_VARCHAR2 :
748 			return php_oci_collection_element_set_string(collection, index, value, value_len TSRMLS_CC);
749 			break;
750 
751 		case OCI_TYPECODE_UNSIGNED16 :						 /* UNSIGNED SHORT	*/
752 		case OCI_TYPECODE_UNSIGNED32 :						  /* UNSIGNED LONG	*/
753 		case OCI_TYPECODE_REAL :									 /* REAL	*/
754 		case OCI_TYPECODE_DOUBLE :									 /* DOUBLE	*/
755 		case OCI_TYPECODE_INTEGER :										/* INT	*/
756 		case OCI_TYPECODE_SIGNED16 :								  /* SHORT	*/
757 		case OCI_TYPECODE_SIGNED32 :								   /* LONG	*/
758 		case OCI_TYPECODE_DECIMAL :									/* DECIMAL	*/
759 		case OCI_TYPECODE_FLOAT :									/* FLOAT	*/
760 		case OCI_TYPECODE_NUMBER :									/* NUMBER	*/
761 		case OCI_TYPECODE_SMALLINT :								/* SMALLINT */
762 			return php_oci_collection_element_set_number(collection, index, value, value_len TSRMLS_CC);
763 			break;
764 
765 		default:
766 			php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
767 			return 1;
768 			break;
769 	}
770 	/* never reached */
771 	return 1;
772 }
773 /* }}} */
774 
775 /* {{{ php_oci_collection_assign()
776  Assigns a value to the collection from another collection */
php_oci_collection_assign(php_oci_collection * collection_dest,php_oci_collection * collection_from TSRMLS_DC)777 int php_oci_collection_assign(php_oci_collection *collection_dest, php_oci_collection *collection_from TSRMLS_DC)
778 {
779 	php_oci_connection *connection = collection_dest->connection;
780 	sword errstatus;
781 
782 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssign, (connection->env, connection->err, collection_from->collection, collection_dest->collection));
783 
784 	if (errstatus != OCI_SUCCESS) {
785 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
786 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
787 		return 1;
788 	}
789 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
790 	return 0;
791 }
792 /* }}} */
793 
794 /* {{{ php_oci_collection_close()
795  Destroy collection and all associated resources */
php_oci_collection_close(php_oci_collection * collection TSRMLS_DC)796 void php_oci_collection_close(php_oci_collection *collection TSRMLS_DC)
797 {
798 	php_oci_connection *connection = collection->connection;
799 	sword errstatus;
800 
801 	if (collection->collection) {
802 		PHP_OCI_CALL_RETURN(errstatus, OCIObjectFree, (connection->env, connection->err, (dvoid *)collection->collection, (ub2)OCI_OBJECTFREE_FORCE));
803 
804 		if (errstatus != OCI_SUCCESS) {
805 			connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
806 			PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
807 		} else {
808 			connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
809 		}
810 	}
811 
812 	zend_list_delete(collection->connection->id);
813 	efree(collection);
814 	return;
815 }
816 /* }}} */
817 
818 #endif /* HAVE_OCI8 */
819 
820 /*
821  * Local variables:
822  * tab-width: 4
823  * c-basic-offset: 4
824  * End:
825  * vim600: noet sw=4 ts=4 fdm=marker
826  * vim<600: noet sw=4 ts=4
827  */
828