sqldb

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2026 License: GPL-3.0 Imports: 16 Imported by: 0

Documentation

Overview

Package sqldb contains SQL plugin helpers that are independent of a specific database driver.

Index

Constants

View Source
const CountExact = "exact"

CountExact is the CountFilterKey value that opts into the exact count.

View Source
const CountFilterKey = "count"

CountFilterKey is the page filter a caller sets (filter.count=exact) to ask a table listing for a precise row count. Counting a SQL table is a full scan on every page and every refresh, so it is opt-in.

View Source
const IdentifierPattern = `^[A-Za-z_][A-Za-z0-9_]{0,62}$`
View Source
const RedactedValue = "***"

Variables

This section is empty.

Functions

func AnnotateTableColumn added in v0.1.1

func AnnotateTableColumn(row plugin.TableRow, databaseType string, readOnly bool)

func AnyColumnRedacted

func AnyColumnRedacted(columns, patterns []string) bool

AnyColumnRedacted reports whether any column matches a redaction pattern. Used to refuse exposing a primary key whose own value is sensitive (api_key, token…) — such tables stay read-only rather than leaking the raw key to the browser.

func AtPlaceholder

func AtPlaceholder(n int) string

AtPlaceholder formats @p1, @p2, … (SQL Server).

func AuditParams

func AuditParams(in QueryAudit) map[string]string

func BoolValue

func BoolValue(v any, def bool) bool

func ColonPlaceholder

func ColonPlaceholder(n int) string

ColonPlaceholder formats :1, :2, … (Oracle).

func ColumnsArrayField

func ColumnsArrayField(opts ColumnsField) plugin.Field

ColumnsArrayField builds the create-table "columns" field as a repeatable array of column objects. The submitted value is the same []ColumnSpec shape ParseDDLColumns reads, so handlers bind it unchanged.

func DDLColumn

func DDLColumn(spec ColumnSpec) (string, error)

func DefaultRedactColumnPatterns

func DefaultRedactColumnPatterns() []string

func DisplayBytes

func DisplayBytes(column string, raw []byte) string

func DisplayValue

func DisplayValue(column string, value any) any

func DisplayValues

func DisplayValues(columns []string, values []any) []any

func DollarPlaceholder

func DollarPlaceholder(n int) string

DollarPlaceholder formats $1, $2, … (PostgreSQL, CockroachDB).

func DurationValue

func DurationValue(v any, def time.Duration) time.Duration

func ExactCountRequested added in v0.1.1

func ExactCountRequested(p plugin.PageRequest) bool

ExactCountRequested reports whether the request opted into the exact row count.

func FirstKeyword

func FirstKeyword(statement string) string

func FormatBinaryID

func FormatBinaryID(column string, raw []byte) (string, bool)

func IDLikeColumn

func IDLikeColumn(column string) bool

func IdentifierList

func IdentifierList(raw string, quote func(string) string) ([]string, error)

IdentifierList parses a comma/whitespace separated list of column identifiers, validates each against the safe-identifier rule, and returns them quoted by the supplied quoter (used to build index column lists across dialects).

func IdentifierListValue

func IdentifierListValue(v any, quote func(string) string) ([]string, error)

IdentifierListValue parses a column list supplied either as a multiselect array (the route-sourced options path) or a comma-separated string (free text), so a handler accepts both without caring how the form rendered the field.

func IsDestructiveStatement

func IsDestructiveStatement(statement string) bool

func IsReadOnlyStatement

func IsReadOnlyStatement(statement string) bool

func NormalizeJSONValue

func NormalizeJSONValue(value any) ([]byte, error)

func OffsetPage added in v0.1.1

func OffsetPage[T any](items []T, offset int, more bool, total *int) plugin.Page[T]

OffsetPage assembles a bounded offset-cursor page. total stays nil — the grid then pages by cursor — unless the caller opted into an exact count, or the whole collection fit in the first page, where its size is exact and free.

func OptionalIdentifier

func OptionalIdentifier(raw string) (string, error)

func OverFetch added in v0.1.1

func OverFetch(limit int) int

OverFetch is the row count to ask the driver for when serving a page of size limit: one extra row, whose presence means another page follows — cheaper than counting the table just to know whether a next cursor exists.

func PageLimit added in v0.1.1

func PageLimit(limit, rowLimit int) int

PageLimit clamps a requested page size to the plugin's row limit, falling back to it when the request omits one.

func ParseDDLColumns

func ParseDDLColumns(value any) ([]string, error)

func ParsePatterns

func ParsePatterns(raw string, fallback []string) []string

func Qualified

func Qualified(schema, name string) string

func QueryHash

func QueryHash(query string) string

func QuestionPlaceholder

func QuestionPlaceholder(int) string

QuestionPlaceholder formats ? (MySQL/MariaDB, ClickHouse).

func QuoteIdent

func QuoteIdent(s string) string

func RedactColumn

func RedactColumn(column string, patterns []string) bool

func RedactRows

func RedactRows(columns []string, rows [][]any, patterns []string) [][]any

func SafeDefault

func SafeDefault(s string) bool

func SafeIdentifier

func SafeIdentifier(raw string) (string, error)

func SafeType

func SafeType(s string) bool

func SplitStatements

func SplitStatements(sqlText string) []string

func TLSConfig

func TLSConfig(opts TLSOptions) (*tls.Config, error)

func TableColumnEditor added in v0.1.1

func TableColumnEditor(databaseType string) plugin.ColumnEditor

func TableColumnType added in v0.1.1

func TableColumnType(databaseType string) plugin.ColumnType

func TrimOverFetch added in v0.1.1

func TrimOverFetch[T any](rows []T, limit int) ([]T, bool)

TrimOverFetch cuts an over-fetched result back to one page and reports whether more rows follow.

func ValidateRowKey

func ValidateRowKey(primaryKey []string, key map[string]any) error

ValidateRowKey ensures a client-supplied key is exactly the table's primary key — same columns, no more, no fewer — so a row mutation can only ever target one identified row and a caller cannot turn an arbitrary column into a WHERE clause that sweeps many rows.

Types

type ColumnSpec

type ColumnSpec struct {
	Name     string `json:"name"`
	Type     string `json:"type"`
	Nullable bool   `json:"nullable"`
	Default  string `json:"default"`
	Primary  bool   `json:"primary"`
	Unique   bool   `json:"unique"`
}

type ColumnsField

type ColumnsField struct {
	TypePlaceholder string
	// TypeSuggestions are the dialect's common column types; the type field
	// becomes a free-text autocomplete offering them (custom types stay typable).
	TypeSuggestions []string
	Default         bool
	Primary         bool
	Unique          bool
}

ColumnsField describes which ColumnSpec attributes a dialect's DDL builder honours, so a plugin only exposes sub-fields its handler actually applies.

type CompletionItem

type CompletionItem struct {
	Label  string `json:"label"`
	Type   string `json:"type,omitempty"`
	Detail string `json:"detail,omitempty"`
	Apply  string `json:"apply,omitempty"`
}

type Dialect

type Dialect struct {
	QuoteIdent  func(string) string
	Placeholder Placeholder
}

Dialect builds parameterized single-row DML for one driver's quoting and placeholder style. The table argument is supplied already quoted/qualified by the caller; QuoteIdent quotes a bare column identifier.

func (Dialect) Delete

func (d Dialect) Delete(table string, key map[string]any) (string, []any, error)

Delete builds a DELETE matching the key columns. The key must be non-empty so an editing mistake can never wipe a whole table.

func (Dialect) Insert

func (d Dialect) Insert(table string, values map[string]any) (string, []any, error)

Insert builds an INSERT for the given column values. Column order is stable (sorted) so the statement is deterministic and testable.

func (Dialect) SearchClause

func (d Dialect) SearchClause(textType string, cols []string, term string, start int) (string, []any)

SearchClause builds a case-insensitive "contains" filter across cols for the term, binding one placeholder formatted at position start. textType is the dialect's CAST target so non-text columns are searchable (e.g. "TEXT", "CHAR", "NVARCHAR(MAX)", "VARCHAR2(4000)", "String"). Returns ("", nil) when term or cols is empty; unsafe identifiers are skipped.

func (Dialect) Update

func (d Dialect) Update(table string, key, values map[string]any) (string, []any, error)

Update builds an UPDATE that sets values and matches the key columns. Both maps must be non-empty.

type ForeignKey

type ForeignKey struct {
	Constraint   string
	ChildSchema  string
	ChildTable   string
	ChildColumn  string
	ParentSchema string
	ParentTable  string
	ParentColumn string
}

ForeignKey is one introspected relationship: a child table column that references a parent table column.

func ForeignKeyFromRow

func ForeignKeyFromRow(r map[string]any) ForeignKey

ForeignKeyFromRow reads a foreign key from an introspection row whose columns are aliased to the standard names, so each dialect only writes its own query.

type GraphEdge

type GraphEdge struct {
	ID          string `json:"id,omitempty"`
	Source      string `json:"source"`
	Target      string `json:"target"`
	Label       string `json:"label,omitempty"`
	SourceField string `json:"sourceField,omitempty"`
	TargetField string `json:"targetField,omitempty"`
}

type GraphField

type GraphField struct {
	Name string `json:"name"`
	Type string `json:"type,omitempty"`
	Key  string `json:"key,omitempty"`
}

GraphField is one column rendered inside an ERD table node. Key marks special columns ("fk" for a foreign key) so the panel can badge them.

type GraphNode

type GraphNode struct {
	ID     string       `json:"id"`
	Label  string       `json:"label"`
	Group  string       `json:"group,omitempty"`
	Fields []GraphField `json:"fields,omitempty"`
}

type GraphPayload

type GraphPayload struct {
	Nodes []GraphNode `json:"nodes"`
	Edges []GraphEdge `json:"edges"`
}

GraphPayload is the {nodes, edges} document the generic graph panel renders. Relational schemas reuse the same panel the graph databases use; the optional Fields turn a node into an ERD table box, and the edge field anchors let the panel draw a foreign key from the exact child column to the parent column.

func RelationGraph

func RelationGraph(columns []TableColumn, fks []ForeignKey) GraphPayload

RelationGraph builds an ERD: one node per table (listing its columns), one edge per foreign key, anchored from the child column to the parent column. Tables referenced by a foreign key but absent from columns still get a (fieldless) node so no edge dangles. Labels are schema-qualified only when more than one schema is present, to keep the common single-schema diagram clean.

type Placeholder

type Placeholder func(n int) string

Placeholder formats a bind placeholder for the 1-based argument position so the row DML builder stays driver-neutral.

type QueryAudit

type QueryAudit struct {
	Query          string
	Statements     []string
	Confirmed      bool
	ReadOnlyMode   bool
	RequiresReview bool
	RowCount       int64
	ElapsedMS      int64
	CommandTag     string
}

type QueryRequest

type QueryRequest struct {
	Query     string `json:"query"`
	Confirm   bool   `json:"confirm,omitempty"`
	RequestID string `json:"requestId,omitempty"`
}

type QueryResult

type QueryResult struct {
	Columns    []string          `json:"columns"`
	Rows       [][]any           `json:"rows"`
	RowCount   int64             `json:"rowCount,omitempty"`
	ElapsedMS  int64             `json:"elapsedMs"`
	Statement  string            `json:"statement,omitempty"`
	CommandTag string            `json:"commandTag,omitempty"`
	Statements []StatementResult `json:"statements,omitempty"`
}

type RowMutation

type RowMutation struct {
	Key    map[string]any `json:"key,omitempty"`
	Values map[string]any `json:"values,omitempty"`
}

RowMutation is the uniform request body for the editable data grid's insert/update/delete routes. Insert sends Values, Update sends Key+Values, Delete sends Key. Keys are the table's identifying columns; the renderer reads their values straight from the row it edited.

type StatementResult

type StatementResult struct {
	Columns    []string `json:"columns"`
	Rows       [][]any  `json:"rows"`
	RowCount   int64    `json:"rowCount,omitempty"`
	ElapsedMS  int64    `json:"elapsedMs"`
	Statement  string   `json:"statement"`
	CommandTag string   `json:"commandTag,omitempty"`
}

type TLSOptions

type TLSOptions struct {
	Mode              string
	Host              string
	CACertificate     string
	ClientCertificate string
}

type TableColumn

type TableColumn struct {
	Schema string
	Table  string
	Name   string
	Type   string
}

TableColumn is one column of a table, used to build ERD table nodes.

func TableColumnFromRow

func TableColumnFromRow(r map[string]any) TableColumn

TableColumnFromRow reads a column from an introspection row aliased to the standard names (table_schema, table_name, column_name, data_type).

Jump to

Keyboard shortcuts

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