根据PHP文档,existsInDatabase()
方法旨在确定数据库中是否存在Collection的实例(作为SchemaObject或Table(。但是,只有当集合的表的模式与使用Schema::createCollection()
方法创建的集合的模式完全匹配时,它才会认为集合存在,例如,正好有两列称为doc
和_id
。
这是PHP模块过于严格导致的错误吗?
这里有一个演示(取决于mysql_xdevapiPHP模块(。。。
首先,使用MySQL在数据库中创建一个名为"people"的集合(在JavaScript/Python的示例中取自MySQL的world_x.sql脚本(:
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;
其次,创建一个名为"people"的集合,与上面的集合非常相似,但省略了_json_schema
列:
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;
第三,使用PHP的createCollection()
方法创建一个名为"animals"的集合:
$dbSession = mysql_xdevapigetSession("mysqlx://test:test@localhost");
$schema = $dbSession->getSchema("world_x");
$collection = $schema->createCollection('animals');
现在,使用PHP的existsInDatabase()
方法检查3个集合:
$dbSession = mysql_xdevapigetSession("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! ";
}
根据MySQL文档,这三个都是有效的集合,但上面的PHP代码只识别"人"one_answers"动物"。
作为进一步的实验,使用MySQL将任何随机命名的列添加到名为"animals">(通过PHP创建(的集合中,然后重新执行脚本,看看它现在是如何不认为它存在的。
ALTER TABLE animals ADD COLUMN test tinyint;
现在,如果您使用$schema->getCollections()
和$schema->getTables()
,您将看到animals
被分类在表下,而不是集合下。放下那一列,它又跳回来了。在发动机罩下,这是模块决定Collection是否"存在"的方式。
我怀疑PHP模块可能过于严格。这是一个问题,因为它将数据库模式与特定语言紧密耦合。例如,如果我想构建一个PHP脚本来与最初通过JavaScript填充的现有MySQL文档存储交互,那么它可能会有问题,因为可能会有额外的_json_schema
列(或其他一些列(存在于某些/所有集合中。
我认为除了doc
和_id
之外还有其他列是合法的,因为我没有发现相反的规范。我可以想象一个在Collection上具有created_at
日期时间列的非常真实的用例。
或者,我是否真的发现了一个问题,不是PHP模块的问题,而是MySQL文档的问题?_json_schema
列是否是早期版本的遗留问题,现在应该删除?集合表的定义现在在所有语言中都标准化了吗?它们必须严格按照规定只有这两列?
MySQL是模糊的,但PHP是严格的,这一切都有点混乱。
感谢您的帮助。如果一致认为存在错误,我会向维护人员报告错误。
------------------------------编辑4月21日}------------------------------
看起来xplugin/server的行为既没有任何错误,也没有任何变化。不允许向集合中添加额外的列。"countryinfo"集合中的_json_schema列不被视为额外的内容,它用于名为"schema validation"的新功能,并且是可选的。因此,它可能会出现在集合的表中,也可能不会出现。因此,给定的表仍然被视为集合,无论它是否包含"_json_schema"。尽管如此,将其名称从"_json_schema"更改为例如"json_schema"(即只删除前导下划线(就足够了,并且它将被视为额外的列,因此给定的表将不再报告为集合(existsDatabase((返回false(。
引用样本:
https://dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-download.html
适用于8.0.19,但该版本的服务器似乎已经为"模式验证"做好了准备,而mysqlxdevapi将从v8.0.21开始正式支持该功能。
在提到的新版本。21这样的调用后:
$coll = $schema->createCollection("animals");
"动物"表中的列将如下所示
mysql> show columns from animals;
+--------------+---------------+------+-----+---------+-------------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+-------------------+
| doc | json | YES | | NULL | |
| _id | varbinary(32) | NO | PRI | NULL | STORED GENERATED |
| _json_schema | json | YES | | NULL | VIRTUAL GENERATED |
+--------------+---------------+------+-----+---------+-------------------+
3 rows in set (0.00 sec)
并将其作为集合进行报告。
-------------------------------{编辑结束4月21日}------------------------------
我们已经检查了con/php的行为,看起来它的性能与con/nodjs类似,即
- "countryinfo"报告为集合
- 添加/删除列也会导致con/nodjs或shell中报告的"animals"类型发生变化(集合与表(
请运行下面的脚本,让我们知道您的环境中的输出是什么。
// please align below variables according to your environment
$connection_uri = "mysqlx://test:test@localhost";
$db = "testx";
$session = mysql_xdevapigetSession($connection_uri);
$session->sql("create database $db")->execute();
$schema = $session->getSchema($db);
$session->sql("USE $db")->execute();
$countryinfo_table_stmt="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";
echo "$countryinfo_table_stmtn";
$session->sql($countryinfo_table_stmt)->execute();
$people_table_stmt="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";
echo "$people_table_stmtn";
$session->sql($people_table_stmt)->execute();
if ($schema->getCollection('countryinfo')->existsInDatabase()) {
print "countryinfo collection exists!n";
} else {
print "countryinfo collection DOES NOT exist!n";
}
if ($schema->getCollection('people')->existsInDatabase()) {
print "People collection exists!n";
} else {
print "People collection DOES NOT exist!n";
}
$coll = $schema->createCollection("animals");
if ($schema->getCollection('animals')->existsInDatabase()) {
print "Animals collection exists!n";
} else {
print "Animals collection DOES NOT exist!n";
}
$session->sql("ALTER TABLE $db.animals ADD COLUMN test tinyint")->execute();
if ($schema->getCollection('animals')->existsInDatabase()) {
print "Animals collection exists!n";
} else {
print "Animals collection DOES NOT exist!n";
}
$session->sql("ALTER TABLE $db.animals DROP COLUMN test")->execute();
if ($schema->getCollection('animals')->existsInDatabase()) {
print "Animals collection exists!n";
} else {
print "Animals collection DOES NOT exist!n";
}
print "done!n";
在我们的环境中,输出如下:
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
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
countryinfo collection exists!
People collection exists!
Animals collection exists!
Animals collection DOES NOT exist!
Animals collection exists!
done!
此外,您使用的服务器/连接器的版本是什么?