]> granicus.if.org Git - php/commitdiff
merge PHP 5 pdo into HEAD. This source compiles on both PHP 5 and PHP 6.
authorWez Furlong <wez@php.net>
Sat, 9 Dec 2006 22:18:43 +0000 (22:18 +0000)
committerWez Furlong <wez@php.net>
Sat, 9 Dec 2006 22:18:43 +0000 (22:18 +0000)
If you're poking around in here, please make sure that any changes you make
compile on both PHP 5 and 6.  Thanks!

ext/pdo/config.m4
ext/pdo/pdo.c
ext/pdo/pdo_dbh.c
ext/pdo/pdo_sql_parser.c
ext/pdo/pdo_stmt.c
ext/pdo/php_pdo.h
ext/pdo/php_pdo_driver.h
ext/pdo/php_pdo_int.h
ext/pdo/php_pdo_phpvers_compat.h

index c823b7b45e7750706343bc247f95fd52dfa022da..8d5cc7253e7994db99021a4fc72e1c18d915244c 100755 (executable)
@@ -49,7 +49,10 @@ for more detail on this issue.
     esac
   fi
   PHP_NEW_EXTENSION(pdo, pdo.c pdo_dbh.c pdo_stmt.c pdo_sql_parser.c pdo_sqlstate.c, $ext_shared)
-  PHP_ADD_EXTENSION_DEP(pdo, spl, true) 
+  ifdef([PHP_ADD_EXTENSION_DEP],
+  [
+    PHP_ADD_EXTENSION_DEP(pdo, spl, true)
+  ])
   
   ifdef([PHP_INSTALL_HEADERS],
   [
index b4b3f202abcc265f3eba3c589d00fee9c4d7b8f3..e4b53b9b30add4e9ea86fb45ff4fdfed9cccd9a0 100755 (executable)
@@ -54,7 +54,12 @@ int php_pdo_list_entry(void)
 /* for exceptional circumstances */
 zend_class_entry *pdo_exception_ce;
 
-PDO_API zend_class_entry *php_pdo_get_exception(TSRMLS_D)
+PDO_API zend_class_entry *php_pdo_get_dbh_ce(void)
+{
+       return pdo_dbh_ce;
+}
+
+PDO_API zend_class_entry *php_pdo_get_exception(void)
 {
        return pdo_exception_ce;
 }
@@ -68,7 +73,7 @@ PDO_API char *php_pdo_str_tolower_dup(const char *src, int len)
 
 PDO_API zend_class_entry *php_pdo_get_exception_base(int root TSRMLS_DC)
 {
-#if can_handle_soft_dependency_on_SPL && defined(HAVE_SPL)
+#if can_handle_soft_dependency_on_SPL && defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
        if (!root) {
                if (!spl_ce_RuntimeException) {
                        zend_class_entry **pce;
@@ -82,7 +87,7 @@ PDO_API zend_class_entry *php_pdo_get_exception_base(int root TSRMLS_DC)
                }
        }
 #endif
-#if (PHP_MAJOR_VERSION < 6)
+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2)
        return zend_exception_get_default();
 #else
        return zend_exception_get_default(TSRMLS_C);
@@ -151,7 +156,7 @@ zend_module_entry pdo_module_entry = {
 /* }}} */
 
 /* TODO: visit persistent handles: for each persistent statement handle,
- * remove bound parameter associations in RSHUTDOWN */
+ * remove bound parameter associations */
 
 #ifdef COMPILE_DL_PDO
 ZEND_GET_MODULE(pdo)
@@ -368,6 +373,8 @@ PHP_MINFO_FUNCTION(pdo)
 
        if (drivers) {
                efree(drivers);
+       } else {
+               efree(ldrivers);
        }
 
        php_info_print_table_end();
index 5f6f92bad23feed1979f32dd066ee1ad6a432193..895d2f48ade54ecee3808b17bf9de2de2ff6bcf6 100755 (executable)
@@ -75,7 +75,7 @@ void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *sqlstate
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
        } else {
                zval *ex, *info;
-               zend_class_entry *def_ex = php_pdo_get_exception_base(1 TSRMLS_CC), *pdo_ex = php_pdo_get_exception(TSRMLS_C);
+               zend_class_entry *def_ex = php_pdo_get_exception_base(1 TSRMLS_CC), *pdo_ex = php_pdo_get_exception();
 
                MAKE_STD_ZVAL(ex);
                object_init_ex(ex, pdo_ex);
@@ -153,7 +153,7 @@ void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
        } else if (EG(exception) == NULL) {
                zval *ex;
-               zend_class_entry *def_ex = php_pdo_get_exception_base(1 TSRMLS_CC), *pdo_ex = php_pdo_get_exception(TSRMLS_C);
+               zend_class_entry *def_ex = php_pdo_get_exception_base(1 TSRMLS_CC), *pdo_ex = php_pdo_get_exception();
 
                MAKE_STD_ZVAL(ex);
                object_init_ex(ex, pdo_ex);
@@ -187,7 +187,7 @@ static char *dsn_from_uri(char *uri, char *buf, size_t buflen TSRMLS_DC) /* {{{
        php_stream *stream;
        char *dsn = NULL;
 
-       stream = php_stream_open_wrapper(uri, "rb", REPORT_ERRORS, NULL);
+       stream = php_stream_open_wrapper(uri, "rb", ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
        if (stream) {
                dsn = php_stream_get_line(stream, ZSTR(buf), buflen, NULL);
                php_stream_close(stream);
@@ -228,7 +228,7 @@ static PHP_METHOD(PDO, dbh_constructor)
 
                snprintf(alt_dsn, sizeof(alt_dsn), "pdo.dsn.%s", data_source);
                if (FAILURE == cfg_get_string(alt_dsn, &ini_dsn)) {
-                       zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "invalid data source name");
+                       zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "invalid data source name");
                        ZVAL_NULL(object);
                        return;
                }
@@ -237,7 +237,7 @@ static PHP_METHOD(PDO, dbh_constructor)
                colon = strchr(data_source, ':');
                
                if (!colon) {
-                       zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "invalid data source name (via INI: %s)", alt_dsn);
+                       zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "invalid data source name (via INI: %s)", alt_dsn);
                        ZVAL_NULL(object);
                        return;
                }
@@ -245,15 +245,15 @@ static PHP_METHOD(PDO, dbh_constructor)
 
        if (!strncmp(data_source, "uri:", sizeof("uri:")-1)) {
                /* the specified URI holds connection details */
-               data_source = dsn_from_uri(data_source, alt_dsn, sizeof(alt_dsn) TSRMLS_CC);
+               data_source = dsn_from_uri(data_source + sizeof("uri:")-1, alt_dsn, sizeof(alt_dsn) TSRMLS_CC);
                if (!data_source) {
-                       zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "invalid data source URI");
+                       zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "invalid data source URI");
                        ZVAL_NULL(object);
                        return;
                }
                colon = strchr(data_source, ':');
                if (!colon) {
-                       zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "invalid data source name (via URI)");
+                       zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "invalid data source name (via URI)");
                        ZVAL_NULL(object);
                        return;
                }
@@ -264,7 +264,7 @@ static PHP_METHOD(PDO, dbh_constructor)
        if (!driver) {
                /* NB: don't want to include the data_source in the error message as
                 * it might contain a password */
-               zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "could not find driver");
+               zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "could not find driver");
                ZVAL_NULL(object);
                return;
        }
@@ -274,7 +274,7 @@ static PHP_METHOD(PDO, dbh_constructor)
        /* is this supposed to be a persistent connection ? */
        if (options) {
                zval **v;
-               int plen;
+               int plen = 0;
                char *hashkey = NULL;
                zend_rsrc_list_entry *le;
                pdo_dbh_t *pdbh = NULL;
@@ -394,11 +394,12 @@ static PHP_METHOD(PDO, dbh_constructor)
                if (options) {
                        zval **attr_value;
                        zstr str_key;
-                       long long_key;
+                       ulong long_key;
                        
                        zend_hash_internal_pointer_reset(Z_ARRVAL_P(options));
                        while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(options), (void**)&attr_value) 
-                                 && HASH_KEY_IS_LONG == zend_hash_get_current_key(Z_ARRVAL_P(options), &str_key, &long_key, 0)) {
+                                       && HASH_KEY_IS_LONG == zend_hash_get_current_key(Z_ARRVAL_P(options),
+                                               &str_key, &long_key, 0)) {
                                
                                pdo_dbh_attribute_set(dbh, long_key, *attr_value TSRMLS_CC);
                                zend_hash_move_forward(Z_ARRVAL_P(options));
@@ -445,7 +446,7 @@ static void pdo_stmt_construct(pdo_stmt_t *stmt, zval *object, zend_class_entry
        ZVAL_ASCII_STRINGL(&z_key, "queryString", sizeof("queryString")-1, 0);
        std_object_handlers.write_property(object, &z_key, query_string TSRMLS_CC);
        zval_ptr_dtor(&query_string);
-#ifdef UG
+#ifdef IS_UNICODE
        if (UG(unicode)) {
                zval_dtor(&z_key);
        }
@@ -520,7 +521,7 @@ static PHP_METHOD(PDO, prepare)
 
        if (ZEND_NUM_ARGS() > 1 && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_STATEMENT_CLASS, (void**)&opt)) {
                if (Z_TYPE_PP(opt) != IS_ARRAY || zend_hash_index_find(Z_ARRVAL_PP(opt), 0, (void**)&item) == FAILURE
-                       || !PDO_ZVAL_PP_IS_TEXT(item)
+                       || PDO_ZVAL_PP_IS_TEXT(item)
                        || zend_u_lookup_class(Z_TYPE_PP(item), Z_UNIVAL_PP(item), Z_UNILEN_PP(item), &pce TSRMLS_CC) == FAILURE
                ) {
                        pdo_raise_impl_error(dbh, NULL, "HY000", 
@@ -605,14 +606,14 @@ static PHP_METHOD(PDO, beginTransaction)
        PDO_CONSTRUCT_CHECK;
 
        if (dbh->in_txn) {
-               zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "There is already an active transaction");
+               zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "There is already an active transaction");
                RETURN_FALSE;
        }
        
        if (!dbh->methods->begin) {
                /* TODO: this should be an exception; see the auto-commit mode
                 * comments below */
-               zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "This driver doesn't support transactions");
+               zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "This driver doesn't support transactions");
                RETURN_FALSE;
        }
 
@@ -635,7 +636,7 @@ static PHP_METHOD(PDO, commit)
        PDO_CONSTRUCT_CHECK;
 
        if (!dbh->in_txn) {
-               zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "There is no active transaction");
+               zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "There is no active transaction");
                RETURN_FALSE;
        }
 
@@ -658,7 +659,7 @@ static PHP_METHOD(PDO, rollBack)
        PDO_CONSTRUCT_CHECK;
 
        if (!dbh->in_txn) {
-               zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "There is no active transaction");
+               zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "There is no active transaction");
                RETURN_FALSE;
        }
 
@@ -720,6 +721,7 @@ static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, long attr, zval *value TSRMLS_D
                                        }
                                }
                        }
+
                        convert_to_long(value);
                        if (Z_LVAL_P(value) == PDO_FETCH_USE_DEFAULT) {
                                pdo_raise_impl_error(dbh, NULL, "HY000", "invalid fetch mode type" TSRMLS_CC);
@@ -804,7 +806,7 @@ static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, long attr, zval *value TSRMLS_D
 
 fail:
        if (attr == PDO_ATTR_AUTOCOMMIT) {
-               zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "The auto-commit mode cannot be changed for this driver");
+               zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "The auto-commit mode cannot be changed for this driver");
        } else if (!dbh->methods->set_attribute) {
                pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support setting attributes" TSRMLS_CC);
        } else {
@@ -968,6 +970,10 @@ static PHP_METHOD(PDO, errorCode)
        }
        PDO_CONSTRUCT_CHECK;
 
+       if (dbh->query_stmt) {
+               RETURN_STRING(dbh->query_stmt->error_code, 1);
+       }
+       
        RETURN_STRING(dbh->error_code, 1);
 }
 /* }}} */
@@ -984,10 +990,14 @@ static PHP_METHOD(PDO, errorInfo)
        PDO_CONSTRUCT_CHECK;
 
        array_init(return_value);
-       add_next_index_string(return_value, dbh->error_code, 1);
 
+       if (dbh->query_stmt) {
+               add_next_index_string(return_value, dbh->query_stmt->error_code, 1);
+       } else {
+               add_next_index_string(return_value, dbh->error_code, 1);
+       }
        if (dbh->methods->fetch_err) {
-               dbh->methods->fetch_err(dbh, NULL, return_value TSRMLS_CC);
+               dbh->methods->fetch_err(dbh, dbh->query_stmt, return_value TSRMLS_CC);
        }
 }
 /* }}} */
@@ -1051,6 +1061,12 @@ static PHP_METHOD(PDO, query)
                        }
                }
                /* something broke */
+               dbh->query_stmt = stmt;
+               dbh->query_stmt_zval = *return_value;
+               PDO_HANDLE_STMT_ERR();
+       } else {
+               PDO_HANDLE_DBH_ERR();
+               zval_dtor(return_value);
        }
 
        RETURN_FALSE;
@@ -1092,7 +1108,7 @@ static PHP_METHOD(PDO, quote)
    Prevents use of a PDO instance that has been unserialized */
 static PHP_METHOD(PDO, __wakeup)
 {
-       zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "You cannot serialize or unserialize PDO instances");
+       zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDO instances");
 }
 /* }}} */
 
@@ -1100,7 +1116,7 @@ static PHP_METHOD(PDO, __wakeup)
    Prevents serialization of a PDO instance */
 static PHP_METHOD(PDO, __sleep)
 {
-       zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "You cannot serialize or unserialize PDO instances");
+       zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDO instances");
 }
 /* }}} */
 
@@ -1160,14 +1176,14 @@ int pdo_hash_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
        }
 
        if (!(dbh->cls_methods[kind] = pemalloc(sizeof(HashTable), dbh->is_persistent))) {
-               php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory while allocating PDO methods");
+               php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory while allocating PDO methods.");
        }
        zend_hash_init_ex(dbh->cls_methods[kind], 8, NULL, NULL, dbh->is_persistent, 0);
 
        while (funcs->fname) {
                ifunc->type = ZEND_INTERNAL_FUNCTION;
                ifunc->handler = funcs->handler;
-               ifunc->function_name.s = funcs->fname;
+               pdo_zstr_sval(ifunc->function_name) = funcs->fname;
                ifunc->scope = dbh->ce;
                ifunc->prototype = NULL;
                if (funcs->arg_info) {
@@ -1209,7 +1225,8 @@ static union _zend_function *dbh_method_get(
 #else
        zval *object,
 #endif
-       zstr method_name, int method_len TSRMLS_DC)
+       zstr method_name,
+       int method_len TSRMLS_DC)
 {
        zend_function *fbc = NULL;
        zstr lc_method_name;
@@ -1223,7 +1240,8 @@ static union _zend_function *dbh_method_get(
 
        lc_method_name = zend_u_str_tolower_dup(ztype, method_name, method_len);
 
-       if (zend_u_hash_find(&dbh->ce->function_table, ztype, lc_method_name, method_len+1, (void**)&fbc) == FAILURE) {
+       if (zend_u_hash_find(&dbh->ce->function_table, ztype, lc_method_name,
+                       method_len+1, (void**)&fbc) == FAILURE) {
                /* not a pre-defined method, nor a user-defined method; check
                 * the driver specific methods */
                if (!dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH]) {
@@ -1243,7 +1261,7 @@ static union _zend_function *dbh_method_get(
        }
        
 out:
-       efree(lc_method_name.v);
+       pdo_zstr_efree(lc_method_name);
        return fbc;
 }
 
@@ -1252,7 +1270,16 @@ static int dbh_compare(zval *object1, zval *object2 TSRMLS_DC)
        return -1;
 }
 
+static zend_object_value dbh_ze1_clone_obj(zval *object TSRMLS_DC)
+{
+       php_error(E_ERROR, "Cannot clone object of class %s due to 'zend.ze1_compatibility_mode'", Z_OBJCE_P(object)->name);
+       return object->value.obj;
+}
+
 static zend_object_handlers pdo_dbh_object_handlers;
+#if PHP_MAJOR_VERSION < 6
+static zend_object_handlers pdo_dbh_object_handlers_ze1;
+#endif
 
 void pdo_dbh_init(TSRMLS_D)
 {
@@ -1265,6 +1292,13 @@ void pdo_dbh_init(TSRMLS_D)
        memcpy(&pdo_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
        pdo_dbh_object_handlers.get_method = dbh_method_get;
        pdo_dbh_object_handlers.compare_objects = dbh_compare;
+       
+#if PHP_MAJOR_VERSION < 6
+       memcpy(&pdo_dbh_object_handlers_ze1, &std_object_handlers, sizeof(zend_object_handlers));
+       pdo_dbh_object_handlers_ze1.get_method = dbh_method_get;
+       pdo_dbh_object_handlers_ze1.compare_objects = dbh_compare;
+       pdo_dbh_object_handlers_ze1.clone_obj = dbh_ze1_clone_obj;
+#endif
 
        REGISTER_PDO_CLASS_CONST_LONG("PARAM_BOOL", (long)PDO_PARAM_BOOL);
        REGISTER_PDO_CLASS_CONST_LONG("PARAM_NULL", (long)PDO_PARAM_NULL);
@@ -1280,6 +1314,7 @@ void pdo_dbh_init(TSRMLS_D)
        REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_EXEC_POST",    (long)PDO_PARAM_EVT_EXEC_POST);
        REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_FETCH_PRE",    (long)PDO_PARAM_EVT_FETCH_PRE);
        REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_FETCH_POST",   (long)PDO_PARAM_EVT_FETCH_POST);
+       REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_NORMALIZE",    (long)PDO_PARAM_EVT_NORMALIZE);
 
        REGISTER_PDO_CLASS_CONST_LONG("FETCH_LAZY", (long)PDO_FETCH_LAZY);
        REGISTER_PDO_CLASS_CONST_LONG("FETCH_ASSOC",(long)PDO_FETCH_ASSOC);
@@ -1319,6 +1354,7 @@ void pdo_dbh_init(TSRMLS_D)
        REGISTER_PDO_CLASS_CONST_LONG("ATTR_DRIVER_NAME",               (long)PDO_ATTR_DRIVER_NAME);
        REGISTER_PDO_CLASS_CONST_LONG("ATTR_STRINGIFY_FETCHES",(long)PDO_ATTR_STRINGIFY_FETCHES);
        REGISTER_PDO_CLASS_CONST_LONG("ATTR_MAX_COLUMN_LEN",(long)PDO_ATTR_MAX_COLUMN_LEN);
+       REGISTER_PDO_CLASS_CONST_LONG("ATTR_EMULATE_PREPARES",(long)PDO_ATTR_EMULATE_PREPARES);
        REGISTER_PDO_CLASS_CONST_LONG("ATTR_DEFAULT_FETCH_MODE",(long)PDO_ATTR_DEFAULT_FETCH_MODE);
        
        REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_SILENT", (long)PDO_ERRMODE_SILENT);
@@ -1406,12 +1442,12 @@ static void dbh_free(pdo_dbh_t *dbh TSRMLS_DC)
 
 PDO_API void php_pdo_dbh_addref(pdo_dbh_t *dbh TSRMLS_DC)
 {
-        dbh->refcount++;
+       dbh->refcount++;
 }
 
 PDO_API void php_pdo_dbh_delref(pdo_dbh_t *dbh TSRMLS_DC)
 {
-        dbh_free(dbh TSRMLS_CC);
+       dbh_free(dbh TSRMLS_CC);
 }
 
 static void pdo_dbh_free_storage(pdo_dbh_t *dbh TSRMLS_DC)
@@ -1450,7 +1486,11 @@ zend_object_value pdo_dbh_new(zend_class_entry *ce TSRMLS_DC)
        dbh->def_stmt_ce = pdo_dbstmt_ce;
        
        retval.handle = zend_objects_store_put(dbh, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_dbh_free_storage, NULL TSRMLS_CC);
+#if PHP_MAJOR_VERSION < 6
+       retval.handlers = EG(ze1_compatibility_mode) ? &pdo_dbh_object_handlers_ze1 : &pdo_dbh_object_handlers;
+#else
        retval.handlers = &pdo_dbh_object_handlers;
+#endif
        
        return retval;
 }
index 4ae1b01614b017e2af4c575757773e046997f8a0..d217095da46c187f3ee2b1814b85e1877acfb619 100644 (file)
@@ -1,5 +1,5 @@
-/* Generated by re2c 0.10.6 on Tue Dec  5 13:05:42 2006 */
-#line 1 "ext/pdo/pdo_sql_parser.re"
+/* Generated by re2c 0.10.6 on Sat Dec  9 17:16:39 2006 */
+#line 1 "pdo_sql_parser.re"
 /*
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
@@ -46,7 +46,7 @@ static int scan(Scanner *s)
        char *cursor = s->cur;
 
        s->tok = cursor;
-       #line 53 "ext/pdo/pdo_sql_parser.re"
+       #line 53 "pdo_sql_parser.re"
 
 
        {
@@ -85,7 +85,7 @@ static int scan(Scanner *s)
                162, 162, 162, 162, 162, 162, 162, 162, 
        };
 
-#line 89 "ext/pdo/pdo_sql_parser.c"
+#line 89 "pdo_sql_parser.c"
        {
                YYCTYPE yych;
 
@@ -107,9 +107,9 @@ yy2:
                if(yych == '"') goto yy26;
                goto yy30;
 yy3:
-#line 61 "ext/pdo/pdo_sql_parser.re"
+#line 61 "pdo_sql_parser.re"
                { RET(PDO_PARSER_TEXT); }
-#line 113 "ext/pdo/pdo_sql_parser.c"
+#line 113 "pdo_sql_parser.c"
 yy4:
                yych = *++YYCURSOR;
                if(yybm[0+yych] & 16) {
@@ -142,9 +142,9 @@ yy6:
                if(yybm[0+(yych = *YYCURSOR)] & 4) {
                        goto yy13;
                }
-#line 60 "ext/pdo/pdo_sql_parser.re"
+#line 60 "pdo_sql_parser.re"
                { RET(PDO_PARSER_BIND_POS); }
-#line 148 "ext/pdo/pdo_sql_parser.c"
+#line 148 "pdo_sql_parser.c"
 yy8:
                ++YYCURSOR;
                if(YYLIMIT == YYCURSOR) YYFILL(1);
@@ -152,14 +152,14 @@ yy8:
                if(yybm[0+yych] & 2) {
                        goto yy8;
                }
-#line 62 "ext/pdo/pdo_sql_parser.re"
+#line 62 "pdo_sql_parser.re"
                { RET(PDO_PARSER_TEXT); }
-#line 158 "ext/pdo/pdo_sql_parser.c"
+#line 158 "pdo_sql_parser.c"
 yy11:
                ++YYCURSOR;
-#line 63 "ext/pdo/pdo_sql_parser.re"
+#line 63 "pdo_sql_parser.re"
                { RET(PDO_PARSER_EOI); }
-#line 163 "ext/pdo/pdo_sql_parser.c"
+#line 163 "pdo_sql_parser.c"
 yy13:
                ++YYCURSOR;
                if(YYLIMIT == YYCURSOR) YYFILL(1);
@@ -167,9 +167,9 @@ yy13:
                if(yybm[0+yych] & 4) {
                        goto yy13;
                }
-#line 58 "ext/pdo/pdo_sql_parser.re"
+#line 58 "pdo_sql_parser.re"
                { RET(PDO_PARSER_TEXT); }
-#line 173 "ext/pdo/pdo_sql_parser.c"
+#line 173 "pdo_sql_parser.c"
 yy16:
                ++YYCURSOR;
                if(YYLIMIT == YYCURSOR) YYFILL(1);
@@ -177,9 +177,9 @@ yy16:
                if(yybm[0+yych] & 8) {
                        goto yy16;
                }
-#line 59 "ext/pdo/pdo_sql_parser.re"
+#line 59 "pdo_sql_parser.re"
                { RET(PDO_PARSER_BIND); }
-#line 183 "ext/pdo/pdo_sql_parser.c"
+#line 183 "pdo_sql_parser.c"
 yy19:
                if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
                yych = *YYCURSOR;
@@ -193,9 +193,9 @@ yy21:
                        goto yy13;
                }
 yy22:
-#line 57 "ext/pdo/pdo_sql_parser.re"
+#line 57 "pdo_sql_parser.re"
                { RET(PDO_PARSER_TEXT); }
-#line 199 "ext/pdo/pdo_sql_parser.c"
+#line 199 "pdo_sql_parser.c"
 yy23:
                ++YYCURSOR;
                if(YYLIMIT == YYCURSOR) YYFILL(1);
@@ -211,9 +211,9 @@ yy26:
                        goto yy13;
                }
 yy27:
-#line 56 "ext/pdo/pdo_sql_parser.re"
+#line 56 "pdo_sql_parser.re"
                { RET(PDO_PARSER_TEXT); }
-#line 217 "ext/pdo/pdo_sql_parser.c"
+#line 217 "pdo_sql_parser.c"
 yy28:
                if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
                yych = *YYCURSOR;
@@ -233,7 +233,7 @@ yy30:
                goto yy27;
        }
 }
-#line 64 "ext/pdo/pdo_sql_parser.re"
+#line 64 "pdo_sql_parser.re"
        
 }
 
index 27dfb64c06d2b054f91fe02734eeef15d6ace115..7c1e1e254a624c3a1734222c48b759e14f424e43 100755 (executable)
@@ -291,7 +291,7 @@ static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_s
                ZVAL_ADDREF(param->driver_params);
        }
 
-       if (param->name && stmt->columns) {
+       if (!is_param && param->name && stmt->columns) {
                /* try to map the name to the column */
                int i;
 
@@ -302,13 +302,11 @@ static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_s
                        }
                }
 
-#if 0
                /* if you prepare and then execute passing an array of params keyed by names,
                 * then this will trigger, and we don't want that */
                if (param->paramno == -1) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Did not found column name '%s' in the defined columns; it will not be bound", param->name);
                }
-#endif
        }
 
        if (param->name) {
@@ -320,24 +318,61 @@ static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_s
                } else {
                        param->name = estrndup(param->name, param->namelen);
                }
-               zend_hash_update(hash, param->name, param->namelen, param, sizeof(*param), (void**)&pparam);
-       } else {
-               zend_hash_index_update(hash, param->paramno, param, sizeof(*param), (void**)&pparam);
        }
 
-       if (is_param && !rewrite_name_to_position(stmt, pparam TSRMLS_CC)) {
+       if (is_param && !rewrite_name_to_position(stmt, param TSRMLS_CC)) {
                if (param->name) {
                        efree(param->name);
                        param->name = NULL;
                }
                return 0;
        }
-       
-       /* tell the driver we just created a parameter */
+
+       /* ask the driver to perform any normalization it needs on the
+        * parameter name.  Note that it is illegal for the driver to take
+        * a reference to param, as it resides in transient storage only
+        * at this time. */
        if (stmt->methods->param_hook) {
-               return stmt->methods->param_hook(stmt, pparam, PDO_PARAM_EVT_ALLOC TSRMLS_CC);
+               if (!stmt->methods->param_hook(stmt, param, PDO_PARAM_EVT_NORMALIZE
+                               TSRMLS_CC)) {
+                       if (param->name) {
+                               efree(param->name);
+                               param->name = NULL;
+                       }
+                       return 0;
+               }
+       }
+
+       /* delete any other parameter registered with this number.
+        * If the parameter is named, it will be removed and correctly
+        * disposed of by the hash_update call that follows */
+       if (param->paramno >= 0) {
+               zend_hash_index_del(hash, param->paramno);
+       }
+
+       /* allocate storage for the parameter, keyed by its "canonical" name */
+       if (param->name) {
+               zend_hash_update(hash, param->name, param->namelen, param,
+                       sizeof(*param), (void**)&pparam);
+       } else {
+               zend_hash_index_update(hash, param->paramno, param, sizeof(*param),
+                       (void**)&pparam);
        }
 
+       /* tell the driver we just created a parameter */
+       if (stmt->methods->param_hook) {
+               if (!stmt->methods->param_hook(stmt, pparam, PDO_PARAM_EVT_ALLOC
+                                       TSRMLS_CC)) {
+                       /* undo storage allocation; the hash will free the parameter
+                        * name if required */
+                       if (pparam->name) {
+                               zend_hash_del(hash, pparam->name, pparam->namelen);
+                       } else {
+                               zend_hash_index_del(hash, pparam->paramno);
+                       }
+                       return 0;
+               }
+       }
        return 1;
 }
 /* }}} */
@@ -371,13 +406,13 @@ static PHP_METHOD(PDOStatement, execute)
                zend_hash_internal_pointer_reset(Z_ARRVAL_P(input_params));
                while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(input_params), (void*)&tmp)) {
                        zstr tmp_str;
-
+                       
                        memset(&param, 0, sizeof(param));
 
                        if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(input_params),
                                                &tmp_str, &str_length, &num_index, 0, NULL)) {
                                /* yes this is correct.  we don't want to count the null byte.  ask wez */
-                               param.name = tmp_str.s;
+                               param.name = pdo_zstr_sval(tmp_str);
                                param.namelen = str_length - 1;
                                param.paramno = -1;
                        } else {
@@ -458,21 +493,24 @@ static PHP_METHOD(PDOStatement, execute)
 }
 /* }}} */
 
-static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno TSRMLS_DC) /* {{{ */
+static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *type_override TSRMLS_DC) /* {{{ */
 {
        struct pdo_column_data *col;
        char *value = NULL;
        unsigned long value_len = 0;
        int caller_frees = 0;
+       int type, new_type;
 
        col = &stmt->columns[colno];
+       type = PDO_PARAM_TYPE(col->param_type);
+       new_type =  type_override ? PDO_PARAM_TYPE(*type_override) : type;
 
        value = NULL;
        value_len = 0;
 
        stmt->methods->get_col(stmt, colno, &value, &value_len, &caller_frees TSRMLS_CC);
 
-       switch (PDO_PARAM_TYPE(col->param_type)) {
+       switch (type) {
                case PDO_PARAM_INT:
                        if (value && value_len == sizeof(long)) {
                                ZVAL_LONG(dest, *(long*)value);
@@ -493,8 +531,16 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno TSRMLS_DC
                        if (value == NULL) {
                                ZVAL_NULL(dest);
                        } else if (value_len == 0) {
-                               php_stream_to_zval((php_stream*)value, dest);
-                       } else {
+                               if (stmt->dbh->stringify || new_type == PDO_PARAM_STR) {
+                                       char *buf = NULL;
+                                       size_t len;
+                                       len = php_stream_copy_to_mem((php_stream*)value, &buf, PHP_STREAM_COPY_ALL, 0);
+                                       ZVAL_STRINGL(dest, buf, len, 0);
+                                       php_stream_close((php_stream*)value);
+                               } else {
+                                       php_stream_to_zval((php_stream*)value, dest);
+                               }
+                       } else if (!stmt->dbh->stringify && new_type != PDO_PARAM_STR) {
                                /* they gave us a string, but LOBs are represented as streams in PDO */
                                php_stream *stm;
 #ifdef TEMP_STREAM_TAKE_BUFFER
@@ -513,27 +559,17 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno TSRMLS_DC
                                } else {
                                        ZVAL_NULL(dest);
                                }
+                       } else {
+                               ZVAL_STRINGL(dest, value, value_len, !caller_frees);
+                               if (caller_frees) {
+                                       caller_frees = 0;
+                               }
                        }
                        break;
                
                case PDO_PARAM_STR:
                        if (value && !(value_len == 0 && stmt->dbh->oracle_nulls == PDO_NULL_EMPTY_STRING)) {
-#ifdef IS_UNICODE
-                               if (UG(unicode)) {
-                                       UErrorCode status = U_ZERO_ERROR;
-                                       UChar *u_str;
-                                       int u_len;
-                       
-                                       zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u_str, &u_len, value, value_len, &status);
-                                       ZVAL_UNICODEL(dest, u_str, u_len, 0);
-                                       if (caller_frees) {
-                                               efree(value);
-                                       }
-                               } else 
-#endif
-                               {
-                                       ZVAL_STRINGL(dest, value, value_len, !caller_frees);
-                               }
+                               ZVAL_STRINGL(dest, value, value_len, !caller_frees);
                                if (caller_frees) {
                                        caller_frees = 0;
                                }
@@ -543,6 +579,25 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno TSRMLS_DC
                        ZVAL_NULL(dest);
        }
 
+       if (type != new_type) {
+               switch (new_type) {
+                       case PDO_PARAM_INT:
+                               convert_to_long_ex(&dest);
+                               break;
+                       case PDO_PARAM_BOOL:
+                               convert_to_boolean_ex(&dest);
+                               break;
+                       case PDO_PARAM_STR:
+                               convert_to_string_ex(&dest);
+                               break;
+                       case PDO_PARAM_NULL:
+                               convert_to_null_ex(&dest);
+                               break;
+                       default:
+                               ;
+               }
+       }
+       
        if (caller_frees && value) {
                efree(value);
        }
@@ -599,7 +654,7 @@ static int do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori,
                                zval_dtor(param->parameter);
 
                                /* set new value */
-                               fetch_value(stmt, param->parameter, param->paramno TSRMLS_CC);
+                               fetch_value(stmt, param->parameter, param->paramno, (int *)&param->param_type TSRMLS_CC);
 
                                /* TODO: some smart thing that avoids duplicating the value in the
                                 * general loop below.  For now, if you're binding output columns,
@@ -666,10 +721,9 @@ static int do_fetch_class_prepare(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
 static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info * fci, zend_fcall_info_cache * fcc, int num_args TSRMLS_DC) /* {{{ */
 {
        zval **object = NULL, **method = NULL;
+       char *fname = NULL, *cname;
        zend_class_entry * ce = NULL, **pce;
        zend_function *function_handler;
-       zstr lcname;
-       unsigned int lcname_len;
        
        if (Z_TYPE_P(callable) == IS_ARRAY) {
                if (Z_ARRVAL_P(callable)->nNumOfElements < 2) {
@@ -679,8 +733,8 @@ static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info *
                object = (zval**)Z_ARRVAL_P(callable)->pListHead->pData;
                method = (zval**)Z_ARRVAL_P(callable)->pListHead->pListNext->pData;
 
-               if (PDO_ZVAL_PP_IS_TEXT(object)) { /* static call */
-                       if (zend_u_lookup_class(Z_TYPE_PP(object), Z_UNIVAL_PP(object), Z_UNILEN_PP(object), &pce TSRMLS_CC) == FAILURE) {
+               if (Z_TYPE_PP(object) == IS_STRING) { /* static call */
+                       if (zend_lookup_class(Z_STRVAL_PP(object), Z_STRLEN_PP(object), &pce TSRMLS_CC) == FAILURE) {
                                pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class does not exist" TSRMLS_CC);
                                return 0;
                        } else {
@@ -694,11 +748,11 @@ static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info *
                        return 0;
                }
                
-               if (!PDO_ZVAL_PP_IS_TEXT(method)) {
+               if (Z_TYPE_PP(method) != IS_STRING) {
                        pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied function must be a valid callback; bogus method name" TSRMLS_CC);
                        return 0;
                }
-       } else if (PDO_ZVAL_P_IS_TEXT(callable)) {
+       } else if (Z_TYPE_P(callable) == IS_STRING) {
                method = &callable;
        }
        
@@ -706,16 +760,39 @@ static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info *
                pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied function must be a valid callback" TSRMLS_CC);
                return 0;
        }
-               
-       lcname = zend_u_str_case_fold(Z_TYPE_PP(method), Z_UNIVAL_PP(method), Z_UNILEN_PP(method), 1, &lcname_len);
+       
+       /* ATM we do not support array($obj, "CLASS::FUNC") or "CLASS_FUNC" */
+       cname = fname;
+       if ((fname = strstr(fname, "::")) == NULL) {
+               fname = cname;
+               cname = NULL;
+       } else {
+               *fname = '\0';
+               fname += 2;
+       }
+       if (cname) {
+               if (zend_lookup_class(cname, strlen(cname), &pce TSRMLS_CC) == FAILURE) {
+                       pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class does not exist" TSRMLS_CC);
+                       return 0;
+               } else {
+                       if (ce) {
+                               /* pce must be base of ce or ce itself */
+                               if (ce != *pce && !instanceof_function(ce, *pce TSRMLS_CC)) {
+                                       pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class has bogus lineage" TSRMLS_CC);
+                                       return 0;
+                               }
+                       }
+                       ce = *pce;
+               }
+       }
 
+       zend_str_tolower_copy(fname, fname, strlen(fname));
        fci->function_table = ce ? &ce->function_table : EG(function_table);
-       if (zend_u_hash_find(fci->function_table, Z_TYPE_PP(method), lcname, lcname_len+1, (void **)&function_handler) == FAILURE) {
-               efree(lcname.v);
+       if (zend_hash_find(fci->function_table, fname, strlen(fname)+1, (void **)&function_handler) == FAILURE) {
                pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied function does not exist" TSRMLS_CC);
                return 0;
        }
-       efree(lcname.v);
+       efree(cname ? cname : fname);
 
        fci->size = sizeof(zend_fcall_info);
        fci->function_name = NULL;
@@ -809,7 +886,7 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
                        case PDO_FETCH_NAMED:
                                if (!return_all) {
                                        ALLOC_HASHTABLE(return_value->value.ht);
-                                       zend_u_hash_init(return_value->value.ht, stmt->column_count, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
+                                       zend_hash_init(return_value->value.ht, stmt->column_count, NULL, ZVAL_PTR_DTOR, 0);
                                        Z_TYPE_P(return_value) = IS_ARRAY;
                                } else {
                                        array_init(return_value);
@@ -818,7 +895,7 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
 
                        case PDO_FETCH_COLUMN:
                                if (stmt->fetch.column >= 0 && stmt->fetch.column < stmt->column_count) {
-                                       fetch_value(stmt, return_value, stmt->fetch.column TSRMLS_CC);
+                                       fetch_value(stmt, return_value, stmt->fetch.column, NULL TSRMLS_CC);
                                        if (!return_all) {
                                                return 1;
                                        } else {
@@ -842,10 +919,10 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
                                        do_fetch_opt_finish(stmt, 0 TSRMLS_CC);
 
                                        INIT_PZVAL(&val);
-                                       fetch_value(stmt, &val, i++ TSRMLS_CC);
+                                       fetch_value(stmt, &val, i++, NULL TSRMLS_CC);
                                        if (Z_TYPE(val) != IS_NULL) {
-                                               convert_to_text(&val);
-                                               if (zend_u_lookup_class(Z_TYPE(val), Z_UNIVAL(val), Z_UNILEN(val), &cep TSRMLS_CC) == FAILURE) {
+                                               convert_to_string(&val);
+                                               if (zend_lookup_class(Z_STRVAL(val), Z_STRLEN(val), &cep TSRMLS_CC) == FAILURE) {
                                                        stmt->fetch.cls.ce = ZEND_STANDARD_CLASS_DEF_PTR;
                                                } else {
                                                        stmt->fetch.cls.ce = *cep;
@@ -921,7 +998,7 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
                
                if (return_all) {
                        INIT_PZVAL(&grp_val);
-                       fetch_value(stmt, &grp_val, i TSRMLS_CC);
+                       fetch_value(stmt, &grp_val, i, NULL TSRMLS_CC);
                        convert_to_string(&grp_val);
                        if (how == PDO_FETCH_COLUMN) {
                                i = stmt->column_count; /* no more data to fetch */
@@ -933,7 +1010,7 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
                for (idx = 0; i < stmt->column_count; i++, idx++) {
                        zval *val;
                        MAKE_STD_ZVAL(val);
-                       fetch_value(stmt, val, i TSRMLS_CC);
+                       fetch_value(stmt, val, i, NULL TSRMLS_CC);
 
                        switch (how) {
                                case PDO_FETCH_ASSOC:
@@ -1014,12 +1091,15 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
                                                }
                                                PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
 #endif
-#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION >= 1
+#if (PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION >= 1) && (PHP_MAJOR_VERSION < 6)
                                                if (!ce->unserialize) {
                                                        zval_ptr_dtor(&val);
                                                        pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "cannot unserialize class" TSRMLS_CC);
                                                        return 0;
-                                               } else if (ce->unserialize(&return_value, ce, Z_TYPE_P(val) == IS_STRING ? Z_STRVAL_P(val) : "", Z_TYPE_P(val) == IS_STRING ? Z_STRLEN_P(val) : 0, NULL TSRMLS_CC) == FAILURE) {
+                                               } else if (ce->unserialize(&return_value, ce, 
+                                                               Z_TYPE_P(val) == IS_STRING ? Z_STRVAL_P(val) : "",
+                                                               Z_TYPE_P(val) == IS_STRING ? Z_STRLEN_P(val) : 0,
+                                                               NULL TSRMLS_CC) == FAILURE) {
                                                        zval_ptr_dtor(&val);
                                                        pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "cannot unserialize class" TSRMLS_CC);
                                                        zval_dtor(return_value);
@@ -1145,6 +1225,13 @@ static int pdo_stmt_verify_mode(pdo_stmt_t *stmt, int mode, int fetch_all TSRMLS
                        return 0;
                }
                return 1;
+
+       case PDO_FETCH_LAZY:
+               if (fetch_all) {
+                       pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_LAZY can't be used with PDOStatement::fetchAll()" TSRMLS_CC);
+                       return 0;
+               }
+               /* fall through */
        
        default:
                if ((flags & PDO_FETCH_SERIALIZE) == PDO_FETCH_SERIALIZE) {
@@ -1289,7 +1376,7 @@ static PHP_METHOD(PDOStatement, fetchColumn)
                RETURN_FALSE;
        }
 
-       fetch_value(stmt, return_value, col_n TSRMLS_CC);
+       fetch_value(stmt, return_value, col_n, NULL TSRMLS_CC);
 }
 /* }}} */
 
@@ -1338,12 +1425,12 @@ static PHP_METHOD(PDOStatement, fetchAll)
                        /* no break */
                case 2:
                        stmt->fetch.cls.ctor_args = ctor_args; /* we're not going to free these */
-                       if (!PDO_ZVAL_P_IS_TEXT(arg2)) {
+                       if (Z_TYPE_P(arg2) != IS_STRING) {
                                pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid class name (should be a string)" TSRMLS_CC);
                                error = 1;
                                break;
                        } else {
-                               stmt->fetch.cls.ce = zend_u_fetch_class(Z_TYPE_P(arg2), Z_UNIVAL_P(arg2), Z_UNILEN_P(arg2), ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
+                               stmt->fetch.cls.ce = zend_fetch_class(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2), ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
                                if (!stmt->fetch.cls.ce) {
                                        pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not find user-specified class" TSRMLS_CC);
                                        error = 1;
@@ -1434,7 +1521,9 @@ static PHP_METHOD(PDOStatement, fetchAll)
                if (error != 2) {
                        RETURN_FALSE;
                } else { /* on no results, return an empty array */
-                       array_init(return_value);
+                       if (Z_TYPE_P(return_value) != IS_ARRAY) {
+                               array_init(return_value);
+                       }
                        return;
                }
        }
@@ -1477,9 +1566,9 @@ static int register_bound_param(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt,
    bind an input parameter to the value of a PHP variable.  $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders).  It should be called prior to execute(). */
 static PHP_METHOD(PDOStatement, bindValue)
 {
-       pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
        struct pdo_bound_param_data param = {0};
-       
+       PHP_STMT_GET_OBJ;
+
        param.paramno = -1;
        param.param_type = PDO_PARAM_STR;
        
@@ -1602,6 +1691,17 @@ fail:
 
 /* {{{ proto mixed PDOStatement::getAttribute(long attribute)
    Get an attribute */
+
+static int generic_stmt_attr_get(pdo_stmt_t *stmt, zval *return_value, long attr)
+{
+       switch (attr) {
+               case PDO_ATTR_EMULATE_PREPARES:
+                       RETVAL_BOOL(stmt->supports_placeholders == PDO_PLACEHOLDER_NONE);
+                       return 1;
+       }
+       return 0;
+}
+   
 static PHP_METHOD(PDOStatement, getAttribute)
 {
        long attr;
@@ -1612,8 +1712,12 @@ static PHP_METHOD(PDOStatement, getAttribute)
        }
 
        if (!stmt->methods->get_attribute) {
-               pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "This driver doesn't support getting attributes" TSRMLS_CC);
-               RETURN_FALSE;
+               if (!generic_stmt_attr_get(stmt, return_value, attr)) {
+                       pdo_raise_impl_error(stmt->dbh, stmt, "IM001",
+                               "This driver doesn't support getting attributes" TSRMLS_CC);
+                       RETURN_FALSE;
+               }
+               return;
        }
 
        PDO_STMT_CLEAR_ERR();
@@ -1623,9 +1727,13 @@ static PHP_METHOD(PDOStatement, getAttribute)
                        RETURN_FALSE;
 
                case 0:
-                       /* XXX: should do something better here */
-                       pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver doesn't support getting that attribute" TSRMLS_CC);
-                       RETURN_FALSE;
+                       if (!generic_stmt_attr_get(stmt, return_value, attr)) {
+                               /* XXX: should do something better here */
+                               pdo_raise_impl_error(stmt->dbh, stmt, "IM001",
+                                       "driver doesn't support getting that attribute" TSRMLS_CC);
+                               RETURN_FALSE;
+                       }
+                       return;
 
                default:
                        return;
@@ -1762,11 +1870,13 @@ fail_out:
                        
                        stmt->fetch.cls.ce = *cep;
                        stmt->fetch.cls.ctor_args = NULL;
+
 #ifdef ilia_0 /* we'll only need this when we have persistent statements, if ever */
                        if (stmt->dbh->is_persistent) {
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement.  This will be fixed in a later release");
                        }
 #endif
+                       
                        if (argc == 3) {
                                if (Z_TYPE_PP(args[skip+2]) != IS_NULL && Z_TYPE_PP(args[skip+2]) != IS_ARRAY) {
                                        pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array" TSRMLS_CC);
@@ -1787,11 +1897,13 @@ fail_out:
                        if (Z_TYPE_PP(args[skip+1]) != IS_OBJECT) {
                                goto fail_out;
                        }
+
 #ifdef ilia_0 /* we'll only need this when we have persistent statements, if ever */
                        if (stmt->dbh->is_persistent) {
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement.  This will be fixed in a later release");
                        }
 #endif
+       
                        MAKE_STD_ZVAL(stmt->fetch.into);
 
                        Z_TYPE_P(stmt->fetch.into) = IS_OBJECT;
@@ -1844,6 +1956,7 @@ static int pdo_stmt_do_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
                return 0;
        }
 
+
        pdo_stmt_describe_columns(stmt TSRMLS_CC);
 
        return 1;
@@ -1864,7 +1977,7 @@ static PHP_METHOD(PDOStatement, nextRowset)
                PDO_HANDLE_STMT_ERR();
                RETURN_FALSE;
        }
-
+       
        RETURN_TRUE;
 }
 /* }}} */
@@ -1954,7 +2067,7 @@ static PHP_METHOD(PDOStatement, debugDumpParams)
    Prevents use of a PDOStatement instance that has been unserialized */
 static PHP_METHOD(PDOStatement, __wakeup)
 {
-       zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances");
+       zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances");
 }
 /* }}} */
 
@@ -1962,7 +2075,7 @@ static PHP_METHOD(PDOStatement, __wakeup)
    Prevents serialization of a PDOStatement instance */
 static PHP_METHOD(PDOStatement, __sleep)
 {
-       zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances");
+       zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances");
 }
 /* }}} */
 
@@ -1996,9 +2109,9 @@ static void dbstmt_prop_write(zval *object, zval *member, zval *value TSRMLS_DC)
 {
        pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
 
-       convert_to_text(member);
+       convert_to_string(member);
 
-       if (PDO_MEMBER_IS(member, "queryString")) {
+       if(strcmp(Z_STRVAL_P(member), "queryString") == 0) {
                pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC);
        } else {
                std_object_handlers.write_property(object, member, value TSRMLS_CC);
@@ -2009,9 +2122,9 @@ static void dbstmt_prop_delete(zval *object, zval *member TSRMLS_DC)
 {
        pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
 
-       convert_to_text(member);
+       convert_to_string(member);
 
-       if (PDO_MEMBER_IS(member, "queryString")) {
+       if(strcmp(Z_STRVAL_P(member), "queryString") == 0) {
                pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC);
        } else {
                std_object_handlers.unset_property(object, member TSRMLS_CC);
@@ -2024,7 +2137,8 @@ static union _zend_function *dbstmt_method_get(
 #else
        zval *object,
 #endif
-       zstr method_name, int method_len TSRMLS_DC)
+       zstr method_name,
+       int method_len TSRMLS_DC)
 {
        zend_function *fbc = NULL;
        zstr lc_method_name;
@@ -2059,7 +2173,7 @@ static union _zend_function *dbstmt_method_get(
        }
        
 out:
-       efree(lc_method_name.v);
+       pdo_zstr_efree(lc_method_name);
        return fbc;
 }
 
@@ -2157,9 +2271,10 @@ static void free_statement(pdo_stmt_t *stmt TSRMLS_DC)
                int i;
                struct pdo_column_data *cols = stmt->columns;
 
-               for (i = stmt->column_count; i > 0;) {
-                       if (cols[--i].name) {
+               for (i = 0; i < stmt->column_count; i++) {
+                       if (cols[i].name) {
                                efree(cols[i].name);
+                               cols[i].name = NULL;
                        }
                }
                efree(stmt->columns);
@@ -2180,13 +2295,23 @@ static void free_statement(pdo_stmt_t *stmt TSRMLS_DC)
        efree(stmt);
 }
 
-void pdo_dbstmt_free_storage(pdo_stmt_t *stmt TSRMLS_DC)
+PDO_API void php_pdo_stmt_addref(pdo_stmt_t *stmt TSRMLS_DC)
+{
+       stmt->refcount++;
+}
+
+PDO_API void php_pdo_stmt_delref(pdo_stmt_t *stmt TSRMLS_DC)
 {
        if (--stmt->refcount == 0) {
                free_statement(stmt TSRMLS_CC);
        }
 }
 
+void pdo_dbstmt_free_storage(pdo_stmt_t *stmt TSRMLS_DC)
+{
+       php_pdo_stmt_delref(stmt TSRMLS_CC);
+}
+
 zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC)
 {
        zend_object_value retval;
@@ -2252,7 +2377,9 @@ static void pdo_stmt_iter_get_data(zend_object_iterator *iter, zval ***data TSRM
        *data = &I->fetch_ahead;
 }
 
-static int pdo_stmt_iter_get_key(zend_object_iterator *iter, zstr *str_key, uint *str_key_len,
+static int pdo_stmt_iter_get_key(zend_object_iterator *iter, 
+       zstr *str_key, 
+       uint *str_key_len,
        ulong *int_key TSRMLS_DC)
 {
        struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter->data;
@@ -2344,7 +2471,7 @@ static zval *row_prop_or_dim_read(zval *object, zval *member, int type TSRMLS_DC
                
        if (Z_TYPE_P(member) == IS_LONG) {
                if (Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count) {
-                       fetch_value(stmt, return_value, Z_LVAL_P(member) TSRMLS_CC);
+                       fetch_value(stmt, return_value, Z_LVAL_P(member), NULL TSRMLS_CC);
                }
        } else {
                convert_to_string(member);
@@ -2352,7 +2479,7 @@ static zval *row_prop_or_dim_read(zval *object, zval *member, int type TSRMLS_DC
                 * 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);
+                               fetch_value(stmt, return_value, colno, NULL TSRMLS_CC);
                                break;
                        }
                }
@@ -2409,7 +2536,7 @@ static HashTable *row_get_properties(zval *object TSRMLS_DC)
        for (i = 0; i < stmt->column_count; i++) {
                zval *val;
                MAKE_STD_ZVAL(val);
-               fetch_value(stmt, val, i TSRMLS_CC);
+               fetch_value(stmt, val, i, NULL TSRMLS_CC);
 
                add_assoc_zval(tmp, stmt->columns[i].name, val);
        }
@@ -2428,23 +2555,30 @@ static union _zend_function *row_method_get(
 #else
        zval *object,
 #endif
-       zstr method_name, int method_len TSRMLS_DC)
+       zstr method_name,
+       int method_len TSRMLS_DC)
 {
        zend_function *fbc;
        zstr lc_method_name;
+#ifdef IS_UNICODE
+       zend_uchar ztype = UG(unicode) ? IS_UNICODE : IS_STRING;
+#endif
 
-       lc_method_name = zend_u_str_tolower_dup(UG(unicode)?IS_UNICODE:IS_STRING, method_name, method_len);
+       lc_method_name = zend_u_str_tolower_dup(ztype, method_name, method_len);
 
-       if (zend_u_hash_find(&pdo_row_ce->function_table, UG(unicode)?IS_UNICODE:IS_STRING, lc_method_name, method_len+1, (void**)&fbc) == FAILURE) {
-               efree(lc_method_name.v);
+       if (zend_u_hash_find(&pdo_row_ce->function_table, ztype,
+                       lc_method_name, method_len+1, (void**)&fbc) == FAILURE) {
+               pdo_zstr_efree(lc_method_name);
                return NULL;
        }
        
-       efree(lc_method_name.v);
+       pdo_zstr_efree(lc_method_name);
        return fbc;
 }
 
-static int row_call_method(zstr method, INTERNAL_FUNCTION_PARAMETERS)
+static int row_call_method(
+       zstr method,
+       INTERNAL_FUNCTION_PARAMETERS)
 {
        return FAILURE;
 }
@@ -2454,7 +2588,8 @@ 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.s = "__construct";
+       pdo_zstr_sval(ctor.function_name) = "__construct";
+
        ctor.scope = pdo_row_ce;
        ctor.handler = ZEND_FN(dbstmt_constructor);
 
@@ -2466,9 +2601,9 @@ static zend_class_entry *row_get_ce(zval *object TSRMLS_DC)
        return pdo_dbstmt_ce;
 }
 
-static int row_get_classname(zval *object, zstr *class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
+static int row_get_classname(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
 {
-       class_name->s = estrndup("PDORow", sizeof("PDORow")-1);
+       *class_name = estrndup("PDORow", sizeof("PDORow")-1);
        *class_name_len = sizeof("PDORow")-1;
        return 0;
 }
index fedc2ca2197809b167d4bc40619d743baa33e5db..cb4f20bd05ed69adeaf4ef8369d544b311f99150 100755 (executable)
@@ -61,7 +61,7 @@ ZEND_END_MODULE_GLOBALS(pdo)
 #endif
 
 #define REGISTER_PDO_CLASS_CONST_LONG(const_name, value) \
-       zend_declare_class_constant_long(pdo_dbh_ce, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
+       zend_declare_class_constant_long(php_pdo_get_dbh_ce(), const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
 
 #define REGISTER_PDO_CONST_LONG(const_name, value) { \
        zend_class_entry **pce; \
@@ -70,7 +70,7 @@ ZEND_END_MODULE_GLOBALS(pdo)
 }      \
 
 #define REGISTER_PDO_CLASS_CONST_STRING(const_name, value) \
-       zend_declare_class_constant_stringl(pdo_dbh_ce, const_name, sizeof(const_name)-1, value, sizeof(value)-1 TSRMLS_CC);
+       zend_declare_class_constant_stringl(php_pdo_get_dbh_ce(), const_name, sizeof(const_name)-1, value, sizeof(value)-1 TSRMLS_CC);
 
 #define PDO_CONSTRUCT_CHECK    \
        if (!dbh->driver) {     \
index be2b9d39967d4b7e61d964eaa2370d7ec53d96f0..539c9fd9c395c6576470ae5415ea5c2a181f8504 100755 (executable)
@@ -22,6 +22,7 @@
 #define PHP_PDO_DRIVER_H
 
 #include "php_pdo.h"
+#include "php_pdo_phpvers_compat.h"
 
 /* forward declarations */
 typedef struct _pdo_dbh_t      pdo_dbh_t;
@@ -44,7 +45,7 @@ PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC);
 # define FALSE 0
 #endif
 
-#define PDO_DRIVER_API 20060318
+#define PDO_DRIVER_API 20061209
 
 enum pdo_param_type {
        PDO_PARAM_NULL,
@@ -131,6 +132,7 @@ enum pdo_attribute_type {
        PDO_ATTR_STRINGIFY_FETCHES,     /* converts integer/float types to strings during fetch */
        PDO_ATTR_MAX_COLUMN_LEN,        /* make database calculate maximum length of data found in a column */
        PDO_ATTR_DEFAULT_FETCH_MODE, /* Set the default fetch mode */
+       PDO_ATTR_EMULATE_PREPARES,  /* use query emulation rather than native */
 
        /* this defines the start of the range for driver specific options.
         * Drivers should define their own attribute constants beginning with this
@@ -251,7 +253,7 @@ typedef int (*pdo_dbh_set_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS
 
 /* return last insert id.  NULL indicates error condition, otherwise, the return value
  * MUST be an emalloc'd NULL terminated string. */
-typedef char *(*pdo_dbh_last_id_func)(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC);
+typedef char *(*pdo_dbh_last_id_func)(pdo_dbh_t *dbh, const char *name, int *len TSRMLS_DC);
 
 /* fetch error information.  if stmt is not null, fetch information pertaining
  * to the statement, otherwise fetch global error information.  The driver
@@ -340,7 +342,8 @@ enum pdo_param_event {
        PDO_PARAM_EVT_EXEC_PRE,
        PDO_PARAM_EVT_EXEC_POST,
        PDO_PARAM_EVT_FETCH_PRE,
-       PDO_PARAM_EVT_FETCH_POST
+       PDO_PARAM_EVT_FETCH_POST,
+       PDO_PARAM_EVT_NORMALIZE,
 };
 
 typedef int (*pdo_stmt_param_hook_func)(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, enum pdo_param_event event_type TSRMLS_DC);
@@ -489,7 +492,7 @@ struct _pdo_dbh_t {
        pdo_driver_t *driver;
        
        zend_class_entry *def_stmt_ce;
-       
+
        zval *def_stmt_ctor_args;
 
        /* when calling PDO::query(), we need to keep the error
@@ -643,7 +646,8 @@ PDO_API int php_pdo_parse_data_source(const char *data_source,
                unsigned long data_source_len, struct pdo_data_src_parser *parsed,
                int nparams);
 
-PDO_API zend_class_entry *php_pdo_get_exception(TSRMLS_D);
+PDO_API zend_class_entry *php_pdo_get_dbh_ce(void);
+PDO_API zend_class_entry *php_pdo_get_exception(void);
 
 PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, 
        char **outquery, int *outquery_len TSRMLS_DC);
@@ -654,6 +658,10 @@ PDO_API void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt,
 PDO_API void php_pdo_dbh_addref(pdo_dbh_t *dbh TSRMLS_DC);
 PDO_API void php_pdo_dbh_delref(pdo_dbh_t *dbh TSRMLS_DC);
 
+PDO_API void php_pdo_stmt_addref(pdo_stmt_t *stmt TSRMLS_DC);
+PDO_API void php_pdo_stmt_delref(pdo_stmt_t *stmt TSRMLS_DC);
+
+
 #endif /* PHP_PDO_DRIVER_H */
 /*
  * Local variables:
index 6ed411cb59235d9b692a332e455750b96a9fc953..8e6832877cfb0116c0756c496b343005618bbcad 100755 (executable)
@@ -20,8 +20,6 @@
 
 /* $Id$ */
 
-#include "php_pdo_phpvers_compat.h"
-
 /* Stuff private to the PDO extension and not for consumption by PDO drivers
  * */
 
@@ -59,7 +57,13 @@ 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);
 
-#define PDO_DBH_CLEAR_ERR()            strcpy(dbh->error_code, PDO_ERR_NONE)
+#define PDO_DBH_CLEAR_ERR()            do { \
+       strcpy(dbh->error_code, PDO_ERR_NONE); \
+       if (dbh->query_stmt) { \
+               dbh->query_stmt = NULL; \
+               zend_objects_store_del_ref(&dbh->query_stmt_zval TSRMLS_CC); \
+       } \
+} while (0)
 #define PDO_STMT_CLEAR_ERR()   strcpy(stmt->error_code, PDO_ERR_NONE)
 #define PDO_HANDLE_DBH_ERR()   if (strcmp(dbh->error_code, PDO_ERR_NONE)) { pdo_handle_error(dbh, NULL TSRMLS_CC); }
 #define PDO_HANDLE_STMT_ERR()  if (strcmp(stmt->error_code, PDO_ERR_NONE)) { pdo_handle_error(stmt->dbh, stmt TSRMLS_CC); }
index da46f4947dc03f194354bd030c47362a0f71ffdb..73ebc6e738837b29befd59e4f52f923e4e11a8ea 100644 (file)
@@ -25,6 +25,9 @@
 # define PHP_PDO_PHPVERS_COMPAT_H
 # if PHP_MAJOR_VERSION < 6
 
+typedef char *zstr;
+#  define ZSTR(x) x
+
 #  define ZVAL_RT_STRINGL(a, b, c, d)          ZVAL_STRINGL(a, b, c, d)
 #  define ZVAL_ASCII_STRINGL(a, b, c, d)       ZVAL_STRINGL(a, b, c, d)
 #  define PDO_ZVAL_PP_IS_TEXT(pp)                      (Z_TYPE_PP(pp) == IS_STRING)
@@ -42,13 +45,16 @@ PDO_API char *php_pdo_str_tolower_dup(const char *src, int len);
 #  define convert_to_text(x)                           convert_to_string(x)
 #  define zend_u_fetch_class(a, b, c, d)       zend_fetch_class(b, c, d)
 #  define PDO_MEMBER_IS(z, strlit)                     ((Z_STRLEN_P(z) == sizeof(strlit)-1) && 0 == strcmp(Z_STRVAL_P(z), strlit))
-
+#  define pdo_zstr_efree(x)  efree(x)
+#  define pdo_zstr_sval(x)   x
 # else
 
 #  define PDO_ZVAL_PP_IS_TEXT(pp)                      ((Z_TYPE_PP(pp) == IS_STRING) || (Z_TYPE_PP(pp) == IS_UNICODE))
 #  define PDO_ZVAL_P_IS_TEXT(pp)                       ((Z_TYPE_P(pp) == IS_STRING) || (Z_TYPE_P(pp) == IS_UNICODE))
 
 #  define PDO_MEMBER_IS(z, strlit)                     ((Z_UNILEN_P(z) == sizeof(strlit)-1) && (ZEND_U_EQUAL(Z_TYPE_P(z), Z_UNIVAL_P(z), Z_UNILEN_P(z), strlit, sizeof(strlit)-1)))
+#  define pdo_zstr_efree(x)  efree(x.v)
+#  define pdo_zstr_sval(x)   x.s
 
 # endif
 #endif