PHP MySQL X Метод DevAPI Collection :: existInDatabase () не распознает коллекции с дополнительными столбцами - PullRequest
0 голосов
/ 06 апреля 2020

В соответствии с PHP документами метод existsInDatabase() предназначен для определения, существует ли экземпляр Collection в базе данных (как SchemaObject aka a Table) . Но он считает, что Коллекция существует, только если схема ее таблицы точно соответствует той, какой она была бы, если бы она была создана с использованием метода Schema::createCollection(), например. Ровно 2 столбца, которые называются doc и _id.

Это ошибка, вызванная слишком строгим модулем PHP?

Вот демонстрация (Зависит от mysql_xdevapi PHP модуль ) ...

Во-первых, используйте MySQL для создания коллекции под названием 'people' в вашей базе данных (как взято из сценария MySQL world_x. sql в примерах для 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;

Во-вторых, создайте коллекцию под названием '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(), чтобы создать коллекцию с именем «животных»:

$dbSession = mysql_xdevapi\getSession("mysqlx://test:test@localhost");

$schema = $dbSession->getSchema("world_x");    

$collection = $schema->createCollection('animals');

Теперь используйте метод PHP 'existsInDatabase(), чтобы проверить 3 коллекции:

$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! ";
}

Все 3 из них являются действительными коллекциями согласно MySQL документам, но вышеприведенный код PHP распознает только "людей" и "животных" как существующих.

В качестве дальнейшего эксперимента используйте MySQL, чтобы добавить любой произвольно названный столбец в коллекцию с именем "animals" (которая была создана с помощью PHP) и повторно выполнить сценарий для посмотрим, как оно сейчас не считает его существующим.

ALTER TABLE animals ADD COLUMN test tinyint;

Теперь, если вы используете $schema->getCollections() и $schema->getTables(), вы увидите, что animals классифицируется по таблицам, а не по коллекциям. Оставьте этот столбец, и он снова отскочит. Под bo nnet именно так модуль решает, существует ли коллекция.

Я подозреваю, что модуль PHP может быть слишком строгим. Это проблема, потому что она тесно связывает вашу схему базы данных с указанным c языком. Если, например, я хотел создать сценарий PHP для взаимодействия с существующим MySQL хранилищем документов, которое изначально заполнялось через JavaScript, это могло бы привести к ошибкам, поскольку предположительно этот дополнительный столбец _json_schema (или некоторые другие столбцы) будет существовать в некоторых / всех коллекциях.

Я предполагаю, что допустимо иметь столбцы, отличные от doc и _id, так как я не нашел спецификаций наоборот. Я могу представить очень реальный вариант использования столбца created_at datetime в коллекции.

Или я обнаружил проблему не с модулем PHP, а с документацией MySQL? Является ли столбец _json_schema похмелью от ранней версии, которую теперь следует удалить? Является ли определение таблицы Collection теперь стандартизированным по всем языкам, и они должны строго содержать только эти 2 столбца, как указано?

Все немного пушисто, когда MySQL неопределенно, но PHP строго.

Любая помощь приветствуется. Я сообщу об ошибках сопровождающим, если все согласны с тем, что есть ошибка.

Ответы [ 2 ]

0 голосов
/ 10 апреля 2020

------------------------------- {edit 21 апреля} ----------- --------------------

Похоже, что нет никаких ошибок или изменений в поведении xplugin / server. Добавление дополнительных столбцов в коллекцию не допускается. Этот столбец _json_schema из коллекции 'countryinfo' не рассматривается как нечто дополнительное - он предназначен для новой функции, называемой 'проверка схемы', и является необязательным. Так может появиться в таблице коллекции или нет. Поэтому данная таблица все еще обрабатывается как коллекция, независимо от того, содержит она _json_schema или нет. Хотя достаточно изменить его имя с «_json_schema» на, например, «json_schema» (т. Е. Просто удалить начальное подчеркивание), и оно будет рассматриваться как дополнительный столбец, поэтому данная таблица больше не будет указываться как коллекция (возвращаетInInInatabase ()) false).

Приведенный пример:

https://dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-download.html

предназначен для 8.0.19, но, похоже, эта версия сервера уже подготовлен для «проверки схемы», в то время как mysql_xdevapi будет официально поддерживать эту функцию начиная с 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)

и будет отображаться как коллекция.

------------------ ------------- {конец редактирования 21 апреля} ------------------------------ -

Мы проверили поведение con / php и похоже, что он работает так же, как con / nodejs, то есть

  1. 'countryinfo' сообщается как коллекция
  2. добавление / удаление c olumns вызывает изменения в сообщаемом типе «животных» в con / nodejs или в оболочке (коллекция против таблицы).

Пожалуйста, запустите приведенный ниже скрипт и сообщите нам, что выводится на ваш среда.

// please align below variables according to your environment
$connection_uri = "mysqlx://test:test@localhost";
$db = "testx";

$session = mysql_xdevapi\getSession($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_stmt\n";
$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_stmt\n";
$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!

Кроме того, какую версию сервера / разъемов вы используете?

0 голосов
/ 07 апреля 2020

Спасибо за отчет. Мы проверим это и вернемся к вам.

...