Repository navigation
Releases: dobpilot/open-sdbl
Release list
open-sdbl 0.8.0
Релиз после 0.7.0: open-sdbl-db научился отдавать не только имена, которые нужны компилятору, но и саму конфигурацию — одним чтением, из той же read-only транзакции, что и метаданные. Изменение оформлено спецификацией OpenSpec (crate-architecture, onec-metadata, access-rights).
Зачем
Потребителю, которому нужны ресурсы конфигурации, приходилось читать Config второй раз — уже после закрытия сеанса, против базы, о которой он больше ничего не знает. Между двумя чтениями конфигурацию могли обновить, расширение включить, ресурс переписать, и ничто в результате об этом бы не сказало.
Согласованное получение конфигурации
use open_sdbl_db::{DatabaseSession, Limits, NoProgress};
let mut session =
DatabaseSession::connect(&connection, &credentials, Limits::default()).await?;
let configuration = session.configuration(&mut NoProgress).await?;
// Снимок и отчёт — те же, что вернул бы `metadata()`.
let snapshot = &configuration.metadata;
// Каждый ресурс таблицы `Config`, собранный из всех `PartNo`, байтами как
// их хранит база: сырой DEFLATE, без распаковки и перекодирования.
for resource in &configuration.config_resources {
let _ = (&resource.file_name, &resource.compressed);
}
// Расширения в порядке применения платформой, каждое со своими ресурсами.
for extension in &configuration.extensions {
if extension.active == Some(false) {
continue;
}
let _ = (&extension.identity, &extension.name, extension.order, &extension.resources);
}AcquiredConfiguration несёт metadata, report, layout, config_resources и extensions; AcquiredExtension — identity, name, active, order, resources. Операция есть и на DatabaseSession, и на обеих сессиях провайдеров, и как свободная acquire_configuration над MetadataSource.
Что операция обещает и чего не обещает
Второго конвейера метаданных и второго пути к СУБД нет: acquire_metadata стала обёрткой над одним внутренним получением, план различается ровно одним шагом. Возвращаются те самые ресурсы, из которых разрешён снимок, — конфигурация читается один раз, а не дважды.
Это не атомарный снимок базы. Транзакция идёт на READ COMMITTED: каждый оператор видит зафиксированное на момент своего начала, и запись в базу во время чтения может развести соседние операторы. Поднять изоляцию бесплатно нельзя — у SQL Server нет MVCC-уровня без ALLOW_SNAPSHOT_ISOLATION, настройки базы, которой библиотека не вправе требовать, а блокирующие уровни заставили бы read-only инструмент блокировать писателей. Поэтому сужен контракт, а не поднята изоляция: операция убирает второе чтение после закрытия сеанса, а узнать, сдвинулась ли конфигурация, можно сравнением CONFIG_FINGERPRINT до и после. Результат публикуется только после успешного завершения всего чтения; любая ошибка откатывает транзакцию и не отдаёт частичный результат.
Расширения
Ресурсы группируются по корневому индексу каждого расширения, а не по имени в content-addressed ConfigCAS, поэтому одинаковые имена в двух расширениях не сливаются. Идентичность — _IDRRef в hex, переживает переименование; порядок — _ExtensionOrder.
Признак применяемости измерен, а не угадан: на базе с двумя расширениями, одинаковыми во всём, кроме того, что платформа применяет одно и не применяет другое, записи по 177 байт различаются в корневом ключе, одном символе синонима и байте на три от конца — 0x82 у применяемого, 0x81 у остального. Оба блоба легли фикстурами.
active — Option<bool>. Разбор _ExtensionZippedInfo знает свои теги и останавливается на любом другом, а флаг принимается, только если разбор дошёл до терминатора и прошёл этот байт именно как односложный тег, а не как payload неизвестного счётного поля. Иначе активность неизвестна: сообщить false про расширение, которое база применяет, значило бы заставить потребителя пропустить живой код.
Пределы и расход памяти
ConfigResource::compressed — Arc<[u8]>: общая строка хранилища и партии декодера стоят ссылку, а не копию конфигурации. В Limits добавлены config_resource_limit (1 000 000) и config_retained_byte_limit (2 ГиБ). Потолки применяются к каждому собираемому хранилищу по отдельности — сначала Config, затем самостоятельно ConfigCAS, — и оба набора удерживаются одновременно, поэтому пик равен потолку столько раз, сколько хранилищ собирается. Totals проверяются до первой строки ресурсов, а потолок повторно — по фактически пришедшему, поскольку totals это отдельный оператор и может устареть. При превышении возвращается типизированная DbError, а не OOM.
Прочее
DatabaseSession::metadataне изменился: та же сигнатура, тот же результат, та же цена — по-прежнему поток с фильтром, ничего не удерживающий.- Новые SELECT-only выражения
CONFIG_ALL,CONFIG_ALL_LEGACY,CONFIG_ALL_TOTALSу обоих провайдеров, в обоих вариантах раскладки;EXTENSIONSтеперь отдаёт идентичность и порядок рядом с именем. open_sdbl::metadata::is_config_metadata_resourceзадаёт фильтр имён ресурсов один раз — тот же, что кодируют выражения обоих провайдеров.InfoBaseUser::can_authenticate()— владелец правила «есть ли у пользователя способ войти»: стандартная аутентификация или непустой логин ОС. Ни список выбора, ниAdmRole, ни роли на ответ не влияют;AdmRole— право, а не способ входа.
Новых production-зависимостей не добавлено. cargo tree -p open-sdbl -e normal по-прежнему пуст: ядро остаётся без зависимостей и без I/O.
open-sdbl 0.7.0
Релиз после 0.6.0: слой работы с СУБД вынесен из консоли в отдельную библиотеку open-sdbl-db. Это перенос, а не переписывание — поведение консоли не изменилось ни в одном месте: те же коды возврата, те же сообщения об ошибках, тот же вывод \users, \roles, \role, \rls, \as, \restrict, \session, \d. Изменение оформлено спецификацией OpenSpec (crate-architecture).
Зачем
Подключение в проверенной read-only транзакции, чтение метаданных, права ролей, разворачивание RLS-ограничений пользователя и декодирование ячеек результата жили в crates/open-sdbl-cli/src под pub(crate) и были доступны только консоли. Это security-логика: копировать её во второе приложение — значит получить две копии, которые разойдутся. Поэтому она стала библиотекой, а консоль — её первым потребителем.
Три крейта
open-sdbl(корень) — без изменений: ноль production-зависимостей,#![forbid(unsafe_code)], никакого I/O. Декодирует переданные байты и генерирует SQL.open-sdbl-db(новый) — I/O СУБД и сети: оба драйвера (tokio-postgres, Tiberius), конвейер чтения метаданных, транспорт SOCKS5, ячейки результата,AccessStoreс выводом ограничений пользователя,RestrictionStore, кеш параметров сеанса БСП и индекс ролей расширений конфигурации. Ничего не печатает, не разбирает командную строку, не читает переменные окружения и файл паролей.open-sdbl-cli— процесс, терминал и файловая система: разбор аргументов, REPL, форматирование вывода, отрисовка прогресса,~/.pgpassи работа с секретами.
Публичный API библиотеки
use open_sdbl_db::{DatabaseSession, Limits, NoProgress};
let mut session =
DatabaseSession::connect(&connection, &credentials, Limits::default()).await?;
let (snapshot, report) = session.metadata(&mut NoProgress).await?;
let rows = session.query(&sql, columns).await?;
session.close().await?;Доступны DatabaseSession, DatabaseDialect, QueryCancellation, MetadataSource, acquire_metadata, AccessStore, role_restrictions, user_restrictions, derive_restrictions, RestrictionStore, read_current_user, read_template_parameters, ExtensionIndex, read_extension_index, read_extension_roles, Cell, QueryRows, декодеры ячеек обоих диалектов, DbError, типы описания подключения, Credentials и трейт прогресса. Всё публичное документировано по-английски; cargo doc проходит с -D warnings.
Где проведена граница
DbError— ошибки СУБД с предикатамиis_database_timeout,is_mssql_connection_failure,requires_mssql_disconnect.CliErrorполучил вариантDb(DbError)иFrom, коды возврата и тексты сообщений сохранены до байта.- Отчёт резолвера не печатается библиотекой:
acquire_metadataвозвращает(snapshot, layout, report), печатает вызывающий — в том же месте последовательности, что и раньше. - Прогресс — трейт
MetadataProgressс пустыми телами по умолчанию и готовой реализациейNoProgress. Терминальная отрисовка осталась в консоли. - Описание подключения и носитель секрета — обычные типы библиотеки. Чтение
PGPASSWORD/MSSQL_PASSWORD/SOCKS5_PASSWORDиPGPASSFILE/~/.pgpass, вместе с проверкой владельца и прав файла, осталось в консоли: она отдаёт библиотеке уже готовый секрет в зачищаемой памяти. - Параметры сеанса: библиотечные функции принимают
&SessionParameters. Команды\users…\as, которые пишут в стор параметров REPL, остались в консоли. Limits— одна структура вместо четырёх констант: таймаут соединения, таймаут запроса, таймаут закрытия PostgreSQL и размер пакета декодирования Config.Defaultдаёт ровно прежние значения (10 с, 120 с, 5 с, 256), сессия применяет то, с чем открыта, внешний потребитель задаёт своё.
Чего нет
Фич postgres/mssql для отключения ненужного драйвера в этом релизе нет: они потребовали бы #[cfg] на вариантах DatabaseSession, DatabaseDialect, DbError и примерно на двадцати ветвях match, то есть переписывания того самого кода, который переносится без изменений. Обоснование — в openspec/changes/archive/2026-09-20-extract-database-crate/design.md.
Новых production-зависимостей не добавлено: все зависимости нового крейта переехали из манифеста консоли. cargo tree -p open-sdbl -e normal по-прежнему пуст.
open-sdbl 0.6.0
Релиз после 0.5.5: чтение прав доступа доведено до рабочего состояния на трёх типовых базах — УНФ, «Документооборот» (PostgreSQL и MS SQL Server). Каждое изменение поведения — со своей спецификацией OpenSpec.
Ограничения доступа применяются к запросам
\as <пользователь> теперь не только запоминает пользователя, а разворачивает ограничения его ролей на Чтение и кладёт их в тот же список, что и \restrict, — по строке на объект, на языке 1С:
open-sdbl=> \as Петрова (бухгалтер)
Current user: Петрова (бухгалтер) (640 roles): …
7 session parameters read from the base: ВерсииШаблоновОграниченияДоступа, …
375 restrictions derived into \restrict.
Петрова (бухгалтер)=>
Набранное руками \restrict перекрывает развёрнутое и никогда не затирается; \as clear и \refresh забывают развёрнутые, \session разворачивает их заново. Приглашение консоли называет текущего пользователя.
Параметры сеанса берутся из базы
\as читает то, что база хранит для своих шаблонов: регистр сведений ПараметрыОграниченияДоступа (на MS SQL Server значение лежит в колонке, на PostgreSQL — ссылкой STORHDR на части в binarydata), элемент Справочник.Пользователи по идентификатору пользователя ИБ как ТекущийПользователь и пустую ссылку ВнешниеПользователи. Заданное руками не перетирается; если регистр есть, а прочитать его не удалось — названа причина.
Шаблоны ограничений
parse_templateразбирает текст ограничения или тело шаблона в узлыTemplateNode— текст,#Еслис ветвями, вызовы с аргументами,#Параметр(N)и прочие имена — со смещением каждого узла; несбалансированные директивы дают ошибку с позицией.- Директивы по документации 5.5.4.8.7:
#ТекущаяТаблица(имя таблицы),#ИмяТекущейТаблицы(оно же строковым значением, в кавычках),##как один#, вызов шаблона без скобок. - Полная форма платформы: описание таблицы после
ИЗи соединенияЛЕВОЕ/ВНУТРЕННЕЕпередГДЕ. Соединения компилируются в коррелированный предикат со строкой-якорем(VALUES (1)), поэтому не размножают строки ограничиваемой таблицы. - Консоль показывает шаблоны:
\role— сигнатуры,\template <роль> [<имя>]— тело, из чего оно состоит и разбирается ли.
Роли расширений
Роль, которой нет в Config, ищется в расширениях: _ExtensionsInfo хранит ключ корневого ресурса, корень — индекс имя → ключ, ConfigCas адресует ресурсы по ключу. Читаются и права (<guid>.0), и описатель (<guid>), поэтому роль расширения называется и ограничивает. Роль, которой нет нигде, ничего не даёт и названа в отчёте, а не валит команду.
Консоль
\usersи\userпоказывают e-mail (v8users.Email, с проверкой наличия колонки).\rlsбез аргументов — список ограничений в прочитанных правах: роль, объект, право.- Команды доступа добавлены в автодополнение.
Производительность
Поиск без учёта регистра при разворачивании сворачивал текст на каждое вхождение: одно разворачивание шаблона БСП стоило 0.63 с. Теперь текст сворачивается один раз на поиск — \as для пользователя с 640 ролями и 470 ограниченными объектами занимает 2 с вместо 5 минут, и настолько же быстрее любой запрос к ограниченной таблице.
Совместимость
ExpandedRestrictionполучил полеjoins;RestrictionError— вариантSyntaxAt { message, offset }(перечисление#[non_exhaustive]).- Новое в API:
parse_template,TemplateNode,TemplateBranch,RestrictionTemplate::new,parse_serialized_sequence,ContentKey,extension_root_key,parse_extension_index,StoredValueRef,decode_stored_value,RoleCatalog::extend,InfoBaseUser::email. #ИмяТекущейТаблицытеперь подставляется в кавычках, как описывает документация платформы.
open-sdbl 0.5.5
Релиз после 0.4.0: регистры бухгалтерии, широкие корпуса двух типовых конфигураций и чтение прав доступа прямо из базы. Каждое изменение поведения — со своей спецификацией OpenSpec.
Регистры бухгалтерии
Виртуальные таблицы РегистрБухгалтерии: Остатки, Обороты, ОстаткиИОбороты, ДвиженияССубконто, ОборотыДтКт. Субконто как аргумент и как поля Субконто1…/СубконтоДт/СубконтоКт, корреспонденция (КорСчет, <Измерение>Кор, КорСубконто), развёрнутые остатки (РазвернутыйОстатокДт/Кт, начальные и конечные), периодичности Регистратор и Запись, Порядок/Первые у движений с субконто, метки составных членов Имя_TYPE. Разыменование через многотипную ссылку в выражениях (Регистратор.Организация = &Орг).
Язык запросов
ИЗ &Таблица— таблицы-параметры с типизированными колонками, встроенные как CTESELECT 1, … UNION ALL …; в консоли литералТАБЛИЦА(Код КАК СТРОКА, …)((…), …).- Безымянное разыменование получает платформенное имя слитно:
Д.Организация.Наименование→ОрганизацияНаименование; ключевое слово послеКАК— псевдоним (КАК Конец). Псевдоним.*среди других полей и в соединениях;РАЗЛИЧНЫЕс сортировкой по спроецированной ссылке; вложенное объединение сПЕРВЫЕв каждой ветке;ССЫЛКАнадВЫРАЗИТЬ; разнотипныйВЫБОРв сравнении; псевдоним подзапроса затеняет внешний;МАКСИМУМ(Регистратор)остаётся runtime-typed; член объединения узнаётся по запрошенному имени и при обрезке метки до лимита PostgreSQL.АВТОУПОРЯДОЧИВАНИЕ,АВТОНОМЕРЗАПИСИ(), соединения без якорного равенства,ПОЛНОЕс прежним правилом.
Корпуса
Бухгалтерия предприятия 3.0 — 613 из 622, УНФ — 674 из 688 запросов модулей и схем компоновки, включая широкую выборку по 200 запросов без регистров на каждую базу. Инструменты корпуса привязывают даты и таблицы-заготовки, а виды колонок заготовок берут из метаданных фикстуры (bind_tables.py --kinds, выгрузка dump_field_kinds).
Права доступа (новая capability access-rights)
- Роли и права читаются из записей
Config(<guid>и<guid>.0): права на объекты и их члены, ограничения на уровне записей с полями, шаблоны, флаги.Rightназывает стандартные права; таблица гвидов выведена из самой базы и подтверждена ролями-одиночками БСП на 8.3.27. Незаписанное право следует умолчаниюsetForNewObjects. - Пользователи ИБ —
v8users, колонкаData(XOR + скобочная запись) даёт имя, полное имя и роли; хеши паролей не отдаются. - Разворачивание ограничений (
open_sdbl::access): шаблоны БСП с#Параметр(N),#Если/#ИначеЕсли/#Иначе/#КонецЕслипо параметрам сеанса,СтрСодержит,Значение(…ПустаяСсылка); результат — полная форма платформыТекущаяТаблица [КАК Т] ГДЕ …, которую принимает компилятор, в том числеТекущаяТаблица.Полево вложенных запросах условия.read_accessобъединяет роли пользователя.
CLI
\users, \user, \roles, \role, \rls, \as: пользователи, роли, права и ограничения, а ВЫБРАТЬ РАЗРЕШЕННЫЕ от имени пользователя получает ограничения его ролей на «Чтение». Проверено на демо-базе УНФ вплоть до исполнения запроса через ветвь ключей доступа шаблона ДляОбъекта. Нечитаемые ресурсы Config (двоичные .7) пропускаются с предупреждением, а не срывают чтение метаданных.
open-sdbl 0.4.0
Первый публичный релиз с момента 0.3.6: 62 промежуточные версии, 72 изменения поведения, каждое — со своей спецификацией OpenSpec и сверкой с платформой 1С.
Язык запросов
Корпус реальных запросов демо-конфигурации компилируется на 377 из 381 — остальные четыре отказа платформа разделяет либо они защищают от заведомо неверного ответа.
- Табличная часть как колонка выборки.
Д.Товары,Д.Товары.(Поле, …)иД.Товары.*возвращаются вложенным результатом: главный оператор плюс по одному вложенному на секцию, со структурной связью по ссылке владельца. Замерено, что платформа отвечает так же — через временную таблицу ключей. ПОЛНОЕ СОЕДИНЕНИЕ→ нативныйFULL JOIN: снят запрет на цепочку, агрегаты и группировку, разыменование вПОвыносится внутрь своей стороны.- Элемент списка через запятую присоединяется целиком — прежний плоский рендер давал неверный ответ для внешних соединений внутри элемента.
- Разыменование любой глубины, в том числе через составные ссылки; цели берутся из описания типа в
Config, категории ссылок — из платформенных констант. ИТОГИ … ПО(включаяОБЩИЕ,ИЕРАРХИЯ,ТОЛЬКО ИЕРАРХИЯ), виртуальные таблицы регистров (срезы, остатки, обороты,ОстаткиИОборотыс периодичностью), журналы документов, критерии отбора,КонстантыиКонстанта.<Имя>.- Условие по колонке табличной части компилируется в коррелированный
EXISTS;В ИЕРАРХИИпринимает составную ссылку;ПРЕДСТАВЛЕНИЕберётся от агрегата и отВЫБОРс разнотипными ветвями. - Функции дат и строк,
ТИП/ТИПЗНАЧЕНИЯ/НЕОПРЕДЕЛЕНО,ССЫЛКА,МЕЖДУ,ВЫРАЗИТЬ, параметры запроса и сеанса, разделители данных, ограничения доступаРАЗРЕШЕННЫЕ, временные таблицы.
Публичный API
CompiledQuery помечен #[non_exhaustive] и получил nested — вложенные результаты табличных частей со связью, описанной данными, а не текстом SQL, — и service_columns. Добавлен тип NestedResult. Генерируемый PostgreSQL рассчитан на версию 13 и новее.
CLI
Сессия MSSQL больше не опрашивает сервер перед чтением: права учётной записи и уровень изоляции — решение администратора, а компилятор порождает только SELECT. Read-only application intent, транзакция вокруг чтения и её откат сохранены.
Приложение разобрано по модулям: точка входа, контроллер команд, фасад сессии, консоль из восьми модулей и по три модуля на провайдера. Тесты вынесены в отдельный каталог.
Проверки
Три независимые сети: голдены компиляции, 256 проб против живой платформы 8.3.27 (расхождений нет) и исполнение всего корпуса на настоящей базе PostgreSQL. CI собирает релиз, выкладывает архив исходников и исполняемый файл для Windows MSVC.