Example #1
0
/* {{{ php_oci_lob_free()
 Close LOB descriptor and free associated resources */
void php_oci_lob_free (php_oci_descriptor *descriptor)
{
	if (!descriptor || !descriptor->connection) {
		return;
	}

	if (descriptor->connection->descriptors) {
		/* delete descriptor from the hash */
		zend_hash_index_del(descriptor->connection->descriptors, descriptor->index);
		if (zend_hash_num_elements(descriptor->connection->descriptors) == 0) {
			descriptor->connection->descriptor_count = 0;
		} else {
			if (descriptor->index + 1 == descriptor->connection->descriptor_count) {
				/* If the descriptor being freed is the end-most one
				 * allocated, then the descriptor_count is reduced so
				 * a future descriptor can reuse the hash table index.
				 * This can prevent the hash index range increasing in
				 * the common case that each descriptor is
				 * allocated/used/freed before another descriptor is
				 * needed.  However it is possible that a script frees
				 * descriptors in arbitrary order which would prevent
				 * descriptor_count ever being reduced to zero until
				 * zend_hash_num_elements() returns 0.
				 */
				descriptor->connection->descriptor_count--;
			}
		}
	}
	
	/* flushing Lobs & Files with buffering enabled */
	if ((descriptor->type == OCI_DTYPE_FILE || descriptor->type == OCI_DTYPE_LOB) && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED) {
		php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE);
	}

	if (descriptor->type == OCI_DTYPE_LOB) {
		php_oci_temp_lob_close(descriptor);
	}

	PHP_OCI_CALL(OCIDescriptorFree, (descriptor->descriptor, descriptor->type));

	zend_list_delete(descriptor->connection->id);
	efree(descriptor);
}
/* {{{ php_oci_collection_create() 
 Create and return connection handle */
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;
	
	collection = emalloc(sizeof(php_oci_collection));

	collection->connection = connection;
	collection->collection = NULL;
	zend_list_addref(collection->connection->rsrc_id);

	/* get type handle by name */
	PHP_OCI_CALL_RETURN(connection->errcode, 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 (connection->errcode != OCI_SUCCESS) {
		goto CLEANUP;
	}

	/* allocate describe handle */
	PHP_OCI_CALL_RETURN(connection->errcode, OCIHandleAlloc, (connection->env, (dvoid **) &dschp1, (ub4) OCI_HTYPE_DESCRIBE, (size_t) 0, (dvoid **) 0));

	if (connection->errcode != OCI_SUCCESS) {
		goto CLEANUP;
	}

	/* describe TDO */
	PHP_OCI_CALL_RETURN(connection->errcode, OCIDescribeAny, 
			(
			 connection->svc,
			 connection->err,
			 (dvoid *) collection->tdo,
			 (ub4) 0,
			 OCI_OTYPE_PTR,
			 (ub1) OCI_DEFAULT,
			 (ub1) OCI_PTYPE_TYPE,
			 dschp1
			)
	);

	if (connection->errcode != OCI_SUCCESS) {
		goto CLEANUP;
	}

	/* get first parameter handle */
	PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, ((dvoid *) dschp1, (ub4) OCI_HTYPE_DESCRIBE, (dvoid *)&parmp1, (ub4 *)0, (ub4)OCI_ATTR_PARAM,	connection->err));

	if (connection->errcode != OCI_SUCCESS) {
		goto CLEANUP;
	}

	/* get the collection type code of the attribute */
	PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, 
			(
			 (dvoid*) parmp1,
			 (ub4) OCI_DTYPE_PARAM,
			 (dvoid*) &(collection->coll_typecode),
			 (ub4 *) 0,
			 (ub4) OCI_ATTR_COLLECTION_TYPECODE,
			 connection->err
			)
	);

	if (connection->errcode != OCI_SUCCESS) {
		goto CLEANUP;
	}

	switch(collection->coll_typecode) {
		case OCI_TYPECODE_TABLE:
		case OCI_TYPECODE_VARRAY:
			/* get collection element handle */
			PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, 
					(
					 (dvoid*) parmp1,
					 (ub4) OCI_DTYPE_PARAM,
					 (dvoid*) &parmp2,
					 (ub4 *) 0,
					 (ub4) OCI_ATTR_COLLECTION_ELEMENT,
					 connection->err
					)
			);

			if (connection->errcode != OCI_SUCCESS) {
				goto CLEANUP;
			}

			/* get REF of the TDO for the type */
			PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, 
					(
					 (dvoid*) parmp2,
					 (ub4) OCI_DTYPE_PARAM,
					 (dvoid*) &(collection->elem_ref),
					 (ub4 *) 0,
					 (ub4) OCI_ATTR_REF_TDO,
					 connection->err
					)
			);

			if (connection->errcode != OCI_SUCCESS) {
				goto CLEANUP;
			}

			/* get the TDO (only header) */
			PHP_OCI_CALL_RETURN(connection->errcode, OCITypeByRef, 
					(
					 connection->env,
					 connection->err,
					 collection->elem_ref,
					 OCI_DURATION_SESSION,
					 OCI_TYPEGET_HEADER,
					 &(collection->element_type)
					)
			);

			if (connection->errcode != OCI_SUCCESS) {
				goto CLEANUP;
			}

			/* get typecode */
			PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, 
					(
					 (dvoid*) parmp2,
					 (ub4) OCI_DTYPE_PARAM,
					 (dvoid*) &(collection->element_typecode),
					 (ub4 *) 0,
					 (ub4) OCI_ATTR_TYPECODE,
					 connection->err
					)
			);

			if (connection->errcode != OCI_SUCCESS) {
				goto CLEANUP;
			}
			break;
			/* we only support VARRAYs and TABLEs */
		default:
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown collection type %d", collection->coll_typecode);
			break;
	}	

	/* Create object to hold return table */
	PHP_OCI_CALL_RETURN(connection->errcode, OCIObjectNew, 
		(
			connection->env, 
			connection->err, 
			connection->svc, 
			OCI_TYPECODE_TABLE, 
			collection->tdo, 
			(dvoid *)0, 
			OCI_DURATION_DEFAULT, 
			TRUE, 
			(dvoid **) &(collection->collection)
		)
	);

	if (connection->errcode != OCI_SUCCESS) {
		goto CLEANUP;
	}

	/* free the describe handle (Bug #44113) */
	PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE));
	PHP_OCI_REGISTER_RESOURCE(collection, le_collection);
	return collection;
	
CLEANUP:

	if (dschp1) {
		/* free the describe handle (Bug #44113) */
		PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE));
	}
	php_oci_error(connection->err, connection->errcode TSRMLS_CC);
	php_oci_collection_close(collection TSRMLS_CC);	
	return NULL;
} /* }}} */