inyorm

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Dec 2, 2025 License: MIT Imports: 7 Imported by: 0

README

Inyorm

Go Reference

Inyorm is a fully declarative ORM for Go, designed for clarity, type safety, and predictable SQL generation.
  • SQL-like declarative API
  • Strong typing
  • Fast mapping with minimal reflection
  • Lightweight, explicit, and predictable
  • Highly customizable

Minimal setup

Install
go get -u github.com/laacin/inyorm

Inyorm is just a query builder and object mapper. It doesn’t manage connections or drivers, so you stay fully in control of the database layer.

package main

import (
	"database/sql"
	"log"

	"github.com/laacin/inyorm"
)

func main() {
    db, err := sql.Open("sqlite3", "./data.db")
    if err != nil {
        log.Fatal(err)
    }

    qe := inyorm.New("sqlite3", db, &inyorm.Options{})

    ctx := context.Background()

    q, c := qe.NewSelect(ctx, "table")
    // q, c := qe.NewInsert(ctx, "table")
    // q, c := qe.NewUpdate(ctx, "table")
    // q, c := qe.NewDelete(ctx, "table")
}

Why inyorm?

Inyorm is a fully declarative, explicit, and strongly typed ORM, letting you write complex queries without falling back to raw SQL.

Examples:
Simple example
q, c := qe.NewSelect(ctx, "users")

var (
	id    = c.Col("id")
	fk    = c.Col("user_id", "posts")
	posts = c.Col("id", "posts").Count()
)

q.Select(c.All(), posts)
q.Join("posts").On(fk).Equal(id)
q.Where(id).Equal(c.Param("uuid"))
q.Limit(1)

SQL:

SELECT a.*, COUNT(b.id)
FROM users a
INNER JOIN posts b ON (b.user_id = a.id)
WHERE (a.id = ?)
LIMIT 1
Complex example
q, c := qe.NewSelect(context.Background(), "users")

// helper
isNull := func(cond inyorm.Column, then, els any) inyorm.Column {
	return c.Search(func(cs inyorm.Case) {
		cond := c.Cond(cond).IsNull()
		cs.When(cond).Then(then)
		cs.Else(els)
	})
}

var (
	// base columns
	fname     = c.Col("firstname")
	lname     = c.Col("lastname")
	lastLogin = c.Col("last_login")
	banned    = c.Col("banned")
	roleName  = c.Col("name", "roles")
	age       = c.Col("age")
	active    = c.Col("active")

	// summary columns
	posts    = c.Col("id", "posts").Count()
	comments = c.Col("id", "comments").Count()
	role     = isNull(roleName, "No role", roleName)
	lastLog  = isNull(lastLogin, "Never", lastLogin)
	status   = isNull(banned, "Active", c.Concat("Banned at: ", banned))

	// join keys
	userId        = c.Col("id")
	roleId        = c.Col("id", "roles")
	postUserFk    = c.Col("user_id", "posts")
	commentUserFk = c.Col("user_id", "comments")

	interUserFk = c.Col("user_id", "user_roles")
	interRoleFk = c.Col("role_id", "user_roles")

	// select columns
	totalPost    = c.Col("id", "posts").Count(true).As("total_posts")
	totalComment = c.Col("id", "comments").Count(true).As("total_comments")
	lastPost     = c.Col("created_at", "posts").Max().As("last_post_date")
	summary      = c.Concat(
		"User: ", fname, " ", lname, " | ",
		"Role: ", role, " | ",
		"Posts: ", posts, " | ",
		"Comments: ", comments, " | ",
		"Last login: ", lastLog, " | ",
		status,
	).As("user_summary")
)

// statement building
q.Select(summary, totalPost, totalComment, lastPost)

q.Join("user_roles").Left().On(interUserFk).Equal(userId)
q.Join("roles").Left().On(roleId).Equal(interRoleFk)
q.Join("posts").Left().On(postUserFk).Equal(userId)
q.Join("comments").Left().On(commentUserFk).Equal(userId)

q.Where(age).Between(18, 60).And(active).Equal(true)

q.GroupBy(userId, fname, lname, lastLogin, banned, roleName)
q.Having(posts).Greater(5)

q.OrderBy(totalPost).Desc()
q.OrderBy(age)
q.Limit(50)

SQL:

SELECT CONCAT(
        'User: ', a.firstname, ' ', a.lastname, ' | ',
        'Role: ', CASE WHEN (b.name IS NULL) THEN 'No role' ELSE b.name END, ' | ',
        'Posts: ', COUNT(c.id), ' | ',
        'Comments: ', COUNT(d.id), ' | ',
        'Last login: ', CASE WHEN (a.last_login IS NULL) THEN 'Never' ELSE a.last_login END, ' | ',
        CASE WHEN (a.banned IS NULL) THEN 'Active' ELSE CONCAT('Banned at: ', a.banned) END
    ) AS user_summary,
    COUNT(DISTINCT c.id) AS total_posts,
    COUNT(DISTINCT d.id) AS total_comments,
    MAX(c.created_at) AS last_post_date
FROM users a
LEFT JOIN user_roles e ON (e.user_id = a.id)
LEFT JOIN roles b ON (b.id = e.role_id)
LEFT JOIN posts c ON (c.user_id = a.id)
LEFT JOIN comments d ON (d.user_id = a.id)
WHERE (a.age BETWEEN 18 AND 60 AND a.active = 1)
GROUP BY a.id, a.firstname, a.lastname, a.last_login, a.banned, b.name
HAVING (COUNT(c.id) > 5)
ORDER BY total_posts DESC, a.age
LIMIT 50;

Guides

Column builder
// The second return value of each new statement is the Column Builder,
// where you can write all non-literal values.
_, c := qe.NewSelect(ctx, "table")

// ----- Col -----

// Col is the most common method. It references a table column
// and accepts two parameters: the first is column name of the main table.
c.Col("id")

// To reference another table, pass a second parameter with the table name.
c.Col("id", "posts")

// ----- All -----

// All references the wildcard '*'.
// In a joined query, the default All() references the main table.
c.All()

// To reference another table, pass a parameter with the table name.
c.All("posts")

// ----- Param -----

// Param writes a placeholder.
// In Inyorm you should write explicit parameters (except in explicit values clause).
// such as Insert().Values() and Update().Values()
c.Param("id")

// You can also skip parameters for lazy values, useful for prepared statements.
c.Param()

// ----- Concat -----

// Concat writes a CONCAT() in SQL.
// You can include any value.
c.Concat(c.Col("firstname"), " ", c.Col("lastname"))

// Expected output:
// CONCAT(firstname, ' ', lastname)

// ----- Switch -----

// Switch is a reference to a simple CASE.
// It accepts two parameters: a comparable value and a callback
// where you can compare against literal values.
c.Switch(c.Col("banned"), func(cs inyorm.Case) {
	cs.When(true).Then("Invalid user")
	cs.Else("Valid")
})

// Expected output:
// CASE banned WHEN 1 THEN 'Invalid user' ELSE 'Valid' END

// ----- Search -----

// Search is a reference to a searched CASE.
// It accepts one callback
// where each When accepts a boolean expression,
// such as a condition (built below) or literals.
c.Search(func(cs inyorm.Case) {
	cond := c.Cond(c.Col("age")).Greater(17)
	cs.When(cond).Then("Adult")
	cs.Else("Kid")
})

// Expected output:
// CASE WHEN (age > 17) THEN 'Adult' ELSE 'Kid' END

// ----- Cond -----

// Cond is a helper used to create a condition.
// Currently, only used in the Search method.
c.Cond(c.Col("banned")).IsNull().And(c.Col("age")).Greater(17)
Columns
// When you have a column built by the Column Builder,
// you can also modify it afterward.

// samples
var (
    age   = c.Col("age")
    stock = c.Col("stock")
    price = c.Col("price")
    fname = c.Col("firstname")
)

// ----- Aggregation ------

// You can call aggregation methods such as Count(), Sum(), Max(), Min(), or Avg().
// Only one aggregation method will be applied, and it will always be the last one called.
// Each method accepts an optional bool that enables DISTINCT inside the aggregation.
age.Count()   // COUNT(age)
age.Sum(true) // SUM(DISTINCT age)
age.Max()     // MAX(age)
age.Min(true) // MIN(DISTINCT age)
age.Avg()     // AVG(age)

// ----- Arithmetic operations -----

// You can perform arithmetic operations with other columns or literal values.
price.Add(10) // price + 10
price.Sub(10) // price - 10
price.Mul(10) // price * 10
price.Div(10) // price / 10
price.Mod(10) // price % 10

stock.Mul(price) // stock * price

// If you want to wrap an expression, use Wrap()
stock.Mul(price).Wrap().Mul(100) // (stock * price) * 100

// ----- Scalar functions ------

// You can use scalar functions that modify the resulting expression.
fname.Upper() // UPPER(firstname)
fname.Lower() // LOWER(firstname)
fname.Trim()  // TRIM(firstname)
price.Round() // ROUND(price)
age.Avg()     // AVG(age)
age.Abs()     // ABS(age)

// ----- Alias -----

// Some methods change the column’s default name.
// To preserve control over the final name, use As() to assign an alias.
age.Avg().As("avg_age") // AVG(age) AS avg_age

// ----- Written methods ------

// Columns can be written differently depending on the clause.
// If you want to force a specific written form, you can use:

// sample:
age.Count().As("avg_age") // (COUNT(age) AS avg_age)

age.Base()  // age
age.Expr()  // COUNT(age)
age.Alias() // avg_age
age.Def()   // COUNT(age) AS avg_age
Select statement
// Start a new SELECT statement.
// Returns (q) the statement and (c) the column builder.
// Requires a context and a default table, which will be used
// as the default table for the column builder and the Auto From() clause.
q, c := qe.NewSelect(ctx, "users")

// Sample columns
var (
	id       = c.Col("id")
	fk       = c.Col("user_id", "posts")
	age      = c.Col("age")
	banned   = c.Col("banned")
	example  = c.Col("example")
	postsNum = c.Col("id", "posts").Count()
)

// ----- SELECT -----

// Accepts a variadic parameter; you can select any columns you want.
q.Select(c.All()) // SELECT *

// You can also start with Distinct() for this purpose.
q.Distinct().Select(id) // SELECT DISTINCT id

// ----- FROM -----

// From() selects the target table.
// If omitted, the default table is used automatically.
q.From("users")

// ----- JOIN -----

// Always start a JOIN clause with Join().
// You can chain On() directly to set the condition, and it will default to INNER JOIN.
q.Join("posts").On(fk).Equal(id)

// You can also explicitly set the join type.
q.Join("posts").Left().On(fk).Equal(id)
q.Join("posts").Full().On(fk).Equal(id)

// CROSS JOIN does not accept a condition.
q.Join("posts").Cross()

// ----- WHERE -----

// Where() starts a condition. Each condition is wrapped in parentheses.
q.Where(age).Greater(17)                     // WHERE (age > 17)
q.Where(age).Less(40).And(banned).IsNull()  // WHERE (age < 40 AND banned IS NULL)

// Multiple Where() calls are combined with AND at the top level.
// Example: WHERE (age > 17) AND (age < 40 AND banned IS NULL)

// You can negate any condition using Not()
q.Where(example).Not().Equal(100)          // WHERE (example <> 100)
q.Where(example).Not().Like("%something%") // WHERE (example NOT LIKE '%something%')
q.Where(example).Not().Greater(40)         // WHERE (example <= 40)
q.Where(example).Not().IsNull()            // WHERE (example IS NOT NULL)

// You can also use parameters for external inputs.
q.Where(id).Equal(c.Param("uuid")) // WHERE (id = ?)

// ----- GROUP BY -----

// GROUP BY behaves similarly to the SELECT clause.
// You can pass multiple columns as variadic parameters.
q.GroupBy(postsNum)

// ----- HAVING -----

// HAVING behaves like WHERE. Start with an identifier to define a condition.
q.Having(postsNum).Greater(10)

// ----- ORDER BY -----

// ORDER BY accepts an identifier.
q.OrderBy(age)

// You can chain Desc() for descending order.
// Multiple OrderBy() calls are allowed.
q.OrderBy(age).Desc()
q.OrderBy(id)

// ----- LIMIT & OFFSET -----

// Pass an integer to set the limit or offset.
q.Limit(10)
q.Offset(5)

Documentation

Index

Constants

View Source
const (
	TypeColumnDef   = core.ColTypDef
	TypeColumnExpr  = core.ColTypExpr
	TypeColumnAlias = core.ColTypAlias
	TypeColumnBase  = core.ColTypBase
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Builder

type Builder = core.Builder

type Case

type Case interface {
	// When starts a CASE WHEN block
	//
	// @SQL: CASE WHEN `when`
	When(when Value) CaseNext

	// Else writes the ELSE value
	//
	// @SQL: ELSE value END
	Else(els Value)
}

Case represents a SQL CASE expression, allowing conditional branching inside statements.

type CaseNext

type CaseNext interface {
	// Then writes THEN value
	//
	// @SQL: THEN value
	Then(then Value) Case
}

CaseNext represents the THEN part of a CASE WHEN branch, allowing chained WHEN/THEN blocks.

type Column

type Column interface {
	// Def writes the definition of the column
	//
	// e.g: if we have this column being built: COUNT(id) AS count:
	//  - Def()   would write: COUNT(id) AS count; Fallbacks: Expr() -> Base()
	//  - Expr()  would write: COUNT(id);          Fallbacks: Base()
	//  - Alias() would write: count;              Fallbacks: Expr() -> Base()
	//  - Base()  would write: id                  Fallbacks: none
	//
	// @SQL: used to build column definitions
	Def() Builder

	// Expr writes the expression of the column
	//
	// e.g: if we have this column being built: COUNT(id) AS count:
	//  - Def()   would write: COUNT(id) AS count; Fallbacks: Expr() -> Base()
	//  - Expr()  would write: COUNT(id);          Fallbacks: Base()
	//  - Alias() would write: count;              Fallbacks: Expr() -> Base()
	//  - Base()  would write: id                  Fallbacks: none
	Expr() Builder

	// Alias writes the column alias
	//
	// e.g: if we have this column being built: COUNT(id) AS count:
	//  - Def()   would write: COUNT(id) AS count; Fallbacks: Expr() -> Base()
	//  - Expr()  would write: COUNT(id);          Fallbacks: Base()
	//  - Alias() would write: count;              Fallbacks: Expr() -> Base()
	//  - Base()  would write: id                  Fallbacks: none
	Alias() Builder

	// Base writes the intrinsic value of the column
	//
	// If this column was generated using a complex builder
	// such as Concat() or Search(), this method does nothing,
	// and that may break the statement.
	//
	// e.g: if we have this column being built: COUNT(id) AS count:
	//  - Def()   would write: COUNT(id) AS count; Fallbacks: Expr() -> Base()
	//  - Expr()  would write: COUNT(id);          Fallbacks: Base()
	//  - Alias() would write: count;              Fallbacks: Expr() -> Base()
	//  - Base()  would write: id                  Fallbacks: none
	Base() Builder

	// Count writes COUNT(column) or COUNT(DISTINCT column)
	//
	// @SQL: COUNT([SELF]) / COUNT(DISTINCT [SELF])
	Count(distinct ...bool) Column

	// Sum writes SUM(column) or SUM(DISTINCT column)
	//
	// @SQL: SUM([SELF])
	Sum(distinct ...bool) Column

	// Min writes MIN(column)
	//
	// @SQL: MIN([SELF])
	Min(distinct ...bool) Column

	// Max writes MAX(column)
	//
	// @SQL: MAX([SELF])
	Max(distinct ...bool) Column

	// Avg writes AVG(column)
	//
	// @SQL: AVG([SELF])
	Avg(distinct ...bool) Column

	// Add writes column + value
	//
	// @SQL: [SELF] + value
	Add(v Value) Column

	// Sub writes column - value
	//
	// @SQL: [SELF] - value
	Sub(v Value) Column

	// Mul writes column * value
	//
	// @SQL: [SELF] * value
	Mul(v Value) Column

	// Div writes column / value
	//
	// @SQL: [SELF] / value
	Div(v Value) Column

	// Mod writes column % value
	//
	// @SQL: [SELF] % value
	Mod(v Value) Column

	// Wrap wraps the entire column expression in parentheses
	//
	// @SQL: ([SELF])
	Wrap() Column

	// Lower writes LOWER(column)
	//
	// @SQL: LOWER([SELF])
	Lower() Column

	// Upper writes UPPER(column)
	//
	// @SQL: UPPER([SELF])
	Upper() Column

	// Trim writes TRIM(column)
	//
	// @SQL: TRIM([SELF])
	Trim() Column

	// Round writes ROUND(column)
	//
	// @SQL: ROUND([SELF])
	Round() Column

	// Abs writes ABS(column)
	//
	// @SQL: ABS([SELF])
	Abs() Column

	// As writes an alias for the column
	//
	// @SQL: [SELF] AS `name`
	As(name string) Column
}

Column represents a selectable or computable SQL column. Provides builders for expressions, aliases, aggregates, arithmetic operations, and transformations.

type ColumnBuilder

type ColumnBuilder interface {
	// Col creates a new column reference
	//
	// @SQL: `internal_alias`.`col`
	Col(name string, table ...string) Column

	// All writes the wildcard *
	//
	// You can specify a table to provide context when joins exist.
	// If not specified, the default table will be used.
	//
	// @SQL: *
	All(table ...string) Column

	// Param writes a placeholder
	//
	// You can omit the value for lazy parameters, useful in prepared statements.
	//
	// @SQL: ? / $[number]
	Param(value ...Value) Builder

	// Cond starts a condition block with the given identifier
	//
	// @SQL: `ident` ... [Condition]
	Cond(ident Value) Condition

	// Concat writes CONCAT(...)
	//
	// @SQL: CONCAT(val1, val2, ...)
	Concat(v ...Value) Column

	// Switch writes a simple CASE expression for this column.
	//
	// The argument `cond` is evaluated and compared against literals
	// in each WHEN branch.
	//
	// @SQL:
	//  CASE `cond`
	//    WHEN compartion1 THEN ...
	//    WHEN comparation2 THEN ...
	//    ELSE ...
	//  END
	Switch(cond Value, fn func(cs Case)) Column

	// Search writes a searched CASE expression for this column.
	//
	// Each WHEN branch can use Cond() to define a boolean condition.
	//
	// @SQL:
	//  CASE
	//    WHEN boolean1 THEN ...
	//    WHEN boolean2 THEN ...
	//    ELSE ...
	//  END
	Search(fn func(cs Case)) Column
}

ColumnBuilder provides constructors for columns, placeholders, conditions, concatenations, and CASE-based expressions.

type ColumnType

type ColumnType = core.ColumnType

type ColumnWriter

type ColumnWriter = core.ColumnWriter

type Condition

type Condition interface {
	// Not negates the current condition
	//
	// @SQL: NOT (`cond`)
	Not() Condition

	// Equal writes column = value
	//
	// @SQL: `col` = value
	Equal(v Value) ConditionNext

	// Like writes column LIKE value
	//
	// @SQL: `col` LIKE value
	Like(v Value) ConditionNext

	// Greater writes column > value
	//
	// @SQL: `col` > value
	Greater(v Value) ConditionNext

	// Less writes column < value
	//
	// @SQL: `col` < value
	Less(v Value) ConditionNext

	// In writes column IN (...)
	//
	// @SQL: `col` IN (value1, value2, ...)
	In(v []Value) ConditionNext

	// Between writes column BETWEEN min AND max
	//
	// @SQL: `col` BETWEEN min AND max
	Between(minV, maxV Value) ConditionNext

	// IsNull writes column IS NULL
	//
	// @SQL: `col` IS NULL
	IsNull() ConditionNext
}

Condition represents a SQL condition used in WHERE and HAVING. It supports comparisons, pattern matching, ranges, null checks, and negation.

type ConditionNext

type ConditionNext interface {
	// And links the next condition with AND
	//
	// @SQL: [Condition] ... AND `ident` ... [Condition]
	And(ident Value) Condition

	// Or links the next condition with OR
	//
	// @SQL: [Condition] ... OR `ident` ... [Condition]
	Or(ident Value) Condition
}

ConditionNext represents the continuation of a condition, allowing logical chaining with AND / OR.

type DeleteStmt added in v0.1.1

type DeleteStmt interface {
	Executor
	From
	Where
}

DeleteStmt represents a full DELETE statement

type Engine

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

func New

func New(dialect string, db *sql.DB, opts *Options) *Engine

func (*Engine) NewDelete added in v0.1.1

func (e *Engine) NewDelete(ctx context.Context, table string) (DeleteStmt, ColumnBuilder)

func (*Engine) NewInsert added in v0.1.1

func (e *Engine) NewInsert(ctx context.Context, table string) (InsertStmt, ColumnBuilder)

func (*Engine) NewSelect

func (e *Engine) NewSelect(ctx context.Context, table string) (SelectStmt, ColumnBuilder)

func (*Engine) NewUpdate added in v0.1.1

func (e *Engine) NewUpdate(ctx context.Context, table string) (UpdateStmt, ColumnBuilder)

type Executor added in v0.1.1

type Executor interface {
	Run(binder ...Scanner) error
	Prepare(fn func(exec Prepare) error) error
}

type From

type From interface {
	// From writes the FROM clause
	//
	// # This method is auto-generated for the statement’s default table.
	// Only use it for complex FROM clauses (such as subqueries)
	//
	// @SQL: FROM `table`
	From(table string)
}

From represents the FROM clause, defining the statement's source table or subquery.

type GroupBy

type GroupBy interface {
	// GroupBy writes the GROUP BY clause
	//
	// @SQL: GROUP BY `group1`, `group2`, `group3` ...
	GroupBy(group ...Value)
}

GroupBy represents the GROUP BY clause, grouping the selected rows.

type Having

type Having interface {
	// Having writes the HAVING clause
	//
	// @SQL: HAVING `having` ... [Condition]
	Having(having Value) Condition
}

Having represents the HAVING clause, filtering grouped results using conditions.

type Insert added in v0.1.1

type Insert interface {
	// Insert specifies the columns to insert and returns a Values handler.
	//
	// The argument can be:
	//   - a struct
	//   - a map[string]any
	//   - individual columns
	//   - any type where columns can be read dynamically
	//
	// Example SQL: INSERT INTO `table` (`columns`) VALUES (...)
	Insert(reference ...Value) Values
}

Insert represents the INSERT INTO clause, defining data to insert into a table.

type InsertStmt added in v0.1.1

type InsertStmt interface {
	Executor
	Insert
}

InsertStmt represents a full INSERT statement

type Join

type Join interface {
	// Join writes the JOIN clause
	//
	// @SQL: INNER JOIN `table 'alias'` ... [JoinNext]
	Join(table string) JoinNext
}

Join represents the JOIN clause, initiating a table join operation.

type JoinEnd added in v0.1.1

type JoinEnd interface {
	// On writes the join condition
	//
	// @SQL: [join] ... ON `on` ... [Condition]
	On(on Value) Condition
}

type JoinNext

type JoinNext interface {
	// Left changes the current join type to LEFT JOIN.
	//
	// @SQL: LEFT JOIN `table` ... [JoinEnd]
	Left() JoinEnd

	// Right changes the current join type to RIGHT JOIN.
	//
	// @SQL: RIGHT JOIN `table` ... [JoinEnd]
	Right() JoinEnd

	// Full changes the current join type to FULL JOIN.
	//
	// @SQL: FULL JOIN `table` ... [JoinEnd]
	Full() JoinEnd

	// Cross changes the current join type to CROSS JOIN.
	//
	// CROSS JOIN does not use an ON clause.
	//
	// @SQL: CROSS JOIN `table`
	Cross()

	// On writes the join condition
	//
	// @SQL: [join] ... ON `on` ... [Condition]
	On(on Value) Condition
}

JoinNext represents the ON clause for a join, returning a condition builder.

type Limit

type Limit interface {
	// Limit writes the LIMIT clause value
	//
	// # Values less than 1 will be ignored
	//
	// @SQL: LIMIT `limit`
	Limit(limit int)
}

Limit represents the LIMIT clause, restricting the maximum number of returned rows.

type Offset

type Offset interface {
	// Offset writes the OFFSET clause value
	//
	// # Values less than 1 will be ignored
	//
	// @SQL: OFFSET `offset`
	Offset(offset int)
}

Offset represents the OFFSET clause, skipping a number of rows before returning results.

type Options

type Options struct {
	// ColumnWriter
	// Allows selecting the default way a column would be written
	//
	// the default configuration is:
	//  - Select  = TypeColumnDef
	//  - Join    = TypeColumnBase
	//  - Where   = TypeColumnExpr
	//  - GroupBy = TypeColumnExpr
	//  - Having  = TypeColumnExpr
	//  - OrderBy = TypeColumnAlias
	ColumnWriter ColumnWriter

	// ColumnTag
	// Defines the tag that the mapper uses to read and bind values.
	//
	// Default:
	//  - "col"
	ColumnTag string

	// Limit
	// Sets an auto limit clause if the provided value is greater than 0
	Limit int

	// MaxLimit
	// If the provided limit is greater than the maximum, it will be capped at this value
	MaxLimit int
}

type OrderBy

type OrderBy interface {
	// OrderBy writes the ORDER BY clause
	//
	// # Can be called multiple times for multiple orderings
	//
	// @SQL: ORDER BY `order` ... [OrderByNext]
	OrderBy(order Value) OrderByNext
}

OrderBy represents the ORDER BY clause, sorting rows by one or more identifiers.

type OrderByNext

type OrderByNext interface {
	// Desc writes the descending direction for the current order
	//
	// @SQL: [OrderBy] ... DESC
	Desc()
}

OrderByNext represents ordering modifiers, such as descending direction.

type Prepare added in v0.1.1

type Prepare interface {
	Run(args []Value, scanner ...Scanner) error
}

type Scanner added in v0.1.1

type Scanner = any

type Select

type Select interface {
	// Distinct writes DISTINCT in the SELECT clause
	//
	// @SQL: SELECT `DISTINCT` ...
	Distinct() SelectNext

	// Select writes the SELECT clause values
	//
	// @SQL: SELECT `DISTINCT?` `sel1`, `sel2`, `sel3` ... [SelectNext]
	Select(sel ...Value)
}

Select represents the SELECT clause of a statement, supporting DISTINCT and selectable identifiers.

type SelectNext

type SelectNext interface {
	// Select writes the SELECT clause values
	//
	// @SQL: SELECT `DISTINCT?` `sel1`, `sel2`, `sel3` ... [SelectNext]
	Select(sel ...Value)
}

SelectNext represents additional chained SELECT values when DISTINCT is already applied.

type SelectStmt

type SelectStmt interface {
	Executor
	Select
	From
	Join
	Where
	GroupBy
	Having
	OrderBy
	Limit
	Offset
}

SelectStmt represents a full SELECT statement

type Update added in v0.1.1

type Update interface {
	// Update specifies the columns to update and returns a Values handler.
	//
	// The argument can be:
	//   - a struct
	//   - a map[string]any
	//   - individual columns
	//   - any type where columns can be read dynamically
	//
	// Example SQL: UPDATE `table` SET `column` = ...
	Update(reference ...Value) Values
}

Update represents the UPDATE clause, defining data to update in a table.

type UpdateStmt added in v0.1.1

type UpdateStmt interface {
	Executor
	Update
	Where
}

UpdateStmt represents a full UPDATE statement

type Value

type Value = any

type Values added in v0.1.1

type Values interface {
	// Values sets the actual values to insert or update.
	//
	// Always provide the raw values; placeholders ("?") are handled internally.
	// You can omit this call if using prepared columns without values.
	Values(values Value)
}

Values represents the VALUES clause for INSERT or the assignment values for UPDATE.

type Where

type Where interface {
	// Where writes the WHERE clause
	//
	// # Can be called multiple times,
	// Conditions are combined using the logical "AND".
	// e.g: (cond1) AND (cond2) AND (cond3) ...
	//
	// @SQL: WHERE `ident` ... [Condition]
	Where(ident Value) Condition
}

Where represents the WHERE clause, supporting multiple AND-combined conditions.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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