]> granicus.if.org Git - php/commitdiff
Version 1 of PDO_FETCH_LAZY
authorWez Furlong <wez@php.net>
Fri, 21 May 2004 13:26:58 +0000 (13:26 +0000)
committerWez Furlong <wez@php.net>
Fri, 21 May 2004 13:26:58 +0000 (13:26 +0000)
ext/pdo/pdo.c
ext/pdo/pdo_dbh.c
ext/pdo/pdo_stmt.c
ext/pdo/php_pdo_driver.h
ext/pdo/php_pdo_int.h

index a1aebf00cd8c7b93c2ecfdbb0980b5b80ece12fc..9751a634e96af8b53af099c5f7e7c7dd206d545a 100755 (executable)
@@ -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;
 }
index 37705b518215d4c4dfb096f4af2b63b02ddd4076..3ebe8b03fa771bc43977bb262c68d031da175ef5 100755 (executable)
@@ -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);
index c68732dddb3d4eebf0974c74b233002d69ffa8ab..5ba5241d1618ab0b89fffac32ce87aa737755d59 100755 (executable)
@@ -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
index 97a4703088858cbbed4bbae3b39b4ed41494f11e..e43a8976cd12db4d3be9cff3dc556e667fce614a 100755 (executable)
@@ -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 */
index 2c3b73de31ef55a51e9991e59f308cabb5191003..882ee904e1c382b7bb4bd0f5b606e9bf68cd1562 100755 (executable)
@@ -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);