Package sql
import "github.com/ornew/hff/backends/sql"
Generated from this checkout's Go source. Released versions are also on pkg.go.dev.
Overview
Package sql translates compiled HFF Programs into parameterized PostgreSQL predicates. It does not open a database connection or execute SQL.
Compile a query with an engine, then call Build with an explicit dialect and bindings for the HFF fields that query uses. Bindings describe storage, not query syntax: Bind maps a scalar column, BindJSON maps a document, BindComposite maps a native struct, BindStruct maps fields spread across columns, and BindRelation maps a list to correlated rows.
Query.Where returns a predicate fragment, not a SELECT statement. Append it to a caller-owned statement and pass Query.Args() to the database driver as parameters. Column quotes literal identifier components; it does not accept SQL expressions. HFF paths and physical SQL names are independent.
Use ColumnValue, Literal, Equal, IsNull, And, and related constructors for parent-state and relation predicates. Their scalar types describe a contract with the application's database schema; Build does not inspect actual column types. TrustedSQL accepts reviewed raw source as an escape hatch and does not parse, sanitize, or prove its meaning, purity, or portability.
Build rejects operations whose HFF meaning cannot be preserved by the selected representation. JSONB numeric metadata can restore supported numeric distinctions; its consistency with data is a caller-owned storage contract. Profile and Query.Profile expose support and guarantees separately from the engine's capability policy. PostgreSQL execution does not enforce HFF step budgets; the application configures database timeouts and resource controls.
Index
func Profile(dialect Dialect) (hff.Profile, error)type Bindingfunc Bind(path hff.Path, column ColumnRef) Bindingfunc BindComposite(path hff.Path, column ColumnRef) Bindingfunc BindJSON(path hff.Path, column ColumnRef, format JSONFormat, options ...JSONBindingOption) Bindingfunc BindRelation(path hff.Path, relation Relation) Bindingfunc BindStruct(path hff.Path, present, null SQLPredicate, fields ...Binding) Bindingfunc BindTimestamp(path hff.Path, column ColumnRef, options ...TimestampBindingOption) Bindingfunc (b Binding) View() BindingView
type BindingViewtype Calltype ColumnReftype Configtype Dialecttype ExecutionLimitstype Expressiontype Guaranteestype JSONBindingOptiontype JSONFormattype MethodFunctype MethodImplementationfunc Implement(declaration hff.MethodDeclaration, dialect Dialect, function MethodFunc) MethodImplementationfunc (m MethodImplementation) Declaration() hff.MethodDeclarationfunc (m MethodImplementation) Dialect() Dialectfunc (m MethodImplementation) SameRegistration(other MethodImplementation) boolfunc (m MethodImplementation) Valid() bool
type Optiontype OrderViewtype PredicateViewtype Querytype Relationtype RelationOptionfunc WithCorrelation(predicate SQLPredicate) RelationOptionfunc WithRelationItem(typ hff.Type, item Binding) RelationOptionfunc WithRelationSource(table ColumnRef, alias string) RelationOptionfunc WithRelationState(present, null SQLPredicate) RelationOptionfunc WithUniqueOrder(order ...RelationOrder) RelationOption
type RelationOrdertype RelationViewtype SQLPredicatefunc And(predicates ...SQLPredicate) SQLPredicatefunc AsPredicate(value Scalar) SQLPredicatefunc Boolean(value bool) SQLPredicatefunc Equal(left, right Scalar) SQLPredicatefunc IsNotNull(value Scalar) SQLPredicatefunc IsNull(value Scalar) SQLPredicatefunc Not(predicate SQLPredicate) SQLPredicatefunc Or(predicates ...SQLPredicate) SQLPredicatefunc TrustedSQL(code string, references ...ColumnRef) SQLPredicatefunc (p SQLPredicate) View() PredicateView
type Scalartype ScalarViewtype TimestampBindingOption
Functions
func Profile
func Profile(dialect Dialect) (hff.Profile, error)
Profile describes statically known translation support for a dialect without connecting to a database. Unicode casing and regex parsing report their Go implementation versions; database, collation, database regex engine, and time-zone versions remain unknown.
Types
type Binding
type Binding struct {
// contains filtered or unexported fields
}
Binding maps one literal HFF schema path to a physical SQL representation. Construct bindings with Bind, BindTimestamp, BindJSON, BindComposite, BindStruct, or BindRelation, then pass them to Build through WithBindings.
func Bind
func Bind(path hff.Path, column ColumnRef) Binding
Bind maps a scalar HFF path to a SQL column. Path components are literal field names, not dotted text; the caller guarantees column type and data satisfy the declared HFF schema. Duration values use bigint nanoseconds.
func BindComposite
func BindComposite(path hff.Path, column ColumnRef) Binding
BindComposite maps a struct path to one native PostgreSQL composite column. SQL attribute names must match HFF schema field names. Composite attributes are always present: an SQL NULL attribute is an explicit HFF null, not an absent optional field. The caller must store schema-compatible data using supported physical types, including one-dimensional SQL arrays for list fields. Build does not inspect the database or verify actual array rank. PostgreSQL array lower bounds do not change HFF's zero-based indexing.
func BindJSON
func BindJSON(path hff.Path, column ColumnRef, format JSONFormat, options ...JSONBindingOption) Binding
BindJSON maps one HFF schema path to a PostgreSQL json or jsonb column. The declared HFF schema supplies scalar subtypes; the caller must store documents valid for that schema and selected format. Build rejects operations whose distinctions cannot be recovered from the stored representation. Options configure metadata for distinctions that JSONB does not preserve.
Schema-known Bytes use canonical padded standard-base64 JSON strings, and schema-known Duration values use canonical duration strings, and schema-known Timestamp values use canonical UTC RFC 3339 strings. The same spelling under Any remains String; ambiguous string-family unions cannot recover their type identity and are rejected when consumed.
func BindRelation
func BindRelation(path hff.Path, relation Relation) Binding
BindRelation binds an HFF list path to a configured correlated row source.
func BindStruct
func BindStruct(path hff.Path, present, null SQLPredicate, fields ...Binding) Binding
BindStruct maps one HFF struct at path to separate columns and explicit parent-state predicates. present is true when the logical object exists; null is true when that present object is logically null. Neither state is inferred from child columns. Each child Binding path is exactly one literal field name relative to this struct; nest BindStruct for nested parent states. Unbound optional fields are absent, while required fields need a binding. A bound scalar SQL NULL means an explicit null field, never omission. The caller owns the truth and deterministic behavior of both predicates and the schema/data contract. BindTimestamp may map a Timestamp child for direct field predicates, but materializing the whole struct with that child is not yet supported.
func BindTimestamp
func BindTimestamp(path hff.Path, column ColumnRef, options ...TimestampBindingOption) Binding
BindTimestamp maps one schema-known Timestamp field to timestamptz storage. It may also be a relative BindStruct child or a BindRelation item for direct Timestamp predicates. Materializing a whole container containing Timestamp remains unsupported. HFF's year 0000 maps to PostgreSQL 1 BC. The caller guarantees stored values are finite, within HFF's years 0000–9999, and satisfy the declared schema. This binding never rounds a query value.
func (Binding) View
func (b Binding) View() BindingView
View returns a recursive, detached description of the binding. Invalid option values remain visible and must be rejected by the caller's usual Build validation before a configuration is used.
type BindingView
type BindingView struct {
Kind string
Invalid bool
Path hff.Path
Column []string
Format JSONFormat
Metadata []string
TimestampRemainder []string
Present PredicateView
Null PredicateView
Fields []BindingView
Relation *RelationView
}
BindingView is a detached description of one physical mapping. Kind is one of native, json, composite, timestamp, struct, or relation. Nested paths remain relative to their enclosing struct or relation item.
type Call
type Call struct {
// contains filtered or unexported fields
}
Call provides the selected dialect, context, and constructors to a translator. Helpers may be called concurrently while translation is active; retaining Call or its expressions for later work is invalid.
func (*Call) Context
func (c *Call) Context() context.Context
Context returns the Build context for this translation, or nil for a nil Call.
func (*Call) Dialect
func (c *Call) Dialect() Dialect
Dialect reports the dialect for this translation.
func (*Call) Expression
func (c *Call) Expression(typ hff.Type, template string, args ...Expression) (Expression, error)
Expression fills each {} in a fixed developer-authored SQL template with a scoped Expression and declares the result's HFF scalar type. Never put query text or record data in the template: use Parameter for values. Templates must not contain $N parameters. HFF checks ownership, placeholder count, and type shape, but does not parse or prove SQL semantics, purity, or database function behavior; the translator author owns those contracts.
Example
{
declaration, err := hff.NewMethodDeclaration(hff.MethodConfig{
ID: "example.emphasis", Name: "emphasis", Receiver: schema.StringType,
Result: schema.StringType, BaseCost: 1,
})
if err != nil {
panic(err)
}
e, err := engine.New(
engine.WithSchema(schema.Struct(schema.String("name"))),
engine.WithCapabilities(capabilities.Standard().Allow(capabilities.Method(declaration.ID()))),
engine.WithMethods(declaration),
)
if err != nil {
panic(err)
}
ctx := context.Background()
program, err := e.Compile(ctx, `name:emphasis="Alice!"`)
if err != nil {
panic(err)
}
implementation := hffsql.Implement(declaration, hffsql.PostgreSQL,
func(call *hffsql.Call, receiver hffsql.Expression, args []hffsql.Expression) (hffsql.Expression, error) {
suffix, err := call.Parameter(hff.String("!"))
if err != nil {
return hffsql.Expression{}, err
}
return call.Expression(schema.StringType, "({} || {})", receiver, suffix)
})
query, err := hffsql.Build(ctx, program,
hffsql.WithDialect(hffsql.PostgreSQL),
hffsql.WithBindings(hffsql.Bind(hff.Path{"name"}, hffsql.Column("people", "name"))),
hffsql.WithMethods(implementation),
)
if err != nil {
panic(err)
}
fmt.Println(query.Args())
}
Complete runnable example
package main
import (
"context"
"fmt"
"github.com/ornew/hff"
hffsql "github.com/ornew/hff/backends/sql"
"github.com/ornew/hff/capabilities"
"github.com/ornew/hff/engine"
"github.com/ornew/hff/schema"
)
func main() {
declaration, err := hff.NewMethodDeclaration(hff.MethodConfig{
ID: "example.emphasis", Name: "emphasis", Receiver: schema.StringType,
Result: schema.StringType, BaseCost: 1,
})
if err != nil {
panic(err)
}
e, err := engine.New(
engine.WithSchema(schema.Struct(schema.String("name"))),
engine.WithCapabilities(capabilities.Standard().Allow(capabilities.Method(declaration.ID()))),
engine.WithMethods(declaration),
)
if err != nil {
panic(err)
}
ctx := context.Background()
program, err := e.Compile(ctx, `name:emphasis="Alice!"`)
if err != nil {
panic(err)
}
implementation := hffsql.Implement(declaration, hffsql.PostgreSQL,
func(call *hffsql.Call, receiver hffsql.Expression, args []hffsql.Expression) (hffsql.Expression, error) {
suffix, err := call.Parameter(hff.String("!"))
if err != nil {
return hffsql.Expression{}, err
}
// {} inserts scoped expressions; values are driver parameters. The
// developer owns the SQL template's types, meaning and purity.
return call.Expression(schema.StringType, "({} || {})", receiver, suffix)
})
query, err := hffsql.Build(ctx, program,
hffsql.WithDialect(hffsql.PostgreSQL),
hffsql.WithBindings(hffsql.Bind(hff.Path{"name"}, hffsql.Column("people", "name"))),
hffsql.WithMethods(implementation),
)
if err != nil {
panic(err)
}
fmt.Println(query.Args())
}
Output:
[! Alice!]
func (*Call) Parameter
func (c *Call) Parameter(value hff.Value) (Expression, error)
Parameter binds a supported HFF scalar using the dialect's validated driver encoding and returns an expression scoped to this Call. PostgreSQL accepts null, bool, int, finite float, string, and bytes. Bytes are bound as immutable hexadecimal text and decoded to bytea; Query.Args never exposes a mutable byte slice. Strings must be valid UTF-8 without NUL.
type ColumnRef
type ColumnRef struct {
// contains filtered or unexported fields
}
ColumnRef is a sequence of literal SQL identifier components, never an SQL expression. Components are quoted separately by Build.
func Column
func Column(parts ...string) ColumnRef
Column constructs a reference from literal identifier components, such as Column("orders", "tenant_id"). It does not accept SQL expressions.
type Config
type Config struct {
// Dialect is required and must currently be PostgreSQL.
Dialect Dialect
// Bindings maps the HFF schema paths used by the Program to SQL storage.
Bindings []Binding
// Methods contains SQL translators for declared extension methods.
Methods []MethodImplementation
// ExecutionLimits requests HFF runtime budgets; positive PostgreSQL requests
// fail because the database translator cannot enforce them.
ExecutionLimits ExecutionLimits
}
Config is the SQL Build configuration. An explicit dialect is required; bindings must cover every schema path used by the Program. Method implementations add SQL translations for declared extension methods.
type Dialect
type Dialect string
Dialect identifies the SQL translation contract. Build requires an explicit dialect; this package currently implements PostgreSQL only.
const PostgreSQL Dialect = "postgresql"
PostgreSQL selects the PostgreSQL translation contract.
type ExecutionLimits
type ExecutionLimits struct {
// MaxSteps requests a maximum HFF runtime work count.
MaxSteps int
// MaxGeneratedValues requests a maximum count of generated HFF values.
MaxGeneratedValues int
}
ExecutionLimits requests per-record HFF evaluation budgets from a backend. Zero requests no guarantee; negative values are invalid. These are HFF budgets, not PostgreSQL statement timeouts.
type Expression
type Expression struct {
// contains filtered or unexported fields
}
Expression is an immutable typed scalar SQL value scoped to one translation Call. Its zero value is invalid. Raw SQL and internal presence flags are not exposed; the declared type does not prove the SQL expression's behavior.
func (Expression) Type
func (e Expression) Type() hff.Type
Type returns the declared HFF scalar type of e.
func (Expression) Valid
func (e Expression) Valid() bool
Valid reports whether e has a translator owner and a declared type. It does not extend its lifetime: expressions may only be used during their own Call.
type Guarantees
type Guarantees struct {
// MaxSteps reports enforcement of per-record HFF runtime steps.
MaxSteps bool
// MaxGeneratedValues reports enforcement of generated HFF value count.
MaxGeneratedValues bool
}
Guarantees reports whether a backend can enforce the requested HFF budgets.
func ExecutionGuarantees
func ExecutionGuarantees(dialect Dialect) (Guarantees, error)
ExecutionGuarantees reports runtime-budget support for a dialect without building a particular Program or contacting a database.
type JSONBindingOption
type JSONBindingOption struct {
// contains filtered or unexported fields
}
JSONBindingOption configures one physical JSON binding. BindJSON applies options from left to right; later metadata options replace earlier ones. A zero option is invalid and is rejected during Build.
func WithTypeMetadata
func WithTypeMetadata(column ColumnRef) JSONBindingOption
WithTypeMetadata binds a JSONB column containing version-1 JSON Pointer metadata relative to the data document. The caller guarantees its consistency with the data and schema, including version 1 and every required type/text entry. Metadata currently restores int/float distinctions and numeric text; it does not encode bytes, timestamps, or durations. Build rejects unsupported configurations but does not inspect rows or validate stored metadata. Use it as BindJSON(path, dataColumn, JSONB, WithTypeMetadata(metadataColumn)).
type JSONFormat
type JSONFormat string
JSONFormat describes the physical PostgreSQL column, not a query syntax.
const (
// JSON selects PostgreSQL's native json physical representation.
JSON JSONFormat = "json"
// JSONB selects PostgreSQL's jsonb physical representation.
JSONB JSONFormat = "jsonb"
)
type MethodFunc
type MethodFunc func(call *Call, receiver Expression, args []Expression) (Expression, error)
MethodFunc translates one declared extension during Build. The function must be deterministic, side-effect-free, safe for concurrent Builds, and preserve the declaration's semantics on the domain it accepts. Return an error when faithful translation is unavailable. SQL execution remains caller-owned.
type MethodImplementation
type MethodImplementation struct {
// contains filtered or unexported fields
}
MethodImplementation associates an extension declaration with one dialect translator. The translator is invoked during Build, never for each database row.
func Implement
func Implement(declaration hff.MethodDeclaration, dialect Dialect, function MethodFunc) MethodImplementation
Implement registers a translator for declaration under dialect. Build checks that the declaration exactly matches the one compiled into the Program.
func (MethodImplementation) Declaration
func (m MethodImplementation) Declaration() hff.MethodDeclaration
Declaration returns the immutable signature this translator implements. It does not expose or invoke the executable translation function.
func (MethodImplementation) Dialect
func (m MethodImplementation) Dialect() Dialect
Dialect returns the dialect selected when this translator was registered.
func (MethodImplementation) SameRegistration
func (m MethodImplementation) SameRegistration(other MethodImplementation) bool
SameRegistration reports whether two values came from the same Implement call, including copies of that immutable registration. Equal signatures do not prove that independently registered functions have equal behavior.
func (MethodImplementation) Valid
func (m MethodImplementation) Valid() bool
Valid reports whether the translator has a declaration and an executable function. A zero implementation or one made with a nil function is invalid.
type Option
type Option struct {
// contains filtered or unexported fields
}
Option changes one SQL Build setting. Options apply from left to right.
func WithBindings
func WithBindings(bindings ...Binding) Option
WithBindings replaces the schema-to-column mappings used by Build. The slice is copied; each path and physical representation is explicit.
func WithConfig
func WithConfig(config *Config) Option
WithConfig copies a complete SQL configuration. Nil is rejected, and later options replace settings copied from this value.
func WithDialect
func WithDialect(dialect Dialect) Option
WithDialect selects the required SQL dialect. PostgreSQL is currently the only supported dialect.
func WithExecutionLimits
func WithExecutionLimits(limits ExecutionLimits) Option
WithExecutionLimits requests backend-enforced HFF runtime budgets during SQL execution. PostgreSQL rejects positive requests because it cannot enforce them; configure database execution limits through the caller instead.
func WithMethods
func WithMethods(methods ...MethodImplementation) Option
WithMethods replaces the translators configured for SQL Build. The slice is copied; implementations must be safe for concurrent Build calls.
type OrderView
type OrderView struct {
Column []string
Type hff.Type
Descending bool
NullsFirst bool
}
OrderView describes one typed component of a relation's unique order.
type PredicateView
type PredicateView struct {
Kind string
Left ScalarView
Right ScalarView
Children []PredicateView
Boolean bool
TrustedCode string
References [][]string
}
PredicateView describes a typed predicate tree or a trusted SQL expression. TrustedCode is developer-authored SQL. A serializer must replace it with an ID from a trusted registry rather than writing that text to an untrusted configuration document.
type Query
type Query struct {
// contains filtered or unexported fields
}
Query owns a reusable PostgreSQL WHERE predicate and its ordered driver parameters. It performs no database I/O, chooses no tables, and does not execute a query; the caller integrates Where and Args into its own SQL.
func Build
func Build(ctx context.Context, program hff.Program, options ...Option) (*Query, error)
Build checks whether PostgreSQL can preserve the Program's supported semantics and translates it to a reusable Query. It performs no database access or record validation. Query values remain bound arguments rather than interpolated SQL. Options apply left to right; unsupported operations return source-located BackendErrors.
Example
{
ctx := context.Background()
e, err := engine.New(engine.WithSchema(schema.Struct(schema.Int("age"))),
engine.WithCapabilities(capabilities.Standard()))
if err != nil {
panic(err)
}
program, err := e.Compile(ctx, `age>=18`)
if err != nil {
panic(err)
}
query, err := hffsql.Build(ctx, program,
hffsql.WithDialect(hffsql.PostgreSQL),
hffsql.WithBindings(hffsql.Bind(hff.Path{"age"}, hffsql.Column("people", "age"))),
)
if err != nil {
panic(err)
}
statement := `SELECT "people"."id" FROM "people" WHERE ` + query.Where()
fmt.Println("statement built:", statement != "")
fmt.Println("bound values:", query.Args())
}
Complete runnable example
package main
import (
"context"
"fmt"
"github.com/ornew/hff"
hffsql "github.com/ornew/hff/backends/sql"
"github.com/ornew/hff/capabilities"
"github.com/ornew/hff/engine"
"github.com/ornew/hff/schema"
)
func main() {
ctx := context.Background()
e, err := engine.New(engine.WithSchema(schema.Struct(schema.Int("age"))),
engine.WithCapabilities(capabilities.Standard()))
if err != nil {
panic(err)
}
program, err := e.Compile(ctx, `age>=18`)
if err != nil {
panic(err)
}
query, err := hffsql.Build(ctx, program,
hffsql.WithDialect(hffsql.PostgreSQL),
hffsql.WithBindings(hffsql.Bind(hff.Path{"age"}, hffsql.Column("people", "age"))),
)
if err != nil {
panic(err)
}
// Supply this statement and Args to your driver's QueryContext. Build never
// connects to the database, and Where is only the predicate fragment.
statement := `SELECT "people"."id" FROM "people" WHERE ` + query.Where()
fmt.Println("statement built:", statement != "")
fmt.Println("bound values:", query.Args())
}
Output:
statement built: true bound values: [18]
func (*Query) Args
func (q *Query) Args() []any
Args returns a fresh, ordered slice of driver arguments corresponding to the placeholders in Where. Current encodings are immutable scalars.
func (*Query) Guarantees
func (q *Query) Guarantees() Guarantees
Guarantees reports budgets enforceable by this Query's backend. PostgreSQL currently reports neither HFF step nor generated-value budget enforcement.
func (*Query) Profile
func (q *Query) Profile() hff.Profile
Profile returns the built query's translation contract, including its compile policy, limits, and registered translations. It does not inspect the executing database or turn caller-owned storage guarantees into HFF checks.
func (*Query) Where
func (q *Query) Where() string
Where returns the generated Boolean SQL expression without a WHERE keyword. A nil Query returns an empty string.
type Relation
type Relation struct {
// contains filtered or unexported fields
}
Relation describes a caller-owned PostgreSQL row source correlated to the enclosing query. Each selected source row represents one HFF list item. Construction and Build perform no database I/O; the caller owns the table, data/schema validity, database execution, and query timeouts.
func NewRelation
func NewRelation(options ...RelationOption) (Relation, error)
NewRelation validates and snapshots a caller-owned relation description. Source, correlation, and an item binding are required. State defaults to a present non-null list; order is optional unless a used operation depends on order. Identifiers are validated here, but table contents are not inspected.
Example
{
itemType := schema.Struct(schema.Int("price"))
relation, err := hffsql.NewRelation(
hffsql.WithRelationSource(hffsql.Column("order_items"), "item"),
hffsql.WithCorrelation(hffsql.Equal(
hffsql.ColumnValue(hffsql.Column("item", "order_id"), schema.IntType),
hffsql.ColumnValue(hffsql.Column("orders", "id"), schema.IntType),
)),
hffsql.WithRelationItem(itemType,
hffsql.BindStruct(hff.Path{}, hffsql.Boolean(true), hffsql.Boolean(false),
hffsql.Bind(hff.Path{"price"}, hffsql.Column("item", "price")))),
hffsql.WithUniqueOrder(hffsql.Ascending(hffsql.Column("item", "id"), schema.IntType)),
)
if err != nil {
panic(err)
}
binding := hffsql.BindRelation(hff.Path{"items"}, relation)
_ = binding
fmt.Println("relation configured without DB access")
}
Complete runnable example
package main
import (
"fmt"
"github.com/ornew/hff"
hffsql "github.com/ornew/hff/backends/sql"
"github.com/ornew/hff/schema"
)
func main() {
// HFF sees items as a list of objects. SQL stores one item per child row.
itemType := schema.Struct(schema.Int("price"))
relation, err := hffsql.NewRelation(
hffsql.WithRelationSource(hffsql.Column("order_items"), "item"),
hffsql.WithCorrelation(hffsql.Equal(
hffsql.ColumnValue(hffsql.Column("item", "order_id"), schema.IntType),
hffsql.ColumnValue(hffsql.Column("orders", "id"), schema.IntType),
)),
hffsql.WithRelationItem(itemType,
hffsql.BindStruct(hff.Path{}, hffsql.Boolean(true), hffsql.Boolean(false),
hffsql.Bind(hff.Path{"price"}, hffsql.Column("item", "price")))),
// The application guarantees that this order tuple is unique.
hffsql.WithUniqueOrder(hffsql.Ascending(hffsql.Column("item", "id"), schema.IntType)),
)
if err != nil {
panic(err)
}
// Pass the root-path binding to WithBindings when building the Program.
binding := hffsql.BindRelation(hff.Path{"items"}, relation)
_ = binding
fmt.Println("relation configured without DB access")
}
Output:
relation configured without DB access
type RelationOption
type RelationOption struct {
// contains filtered or unexported fields
}
RelationOption configures a Relation. NewRelation applies options in order.
func WithCorrelation
func WithCorrelation(predicate SQLPredicate) RelationOption
WithCorrelation supplies the predicate that relates source rows to the enclosing record. Build lowers it to a correlated PostgreSQL condition. Prefer typed SQLPredicate constructors; the condition must accurately and deterministically express the intended relationship.
func WithRelationItem
func WithRelationItem(typ hff.Type, item Binding) RelationOption
WithRelationItem declares the exact HFF element type and maps each source row to one item. The Binding path must be empty because it is relative to that row; use BindStruct for a flattened struct item or another binding for its physical representation. BindTimestamp supports Timestamp item predicates; materializing a whole relation containing Timestamp items is not yet supported.
func WithRelationSource
func WithRelationSource(table ColumnRef, alias string) RelationOption
WithRelationSource selects a literal table identifier and local SQL alias. The alias is visible to the correlation and item bindings.
func WithRelationState
func WithRelationState(present, null SQLPredicate) RelationOption
WithRelationState supplies explicit predicates for a relation's logical list presence and null state. Without it, the list is present and non-null even when the row source has no matching rows (an empty list). The caller owns the truth and deterministic behavior of these predicates.
func WithUniqueOrder
func WithUniqueOrder(order ...RelationOrder) RelationOption
WithUniqueOrder configures the order tuple that the caller guarantees is unique. Order is required only for operations whose results depend on item order, such as indexing, stable sort ties, order-observed map results, or folds.
type RelationOrder
type RelationOrder struct {
// contains filtered or unexported fields
}
RelationOrder is one component of an immutable typed row ordering. PostgreSQL scalar ordering is used. The caller guarantees the complete order tuple is unique whenever the HFF operation depends on stable element order.
func Ascending
func Ascending(column ColumnRef, typ hff.Type) RelationOrder
Ascending orders a relation by the given typed SQL column in ascending order.
func Descending
func Descending(column ColumnRef, typ hff.Type) RelationOrder
Descending orders a relation by the given typed SQL column in descending order.
func NullsFirst
func NullsFirst(order RelationOrder) RelationOrder
NullsFirst returns an ordering with null values before non-null values.
type RelationView
type RelationView struct {
Table []string
Alias string
Correlation PredicateView
Present PredicateView
Null PredicateView
ItemType hff.Type
Item BindingView
Order []OrderView
}
RelationView describes a correlated row source and its item mapping. An empty Order means order-dependent operations are unavailable.
type SQLPredicate
type SQLPredicate struct {
// contains filtered or unexported fields
}
SQLPredicate is an immutable PostgreSQL Boolean expression used for explicit parent-state and relation conditions. Prefer typed constructors such as Equal, IsNull, And, and AsPredicate: they quote identifiers and bind literal values. TrustedSQL is an escape hatch for developer-authored SQL and is not parsed or proven equivalent to HFF by this package.
func And
func And(predicates ...SQLPredicate) SQLPredicate
And combines predicates using SQL AND semantics. SQL NULL remains unknown.
func AsPredicate
func AsPredicate(value Scalar) SQLPredicate
AsPredicate uses a Boolean scalar as a SQL predicate. It preserves SQL's three-valued NULL behavior; it does not coerce SQL NULL to false. Use it only where SQL truth semantics are the intended predicate semantics.
func Boolean
func Boolean(value bool) SQLPredicate
Boolean constructs a fixed SQL TRUE/FALSE predicate without raw SQL.
func Equal
func Equal(left, right Scalar) SQLPredicate
Equal constructs SQL equality between matching scalar kinds. int64 and float64 are not implicitly promoted. For example, use Equal(ColumnValue(...), Literal(hff.Int(17))) to compare a declared int64 column with a bound value. SQL NULL yields unknown, not an HFF null-identity comparison; use IsNull or IsNotNull to test SQL null.
Example
{
ctx := context.Background()
e, err := engine.New(engine.WithSchema(schema.Struct(
schema.Optional(schema.Field("profile", schema.Struct(schema.String("name")))),
)), engine.WithCapabilities(capabilities.Standard()))
if err != nil {
panic(err)
}
program, err := e.Compile(ctx, `profile.name="Alice"`)
if err != nil {
panic(err)
}
present := hffsql.Equal(
hffsql.ColumnValue(hffsql.Column("records", "tenant_id"), schema.StringType),
hffsql.Literal(hff.String("tenant-17")),
)
query, err := hffsql.Build(ctx, program, hffsql.WithDialect(hffsql.PostgreSQL), hffsql.WithBindings(
hffsql.BindStruct(hff.Path{"profile"}, present, hffsql.Boolean(false),
hffsql.Bind(hff.Path{"name"}, hffsql.Column("records", "profile_name")),
),
))
if err != nil {
panic(err)
}
fmt.Println(query.Args())
}
Complete runnable example
package main
import (
"context"
"fmt"
"github.com/ornew/hff"
hffsql "github.com/ornew/hff/backends/sql"
"github.com/ornew/hff/capabilities"
"github.com/ornew/hff/engine"
"github.com/ornew/hff/schema"
)
func main() {
ctx := context.Background()
e, err := engine.New(engine.WithSchema(schema.Struct(
schema.Optional(schema.Field("profile", schema.Struct(schema.String("name")))),
)), engine.WithCapabilities(capabilities.Standard()))
if err != nil {
panic(err)
}
program, err := e.Compile(ctx, `profile.name="Alice"`)
if err != nil {
panic(err)
}
// ColumnValue describes a physical column; Literal becomes a driver argument.
present := hffsql.Equal(
hffsql.ColumnValue(hffsql.Column("records", "tenant_id"), schema.StringType),
hffsql.Literal(hff.String("tenant-17")),
)
query, err := hffsql.Build(ctx, program, hffsql.WithDialect(hffsql.PostgreSQL), hffsql.WithBindings(
hffsql.BindStruct(hff.Path{"profile"}, present, hffsql.Boolean(false),
hffsql.Bind(hff.Path{"name"}, hffsql.Column("records", "profile_name")),
),
))
if err != nil {
panic(err)
}
// Pass these arguments separately when executing a statement using Where().
fmt.Println(query.Args())
}
Output:
[tenant-17 Alice]
func IsNotNull
func IsNotNull(value Scalar) SQLPredicate
IsNotNull constructs a physical SQL non-NULL test for value.
func IsNull
func IsNull(value Scalar) SQLPredicate
IsNull constructs a physical SQL NULL test for value.
func Not
func Not(predicate SQLPredicate) SQLPredicate
Not negates a predicate using SQL NOT semantics, preserving unknown.
func Or
func Or(predicates ...SQLPredicate) SQLPredicate
Or combines predicates using SQL OR semantics. SQL NULL remains unknown.
func TrustedSQL
func TrustedSQL(code string, references ...ColumnRef) SQLPredicate
TrustedSQL wraps a developer-authored PostgreSQL Boolean expression. It is not parsed, type-checked, sanitized, or proven deterministic or side-effect-free. Use only fixed trusted source text, never query or record data. Supply referenced identifiers as ColumnRefs for alias tracking; this does not validate that the text uses those references or is a predicate.
func (SQLPredicate) View
func (p SQLPredicate) View() PredicateView
View returns a recursive, detached description of p.
type Scalar
type Scalar struct {
// contains filtered or unexported fields
}
Scalar is an immutable SQL scalar expression for one supported physical type: null, Boolean, int64, float64, string, or duration as int64 nanoseconds, optionally unioned with HFF null. Equality requires the same non-null scalar kind (comparison with a null literal is allowed); Build does not promote mixed int/float SQL values. A Scalar may be reused across Builds.
func ColumnValue
func ColumnValue(column ColumnRef, typ hff.Type) Scalar
ColumnValue declares a physical column and its HFF scalar type. Build quotes every identifier; the caller guarantees the database column and data match that type. For example, ColumnValue(Column("orders", "tenant_id"), hff.PrimitiveType(hff.IntType)) describes an int64 column.
func Literal
func Literal(value hff.Value) Scalar
Literal creates a typed scalar value. Build binds non-null values in Query.Args; explicit null becomes SQL NULL. Unsupported values are rejected during Build. Supported values are null, bool, int64, finite float64, string, and duration. Bytes and timestamps are not SQL predicate scalars in the current dialect profile.
func (Scalar) Type
func (s Scalar) Type() hff.Type
Type returns the declared HFF type of this SQL scalar expression.
func (Scalar) View
func (s Scalar) View() ScalarView
View describes the scalar without exposing its mutable internal storage.
type ScalarView
type ScalarView struct {
Column []string
Literal hff.Value
HasLiteral bool
Type hff.Type
}
ScalarView is a defensive description of a typed SQL scalar. Exactly one of Column and HasLiteral is set for a valid scalar.
type TimestampBindingOption
type TimestampBindingOption struct {
// contains filtered or unexported fields
}
TimestampBindingOption configures a native PostgreSQL Timestamp binding. Options apply from left to right.
func WithNanosecondRemainder
func WithNanosecondRemainder(column ColumnRef) TimestampBindingOption
WithNanosecondRemainder identifies the SMALLINT column containing the sub-microsecond remainder, from 0 through 999 nanoseconds. The caller stores the timestamptz rounded down to a whole microsecond and guarantees that both columns are null together. Without this option, the caller guarantees that every stored instant is already exact to a microsecond.