xref: /PHP-8.0/ext/oci8/oci8_interface.c (revision 26aa54e0)
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    | http://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 	zend_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 	zend_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 	zend_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 	zend_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 	zend_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, 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 client identifier attribute on the connection */
PHP_FUNCTION(oci_set_client_identifier)1637 PHP_FUNCTION(oci_set_client_identifier)
1638 {
1639 	zval *z_connection;
1640 	php_oci_connection *connection;
1641 	char *client_id;
1642 	size_t client_id_len;
1643 	sword errstatus;
1644 
1645 	ZEND_PARSE_PARAMETERS_START(2, 2)
1646 		Z_PARAM_RESOURCE(z_connection)
1647 		Z_PARAM_STRING(client_id, client_id_len)
1648 	ZEND_PARSE_PARAMETERS_END();
1649 
1650 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1651 
1652 	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));
1653 
1654 	if (errstatus != OCI_SUCCESS) {
1655 		connection->errcode = php_oci_error(connection->err, errstatus);
1656 		RETURN_FALSE;
1657 	}
1658 
1659 #ifdef HAVE_OCI8_DTRACE
1660 	/* The alternatives to storing client_id like done below are
1661 	   i) display it in a probe here in oci_set_client_identifier and
1662 	   let the user D script correlate the connection address probe
1663 	   argument and the client_id. This would likely require user D
1664 	   script variables, which would use kernel memory.
1665 	   ii) call OCIAttrGet for each probe definition that uses
1666 	   client_id. This would be slower than storing it.
1667 	*/
1668 
1669 	if (connection->client_id) {
1670 		pefree(connection->client_id, connection->is_persistent);
1671 	}
1672 
1673 	if (client_id) {
1674 		/* this long winded copy allows compatibility with older PHP versions */
1675 		connection->client_id = (char *)pemalloc(client_id_len+1, connection->is_persistent);
1676 		memcpy(connection->client_id, client_id, client_id_len);
1677 		connection->client_id[client_id_len] = '\0';
1678 	} else {
1679 		connection->client_id = NULL;
1680 	}
1681 #endif /* HAVE_OCI8_DTRACE */
1682 
1683 	RETURN_TRUE;
1684 }
1685 /* }}} */
1686 
1687 /* {{{ Sets the edition attribute for all subsequent connections created */
PHP_FUNCTION(oci_set_edition)1688 PHP_FUNCTION(oci_set_edition)
1689 {
1690 	char *edition;
1691 	size_t edition_len;
1692 
1693 	ZEND_PARSE_PARAMETERS_START(1, 1)
1694 		Z_PARAM_STRING(edition, edition_len)
1695 	ZEND_PARSE_PARAMETERS_END();
1696 
1697 #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
1698 	if (OCI_G(edition)) {
1699 		efree(OCI_G(edition));
1700 	}
1701 
1702 	if (edition) {
1703 		OCI_G(edition) = (char *)safe_emalloc(edition_len+1, sizeof(char), 0);
1704 		memcpy(OCI_G(edition), edition, edition_len);
1705 		OCI_G(edition)[edition_len] = '\0';
1706 	} else {
1707 		OCI_G(edition) = NULL;
1708 	}
1709 
1710 	RETURN_TRUE;
1711 #else
1712 	php_error_docref(NULL, E_NOTICE, "Unsupported attribute type");
1713 	RETURN_FALSE;
1714 #endif
1715 }
1716 /* }}} */
1717 
1718 /* {{{ Sets the module attribute on the connection for end-to-end tracing */
PHP_FUNCTION(oci_set_module_name)1719 PHP_FUNCTION(oci_set_module_name)
1720 {
1721 	zval *z_connection;
1722 	char *module;
1723 	size_t module_len;
1724 
1725 	ZEND_PARSE_PARAMETERS_START(2, 2)
1726 		Z_PARAM_RESOURCE(z_connection)
1727 		Z_PARAM_STRING(module, module_len)
1728 	ZEND_PARSE_PARAMETERS_END();
1729 
1730 #if (OCI_MAJOR_VERSION >= 10)
1731 
1732 	php_oci_connection *connection;
1733 	sword errstatus;
1734 
1735 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1736 
1737 	PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) module, (ub4) module_len, (ub4) OCI_ATTR_MODULE, connection->err));
1738 
1739 	if (errstatus != OCI_SUCCESS) {
1740 		connection->errcode = php_oci_error(connection->err, errstatus);
1741 		RETURN_FALSE;
1742 	}
1743 
1744 	RETURN_TRUE;
1745 #else
1746 	php_error_docref(NULL, E_NOTICE, "Unsupported attribute type");
1747 	RETURN_FALSE;
1748 #endif
1749 }
1750 /* }}} */
1751 
1752 /* {{{ Sets the action attribute on the connection for end-to-end tracing */
PHP_FUNCTION(oci_set_action)1753 PHP_FUNCTION(oci_set_action)
1754 {
1755 	zval *z_connection;
1756 	char *action;
1757 	size_t action_len;
1758 
1759 	ZEND_PARSE_PARAMETERS_START(2, 2)
1760 		Z_PARAM_RESOURCE(z_connection)
1761 		Z_PARAM_STRING(action, action_len)
1762 	ZEND_PARSE_PARAMETERS_END();
1763 
1764 #if (OCI_MAJOR_VERSION >= 10)
1765 
1766 	php_oci_connection *connection;
1767 	sword errstatus;
1768 
1769 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1770 
1771 	PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) action, (ub4) action_len, (ub4) OCI_ATTR_ACTION, connection->err));
1772 
1773 	if (errstatus != OCI_SUCCESS) {
1774 		connection->errcode = php_oci_error(connection->err, errstatus);
1775 		RETURN_FALSE;
1776 	}
1777 
1778 	RETURN_TRUE;
1779 #else
1780 	php_error_docref(NULL, E_NOTICE, "Unsupported attribute type");
1781 	RETURN_FALSE;
1782 #endif
1783 }
1784 /* }}} */
1785 
1786 /* {{{ Sets the client info attribute on the connection  for end-to-end tracing */
PHP_FUNCTION(oci_set_client_info)1787 PHP_FUNCTION(oci_set_client_info)
1788 {
1789 	zval *z_connection;
1790 	char *client_info;
1791 	size_t client_info_len;
1792 
1793 	ZEND_PARSE_PARAMETERS_START(2, 2)
1794 		Z_PARAM_RESOURCE(z_connection)
1795 		Z_PARAM_STRING(client_info, client_info_len)
1796 	ZEND_PARSE_PARAMETERS_END();
1797 
1798 #if (OCI_MAJOR_VERSION >= 10)
1799 
1800 	php_oci_connection *connection;
1801 	sword errstatus;
1802 
1803 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1804 
1805 	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));
1806 
1807 	if (errstatus != OCI_SUCCESS) {
1808 		connection->errcode = php_oci_error(connection->err, errstatus);
1809 		RETURN_FALSE;
1810 	}
1811 
1812 	RETURN_TRUE;
1813 #else
1814 	php_error_docref(NULL, E_NOTICE, "Unsupported attribute type");
1815 	RETURN_FALSE;
1816 #endif
1817 }
1818 /* }}} */
1819 
1820 /* {{{ Sets the "DB operation" on the connection for Oracle end-to-end tracing.
1821    For history, see Oracle bug 16695981 */
PHP_FUNCTION(oci_set_db_operation)1822 PHP_FUNCTION(oci_set_db_operation)
1823 {
1824 	zval *z_connection;
1825 	char *dbop_name;
1826 	size_t dbop_name_len;
1827 
1828 	ZEND_PARSE_PARAMETERS_START(2, 2)
1829 		Z_PARAM_RESOURCE(z_connection)
1830 		Z_PARAM_STRING(dbop_name, dbop_name_len)
1831 	ZEND_PARSE_PARAMETERS_END();
1832 
1833 #if (OCI_MAJOR_VERSION > 11)
1834 	php_oci_connection *connection;
1835 
1836 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1837 
1838 	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)));
1839 
1840 	if (OCI_G(errcode) != OCI_SUCCESS) {
1841 		php_oci_error(OCI_G(err), OCI_G(errcode));
1842 		RETURN_FALSE;
1843 	}
1844 	RETURN_TRUE;
1845 #else
1846 	php_error_docref(NULL, E_NOTICE, "Unsupported attribute type");
1847 	RETURN_FALSE;
1848 #endif
1849 }
1850 /* }}} */
1851 
1852 /* {{{ */
PHP_FUNCTION(oci_set_call_timeout)1853 PHP_FUNCTION(oci_set_call_timeout)
1854 {
1855 	zval *z_connection;
1856 	zend_long call_timeout;  // milliseconds
1857 
1858 	ZEND_PARSE_PARAMETERS_START(2, 2)
1859 		Z_PARAM_RESOURCE(z_connection)
1860 		Z_PARAM_LONG(call_timeout)
1861 	ZEND_PARSE_PARAMETERS_END();
1862 
1863 #if (OCI_MAJOR_VERSION >= 18)
1864 	php_oci_connection *connection;
1865 
1866 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1867 
1868 	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)));
1869 
1870 	if (OCI_G(errcode) != OCI_SUCCESS) {
1871 		php_oci_error(OCI_G(err), OCI_G(errcode));
1872 		RETURN_FALSE;
1873 	}
1874 	RETURN_TRUE;
1875 #else
1876 	php_error_docref(NULL, E_NOTICE, "Unsupported with this version of Oracle Client");
1877 	RETURN_FALSE;
1878 #endif
1879 }
1880 /* }}} */
1881 
1882 /* {{{ Changes the password of an account */
PHP_FUNCTION(oci_password_change)1883 PHP_FUNCTION(oci_password_change)
1884 {
1885 	zval *z_connection;
1886 	char *user, *pass_old, *pass_new, *dbname;
1887 	size_t user_len, pass_old_len, pass_new_len, dbname_len;
1888 	php_oci_connection *connection;
1889 
1890 	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) {
1891 		PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1892 
1893 		if (!user_len) {
1894 			zend_argument_value_error(2, "cannot be empty");
1895 			RETURN_THROWS();
1896 		}
1897 		if (!pass_old_len) {
1898 			zend_argument_value_error(3, "cannot be empty");
1899 			RETURN_THROWS();
1900 		}
1901 		if (!pass_new_len) {
1902 			zend_argument_value_error(4, "cannot be empty");
1903 			RETURN_THROWS();
1904 		}
1905 
1906 		if (php_oci_password_change(connection, user, (int) user_len, pass_old, (int) pass_old_len, pass_new, (int) pass_new_len)) {
1907 			RETURN_FALSE;
1908 		}
1909 		RETURN_TRUE;
1910 	} 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) {
1911 
1912 		if (!user_len) {
1913 			zend_argument_value_error(2, "cannot be empty");
1914 			RETURN_THROWS();
1915 		}
1916 		if (!pass_old_len) {
1917 			zend_argument_value_error(3, "cannot be empty");
1918 			RETURN_THROWS();
1919 		}
1920 		if (!pass_new_len) {
1921 			zend_argument_value_error(4, "cannot be empty");
1922 			RETURN_THROWS();
1923 		}
1924 
1925 		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);
1926 		if (!connection) {
1927 			RETURN_FALSE;
1928 		}
1929 		RETURN_RES(connection->id);
1930 	}
1931 	WRONG_PARAM_COUNT;
1932 }
1933 /* }}} */
1934 
1935 /* {{{ Return a new cursor (Statement-Handle) - use this to bind ref-cursors! */
PHP_FUNCTION(oci_new_cursor)1936 PHP_FUNCTION(oci_new_cursor)
1937 {
1938 	zval *z_connection;
1939 	php_oci_connection *connection;
1940 	php_oci_statement *statement;
1941 
1942 	ZEND_PARSE_PARAMETERS_START(1, 1)
1943 		Z_PARAM_RESOURCE(z_connection)
1944 	ZEND_PARSE_PARAMETERS_END();
1945 
1946 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1947 
1948 	statement = php_oci_statement_create(connection, NULL, 0);
1949 
1950 	if (statement) {
1951 		RETURN_RES(statement->id);
1952 	}
1953 	RETURN_FALSE;
1954 }
1955 /* }}} */
1956 
1957 /* {{{ Return a single column of result data */
PHP_FUNCTION(oci_result)1958 PHP_FUNCTION(oci_result)
1959 {
1960 	php_oci_out_column *column;
1961 
1962 	column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1963 	if(column) {
1964 		php_oci_column_to_zval(column, return_value, 0);
1965 	}
1966 	else {
1967 		RETURN_FALSE;
1968 	}
1969 }
1970 /* }}} */
1971 
1972 /* {{{ Return a string containing runtime client library version information */
PHP_FUNCTION(oci_client_version)1973 PHP_FUNCTION(oci_client_version)
1974 {
1975 	char version[256];
1976 	ZEND_PARSE_PARAMETERS_NONE();
1977 
1978 	php_oci_client_get_version(version, sizeof(version));
1979 	RETURN_STRING(version);
1980 }
1981 /* }}} */
1982 
1983 /* {{{ Return a string containing server version information */
PHP_FUNCTION(oci_server_version)1984 PHP_FUNCTION(oci_server_version)
1985 {
1986 	zval *z_connection;
1987 	php_oci_connection *connection;
1988 	char version[256];
1989 	zend_string *ret;
1990 
1991 	ZEND_PARSE_PARAMETERS_START(1, 1)
1992 		Z_PARAM_RESOURCE(z_connection)
1993 	ZEND_PARSE_PARAMETERS_END();
1994 
1995 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
1996 
1997 	if (php_oci_server_get_version(connection, version, sizeof(version))) {
1998 		RETURN_FALSE;
1999 	}
2000 
2001 	ret = zend_string_init(version, strlen(version), 0);
2002 	RETURN_STR(ret);
2003 }
2004 /* }}} */
2005 
2006 /* {{{ Return the query type of an OCI statement */
PHP_FUNCTION(oci_statement_type)2007 PHP_FUNCTION(oci_statement_type)
2008 {
2009 	zval *z_statement;
2010 	php_oci_statement *statement;
2011 	ub2 type;
2012 
2013 	ZEND_PARSE_PARAMETERS_START(1, 1)
2014 		Z_PARAM_RESOURCE(z_statement)
2015 	ZEND_PARSE_PARAMETERS_END();
2016 
2017 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
2018 
2019 	if (php_oci_statement_get_type(statement, &type)) {
2020 		RETURN_FALSE;
2021 	}
2022 
2023 	switch (type) {
2024 		case OCI_STMT_SELECT:
2025 			RETVAL_STRING("SELECT");
2026 			break;
2027 		case OCI_STMT_UPDATE:
2028 			RETVAL_STRING("UPDATE");
2029 			break;
2030 		case OCI_STMT_DELETE:
2031 			RETVAL_STRING("DELETE");
2032 			break;
2033 		case OCI_STMT_INSERT:
2034 			RETVAL_STRING("INSERT");
2035 			break;
2036 		case OCI_STMT_CREATE:
2037 			RETVAL_STRING("CREATE");
2038 			break;
2039 		case OCI_STMT_DROP:
2040 			RETVAL_STRING("DROP");
2041 			break;
2042 		case OCI_STMT_ALTER:
2043 			RETVAL_STRING("ALTER");
2044 			break;
2045 		case OCI_STMT_BEGIN:
2046 			RETVAL_STRING("BEGIN");
2047 			break;
2048 		case OCI_STMT_DECLARE:
2049 			RETVAL_STRING("DECLARE");
2050 			break;
2051 		case OCI_STMT_CALL:
2052 			RETVAL_STRING("CALL");
2053 			break;
2054 		default:
2055 			RETVAL_STRING("UNKNOWN");
2056 	}
2057 }
2058 /* }}} */
2059 
2060 /* {{{ Return the row count of an OCI statement */
PHP_FUNCTION(oci_num_rows)2061 PHP_FUNCTION(oci_num_rows)
2062 {
2063 	zval *z_statement;
2064 	php_oci_statement *statement;
2065 	ub4 rowcount;
2066 
2067 	ZEND_PARSE_PARAMETERS_START(1, 1)
2068 		Z_PARAM_RESOURCE(z_statement)
2069 	ZEND_PARSE_PARAMETERS_END();
2070 
2071 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
2072 
2073 	if (php_oci_statement_get_numrows(statement, &rowcount)) {
2074 		RETURN_FALSE;
2075 	}
2076 	RETURN_LONG(rowcount);
2077 }
2078 /* }}} */
2079 
2080 /* {{{ Deletes collection object*/
PHP_FUNCTION(oci_free_collection)2081 PHP_FUNCTION(oci_free_collection)
2082 {
2083 	zval *tmp, *z_collection;
2084 	php_oci_collection *collection;
2085 
2086 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &z_collection, oci_coll_class_entry_ptr) == FAILURE) {
2087 		RETURN_THROWS();
2088 	}
2089 
2090 	if ((tmp = zend_hash_str_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection")-1)) == NULL) {
2091 		php_error_docref(NULL, E_WARNING, "Unable to find collection property");
2092 		RETURN_FALSE;
2093 	}
2094 
2095 	PHP_OCI_ZVAL_TO_COLLECTION(tmp, collection);
2096 
2097 	zend_list_close(collection->id);
2098 	RETURN_TRUE;
2099 }
2100 /* }}} */
2101 
2102 /* {{{ Append an object to the collection */
PHP_FUNCTION(oci_collection_append)2103 PHP_FUNCTION(oci_collection_append)
2104 {
2105 	zval *tmp, *z_collection;
2106 	php_oci_collection *collection;
2107 	char *value;
2108 	size_t value_len;
2109 
2110 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &z_collection, oci_coll_class_entry_ptr, &value, &value_len) == FAILURE) {
2111 		RETURN_THROWS();
2112 	}
2113 
2114 	if ((tmp = zend_hash_str_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection")-1)) == NULL) {
2115 		php_error_docref(NULL, E_WARNING, "Unable to find collection property");
2116 		RETURN_FALSE;
2117 	}
2118 
2119 	PHP_OCI_ZVAL_TO_COLLECTION(tmp, collection);
2120 
2121 	if (php_oci_collection_append(collection, value, (int) value_len)) {
2122 		RETURN_FALSE;
2123 	}
2124 	RETURN_TRUE;
2125 }
2126 /* }}} */
2127 
2128 /* {{{ Retrieve the value at collection index ndx */
PHP_FUNCTION(oci_collection_element_get)2129 PHP_FUNCTION(oci_collection_element_get)
2130 {
2131 	zval *tmp, *z_collection;
2132 	php_oci_collection *collection;
2133 	zend_long element_index;
2134 
2135 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &z_collection, oci_coll_class_entry_ptr, &element_index) == FAILURE) {
2136 		RETURN_THROWS();
2137 	}
2138 
2139 	if ((tmp = zend_hash_str_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection")-1)) == NULL) {
2140 		php_error_docref(NULL, E_WARNING, "Unable to find collection property");
2141 		RETURN_FALSE;
2142 	}
2143 
2144 	PHP_OCI_ZVAL_TO_COLLECTION(tmp, collection);
2145 
2146 	if (php_oci_collection_element_get(collection, element_index, return_value)) {
2147 		RETURN_FALSE;
2148 	}
2149 }
2150 /* }}} */
2151 
2152 /* {{{ Assign a collection from another existing collection */
PHP_FUNCTION(oci_collection_assign)2153 PHP_FUNCTION(oci_collection_assign)
2154 {
2155 	zval *tmp_dest, *tmp_from, *z_collection_dest, *z_collection_from;
2156 	php_oci_collection *collection_dest, *collection_from;
2157 
2158 	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) {
2159 		RETURN_THROWS();
2160 	}
2161 
2162 	if ((tmp_dest = zend_hash_str_find(Z_OBJPROP_P(z_collection_dest), "collection", sizeof("collection")-1)) == NULL) {
2163 		php_error_docref(NULL, E_WARNING, "Unable to find collection property. The first argument should be valid collection object");
2164 		RETURN_FALSE;
2165 	}
2166 
2167 	if ((tmp_from = zend_hash_str_find(Z_OBJPROP_P(z_collection_from), "collection", sizeof("collection")-1)) == NULL) {
2168 		php_error_docref(NULL, E_WARNING, "Unable to find collection property. The second argument should be valid collection object");
2169 		RETURN_FALSE;
2170 	}
2171 
2172 	PHP_OCI_ZVAL_TO_COLLECTION(tmp_dest, collection_dest);
2173 	PHP_OCI_ZVAL_TO_COLLECTION(tmp_from, collection_from);
2174 
2175 	if (php_oci_collection_assign(collection_dest, collection_from)) {
2176 		RETURN_FALSE;
2177 	}
2178 	RETURN_TRUE;
2179 }
2180 /* }}} */
2181 
2182 /* {{{ Assign element val to collection at index ndx */
PHP_FUNCTION(oci_collection_element_assign)2183 PHP_FUNCTION(oci_collection_element_assign)
2184 {
2185 	zval *tmp, *z_collection;
2186 	php_oci_collection *collection;
2187 	size_t value_len;
2188 	zend_long element_index;
2189 	char *value;
2190 
2191 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &z_collection, oci_coll_class_entry_ptr, &element_index, &value, &value_len) == FAILURE) {
2192 		RETURN_THROWS();
2193 	}
2194 
2195 	if ((tmp = zend_hash_str_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection")-1)) == NULL) {
2196 		php_error_docref(NULL, E_WARNING, "Unable to find collection property");
2197 		RETURN_FALSE;
2198 	}
2199 
2200 	PHP_OCI_ZVAL_TO_COLLECTION(tmp, collection);
2201 
2202 	if (php_oci_collection_element_set(collection, element_index, value, (int) value_len)) {
2203 		RETURN_FALSE;
2204 	}
2205 	RETURN_TRUE;
2206 }
2207 /* }}} */
2208 
2209 /* {{{ Return the size of a collection */
PHP_FUNCTION(oci_collection_size)2210 PHP_FUNCTION(oci_collection_size)
2211 {
2212 	zval *tmp, *z_collection;
2213 	php_oci_collection *collection;
2214 	sb4 size = 0;
2215 
2216 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &z_collection, oci_coll_class_entry_ptr) == FAILURE) {
2217 		RETURN_THROWS();
2218 	}
2219 
2220 	if ((tmp = zend_hash_str_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection")-1)) == NULL) {
2221 		php_error_docref(NULL, E_WARNING, "Unable to find collection property");
2222 		RETURN_FALSE;
2223 	}
2224 
2225 	PHP_OCI_ZVAL_TO_COLLECTION(tmp, collection);
2226 
2227 	if (php_oci_collection_size(collection, &size)) {
2228 		RETURN_FALSE;
2229 	}
2230 	RETURN_LONG(size);
2231 }
2232 /* }}} */
2233 
2234 /* {{{ Return the max value of a collection. For a varray this is the maximum length of the array */
PHP_FUNCTION(oci_collection_max)2235 PHP_FUNCTION(oci_collection_max)
2236 {
2237 	zval *tmp, *z_collection;
2238 	php_oci_collection *collection;
2239 	zend_long max;
2240 
2241 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &z_collection, oci_coll_class_entry_ptr) == FAILURE) {
2242 		RETURN_THROWS();
2243 	}
2244 
2245 	if ((tmp = zend_hash_str_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection")-1)) == NULL) {
2246 		php_error_docref(NULL, E_WARNING, "Unable to find collection property");
2247 		RETURN_FALSE;
2248 	}
2249 
2250 	PHP_OCI_ZVAL_TO_COLLECTION(tmp, collection);
2251 
2252 	if (php_oci_collection_max(collection, &max)) {
2253 		RETURN_FALSE;
2254 	}
2255 	RETURN_LONG(max);
2256 }
2257 /* }}} */
2258 
2259 /* {{{ Trim num elements from the end of a collection */
PHP_FUNCTION(oci_collection_trim)2260 PHP_FUNCTION(oci_collection_trim)
2261 {
2262 	zval *tmp, *z_collection;
2263 	php_oci_collection *collection;
2264 	zend_long trim_size;
2265 
2266 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &z_collection, oci_coll_class_entry_ptr, &trim_size) == FAILURE) {
2267 		RETURN_THROWS();
2268 	}
2269 
2270 	if ((tmp = zend_hash_str_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection")-1)) == NULL) {
2271 		php_error_docref(NULL, E_WARNING, "Unable to find collection property");
2272 		RETURN_FALSE;
2273 	}
2274 
2275 	PHP_OCI_ZVAL_TO_COLLECTION(tmp, collection);
2276 
2277 	if (php_oci_collection_trim(collection, trim_size)) {
2278 		RETURN_FALSE;
2279 	}
2280 	RETURN_TRUE;
2281 }
2282 /* }}} */
2283 
2284 /* {{{ Initialize a new collection */
PHP_FUNCTION(oci_new_collection)2285 PHP_FUNCTION(oci_new_collection)
2286 {
2287 	zval *z_connection;
2288 	php_oci_connection *connection;
2289 	php_oci_collection *collection;
2290 	char *tdo, *schema = NULL;
2291 	size_t tdo_len, schema_len = 0;
2292 
2293 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|s!", &z_connection, &tdo, &tdo_len, &schema, &schema_len) == FAILURE) {
2294 		RETURN_THROWS();
2295 	}
2296 
2297 	PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
2298 
2299 	if ( (collection = php_oci_collection_create(connection, tdo, (int) tdo_len, schema, (int) schema_len)) ) {
2300 		object_init_ex(return_value, oci_coll_class_entry_ptr);
2301 		add_property_resource(return_value, "collection", collection->id);
2302 	}
2303 	else {
2304 		RETURN_FALSE;
2305 	}
2306 }
2307 /* }}} */
2308 
2309 /* {{{ Get the next statement resource from an Oracle 12c PL/SQL Implicit Result Set */
PHP_FUNCTION(oci_get_implicit_resultset)2310 PHP_FUNCTION(oci_get_implicit_resultset)
2311 {
2312 	zval *z_statement;
2313 	php_oci_statement *statement;
2314 	php_oci_statement *imp_statement;
2315 
2316 	ZEND_PARSE_PARAMETERS_START(1, 1)
2317 		Z_PARAM_RESOURCE(z_statement)
2318 	ZEND_PARSE_PARAMETERS_END();
2319 
2320 	PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
2321 
2322 	imp_statement = php_oci_get_implicit_resultset(statement);
2323 
2324 	if (imp_statement) {
2325 		if (php_oci_statement_execute(imp_statement, (ub4)OCI_DEFAULT))
2326 			RETURN_FALSE;
2327 		RETURN_RES(imp_statement->id);
2328 	}
2329 	RETURN_FALSE;
2330 }
2331 
2332 /* }}} */
2333 
2334 #endif /* HAVE_OCI8 */
2335