managers

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package managers provides high-level fluent APIs for building SQL ASTs.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrSetTargetTable = errors.New("gosbee: SET target column belongs to another table")

ErrSetTargetTable is returned by ToSQL when a SET target (UPDATE SET, or INSERT ... ON CONFLICT DO UPDATE SET) is a column of a table other than the one the statement writes. Visitors write a SET target as a bare column name, as PostgreSQL and SQLite require, so such a target would otherwise resolve silently to a column of the statement's own table.

The check is made by the managers. Rendering a statement node directly with Accept bypasses it.

Functions

This section is empty.

Types

type DeleteManager

type DeleteManager struct {
	Statement *nodes.DeleteStatement
	// contains filtered or unexported fields
}

DeleteManager provides a fluent API for building DELETE statements.

func NewDeleteManager

func NewDeleteManager(from nodes.Node) *DeleteManager

NewDeleteManager creates a new DeleteManager targeting the given table.

func (*DeleteManager) Returning

func (m *DeleteManager) Returning(cols ...nodes.Node) *DeleteManager

Returning sets the RETURNING clause columns.

func (*DeleteManager) ToSQL

func (m *DeleteManager) ToSQL(v nodes.Visitor) (string, []any, error)

ToSQL applies transformers and generates SQL with parameters. Returns SQL string, parameter values (if parameterised), and any error.

func (*DeleteManager) ToSQLParams deprecated

func (m *DeleteManager) ToSQLParams(v nodes.Visitor) (string, []any, error)

ToSQLParams applies transformers and generates parameterized SQL.

Deprecated: Use ToSQL() instead, which now always returns params.

func (*DeleteManager) Transformers

func (tm *DeleteManager) Transformers() []plugins.Transformer

Transformers returns the registered transformer pipeline.

func (*DeleteManager) Use

Use registers a transformer plugin.

func (*DeleteManager) Where

func (m *DeleteManager) Where(conditions ...nodes.Node) *DeleteManager

Where appends conditions to the WHERE clause.

Example
package main

import (
	"fmt"

	"github.com/bawdo/gosbee/managers"
	"github.com/bawdo/gosbee/nodes"
	"github.com/bawdo/gosbee/visitors"
)

// printSQL prints a statement and its bind parameters, or the error that
// stopped it rendering.
func printSQL(sql string, params []any, err error) {
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(sql)
	fmt.Println(params)
}

func main() {
	sessions := nodes.NewTable("sessions")

	del := managers.NewDeleteManager(sessions).
		Where(sessions.Col("expires_at").Lt("2026-01-01"))

	printSQL(del.ToSQL(visitors.NewPostgresVisitor()))
}
Output:
DELETE FROM "sessions" WHERE "sessions"."expires_at" < $1
[2026-01-01]

type InsertManager

type InsertManager struct {
	Statement *nodes.InsertStatement
	// contains filtered or unexported fields
}

InsertManager provides a fluent API for building INSERT statements.

func NewInsertManager

func NewInsertManager(into nodes.Node) *InsertManager

NewInsertManager creates a new InsertManager targeting the given table.

func (*InsertManager) Columns

func (m *InsertManager) Columns(cols ...nodes.Node) *InsertManager

Columns sets the column list for the INSERT statement.

func (*InsertManager) FromSelect

func (m *InsertManager) FromSelect(sel *SelectManager) *InsertManager

FromSelect sets a SELECT subquery as the source of rows. Mutually exclusive with Values — if Select is set, Values are ignored by the visitor.

func (*InsertManager) OnConflict

func (m *InsertManager) OnConflict(cols ...nodes.Node) *OnConflictContext

OnConflict begins an ON CONFLICT clause targeting the given columns. Returns an OnConflictContext for specifying the action.

func (*InsertManager) Returning

func (m *InsertManager) Returning(cols ...nodes.Node) *InsertManager

Returning sets the RETURNING clause columns.

func (*InsertManager) ToSQL

func (m *InsertManager) ToSQL(v nodes.Visitor) (string, []any, error)

ToSQL applies transformers and generates SQL with parameters. Returns SQL string, parameter values (if parameterised), and any error.

func (*InsertManager) ToSQLParams deprecated

func (m *InsertManager) ToSQLParams(v nodes.Visitor) (string, []any, error)

ToSQLParams applies transformers and generates parameterized SQL.

Deprecated: Use ToSQL() instead, which now always returns params.

func (*InsertManager) Transformers

func (tm *InsertManager) Transformers() []plugins.Transformer

Transformers returns the registered transformer pipeline.

func (*InsertManager) Use

Use registers a transformer plugin.

func (*InsertManager) Values

func (m *InsertManager) Values(vals ...any) *InsertManager

Values appends a row of values to the INSERT statement. Each call to Values adds one row. Pass raw Go values; they are wrapped with nodes.Literal automatically.

Example
package main

import (
	"fmt"

	"github.com/bawdo/gosbee/managers"
	"github.com/bawdo/gosbee/nodes"
	"github.com/bawdo/gosbee/visitors"
)

// printSQL prints a statement and its bind parameters, or the error that
// stopped it rendering.
func printSQL(sql string, params []any, err error) {
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(sql)
	fmt.Println(params)
}

func main() {
	users := nodes.NewTable("users")

	insert := managers.NewInsertManager(users).
		Columns(users.Col("name"), users.Col("email")).
		Values("Alice", "alice@example.com").
		Values("Bob", "bob@example.com")

	printSQL(insert.ToSQL(visitors.NewPostgresVisitor()))
}
Output:
INSERT INTO "users" ("name", "email") VALUES ($1, $2), ($3, $4)
[Alice alice@example.com Bob bob@example.com]

type JoinContext

type JoinContext struct {
	// contains filtered or unexported fields
}

JoinContext is returned by SelectManager.Join() and enforces that a join condition is provided via On() before continuing to build the query. This prevents incomplete JOINs in the AST.

func (*JoinContext) On

func (jc *JoinContext) On(condition nodes.Node) *SelectManager

On sets the join condition and returns the SelectManager for continued method chaining.

type OnConflictContext

type OnConflictContext struct {
	// contains filtered or unexported fields
}

OnConflictContext guides ON CONFLICT clause construction.

func (*OnConflictContext) DoNothing

func (c *OnConflictContext) DoNothing() *InsertManager

DoNothing sets the action to DO NOTHING and returns the InsertManager.

func (*OnConflictContext) DoUpdate

func (c *OnConflictContext) DoUpdate(assignments ...*nodes.AssignmentNode) *OnConflictUpdateContext

DoUpdate sets the action to DO UPDATE with the given assignments. Returns an OnConflictUpdateContext for an optional WHERE clause.

type OnConflictUpdateContext

type OnConflictUpdateContext struct {
	// contains filtered or unexported fields
}

OnConflictUpdateContext allows adding a WHERE to DO UPDATE.

func (*OnConflictUpdateContext) Where

func (c *OnConflictUpdateContext) Where(conditions ...nodes.Node) *InsertManager

Where adds conditions to the ON CONFLICT DO UPDATE clause.

type SelectManager

type SelectManager struct {
	Core *nodes.SelectCore
	// contains filtered or unexported fields
}

SelectManager provides a fluent API for building SELECT queries. It wraps a SelectCore and applies transformer plugins before SQL generation.

func NewSelectManager

func NewSelectManager(from nodes.Node) *SelectManager

NewSelectManager creates a new SelectManager with the given table as FROM. If from is nil, the FROM clause is left unset.

func (*SelectManager) Accept

func (m *SelectManager) Accept(v nodes.Visitor) string

Accept implements the Node interface so that a SelectManager can be used as a subquery (e.g., as the right side of a JoinNode). It delegates to the underlying SelectCore.

func (*SelectManager) As

func (m *SelectManager) As(name string) *nodes.TableAlias

As wraps the query's SelectCore in a TableAlias, enabling it to be used as a named subquery in FROM or JOIN clauses.

func (*SelectManager) CloneCore

func (m *SelectManager) CloneCore() *nodes.SelectCore

CloneCore returns a shallow copy of the SelectCore so transformers don't modify the original.

func (*SelectManager) Comment

func (m *SelectManager) Comment(text string) *SelectManager

Comment sets a query comment (rendered as /* ... */). Any occurrence of */ in the text is sanitized to prevent comment breakout.

func (*SelectManager) CrossJoin

func (m *SelectManager) CrossJoin(table nodes.Node) *SelectManager

CrossJoin adds a cross join (no ON clause).

func (*SelectManager) Distinct

func (m *SelectManager) Distinct(on ...bool) *SelectManager

Distinct enables or disables the DISTINCT modifier on the SELECT clause.

func (*SelectManager) DistinctOn

func (m *SelectManager) DistinctOn(cols ...nodes.Node) *SelectManager

DistinctOn sets the DISTINCT ON columns (PostgreSQL).

func (*SelectManager) Except

Except creates an EXCEPT set operation between this query and another. The node runs no transformers; use NewSetOperationManager to apply them.

func (*SelectManager) ExceptAll

func (m *SelectManager) ExceptAll(other *SelectManager) *nodes.SetOperationNode

ExceptAll creates an EXCEPT ALL set operation between this query and another. The node runs no transformers; use NewSetOperationManager to apply them.

func (*SelectManager) ForKeyShare

func (m *SelectManager) ForKeyShare() *SelectManager

ForKeyShare sets the FOR KEY SHARE lock mode.

func (*SelectManager) ForNoKeyUpdate

func (m *SelectManager) ForNoKeyUpdate() *SelectManager

ForNoKeyUpdate sets the FOR NO KEY UPDATE lock mode.

func (*SelectManager) ForShare

func (m *SelectManager) ForShare() *SelectManager

ForShare sets the FOR SHARE lock mode.

func (*SelectManager) ForUpdate

func (m *SelectManager) ForUpdate() *SelectManager

ForUpdate sets the FOR UPDATE lock mode.

func (*SelectManager) From

func (m *SelectManager) From(table nodes.Node) *SelectManager

From sets or changes the FROM source.

func (*SelectManager) Group

func (m *SelectManager) Group(columns ...nodes.Node) *SelectManager

Group appends one or more expressions to the GROUP BY clause.

func (*SelectManager) Having

func (m *SelectManager) Having(conditions ...nodes.Node) *SelectManager

Having appends one or more conditions to the HAVING clause. Multiple calls to Having are combined with AND at the visitor level.

func (*SelectManager) Hint

func (m *SelectManager) Hint(hint string) *SelectManager

Hint adds an optimizer hint (rendered as /*+ ... */ after SELECT). Any occurrence of */ in the hint is sanitized to prevent comment breakout.

func (*SelectManager) Intersect

func (m *SelectManager) Intersect(other *SelectManager) *nodes.SetOperationNode

Intersect creates an INTERSECT set operation between this query and another. The node runs no transformers; use NewSetOperationManager to apply them.

func (*SelectManager) IntersectAll

func (m *SelectManager) IntersectAll(other *SelectManager) *nodes.SetOperationNode

IntersectAll creates an INTERSECT ALL set operation between this query and another. The node runs no transformers; use NewSetOperationManager to apply them.

func (*SelectManager) Join

func (m *SelectManager) Join(table nodes.Node, joinTypes ...nodes.JoinType) *JoinContext

Join adds a join to the query and returns a JoinContext for specifying the ON condition. The default join type is InnerJoin.

Example

Join returns a JoinContext; On supplies the join condition and hands the SelectManager back so the chain can carry on.

package main

import (
	"fmt"

	"github.com/bawdo/gosbee/managers"
	"github.com/bawdo/gosbee/nodes"
	"github.com/bawdo/gosbee/visitors"
)

// printSQL prints a statement and its bind parameters, or the error that
// stopped it rendering.
func printSQL(sql string, params []any, err error) {
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(sql)
	fmt.Println(params)
}

func main() {
	users := nodes.NewTable("users")
	posts := nodes.NewTable("posts")

	query := managers.NewSelectManager(users).
		Select(users.Col("name"), posts.Col("title")).
		Join(posts).On(posts.Col("user_id").Eq(users.Col("id")))

	printSQL(query.ToSQL(visitors.NewPostgresVisitor()))
}
Output:
SELECT "users"."name", "posts"."title" FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
[]

func (*SelectManager) LateralJoin

func (m *SelectManager) LateralJoin(table nodes.Node, joinTypes ...nodes.JoinType) *JoinContext

LateralJoin adds a LATERAL join (PostgreSQL). Default join type is InnerJoin.

func (*SelectManager) Limit

func (m *SelectManager) Limit(n int) *SelectManager

Limit sets the LIMIT value.

func (*SelectManager) Offset

func (m *SelectManager) Offset(n int) *SelectManager

Offset sets the OFFSET value.

func (*SelectManager) Order

func (m *SelectManager) Order(orderings ...nodes.Node) *SelectManager

Order sets the ORDER BY clause. Pass OrderingNode values (e.g., table.Col("name").Asc()).

func (*SelectManager) OuterJoin

func (m *SelectManager) OuterJoin(table nodes.Node) *JoinContext

OuterJoin is a convenience for Join with LeftOuterJoin type.

func (*SelectManager) Project

func (m *SelectManager) Project(projections ...nodes.Node) *SelectManager

Project is an alias for Select (Ruby Arel uses "project").

func (*SelectManager) Select

func (m *SelectManager) Select(projections ...nodes.Node) *SelectManager

Select sets the projection list, replacing any existing projections. Pass column attributes, stars, literals, or any Node.

Example

A projection names the columns the query returns.

package main

import (
	"fmt"

	"github.com/bawdo/gosbee/managers"
	"github.com/bawdo/gosbee/nodes"
	"github.com/bawdo/gosbee/visitors"
)

// printSQL prints a statement and its bind parameters, or the error that
// stopped it rendering.
func printSQL(sql string, params []any, err error) {
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(sql)
	fmt.Println(params)
}

func main() {
	users := nodes.NewTable("users")

	query := managers.NewSelectManager(users).
		Select(users.Col("id"), users.Col("name"))

	printSQL(query.ToSQL(visitors.NewPostgresVisitor()))
}
Output:
SELECT "users"."id", "users"."name" FROM "users"
[]

func (*SelectManager) SkipLocked

func (m *SelectManager) SkipLocked() *SelectManager

SkipLocked adds SKIP LOCKED to the current lock mode.

func (*SelectManager) StringJoin

func (m *SelectManager) StringJoin(raw nodes.RawSQL) *SelectManager

StringJoin adds a raw SQL join fragment.

SECURITY: The raw string is injected verbatim into SQL output. Never pass user-controlled input to this method. The RawSQL type enforces this at compile time — use nodes.RawSQL("...") for developer-controlled fragments only.

func (*SelectManager) Take

func (m *SelectManager) Take(n int) *SelectManager

Take is an alias for Limit (Ruby Arel convention).

func (*SelectManager) ToSQL

func (m *SelectManager) ToSQL(v nodes.Visitor) (string, []any, error)

ToSQL applies all registered transformers and generates SQL with parameters. Returns SQL string, parameter values (if parameterised), and any error. Parameters are collected automatically when the visitor has parameterisation enabled.

func (*SelectManager) ToSQLParams deprecated

func (m *SelectManager) ToSQLParams(v nodes.Visitor) (string, []any, error)

ToSQLParams applies transformers and generates parameterized SQL.

Deprecated: Use ToSQL() instead, which now always returns params.

func (*SelectManager) Transformers

func (tm *SelectManager) Transformers() []plugins.Transformer

Transformers returns the registered transformer pipeline.

func (*SelectManager) Union

Union creates a UNION set operation between this query and another. The node runs no transformers; use NewSetOperationManager to apply them.

func (*SelectManager) UnionAll

func (m *SelectManager) UnionAll(other *SelectManager) *nodes.SetOperationNode

UnionAll creates a UNION ALL set operation between this query and another. The node runs no transformers; use NewSetOperationManager to apply them.

func (*SelectManager) Use

Use registers a transformer plugin to be applied before SQL generation.

func (*SelectManager) Where

func (m *SelectManager) Where(conditions ...nodes.Node) *SelectManager

Where appends one or more conditions to the WHERE clause. Multiple calls to Where are combined with AND at the visitor level.

Example

Several conditions passed to Where are joined with AND. Or groups its operands in parentheses so the precedence reads as written. Values are bound as parameters, never spliced into the SQL.

package main

import (
	"fmt"

	"github.com/bawdo/gosbee/managers"
	"github.com/bawdo/gosbee/nodes"
	"github.com/bawdo/gosbee/visitors"
)

// printSQL prints a statement and its bind parameters, or the error that
// stopped it rendering.
func printSQL(sql string, params []any, err error) {
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(sql)
	fmt.Println(params)
}

func main() {
	users := nodes.NewTable("users")

	query := managers.NewSelectManager(users).
		Select(users.Col("id")).
		Where(
			users.Col("active").Eq(true),
			users.Col("role").Eq("admin").Or(users.Col("age").GtEq(18)),
		)

	printSQL(query.ToSQL(visitors.NewPostgresVisitor()))
}
Output:
SELECT "users"."id" FROM "users" WHERE "users"."active" = $1 AND ("users"."role" = $2 OR "users"."age" >= $3)
[true admin 18]

func (*SelectManager) Window

func (m *SelectManager) Window(defs ...*nodes.WindowDefinition) *SelectManager

Window appends one or more named window definitions to the WINDOW clause.

func (*SelectManager) With

func (m *SelectManager) With(name string, query nodes.Node) *SelectManager

With adds a Common Table Expression (WITH clause).

func (*SelectManager) WithRecursive

func (m *SelectManager) WithRecursive(name string, query nodes.Node) *SelectManager

WithRecursive adds a recursive Common Table Expression (WITH RECURSIVE clause).

type SetOperationManager added in v0.2.0

type SetOperationManager struct {
	Node *nodes.SetOperationNode
	// contains filtered or unexported fields
}

SetOperationManager provides transformer support for set operations (UNION, INTERSECT, EXCEPT) so plugins police every branch.

func NewSetOperationManager added in v0.2.0

func NewSetOperationManager(op *nodes.SetOperationNode) *SetOperationManager

NewSetOperationManager creates a new SetOperationManager wrapping the given set operation.

func (*SetOperationManager) ToSQL added in v0.2.0

func (m *SetOperationManager) ToSQL(v nodes.Visitor) (string, []any, error)

ToSQL applies transformers and generates SQL with parameters. Returns SQL string, parameter values (if parameterised), and any error.

func (*SetOperationManager) Transformers added in v0.2.0

func (tm *SetOperationManager) Transformers() []plugins.Transformer

Transformers returns the registered transformer pipeline.

func (*SetOperationManager) Use added in v0.2.0

Use registers a transformer plugin.

type UpdateManager

type UpdateManager struct {
	Statement *nodes.UpdateStatement
	// contains filtered or unexported fields
}

UpdateManager provides a fluent API for building UPDATE statements.

func NewUpdateManager

func NewUpdateManager(table nodes.Node) *UpdateManager

NewUpdateManager creates a new UpdateManager targeting the given table.

func (*UpdateManager) Returning

func (m *UpdateManager) Returning(cols ...nodes.Node) *UpdateManager

Returning sets the RETURNING clause columns.

func (*UpdateManager) Set

func (m *UpdateManager) Set(col nodes.Node, val any) *UpdateManager

Set adds a column assignment to the SET clause. val can be a raw Go value or a Node.

Example
package main

import (
	"fmt"

	"github.com/bawdo/gosbee/managers"
	"github.com/bawdo/gosbee/nodes"
	"github.com/bawdo/gosbee/visitors"
)

// printSQL prints a statement and its bind parameters, or the error that
// stopped it rendering.
func printSQL(sql string, params []any, err error) {
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(sql)
	fmt.Println(params)
}

func main() {
	users := nodes.NewTable("users")

	update := managers.NewUpdateManager(users).
		Set(users.Col("name"), "Alice").
		Set(users.Col("active"), false).
		Where(users.Col("id").Eq(42))

	printSQL(update.ToSQL(visitors.NewPostgresVisitor()))
}
Output:
UPDATE "users" SET "name" = $1, "active" = $2 WHERE "users"."id" = $3
[Alice false 42]

func (*UpdateManager) ToSQL

func (m *UpdateManager) ToSQL(v nodes.Visitor) (string, []any, error)

ToSQL applies transformers and generates SQL with parameters. Returns SQL string, parameter values (if parameterised), and any error.

func (*UpdateManager) ToSQLParams deprecated

func (m *UpdateManager) ToSQLParams(v nodes.Visitor) (string, []any, error)

ToSQLParams applies transformers and generates parameterized SQL.

Deprecated: Use ToSQL() instead, which now always returns params.

func (*UpdateManager) Transformers

func (tm *UpdateManager) Transformers() []plugins.Transformer

Transformers returns the registered transformer pipeline.

func (*UpdateManager) Use

Use registers a transformer plugin.

func (*UpdateManager) Where

func (m *UpdateManager) Where(conditions ...nodes.Node) *UpdateManager

Where appends conditions to the WHERE clause.

Jump to

Keyboard shortcuts

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