diff --git a/src/xPDO/Om/mysql/xPDOManager.php b/src/xPDO/Om/mysql/xPDOManager.php
index 26d2bdde..7cdcc9c0 100644
--- a/src/xPDO/Om/mysql/xPDOManager.php
+++ b/src/xPDO/Om/mysql/xPDOManager.php
@@ -114,9 +114,14 @@ public function createObjectContainer($className) {
$instance= $this->xpdo->newObject($className);
if ($instance) {
$tableName= $this->xpdo->getTableName($className);
- $existsStmt = $this->xpdo->query("SELECT COUNT(*) FROM {$tableName}");
- if ($existsStmt && $existsStmt->fetchAll()) {
- return true;
+ try {
+ $existsStmt = $this->xpdo->query("SELECT COUNT(*) FROM {$tableName}");
+ if ($existsStmt && $existsStmt->fetchAll()) {
+ return true;
+ }
+ } catch (\PDOException $e) {
+ /* Table does not exist; proceed to CREATE TABLE below. */
+ $this->xpdo->log(xPDO::LOG_LEVEL_DEBUG, "Table {$tableName} does not exist, creating: " . $e->getMessage());
}
$modelVersion= $this->xpdo->getModelVersion($className);
$tableMeta= $this->xpdo->getTableMeta($className);
diff --git a/src/xPDO/Om/pgsql/xPDOManager.php b/src/xPDO/Om/pgsql/xPDOManager.php
index ee8a43d0..a9e429f1 100644
--- a/src/xPDO/Om/pgsql/xPDOManager.php
+++ b/src/xPDO/Om/pgsql/xPDOManager.php
@@ -132,9 +132,14 @@ public function createObjectContainer($className)
$instance= $this->xpdo->newObject($className);
if ($instance) {
$tableName= $this->xpdo->getTableName($className);
- $existsStmt = $this->xpdo->query("SELECT COUNT(*) FROM {$tableName}");
- if ($existsStmt && $existsStmt->fetchAll()) {
- return true;
+ try {
+ $existsStmt = $this->xpdo->query("SELECT COUNT(*) FROM {$tableName}");
+ if ($existsStmt && $existsStmt->fetchAll()) {
+ return true;
+ }
+ } catch (\PDOException $e) {
+ /* Table does not exist; proceed to CREATE TABLE below. */
+ $this->xpdo->log(xPDO::LOG_LEVEL_DEBUG, "Table {$tableName} does not exist, creating: " . $e->getMessage());
}
$tableMeta= $this->xpdo->getTableMeta($className);
$sql= 'CREATE TABLE ' . $tableName . ' (';
diff --git a/src/xPDO/Om/sqlite/xPDOManager.php b/src/xPDO/Om/sqlite/xPDOManager.php
index 844c232b..c8eaf18b 100644
--- a/src/xPDO/Om/sqlite/xPDOManager.php
+++ b/src/xPDO/Om/sqlite/xPDOManager.php
@@ -87,9 +87,14 @@ public function createObjectContainer($className) {
$instance= $this->xpdo->newObject($className);
if ($instance) {
$tableName= $this->xpdo->getTableName($className);
- $existsStmt = $this->xpdo->query("SELECT COUNT(*) FROM {$tableName}");
- if ($existsStmt && $existsStmt->fetchAll()) {
- return true;
+ try {
+ $existsStmt = $this->xpdo->query("SELECT COUNT(*) FROM {$tableName}");
+ if ($existsStmt && $existsStmt->fetchAll()) {
+ return true;
+ }
+ } catch (\PDOException $e) {
+ /* Table does not exist; proceed to CREATE TABLE below. */
+ $this->xpdo->log(xPDO::LOG_LEVEL_DEBUG, "Table {$tableName} does not exist, creating: " . $e->getMessage());
}
$tableMeta= $this->xpdo->getTableMeta($className);
$sql= 'CREATE TABLE ' . $tableName . ' (';
diff --git a/src/xPDO/Om/sqlsrv/xPDOManager.php b/src/xPDO/Om/sqlsrv/xPDOManager.php
index 15fab64d..2a01f7f3 100644
--- a/src/xPDO/Om/sqlsrv/xPDOManager.php
+++ b/src/xPDO/Om/sqlsrv/xPDOManager.php
@@ -109,9 +109,14 @@ public function createObjectContainer($className) {
$instance= $this->xpdo->newObject($className);
if ($instance) {
$tableName= $this->xpdo->getTableName($className);
- $existsStmt = $this->xpdo->query("SELECT COUNT(*) FROM {$tableName}");
- if ($existsStmt && $existsStmt->fetchAll()) {
- return true;
+ try {
+ $existsStmt = $this->xpdo->query("SELECT COUNT(*) FROM {$tableName}");
+ if ($existsStmt && $existsStmt->fetchAll()) {
+ return true;
+ }
+ } catch (\PDOException $e) {
+ /* Table does not exist; proceed to CREATE TABLE below. */
+ $this->xpdo->log(xPDO::LOG_LEVEL_DEBUG, "Table {$tableName} does not exist, creating: " . $e->getMessage());
}
$tableMeta= $this->xpdo->getTableMeta($className);
$sql= 'CREATE TABLE ' . $tableName . ' (';
diff --git a/test/complete.phpunit.xml b/test/complete.phpunit.xml
index db844f7d..87acd1e5 100644
--- a/test/complete.phpunit.xml
+++ b/test/complete.phpunit.xml
@@ -29,6 +29,7 @@
./xPDO/Test/Om/xPDOQueryLimitTest.php
./xPDO/Test/Om/xPDOQuerySortByTest.php
./xPDO/Test/Om/xPDOGeneratorTest.php
+ ./xPDO/Test/Om/xPDOManagerCreateObjectContainerTest.php
./xPDO/Test/Cache/xPDOCacheManagerTest.php
./xPDO/Test/Cache/xPDOCacheDbTest.php
./xPDO/Test/Compression/xPDOZipTest.php
diff --git a/test/mysql.phpunit.xml b/test/mysql.phpunit.xml
index db844f7d..87acd1e5 100644
--- a/test/mysql.phpunit.xml
+++ b/test/mysql.phpunit.xml
@@ -29,6 +29,7 @@
./xPDO/Test/Om/xPDOQueryLimitTest.php
./xPDO/Test/Om/xPDOQuerySortByTest.php
./xPDO/Test/Om/xPDOGeneratorTest.php
+ ./xPDO/Test/Om/xPDOManagerCreateObjectContainerTest.php
./xPDO/Test/Cache/xPDOCacheManagerTest.php
./xPDO/Test/Cache/xPDOCacheDbTest.php
./xPDO/Test/Compression/xPDOZipTest.php
diff --git a/test/pgsql.phpunit.xml b/test/pgsql.phpunit.xml
index 0052140b..31070e12 100644
--- a/test/pgsql.phpunit.xml
+++ b/test/pgsql.phpunit.xml
@@ -29,6 +29,7 @@
./xPDO/Test/Om/xPDOQueryLimitTest.php
./xPDO/Test/Om/xPDOQuerySortByTest.php
./xPDO/Test/Om/xPDOGeneratorTest.php
+ ./xPDO/Test/Om/xPDOManagerCreateObjectContainerTest.php
./xPDO/Test/Cache/xPDOCacheManagerTest.php
./xPDO/Test/Cache/xPDOCacheDbTest.php
./xPDO/Test/Compression/xPDOZipTest.php
diff --git a/test/sqlite.phpunit.xml b/test/sqlite.phpunit.xml
index baae2486..fb433abd 100644
--- a/test/sqlite.phpunit.xml
+++ b/test/sqlite.phpunit.xml
@@ -29,6 +29,7 @@
./xPDO/Test/Om/xPDOQueryLimitTest.php
./xPDO/Test/Om/xPDOQuerySortByTest.php
./xPDO/Test/Om/xPDOGeneratorTest.php
+ ./xPDO/Test/Om/xPDOManagerCreateObjectContainerTest.php
./xPDO/Test/Cache/xPDOCacheManagerTest.php
./xPDO/Test/Cache/xPDOCacheDbTest.php
./xPDO/Test/Compression/xPDOZipTest.php
diff --git a/test/xPDO/Test/Om/xPDOManagerCreateObjectContainerTest.php b/test/xPDO/Test/Om/xPDOManagerCreateObjectContainerTest.php
new file mode 100644
index 00000000..70aed37c
--- /dev/null
+++ b/test/xPDO/Test/Om/xPDOManagerCreateObjectContainerTest.php
@@ -0,0 +1,133 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace xPDO\Test\Om;
+
+use xPDO\TestCase;
+use xPDO\xPDO;
+
+/**
+ * Regression test for issue #207:
+ * xPDOManager->createObjectContainer() broken in MySQL 8+ (and other drivers)
+ * when the table does not yet exist.
+ *
+ * Prior to the fix, calling createObjectContainer() on a non-existent table
+ * would cause an uncaught PDOException on drivers that raise errors as
+ * exceptions (ERRMODE_EXCEPTION). The fix wraps the existence probe in a
+ * try/catch so that a missing table causes the method to proceed with
+ * CREATE TABLE rather than propagating an exception.
+ *
+ * @package xPDO\Test\Om
+ */
+class xPDOManagerCreateObjectContainerTest extends TestCase
+{
+ /**
+ * Set up for each test: ensure the test table does NOT exist beforehand
+ * so we exercise the "table missing" code path in createObjectContainer().
+ *
+ * @before
+ */
+ public function setUpFixtures()
+ {
+ parent::setUpFixtures();
+ $this->xpdo->getManager();
+ // Drop the table if it already exists so each test starts clean.
+ try {
+ $this->xpdo->exec(
+ 'DROP TABLE IF EXISTS ' . $this->xpdo->getTableName('xPDO\\Test\\Sample\\Person')
+ );
+ } catch (\PDOException $e) {
+ // Ignore; the table may not exist yet.
+ }
+ }
+
+ /**
+ * Tear down after each test: remove the created table.
+ *
+ * @after
+ */
+ public function tearDownFixtures()
+ {
+ try {
+ $this->xpdo->exec(
+ 'DROP TABLE IF EXISTS ' . $this->xpdo->getTableName('xPDO\\Test\\Sample\\Person')
+ );
+ } catch (\PDOException $e) {
+ // Ignore.
+ }
+ parent::tearDownFixtures();
+ }
+
+ /**
+ * Verify createObjectContainer() returns true and does not throw when the
+ * table does not yet exist.
+ *
+ * Regression: on MySQL 8+ (and any driver in ERRMODE_EXCEPTION mode) the
+ * SELECT COUNT(*) existence probe threw an uncaught PDOException instead of
+ * proceeding to CREATE TABLE.
+ */
+ public function testCreateObjectContainerOnNonExistentTableReturnsTrue()
+ {
+ $this->xpdo->getManager();
+
+ // Force ERRMODE_EXCEPTION on the underlying PDO connection to reproduce
+ // the MySQL 8+ behaviour that triggered the bug.
+ if ($this->xpdo->pdo instanceof \PDO) {
+ $this->xpdo->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+ }
+
+ $threwException = false;
+ $result = false;
+ try {
+ $result = $this->xpdo->manager->createObjectContainer('xPDO\\Test\\Sample\\Person');
+ } catch (\PDOException $e) {
+ $threwException = true;
+ }
+
+ $this->assertFalse(
+ $threwException,
+ 'createObjectContainer() must not propagate a PDOException when the table does not yet exist (#207).'
+ );
+ $this->assertTrue(
+ $result,
+ 'createObjectContainer() must return true after successfully creating the table.'
+ );
+ }
+
+ /**
+ * Verify createObjectContainer() returns true (idempotent) when the table
+ * already exists, and does not throw.
+ */
+ public function testCreateObjectContainerOnExistingTableReturnsTrue()
+ {
+ $this->xpdo->getManager();
+
+ // Create the table first.
+ $this->xpdo->manager->createObjectContainer('xPDO\\Test\\Sample\\Person');
+
+ // Calling a second time must return true without exception.
+ $threwException = false;
+ $result = false;
+ try {
+ $result = $this->xpdo->manager->createObjectContainer('xPDO\\Test\\Sample\\Person');
+ } catch (\PDOException $e) {
+ $threwException = true;
+ }
+
+ $this->assertFalse(
+ $threwException,
+ 'createObjectContainer() must not throw when called on an already-existing table.'
+ );
+ $this->assertTrue(
+ $result,
+ 'createObjectContainer() must return true when the table already exists (idempotent).'
+ );
+ }
+}