diff options
author | Thies C. Arntzen <thies@php.net> | 2001-04-13 14:43:39 +0000 |
---|---|---|
committer | Thies C. Arntzen <thies@php.net> | 2001-04-13 14:43:39 +0000 |
commit | b9216bcc1bac4857b852767c243a226ebdd8bc96 (patch) | |
tree | f3ae0e6de30a2fce5dd86871a2e4f763e0503ba1 /ext/oci8 | |
parent | e9731903d1f78e4562c60bed0d8efd1914b740ae (diff) | |
download | php-git-b9216bcc1bac4857b852767c243a226ebdd8bc96.tar.gz |
@ - OCI8 now supports binding of collections
@ (Patch by Andy Sautins <asautins@veripost.net>)
Diffstat (limited to 'ext/oci8')
-rw-r--r-- | ext/oci8/oci8.c | 1091 | ||||
-rw-r--r-- | ext/oci8/php_oci8.h | 16 |
2 files changed, 1100 insertions, 7 deletions
diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index 6856c6761f..4342af429b 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -14,6 +14,8 @@ +----------------------------------------------------------------------+ | Authors: Stig Sæther Bakken <ssb@fast.no> | | Thies C. Arntzen <thies@thieso.net> | + | | + | Collection support by Andy Sautins <asautins@veripost.net> | +----------------------------------------------------------------------+ */ @@ -53,6 +55,8 @@ #include "ext/standard/head.h" #include "ext/standard/info.h" +#define WITH_COLLECTIONS 1 + #if HAVE_OCI8 #include "php_oci8.h" @@ -61,9 +65,15 @@ static int le_conn; static int le_stmt; static int le_desc; +#ifdef WITH_COLLECTIONS +static int le_coll; +#endif static int le_server; static int le_session; static zend_class_entry *oci_lob_class_entry_ptr; +#ifdef WITH_COLLECTIONS +static zend_class_entry *oci_coll_class_entry_ptr; +#endif #ifndef SQLT_BFILEE #define SQLT_BFILEE 114 @@ -117,6 +127,9 @@ static void oci_debug(const char *format, ...); static void _oci_conn_list_dtor(oci_connection *connection); static void _oci_stmt_list_dtor(zend_rsrc_list_entry *rsrc); static void _oci_descriptor_list_dtor(zend_rsrc_list_entry *rsrc); +#ifdef WITH_COLLECTIONS +static void _oci_coll_list_dtor(zend_rsrc_list_entry *rsrc); +#endif static void _oci_server_list_dtor(zend_rsrc_list_entry *rsrc); static void _oci_session_list_dtor(zend_rsrc_list_entry *rsrc); static void php_oci_free_conn_list(zend_rsrc_list_entry *rsrc); @@ -128,6 +141,10 @@ static void _oci_bind_hash_dtor(void *data); static oci_connection *oci_get_conn(zval **); static oci_statement *oci_get_stmt(zval **); static oci_descriptor *oci_get_desc(int); +#ifdef WITH_COLLECTIONS +/* Questionable name. Very close to oci_get_col */ +static oci_collection *oci_get_coll(int); +#endif static oci_out_column *oci_get_col(oci_statement *, int, zval **); static int _oci_make_zval(zval *, oci_statement *, oci_out_column *, char *, int mode); @@ -192,6 +209,20 @@ PHP_FUNCTION(ociserverversion); PHP_FUNCTION(ocistatementtype); PHP_FUNCTION(ocirowcount); PHP_FUNCTION(ocisetprefetch); +#ifdef WITH_COLLECTIONS +PHP_FUNCTION(ocinewcollection); +PHP_FUNCTION(ocifreecoll); +PHP_FUNCTION(ocicollappend); +PHP_FUNCTION(ocicollgetelem); +PHP_FUNCTION(ocicollassignelem); +PHP_FUNCTION(ocicollassign); +PHP_FUNCTION(ocicollsize); +PHP_FUNCTION(ocicollmax); +PHP_FUNCTION(ocicolltrim); +PHP_FUNCTION(ocicolldategetelem); +PHP_FUNCTION(ocicolldateassignelem); +PHP_FUNCTION(ocicolldateappendelem); +#endif #define OCI_GET_STMT(statement,value) \ statement = oci_get_stmt(value); \ @@ -211,6 +242,14 @@ PHP_FUNCTION(ocisetprefetch); RETURN_FALSE; \ } +#ifdef WITH_COLLECTIONS +#define OCI_GET_COLL(collection,index) \ + collection = oci_get_coll(index); \ + if (collection == NULL) { \ + RETURN_FALSE; \ + } +#endif + /* }}} */ /* {{{ extension definition structures */ @@ -262,6 +301,20 @@ static zend_function_entry php_oci_functions[] = { PHP_FE(ocirollback, NULL) PHP_FE(ocinewdescriptor, NULL) PHP_FE(ocisetprefetch, NULL) +#ifdef WITH_COLLECTIONS + PHP_FE(ocifreecoll, NULL) + PHP_FE(ocicollappend, NULL) + PHP_FE(ocicollgetelem, NULL) + PHP_FE(ocicolldategetelem,NULL) + PHP_FE(ocicolldateassignelem,NULL) + PHP_FE(ocicolldateappendelem,NULL) + PHP_FE(ocicollassignelem,NULL) + PHP_FE(ocicollassign, NULL) + PHP_FE(ocicollsize, NULL) + PHP_FE(ocicollmax, NULL) + PHP_FE(ocicolltrim, NULL) + PHP_FE(ocinewcollection, NULL) +#endif PHP_FALIAS(ocifreecursor,ocifreestatement,NULL) @@ -277,6 +330,23 @@ static zend_function_entry php_oci_lob_class_functions[] = { {NULL,NULL,NULL} }; +#ifdef WITH_COLLECTIONS +static zend_function_entry php_oci_coll_class_functions[] = { + PHP_FALIAS(append, ocicollappend, NULL) + PHP_FALIAS(getelem, ocicollgetelem, NULL) + PHP_FALIAS(dategetelem, ocicolldategetelem, NULL) + PHP_FALIAS(dateassignelem, ocicolldateassignelem, NULL) + PHP_FALIAS(dateappendelem, ocicolldateappendelem, NULL) + PHP_FALIAS(assignelem, ocicollassignelem, NULL) + PHP_FALIAS(assign, ocicollassign, NULL) + PHP_FALIAS(size, ocicollsize, NULL) + PHP_FALIAS(max, ocicollmax, NULL) + PHP_FALIAS(trim, ocicolltrim, NULL) + PHP_FALIAS(free, ocifreecoll, NULL) + {NULL,NULL,NULL} +}; +#endif + zend_module_entry oci8_module_entry = { "oci8", /* extension name */ php_oci_functions, /* extension function list */ @@ -341,17 +411,15 @@ static void php_oci_init_globals(OCILS_D) PHP_MINIT_FUNCTION(oci) { zend_class_entry oci_lob_class_entry; +#ifdef WITH_COLLECTIONS + zend_class_entry oci_coll_class_entry; +#endif -/* XXX Joe Brown says OCI_THREADED breaks windows, assuming the same is true for unix - tc -#ifdef ZTS -#define PHP_OCI_INIT_MODE OCI_THREADED +#ifdef WITH_COLLECTIONS +#define PHP_OCI_INIT_MODE OCI_DEFAULT | OCI_OBJECT #else -*/ #define PHP_OCI_INIT_MODE OCI_DEFAULT - -/* #endif -*/ #if OCI_USE_EMALLOC OCIInitialize(PHP_OCI_INIT_MODE, NULL, ocimalloc, ocirealloc, ocifree); @@ -368,12 +436,21 @@ PHP_MINIT_FUNCTION(oci) le_stmt = zend_register_list_destructors_ex(_oci_stmt_list_dtor, NULL, "oci8 statement", module_number); le_conn = zend_register_list_destructors_ex(php_oci_free_conn_list, NULL, "oci8 connection", module_number); le_desc = zend_register_list_destructors_ex(_oci_descriptor_list_dtor, NULL, "oci8 descriptor", module_number); +#ifdef WITH_COLLECTIONS + le_coll = zend_register_list_destructors_ex(_oci_coll_list_dtor, NULL, "oci8 collection", module_number); +#endif le_server = zend_register_list_destructors_ex(_oci_server_list_dtor, NULL, "oci8 server", module_number); le_session = zend_register_list_destructors_ex(_oci_session_list_dtor, NULL, "oci8 session", module_number); INIT_CLASS_ENTRY(oci_lob_class_entry, "OCI-Lob", php_oci_lob_class_functions); +#ifdef WITH_COLLECTIONS + INIT_CLASS_ENTRY(oci_coll_class_entry, "OCI-Collection", php_oci_coll_class_functions); +#endif oci_lob_class_entry_ptr = zend_register_internal_class(&oci_lob_class_entry); +#ifdef WITH_COLLECTIONS + oci_coll_class_entry_ptr = zend_register_internal_class(&oci_coll_class_entry); +#endif /* thies@thieso.net 990203 i do not think that we will need all of them - just in here for completeness for now! */ REGISTER_LONG_CONSTANT("OCI_DEFAULT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT); @@ -388,6 +465,11 @@ PHP_MINIT_FUNCTION(oci) REGISTER_LONG_CONSTANT("SQLT_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SQLT_RDD",SQLT_RDD, CONST_CS | CONST_PERSISTENT); +#ifdef WITH_COLLECTIONS + REGISTER_LONG_CONSTANT("OCI_B_SQLT_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT); + REGISTER_STRING_CONSTANT("OCI_SYSDATE","SYSDATE",CONST_PERSISTENT); +#endif + REGISTER_LONG_CONSTANT("OCI_B_BFILE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OCI_B_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OCI_B_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT); @@ -689,6 +771,29 @@ static void php_oci_free_conn_list(zend_rsrc_list_entry *rsrc) _oci_conn_list_dtor(conn); } +#ifdef WITH_COLLECTIONS + +/* {{{ _oci_coll_list_dtor() + */ + +static void +_oci_coll_list_dtor(zend_rsrc_list_entry *rsrc) +{ + oci_collection *coll = (oci_collection *)rsrc->ptr; + oci_debug("START _oci_coll_list_dtor: %d",coll->id); + + zend_list_delete(coll->conn->id); + // Note sure if we need to free the object. Have an + // oracle TAR out on this one. + // OCIDescriptorFree(descr->ocidescr, descr->type); + + oci_debug("END _oci_coll_list_dtor: %d",coll->id); + + efree(coll); +} + +#endif + /* {{{ _oci_descriptor_list_dtor() */ @@ -973,6 +1078,31 @@ oci_new_desc(int type,oci_connection *connection) return descr; } +#ifdef WITH_COLLECTIONS + +/* {{{ _oci_get_ocicoll() */ + +static int +_oci_get_ocicoll(zval *id,oci_collection **collection) +{ + zval **coll; + + if (zend_hash_find(id->value.obj.properties, "collection", sizeof("collection"), (void **)&coll) == FAILURE) { + php_error(E_WARNING, "cannot find collection"); + return 0; + } + if ((*collection = oci_get_coll((*coll)->value.lval)) == NULL) { + php_error(E_WARNING, "collection not found"); + return 0; + } + + return (*coll)->value.lval; +} + +/* }}} */ + +#endif + /* }}} */ /* {{{ _oci_get_ocidesc() */ @@ -2471,6 +2601,11 @@ PHP_FUNCTION(ocibindbyname) oci_statement *bindstmt; oci_bind bind, *bindp; oci_descriptor *descr; +#ifdef WITH_COLLECTIONS + oci_collection *coll; + int mode = OCI_DATA_AT_EXEC; + dvoid *mycoll = 0; +#endif ub2 ocitype = SQLT_CHR; /* unterminated string */ OCIStmt *mystmt = 0; dvoid *mydescr = 0; @@ -2495,6 +2630,24 @@ PHP_FUNCTION(ocibindbyname) OCI_GET_STMT(statement,stmt); switch (ocitype) { +#ifdef WITH_COLLECTIONS + case SQLT_NTY: + if((*var)->type != IS_OBJECT) { + php_error(E_WARNING,"Variable must be allocated using OCINewCollection()"); + RETURN_FALSE; + } + if ((inx = _oci_get_ocicoll(*var,&coll)) == 0) { + php_error(E_WARNING,"Variable must be allocated using OCINewCollection()"); + RETURN_FALSE; + } + if (! (mycoll = (dvoid *) coll->coll)) { + php_error(E_WARNING,"Collection empty"); + RETURN_FALSE; + } + value_sz = sizeof(void*); + mode = OCI_DEFAULT; + break; +#endif case SQLT_BFILEE: case SQLT_CFILEE: case SQLT_CLOB: @@ -2565,7 +2718,11 @@ PHP_FUNCTION(ocibindbyname) (ub2 *)&bindp->retcode, /* return code (ignored) */ (ub4)0, /* maxarr_len (PL/SQL only?) */ (ub4 *)0, /* actual array size (PL/SQL only?) */ +#ifdef WITH_COLLECTIONS + mode /* mode */); +#else OCI_DATA_AT_EXEC /* mode */); +#endif if (statement->error != OCI_SUCCESS) { oci_error(statement->pError, "OCIBindByName", statement->error); @@ -2573,6 +2730,9 @@ PHP_FUNCTION(ocibindbyname) RETURN_FALSE; } +#ifdef WITH_COLLECTIONS + if(mode == OCI_DATA_AT_EXEC) { +#endif statement->error = OCIBindDynamic(bindp->pBind, statement->pError, @@ -2586,6 +2746,24 @@ PHP_FUNCTION(ocibindbyname) oci_handle_error(statement->conn, statement->error); RETURN_FALSE; } +#ifdef WITH_COLLECTIONS + } +#endif + +#ifdef WITH_COLLECTIONS + if(ocitype == SQLT_NTY) { + /* Bind object */ + statement->error = OCIBindObject(bindp->pBind, + statement->pError, + coll->tdo, + (dvoid **) &(coll->coll), + (ub4 *) 0, (dvoid **) 0, (ub4 *) 0); + if (statement->error) { + oci_error(statement->pError, "OCIBindObject", statement->error); + RETURN_FALSE; + } + } +#endif RETURN_TRUE; } @@ -3943,6 +4121,905 @@ PHP_FUNCTION(ocirowcount) /* }}} */ +#ifdef WITH_COLLECTIONS +/* {{{ oci_get_coll() */ + +static oci_collection *oci_get_coll(int ind) +{ + oci_collection *collection; + int actual_resource_type; + + collection = (oci_collection *) zend_list_find(ind, &actual_resource_type); + + if (collection && (actual_resource_type == le_coll)) { + return collection; + } else { + return (oci_collection *) NULL; + } +} + + + +/* {{{ proto string ocifreecoll(object lob) + Deletes collection */ + +PHP_FUNCTION(ocifreecoll) +{ + zval *id; + int inx; + oci_collection *coll; + oci_connection *connection; + + if ((id = getThis()) != 0) { + inx = _oci_get_ocicoll(id,&coll); + if (inx) { + /* + * Do we need to free the object? + */ + connection = coll->conn; + oci_debug("OCIfreecoll: coll=%d",inx); + zend_list_delete(inx); + RETURN_TRUE; + } + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string ocicollappend(object collection,value) + Append an object to the collection */ + +PHP_FUNCTION(ocicollappend) +{ + zval *id, **arg; + oci_connection *connection; + oci_collection *coll; + OCINumber num; + OCIString *ocistr = (OCIString *)0; + OCIInd new_ind = OCI_IND_NOTNULL; + OCIDate dt; + char *buffer; + int inx; + double ndx; + ub4 loblen; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + + connection = coll->conn; + if (zend_get_parameters_ex(1, &arg) == FAILURE) { + WRONG_PARAM_COUNT; + } + + switch(coll->element_typecode) { + case OCI_TYPECODE_DATE: + convert_to_string_ex(arg); + connection->error = OCIDateFromText(connection->pError, + (*arg)->value.str.val, + (*arg)->value.str.len, + 0,0,0,0,&dt); + if (connection->error) { + oci_error(connection->pError, "OCIDateFromText", connection->error); + } + connection->error = OCICollAppend(OCI(pEnv), + connection->pError, + (dvoid *) &dt, + (dvoid *) &new_ind, + (OCIColl *) coll->coll); + if (connection->error) { + oci_error(connection->pError, "OCICollAppend", connection->error); + } + break; + case OCI_TYPECODE_VARCHAR2 : + convert_to_string_ex(arg); + connection->error = OCIStringAssignText(OCI(pEnv), + connection->pError, + (*arg)->value.str.val, + (*arg)->value.str.len, + &ocistr); + if (connection->error) { + oci_error(connection->pError, "OCIStringAssignText", connection->error); + } + connection->error = OCICollAppend(OCI(pEnv), + connection->pError, + (dvoid *) ocistr, + (dvoid *) &new_ind, + (OCIColl *) coll->coll); + if (connection->error) { + oci_error(connection->pError, "OCICollAppend", connection->error); + } + break; + case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */ + case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */ + case OCI_TYPECODE_REAL : /* REAL */ + case OCI_TYPECODE_DOUBLE : /* DOUBLE */ + case OCI_TYPECODE_INTEGER : /* INT */ + case OCI_TYPECODE_SIGNED16 : /* SHORT */ + case OCI_TYPECODE_SIGNED32 : /* LONG */ + case OCI_TYPECODE_DECIMAL : /* DECIMAL */ + case OCI_TYPECODE_FLOAT : /* FLOAT */ + case OCI_TYPECODE_NUMBER : /* NUMBER */ + case OCI_TYPECODE_SMALLINT : /* SMALLINT */ + convert_to_double_ex(arg); + ndx = (double)(*arg)->value.dval; + connection->error = OCINumberFromReal(connection->pError,&ndx, + sizeof(double),&num); + if (connection->error) { + oci_error(connection->pError, "OCINumberFromReal", connection->error); + } + + connection->error = OCICollAppend(OCI(pEnv), + connection->pError, + (dvoid *) &num, + (dvoid *) &new_ind, + (OCIColl *) coll->coll); + break; + } + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string ocicolldategetelem(object collection,ndx,[format],[lang]) + Retrieve the value at collection index ndx */ + +PHP_FUNCTION(ocicolldategetelem) +{ + zval *id,**arg,**fmt,**lang; + oci_connection *connection; + oci_collection *coll; + OCINumber num; + OCIInd new_ind = OCI_IND_NOTNULL; + char *buffer; + ub4 ndx; + ub4 loblen; + int i; + dvoid *elem; + dvoid *elemind; + boolean exists; + OCIString *ocistr = (OCIString *)0; + text *str; + char buff[1024]; + int len; + double dnum; + int ac = ZEND_NUM_ARGS(), inx; + char *ocifmt; + int ocifmt_len; + char *ocilang; + int ocilang_len; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + + if(coll->element_typecode != OCI_TYPECODE_DATE) { + php_error(E_WARNING, "Collection is not of date datatype"); + RETURN_FALSE; + } + + if (ac < 1 || ac > 3 || zend_get_parameters_ex(ac, &arg, &fmt, &lang) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long_ex(arg); + if(ac > 1) { + convert_to_string_ex(fmt); + ocifmt = (*fmt)->value.str.val; + ocifmt_len = (*fmt)->value.str.len; + } else { + ocifmt = 0; + ocifmt_len = 0; + } + + if(ac > 2) { + convert_to_string_ex(lang); + ocilang = (*lang)->value.str.val; + ocilang_len = (*lang)->value.str.len; + } else { + ocilang = 0; + ocilang_len = 0; + } + ndx = (*arg)->value.lval; + + connection = coll->conn; + + connection->error = OCICollGetElem(OCI(pEnv), + connection->pError, + coll->coll, + ndx, + &exists, + &elem, + &elemind); + if (connection->error) { + oci_error(connection->pError, "OCICollGetElem", connection->error); + } + len = 1024; + connection->error = OCIDateToText(connection->pError, + elem, + ocifmt, /* fmt */ + ocifmt_len, /* fmt_length */ + ocilang, /* lang_name */ + ocilang_len, /* lang_length */ + &len,buff); + if (connection->error) { + oci_error(connection->pError, "OCIDateToText", connection->error); + } + RETURN_STRINGL(buff,len,1); + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string ocicolldateassignelem(object collection,ndx,val,[format],[lang]) + assign value at collection index ndx */ + +PHP_FUNCTION(ocicolldateassignelem) +{ + zval *id,**arg,**val,**fmt,**lang; + oci_connection *connection; + oci_collection *coll; + OCINumber num; + OCIInd new_ind = OCI_IND_NOTNULL; + char *buffer; + ub4 ndx; + ub4 loblen; + int i; + dvoid *elem; + dvoid *elemind; + boolean exists; + OCIString *ocistr = (OCIString *)0; + OCIDate dt; + text *str; + char buff[1024]; + int len; + double dnum; + int ac = ZEND_NUM_ARGS(), inx; + char *ocifmt; + int ocifmt_len; + char *ocilang; + int ocilang_len; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + + if(coll->element_typecode != OCI_TYPECODE_DATE) { + php_error(E_WARNING, "Collection is not of date datatype"); + RETURN_FALSE; + } + + if (ac < 2 || ac > 5 || zend_get_parameters_ex(ac, &arg, &val,&fmt, &lang) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long_ex(arg); + convert_to_string_ex(val); + if(ac > 2) { + convert_to_string_ex(fmt); + ocifmt = (*fmt)->value.str.val; + ocifmt_len = (*fmt)->value.str.len; + } else { + ocifmt = 0; + ocifmt_len = 0; + } + + if(ac > 3) { + convert_to_string_ex(lang); + ocilang = (*lang)->value.str.val; + ocilang_len = (*lang)->value.str.len; + } else { + ocilang = 0; + ocilang_len = 0; + } + ndx = (*arg)->value.lval; + + connection = coll->conn; + convert_to_string_ex(val); + + if((*val)->value.str.len == 7 && !strncmp((*val)->value.str.val,"SYSDATE",7)) { + connection->error = OCIDateSysDate(connection->pError,&dt); + if (connection->error) { + oci_error(connection->pError, "OCIDateSysDate", connection->error); + } + } else { + connection->error = OCIDateFromText(connection->pError, + (*val)->value.str.val, + (*val)->value.str.len, + ocifmt,ocifmt_len,ocilang,ocilang_len,&dt); + if (connection->error) { + oci_error(connection->pError, "OCIDateFromText", connection->error); + } + } + + connection->error = OCICollAssignElem(OCI(pEnv), + connection->pError, + ndx, + (dword *)&dt, + &new_ind, + coll->coll); + if (connection->error) { + oci_error(connection->pError, "OCIAssignElem", connection->error); + } + + RETURN_TRUE; + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string ocicolldateappendelem(object collection,val,[format],[lang]) + assign value at collection index ndx */ + +PHP_FUNCTION(ocicolldateappendelem) +{ + zval *id,**arg,**fmt,**lang; + oci_connection *connection; + oci_collection *coll; + OCINumber num; + OCIInd new_ind = OCI_IND_NOTNULL; + char *buffer; + ub4 ndx; + ub4 loblen; + int i; + dvoid *elem; + dvoid *elemind; + boolean exists; + OCIString *ocistr = (OCIString *)0; + OCIDate dt; + text *str; + char buff[1024]; + int len; + double dnum; + int ac = ZEND_NUM_ARGS(), inx; + char *ocifmt; + int ocifmt_len; + char *ocilang; + int ocilang_len; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + + if(coll->element_typecode != OCI_TYPECODE_DATE) { + php_error(E_WARNING, "Collection is not of date datatype"); + RETURN_FALSE; + } + + if (ac < 1 || ac > 3 || zend_get_parameters_ex(ac, &arg, &fmt, &lang) == FAILURE) { + WRONG_PARAM_COUNT; + } + + if(ac > 1) { + convert_to_string_ex(fmt); + ocifmt = (*fmt)->value.str.val; + ocifmt_len = (*fmt)->value.str.len; + } else { + ocifmt = 0; + ocifmt_len = 0; + } + + if(ac > 2) { + convert_to_string_ex(lang); + ocilang = (*lang)->value.str.val; + ocilang_len = (*lang)->value.str.len; + } else { + ocilang = 0; + ocilang_len = 0; + } + connection = coll->conn; + + convert_to_string_ex(arg); + if((*arg)->value.str.len == 7 && !strncmp((*arg)->value.str.val,"SYSDATE",7)) { + connection->error = OCIDateSysDate(connection->pError,&dt); + if (connection->error) { + oci_error(connection->pError, "OCIDateSysDate", connection->error); + } + } else { + connection->error = OCIDateFromText(connection->pError, + (*arg)->value.str.val, + (*arg)->value.str.len, + ocifmt,ocifmt_len,ocilang,ocilang_len,&dt); + if (connection->error) { + oci_error(connection->pError, "OCIDateFromText", connection->error); + } + } + connection->error = OCICollAppend(OCI(pEnv), + connection->pError, + &dt, + &new_ind, + coll->coll); + if (connection->error) { + oci_error(connection->pError, "OCICollAppend", connection->error); + } + RETURN_TRUE; + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string ocicollgetelem(object collection,ndx,[format],[lang]) + Retrieve the value at collection index ndx */ + +PHP_FUNCTION(ocicollgetelem) +{ + zval *id,**arg,**dt_format,**lang; + oci_connection *connection; + oci_collection *coll; + OCINumber num; + OCIInd new_ind = OCI_IND_NOTNULL; + char *buffer; + ub4 ndx; + int inx; + ub4 loblen; + int i; + dvoid *elem; + dvoid *elemind; + boolean exists; + OCIString *ocistr = (OCIString *)0; + text *str; + char buff[1024]; + int len; + double dnum; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + if (zend_get_parameters_ex(1, &arg) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long_ex(arg); + ndx = (*arg)->value.lval; + + connection = coll->conn; + + connection->error = OCICollGetElem(OCI(pEnv), + connection->pError, + coll->coll, + ndx, + &exists, + &elem, + &elemind); + if (connection->error) { + oci_error(connection->pError, "OCICollGetElem", connection->error); + } + switch(coll->element_typecode) { + case OCI_TYPECODE_DATE: + len = 1024; + OCIDateToText(connection->pError, + elem, + 0, /* fmt */ + 0, /* fmt_length */ + 0, /* lang_name */ + 0, /* lang_length */ + &len,buff); + RETURN_STRINGL(buff,len,1); + case OCI_TYPECODE_VARCHAR2 : + ocistr = *(OCIString **)elem; + str = OCIStringPtr(OCI(pEnv),ocistr); + RETURN_STRINGL(str,strlen(str),1); + break; + case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */ + case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */ + case OCI_TYPECODE_REAL : /* REAL */ + case OCI_TYPECODE_DOUBLE : /* DOUBLE */ + case OCI_TYPECODE_INTEGER : /* INT */ + case OCI_TYPECODE_SIGNED16 : /* SHORT */ + case OCI_TYPECODE_SIGNED32 : /* LONG */ + case OCI_TYPECODE_DECIMAL : /* DECIMAL */ + case OCI_TYPECODE_FLOAT : /* FLOAT */ + case OCI_TYPECODE_NUMBER : /* NUMBER */ + case OCI_TYPECODE_SMALLINT : /* SMALLINT */ + connection->error = OCINumberToReal(connection->pError, + (CONST OCINumber *) elem, + (uword) sizeof(dnum), (dvoid *) &dnum); + if (connection->error) { + oci_error(connection->pError, "OCINumberToReal", connection->error); + } + RETURN_DOUBLE(dnum); + break; + } + } + + RETURN_FALSE; +} +/* }}} */ +/* {{{ proto string ocicollassign(object collection,object) + Assign a collection from another existing collection */ + +PHP_FUNCTION(ocicollassign) +{ + zval *id,**from; + oci_connection *connection; + oci_collection *coll,*from_coll; + OCINumber num; + OCIInd new_ind = OCI_IND_NOTNULL; + char *buffer; + ub4 ndx; + int inx; + ub4 loblen; + int i; + boolean exists; + OCIString *ocistr = (OCIString *)0; + text *str; + char buff[1024]; + double dnum; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + + if (zend_get_parameters_ex(1, &from) == FAILURE) { + WRONG_PARAM_COUNT; + } + + if ((inx = _oci_get_ocicoll(*from,&from_coll)) == 0) { + RETURN_FALSE; + } + + connection = coll->conn; + + connection->error = OCICollAssign(OCI(pEnv),connection->pError, + from_coll->coll,coll->coll); + if (connection->error) { + oci_error(connection->pError, "OCICollAssignElem", connection->error); + } + RETURN_TRUE; + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string ocicollassignelem(object collection,ndx,val) + Assign element val to collection at index ndx */ + +PHP_FUNCTION(ocicollassignelem) +{ + zval *id,**index,**val; + oci_connection *connection; + oci_collection *coll; + OCINumber num; + OCIInd new_ind = OCI_IND_NOTNULL; + char *buffer; + ub4 ndx; + int inx; + ub4 loblen; + int i; + boolean exists; + OCIString *ocistr = (OCIString *)0; + OCIDate dt; + text *str; + char buff[1024]; + double dnum; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + + if (zend_get_parameters_ex(2, &index,&val) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long_ex(index); + ndx = (*index)->value.lval; + + connection = coll->conn; + + if (connection->error) { + oci_error(connection->pError, "OCICollAssignElem", connection->error); + } + switch(coll->element_typecode) { + case OCI_TYPECODE_DATE: + convert_to_string_ex(val); + connection->error = OCIDateFromText(connection->pError, + (*val)->value.str.val, + (*val)->value.str.len, + 0,0,0,0,&dt); + if (connection->error) { + oci_error(connection->pError, "OCIDateFromText", connection->error); + } + connection->error = OCICollAssignElem(OCI(pEnv), + connection->pError, + ndx, + (dword *)&dt, + &new_ind, + coll->coll); + if (connection->error) { + oci_error(connection->pError, "OCIAssignElem", connection->error); + } + break; + case OCI_TYPECODE_VARCHAR2 : + convert_to_string_ex(val); + connection->error = OCIStringAssignText(OCI(pEnv), + connection->pError, + (*val)->value.str.val, + (*val)->value.str.len, + &ocistr); + if (connection->error) { + oci_error(connection->pError, "OCIStringAssignText", connection->error); + } + connection->error = OCICollAssignElem(OCI(pEnv), + connection->pError, + ndx, + (dword *)ocistr, + &new_ind, + coll->coll); + if (connection->error) { + oci_error(connection->pError, "OCIAssignElem", connection->error); + } + RETURN_TRUE; + break; + case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */ + case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */ + case OCI_TYPECODE_REAL : /* REAL */ + case OCI_TYPECODE_DOUBLE : /* DOUBLE */ + case OCI_TYPECODE_INTEGER : /* INT */ + case OCI_TYPECODE_SIGNED16 : /* SHORT */ + case OCI_TYPECODE_SIGNED32 : /* LONG */ + case OCI_TYPECODE_DECIMAL : /* DECIMAL */ + case OCI_TYPECODE_FLOAT : /* FLOAT */ + case OCI_TYPECODE_NUMBER : /* NUMBER */ + case OCI_TYPECODE_SMALLINT : /* SMALLINT */ + convert_to_double_ex(val); + dnum = (double)(*val)->value.dval; + connection->error = OCINumberFromReal(connection->pError,&dnum, + sizeof(double),&num); + if (connection->error) { + oci_error(connection->pError, "OCINumberFromReal", connection->error); + } + connection->error = OCICollAssignElem(OCI(pEnv), + connection->pError, + ndx, + (dword *)&num, + &new_ind, + coll->coll); + if (connection->error) { + oci_error(connection->pError, "OCIAssignElem", connection->error); + } + RETURN_TRUE; + break; + } + + + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string ocicollsize(object collection) + Return the size of a collection */ + +PHP_FUNCTION(ocicollsize) +{ + zval *id,**arg; + oci_collection *coll; + sb4 sz; + int inx; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + OCICollSize(OCI(pEnv),coll->conn->pError,coll->coll,&sz); + RETURN_LONG(sz); + } + + RETURN_FALSE; +} +/* }}} */ +/* {{{ proto string ocicollmax(object collection) + Return the max value of a collection. For a + varray this is the maximum length of the array */ + +PHP_FUNCTION(ocicollmax) +{ + zval *id,**arg; + oci_collection *coll; + sb4 sz; + int inx; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + sz = OCICollMax(OCI(pEnv),coll->coll); + RETURN_LONG(sz); + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string ocicolltrim(object collection,num) + Trim num elements from the end of a collection */ + +PHP_FUNCTION(ocicolltrim) +{ + zval *id,**arg; + oci_collection *coll; + sb4 sz; + int inx; + + if ((id = getThis()) != 0) { + if ((inx = _oci_get_ocicoll(id,&coll)) == 0) { + RETURN_FALSE; + } + if (zend_get_parameters_ex(1, &arg) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(arg); + coll->conn->error = OCICollTrim(OCI(pEnv),coll->conn->pError,(*arg)->value.lval,coll->coll); + if (coll->conn->error) { + oci_error(coll->conn->pError, "OCICollTrim", coll->conn->error); + } + + RETURN_TRUE; + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string ocinewcollection(int connection, string tdo) + Initialize a new collection */ + +PHP_FUNCTION(ocinewcollection) +{ + dvoid *dschp1; + dvoid *parmp1; + dvoid *parmp2; + zval **conn, **tdo; + oci_connection *connection; + oci_collection *coll; + OCISvcCtx *svchp = 0; + + int dtype; + + dtype = OCI_DTYPE_LOB; + + if (zend_get_parameters_ex(2, &conn, &tdo) != SUCCESS) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(tdo); + + coll = emalloc(sizeof(oci_collection)); + + OCI_GET_CONN(connection,conn); + + coll->conn = connection; + coll->id = zend_list_insert(coll,le_coll); + zend_list_addref(connection->id); + + connection->error = OCITypeByName(OCI(pEnv), + connection->pError, + connection->pServiceContext, + (text *) 0, + (ub4) 0, + (text *) (*tdo)->value.str.val, + (ub4) (*tdo)->value.str.len, + (CONST text *) 0, (ub4) 0, + OCI_DURATION_SESSION, + OCI_TYPEGET_ALL, + &(coll->tdo)); + if (connection->error) { + oci_error(connection->pError, "OCITypeByName", connection->error); + RETURN_FALSE; + } + + connection->error = OCIHandleAlloc(OCI(pEnv), (dvoid **) &dschp1, + (ub4) OCI_HTYPE_DESCRIBE, + (size_t) 0, (dvoid **) 0); + + if (connection->error) { + oci_error(connection->pError, "OCI_HTYPE_DESCRIBE", connection->error); + RETURN_FALSE; + } + connection->error = OCIDescribeAny(connection->pServiceContext, connection->pError, (dvoid *) coll->tdo, + (ub4) 0, OCI_OTYPE_PTR, (ub1)1, + (ub1) OCI_PTYPE_TYPE, dschp1); + if (connection->error) { + oci_error(connection->pError, "OCI_OTYPE_PTR", connection->error); + RETURN_FALSE; + } + + connection->error = OCIAttrGet((dvoid *) dschp1, + (ub4) OCI_HTYPE_DESCRIBE, + (dvoid *)&parmp1, (ub4 *)0, (ub4)OCI_ATTR_PARAM,connection->pError); + if (connection->error) { + oci_error(connection->pError, "OCI_ATTR_PARAM", connection->error); + RETURN_FALSE; + } + + // get the collection type code of the attribute + connection->error = OCIAttrGet((dvoid*) parmp1, (ub4) OCI_DTYPE_PARAM, + (dvoid*) &(coll->coll_typecode), (ub4 *) 0, + (ub4) OCI_ATTR_COLLECTION_TYPECODE, + connection->pError); + if (connection->error) { + oci_error(connection->pError, "OCI_ATTR_COLLECTION_TYPECODE", connection->error); + RETURN_FALSE; + } + + switch(coll->coll_typecode) { + case OCI_TYPECODE_VARRAY: + connection->error = OCIAttrGet((dvoid*) parmp1, + (ub4) OCI_DTYPE_PARAM, + (dvoid*) &parmp2, (ub4 *) 0, + (ub4) OCI_ATTR_COLLECTION_ELEMENT, + connection->pError); + if (connection->error) { + oci_error(connection->pError, "OCI_ATTR_COLLECTION_ELEMENT", connection->error); + RETURN_FALSE; + } + connection->error = OCIAttrGet((dvoid*) parmp2, + (ub4) OCI_DTYPE_PARAM, + (dvoid*) &(coll->elem_ref), (ub4 *) 0, + (ub4) OCI_ATTR_REF_TDO, + connection->pError); + if (connection->error) { + oci_error(connection->pError, "OCI_ATTR_REF_TDO", connection->error); + RETURN_FALSE; + } + connection->error = OCITypeByRef(OCI(pEnv), connection->pError, coll->elem_ref, + OCI_DURATION_SESSION, + OCI_TYPEGET_HEADER, &(coll->element_type)); + if (connection->error) { + oci_error(connection->pError, "OCI_TYPEGET_HEADER", connection->error); + RETURN_FALSE; + } + + connection->error = OCIAttrGet((dvoid*) parmp2, + (ub4) OCI_DTYPE_PARAM, + (dvoid*) &(coll->element_typecode), (ub4 *) 0, + (ub4) OCI_ATTR_TYPECODE, + connection->pError); + if (connection->error) { + oci_error(connection->pError, "OCI_ATTR_TYPECODE", connection->error); + RETURN_FALSE; + } + break; + default: + printf("Unknown Type\n"); + } + + /* Create object to hold return table */ + connection->error = OCIObjectNew(OCI(pEnv), + connection->pError, + connection->pServiceContext, + OCI_TYPECODE_TABLE, + coll->tdo, + (dvoid *)0, + OCI_DURATION_DEFAULT, + TRUE, + (dvoid **) &(coll->coll)); + if (connection->error) { + oci_error(connection->pError, "OCIObjectNew", connection->error); + RETURN_FALSE; + } + + object_init_ex(return_value, oci_coll_class_entry_ptr); + add_property_resource(return_value, "collection",coll->id); +} + +/* }}} */ + +#endif + #endif /* HAVE_OCI8 */ /* diff --git a/ext/oci8/php_oci8.h b/ext/oci8/php_oci8.h index 72be7f095a..2dc3b14889 100644 --- a/ext/oci8/php_oci8.h +++ b/ext/oci8/php_oci8.h @@ -82,6 +82,22 @@ typedef struct { } oci_descriptor; typedef struct { + int id; + int open; + oci_connection *conn; + oci_session *session; + OCISvcCtx *pServiceContext; + OCIType *tdo; + OCITypeCode coll_typecode; + OCIRef *elem_ref; + OCIType *element_type; + OCITypeCode element_typecode; + OCIColl *coll; + sword error; + OCIError *pError; +} oci_collection; + +typedef struct { zval *zval; text *name; ub4 name_len; |