Help us shape the future of Go! Take the 2026 Go Developer Survey

storage

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: MIT Imports: 14 Imported by: 0

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

View Source
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

func MaskDSN(dsn string) string

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

type AnalogRow struct {
	TargetID    int64
	Designation string
	System      domain.System
	Note        string
}

AnalogRow — исходящая ссылка-аналог: цель с обозначением и системой (направленность — D8: строка принадлежит владельцу device_id).

type AttrCond

type AttrCond struct {
	Code   string
	Text   string
	Num    float64
	HasNum bool
	Op     FilterOp
}

AttrCond — фильтр по атрибуту: текстовое либо числовое значение.

type AttrRow

type AttrRow struct {
	Attribute string
	Text      *string
	Texts     []string
	Num       *float64
	Bool      *bool
}

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 Cond

type Cond struct {
	Code  string
	Value float64
}

Cond — условие измерения со значением.

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

func Open(ctx context.Context, cfg Config) (*DB, error)

Open открывает хранилище по конфигурации; схему не проверяет и не создаёт (это делают CheckSchema/EnsureCreated). Ошибки конфигурации и подключения — доменные (storage_dsn_missing / storage_dialect_unknown / storage_open_failed) — деталь драйвера передаётся аргументом сообщения.

func (*DB) Begin

func (d *DB) Begin(ctx context.Context) (*Tx, error)

Begin открывает явную транзакцию записи (единственный путь DML).

func (*DB) BeginReadOnly added in v0.0.2

func (d *DB) BeginReadOnly(ctx context.Context) (*Tx, error)

BeginReadOnly открывает транзакцию чтения из пула чтения: проверки без DML (dry-run, каноническое сравнение Skipped, пакетные чтения карточки) не занимают выделенное соединение записи (SQLite) и не блокируют писателей. Транзакция только читается — Commit отвергается, откат — Rollback вызывающего (обычно defer).

func (*DB) CatalogRevision

func (d *DB) CatalogRevision(ctx context.Context) (int64, error)

CatalogRevision возвращает catalog_revision — проверка кэша каталога на каждом обращении к сервисам (единственный SELECT schema_meta).

func (*DB) CheckSchema

func (d *DB) CheckSchema(ctx context.Context) error

CheckSchema читает schema_meta.schema_version и сверяет с версией модуля (docs/plan/02-database.md §5.2): отсутствие таблицы — database_not_initialized (не инициализирована, чужая или повреждённая база), несовпадение версии — schema_version_mismatch; продолжение работы запрещено.

func (*DB) Close

func (d *DB) Close() error

Close закрывает пулы соединений.

func (*DB) CountDevices

func (d *DB) CountDevices(ctx context.Context, kind domain.Kind) (int, error)

CountDevices возвращает число записей (класса, если задан).

func (*DB) CountDevicesByKind

func (d *DB) CountDevicesByKind(ctx context.Context) (map[string]int, error)

CountDevicesByKind — числа записей по классам одним GROUP BY-запросом (агрегат /stats); классы без записей в результате отсутствуют.

func (*DB) CountKinds

func (d *DB) CountKinds(ctx context.Context) (int, error)

CountKinds возвращает число строк kinds (признак пустого каталога для сидирования при EnsureCreated).

func (*DB) CountManufacturers

func (d *DB) CountManufacturers(ctx context.Context) (int, error)

CountManufacturers возвращает число строк manufacturers (контроль чистки сирот в тестах и диагностике).

func (*DB) DialectName

func (d *DB) DialectName() string

DialectName возвращает код диалекта хранилища.

func (*DB) EnsureCreated

func (d *DB) EnsureCreated(ctx context.Context) (bool, error)

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 (d *DB) FindDevice(ctx context.Context, kind domain.Kind, designation string) (*DeviceRow, error)

func (*DB) FindDeviceAnyKind

func (d *DB) FindDeviceAnyKind(ctx context.Context, designation string) (*DeviceRow, error)

FindDeviceAnyKind ищет запись по обозначению без фильтра классом (разрешение аналогов, find).

func (*DB) FindDevicesByIDs

func (d *DB) FindDevicesByIDs(ctx context.Context, ids []int64) ([]*DeviceRow, error)

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

func (d *DB) ListDeviceIDsByKind(ctx context.Context, kind domain.Kind) ([]int64, error)

ListDeviceIDsByKind перечисляет id записей класса в порядке (designation) — единый снимок одного запроса: последовательный обход страниц по OFFSET на живой базе даёт дубли и пропуски (экспорт).

func (*DB) LoadAttributesByIDs

func (d *DB) LoadAttributesByIDs(ctx context.Context, ids []int64) (map[int64][]AttrRow, error)

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

func (d *DB) LoadBacklinksByIDs(ctx context.Context, ids []int64) (map[int64][]BacklinkRow, error)

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

func (d *DB) LoadFields(ctx context.Context, deviceID int64) ([]domain.Field, error)

LoadFields — поля разбора обозначения (порядок алфавитный — стабильно для карточки и сравнения состояний).

func (*DB) LoadFieldsByIDs

func (d *DB) LoadFieldsByIDs(ctx context.Context, ids []int64) (map[int64][]domain.Field, error)

LoadFieldsByIDs — поля разбора обозначений по списку записей.

func (*DB) LoadManufacturers

func (d *DB) LoadManufacturers(ctx context.Context, deviceID int64) ([]string, error)

func (*DB) LoadManufacturersByIDs

func (d *DB) LoadManufacturersByIDs(ctx context.Context, ids []int64) (map[int64][]string, error)

LoadManufacturersByIDs — производители по списку записей.

func (*DB) LoadOutgoingAnalogsByIDs

func (d *DB) LoadOutgoingAnalogsByIDs(ctx context.Context, ids []int64) (map[int64][]AnalogRow, error)

LoadOutgoingAnalogsByIDs — исходящие ссылки-аналоги по списку записей.

func (*DB) LoadSnapshot

func (d *DB) LoadSnapshot(ctx context.Context) (*catalog.Snapshot, error)

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

func (d *DB) LoadSources(ctx context.Context) ([]SourceRow, error)

LoadSources читает весь реестр источников с лицами и ссылками в порядке кода (одно соединение чтения; служебное чтение и экспорт).

func (*DB) LoadSynonymsByIDs added in v0.0.8

func (d *DB) LoadSynonymsByIDs(ctx context.Context, ids []int64) (map[int64][]SynonymRow, error)

LoadSynonymsByIDs — исторические названия записей по списку (пакетное чтение карточек; порядок внутри записи — как у LoadSynonyms).

func (*DB) LoadValuesByIDs

func (d *DB) LoadValuesByIDs(ctx context.Context, ids []int64) (map[int64][]ValueRow, error)

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

func (d *DB) LoadVariantsByIDs(ctx context.Context, ids []int64) (map[int64][]VariantRow, error)

LoadVariantsByIDs — исполнения по списку записей.

func (*DB) Revisions

func (d *DB) Revisions(ctx context.Context) (catalog, data int64, err error)

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 DeviceRow

type DeviceRow struct {
	ID          int64
	Kind        domain.Kind
	System      domain.System
	Designation string
}

DeviceRow — строка devices.

type DeviceSourceRef added in v0.3.0

type DeviceSourceRef struct {
	SourceID int64
	Note     string
}

DeviceSourceRef — ссылка записи на источник для применения: id строки реестра и заметка; порядок среза — sort_order.

type DeviceSourceRow added in v0.3.0

type DeviceSourceRow struct {
	SourceRow
	Note string
}

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 FilterOp

type FilterOp string

FilterOp — операция сравнения числового фильтра.

const (
	OpEq  FilterOp = "eq"
	OpGte FilterOp = "gte"
	OpLte FilterOp = "lte"
)

Реестр операций фильтров.

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

type ParamValueFreq struct {
	Text    string
	Devices int
}

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

type SortKey struct {
	Key     string
	Numeric bool
	Param   bool
	Desc    bool
}

SortKey — ключ сортировки: "designation", "id", код поля разбора (Numeric — числовая сортировка поля, иначе текстовая) либо код числового параметра (Param — значение записи агрегируется из parameter_values производной таблицей).

type SourceLinkRow added in v0.3.0

type SourceLinkRow struct {
	Code string
	Note string
}

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

type SynonymOwnerRow struct {
	DeviceID    int64
	Kind        domain.Kind
	Designation string
}

SynonymOwnerRow — владелец синонима: запись, чьим историческим названием является обозначение (разрешение синонима и конфликты уникальности).

type SynonymRow added in v0.0.8

type SynonymRow struct {
	Designation string
	Note        string
	YearFrom    *int
	YearTo      *int
	SortOrder   int
}

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

func (t *Tx) BumpCatalogRevision(ctx context.Context) error

BumpCatalogRevision инкрементирует catalog_revision (транзакция меняет каталог).

func (*Tx) BumpDataRevision

func (t *Tx) BumpDataRevision(ctx context.Context) error

BumpDataRevision инкрементирует data_revision (транзакция меняет устройства).

func (*Tx) CatalogRevision added in v0.0.2

func (t *Tx) CatalogRevision(ctx context.Context) (int64, error)

CatalogRevision в текущей транзакции — перепроверка свежести снимка, по которому валидировалась запись (валидированное = записанному).

func (*Tx) Commit

func (t *Tx) Commit() error

Commit фиксирует транзакцию.

func (*Tx) CountDevicesByKind added in v0.0.2

func (t *Tx) CountDevicesByKind(ctx context.Context) (map[string]int, error)

CountDevicesByKind в текущей транзакции — согласованный агрегат /stats.

func (*Tx) DeleteDesignationFields

func (t *Tx) DeleteDesignationFields(ctx context.Context, deviceID int64, names []string) error

DeleteDesignationFields удаляет именованные поля разбора записи (замена набора явных классификационных полей секцией fields; поля грамматики парсера не затрагиваются).

func (*Tx) DeleteDevice

func (t *Tx) DeleteDevice(ctx context.Context, deviceID int64) error

DeleteDevice удаляет запись (каскад FK по всем дочерним таблицам, включая обе стороны device_analogs) и чистит сирот производителей и источников.

func (*Tx) DeleteDeviceAnyKindByKey

func (t *Tx) DeleteDeviceAnyKindByKey(ctx context.Context, designation string) (*DeviceRow, error)

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

func (t *Tx) DeleteTypeGroupValues(ctx context.Context, deviceID int64, groupCode string) error

DeleteTypeGroupValues удаляет данные типа в целом (variant_id NULL) по группе каталога — замена секции группы.

func (*Tx) DeleteVariants

func (t *Tx) DeleteVariants(ctx context.Context, deviceID int64) error

DeleteVariants удаляет исполнения записи вместе с их значениями (каскад FK parameter_values.variant_id).

func (*Tx) FindDevice

func (t *Tx) FindDevice(ctx context.Context, kind domain.Kind, designation string) (*DeviceRow, error)

func (*Tx) FindDevicesByIDs added in v0.0.2

func (t *Tx) FindDevicesByIDs(ctx context.Context, ids []int64) ([]*DeviceRow, error)

func (*Tx) FindSourceID added in v0.3.0

func (t *Tx) FindSourceID(ctx context.Context, code string) (int64, bool, error)

FindSourceID ищет строку реестра по коду (разрешение ссылок записей); false — код не найден.

func (*Tx) FindSynonymOwner added in v0.0.8

func (t *Tx) FindSynonymOwner(ctx context.Context, kind domain.Kind, designation string) (*SynonymOwnerRow, error)

func (*Tx) FindTypeSiblings added in v0.0.4

func (t *Tx) FindTypeSiblings(ctx context.Context, bases []string) (map[string][]TypeSiblingRow, error)

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

func (t *Tx) InsertIfAbsent(ctx context.Context, query string, args map[string]any) (bool, error)

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

func (t *Tx) InsertSource(ctx context.Context, r SourceRow) (int64, bool, error)

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

func (t *Tx) InsertVariantAttributes(ctx context.Context, variantID int64, rows []AttrRow) error

InsertVariantAttributes вставляет атрибуты исполнения после InsertVariant: строки нового варианта пусты (DELETE не нужен — замена набора исполнений пересоздаёт варианты целиком, старые строки уходят каскадом FK); построчное подавление конфликтов уникальности — как у ReplaceAttributes.

func (*Tx) LoadAttributes

func (t *Tx) LoadAttributes(ctx context.Context, deviceID int64) ([]AttrRow, error)

func (*Tx) LoadAttributesByIDs added in v0.0.2

func (t *Tx) LoadAttributesByIDs(ctx context.Context, ids []int64) (map[int64][]AttrRow, error)

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 (t *Tx) LoadBacklinksByIDs(ctx context.Context, ids []int64) (map[int64][]BacklinkRow, error)

func (*Tx) LoadDeviceSources added in v0.3.0

func (t *Tx) LoadDeviceSources(ctx context.Context, deviceID int64) ([]SourceLinkRow, error)

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 (t *Tx) LoadFields(ctx context.Context, deviceID int64) ([]domain.Field, error)

func (*Tx) LoadFieldsByIDs added in v0.0.2

func (t *Tx) LoadFieldsByIDs(ctx context.Context, ids []int64) (map[int64][]domain.Field, error)

func (*Tx) LoadManufacturers

func (t *Tx) LoadManufacturers(ctx context.Context, deviceID int64) ([]string, error)

func (*Tx) LoadManufacturersByIDs added in v0.0.2

func (t *Tx) LoadManufacturersByIDs(ctx context.Context, ids []int64) (map[int64][]string, error)

func (*Tx) LoadOutgoingAnalogs

func (t *Tx) LoadOutgoingAnalogs(ctx context.Context, deviceID int64) ([]AnalogRow, error)

func (*Tx) LoadOutgoingAnalogsByIDs added in v0.0.2

func (t *Tx) LoadOutgoingAnalogsByIDs(ctx context.Context, ids []int64) (map[int64][]AnalogRow, error)

func (*Tx) LoadSourceByCode added in v0.3.0

func (t *Tx) LoadSourceByCode(ctx context.Context, code string) (*SourceRow, error)

LoadSourceByCode читает определение источника по коду с лицами и ссылками; nil — код не найден.

func (*Tx) LoadSynonyms added in v0.0.8

func (t *Tx) LoadSynonyms(ctx context.Context, deviceID int64) ([]SynonymRow, error)

LoadSynonyms — исторические названия записи (порядок — sort_order, затем обозначение: детерминирован между диалектами).

func (*Tx) LoadSynonymsByIDs added in v0.0.8

func (t *Tx) LoadSynonymsByIDs(ctx context.Context, ids []int64) (map[int64][]SynonymRow, error)

func (*Tx) LoadValues

func (t *Tx) LoadValues(ctx context.Context, deviceID int64) ([]ValueRow, error)

loadValues — все значения параметров устройства (тип в целом и исполнения) с условиями; порядок детерминирован: сначала данные типа, затем значения вариантов по (variant_id, sort_order, id); условия — по коду.

func (*Tx) LoadValuesByIDs added in v0.0.2

func (t *Tx) LoadValuesByIDs(ctx context.Context, ids []int64) (map[int64][]ValueRow, error)

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 (t *Tx) LoadVariants(ctx context.Context, deviceID int64) ([]VariantRow, error)

func (*Tx) LoadVariantsByIDs added in v0.0.2

func (t *Tx) LoadVariantsByIDs(ctx context.Context, ids []int64) (map[int64][]VariantRow, error)

func (*Tx) ParameterBounds added in v0.0.5

func (t *Tx) ParameterBounds(ctx context.Context, kind domain.Kind) (map[string]ParamBounds, error)

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

func (t *Tx) ReplaceAnalogs(ctx context.Context, deviceID int64, targets []AnalogRow) error

ReplaceAnalogs заменяет исходящие ссылки-аналоги целиком (встречные ссылки других записей не затрагиваются — D8); ссылки, вставленные параллельным писателем в той же записи и не видимые DELETE этого вызова, сохраняются.

func (*Tx) ReplaceAttributes

func (t *Tx) ReplaceAttributes(ctx context.Context, deviceID int64, rows []AttrRow) error

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

func (t *Tx) ReplaceManufacturers(ctx context.Context, deviceID int64, names []string) error

ReplaceManufacturers заменяет список производителей целиком: связи пересоздаются, недостающие строки manufacturers создаются, производители этого устройства, оставшиеся без единой связи, удаляются (адресная чистка сирот — только затронутые заменой строки: полный анти-джойн растущей таблицы на каждую замену делал импорт квадратичным; индекс idx_dm_manufacturer держит проверку «без связей» точечной). Создание строки производителя атомарно подавляет конфликт уникальности имени: параллельный писатель успел вставить то же имя — id перечитывается по имени.

func (*Tx) ReplaceSynonyms added in v0.0.8

func (t *Tx) ReplaceSynonyms(ctx context.Context, deviceID int64, rows []SynonymRow) error

ReplaceSynonyms заменяет исторические названия записи целиком (секция synonyms); строки, вставленные параллельным писателем в той же записи и не видимые DELETE этого вызова, сохраняются. Порядок среза — sort_order.

func (*Tx) Revisions added in v0.0.2

func (t *Tx) Revisions(ctx context.Context) (catalog, data int64, err error)

Revisions в текущей транзакции — согласованные агрегаты (один снимок чтения с прочими чтениями вызывающего, например /stats).

func (*Tx) Rollback

func (t *Tx) Rollback() error

Rollback откатывает транзакцию.

func (*Tx) UpdateSource added in v0.3.0

func (t *Tx) UpdateSource(ctx context.Context, id int64, r SourceRow) error

UpdateSource обновляет поля строки реестра; лица и ссылки замещаются целиком (upsert определения по коду — план 03 §13).

func (*Tx) WriteCatalog

func (t *Tx) WriteCatalog(ctx context.Context, in catalog.Input) error

WriteCatalog применяет строки каталога upsert'ом по коду внутри транзакции записи (docs/plan/02-database.md §5.4): вставка новой строки либо обновление полей существующей; enum-значения, наборы условий и применимость к классам замещаются целиком; удаления строк каталога нет — только деактивация (is_active = 0) самим входом. Валидацию метасхемы выполняет сервисный слой до записи; порядок таблиц учитывает FK.

type TypeSiblingRow added in v0.0.4

type TypeSiblingRow struct {
	Base        string
	ID          int64
	Kind        string
	System      string
	Designation string
}

TypeSiblingRow — запись группы типа: запись того же класса с тем же базовым обозначением (производное поле base — план 03 §2.6).

type ValueRow

type ValueRow struct {
	VariantID *int64
	Value     ParamValue
}

ValueRow — значение в контексте устройства: данные типа (VariantID = nil) либо исполнения (VariantID = id варианта).

type VariantRow

type VariantRow struct {
	ID        int64
	Label     string
	SortOrder int
}

VariantRow — строка device_variants.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL