diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 65034179ddf26..62f4575622373 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -1379,9 +1379,21 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* } do { +#if FB_API_VER >= 40 + zend_string *session_timezone = pdo_attr_strval(driver_options, PDO_FB_SESSION_TIMEZONE, NULL); +#endif + static char const dpb_flags[] = { - isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name }; - char const *dpb_values[] = { dbh->username, dbh->password, vars[1].optval, vars[2].optval }; + isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name +#if FB_API_VER >= 40 + , isc_dpb_session_time_zone +#endif + }; + char const *dpb_values[] = { dbh->username, dbh->password, vars[1].optval, vars[2].optval +#if FB_API_VER >= 40 + , session_timezone ? ZSTR_VAL(session_timezone) : NULL +#endif + }; char dpb_buffer[256] = { isc_dpb_version1 }, *dpb; dpb = dpb_buffer + 1; @@ -1396,6 +1408,12 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* } } +#if FB_API_VER >= 40 + if (session_timezone) { + zend_string_release_ex(session_timezone, 0); + } +#endif + H->sql_dialect = PDO_FB_DIALECT; if (vars[3].optval) { H->sql_dialect = atoi(vars[3].optval); diff --git a/ext/pdo_firebird/pdo_firebird.stub.php b/ext/pdo_firebird/pdo_firebird.stub.php index f8c9ea46fcb07..c441a7ffbd223 100644 --- a/ext/pdo_firebird/pdo_firebird.stub.php +++ b/ext/pdo_firebird/pdo_firebird.stub.php @@ -34,5 +34,8 @@ class Firebird extends \PDO /** @cvalue PDO_FB_WRITABLE_TRANSACTION */ public const int WRITABLE_TRANSACTION = UNKNOWN; + /** @cvalue PDO_FB_SESSION_TIMEZONE */ + public const int SESSION_TIMEZONE = UNKNOWN; + public static function getApiVersion(): int {} } diff --git a/ext/pdo_firebird/pdo_firebird_arginfo.h b/ext/pdo_firebird/pdo_firebird_arginfo.h index a5a9c562c9c12..77cbf5284f18c 100644 --- a/ext/pdo_firebird/pdo_firebird_arginfo.h +++ b/ext/pdo_firebird/pdo_firebird_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d36b2055abc48ae91c3442dda68fa2a28eb6d25b */ + * Stub hash: 50db19699b572bf8653790782327f05bbada9575 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Pdo_Firebird_getApiVersion, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -66,5 +66,11 @@ static zend_class_entry *register_class_Pdo_Firebird(zend_class_entry *class_ent zend_declare_typed_class_constant(class_entry, const_WRITABLE_TRANSACTION_name, &const_WRITABLE_TRANSACTION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_WRITABLE_TRANSACTION_name); + zval const_SESSION_TIMEZONE_value; + ZVAL_LONG(&const_SESSION_TIMEZONE_value, PDO_FB_SESSION_TIMEZONE); + zend_string *const_SESSION_TIMEZONE_name = zend_string_init_interned("SESSION_TIMEZONE", sizeof("SESSION_TIMEZONE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_SESSION_TIMEZONE_name, &const_SESSION_TIMEZONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_SESSION_TIMEZONE_name); + return class_entry; } diff --git a/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h index dc1e4bb7f4086..d2f0b410579fe 100644 --- a/ext/pdo_firebird/php_pdo_firebird_int.h +++ b/ext/pdo_firebird/php_pdo_firebird_int.h @@ -154,6 +154,9 @@ enum { /* transaction access mode */ PDO_FB_WRITABLE_TRANSACTION, + + /* session time zone */ + PDO_FB_SESSION_TIMEZONE, }; #endif /* PHP_PDO_FIREBIRD_INT_H */ diff --git a/ext/pdo_firebird/tests/set_timezone.phpt b/ext/pdo_firebird/tests/set_timezone.phpt new file mode 100644 index 0000000000000..35cc4797331af --- /dev/null +++ b/ext/pdo_firebird/tests/set_timezone.phpt @@ -0,0 +1,55 @@ +--TEST-- +PDO_Firebird: Set session timezone in connection properties +--EXTENSIONS-- +pdo_firebird +--SKIPIF-- +query("SELECT RDB\$get_context('SYSTEM', 'ENGINE_VERSION') AS VERSION FROM RDB\$DATABASE"); +$data = $stmt->fetch(\PDO::FETCH_ASSOC); +if (!$data || !array_key_exists('VERSION', $data) || version_compare($data['VERSION'], '4.0.0') < 0) { + die("skip Firebird Server version must be greater than or equal to 4.0.0"); +} +unset($stmt); +unset($dbh); +?> +--XLEAK-- +A bug in firebird causes a memory leak when calling `isc_attach_database()`. +See https://github.com/FirebirdSQL/firebird/issues/7849 +--FILE-- + 'Europe/Rome' +]; + +$dbh = connectToDb($attr); + +$stmt = $dbh->prepare($sql); +$stmt->execute(); +$data = $stmt->fetch(\PDO::FETCH_ASSOC); +$stmt->closeCursor(); +$str = json_encode($data, JSON_PRETTY_PRINT); +echo $str; +echo "\ndone\n"; +?> +--EXPECT-- +{ + "TZ": "Europe\/Rome", + "TZ1": "Europe\/Rome", + "TZ2": "Europe\/Rome" +} +done diff --git a/ext/pdo_firebird/tests/testdb.inc b/ext/pdo_firebird/tests/testdb.inc index 6be882297188b..d155cdfd9655c 100644 --- a/ext/pdo_firebird/tests/testdb.inc +++ b/ext/pdo_firebird/tests/testdb.inc @@ -21,8 +21,8 @@ function getDbConnection($class = PDO::class): PDO { return new $class(PDO_FIREBIRD_TEST_DSN, PDO_FIREBIRD_TEST_USER, PDO_FIREBIRD_TEST_PASS); } -function connectToDb(): Pdo\Firebird { - return Pdo\Firebird::connect(PDO_FIREBIRD_TEST_DSN, PDO_FIREBIRD_TEST_USER, PDO_FIREBIRD_TEST_PASS); +function connectToDb(array $options = []): Pdo\Firebird { + return Pdo\Firebird::connect(PDO_FIREBIRD_TEST_DSN, PDO_FIREBIRD_TEST_USER, PDO_FIREBIRD_TEST_PASS, $options); } ?>