storage

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 13 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 = 7

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): адресная чистка сирот производителей проверяет «без связей» точечно, без полного анти-джойна.

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
	Num       *float64
	Bool      *bool
}

AttrRow — значение атрибута записи (ровно одно из Text/Num/Bool задано).

type BacklinkRow

type BacklinkRow struct {
	SourceID    int64
	Kind        domain.Kind
	Designation string
	System      domain.System
	Note        string
}

BacklinkRow — встречная ссылка: запись, указавшая устройство аналогом.

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) 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) 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) 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) LoadValuesByIDs

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

LoadValuesByIDs — все значения параметров (тип в целом и исполнения) с условиями по списку записей; порядок строк внутри записи — как у LoadValues.

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 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
	Num    float64
	HasNum bool
	Op     FilterOp
}

FieldCond — фильтр по полю разбора обозначения: текстовое значение (Text) либо числовое со сравнением (Num + Op).

type FilterOp

type FilterOp string

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

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

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

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 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 // подстрока обозначения (каноническая, без масок)
	Fields []FieldCond
	Attrs  []AttrCond
	Params []ParamCond
	Sorts  []SortKey
	Limit  int
	Offset int
}

SearchRequest — параметры поиска без бизнес-правил: готовые условия (валидация применимости — сервисный слой).

type SortKey

type SortKey struct {
	Key     string
	Numeric bool
	Desc    bool
}

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

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) (int64, error)

DeleteDeviceAnyKindByKey удаляет запись по обозначению без фильтра классом — детерминированно первая по kind_code, как FindDeviceAnyKind (подзапрос переносим: sqlite и postgres).

func (*Tx) DeleteDeviceByKey

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

DeleteDeviceByKey удаляет запись по ключу (kind_code, designation) в текущей транзакции и чистит сирот производителей; возвращает число удалённых строк (0 — записи нет). Поиск и удаление атомарны в одном операторе: конкурентное удаление того же ключа даёт ноль строк — без «пустого» успеха и лишнего инкремента ревизии (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) 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) 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) 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) LoadBacklinksByIDs added in v0.0.2

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

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) 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) 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) 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); значения, вставленные параллельным писателем в той же записи и не видимые DELETE этого вызова, сохраняются.

func (*Tx) ReplaceManufacturers

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

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

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) 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 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