#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "ext/standard/info.h"
#include "php_ini.h"
#if HAVE_OCI8
#include "php_oci8.h"
#include "php_oci8_int.h"
php_oci_collection *php_oci_collection_create(php_oci_connection *connection, char *tdo, int tdo_len, char *schema, int schema_len TSRMLS_DC)
{
dvoid *dschp1 = NULL;
dvoid *parmp1;
dvoid *parmp2;
php_oci_collection *collection;
sword errstatus;
collection = emalloc(sizeof(php_oci_collection));
collection->connection = connection;
collection->collection = NULL;
zend_list_addref(collection->connection->id);
PHP_OCI_CALL_RETURN(errstatus, OCITypeByName,
(
connection->env,
connection->err,
connection->svc,
(text *) schema,
(ub4) schema_len,
(text *) tdo,
(ub4) tdo_len,
(CONST text *) 0,
(ub4) 0,
OCI_DURATION_SESSION,
OCI_TYPEGET_ALL,
&(collection->tdo)
)
);
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (connection->env, (dvoid **) &dschp1, (ub4) OCI_HTYPE_DESCRIBE, (size_t) 0, (dvoid **) 0));
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
PHP_OCI_CALL_RETURN(errstatus, OCIDescribeAny,
(
connection->svc,
connection->err,
(dvoid *) collection->tdo,
(ub4) 0,
OCI_OTYPE_PTR,
(ub1) OCI_DEFAULT,
(ub1) OCI_PTYPE_TYPE,
dschp1
)
);
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *) dschp1, (ub4) OCI_HTYPE_DESCRIBE, (dvoid *)&parmp1, (ub4 *)0, (ub4)OCI_ATTR_PARAM, connection->err));
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet,
(
(dvoid*) parmp1,
(ub4) OCI_DTYPE_PARAM,
(dvoid*) &(collection->coll_typecode),
(ub4 *) 0,
(ub4) OCI_ATTR_COLLECTION_TYPECODE,
connection->err
)
);
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
switch(collection->coll_typecode) {
case OCI_TYPECODE_TABLE:
case OCI_TYPECODE_VARRAY:
PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet,
(
(dvoid*) parmp1,
(ub4) OCI_DTYPE_PARAM,
(dvoid*) &parmp2,
(ub4 *) 0,
(ub4) OCI_ATTR_COLLECTION_ELEMENT,
connection->err
)
);
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet,
(
(dvoid*) parmp2,
(ub4) OCI_DTYPE_PARAM,
(dvoid*) &(collection->elem_ref),
(ub4 *) 0,
(ub4) OCI_ATTR_REF_TDO,
connection->err
)
);
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
PHP_OCI_CALL_RETURN(errstatus, OCITypeByRef,
(
connection->env,
connection->err,
collection->elem_ref,
OCI_DURATION_SESSION,
OCI_TYPEGET_HEADER,
&(collection->element_type)
)
);
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet,
(
(dvoid*) parmp2,
(ub4) OCI_DTYPE_PARAM,
(dvoid*) &(collection->element_typecode),
(ub4 *) 0,
(ub4) OCI_ATTR_TYPECODE,
connection->err
)
);
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown collection type %d", collection->coll_typecode);
break;
}
PHP_OCI_CALL_RETURN(errstatus, OCIObjectNew,
(
connection->env,
connection->err,
connection->svc,
OCI_TYPECODE_TABLE,
collection->tdo,
(dvoid *)0,
OCI_DURATION_DEFAULT,
TRUE,
(dvoid **) &(collection->collection)
)
);
if (errstatus != OCI_SUCCESS) {
goto CLEANUP;
}
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE));
PHP_OCI_REGISTER_RESOURCE(collection, le_collection);
connection->errcode = 0;
return collection;
CLEANUP:
if (dschp1) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE));
}
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
php_oci_collection_close(collection TSRMLS_CC);
return NULL;
}
int php_oci_collection_size(php_oci_collection *collection, sb4 *size TSRMLS_DC)
{
php_oci_connection *connection = collection->connection;
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCICollSize, (connection->env, connection->err, collection->collection, (sb4 *)size));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_max(php_oci_collection *collection, long *max TSRMLS_DC)
{
php_oci_connection *connection = collection->connection;
PHP_OCI_CALL_RETURN(*max, OCICollMax, (connection->env, collection->collection));
return 0;
}
int php_oci_collection_trim(php_oci_collection *collection, long trim_size TSRMLS_DC)
{
php_oci_connection *connection = collection->connection;
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCICollTrim, (connection->env, connection->err, trim_size, collection->collection));
if (errstatus != OCI_SUCCESS) {
errstatus = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_append_null(php_oci_collection *collection TSRMLS_DC)
{
OCIInd null_index = OCI_IND_NULL;
php_oci_connection *connection = collection->connection;
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCICollAppend, (connection->env, connection->err, (dvoid *)0, &null_index, collection->collection));
if (errstatus != OCI_SUCCESS) {
errstatus = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_append_date(php_oci_collection *collection, char *date, int date_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
OCIDate oci_date;
php_oci_connection *connection = collection->connection;
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
PHP_OCI_CALL_RETURN(errstatus, OCICollAppend,
(
connection->env,
connection->err,
(dvoid *) &oci_date,
(dvoid *) &new_index,
(OCIColl *) collection->collection
)
);
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_append_number(php_oci_collection *collection, char *number, int number_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
double element_double;
OCINumber oci_number;
php_oci_connection *connection = collection->connection;
sword errstatus;
element_double = zend_strtod(number, NULL);
PHP_OCI_CALL_RETURN(errstatus, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
PHP_OCI_CALL_RETURN(errstatus, OCICollAppend,
(
connection->env,
connection->err,
(dvoid *) &oci_number,
(dvoid *) &new_index,
(OCIColl *) collection->collection
)
);
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_append_string(php_oci_collection *collection, char *element, int element_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
OCIString *ocistr = (OCIString *)0;
php_oci_connection *connection = collection->connection;
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
PHP_OCI_CALL_RETURN(errstatus, OCICollAppend,
(
connection->env,
connection->err,
(dvoid *) ocistr,
(dvoid *) &new_index,
(OCIColl *) collection->collection
)
);
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_append(php_oci_collection *collection, char *element, int element_len TSRMLS_DC)
{
if (element_len == 0) {
return php_oci_collection_append_null(collection TSRMLS_CC);
}
switch(collection->element_typecode) {
case OCI_TYPECODE_DATE:
return php_oci_collection_append_date(collection, element, element_len TSRMLS_CC);
break;
case OCI_TYPECODE_VARCHAR2 :
return php_oci_collection_append_string(collection, element, element_len TSRMLS_CC);
break;
case OCI_TYPECODE_UNSIGNED16 :
case OCI_TYPECODE_UNSIGNED32 :
case OCI_TYPECODE_REAL :
case OCI_TYPECODE_DOUBLE :
case OCI_TYPECODE_INTEGER :
case OCI_TYPECODE_SIGNED16 :
case OCI_TYPECODE_SIGNED32 :
case OCI_TYPECODE_DECIMAL :
case OCI_TYPECODE_FLOAT :
case OCI_TYPECODE_NUMBER :
case OCI_TYPECODE_SMALLINT :
return php_oci_collection_append_number(collection, element, element_len TSRMLS_CC);
break;
default:
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
return 1;
break;
}
return 1;
}
int php_oci_collection_element_get(php_oci_collection *collection, long index, zval **result_element TSRMLS_DC)
{
php_oci_connection *connection = collection->connection;
dvoid *element;
OCIInd *element_index;
boolean exists;
oratext buff[1024];
ub4 buff_len = 1024;
sword errstatus;
MAKE_STD_ZVAL(*result_element);
ZVAL_NULL(*result_element);
connection->errcode = 0;
PHP_OCI_CALL_RETURN(errstatus, OCICollGetElem,
(
connection->env,
connection->err,
collection->collection,
(ub4)index,
&exists,
&element,
(dvoid **)&element_index
)
);
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
FREE_ZVAL(*result_element);
return 1;
}
if (exists == 0) {
FREE_ZVAL(*result_element);
return 1;
}
if (*element_index == OCI_IND_NULL) {
return 0;
}
switch (collection->element_typecode) {
case OCI_TYPECODE_DATE:
PHP_OCI_CALL_RETURN(errstatus, OCIDateToText, (connection->err, element, 0, 0, 0, 0, &buff_len, buff));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
FREE_ZVAL(*result_element);
return 1;
}
ZVAL_STRINGL(*result_element, (char *)buff, buff_len, 1);
Z_STRVAL_P(*result_element)[buff_len] = '\0';
return 0;
break;
case OCI_TYPECODE_VARCHAR2:
{
OCIString *oci_string = *(OCIString **)element;
text *str;
PHP_OCI_CALL_RETURN(str, OCIStringPtr, (connection->env, oci_string));
if (str) {
ZVAL_STRING(*result_element, (char *)str, 1);
}
return 0;
}
break;
case OCI_TYPECODE_UNSIGNED16:
case OCI_TYPECODE_UNSIGNED32:
case OCI_TYPECODE_REAL:
case OCI_TYPECODE_DOUBLE:
case OCI_TYPECODE_INTEGER:
case OCI_TYPECODE_SIGNED16:
case OCI_TYPECODE_SIGNED32:
case OCI_TYPECODE_DECIMAL:
case OCI_TYPECODE_FLOAT:
case OCI_TYPECODE_NUMBER:
case OCI_TYPECODE_SMALLINT:
{
double double_number;
PHP_OCI_CALL_RETURN(errstatus, OCINumberToReal, (connection->err, (CONST OCINumber *) element, (uword) sizeof(double), (dvoid *) &double_number));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
FREE_ZVAL(*result_element);
return 1;
}
ZVAL_DOUBLE(*result_element, double_number);
return 0;
}
break;
default:
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
FREE_ZVAL(*result_element);
return 1;
break;
}
return 1;
}
int php_oci_collection_element_set_null(php_oci_collection *collection, long index TSRMLS_DC)
{
OCIInd null_index = OCI_IND_NULL;
php_oci_connection *connection = collection->connection;
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem, (connection->env, connection->err, (ub4) index, (dvoid *)"", &null_index, collection->collection));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_element_set_date(php_oci_collection *collection, long index, char *date, int date_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
OCIDate oci_date;
php_oci_connection *connection = collection->connection;
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem,
(
connection->env,
connection->err,
(ub4)index,
(dvoid *) &oci_date,
(dvoid *) &new_index,
(OCIColl *) collection->collection
)
);
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_element_set_number(php_oci_collection *collection, long index, char *number, int number_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
double element_double;
OCINumber oci_number;
php_oci_connection *connection = collection->connection;
sword errstatus;
element_double = zend_strtod(number, NULL);
PHP_OCI_CALL_RETURN(errstatus, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem,
(
connection->env,
connection->err,
(ub4) index,
(dvoid *) &oci_number,
(dvoid *) &new_index,
(OCIColl *) collection->collection
)
);
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_element_set_string(php_oci_collection *collection, long index, char *element, int element_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
OCIString *ocistr = (OCIString *)0;
php_oci_connection *connection = collection->connection;
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem,
(
connection->env,
connection->err,
(ub4)index,
(dvoid *) ocistr,
(dvoid *) &new_index,
(OCIColl *) collection->collection
)
);
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
int php_oci_collection_element_set(php_oci_collection *collection, long index, char *value, int value_len TSRMLS_DC)
{
if (value_len == 0) {
return php_oci_collection_element_set_null(collection, index TSRMLS_CC);
}
switch(collection->element_typecode) {
case OCI_TYPECODE_DATE:
return php_oci_collection_element_set_date(collection, index, value, value_len TSRMLS_CC);
break;
case OCI_TYPECODE_VARCHAR2 :
return php_oci_collection_element_set_string(collection, index, value, value_len TSRMLS_CC);
break;
case OCI_TYPECODE_UNSIGNED16 :
case OCI_TYPECODE_UNSIGNED32 :
case OCI_TYPECODE_REAL :
case OCI_TYPECODE_DOUBLE :
case OCI_TYPECODE_INTEGER :
case OCI_TYPECODE_SIGNED16 :
case OCI_TYPECODE_SIGNED32 :
case OCI_TYPECODE_DECIMAL :
case OCI_TYPECODE_FLOAT :
case OCI_TYPECODE_NUMBER :
case OCI_TYPECODE_SMALLINT :
return php_oci_collection_element_set_number(collection, index, value, value_len TSRMLS_CC);
break;
default:
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
return 1;
break;
}
return 1;
}
int php_oci_collection_assign(php_oci_collection *collection_dest, php_oci_collection *collection_from TSRMLS_DC)
{
php_oci_connection *connection = collection_dest->connection;
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCICollAssign, (connection->env, connection->err, collection_from->collection, collection_dest->collection));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0;
return 0;
}
void php_oci_collection_close(php_oci_collection *collection TSRMLS_DC)
{
php_oci_connection *connection = collection->connection;
sword errstatus;
if (collection->collection) {
PHP_OCI_CALL_RETURN(errstatus, OCIObjectFree, (connection->env, connection->err, (dvoid *)collection->collection, (ub2)OCI_OBJECTFREE_FORCE));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
} else {
connection->errcode = 0;
}
}
zend_list_delete(collection->connection->id);
efree(collection);
return;
}
#endif