PHP MySQL X DevAPI Collection::existsDatabase()方法无法识别具有附加列的C



根据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类似,即

  1. "countryinfo"报告为集合
  2. 添加/删除列也会导致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!

此外,您使用的服务器/连接器的版本是什么?

相关内容

  • 没有找到相关文章

最新更新