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