Documentation
¶
Overview ¶
Package base предоставляет общие хелперы и утилиты для всех адаптеров БД
Этот пакет устраняет дублирование кода между адаптерами (SQLite, PostgreSQL, MS SQL Server, MySQL) путем вынесения общей логики экспорта, импорта и конвертации типов в переиспользуемые компоненты.
Основные компоненты ¶
ExportHelper - общая логика экспорта данных в TDTP пакеты:
- ExportTable() - экспорт всей таблицы
- ExportTableWithQuery() - экспорт с TDTQL фильтрацией и SQL оптимизацией
- ExportTableIncremental() - инкрементальная синхронизация
ImportHelper - общая логика импорта TDTP пакетов в БД:
- ImportPacket() - импорт одного пакета
- ImportPackets() - импорт нескольких пакетов атомарно
- Поддержка временных таблиц для атомарной замены
UniversalTypeConverter - универсальная конвертация типов данных:
- ConvertValueToTDTP() - БД → TDTP формат
- DBValueToString() - значение БД → строка (с учетом специфики СУБД)
- TypedValueToSQL() - TDTP → SQL значение для PreparedStatement
- Поддержка PostgreSQL-специфичных типов (UUID, JSONB, NUMERIC)
- Поддержка MS SQL-специфичных типов (UNIQUEIDENTIFIER, TIMESTAMP/ROWVERSION)
Использование ¶
Для создания адаптера необходимо:
1. Реализовать интерфейсы для ExportHelper:
- SchemaReader (GetTableSchema)
- DataReader (ReadAllRows, ReadRowsWithSQL, GetRowCount)
- SQLAdapter (AdaptSQL) - опционально, для адаптации SQL под СУБД
2. Реализовать интерфейсы для ImportHelper:
- TableManager (TableExists, CreateTable, DropTable, RenameTable)
- DataInserter (InsertRows)
- TransactionManager (BeginTx)
3. Создать хелперы в адаптере:
type Adapter struct {
db *sql.DB
exportHelper *base.ExportHelper
importHelper *base.ImportHelper
converter *base.UniversalTypeConverter
}
func (a *Adapter) initHelpers() {
a.converter = base.NewUniversalTypeConverter()
a.exportHelper = base.NewExportHelper(a, a, a.converter, nil)
a.importHelper = base.NewImportHelper(a, a, a, true) // useTemporaryTables = true
}
4. Делегировать методы интерфейса Adapter хелперам:
func (a *Adapter) ExportTable(ctx context.Context, tableName string) ([]*packet.DataPacket, error) {
return a.exportHelper.ExportTable(ctx, tableName)
}
func (a *Adapter) ImportPacket(ctx context.Context, pkt *packet.DataPacket, strategy adapters.ImportStrategy) error {
return a.importHelper.ImportPacket(ctx, pkt, strategy)
}
Эффект от использования ¶
Использование base пакета позволяет:
- Сократить код адаптеров на ~60-70% (с ~1000 строк до ~300 строк)
- Устранить дублирование логики экспорта (~800 строк дублированного кода)
- Устранить дублирование логики импорта (~600 строк дублированного кода)
- Устранить дублирование конвертации типов (~300 строк дублированного кода)
- Упростить поддержку и добавление новых адаптеров
- Обеспечить консистентность поведения между адаптерами
Совместимость ¶
Пакет совместим с:
- pkg/core/packet - генерация и парсинг TDTP пакетов
- pkg/core/schema - система типов данных
- pkg/core/tdtql - язык запросов и SQL оптимизация
- pkg/etl - ETL конвейеры (использует packet.Generator)
- Все существующие адаптеры (SQLite, PostgreSQL, MS SQL Server, MySQL)
Архитектурные принципы ¶
- Dependency Inversion: хелперы зависят от интерфейсов, не от конкретных реализаций - Single Responsibility: каждый хелпер отвечает за свою область (export/import/conversion) - Open/Closed: легко расширяется новыми адаптерами без изменения базового кода - DRY (Don't Repeat Yourself): устранение дублирования кода
Index ¶
- Constants
- func ConvertRowToSQLValues(rowValues []string, pkgSchema packet.Schema, converter *UniversalTypeConverter, ...) ([]any, error)
- func FilterSchemaByFields(full packet.Schema, fields []string) (packet.Schema, []int, error)
- func GenerateTempTableName(baseName string) string
- func ParseRowValues(row packet.Row) []string
- func ProjectRows(rows [][]string, indices []int) [][]string
- func ScanSQLRows(rows *sql.Rows, schema packet.Schema, converter *UniversalTypeConverter, ...) ([][]string, error)
- func StreamSQLRows(ctx context.Context, rows *sql.Rows, sch packet.Schema, ...) error
- type ArenaBlock
- type ColumnArena
- type ColumnBlock
- type DataInserter
- type DataReader
- type ExportHelper
- func (h *ExportHelper) ExportTable(ctx context.Context, tableName string) ([]*packet.DataPacket, error)
- func (h *ExportHelper) ExportTableIncremental(ctx context.Context, tableName string, ...) ([]*packet.DataPacket, string, error)
- func (h *ExportHelper) ExportTableWithQuery(ctx context.Context, tableName string, query *packet.Query, ...) ([]*packet.DataPacket, error)
- func (h *ExportHelper) SetColumnarLayout(on bool)
- func (h *ExportHelper) SetMaxFallbackRows(n int64)
- func (h *ExportHelper) SetMaxMessageSize(size int)
- func (h *ExportHelper) SetSkipSpecialValues(skip bool)
- type FieldNameRenderer
- type ImportHelper
- type MSSQLAdapter
- type ParseFailure
- type ParseFailureReporter
- type PostgreSQLSchemaAdapter
- type RowPostProcessor
- type SQLAdapter
- type SchemaReader
- type StandardSQLAdapter
- type StreamingDataReader
- type TableManager
- type TransactionManager
- type UniversalTypeConverter
- func (c *UniversalTypeConverter) ConvertValueToTDTP(field packet.Field, value string) string
- func (c *UniversalTypeConverter) DBValueToString(value any, field packet.Field, dbType string) string
- func (c *UniversalTypeConverter) SetNoDateSentinels(dates []string)
- func (c *UniversalTypeConverter) TakeParseFailures() []ParseFailure
- func (c *UniversalTypeConverter) TypedValueToSQL(tv schema.TypedValue, dbType string) any
- type ValueConverter
- type ValueRenderer
Constants ¶
const NullSentinel = "\x00"
NullSentinel — внутренний маркер DB NULL, сохраняющий информацию через pipeline конвертации. Заменяется на SpecialValues.Null.Marker (или "") в DetectAndApply перед записью в TDTP. Не попадает в финальный TDTP файл.
Variables ¶
This section is empty.
Functions ¶
func ConvertRowToSQLValues ¶
func ConvertRowToSQLValues( rowValues []string, pkgSchema packet.Schema, converter *UniversalTypeConverter, dbType string, ) ([]any, error)
ConvertRowToSQLValues конвертирует строку TDTP в SQL значения для PreparedStatement Общая утилита для всех адаптеров
func FilterSchemaByFields ¶
FilterSchemaByFields возвращает схему только с запрошенными полями и их индексы в исходной полной схеме. Возвращает ошибку если поле не найдено. Экспортируется для использования в адаптерах (например, mssql).
func GenerateTempTableName ¶
GenerateTempTableName генерирует имя временной таблицы Формат: {table_name}_tmp_{timestamp}
func ParseRowValues ¶
ParseRowValues парсит строку TDTP в массив значений. Общая утилита для всех адаптеров.
func ProjectRows ¶
ProjectRows возвращает только колонки по указанным индексам из каждой строки. Экспортируется для использования в адаптерах (например, mssql).
func ScanSQLRows ¶
func ScanSQLRows(rows *sql.Rows, schema packet.Schema, converter *UniversalTypeConverter, dbType string) ([][]string, error)
ScanSQLRows scans database/sql rows into [][]string using the provided converter. dbType must match the converter's dbType parameter (e.g. "mssql", "sqlite", "mysql"). This eliminates the duplicated scanRows pattern across sql-based adapters.
Every column is scanned into `any`, including SQLite DATE/DATETIME/TIMESTAMP. There used to be a special case that bound those to *string, on the theory that it skipped modernc.parseTime. It did not: modernc keys its time parsing off the column's declared type — exactly the types the special case matched — so the driver still produced a time.Time and database/sql then formatted it back into the string with RFC3339Nano. The path cost an extra format and allocation per cell, left normalizeSQLiteDateTime dead (its input never had the space separator it looked for), carried the driver's own zone into a packet whose schema declares UTC, and — because a string cannot hold NULL — aborted the whole export with "converting NULL to string is unsupported" on the first NULL date.
func StreamSQLRows ¶
func StreamSQLRows(ctx context.Context, rows *sql.Rows, sch packet.Schema, converter *UniversalTypeConverter, dbType string, out chan<- []string) error
StreamSQLRows перекладывает sql.Rows в канал, преобразуя ячейки тем же cellToTDTP, что и построчный ScanSQLRows.
Общий cellToTDTP здесь не для экономии строк: потоковый и обычный экспорт обязаны давать одинаковые байты, иначе выбор режима менял бы данные — и менял бы xxh3, который по ним считается.
Types ¶
type ArenaBlock ¶
type ArenaBlock struct {
Names []string
Columns []*ColumnArena
Rows int
}
ArenaBlock — таблица, разложенная по аренам.
func ScanSQLArena ¶
func ScanSQLArena(rows *sql.Rows, sch packet.Schema, converter *UniversalTypeConverter, dbType string, rowHint int) (*ArenaBlock, error)
ScanSQLArena читает sql.Rows в поколоночные арены.
Отличие от ScanSQLColumns в том, что здесь нет строки на ячейку. Колоночный сканер снял срез на строку, но оставил по string на значение — и именно они, а не срезы, составляли основную массу аллокаций. Здесь значение дописывается в буфер колонки прямо из того, что отдал драйвер.
Быстрый путь берётся не всегда; там, где он не берётся, вызывается обычный cellToTDTP и его результат копируется в буфер. Так что выигрыш зависит от типов колонок, а корректность — нет.
type ColumnArena ¶
ColumnArena — колонка целиком в одном буфере.
Buf хранит значения подряд, каждое завершается '\n'; Offsets[i] — начало значения i, длина Offsets равна числу строк плюс один. Границы задаются смещениями, а не разделителем, — '\n' лежит там для кодека, которому границы записей заметно помогают.
ВНИМАНИЕ: значение может содержать свой '\n'. Смещения от этого не страдают, а вот один Buf как поток — да. Экранирование это забота формата (её делает writeEscaped на записи), и колоночному формату придётся либо экранировать, либо передавать Offsets рядом с данными. Прототип границы не размечает.
func (*ColumnArena) At ¶
func (c *ColumnArena) At(i int) []byte
At отдаёт значение без копирования — срез внутрь Buf, без завершающего '\n'.
func (*ColumnArena) String ¶
func (c *ColumnArena) String(i int) string
String отдаёт значение строкой, аллоцируя. Для сверки и для потребителей, которым нужна строка; в самом колоночном пути звать незачем.
type ColumnBlock ¶
ColumnBlock — таблица, разложенная по колонкам: Values[c][r] это ячейка строки r в колонке c. Names идёт параллельно Values и повторяет порядок schema.Fields.
ПРОТОТИП. Ничем в рабочем пути ещё не используется; смысл в том, чтобы померить, что даёт колоночная раскладка, не переписывая формат.
func ScanSQLColumns ¶
func ScanSQLColumns(rows *sql.Rows, schema packet.Schema, converter *UniversalTypeConverter, dbType string, hint int) (*ColumnBlock, error)
ScanSQLColumns читает sql.Rows сразу по колонкам.
Отличие от ScanSQLRows не в порядке байт, а в том, что аллоцируется. Строчный сканер делает по []string на строку — сто тысяч строк это сто тысяч мелких срезов, каждый со своим заголовком и своей долей работы для сборщика мусора. Здесь срезов ровно столько, сколько колонок, и каждый выделен на всю высоту таблицы разом.
Ячейки проходят через тот же cellToTDTP, что и строчный путь, поэтому значения совпадают байт в байт — на это есть тест.
func (*ColumnBlock) ToRows ¶
func (b *ColumnBlock) ToRows() [][]string
ToRows разворачивает блок обратно в строчную матрицу.
Нужен только для сверки с существующим путём и для тех потребителей, что ещё умеют лишь строки; в самом колоночном экспорте вызывать его незачем — он ровно та аллокация на строку, ради устранения которой всё и затевалось.
type DataInserter ¶
type DataInserter interface {
// InsertRows вставляет строки данных с использованием стратегии
InsertRows(ctx context.Context, tableName string, schema packet.Schema, rows []packet.Row, strategy adapters.ImportStrategy) error
}
DataInserter предоставляет методы для вставки данных
type DataReader ¶
type DataReader interface {
// ReadAllRows читает все строки из таблицы
ReadAllRows(ctx context.Context, tableName string, schema packet.Schema) ([][]string, error)
// ReadRowsWithSQL выполняет SQL запрос и возвращает строки
ReadRowsWithSQL(ctx context.Context, sql string, schema packet.Schema) ([][]string, error)
// GetRowCount возвращает количество строк в таблице
GetRowCount(ctx context.Context, tableName string) (int64, error)
}
DataReader предоставляет методы для чтения данных из таблицы
type ExportHelper ¶
type ExportHelper struct {
// contains filtered or unexported fields
}
ExportHelper содержит общую логику экспорта для всех адаптеров Устраняет дублирование кода между SQLite, PostgreSQL, MS SQL Server, MySQL
func NewExportHelper ¶
func NewExportHelper( schemaReader SchemaReader, dataReader DataReader, valueConverter ValueConverter, sqlAdapter SQLAdapter, ) *ExportHelper
NewExportHelper создает новый ExportHelper
func (*ExportHelper) ExportTable ¶
func (h *ExportHelper) ExportTable(ctx context.Context, tableName string) ([]*packet.DataPacket, error)
ExportTable экспортирует всю таблицу в TDTP reference пакеты Общая реализация для всех адаптеров
func (*ExportHelper) ExportTableIncremental ¶
func (h *ExportHelper) ExportTableIncremental( ctx context.Context, tableName string, incrementalConfig adapters.IncrementalConfig, buildIncrementalSQL func(tableName string, config adapters.IncrementalConfig) (string, []any), executeIncrementalQuery func(ctx context.Context, sql string, args []any, schema packet.Schema) ([][]string, string, error), ) ([]*packet.DataPacket, string, error)
ExportTableIncremental экспортирует только измененные записи с момента последней синхронизации Общая реализация для адаптеров поддерживающих инкрементальную синхронизацию
func (*ExportHelper) ExportTableWithQuery ¶
func (h *ExportHelper) ExportTableWithQuery( ctx context.Context, tableName string, query *packet.Query, sender, recipient string, ) ([]*packet.DataPacket, error)
ExportTableWithQuery экспортирует таблицу с фильтрацией через TDTQL Общая реализация с SQL оптимизацией для всех адаптеров
func (*ExportHelper) SetColumnarLayout ¶
func (h *ExportHelper) SetColumnarLayout(on bool)
SetColumnarLayout включает колоночную раскладку Data (--columnar).
Выключено по умолчанию: атрибут layout меняет смысл <R>, и читатель, ничего о нём не знающий, разберёт пакет неверно и молча. Включать только когда известно, что принимающая сторона умеет разворачивать.
func (*ExportHelper) SetMaxFallbackRows ¶
func (h *ExportHelper) SetMaxFallbackRows(n int64)
SetMaxFallbackRows задаёт лимит строк для in-memory fallback при провале SQL pushdown. При 0 — без лимита (текущее поведение). При > 0 — если таблица больше лимита, возвращается ошибка вместо чтения всей таблицы в RAM. Защищает прод-БД от 17 GB сканов.
func (*ExportHelper) SetMaxMessageSize ¶
func (h *ExportHelper) SetMaxMessageSize(size int)
SetMaxMessageSize задаёт максимальный размер одного TDTP пакета в байтах. Используется адаптерами для передачи настройки --packet-size из CLI.
func (*ExportHelper) SetSkipSpecialValues ¶
func (h *ExportHelper) SetSkipSpecialValues(skip bool)
SetSkipSpecialValues включает режим --fast: DetectAndApply пропускается. NULL/NaN/Inf не получат canonical markers. Применять только для источников без спецзначений или когда скорость важнее полноты метаданных.
type FieldNameRenderer ¶
type FieldNameRenderer interface {
FieldNameRenderer(schema packet.Schema) func(name string) string
}
FieldNameRenderer is optional on an SQLAdapter: it renders field references for the pushdown query instead of the generator's ANSI default (simple names bare). Oracle needs it — a bare `name` is folded to NAME, so a column created as "name" (every table the adapter imports from another engine) failed with ORA-00904 and every filtered export fell back to reading the whole table into memory.
type ImportHelper ¶
type ImportHelper struct {
// contains filtered or unexported fields
}
ImportHelper содержит общую логику импорта для всех адаптеров Устраняет дублирование кода между адаптерами
func NewImportHelper ¶
func NewImportHelper( tableManager TableManager, dataInserter DataInserter, transactionManager TransactionManager, useTemporaryTables bool, ) *ImportHelper
NewImportHelper создает новый ImportHelper
func (*ImportHelper) ImportPacket ¶
func (h *ImportHelper) ImportPacket(ctx context.Context, pkt *packet.DataPacket, strategy adapters.ImportStrategy) error
ImportPacket импортирует один TDTP пакет в БД StrategyCopy (и useTemporaryTables=true): атомарная замена через temp-таблицу. StrategyReplace/Ignore/Fail: прямой UPSERT в существующую таблицу. Общая реализация для всех адаптеров
func (*ImportHelper) ImportPackets ¶
func (h *ImportHelper) ImportPackets(ctx context.Context, packets []*packet.DataPacket, strategy adapters.ImportStrategy) error
ImportPackets импортирует несколько пакетов атомарно (в одной транзакции) Общая реализация для всех адаптеров
type MSSQLAdapter ¶
type MSSQLAdapter struct {
// contains filtered or unexported fields
}
MSSQLAdapter реализует SQLAdapter для MS SQL Server Использует синтаксис OFFSET/FETCH вместо LIMIT
func NewMSSQLAdapter ¶
func NewMSSQLAdapter(schemaName string) *MSSQLAdapter
NewMSSQLAdapter создает MSSQLAdapter
func (*MSSQLAdapter) AdaptSQL ¶
func (a *MSSQLAdapter) AdaptSQL(standardSQL, tableName string, schema packet.Schema, query *packet.Query) string
AdaptSQL адаптирует стандартный SQL под MS SQL Server синтаксис Основные изменения: 1. LIMIT N → FETCH NEXT N ROWS ONLY 2. OFFSET N → OFFSET N ROWS 3. Добавляет ORDER BY если нужен для OFFSET/FETCH (обязательно с 2012+) 4. Квалифицирует имена таблиц: schema.[table] (поддержка "schema.table" формата) 5. Квалифицирует имена полей: [field]
func (*MSSQLAdapter) QuoteIdentifier ¶
func (a *MSSQLAdapter) QuoteIdentifier(identifier string) string
QuoteIdentifier квотирует идентификатор для SQL Server
type ParseFailure ¶
type ParseFailure struct {
Field string
Type string
Count int
Sample string // the first offending value, cut to sampleLen runes
Err string // the first error
Replaced bool // the value was substituted (JSON → "{}"/"[]"), not passed through
}
ParseFailure counts the values of one field that the converter could not handle as the field's declared type, and so wrote to the packet as they came (or, for an unserialisable JSON value, replaced).
This used to be one log line per cell and nothing else: an export with a wrong (p,s) on a DECIMAL column, or a date column holding text, finished successfully, and the only trace was a log nobody read. That is how the MySQL export declaring every DECIMAL as (18,2) went unnoticed — the values still matched on a round trip, because they were passed through raw.
func (ParseFailure) String ¶
func (f ParseFailure) String() string
String renders the failure as one warning line, the same for every caller.
type ParseFailureReporter ¶
type ParseFailureReporter interface {
// ParseFailures returns the failures recorded since the previous call,
// in the order the fields first failed, and clears the tally.
ParseFailures() []ParseFailure
}
ParseFailureReporter is implemented by adapters whose converter keeps a ParseFailure tally. A caller exporting through an adapter asks it once the export is done, and reports what it gets.
type PostgreSQLSchemaAdapter ¶
type PostgreSQLSchemaAdapter struct {
// contains filtered or unexported fields
}
PostgreSQLSchemaAdapter реализует SQLAdapter для PostgreSQL с non-public схемой. Квалифицирует имя таблицы: "schema"."table". Используется когда schema != "public" (т.к. SQLGenerator генерирует только имя таблицы).
func NewPostgreSQLSchemaAdapter ¶
func NewPostgreSQLSchemaAdapter(schema string) *PostgreSQLSchemaAdapter
NewPostgreSQLSchemaAdapter создает PostgreSQLSchemaAdapter для указанной схемы.
type RowPostProcessor ¶
type RowPostProcessor interface {
PostProcessRows(ctx context.Context, schema packet.Schema, rows [][]string) (packet.Schema, [][]string)
}
RowPostProcessor — опциональный интерфейс для постобработки строк после чтения. Адаптеры реализуют его когда нужна специфичная фильтрация столбцов (например, MSSQL фильтрует read-only поля: identity, computed, timestamp). ExportHelper проверяет DataReader на реализацию этого интерфейса и вызывает PostProcessRows перед сборкой пакетов.
type SQLAdapter ¶
type SQLAdapter interface {
// AdaptSQL адаптирует стандартный SQL под синтаксис СУБД
AdaptSQL(standardSQL string, tableName string, schema packet.Schema, query *packet.Query) string
}
SQLAdapter предоставляет методы для адаптации SQL под конкретную СУБД
type SchemaReader ¶
type SchemaReader interface {
GetTableSchema(ctx context.Context, tableName string) (packet.Schema, error)
}
SchemaReader предоставляет методы для чтения схемы таблицы
type StandardSQLAdapter ¶
type StandardSQLAdapter struct {
// contains filtered or unexported fields
}
StandardSQLAdapter реализует SQLAdapter для стандартного SQL (SQLite, PostgreSQL, MySQL) Использует синтаксис LIMIT/OFFSET
func NewStandardSQLAdapter ¶
func NewStandardSQLAdapter(dbType, schemaPrefix, quoteChar string) *StandardSQLAdapter
NewStandardSQLAdapter создает StandardSQLAdapter
type StreamingDataReader ¶
type StreamingDataReader interface {
ReadAllRowsStream(ctx context.Context, tableName string, schema packet.Schema) (packet.Schema, <-chan []string, <-chan error, error)
}
StreamingDataReader — необязательное расширение DataReader: отдаёт строки потоком, не собирая их в память.
Необязательное намеренно. DataReader реализуют пять адаптеров плюс моки в тестах; добавление метода в сам интерфейс сломало бы всех разом ради того, что пока умеет один. Вызывающий проверяет приведением типа и откатывается на ReadAllRows, если потока нет.
Канал строк закрывается по исчерпании данных. Ошибки приходят в отдельный канал: читать его нужно ПОСЛЕ того, как канал строк закрыт, иначе ошибку, случившуюся в середине чтения, легко принять за нормальный конец.
Возвращает схему, которую РЕАЛЬНО будет отдавать, а не ту, что получил. Они расходятся: MSSQL выкидывает read-only колонки (identity, computed, rowversion), и обычный путь делает это хуком PostProcessRows уже после чтения. Потоку постфактум фильтровать нечего — строки уже ушли потребителю, — поэтому схема согласовывается заранее, и вызывающий обязан строить пакеты по возвращённой, а не по переданной.
type TableManager ¶
type TableManager interface {
// TableExists проверяет существование таблицы
TableExists(ctx context.Context, tableName string) (bool, error)
// CreateTable создает таблицу по TDTP схеме
CreateTable(ctx context.Context, tableName string, schema packet.Schema) error
// DropTable удаляет таблицу
DropTable(ctx context.Context, tableName string) error
// RenameTable переименовывает таблицу
RenameTable(ctx context.Context, oldName, newName string) error
}
TableManager предоставляет методы для управления таблицами
type TransactionManager ¶
type TransactionManager interface {
// BeginTx начинает транзакцию
BeginTx(ctx context.Context) (adapters.Tx, error)
}
TransactionManager предоставляет методы для работы с транзакциями
type UniversalTypeConverter ¶
type UniversalTypeConverter struct {
// contains filtered or unexported fields
}
UniversalTypeConverter - универсальный конвертер типов для всех адаптеров Устраняет дублирование кода конвертации между адаптерами
func NewUniversalTypeConverter ¶
func NewUniversalTypeConverter() *UniversalTypeConverter
NewUniversalTypeConverter создает новый UniversalTypeConverter
func (*UniversalTypeConverter) ConvertValueToTDTP ¶
func (c *UniversalTypeConverter) ConvertValueToTDTP(field packet.Field, value string) string
ConvertValueToTDTP конвертирует значение из БД в TDTP формат Общая реализация (вместо 4 копий в адаптерах)
func (*UniversalTypeConverter) DBValueToString ¶
func (c *UniversalTypeConverter) DBValueToString(value any, field packet.Field, dbType string) string
DBValueToString конвертирует значение БД в строку для последующей обработки Общий метод с поддержкой специфичных типов для разных СУБД
func (*UniversalTypeConverter) SetNoDateSentinels ¶
func (c *UniversalTypeConverter) SetNoDateSentinels(dates []string)
SetNoDateSentinels configures date strings that should be treated as "no date" / zero-date. Used for MSSQL conventions like "1900-01-01" or "1753-01-01". At export time: if the date matches a sentinel → encoded as SpecNoDateMarker ("0000-00-00").
func (*UniversalTypeConverter) TakeParseFailures ¶
func (c *UniversalTypeConverter) TakeParseFailures() []ParseFailure
TakeParseFailures returns and clears the failures recorded by ConvertValueToTDTP and the JSON branches of DBValueToString.
func (*UniversalTypeConverter) TypedValueToSQL ¶
func (c *UniversalTypeConverter) TypedValueToSQL(tv schema.TypedValue, dbType string) any
TypedValueToSQL конвертирует TypedValue в значение для SQL Общая реализация для PreparedStatement parameters
type ValueConverter ¶
type ValueConverter interface {
// ConvertValueToTDTP конвертирует значение из БД в TDTP формат
ConvertValueToTDTP(field packet.Field, value string) string
}
ValueConverter предоставляет методы для конвертации значений
type ValueRenderer ¶
type ValueRenderer interface {
ValueRenderer(schema packet.Schema) func(field, value string) (string, bool)
}
ValueRenderer is optional on an SQLAdapter: it renders comparison values with knowledge of the column type (tdtql.SQLGenerator.Value). Oracle uses it for ANSI DATE/TIMESTAMP literals, which do not depend on the session's NLS settings the way a plain '1995-01-01' does.