According to the PHP docs the existsInDatabase()
method is intended to determine if an instance of Collection exists in the database (as a SchemaObject aka a Table). But it only considers a Collection to exist if it's table's schema fits exactly that which it would if it was created using the Schema::createCollection()
method, eg. Exactly 2 columns called doc
and _id
.
Is this a bug caused by PHP module being too strict?
Here's a demonstration (Depends on the mysql_xdevapi PHP module)...
Firstly, use MySQL to create a collection called 'people' in your db (as taken from MySQL's world_x.sql script in examples for JavaScript/Python):
CREATE TABLE `countryinfo` (
`doc` json DEFAULT NULL,
`_id` varbinary(32) GENERATED ALWAYS AS (json_unquote(json_extract(`doc`,_utf8mb4'$._id'))) STORED NOT NULL,
`_json_schema` json GENERATED ALWAYS AS (_utf8mb4'{"type":"object"}') VIRTUAL,
PRIMARY KEY (`_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Secondly, create a collection called 'people', very similar to above but with the _json_schema
column omitted:
CREATE TABLE `people` (
`doc` json DEFAULT NULL,
`_id` varbinary(32) GENERATED ALWAYS AS (json_unquote(json_extract(`doc`,_utf8mb4'$._id'))) STORED NOT NULL,
PRIMARY KEY (`_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Thirdly, use PHP's createCollection()
method to create a collection named 'animals':
$dbSession = mysql_xdevapi\getSession("mysqlx://test:test@localhost");
$schema = $dbSession->getSchema("world_x");
$collection = $schema->createCollection('animals');
Now, use PHP's existsInDatabase()
method to check the 3 collections:
$dbSession = mysql_xdevapi\getSession("mysqlx://test:test@localhost");
$schema = $dbSession->getSchema("world_x");
if ($schema->getCollection('countryinfo')->existsInDatabase()) {
print "countryinfo collection exist! ";
}
if ($schema->getCollection('people')->existsInDatabase()) {
print "People collection exist! ";
}
if ($schema->getCollection('animals')->existsInDatabase()) {
print "Animals collection exist! ";
}
All 3 of these are valid collections according to MySQL docs but the above PHP code only recognises 'people' and 'animals' as existing.
As a further experiment, use MySQL to add any randomly named column to the collection named "animals" (which was created via PHP) and re-execute the script to see how it now does not consider it to exist.
ALTER TABLE animals ADD COLUMN test tinyint;
Now if you use $schema->getCollections()
and $schema->getTables()
you will see that animals
is classified under tables not collections. Drop that column and it jumps back again. Under the bonnet, this is how the module decides if a Collection "exists".
I suspect the PHP module might be being too strict. This a problem because it tightly-couples your database schema to a specific language. If, for example, I wanted to build a PHP script to interact with an existing MySQL Document Store that was originally populated via JavaScript it could be buggy because presumably that extra _json_schema
column (or some other columns) would exist in some/all of the Collections.
I assume it is legitimate to have columns other than doc
and _id
as I have not found specifications to the contrary. I can imagine a very real use case for having a created_at
datetime column on a Collection.
Alternatively, have I actually discovered a problem not with the PHP module but with MySQLs documentation? Is the _json_schema
column a hangover from an early version that should now be removed? Is the definition of a Collection table now standardised across all languages and they must strictly have just those 2 columns as specified?
It's all a bit fluffy with MySQL being vague but PHP being strict.
Any help is appreciated. I will report bugs to maintainers if the consensus is that there is a bug.