query

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 12, 2025 License: MIT Imports: 3 Imported by: 0

README

Query Builder (oca/query)

A lightweight SQL query builder for Go, designed to be simple, composable, and easy to extend. It generates parameterized SQL queries and supports a fluent API style.

Road Map

See ROADMAP.md for planned features and progress.

Features

  • Chainable builder API
  • Safe parameter binding (? placeholders)
  • Supports:
    • SELECT with custom columns or *
    • INSERT (InsertInto, Columns, Values)
    • JOIN (INNER, LEFT, RIGHT, FULL
    • WHERE (multiple conditions with AND)
    • ORDER BY
    • LIMIT / OFFSET

Installation

go get github.com/mhdiiilham/oca/query

Usage

INSERT
q := query.InsertInto("users").
    Columns("id", "name", "email").
    Values(1, "Alice", "alice@example.com").
    Values(2, "Bob", "bob@example.com")

sql, args := q.ToSQL()

// sql:  "INSERT INTO users (id, name, email) VALUES (?, ?, ?), (?, ?, ?)"
// args: [1 "Alice" "alice@example.com" 2 "Bob" "bob@example.com"]

INSERT With Returning

q := query.InsertInto("users").
    Columns("name", "email").
    Values("Alice", "alice@example.com").
    ReturningID()

sql, args := q.ToSQL()
// sql:  "INSERT INTO users (name, email) VALUES (?, ?) RETURNING id"
// args: ["Alice", "alice@example.com"]
Basic SELECT
sql, args := query.From("users").
    Select("id", "name").
    Build()

// sql:  "SELECT id, name FROM users"
// args: []
Join
INNER JOIN
sql, args := query.From("users").
    Select("users.id", "profiles.bio").
    Join("profiles", "users.id = profiles.user_id").
    Build()

// sql:  "SELECT users.id, profiles.bio FROM users INNER JOIN profiles ON users.id = profiles.user_id"
// args: []
LEFT JOIN
sql, args := query.From("orders").
    Select("orders.id", "customers.name").
    LeftJoin("customers", "orders.customer_id = customers.id").
    Build()

// sql:  "SELECT orders.id, customers.name FROM orders LEFT JOIN customers ON orders.customer_id = customers.id"
// args: []
RIGHT JOIN
sql, args := query.From("a").
    Select("a.x", "b.y").
    RightJoin("b", "a.id = b.a_id").
    Build()

// sql:  "SELECT a.x, b.y FROM a RIGHT JOIN b ON a.id = b.a_id"
// args: []
FULL JOIN
sql, args := query.From("products").
    Select("products.id", "categories.name").
    FullJoin("categories", "products.category_id = categories.id").
    Build()

// sql:  "SELECT products.id, categories.name FROM products FULL JOIN categories ON products.category_id = categories.id"
// args: []
SELECT with WHERE
sql, args := query.From("users").
    Select("id", "email").
    Where("age > ?", 18).
    Build()

// sql:  "SELECT id, email FROM users WHERE age > ?"
// args: [18]
Multiple WHERE conditions
sql, args := query.From("users").
    Select("id").
    Where("age > ?", 18).
    Where("status = ?", "active").
    Build()

// sql:  "SELECT id FROM users WHERE age > ? AND status = ?"
// args: [18, "active"]
ORDER BY, LIMIT, OFFSET
sql, args := query.From("users").
    Select("id", "email").
    OrderBy("created_at DESC").
    Limit(10).
    Offset(5).
    Build()

// sql:  "SELECT id, email FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?"
// args: [10, 5]
Default SELECT *
sql, args := query.From("products").Build()

// sql:  "SELECT * FROM products"
// args: []

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetDialect

func SetDialect(d Dialect)

SetDialect sets the global SQL dialect for all queries. Example: query.SetDialect(query.PostgresDialect{})

Types

type Builder

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

Builder builds SQL SELECT queries in a fluent DSL style. It supports SELECT, WHERE, ORDER BY, LIMIT, OFFSET.

func From

func From(table string) *Builder

From creates a new Builder for a given table.

func (*Builder) Build

func (b *Builder) Build() (string, []any)

Build assembles the SQL string and returns args.

func (*Builder) FullJoin

func (b *Builder) FullJoin(table, on string) *Builder

FullJoin adds a FULL JOIN clause.

func (*Builder) Join

func (b *Builder) Join(table, on string) *Builder

Join adds an INNER JOIN clause.

func (*Builder) LeftJoin

func (b *Builder) LeftJoin(table, on string) *Builder

LeftJoin adds a LEFT JOIN clause.

func (*Builder) Limit

func (b *Builder) Limit(limit int) *Builder

Limit sets the LIMIT clause.

func (*Builder) Offset

func (b *Builder) Offset(offset int) *Builder

Offset sets the OFFSET clause.

func (*Builder) OrderBy

func (b *Builder) OrderBy(order string) *Builder

OrderBy sets the ORDER BY clause.

func (*Builder) RightJoin

func (b *Builder) RightJoin(table, on string) *Builder

RightJoin adds a RIGHT JOIN clause.

func (*Builder) Select

func (b *Builder) Select(cols ...string) *Builder

Select specifies the columns to select.

func (*Builder) Where

func (b *Builder) Where(conds ...Condition) *Builder

Where adds one or more conditions. Multiple calls are combined with AND.

type Column

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

Column wraps a SQL column name and provides methods for building conditions.

func C

func C(column string) Column

C creates a new column reference that can be used to build conditions. Example: query.C("age").Gt(18)

func (Column) Between

func (c Column) Between(start, end any) Condition

Between creates a condition: "column BETWEEN ? AND ?".

func (Column) Eq

func (c Column) Eq(val any) Condition

Eq creates an equality condition: "column = ?".

func (Column) Gt

func (c Column) Gt(val any) Condition

Gt creates a greater-than condition: "column > ?".

func (Column) Gte

func (c Column) Gte(val any) Condition

Gte creates a greater-than-or-equal condition: "column >= ?".

func (Column) In

func (c Column) In(vals ...any) Condition

In creates a condition: "column IN (?, ?, ...)".

func (Column) IsNotNull

func (c Column) IsNotNull() Condition

IsNotNull creates a condition: "column IS NOT NULL".

func (Column) IsNull

func (c Column) IsNull() Condition

IsNull creates a condition: "column IS NULL".

func (Column) Like

func (c Column) Like(pattern string) Condition

Like creates a condition: "column LIKE ?". Example: query.C("name").Like("%john%")

func (Column) Lt

func (c Column) Lt(val any) Condition

Lt creates a less-than condition: "column < ?".

func (Column) Lte

func (c Column) Lte(val any) Condition

Lte creates a less-than-or-equal condition: "column <= ?".

func (Column) Neq

func (c Column) Neq(val any) Condition

Neq creates a not equal condition: "column != ?".

func (Column) NotBetween

func (c Column) NotBetween(start, end any) Condition

NotBetween creates a condition: "column NOT BETWEEN ? AND ?".

func (Column) NotIn

func (c Column) NotIn(vals ...any) Condition

NotIn creates a condition: "column NOT IN (?, ?, ...)".

func (Column) NotLike

func (c Column) NotLike(pattern string) Condition

NotLike creates a condition: "column NOT LIKE ?".

type Condition

type Condition struct {
	Expr string // SQL expression with placeholders (e.g., "age > ?")
	Args []any  // Values to bind into placeholders
}

Condition represents a SQL WHERE condition expression and its bound arguments. Example: Condition{Expr: "age > ?", Args: []any{18}}

func And

func And(conds ...Condition) Condition

And combines multiple conditions with AND: "(cond1 AND cond2 ...)".

func Not

func Not(cond Condition) Condition

Not negates a condition: "NOT (cond)".

func Or

func Or(conds ...Condition) Condition

Or combines multiple conditions with OR: "(cond1 OR cond2 ...)".

type DeleteBuilder

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

DeleteBuilder builds SQL DELETE queries with dialect support.

func Delete

func Delete(table string) *DeleteBuilder

Delete creates a new DeleteBuilder for the given table.

Example:

q := query.Delete("users").
	Where("id = ?", 42)

sql, args := q.Build()
 MySQL:    "DELETE FROM users WHERE id = ?"
 Postgres: "DELETE FROM users WHERE id = $1"
 args: [42]

func (*DeleteBuilder) Build

func (b *DeleteBuilder) Build() (string, []any)

Build assembles the SQL DELETE query string and returns it with args. It rewrites placeholders depending on the active dialect.

func (*DeleteBuilder) Where

func (b *DeleteBuilder) Where(conds ...Condition) *DeleteBuilder

Where adds a WHERE clause to the DELETE query. Multiple calls are joined with AND.

type Dialect

type Dialect interface {
	// Placeholder returns the placeholder string for the given index.
	// Example: $1 for PostgreSQL, ? for MySQL/MariaDB.
	Placeholder(index int) string
	// Name returns the name of the dialect (for debugging/logging).
	Name() string
}

Dialect defines the behavior that differs across SQL databases. For example, how parameter placeholders are represented.

func GetDialect

func GetDialect() Dialect

GetDialect returns the current global dialect.

type InsertBuilder

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

InsertBuilder builds SQL INSERT statements.

func InsertInto

func InsertInto(table string) *InsertBuilder

InsertInto creates a new InsertBuilder for the given table. Example: query.InsertInto("users")

func (*InsertBuilder) Columns

func (b *InsertBuilder) Columns(cols ...string) *InsertBuilder

Columns sets the columns for the INSERT statement. Example: .Columns("id", "name")

func (*InsertBuilder) Returning

func (b *InsertBuilder) Returning(cols ...string) *InsertBuilder

Returning specifies columns to return (Postgres style). Example: .Returning("id", "created_at")

func (*InsertBuilder) ReturningID

func (b *InsertBuilder) ReturningID() *InsertBuilder

ReturningID is a convenience method for "RETURNING id".

func (*InsertBuilder) ToSQL

func (b *InsertBuilder) ToSQL() (string, []interface{})

ToSQL builds the final INSERT query and returns the SQL string and arguments. Example output: "INSERT INTO users (id, name) VALUES (?, ?) RETURNING id", [1, "John"]

func (*InsertBuilder) Values

func (b *InsertBuilder) Values(vals ...interface{}) *InsertBuilder

Values adds a row of values to insert. Supports RawSQL for literals. Example: .Values(1, "John", query.Raw("NOW()"))

type MariaDBDialect

type MariaDBDialect struct{}

MariaDBDialect behaves the same as MySQL for placeholders.

func (MariaDBDialect) Name

func (d MariaDBDialect) Name() string

Name returns the dialect name.

func (MariaDBDialect) Placeholder

func (d MariaDBDialect) Placeholder(_ int) string

Placeholder returns "?" for all indexes.

type MySQLDialect

type MySQLDialect struct{}

MySQLDialect uses "?" placeholders.

func (MySQLDialect) Name

func (d MySQLDialect) Name() string

Name returns the dialect name.

func (MySQLDialect) Placeholder

func (d MySQLDialect) Placeholder(_ int) string

Placeholder returns "?" for all indexes.

type PostgresDialect

type PostgresDialect struct{}

PostgresDialect uses "$1, $2, ..." placeholders.

func (PostgresDialect) Name

func (d PostgresDialect) Name() string

Name returns the dialect name.

func (PostgresDialect) Placeholder

func (d PostgresDialect) Placeholder(i int) string

Placeholder returns "$n".

type RawSQL

type RawSQL string

RawSQL wraps a SQL literal so it can be inserted directly into the query without being parameterized.

func Raw

func Raw(val string) RawSQL

Raw creates a RawSQL instance. Example: query.Raw("NOW()")

Directories

Path Synopsis
Package mariadb registers the PostgreSQL dialect for the OCA query builder.
Package mariadb registers the PostgreSQL dialect for the OCA query builder.
Package mysql registers the PostgreSQL dialect for the OCA query builder.
Package mysql registers the PostgreSQL dialect for the OCA query builder.
Package pgsql registers the PostgreSQL dialect for the OCA query builder.
Package pgsql registers the PostgreSQL dialect for the OCA query builder.

Jump to

Keyboard shortcuts

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