summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2004-05-21 13:26:58 +0000
committerWez Furlong <wez@php.net>2004-05-21 13:26:58 +0000
commitbf48daa8d595026dd8b4d0ff4030c4073ede9306 (patch)
tree0586cba18bc3432a2a0f11f127d644e00e5332b0
parent126531a44b240b15b1aedbe7b61869da5db5e75a (diff)
downloadphp-git-bf48daa8d595026dd8b4d0ff4030c4073ede9306.tar.gz
Version 1 of PDO_FETCH_LAZY
-rwxr-xr-xext/pdo/pdo.c5
-rwxr-xr-xext/pdo/pdo_dbh.c3
-rwxr-xr-xext/pdo/pdo_stmt.c206
-rwxr-xr-xext/pdo/php_pdo_driver.h4
-rwxr-xr-xext/pdo/php_pdo_int.h7
5 files changed, 219 insertions, 6 deletions
diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c
index a1aebf00cd..9751a634e9 100755
--- a/ext/pdo/pdo.c
+++ b/ext/pdo/pdo.c
@@ -51,7 +51,7 @@ PDO_API zend_class_entry *php_pdo_get_exception(void)
return pdo_exception_ce;
}
-zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce;
+zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce;
/* {{{ pdo_functions[] */
function_entry pdo_functions[] = {
@@ -258,6 +258,9 @@ PHP_MINIT_FUNCTION(pdo)
ce.create_object = pdo_dbstmt_new;
pdo_dbstmt_ce = zend_register_internal_class(&ce TSRMLS_CC);
+ INIT_CLASS_ENTRY(ce, "PDORow", pdo_row_functions);
+ ce.create_object = pdo_row_new;
+ pdo_row_ce = zend_register_internal_class(&ce TSRMLS_CC);
return SUCCESS;
}
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index 37705b5182..3ebe8b03fa 100755
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -242,6 +242,9 @@ static PHP_METHOD(PDO, prepare)
stmt->database_object_handle = *getThis();
zend_objects_store_add_ref(getThis() TSRMLS_CC);
stmt->dbh = dbh;
+
+ /* we haven't created a lazy object yet */
+ ZVAL_NULL(&stmt->lazy_object_ref);
return;
}
efree(stmt);
diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
index c68732dddb..5ba5241d16 100755
--- a/ext/pdo/pdo_stmt.c
+++ b/ext/pdo/pdo_stmt.c
@@ -163,6 +163,18 @@ static int describe_columns(pdo_stmt_t *stmt TSRMLS_DC)
return 1;
}
+static void get_lazy_object(pdo_stmt_t *stmt, zval *return_value TSRMLS_DC)
+{
+ if (Z_TYPE(stmt->lazy_object_ref) == IS_NULL) {
+ Z_TYPE(stmt->lazy_object_ref) = IS_OBJECT;
+ Z_OBJ_HANDLE(stmt->lazy_object_ref) = zend_objects_store_put(stmt, NULL, pdo_row_free_storage, NULL TSRMLS_CC);
+ Z_OBJ_HT(stmt->lazy_object_ref) = &pdo_row_object_handlers;
+ }
+ Z_TYPE_P(return_value) = IS_OBJECT;
+ Z_OBJ_HANDLE_P(return_value) = Z_OBJ_HANDLE(stmt->lazy_object_ref);
+ Z_OBJ_HT_P(return_value) = Z_OBJ_HT(stmt->lazy_object_ref);
+}
+
static void param_dtor(void *data)
{
struct pdo_bound_param_data *param = (struct pdo_bound_param_data *)data;
@@ -428,12 +440,15 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_
if (return_value) {
int i;
+ if (how == PDO_FETCH_LAZY) {
+ get_lazy_object(stmt, return_value TSRMLS_CC);
+ return 1;
+ }
+
array_init(return_value);
if (how == PDO_FETCH_OBJ) {
how = PDO_FETCH_ASSOC;
- } else if (how == PDO_FETCH_LAZY) {
- how = PDO_FETCH_BOTH;
}
for (i = 0; i < stmt->column_count; i++) {
@@ -698,12 +713,12 @@ static int dbstmt_dim_exists(zval *object, zval *member, int check_empty TSRMLS_
static void dbstmt_prop_delete(zval *object, zval *offset TSRMLS_DC)
{
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDO STMT");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDOStatement");
}
static void dbstmt_dim_delete(zval *object, zval *offset TSRMLS_DC)
{
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete dimensions from a PDO STMT");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete dimensions from a PDOStatement");
}
static HashTable *dbstmt_get_properties(zval *object TSRMLS_DC)
@@ -793,10 +808,16 @@ void pdo_dbstmt_free_storage(zend_object *object TSRMLS_DC)
if (stmt->methods && stmt->methods->dtor) {
stmt->methods->dtor(stmt TSRMLS_CC);
}
- if(stmt->query_string) {
+ if (stmt->query_string) {
efree(stmt->query_string);
}
zend_objects_store_del_ref(&stmt->database_object_handle TSRMLS_CC);
+#if 0
+ /* declared in the header, but not implemented... */
+ zend_objects_store_delete_obj(&stmt->lazy_object_ref TSRMLS_CC);
+#else
+ zend_objects_store_del_ref(&stmt->lazy_object_ref TSRMLS_CC);
+#endif
efree(stmt);
}
@@ -812,6 +833,181 @@ zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC)
}
/* }}} */
+/* {{{ overloaded handlers for PDORow class (used by PDO_FETCH_LAZY) */
+
+function_entry pdo_row_functions[] = {
+ {NULL, NULL, NULL}
+};
+
+static zval *row_prop_or_dim_read(zval *object, zval *member, int type TSRMLS_DC)
+{
+ zval *return_value;
+ pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
+ int colno = -1;
+
+ MAKE_STD_ZVAL(return_value);
+ convert_to_string(member);
+
+ /* look up the column */
+ /* TODO: replace this with a hash of available column names to column
+ * numbers */
+ for (colno = 0; colno < stmt->column_count; colno++) {
+ if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) {
+ fetch_value(stmt, return_value, colno TSRMLS_CC);
+ break;
+ }
+ }
+
+ return return_value;
+}
+
+static void row_prop_or_dim_write(zval *object, zval *member, zval *value TSRMLS_DC)
+{
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "This PDORow is not from a writable result set");
+}
+
+static int row_prop_or_dim_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
+{
+ pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
+ int colno = -1;
+
+ convert_to_string(member);
+
+ /* TODO: replace this with a hash of available column names to column
+ * numbers */
+ for (colno = 0; colno < stmt->column_count; colno++) {
+ if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void row_prop_or_dim_delete(zval *object, zval *offset TSRMLS_DC)
+{
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDORow");
+}
+
+static HashTable *row_get_properties(zval *object TSRMLS_DC)
+{
+ zval *tmp;
+ pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
+ int i;
+ HashTable *ht;
+
+ MAKE_STD_ZVAL(tmp);
+ array_init(tmp);
+
+ for (i = 0; i < stmt->column_count; i++) {
+ zval *val;
+ MAKE_STD_ZVAL(val);
+ fetch_value(stmt, val, i TSRMLS_CC);
+
+ add_assoc_zval(tmp, stmt->columns[i].name, val);
+ }
+
+ ht = Z_ARRVAL_P(tmp);
+
+ ZVAL_NULL(tmp);
+ FREE_ZVAL(tmp);
+
+ return ht;
+}
+
+static union _zend_function *row_method_get(zval *object, char *method_name, int method_len TSRMLS_DC)
+{
+ zend_function *fbc;
+ char *lc_method_name;
+
+ lc_method_name = do_alloca(method_len + 1);
+ zend_str_tolower_copy(lc_method_name, method_name, method_len);
+
+ if (zend_hash_find(&pdo_row_ce->function_table, lc_method_name, method_len+1, (void**)&fbc) == FAILURE) {
+ free_alloca(lc_method_name);
+ return NULL;
+ }
+
+ free_alloca(lc_method_name);
+ return fbc;
+}
+
+static int row_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
+{
+ return FAILURE;
+}
+
+static union _zend_function *row_get_ctor(zval *object TSRMLS_DC)
+{
+ static zend_internal_function ctor = {0};
+
+ ctor.type = ZEND_INTERNAL_FUNCTION;
+ ctor.function_name = "__construct";
+ ctor.scope = pdo_row_ce;
+ ctor.handler = ZEND_FN(dbstmt_constructor);
+
+ return (union _zend_function*)&ctor;
+}
+
+static zend_class_entry *row_get_ce(zval *object TSRMLS_DC)
+{
+ return pdo_dbstmt_ce;
+}
+
+static int row_get_classname(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
+{
+ *class_name = estrndup("PDORow", sizeof("PDORow")-1);
+ *class_name_len = sizeof("PDORow")-1;
+ return 0;
+}
+
+static int row_compare(zval *object1, zval *object2 TSRMLS_DC)
+{
+ return -1;
+}
+
+zend_object_handlers pdo_row_object_handlers = {
+ ZEND_OBJECTS_STORE_HANDLERS,
+ row_prop_or_dim_read,
+ row_prop_or_dim_write,
+ row_prop_or_dim_read,
+ row_prop_or_dim_write,
+ NULL,
+ NULL,
+ NULL,
+ row_prop_or_dim_exists,
+ row_prop_or_dim_delete,
+ row_prop_or_dim_exists,
+ row_prop_or_dim_delete,
+ row_get_properties,
+ row_method_get,
+ row_call_method,
+ row_get_ctor,
+ row_get_ce,
+ row_get_classname,
+ row_compare,
+ NULL, /* cast */
+ NULL
+};
+
+void pdo_row_free_storage(zend_object *object TSRMLS_DC)
+{
+ pdo_stmt_t *stmt = (pdo_stmt_t*)object;
+
+ /* nothing to do here */
+}
+
+zend_object_value pdo_row_new(zend_class_entry *ce TSRMLS_DC)
+{
+ zend_object_value retval;
+
+ retval.handle = zend_objects_store_put(NULL, NULL, pdo_row_free_storage, NULL TSRMLS_CC);
+ retval.handlers = &pdo_row_object_handlers;
+
+ return retval;
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h
index 97a4703088..e43a8976cd 100755
--- a/ext/pdo/php_pdo_driver.h
+++ b/ext/pdo/php_pdo_driver.h
@@ -352,6 +352,10 @@ struct _pdo_stmt_t {
/* the cursor specific error code. */
enum pdo_error_type error_code;
+
+ /* for lazy fetches, we always return the same lazy object handle.
+ * Let's keep it here. */
+ zval lazy_object_ref;
};
/* call this in MINIT to register your PDO driver */
diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h
index 2c3b73de31..882ee904e1 100755
--- a/ext/pdo/php_pdo_int.h
+++ b/ext/pdo/php_pdo_int.h
@@ -34,6 +34,13 @@ extern zend_class_entry *pdo_dbstmt_ce;
void pdo_dbstmt_free_storage(zend_object *object TSRMLS_DC);
extern zend_object_handlers pdo_dbstmt_object_handlers;
+extern zend_object_value pdo_row_new(zend_class_entry *ce TSRMLS_DC);
+extern function_entry pdo_row_functions[];
+extern zend_class_entry *pdo_row_ce;
+void pdo_row_free_storage(zend_object *object TSRMLS_DC);
+extern zend_object_handlers pdo_row_object_handlers;
+
+
extern pdo_driver_t *pdo_find_driver(const char *name, int namelen);
extern void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC);