Skip to content

Запрос к регистру сведений: ссылочное измерение — строкой-наименованием, ресурс — Неопределено, СрезПоследних со ссылочным ресурсом не компилируется #1920

Description

@AnnaSIceberg

Что происходит

Запрос к регистру сведений неверно отдаёт ссылочные поля регистра.

  1. Обычный запрос (ВЫБРАТЬ … ИЗ РегистрСведений.X):

    • ссылочное измерение приходит строкой с наименованием (Строка, «МСК»), а не ссылкой;
    • ссылочный ресурс приходит Неопределено, хотя в записи он заполнен.

    По контракту ТипЗнч на колонке результата запроса отдаёт «Строка», а не ссылочный тип #1150 (wrapRefColumns) ссылочная колонка результата должна быть СправочникСсылка.X.

  2. СрезПоследних со ссылочным ресурсом не выполняется: no such column: реклама. В сгенерированном SQL ресурс назван реклама, а колонка в таблице — реклама_id; измерение при этом развёрнуто как филиал_id AS филиал.

  3. onebase check, который исполняет запросы модулей, падает на таком модуле той же ошибкой. Проверку конфигурации не пройти, хотя запрос написан корректно.

РегистрыСведений.X.СоздатьНаборЗаписей() + Отбор + Прочитать() по тому же регистру отдаёт настоящие ссылки (СправочникСсылка.Филиал) и дату периода. Сломан именно путь Запрос.

Воспроизведение

Upstream main 66a9a104, SQLite, Windows. Минимальный проект:

catalogs/филиал.yaml и catalogs/реклама.yaml — по одному полю Наименование: string.

inforegs/номерарекламы.yaml:

name: НомераРекламы
periodic: true
dimensions:
  - name: НомерТелефона
    type: string
  - name: Филиал
    type: reference:Филиал
resources:
  - name: Реклама
    type: reference:Реклама

processors/ПробаРегистра.yaml — kind: test, модуль src/пробарегистра.proc.os:

Процедура Выполнить()
    Ф = Справочники.Филиал.Создать();
    Ф.Наименование = "МСК";
    СсылкаФ = Ф.Записать();
    Р = Справочники.Реклама.Создать();
    Р.Наименование = "Тест";
    СсылкаР = Р.Записать();
    З = РегистрыСведений.НомераРекламы.СоздатьМенеджерЗаписи();
    З.Период = ДобавитьДень(ТекущаяДата(), -1);
    З.НомерТелефона = "4951983100";
    З.Филиал = СсылкаФ;
    З.Реклама = СсылкаР;
    З.Записать();

    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ Филиал, Реклама ИЗ РегистрСведений.НомераРекламы ГДЕ НомерТелефона = &Н";
    Запрос.УстановитьПараметр("Н", "4951983100");
    Для Каждого С Из Запрос.Выполнить() Цикл
        Утверждать.Равно(Строка(ТипЗнч(С.Филиал)), "СправочникСсылка.Филиал", "запрос: тип измерения Филиал");
        Утверждать.Равно(Строка(ТипЗнч(С.Реклама)), "СправочникСсылка.Реклама", "запрос: тип ресурса Реклама");
        Утверждать.Равно(С.Филиал, СсылкаФ, "запрос: измерение Филиал = записанная ссылка");
    КонецЦикла;

    Запрос.Текст = "ВЫБРАТЬ Филиал, Реклама ИЗ РегистрСведений.НомераРекламы.СрезПоследних(&НаДату) ГДЕ НомерТелефона = &Н";
    Запрос.УстановитьПараметр("НаДату", ТекущаяДатаВремя());
    Для Каждого С Из Запрос.Выполнить() Цикл
        Утверждать.Равно(С.Реклама, СсылкаР, "СрезПоследних: ресурс Реклама = записанная ссылка");
    КонецЦикла;

    Набор = РегистрыСведений.НомераРекламы.СоздатьНаборЗаписей();
    Набор.Отбор.НомерТелефона = "4951983100";
    Набор.Прочитать();
    Утверждать.Равно(Строка(ТипЗнч(Набор.Получить(0).Филиал)), "СправочникСсылка.Филиал", "набор записей: тип измерения Филиал");
КонецПроцедуры
onebase migrate --project . --sqlite repro.db
onebase test    --project . --sqlite repro.db

Фактически

▶ ПробаРегистра
  ПРОВАЛ — запрос: тип измерения Филиал (ожидалось «СправочникСсылка.Филиал», получено «Строка»)
  ПРОВАЛ — запрос: тип ресурса Реклама (ожидалось «СправочникСсылка.Реклама», получено «Неопределено»)
  ПРОВАЛ — запрос: измерение Филиал = записанная ссылка (ожидалось «МСК», получено «МСК»)
  ОШИБКА — src\пробарегистра.proc.os:28: Ошибка выполнения SQL: run query: SQL logic error: no such column: реклама (1)
SQL: SELECT ref_филиал.наименование AS филиал, реклама FROM (SELECT period, номертелефона, филиал, реклама FROM (SELECT period, номертелефона, филиал_id AS филиал, реклама, ROW_NUMBER() OVER (PARTITION BY номертелефона, филиал_id ORDER BY period DESC) AS _rn FROM инфо_номерарекламы AS _t WHERE period <= ?) _w WHERE _rn = 1) AS срезпоследних_номерарекламы LEFT JOIN филиал ref_филиал ON ref_филиал.id = срезпоследних_номерарекламы.филиал WHERE COALESCE(номертелефона, '') = ?

onebase check --project .:

src/пробарегистра.proc.os:26:20: [Запрос модуля (исполнение)] [dsl.syntax] SQL logic error: no such column: реклама (1)
Найдено ошибок: 1

Строка «ожидалось «МСК», получено «МСК»» — то же самое с другой стороны: значение из запроса — строка-наименование, сравнение со ссылкой ложно.

Ожидаемое

Где это мешает

Конфигурация cc2: входящему звонку подставляются филиал и реклама по номеру линии из периодического регистра сведений. Через Запрос этого не сделать: присвоение реквизиту документа даёт «несоответствие типов… передано значение типа «Строка»», а поиск ссылки по наименованию неоднозначен — у реклам и филиалов бывают одинаковые имена. Пока обходим набором записей (СоздатьНаборЗаписей + Отбор + Прочитать).

Реализацию готов взять контрибутором (@AnnaSIceberg) Draft PR от свежего main, если сопровождающий решит так.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    approvedИван одобрил: можно делать фикс/PRbugSomething isn't workingdecision:1Решение человека: делаем вариант 1 из разбора триажаqueue:p0Manual queue priority P0 (highest)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions