Example #1
0
/* {{{ php_oci_lob_create()
 Create LOB descriptor and allocate all the resources needed */
php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long type TSRMLS_DC)
{
	php_oci_descriptor *descriptor;

	switch (type) {
		case OCI_DTYPE_FILE:
		case OCI_DTYPE_LOB:
		case OCI_DTYPE_ROWID:
			/* these three are allowed */
			break;
		default:
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown descriptor type %ld", type);
			return NULL;
			break;
	}

	descriptor = ecalloc(1, sizeof(php_oci_descriptor));
	descriptor->type = type;
	descriptor->connection = connection;
	zend_list_addref(descriptor->connection->rsrc_id);

	PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0));

	if (OCI_G(errcode) != OCI_SUCCESS) {
		OCI_G(errcode) = php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
		PHP_OCI_HANDLE_ERROR(connection, OCI_G(errcode));
		efree(descriptor);
		return NULL;
	}

	PHP_OCI_REGISTER_RESOURCE(descriptor, le_descriptor);
	
	descriptor->lob_current_position = 0;
	descriptor->lob_size = -1;				/* we should set it to -1 to know, that it's just not initialized */
	descriptor->buffering = PHP_OCI_LOB_BUFFER_DISABLED;				/* buffering is off by default */
	descriptor->charset_form = SQLCS_IMPLICIT;	/* default value */
	descriptor->charset_id = connection->charset;
	descriptor->is_open = 0;

	if (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE) {
		/* add Lobs & Files to hash. we'll flush them at the end */
		if (!connection->descriptors) {
			ALLOC_HASHTABLE(connection->descriptors);
			zend_hash_init(connection->descriptors, 0, NULL, php_oci_descriptor_flush_hash_dtor, 0);
			connection->descriptor_count = 0;
		}
		
		descriptor->index = (connection->descriptor_count)++;
		if (connection->descriptor_count == LONG_MAX) {
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal descriptor counter has reached limit");
			php_oci_connection_descriptors_free(connection TSRMLS_CC);
			return NULL;
		}

		zend_hash_index_update(connection->descriptors,descriptor->index,&descriptor,sizeof(php_oci_descriptor *),NULL);
	}
	return 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;
} /* }}} */