Documentation
¶
Overview ¶
Package nameformdb — общий двигатель пробы «ограничение формы имени ДЕЙСТВУЕТ на живой базе».
Предмет ¶
Ограничение формы имени стоит в схемах, принявших канон #715. «Миграция применилась» и «ограничение отвергает негодную строку» — РАЗНЫЕ утверждения, и до задачи #721 проверялось только первое: перепись пробы, доказывающей второе, давала один сервис из пяти.
Ни число схем, ни имя миграции здесь НЕ выписываются, и это не небрежность. Прежняя редакция называла `715001_resource_name_single_form.sql` и «пять схем»: первое перестало быть верным, когда цепь iam была сведена в одну первичную миграцию (форма стоит в ней), второе — потому что состав пятёрки сменился, а её размер совпал случайно, geo форму снял, iam её принял. Число, пережившее свой предикат, читается как измеренное. Действующий состав печатает переписью гейт `TestNameFormConstraintIsProvenWhereItIsDeclared` на каждом прогоне.
Ограничение базы — последний рубеж канона: код может смениться, вызывающий может пойти мимо слоя домена, но оператор базы отвергнет негодную строку всегда. Ровно поэтому его действие обязано быть ДОКАЗАНО вставкой, а не выведено из того, что файл миграции лежит в дереве.
Почему двигатель общий, а не скопирован в четыре пакета ¶
Копия расходится с оригиналом молча и расходится там, где расхождение не видно, — на составе утверждений. Своего у сервиса ровно одно: как выглядит МИНИМАЛЬНАЯ ЗАКОННАЯ СТРОКА его таблицы. Перечень проверяемых значений, чтение отказа и перепись — одно на всех.
Что проба утверждает ¶
- ПЕРЕПИСЬ. Перечень таблиц схемы, несущих форму имени, совпадает с перечнем, который проба обходит. Таблица, получившая форму позже, и таблица, её потерявшая, — обе находка, а не тишина.
- ОТРИЦАНИЕ. Имя вне канона отвергается — и отвергается ИМЕННО формой: сверяется не только SQLSTATE 23514, но и имя ограничения, назвавшего отказ. Без второго условия проба зеленела бы на отказе любого соседнего ограничения той же таблицы.
- ПОЛОЖИТЕЛЬНЫЙ КОНТРОЛЬ. Каноничное имя вставляется УСПЕШНО. Без него отрицание зеленеет на любой поломке фикстуры: строка, отвергнутая по совершенно другой причине, выглядит как сработавшая защита.
Пункт 3 несёт отдельную ценность, названную самой миграцией: прежние формы требовали БУКВУ первым символом, канон допускает цифру. Поэтому среди принимаемых значений стоит имя, начинающееся с цифры: возврат к прежней форме покраснит пробу, тогда как одно отрицание его бы не заметило.
Почему исход, а не сразу падение ¶
Probe.Check возвращает ОТЧЁТ, а падение производит Probe.Run. Так способность пробы упасть доказуема инъекцией: проба сноса ограничения зовёт Check и утверждает, что находка появилась и назвала координату, — а рядом законный близнец той же формы, на котором находок ноль. Проверка, которая умеет только звать t.Fatal, о себе самой ничего доказать не может.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Execer ¶
type Execer interface {
Exec(ctx context.Context, sql string, args ...any) (pgconn.CommandTag, error)
Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
}
Execer — та часть пула, которой пользуется двигатель. Интерфейс, а не *pgxpool.Pool, чтобы пакет не тянул за собой конструкцию пула вызывающего.
type Probe ¶
type Probe struct {
Schema string
Tables []Table
Excluded map[string]string
// OtherForm — таблицы схемы, которые несут форму имени НАМЕРЕННО ДРУГУЮ,
// чем канон; значение — причина. Отличается от Excluded по существу:
// исключённая таблица формы не несёт ВОВСЕ, а эта несёт СВОЮ, и та форма
// действует.
//
// Категория заведена схемой iam, где рядом с шестью именуемыми ресурсами
// живёт идентификатор роли (`roles/vpc.admin`): он не косметическая метка,
// а то, на что ссылаются привязки, и формой имени не судится — записанное
// решение владельца (#715). Без третьей категории такую таблицу пришлось бы
// либо привести к канону (сломав ссылки), либо объявить исключением
// (соврав: форму она несёт).
//
// Перечень проверяется в ОБЕ стороны: запись, чья таблица формы не несёт
// вовсе, и запись, чья таблица пришла К КАНОНУ, — обе находка. Так
// послабление истекает само, а не переживает свой предмет.
OtherForm map[string]string
}
Probe — то, что объявляет вызывающий: схема, таблицы и намеренные исключения.
Excluded — таблицы схемы, которые несут столбец имени и которым форма НЕ ставится ОСОЗНАННО; значение — причина. Перечень проверяется в обе стороны: исключение, которому больше нечего исключать (форму поставили), — находка, а не молчание. Так послабление истекает само, а не переживает свой предмет.
func (Probe) Check ¶
Check исполняет пробу и возвращает отчёт. Ошибку возвращает только тогда, когда прочитать схему не удалось вовсе, — то есть когда отчёт был бы не «находок нет», а «ничего не прочитано».
func (Probe) Run ¶
Run исполняет пробу и роняет прогон на каждой находке, печатая перепись.
Перепись и уже найденное печатаются ДО вердикта и на ЛЮБОМ исходе — включая отказ чтения схемы. Прежняя редакция роняла прогон сразу и теряла оба: расхождения образцов с каноном находятся ДО обращения к базе, и молчание о них посылало читателя чинить соединение там, где разошёлся перечень значений. Ложного зелёного здесь не было — терялась диагностика, а она и есть то, ради чего пробу читают.
type Report ¶
type Report struct {
Schema string
// Probed — таблицы, которые обошла проба.
Probed []string
// CarriedInDB — таблицы схемы, реально несущие форму имени.
CarriedInDB []string
// BareInDB — таблицы схемы со столбцом имени и БЕЗ формы.
BareInDB []string
// Excluded — объявленные намеренные исключения.
Excluded []string
// OtherForm — таблицы, объявленные несущими намеренно иную форму.
OtherForm []string
// OtherFormWhy — причина по каждой такой таблице.
OtherFormWhy map[string]string
// ExcludedWhy — причина по каждому исключению. Поле читается переписью и
// печатается: причина, которую никто не читает, — то же «принято и
// проигнорировано», только в оснастке.
ExcludedWhy map[string]string
// RejectedPerTable / AcceptedPerTable — сколько значений проверено на таблицу.
RejectedPerTable int
AcceptedPerTable int
// Findings — находки. Пусто = ограничение действует всюду, где объявлено.
Findings []string
}
Report — исход прогона: объём осмотренного и перечень находок.
Объём печатается ВСЕГДА, в том числе при нуле находок: иначе «находок нет» неотличимо от «ничего не прочитано».
type Table ¶
Table — таблица под пробой и способ собрать для неё МИНИМАЛЬНУЮ ЗАКОННУЮ строку с заданным именем.
Row обязан вернуть INSERT, отвергаемый ТОЛЬКО формой имени: все прочие ограничения таблицы (перечисления состояний, диапазоны, внешние ключи, уникальность, учёт числа ресурсов) он обязан удовлетворять. Иначе положительный контроль перестанет быть контролем — он будет падать по чужой причине.
seq различает строки одного прогона: у большинства таблиц уникальны и ключ, и пара «проект, имя», а у слушателя nlb — ещё и тройка «балансировщик, порт, протокол».