Documentation
¶
Index ¶
- Constants
- func BuildFirstRowQuery(sourceType, table string) (string, error)
- func BuildIncrementalQuery(sourceType, table, idField string) (string, error)
- func CanonicalDriver(sourceType string) (string, bool)
- func Placeholder(driver string, index int) string
- func QuoteIdent(driver, name string) (string, error)
- func ScanRows(rows *sql.Rows) ([]map[string]any, error)
- func ValidateIdent(name string) error
- type ColumnMapping
Constants ¶
const DefaultMaxRows = 1000
DefaultMaxRows is the maximum number of rows ScanRows will fetch to prevent OOM.
Variables ¶
This section is empty.
Functions ¶
func BuildFirstRowQuery ¶
BuildFirstRowQuery returns a dialect-correct query selecting any single row from a table, with no watermark and no ordering.
It is used for schema probes and for the first read of a table that has no cursor yet. Ordering is intentionally omitted: there is no cursor to advance, so "any row" is the intended semantics and a sort would be wasted work on a large table.
func BuildIncrementalQuery ¶
BuildIncrementalQuery returns a dialect-correct query that selects the single next row after a watermark, ordered ascending by idField. The watermark value is bound as parameter 1; callers must pass it as the only query argument.
Use this instead of hand-writing the query in a connector. Watermark polling looks trivial and is not: the row-limiting clause must be applied after the sort, and three of the four dialect families here spell that differently. Every connector that wrote its own got at least the Oracle case wrong.
Both identifiers are validated and quoted, so the result is injection-safe. An unknown sourceType is an error rather than a guess — emitting plausible SQL for the wrong dialect is the failure mode this helper exists to prevent.
func CanonicalDriver ¶
CanonicalDriver maps a user-facing source/sink type (e.g. "mssql", "postgres") to the actual database/sql driver name that must be passed to sql.Open. It is the single source of truth shared by connection opening and placeholder generation so the two can never drift apart. The second return value reports whether the type is backed by a generic SQL driver.
IMPORTANT: this mapping MUST stay in sync with how connections are opened (see registry.getOrOpenDB). For example "mssql" is opened with the microsoft/go-mssqldb "sqlserver" driver, which only accepts @pN placeholders.
func Placeholder ¶
Placeholder returns a bound-parameter placeholder suitable for the driver and 1-based index. The driver argument may be either a user-facing type label (e.g. "mssql") or an actual driver name (e.g. "sqlserver"); both are normalized through CanonicalDriver so the placeholder style always matches the driver that will ultimately execute the query.
func QuoteIdent ¶
QuoteIdent validates and quotes an SQL identifier (optionally schema-qualified) according to the target driver. It supports dot-separated identifiers like schema.table. Drivers: pgx/postgres -> "name", mysql/mariadb/sqlite -> `name`, mssql -> [name].
It returns an error for any malformed or unsafe identifier. Callers MUST check the error and never splice the result on failure, otherwise an empty identifier would be interpolated straight into the SQL (e.g. "WHERE = $1").
NOTE: quoting makes identifiers case-sensitive. On engines that fold unquoted identifiers (e.g. PostgreSQL lower-cases them) a column physically named "id" must be referenced as "id", not "ID".
func ValidateIdent ¶
ValidateIdent verifies that an identifier (optionally schema/keyspace-qualified) contains only safe characters, has no empty segments, and respects the common length limit, without altering its quoting. Use it for engines (e.g. CQL) where identifiers are interpolated as-is, to prevent SQL/CQL injection.
Types ¶
type ColumnMapping ¶
type ColumnMapping struct {
SourceField string `json:"source_field"`
TargetColumn string `json:"target_column"`
DataType string `json:"data_type"` // Optional, used for auto-creation
IsPrimaryKey bool `json:"is_primary_key"` // Optional
IsNullable bool `json:"is_nullable"` // Optional
IsIdentity bool `json:"is_identity"` // Optional, auto-increment/sequence
}
ColumnMapping defines how a source field maps to a sink column.
func ParseColumnMappings ¶
func ParseColumnMappings(s string) ([]ColumnMapping, error)
ParseColumnMappings parses a JSON string into a slice of ColumnMapping.
A blank source_field is treated as "use the column's own name": it falls back to target_column. Without this normalization an empty source_field resolves to a nil value at write time (evaluator.GetMsgValByPath returns nil for an empty path), so every such column is bound as NULL and rows fail on NOT NULL / PRIMARY KEY constraints. UIs commonly leave source_field blank to mean "same name as the target column", so this default makes that intent work safely.