xref: /PHP-7.4/ext/oci8/oci8_collection.c (revision 92ac598a)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 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@php.net>                           |
24    |                Wez Furlong <wez@omniti.com>                          |
25    +----------------------------------------------------------------------+
26 */
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include "php.h"
33 #include "ext/standard/info.h"
34 #include "php_ini.h"
35 
36 #if HAVE_OCI8
37 
38 #include "php_oci8.h"
39 #include "php_oci8_int.h"
40 
41 /* {{{ php_oci_collection_create()
42  Create and return connection handle */
php_oci_collection_create(php_oci_connection * connection,char * tdo,int tdo_len,char * schema,int schema_len)43 php_oci_collection *php_oci_collection_create(php_oci_connection *connection, char *tdo, int tdo_len, char *schema, int schema_len)
44 {
45 	dvoid *dschp1 = NULL;
46 	dvoid *parmp1;
47 	dvoid *parmp2;
48 	php_oci_collection *collection;
49 	sword errstatus;
50 
51 	collection = emalloc(sizeof(php_oci_collection));
52 
53 	collection->connection = connection;
54 	collection->collection = NULL;
55 #if PHP_VERSION_ID < 70300
56 	++GC_REFCOUNT(collection->connection->id);
57 #else
58 	GC_ADDREF(collection->connection->id);
59 #endif
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, 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);
236 	PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
237 	php_oci_collection_close(collection);
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)244 int php_oci_collection_size(php_oci_collection *collection, sb4 *size)
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);
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,zend_long * max)263 int php_oci_collection_max(php_oci_collection *collection, zend_long *max)
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,zend_long trim_size)276 int php_oci_collection_trim(php_oci_collection *collection, zend_long trim_size)
277 {
278 	php_oci_connection *connection = collection->connection;
279 	sword errstatus;
280 
281 	PHP_OCI_CALL_RETURN(errstatus, OCICollTrim, (connection->env, connection->err, (sb4) trim_size, collection->collection));
282 
283 	if (errstatus != OCI_SUCCESS) {
284 		errstatus = php_oci_error(connection->err, errstatus);
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)295 int php_oci_collection_append_null(php_oci_collection *collection)
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);
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)316 int php_oci_collection_append_date(php_oci_collection *collection, char *date, int date_len)
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);
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);
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)356 int php_oci_collection_append_number(php_oci_collection *collection, char *number, int number_len)
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);
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);
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)397 int php_oci_collection_append_string(php_oci_collection *collection, char *element, int element_len)
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);
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);
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)435 int php_oci_collection_append(php_oci_collection *collection, char *element, int element_len)
436 {
437 	if (element_len == 0) {
438 		return php_oci_collection_append_null(collection);
439 	}
440 
441 	switch(collection->element_typecode) {
442 		case OCI_TYPECODE_DATE:
443 			return php_oci_collection_append_date(collection, element, element_len);
444 			break;
445 
446 		case OCI_TYPECODE_VARCHAR2 :
447 			return php_oci_collection_append_string(collection, element, element_len);
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);
462 			break;
463 
464 		default:
465 			php_error_docref(NULL, 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,zend_long index,zval * result_element)476 int php_oci_collection_element_get(php_oci_collection *collection, zend_long index, zval *result_element)
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 	ZVAL_NULL(result_element);
487 
488 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
489 
490 	PHP_OCI_CALL_RETURN(errstatus, OCICollGetElem,
491 			(
492 			 connection->env,
493 			 connection->err,
494 			 collection->collection,
495 			 (ub4)index,
496 			 &exists,
497 			 &element,
498 			 (dvoid **)&element_index
499 			)
500 	);
501 
502 	if (errstatus != OCI_SUCCESS) {
503 		connection->errcode = php_oci_error(connection->err, errstatus);
504 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
505 		return 1;
506 	}
507 
508 	if (exists == 0) {
509 		/* element doesn't exist */
510 		return 1;
511 	}
512 
513 	if (*element_index == OCI_IND_NULL) {
514 		/* this is not an error, we're returning NULL here */
515 		return 0;
516 	}
517 
518 	switch (collection->element_typecode) {
519 		case OCI_TYPECODE_DATE:
520 			PHP_OCI_CALL_RETURN(errstatus, OCIDateToText, (connection->err, element, 0, 0, 0, 0, &buff_len, buff));
521 
522 			if (errstatus != OCI_SUCCESS) {
523 				connection->errcode = php_oci_error(connection->err, errstatus);
524 				PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
525 				return 1;
526 			}
527 
528 			ZVAL_STRINGL(result_element, (char *)buff, buff_len);
529 			Z_STRVAL_P(result_element)[buff_len] = '\0';
530 
531 			return 0;
532 			break;
533 
534 		case OCI_TYPECODE_VARCHAR2:
535 		{
536 			OCIString *oci_string = *(OCIString **)element;
537 			text *str;
538 
539 			PHP_OCI_CALL_RETURN(str, OCIStringPtr, (connection->env, oci_string));
540 
541 			if (str) {
542 				ZVAL_STRING(result_element, (char *)str);
543 			}
544 			return 0;
545 		}
546 			break;
547 
548 		case OCI_TYPECODE_UNSIGNED16:						/* UNSIGNED SHORT  */
549 		case OCI_TYPECODE_UNSIGNED32:						/* UNSIGNED LONG  */
550 		case OCI_TYPECODE_REAL:								/* REAL	   */
551 		case OCI_TYPECODE_DOUBLE:							/* DOUBLE  */
552 		case OCI_TYPECODE_INTEGER:							/* INT	*/
553 		case OCI_TYPECODE_SIGNED16:							/* SHORT  */
554 		case OCI_TYPECODE_SIGNED32:							/* LONG	 */
555 		case OCI_TYPECODE_DECIMAL:							/* DECIMAL	*/
556 		case OCI_TYPECODE_FLOAT:							/* FLOAT	*/
557 		case OCI_TYPECODE_NUMBER:							/* NUMBER	*/
558 		case OCI_TYPECODE_SMALLINT:							/* SMALLINT */
559 		{
560 			double double_number;
561 
562 			PHP_OCI_CALL_RETURN(errstatus, OCINumberToReal, (connection->err, (CONST OCINumber *) element, (uword) sizeof(double), (dvoid *) &double_number));
563 
564 			if (errstatus != OCI_SUCCESS) {
565 				connection->errcode = php_oci_error(connection->err, errstatus);
566 				PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
567 				return 1;
568 			}
569 
570 			ZVAL_DOUBLE(result_element, double_number);
571 
572 			return 0;
573 		}
574 			break;
575 		default:
576 			php_error_docref(NULL, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
577 			return 1;
578 			break;
579 	}
580 	/* never reached */
581 	return 1;
582 }
583 /* }}} */
584 
585 /* {{{ php_oci_collection_element_set_null()
586  Set the element with the given index to NULL */
php_oci_collection_element_set_null(php_oci_collection * collection,zend_long index)587 int php_oci_collection_element_set_null(php_oci_collection *collection, zend_long index)
588 {
589 	OCIInd null_index = OCI_IND_NULL;
590 	php_oci_connection *connection = collection->connection;
591 	sword errstatus;
592 
593 	/* set NULL element */
594 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem, (connection->env, connection->err, (ub4) index, (dvoid *)"", &null_index, collection->collection));
595 
596 	if (errstatus != OCI_SUCCESS) {
597 		connection->errcode = php_oci_error(connection->err, errstatus);
598 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
599 		return 1;
600 	}
601 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
602 	return 0;
603 }
604 /* }}} */
605 
606 /* {{{ php_oci_collection_element_set_date()
607  Change element's value to the given DATE */
php_oci_collection_element_set_date(php_oci_collection * collection,zend_long index,char * date,int date_len)608 int php_oci_collection_element_set_date(php_oci_collection *collection, zend_long index, char *date, int date_len)
609 {
610 	OCIInd new_index = OCI_IND_NOTNULL;
611 	OCIDate oci_date;
612 	php_oci_connection *connection = collection->connection;
613 	sword errstatus;
614 
615 	/* format and language are NULLs, so format is "DD-MON-YY" and language is the default language of the session */
616 	PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date));
617 
618 	if (errstatus != OCI_SUCCESS) {
619 		/* failed to convert string to date */
620 		connection->errcode = php_oci_error(connection->err, errstatus);
621 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
622 		return 1;
623 	}
624 
625 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem,
626 			(
627 			 connection->env,
628 			 connection->err,
629 			 (ub4)index,
630 			 (dvoid *) &oci_date,
631 			 (dvoid *) &new_index,
632 			 (OCIColl *) collection->collection
633 			 )
634 	);
635 
636 	if (errstatus != OCI_SUCCESS) {
637 		connection->errcode = php_oci_error(connection->err, errstatus);
638 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
639 		return 1;
640 	}
641 
642 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
643 	return 0;
644 }
645 /* }}} */
646 
647 /* {{{ php_oci_collection_element_set_number()
648  Change element's value to the given NUMBER */
php_oci_collection_element_set_number(php_oci_collection * collection,zend_long index,char * number,int number_len)649 int php_oci_collection_element_set_number(php_oci_collection *collection, zend_long index, char *number, int number_len)
650 {
651 	OCIInd new_index = OCI_IND_NOTNULL;
652 	double element_double;
653 	OCINumber oci_number;
654 	php_oci_connection *connection = collection->connection;
655 	sword errstatus;
656 
657 	element_double = zend_strtod(number, NULL);
658 
659 	PHP_OCI_CALL_RETURN(errstatus, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number));
660 
661 	if (errstatus != OCI_SUCCESS) {
662 		connection->errcode = php_oci_error(connection->err, errstatus);
663 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
664 		return 1;
665 	}
666 
667 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem,
668 			(
669 			 connection->env,
670 			 connection->err,
671 			 (ub4) index,
672 			 (dvoid *) &oci_number,
673 			 (dvoid *) &new_index,
674 			 (OCIColl *) collection->collection
675 			 )
676 	);
677 
678 	if (errstatus != OCI_SUCCESS) {
679 		connection->errcode = php_oci_error(connection->err, errstatus);
680 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
681 		return 1;
682 	}
683 
684 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
685 	return 0;
686 }
687 /* }}} */
688 
689 /* {{{ php_oci_collection_element_set_string()
690  Change element's value to the given string */
php_oci_collection_element_set_string(php_oci_collection * collection,zend_long index,char * element,int element_len)691 int php_oci_collection_element_set_string(php_oci_collection *collection, zend_long index, char *element, int element_len)
692 {
693 	OCIInd new_index = OCI_IND_NOTNULL;
694 	OCIString *ocistr = (OCIString *)0;
695 	php_oci_connection *connection = collection->connection;
696 	sword errstatus;
697 
698 	PHP_OCI_CALL_RETURN(errstatus, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr));
699 
700 	if (errstatus != OCI_SUCCESS) {
701 		connection->errcode = php_oci_error(connection->err, errstatus);
702 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
703 		return 1;
704 	}
705 
706 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem,
707 			(
708 			 connection->env,
709 			 connection->err,
710 			 (ub4)index,
711 			 (dvoid *) ocistr,
712 			 (dvoid *) &new_index,
713 			 (OCIColl *) collection->collection
714 			 )
715 	);
716 
717 	if (errstatus != OCI_SUCCESS) {
718 		connection->errcode = php_oci_error(connection->err, errstatus);
719 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
720 		return 1;
721 	}
722 
723 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
724 	return 0;
725 }
726 /* }}} */
727 
728 /* {{{ php_oci_collection_element_set()
729  Collection element setter */
php_oci_collection_element_set(php_oci_collection * collection,zend_long index,char * value,int value_len)730 int php_oci_collection_element_set(php_oci_collection *collection, zend_long index, char *value, int value_len)
731 {
732 	if (value_len == 0) {
733 		return php_oci_collection_element_set_null(collection, index);
734 	}
735 
736 	switch(collection->element_typecode) {
737 		case OCI_TYPECODE_DATE:
738 			return php_oci_collection_element_set_date(collection, index, value, value_len);
739 			break;
740 
741 		case OCI_TYPECODE_VARCHAR2 :
742 			return php_oci_collection_element_set_string(collection, index, value, value_len);
743 			break;
744 
745 		case OCI_TYPECODE_UNSIGNED16 :						 /* UNSIGNED SHORT	*/
746 		case OCI_TYPECODE_UNSIGNED32 :						  /* UNSIGNED LONG	*/
747 		case OCI_TYPECODE_REAL :									 /* REAL	*/
748 		case OCI_TYPECODE_DOUBLE :									 /* DOUBLE	*/
749 		case OCI_TYPECODE_INTEGER :										/* INT	*/
750 		case OCI_TYPECODE_SIGNED16 :								  /* SHORT	*/
751 		case OCI_TYPECODE_SIGNED32 :								   /* LONG	*/
752 		case OCI_TYPECODE_DECIMAL :									/* DECIMAL	*/
753 		case OCI_TYPECODE_FLOAT :									/* FLOAT	*/
754 		case OCI_TYPECODE_NUMBER :									/* NUMBER	*/
755 		case OCI_TYPECODE_SMALLINT :								/* SMALLINT */
756 			return php_oci_collection_element_set_number(collection, index, value, value_len);
757 			break;
758 
759 		default:
760 			php_error_docref(NULL, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
761 			return 1;
762 			break;
763 	}
764 	/* never reached */
765 	return 1;
766 }
767 /* }}} */
768 
769 /* {{{ php_oci_collection_assign()
770  Assigns a value to the collection from another collection */
php_oci_collection_assign(php_oci_collection * collection_dest,php_oci_collection * collection_from)771 int php_oci_collection_assign(php_oci_collection *collection_dest, php_oci_collection *collection_from)
772 {
773 	php_oci_connection *connection = collection_dest->connection;
774 	sword errstatus;
775 
776 	PHP_OCI_CALL_RETURN(errstatus, OCICollAssign, (connection->env, connection->err, collection_from->collection, collection_dest->collection));
777 
778 	if (errstatus != OCI_SUCCESS) {
779 		connection->errcode = php_oci_error(connection->err, errstatus);
780 		PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
781 		return 1;
782 	}
783 	connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
784 	return 0;
785 }
786 /* }}} */
787 
788 /* {{{ php_oci_collection_close()
789  Destroy collection and all associated resources */
php_oci_collection_close(php_oci_collection * collection)790 void php_oci_collection_close(php_oci_collection *collection)
791 {
792 	php_oci_connection *connection = collection->connection;
793 	sword errstatus;
794 
795 	if (collection->collection) {
796 		PHP_OCI_CALL_RETURN(errstatus, OCIObjectFree, (connection->env, connection->err, (dvoid *)collection->collection, (ub2)OCI_OBJECTFREE_FORCE));
797 
798 		if (errstatus != OCI_SUCCESS) {
799 			connection->errcode = php_oci_error(connection->err, errstatus);
800 			PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
801 		} else {
802 			connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
803 		}
804 	}
805 
806 	zend_list_delete(collection->connection->id);
807 	efree(collection);
808 	return;
809 }
810 /* }}} */
811 
812 #endif /* HAVE_OCI8 */
813