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