@@ -163,6 +163,18 @@ static int describe_columns(pdo_stmt_t *stmt TSRMLS_DC)
163163 return 1 ;
164164}
165165
166+ static void get_lazy_object (pdo_stmt_t * stmt , zval * return_value TSRMLS_DC )
167+ {
168+ if (Z_TYPE (stmt -> lazy_object_ref ) == IS_NULL ) {
169+ Z_TYPE (stmt -> lazy_object_ref ) = IS_OBJECT ;
170+ Z_OBJ_HANDLE (stmt -> lazy_object_ref ) = zend_objects_store_put (stmt , NULL , pdo_row_free_storage , NULL TSRMLS_CC );
171+ Z_OBJ_HT (stmt -> lazy_object_ref ) = & pdo_row_object_handlers ;
172+ }
173+ Z_TYPE_P (return_value ) = IS_OBJECT ;
174+ Z_OBJ_HANDLE_P (return_value ) = Z_OBJ_HANDLE (stmt -> lazy_object_ref );
175+ Z_OBJ_HT_P (return_value ) = Z_OBJ_HT (stmt -> lazy_object_ref );
176+ }
177+
166178static void param_dtor (void * data )
167179{
168180 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_
428440 if (return_value ) {
429441 int i ;
430442
443+ if (how == PDO_FETCH_LAZY ) {
444+ get_lazy_object (stmt , return_value TSRMLS_CC );
445+ return 1 ;
446+ }
447+
431448 array_init (return_value );
432449
433450 if (how == PDO_FETCH_OBJ ) {
434451 how = PDO_FETCH_ASSOC ;
435- } else if (how == PDO_FETCH_LAZY ) {
436- how = PDO_FETCH_BOTH ;
437452 }
438453
439454 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_
698713
699714static void dbstmt_prop_delete (zval * object , zval * offset TSRMLS_DC )
700715{
701- php_error_docref (NULL TSRMLS_CC , E_WARNING , "Cannot delete properties from a PDO STMT " );
716+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Cannot delete properties from a PDOStatement " );
702717}
703718
704719static void dbstmt_dim_delete (zval * object , zval * offset TSRMLS_DC )
705720{
706- php_error_docref (NULL TSRMLS_CC , E_WARNING , "Cannot delete dimensions from a PDO STMT " );
721+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Cannot delete dimensions from a PDOStatement " );
707722}
708723
709724static HashTable * dbstmt_get_properties (zval * object TSRMLS_DC )
@@ -793,10 +808,16 @@ void pdo_dbstmt_free_storage(zend_object *object TSRMLS_DC)
793808 if (stmt -> methods && stmt -> methods -> dtor ) {
794809 stmt -> methods -> dtor (stmt TSRMLS_CC );
795810 }
796- if (stmt -> query_string ) {
811+ if (stmt -> query_string ) {
797812 efree (stmt -> query_string );
798813 }
799814 zend_objects_store_del_ref (& stmt -> database_object_handle TSRMLS_CC );
815+ #if 0
816+ /* declared in the header, but not implemented... */
817+ zend_objects_store_delete_obj (& stmt -> lazy_object_ref TSRMLS_CC );
818+ #else
819+ zend_objects_store_del_ref (& stmt -> lazy_object_ref TSRMLS_CC );
820+ #endif
800821
801822 efree (stmt );
802823}
@@ -812,6 +833,181 @@ zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC)
812833}
813834/* }}} */
814835
836+ /* {{{ overloaded handlers for PDORow class (used by PDO_FETCH_LAZY) */
837+
838+ function_entry pdo_row_functions [] = {
839+ {NULL , NULL , NULL }
840+ };
841+
842+ static zval * row_prop_or_dim_read (zval * object , zval * member , int type TSRMLS_DC )
843+ {
844+ zval * return_value ;
845+ pdo_stmt_t * stmt = (pdo_stmt_t * ) zend_object_store_get_object (object TSRMLS_CC );
846+ int colno = -1 ;
847+
848+ MAKE_STD_ZVAL (return_value );
849+ convert_to_string (member );
850+
851+ /* look up the column */
852+ /* TODO: replace this with a hash of available column names to column
853+ * numbers */
854+ for (colno = 0 ; colno < stmt -> column_count ; colno ++ ) {
855+ if (strcmp (stmt -> columns [colno ].name , Z_STRVAL_P (member )) == 0 ) {
856+ fetch_value (stmt , return_value , colno TSRMLS_CC );
857+ break ;
858+ }
859+ }
860+
861+ return return_value ;
862+ }
863+
864+ static void row_prop_or_dim_write (zval * object , zval * member , zval * value TSRMLS_DC )
865+ {
866+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "This PDORow is not from a writable result set" );
867+ }
868+
869+ static int row_prop_or_dim_exists (zval * object , zval * member , int check_empty TSRMLS_DC )
870+ {
871+ pdo_stmt_t * stmt = (pdo_stmt_t * ) zend_object_store_get_object (object TSRMLS_CC );
872+ int colno = -1 ;
873+
874+ convert_to_string (member );
875+
876+ /* TODO: replace this with a hash of available column names to column
877+ * numbers */
878+ for (colno = 0 ; colno < stmt -> column_count ; colno ++ ) {
879+ if (strcmp (stmt -> columns [colno ].name , Z_STRVAL_P (member )) == 0 ) {
880+ return 1 ;
881+ }
882+ }
883+
884+ return 0 ;
885+ }
886+
887+ static void row_prop_or_dim_delete (zval * object , zval * offset TSRMLS_DC )
888+ {
889+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Cannot delete properties from a PDORow" );
890+ }
891+
892+ static HashTable * row_get_properties (zval * object TSRMLS_DC )
893+ {
894+ zval * tmp ;
895+ pdo_stmt_t * stmt = (pdo_stmt_t * ) zend_object_store_get_object (object TSRMLS_CC );
896+ int i ;
897+ HashTable * ht ;
898+
899+ MAKE_STD_ZVAL (tmp );
900+ array_init (tmp );
901+
902+ for (i = 0 ; i < stmt -> column_count ; i ++ ) {
903+ zval * val ;
904+ MAKE_STD_ZVAL (val );
905+ fetch_value (stmt , val , i TSRMLS_CC );
906+
907+ add_assoc_zval (tmp , stmt -> columns [i ].name , val );
908+ }
909+
910+ ht = Z_ARRVAL_P (tmp );
911+
912+ ZVAL_NULL (tmp );
913+ FREE_ZVAL (tmp );
914+
915+ return ht ;
916+ }
917+
918+ static union _zend_function * row_method_get (zval * object , char * method_name , int method_len TSRMLS_DC )
919+ {
920+ zend_function * fbc ;
921+ char * lc_method_name ;
922+
923+ lc_method_name = do_alloca (method_len + 1 );
924+ zend_str_tolower_copy (lc_method_name , method_name , method_len );
925+
926+ if (zend_hash_find (& pdo_row_ce -> function_table , lc_method_name , method_len + 1 , (void * * )& fbc ) == FAILURE ) {
927+ free_alloca (lc_method_name );
928+ return NULL ;
929+ }
930+
931+ free_alloca (lc_method_name );
932+ return fbc ;
933+ }
934+
935+ static int row_call_method (char * method , INTERNAL_FUNCTION_PARAMETERS )
936+ {
937+ return FAILURE ;
938+ }
939+
940+ static union _zend_function * row_get_ctor (zval * object TSRMLS_DC )
941+ {
942+ static zend_internal_function ctor = {0 };
943+
944+ ctor .type = ZEND_INTERNAL_FUNCTION ;
945+ ctor .function_name = "__construct" ;
946+ ctor .scope = pdo_row_ce ;
947+ ctor .handler = ZEND_FN (dbstmt_constructor );
948+
949+ return (union _zend_function * )& ctor ;
950+ }
951+
952+ static zend_class_entry * row_get_ce (zval * object TSRMLS_DC )
953+ {
954+ return pdo_dbstmt_ce ;
955+ }
956+
957+ static int row_get_classname (zval * object , char * * class_name , zend_uint * class_name_len , int parent TSRMLS_DC )
958+ {
959+ * class_name = estrndup ("PDORow" , sizeof ("PDORow" )- 1 );
960+ * class_name_len = sizeof ("PDORow" )- 1 ;
961+ return 0 ;
962+ }
963+
964+ static int row_compare (zval * object1 , zval * object2 TSRMLS_DC )
965+ {
966+ return -1 ;
967+ }
968+
969+ zend_object_handlers pdo_row_object_handlers = {
970+ ZEND_OBJECTS_STORE_HANDLERS ,
971+ row_prop_or_dim_read ,
972+ row_prop_or_dim_write ,
973+ row_prop_or_dim_read ,
974+ row_prop_or_dim_write ,
975+ NULL ,
976+ NULL ,
977+ NULL ,
978+ row_prop_or_dim_exists ,
979+ row_prop_or_dim_delete ,
980+ row_prop_or_dim_exists ,
981+ row_prop_or_dim_delete ,
982+ row_get_properties ,
983+ row_method_get ,
984+ row_call_method ,
985+ row_get_ctor ,
986+ row_get_ce ,
987+ row_get_classname ,
988+ row_compare ,
989+ NULL , /* cast */
990+ NULL
991+ };
992+
993+ void pdo_row_free_storage (zend_object * object TSRMLS_DC )
994+ {
995+ pdo_stmt_t * stmt = (pdo_stmt_t * )object ;
996+
997+ /* nothing to do here */
998+ }
999+
1000+ zend_object_value pdo_row_new (zend_class_entry * ce TSRMLS_DC )
1001+ {
1002+ zend_object_value retval ;
1003+
1004+ retval .handle = zend_objects_store_put (NULL , NULL , pdo_row_free_storage , NULL TSRMLS_CC );
1005+ retval .handlers = & pdo_row_object_handlers ;
1006+
1007+ return retval ;
1008+ }
1009+ /* }}} */
1010+
8151011/*
8161012 * Local variables:
8171013 * tab-width: 4
0 commit comments