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