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