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