[PECL-CVS] [pecl-database-pdo_ibm] master: Merge pull request #30 from php/pdo-class-8.5

[email protected] (Calvin Buckley via GitHub)
Newsgroups php.pecl.cvs
Message-ID <[email protected]>
Author: Calvin Buckley (NattyNarwhal)
Committer: GitHub (web-flow)
Pusher: NattyNarwhal
Date: 2025-09-22T11:01:18-03:00

Commit: https://github.com/php/pecl-database-pdo_ibm/commit/3492bbdf9a5f8dad445696da5c9316006ef7e7d1
Raw diff: https://github.com/php/pecl-database-pdo_ibm/commit/3492bbdf9a5f8dad445696da5c9316006ef7e7d1.diff

Merge pull request #30 from php/pdo-class-8.5

PDO driver class and constant conversion for PHP 8.5

Changed paths:
  A  pdo_ibm.stub.php
  A  pdo_ibm_arginfo.h
  M  package.xml
  M  pdo_ibm.c
  M  tests/fvt.inc
  M  tests/fvt_client_info.phpt


Diff:

diff --git a/package.xml b/package.xml
index 3ba37fc..6b03a8e 100644
--- a/package.xml
+++ b/package.xml
@@ -142,6 +142,8 @@ Universal Database, IBM Cloudscape, Apache Derby databases and IDS (Informix Dat
    <file baseinstalldir="pdo_ibm" name="ibm_driver.c" role="src" />
    <file baseinstalldir="pdo_ibm" name="ibm_statement.c" role="src" />
    <file baseinstalldir="pdo_ibm" name="pdo_ibm.c" role="src" />
+   <file baseinstalldir="pdo_ibm" name="pdo_ibm_arginfo.h" role="src" />
+   <file baseinstalldir="pdo_ibm" name="pdo_ibm.stub.php" role="src" />
    <file baseinstalldir="pdo_ibm" name="php_pdo_ibm.h" role="src" />
    <file baseinstalldir="pdo_ibm" name="php_pdo_ibm_int.h" role="src" />
   </dir>
diff --git a/pdo_ibm.c b/pdo_ibm.c
index 5044a73..97cb3e0 100644
--- a/pdo_ibm.c
+++ b/pdo_ibm.c
@@ -30,8 +30,11 @@
 #include "php_pdo_ibm.h"
 #include "php_pdo_ibm_int.h"
 
-/* If you declare any globals in php_pdo_ibm.h uncomment this:
-*/
+/* The class constants are only useful on 8.4+ */
+#if PHP_VERSION_ID >= 80400
+#include "pdo_ibm_arginfo.h"
+#endif
+
 #ifdef PASE
 ZEND_DECLARE_MODULE_GLOBALS(pdo_ibm)
 #endif
@@ -40,6 +43,7 @@ ZEND_DECLARE_MODULE_GLOBALS(pdo_ibm)
 static int le_pdo_ibm;
 extern pdo_driver_t pdo_ibm_driver;	/* the registration table */
 
+static zend_class_entry *pdo_ibm_ce;
 
 #ifdef PASE /* PASE i5/OS start-up */
 #include <as400_protos.h>
@@ -47,32 +51,26 @@ extern pdo_driver_t pdo_ibm_driver;	/* the registration table */
 
 /* {{{ pdo_ibm_deps
  */
-#if ZEND_MODULE_API_NO >= 20041225
 static zend_module_dep pdo_ibm_deps[] = {
 	ZEND_MOD_REQUIRED("pdo")
 	{NULL, NULL, NULL}
 };
-#endif
 /* }}} */
 
 /* {{{ pdo_ibm_module_entry
  */
 zend_module_entry pdo_ibm_module_entry =
 {
-#if ZEND_MODULE_API_NO >= 20041225
 	STANDARD_MODULE_HEADER_EX, NULL,
 	pdo_ibm_deps,
-#else
-	STANDARD_MODULE_HEADER,
-#endif
 	"pdo_ibm",
 	NULL,
 	PHP_MINIT(pdo_ibm),
 	PHP_MSHUTDOWN(pdo_ibm),
-	PHP_RINIT(pdo_ibm),        /* Replace with NULL if there's nothing to do at request start */
-	PHP_RSHUTDOWN(pdo_ibm),    /* Replace with NULL if there's nothing to do at request end */
+	PHP_RINIT(pdo_ibm),
+	PHP_RSHUTDOWN(pdo_ibm),
 	PHP_MINFO(pdo_ibm),
-	PDO_IBM_VERSION,   /* Replace with version number for your extension */
+	PDO_IBM_VERSION,
 	STANDARD_MODULE_PROPERTIES
 };
 /* }}} */
@@ -111,6 +109,19 @@ static void php_pdo_ibm_init_globals(zend_pdo_ibm_globals *pdo_ibm_globals)
 /* }}} */
 #endif /* PASE */
 
+/* PDO_IBM used both SQL_ and I5_ as prefixes for constants */
+#if PHP_VERSION_ID >= 80500
+#define REGISTER_PDO_IBM_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \
+		REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, "SQL_", "Pdo\\Ibm::", value)
+#define REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \
+		REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, "I5_", "Pdo\\Ibm::", value)
+#else
+#define REGISTER_PDO_IBM_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \
+		REGISTER_PDO_CLASS_CONST_LONG("SQL_" base_name, value)
+#define REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \
+		REGISTER_PDO_CLASS_CONST_LONG("I5_" base_name, value)
+#endif
+
 /* {{{ PHP_MINIT_FUNCTION
  */
 PHP_MINIT_FUNCTION(pdo_ibm)
@@ -121,33 +132,43 @@ PHP_MINIT_FUNCTION(pdo_ibm)
 	REGISTER_INI_ENTRIES();
 #endif
 
+	if (FAILURE == php_pdo_register_driver(&pdo_ibm_driver)) {
+		return FAILURE;
+	}
+
 #ifndef PASE /* i5/OS no support trusted */
-	REGISTER_PDO_CLASS_CONST_LONG("SQL_ATTR_USE_TRUSTED_CONTEXT", (long) PDO_SQL_ATTR_USE_TRUSTED_CONTEXT);
-	REGISTER_PDO_CLASS_CONST_LONG("SQL_ATTR_TRUSTED_CONTEXT_USERID", (long) PDO_SQL_ATTR_TRUSTED_CONTEXT_USERID);	
-	REGISTER_PDO_CLASS_CONST_LONG("SQL_ATTR_TRUSTED_CONTEXT_PASSWORD", (long) PDO_SQL_ATTR_TRUSTED_CONTEXT_PASSWORD);
+	REGISTER_PDO_IBM_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_USE_TRUSTED_CONTEXT", (long) PDO_SQL_ATTR_USE_TRUSTED_CONTEXT);
+	REGISTER_PDO_IBM_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_TRUSTED_CONTEXT_USERID", (long) PDO_SQL_ATTR_TRUSTED_CONTEXT_USERID);
+	REGISTER_PDO_IBM_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_TRUSTED_CONTEXT_PASSWORD", (long) PDO_SQL_ATTR_TRUSTED_CONTEXT_PASSWORD);
 #else /* PASE i5/OS introduced (1.3.4) */
-	REGISTER_PDO_CLASS_CONST_LONG("I5_ATTR_DBC_SYS_NAMING", (long)PDO_I5_ATTR_DBC_SYS_NAMING);
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_DBC_SYS_NAMING", (long)PDO_I5_ATTR_DBC_SYS_NAMING);
 	
-	REGISTER_PDO_CLASS_CONST_LONG("I5_ATTR_COMMIT", (long)PDO_I5_ATTR_COMMIT);
-	REGISTER_PDO_CLASS_CONST_LONG("I5_TXN_NO_COMMIT", (long)PDO_I5_TXN_NO_COMMIT);
-	REGISTER_PDO_CLASS_CONST_LONG("I5_TXN_READ_UNCOMMITTED", (long)PDO_I5_TXN_READ_UNCOMMITTED);
-	REGISTER_PDO_CLASS_CONST_LONG("I5_TXN_READ_COMMITTED", (long)PDO_I5_TXN_READ_COMMITTED);
-	REGISTER_PDO_CLASS_CONST_LONG("I5_TXN_REPEATABLE_READ", (long)PDO_I5_TXN_REPEATABLE_READ);
-	REGISTER_PDO_CLASS_CONST_LONG("I5_TXN_SERIALIZABLE", (long)PDO_I5_TXN_SERIALIZABLE);
-
-	REGISTER_PDO_CLASS_CONST_LONG("I5_ATTR_JOB_SORT", (long)PDO_I5_ATTR_JOB_SORT);
-	REGISTER_PDO_CLASS_CONST_LONG("I5_ATTR_DBC_LIBL", (long)PDO_I5_ATTR_DBC_LIBL);
-	REGISTER_PDO_CLASS_CONST_LONG("I5_ATTR_DBC_CURLIB", (long)PDO_I5_ATTR_DBC_CURLIB);
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_COMMIT", (long)PDO_I5_ATTR_COMMIT);
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("TXN_NO_COMMIT", (long)PDO_I5_TXN_NO_COMMIT);
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("TXN_READ_UNCOMMITTED", (long)PDO_I5_TXN_READ_UNCOMMITTED);
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("TXN_READ_COMMITTED", (long)PDO_I5_TXN_READ_COMMITTED);
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("TXN_REPEATABLE_READ", (long)PDO_I5_TXN_REPEATABLE_READ);
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("TXN_SERIALIZABLE", (long)PDO_I5_TXN_SERIALIZABLE);
+
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_JOB_SORT", (long)PDO_I5_ATTR_JOB_SORT);
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_DBC_LIBL", (long)PDO_I5_ATTR_DBC_LIBL);
+	REGISTER_PDO_IBM_I5_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_DBC_CURLIB", (long)PDO_I5_ATTR_DBC_CURLIB);
 #endif /* PASE */
 
 	/* Client information variables */
-	REGISTER_PDO_CLASS_CONST_LONG("SQL_ATTR_INFO_USERID", (long) PDO_SQL_ATTR_INFO_USERID);
-	REGISTER_PDO_CLASS_CONST_LONG("SQL_ATTR_INFO_ACCTSTR", (long) PDO_SQL_ATTR_INFO_ACCTSTR);	
-	REGISTER_PDO_CLASS_CONST_LONG("SQL_ATTR_INFO_APPLNAME", (long) PDO_SQL_ATTR_INFO_APPLNAME);
-	REGISTER_PDO_CLASS_CONST_LONG("SQL_ATTR_INFO_WRKSTNNAME", (long) PDO_SQL_ATTR_INFO_WRKSTNNAME);
-	
-	php_pdo_register_driver(&pdo_ibm_driver);
-	return TRUE;  
+	REGISTER_PDO_IBM_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_INFO_USERID", (long) PDO_SQL_ATTR_INFO_USERID);
+	REGISTER_PDO_IBM_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_INFO_ACCTSTR", (long) PDO_SQL_ATTR_INFO_ACCTSTR);
+	REGISTER_PDO_IBM_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_INFO_APPLNAME", (long) PDO_SQL_ATTR_INFO_APPLNAME);
+	REGISTER_PDO_IBM_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_INFO_WRKSTNNAME", (long) PDO_SQL_ATTR_INFO_WRKSTNNAME);
+
+#if PHP_VERSION_ID >= 80400
+	pdo_ibm_ce = register_class_Pdo_Ibm(pdo_dbh_ce);
+	pdo_ibm_ce->create_object = pdo_dbh_new;
+
+	return php_pdo_register_driver_specific_ce(&pdo_ibm_driver, pdo_ibm_ce);
+#else
+	return TRUE;
+#endif
 }
 /* }}} */
 
diff --git a/pdo_ibm.stub.php b/pdo_ibm.stub.php
new file mode 100644
index 0000000..4a8da6e
--- /dev/null
+++ b/pdo_ibm.stub.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @generate-class-entries 
+ *
+ * This driver specific PDO class is only used for PHP 8.4+
+ */
+
+namespace Pdo {
+	/**
+	 * @strict-properties
+	 * @not-serializable
+	 */
+	class Ibm extends \PDO
+	{
+		/** @cvalue PDO_SQL_ATTR_INFO_USERID */
+		public const int ATTR_INFO_USERID = UNKNOWN;
+
+		/** @cvalue PDO_SQL_ATTR_INFO_ACCTSTR */
+		public const int ATTR_INFO_ACCTSTR = UNKNOWN;
+
+		/** @cvalue PDO_SQL_ATTR_INFO_APPLNAME */
+		public const int ATTR_INFO_APPLNAME = UNKNOWN;
+
+		/** @cvalue PDO_SQL_ATTR_INFO_WRKSTNNAME */
+		public const int ATTR_INFO_WRKSTNNAME = UNKNOWN;
+
+#ifndef PASE
+		/** @cvalue PDO_SQL_ATTR_USE_TRUSTED_CONTEXT */
+		public const int ATTR_USE_TRUSTED_CONTEXT = UNKNOWN;
+
+		/** @cvalue PDO_SQL_ATTR_TRUSTED_CONTEXT_USERID */
+		public const int ATTR_TRUSTED_CONTEXT_USERID = UNKNOWN;
+
+		/** @cvalue PDO_SQL_ATTR_TRUSTED_CONTEXT_PASSWORD */
+		public const int ATTR_TRUSTED_CONTEXT_PASSWORD = UNKNOWN;
+#endif
+#ifdef PASE
+		/** @cvalue PDO_I5_ATTR_DBC_SYS_NAMING */
+		public const int ATTR_DBC_SYS_NAMING = UNKNOWN;
+
+		/** @cvalue PDO_I5_ATTR_COMMIT */
+		public const int ATTR_COMMIT = UNKNOWN;
+
+		/** @cvalue PDO_I5_TXN_NO_COMMIT */
+		public const int TXN_NO_COMMIT = UNKNOWN;
+
+		/** @cvalue PDO_I5_TXN_READ_UNCOMMITTED */
+		public const int TXN_READ_UNCOMMITTED = UNKNOWN;
+
+		/** @cvalue PDO_I5_TXN_READ_COMMITTED */
+		public const int TXN_READ_COMMITTED = UNKNOWN;
+
+		/** @cvalue PDO_I5_TXN_REPEATABLE_READ */
+		public const int TXN_REPEATABLE_READ = UNKNOWN;
+
+		/** @cvalue PDO_I5_TXN_SERIALIZABLE */
+		public const int TXN_SERIALIZABLE = UNKNOWN;
+
+		/** @cvalue PDO_I5_ATTR_JOB_SORT */
+		public const int ATTR_JOB_SORT = UNKNOWN;
+
+		/** @cvalue PDO_I5_ATTR_DBC_LIBL */
+		public const int ATTR_DBC_LIBL = UNKNOWN;
+
+		/** @cvalue PDO_I5_ATTR_DBC_CURLIB */
+		public const int ATTR_DBC_CURLIB = UNKNOWN;
+#endif
+	}
+}
+
diff --git a/pdo_ibm_arginfo.h b/pdo_ibm_arginfo.h
new file mode 100644
index 0000000..24b0464
--- /dev/null
+++ b/pdo_ibm_arginfo.h
@@ -0,0 +1,118 @@
+/* This is a generated file, edit the .stub.php file instead.
+ * Stub hash: e6e91d0261810097515617adf9364f2ddf293a43 */
+
+static zend_class_entry *register_class_Pdo_Ibm(zend_class_entry *class_entry_PDO)
+{
+	zend_class_entry ce, *class_entry;
+
+	INIT_NS_CLASS_ENTRY(ce, "Pdo", "Ibm", NULL);
+	class_entry = zend_register_internal_class_with_flags(&ce, class_entry_PDO, ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE);
+
+	zval const_ATTR_INFO_USERID_value;
+	ZVAL_LONG(&const_ATTR_INFO_USERID_value, PDO_SQL_ATTR_INFO_USERID);
+	zend_string *const_ATTR_INFO_USERID_name = zend_string_init_interned("ATTR_INFO_USERID", sizeof("ATTR_INFO_USERID") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_INFO_USERID_name, &const_ATTR_INFO_USERID_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_INFO_USERID_name);
+
+	zval const_ATTR_INFO_ACCTSTR_value;
+	ZVAL_LONG(&const_ATTR_INFO_ACCTSTR_value, PDO_SQL_ATTR_INFO_ACCTSTR);
+	zend_string *const_ATTR_INFO_ACCTSTR_name = zend_string_init_interned("ATTR_INFO_ACCTSTR", sizeof("ATTR_INFO_ACCTSTR") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_INFO_ACCTSTR_name, &const_ATTR_INFO_ACCTSTR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_INFO_ACCTSTR_name);
+
+	zval const_ATTR_INFO_APPLNAME_value;
+	ZVAL_LONG(&const_ATTR_INFO_APPLNAME_value, PDO_SQL_ATTR_INFO_APPLNAME);
+	zend_string *const_ATTR_INFO_APPLNAME_name = zend_string_init_interned("ATTR_INFO_APPLNAME", sizeof("ATTR_INFO_APPLNAME") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_INFO_APPLNAME_name, &const_ATTR_INFO_APPLNAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_INFO_APPLNAME_name);
+
+	zval const_ATTR_INFO_WRKSTNNAME_value;
+	ZVAL_LONG(&const_ATTR_INFO_WRKSTNNAME_value, PDO_SQL_ATTR_INFO_WRKSTNNAME);
+	zend_string *const_ATTR_INFO_WRKSTNNAME_name = zend_string_init_interned("ATTR_INFO_WRKSTNNAME", sizeof("ATTR_INFO_WRKSTNNAME") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_INFO_WRKSTNNAME_name, &const_ATTR_INFO_WRKSTNNAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_INFO_WRKSTNNAME_name);
+#if !defined(PASE)
+
+	zval const_ATTR_USE_TRUSTED_CONTEXT_value;
+	ZVAL_LONG(&const_ATTR_USE_TRUSTED_CONTEXT_value, PDO_SQL_ATTR_USE_TRUSTED_CONTEXT);
+	zend_string *const_ATTR_USE_TRUSTED_CONTEXT_name = zend_string_init_interned("ATTR_USE_TRUSTED_CONTEXT", sizeof("ATTR_USE_TRUSTED_CONTEXT") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_USE_TRUSTED_CONTEXT_name, &const_ATTR_USE_TRUSTED_CONTEXT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_USE_TRUSTED_CONTEXT_name);
+
+	zval const_ATTR_TRUSTED_CONTEXT_USERID_value;
+	ZVAL_LONG(&const_ATTR_TRUSTED_CONTEXT_USERID_value, PDO_SQL_ATTR_TRUSTED_CONTEXT_USERID);
+	zend_string *const_ATTR_TRUSTED_CONTEXT_USERID_name = zend_string_init_interned("ATTR_TRUSTED_CONTEXT_USERID", sizeof("ATTR_TRUSTED_CONTEXT_USERID") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_TRUSTED_CONTEXT_USERID_name, &const_ATTR_TRUSTED_CONTEXT_USERID_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_TRUSTED_CONTEXT_USERID_name);
+
+	zval const_ATTR_TRUSTED_CONTEXT_PASSWORD_value;
+	ZVAL_LONG(&const_ATTR_TRUSTED_CONTEXT_PASSWORD_value, PDO_SQL_ATTR_TRUSTED_CONTEXT_PASSWORD);
+	zend_string *const_ATTR_TRUSTED_CONTEXT_PASSWORD_name = zend_string_init_interned("ATTR_TRUSTED_CONTEXT_PASSWORD", sizeof("ATTR_TRUSTED_CONTEXT_PASSWORD") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_TRUSTED_CONTEXT_PASSWORD_name, &const_ATTR_TRUSTED_CONTEXT_PASSWORD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_TRUSTED_CONTEXT_PASSWORD_name);
+#endif
+#if defined(PASE)
+
+	zval const_ATTR_DBC_SYS_NAMING_value;
+	ZVAL_LONG(&const_ATTR_DBC_SYS_NAMING_value, PDO_I5_ATTR_DBC_SYS_NAMING);
+	zend_string *const_ATTR_DBC_SYS_NAMING_name = zend_string_init_interned("ATTR_DBC_SYS_NAMING", sizeof("ATTR_DBC_SYS_NAMING") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_DBC_SYS_NAMING_name, &const_ATTR_DBC_SYS_NAMING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_DBC_SYS_NAMING_name);
+
+	zval const_ATTR_COMMIT_value;
+	ZVAL_LONG(&const_ATTR_COMMIT_value, PDO_I5_ATTR_COMMIT);
+	zend_string *const_ATTR_COMMIT_name = zend_string_init_interned("ATTR_COMMIT", sizeof("ATTR_COMMIT") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_COMMIT_name, &const_ATTR_COMMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_COMMIT_name);
+
+	zval const_TXN_NO_COMMIT_value;
+	ZVAL_LONG(&const_TXN_NO_COMMIT_value, PDO_I5_TXN_NO_COMMIT);
+	zend_string *const_TXN_NO_COMMIT_name = zend_string_init_interned("TXN_NO_COMMIT", sizeof("TXN_NO_COMMIT") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_TXN_NO_COMMIT_name, &const_TXN_NO_COMMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_TXN_NO_COMMIT_name);
+
+	zval const_TXN_READ_UNCOMMITTED_value;
+	ZVAL_LONG(&const_TXN_READ_UNCOMMITTED_value, PDO_I5_TXN_READ_UNCOMMITTED);
+	zend_string *const_TXN_READ_UNCOMMITTED_name = zend_string_init_interned("TXN_READ_UNCOMMITTED", sizeof("TXN_READ_UNCOMMITTED") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_TXN_READ_UNCOMMITTED_name, &const_TXN_READ_UNCOMMITTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_TXN_READ_UNCOMMITTED_name);
+
+	zval const_TXN_READ_COMMITTED_value;
+	ZVAL_LONG(&const_TXN_READ_COMMITTED_value, PDO_I5_TXN_READ_COMMITTED);
+	zend_string *const_TXN_READ_COMMITTED_name = zend_string_init_interned("TXN_READ_COMMITTED", sizeof("TXN_READ_COMMITTED") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_TXN_READ_COMMITTED_name, &const_TXN_READ_COMMITTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_TXN_READ_COMMITTED_name);
+
+	zval const_TXN_REPEATABLE_READ_value;
+	ZVAL_LONG(&const_TXN_REPEATABLE_READ_value, PDO_I5_TXN_REPEATABLE_READ);
+	zend_string *const_TXN_REPEATABLE_READ_name = zend_string_init_interned("TXN_REPEATABLE_READ", sizeof("TXN_REPEATABLE_READ") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_TXN_REPEATABLE_READ_name, &const_TXN_REPEATABLE_READ_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_TXN_REPEATABLE_READ_name);
+
+	zval const_TXN_SERIALIZABLE_value;
+	ZVAL_LONG(&const_TXN_SERIALIZABLE_value, PDO_I5_TXN_SERIALIZABLE);
+	zend_string *const_TXN_SERIALIZABLE_name = zend_string_init_interned("TXN_SERIALIZABLE", sizeof("TXN_SERIALIZABLE") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_TXN_SERIALIZABLE_name, &const_TXN_SERIALIZABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_TXN_SERIALIZABLE_name);
+
+	zval const_ATTR_JOB_SORT_value;
+	ZVAL_LONG(&const_ATTR_JOB_SORT_value, PDO_I5_ATTR_JOB_SORT);
+	zend_string *const_ATTR_JOB_SORT_name = zend_string_init_interned("ATTR_JOB_SORT", sizeof("ATTR_JOB_SORT") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_JOB_SORT_name, &const_ATTR_JOB_SORT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_JOB_SORT_name);
+
+	zval const_ATTR_DBC_LIBL_value;
+	ZVAL_LONG(&const_ATTR_DBC_LIBL_value, PDO_I5_ATTR_DBC_LIBL);
+	zend_string *const_ATTR_DBC_LIBL_name = zend_string_init_interned("ATTR_DBC_LIBL", sizeof("ATTR_DBC_LIBL") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_DBC_LIBL_name, &const_ATTR_DBC_LIBL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_DBC_LIBL_name);
+
+	zval const_ATTR_DBC_CURLIB_value;
+	ZVAL_LONG(&const_ATTR_DBC_CURLIB_value, PDO_I5_ATTR_DBC_CURLIB);
+	zend_string *const_ATTR_DBC_CURLIB_name = zend_string_init_interned("ATTR_DBC_CURLIB", sizeof("ATTR_DBC_CURLIB") - 1, 1);
+	zend_declare_typed_class_constant(class_entry, const_ATTR_DBC_CURLIB_name, &const_ATTR_DBC_CURLIB_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+	zend_string_release(const_ATTR_DBC_CURLIB_name);
+#endif
+
+	return class_entry;
+}
diff --git a/tests/fvt.inc b/tests/fvt.inc
index c34d62c..8cd222b 100644
--- a/tests/fvt.inc
+++ b/tests/fvt.inc
@@ -39,7 +39,10 @@ abstract class FVTTest
 	public function connect($autoCommit=true, $useLibl=false, $useIsolation=false)
 	{
 		$options = array(PDO::ATTR_AUTOCOMMIT=>$autoCommit);
-		$this->db = new PDO($this->dsn, $this->user, $this->pass, $options);
+		// Use the driver subclass on PHP 8.4+
+		$this->db = version_compare(PHP_VERSION, '8.4.0') >= 0
+			? PDO::connect($this->dsn, $this->user, $this->pass, $options)
+			: new PDO($this->dsn, $this->user, $this->pass, $options);
 		$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 		$this->db->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
 		$this->db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
diff --git a/tests/fvt_client_info.phpt b/tests/fvt_client_info.phpt
index d44fee3..8d5ee86 100644
--- a/tests/fvt_client_info.phpt
+++ b/tests/fvt_client_info.phpt
@@ -11,22 +11,33 @@ pdo_ibm: Client Info
 		{
 			print "Attempting to connect..\n";
 			$this->connect();
+
+			// Use class constants in 8.4 or newer, 8.5 will show
+			// a deprecation message when using the PDO constants
+			$userID = version_compare(PHP_VERSION, '8.4.0') >= 0
+				? \PDO\Ibm::ATTR_INFO_USERID : PDO::SQL_ATTR_INFO_USERID;
+			$acctStr = version_compare(PHP_VERSION, '8.4.0') >= 0
+				? \PDO\Ibm::ATTR_INFO_ACCTSTR : PDO::SQL_ATTR_INFO_ACCTSTR;
+			$applName = version_compare(PHP_VERSION, '8.4.0') >= 0
+				? \PDO\Ibm::ATTR_INFO_APPLNAME : PDO::SQL_ATTR_INFO_APPLNAME;
+			$wrkstnName = version_compare(PHP_VERSION, '8.4.0') >= 0
+				? \PDO\Ibm::ATTR_INFO_WRKSTNNAME : PDO::SQL_ATTR_INFO_WRKSTNNAME;
 			
-			var_dump($this->db->getAttribute(PDO::SQL_ATTR_INFO_USERID));
-			var_dump($this->db->getAttribute(PDO::SQL_ATTR_INFO_ACCTSTR));
-			var_dump($this->db->getAttribute(PDO::SQL_ATTR_INFO_APPLNAME));
+			var_dump($this->db->getAttribute($userID));
+			var_dump($this->db->getAttribute($acctStr));
+			var_dump($this->db->getAttribute($applName));
 			// This will default to the hostname of the system nowadays.
-			var_dump($this->db->getAttribute(PDO::SQL_ATTR_INFO_WRKSTNNAME));
+			var_dump($this->db->getAttribute($wrkstnName));
 		
-			$this->db->setAttribute(PDO::SQL_ATTR_INFO_USERID, "MyUser");
-			$this->db->setAttribute(PDO::SQL_ATTR_INFO_ACCTSTR, "MyAccountString");
-			$this->db->setAttribute(PDO::SQL_ATTR_INFO_APPLNAME, "MyApp");
-			$this->db->setAttribute(PDO::SQL_ATTR_INFO_WRKSTNNAME, "MyWorkStation");
+			$this->db->setAttribute($userID, "MyUser");
+			$this->db->setAttribute($acctStr, "MyAccountString");
+			$this->db->setAttribute($applName, "MyApp");
+			$this->db->setAttribute($wrkstnName, "MyWorkStation");
 			
-			var_dump($this->db->getAttribute(PDO::SQL_ATTR_INFO_USERID));
-			var_dump($this->db->getAttribute(PDO::SQL_ATTR_INFO_ACCTSTR));
-			var_dump($this->db->getAttribute(PDO::SQL_ATTR_INFO_APPLNAME));
-			var_dump($this->db->getAttribute(PDO::SQL_ATTR_INFO_WRKSTNNAME));
+			var_dump($this->db->getAttribute($userID));
+			var_dump($this->db->getAttribute($acctStr));
+			var_dump($this->db->getAttribute($applName));
+			var_dump($this->db->getAttribute($wrkstnName));
 		}
 	}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.