Documentation
¶
Index ¶
- Constants
- Variables
- func NewDatabase(db *sql.DB, schema dal.Schema, options DbOptions) dal.DB
- func NewSimpleSchema(idFieldName string) dal.Schema
- type DbOptions
- type Field
- type NativeJoinEligibility
- type NativeJoinHintFragments
- type NativeJoinHintTranslator
- type NativeStructuredQueryCompiler
- type PlaceholderDialect
- type Recordset
- type RecordsetType
Constants ¶
const Version = "0.0.8"
Version indicates package version
Variables ¶
var ErrUnsafeName = errors.New("unsafe SQL name")
ErrUnsafeName is wrapped by the error a key read or write returns when a collection, field or primary-key name may not be written into SQL text. The statement is not sent. Test for it with errors.Is.
Names are the one thing of a key read or write that is not a bound parameter, so every name is checked before it enters SQL text:
- With a dialect whose identifier quoting has been reviewed (DbOptions.StructuredQueryDialect "sqlite"), a name must not be empty, contain a control character (NUL included) or invalid UTF-8, or be longer than 255 bytes. It is then written quoted with the quote character escaped, so a name with a space, a quote or a comment marker is an ordinary identifier.
- With no dialect, or one without reviewed quoting, a name must be a plain identifier: a letter or underscore followed by letters, digits or underscores, ASCII only, and no longer than 255 bytes. It is written as given, so the statement text of every name accepted is the text this package has always sent.
A name used to be pasted into the statement as written, so one that carried its own quoting ("Order Details" with the quote characters, [Order Details], a name between backticks) acted as a quoted identifier. It no longer does: with no dialect such a name is refused, and with "sqlite" it is one literal name, quote characters included, that finds no table. A caller passes the bare name (Order Details) with the "sqlite" dialect. With no dialect there is no way to reach a table or column that needs quoting until that engine has reviewed quoting.
Functions ¶
func NewDatabase ¶
NewDatabase creates a new instance of DALgo adapter to SQL database.
The returned dal.DB is sealed by dal.NewDB: every read-write transaction it starts hands the worker a transaction whose writes run the framework's BeforeSave validation and hooks before reaching this adapter's code.
func NewSimpleSchema ¶ added in v0.2.1
Types ¶
type DbOptions ¶ added in v0.4.2
type DbOptions struct {
ID string
PrimaryKey []string
Recordsets map[string]*Recordset
// Placeholder controls how SQL parameter markers are emitted.
// The zero value (PlaceholderQuestion) uses "?" — compatible with
// SQLite, MySQL, and most other drivers. Set to PlaceholderDollar
// for PostgreSQL, which requires "$1", "$2", … positional markers.
Placeholder PlaceholderDialect
// StructuredQueryDialect names the SQL dialect whose identifier quoting has
// been reviewed. Empty preserves legacy emission; "sqlite" is supported. It
// decides two things:
//
// - Structured reads: "sqlite" opts them into safe dialect-specific
// compilation.
// - The collection, field and primary-key names of every key read and write
// (Exists, Get, GetMulti, Insert, Set, SetMulti, Update, UpdateMulti,
// Delete, DeleteMulti): with "sqlite" a name is written quoted, and only an
// empty name, a control character, invalid UTF-8 or more than 255 bytes is
// refused; with an empty or any other value a name must be a plain
// identifier (letters, digits and underscores, not starting with a digit,
// at most 255 bytes), or the call fails with ErrUnsafeName and sends no
// statement.
//
// A name that carries its own quoting ("Order Details" with the quote
// characters, [Order Details]) is no longer a quoted identifier: with "sqlite"
// it is one literal name, quote characters included, and finds no table, so
// pass the bare name; with no dialect it is refused.
StructuredQueryDialect string
// NativeJoinHintTranslator optionally translates validated DALgo JOIN
// algorithm preferences into trusted, dialect-owned SQL fragments. The
// translator receives the complete relation tree so it can preserve each
// edge's independent preference order. Nil is the adapter's explicit ignore
// policy: a custom compiler receives no fragments. It also preserves the
// existing SQL byte stream, which is how SQLite ignores JOIN hints by default.
NativeJoinHintTranslator NativeJoinHintTranslator
// NativeJoinEligibility is the adapter's opt-in semantic proof for native
// JOIN execution with NativeStructuredQueryCompiler. Both fields are
// required for a non-SQLite native path; a nil hook preserves SQLite's
// transaction-local key preflight and declines other dialects.
NativeJoinEligibility NativeJoinEligibility
// NativeStructuredQueryCompiler emits a complete structured SQL query for a
// trusted adapter dialect. It receives translated JOIN hint fragments on the
// actual read path. dalgo2sql provides no SQL Server or Oracle compiler.
NativeStructuredQueryCompiler NativeStructuredQueryCompiler
// IsAlreadyExists reports whether err — the raw error returned by the
// underlying database/sql driver for a failed INSERT — represents a
// duplicate-key violation (a unique or primary-key constraint failure).
// Detection is driver-specific — pgx's *pgconn.PgError with code
// "23505", go-sql-driver/mysql's *mysql.MySQLError with number 1062,
// modernc.org/sqlite's *sqlite.Error with an SQLITE_CONSTRAINT_* code —
// so dalgo2sql cannot recognize it on its own. The wrapping adapter
// (dalgo2postgres, dalgo2mysql, dalgo2sqlite, …) supplies this hook.
//
// The zero value (nil) is backward compatible: it preserves today's
// behavior exactly, and the raw driver error passes through unwrapped.
// When set and it reports true for an insert's error, dalgo2sql wraps
// that error with record.ErrRecordExists (see execInsert) so callers
// can test it with record.IsAlreadyExists — the driver error itself is
// preserved in the chain, never replaced, so existing callers matching
// on error text or type keep working.
IsAlreadyExists func(err error) bool
}
DbOptions provides database sqlOptions for DALgo - // TODO: document why & how to use
func (DbOptions) GetRecordsetByKey ¶ added in v0.4.2
type NativeJoinEligibility ¶ added in v0.19.0
type NativeJoinEligibility func(context.Context, dal.StructuredQuery) error
NativeJoinEligibility lets a concrete adapter validate whether its native compiler can preserve DALgo JOIN semantics for one complete query.
type NativeJoinHintFragments ¶ added in v0.19.0
type NativeJoinHintFragments struct {
AfterSelect string
JoinOperators map[string]string
AfterQuery string
HandledPaths []string
}
NativeJoinHintFragments identifies where a dialect places its trusted SQL JOIN hints. JoinOperators is keyed by DALgo structural paths such as "from.joins[0]" and is emitted between the JOIN type and JOIN keyword, so a SQL Server adapter can return "HASH" for `INNER HASH JOIN`. AfterSelect and AfterQuery support dialects such as Oracle that place optimizer hints after SELECT or at the end of the statement. HandledPaths must acknowledge every hinted edge as applied or intentionally ignored by adapter policy; a rejected preference is returned as an error. This prevents a configured translator from silently dropping a per-edge preference while using only a statement level fragment.
type NativeJoinHintTranslator ¶ added in v0.19.0
type NativeJoinHintTranslator interface {
TranslateNativeJoinHints(dal.FromSource) (NativeJoinHintFragments, error)
}
NativeJoinHintTranslator translates a complete, validated relation tree for one native SQL query. It is implemented by trusted database adapters, never from DTQL input. An error prevents SQL from being emitted.
type NativeStructuredQueryCompiler ¶ added in v0.19.0
type NativeStructuredQueryCompiler interface {
CompileNativeStructuredQuery(dal.StructuredQuery, NativeJoinHintFragments) (string, []any, error)
}
NativeStructuredQueryCompiler emits a complete structured query for a concrete adapter dialect. Its implementation owns parameter syntax, identifier quoting, and all dialect semantics.
type PlaceholderDialect ¶ added in v0.9.0
type PlaceholderDialect int
PlaceholderDialect selects how positional SQL parameters are formatted. The zero value (PlaceholderQuestion) is backward-compatible with all drivers that accept "?" — SQLite, MySQL, etc.
const ( // PlaceholderQuestion emits "?" for every parameter (default, SQLite/MySQL style). PlaceholderQuestion PlaceholderDialect = iota // PlaceholderDollar emits "$1", "$2", … (PostgreSQL style). PlaceholderDollar )
type Recordset ¶
type Recordset struct {
// contains filtered or unexported fields
}
Recordset hold recordset settings
func NewRecordset ¶ added in v0.0.9
func NewRecordset(name string, t RecordsetType, primaryKey []dal.FieldRef) *Recordset
func (*Recordset) PrimaryKey ¶
func (*Recordset) PrimaryKeyFieldNames ¶ added in v0.0.9
func (*Recordset) Type ¶
func (v *Recordset) Type() RecordsetType
type RecordsetType ¶
type RecordsetType = int
RecordsetType defines type of a database recordset
const ( // Table identifies a table in a database Table RecordsetType = iota )
Source Files
¶
- database.go
- database_options.go
- default_schema.go
- deleter.go
- getter.go
- inserter.go
- native_join_hints.go
- placeholder.go
- projection.go
- reader_base.go
- reader_records.go
- reader_recordset.go
- recordset.go
- recordsets.go
- setter.go
- sql.go
- sql_names.go
- sqlite_emit.go
- sqlite_join_eligibility.go
- sqlite_protected.go
- transaction.go
- updater.go
- upserter.go
- version.go