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