xref: /PHP-5.6/ext/oci8/oci8_interface.c (revision 49493a2d)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2016 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Stig S�ther Bakken <ssb@php.net>                            |
16    |          Thies C. Arntzen <thies@thieso.net>                         |
17    |                                                                      |
18    | Collection support by Andy Sautins <asautins@veripost.net>           |
19    | Temporary LOB support by David Benson <dbenson@mancala.com>          |
20    | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at>        |
21    |                                                                      |
22    | Redesigned by: Antony Dovgal <antony@zend.com>                       |
23    |                Andi Gutmans <andi@zend.com>                          |
24    |                Wez Furlong <wez@omniti.com>                          |
25    +----------------------------------------------------------------------+
26 */
27 
28 /* $Id$ */
29 
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #include "php.h"
35 #include "ext/standard/info.h"
36 #include "php_ini.h"
37 
38 #if HAVE_OCI8
39 
40 #include "php_oci8.h"
41 #include "php_oci8_int.h"
42 
43 #ifndef OCI_STMT_CALL
44 #define OCI_STMT_CALL 10
45 #endif
46 
47 /* {{{ proto bool oci_define_by_name(resource stmt, string name, mixed &var [, int type])
48    Define a PHP variable to an Oracle column by name */
49 /* if you want to define a LOB/CLOB etc make sure you allocate it via OCINewDescriptor BEFORE defining!!! */
PHP_FUNCTION(oci_define_by_name)50 PHP_FUNCTION(oci_define_by_name)
51 {
52 	zval *stmt, *var;
53 	char *name;
54 	int name_len;
55 	long type = 0;
56 	php_oci_statement *statement;
57 	php_oci_define *define, *tmp_define;
58 
59 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz/|l", &stmt, &name, &name_len, &var, &type) == FAILURE) {
60 		return;
61 	}
62 
63 	if (!name_len) {
64 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column name cannot be empty");
65 		RETURN_FALSE;
66 	}
67 
68 	PHP_OCI_ZVAL_TO_STATEMENT(stmt, statement);
69 
70 	if (statement->defines == NULL) {
71 		ALLOC_HASHTABLE(statement->defines);
72 		zend_hash_init(statement->defines, 13, NULL, php_oci_define_hash_dtor, 0);
73 	}
74 
75 	define = ecalloc(1,sizeof(php_oci_define));
76 
77 	if (zend_hash_add(statement->defines, name, name_len, define, sizeof(php_oci_define), (void **)&tmp_define) == SUCCESS) {
78 		efree(define);
79 		define = tmp_define;
80 	} else {
81 		efree(define);
82 		RETURN_FALSE;
83 	}
84 
85 	define->name = (text*) estrndup(name, name_len);
86 	define->name_len = name_len;
87 	define->type = type;
88 	define->zval = var;
89 	zval_add_ref(&var);
90 
91 	RETURN_TRUE;
92 }
93 /* }}} */
94 
95 /* {{{ proto bool oci_bind_by_name(resource stmt, string name, mixed &var, [, int maxlength [, int type]])
96    Bind a PHP variable to an Oracle placeholder by name */
97 /* if you want to bind a LOB/CLOB etc make sure you allocate it via OCINewDescriptor BEFORE binding!!! */
PHP_FUNCTION(oci_bind_by_name)98 PHP_FUNCTION(oci_bind_by_name)
99 {
100 	ub2	bind_type = SQLT_CHR; /* unterminated string */
101 	int name_len;
102 	long maxlen = -1, type = 0;
103 	char *name;
104 	zval *z_statement;
105 	zval *bind_var = NULL;
106 	php_oci_statement *statement;
107 
108 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz/|ll", &z_statement, &name, &name_len, &bind_var, &maxlen, &type) == FAILURE) {
109 		return;
110 	}
111 
112 	if (type) {
113 		bind_type = (ub2) type;
114 	}
115 
116 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
117 
118 	if (php_oci_bind_by_name(statement, name, name_len, bind_var, maxlen, bind_type TSRMLS_CC)) {
119 		RETURN_FALSE;
120 	}
121 	RETURN_TRUE;
122 }
123 /* }}} */
124 
125 /* {{{ proto bool oci_bind_array_by_name(resource stmt, string name, array &var, int max_table_length [, int max_item_length [, int type ]])
126    Bind a PHP array to an Oracle PL/SQL type by name */
PHP_FUNCTION(oci_bind_array_by_name)127 PHP_FUNCTION(oci_bind_array_by_name)
128 {
129 	int name_len;
130 	long max_item_len = -1;
131 	long max_array_len = 0;
132 	long type = SQLT_AFC;
133 	char *name;
134 	zval *z_statement;
135 	zval *bind_var = NULL;
136 	php_oci_statement *statement;
137 
138 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz/l|ll", &z_statement, &name, &name_len, &bind_var, &max_array_len, &max_item_len, &type) == FAILURE) {
139 		return;
140 	}
141 
142 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
143 
144 	if (ZEND_NUM_ARGS() == 5 && max_item_len <= 0) {
145 		max_item_len = -1;
146 	}
147 
148 	if (max_array_len <= 0) {
149 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum array length must be greater than zero");
150 		RETURN_FALSE;
151 	}
152 
153 	if (php_oci_bind_array_by_name(statement, name, name_len, bind_var, max_array_len, max_item_len, type TSRMLS_CC)) {
154 		RETURN_FALSE;
155 	}
156 	RETURN_TRUE;
157 }
158 /* }}} */
159 
160 /* {{{ proto bool oci_free_descriptor()
161    Deletes large object description */
PHP_FUNCTION(oci_free_descriptor)162 PHP_FUNCTION(oci_free_descriptor)
163 {
164 	zval **tmp, *z_descriptor = getThis();
165 	php_oci_descriptor *descriptor;
166 
167 	if (!getThis()) {
168 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
169 			return;
170 		}
171 	}
172 
173 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
174 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
175 		RETURN_FALSE;
176 	}
177 
178 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
179 
180 	zend_list_delete(descriptor->id);
181 	RETURN_TRUE;
182 }
183 /* }}} */
184 
185 /* {{{ proto bool oci_lob_save( string data [, int offset ])
186    Saves a large object */
PHP_FUNCTION(oci_lob_save)187 PHP_FUNCTION(oci_lob_save)
188 {
189 	zval **tmp, *z_descriptor = getThis();
190 	php_oci_descriptor *descriptor;
191 	char *data;
192 	int data_len;
193 	long offset = 0;
194 	ub4 bytes_written;
195 
196 	if (getThis()) {
197 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &offset) == FAILURE) {
198 			return;
199 		}
200 	}
201 	else {
202 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &z_descriptor, oci_lob_class_entry_ptr, &data, &data_len, &offset) == FAILURE) {
203 			return;
204 		}
205 	}
206 
207 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
208 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
209 		RETURN_FALSE;
210 	}
211 
212 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
213 
214 	if (offset < 0) {
215 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset parameter must be greater than or equal to 0");
216 		RETURN_FALSE;
217 	}
218 
219 	if (php_oci_lob_write(descriptor, offset, data, data_len, &bytes_written TSRMLS_CC)) {
220 		RETURN_FALSE;
221 	}
222 	RETURN_TRUE;
223 }
224 /* }}} */
225 
226 /* {{{ proto bool oci_lob_import( string filename )
227    Loads file into a LOB */
PHP_FUNCTION(oci_lob_import)228 PHP_FUNCTION(oci_lob_import)
229 {
230 	zval **tmp, *z_descriptor = getThis();
231 	php_oci_descriptor *descriptor;
232 	char *filename;
233 	int filename_len;
234 
235 	if (getThis()) {
236 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
237 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
238 #else
239 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
240 #endif
241 			return;
242 		}
243 	}
244 	else {
245 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
246 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Op", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len) == FAILURE) {
247 #else
248 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len) == FAILURE) {
249 #endif
250 			return;
251 		}
252 	}
253 
254 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5)
255 	/* The "p" parsing parameter handles this case in PHP 5.4+ */
256 	if (strlen(filename) != filename_len) {
257 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filename cannot contain null bytes");
258 		RETURN_FALSE;
259 	}
260 #endif
261 
262 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
263 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
264 		RETURN_FALSE;
265 	}
266 
267 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
268 
269 	if (php_oci_lob_import(descriptor, filename TSRMLS_CC)) {
270 		RETURN_FALSE;
271 	}
272 	RETURN_TRUE;
273 }
274 /* }}} */
275 
276 /* {{{ proto string oci_lob_load()
277    Loads a large object */
278 PHP_FUNCTION(oci_lob_load)
279 {
280 	zval **tmp, *z_descriptor = getThis();
281 	php_oci_descriptor *descriptor;
282 	char *buffer = NULL;
283 	ub4 buffer_len;
284 
285 	if (!getThis()) {
286 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
287 			return;
288 		}
289 	}
290 
291 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
292 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
293 		RETURN_FALSE;
294 	}
295 
296 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
297 
298 	if (php_oci_lob_read(descriptor, -1, 0, &buffer, &buffer_len TSRMLS_CC)) {
299 		RETURN_FALSE;
300 	}
301 	if (buffer_len > 0) {
302 		RETURN_STRINGL(buffer, buffer_len, 0);
303 	}
304 	else {
305 		RETURN_EMPTY_STRING();
306 	}
307 }
308 /* }}} */
309 
310 /* {{{ proto string oci_lob_read( int length )
311    Reads particular part of a large object */
312 PHP_FUNCTION(oci_lob_read)
313 {
314 	zval **tmp, *z_descriptor = getThis();
315 	php_oci_descriptor *descriptor;
316 	long length;
317 	char *buffer;
318 	ub4 buffer_len;
319 
320 	if (getThis()) {
321 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) {
322 			return;
323 		}
324 	}
325 	else {
326 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &z_descriptor, oci_lob_class_entry_ptr, &length) == FAILURE) {
327 			return;
328 		}
329 	}
330 
331 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
332 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
333 		RETURN_FALSE;
334 	}
335 
336 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
337 
338 	if (length <= 0) {
339 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
340 		RETURN_FALSE;
341 	}
342 
343 	if (php_oci_lob_read(descriptor, length, descriptor->lob_current_position, &buffer, &buffer_len TSRMLS_CC)) {
344 		RETURN_FALSE;
345 	}
346 	if (buffer_len > 0) {
347 		RETURN_STRINGL(buffer, buffer_len, 0);
348 	}
349 	else {
350 		RETURN_EMPTY_STRING();
351 	}
352 }
353 /* }}} */
354 
355 /* {{{ proto bool oci_lob_eof()
356    Checks if EOF is reached */
357 PHP_FUNCTION(oci_lob_eof)
358 {
359 	zval **tmp, *z_descriptor = getThis();
360 	php_oci_descriptor *descriptor;
361 	ub4 lob_length;
362 
363 	if (!getThis()) {
364 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
365 			return;
366 		}
367 	}
368 
369 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
370 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
371 		RETURN_FALSE;
372 	}
373 
374 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
375 
376 	if (!php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
377 		if (lob_length == descriptor->lob_current_position) {
378 			RETURN_TRUE;
379 		}
380 	}
381 	RETURN_FALSE;
382 }
383 /* }}} */
384 
385 /* {{{ proto int oci_lob_tell()
386    Tells LOB pointer position */
387 PHP_FUNCTION(oci_lob_tell)
388 {
389 	zval **tmp, *z_descriptor = getThis();
390 	php_oci_descriptor *descriptor;
391 
392 	if (!getThis()) {
393 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
394 			return;
395 		}
396 	}
397 
398 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
399 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
400 		RETURN_FALSE;
401 	}
402 
403 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
404 
405 	RETURN_LONG(descriptor->lob_current_position);
406 }
407 /* }}} */
408 
409 /* {{{ proto bool oci_lob_rewind()
410    Rewind pointer of a LOB */
411 PHP_FUNCTION(oci_lob_rewind)
412 {
413 	zval **tmp, *z_descriptor = getThis();
414 	php_oci_descriptor *descriptor;
415 
416 	if (!getThis()) {
417 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
418 			return;
419 		}
420 	}
421 
422 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
423 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
424 		RETURN_FALSE;
425 	}
426 
427 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
428 
429 	descriptor->lob_current_position = 0;
430 
431 	RETURN_TRUE;
432 }
433 /* }}} */
434 
435 /* {{{ proto bool oci_lob_seek( int offset [, int whence ])
436    Moves the pointer of a LOB */
437 PHP_FUNCTION(oci_lob_seek)
438 {
439 	zval **tmp, *z_descriptor = getThis();
440 	php_oci_descriptor *descriptor;
441 	long offset, whence = PHP_OCI_SEEK_SET;
442 	ub4 lob_length;
443 
444 	if (getThis()) {
445 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &offset, &whence) == FAILURE) {
446 			return;
447 		}
448 	}
449 	else {
450 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|l", &z_descriptor, oci_lob_class_entry_ptr, &offset, &whence) == FAILURE) {
451 			return;
452 		}
453 	}
454 
455 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
456 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
457 		RETURN_FALSE;
458 	}
459 
460 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
461 
462 	if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
463 		RETURN_FALSE;
464 	}
465 
466 	switch(whence) {
467 		case PHP_OCI_SEEK_CUR:
468 			descriptor->lob_current_position += offset;
469 			break;
470 		case PHP_OCI_SEEK_END:
471 			if ((descriptor->lob_size + offset) >= 0) {
472 				descriptor->lob_current_position = descriptor->lob_size + offset;
473 			}
474 			else {
475 				descriptor->lob_current_position = 0;
476 			}
477 			break;
478 		case PHP_OCI_SEEK_SET:
479 		default:
480 				descriptor->lob_current_position = (offset > 0) ? offset : 0;
481 			break;
482 	}
483 	RETURN_TRUE;
484 }
485 /* }}} */
486 
487 /* {{{ proto int oci_lob_size()
488    Returns size of a large object */
489 PHP_FUNCTION(oci_lob_size)
490 {
491 	zval **tmp, *z_descriptor = getThis();
492 	php_oci_descriptor *descriptor;
493 	ub4 lob_length;
494 
495 	if (!getThis()) {
496 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
497 			return;
498 		}
499 	}
500 
501 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
502 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
503 		RETURN_FALSE;
504 	}
505 
506 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
507 
508 	if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
509 		RETURN_FALSE;
510 	}
511 	RETURN_LONG(lob_length);
512 }
513 /* }}} */
514 
515 /* {{{ proto int oci_lob_write( string string [, int length ])
516    Writes data to current position of a LOB */
517 PHP_FUNCTION(oci_lob_write)
518 {
519 	zval **tmp, *z_descriptor = getThis();
520 	php_oci_descriptor *descriptor;
521 	int data_len;
522 	long write_len = 0;
523 	ub4 bytes_written;
524 	char *data;
525 
526 	if (getThis()) {
527 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &write_len) == FAILURE) {
528 			return;
529 		}
530 
531 		if (ZEND_NUM_ARGS() == 2) {
532 			data_len = MIN(data_len, write_len);
533 		}
534 	}
535 	else {
536 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &z_descriptor, oci_lob_class_entry_ptr, &data, &data_len, &write_len) == FAILURE) {
537 			return;
538 		}
539 
540 		if (ZEND_NUM_ARGS() == 3) {
541 			data_len = MIN(data_len, write_len);
542 		}
543 	}
544 
545 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
546 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
547 		RETURN_FALSE;
548 	}
549 
550 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
551 
552 	if (data_len <= 0) {
553 		RETURN_LONG(0);
554 	}
555 
556 	if (php_oci_lob_write(descriptor, descriptor->lob_current_position, data, data_len, &bytes_written TSRMLS_CC)) {
557 		RETURN_FALSE;
558 	}
559 	RETURN_LONG(bytes_written);
560 }
561 /* }}} */
562 
563 /* {{{ proto bool oci_lob_append( object lob )
564    Appends data from a LOB to another LOB */
565 PHP_FUNCTION(oci_lob_append)
566 {
567 	zval **tmp_dest, **tmp_from, *z_descriptor_dest = getThis(), *z_descriptor_from;
568 	php_oci_descriptor *descriptor_dest, *descriptor_from;
569 
570 	if (getThis()) {
571 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor_from, oci_lob_class_entry_ptr) == FAILURE) {
572 			return;
573 		}
574 	}
575 	else {
576 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &z_descriptor_dest, oci_lob_class_entry_ptr, &z_descriptor_from, oci_lob_class_entry_ptr) == FAILURE) {
577 			return;
578 		}
579 	}
580 
581 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor_dest), "descriptor", sizeof("descriptor"), (void **)&tmp_dest) == FAILURE) {
582 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The first argument should be valid descriptor object");
583 		RETURN_FALSE;
584 	}
585 
586 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor_from), "descriptor", sizeof("descriptor"), (void **)&tmp_from) == FAILURE) {
587 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The second argument should be valid descriptor object");
588 		RETURN_FALSE;
589 	}
590 
591 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_dest, descriptor_dest);
592 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_from, descriptor_from);
593 
594 	if (php_oci_lob_append(descriptor_dest, descriptor_from TSRMLS_CC)) {
595 		RETURN_FALSE;
596 	}
597 	/* XXX should we increase lob_size here ? */
598 	RETURN_TRUE;
599 }
600 /* }}} */
601 
602 /* {{{ proto bool oci_lob_truncate( [ int length ])
603    Truncates a LOB */
604 PHP_FUNCTION(oci_lob_truncate)
605 {
606 	zval **tmp, *z_descriptor = getThis();
607 	php_oci_descriptor *descriptor;
608 	long trim_length = 0;
609 	ub4 ub_trim_length;
610 
611 	if (getThis()) {
612 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &trim_length) == FAILURE) {
613 			return;
614 		}
615 	}
616 	else {
617 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &z_descriptor, oci_lob_class_entry_ptr, &trim_length) == FAILURE) {
618 			return;
619 		}
620 	}
621 
622 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
623 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
624 		RETURN_FALSE;
625 	}
626 
627 	if (trim_length < 0) {
628 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length must be greater than or equal to zero");
629 		RETURN_FALSE;
630 	}
631 
632 	ub_trim_length = (ub4) trim_length;
633 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
634 
635 	if (php_oci_lob_truncate(descriptor, ub_trim_length TSRMLS_CC)) {
636 		RETURN_FALSE;
637 	}
638 	RETURN_TRUE;
639 }
640 /* }}} */
641 
642 /* {{{ proto int oci_lob_erase( [ int offset [, int length ] ] )
643    Erases a specified portion of the internal LOB, starting at a specified offset */
644 PHP_FUNCTION(oci_lob_erase)
645 {
646 	zval **tmp, *z_descriptor = getThis();
647 	php_oci_descriptor *descriptor;
648 	ub4 bytes_erased;
649 	long offset = -1, length = -1;
650 
651 	if (getThis()) {
652 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &offset, &length) == FAILURE) {
653 			return;
654 		}
655 
656 		if (ZEND_NUM_ARGS() > 0 && offset < 0) {
657 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be greater than or equal to 0");
658 			RETURN_FALSE;
659 		}
660 
661 		if (ZEND_NUM_ARGS() > 1 && length < 0) {
662 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length must be greater than or equal to 0");
663 			RETURN_FALSE;
664 		}
665 	}
666 	else {
667 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|ll", &z_descriptor, oci_lob_class_entry_ptr, &offset, &length) == FAILURE) {
668 			return;
669 		}
670 
671 		if (ZEND_NUM_ARGS() > 1 && offset < 0) {
672 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be greater than or equal to 0");
673 			RETURN_FALSE;
674 		}
675 
676 		if (ZEND_NUM_ARGS() > 2 && length < 0) {
677 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length must be greater than or equal to 0");
678 			RETURN_FALSE;
679 		}
680 	}
681 
682 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
683 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
684 		RETURN_FALSE;
685 	}
686 
687 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
688 
689 	if (php_oci_lob_erase(descriptor, offset, length, &bytes_erased TSRMLS_CC)) {
690 		RETURN_FALSE;
691 	}
692 	RETURN_LONG(bytes_erased);
693 }
694 /* }}} */
695 
696 /* {{{ proto bool oci_lob_flush( [ int flag ] )
697    Flushes the LOB buffer */
698 PHP_FUNCTION(oci_lob_flush)
699 {
700 	zval **tmp, *z_descriptor = getThis();
701 	php_oci_descriptor *descriptor;
702 	long flush_flag = 0;
703 
704 	if (getThis()) {
705 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flush_flag) == FAILURE) {
706 			return;
707 		}
708 	}
709 	else {
710 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &z_descriptor, oci_lob_class_entry_ptr, &flush_flag) == FAILURE) {
711 			return;
712 		}
713 	}
714 
715 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
716 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
717 		RETURN_FALSE;
718 	}
719 
720 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
721 
722 	if (descriptor->buffering == PHP_OCI_LOB_BUFFER_DISABLED) {
723 		/* buffering wasn't enabled, there is nothing to flush */
724 		RETURN_FALSE;
725 	}
726 
727 	if (php_oci_lob_flush(descriptor, flush_flag TSRMLS_CC)) {
728 		RETURN_FALSE;
729 	}
730 	RETURN_TRUE;
731 }
732 /* }}} */
733 
734 /* {{{ proto bool ocisetbufferinglob( boolean flag )
735    Enables/disables buffering for a LOB */
736 PHP_FUNCTION(ocisetbufferinglob)
737 {
738 	zval **tmp, *z_descriptor = getThis();
739 	php_oci_descriptor *descriptor;
740 	zend_bool flag;
741 
742 	if (getThis()) {
743 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &flag) == FAILURE) {
744 			return;
745 		}
746 	}
747 	else {
748 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ob", &z_descriptor, oci_lob_class_entry_ptr, &flag) == FAILURE) {
749 			return;
750 		}
751 	}
752 
753 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
754 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
755 		RETURN_FALSE;
756 	}
757 
758 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
759 
760 	if (php_oci_lob_set_buffering(descriptor, flag TSRMLS_CC)) {
761 		RETURN_FALSE;
762 	}
763 	RETURN_TRUE;
764 }
765 /* }}} */
766 
767 /* {{{ proto bool ocigetbufferinglob()
768    Returns current state of buffering for a LOB */
769 PHP_FUNCTION(ocigetbufferinglob)
770 {
771 	zval **tmp, *z_descriptor = getThis();
772 	php_oci_descriptor *descriptor;
773 
774 	if (!getThis()) {
775 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
776 			return;
777 		}
778 	}
779 
780 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
781 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
782 		RETURN_FALSE;
783 	}
784 
785 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
786 
787 	if (descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
788 		RETURN_TRUE;
789 	}
790 	RETURN_FALSE;
791 }
792 /* }}} */
793 
794 /* {{{ proto bool oci_lob_copy( object lob_to, object lob_from [, int length ] )
795    Copies data from a LOB to another LOB */
796 PHP_FUNCTION(oci_lob_copy)
797 {
798 	zval **tmp_dest, **tmp_from, *z_descriptor_dest, *z_descriptor_from;
799 	php_oci_descriptor *descriptor_dest, *descriptor_from;
800 	long length = 0;
801 
802 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO|l", &z_descriptor_dest, oci_lob_class_entry_ptr, &z_descriptor_from, oci_lob_class_entry_ptr, &length) == FAILURE) {
803 		return;
804 	}
805 
806 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor_dest), "descriptor", sizeof("descriptor"), (void **)&tmp_dest) == FAILURE) {
807 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The first argument should be valid descriptor object");
808 		RETURN_FALSE;
809 	}
810 
811 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor_from), "descriptor", sizeof("descriptor"), (void **)&tmp_from) == FAILURE) {
812 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The second argument should be valid descriptor object");
813 		RETURN_FALSE;
814 	}
815 
816 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_dest, descriptor_dest);
817 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_from, descriptor_from);
818 
819 	if (ZEND_NUM_ARGS() == 3 && length < 0) {
820 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
821 		RETURN_FALSE;
822 	}
823 
824 	if (ZEND_NUM_ARGS() == 2) {
825 		/* indicate that we want to copy from the current position to the end of the LOB */
826 		length = -1;
827 	}
828 
829 	if (php_oci_lob_copy(descriptor_dest, descriptor_from, length TSRMLS_CC)) {
830 		RETURN_FALSE;
831 	}
832 	RETURN_TRUE;
833 }
834 /* }}} */
835 
836 /* {{{ proto bool oci_lob_is_equal( object lob1, object lob2 )
837    Tests to see if two LOB/FILE locators are equal */
838 PHP_FUNCTION(oci_lob_is_equal)
839 {
840 	zval **tmp_first, **tmp_second, *z_descriptor_first, *z_descriptor_second;
841 	php_oci_descriptor *descriptor_first, *descriptor_second;
842 	boolean is_equal;
843 
844 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &z_descriptor_first, oci_lob_class_entry_ptr, &z_descriptor_second, oci_lob_class_entry_ptr) == FAILURE) {
845 		return;
846 	}
847 
848 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor_first), "descriptor", sizeof("descriptor"), (void **)&tmp_first) == FAILURE) {
849 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The first argument should be valid descriptor object");
850 		RETURN_FALSE;
851 	}
852 
853 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor_second), "descriptor", sizeof("descriptor"), (void **)&tmp_second) == FAILURE) {
854 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The second argument should be valid descriptor object");
855 		RETURN_FALSE;
856 	}
857 
858 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_first, descriptor_first);
859 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_second, descriptor_second);
860 
861 	if (php_oci_lob_is_equal(descriptor_first, descriptor_second, &is_equal TSRMLS_CC)) {
862 		RETURN_FALSE;
863 	}
864 
865 	if (is_equal == TRUE) {
866 		RETURN_TRUE;
867 	}
868 	RETURN_FALSE;
869 }
870 /* }}} */
871 
872 /* {{{ proto bool oci_lob_export([string filename [, int start [, int length]]])
873    Writes a large object into a file */
874 PHP_FUNCTION(oci_lob_export)
875 {
876 	zval **tmp, *z_descriptor = getThis();
877 	php_oci_descriptor *descriptor;
878 	char *filename;
879 	char *buffer;
880 	int filename_len;
881 	long start = -1, length = -1, block_length;
882 	php_stream *stream;
883 	ub4 lob_length;
884 
885 	if (getThis()) {
886 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
887 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ll", &filename, &filename_len, &start, &length) == FAILURE) {
888 #else
889 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &filename, &filename_len, &start, &length) == FAILURE) {
890 #endif
891 			return;
892 		}
893 
894 		if (ZEND_NUM_ARGS() > 1 && start < 0) {
895 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Start parameter must be greater than or equal to 0");
896 			RETURN_FALSE;
897 		}
898 		if (ZEND_NUM_ARGS() > 2 && length < 0) {
899 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than or equal to 0");
900 			RETURN_FALSE;
901 		}
902 	}
903 	else {
904 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
905 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Op|ll", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len, &start, &length) == FAILURE) {
906 #else
907 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|ll", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len, &start, &length) == FAILURE) {
908 #endif
909 			return;
910 		}
911 
912 		if (ZEND_NUM_ARGS() > 2 && start < 0) {
913 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Start parameter must be greater than or equal to 0");
914 			RETURN_FALSE;
915 		}
916 		if (ZEND_NUM_ARGS() > 3 && length < 0) {
917 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than or equal to 0");
918 			RETURN_FALSE;
919 		}
920 	}
921 
922 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5)
923 	/* The "p" parsing parameter handles this case in PHP 5.4+ */
924 	if (strlen(filename) != filename_len) {
925 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filename cannot contain null bytes");
926 		RETURN_FALSE;
927 	}
928 #endif
929 
930 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
931 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
932 		RETURN_FALSE;
933 	}
934 
935 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
936 
937 	if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
938 		RETURN_FALSE;
939 	}
940 
941 	if (start == -1) {
942 		start = 0;
943 	}
944 
945 	if (length == -1) {
946 		length = lob_length - descriptor->lob_current_position;
947 	}
948 
949 	if (length == 0) {
950 		/* nothing to write, fail silently */
951 		RETURN_FALSE;
952 	}
953 
954 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5)
955 	/* Safe mode has been removed in PHP 5.4 */
956 	if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
957 		RETURN_FALSE;
958 	}
959 #endif
960 
961 	if (php_check_open_basedir(filename TSRMLS_CC)) {
962 		RETURN_FALSE;
963 	}
964 
965 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
966 	stream = php_stream_open_wrapper_ex(filename, "w", REPORT_ERRORS, NULL, NULL);
967 #else
968 	stream = php_stream_open_wrapper_ex(filename, "w", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL);
969 #endif
970 
971 	block_length = PHP_OCI_LOB_BUFFER_SIZE;
972 	if (block_length > length) {
973 		block_length = length;
974 	}
975 
976 	while(length > 0) {
977 		ub4 tmp_bytes_read = 0;
978 		if (php_oci_lob_read(descriptor, block_length, start, &buffer, &tmp_bytes_read TSRMLS_CC)) {
979 			php_stream_close(stream);
980 			RETURN_FALSE;
981 		}
982 		if (tmp_bytes_read && !php_stream_write(stream, buffer, tmp_bytes_read)) {
983 			php_stream_close(stream);
984 			efree(buffer);
985 			RETURN_FALSE;
986 		}
987 		if (buffer) {
988 			efree(buffer);
989 		}
990 
991 		length -= tmp_bytes_read;
992 		descriptor->lob_current_position += tmp_bytes_read;
993 		start += tmp_bytes_read;
994 
995 		if (block_length > length) {
996 			block_length = length;
997 		}
998 	}
999 
1000 	php_stream_close(stream);
1001 	RETURN_TRUE;
1002 }
1003 /* }}} */
1004 
1005 /* {{{ proto bool oci_lob_write_temporary(string var [, int lob_type])
1006    Writes temporary blob */
1007 PHP_FUNCTION(oci_lob_write_temporary)
1008 {
1009 	zval **tmp, *z_descriptor = getThis();
1010 	php_oci_descriptor *descriptor;
1011 	char *data;
1012 	int data_len;
1013 	long type = OCI_TEMP_CLOB;
1014 
1015 	if (getThis()) {
1016 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &type) == FAILURE) {
1017 			return;
1018 		}
1019 	}
1020 	else {
1021 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &z_descriptor, oci_lob_class_entry_ptr, &data, &data_len, &type) == FAILURE) {
1022 			return;
1023 		}
1024 	}
1025 
1026 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
1027 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
1028 		RETURN_FALSE;
1029 	}
1030 
1031 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
1032 
1033 	if (php_oci_lob_write_tmp(descriptor, type, data, data_len TSRMLS_CC)) {
1034 		RETURN_FALSE;
1035 	}
1036 	RETURN_TRUE;
1037 }
1038 /* }}} */
1039 
1040 /* {{{ proto bool oci_lob_close()
1041    Closes lob descriptor */
1042 PHP_FUNCTION(oci_lob_close)
1043 {
1044 	zval **tmp, *z_descriptor = getThis();
1045 	php_oci_descriptor *descriptor;
1046 
1047 	if (!getThis()) {
1048 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
1049 			return;
1050 		}
1051 	}
1052 
1053 	if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
1054 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
1055 		RETURN_FALSE;
1056 	}
1057 
1058 	PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
1059 
1060 	if (php_oci_lob_close(descriptor TSRMLS_CC)) {
1061 		RETURN_FALSE;
1062 	}
1063 	RETURN_TRUE;
1064 }
1065 /* }}} */
1066 
1067 /* {{{ proto object oci_new_descriptor(resource connection [, int type])
1068    Initialize a new empty descriptor LOB/FILE (LOB is default) */
1069 PHP_FUNCTION(oci_new_descriptor)
1070 {
1071 	zval *z_connection;
1072 	php_oci_connection *connection;
1073 	php_oci_descriptor *descriptor;
1074 	long type = OCI_DTYPE_LOB;
1075 
1076 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &z_connection, &type) == FAILURE) {
1077 		return;
1078 	}
1079 
1080 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1081 
1082 	/* php_oci_lob_create() checks type */
1083 	descriptor = php_oci_lob_create(connection, type TSRMLS_CC);
1084 
1085 	if (!descriptor) {
1086 		RETURN_NULL();
1087 	}
1088 
1089 	object_init_ex(return_value, oci_lob_class_entry_ptr);
1090 	add_property_resource(return_value, "descriptor", descriptor->id);
1091 }
1092 /* }}} */
1093 
1094 /* {{{ proto bool oci_rollback(resource connection)
1095    Rollback the current context */
1096 PHP_FUNCTION(oci_rollback)
1097 {
1098 	zval *z_connection;
1099 	php_oci_connection *connection;
1100 
1101 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
1102 		return;
1103 	}
1104 
1105 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1106 
1107 	if (connection->descriptors) {
1108 		php_oci_connection_descriptors_free(connection TSRMLS_CC);
1109 	}
1110 
1111 	if (php_oci_connection_rollback(connection TSRMLS_CC)) {
1112 		RETURN_FALSE;
1113 	}
1114 	RETURN_TRUE;
1115 }
1116 /* }}} */
1117 
1118 /* {{{ proto bool oci_commit(resource connection)
1119    Commit the current context */
1120 PHP_FUNCTION(oci_commit)
1121 {
1122 	zval *z_connection;
1123 	php_oci_connection *connection;
1124 
1125 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
1126 		return;
1127 	}
1128 
1129 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1130 
1131 	if (connection->descriptors) {
1132 		php_oci_connection_descriptors_free(connection TSRMLS_CC);
1133 	}
1134 
1135 	if (php_oci_connection_commit(connection TSRMLS_CC)) {
1136 		RETURN_FALSE;
1137 	}
1138 	RETURN_TRUE;
1139 }
1140 /* }}} */
1141 
1142 /* {{{ proto string oci_field_name(resource stmt, mixed col)
1143    Tell the name of a column */
1144 PHP_FUNCTION(oci_field_name)
1145 {
1146 	php_oci_out_column *column;
1147 
1148 	if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
1149 		RETURN_STRINGL(column->name, column->name_len, 1);
1150 	}
1151 	RETURN_FALSE;
1152 }
1153 /* }}} */
1154 
1155 /* {{{ proto int oci_field_size(resource stmt, mixed col)
1156    Tell the maximum data size of a column */
1157 PHP_FUNCTION(oci_field_size)
1158 {
1159 	php_oci_out_column *column;
1160 
1161 	if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
1162 		/* Handle data type of LONG */
1163 		if (column->data_type == SQLT_LNG){
1164 			RETURN_LONG(column->storage_size4);
1165 		}
1166 		RETURN_LONG(column->data_size);
1167 	}
1168 	RETURN_FALSE;
1169 }
1170 /* }}} */
1171 
1172 /* {{{ proto int oci_field_scale(resource stmt, mixed col)
1173    Tell the scale of a column */
1174 PHP_FUNCTION(oci_field_scale)
1175 {
1176 	php_oci_out_column *column;
1177 
1178 	if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
1179 		RETURN_LONG(column->scale);
1180 	}
1181 	RETURN_FALSE;
1182 }
1183 /* }}} */
1184 
1185 /* {{{ proto int oci_field_precision(resource stmt, mixed col)
1186    Tell the precision of a column */
1187 PHP_FUNCTION(oci_field_precision)
1188 {
1189 	php_oci_out_column *column;
1190 
1191 	if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
1192 		RETURN_LONG(column->precision);
1193 	}
1194 	RETURN_FALSE;
1195 }
1196 /* }}} */
1197 
1198 /* {{{ proto mixed oci_field_type(resource stmt, mixed col)
1199    Tell the data type of a column */
1200 PHP_FUNCTION(oci_field_type)
1201 {
1202 	php_oci_out_column *column;
1203 
1204 	column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1205 
1206 	if (!column) {
1207 		RETURN_FALSE;
1208 	}
1209 
1210 	switch (column->data_type) {
1211 #ifdef SQLT_TIMESTAMP
1212 		case SQLT_TIMESTAMP:
1213 			RETVAL_STRING("TIMESTAMP",1);
1214 			break;
1215 #endif
1216 #ifdef SQLT_TIMESTAMP_TZ
1217 		case SQLT_TIMESTAMP_TZ:
1218 			RETVAL_STRING("TIMESTAMP WITH TIMEZONE",1);
1219 			break;
1220 #endif
1221 #ifdef SQLT_TIMESTAMP_LTZ
1222 		case SQLT_TIMESTAMP_LTZ:
1223 			RETVAL_STRING("TIMESTAMP WITH LOCAL TIMEZONE",1);
1224 			break;
1225 #endif
1226 #ifdef SQLT_INTERVAL_YM
1227 		case SQLT_INTERVAL_YM:
1228 			RETVAL_STRING("INTERVAL YEAR TO MONTH",1);
1229 			break;
1230 #endif
1231 #ifdef SQLT_INTERVAL_DS
1232 		case SQLT_INTERVAL_DS:
1233 			RETVAL_STRING("INTERVAL DAY TO SECOND",1);
1234 			break;
1235 #endif
1236 		case SQLT_DAT:
1237 			RETVAL_STRING("DATE",1);
1238 			break;
1239 		case SQLT_NUM:
1240 			RETVAL_STRING("NUMBER",1);
1241 			break;
1242 		case SQLT_LNG:
1243 			RETVAL_STRING("LONG",1);
1244 			break;
1245 		case SQLT_BIN:
1246 			RETVAL_STRING("RAW",1);
1247 			break;
1248 		case SQLT_LBI:
1249 			RETVAL_STRING("LONG RAW",1);
1250 			break;
1251 		case SQLT_CHR:
1252 			RETVAL_STRING("VARCHAR2",1);
1253 			break;
1254 		case SQLT_RSET:
1255 			RETVAL_STRING("REFCURSOR",1);
1256 			break;
1257 		case SQLT_AFC:
1258 			RETVAL_STRING("CHAR",1);
1259 			break;
1260 		case SQLT_BLOB:
1261 			RETVAL_STRING("BLOB",1);
1262 			break;
1263 		case SQLT_CLOB:
1264 			RETVAL_STRING("CLOB",1);
1265 			break;
1266 		case SQLT_BFILE:
1267 			RETVAL_STRING("BFILE",1);
1268 			break;
1269 		case SQLT_RDD:
1270 			RETVAL_STRING("ROWID",1);
1271 			break;
1272 		default:
1273 			RETVAL_LONG(column->data_type);
1274 	}
1275 }
1276 /* }}} */
1277 
1278 /* {{{ proto int oci_field_type_raw(resource stmt, mixed col)
1279    Tell the raw oracle data type of a column */
1280 PHP_FUNCTION(oci_field_type_raw)
1281 {
1282 	php_oci_out_column *column;
1283 
1284 	column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1285 	if (column) {
1286 		RETURN_LONG(column->data_type);
1287 	}
1288 	RETURN_FALSE;
1289 }
1290 /* }}} */
1291 
1292 /* {{{ proto bool oci_field_is_null(resource stmt, mixed col)
1293    Tell whether a field in the current row is NULL */
1294 PHP_FUNCTION(oci_field_is_null)
1295 {
1296 	php_oci_out_column *column;
1297 
1298 	if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
1299 		if (column->indicator == -1) {
1300 			RETURN_TRUE;
1301 		}
1302 	}
1303 	RETURN_FALSE;
1304 }
1305 /* }}} */
1306 
1307 /* {{{ proto void oci_internal_debug(int onoff)
1308    Toggle internal debugging output for the OCI extension */
1309 PHP_FUNCTION(oci_internal_debug)
1310 {
1311 	/* NOP in OCI8 2.0. Obsoleted by DTrace probes */
1312 }
1313 /* }}} */
1314 
1315 /* {{{ proto bool oci_execute(resource stmt [, int mode])
1316    Execute a parsed statement */
1317 PHP_FUNCTION(oci_execute)
1318 {
1319 	zval *z_statement;
1320 	php_oci_statement *statement;
1321 	long mode = OCI_COMMIT_ON_SUCCESS;
1322 
1323 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &z_statement, &mode) == FAILURE) {
1324 		return;
1325 	}
1326 
1327 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
1328 
1329 	if (php_oci_statement_execute(statement, mode TSRMLS_CC)) {
1330 		RETURN_FALSE;
1331 	}
1332 	RETURN_TRUE;
1333 }
1334 /* }}} */
1335 
1336 /* {{{ proto bool oci_cancel(resource stmt)
1337    Cancel reading from a cursor */
1338 PHP_FUNCTION(oci_cancel)
1339 {
1340 	zval *z_statement;
1341 	php_oci_statement *statement;
1342 
1343 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
1344 		return;
1345 	}
1346 
1347 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
1348 
1349 	if (php_oci_statement_cancel(statement TSRMLS_CC)) {
1350 		RETURN_FALSE;
1351 	}
1352 	RETURN_TRUE;
1353 }
1354 /* }}} */
1355 
1356 /* {{{ proto bool oci_fetch(resource stmt)
1357    Prepare a new row of data for reading */
1358 PHP_FUNCTION(oci_fetch)
1359 {
1360 	zval *z_statement;
1361 	php_oci_statement *statement;
1362 	ub4 nrows = 1; /* only one row at a time is supported for now */
1363 
1364 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
1365 		return;
1366 	}
1367 
1368 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
1369 
1370 	if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
1371 		RETURN_FALSE;
1372 	}
1373 	RETURN_TRUE;
1374 }
1375 /* }}} */
1376 
1377 /* {{{ proto int ocifetchinto(resource stmt, array &output [, int mode])
1378    Fetch a row of result data into an array */
1379 PHP_FUNCTION(ocifetchinto)
1380 {
1381 	php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_NUM, 3);
1382 }
1383 /* }}} */
1384 
1385 /* {{{ proto int oci_fetch_all(resource stmt, array &output[, int skip[, int maxrows[, int flags]]])
1386    Fetch all rows of result data into an array */
1387 PHP_FUNCTION(oci_fetch_all)
1388 {
1389 	zval *z_statement, *array, *element, *tmp;
1390 	php_oci_statement *statement;
1391 	php_oci_out_column **columns;
1392 	zval ***outarrs;
1393 	ub4 nrows = 1;
1394 	int i;
1395 	long rows = 0, flags = 0, skip = 0, maxrows = -1;
1396 
1397 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz/|lll", &z_statement, &array, &skip, &maxrows, &flags) == FAILURE) {
1398 		return;
1399 	}
1400 
1401 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
1402 
1403 	zval_dtor(array);
1404 	array_init(array);
1405 
1406 	while (skip--) {
1407 		if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
1408 			RETURN_LONG(0);
1409 		}
1410 	}
1411 
1412 	if (flags & PHP_OCI_FETCHSTATEMENT_BY_ROW) {
1413 		columns = safe_emalloc(statement->ncolumns, sizeof(php_oci_out_column *), 0);
1414 
1415 		for (i = 0; i < statement->ncolumns; i++) {
1416 			columns[ i ] = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
1417 		}
1418 
1419 		while (!php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
1420 			zval *row;
1421 
1422 			MAKE_STD_ZVAL(row);
1423 			array_init(row);
1424 
1425 			for (i = 0; i < statement->ncolumns; i++) {
1426 				MAKE_STD_ZVAL(element);
1427 				php_oci_column_to_zval(columns[ i ], element, PHP_OCI_RETURN_LOBS TSRMLS_CC);
1428 
1429 				if (flags & PHP_OCI_NUM) {
1430 					zend_hash_next_index_insert(Z_ARRVAL_P(row), &element, sizeof(zval*), NULL);
1431 				} else { /* default to ASSOC */
1432 					zend_symtable_update(Z_ARRVAL_P(row), columns[ i ]->name, columns[ i ]->name_len+1, &element, sizeof(zval*), NULL);
1433 				}
1434 			}
1435 
1436 			zend_hash_next_index_insert(Z_ARRVAL_P(array), &row, sizeof(zval*), NULL);
1437 			rows++;
1438 
1439 			if (maxrows != -1 && rows == maxrows) {
1440 				php_oci_statement_cancel(statement TSRMLS_CC);
1441 				break;
1442 			}
1443 		}
1444 		efree(columns);
1445 
1446 	} else { /* default to BY_COLUMN */
1447 		columns = safe_emalloc(statement->ncolumns, sizeof(php_oci_out_column *), 0);
1448 		outarrs = safe_emalloc(statement->ncolumns, sizeof(zval*), 0);
1449 
1450 		if (flags & PHP_OCI_NUM) {
1451 			for (i = 0; i < statement->ncolumns; i++) {
1452 				columns[ i ] = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
1453 
1454 				MAKE_STD_ZVAL(tmp);
1455 				array_init(tmp);
1456 				zend_hash_next_index_insert(Z_ARRVAL_P(array), &tmp, sizeof(zval*), (void **) &(outarrs[ i ]));
1457 			}
1458 		} else { /* default to ASSOC */
1459 			for (i = 0; i < statement->ncolumns; i++) {
1460 				columns[ i ] = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
1461 
1462 				MAKE_STD_ZVAL(tmp);
1463 				array_init(tmp);
1464 				zend_symtable_update(Z_ARRVAL_P(array), columns[ i ]->name, columns[ i ]->name_len+1, (void *) &tmp, sizeof(zval*), (void **) &(outarrs[ i ]));
1465 			}
1466 		}
1467 
1468 		while (!php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
1469 			for (i = 0; i < statement->ncolumns; i++) {
1470 				MAKE_STD_ZVAL(element);
1471 				php_oci_column_to_zval(columns[ i ], element, PHP_OCI_RETURN_LOBS TSRMLS_CC);
1472 				zend_hash_index_update((*(outarrs[ i ]))->value.ht, rows, (void *)&element, sizeof(zval*), NULL);
1473 			}
1474 
1475 			rows++;
1476 
1477 			if (maxrows != -1 && rows == maxrows) {
1478 				php_oci_statement_cancel(statement TSRMLS_CC);
1479 				break;
1480 			}
1481 		}
1482 
1483 		efree(columns);
1484 		efree(outarrs);
1485 	}
1486 
1487 	RETURN_LONG(rows);
1488 }
1489 /* }}} */
1490 
1491 /* {{{ proto object oci_fetch_object( resource stmt )
1492    Fetch a result row as an object */
1493 PHP_FUNCTION(oci_fetch_object)
1494 {
1495 	php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_ASSOC | PHP_OCI_RETURN_NULLS, 2);
1496 
1497 	if (Z_TYPE_P(return_value) == IS_ARRAY) {
1498 		object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
1499 	}
1500 }
1501 /* }}} */
1502 
1503 /* {{{ proto array oci_fetch_row( resource stmt )
1504    Fetch a result row as an enumerated array */
1505 PHP_FUNCTION(oci_fetch_row)
1506 {
1507 	php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_NUM | PHP_OCI_RETURN_NULLS, 1);
1508 }
1509 /* }}} */
1510 
1511 /* {{{ proto array oci_fetch_assoc( resource stmt )
1512    Fetch a result row as an associative array */
1513 PHP_FUNCTION(oci_fetch_assoc)
1514 {
1515 	php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_ASSOC | PHP_OCI_RETURN_NULLS, 1);
1516 }
1517 /* }}} */
1518 
1519 /* {{{ proto array oci_fetch_array( resource stmt [, int mode ])
1520    Fetch a result row as an array */
1521 PHP_FUNCTION(oci_fetch_array)
1522 {
1523 	php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_BOTH | PHP_OCI_RETURN_NULLS, 2);
1524 }
1525 /* }}} */
1526 
1527 /* {{{ proto bool oci_free_statement(resource stmt)
1528    Free all resources associated with a statement */
1529 PHP_FUNCTION(oci_free_statement)
1530 {
1531 	zval *z_statement;
1532 	php_oci_statement *statement;
1533 
1534 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
1535 		return;
1536 	}
1537 
1538 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
1539 
1540 	zend_list_delete(statement->id);
1541 	RETURN_TRUE;
1542 }
1543 /* }}} */
1544 
1545 /* {{{ proto bool oci_close(resource connection)
1546    Disconnect from database */
1547 PHP_FUNCTION(oci_close)
1548 {
1549 	/* oci_close for pconnect (if old_oci_close_semantics not set) would
1550 	 * release the connection back to the client-side session pool (and to the
1551 	 * server-side pool if Database Resident Connection Pool is being used).
1552 	 * Subsequent pconnects in the same script are not guaranteed to get the
1553 	 * same database session.
1554 	 */
1555 
1556 	zval *z_connection;
1557 	php_oci_connection *connection;
1558 
1559 	if (OCI_G(old_oci_close_semantics)) {
1560 		/* do nothing to keep BC */
1561 		return;
1562 	}
1563 
1564 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
1565 		return;
1566 	}
1567 
1568 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1569 	zend_list_delete(connection->id);
1570 
1571 	ZVAL_NULL(z_connection);
1572 
1573 	RETURN_TRUE;
1574 }
1575 /* }}} */
1576 
1577 /* {{{ proto resource oci_new_connect(string user, string pass [, string db, string charset [, int session_mode ]])
1578    Connect to an Oracle database and log on. Returns a new session. */
1579 PHP_FUNCTION(oci_new_connect)
1580 {
1581 	php_oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
1582 }
1583 /* }}} */
1584 
1585 /* {{{ proto resource oci_connect(string user, string pass [, string db [, string charset [, int session_mode ]])
1586    Connect to an Oracle database and log on. Returns a new session. */
1587 PHP_FUNCTION(oci_connect)
1588 {
1589 	php_oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
1590 }
1591 /* }}} */
1592 
1593 /* {{{ proto resource oci_pconnect(string user, string pass [, string db [, string charset [, int session_mode ]])
1594    Connect to an Oracle database using a persistent connection and log on. Returns a new session. */
1595 PHP_FUNCTION(oci_pconnect)
1596 {
1597 	php_oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
1598 }
1599 /* }}} */
1600 
1601 /* {{{ proto array oci_error([resource stmt|connection|global])
1602    Return the last error of stmt|connection|global. If no error happened returns false. */
1603 PHP_FUNCTION(oci_error)
1604 {
1605 	zval *arg = NULL;
1606 	php_oci_statement *statement;
1607 	php_oci_connection *connection;
1608 	text *errbuf;
1609 	sb4 errcode = 0;
1610 	dvoid *errh = NULL;
1611 	ub2 error_offset = 0;
1612 	text *sqltext = NULL;
1613 
1614 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg) == FAILURE) {
1615 		return;
1616 	}
1617 
1618 	if (ZEND_NUM_ARGS() > 0) {
1619 		statement = (php_oci_statement *) zend_fetch_resource(&arg TSRMLS_CC, -1, NULL, NULL, 1, le_statement);
1620 		if (statement) {
1621 			errh = statement->err;
1622 			errcode = statement->errcode;
1623 
1624 			if (php_oci_fetch_sqltext_offset(statement, &sqltext, &error_offset TSRMLS_CC)) {
1625 				RETURN_FALSE;
1626 			}
1627 			goto go_out;
1628 		}
1629 
1630 		connection = (php_oci_connection *) zend_fetch_resource(&arg TSRMLS_CC, -1, NULL, NULL, 1, le_connection);
1631 		if (connection) {
1632 			errh = connection->err;
1633 			errcode = connection->errcode;
1634 			goto go_out;
1635 		}
1636 
1637 		connection = (php_oci_connection *) zend_fetch_resource(&arg TSRMLS_CC, -1, NULL, NULL, 1, le_pconnection);
1638 		if (connection) {
1639 			errh = connection->err;
1640 			errcode = connection->errcode;
1641 			goto go_out;
1642 		}
1643 	} else {
1644 		errh = OCI_G(err);
1645 		errcode = OCI_G(errcode);
1646 	}
1647 
1648 go_out:
1649 	if (errcode == 0) { /* no error set in the handle */
1650 		RETURN_FALSE;
1651 	}
1652 
1653 	if (!errh) {
1654 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Oci_error: unable to find error handle");
1655 		RETURN_FALSE;
1656 	}
1657 
1658 	errcode = php_oci_fetch_errmsg(errh, &errbuf TSRMLS_CC);
1659 
1660 	if (errcode) {
1661 		array_init(return_value);
1662 		add_assoc_long(return_value, "code", errcode);
1663 		add_assoc_string(return_value, "message", (char*) errbuf, 0);
1664 		add_assoc_long(return_value, "offset", error_offset);
1665 		add_assoc_string(return_value, "sqltext", sqltext ? (char *) sqltext : "", 1);
1666 	} else {
1667 		RETURN_FALSE;
1668 	}
1669 }
1670 /* }}} */
1671 
1672 /* {{{ proto int oci_num_fields(resource stmt)
1673    Return the number of result columns in a statement */
1674 PHP_FUNCTION(oci_num_fields)
1675 {
1676 	zval *z_statement;
1677 	php_oci_statement *statement;
1678 
1679 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
1680 		return;
1681 	}
1682 
1683 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
1684 
1685 	RETURN_LONG(statement->ncolumns);
1686 }
1687 /* }}} */
1688 
1689 /* {{{ proto resource oci_parse(resource connection, string statement)
1690    Parse a SQL or PL/SQL statement and return a statement resource */
1691 PHP_FUNCTION(oci_parse)
1692 {
1693 	zval *z_connection;
1694 	php_oci_connection *connection;
1695 	php_oci_statement *statement;
1696 	char *query;
1697 	int query_len;
1698 
1699 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &query, &query_len) == FAILURE) {
1700 		return;
1701 	}
1702 
1703 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1704 
1705 	statement = php_oci_statement_create(connection, query, query_len TSRMLS_CC);
1706 
1707 	if (statement) {
1708 		RETURN_RESOURCE(statement->id);
1709 	}
1710 	RETURN_FALSE;
1711 }
1712 /* }}} */
1713 
1714 /* {{{ proto bool oci_set_prefetch(resource stmt, int prefetch_rows)
1715   Sets the number of rows to be prefetched on execute to prefetch_rows for stmt */
1716 PHP_FUNCTION(oci_set_prefetch)
1717 {
1718 	zval *z_statement;
1719 	php_oci_statement *statement;
1720 	long size;
1721 
1722 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &z_statement, &size) == FAILURE) {
1723 		return;
1724 	}
1725 
1726 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
1727 
1728 	if (size < 0) {
1729 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows to be prefetched has to be greater than or equal to 0");
1730 		return;
1731 	}
1732 
1733 	if (php_oci_statement_set_prefetch(statement, (ub4)size TSRMLS_CC)) {
1734 		RETURN_FALSE;
1735 	}
1736 	RETURN_TRUE;
1737 }
1738 /* }}} */
1739 
1740 /* {{{ proto bool oci_set_client_identifier(resource connection, string value)
1741   Sets the client identifier attribute on the connection */
1742 PHP_FUNCTION(oci_set_client_identifier)
1743 {
1744 	zval *z_connection;
1745 	php_oci_connection *connection;
1746 	char *client_id;
1747 	int client_id_len;
1748 	sword errstatus;
1749 
1750 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &client_id, &client_id_len) == FAILURE) {
1751 		return;
1752 	}
1753 
1754 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1755 
1756 	PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) client_id, (ub4) client_id_len, (ub4) OCI_ATTR_CLIENT_IDENTIFIER, connection->err));
1757 
1758 	if (errstatus != OCI_SUCCESS) {
1759 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
1760 		RETURN_FALSE;
1761 	}
1762 
1763 #ifdef HAVE_OCI8_DTRACE
1764 	/* The alternatives to storing client_id like done below are
1765 	   i) display it in a probe here in oci_set_client_identifier and
1766 	   let the user D script correlate the connection address probe
1767 	   argument and the client_id. This would likely require user D
1768 	   script variables, which would use kernel memory.
1769 	   ii) call OCIAttrGet for each probe definition that uses
1770 	   client_id. This would be slower than storing it.
1771 	*/
1772 
1773 	if (connection->client_id) {
1774 		pefree(connection->client_id, connection->is_persistent);
1775 	}
1776 
1777 	if (client_id) {
1778 		/* this long winded copy allows compatibility with older PHP versions */
1779 		connection->client_id = (char *)pemalloc(client_id_len+1, connection->is_persistent);
1780 		memcpy(connection->client_id, client_id, client_id_len);
1781 		connection->client_id[client_id_len] = '\0';
1782 	} else {
1783 		connection->client_id = NULL;
1784 	}
1785 #endif /* HAVE_OCI8_DTRACE */
1786 
1787 	RETURN_TRUE;
1788 }
1789 /* }}} */
1790 
1791 /* {{{ proto bool oci_set_edition(string value)
1792   Sets the edition attribute for all subsequent connections created */
1793 PHP_FUNCTION(oci_set_edition)
1794 {
1795 #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
1796 	char *edition;
1797 	int edition_len;
1798 
1799 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &edition, &edition_len) == FAILURE) {
1800 		return;
1801 	}
1802 
1803 	if (OCI_G(edition)) {
1804 		efree(OCI_G(edition));
1805 	}
1806 
1807 	if (edition) {
1808 		OCI_G(edition) = (char *)safe_emalloc(edition_len+1, sizeof(char), 0);
1809 		memcpy(OCI_G(edition), edition, edition_len);
1810 		OCI_G(edition)[edition_len] = '\0';
1811 	} else {
1812 		OCI_G(edition) = NULL;
1813 	}
1814 
1815 	RETURN_TRUE;
1816 #else
1817 	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type");
1818 	RETURN_FALSE;
1819 #endif
1820 }
1821 /* }}} */
1822 
1823 /* {{{ proto bool oci_set_module_name(resource connection, string value)
1824   Sets the module attribute on the connection for end-to-end tracing */
1825 PHP_FUNCTION(oci_set_module_name)
1826 {
1827 #if (OCI_MAJOR_VERSION >= 10)
1828 	zval *z_connection;
1829 	php_oci_connection *connection;
1830 	char *module;
1831 	int module_len;
1832 	sword errstatus;
1833 
1834 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &module, &module_len) == FAILURE) {
1835 		return;
1836 	}
1837 
1838 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1839 
1840 	PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) module, (ub4) module_len, (ub4) OCI_ATTR_MODULE, connection->err));
1841 
1842 	if (errstatus != OCI_SUCCESS) {
1843 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
1844 		RETURN_FALSE;
1845 	}
1846 
1847 	RETURN_TRUE;
1848 #else
1849 	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type");
1850 	RETURN_FALSE;
1851 #endif
1852 }
1853 /* }}} */
1854 
1855 /* {{{ proto bool oci_set_action(resource connection, string value)
1856   Sets the action attribute on the connection for end-to-end tracing */
1857 PHP_FUNCTION(oci_set_action)
1858 {
1859 #if (OCI_MAJOR_VERSION >= 10)
1860 	zval *z_connection;
1861 	php_oci_connection *connection;
1862 	char *action;
1863 	int action_len;
1864 	sword errstatus;
1865 
1866 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &action, &action_len) == FAILURE) {
1867 		return;
1868 	}
1869 
1870 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1871 
1872 	PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) action, (ub4) action_len, (ub4) OCI_ATTR_ACTION, connection->err));
1873 
1874 	if (errstatus != OCI_SUCCESS) {
1875 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
1876 		RETURN_FALSE;
1877 	}
1878 
1879 	RETURN_TRUE;
1880 #else
1881 	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type");
1882 	RETURN_FALSE;
1883 #endif
1884 }
1885 /* }}} */
1886 
1887 /* {{{ proto bool oci_set_client_info(resource connection, string value)
1888   Sets the client info attribute on the connection  for end-to-end tracing */
1889 PHP_FUNCTION(oci_set_client_info)
1890 {
1891 #if (OCI_MAJOR_VERSION >= 10)
1892 	zval *z_connection;
1893 	php_oci_connection *connection;
1894 	char *client_info;
1895 	int client_info_len;
1896 	sword errstatus;
1897 
1898 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &client_info, &client_info_len) == FAILURE) {
1899 		return;
1900 	}
1901 
1902 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1903 
1904 	PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) client_info, (ub4) client_info_len, (ub4) OCI_ATTR_CLIENT_INFO, connection->err));
1905 
1906 	if (errstatus != OCI_SUCCESS) {
1907 		connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
1908 		RETURN_FALSE;
1909 	}
1910 
1911 	RETURN_TRUE;
1912 #else
1913 	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type");
1914 	RETURN_FALSE;
1915 #endif
1916 }
1917 /* }}} */
1918 
1919 #ifdef WAITIING_ORACLE_BUG_16695981_FIX
1920 /* {{{ proto bool oci_set_db_operation(resource connection, string value)
1921    Sets the "DB operation" on the connection for Oracle end-to-end tracing */
1922 PHP_FUNCTION(oci_set_db_operation)
1923 {
1924 #if (OCI_MAJOR_VERSION > 11)
1925 	zval *z_connection;
1926 	php_oci_connection *connection;
1927 	char *dbop_name;
1928 	int dbop_name_len;
1929 
1930 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &dbop_name, &dbop_name_len) == FAILURE) {
1931 		return;
1932 	}
1933 
1934 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1935 
1936 	PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) dbop_name, (ub4) dbop_name_len, (ub4) OCI_ATTR_DBOP, OCI_G(err)));
1937 
1938 	if (OCI_G(errcode) != OCI_SUCCESS) {
1939 		php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
1940 		RETURN_FALSE;
1941 	}
1942 	RETURN_TRUE;
1943 #else
1944 	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type");
1945 	RETURN_FALSE;
1946 #endif
1947 }
1948 /* }}} */
1949 #endif /* WAITIING_ORACLE_BUG_16695981_FIX */
1950 
1951 /* {{{ proto bool oci_password_change(resource connection, string username, string old_password, string new_password)
1952   Changes the password of an account */
1953 PHP_FUNCTION(oci_password_change)
1954 {
1955 	zval *z_connection;
1956 	char *user, *pass_old, *pass_new, *dbname;
1957 	int user_len, pass_old_len, pass_new_len, dbname_len;
1958 	php_oci_connection *connection;
1959 
1960 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5)
1961 	/* Safe mode has been removed in PHP 5.4 */
1962 	if (PG(safe_mode)) {
1963 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "is disabled in Safe Mode");
1964 		RETURN_FALSE;
1965 	}
1966 #endif
1967 
1968 	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &z_connection, &user, &user_len, &pass_old, &pass_old_len, &pass_new, &pass_new_len) == SUCCESS) {
1969 		PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1970 
1971 		if (!user_len) {
1972 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "username cannot be empty");
1973 			RETURN_FALSE;
1974 		}
1975 		if (!pass_old_len) {
1976 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "old password cannot be empty");
1977 			RETURN_FALSE;
1978 		}
1979 		if (!pass_new_len) {
1980 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "new password cannot be empty");
1981 			RETURN_FALSE;
1982 		}
1983 
1984 		if (php_oci_password_change(connection, user, user_len, pass_old, pass_old_len, pass_new, pass_new_len TSRMLS_CC)) {
1985 			RETURN_FALSE;
1986 		}
1987 		RETURN_TRUE;
1988 	} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ssss", &dbname, &dbname_len, &user, &user_len, &pass_old, &pass_old_len, &pass_new, &pass_new_len) == SUCCESS) {
1989 
1990 		if (!user_len) {
1991 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "username cannot be empty");
1992 			RETURN_FALSE;
1993 		}
1994 		if (!pass_old_len) {
1995 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "old password cannot be empty");
1996 			RETURN_FALSE;
1997 		}
1998 		if (!pass_new_len) {
1999 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "new password cannot be empty");
2000 			RETURN_FALSE;
2001 		}
2002 
2003 		connection = php_oci_do_connect_ex(user, user_len, pass_old, pass_old_len, pass_new, pass_new_len, dbname, dbname_len, NULL, OCI_DEFAULT, 0, 0 TSRMLS_CC);
2004 		if (!connection) {
2005 			RETURN_FALSE;
2006 		}
2007 		RETURN_RESOURCE(connection->id);
2008 	}
2009 	WRONG_PARAM_COUNT;
2010 }
2011 /* }}} */
2012 
2013 /* {{{ proto resource oci_new_cursor(resource connection)
2014    Return a new cursor (Statement-Handle) - use this to bind ref-cursors! */
2015 PHP_FUNCTION(oci_new_cursor)
2016 {
2017 	zval *z_connection;
2018 	php_oci_connection *connection;
2019 	php_oci_statement *statement;
2020 
2021 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
2022 		return;
2023 	}
2024 
2025 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
2026 
2027 	statement = php_oci_statement_create(connection, NULL, 0 TSRMLS_CC);
2028 
2029 	if (statement) {
2030 		RETURN_RESOURCE(statement->id);
2031 	}
2032 	RETURN_FALSE;
2033 }
2034 /* }}} */
2035 
2036 /* {{{ proto string oci_result(resource stmt, mixed column)
2037    Return a single column of result data */
2038 PHP_FUNCTION(oci_result)
2039 {
2040 	php_oci_out_column *column;
2041 
2042 	column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2043 	if(column) {
2044 		php_oci_column_to_zval(column, return_value, 0 TSRMLS_CC);
2045 	}
2046 	else {
2047 		RETURN_FALSE;
2048 	}
2049 }
2050 /* }}} */
2051 
2052 /* {{{ proto string oci_client_version()
2053    Return a string containing runtime client library version information */
2054 PHP_FUNCTION(oci_client_version)
2055 {
2056 	char *version = NULL;
2057 
2058 	php_oci_client_get_version(&version TSRMLS_CC);
2059 	RETURN_STRING(version, 0);
2060 }
2061 /* }}} */
2062 
2063 /* {{{ proto string oci_server_version(resource connection)
2064    Return a string containing server version information */
2065 PHP_FUNCTION(oci_server_version)
2066 {
2067 	zval *z_connection;
2068 	php_oci_connection *connection;
2069 	char *version = NULL;
2070 
2071 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
2072 		return;
2073 	}
2074 
2075 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
2076 
2077 	if (php_oci_server_get_version(connection, &version TSRMLS_CC)) {
2078 		RETURN_FALSE;
2079 	}
2080 
2081 	RETURN_STRING(version, 0);
2082 }
2083 /* }}} */
2084 
2085 /* {{{ proto string oci_statement_type(resource stmt)
2086    Return the query type of an OCI statement */
2087 PHP_FUNCTION(oci_statement_type)
2088 {
2089 	zval *z_statement;
2090 	php_oci_statement *statement;
2091 	ub2 type;
2092 
2093 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
2094 		return;
2095 	}
2096 
2097 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
2098 
2099 	if (php_oci_statement_get_type(statement, &type TSRMLS_CC)) {
2100 		RETURN_FALSE;
2101 	}
2102 
2103 	switch (type) {
2104 		case OCI_STMT_SELECT:
2105 			RETVAL_STRING("SELECT",1);
2106 			break;
2107 		case OCI_STMT_UPDATE:
2108 			RETVAL_STRING("UPDATE",1);
2109 			break;
2110 		case OCI_STMT_DELETE:
2111 			RETVAL_STRING("DELETE",1);
2112 			break;
2113 		case OCI_STMT_INSERT:
2114 			RETVAL_STRING("INSERT",1);
2115 			break;
2116 		case OCI_STMT_CREATE:
2117 			RETVAL_STRING("CREATE",1);
2118 			break;
2119 		case OCI_STMT_DROP:
2120 			RETVAL_STRING("DROP",1);
2121 			break;
2122 		case OCI_STMT_ALTER:
2123 			RETVAL_STRING("ALTER",1);
2124 			break;
2125 		case OCI_STMT_BEGIN:
2126 			RETVAL_STRING("BEGIN",1);
2127 			break;
2128 		case OCI_STMT_DECLARE:
2129 			RETVAL_STRING("DECLARE",1);
2130 			break;
2131 		case OCI_STMT_CALL:
2132 			RETVAL_STRING("CALL",1);
2133 			break;
2134 		default:
2135 			RETVAL_STRING("UNKNOWN",1);
2136 	}
2137 }
2138 /* }}} */
2139 
2140 /* {{{ proto int oci_num_rows(resource stmt)
2141    Return the row count of an OCI statement */
2142 PHP_FUNCTION(oci_num_rows)
2143 {
2144 	zval *z_statement;
2145 	php_oci_statement *statement;
2146 	ub4 rowcount;
2147 
2148 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
2149 		return;
2150 	}
2151 
2152 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
2153 
2154 	if (php_oci_statement_get_numrows(statement, &rowcount TSRMLS_CC)) {
2155 		RETURN_FALSE;
2156 	}
2157 	RETURN_LONG(rowcount);
2158 }
2159 /* }}} */
2160 
2161 /* {{{ proto bool oci_free_collection()
2162    Deletes collection object*/
2163 PHP_FUNCTION(oci_free_collection)
2164 {
2165 	zval **tmp, *z_collection = getThis();
2166 	php_oci_collection *collection;
2167 
2168 	if (!getThis()) {
2169 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_collection, oci_coll_class_entry_ptr) == FAILURE) {
2170 			return;
2171 		}
2172 	}
2173 
2174 	if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
2175 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
2176 		RETURN_FALSE;
2177 	}
2178 
2179 	PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
2180 
2181 	zend_list_delete(collection->id);
2182 	RETURN_TRUE;
2183 }
2184 /* }}} */
2185 
2186 /* {{{ proto bool oci_collection_append(string value)
2187    Append an object to the collection */
2188 PHP_FUNCTION(oci_collection_append)
2189 {
2190 	zval **tmp, *z_collection = getThis();
2191 	php_oci_collection *collection;
2192 	char *value;
2193 	int value_len;
2194 
2195 	if (getThis()) {
2196 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) == FAILURE) {
2197 			return;
2198 		}
2199 	}
2200 	else {
2201 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &z_collection, oci_coll_class_entry_ptr, &value, &value_len) == FAILURE) {
2202 			return;
2203 		}
2204 	}
2205 
2206 	if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
2207 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
2208 		RETURN_FALSE;
2209 	}
2210 
2211 	PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
2212 
2213 	if (php_oci_collection_append(collection, value, value_len TSRMLS_CC)) {
2214 		RETURN_FALSE;
2215 	}
2216 	RETURN_TRUE;
2217 }
2218 /* }}} */
2219 
2220 /* {{{ proto string oci_collection_element_get(int ndx)
2221    Retrieve the value at collection index ndx */
2222 PHP_FUNCTION(oci_collection_element_get)
2223 {
2224 	zval **tmp, *z_collection = getThis();
2225 	php_oci_collection *collection;
2226 	long element_index;
2227 	zval *value;
2228 
2229 	if (getThis()) {
2230 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &element_index) == FAILURE) {
2231 			return;
2232 		}
2233 	}
2234 	else {
2235 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &z_collection, oci_coll_class_entry_ptr, &element_index) == FAILURE) {
2236 			return;
2237 		}
2238 	}
2239 
2240 	if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
2241 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
2242 		RETURN_FALSE;
2243 	}
2244 
2245 	PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
2246 
2247 	if (php_oci_collection_element_get(collection, element_index, &value TSRMLS_CC)) {
2248 		RETURN_FALSE;
2249 	}
2250 
2251 	*return_value = *value;
2252 	zval_copy_ctor(return_value);
2253 	zval_ptr_dtor(&value);
2254 }
2255 /* }}} */
2256 
2257 /* {{{ proto bool oci_collection_assign(object from)
2258    Assign a collection from another existing collection */
2259 PHP_FUNCTION(oci_collection_assign)
2260 {
2261 	zval **tmp_dest, **tmp_from, *z_collection_dest = getThis(), *z_collection_from;
2262 	php_oci_collection *collection_dest, *collection_from;
2263 
2264 	if (getThis()) {
2265 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_collection_from, oci_coll_class_entry_ptr) == FAILURE) {
2266 			return;
2267 		}
2268 	}
2269 	else {
2270 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &z_collection_dest, oci_coll_class_entry_ptr, &z_collection_from, oci_coll_class_entry_ptr) == FAILURE) {
2271 			return;
2272 		}
2273 	}
2274 
2275 	if (zend_hash_find(Z_OBJPROP_P(z_collection_dest), "collection", sizeof("collection"), (void **)&tmp_dest) == FAILURE) {
2276 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property. The first argument should be valid collection object");
2277 		RETURN_FALSE;
2278 	}
2279 
2280 	if (zend_hash_find(Z_OBJPROP_P(z_collection_from), "collection", sizeof("collection"), (void **)&tmp_from) == FAILURE) {
2281 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property. The second argument should be valid collection object");
2282 		RETURN_FALSE;
2283 	}
2284 
2285 	PHP_OCI_ZVAL_TO_COLLECTION(*tmp_dest, collection_dest);
2286 	PHP_OCI_ZVAL_TO_COLLECTION(*tmp_from, collection_from);
2287 
2288 	if (php_oci_collection_assign(collection_dest, collection_from TSRMLS_CC)) {
2289 		RETURN_FALSE;
2290 	}
2291 	RETURN_TRUE;
2292 }
2293 /* }}} */
2294 
2295 /* {{{ proto bool oci_collection_element_assign(int index, string val)
2296    Assign element val to collection at index ndx */
2297 PHP_FUNCTION(oci_collection_element_assign)
2298 {
2299 	zval **tmp, *z_collection = getThis();
2300 	php_oci_collection *collection;
2301 	int value_len;
2302 	long element_index;
2303 	char *value;
2304 
2305 	if (getThis()) {
2306 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &element_index, &value, &value_len) == FAILURE) {
2307 			return;
2308 		}
2309 	}
2310 	else {
2311 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ols", &z_collection, oci_coll_class_entry_ptr, &element_index, &value, &value_len) == FAILURE) {
2312 			return;
2313 		}
2314 	}
2315 
2316 	if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
2317 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
2318 		RETURN_FALSE;
2319 	}
2320 
2321 	PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
2322 
2323 	if (php_oci_collection_element_set(collection, element_index, value, value_len TSRMLS_CC)) {
2324 		RETURN_FALSE;
2325 	}
2326 	RETURN_TRUE;
2327 }
2328 /* }}} */
2329 
2330 /* {{{ proto int oci_collection_size()
2331    Return the size of a collection */
2332 PHP_FUNCTION(oci_collection_size)
2333 {
2334 	zval **tmp, *z_collection = getThis();
2335 	php_oci_collection *collection;
2336 	sb4 size = 0;
2337 
2338 	if (!getThis()) {
2339 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_collection, oci_coll_class_entry_ptr) == FAILURE) {
2340 			return;
2341 		}
2342 	}
2343 
2344 	if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
2345 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
2346 		RETURN_FALSE;
2347 	}
2348 
2349 	PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
2350 
2351 	if (php_oci_collection_size(collection, &size TSRMLS_CC)) {
2352 		RETURN_FALSE;
2353 	}
2354 	RETURN_LONG(size);
2355 }
2356 /* }}} */
2357 
2358 /* {{{ proto int oci_collection_max()
2359    Return the max value of a collection. For a varray this is the maximum length of the array */
2360 PHP_FUNCTION(oci_collection_max)
2361 {
2362 	zval **tmp, *z_collection = getThis();
2363 	php_oci_collection *collection;
2364 	long max;
2365 
2366 	if (!getThis()) {
2367 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_collection, oci_coll_class_entry_ptr) == FAILURE) {
2368 			return;
2369 		}
2370 	}
2371 
2372 	if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
2373 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
2374 		RETURN_FALSE;
2375 	}
2376 
2377 	PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
2378 
2379 	if (php_oci_collection_max(collection, &max TSRMLS_CC)) {
2380 		RETURN_FALSE;
2381 	}
2382 	RETURN_LONG(max);
2383 }
2384 /* }}} */
2385 
2386 /* {{{ proto bool oci_collection_trim(int num)
2387    Trim num elements from the end of a collection */
2388 PHP_FUNCTION(oci_collection_trim)
2389 {
2390 	zval **tmp, *z_collection = getThis();
2391 	php_oci_collection *collection;
2392 	long trim_size;
2393 
2394 	if (getThis()) {
2395 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &trim_size) == FAILURE) {
2396 			return;
2397 		}
2398 	}
2399 	else {
2400 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &z_collection, oci_coll_class_entry_ptr, &trim_size) == FAILURE) {
2401 			return;
2402 		}
2403 	}
2404 
2405 	if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
2406 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
2407 		RETURN_FALSE;
2408 	}
2409 
2410 	PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
2411 
2412 	if (php_oci_collection_trim(collection, trim_size TSRMLS_CC)) {
2413 		RETURN_FALSE;
2414 	}
2415 	RETURN_TRUE;
2416 }
2417 /* }}} */
2418 
2419 /* {{{ proto object oci_new_collection(resource connection, string tdo [, string schema])
2420    Initialize a new collection */
2421 PHP_FUNCTION(oci_new_collection)
2422 {
2423 	zval *z_connection;
2424 	php_oci_connection *connection;
2425 	php_oci_collection *collection;
2426 	char *tdo, *schema = NULL;
2427 	int tdo_len, schema_len = 0;
2428 
2429 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|s", &z_connection, &tdo, &tdo_len, &schema, &schema_len) == FAILURE) {
2430 		return;
2431 	}
2432 
2433 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
2434 
2435 	if ( (collection = php_oci_collection_create(connection, tdo, tdo_len, schema, schema_len TSRMLS_CC)) ) {
2436 		object_init_ex(return_value, oci_coll_class_entry_ptr);
2437 		add_property_resource(return_value, "collection", collection->id);
2438 	}
2439 	else {
2440 		RETURN_FALSE;
2441 	}
2442 }
2443 /* }}} */
2444 
2445 /* {{{ proto bool oci_get_implicit(resource stmt)
2446    Get the next statement resource from an Oracle 12c PL/SQL Implicit Result Set */
2447 PHP_FUNCTION(oci_get_implicit_resultset)
2448 {
2449 	zval *z_statement;
2450 	php_oci_statement *statement;
2451 	php_oci_statement *imp_statement;
2452 
2453 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
2454 		return;
2455 	}
2456 
2457 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
2458 
2459 	imp_statement = php_oci_get_implicit_resultset(statement TSRMLS_CC);
2460 
2461 	if (imp_statement) {
2462 		if (php_oci_statement_execute(imp_statement, (ub4)OCI_DEFAULT TSRMLS_CC))
2463 			RETURN_FALSE;
2464 		RETURN_RESOURCE(imp_statement->id);
2465 	}
2466 	RETURN_FALSE;
2467 }
2468 
2469 /* }}} */
2470 
2471 #endif /* HAVE_OCI8 */
2472 
2473 /*
2474  * Local variables:
2475  * tab-width: 4
2476  * c-basic-offset: 4
2477  * End:
2478  * vim600: noet sw=4 ts=4 fdm=marker
2479  * vim<600: noet sw=4 ts=4
2480  */
2481