Documentation
¶
Overview ¶
Package storage — переносимое реляционное ядро на database/sql с двумя диалектами: sqlite (modernc.org/sqlite) и postgres (pgx/v5 stdlib).
Бизнес-правил не содержит: только переносимый DML, диалектные различия (DDL, открытие, пулы) и версия схемы (docs/plan/01-architecture.md §2.3).
Index ¶
- Constants
- func MaskDSN(dsn string) string
- func TableNames() []string
- type AnalogRow
- type AttrCond
- type AttrRow
- type BacklinkRow
- type ChangeEvent
- type Cond
- type Config
- type DB
- func (d *DB) Begin(ctx context.Context) (*Tx, error)
- func (d *DB) BeginReadOnly(ctx context.Context) (*Tx, error)
- func (d *DB) CatalogRevision(ctx context.Context) (int64, error)
- func (d *DB) CheckSchema(ctx context.Context) error
- func (d *DB) Close() error
- func (d *DB) CountDevices(ctx context.Context, kind domain.Kind) (int, error)
- func (d *DB) CountDevicesByKind(ctx context.Context) (map[string]int, error)
- func (d *DB) CountKinds(ctx context.Context) (int, error)
- func (d *DB) CountManufacturers(ctx context.Context) (int, error)
- func (d *DB) DialectName() string
- func (d *DB) EnsureCreated(ctx context.Context) (bool, error)
- func (d *DB) FindDevice(ctx context.Context, kind domain.Kind, designation string) (*DeviceRow, error)
- func (d *DB) FindDeviceAnyKind(ctx context.Context, designation string) (*DeviceRow, error)
- func (d *DB) FindDevicesByIDs(ctx context.Context, ids []int64) ([]*DeviceRow, error)
- func (d *DB) FindSynonymOwner(ctx context.Context, kind domain.Kind, designation string) (*SynonymOwnerRow, error)
- func (d *DB) FindTypeSiblings(ctx context.Context, bases []string) (map[string][]TypeSiblingRow, error)
- func (d *DB) ListDeviceIDsByKind(ctx context.Context, kind domain.Kind) ([]int64, error)
- func (d *DB) LoadAttributesByIDs(ctx context.Context, ids []int64) (map[int64][]AttrRow, error)
- func (d *DB) LoadAttributesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]AttrRow, error)
- func (d *DB) LoadBacklinksByIDs(ctx context.Context, ids []int64) (map[int64][]BacklinkRow, error)
- func (d *DB) LoadChangeEvents(ctx context.Context, after int64, limit int) ([]ChangeEvent, int64, error)
- func (d *DB) LoadFields(ctx context.Context, deviceID int64) ([]domain.Field, error)
- func (d *DB) LoadFieldsByIDs(ctx context.Context, ids []int64) (map[int64][]domain.Field, error)
- func (d *DB) LoadManufacturers(ctx context.Context, deviceID int64) ([]string, error)
- func (d *DB) LoadManufacturersByIDs(ctx context.Context, ids []int64) (map[int64][]string, error)
- func (d *DB) LoadOutgoingAnalogsByIDs(ctx context.Context, ids []int64) (map[int64][]AnalogRow, error)
- func (d *DB) LoadSnapshot(ctx context.Context) (*catalog.Snapshot, error)
- func (d *DB) LoadSources(ctx context.Context) ([]SourceRow, error)
- func (d *DB) LoadSynonymsByIDs(ctx context.Context, ids []int64) (map[int64][]SynonymRow, error)
- func (d *DB) LoadValuesByIDs(ctx context.Context, ids []int64) (map[int64][]ValueRow, error)
- func (d *DB) LoadValuesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]ValueRow, error)
- func (d *DB) LoadVariantsByIDs(ctx context.Context, ids []int64) (map[int64][]VariantRow, error)
- func (d *DB) Revisions(ctx context.Context) (catalog, data int64, err error)
- func (d *DB) Search(ctx context.Context, r SearchRequest) ([]SearchItemRow, int, error)
- func (d *DB) SuggestPrefix(ctx context.Context, prefix string, kind string, limit int) ([]SearchItemRow, error)
- type DeviceRow
- type DeviceSourceRef
- type DeviceSourceRow
- type Dialect
- type FieldCond
- type FilterOp
- type ParamBounds
- type ParamCond
- type ParamValue
- type ParamValueFreq
- type PoolConfig
- type SearchItemRow
- type SearchRequest
- type SortKey
- type SourceLinkRow
- type SourceRow
- type SynonymOwnerRow
- type SynonymRow
- type Tx
- func (t *Tx) BumpCatalogRevision(ctx context.Context) error
- func (t *Tx) BumpDataRevision(ctx context.Context) error
- func (t *Tx) CatalogRevision(ctx context.Context) (int64, error)
- func (t *Tx) Commit() error
- func (t *Tx) CountDevicesByKind(ctx context.Context) (map[string]int, error)
- func (t *Tx) DeleteDesignationFields(ctx context.Context, deviceID int64, names []string) error
- func (t *Tx) DeleteDevice(ctx context.Context, deviceID int64) error
- func (t *Tx) DeleteDeviceAnyKindByKey(ctx context.Context, designation string) (*DeviceRow, error)
- func (t *Tx) DeleteDeviceByKey(ctx context.Context, kind domain.Kind, designation string) (*DeviceRow, error)
- func (t *Tx) DeleteTypeGroupValues(ctx context.Context, deviceID int64, groupCode string) error
- func (t *Tx) DeleteVariants(ctx context.Context, deviceID int64) error
- func (t *Tx) FindDevice(ctx context.Context, kind domain.Kind, designation string) (*DeviceRow, error)
- func (t *Tx) FindDevicesByIDs(ctx context.Context, ids []int64) ([]*DeviceRow, error)
- func (t *Tx) FindSourceID(ctx context.Context, code string) (int64, bool, error)
- func (t *Tx) FindSynonymOwner(ctx context.Context, kind domain.Kind, designation string) (*SynonymOwnerRow, error)
- func (t *Tx) FindTypeSiblings(ctx context.Context, bases []string) (map[string][]TypeSiblingRow, error)
- func (t *Tx) InsertDesignationFields(ctx context.Context, deviceID int64, fields []domain.Field) error
- func (t *Tx) InsertDevice(ctx context.Context, kind domain.Kind, system domain.System, ...) (int64, bool, error)
- func (t *Tx) InsertIfAbsent(ctx context.Context, query string, args map[string]any) (bool, error)
- func (t *Tx) InsertIfAbsentReturningID(ctx context.Context, query string, args map[string]any) (int64, bool, error)
- func (t *Tx) InsertReturningID(ctx context.Context, query string, args map[string]any) (int64, error)
- func (t *Tx) InsertSource(ctx context.Context, r SourceRow) (int64, bool, error)
- func (t *Tx) InsertValues(ctx context.Context, deviceID int64, variantID *int64, values []ParamValue) error
- func (t *Tx) InsertVariant(ctx context.Context, deviceID int64, label string, sortOrder int) (int64, error)
- func (t *Tx) InsertVariantAttributes(ctx context.Context, variantID int64, rows []AttrRow) error
- func (t *Tx) LoadAttributes(ctx context.Context, deviceID int64) ([]AttrRow, error)
- func (t *Tx) LoadAttributesByIDs(ctx context.Context, ids []int64) (map[int64][]AttrRow, error)
- func (t *Tx) LoadAttributesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]AttrRow, error)
- func (t *Tx) LoadBacklinksByIDs(ctx context.Context, ids []int64) (map[int64][]BacklinkRow, error)
- func (t *Tx) LoadDeviceSources(ctx context.Context, deviceID int64) ([]SourceLinkRow, error)
- func (t *Tx) LoadDeviceSourcesByIDs(ctx context.Context, ids []int64) (map[int64][]DeviceSourceRow, error)
- func (t *Tx) LoadFields(ctx context.Context, deviceID int64) ([]domain.Field, error)
- func (t *Tx) LoadFieldsByIDs(ctx context.Context, ids []int64) (map[int64][]domain.Field, error)
- func (t *Tx) LoadManufacturers(ctx context.Context, deviceID int64) ([]string, error)
- func (t *Tx) LoadManufacturersByIDs(ctx context.Context, ids []int64) (map[int64][]string, error)
- func (t *Tx) LoadOutgoingAnalogs(ctx context.Context, deviceID int64) ([]AnalogRow, error)
- func (t *Tx) LoadOutgoingAnalogsByIDs(ctx context.Context, ids []int64) (map[int64][]AnalogRow, error)
- func (t *Tx) LoadSourceByCode(ctx context.Context, code string) (*SourceRow, error)
- func (t *Tx) LoadSynonyms(ctx context.Context, deviceID int64) ([]SynonymRow, error)
- func (t *Tx) LoadSynonymsByIDs(ctx context.Context, ids []int64) (map[int64][]SynonymRow, error)
- func (t *Tx) LoadValues(ctx context.Context, deviceID int64) ([]ValueRow, error)
- func (t *Tx) LoadValuesByIDs(ctx context.Context, ids []int64) (map[int64][]ValueRow, error)
- func (t *Tx) LoadValuesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]ValueRow, error)
- func (t *Tx) LoadVariantAttributesByIDs(ctx context.Context, ids []int64) (map[int64][]AttrRow, error)
- func (t *Tx) LoadVariantAttributesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]AttrRow, error)
- func (t *Tx) LoadVariants(ctx context.Context, deviceID int64) ([]VariantRow, error)
- func (t *Tx) LoadVariantsByIDs(ctx context.Context, ids []int64) (map[int64][]VariantRow, error)
- func (t *Tx) ParameterBounds(ctx context.Context, kind domain.Kind) (map[string]ParamBounds, error)
- func (t *Tx) ParameterValueFreqs(ctx context.Context, kind domain.Kind) (map[string][]ParamValueFreq, error)
- func (t *Tx) RecordChange(ctx context.Context, op string, kind domain.Kind, designation string, ...) error
- func (t *Tx) ReplaceAnalogs(ctx context.Context, deviceID int64, targets []AnalogRow) error
- func (t *Tx) ReplaceAttributes(ctx context.Context, deviceID int64, rows []AttrRow) error
- func (t *Tx) ReplaceDeviceSources(ctx context.Context, deviceID int64, refs []DeviceSourceRef) error
- func (t *Tx) ReplaceManufacturers(ctx context.Context, deviceID int64, names []string) error
- func (t *Tx) ReplaceSynonyms(ctx context.Context, deviceID int64, rows []SynonymRow) error
- func (t *Tx) Revisions(ctx context.Context) (catalog, data int64, err error)
- func (t *Tx) Rollback() error
- func (t *Tx) UpdateSource(ctx context.Context, id int64, r SourceRow) error
- func (t *Tx) WriteCatalog(ctx context.Context, in catalog.Input) error
- type TypeSiblingRow
- type ValueRow
- type VariantRow
Constants ¶
const SchemaVersion = 13
SchemaVersion — версия схемы модуля (docs/plan/02-database.md §5): любое изменение DDL ниже — с инкрементом этой константы; несовпадение с schema_meta.schema_version — отказ в работе (schema_version_mismatch), миграций нет (D5). Версия 2 — каталожные таблицы без текстовых колонок (D9: отображаемые строки — бандлы internal/i18n; коды единиц — латиница). Версия 3 — словарь материалов полупроводников (коды вместо русских названий в device_designation_fields.text_value). Версия 4 — словарь подклассов и способов подстройки (коды полей subclass/adjustment), классификационные поля секции fields и каталожный словарь категорий. Версия 5 — postgres-диалект переписывает INTEGER в BIGINT и REAL в DOUBLE PRECISION (диапазон и точность sqlite: int64 и float64; текст переносимого DML не менялся). Версия 6 — удалена таблица series_families (система обозначений series исключена: бывшие серийные записи — система other, семейство/номер/буквы — явные поля секции fields, мощность — параметр Pnom). Версия 7 — индекс device_manufacturers(manufacturer_id): адресная чистка сирот производителей проверяет «без связей» точечно, без полного анти-джойна. Версия 8 — производное поле base в device_designation_fields (тип — базовое обозначение записи без буквы классификации и хвостовых элементов): DDL не менялось, но состав строк полей записи расширился — базы прежней версии лишены поля и пересоздаются импортом (D5). Версия 9 — таблица change_events: поток изменений записей (change feed) для инкрементальной синхронизации производных индексов; события пишет та же транзакция записи, что инкрементирует data_revision. Версия 10 — таблица device_synonyms: исторические названия записи (синонимы) с заметкой и годами употребления имени; обозначение-синоним не является записью и не имеет своей карточки — find и поиск разрешают его в запись-владельца (план 03 §9). Версия 11 — колонка sort_order и составной PK (device_id, attribute_code, sort_order) таблицы device_attribute_values: атрибуты типа text_list (notes, spec, datasheetUrl) хранятся списком строк; базы прежних версий пересоздаются импортом (D5). Версия 12 — таблица device_variant_attribute_values: атрибуты исполнений записей (план 03 §7/§10 — атрибуты двухуровневые: запись и исполнение); замена набора исполнений пересоздаёт строки каскадом FK device_variants; базы прежних версий пересоздаются импортом (D5). Версия 13 — источники данных записи (план 03 §13, D13): словарь source_types (каталог), реестр sources с лицами (авторы/редакторы) и ссылками device_sources; атрибут datasheetUrl упразднён — ссылки на документацию несут источники типа datasheet; базы прежних версий пересоздаются импортом (D5).
Variables ¶
This section is empty.
Functions ¶
func MaskDSN ¶
MaskDSN скрывает секрет в DSN для безопасного отображения (вывод CLI, отчёты QA, сообщения тестов): в URL-форме маскируется пароль userinfo, в ключевой форме — значения всех ключей password (конфликт ключей у pgx решается поздним значением — маскируются все). DSN без опознаваемого пароля возвращается без изменений; не разбираемая URL-форма маскируется целиком — безопаснее потерять наглядность, чем показать секрет.
func TableNames ¶
func TableNames() []string
TableNames — имена каталожных таблиц модуля, выведенные из DDL (ddlStatements): единый источник для очистки одноразовых баз — qa/runner использует напрямую, internal/testutil — копией, синхронизированной пин-тестом (импорт storage в testutil запрещён: тесты storage импортируют testutil). DROP — с CASCADE, порядок не важен.
Types ¶
type AnalogRow ¶
AnalogRow — исходящая ссылка-аналог: цель с обозначением и системой (направленность — D8: строка принадлежит владельцу device_id).
type AttrRow ¶
AttrRow — значение атрибута записи: скалярные типы — ровно одно из Text/Num/Bool (первая строка группы кода), тексты всех строк группы — в Texts в порядке sort_order (тип text_list: список заметок; скаляр — ноль либо один элемент). Какой поле читать — решает потребитель по типу атрибута каталога; хранилище группировку строк не семантизирует.
type BacklinkRow ¶
type BacklinkRow struct {
SourceID int64
Kind domain.Kind
Designation string
System domain.System
Note string
}
BacklinkRow — встречная ссылка: запись, указавшая устройство аналогом.
type ChangeEvent ¶ added in v0.0.5
type ChangeEvent struct {
ID int64
Revision int64
Op string // created | updated | deleted — коды задаёт сервисный слой
Kind domain.Kind
Designation string
DeviceID int64
}
ChangeEvent — строка change_events: операция над записью, зафиксированная транзакцией изменения. Revision — значение data_revision ПОСЛЕ инкремента в той же транзакции; курсор потребителя — монотонный ID события: id присваивается вставкой и остаётся плотным курсором при любом числе событий в транзакции и при инкрементах ревизии мимо фида.
type Config ¶
type Config struct {
Dialect string // "sqlite" | "postgres"
DSN string // путь файла sqlite / DSN postgres
Pool PoolConfig
}
Config — конфигурация открытия хранилища (docs/plan/01-architecture.md §2.3): диалект, DSN/путь и параметры пулов соединений.
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB — открытое хранилище. Правило (docs/plan/01-architecture.md §2.3): весь DML — только внутри явных транзакций Begin (соединение записи); вне транзакций — только SELECT из пула чтения. Бизнес-правил не содержит.
Ловушка единственного соединения: у базы sqlite :memory: (и при MaxOpenConns(1) у postgres) чтение и запись делят одно соединение — DB-чтение (методы DB) внутри открытой Tx самозаблокируется до отмены контекста: соединение занято транзакцией. Внутри транзакции читайте только методами Tx; DB-чтения — вне транзакций.
func Open ¶
Open открывает хранилище по конфигурации; схему не проверяет и не создаёт (это делают CheckSchema/EnsureCreated). Ошибки конфигурации и подключения — доменные (storage_dsn_missing / storage_dialect_unknown / storage_open_failed) — деталь драйвера передаётся аргументом сообщения.
func (*DB) BeginReadOnly ¶ added in v0.0.2
BeginReadOnly открывает транзакцию чтения из пула чтения: проверки без DML (dry-run, каноническое сравнение Skipped, пакетные чтения карточки) не занимают выделенное соединение записи (SQLite) и не блокируют писателей. Транзакция только читается — Commit отвергается, откат — Rollback вызывающего (обычно defer).
func (*DB) CatalogRevision ¶
CatalogRevision возвращает catalog_revision — проверка кэша каталога на каждом обращении к сервисам (единственный SELECT schema_meta).
func (*DB) CheckSchema ¶
CheckSchema читает schema_meta.schema_version и сверяет с версией модуля (docs/plan/02-database.md §5.2): отсутствие таблицы — database_not_initialized (не инициализирована, чужая или повреждённая база), несовпадение версии — schema_version_mismatch; продолжение работы запрещено.
func (*DB) CountDevices ¶
CountDevices возвращает число записей (класса, если задан).
func (*DB) CountDevicesByKind ¶
CountDevicesByKind — числа записей по классам одним GROUP BY-запросом (агрегат /stats); классы без записей в результате отсутствуют.
func (*DB) CountKinds ¶
CountKinds возвращает число строк kinds (признак пустого каталога для сидирования при EnsureCreated).
func (*DB) CountManufacturers ¶
CountManufacturers возвращает число строк manufacturers (контроль чистки сирот в тестах и диагностике).
func (*DB) DialectName ¶
DialectName возвращает код диалекта хранилища.
func (*DB) EnsureCreated ¶
EnsureCreated выполняет полный DDL (CREATE … IF NOT EXISTS) и записывает schema_version, catalog_revision и data_revision, если их ещё нет (docs/plan/02-database.md §5). Гонка-безопасна: вставка меты подавляет конфликт уникальности атомарно (ON CONFLICT DO NOTHING) — конкурентное создание той же меты ошибки не даёт. Возвращает true, если база создана этим вызовом (мета была вставлена).
func (*DB) FindDevice ¶
func (*DB) FindDeviceAnyKind ¶
FindDeviceAnyKind ищет запись по обозначению без фильтра классом (разрешение аналогов, find).
func (*DB) FindDevicesByIDs ¶
FindDevicesByIDs — записи по списку стабильных id (параллельно удалённые в результате отсутствуют; порядок строк — по id).
func (*DB) FindSynonymOwner ¶ added in v0.0.8
func (d *DB) FindSynonymOwner(ctx context.Context, kind domain.Kind, designation string) (*SynonymOwnerRow, error)
FindSynonymOwner возвращает запись-владельца синонима по каноническому обозначению синонима (kind == "" — любой класс, детерминированно первая по kind_code, как FindDeviceAnyKind); nil — синонима нет. Уникальность (синоним не равен обозначению записи и не принадлежит двум записям) — инвариант сервисного слоя, читающий метод выбирает первую строку.
func (*DB) FindTypeSiblings ¶ added in v0.0.4
func (d *DB) FindTypeSiblings(ctx context.Context, bases []string) (map[string][]TypeSiblingRow, error)
FindTypeSiblings — записи групп типов по списку базовых обозначений (пакетное чтение карточек: блок «группа типа»): соединение по полю base, отбор пары (класс, базовое обозначение) — вызывающим (строки чужого класса с совпадающей строкой base отбрасываются). Порядок — по обозначению внутри группы.
func (*DB) ListDeviceIDsByKind ¶
ListDeviceIDsByKind перечисляет id записей класса в порядке (designation) — единый снимок одного запроса: последовательный обход страниц по OFFSET на живой базе даёт дубли и пропуски (экспорт).
func (*DB) LoadAttributesByIDs ¶
LoadAttributesByIDs — значения атрибутов по списку записей.
func (*DB) LoadAttributesByIDsCodes ¶ added in v0.0.7
func (d *DB) LoadAttributesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]AttrRow, error)
LoadAttributesByIDsCodes — значения атрибутов по списку записей и кодов атрибутов (пакетная проекция колонок значений поиска).
func (*DB) LoadBacklinksByIDs ¶
LoadBacklinksByIDs — встречные ссылки («кто указал запись аналогом») по списку записей, индекс по analog_device_id (docs/plan/02-database.md §3).
func (*DB) LoadChangeEvents ¶ added in v0.0.5
func (d *DB) LoadChangeEvents(ctx context.Context, after int64, limit int) ([]ChangeEvent, int64, error)
LoadChangeEvents возвращает события с идентификатором больше after в порядке возрастания id (курсор — монотонный id события, не ревизия) и текущий data_revision одним согласованным чтением: транзакция пула чтения даёт страницу событий и ревизию из одного снимка.
func (*DB) LoadFields ¶
LoadFields — поля разбора обозначения (порядок алфавитный — стабильно для карточки и сравнения состояний).
func (*DB) LoadFieldsByIDs ¶
LoadFieldsByIDs — поля разбора обозначений по списку записей.
func (*DB) LoadManufacturers ¶
func (*DB) LoadManufacturersByIDs ¶
LoadManufacturersByIDs — производители по списку записей.
func (*DB) LoadOutgoingAnalogsByIDs ¶
func (d *DB) LoadOutgoingAnalogsByIDs(ctx context.Context, ids []int64) (map[int64][]AnalogRow, error)
LoadOutgoingAnalogsByIDs — исходящие ссылки-аналоги по списку записей.
func (*DB) LoadSnapshot ¶
LoadSnapshot загружает полный снимок каталога одной транзакцией чтения из пула чтения (транспорт каталога — docs/plan/01-architecture.md §2.2; реализация catalog.Store). Все SELECT и чтение catalog_revision идут из одного снапшота СУБД: конкурентный импорт каталога не может смешать в снимке старые и новые определения, а Revision соответствует загруженным строкам. Уровень REPEATABLE READ переносим: pgx задаёт его явно, sqlite-драйвер игнорирует — WAL-транзакция чтения и так держит стабильный снапшот на всё время транзакции. Порядок строк детерминирован (ORDER BY), чтобы снимки одной базы были сравнимы.
func (*DB) LoadSources ¶ added in v0.3.0
LoadSources читает весь реестр источников с лицами и ссылками в порядке кода (одно соединение чтения; служебное чтение и экспорт).
func (*DB) LoadSynonymsByIDs ¶ added in v0.0.8
LoadSynonymsByIDs — исторические названия записей по списку (пакетное чтение карточек; порядок внутри записи — как у LoadSynonyms).
func (*DB) LoadValuesByIDs ¶
LoadValuesByIDs — все значения параметров (тип в целом и исполнения) с условиями по списку записей; порядок строк внутри записи — как у LoadValues.
func (*DB) LoadValuesByIDsCodes ¶ added in v0.0.7
func (d *DB) LoadValuesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]ValueRow, error)
LoadValuesByIDsCodes — значения параметров (тип в целом и исполнения) с условиями по списку записей и кодов параметров (пакетная проекция колонок значений поиска).
func (*DB) LoadVariantsByIDs ¶
LoadVariantsByIDs — исполнения по списку записей.
func (*DB) Revisions ¶
Revisions возвращает текущие счётчики catalog_revision и data_revision (для ETag REST — docs/plan/02-database.md §5.5).
func (*DB) Search ¶
func (d *DB) Search(ctx context.Context, r SearchRequest) ([]SearchItemRow, int, error)
Search выполняет поиск записей: WHERE — общие условия, ORDER BY — сортировка с финальным (kind, designation), LIMIT/OFFSET — пагинация. Возвращает страницу и общее число записей под фильтрами одним оператором (COUNT(*) OVER() — оконная функция переносима: sqlite ≥ 3.25, postgres): total и страница — один снимок данных, тяжёлый WHERE вычисляется один раз. Пустая страница (фильтр без строк либо страница за концом выдачи) оконного COUNT не даёт — total добирается отдельным COUNT-запросом того же фильтра. Отрицательные limit/offset отвергаются доменной ошибкой — диалекты расходятся в их трактовке (postgres — ошибка протокола, sqlite молча «без лимита»).
func (*DB) SuggestPrefix ¶
func (d *DB) SuggestPrefix(ctx context.Context, prefix string, kind string, limit int) ([]SearchItemRow, error)
SuggestPrefix — автодополнение по префиксу обозначения (каноническому): совпадает префикс обозначения записи либо одного из её исторических названий (синонимов); kind — необязательный фильтр классом.
type DeviceSourceRef ¶ added in v0.3.0
DeviceSourceRef — ссылка записи на источник для применения: id строки реестра и заметка; порядок среза — sort_order.
type DeviceSourceRow ¶ added in v0.3.0
DeviceSourceRow — ссылка записи на источник с полным определением (карточка, экспорт): Note — место в источнике, порядок — sort_order.
type Dialect ¶
type Dialect interface {
// Name возвращает код диалекта ("sqlite" | "postgres").
Name() string
// Open открывает пулы соединений по конфигурации.
Open(ctx context.Context, cfg Config) (*pools, error)
// RewriteDDL подставляет в переносимый оператор DDL определения
// диалекта: авто-PK колонок id (sqlite: INTEGER PRIMARY KEY
// AUTOINCREMENT; postgres: IDENTITY) и точный целочисленный тип
// (postgres: INTEGER → BIGINT — паритет диапазона int64 со sqlite).
RewriteDDL(stmt string) string
// InsertReturningID выполняет INSERT внутри транзакции и возвращает
// сгенерированный id (sqlite: INSERT … RETURNING id; postgres:
// INSERT … RETURNING id).
InsertReturningID(ctx context.Context, tx *sql.Tx, query string, args []any) (int64, error)
// InsertIfAbsentReturningID выполняет INSERT внутри транзакции,
// атомарно подавляя конфликт уникальности (ON CONFLICT DO NOTHING),
// и возвращает сгенерированный id. inserted=false — строка уже есть:
// либо существовала, либо вставлена конкурирующей транзакцией
// (postgres: писатели параллельны — общий пул соединений); id в этом
// случае возвращает SELECT вызывающего кода. Ошибки уникальности
// не возникает — транзакция остаётся рабочей в обоих диалектах.
InsertIfAbsentReturningID(ctx context.Context, tx *sql.Tx, query string, args []any) (id int64, inserted bool, err error)
}
Dialect — диалектозависимая часть хранилища (docs/plan/02-database.md §4): открытие и пулы, определение авто-PK в DDL, получение id после вставки. Всё прочее — переносимый DML на database/sql: текст с @имя-плейсхолдерами переписывается в позиционные $n (positional).
type FieldCond ¶
type FieldCond struct {
Field string
Text string
Texts []string
Num float64
HasNum bool
Op FilterOp
}
FieldCond — фильтр по полю разбора обозначения: текстовое значение (Text), набор текстовых значений с семантикой ИЛИ (Texts — словарные поля мультивыбора; приоритетнее Text) либо числовое со сравнением (Num + Op).
type ParamBounds ¶ added in v0.0.5
type ParamBounds struct {
Min, Max *float64
}
ParamBounds — численные границы значений параметра по записям класса: нижняя — MIN по нижним границам строк (value_min, точные значения — value_exact), верхняя — MAX по верхним (value_max, точные — value_exact); nil — строк такой формы нет. Семантика — как у параметрических фильтров поиска (paramCondSQL): границы фильтра применяются и к value_min/value_max, и к value_exact, поэтому слайдер по этим границам не отсекает записи, которые фильтр нашёл бы.
type ParamCond ¶
type ParamCond struct {
Code string
Min, Max, Exact float64
HasMin, HasMax bool
HasExact, HasText bool
Text string
}
ParamCond — фильтр по параметру: нижняя/верхняя граница, точное значение либо текст/enum. Вариантные параметры применяются в пределах одного исполнения (EXISTS по device_variants) — перекрёстные сочетания значений разных исполнений не сопоставляются (docs/plan/04-module-functionality.md §1).
type ParamValue ¶
type ParamValue struct {
Parameter string
Exact *float64
Min *float64
Max *float64
Text *string
Conditions []Cond
}
ParamValue — значение параметра с условиями (строка parameter_values вместе с parameter_value_conditions).
type ParamValueFreq ¶ added in v0.0.5
ParamValueFreq — текстовое значение параметра и число записей класса, имеющих его (значение в данных типа и нескольких исполнениях одной записи считается один раз — столько записей отфильтрует поиск).
type PoolConfig ¶
type PoolConfig struct {
MaxOpen int
MaxIdle int
ConnMaxLifetime int64 // наносекунды; 0 — без ограничения
BusyTimeout int64 // миллисекунды (sqlite); 0 — 5000
}
PoolConfig — параметры пулов соединений. Для postgres — единый пул (MaxOpen/MaxIdle/ConnMaxLifetime); для sqlite — размер пула чтения (запись всегда идёт через одно выделенное соединение) и busy_timeout.
type SearchItemRow ¶
type SearchItemRow struct {
ID int64
Kind string
System string
Designation string
Fields []anyField
}
SearchItemRow — строка результата поиска.
type SearchRequest ¶
type SearchRequest struct {
Kind string
System string
Query string // подстрока обозначения (каноническая, без масок)
IDs []int64
Fields []FieldCond
Attrs []AttrCond
Params []ParamCond
Sorts []SortKey
Limit int
Offset int
}
SearchRequest — параметры поиска без бизнес-правил: готовые условия (валидация применимости — сервисный слой). IDs — фильтр по набору стабильных id записей (пересечение с прочими условиями; без сортировки порядок выдачи — порядок передачи id).
type SortKey ¶
SortKey — ключ сортировки: "designation", "id", код поля разбора (Numeric — числовая сортировка поля, иначе текстовая) либо код числового параметра (Param — значение записи агрегируется из parameter_values производной таблицей).
type SourceLinkRow ¶ added in v0.3.0
SourceLinkRow — ссылка записи на источник: код реестра и заметка места в источнике (слитое состояние Upsert; порядок — по коду, канонический).
type SourceRow ¶ added in v0.3.0
type SourceRow struct {
ID int64
Code string
Title string
Type string
Year *int
Publisher string
Edition string
ISBN string
Authors []string
Editors []string
URLs []string
}
SourceRow — строка реестра sources вместе с лицами и ссылками (Year/Publisher/Edition/ISBN nil/"" — не задано; Authors/Editors/URLs — упорядоченные списки, nil — список не задан).
type SynonymOwnerRow ¶ added in v0.0.8
SynonymOwnerRow — владелец синонима: запись, чьим историческим названием является обозначение (разрешение синонима и конфликты уникальности).
type SynonymRow ¶ added in v0.0.8
SynonymRow — историческое название записи (синоним, план 03 §9): строка принадлежит владельцу device_id; YearFrom/YearTo — годы употребления имени (nil — не задано).
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Tx — транзакция записи: Commit фиксирует, откат — Rollback (присутствует в defer вызывающего). Все DML-методы хранилища принимают *Tx.
func (*Tx) BumpCatalogRevision ¶
BumpCatalogRevision инкрементирует catalog_revision (транзакция меняет каталог).
func (*Tx) BumpDataRevision ¶
BumpDataRevision инкрементирует data_revision (транзакция меняет устройства).
func (*Tx) CatalogRevision ¶ added in v0.0.2
CatalogRevision в текущей транзакции — перепроверка свежести снимка, по которому валидировалась запись (валидированное = записанному).
func (*Tx) CountDevicesByKind ¶ added in v0.0.2
CountDevicesByKind в текущей транзакции — согласованный агрегат /stats.
func (*Tx) DeleteDesignationFields ¶
DeleteDesignationFields удаляет именованные поля разбора записи (замена набора явных классификационных полей секцией fields; поля грамматики парсера не затрагиваются).
func (*Tx) DeleteDevice ¶
DeleteDevice удаляет запись (каскад FK по всем дочерним таблицам, включая обе стороны device_analogs) и чистит сирот производителей и источников.
func (*Tx) DeleteDeviceAnyKindByKey ¶
DeleteDeviceAnyKindByKey удаляет запись по обозначению без фильтра классом — детерминированно первая по kind_code, как FindDeviceAnyKind (подзапрос переносим: sqlite и postgres).
func (*Tx) DeleteDeviceByKey ¶
func (t *Tx) DeleteDeviceByKey(ctx context.Context, kind domain.Kind, designation string) (*DeviceRow, error)
DeleteDeviceByKey удаляет запись по ключу (kind_code, designation) в текущей транзакции и чистит сирот производителей; возвращает удалённую строку (nil — записи нет) — данные для события потока изменений. Поиск и удаление атомарны в одной транзакции: удаляется ровно найденная строка, конкурентное удаление того же ключа даёт nil — без «пустого» успеха и лишнего инкремента ревизии (TOCTOU отдельного поиска и удаления).
func (*Tx) DeleteTypeGroupValues ¶
DeleteTypeGroupValues удаляет данные типа в целом (variant_id NULL) по группе каталога — замена секции группы.
func (*Tx) DeleteVariants ¶
DeleteVariants удаляет исполнения записи вместе с их значениями (каскад FK parameter_values.variant_id).
func (*Tx) FindDevice ¶
func (*Tx) FindDevicesByIDs ¶ added in v0.0.2
func (*Tx) FindSourceID ¶ added in v0.3.0
FindSourceID ищет строку реестра по коду (разрешение ссылок записей); false — код не найден.
func (*Tx) FindSynonymOwner ¶ added in v0.0.8
func (*Tx) FindTypeSiblings ¶ added in v0.0.4
func (*Tx) InsertDesignationFields ¶
func (t *Tx) InsertDesignationFields(ctx context.Context, deviceID int64, fields []domain.Field) error
InsertDesignationFields записывает поля разбора обозначения; поля, уже существующие у записи (параллельный писатель), не затрагиваются — конфликт уникальности (device_id, field) подавляется атомарно. Вставка многострочная: число операторов не зависит от числа полей.
func (*Tx) InsertDevice ¶
func (t *Tx) InsertDevice(ctx context.Context, kind domain.Kind, system domain.System, designation string) (int64, bool, error)
InsertDevice вставляет запись, если её нет, и возвращает id вместе с признаком вставки. Вставка атомарно подавляет конфликт уникальности (kind_code, designation): параллельный писатель (postgres — общий пул соединений; sqlite-писатель один) успел вставить то же обозначение — вставки не происходит, id перечитывается по ключу. Строка, не видная перечитыванию (изоляция сервера выше READ COMMITTED), — доменная ошибка вместо сырого ErrNoRows драйвера.
func (*Tx) InsertIfAbsent ¶
InsertIfAbsent — вставка с атомарным подавлением конфликта уникальности для таблиц без суррогатного id (составной PK: связи производителей, атрибуты, аналоги): inserted=false — строка уже есть (вставлена конкурирующей транзакцией). ON CONFLICT DO NOTHING и RowsAffected переносимы, RETURNING не используется.
func (*Tx) InsertIfAbsentReturningID ¶
func (t *Tx) InsertIfAbsentReturningID(ctx context.Context, query string, args map[string]any) (int64, bool, error)
InsertIfAbsentReturningID — вставка с атомарным подавлением конфликта уникальности и возвратом сгенерированного id (метод диалекта — docs/plan/02-database.md §4); для таблиц с суррогатным id.
func (*Tx) InsertReturningID ¶
func (t *Tx) InsertReturningID(ctx context.Context, query string, args map[string]any) (int64, error)
InsertReturningID — вставка с возвратом сгенерированного id (метод диалекта; сигнатура зафиксирована планом — docs/plan/02-database.md §4).
func (*Tx) InsertSource ¶ added in v0.3.0
InsertSource вставляет определение источника (строку реестра, лица и ссылки) и возвращает id с признаком вставки; конфликт уникальности кода при параллельном писателе подавляется атомарно — определение конкурента не перезаписывается, id перечитывается по коду, inserted = false (строка, не видная перечитыванию, — доменная ошибка, как у производителей).
func (*Tx) InsertValues ¶
func (t *Tx) InsertValues(ctx context.Context, deviceID int64, variantID *int64, values []ParamValue) error
InsertValues вставляет значения параметров в контексте типа (variantID = nil) либо исполнения; порядок среза — sort_order. Значения без условий идут многострочной вставкой (id строк не нужен), значения с условиями — построчно (id нужен для условий), условия одного значения — одной многострочной вставкой.
func (*Tx) InsertVariant ¶
func (t *Tx) InsertVariant(ctx context.Context, deviceID int64, label string, sortOrder int) (int64, error)
InsertVariant вставляет исполнение и возвращает его id.
func (*Tx) InsertVariantAttributes ¶ added in v0.0.8
InsertVariantAttributes вставляет атрибуты исполнения после InsertVariant: строки нового варианта пусты (DELETE не нужен — замена набора исполнений пересоздаёт варианты целиком, старые строки уходят каскадом FK); построчное подавление конфликтов уникальности — как у ReplaceAttributes.
func (*Tx) LoadAttributes ¶
func (*Tx) LoadAttributesByIDs ¶ added in v0.0.2
func (*Tx) LoadAttributesByIDsCodes ¶ added in v0.0.7
func (t *Tx) LoadAttributesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]AttrRow, error)
LoadAttributesByIDsCodes — значения атрибутов по списку записей и кодов атрибутов; вызывается в транзакции чтения — согласованный снимок с прочими чтениями страницы.
func (*Tx) LoadBacklinksByIDs ¶ added in v0.0.2
func (*Tx) LoadDeviceSources ¶ added in v0.3.0
LoadDeviceSources — ссылки записи на источники в каноническом порядке (по коду — сравнение состояний не зависит от порядка чтения).
func (*Tx) LoadDeviceSourcesByIDs ¶ added in v0.3.0
func (t *Tx) LoadDeviceSourcesByIDs(ctx context.Context, ids []int64) (map[int64][]DeviceSourceRow, error)
LoadDeviceSourcesByIDs — ссылки записей на источники с полными определениями (пакетное чтение карточек): SELECT по чанкам списка записей, лица и ссылки — одним проходом по вовлечённым источникам; порядок внутри записи — как у LoadDeviceSources.
func (*Tx) LoadFields ¶
func (*Tx) LoadFieldsByIDs ¶ added in v0.0.2
func (*Tx) LoadManufacturers ¶
func (*Tx) LoadManufacturersByIDs ¶ added in v0.0.2
func (*Tx) LoadOutgoingAnalogs ¶
func (*Tx) LoadOutgoingAnalogsByIDs ¶ added in v0.0.2
func (*Tx) LoadSourceByCode ¶ added in v0.3.0
LoadSourceByCode читает определение источника по коду с лицами и ссылками; nil — код не найден.
func (*Tx) LoadSynonyms ¶ added in v0.0.8
LoadSynonyms — исторические названия записи (порядок — sort_order, затем обозначение: детерминирован между диалектами).
func (*Tx) LoadSynonymsByIDs ¶ added in v0.0.8
func (*Tx) LoadValues ¶
loadValues — все значения параметров устройства (тип в целом и исполнения) с условиями; порядок детерминирован: сначала данные типа, затем значения вариантов по (variant_id, sort_order, id); условия — по коду.
func (*Tx) LoadValuesByIDs ¶ added in v0.0.2
func (*Tx) LoadValuesByIDsCodes ¶ added in v0.0.7
func (t *Tx) LoadValuesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]ValueRow, error)
LoadValuesByIDsCodes — значения параметров с условиями по списку записей и кодов параметров; вызывается в транзакции чтения — согласованный снимок с прочими чтениями страницы.
func (*Tx) LoadVariantAttributesByIDs ¶ added in v0.0.8
func (t *Tx) LoadVariantAttributesByIDs(ctx context.Context, ids []int64) (map[int64][]AttrRow, error)
LoadVariantAttributesByIDs — атрибуты исполнений по списку id исполнений (карточки, слитое состояние Upsert).
func (*Tx) LoadVariantAttributesByIDsCodes ¶ added in v0.0.8
func (t *Tx) LoadVariantAttributesByIDsCodes(ctx context.Context, ids []int64, codes []string) (map[int64][]AttrRow, error)
LoadVariantAttributesByIDsCodes — атрибуты исполнений по списку id исполнений и кодов атрибутов (пакетная проекция колонок значений поиска); вызывается в транзакции чтения — согласованный снимок.
func (*Tx) LoadVariants ¶
func (*Tx) LoadVariantsByIDs ¶ added in v0.0.2
func (*Tx) ParameterBounds ¶ added in v0.0.5
ParameterBounds — MIN/MAX по параметрам записей класса одним GROUP BY-запросом (COALESCE/MIN/MAX переносимы между диалектами); параметры без численных строк в результате отсутствуют. Вызывается в транзакции чтения — согласованный снимок с прочими агрегатами (data_revision, частоты).
func (*Tx) ParameterValueFreqs ¶ added in v0.0.5
func (t *Tx) ParameterValueFreqs(ctx context.Context, kind domain.Kind) (map[string][]ParamValueFreq, error)
ParameterValueFreqs — частоты текстовых значений параметров класса: GROUP BY (parameter_code, value_text), счётчик — число записей класса (COUNT(DISTINCT d.id)); порядок значений параметра — по убыванию частоты, затем по тексту (детерминированный порядок фасета).
func (*Tx) RecordChange ¶ added in v0.0.5
func (t *Tx) RecordChange(ctx context.Context, op string, kind domain.Kind, designation string, deviceID int64) error
RecordChange инкрементирует data_revision и записывает событие изменения записи в той же транзакции — единый путь операций записи устройств: событие и изменение данных атомарны (откат транзакции не оставляет ни того, ни другого), вызывается один раз на транзакцию записи. Новое значение счётчика читается после UPDATE здесь же, в той же транзакции (не выносится за её пределы): SQLite — одно выделенное соединение записи, PostgreSQL — строка schema_meta заблокирована UPDATE до конца транзакции — конкурентный писатель не увидит промежуточное значение.
func (*Tx) ReplaceAnalogs ¶
ReplaceAnalogs заменяет исходящие ссылки-аналоги целиком (встречные ссылки других записей не затрагиваются — D8); ссылки, вставленные параллельным писателем в той же записи и не видимые DELETE этого вызова, сохраняются.
func (*Tx) ReplaceAttributes ¶
ReplaceAttributes заменяет значения атрибутов целиком (секция attributes); подавление конфликтов уникальности — по строке (составной PK со sort_order): значения, вставленные параллельным писателем в той же записи и не видные DELETE этого вызова, сохраняются; для text_list подавление также построчно — списки двух невидимых друг другу писателей могут перемешаться (сервис перечитывает слитое состояние в своей транзакции записи и этим сценарием не владеет). Texts — список строк типа text_list: по строке на элемент, sort_order — порядок списка (пустой список — строк нет); скалярные типы — одна строка с sort_order 0.
func (*Tx) ReplaceDeviceSources ¶ added in v0.3.0
func (t *Tx) ReplaceDeviceSources(ctx context.Context, deviceID int64, refs []DeviceSourceRef) error
ReplaceDeviceSources заменяет ссылки записи на источники целиком (секция sources записи): связи пересоздаются, источники этой записи, оставшиеся без единой связи, удаляются (адресная чистка сирот — по образцу производителей; индекс idx_device_sources_source держит проверку «без связей» точечной). Строки, вставленные параллельным писателем в той же записи и не видные DELETE этого вызова, сохраняются.
func (*Tx) ReplaceManufacturers ¶
ReplaceManufacturers заменяет список производителей целиком: связи пересоздаются, недостающие строки manufacturers создаются, производители этого устройства, оставшиеся без единой связи, удаляются (адресная чистка сирот — только затронутые заменой строки: полный анти-джойн растущей таблицы на каждую замену делал импорт квадратичным; индекс idx_dm_manufacturer держит проверку «без связей» точечной). Создание строки производителя атомарно подавляет конфликт уникальности имени: параллельный писатель успел вставить то же имя — id перечитывается по имени.
func (*Tx) ReplaceSynonyms ¶ added in v0.0.8
ReplaceSynonyms заменяет исторические названия записи целиком (секция synonyms); строки, вставленные параллельным писателем в той же записи и не видимые DELETE этого вызова, сохраняются. Порядок среза — sort_order.
func (*Tx) Revisions ¶ added in v0.0.2
Revisions в текущей транзакции — согласованные агрегаты (один снимок чтения с прочими чтениями вызывающего, например /stats).
func (*Tx) UpdateSource ¶ added in v0.3.0
UpdateSource обновляет поля строки реестра; лица и ссылки замещаются целиком (upsert определения по коду — план 03 §13).
func (*Tx) WriteCatalog ¶
WriteCatalog применяет строки каталога upsert'ом по коду внутри транзакции записи (docs/plan/02-database.md §5.4): вставка новой строки либо обновление полей существующей; enum-значения, наборы условий и применимость к классам замещаются целиком; удаления строк каталога нет — только деактивация (is_active = 0) самим входом. Валидацию метасхемы выполняет сервисный слой до записи; порядок таблиц учитывает FK.
type TypeSiblingRow ¶ added in v0.0.4
TypeSiblingRow — запись группы типа: запись того же класса с тем же базовым обозначением (производное поле base — план 03 §2.6).
type ValueRow ¶
type ValueRow struct {
VariantID *int64
Value ParamValue
}
ValueRow — значение в контексте устройства: данные типа (VariantID = nil) либо исполнения (VariantID = id варианта).
type VariantRow ¶
VariantRow — строка device_variants.