Где функция drupal_write_record() берёт значения для уникальных индексных полей?

Главные вкладки

Аватар пользователя roman-ivannikov roman-ivannikov 21 июля 2019 в 14:52

Всем привет!
В таблице одно из полей является первичным ключом. В одном из модулей Drupal, который использует эту таблицу, при добавлении новой записи через функцию drupal_write_record() возникает нарушение уникальности поля.
Таблицу через phpMyAdmin я посмотрел, видимых нарушений в ней нет. Все записи присутствуют.
Лог ошибок показывает, что при вызове функции drupal_write_record() в ключевое поле пытаются записаться различные значения, возрастающие при каждой попытке. Но в таблице, для определенности, 90 записей, то есть ближайшее свободное значение для ключа - это 91. А функция при первом вызове подставила значение 7 (это было видно в логе), следующая попытка увеличила это значение и т.д.
Где в моей базе данных закрался косяк? От куда функция drupal_write_record() берёт значения для уникальных полей?

Лучший ответ

Аватар пользователя roman-ivannikov roman-ivannikov 25 июля 2019 в 18:24

Ура! Разобрался в логике работы модуля. Модуль, кстати, называется Domain Access.
Есть еще таблица связанная с модулем - domain_export. В ней было всего 5 записей. Состоит она из двух полей. Одно из полей, с именем "domain_id", как раз и является авто-инкрементным.
Добавил в эту таблицу строку с данными из последней записи таблицы domain и всё: добавление новых записей через интерфейс модуля стал возможен. Значит кто-то ранее вносил изменения в эту таблицу.

Комментарии

Аватар пользователя Semantics Semantics 21 июля 2019 в 22:13

Функция drupal_write_record() ниоткуда не берет эти значения.
ID либо передаётся при её вызове, либо в ID передаётся NULL и СУБД при вставке назначает очередной инкремент.
У вас в таблице может вообще не быть строк, а очередной инкремент будет 1 000 000.

Нужно для начала проверить, что передаётся в drupal_write_record().

Для саморазвития:

  • Изучить функцию max()
  • Изучить функцию count()
  • SELECT AUTO_INCREMENT FROM  INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'DatabaseName' AND   TABLE_NAME   = 'TableName';
Аватар пользователя roman-ivannikov roman-ivannikov 22 июля 2019 в 6:52

<a href="mailto:sas@drupal.org">sas@drupal.org</a> wrote:
Инкремент уникального ключа делает автоматически, если записи стерты инкремент не уменьшается.

Уважаемый камрад.
Посмотрел, в таблице данное поле не автокриментно. Но уникально. Значит сам модуль отвечает за корректность значений в этом поле?

Аватар пользователя roman-ivannikov roman-ivannikov 22 июля 2019 в 6:48

Уважаемый камрад.
Спасибо за ответ. Функции max() и count() я изучил. Запросы SQL касался поверхностно.
Запросы к БД сделаю. Посмотрю что выйдет.

Запрос показал значение Null. То есть, автокремента нет.
Значит сам модуль генерирует новое значение для ключевого поля, так?
А разработчик модуля написал, что это значение автоматические генерируется из drupal_write_record(). Вот его ответ:
It is auto-generated from drupal_write_record(). I don't recall how that code looks up the value to use.

Скажите, куда мне дальше копать?

Аватар пользователя Orion76 Orion76 22 июля 2019 в 7:54

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

Аватар пользователя roman-ivannikov roman-ivannikov 22 июля 2019 в 15:48

Уважаемый камрад.
Я посмотрел структуру таблицы. Поле ID является уникальным, но без автоинкремента. Также оно является первичным ключом. Это 100%. Для точности: поле называется не ID, но не думаю что это важно.
Через интерфейс модуля успешно добавляли новые записи пару лет назад. За прошедшее время успели обновить ядро drupal. Но всё это я не застал.
Модуль обновил до последней рабочей версии.
Я так понимаю, что придется капать в коде модуля и смотреть что от куда берется?
А если я попробую изменить структуры таблицы и задать для поля свойство автоинкримента? СУБД даст это сделать при наличии записей в таблице. Где и что мне внести в этом случае, чтобы для автоинкримента бралось нужное значение. Например, я знаю сколько записей в таблице и смогу указать нужное значение.

Аватар пользователя Orion76 Orion76 22 июля 2019 в 21:42

Quote:

Я посмотрел структуру таблицы. Поле ID является уникальным, но без автоинкремента.

Это "сейчас" так, есть гарантия что параметры таблиц в БД никто не менял?

А если всё-таки не менял, значит назначение ID новому материалу производится "программно" в каком-то модуле, скорее всего "самописном".

Значит надо сначала выяснить, каким образом новому материалу назначается ID: программно или автоинкрементом в БД.

Если "программно" нужно искать ошибку в коде.
Если автоинкрементом - установить автоинкремент для поля ID и увеличить счетчик автоинкремента для этой таблицы .

Если решитесь разобраться сами, не забудьте обязательно сделать бэкап базы данных.

Аватар пользователя roman-ivannikov roman-ivannikov 25 июля 2019 в 18:24

Ура! Разобрался в логике работы модуля. Модуль, кстати, называется Domain Access.
Есть еще таблица связанная с модулем - domain_export. В ней было всего 5 записей. Состоит она из двух полей. Одно из полей, с именем "domain_id", как раз и является авто-инкрементным.
Добавил в эту таблицу строку с данными из последней записи таблицы domain и всё: добавление новых записей через интерфейс модуля стал возможен. Значит кто-то ранее вносил изменения в эту таблицу.