При разработке и активном сопровождении мобильных приложений на платформе 1С:Предприятие разработчики часто сталкиваются со специфическим поведением локальной СУБД SQLite. Одной из наиболее неприятных проблем является сбой реструктуризации базы данных при изменении метаданных. Типичный сценарий: в регистр сведений, который включен в состав плана обмена, добавляется новое измерение. После обновления конфигурации и попытке записи в этот регистр система аварийно завершает работу с сообщением:
«Ошибка SDBL: Таблица или поле (Fld336) не содержится в разделе FROM»
В этой статье мы подробно разберем, почему возникает этот сбой, проанализируем внутренние механизмы платформы и рассмотрим несколько практических способов решения проблемы — от простых "костылей" до системных подходов.
Для того чтобы понять природу ошибки, заглянем "под капот" платформы 1С. Аббревиатура SDBL расшифровывается как Simple Data Base Layer — это промежуточный логический слой платформы, который транслирует запросы на языке 1С в физические SQL-запросы к конкретной СУБД (в случае мобильной платформы — к SQLite).
Когда объект метаданных (например, регистр сведений) включается в состав плана обмена, платформа автоматически создает в базе данных служебную таблицу для регистрации изменений. Физическое имя этой таблицы в базе данных начинается с префикса _InfoRgChngR (для регистров сведений). Эта таблица содержит ключевые поля (измерения) регистра, по которым фиксируются изменения для каждого узла обмена.
При добавлении нового измерения в регистр сведений платформа обязана выполнить реструктуризацию двух физических таблиц в файле базы данных SQLite мобильного устройства:
_InfoRg)._InfoRgChngR).В устаревших или проблемных релизах мобильной платформы (особенно ярко это выражено в ветке 8.3.15, например 8.3.15.62) механизм реструктуризации таблиц регистрации изменений в СУБД SQLite работает некорректно. Платформа успешно добавляет новое поле (например, _Fld336) в основную таблицу регистра, но "забывает" или некорректно добавляет его в таблицу регистрации изменений _InfoRgChngR.
В итоге возникает рассинхронизация: транслятор SDBL на логическом уровне "знает", что у регистра появилось новое измерение, и пытается построить SQL-запрос к таблице изменений с участием этого поля. Но физически в таблице SQLite этого поля нет. СУБД SQLite возвращает ошибку, которую SDBL транслирует разработчику в виде сообщения: «Таблица или поле не содержится в разделе FROM».
Подобные баги реструктуризации периодически возникают не только на мобильной, но и на десктопной платформе (например, известные баги платформы версий 8.3.24 / 8.3.25 при работе с расширениями и планами обмена).
---
Если конфигурация уже находится на "живых" устройствах пользователей, и вам критически важно избежать их принудительного перезапуска или полной переустановки приложения, можно применить надежный обходной путь. Мы создаем новый регистр вместо модификации старого. Рассмотрим этот процесс по шагам:
РегистрНоменклатура.РегистрНоменклатура_Новый.РегистрНоменклатура_Новый в состав нужного плана обмена.РегистрНоменклатура_Устарел и снимем с него признак участия в плане обмена.РегистрНоменклатура_Новый и таблицы регистрации изменений для него. Поскольку реструктуризации "на лету" для новой таблицы не требуется, она создается с нуля в корректном виде, и ошибка SDBL не возникнет.Этот костыль хорош тем, что он на 100% гарантирует бесконфликтное обновление у конечных пользователей без необходимости очистки данных.
---
Если плодить сущности в конфигурации не хочется, и вы желаете сохранить исходный регистр сведений, можно прибегнуть к двухэтапному обновлению конфигурации базы данных. Этот метод заставляет платформу полностью удалить, а затем заново создать таблицы регистрации изменений.
Разберем алгоритм действий:
_InfoRgChngR на мобильных устройствах, так как объект больше не участвует в обмене.Минус метода: Требует жесткого контроля за тем, чтобы все пользователи гарантированно установили промежуточное обновление (Этап 1) перед тем, как получат финальное (Этап 2).
---
Иногда реструктуризация в SQLite проходит успешно, если сама таблица регистрации изменений на мобильном устройстве абсолютно пуста. Если в ней есть записи, SDBL пытается выполнить сложный перенос данных, на котором и спотыкается.
Мы можем попытаться программно очистить регистрацию перед тем, как обновить конфигурацию. Для этого на мобильном клиенте перед синхронизацией и загрузкой новой конфигурации можно выполнить следующий код:
// Выбираем узел, для которого зарегистрированы изменения
УзелОбмена = ПланыОбмена.ГлавныйУзел();
Если ЗначениеЗаполнено(УзелОбмена) Тогда
// Полностью очищаем регистрацию изменений для нашего регистра
ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, Метаданные.РегистрыСведений.РегистрНоменклатура);
КонецЕсли;
После очистки таблицы изменений закроем приложение и выполним обновление конфигурации. Пустая таблица реструктуризируется значительно легче и с меньшей вероятностью вызовет ошибку SDBL.
---
Самый простой, но радикальный метод — полная переустановка мобильного приложения на устройствах пользователей (или очистка данных приложения через настройки Android/iOS). При этом база данных SQLite создается заново с актуальной структурой "из коробки".
Важное предупреждение: Этот метод категорически не рекомендуется использовать в продакшене, если мобильное приложение работает в режиме офлайн и хранит на устройстве уникальные данные, которые еще не были отправлены на центральный сервер. Переустановка приведет к безвозвратной потере этих данных. Также это создаст неудобства для пользователей, которым придется заново проходить авторизацию и первичную инициализацию (создание начального образа базы данных).
---
Поскольку корень проблемы кроется в ошибках конкретного релиза мобильной платформы, наиболее правильным системным решением является переход на более современные и стабильные версии платформы 1С.
Разработчиками 1С подобные ошибки реструктуризации SQLite были признаны и устранены в последующих ветках платформы. Рекомендуется поднять версию мобильной платформы до стабильных релизов веток 8.3.17, 8.3.18 или выше. При переходе на новые версии реструктуризация таблиц SQLite при добавлении измерений будет проходить в штатном автоматическом режиме без падений транслятора SDBL.