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