2
+----------------------------------------------------------------------+
4
+----------------------------------------------------------------------+
5
| Copyright (c) 1997-2004 The PHP Group |
6
+----------------------------------------------------------------------+
7
| This source file is subject to version 3.0 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_0.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
| Maxim Maletsky <maxim@maxim.cx> |
19
| Collection support by Andy Sautins <asautins@veripost.net> |
20
| Temporary LOB support by David Benson <dbenson@mancala.com> |
21
| ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
22
+----------------------------------------------------------------------+
25
/* $Id: oci8.c,v 1.257.2.8 2005/06/13 09:31:03 tony2001 Exp $ */
30
* especialliy important for things like oci_ping
35
* - Change return-value for OCIFetch*() (1-row read, 0-Normal end, false-error)
36
* - Error mode (print or shut up?)
38
* - Character sets for NCLOBS
39
* - split the module into an upper (php-callable) and lower (c-callable) layer!
41
* - clean up and documentation
42
* - make OCIInternalDebug accept a mask of flags....
43
* - have one ocifree() call.
44
* - make it possible to have persistent statements?
46
* - change all the lob stuff to work without classes (optional)!
47
* - make sure that the callbacks terminate the strings with \0
48
* - cleanup the ociexecute semantics for refcursors
49
* - make $lob->savefile use O_BINARY
50
* - line 2728: ub4 length = -1; needs fixing
51
* - delay OCIInitialize() as far as we can.
52
* - add PHP Array <-> OCICollection conversion
53
* - add Collection iterator object for INDEX BY tables
54
* - make auto-rollback only happen if we have an outstanding transaction
55
* - implement ocidisconnect
56
* - add OCI9-specific functions and separate them from OCI8 with ifdefs
59
/* {{{ includes & stuff */
66
#include "ext/standard/info.h"
73
/* True globals, only used by thread safe functions */
74
static TsHashTable *persistent_servers;
75
static TsHashTable *persistent_sessions;
77
static long num_persistent = 0;
78
static long num_links = 0;
80
/* True globals, no need for thread safety */
84
#ifdef PHP_OCI8_HAVE_COLLECTIONS
88
static int le_session;
89
static zend_class_entry *oci_lob_class_entry_ptr;
90
#ifdef PHP_OCI8_HAVE_COLLECTIONS
91
static zend_class_entry *oci_coll_class_entry_ptr;
95
#define SQLT_BFILEE 114
98
#define SQLT_CFILEE 115
101
#define SAFE_STRING(s) ((s)?(s):"")
106
#define mutex_alloc(mutex) mutex = tsrm_mutex_alloc()
107
#define mutex_free(mutex) tsrm_mutex_free(mutex)
108
#define mutex_lock(mutex) tsrm_mutex_lock(mutex)
109
#define mutex_unlock(mutex) tsrm_mutex_unlock(mutex)
110
#define thread_id() tsrm_thread_id()
112
#define mutex_alloc(mutex)
113
#define mutex_free(mutex)
114
#define mutex_lock(mutex)
115
#define mutex_unlock(mutex)
116
#define thread_id() 1
119
/* dirty marcos to make sure we _never_ call oracle-functions recursivly
121
* i'm well aware that we should _never_ call exit directly - this core is for
122
* pure testing and commented out - as you can see;-)
123
* thies@thieso.net 20010723
126
#define CALL_OCI(call) \
128
if (OCI(in_call)) { \
129
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI8 Recursive call!\n"); \
138
#define CALL_OCI_RETURN(retcode,call) \
140
if (OCI(in_call)) { \
142
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI8 Recursive call!\n"); \
158
/* {{{ thread safety stuff */
163
PHP_OCI_API php_oci_globals oci_globals;
167
/* {{{ dynamically loadable module stuff */
169
#ifdef COMPILE_DL_OCI8
170
ZEND_GET_MODULE(oci8)
172
# include "zend_arg_defs.c"
174
#endif /* COMPILE_DL */
177
/* {{{ startup/shutdown/info/internal function prototypes */
179
PHP_MINIT_FUNCTION(oci);
180
PHP_RINIT_FUNCTION(oci);
181
PHP_MSHUTDOWN_FUNCTION(oci);
182
PHP_RSHUTDOWN_FUNCTION(oci);
183
PHP_MINFO_FUNCTION(oci);
185
static ub4 oci_handle_error(oci_connection *connection, ub4 errcode);
186
static ub4 oci_error(OCIError *err_p, char *what, sword status);
187
static int oci_ping(oci_server *server);
188
static void oci_debug(const char *format, ...);
190
static void _oci_conn_list_dtor(oci_connection *connection TSRMLS_DC);
191
static void _oci_stmt_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
192
static void _oci_descriptor_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
193
#ifdef PHP_OCI8_HAVE_COLLECTIONS
194
static void _oci_coll_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
196
static void _oci_server_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
197
static void _oci_session_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
198
static void php_oci_free_conn_list(zend_rsrc_list_entry *rsrc TSRMLS_DC);
200
static void _oci_column_hash_dtor(void *data);
201
static void _oci_define_hash_dtor(void *data);
202
static void _oci_bind_hash_dtor(void *data);
203
static void _oci_desc_flush_hash_dtor(void *data);
205
static oci_connection *oci_get_conn(zval ** TSRMLS_DC);
206
static oci_statement *oci_get_stmt(zval ** TSRMLS_DC);
207
static oci_descriptor *oci_get_desc(int TSRMLS_DC);
208
#ifdef PHP_OCI8_HAVE_COLLECTIONS
209
/* Questionable name. Very close to oci_get_col */
210
static oci_collection *oci_get_coll(int TSRMLS_DC);
212
static oci_out_column *oci_get_col(oci_statement *, int, zval **);
214
static int _oci_make_zval(zval *, oci_statement *, oci_out_column *, char *, int mode TSRMLS_DC);
215
static oci_statement *oci_parse(oci_connection *, char *, int);
216
static int oci_execute(oci_statement *, char *, ub4 mode);
217
static int oci_fetch(oci_statement *, ub4, char * TSRMLS_DC);
218
static int oci_lobgetlen(oci_connection *, oci_descriptor *, ub4 *length);
219
static int oci_loadlob(oci_connection *, oci_descriptor *, char **, ub4 *length);
220
static int oci_readlob(oci_connection *, oci_descriptor *, char **, ub4 *len);
221
static int oci_setprefetch(oci_statement *statement, int size);
223
static void oci_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent,int exclusive);
225
static oci_server *_oci_open_server(char *dbname,int persistent);
226
static void _oci_close_server(oci_server *server);
228
static oci_session *_oci_open_session(oci_server* server,char *username,char *password,int persistent,int exclusive, char *charset);
229
static void _oci_close_session(oci_session *session);
231
static sb4 oci_bind_in_callback(dvoid *, OCIBind *, ub4, ub4, dvoid **, ub4 *, ub1 *, dvoid **);
232
static sb4 oci_bind_out_callback(dvoid *, OCIBind *, ub4, ub4, dvoid **, ub4 **, ub1 *, dvoid **, ub2 **);
235
static sb4 oci_failover_callback(dvoid *svchp,dvoid* envhp,dvoid *fo_ctx,ub4 fo_type, ub4 fo_event);
238
static int oci_lob_flush(oci_descriptor *, int flush_flag TSRMLS_DC);
242
/* {{{ extension macros
244
#define OCI_GET_STMT(statement,value) \
245
statement = oci_get_stmt(value TSRMLS_CC); \
246
if (statement == NULL) { \
250
#define OCI_GET_CONN(connection,value) \
251
connection = oci_get_conn(value TSRMLS_CC); \
252
if (connection == NULL) { \
256
#define OCI_GET_DESC(descriptor,index) \
257
descriptor = oci_get_desc(index TSRMLS_CC); \
258
if (descriptor == NULL) { \
262
#ifdef PHP_OCI8_HAVE_COLLECTIONS
263
#define OCI_GET_COLL(collection,index) \
264
collection = oci_get_coll(index TSRMLS_CC); \
265
if (collection == NULL) { \
270
#define IS_LOB_INTERNAL(lob) \
271
if (lob->type != OCI_DTYPE_LOB) { \
272
switch (lob->type) { \
273
case OCI_DTYPE_FILE: \
274
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "internal LOB was expected, FILE locator is given"); \
276
case OCI_DTYPE_ROWID: \
277
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "internal LOB was expected, ROWID locator is given"); \
280
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "internal LOB was expected, locator of unknown type is given"); \
287
/* {{{ extension function prototypes
289
PHP_FUNCTION(oci_bind_by_name);
290
PHP_FUNCTION(oci_define_by_name);
291
PHP_FUNCTION(oci_field_is_null);
292
PHP_FUNCTION(oci_field_name);
293
PHP_FUNCTION(oci_field_size);
294
PHP_FUNCTION(oci_field_scale);
295
PHP_FUNCTION(oci_field_precision);
296
PHP_FUNCTION(oci_field_type);
297
PHP_FUNCTION(oci_field_type_raw);
298
PHP_FUNCTION(oci_execute);
299
PHP_FUNCTION(oci_fetch);
300
PHP_FUNCTION(oci_cancel);
301
PHP_FUNCTION(ocifetchinto);
302
PHP_FUNCTION(oci_fetch_object);
303
PHP_FUNCTION(oci_fetch_row);
304
PHP_FUNCTION(oci_fetch_assoc);
305
PHP_FUNCTION(oci_fetch_array);
306
PHP_FUNCTION(ocifetchstatement);
307
PHP_FUNCTION(oci_fetch_all);
308
PHP_FUNCTION(oci_free_statement);
309
PHP_FUNCTION(oci_internal_debug);
310
PHP_FUNCTION(oci_close);
311
PHP_FUNCTION(oci_connect);
312
PHP_FUNCTION(oci_new_connect);
313
PHP_FUNCTION(oci_pconnect);
314
PHP_FUNCTION(oci_error);
315
PHP_FUNCTION(oci_free_descriptor);
316
PHP_FUNCTION(oci_commit);
317
PHP_FUNCTION(oci_rollback);
318
PHP_FUNCTION(oci_new_descriptor);
319
PHP_FUNCTION(oci_num_fields);
320
PHP_FUNCTION(oci_parse);
321
PHP_FUNCTION(oci_new_cursor);
322
PHP_FUNCTION(oci_result);
323
PHP_FUNCTION(oci_server_version);
324
PHP_FUNCTION(oci_statement_type);
325
PHP_FUNCTION(oci_num_rows);
326
PHP_FUNCTION(oci_set_prefetch);
327
PHP_FUNCTION(oci_password_change);
328
PHP_FUNCTION(oci_lob_save);
329
PHP_FUNCTION(oci_lob_import);
330
PHP_FUNCTION(oci_lob_export);
331
PHP_FUNCTION(oci_lob_load);
332
PHP_FUNCTION(oci_lob_tell);
333
PHP_FUNCTION(oci_lob_write);
334
PHP_FUNCTION(oci_lob_append);
335
PHP_FUNCTION(oci_lob_copy);
336
PHP_FUNCTION(oci_lob_truncate);
337
PHP_FUNCTION(oci_lob_erase);
338
PHP_FUNCTION(oci_lob_flush);
339
PHP_FUNCTION(ocisetbufferinglob);
340
PHP_FUNCTION(ocigetbufferinglob);
341
PHP_FUNCTION(oci_lob_is_equal);
342
PHP_FUNCTION(oci_lob_rewind);
343
PHP_FUNCTION(oci_lob_read);
344
PHP_FUNCTION(oci_lob_eof);
345
PHP_FUNCTION(oci_lob_seek);
346
PHP_FUNCTION(oci_lob_size);
347
#ifdef HAVE_OCI8_TEMP_LOB
348
PHP_FUNCTION(oci_lob_write_temporary);
349
PHP_FUNCTION(oci_lob_close);
351
#ifdef PHP_OCI8_HAVE_COLLECTIONS
352
PHP_FUNCTION(oci_new_collection);
353
PHP_FUNCTION(oci_free_collection);
354
PHP_FUNCTION(oci_collection_append);
355
PHP_FUNCTION(oci_collection_element_get);
356
PHP_FUNCTION(oci_collection_element_assign);
357
PHP_FUNCTION(oci_collection_assign);
358
PHP_FUNCTION(oci_collection_size);
359
PHP_FUNCTION(oci_collection_max);
360
PHP_FUNCTION(oci_collection_trim);
364
/* {{{ extension definition structures
366
#define OCI_ASSOC 1<<0
368
#define OCI_BOTH (OCI_ASSOC|OCI_NUM)
370
#define OCI_RETURN_NULLS 1<<2
371
#define OCI_RETURN_LOBS 1<<3
373
#define OCI_FETCHSTATEMENT_BY_COLUMN 1<<4
374
#define OCI_FETCHSTATEMENT_BY_ROW 1<<5
375
#define OCI_FETCHSTATEMENT_BY (OCI_FETCHSTATEMENT_BY_COLUMN | OCI_FETCHSTATEMENT_BY_ROW)
377
static zend_function_entry php_oci_functions[] = {
378
PHP_FE(oci_define_by_name, third_arg_force_ref)
379
PHP_FE(oci_bind_by_name, third_arg_force_ref)
380
PHP_FE(oci_field_is_null, NULL)
381
PHP_FE(oci_field_name, NULL)
382
PHP_FE(oci_field_size, NULL)
383
PHP_FE(oci_field_scale, NULL)
384
PHP_FE(oci_field_precision, NULL)
385
PHP_FE(oci_field_type, NULL)
386
PHP_FE(oci_field_type_raw, NULL)
387
PHP_FE(oci_execute, NULL)
388
PHP_FE(oci_cancel, NULL)
389
PHP_FE(oci_fetch, NULL)
390
PHP_FE(oci_fetch_object, NULL)
391
PHP_FE(oci_fetch_row, NULL)
392
PHP_FE(oci_fetch_assoc, NULL)
393
PHP_FE(oci_fetch_array, NULL)
394
PHP_FE(ocifetchinto, second_arg_force_ref)
395
PHP_FE(oci_fetch_all, second_arg_force_ref)
396
PHP_FE(oci_free_statement, NULL)
397
PHP_FE(oci_internal_debug, NULL)
398
PHP_FE(oci_num_fields, NULL)
399
PHP_FE(oci_parse, NULL)
400
PHP_FE(oci_new_cursor, NULL)
401
PHP_FE(oci_result, NULL)
402
PHP_FE(oci_server_version, NULL)
403
PHP_FE(oci_statement_type, NULL)
404
PHP_FE(oci_num_rows, NULL)
405
PHP_FE(oci_close, NULL)
406
PHP_FE(oci_connect, NULL)
407
PHP_FE(oci_new_connect, NULL)
408
PHP_FE(oci_pconnect, NULL)
409
PHP_FE(oci_error, NULL)
410
PHP_FE(oci_free_descriptor, NULL)
411
PHP_FE(oci_lob_save, NULL)
412
PHP_FE(oci_lob_import, NULL)
413
PHP_FE(oci_lob_size, NULL)
414
PHP_FE(oci_lob_load, NULL)
415
PHP_FE(oci_lob_read, NULL)
416
PHP_FE(oci_lob_eof, NULL)
417
PHP_FE(oci_lob_tell, NULL)
418
PHP_FE(oci_lob_truncate, NULL)
419
PHP_FE(oci_lob_erase, NULL)
420
PHP_FE(oci_lob_flush, NULL)
421
PHP_FE(ocisetbufferinglob, NULL)
422
PHP_FE(ocigetbufferinglob, NULL)
423
PHP_FE(oci_lob_is_equal, NULL)
424
PHP_FE(oci_lob_rewind, NULL)
425
PHP_FE(oci_lob_write, NULL)
426
PHP_FE(oci_lob_append, NULL)
427
PHP_FE(oci_lob_copy, NULL)
428
PHP_FE(oci_lob_export, NULL)
429
PHP_FE(oci_commit, NULL)
430
PHP_FE(oci_rollback, NULL)
431
PHP_FE(oci_new_descriptor, NULL)
432
PHP_FE(oci_set_prefetch, NULL)
433
PHP_FE(oci_password_change, NULL)
434
#ifdef PHP_OCI8_HAVE_COLLECTIONS
435
PHP_FE(oci_free_collection, NULL)
436
PHP_FE(oci_collection_append, NULL)
437
PHP_FE(oci_collection_element_get, NULL)
438
PHP_FE(oci_collection_element_assign, NULL)
439
PHP_FE(oci_collection_assign, NULL)
440
PHP_FE(oci_collection_size, NULL)
441
PHP_FE(oci_collection_max, NULL)
442
PHP_FE(oci_collection_trim, NULL)
443
PHP_FE(oci_new_collection, NULL)
446
PHP_FALIAS(oci_free_cursor, oci_free_statement, NULL)
447
PHP_FALIAS(ocifreecursor, oci_free_statement, NULL)
448
PHP_FALIAS(ocibindbyname, oci_bind_by_name, third_arg_force_ref)
449
PHP_FALIAS(ocidefinebyname, oci_define_by_name, third_arg_force_ref)
450
PHP_FALIAS(ocicolumnisnull, oci_field_is_null, NULL)
451
PHP_FALIAS(ocicolumnname, oci_field_name, NULL)
452
PHP_FALIAS(ocicolumnsize, oci_field_size, NULL)
453
PHP_FALIAS(ocicolumnscale, oci_field_scale, NULL)
454
PHP_FALIAS(ocicolumnprecision, oci_field_precision, NULL)
455
PHP_FALIAS(ocicolumntype, oci_field_type, NULL)
456
PHP_FALIAS(ocicolumntyperaw, oci_field_type_raw, NULL)
457
PHP_FALIAS(ociexecute, oci_execute, NULL)
458
PHP_FALIAS(ocicancel, oci_cancel, NULL)
459
PHP_FALIAS(ocifetch, oci_fetch, NULL)
460
PHP_FALIAS(ocifetchstatement, oci_fetch_all, second_arg_force_ref)
461
PHP_FALIAS(ocifreestatement, oci_free_statement, NULL)
462
PHP_FALIAS(ociinternaldebug, oci_internal_debug, NULL)
463
PHP_FALIAS(ocinumcols, oci_num_fields, NULL)
464
PHP_FALIAS(ociparse, oci_parse, NULL)
465
PHP_FALIAS(ocinewcursor, oci_new_cursor, NULL)
466
PHP_FALIAS(ociresult, oci_result, NULL)
467
PHP_FALIAS(ociserverversion, oci_server_version, NULL)
468
PHP_FALIAS(ocistatementtype, oci_statement_type, NULL)
469
PHP_FALIAS(ocirowcount, oci_num_rows, NULL)
470
PHP_FALIAS(ocilogoff, oci_close, NULL)
471
PHP_FALIAS(ocilogon, oci_connect, NULL)
472
PHP_FALIAS(ocinlogon, oci_new_connect, NULL)
473
PHP_FALIAS(ociplogon, oci_pconnect, NULL)
474
PHP_FALIAS(ocierror, oci_error, NULL)
475
PHP_FALIAS(ocifreedesc, oci_free_descriptor, NULL)
476
PHP_FALIAS(ocisavelob, oci_lob_save, NULL)
477
PHP_FALIAS(ocisavelobfile, oci_lob_import, NULL)
478
PHP_FALIAS(ociwritelobtofile, oci_lob_export, NULL)
479
PHP_FALIAS(ociloadlob, oci_lob_load, NULL)
480
PHP_FALIAS(ocicommit, oci_commit, NULL)
481
PHP_FALIAS(ocirollback, oci_rollback, NULL)
482
PHP_FALIAS(ocinewdescriptor, oci_new_descriptor, NULL)
483
PHP_FALIAS(ocisetprefetch, oci_set_prefetch, NULL)
484
PHP_FALIAS(ocipasswordchange, oci_password_change, NULL)
485
#ifdef PHP_OCI8_HAVE_COLLECTIONS
486
PHP_FALIAS(ocifreecollection, oci_free_collection, NULL)
487
PHP_FALIAS(ocinewcollection, oci_new_collection, NULL)
488
PHP_FALIAS(ocicollappend, oci_collection_append, NULL)
489
PHP_FALIAS(ocicollgetelem, oci_collection_element_get, NULL)
490
PHP_FALIAS(ocicollassignelem, oci_collection_element_assign, NULL)
491
PHP_FALIAS(ocicollsize, oci_collection_size, NULL)
492
PHP_FALIAS(ocicollmax, oci_collection_max, NULL)
493
PHP_FALIAS(ocicolltrim, oci_collection_trim, NULL)
498
static zend_function_entry php_oci_lob_class_functions[] = {
499
PHP_FALIAS(load, oci_lob_load, NULL)
500
PHP_FALIAS(tell, oci_lob_tell, NULL)
501
PHP_FALIAS(truncate, oci_lob_truncate, NULL)
502
PHP_FALIAS(erase, oci_lob_erase, NULL)
503
PHP_FALIAS(flush, oci_lob_flush, NULL)
504
PHP_FALIAS(setbuffering,ocisetbufferinglob, NULL)
505
PHP_FALIAS(getbuffering,ocigetbufferinglob, NULL)
506
PHP_FALIAS(rewind, oci_lob_rewind, NULL)
507
PHP_FALIAS(read, oci_lob_read, NULL)
508
PHP_FALIAS(eof, oci_lob_eof, NULL)
509
PHP_FALIAS(seek, oci_lob_seek, NULL)
510
PHP_FALIAS(write, oci_lob_write, NULL)
511
PHP_FALIAS(append, oci_lob_append, NULL)
512
PHP_FALIAS(size, oci_lob_size, NULL)
513
PHP_FALIAS(writetofile, oci_lob_export, NULL)
514
#ifdef HAVE_OCI8_TEMP_LOB
515
PHP_FALIAS(writetemporary, oci_lob_write_temporary, NULL)
516
PHP_FALIAS(close, oci_lob_close, NULL)
518
PHP_FALIAS(save, oci_lob_save, NULL)
519
PHP_FALIAS(savefile, oci_lob_import, NULL)
520
PHP_FALIAS(free, oci_free_descriptor, NULL)
524
#ifdef PHP_OCI8_HAVE_COLLECTIONS
525
static zend_function_entry php_oci_coll_class_functions[] = {
526
PHP_FALIAS(append, oci_collection_append, NULL)
527
PHP_FALIAS(getelem, oci_collection_element_get, NULL)
528
PHP_FALIAS(assignelem, oci_collection_element_assign, NULL)
529
PHP_FALIAS(assign, oci_collection_assign, NULL)
530
PHP_FALIAS(size, oci_collection_size, NULL)
531
PHP_FALIAS(max, oci_collection_max, NULL)
532
PHP_FALIAS(trim, oci_collection_trim, NULL)
533
PHP_FALIAS(free, oci_free_collection, NULL)
538
zend_module_entry oci8_module_entry = {
539
STANDARD_MODULE_HEADER,
540
"oci8", /* extension name */
541
php_oci_functions, /* extension function list */
542
PHP_MINIT(oci), /* extension-wide startup function */
543
PHP_MSHUTDOWN(oci), /* extension-wide shutdown function */
544
PHP_RINIT(oci), /* per-request startup function */
545
PHP_RSHUTDOWN(oci), /* per-request shutdown function */
546
PHP_MINFO(oci), /* information function */
548
STANDARD_MODULE_PROPERTIES
552
/* {{{ startup, shutdown and info functions
554
static void php_oci_init_globals(php_oci_globals *oci_globals_p TSRMLS_DC)
571
(dvoid **)&OCI(pError),
579
static int _sessions_pcleanup(zend_llist *session_list TSRMLS_DC)
581
zend_llist_destroy(session_list);
586
static int _session_pcleanup(oci_session *session TSRMLS_DC)
588
_oci_close_session(session);
593
static int _server_pcleanup(oci_server *server TSRMLS_DC)
595
_oci_close_server(server);
600
PHP_MINIT_FUNCTION(oci)
602
zend_class_entry oci_lob_class_entry;
603
#ifdef PHP_OCI8_HAVE_COLLECTIONS
604
zend_class_entry oci_coll_class_entry;
607
#ifdef HAVE_OCI8_SHARED_MODE
609
#ifdef PHP_OCI8_HAVE_COLLECTIONS
610
#define PHP_OCI_INIT_MODE_TMP OCI_SHARED | OCI_OBJECT
612
#define PHP_OCI_INIT_MODE_TMP OCI_SHARED
617
#ifdef PHP_OCI8_HAVE_COLLECTIONS
618
#define PHP_OCI_INIT_MODE_TMP OCI_DEFAULT | OCI_OBJECT
620
#define PHP_OCI_INIT_MODE_TMP OCI_DEFAULT
626
#define PHP_OCI_INIT_MODE PHP_OCI_INIT_MODE_TMP | OCI_THREADED
628
#define PHP_OCI_INIT_MODE PHP_OCI_INIT_MODE_TMP
631
mutex_alloc(mx_lock);
633
persistent_servers = malloc(sizeof(TsHashTable));
634
persistent_sessions = malloc(sizeof(TsHashTable));
635
zend_ts_hash_init(persistent_servers, 13, NULL, (dtor_func_t) _server_pcleanup, 1);
636
zend_ts_hash_init(persistent_sessions, 13, NULL, (dtor_func_t) _sessions_pcleanup, 1);
638
OCIInitialize(PHP_OCI_INIT_MODE, NULL, NULL, NULL, NULL);
641
ts_allocate_id(&oci_globals_id, sizeof(php_oci_globals), (ts_allocate_ctor) php_oci_init_globals, NULL);
643
php_oci_init_globals(&oci_globals TSRMLS_CC);
646
le_stmt = zend_register_list_destructors_ex(_oci_stmt_list_dtor, NULL, "oci8 statement", module_number);
647
le_conn = zend_register_list_destructors_ex(php_oci_free_conn_list, NULL, "oci8 connection", module_number);
648
le_desc = zend_register_list_destructors_ex(_oci_descriptor_list_dtor, NULL, "oci8 descriptor", module_number);
649
#ifdef PHP_OCI8_HAVE_COLLECTIONS
650
le_coll = zend_register_list_destructors_ex(_oci_coll_list_dtor, NULL, "oci8 collection", module_number);
652
le_server = zend_register_list_destructors_ex(_oci_server_list_dtor, NULL, "oci8 server", module_number);
653
le_session = zend_register_list_destructors_ex(_oci_session_list_dtor, NULL, "oci8 session", module_number);
655
INIT_CLASS_ENTRY(oci_lob_class_entry, "OCI-Lob", php_oci_lob_class_functions);
656
#ifdef PHP_OCI8_HAVE_COLLECTIONS
657
INIT_CLASS_ENTRY(oci_coll_class_entry, "OCI-Collection", php_oci_coll_class_functions);
660
oci_lob_class_entry_ptr = zend_register_internal_class(&oci_lob_class_entry TSRMLS_CC);
661
#ifdef PHP_OCI8_HAVE_COLLECTIONS
662
oci_coll_class_entry_ptr = zend_register_internal_class(&oci_coll_class_entry TSRMLS_CC);
665
/* thies@thieso.net 990203 i do not think that we will need all of them - just in here for completeness for now! */
666
REGISTER_LONG_CONSTANT("OCI_DEFAULT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
667
REGISTER_LONG_CONSTANT("OCI_DESCRIBE_ONLY",OCI_DESCRIBE_ONLY, CONST_CS | CONST_PERSISTENT);
668
REGISTER_LONG_CONSTANT("OCI_COMMIT_ON_SUCCESS",OCI_COMMIT_ON_SUCCESS, CONST_CS | CONST_PERSISTENT);
669
REGISTER_LONG_CONSTANT("OCI_EXACT_FETCH",OCI_EXACT_FETCH, CONST_CS | CONST_PERSISTENT);
671
/* for $LOB->seek() */
672
REGISTER_LONG_CONSTANT("OCI_SEEK_SET",OCI_SEEK_SET, CONST_CS | CONST_PERSISTENT);
673
REGISTER_LONG_CONSTANT("OCI_SEEK_CUR",OCI_SEEK_CUR, CONST_CS | CONST_PERSISTENT);
674
REGISTER_LONG_CONSTANT("OCI_SEEK_END",OCI_SEEK_END, CONST_CS | CONST_PERSISTENT);
676
/* for $LOB->flush() */
677
REGISTER_LONG_CONSTANT("OCI_LOB_BUFFER_FREE",OCI_LOB_BUFFER_FREE, CONST_CS | CONST_PERSISTENT);
679
/* for OCIBindByName (real "oci" names + short "php" names*/
680
REGISTER_LONG_CONSTANT("SQLT_BFILEE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
681
REGISTER_LONG_CONSTANT("SQLT_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
682
REGISTER_LONG_CONSTANT("SQLT_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
683
REGISTER_LONG_CONSTANT("SQLT_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
684
REGISTER_LONG_CONSTANT("SQLT_RDD",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
686
#ifdef PHP_OCI8_HAVE_COLLECTIONS
687
REGISTER_LONG_CONSTANT("OCI_B_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
688
REGISTER_LONG_CONSTANT("SQLT_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
689
REGISTER_STRING_CONSTANT("OCI_SYSDATE","SYSDATE",CONST_PERSISTENT);
692
REGISTER_LONG_CONSTANT("OCI_B_BFILE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
693
REGISTER_LONG_CONSTANT("OCI_B_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
694
REGISTER_LONG_CONSTANT("OCI_B_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
695
REGISTER_LONG_CONSTANT("OCI_B_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
696
REGISTER_LONG_CONSTANT("OCI_B_ROWID",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
697
REGISTER_LONG_CONSTANT("OCI_B_CURSOR",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
698
REGISTER_LONG_CONSTANT("OCI_B_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
700
/* for OCIFetchStatement */
701
REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_COLUMN", OCI_FETCHSTATEMENT_BY_COLUMN, CONST_CS | CONST_PERSISTENT);
702
REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_ROW", OCI_FETCHSTATEMENT_BY_ROW, CONST_CS | CONST_PERSISTENT);
704
/* for OCIFetchInto & OCIResult */
705
REGISTER_LONG_CONSTANT("OCI_ASSOC",OCI_ASSOC, CONST_CS | CONST_PERSISTENT);
706
REGISTER_LONG_CONSTANT("OCI_NUM",OCI_NUM, CONST_CS | CONST_PERSISTENT);
707
REGISTER_LONG_CONSTANT("OCI_BOTH",OCI_BOTH, CONST_CS | CONST_PERSISTENT);
708
REGISTER_LONG_CONSTANT("OCI_RETURN_NULLS",OCI_RETURN_NULLS, CONST_CS | CONST_PERSISTENT);
709
REGISTER_LONG_CONSTANT("OCI_RETURN_LOBS",OCI_RETURN_LOBS, CONST_CS | CONST_PERSISTENT);
711
/* for OCINewDescriptor (real "oci" names + short "php" names*/
712
REGISTER_LONG_CONSTANT("OCI_DTYPE_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
713
REGISTER_LONG_CONSTANT("OCI_DTYPE_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
714
REGISTER_LONG_CONSTANT("OCI_DTYPE_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
716
REGISTER_LONG_CONSTANT("OCI_D_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
717
REGISTER_LONG_CONSTANT("OCI_D_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
718
REGISTER_LONG_CONSTANT("OCI_D_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
720
/* for OCIWriteTemporaryLob */
721
#ifdef HAVE_OCI8_TEMP_LOB
722
REGISTER_LONG_CONSTANT("OCI_TEMP_CLOB",OCI_TEMP_CLOB, CONST_CS | CONST_PERSISTENT);
723
REGISTER_LONG_CONSTANT("OCI_TEMP_BLOB",OCI_TEMP_BLOB, CONST_CS | CONST_PERSISTENT);
729
/* ----------------------------------------------------------------- */
731
PHP_RINIT_FUNCTION(oci)
733
OCI(debug_mode) = 0; /* start "fresh" */
734
/* OCI(in_call) = 0; i don't think we want this! */
736
oci_debug("php_rinit_oci");
741
PHP_MSHUTDOWN_FUNCTION(oci)
745
oci_debug("START php_mshutdown_oci");
747
zend_ts_hash_destroy(persistent_sessions);
748
zend_ts_hash_destroy(persistent_servers);
750
free(persistent_sessions);
751
free(persistent_servers);
762
oci_debug("END php_mshutdown_oci");
767
PHP_RSHUTDOWN_FUNCTION(oci)
769
oci_debug("START php_rshutdown_oci");
772
/* XXX free all statements, rollback all outstanding transactions */
774
zend_ts_hash_apply(persistent_sessions, (apply_func_t) _session_cleanup TSRMLS_CC);
775
zend_ts_hash_apply(persistent_servers, (apply_func_t) _server_cleanup TSRMLS_CC);
778
oci_debug("END php_rshutdown_oci");
783
PHP_MINFO_FUNCTION(oci)
787
php_info_print_table_start();
788
php_info_print_table_row(2, "OCI8 Support", "enabled");
789
php_info_print_table_row(2, "Revision", "$Revision: 1.257.2.8 $");
791
sprintf(buf, "%ld", num_persistent);
792
php_info_print_table_row(2, "Active Persistent Links", buf);
793
sprintf(buf, "%ld", num_links);
794
php_info_print_table_row(2, "Active Links", buf);
797
php_info_print_table_row(2, "Oracle Version", PHP_OCI8_VERSION );
798
php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DIR );
799
php_info_print_table_row(2, "Libraries Used", PHP_OCI8_SHARED_LIBADD );
802
#ifdef HAVE_OCI8_TEMP_LOB
803
php_info_print_table_row(2, "Temporary Lob support", "enabled" );
805
php_info_print_table_row(2, "Temporary Lob support", "disabled" );
808
#ifdef PHP_OCI8_HAVE_COLLECTIONS
809
php_info_print_table_row(2, "Collections support", "enabled" );
811
php_info_print_table_row(2, "Collections support", "disabled" );
814
php_info_print_table_end();
818
/* {{{ _oci_define_hash_dtor()
820
static void _oci_define_hash_dtor(void *data)
822
oci_define *define = (oci_define *) data;
824
oci_debug("_oci_define_hash_dtor: %s",define->name);
826
zval_ptr_dtor(&define->zval);
835
/* {{{ _oci_desc_flush_hash_dtor()
837
static void _oci_desc_flush_hash_dtor(void *data)
839
oci_descriptor *descr = *(oci_descriptor **)data;
842
if (descr->buffering == 2 && (descr->type == OCI_DTYPE_LOB || descr->type == OCI_DTYPE_FILE)) {
843
oci_lob_flush(descr,OCI_LOB_BUFFER_FREE TSRMLS_CC);
844
descr->buffering = 1;
849
/* {{{ _oci_bind_hash_dtor()
851
static void _oci_bind_hash_dtor(void *data)
853
oci_bind *bind = (oci_bind *) data;
855
oci_debug("_oci_bind_hash_dtor:");
857
zval_ptr_dtor(&(bind->zval));
861
/* {{{ _oci_bind_pre_exec()
863
static int _oci_bind_pre_exec(void *data TSRMLS_DC)
865
oci_bind *bind = (oci_bind *) data;
867
/* reset all bind stuff to a normal state..-. */
875
/* {{{ _oci_bind_post_exec()
877
static int _oci_bind_post_exec(void *data TSRMLS_DC)
879
oci_bind *bind = (oci_bind *) data;
881
if (bind->indicator == -1) { /* NULL */
882
zval *val = bind->zval;
883
if (Z_TYPE_P(val) == IS_STRING && (Z_STRVAL_P(val) != empty_string)) {
884
*Z_STRVAL_P(val) = '\0'; /* XXX avoid warning in debug mode */
888
} else if (Z_TYPE_P(bind->zval) == IS_STRING && (Z_STRVAL_P(bind->zval) != empty_string)) {
889
Z_STRVAL_P(bind->zval) = erealloc(Z_STRVAL_P(bind->zval), Z_STRLEN_P(bind->zval)+1);
890
Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] = '\0';
898
/* {{{ _oci_column_hash_dtor()
900
static void _oci_column_hash_dtor(void *data)
902
oci_out_column *column = (oci_out_column *) data;
905
oci_debug("START _oci_column_hash_dtor: %s",column->name);
907
if (column->stmtid) {
908
zend_list_delete(column->stmtid);
911
if (column->is_descr) {
912
zend_list_delete(column->descid);
919
oci_debug("END _oci_column_hash_dtor: %s",column->name);
927
/* {{{ _oci_stmt_list_dtor()
929
static void _oci_stmt_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
931
oci_statement *statement = (oci_statement *)rsrc->ptr;
932
oci_debug("START _oci_stmt_list_dtor: id=%d last_query=\"%s\"",statement->id,SAFE_STRING(statement->last_query));
934
if (statement->pStmt) {
942
statement->pStmt = 0;
945
if (statement->pError) {
953
statement->pError = 0;
956
if (statement->last_query) {
957
efree(statement->last_query);
960
if (statement->columns) {
961
zend_hash_destroy(statement->columns);
962
efree(statement->columns);
965
if (statement->binds) {
966
zend_hash_destroy(statement->binds);
967
efree(statement->binds);
970
if (statement->defines) {
971
zend_hash_destroy(statement->defines);
972
efree(statement->defines);
975
oci_debug("END _oci_stmt_list_dtor: id=%d",statement->id);
981
/* {{{ _oci_conn_list_dtor()
983
static void _oci_conn_list_dtor(oci_connection *connection TSRMLS_DC)
986
as the connection is "only" a in memory service context we do not disconnect from oracle.
989
oci_debug("START _oci_conn_list_dtor: id=%d",connection->id);
991
if (connection->pServiceContext) {
993
if (connection->needs_commit) {
994
oci_debug("OCITransRollback");
995
CALL_OCI_RETURN(connection->error,
997
connection->pServiceContext,
1003
if (connection->error) {
1004
oci_error(connection->pError, "failed to rollback outstanding transactions!", connection->error);
1006
connection->needs_commit = 0;
1008
oci_debug("nothing to do..");
1013
(dvoid *) connection->pServiceContext,
1014
(ub4) OCI_HTYPE_SVCCTX
1019
if (connection->pError) {
1022
(dvoid *) connection->pError,
1023
(ub4) OCI_HTYPE_ERROR
1028
if (connection->session && connection->session->exclusive) {
1029
/* close associated session when destructed */
1030
zend_list_delete(connection->session->num);
1033
if (connection->descriptors) {
1034
zend_hash_destroy(connection->descriptors);
1035
efree(connection->descriptors);
1038
oci_debug("END _oci_conn_list_dtor: id=%d",connection->id);
1044
/* {{{ php_oci_free_conn_list
1046
static void php_oci_free_conn_list(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1048
oci_connection *conn = (oci_connection *)rsrc->ptr;
1049
_oci_conn_list_dtor(conn TSRMLS_CC);
1053
#ifdef PHP_OCI8_HAVE_COLLECTIONS
1055
/* {{{ _oci_coll_list_dtor()
1057
static void _oci_coll_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1059
oci_collection *coll = (oci_collection *)rsrc->ptr;
1060
oci_debug("START _oci_coll_list_dtor: %d",coll->id);
1062
/* Note sure if we need to free the object. Have an
1063
oracle TAR out on this one.
1064
OCIDescriptorFree(descr->ocidescr, descr->type); */
1066
oci_debug("END _oci_coll_list_dtor: %d",coll->id);
1073
/* {{{ _oci_descriptor_list_dtor()
1075
static void _oci_descriptor_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1077
oci_descriptor *descr = (oci_descriptor *)rsrc->ptr;
1078
oci_debug("START _oci_descriptor_list_dtor: %d",descr->id);
1080
/* flushing Lobs & Files with buffering enabled */
1081
if ((descr->type == OCI_DTYPE_FILE || descr->type == OCI_DTYPE_LOB) && descr->buffering == 2) {
1082
oci_debug("descriptor #%d needs to be flushed. flushing..",descr->id);
1083
oci_lob_flush(descr,OCI_LOB_BUFFER_FREE TSRMLS_CC);
1093
oci_debug("END _oci_descriptor_list_dtor: %d",descr->id);
1099
/* {{{ _oci_server_list_dtor()
1101
static void _oci_server_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1104
oci_server *server = (oci_server *)rsrc->ptr;
1105
if (server->persistent)
1108
_oci_close_server(server);
1113
/* {{{ _oci_session_list_dtor()
1115
static void _oci_session_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1117
oci_session *session = (oci_session *)rsrc->ptr;
1118
if (session->persistent) {
1119
/* clear thread assignment */
1120
session->thread = 0;
1124
_oci_close_session(session);
1128
/* {{{ oci_handle_error
1130
static ub4 oci_handle_error(oci_connection *connection, ub4 errcode)
1133
case 1013: /* user requested cancel of current operation */
1137
case 22: /* ORA-00022 Invalid session id */
1138
case 1012: /* ORA-01012: */
1139
case 3113: /* ORA-03113: end-of-file on communication channel */
1142
connection->is_open = 0;
1143
connection->session->is_open = 0;
1144
connection->session->server->is_open = 0;
1145
return 1; /* fatal error */
1148
return 0; /* no fatal error */
1154
static ub4 oci_error(OCIError *err_p, char *what, sword status)
1163
case OCI_SUCCESS_WITH_INFO:
1171
(ub4)sizeof(errbuf),
1172
(ub4)OCI_HTYPE_ERROR
1175
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: OCI_SUCCESS_WITH_INFO: %s", what, errbuf);
1178
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: OCI_NEED_DATA", what);
1181
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: OCI_NO_DATA", what);
1191
(ub4)sizeof(errbuf),
1192
(ub4)OCI_HTYPE_ERROR
1195
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", what, errbuf);
1198
case OCI_INVALID_HANDLE:
1199
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: OCI_INVALID_HANDLE", what);
1201
case OCI_STILL_EXECUTING:
1202
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: OCI_STILL_EXECUTING", what);
1205
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: OCI_CONTINUE", what);
1216
static int oci_ping(oci_server *server)
1221
CALL_OCI_RETURN(OCI(error),
1231
if (OCI(error) == OCI_SUCCESS) {
1235
oci_error(OCI(pError), "oci_ping", OCI(error));
1241
/************************* INTERNAL FUNCTIONS *************************/
1245
static void oci_debug(const char *format, ...)
1249
if (OCI(debug_mode)) {
1253
va_start(args, format);
1254
vsnprintf(buffer, sizeof(buffer)-1, format, args);
1256
buffer[sizeof(buffer)-1] = '\0';
1257
php_printf("OCIDebug: %s<br />\n", buffer);
1262
/* {{{ oci_get_conn()
1264
static oci_connection *oci_get_conn(zval **conn TSRMLS_DC)
1266
oci_connection *connection;
1268
connection = (oci_connection *) zend_fetch_resource(conn TSRMLS_CC, -1, "OCI8-Connection", NULL, 1, le_conn);
1270
if (connection && connection->is_open) {
1273
return (oci_connection *) NULL;
1278
/* {{{ oci_get_stmt()
1280
static oci_statement *oci_get_stmt(zval **stmt TSRMLS_DC)
1282
oci_statement *statement;
1284
statement = (oci_statement *) zend_fetch_resource(stmt TSRMLS_CC, -1, "OCI8-Statement", NULL, 1, le_stmt);
1286
if (statement && statement->conn->is_open) {
1289
return (oci_statement *) NULL;
1294
/* {{{ oci_get_desc()
1296
static oci_descriptor *oci_get_desc(int ind TSRMLS_DC)
1298
oci_descriptor *descriptor;
1299
int actual_resource_type;
1301
descriptor = (oci_descriptor *) zend_list_find(ind, &actual_resource_type);
1303
if (descriptor && (actual_resource_type == le_desc)) {
1306
return (oci_descriptor *) NULL;
1311
/* {{{ oci_get_col()
1313
static oci_out_column *oci_get_col(oci_statement *statement, int col, zval **value)
1315
oci_out_column *outcol = NULL;
1319
if (statement->columns == 0) { /* we release the columns at the end of a fetch */
1324
if (Z_TYPE_PP(value) == IS_STRING) {
1325
for (i = 0; i < statement->ncolumns; i++) {
1326
outcol = oci_get_col(statement, i + 1, 0);
1327
if (outcol == NULL) {
1329
} else if (((int) outcol->name_len == Z_STRLEN_PP(value)) &&
1330
(!strncmp(outcol->name, Z_STRVAL_PP(value), Z_STRLEN_PP(value)))
1336
convert_to_long_ex(value);
1337
return oci_get_col(statement,Z_LVAL_PP(value),0);
1339
} else if (col != -1) {
1340
if (zend_hash_index_find(statement->columns, col, (void **)&outcol) == FAILURE) {
1341
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column %d", col);
1351
/* {{{ oci_new_desc()
1353
static oci_descriptor *oci_new_desc(int type, oci_connection *connection)
1355
oci_descriptor *descr;
1358
descr = emalloc(sizeof(oci_descriptor));
1362
switch (descr->type) {
1363
case OCI_DTYPE_FILE:
1365
case OCI_DTYPE_ROWID:
1369
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown descriptor type %d.", descr->type);
1374
CALL_OCI_RETURN(OCI(error),
1376
connection->session->pEnv,
1377
(dvoid*)&(descr->ocidescr),
1386
error = oci_error(OCI(pError),"OCIDescriptorAlloc %d",OCI(error));
1387
oci_handle_error(connection, error);
1392
descr->id = zend_list_insert(descr,le_desc);
1393
descr->conn = connection;
1394
descr->lob_current_position = 0;
1395
descr->lob_size = -1; /* we should set it to -1 to know, that it's just not initialized */
1396
descr->buffering = 0; /* buffering is off by default */
1397
zend_list_addref(connection->id);
1399
if (descr->type == OCI_DTYPE_LOB || descr->type == OCI_DTYPE_FILE) {
1400
/* add Lobs & Files to hash. we'll flush them ate the end */
1401
if (!connection->descriptors) {
1402
ALLOC_HASHTABLE(connection->descriptors);
1403
zend_hash_init(connection->descriptors, 13, NULL, _oci_desc_flush_hash_dtor, 0);
1406
zend_hash_next_index_insert(connection->descriptors,&descr,sizeof(oci_descriptor *),NULL);
1408
oci_debug("oci_new_desc %d",descr->id);
1414
#ifdef PHP_OCI8_HAVE_COLLECTIONS
1416
/* {{{ _oci_get_ocicoll()
1418
static int _oci_get_ocicoll(zval *id,oci_collection **collection TSRMLS_DC)
1422
if (zend_hash_find(Z_OBJPROP_P(id), "collection", sizeof("collection"), (void **)&coll) == FAILURE) {
1423
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find collection");
1426
if ((*collection = oci_get_coll(Z_LVAL_PP(coll) TSRMLS_CC)) == NULL) {
1427
php_error_docref(NULL TSRMLS_CC, E_WARNING, "collection not found");
1431
return Z_LVAL_PP(coll);
1437
/* {{{ _oci_get_ocidesc()
1439
static int _oci_get_ocidesc(zval *id,oci_descriptor **descriptor TSRMLS_DC)
1443
if (zend_hash_find(Z_OBJPROP_P(id), "descriptor", sizeof("descriptor"), (void **)&desc) == FAILURE) {
1444
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find descriptor");
1448
if ((*descriptor = oci_get_desc(Z_LVAL_PP(desc) TSRMLS_CC)) == NULL) {
1449
php_error_docref(NULL TSRMLS_CC, E_WARNING, "descriptor not found");
1453
return Z_LVAL_PP(desc);
1457
/* {{{ _oci_make_zval()
1459
static int _oci_make_zval(zval *value,oci_statement *statement,oci_out_column *column, char *func, int mode TSRMLS_DC)
1461
oci_descriptor *descr;
1466
if (column->indicator || column->retcode)
1467
if ((column->indicator != -1) && (column->retcode != 1405))
1468
oci_debug("_oci_make_zval: %16s,retlen = %4d,retlen4 = %d,storage_size4 = %4d,indicator %4d, retcode = %4d",
1469
column->name,column->retlen,column->retlen4,column->storage_size4,column->indicator,column->retcode);
1471
if ((!statement->has_data) || (column->indicator == -1)) { /* column is NULL or statment has no current data */
1476
if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */
1477
ZVAL_RESOURCE(value,column->stmtid);
1478
zend_list_addref(column->stmtid);
1479
} else if (column->is_descr) {
1480
if ((column->data_type != SQLT_RDD) && (mode & OCI_RETURN_LOBS)) {
1481
/* OCI_RETURN_LOBS means that we want the content of the LOB back instead of the locator */
1483
descr = oci_get_desc(column->descid TSRMLS_CC);
1485
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to find my descriptor %p",column->data);
1489
if (oci_loadlob(statement->conn,descr,&buffer,&loblen)) {
1492
ZVAL_STRINGL(value,buffer,loblen,0);
1495
/* return the locator */
1496
object_init_ex(value, oci_lob_class_entry_ptr);
1497
add_property_resource(value, "descriptor", column->descid);
1498
zend_list_addref(column->descid);
1501
switch (column->retcode) {
1504
if (column->piecewise) {
1505
size = column->retlen4;
1507
size = column->retlen;
1512
/* XXX we SHOULD maybe have a different behaviour for unknown results! */
1517
ZVAL_STRINGL(value,column->data,size,1);
1524
/* {{{ oci_setprefetch()
1526
static int oci_setprefetch(oci_statement *statement,int size)
1532
prefetch = size * 1024;
1534
CALL_OCI_RETURN(error,
1540
OCI_ATTR_PREFETCH_MEMORY,
1545
statement->error = oci_error(statement->pError, "OCIAttrSet OCI_ATTR_PREFETCH_MEMORY", error);
1547
if (statement->error) {
1548
oci_handle_error(statement->conn, statement->error);
1552
CALL_OCI_RETURN(error,
1558
OCI_ATTR_PREFETCH_ROWS,
1563
statement->error = oci_error(statement->pError, "OCIAttrSet OCI_ATTR_PREFETCH_MEMORY", error);
1564
if (statement->error) {
1565
oci_handle_error(statement->conn, statement->error);
1574
static oci_statement *oci_parse(oci_connection *connection, char *query, int len)
1576
oci_statement *statement;
1580
statement = ecalloc(1,sizeof(oci_statement));
1584
connection->session->pEnv,
1585
(dvoid **)&statement->pStmt,
1594
connection->session->pEnv,
1595
(dvoid **)&statement->pError,
1603
CALL_OCI_RETURN(error,
1614
connection->error = oci_error(connection->pError, "OCIParse", error);
1615
if (connection->error) {
1631
oci_handle_error(connection, connection->error);
1637
statement->last_query = estrdup(query);
1640
statement->conn = connection;
1641
statement->has_data = 0;
1643
statement->id = zend_list_insert(statement,le_stmt);
1645
oci_debug("oci_parse \"%s\" id=%d conn=%d",
1648
statement->conn->id);
1650
zend_list_addref(statement->conn->id);
1656
/* {{{ oci_execute()
1658
static int oci_execute(oci_statement *statement, char *func,ub4 mode)
1660
oci_out_column *outcol;
1661
oci_out_column column;
1662
OCIParam *param = 0;
1671
oci_descriptor *descr;
1675
if (!statement->stmttype) {
1676
CALL_OCI_RETURN(error,
1678
(dvoid *)statement->pStmt,
1680
(ub2 *)&statement->stmttype,
1687
statement->error = oci_error(statement->pError, "OCIAttrGet OCI_HTYPE_STMT/OCI_ATTR_STMT_TYPE", error);
1689
if (statement->error) {
1690
oci_handle_error(statement->conn, statement->error);
1695
if (statement->stmttype == OCI_STMT_SELECT) {
1701
if (statement->last_query) {
1702
/* if we execute refcursors we don't have a query and
1703
we don't want to execute!!! */
1705
if (statement->binds) {
1706
zend_hash_apply(statement->binds, (apply_func_t) _oci_bind_pre_exec TSRMLS_CC);
1709
CALL_OCI_RETURN(error,
1711
statement->conn->pServiceContext,
1722
statement->error = oci_error(statement->pError, "OCIStmtExecute", error);
1724
if (statement->binds) {
1725
zend_hash_apply(statement->binds, (apply_func_t) _oci_bind_post_exec TSRMLS_CC);
1728
oci_handle_error(statement->conn, statement->error);
1730
if (statement->error) {
1734
if (mode & OCI_COMMIT_ON_SUCCESS) {
1735
statement->conn->needs_commit = 0;
1737
statement->conn->needs_commit = 1;
1741
if ((statement->stmttype == OCI_STMT_SELECT) && (statement->executed == 0)) {
1742
/* we only need to do the define step is this very statement is executed the first time! */
1743
statement->executed = 1;
1745
ALLOC_HASHTABLE(statement->columns);
1746
zend_hash_init(statement->columns, 13, NULL, _oci_column_hash_dtor, 0);
1750
CALL_OCI_RETURN(error,
1752
(dvoid *)statement->pStmt,
1756
OCI_ATTR_PARAM_COUNT,
1761
statement->error = oci_error(statement->pError, "OCIAttrGet OCI_HTYPE_STMT/OCI_ATTR_PARAM_COUNT", error);
1762
if (statement->error) {
1763
oci_handle_error(statement->conn, statement->error);
1764
return 0; /* XXX we loose memory!!! */
1767
statement->ncolumns = colcount;
1769
for (counter = 1; counter <= colcount; counter++) {
1770
memset(&column,0,sizeof(oci_out_column));
1772
if (zend_hash_index_update(statement->columns, counter, &column,
1773
sizeof(oci_out_column), (void**) &outcol) == FAILURE) {
1774
efree(statement->columns);
1779
outcol->statement = statement;
1781
CALL_OCI_RETURN(error,
1783
(dvoid *)statement->pStmt,
1791
statement->error = oci_error(statement->pError, "OCIParamGet OCI_HTYPE_STMT", error);
1792
if (statement->error) {
1793
oci_handle_error(statement->conn, statement->error);
1794
return 0; /* XXX we loose memory!!! */
1797
CALL_OCI_RETURN(error,
1801
(dvoid *)&outcol->data_type,
1808
statement->error = oci_error(statement->pError, "OCIAttrGet OCI_DTYPE_PARAM/OCI_ATTR_DATA_TYPE", error);
1809
if (statement->error) {
1810
oci_handle_error(statement->conn, statement->error);
1811
return 0; /* XXX we loose memory!!! */
1814
CALL_OCI_RETURN(error,
1818
(dvoid *)&outcol->data_size,
1825
statement->error = oci_error(statement->pError, "OCIAttrGet OCI_DTYPE_PARAM/OCI_ATTR_DATA_SIZE", error);
1826
if (statement->error) {
1827
oci_handle_error(statement->conn, statement->error);
1828
return 0; /* XXX we loose memory!!! */
1831
outcol->storage_size4 = outcol->data_size;
1832
outcol->retlen = outcol->data_size;
1834
CALL_OCI_RETURN(error,
1838
(dvoid *)&outcol->scale,
1845
statement->error = oci_error(statement->pError, "OCIAttrGet OCI_DTYPE_PARAM/OCI_ATTR_SCALE", error);
1846
if (statement->error) {
1847
oci_handle_error(statement->conn, statement->error);
1848
return 0; /* XXX we lose memory!!! */
1851
CALL_OCI_RETURN(error,
1855
(dvoid *)&outcol->precision,
1862
statement->error = oci_error(statement->pError, "OCIAttrGet OCI_DTYPE_PARAM/OCI_ATTR_PRECISION", error);
1863
if (statement->error) {
1864
oci_handle_error(statement->conn, statement->error);
1865
return 0; /* XXX we lose memory!!! */
1868
CALL_OCI_RETURN(error,
1872
(dvoid **)&colname, /* XXX this string is NOT zero terminated!!!! */
1873
(ub4 *)&outcol->name_len,
1879
statement->error = oci_error(statement->pError, "OCIAttrGet OCI_DTYPE_PARAM/OCI_ATTR_NAME", error);
1880
if (statement->error) {
1881
oci_handle_error(statement->conn, statement->error);
1882
return 0; /* XXX we loose memory!!! */
1885
outcol->name = estrndup((char*) colname,outcol->name_len);
1887
/* find a user-setted define */
1888
if (statement->defines) {
1889
zend_hash_find(statement->defines,outcol->name,outcol->name_len,(void **) &outcol->define);
1893
switch (outcol->data_type) {
1895
outcol->pstmt = oci_parse(statement->conn,0,0);
1896
outcol->stmtid = outcol->pstmt->id;
1898
define_type = SQLT_RSET;
1899
outcol->is_cursor = 1;
1900
outcol->storage_size4 = -1;
1901
outcol->retlen = -1;
1902
dynamic = OCI_DEFAULT;
1903
buf = &(outcol->pstmt->pStmt);
1906
case SQLT_RDD: /* ROWID */
1907
case SQLT_BLOB: /* binary LOB */
1908
case SQLT_CLOB: /* character LOB */
1909
case SQLT_BFILE: /* binary file LOB */
1910
define_type = outcol->data_type;
1911
outcol->is_descr = 1;
1912
outcol->storage_size4 = -1;
1913
dynamic = OCI_DEFAULT;
1915
if (outcol->data_type == SQLT_BFILE) {
1916
dtype = OCI_DTYPE_FILE;
1917
} else if (outcol->data_type == SQLT_RDD ) {
1918
dtype = OCI_DTYPE_ROWID;
1920
dtype = OCI_DTYPE_LOB;
1923
descr = oci_new_desc(dtype,statement->conn);
1925
/* need better error checking XXX */
1927
outcol->descid = descr->id;
1928
buf = &(descr->ocidescr);
1933
if (outcol->data_type == SQLT_LBI) {
1934
define_type = SQLT_BIN;
1936
define_type = SQLT_CHR;
1938
outcol->storage_size4 = OCI_MAX_DATA_SIZE;
1939
outcol->piecewise = 1;
1940
dynamic = OCI_DYNAMIC_FETCH;
1945
define_type = SQLT_CHR;
1946
if ((outcol->data_type == SQLT_DAT) || (outcol->data_type == SQLT_NUM)
1947
#ifdef SQLT_TIMESTAMP
1948
|| (outcol->data_type == SQLT_TIMESTAMP)
1950
#ifdef SQLT_TIMESTAMP_TZ
1951
|| (outcol->data_type == SQLT_TIMESTAMP_TZ)
1954
outcol->storage_size4 = 512; /* XXX this should fit "most" NLS date-formats and Numbers */
1956
outcol->storage_size4++; /* add one for string terminator */
1958
if (outcol->data_type == SQLT_BIN) {
1959
outcol->storage_size4 *= 3;
1961
dynamic = OCI_DEFAULT;
1962
buf = outcol->data = (text *) emalloc(outcol->storage_size4);
1966
if (dynamic == OCI_DYNAMIC_FETCH) {
1967
CALL_OCI_RETURN(error,
1969
statement->pStmt, /* IN/OUT handle to the requested SQL query */
1970
(OCIDefine **)&outcol->pDefine, /* IN/OUT pointer to a pointer to a define handle */
1971
statement->pError, /* IN/OUT An error handle */
1972
counter, /* IN position in the select list */
1973
(dvoid *)NULL, /* IN/OUT pointer to a buffer */
1974
outcol->storage_size4, /* IN The size of each valuep buffer in bytes */
1975
define_type, /* IN The data type */
1976
(dvoid *)&outcol->indicator, /* IN pointer to an indicator variable or arr */
1977
(ub2 *)NULL, /* IN/OUT Pointer to array of length of data fetched */
1978
(ub2 *)NULL, /* OUT Pointer to array of column-level return codes */
1979
OCI_DYNAMIC_FETCH /* IN mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
1983
statement->error = oci_error(statement->pError, "OCIDefineByPos", error);
1985
CALL_OCI_RETURN(error,
1987
statement->pStmt, /* IN/OUT handle to the requested SQL query */
1988
(OCIDefine **)&outcol->pDefine, /* IN/OUT pointer to a pointer to a define handle */
1989
statement->pError, /* IN/OUT An error handle */
1990
counter, /* IN position in the select list */
1991
(dvoid *)buf, /* IN/OUT pointer to a buffer */
1992
outcol->storage_size4, /* IN The size of each valuep buffer in bytes */
1993
define_type, /* IN The data type */
1994
(dvoid *)&outcol->indicator, /* IN pointer to an indicator variable or arr */
1995
(ub2 *)&outcol->retlen, /* IN/OUT Pointer to array of length of data fetched */
1996
(ub2 *)&outcol->retcode, /* OUT Pointer to array of column-level return codes */
1997
OCI_DEFAULT /* IN mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
2001
statement->error = oci_error(statement->pError, "OCIDefineByPos", error);
2003
if (statement->error) {
2004
oci_handle_error(statement->conn, statement->error);
2005
return 0; /* XXX we loose memory!!! */
2016
static int _oci_column_pre_fetch(void *data TSRMLS_DC)
2018
oci_out_column *col = (oci_out_column *) data;
2020
if (col->piecewise) {
2027
static int oci_fetch(oci_statement *statement, ub4 nrows, char *func TSRMLS_DC)
2030
oci_out_column *column;
2032
if (statement->columns) {
2033
zend_hash_apply(statement->columns, (apply_func_t) _oci_column_pre_fetch TSRMLS_CC);
2037
CALL_OCI_RETURN(statement->error,
2047
if ((statement->error == OCI_NO_DATA) || (nrows == 0)) {
2048
if (statement->last_query == 0) {
2049
/* reset define-list for refcursors */
2050
if (statement->columns) {
2051
zend_hash_destroy(statement->columns);
2052
efree(statement->columns);
2053
statement->columns = 0;
2054
statement->ncolumns = 0;
2056
statement->executed = 0;
2059
statement->error = 0; /* OCI_NO_DATA is NO error for us!!! */
2060
statement->has_data = 0;
2065
while (statement->error == OCI_NEED_DATA) {
2066
for (i = 0; i < statement->ncolumns; i++) {
2067
column = oci_get_col(statement, i + 1, 0);
2068
if (column->piecewise) {
2069
if (!column->data) {
2070
column->data = (text *) emalloc(OCI_PIECE_SIZE);
2072
column->data = erealloc(column->data,column->retlen4 + OCI_PIECE_SIZE);
2075
column->cb_retlen = OCI_PIECE_SIZE;
2078
OCIStmtSetPieceInfo(
2079
(void *) column->pDefine,
2082
((char*)column->data) + column->retlen4,
2083
&(column->cb_retlen),
2092
CALL_OCI_RETURN(statement->error,
2102
for (i = 0; i < statement->ncolumns; i++) {
2103
column = oci_get_col(statement, i + 1, 0);
2104
if (column->piecewise) {
2105
column->retlen4 += column->cb_retlen;
2110
if (statement->error == OCI_SUCCESS_WITH_INFO || statement->error == OCI_SUCCESS) {
2111
statement->has_data = 1;
2113
/* do the stuff needed for OCIDefineByName */
2114
for (i = 0; i < statement->ncolumns; i++) {
2115
column = oci_get_col(statement, i + 1, 0);
2116
if (column == NULL) {
2120
if (!column->define) {
2124
zval_dtor(column->define->zval);
2125
_oci_make_zval(column->define->zval,statement,column,"OCIFetch",0 TSRMLS_CC);
2131
oci_error(statement->pError, func, statement->error);
2132
oci_handle_error(statement->conn, statement->error);
2134
statement->has_data = 0;
2140
/* {{{ oci_lobgetlen()
2142
static int oci_lobgetlen(oci_connection *connection, oci_descriptor *mydescr, ub4 *loblen)
2148
/* do we need to ask oracle about LOB's length, if we do already know it? I think no. */
2149
if (mydescr->lob_size >= 0) {
2150
*loblen = mydescr->lob_size;
2152
if (mydescr->type == OCI_DTYPE_FILE) {
2153
CALL_OCI_RETURN(connection->error,
2155
connection->pServiceContext,
2161
if (connection->error) {
2162
oci_error(connection->pError, "OCILobFileOpen",connection->error);
2163
oci_handle_error(connection, connection->error);
2168
CALL_OCI_RETURN(connection->error,
2170
connection->pServiceContext,
2177
if (connection->error) {
2178
oci_error(connection->pError, "OCILobGetLength",connection->error);
2179
oci_handle_error(connection, connection->error);
2182
mydescr->lob_size = *loblen;
2184
if (mydescr->type == OCI_DTYPE_FILE) {
2185
CALL_OCI_RETURN(connection->error,
2187
connection->pServiceContext,
2193
if (connection->error) {
2194
oci_error(connection->pError, "OCILobFileClose", connection->error);
2195
oci_handle_error(connection, connection->error);
2201
oci_debug("oci_lobgetlen: len=%d",*loblen);
2207
/* {{{ oci_loadlob()
2209
#define LOBREADSIZE 1048576l /* 1MB */
2210
static int oci_loadlob(oci_connection *connection, oci_descriptor *mydescr, char **buffer, ub4 *loblen)
2219
if (mydescr->type == OCI_DTYPE_FILE) {
2220
CALL_OCI_RETURN(connection->error,
2222
connection->pServiceContext,
2229
if (connection->error) {
2230
oci_error(connection->pError, "OCILobFileOpen",connection->error);
2231
oci_handle_error(connection, connection->error);
2236
CALL_OCI_RETURN(connection->error,
2238
connection->pServiceContext,
2245
if (connection->error) {
2246
oci_error(connection->pError, "OCILobGetLength",connection->error);
2247
oci_handle_error(connection, connection->error);
2251
buf = emalloc(readlen + 1);
2253
while (readlen > 0) { /* thies loop should not be entered on readlen == 0 */
2254
CALL_OCI_RETURN(connection->error,
2256
connection->pServiceContext,
2259
&readlen, /* IN/OUT bytes toread/read */
2260
siz + 1, /* offset (starts with 1) */
2261
(dvoid *) ((char *) buf + siz),
2262
readlen, /* size of buffer */
2264
(OCICallbackLobRead) 0, /* callback... */
2265
(ub2) connection->session->charsetId, /* The character set ID of the buffer data. */
2266
(ub1) SQLCS_IMPLICIT /* The character set form of the buffer data. */
2271
readlen = LOBREADSIZE;
2273
if (connection->error == OCI_NEED_DATA) {
2274
buf = erealloc(buf,siz + LOBREADSIZE + 1);
2281
if (connection->error) {
2282
oci_error(connection->pError, "OCILobRead", connection->error);
2283
oci_handle_error(connection, connection->error);
2288
if (mydescr->type == OCI_DTYPE_FILE) {
2289
CALL_OCI_RETURN(connection->error,
2291
connection->pServiceContext,
2297
if (connection->error) {
2298
oci_error(connection->pError, "OCILobFileClose", connection->error);
2299
oci_handle_error(connection, connection->error);
2305
buf = erealloc(buf,siz+1);
2311
oci_debug("oci_loadlob: size=%d",siz);
2317
/* {{{ oci_readlob()
2319
static int oci_readlob(oci_connection *connection, oci_descriptor *mydescr, char **buffer, ub4 *len)
2328
/* we're not going to read LOB, if length is not known */
2329
if (!len || (int)*len <= 0) {
2333
if (mydescr->type == OCI_DTYPE_FILE) {
2334
CALL_OCI_RETURN(connection->error,
2336
connection->pServiceContext,
2343
if (connection->error) {
2344
oci_error(connection->pError, "OCILobFileOpen",connection->error);
2345
oci_handle_error(connection, connection->error);
2350
if (oci_lobgetlen(connection, mydescr, &loblen) != 0) {
2355
/* check if we're in LOB's borders */
2356
if ((mydescr->lob_current_position + *len) > loblen) {
2357
*len = loblen - mydescr->lob_current_position;
2360
if ((int)*len > 0) {
2361
buf = emalloc(*len + 1);
2363
/* set offset to current LOB's position */
2364
siz = mydescr->lob_current_position;
2366
/* check if len is smaller, if not - using LOBREADSIZE' sized buffer */
2367
if (*len > LOBREADSIZE) {
2368
readlen = LOBREADSIZE;
2377
while (readlen > 0 && bytes < *len && siz < loblen) { /* paranoia */
2378
CALL_OCI_RETURN(connection->error,
2380
connection->pServiceContext,
2383
&readlen, /* IN/OUT bytes toread/read */
2384
siz + 1, /* offset (starts with 1) */
2385
(dvoid *) ((char *) buf + bytes),
2386
readlen, /* size of buffer */
2388
(OCICallbackLobRead) 0, /* callback... */
2389
(ub2) connection->session->charsetId, /* The character set ID of the buffer data. */
2390
(ub1) SQLCS_IMPLICIT /* The character set form of the buffer data. */
2397
if ((*len - bytes) > LOBREADSIZE) {
2398
readlen = LOBREADSIZE;
2400
readlen = *len - bytes;
2403
if (connection->error == OCI_NEED_DATA) {
2404
buf = erealloc(buf,bytes + LOBREADSIZE + 1);
2411
/* moving current position */
2412
mydescr->lob_current_position = siz;
2414
if (connection->error) {
2415
oci_error(connection->pError, "OCILobRead", connection->error);
2416
oci_handle_error(connection, connection->error);
2421
if (mydescr->type == OCI_DTYPE_FILE) {
2422
CALL_OCI_RETURN(connection->error,
2424
connection->pServiceContext,
2430
if (connection->error) {
2431
oci_error(connection->pError, "OCILobFileClose", connection->error);
2432
oci_handle_error(connection, connection->error);
2438
buf = erealloc(buf,bytes+1);
2444
oci_debug("oci_readlob: size=%d",bytes);
2450
/* {{{ oci_failover_callback()
2452
#if 0 /* not needed yet ! */
2453
static sb4 oci_failover_callback(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx, ub4 fo_type, ub4 fo_event)
2456
this stuff is from an oci sample - it will get cleaned up as soon as i understand it!!! (thies@thieso.net 990420)
2457
right now i cant get oracle to even call it;-(((((((((((
2461
case OCI_FO_BEGIN: {
2462
printf(" Failing Over ... Please stand by \n");
2463
printf(" Failover type was found to be %s \n",
2464
((fo_type==OCI_FO_NONE) ? "NONE"
2465
:(fo_type==OCI_FO_SESSION) ? "SESSION"
2466
:(fo_type==OCI_FO_SELECT) ? "SELECT"
2468
printf(" Failover Context is :%s\n",
2469
(fo_ctx?(char *)fo_ctx:"NULL POINTER!"));
2473
case OCI_FO_ABORT: {
2474
printf(" Failover aborted. Failover will not take place.\n");
2479
printf(" Failover ended ...resuming services\n");
2483
case OCI_FO_REAUTH: {
2484
printf(" Failed over user. Resuming services\n");
2486
/* Application can check the OCI_ATTR_SESSION attribute of
2487
the service handle to find out the user being
2490
After this, the application can replay any ALTER SESSION
2491
commands associated with this session. These must have
2492
been saved by the application in the fo_ctx
2497
case OCI_FO_ERROR: {
2498
printf(" Failover error gotten. Sleeping...\n");
2500
/* cannot find this blody define !!! return OCI_FO_RETRY; */
2505
printf("Bad Failover Event: %ld.\n", fo_event);
2515
/* {{{ oci_bind_in_callback()
2517
static sb4 oci_bind_in_callback(
2518
dvoid *ictxp, /* context pointer */
2519
OCIBind *bindp, /* bind handle */
2520
ub4 iter, /* 0-based execute iteration value */
2521
ub4 index, /* index of current array for PL/SQL or row index for SQL */
2522
dvoid **bufpp, /* pointer to data */
2523
ub4 *alenp, /* size after value/piece has been read */
2524
ub1 *piecep, /* which piece */
2525
dvoid **indpp) /* indicator value */
2531
if (!(phpbind=(oci_bind *)ictxp) || !(val = phpbind->zval)) {
2532
php_error_docref(NULL TSRMLS_CC, E_WARNING, "!phpbind || !phpbind->val");
2536
if (ZVAL_IS_NULL(val)) {
2537
/* we're going to insert a NULL column */
2538
phpbind->indicator = -1;
2541
*indpp = (dvoid *)&phpbind->indicator;
2542
} else if ((phpbind->descr == 0) && (phpbind->pStmt == 0)) {
2543
/* "normal string bind */
2544
convert_to_string(val);
2546
*bufpp = Z_STRVAL_P(val);
2547
*alenp = Z_STRLEN_P(val);
2548
*indpp = (dvoid *)&phpbind->indicator;
2549
} else if (phpbind->pStmt != 0) {
2551
*bufpp = phpbind->pStmt;
2552
*alenp = -1; /* seems to be allright */
2553
*indpp = (dvoid *)&phpbind->indicator;
2555
/* descriptor bind */
2556
*bufpp = phpbind->descr;
2557
*alenp = -1; /* seems to be allright */
2558
*indpp = (dvoid *)&phpbind->indicator;
2561
*piecep = OCI_ONE_PIECE; /* pass all data in one go */
2563
return OCI_CONTINUE;
2567
/* {{{ oci_bind_out_callback() */
2568
static sb4 oci_bind_out_callback(
2569
dvoid *octxp, /* context pointer */
2570
OCIBind *bindp, /* bind handle */
2571
ub4 iter, /* 0-based execute iteration value */
2572
ub4 index, /* index of current array for PL/SQL or row index for SQL */
2573
dvoid **bufpp, /* pointer to data */
2574
ub4 **alenpp, /* size after value/piece has been read */
2575
ub1 *piecep, /* which piece */
2576
dvoid **indpp, /* indicator value */
2577
ub2 **rcodepp) /* return code */
2581
sb4 retval = OCI_ERROR;
2584
if (!(phpbind=(oci_bind *)octxp) || !(val = phpbind->zval)) {
2585
php_error_docref(NULL TSRMLS_CC, E_WARNING, "!phpbind || !phpbind->val");
2589
if ((Z_TYPE_P(val) == IS_OBJECT) || (Z_TYPE_P(val) == IS_RESOURCE)) {
2590
retval = OCI_CONTINUE;
2592
convert_to_string(val);
2595
Z_STRLEN_P(val) = OCI_PIECE_SIZE; /* 64K-1 is max XXX */
2596
Z_STRVAL_P(val) = emalloc(Z_STRLEN_P(phpbind->zval));
2598
/* XXX we assume that zend-zval len has 4 bytes */
2599
*alenpp = (ub4*) &Z_STRLEN_P(phpbind->zval);
2600
*bufpp = Z_STRVAL_P(phpbind->zval);
2601
*piecep = OCI_ONE_PIECE;
2602
*rcodepp = &phpbind->retcode;
2603
*indpp = &phpbind->indicator;
2604
retval = OCI_CONTINUE;
2611
/* {{{ _oci_open_session()
2613
#include "ext/standard/php_smart_str.h"
2614
static oci_session *_oci_open_session(oci_server* server,char *username,char *password,int persistent,int exclusive,char *charset)
2616
zend_llist *session_list;
2617
oci_session *session = NULL;
2618
OCISvcCtx *svchp = NULL;
2619
smart_str hashed_details = {0};
2626
check if we already have this user authenticated
2628
we will reuse authenticated users within a request no matter if the user requested a persistent
2631
but only as persistent requested connections will be kept between requests!
2634
#if defined(HAVE_OCI_9_2)
2636
smart_str_appends_ex(&hashed_details, charset, 1);
2640
/* Safe, charsetid is initialized to 0 */
2642
OCINlsEnvironmentVariableGet(
2651
smart_str_append_unsigned_ex(&hashed_details, charsetid, 1);
2657
char *nls_lang = getenv("NLS_LANG");
2659
/* extract charset from NLS_LANG=LANUAGE_TERRITORY.CHARSET */
2661
char *p = strchr(nls_lang, '.');
2664
smart_str_appends_ex(&hashed_details, p + 1, 1);
2670
smart_str_appends_ex(&hashed_details, SAFE_STRING(username), 1);
2671
smart_str_appends_ex(&hashed_details, SAFE_STRING(password), 1);
2672
smart_str_appends_ex(&hashed_details, SAFE_STRING(server->dbname), 1);
2673
smart_str_0(&hashed_details);
2676
mutex_lock(mx_lock);
2677
if (zend_ts_hash_find(persistent_sessions, hashed_details.c, hashed_details.len+1, (void **) &session_list) != SUCCESS) {
2679
/* first session, set up a session list */
2680
zend_llist_init(&tmp, sizeof(oci_session), (llist_dtor_func_t) _session_pcleanup, 1);
2681
zend_ts_hash_update(persistent_sessions, hashed_details.c, hashed_details.len+1, &tmp, sizeof(zend_llist), (void **) &session_list);
2684
/* session list found, search for an idle session or an already opened session by the current thread */
2685
session = zend_llist_get_first(session_list);
2686
while ((session != NULL) && session->thread && (session->thread != thread_id())) {
2687
session = zend_llist_get_next(session_list);
2690
if (session != NULL) {
2691
/* mark session as busy */
2692
session->thread = thread_id();
2698
if (session->is_open) {
2700
session->persistent = 1;
2702
smart_str_free_ex(&hashed_details, 1);
2703
mutex_unlock(mx_lock);
2706
_oci_close_session(session);
2707
/* breakthru to open */
2710
mutex_unlock(mx_lock);
2713
session = ecalloc(1,sizeof(oci_session));
2719
session->persistent = persistent;
2720
session->server = server;
2721
session->exclusive = exclusive;
2722
session->sessions_list = session_list;
2723
session->thread = thread_id();
2727
/* following chunk is Oracle 9i+ ONLY */
2730
get ub2 charset id based on charset
2731
this is pretty secure, since if we don't have a valid character set name,
2732
0 comes back and we can still use the 0 in all further statements -> OCI uses NLS_LANG
2733
setting in that case
2735
CALL_OCI_RETURN(charsetid,
2736
OCINlsCharSetNameToId(
2742
oci_debug("oci_do_connect: using charset id=%d",charsetid);
2745
session->charsetId = charsetid;
2747
/* create an environment using the character set id, Oracle 9i+ ONLY */
2765
/* fallback solution (simply use global env and charset, same behaviour as always been) */
2766
session->pEnv = OCI(pEnv);
2767
session->charsetId = 0;
2769
#endif /* HAVE_OCI_9_2 */
2771
/* allocate temporary Service Context */
2772
CALL_OCI_RETURN(OCI(error),
2782
if (OCI(error) != OCI_SUCCESS) {
2783
oci_error(OCI(pError), "_oci_open_session: OCIHandleAlloc OCI_HTYPE_SVCCTX", OCI(error));
2787
/* allocate private session-handle */
2788
CALL_OCI_RETURN(OCI(error),
2791
(dvoid **)&session->pSession,
2798
if (OCI(error) != OCI_SUCCESS) {
2799
oci_error(OCI(pError), "_oci_open_session: OCIHandleAlloc OCI_HTYPE_SESSION", OCI(error));
2803
/* Set the server handle in service handle */
2804
CALL_OCI_RETURN(OCI(error),
2815
if (OCI(error) != OCI_SUCCESS) {
2816
oci_error(OCI(pError), "_oci_open_session: OCIAttrSet OCI_ATTR_SERVER", OCI(error));
2820
/* set the username in user handle */
2821
CALL_OCI_RETURN(OCI(error),
2823
(dvoid *) session->pSession,
2824
(ub4) OCI_HTYPE_SESSION,
2826
(ub4) strlen(username),
2827
(ub4) OCI_ATTR_USERNAME,
2832
if (OCI(error) != OCI_SUCCESS) {
2833
oci_error(OCI(pError), "OCIAttrSet OCI_ATTR_USERNAME", OCI(error));
2837
/* set the password in user handle */
2838
CALL_OCI_RETURN(OCI(error),
2840
(dvoid *) session->pSession,
2841
(ub4) OCI_HTYPE_SESSION,
2843
(ub4) strlen(password),
2844
(ub4) OCI_ATTR_PASSWORD,
2849
if (OCI(error) != OCI_SUCCESS) {
2850
oci_error(OCI(pError), "OCIAttrSet OCI_ATTR_PASSWORD", OCI(error));
2854
CALL_OCI_RETURN(OCI(error),
2859
(ub4) OCI_CRED_RDBMS,
2864
if (OCI(error) != OCI_SUCCESS) {
2865
oci_error(OCI(pError), "OCISessionBegin", OCI(error));
2866
/* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
2867
* user's password has expired, but is still usable.
2869
if (OCI(error) != OCI_SUCCESS_WITH_INFO) {
2874
/* Free Temporary Service Context */
2878
(ub4) OCI_HTYPE_SVCCTX
2882
session->num = zend_list_insert(session, le_session);
2883
session->is_open = 1;
2885
mutex_lock(mx_lock);
2888
zend_llist_add_element(session_list, session);
2890
session = (oci_session*) session_list->tail->data;
2893
mutex_unlock(mx_lock);
2895
oci_debug("_oci_open_session new sess=%d user=%s",session->num,username);
2900
oci_debug("_oci_open_session: FAILURE -> CLEANUP called");
2902
_oci_close_session(session);
2908
/* {{{ _oci_close_session()
2910
static int _session_compare(void *a, void *b)
2912
oci_session *sess1 = (oci_session*) a;
2913
oci_session *sess2 = (oci_session*) b;
2915
return sess1->num == sess2->num;
2918
static void _oci_close_session(oci_session *session)
2927
oci_debug("START _oci_close_session: logging-off sess=%d",session->num);
2929
if (session->is_open) {
2930
/* Temporary Service Context */
2931
CALL_OCI_RETURN(OCI(error),
2935
(ub4) OCI_HTYPE_SVCCTX,
2941
if (OCI(error) != OCI_SUCCESS) {
2942
oci_error(OCI(pError), "_oci_close_session OCIHandleAlloc OCI_HTYPE_SVCCTX", OCI(error));
2945
/* Set the server handle in service handle */
2946
CALL_OCI_RETURN(OCI(error),
2950
session->server->pServer,
2957
if (OCI(error) != OCI_SUCCESS) {
2958
oci_error(OCI(pError), "_oci_close_session: OCIAttrSet OCI_ATTR_SERVER", OCI(error));
2961
/* Set the Authentication handle in the service handle */
2962
CALL_OCI_RETURN(OCI(error),
2973
if (OCI(error) != OCI_SUCCESS) {
2974
oci_error(OCI(pError), "_oci_close_session: OCIAttrSet OCI_ATTR_SESSION", OCI(error));
2977
CALL_OCI_RETURN(OCI(error),
2986
if (OCI(error) != OCI_SUCCESS) {
2987
oci_error(OCI(pError), "_oci_close_session: OCISessionEnd", OCI(error));
2993
(ub4) OCI_HTYPE_SVCCTX
2998
oci_debug("_oci_close_session: logging-off DEAD session");
3001
if (session->pSession) {
3004
(dvoid *) session->pSession,
3005
(ub4) OCI_HTYPE_SESSION
3010
mutex_lock(mx_lock);
3012
if (!OCI(shutdown) && session->persistent) {
3013
zend_llist_del_element(session->sessions_list, session, _session_compare);
3016
mutex_unlock(mx_lock);
3019
/* free environment handle (and fix bug #29652 with growing .msb FD number under weirdie Solarises) */
3022
(dvoid *) session->pEnv,
3028
if (session->exclusive) {
3034
/* {{{ _oci_open_server()
3036
static oci_server *_oci_open_server(char *dbname,int persistent)
3038
oci_server *server, *pserver = NULL;
3042
check if we already have this server open
3044
we will reuse servers within a request no matter if the user requested persistent
3047
but only as pesistent requested connections will be kept between requests!
3050
/* TODO either keep servers global or don't reuse them at all */
3051
zend_ts_hash_find(persistent_servers, dbname, strlen(dbname)+1, (void **) &pserver);
3056
if (!oci_ping(pserver)) {
3057
pserver->is_open = 0;
3060
if (pserver->is_open) {
3061
/* if our new users uses this connection persistent, we're keeping it! */
3063
pserver->persistent = persistent;
3067
} else { /* server "died" in the meantime - try to reconnect! */
3068
_oci_close_server(pserver);
3069
/* breakthru to open */
3073
server = ecalloc(1,sizeof(oci_server));
3075
server->persistent = persistent;
3076
server->dbname = strdup(SAFE_STRING(dbname));
3081
(dvoid **)&server->pServer,
3088
CALL_OCI_RETURN(OCI(error),
3092
(text*)server->dbname,
3093
strlen(server->dbname),
3099
oci_error(OCI(pError), "_oci_open_server", OCI(error));
3103
zend_ts_hash_update(persistent_servers,
3105
strlen(server->dbname)+1,
3110
pserver->num = zend_list_insert(pserver,le_server);
3111
pserver->is_open = 1;
3113
oci_debug("_oci_open_server new conn=%d dname=%s",server->num,server->dbname);
3120
oci_debug("_oci_open_server: FAILURE -> CLEANUP called");
3122
_oci_close_server(server);
3128
server->failover.fo_ctx = (dvoid *) server;
3129
server->failover.callback_function = oci_failover_callback;
3131
error = OCIAttrSet((dvoid *)server->pServer,
3132
(ub4) OCI_HTYPE_SERVER,
3133
(dvoid *) &server->failover,
3135
(ub4) OCI_ATTR_FOCBK,
3139
oci_error(OCI(pError), "_oci_open_server OCIAttrSet OCI_ATTR_FOCBK", error);
3145
/* {{{ _oci_close_server()
3147
static int _oci_session_cleanup(void *data TSRMLS_DC)
3149
zend_rsrc_list_entry *le = (zend_rsrc_list_entry *) data;
3151
if (le->type == le_session) {
3152
oci_server *server = ((oci_session*) le->ptr)->server;
3153
if (server && server->is_open == 2)
3159
static void _oci_close_server(oci_server *server)
3165
oldopen = server->is_open;
3166
server->is_open = 2;
3167
if (!OCI(shutdown)) {
3168
zend_hash_apply(&EG(regular_list), (apply_func_t) _oci_session_cleanup TSRMLS_CC);
3170
server->is_open = oldopen;
3172
oci_debug("START _oci_close_server: detaching conn=%d dbname=%s",server->num,server->dbname);
3174
/* XXX close server here */
3176
if (server->is_open) {
3177
if (server->pServer && OCI(pError)) {
3178
CALL_OCI_RETURN(OCI(error),
3187
oci_error(OCI(pError), "oci_close_server OCIServerDetach", OCI(error));
3191
oci_debug("_oci_close_server: closing DEAD server");
3194
if (server->pServer) {
3197
(dvoid *) server->pServer,
3198
(ub4) OCI_HTYPE_SERVER
3203
dbname = server->dbname;
3205
if (!OCI(shutdown)) {
3206
zend_ts_hash_del(persistent_servers, dbname, strlen(dbname)+1);
3213
/* {{{ oci_do_connect()
3214
Connect to an Oracle database and log on. returns a new session. */
3215
static void oci_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent,int exclusive)
3217
char *username, *password, *dbname, *charset;
3218
zval **userParam, **passParam, **dbParam, **charParam;
3219
oci_server *server = 0;
3220
oci_session *session = 0;
3221
oci_connection *connection = 0;
3223
/* if a forth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
3224
if (zend_get_parameters_ex(4, &userParam, &passParam, &dbParam, &charParam) == SUCCESS) {
3225
convert_to_string_ex(userParam);
3226
convert_to_string_ex(passParam);
3227
convert_to_string_ex(dbParam);
3228
convert_to_string_ex(charParam);
3230
username = Z_STRVAL_PP(userParam);
3231
password = Z_STRVAL_PP(passParam);
3232
dbname = Z_STRVAL_PP(dbParam);
3233
charset = Z_STRVAL_PP(charParam);
3234
oci_debug("oci_do_connect: using charset=%s",charset);
3235
} else if (zend_get_parameters_ex(3, &userParam, &passParam, &dbParam) == SUCCESS) {
3236
convert_to_string_ex(userParam);
3237
convert_to_string_ex(passParam);
3238
convert_to_string_ex(dbParam);
3240
username = Z_STRVAL_PP(userParam);
3241
password = Z_STRVAL_PP(passParam);
3242
dbname = Z_STRVAL_PP(dbParam);
3244
} else if (zend_get_parameters_ex(2, &userParam, &passParam) == SUCCESS) {
3245
convert_to_string_ex(userParam);
3246
convert_to_string_ex(passParam);
3248
username = Z_STRVAL_PP(userParam);
3249
password = Z_STRVAL_PP(passParam);
3256
connection = (oci_connection *) ecalloc(1,sizeof(oci_connection));
3262
server = _oci_open_server(dbname,persistent);
3269
/* exlusive session can never be persistent!*/
3272
/* if our server-context is not persistent we can't */
3273
persistent = (server->persistent) ? persistent : 0;
3276
session = _oci_open_session(server,username,password,persistent,exclusive,charset);
3282
/* set our session */
3283
connection->session = session;
3285
/* allocate our private error-handle */
3286
CALL_OCI_RETURN(OCI(error),
3288
connection->session->pEnv,
3289
(dvoid **)&connection->pError,
3296
if (OCI(error) != OCI_SUCCESS) {
3297
oci_error(OCI(pError), "oci_do_connect: OCIHandleAlloc OCI_HTYPE_ERROR",OCI(error));
3301
/* allocate our service-context */
3302
CALL_OCI_RETURN(OCI(error),
3304
connection->session->pEnv,
3305
(dvoid **)&connection->pServiceContext,
3312
if (OCI(error) != OCI_SUCCESS) {
3313
oci_error(OCI(pError), "oci_do_connect: OCIHandleAlloc OCI_HTYPE_SVCCTX",OCI(error));
3317
/* Set the server handle in service handle */
3318
CALL_OCI_RETURN(connection->error,
3320
connection->pServiceContext,
3329
if (connection->error != OCI_SUCCESS) {
3330
oci_error(connection->pError, "oci_do_connect: OCIAttrSet OCI_ATTR_SERVER", connection->error);
3334
/* Set the Authentication handle in the service handle */
3335
CALL_OCI_RETURN(connection->error,
3337
connection->pServiceContext,
3346
if (connection->error != OCI_SUCCESS) {
3347
oci_error(connection->pError, "oci_do_connect: OCIAttrSet OCI_ATTR_SESSION", connection->error);
3352
OCIAttrSet((dvoid *)session->server->pServer,
3356
OCI_ATTR_EXTERNAL_NAME,
3357
connection->pError);
3359
OCIAttrSet((dvoid *)session->server->pServer,
3361
(dvoid *) "txn demo2",
3363
OCI_ATTR_INTERNAL_NAME,
3364
connection->pError);
3367
connection->id = zend_list_insert(connection, le_conn);
3369
connection->is_open = 1;
3371
oci_debug("oci_do_connect: id=%d",connection->id);
3373
RETURN_RESOURCE(connection->id);
3376
oci_debug("oci_do_connect: FAILURE -> CLEANUP called");
3378
if (connection->id) {
3379
zend_list_delete(connection->id);
3381
_oci_conn_list_dtor(connection TSRMLS_CC);
3388
/* {{{ oci_lob_flush()
3390
static int oci_lob_flush(oci_descriptor* descr, int flush_flag TSRMLS_DC)
3392
OCILobLocator *mylob;
3393
oci_connection *connection;
3395
mylob = (OCILobLocator *) descr->ocidescr;
3401
/* do not really flush buffer, but reporting success
3402
* to suppress OCI error when flushing not used buffer
3404
if (descr->buffering != 2) {
3408
connection = descr->conn;
3410
CALL_OCI_RETURN(connection->error,
3412
connection->pServiceContext,
3419
oci_debug("oci_lob_flush: flush_flag=%d",flush_flag);
3421
if (connection->error) {
3422
oci_error(connection->pError, "OCILobFlushBuffer", connection->error);
3423
oci_handle_error(connection, connection->error);
3427
/* marking buffer as enabled and not used */
3428
descr->buffering = 1;
3433
/* {{{ php_oci_fetch_row()
3435
static void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
3437
zval **stmt, **arg2, **arg3;
3438
oci_statement *statement;
3439
oci_out_column *column;
3443
if (ZEND_NUM_ARGS() > expected_args) {
3447
if (expected_args > 2) {
3448
/* only for ocifetchinto BC */
3450
switch (ZEND_NUM_ARGS()) {
3452
if (zend_get_parameters_ex(2, &stmt, &arg2) == FAILURE) {
3461
if (zend_get_parameters_ex(3, &stmt, &arg2, &arg3) == FAILURE) {
3464
convert_to_long_ex(arg3);
3465
mode = Z_LVAL_PP(arg3);
3475
switch (ZEND_NUM_ARGS()) {
3477
if (zend_get_parameters_ex(1, &stmt) == FAILURE) {
3486
if (zend_get_parameters_ex(2, &stmt, &arg2)==FAILURE) {
3489
convert_to_long_ex(arg2);
3490
mode = Z_LVAL_PP(arg2);
3499
OCI_GET_STMT(statement,stmt);
3501
if (!oci_fetch(statement, nrows, "OCIFetchInto" TSRMLS_CC)) {
3505
array_init(return_value);
3507
for (i = 0; i < statement->ncolumns; i++) {
3508
column = oci_get_col(statement, i + 1, 0);
3509
if (column == NULL) {
3512
if ((column->indicator == -1) && ((mode & OCI_RETURN_NULLS) == 0)) {
3516
if (!(column->indicator == -1)) {
3519
MAKE_STD_ZVAL(element);
3520
_oci_make_zval(element,statement,column,"OCIFetchInto",mode TSRMLS_CC);
3522
if (mode & OCI_NUM || !(mode & OCI_ASSOC)) {
3523
add_index_zval(return_value, i, element);
3525
if (mode & OCI_ASSOC) {
3526
if (mode & OCI_NUM) {
3527
ZVAL_ADDREF(element);
3529
add_assoc_zval(return_value, column->name, element);
3533
if (mode & OCI_NUM || !(mode & OCI_ASSOC)) {
3534
add_index_null(return_value, i);
3536
if (mode & OCI_ASSOC) {
3537
add_assoc_null(return_value, column->name);
3542
if (expected_args > 2) {
3543
/* only for ocifetchinto BC
3544
* in all other cases we return array, not long
3546
REPLACE_ZVAL_VALUE(arg2, return_value, 1); /* copy return_value to given reference */
3547
zval_dtor(return_value);
3548
RETURN_LONG(statement->ncolumns);
3553
/************************* EXTENSION FUNCTIONS *************************/
3555
/* {{{ proto bool oci_define_by_name(resource stmt, string name, mixed &var [, int type])
3556
Define a PHP variable to an Oracle column by name */
3557
/* if you want to define a LOB/CLOB etc make sure you allocate it via OCINewDescriptor BEFORE defining!!! */
3558
PHP_FUNCTION(oci_define_by_name)
3560
zval **stmt, **name, **var, **type;
3561
oci_statement *statement;
3562
oci_define *define, *tmp_define;
3563
ub2 ocitype = SQLT_CHR; /* zero terminated string */
3564
int ac = ZEND_NUM_ARGS();
3566
if (ac < 3 || ac > 4 || zend_get_parameters_ex(ac, &stmt, &name, &var, &type) == FAILURE) {
3572
convert_to_long_ex(type);
3573
ocitype = (ub2) Z_LVAL_PP(type);
3574
/* possible breakthru */
3577
OCI_GET_STMT(statement,stmt);
3579
convert_to_string_ex(name);
3581
if (statement->defines == NULL) {
3582
ALLOC_HASHTABLE(statement->defines);
3583
zend_hash_init(statement->defines, 13, NULL, _oci_define_hash_dtor, 0);
3586
define = ecalloc(1,sizeof(oci_define));
3588
if (zend_hash_add(statement->defines,
3593
(void **)&tmp_define) == SUCCESS) {
3595
define = tmp_define;
3601
define->name = (text*) estrndup(Z_STRVAL_PP(name),Z_STRLEN_PP(name));
3602
define->name_len = Z_STRLEN_PP(name);
3603
define->type = ocitype;
3604
define->zval = *var;
3611
/* {{{ proto bool oci_bind_by_name(resource stmt, string name, mixed &var, [, int maxlength [, int type]])
3612
Bind a PHP variable to an Oracle placeholder by name */
3613
/* if you want to bind a LOB/CLOB etc make sure you allocate it via OCINewDescriptor BEFORE binding!!! */
3614
PHP_FUNCTION(oci_bind_by_name)
3616
zval **stmt, **name, **var, **maxlen, **type;
3617
oci_statement *statement;
3618
oci_statement *bindstmt;
3619
oci_bind bind, *bindp;
3620
oci_descriptor *descr;
3621
#ifdef PHP_OCI8_HAVE_COLLECTIONS
3622
oci_collection *coll;
3625
int mode = OCI_DATA_AT_EXEC;
3626
ub2 ocitype = SQLT_CHR; /* unterminated string */
3627
OCIStmt *mystmt = 0;
3630
int ac = ZEND_NUM_ARGS(), inx;
3632
if (ac < 3 || ac > 5 || zend_get_parameters_ex(ac, &stmt, &name, &var, &maxlen, &type) == FAILURE) {
3638
convert_to_long_ex(type);
3639
ocitype = (ub2) Z_LVAL_PP(type);
3640
/* possible breakthru */
3642
convert_to_long_ex(maxlen);
3643
value_sz = Z_LVAL_PP(maxlen);
3644
/* possible breakthru */
3647
OCI_GET_STMT(statement,stmt);
3650
#ifdef PHP_OCI8_HAVE_COLLECTIONS
3652
if (Z_TYPE_PP(var) != IS_OBJECT) {
3653
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Variable must be allocated using OCINewCollection()");
3656
if ((inx = _oci_get_ocicoll(*var,&coll TSRMLS_CC)) == 0) {
3657
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Variable must be allocated using OCINewCollection()");
3660
if (!(mycoll = (dvoid *) coll->coll)) {
3661
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Collection empty");
3664
value_sz = sizeof(void*);
3673
if (Z_TYPE_PP(var) != IS_OBJECT) {
3674
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Variable must be allocated using OCINewDescriptor()");
3678
if ((inx = _oci_get_ocidesc(*var,&descr TSRMLS_CC)) == 0) {
3679
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Variable must be allocated using OCINewDescriptor()");
3683
if (!(mydescr = (dvoid *) descr->ocidescr)) {
3684
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Descriptor empty");
3687
value_sz = sizeof(void*);
3691
OCI_GET_STMT(bindstmt,var);
3693
if (!(mystmt = bindstmt->pStmt)) {
3696
value_sz = sizeof(void*);
3701
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %u", ocitype);
3706
if ((ocitype == SQLT_CHR) && (value_sz == -1)) {
3707
convert_to_string_ex(var);
3708
value_sz = Z_STRLEN_PP(var);
3711
if (value_sz == 0) {
3715
convert_to_string_ex(name);
3717
if (!statement->binds) {
3718
ALLOC_HASHTABLE(statement->binds);
3719
zend_hash_init(statement->binds, 13, NULL, _oci_bind_hash_dtor, 0);
3722
memset((void*)&bind,0,sizeof(oci_bind));
3723
zend_hash_update(statement->binds, Z_STRVAL_PP(name), Z_STRLEN_PP(name) + 1, &bind, sizeof(oci_bind), (void **)&bindp);
3725
bindp->descr = mydescr;
3726
bindp->pStmt = mystmt;
3730
CALL_OCI_RETURN(statement->error,
3732
statement->pStmt, /* statement handle */
3733
(OCIBind **)&bindp->pBind, /* bind hdl (will alloc) */
3734
statement->pError, /* error handle */
3735
(text*) Z_STRVAL_PP(name), /* placeholder name */
3736
Z_STRLEN_PP(name), /* placeholder length */
3737
(dvoid *)0, /* in/out data */
3738
value_sz, /* OCI_MAX_DATA_SIZE, */ /* max size of input/output data */
3739
(ub2)ocitype, /* in/out data type */
3740
(dvoid *)&bindp->indicator, /* indicator (ignored) */
3741
(ub2 *)0, /* size array (ignored) */
3742
(ub2 *)&bindp->retcode, /* return code (ignored) */
3743
(ub4)0, /* maxarr_len (PL/SQL only?) */
3744
(ub4 *)0, /* actual array size (PL/SQL only?) */
3749
if (statement->error != OCI_SUCCESS) {
3750
oci_error(statement->pError, "OCIBindByName", statement->error);
3751
oci_handle_error(statement->conn, statement->error);
3755
if (mode == OCI_DATA_AT_EXEC) {
3756
CALL_OCI_RETURN(statement->error,
3761
oci_bind_in_callback,
3763
oci_bind_out_callback
3767
if (statement->error != OCI_SUCCESS) {
3768
oci_error(statement->pError, "OCIBindDynamic", statement->error);
3769
oci_handle_error(statement->conn, statement->error);
3774
#ifdef PHP_OCI8_HAVE_COLLECTIONS
3775
if (ocitype == SQLT_NTY) {
3777
CALL_OCI_RETURN(statement->error,
3782
(dvoid **) &(coll->coll),
3789
if (statement->error) {
3790
oci_error(statement->pError, "OCIBindObject", statement->error);
3800
/* {{{ proto bool oci_free_descriptor()
3801
Deletes large object description */
3802
PHP_FUNCTION(oci_free_descriptor)
3806
oci_descriptor *descriptor;
3808
if ((id = getThis()) != 0) {
3809
inx = _oci_get_ocidesc(id,&descriptor TSRMLS_CC);
3811
oci_debug("oci_free_descriptor: descr=%d",inx);
3812
zend_list_delete(inx);
3817
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_free_descriptor() should not be called like this. Use $somelob->free() to free a LOB");
3823
/* {{{ proto bool oci_lob_save( string data [, int offset ])
3824
Saves a large object */
3825
PHP_FUNCTION(oci_lob_save)
3827
zval *id, **arg,**oarg;
3828
OCILobLocator *mylob;
3829
oci_connection *connection;
3830
oci_descriptor *descr;
3836
if ((id = getThis()) != 0) {
3837
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
3841
mylob = (OCILobLocator *) descr->ocidescr;
3847
connection = descr->conn;
3850
if (zend_get_parameters_ex(2, &arg, &oarg) == SUCCESS) {
3851
convert_to_long_ex(oarg);
3852
offparam = Z_LVAL_PP(oarg);
3854
CALL_OCI_RETURN(connection->error,
3856
connection->pServiceContext,
3863
oci_debug("oci_lob_save: curloblen=%d",curloblen);
3865
if (offparam == -1) {
3867
} else if ((ub4)offparam >= curloblen) {
3868
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is bigger than current LOB-Size - appending");
3871
offset = (ub4)offparam;
3873
} else if (zend_get_parameters_ex(1, &arg) == FAILURE) {
3877
convert_to_string_ex(arg);
3878
loblen = Z_STRLEN_PP(arg);
3881
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot save a lob which size is less than 1 byte");
3889
CALL_OCI_RETURN(connection->error,
3891
connection->pServiceContext,
3896
(dvoid *) Z_STRVAL_PP(arg),
3900
(OCICallbackLobWrite) 0,
3902
(ub1) SQLCS_IMPLICIT
3906
oci_debug("oci_lob_save: size=%d offset=%d",loblen,offset);
3908
if (connection->error) {
3909
oci_error(connection->pError, "OCILobWrite", connection->error);
3910
oci_handle_error(connection, connection->error);
3921
/* {{{ proto bool oci_lob_import( string filename )
3922
Saves a large object to file */
3923
PHP_FUNCTION(oci_lob_import)
3926
OCILobLocator *mylob;
3927
oci_connection *connection;
3928
oci_descriptor *descr;
3935
if ((id = getThis()) != 0) {
3936
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
3940
mylob = (OCILobLocator *) descr->ocidescr;
3946
connection = descr->conn;
3948
if (zend_get_parameters_ex(1, &arg) == FAILURE) {
3952
convert_to_string_ex(arg);
3954
if (php_check_open_basedir(Z_STRVAL_PP(arg) TSRMLS_CC)) {
3958
filename = Z_STRVAL_PP(arg);
3960
if ((fp = VCWD_OPEN(filename, O_RDONLY|O_BINARY)) == -1) {
3961
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't open file %s", filename);
3965
while ((loblen = read(fp, &buf, sizeof(buf))) > 0) {
3966
CALL_OCI_RETURN(connection->error,
3968
connection->pServiceContext,
3977
(OCICallbackLobWrite) 0,
3979
(ub1) SQLCS_IMPLICIT
3983
oci_debug("oci_lob_import: size=%d",loblen);
3985
if (connection->error) {
3986
oci_error(connection->pError, "OCILobWrite", connection->error);
3987
oci_handle_error(connection, connection->error);
4003
/* {{{ proto string oci_lob_load()
4004
Loads a large object */
4005
PHP_FUNCTION(oci_lob_load)
4008
oci_descriptor *descr;
4013
if ((id = getThis()) != 0) {
4014
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4018
if (!oci_loadlob(descr->conn,descr,&buffer,&loblen)) {
4019
RETURN_STRINGL(buffer,loblen,0);
4025
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_load() should not be called like this. Use $somelob->load() to load a LOB");
4031
/* {{{ proto string oci_lob_read( int length )
4032
Reads particular part of a large object */
4033
PHP_FUNCTION(oci_lob_read)
4037
oci_descriptor *descr;
4042
if ((id = getThis()) != 0) {
4043
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4047
if (zend_get_parameters_ex(1, &len) == FAILURE) {
4051
loblen = Z_LVAL_PP(len);
4052
if (oci_readlob(descr->conn,descr,&buffer,&loblen) == 0) {
4053
RETURN_STRINGL(buffer,loblen,0);
4059
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_read() should not be called like this. Use $somelob->read($len) to read a LOB");
4064
/* {{{ proto bool oci_lob_eof()
4065
Checks if EOF is reached */
4066
PHP_FUNCTION(oci_lob_eof)
4069
oci_descriptor *descr;
4073
if ((id = getThis()) != 0) {
4074
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4078
if (oci_lobgetlen(descr->conn,descr,&len) == 0 && descr->lob_size >= 0) {
4079
if (descr->lob_size == descr->lob_current_position) {
4088
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_eof() should not be called like this. Use $somelob->eof() to check if end of LOB is reached");
4093
/* {{{ proto int oci_lob_tell()
4094
Tells LOB pointer position */
4095
PHP_FUNCTION(oci_lob_tell)
4098
oci_descriptor *descr;
4101
if ((id = getThis()) != 0) {
4102
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4105
RETURN_LONG(descr->lob_current_position);
4108
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_tell() should not be called like this. Use $somelob->tell() to get current position of LOB pointer");
4113
/* {{{ proto bool oci_lob_rewind()
4114
Rewind pointer of a LOB */
4115
PHP_FUNCTION(oci_lob_rewind)
4118
oci_descriptor *descr;
4121
if ((id = getThis()) != 0) {
4122
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4125
descr->lob_current_position = 0;
4129
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_rewind() should not be called like this. Use $somelob->rewind() to set current position of LOB pointer to beginning");
4134
/* {{{ proto bool oci_lob_seek( int offset [, int whence ])
4135
Moves the pointer of a LOB */
4136
PHP_FUNCTION(oci_lob_seek)
4139
zval **arg1, **arg2;
4140
int argcount = ZEND_NUM_ARGS(), whence = OCI_SEEK_SET;
4141
oci_descriptor *descr;
4144
if ((id = getThis()) != 0) {
4145
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4149
if (argcount < 1 || argcount > 2 || zend_get_parameters_ex(argcount, &arg1, &arg2) == FAILURE) {
4153
convert_to_long_ex(arg1);
4155
if (oci_lobgetlen(descr->conn,descr,&len) == 0 && descr->lob_size >= 0) {
4157
convert_to_long_ex(arg2);
4158
whence = Z_LVAL_PP(arg2);
4161
descr->lob_current_position += Z_LVAL_PP(arg1);
4165
if (descr->lob_size + Z_LVAL_PP(arg1) >= 0) {
4166
descr->lob_current_position = descr->lob_size + Z_LVAL_PP(arg1);
4168
descr->lob_current_position = 0;
4174
descr->lob_current_position = Z_LVAL_PP(arg1);
4178
/* OCI_SEEK_SET by default */
4179
descr->lob_current_position = Z_LVAL_PP(arg1);
4187
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_seek() should not be called like this. Use $somelob->seek($offset) to move pointer");
4192
/* {{{ proto int oci_lob_size()
4193
Returns size of a large object */
4194
PHP_FUNCTION(oci_lob_size)
4197
oci_descriptor *descr;
4201
if ((id = getThis()) != 0) {
4202
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4206
if (!oci_lobgetlen(descr->conn,descr,&loblen)) {
4207
RETURN_LONG(loblen);
4213
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_size() should not be called like this. Use $somelob->size() to get size of a LOB");
4218
/* {{{ proto int oci_lob_write( string string [, int length ])
4219
Writes data to current position of a LOB */
4220
PHP_FUNCTION(oci_lob_write)
4222
zval *id, **data,**length;
4223
OCILobLocator *mylob;
4224
oci_connection *connection;
4225
oci_descriptor *descr;
4226
int write_length,inx;
4230
if ((id = getThis()) != 0) {
4231
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4235
IS_LOB_INTERNAL(descr);
4237
mylob = (OCILobLocator *) descr->ocidescr;
4243
connection = descr->conn;
4245
if (oci_lobgetlen(descr->conn,descr,&curloblen) != 0) {
4249
if (zend_get_parameters_ex(2, &data, &length) == SUCCESS) {
4250
convert_to_string_ex(data);
4251
convert_to_long_ex(length);
4252
write_length = Z_LVAL_PP(length);
4253
} else if (zend_get_parameters_ex(1, &data) == SUCCESS) {
4254
convert_to_string_ex(data);
4255
write_length = Z_STRLEN_PP(data);
4260
if (write_length < 1) {
4264
loblen = write_length;
4266
CALL_OCI_RETURN(connection->error,
4268
connection->pServiceContext,
4272
(ub4) descr->lob_current_position+1,
4273
(dvoid *) Z_STRVAL_PP(data),
4277
(OCICallbackLobWrite) 0,
4279
(ub1) SQLCS_IMPLICIT
4283
oci_debug("oci_lob_write: size=%d offset=%d",loblen,descr->lob_current_position);
4285
if (connection->error) {
4286
oci_error(connection->pError, "OCILobWrite", connection->error);
4287
oci_handle_error(connection, connection->error);
4291
descr->lob_current_position += loblen;
4293
if (descr->lob_current_position > descr->lob_size) {
4294
descr->lob_size = descr->lob_current_position;
4297
/* marking buffer as used */
4298
if (descr->buffering == 1) {
4299
descr->buffering = 2;
4301
RETURN_LONG(loblen);
4304
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_write() should not be called like this. Use $somelob->write($data,$len) to write to a LOB");
4309
/* {{{ proto bool oci_lob_append( object lob )
4310
Appends data from a LOB to another LOB */
4311
PHP_FUNCTION(oci_lob_append)
4314
OCILobLocator *mylob,*my_fromlob;
4315
oci_connection *connection;
4316
oci_descriptor *descr,*from_descr;
4318
ub4 curloblen,from_curloblen;
4320
if ((id = getThis()) != 0) {
4321
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4325
IS_LOB_INTERNAL(descr);
4327
mylob = (OCILobLocator *) descr->ocidescr;
4333
connection = descr->conn;
4335
if (oci_lobgetlen(descr->conn,descr,&curloblen) != 0) {
4339
if (zend_get_parameters_ex(1, &arg) == SUCCESS) {
4340
convert_to_object_ex(arg);
4341
if ((inx = _oci_get_ocidesc(*arg,&from_descr TSRMLS_CC)) == 0) {
4345
my_fromlob = (OCILobLocator *) from_descr->ocidescr;
4351
if (oci_lobgetlen(from_descr->conn,from_descr,&from_curloblen) != 0) {
4358
if (from_descr->lob_size == 0) {
4362
CALL_OCI_RETURN(connection->error,
4364
connection->pServiceContext,
4371
if (connection->error) {
4372
oci_error(connection->pError, "OCILobAppend", connection->error);
4373
oci_handle_error(connection, connection->error);
4380
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_append() should not be called like this. Use $somelob->append($LOB_from) to append data from a LOB to another LOB");
4385
/* {{{ proto bool oci_lob_truncate( [ int length ])
4387
PHP_FUNCTION(oci_lob_truncate)
4390
OCILobLocator *mylob;
4391
oci_connection *connection;
4392
oci_descriptor *descr;
4397
if ((id = getThis()) != 0) {
4398
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4402
IS_LOB_INTERNAL(descr);
4404
mylob = (OCILobLocator *) descr->ocidescr;
4410
connection = descr->conn;
4412
if (oci_lobgetlen(descr->conn,descr,&curloblen) != 0) {
4416
if (zend_get_parameters_ex(1, &length) == SUCCESS) {
4417
convert_to_long_ex(length);
4418
trim_length = Z_LVAL_PP(length);
4423
if (trim_length < 0) {
4424
/* negative length is not allowed */
4428
CALL_OCI_RETURN(connection->error,
4430
connection->pServiceContext,
4437
oci_debug("oci_lob_truncate: trim_length=%d",trim_length);
4439
if (connection->error) {
4440
oci_error(connection->pError, "OCILobTrim", connection->error);
4441
oci_handle_error(connection, connection->error);
4445
descr->lob_size = trim_length;
4449
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_truncate() should not be called like this. Use $somelob->truncate($length) to truncate a LOB to a specified length");
4454
/* {{{ proto int oci_lob_erase( [ int offset [, int length ] ] )
4455
Erases a specified portion of the internal LOB, starting at a specified offset */
4456
PHP_FUNCTION(oci_lob_erase)
4458
zval *id, **length, **offset;
4459
OCILobLocator *mylob;
4460
oci_connection *connection;
4461
oci_descriptor *descr;
4463
ub4 erase_length, erase_offset;
4466
if ((id = getThis()) != 0) {
4467
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4471
IS_LOB_INTERNAL(descr);
4473
mylob = (OCILobLocator *) descr->ocidescr;
4479
connection = descr->conn;
4481
if (oci_lobgetlen(descr->conn,descr,&curloblen) != 0) {
4485
if (zend_get_parameters_ex(2, &offset, &length) == SUCCESS) {
4486
convert_to_long_ex(offset);
4487
convert_to_long_ex(length);
4489
erase_offset = Z_LVAL_PP(offset);
4490
erase_length = Z_LVAL_PP(length);
4491
} else if (zend_get_parameters_ex(1, &offset) == SUCCESS) {
4492
convert_to_long_ex(offset);
4494
erase_offset = Z_LVAL_PP(offset);
4495
erase_length = descr->lob_size - erase_offset;
4498
erase_length = descr->lob_size;
4501
if (erase_length < 1) {
4505
if (erase_offset > descr->lob_size) {
4506
php_error_docref(NULL TSRMLS_CC, E_WARNING, "oci_lob_erase(): offset is greater than LOB's length");
4509
CALL_OCI_RETURN(connection->error,
4511
connection->pServiceContext,
4519
oci_debug("oci_lob_erase: erase_length=%d, erase_offset=%d",erase_length,erase_offset);
4521
if (connection->error) {
4522
oci_error(connection->pError, "OCILobErase", connection->error);
4523
oci_handle_error(connection, connection->error);
4527
RETURN_LONG(erase_length);
4530
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_erase() should not be called like this. Use $somelob->erase($offset, $length) to erase specified part of LOB");
4535
/* {{{ proto bool oci_lob_flush( [ int flag ] )
4536
Flushes the LOB buffer */
4537
PHP_FUNCTION(oci_lob_flush)
4540
OCILobLocator *mylob;
4541
oci_connection *connection;
4542
oci_descriptor *descr;
4543
int inx, flush_flag;
4545
if ((id = getThis()) != 0) {
4546
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4550
IS_LOB_INTERNAL(descr);
4552
mylob = (OCILobLocator *) descr->ocidescr;
4558
connection = descr->conn;
4560
if (zend_get_parameters_ex(1, &flag) == SUCCESS) {
4561
convert_to_long_ex(flag);
4562
flush_flag = Z_LVAL_PP(flag);
4567
if (descr->buffering == 0) {
4568
/* buffering wasn't enabled, there is nothing to flush */
4572
if (oci_lob_flush(descr,flush_flag TSRMLS_CC) == 1) {
4578
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_flush() should not be called like this. Use $somelob->flush() to flush LOB buffer");
4583
/* {{{ proto bool ocisetbufferinglob( boolean flag )
4584
Enables/disables buffering for a LOB */
4585
PHP_FUNCTION(ocisetbufferinglob)
4588
OCILobLocator *mylob;
4589
oci_connection *connection;
4590
oci_descriptor *descr;
4591
int inx, buffering_flag;
4594
if ((id = getThis()) != 0) {
4595
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4599
IS_LOB_INTERNAL(descr);
4601
mylob = (OCILobLocator *) descr->ocidescr;
4607
connection = descr->conn;
4609
if (oci_lobgetlen(descr->conn,descr,&curloblen) != 0) {
4613
if (zend_get_parameters_ex(1, &flag) == SUCCESS) {
4614
convert_to_boolean_ex(flag);
4615
buffering_flag = Z_LVAL_PP(flag);
4620
/* we'll return true if function was called twice with the same parameter */
4621
if (buffering_flag == 0 && descr->buffering == 0) {
4623
} else if (buffering_flag == 1 && descr->buffering > 0) {
4627
switch (buffering_flag) {
4629
CALL_OCI_RETURN(connection->error,
4630
OCILobDisableBuffering(
4631
connection->pServiceContext,
4638
CALL_OCI_RETURN(connection->error,
4639
OCILobEnableBuffering(
4640
connection->pServiceContext,
4648
oci_debug("oci_lob_set_buffering: buffering_flag=%d",buffering_flag);
4650
if (connection->error) {
4651
oci_error(connection->pError, "OCILobFlushBuffer", connection->error);
4652
oci_handle_error(connection, connection->error);
4656
descr->buffering = buffering_flag;
4660
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OCISetBufferingLob() should not be called like this. Use $somelob->setBuffering($flag) to set buffering on/off for a LOB");
4665
/* {{{ proto bool ocigetbufferinglob()
4666
Returns current state of buffering for a LOB */
4667
PHP_FUNCTION(ocigetbufferinglob)
4670
OCILobLocator *mylob;
4671
oci_descriptor *descr;
4674
if ((id = getThis()) != 0) {
4675
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4679
IS_LOB_INTERNAL(descr);
4681
mylob = (OCILobLocator *) descr->ocidescr;
4687
switch (descr->buffering) {
4700
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OCIGetBufferingLob() should not be called like this. Use $somelob->getBuffering() to get current state of buffering for a LOB");
4705
/* {{{ proto bool oci_lob_copy( object lob_to, object lob_from [, int length ] )
4706
Copies data from a LOB to another LOB */
4707
PHP_FUNCTION(oci_lob_copy)
4709
zval **arg1, **arg2, **arg3;
4710
OCILobLocator *mylob,*my_fromlob;
4711
oci_connection *connection;
4712
oci_descriptor *descr,*from_descr;
4713
int inx, ac = ZEND_NUM_ARGS();
4714
ub4 curloblen,from_curloblen, copylen;
4716
if (ac < 2 || ac > 3 || zend_get_parameters_ex(ac, &arg1, &arg2, &arg3) == FAILURE) {
4720
convert_to_object_ex(arg1);
4721
convert_to_object_ex(arg2);
4723
if ((inx = _oci_get_ocidesc(*arg1,&descr TSRMLS_CC)) == 0 || (inx = _oci_get_ocidesc(*arg2,&from_descr TSRMLS_CC)) == 0) {
4727
IS_LOB_INTERNAL(descr);
4728
IS_LOB_INTERNAL(from_descr);
4730
mylob = (OCILobLocator *) descr->ocidescr;
4731
my_fromlob = (OCILobLocator *) from_descr->ocidescr;
4733
if (!mylob || !my_fromlob) {
4737
if (oci_lobgetlen(descr->conn,descr,&curloblen) != 0 || oci_lobgetlen(from_descr->conn,from_descr,&from_curloblen) != 0) {
4742
convert_to_long_ex(arg3);
4743
copylen = Z_LVAL_PP(arg3);
4745
copylen = from_descr->lob_size - from_descr->lob_current_position;
4748
if ((int)copylen <= 0) {
4752
connection = descr->conn;
4754
CALL_OCI_RETURN(connection->error,
4756
connection->pServiceContext,
4761
descr->lob_current_position+1,
4762
from_descr->lob_current_position+1
4766
if (connection->error) {
4767
oci_error(connection->pError, "OCILobCopy", connection->error);
4768
oci_handle_error(connection, connection->error);
4776
/* {{{ proto bool oci_lob_is_equal( object lob1, object lob2 )
4777
Tests to see if two LOB/FILE locators are equal */
4778
PHP_FUNCTION(oci_lob_is_equal)
4780
zval **arg1, **arg2;
4781
OCILobLocator *first_lob,*second_lob;
4782
oci_connection *connection;
4783
oci_descriptor *first_descr,*second_descr;
4787
if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
4791
convert_to_object_ex(arg1);
4792
convert_to_object_ex(arg2);
4794
if ((inx = _oci_get_ocidesc(*arg1,&first_descr TSRMLS_CC)) == 0 || (inx = _oci_get_ocidesc(*arg2,&second_descr TSRMLS_CC)) == 0) {
4798
first_lob = (OCILobLocator *) first_descr->ocidescr;
4799
second_lob = (OCILobLocator *) second_descr->ocidescr;
4801
if (!first_lob || !second_lob) {
4805
connection = first_descr->conn;
4807
CALL_OCI_RETURN(connection->error,
4809
connection->session->pEnv,
4816
if (connection->error) {
4817
oci_error(connection->pError, "OCILobIsEqual", connection->error);
4818
oci_handle_error(connection, connection->error);
4822
if (is_equal == TRUE) {
4830
/* {{{ proto bool oci_lob_export([string filename [, int start [, int length]]])
4831
Writes a large object into a file */
4832
PHP_FUNCTION(oci_lob_export)
4834
zval *id, **zfilename, **zstart, **zlength;
4835
char *filename = NULL;
4838
oci_connection *connection;
4839
oci_descriptor *descr;
4842
int ac = ZEND_NUM_ARGS();
4844
OCILobLocator *mylob;
4847
if ((id = getThis()) != 0) {
4848
if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
4852
mylob = (OCILobLocator *) descr->ocidescr;
4858
connection = descr->conn;
4860
if (ac < 0 || ac > 3 || zend_get_parameters_ex(ac, &zfilename, &zstart, &zlength) == FAILURE) {
4866
convert_to_long_ex(zlength);
4867
length = Z_LVAL_PP(zlength);
4869
convert_to_long_ex(zstart);
4870
start = Z_LVAL_PP(zstart);
4872
convert_to_string_ex(zfilename);
4873
filename = Z_STRVAL_PP(zfilename);
4876
if (filename && *filename) {
4877
if (php_check_open_basedir(filename TSRMLS_CC)) {
4881
if ((fp = VCWD_OPEN_MODE(filename,O_CREAT | O_RDWR | O_BINARY | O_TRUNC, 0600)) == -1) {
4882
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't create file %s", filename);
4887
CALL_OCI_RETURN(connection->error,
4889
connection->pServiceContext,
4896
if (connection->error) {
4897
oci_error(connection->pError, "OCILobGetLength", connection->error);
4898
oci_handle_error(connection, connection->error);
4902
if (descr->type == OCI_DTYPE_FILE) {
4903
CALL_OCI_RETURN(connection->error,
4905
connection->pServiceContext,
4912
if (connection->error) {
4913
oci_error(connection->pError, "OCILobFileOpen",connection->error);
4914
oci_handle_error(connection, connection->error);
4924
length = loblen - start;
4927
if ((start + length) > loblen) {
4928
length = loblen - start;
4931
#define OCI_LOB_READ_BUFFER 128*1024
4933
buffer = emalloc(OCI_LOB_READ_BUFFER);
4937
oci_debug("oci_lob_export(start = %d, length = %d, loblen = %d",start,length,loblen);
4939
while (length > 0) {
4942
if (length > OCI_LOB_READ_BUFFER) {
4943
toread = OCI_LOB_READ_BUFFER;
4948
oci_debug("oci_lob_read(coffs = %d, toread = %d",coffs,toread);
4950
CALL_OCI_RETURN(connection->error,
4952
connection->pServiceContext,
4955
&toread, /* IN/OUT bytes toread/read */
4956
coffs+1, /* offset (starts with 1) */
4958
toread, /* size of buffer */
4960
(OCICallbackLobRead) 0, /* callback... */
4961
(ub2) 0, /* The character set ID of the buffer data. */
4962
(ub1) SQLCS_IMPLICIT /* The character set form of the buffer data. */
4966
oci_debug("oci_lob_read(read - %d",toread);
4968
if (connection->error) {
4969
oci_error(connection->pError, "OCILobRead", connection->error);
4970
oci_handle_error(connection, connection->error);
4975
if ((ub4) write(fp,buffer,toread) != toread) {
4976
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot write file!");
4980
PHPWRITE(buffer,toread);
4995
if (descr->type == OCI_DTYPE_FILE) {
4996
CALL_OCI_RETURN(connection->error,
4998
connection->pServiceContext,
5004
if (connection->error) {
5005
oci_error(connection->pError, "OCILobFileClose", connection->error);
5006
oci_handle_error(connection, connection->error);
5026
#ifdef HAVE_OCI8_TEMP_LOB
5027
/* {{{ proto bool oci_lob_write_temporary(string var [, int lob_type])
5028
Writes temporary blob */
5029
PHP_FUNCTION(oci_lob_write_temporary)
5032
OCILobLocator *mylob;
5033
oci_connection *connection;
5034
oci_descriptor *descr;
5037
long lob_type = OCI_TEMP_CLOB;
5039
oci_debug ("oci_write_temporary_lob");
5041
if ((id = getThis()) == 0) {
5045
if (_oci_get_ocidesc(id,&descr TSRMLS_CC) == 0) {
5049
mylob = (OCILobLocator *) descr->ocidescr;
5055
connection = descr->conn;
5057
if (ZEND_NUM_ARGS() < 1) WRONG_PARAM_COUNT;
5058
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &var, &lob_type) == FAILURE) {
5062
CALL_OCI_RETURN(connection->error,
5063
OCILobCreateTemporary(
5064
connection->pServiceContext,
5071
OCI_DURATION_SESSION
5075
if (connection->error) {
5076
oci_error(connection->pError, "OCILobCreateTemporary", connection->error);
5077
oci_handle_error(connection, connection->error);
5081
CALL_OCI_RETURN(connection->error,
5083
connection->pServiceContext,
5090
if (connection->error) {
5091
oci_error(connection->pError, "OCILobOpen", connection->error);
5092
oci_handle_error(connection, connection->error);
5096
convert_to_string_ex(&var);
5097
loblen = Z_STRLEN_P(var);
5100
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot save a lob that is less than 1 byte");
5104
CALL_OCI_RETURN(connection->error,
5106
connection->pServiceContext,
5111
(dvoid *) Z_STRVAL_P(var),
5115
(sb4 (*)(dvoid *, dvoid *, ub4 *, ub1 *)) 0,
5117
(ub1) SQLCS_IMPLICIT
5121
if (connection->error) {
5122
oci_error(connection->pError, "OCILobWrite", connection->error);
5123
oci_handle_error(connection, connection->error);
5131
/* {{{ proto bool oci_lob_close()
5132
Closes lob descriptor */
5133
PHP_FUNCTION(oci_lob_close)
5137
OCILobLocator *mylob;
5138
oci_connection *connection;
5139
oci_descriptor *descriptor;
5142
if ((id = getThis()) != 0) {
5143
inx = _oci_get_ocidesc(id,&descriptor TSRMLS_CC);
5146
mylob = (OCILobLocator *) descriptor->ocidescr;
5152
connection = descriptor->conn;
5154
CALL_OCI_RETURN(connection->error,
5156
connection->pServiceContext,
5162
if (connection->error) {
5163
oci_error(connection->pError, "OCILobClose", connection->error);
5164
oci_handle_error(connection, connection->error);
5169
OCILobIsTemporary(connection->session->pEnv,
5175
OCILobFreeTemporary(connection->pServiceContext,
5179
if (connection->error) {
5180
oci_error(connection->pError, "OCILobFreeTemporary",
5182
oci_handle_error(connection, connection->error);
5185
oci_debug("oci_lob_free_temporary: descr=%d",inx);
5188
oci_debug("oci_close_lob: descr=%d",inx);
5193
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_lob_close() should not be called like this. Use $somelob->close() to close a LOB");
5200
/* {{{ proto object oci_new_descriptor(resource connection [, int type])
5201
Initialize a new empty descriptor LOB/FILE (LOB is default) */
5202
PHP_FUNCTION(oci_new_descriptor)
5204
zval **conn, **type;
5205
oci_connection *connection;
5206
oci_descriptor *descr;
5209
dtype = OCI_DTYPE_LOB;
5211
if (zend_get_parameters_ex(2, &conn, &type) == SUCCESS) {
5212
convert_to_long_ex(type);
5213
dtype = Z_LVAL_PP(type);
5214
} else if (zend_get_parameters_ex(1, &conn) == FAILURE) {
5218
OCI_GET_CONN(connection,conn);
5220
descr = oci_new_desc(dtype,connection);
5226
object_init_ex(return_value, oci_lob_class_entry_ptr);
5227
add_property_resource(return_value, "descriptor", descr->id);
5231
/* {{{ proto bool oci_rollback(resource conn)
5232
Rollback the current context */
5233
PHP_FUNCTION(oci_rollback)
5236
oci_connection *connection;
5238
if (zend_get_parameters_ex(1, &conn) == FAILURE) {
5242
OCI_GET_CONN(connection,conn);
5244
if (connection->descriptors) {
5245
zend_hash_apply(connection->descriptors,(apply_func_t) _oci_desc_flush_hash_dtor TSRMLS_CC);
5248
oci_debug("<OCITransRollback");
5250
CALL_OCI_RETURN(connection->error,
5252
connection->pServiceContext,
5258
connection->needs_commit = 0;
5260
oci_debug(">OCITransRollback");
5262
if (connection->error) {
5263
oci_error(connection->pError, "OCIRollback", connection->error);
5264
oci_handle_error(connection, connection->error);
5272
/* {{{ proto bool oci_commit(resource conn)
5273
Commit the current context */
5274
PHP_FUNCTION(oci_commit)
5277
oci_connection *connection;
5279
if (zend_get_parameters_ex(1, &conn) == FAILURE) {
5283
OCI_GET_CONN(connection,conn);
5285
if (connection->descriptors) {
5286
zend_hash_apply(connection->descriptors,(apply_func_t) _oci_desc_flush_hash_dtor TSRMLS_CC);
5289
oci_debug("<OCITransCommit");
5291
CALL_OCI_RETURN(connection->error,
5293
connection->pServiceContext,
5299
connection->needs_commit = 0;
5301
oci_debug(">OCITransCommit");
5303
if (connection->error) {
5304
oci_error(connection->pError, "OCICommit", connection->error);
5305
oci_handle_error(connection, connection->error);
5313
/* {{{ proto string oci_field_name(resource stmt, int col)
5314
Tell the name of a column */
5315
PHP_FUNCTION(oci_field_name)
5318
oci_statement *statement;
5319
oci_out_column *outcol;
5321
if (zend_get_parameters_ex(2, &stmt, &col) == FAILURE) {
5325
OCI_GET_STMT(statement,stmt);
5327
outcol = oci_get_col(statement, -1, col);
5328
if (outcol == NULL) {
5332
RETURN_STRINGL(outcol->name, outcol->name_len, 1);
5336
/* {{{ proto int oci_field_size(resource stmt, int col)
5337
Tell the maximum data size of a column */
5338
PHP_FUNCTION(oci_field_size)
5341
oci_statement *statement;
5342
oci_out_column *outcol;
5344
if (zend_get_parameters_ex(2, &stmt, &col) == FAILURE) {
5348
OCI_GET_STMT(statement,stmt);
5350
outcol = oci_get_col(statement, -1, col);
5351
if (outcol == NULL) {
5355
oci_debug("oci_field_size: %16s, retlen = %4d, retlen4 = %d, data_size = %4d, storage_size4 = %4d, indicator %4d, retcode = %4d",
5356
outcol->name,outcol->retlen,outcol->retlen4,outcol->data_size,outcol->storage_size4,outcol->indicator,outcol->retcode);
5358
/* Handle data type of LONG */
5359
if (outcol->data_type == SQLT_LNG){
5360
RETURN_LONG(outcol->storage_size4);
5362
RETURN_LONG(outcol->data_size);
5367
/* {{{ proto int oci_field_scale(resource stmt, int col)
5368
Tell the scale of a column */
5369
PHP_FUNCTION(oci_field_scale)
5372
oci_statement *statement;
5373
oci_out_column *outcol;
5375
if (zend_get_parameters_ex(2, &stmt, &col) == FAILURE) {
5379
OCI_GET_STMT(statement,stmt);
5381
outcol = oci_get_col(statement, -1, col);
5382
if (outcol == NULL) {
5385
RETURN_LONG(outcol->scale);
5389
/* {{{ proto int oci_field_precision(resource stmt, int col)
5390
Tell the precision of a column */
5391
PHP_FUNCTION(oci_field_precision)
5394
oci_statement *statement;
5395
oci_out_column *outcol;
5397
if (zend_get_parameters_ex(2, &stmt, &col) == FAILURE) {
5401
OCI_GET_STMT(statement,stmt);
5403
outcol = oci_get_col(statement, -1, col);
5404
if (outcol == NULL) {
5407
RETURN_LONG(outcol->precision);
5411
/* {{{ proto mixed oci_field_type(resource stmt, int col)
5412
Tell the data type of a column */
5413
PHP_FUNCTION(oci_field_type)
5416
oci_statement *statement;
5417
oci_out_column *outcol;
5419
if (zend_get_parameters_ex(2, &stmt, &col) == FAILURE) {
5423
OCI_GET_STMT(statement,stmt);
5425
outcol = oci_get_col(statement, -1, col);
5426
if (outcol == NULL) {
5429
switch (outcol->data_type) {
5430
#ifdef SQLT_TIMESTAMP
5431
case SQLT_TIMESTAMP:
5432
RETVAL_STRING("TIMESTAMP",1);
5435
#ifdef SQLT_TIMESTAMP_TZ
5436
case SQLT_TIMESTAMP_TZ:
5437
RETVAL_STRING("TIMESTAMP_TZ",1);
5441
RETVAL_STRING("DATE",1);
5444
RETVAL_STRING("NUMBER",1);
5447
RETVAL_STRING("LONG",1);
5450
RETVAL_STRING("RAW",1);
5453
RETVAL_STRING("LONG RAW",1);
5456
RETVAL_STRING("VARCHAR",1);
5459
RETVAL_STRING("REFCURSOR",1);
5462
RETVAL_STRING("CHAR",1);
5465
RETVAL_STRING("BLOB",1);
5468
RETVAL_STRING("CLOB",1);
5471
RETVAL_STRING("BFILE",1);
5474
RETVAL_STRING("ROWID",1);
5477
RETVAL_LONG(outcol->data_type);
5482
/* {{{ proto int oci_field_type_raw(resource stmt, int col)
5483
Tell the raw oracle data type of a column */
5484
PHP_FUNCTION(oci_field_type_raw)
5487
oci_statement *statement;
5488
oci_out_column *outcol;
5490
if (zend_get_parameters_ex(2, &stmt, &col) == FAILURE) {
5494
OCI_GET_STMT(statement,stmt);
5496
outcol = oci_get_col(statement, -1, col);
5497
if (outcol == NULL) {
5500
RETVAL_LONG(outcol->data_type);
5504
/* {{{ proto bool oci_field_is_null(resource stmt, int col)
5505
Tell whether a column is NULL */
5506
PHP_FUNCTION(oci_field_is_null)
5509
oci_statement *statement;
5510
oci_out_column *outcol;
5512
if (zend_get_parameters_ex(2, &stmt, &col) == FAILURE) {
5516
OCI_GET_STMT(statement,stmt);
5518
outcol = oci_get_col(statement, -1, col);
5519
if (outcol == NULL) {
5522
if (outcol->indicator == -1) {
5530
/* {{{ proto void oci_internal_debug(int onoff)
5531
Toggle internal debugging output for the OCI extension */
5532
PHP_FUNCTION(oci_internal_debug)
5536
if (zend_get_parameters_ex(1, &arg) == FAILURE) {
5539
convert_to_long_ex(arg);
5540
OCI(debug_mode) = Z_LVAL_PP(arg);
5544
/* {{{ proto bool oci_execute(resource stmt [, int mode])
5545
Execute a parsed statement */
5546
PHP_FUNCTION(oci_execute)
5549
oci_statement *statement;
5552
if (zend_get_parameters_ex(2, &stmt, &mode) == SUCCESS) {
5553
convert_to_long_ex(mode);
5554
execmode = Z_LVAL_PP(mode);
5555
} else if (zend_get_parameters_ex(1, &stmt) == SUCCESS) {
5556
execmode = OCI_COMMIT_ON_SUCCESS;
5561
OCI_GET_STMT(statement,stmt);
5563
if (oci_execute(statement, "OCIExecute",execmode)) {
5571
/* {{{ proto bool oci_cancel(resource stmt)
5572
Cancel reading from a cursor */
5573
PHP_FUNCTION(oci_cancel)
5576
oci_statement *statement;
5578
if (zend_get_parameters_ex(1, &stmt) == FAILURE) {
5582
OCI_GET_STMT(statement,stmt);
5584
if (oci_fetch(statement, 0, "OCICancel" TSRMLS_CC)) {
5592
/* {{{ proto bool oci_fetch(resource stmt)
5593
Prepare a new row of data for reading */
5594
PHP_FUNCTION(oci_fetch)
5597
oci_statement *statement;
5598
ub4 nrows = 1; /* only one row at a time is supported for now */
5600
if (zend_get_parameters_ex(1, &stmt) == FAILURE) {
5604
OCI_GET_STMT(statement,stmt);
5606
if (oci_fetch(statement, nrows, "OCIFetch" TSRMLS_CC)) {
5614
/* {{{ proto int ocifetchinto(resource stmt, array &output [, int mode])
5615
Fetch a row of result data into an array */
5616
PHP_FUNCTION(ocifetchinto)
5618
php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 3);
5622
/* {{{ proto int oci_fetch_all(resource stmt, array &output[, int skip[, int maxrows[, int flags]]])
5623
Fetch all rows of result data into an array */
5624
PHP_FUNCTION(oci_fetch_all)
5626
zval **stmt, **array, *element, **zskip, **zmaxrows, **zflags, *tmp;
5627
oci_statement *statement;
5628
oci_out_column **columns;
5632
int skip = 0, maxrows = -1;
5635
int ac = ZEND_NUM_ARGS();
5637
if (ac < 2 || ac > 5 || zend_get_parameters_ex(ac, &stmt, &array, &zskip, &zmaxrows, &zflags) == FAILURE) {
5643
convert_to_long_ex(zflags);
5644
flags = Z_LVAL_PP(zflags);
5646
convert_to_long_ex(zmaxrows);
5647
maxrows = Z_LVAL_PP(zmaxrows);
5649
convert_to_long_ex(zskip);
5650
skip = Z_LVAL_PP(zskip);
5653
OCI_GET_STMT(statement,stmt);
5659
if (!oci_fetch(statement, nrows, "OCIFetchStatement" TSRMLS_CC)) {
5664
if (flags & OCI_FETCHSTATEMENT_BY_ROW) {
5665
columns = safe_emalloc(statement->ncolumns, sizeof(oci_out_column *), 0);
5667
for (i = 0; i < statement->ncolumns; i++) {
5668
columns[ i ] = oci_get_col(statement, i + 1, 0);
5671
while (oci_fetch(statement, nrows, "OCIFetchStatement" TSRMLS_CC)) {
5677
for (i = 0; i < statement->ncolumns; i++) {
5678
MAKE_STD_ZVAL(element);
5680
_oci_make_zval(element,statement,columns[ i ], "OCIFetchStatement",OCI_RETURN_LOBS TSRMLS_CC);
5682
if (flags & OCI_NUM) {
5683
zend_hash_next_index_insert(Z_ARRVAL_P(row), &element, sizeof(zval*), NULL);
5684
} else { /* default to ASSOC */
5685
zend_hash_update(Z_ARRVAL_P(row),
5686
columns[ i ]->name, columns[ i ]->name_len+1,
5687
&element, sizeof(zval*), NULL);
5691
zend_hash_next_index_insert(Z_ARRVAL_PP(array), &row, sizeof(zval*), NULL);
5695
if ((maxrows != -1) && (rows == maxrows)) {
5696
oci_fetch(statement, 0, "OCIFetchStatement" TSRMLS_CC);
5702
} else { /* default to BY_COLUMN */
5703
columns = safe_emalloc(statement->ncolumns, sizeof(oci_out_column *), 0);
5704
outarrs = safe_emalloc(statement->ncolumns, sizeof(zval*), 0);
5706
if (flags & OCI_NUM) {
5707
for (i = 0; i < statement->ncolumns; i++) {
5708
columns[ i ] = oci_get_col(statement, i + 1, 0);
5713
zend_hash_next_index_insert(Z_ARRVAL_PP(array),
5714
&tmp, sizeof(zval*), (void **) &(outarrs[ i ]));
5716
} else { /* default to ASSOC */
5717
for (i = 0; i < statement->ncolumns; i++) {
5718
columns[ i ] = oci_get_col(statement, i + 1, 0);
5723
zend_hash_update(Z_ARRVAL_PP(array),
5724
columns[ i ]->name, columns[ i ]->name_len+1,
5725
(void *) &tmp, sizeof(zval*), (void **) &(outarrs[ i ]));
5729
while (oci_fetch(statement, nrows, "OCIFetchStatement" TSRMLS_CC)) {
5730
for (i = 0; i < statement->ncolumns; i++) {
5731
MAKE_STD_ZVAL(element);
5733
_oci_make_zval(element,statement,columns[ i ], "OCIFetchStatement",OCI_RETURN_LOBS TSRMLS_CC);
5735
zend_hash_index_update((*(outarrs[ i ]))->value.ht, rows, (void *)&element, sizeof(zval*), NULL);
5740
if ((maxrows != -1) && (rows == maxrows)) {
5741
oci_fetch(statement, 0, "OCIFetchStatement" TSRMLS_CC);
5754
/* {{{ proto object oci_fetch_object( resource stmt )
5755
Fetch a result row as an object */
5756
PHP_FUNCTION(oci_fetch_object)
5758
php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, OCI_ASSOC, 2);
5760
if (Z_TYPE_P(return_value) == IS_ARRAY) {
5761
object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
5766
/* {{{ proto array oci_fetch_row( resource stmt )
5767
Fetch a result row as an enumerated array */
5768
PHP_FUNCTION(oci_fetch_row)
5770
php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, OCI_NUM, 1);
5774
/* {{{ proto array oci_fetch_assoc( resource stmt )
5775
Fetch a result row as an associative array */
5776
PHP_FUNCTION(oci_fetch_assoc)
5778
php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, OCI_ASSOC, 1);
5782
/* {{{ proto array oci_fetch_array( resource stmt [, int mode ])
5783
Fetch a result row as an array */
5784
PHP_FUNCTION(oci_fetch_array)
5786
php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, OCI_BOTH, 2);
5790
/* {{{ proto bool oci_free_statement(resource stmt)
5791
Free all resources associated with a statement */
5792
PHP_FUNCTION(oci_free_statement)
5795
oci_statement *statement;
5797
if (zend_get_parameters_ex(1, &stmt) == FAILURE) {
5801
OCI_GET_STMT(statement,stmt);
5803
zend_list_delete(statement->id);
5809
/* {{{ proto bool oci_close(resource conn)
5810
Disconnect from database */
5811
PHP_FUNCTION(oci_close)
5814
this function does nothing any more. server-connections get automagiclly closed on
5815
request-end. connection handles will "dissappear" as soon as they are no longer
5816
referenced. as this module makes heavy use of zends reference-counting mechanism
5817
this is the desired behavior. it has always been a bad idea to close a connection that
5818
has outstanding transactions. this way we have a nice-clean approach.
5819
(thies@thieso.net 20000110)
5821
oci_connection *connection;
5824
if (zend_get_parameters_ex(1, &conn) == FAILURE) {
5828
OCI_GET_CONN(connection,conn);
5830
connection->is_open = 0;
5832
zend_hash_apply(list, (apply_func_t) _stmt_cleanup TSRMLS_CC);
5834
if (zend_list_delete(connection->id) == SUCCESS) {
5843
/* {{{ proto resource oci_new_connect(string user, string pass [, string db])
5844
Connect to an Oracle database and log on. Returns a new session. */
5845
PHP_FUNCTION(oci_new_connect)
5847
oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
5851
/* {{{ proto resource oci_connect(string user, string pass [, string db])
5852
Connect to an Oracle database and log on. Returns a new session. */
5853
PHP_FUNCTION(oci_connect)
5855
oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
5859
/* {{{ proto resource oci_pconnect(string user, string pass [, string db])
5860
Connect to an Oracle database using a persistent connection and log on. Returns a new session. */
5861
PHP_FUNCTION(oci_pconnect)
5863
oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1,0);
5867
/* {{{ proto array oci_error([resource stmt|conn|global])
5868
Return the last error of stmt|conn|global. If no error happened returns false. */
5869
PHP_FUNCTION(oci_error)
5872
oci_statement *statement;
5873
oci_connection *connection;
5878
#ifdef HAVE_OCI8_ATTR_STATEMENT
5880
text *sqltext = NULL;
5883
if (zend_get_parameters_ex(1, &arg) == SUCCESS) {
5884
statement = (oci_statement *) zend_fetch_resource(arg TSRMLS_CC, -1, NULL, NULL, 1, le_stmt);
5886
errh = statement->pError;
5887
error = statement->error;
5889
#ifdef HAVE_OCI8_ATTR_STATEMENT
5890
CALL_OCI_RETURN(statement->error,
5892
(dvoid *)statement->pStmt,
5901
CALL_OCI_RETURN(statement->error,
5903
(dvoid *)statement->pStmt,
5907
OCI_ATTR_PARSE_ERROR_OFFSET,
5914
connection = (oci_connection *) zend_fetch_resource(arg TSRMLS_CC, -1, NULL, NULL, 1, le_conn);
5916
errh = connection->pError;
5917
error = connection->error;
5925
if (!error) { /* no error set in the handle */
5930
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIError: unable to find Error handle");
5941
(ub4) sizeof(errbuf),
5942
(ub4) OCI_HTYPE_ERROR
5947
array_init(return_value);
5948
add_assoc_long(return_value, "code", errcode);
5949
add_assoc_string(return_value, "message", (char*) errbuf, 1);
5950
#ifdef HAVE_OCI8_ATTR_STATEMENT
5951
add_assoc_long(return_value, "offset", errorofs);
5952
add_assoc_string(return_value, "sqltext", sqltext ? (char *) sqltext : "", 1);
5960
/* {{{ proto int oci_num_fields(resource stmt)
5961
Return the number of result columns in a statement */
5962
PHP_FUNCTION(oci_num_fields)
5965
oci_statement *statement;
5967
if (zend_get_parameters_ex(1, &stmt) == FAILURE) {
5971
OCI_GET_STMT(statement,stmt);
5973
RETURN_LONG(statement->ncolumns);
5977
/* {{{ proto resource oci_parse(resource conn, string query)
5978
Parse a query and return a statement */
5979
PHP_FUNCTION(oci_parse)
5981
zval **conn, **query;
5982
oci_connection *connection;
5983
oci_statement *statement;
5985
if (zend_get_parameters_ex(2, &conn, &query) == FAILURE) {
5989
OCI_GET_CONN(connection,conn);
5991
convert_to_string_ex(query);
5993
statement = oci_parse(connection,Z_STRVAL_PP(query),Z_STRLEN_PP(query));
5996
RETURN_RESOURCE(statement->id);
6003
/* {{{ proto bool oci_set_prefetch(resource stmt, int prefetch_rows)
6004
Sets the number of rows to be prefetched on execute to prefetch_rows for stmt */
6005
PHP_FUNCTION(oci_set_prefetch)
6007
zval **stmt, **size;
6008
oci_statement *statement;
6010
if (zend_get_parameters_ex(2, &stmt, &size) == FAILURE) {
6014
convert_to_long_ex(size);
6016
OCI_GET_STMT(statement,stmt);
6018
oci_setprefetch(statement,Z_LVAL_PP(size));
6024
/* {{{ proto bool oci_password_change(resource conn, string username, string old_password, string new_password)
6025
Changes the password of an account */
6026
PHP_FUNCTION(oci_password_change)
6028
zval **conn, **user_param, **pass_old_param, **pass_new_param;
6029
text *user, *pass_old, *pass_new;
6030
oci_connection *connection;
6032
/* Disable in Safe Mode */
6033
if (PG(safe_mode)) {
6034
php_error_docref(NULL TSRMLS_CC, E_WARNING, "is disabled in Safe Mode");
6038
if (zend_get_parameters_ex(4, &conn, &user_param, &pass_old_param, &pass_new_param) == FAILURE) {
6042
convert_to_string_ex(user_param);
6043
convert_to_string_ex(pass_old_param);
6044
convert_to_string_ex(pass_new_param);
6046
user = Z_STRVAL_PP(user_param);
6047
pass_old = Z_STRVAL_PP(pass_old_param);
6048
pass_new = Z_STRVAL_PP(pass_new_param);
6050
OCI_GET_CONN(connection, conn);
6052
CALL_OCI_RETURN(connection->error,
6054
connection->pServiceContext,
6066
if (connection->error == OCI_SUCCESS) {
6069
oci_error(connection->pError, "OCIPasswordChange", connection->error);
6070
oci_handle_error(connection, connection->error);
6076
/* {{{ proto resource oci_new_cursor(resource conn)
6077
Return a new cursor (Statement-Handle) - use this to bind ref-cursors! */
6078
PHP_FUNCTION(oci_new_cursor)
6081
oci_connection *connection;
6082
oci_statement *statement;
6084
if (zend_get_parameters_ex(1, &conn) == FAILURE) {
6088
OCI_GET_CONN(connection,conn);
6090
statement = oci_parse(connection,0,0);
6092
RETURN_RESOURCE(statement->id);
6096
/* {{{ proto string oci_result(resource stmt, mixed column)
6097
Return a single column of result data */
6098
PHP_FUNCTION(oci_result)
6101
oci_statement *statement;
6102
oci_out_column *outcol = NULL;
6104
if (zend_get_parameters_ex(2, &stmt, &col) == FAILURE) {
6108
OCI_GET_STMT(statement,stmt);
6110
outcol = oci_get_col(statement, -1, col);
6112
if (outcol == NULL) {
6116
_oci_make_zval(return_value,statement,outcol, "OCIResult",0 TSRMLS_CC);
6120
/* {{{ proto string oci_server_version(resource conn)
6121
Return a string containing server version information */
6122
PHP_FUNCTION(oci_server_version)
6124
oci_connection *connection;
6128
if (zend_get_parameters_ex(1, &conn) == FAILURE) {
6132
OCI_GET_CONN(connection,conn);
6134
CALL_OCI_RETURN(connection->error,
6136
connection->pServiceContext,
6144
if (connection->error != OCI_SUCCESS) {
6145
oci_error(connection->pError, "OCIServerVersion", connection->error);
6146
oci_handle_error(connection, connection->error);
6150
RETURN_STRING(version,1);
6154
/* {{{ proto string oci_statement_type(resource stmt)
6155
Return the query type of an OCI statement */
6156
/* XXX it would be better with a general interface to OCIAttrGet() */
6157
PHP_FUNCTION(oci_statement_type)
6160
oci_statement *statement;
6163
if (zend_get_parameters_ex(1, &stmt) == FAILURE) {
6167
OCI_GET_STMT(statement,stmt);
6169
CALL_OCI_RETURN(statement->error,
6171
(dvoid *)statement->pStmt,
6180
if (statement->error != OCI_SUCCESS) {
6181
oci_error(statement->pError, "OCIStatementType", statement->error);
6182
oci_handle_error(statement->conn, statement->error);
6187
case OCI_STMT_SELECT:
6188
RETVAL_STRING("SELECT",1);
6190
case OCI_STMT_UPDATE:
6191
RETVAL_STRING("UPDATE",1);
6193
case OCI_STMT_DELETE:
6194
RETVAL_STRING("DELETE",1);
6196
case OCI_STMT_INSERT:
6197
RETVAL_STRING("INSERT",1);
6199
case OCI_STMT_CREATE:
6200
RETVAL_STRING("CREATE",1);
6203
RETVAL_STRING("DROP",1);
6205
case OCI_STMT_ALTER:
6206
RETVAL_STRING("ALTER",1);
6208
case OCI_STMT_BEGIN:
6209
RETVAL_STRING("BEGIN",1);
6211
case OCI_STMT_DECLARE:
6212
RETVAL_STRING("DECLARE",1);
6215
RETVAL_STRING("UNKNOWN",1);
6220
/* {{{ proto int oci_num_rows(resource stmt)
6221
Return the row count of an OCI statement */
6222
PHP_FUNCTION(oci_num_rows)
6225
oci_statement *statement;
6228
if (zend_get_parameters_ex(1, &stmt) == FAILURE) {
6232
OCI_GET_STMT(statement,stmt);
6234
CALL_OCI_RETURN(statement->error,
6236
(dvoid *)statement->pStmt,
6245
if (statement->error != OCI_SUCCESS) {
6246
oci_error(statement->pError, "OCIRowCount", statement->error);
6247
oci_handle_error(statement->conn, statement->error);
6251
RETURN_LONG(rowcount);
6255
#ifdef PHP_OCI8_HAVE_COLLECTIONS
6256
/* {{{ oci_get_coll() */
6257
static oci_collection *oci_get_coll(int ind TSRMLS_DC)
6259
oci_collection *collection;
6260
int actual_resource_type;
6262
collection = (oci_collection *) zend_list_find(ind, &actual_resource_type);
6264
if (collection && (actual_resource_type == le_coll)) {
6267
return (oci_collection *) NULL;
6272
/* {{{ proto bool oci_free_collection()
6273
Deletes collection object*/
6274
PHP_FUNCTION(oci_free_collection)
6278
oci_collection *coll;
6279
oci_connection *connection;
6281
if ((id = getThis()) != 0) {
6282
inx = _oci_get_ocicoll(id,&coll TSRMLS_CC);
6285
* Do we need to free the object?
6288
connection = coll->conn;
6289
oci_debug("oci_free_collection: coll=%d",inx);
6291
CALL_OCI_RETURN(connection->error,
6293
connection->session->pEnv,
6295
(dvoid *)coll->coll,
6296
(ub2)(OCI_OBJECTFREE_FORCE)
6300
if (connection->error) {
6301
oci_error(connection->pError, "OCIObjectFree", connection->error);
6305
zend_list_delete(inx);
6314
/* {{{ proto bool oci_collection_append(string value)
6315
Append an object to the collection */
6316
PHP_FUNCTION(oci_collection_append)
6319
oci_connection *connection;
6320
oci_collection *coll;
6322
OCIString *ocistr = (OCIString *)0;
6323
OCIInd new_ind = OCI_IND_NOTNULL;
6324
OCIInd null_ind = OCI_IND_NULL;
6329
if ((id = getThis()) != 0) {
6330
if ((inx = _oci_get_ocicoll(id,&coll TSRMLS_CC)) == 0) {
6334
connection = coll->conn;
6335
if (zend_get_parameters_ex(1, &arg) == FAILURE) {
6340
* Handle NULLS. For consistency with the rest of the OCI8 library, when
6341
* a value passed in is a 0 length string, consider it a null
6343
convert_to_string_ex(arg);
6344
if (Z_STRLEN_PP(arg) == 0) {
6345
CALL_OCI_RETURN(connection->error,
6347
connection->session->pEnv,
6354
if (connection->error) {
6355
oci_error(connection->pError, "OCICollAppend - NULL", connection->error);
6362
switch(coll->element_typecode) {
6363
case OCI_TYPECODE_DATE:
6364
convert_to_string_ex(arg);
6366
CALL_OCI_RETURN(connection->error,
6379
if (connection->error) {
6380
oci_error(connection->pError, "OCIDateFromText", connection->error);
6384
CALL_OCI_RETURN(connection->error,
6386
connection->session->pEnv,
6390
(OCIColl *) coll->coll
6394
if (connection->error) {
6395
oci_error(connection->pError, "OCICollAppend", connection->error);
6400
case OCI_TYPECODE_VARCHAR2 :
6401
convert_to_string_ex(arg);
6403
CALL_OCI_RETURN(connection->error,
6404
OCIStringAssignText(
6405
connection->session->pEnv,
6413
if (connection->error) {
6414
oci_error(connection->pError, "OCIStringAssignText", connection->error);
6418
CALL_OCI_RETURN(connection->error,
6420
connection->session->pEnv,
6424
(OCIColl *) coll->coll
6428
if (connection->error) {
6429
oci_error(connection->pError, "OCICollAppend", connection->error);
6434
case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */
6435
case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */
6436
case OCI_TYPECODE_REAL : /* REAL */
6437
case OCI_TYPECODE_DOUBLE : /* DOUBLE */
6438
case OCI_TYPECODE_INTEGER : /* INT */
6439
case OCI_TYPECODE_SIGNED16 : /* SHORT */
6440
case OCI_TYPECODE_SIGNED32 : /* LONG */
6441
case OCI_TYPECODE_DECIMAL : /* DECIMAL */
6442
case OCI_TYPECODE_FLOAT : /* FLOAT */
6443
case OCI_TYPECODE_NUMBER : /* NUMBER */
6444
case OCI_TYPECODE_SMALLINT : /* SMALLINT */
6445
convert_to_double_ex(arg);
6446
ndx = (double)Z_DVAL_PP(arg);
6448
CALL_OCI_RETURN(connection->error,
6457
if (connection->error) {
6458
oci_error(connection->pError, "OCINumberFromReal", connection->error);
6462
CALL_OCI_RETURN(connection->error,
6464
connection->session->pEnv,
6468
(OCIColl *) coll->coll
6475
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element");
6481
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_collection_append() should not be called like this. Use $collection->append($element) to append an element to the collection");
6486
/* {{{ proto string oci_collection_element_get(int ndx)
6487
Retrieve the value at collection index ndx */
6488
PHP_FUNCTION(oci_collection_element_get)
6491
oci_connection *connection;
6492
oci_collection *coll;
6498
OCIString *ocistr = (OCIString *)0;
6504
if ((id = getThis()) != 0) {
6505
if ((inx = _oci_get_ocicoll(id,&coll TSRMLS_CC)) == 0) {
6508
if (zend_get_parameters_ex(1, &arg) == FAILURE) {
6512
convert_to_long_ex(arg);
6513
ndx = Z_LVAL_PP(arg);
6515
connection = coll->conn;
6517
CALL_OCI_RETURN(connection->error,
6519
connection->session->pEnv,
6529
if (connection->error) {
6530
oci_error(connection->pError, "OCICollGetElem", connection->error);
6534
/* Return false if value does not exist at that location */
6536
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCICollGetElem - Invalid index %d", ndx);
6540
/* Return null if the value is null */
6541
if (*elemind == OCI_IND_NULL) {
6545
switch (coll->element_typecode) {
6546
case OCI_TYPECODE_DATE:
6555
0, /* lang_length */
6561
RETURN_STRINGL(buff,len,1);
6562
case OCI_TYPECODE_VARCHAR2 :
6563
ocistr = *(OCIString **)elem;
6564
str = OCIStringPtr(connection->session->pEnv,ocistr); /* XXX not protected against recursion! */
6565
RETURN_STRINGL(str,strlen(str),1);
6567
case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */
6568
case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */
6569
case OCI_TYPECODE_REAL : /* REAL */
6570
case OCI_TYPECODE_DOUBLE : /* DOUBLE */
6571
case OCI_TYPECODE_INTEGER : /* INT */
6572
case OCI_TYPECODE_SIGNED16 : /* SHORT */
6573
case OCI_TYPECODE_SIGNED32 : /* LONG */
6574
case OCI_TYPECODE_DECIMAL : /* DECIMAL */
6575
case OCI_TYPECODE_FLOAT : /* FLOAT */
6576
case OCI_TYPECODE_NUMBER : /* NUMBER */
6577
case OCI_TYPECODE_SMALLINT : /* SMALLINT */
6578
CALL_OCI_RETURN(connection->error,
6581
(CONST OCINumber *) elem,
6582
(uword) sizeof(dnum),
6587
if (connection->error) {
6588
oci_error(connection->pError, "OCINumberToReal", connection->error);
6591
RETURN_DOUBLE(dnum);
6594
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element");
6600
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_collection_element_get() should not be called like this. Use $collection->getelem($index) to get an element of the collection with the given index");
6605
/* {{{ proto bool oci_collection_assign(object from)
6606
Assign a collection from another existing collection */
6607
PHP_FUNCTION(oci_collection_assign)
6610
oci_connection *connection;
6611
oci_collection *coll,*from_coll;
6614
if ((id = getThis()) != 0) {
6615
if ((inx = _oci_get_ocicoll(id,&coll TSRMLS_CC)) == 0) {
6619
if (zend_get_parameters_ex(1, &from) == FAILURE) {
6623
if ((inx = _oci_get_ocicoll(*from,&from_coll TSRMLS_CC)) == 0) {
6627
connection = coll->conn;
6629
CALL_OCI_RETURN(connection->error,
6631
connection->session->pEnv,
6638
if (connection->error) {
6639
oci_error(connection->pError, "OCICollAssignElem", connection->error);
6645
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_collection_assign() should not be called like this. Use $collection->assign($collection_value) to assign value to the collection");
6650
/* {{{ proto bool oci_collection_element_assign(int index, string val)
6651
Assign element val to collection at index ndx */
6652
PHP_FUNCTION(oci_collection_element_assign)
6654
zval *id,**index,**val;
6655
oci_connection *connection;
6656
oci_collection *coll;
6658
OCIInd new_ind = OCI_IND_NOTNULL;
6659
OCIInd null_ind = OCI_IND_NULL;
6662
OCIString *ocistr = (OCIString *)0;
6666
if ((id = getThis()) != 0) {
6667
if ((inx = _oci_get_ocicoll(id,&coll TSRMLS_CC)) == 0) {
6671
if (zend_get_parameters_ex(2, &index,&val) == FAILURE) {
6675
convert_to_long_ex(index);
6676
ndx = Z_LVAL_PP(index);
6678
connection = coll->conn;
6680
if (connection->error) {
6681
oci_error(connection->pError, "OCICollAssignElem", connection->error);
6686
* Handle NULLs. For consistency with the rest of the OCI8 library, when
6687
* a value passed in is a 0 length string, consider it a null
6689
convert_to_string_ex(val);
6691
if (Z_STRLEN_PP(val) == 0) {
6692
CALL_OCI_RETURN(connection->error,
6694
connection->session->pEnv,
6702
if (connection->error) {
6703
oci_error(connection->pError, "OCICollAssignElem - NULL", connection->error);
6710
switch (coll->element_typecode) {
6711
case OCI_TYPECODE_DATE:
6712
convert_to_string_ex(val);
6713
CALL_OCI_RETURN(connection->error,
6726
if (connection->error) {
6727
oci_error(connection->pError, "OCIDateFromText", connection->error);
6731
CALL_OCI_RETURN(connection->error,
6733
connection->session->pEnv,
6742
if (connection->error) {
6743
oci_error(connection->pError, "OCICollAssignElem", connection->error);
6747
case OCI_TYPECODE_VARCHAR2 :
6748
convert_to_string_ex(val);
6750
CALL_OCI_RETURN(connection->error,
6751
OCIStringAssignText(
6752
connection->session->pEnv,
6760
if (connection->error) {
6761
oci_error(connection->pError, "OCIStringAssignText", connection->error);
6765
CALL_OCI_RETURN(connection->error,
6767
connection->session->pEnv,
6776
if (connection->error) {
6777
oci_error(connection->pError, "OCICollAssignElem", connection->error);
6782
case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */
6783
case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */
6784
case OCI_TYPECODE_REAL : /* REAL */
6785
case OCI_TYPECODE_DOUBLE : /* DOUBLE */
6786
case OCI_TYPECODE_INTEGER : /* INT */
6787
case OCI_TYPECODE_SIGNED16 : /* SHORT */
6788
case OCI_TYPECODE_SIGNED32 : /* LONG */
6789
case OCI_TYPECODE_DECIMAL : /* DECIMAL */
6790
case OCI_TYPECODE_FLOAT : /* FLOAT */
6791
case OCI_TYPECODE_NUMBER : /* NUMBER */
6792
case OCI_TYPECODE_SMALLINT : /* SMALLINT */
6793
convert_to_double_ex(val);
6794
dnum = (double)Z_DVAL_PP(val);
6796
CALL_OCI_RETURN(connection->error,
6805
if (connection->error) {
6806
oci_error(connection->pError, "OCINumberFromReal", connection->error);
6810
CALL_OCI_RETURN(connection->error,
6812
connection->session->pEnv,
6821
if (connection->error) {
6822
oci_error(connection->pError, "OCICollAssignElem", connection->error);
6830
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_collection_element_assign() should not be called like this. Use $collection->assignelem($index, $value) to assign value to an element of the collection");
6835
/* {{{ proto int oci_collection_size()
6836
Return the size of a collection */
6837
PHP_FUNCTION(oci_collection_size)
6840
oci_connection *connection;
6841
oci_collection *coll;
6845
if ((id = getThis()) != 0) {
6846
if ((inx = _oci_get_ocicoll(id,&coll TSRMLS_CC)) == 0) {
6849
connection = coll->conn;
6851
CALL_OCI_RETURN(connection->error,
6853
connection->session->pEnv,
6860
if (connection->error) {
6861
oci_error(connection->pError, "OCICollSize", connection->error);
6868
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_collection_size() should not be called like this. Use $collection->size() to get size of the collection");
6873
/* {{{ proto int oci_collection_max()
6874
Return the max value of a collection. For a varray this is the maximum length of the array */
6875
PHP_FUNCTION(oci_collection_max)
6878
oci_collection *coll;
6882
if ((id = getThis()) != 0) {
6883
if ((inx = _oci_get_ocicoll(id,&coll TSRMLS_CC)) == 0) {
6886
sz = OCICollMax(OCI(pEnv),coll->coll); /* XXX not protected against recursion */
6891
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_collection_max() should not be called like this. Use $collection->max() to get maximum number of elements in the collection");
6896
/* {{{ proto bool oci_collection_trim(int num)
6897
Trim num elements from the end of a collection */
6898
PHP_FUNCTION(oci_collection_trim)
6901
oci_collection *coll;
6904
if ((id = getThis()) != 0) {
6905
if ((inx = _oci_get_ocicoll(id,&coll TSRMLS_CC)) == 0) {
6908
if (zend_get_parameters_ex(1, &arg) == FAILURE) {
6911
convert_to_long_ex(arg);
6913
CALL_OCI_RETURN(coll->conn->error,
6922
if (coll->conn->error) {
6923
oci_error(coll->conn->pError, "OCICollTrim", coll->conn->error);
6929
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "oci_collection_trim() should not be called like this. Use $collection->trim($length) to trim collection to the given length");
6934
/* {{{ proto object oci_new_collection(resource connection, string tdo [, string schema])
6935
Initialize a new collection */
6936
PHP_FUNCTION(oci_new_collection)
6941
zval **conn, **tdo, **schema;
6942
oci_connection *connection;
6943
oci_collection *coll;
6944
int ac = ZEND_NUM_ARGS();
6946
if (ac < 2 || ac > 3 || zend_get_parameters_ex(ac, &conn, &tdo, &schema) == FAILURE) {
6950
convert_to_string_ex(tdo);
6953
convert_to_string_ex(schema);
6956
coll = emalloc(sizeof(oci_collection));
6958
OCI_GET_CONN(connection,conn);
6960
coll->conn = connection;
6961
coll->id = zend_list_insert(coll,le_coll);
6962
zend_list_addref(connection->id);
6964
CALL_OCI_RETURN(connection->error,
6966
connection->session->pEnv,
6968
connection->pServiceContext,
6969
ac == 3 ? (text *) Z_STRVAL_PP(schema) : (text *) 0,
6970
ac == 3 ? (ub4) Z_STRLEN_PP(schema) : (ub4) 0,
6971
(text *) Z_STRVAL_PP(tdo),
6972
(ub4) Z_STRLEN_PP(tdo),
6975
OCI_DURATION_SESSION,
6981
if (connection->error) {
6982
oci_error(connection->pError, "OCITypeByName", connection->error);
6986
CALL_OCI_RETURN(connection->error,
6988
connection->session->pEnv,
6990
(ub4) OCI_HTYPE_DESCRIBE,
6996
if (connection->error) {
6997
oci_error(connection->pError, "OCI_HTYPE_DESCRIBE", connection->error);
7001
CALL_OCI_RETURN(connection->error,
7003
connection->pServiceContext,
7005
(dvoid *) coll->tdo,
7009
(ub1) OCI_PTYPE_TYPE,
7014
if (connection->error) {
7015
oci_error(connection->pError, "OCI_OTYPE_PTR", connection->error);
7019
CALL_OCI_RETURN(connection->error,
7022
(ub4) OCI_HTYPE_DESCRIBE,
7025
(ub4)OCI_ATTR_PARAM,
7030
if (connection->error) {
7031
oci_error(connection->pError, "OCI_ATTR_PARAM", connection->error);
7035
/* get the collection type code of the attribute */
7037
CALL_OCI_RETURN(connection->error,
7040
(ub4) OCI_DTYPE_PARAM,
7041
(dvoid*) &(coll->coll_typecode),
7043
(ub4) OCI_ATTR_COLLECTION_TYPECODE,
7048
if (connection->error) {
7049
oci_error(connection->pError, "OCI_ATTR_COLLECTION_TYPECODE", connection->error);
7053
switch(coll->coll_typecode) {
7054
case OCI_TYPECODE_TABLE:
7055
case OCI_TYPECODE_VARRAY:
7056
CALL_OCI_RETURN(connection->error,
7059
(ub4) OCI_DTYPE_PARAM,
7062
(ub4) OCI_ATTR_COLLECTION_ELEMENT,
7067
if (connection->error) {
7068
oci_error(connection->pError, "OCI_ATTR_COLLECTION_ELEMENT", connection->error);
7072
CALL_OCI_RETURN(connection->error,
7075
(ub4) OCI_DTYPE_PARAM,
7076
(dvoid*) &(coll->elem_ref),
7078
(ub4) OCI_ATTR_REF_TDO,
7083
if (connection->error) {
7084
oci_error(connection->pError, "OCI_ATTR_REF_TDO", connection->error);
7088
CALL_OCI_RETURN(connection->error,
7090
connection->session->pEnv,
7093
OCI_DURATION_SESSION,
7095
&(coll->element_type)
7099
if (connection->error) {
7100
oci_error(connection->pError, "OCI_TYPEGET_HEADER", connection->error);
7104
CALL_OCI_RETURN(connection->error,
7107
(ub4) OCI_DTYPE_PARAM,
7108
(dvoid*) &(coll->element_typecode),
7110
(ub4) OCI_ATTR_TYPECODE,
7115
if (connection->error) {
7116
oci_error(connection->pError, "OCI_ATTR_TYPECODE", connection->error);
7121
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCINewCollection - Unknown Type %d", coll->coll_typecode);
7125
/* Create object to hold return table */
7126
CALL_OCI_RETURN(connection->error,
7128
connection->session->pEnv,
7130
connection->pServiceContext,
7134
OCI_DURATION_DEFAULT,
7136
(dvoid **) &(coll->coll)
7140
if (connection->error) {
7141
oci_error(connection->pError, "OCIObjectNew", connection->error);
7145
object_init_ex(return_value, oci_coll_class_entry_ptr);
7146
add_property_resource(return_value, "collection",coll->id);
7151
#endif /* HAVE_OCI8 */
7158
* vim600: sw=4 ts=4 fdm=marker
7159
* vim<600: sw=4 ts=4