Full Code of bokwoon95/sq for AI

main eae3b0c03361 cached
44 files
745.8 KB
221.1k tokens
1594 symbols
1 requests
Download .txt
Showing preview only (770K chars total). Download the full file or copy to clipboard to get everything.
Repository: bokwoon95/sq
Branch: main
Commit: eae3b0c03361
Files: 44
Total size: 745.8 KB

Directory structure:
gitextract_lej4qbg4/

├── .github/
│   ├── mddocs
│   └── workflows/
│       ├── neocities.yml
│       └── tests.yml
├── .gitignore
├── LICENSE
├── README.md
├── START_HERE.md
├── builtins.go
├── builtins_test.go
├── colors.go
├── cte.go
├── cte_test.go
├── delete_query.go
├── delete_query_test.go
├── fetch_exec.go
├── fetch_exec_test.go
├── fields.go
├── fields_test.go
├── fmt.go
├── fmt_test.go
├── go.mod
├── go.sum
├── insert_query.go
├── insert_query_test.go
├── integration_test.go
├── internal/
│   ├── googleuuid/
│   │   └── googleuuid.go
│   ├── pqarray/
│   │   └── pqarray.go
│   └── testutil/
│       └── testutil.go
├── joins.go
├── joins_test.go
├── logger.go
├── logger_test.go
├── misc.go
├── misc_test.go
├── row_column.go
├── select_query.go
├── select_query_test.go
├── sq.go
├── sq.md
├── sq_test.go
├── update_query.go
├── update_query_test.go
├── window.go
└── window_test.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/neocities.yml
================================================
name: Deploy docs to Neocities
on:
  push:
    branches: [main]
jobs:
  deploy_to_neocities:
    runs-on: ubuntu-latest
    steps:
      - name: Clone repo
        uses: actions/checkout@v3
      - run: mkdir public && .github/mddocs sq.md public/sq.html
      - name: Deploy to neocities
        uses: bcomnes/deploy-to-neocities@v1
        with:
          api_token: ${{ secrets.NEOCITIES_API_KEY }}
          dist_dir: public


================================================
FILE: .github/workflows/tests.yml
================================================
name: tests
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
jobs:
  run_sq_tests:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres
        env:
          POSTGRES_USER: 'user1'
          POSTGRES_PASSWORD: 'Hunter2!'
          POSTGRES_DB: 'sakila'
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - '5456:5432'
      mysql:
        image: mysql
        env:
          MYSQL_ROOT_PASSWORD: 'Hunter2!'
          MYSQL_USER: 'user1'
          MYSQL_PASSWORD: 'Hunter2!'
          MYSQL_DATABASE: 'sakila'
        options: >-
          --health-cmd "mysqladmin ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
          --health-start-period 30s
        ports:
          - '3330:3306'
      sqlserver:
        image: 'mcr.microsoft.com/azure-sql-edge'
        env:
          ACCEPT_EULA: 'Y'
          MSSQL_SA_PASSWORD: 'Hunter2!'
        options: >-
          --health-cmd "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Hunter2! -Q 'select 1' -b -o /dev/null"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
          --health-start-period 30s
        ports:
          - '1447:1433'
    steps:
      - name: Install go
        uses: actions/setup-go@v3
        with:
          go-version: '>=1.18.0'
      - name: Clone repo
        uses: actions/checkout@v3
      - run: go test . -tags=fts5 -failfast -shuffle on -coverprofile coverage -race -postgres 'postgres://user1:Hunter2!@localhost:5456/sakila?sslmode=disable' -mysql 'root:Hunter2!@tcp(localhost:3330)/sakila?multiStatements=true&parseTime=true' -sqlserver 'sqlserver://sa:Hunter2!@localhost:1447'
      - name: Convert coverage to coverage.lcov
        uses: jandelgado/gcov2lcov-action@v1.0.0
        with:
          infile: coverage
          outfile: coverage.lcov
      - name: Upload coverage.lcov to Coveralls
        uses: coverallsapp/github-action@master
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          path-to-lcov: coverage.lcov


================================================
FILE: .gitignore
================================================
*.sqlite*
.idea
coverage.out
coverage


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2022 Chua Bok Woon

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
[![GoDoc](https://img.shields.io/badge/pkg.go.dev-sq-blue)](https://pkg.go.dev/github.com/bokwoon95/sq)
![tests](https://github.com/bokwoon95/sq/actions/workflows/tests.yml/badge.svg?branch=main)
[![Go Report Card](https://goreportcard.com/badge/github.com/bokwoon95/sq)](https://goreportcard.com/report/github.com/bokwoon95/sq)
[![Coverage Status](https://coveralls.io/repos/github/bokwoon95/sq/badge.svg?branch=main)](https://coveralls.io/github/bokwoon95/sq?branch=main)

<img src="https://raw.githubusercontent.com/bokwoon95/sq/main/header.png" title="code example of a select query using sq" alt="code example of a select query using sq, to give viewers a quick idea of what the library is about" style="max-width:90%;">

# sq (Structured Query)

[one-page documentation](https://bokwoon.neocities.org/sq.html)

sq is a type-safe data mapper and query builder for Go. Its concept is simple: you provide a callback function that maps a row to a struct, generics ensure that you get back a slice of structs at the end. Additionally, mentioning a column in the callback function automatically adds it to the SELECT clause so you don't even have to explicitly mention what columns you want to select: the [act of mapping a column is the same as selecting it](#select-example-raw-sql). This eliminates a source of errors where you have specify the columns twice (once in the query itself, once to the call to rows.Scan) and end up missing a column, getting the column order wrong or mistyping a column name.

Notable features:

- Works across SQLite, Postgres, MySQL and SQL Server. [[more info](https://bokwoon.neocities.org/sq.html#set-query-dialect)]
- Each dialect has its own query builder, allowing you to use dialect-specific features. [[more info](https://bokwoon.neocities.org/sq.html#dialect-specific-features)]
- Declarative schema migrations. [[more info](https://bokwoon.neocities.org/sq.html#declarative-schema)]
- Supports arrays, enums, JSON and UUID. [[more info](https://bokwoon.neocities.org/sq.html#arrays-enums-json-uuid)]
- Query logging. [[more info](https://bokwoon.neocities.org/sq.html#logging)]

# Installation

This package only supports Go 1.19 and above.

```shell
$ go get github.com/bokwoon95/sq
$ go install -tags=fts5 github.com/bokwoon95/sqddl@latest
```

# Features

- IN
    - [In Slice](https://bokwoon.neocities.org/sq.html#in-slice) - `a IN (1, 2, 3)`
    - [In RowValues](https://bokwoon.neocities.org/sq.html#in-rowvalues) - `(a, b, c) IN ((1, 2, 3), (4, 5, 6), (7, 8, 9))`
    - [In Subquery](https://bokwoon.neocities.org/sq.html#in-subquery) - `(a, b) IN (SELECT a, b FROM tbl WHERE condition)`
- CASE
    - [Predicate Case](https://bokwoon.neocities.org/sq.html#predicate-case) - `CASE WHEN a THEN b WHEN c THEN d ELSE e END`
    - [Simple case](https://bokwoon.neocities.org/sq.html#simple-case) - `CASE expr WHEN a THEN b WHEN c THEN d ELSE e END`
- EXISTS
    - [Where Exists](https://bokwoon.neocities.org/sq.html#where-exists)
    - [Where Not Exists](https://bokwoon.neocities.org/sq.html#where-not-exists)
    - [Select Exists](https://bokwoon.neocities.org/sq.html#querybuilder-fetch-exists)
- [Subqueries](https://bokwoon.neocities.org/sq.html#subqueries)
- [WITH (Common Table Expressions)](https://bokwoon.neocities.org/sq.html#common-table-expressions)
- [Aggregate functions](https://bokwoon.neocities.org/sq.html#aggregate-functions)
- [Window functions](https://bokwoon.neocities.org/sq.html#window-functions)
- [UNION, INTERSECT, EXCEPT](https://bokwoon.neocities.org/sq.html#union-intersect-except)
- [INSERT from SELECT](https://bokwoon.neocities.org/sq.html#querybuilder-insert-from-select)
- RETURNING
    - [SQLite RETURNING](https://bokwoon.neocities.org/sq.html#sqlite-returning)
    - [Postgres RETURNING](https://bokwoon.neocities.org/sq.html#postgres-returning)
- LastInsertId
    - [SQLite LastInsertId](https://bokwoon.neocities.org/sq.html#sqlite-last-insert-id)
    - [MySQL LastInsertId](https://bokwoon.neocities.org/sq.html#mysql-last-insert-id)
- Insert ignore duplicates
    - [SQLite Insert ignore duplicates](https://bokwoon.neocities.org/sq.html#sqlite-insert-ignore-duplicates)
    - [Postgres Insert ignore duplicates](https://bokwoon.neocities.org/sq.html#postgres-insert-ignore-duplicates)
    - [MySQL Insert ignore duplicates](https://bokwoon.neocities.org/sq.html#mysql-insert-ignore-duplicates)
    - [SQL Server Insert ignore duplicates](https://bokwoon.neocities.org/sq.html#sqlserver-insert-ignore-duplicates)
- Upsert
    - [SQLite Upsert](https://bokwoon.neocities.org/sq.html#sqlite-upsert)
    - [Postgres Upsert](https://bokwoon.neocities.org/sq.html#postgres-upsert)
    - [MySQL Upsert](https://bokwoon.neocities.org/sq.html#mysql-upsert)
    - [SQL Server Upsert](https://bokwoon.neocities.org/sq.html#sqlserver-upsert)
- Update with Join
    - [SQLite Update with Join](https://bokwoon.neocities.org/sq.html#sqlite-update-with-join)
    - [Postgres Update with Join](https://bokwoon.neocities.org/sq.html#postgres-update-with-join)
    - [MySQL Update with Join](https://bokwoon.neocities.org/sq.html#mysql-update-with-join)
    - [SQL Server Update with Join](https://bokwoon.neocities.org/sq.html#sqlserver-update-with-join)
- Delete with Join
    - [SQLite Delete with Join](https://bokwoon.neocities.org/sq.html#sqlite-delete-with-join)
    - [Postgres Delete with Join](https://bokwoon.neocities.org/sq.html#postgres-delete-with-join)
    - [MySQL Delete with Join](https://bokwoon.neocities.org/sq.html#mysql-delete-with-join)
    - [SQL Server Delete with Join](https://bokwoon.neocities.org/sq.html#sqlserver-delete-with-join)
- Bulk Update
    - [SQLite Bulk Update](https://bokwoon.neocities.org/sq.html#sqlite-bulk-update)
    - [Postgres Bulk Update](https://bokwoon.neocities.org/sq.html#postgres-bulk-update)
    - [MySQL Bulk Update](https://bokwoon.neocities.org/sq.html#mysql-bulk-update)
    - [SQL Server Bulk Update](https://bokwoon.neocities.org/sq.html#sqlserver-bulk-update)

## SELECT example (Raw SQL)

```go
db, err := sql.Open("postgres", "postgres://username:password@localhost:5432/sakila?sslmode=disable")

actors, err := sq.FetchAll(db, sq.
    Queryf("SELECT {*} FROM actor AS a WHERE a.actor_id IN ({})",
        []int{1, 2, 3, 4, 5},
    ).
    SetDialect(sq.DialectPostgres),
    func(row *sq.Row) Actor {
        return Actor{
            ActorID:     row.Int("a.actor_id"),
            FirstName:   row.String("a.first_name"),
            LastName:    row.String("a.last_name"),
            LastUpdate:  row.Time("a.last_update"),
        }
    },
)
```

## SELECT example (Query Builder)

To use the query builder, you must first [define your table structs](https://bokwoon.neocities.org/sq.html#table-structs).

```go
type ACTOR struct {
    sq.TableStruct
    ACTOR_ID    sq.NumberField
    FIRST_NAME  sq.StringField
    LAST_NAME   sq.StringField
    LAST_UPDATE sq.TimeField
}

db, err := sql.Open("postgres", "postgres://username:password@localhost:5432/sakila?sslmode=disable")

a := sq.New[ACTOR]("a")
actors, err := sq.FetchAll(db, sq.
    From(a).
    Where(a.ACTOR_ID.In([]int{1, 2, 3, 4, 5})).
    SetDialect(sq.DialectPostgres),
    func(row *sq.Row) Actor {
        return Actor{
            ActorID:     row.IntField(a.ACTOR_ID),
            FirstName:   row.StringField(a.FIRST_NAME),
            LastName:    row.StringField(a.LAST_NAME),
            LastUpdate:  row.TimeField(a.LAST_UPDATE),
        }
    },
)
```

## INSERT example (Raw SQL)

```go
db, err := sql.Open("postgres", "postgres://username:password@localhost:5432/sakila?sslmode=disable")

_, err := sq.Exec(db, sq.
    Queryf("INSERT INTO actor (actor_id, first_name, last_name) VALUES {}", sq.RowValues{
        {18, "DAN", "TORN"},
        {56, "DAN", "HARRIS"},
        {166, "DAN", "STREEP"},
    }).
    SetDialect(sq.DialectPostgres),
)
```

## INSERT example (Query Builder)

To use the query builder, you must first [define your table structs](https://bokwoon.neocities.org/sq.html#table-structs).

```go
type ACTOR struct {
    sq.TableStruct
    ACTOR_ID    sq.NumberField
    FIRST_NAME  sq.StringField
    LAST_NAME   sq.StringField
    LAST_UPDATE sq.TimeField
}

db, err := sql.Open("postgres", "postgres://username:password@localhost:5432/sakila?sslmode=disable")

a := sq.New[ACTOR]("a")
_, err := sq.Exec(db, sq.
    InsertInto(a).
    Columns(a.ACTOR_ID, a.FIRST_NAME, a.LAST_NAME).
    Values(18, "DAN", "TORN").
    Values(56, "DAN", "HARRIS").
    Values(166, "DAN", "STREEP").
    SetDialect(sq.DialectPostgres),
)
```

For a more detailed overview, look at the [Quickstart](https://bokwoon.neocities.org/sq.html#quickstart).

## Project Status

sq is done for my use case (hence it may seem inactive, but it's just complete). At this point I'm just waiting for people to ask questions or file feature requests under [discussions](https://github.com/bokwoon95/sq/discussions).

## Contributing

See [START\_HERE.md](https://github.com/bokwoon95/sq/blob/main/START_HERE.md).


================================================
FILE: START_HERE.md
================================================
This document describes how the codebase is organized. It is meant for people who are contributing to the codebase (or are just casually browsing).

Files are written in such a way that **each successive file in the list below only depends on files that come before it**. This self-enforced restriction makes deep architectural changes trivial because you can essentially blow away the entire codebase and rewrite it from scratch file-by-file, complete with working tests every step of the way. Please adhere to this file order when submitting pull requests.

- [**sq.go**](https://github.com/bokwoon95/sq/blob/main/sq.go)
    - Core interfaces: SQLWriter, DB, Query, Table, PolicyTable, Window, Field, Predicate, Assignment, Any, Array, Binary, Boolean, Enum, JSON, Number, String, UUID, Time, Enumeration, DialectValuer,
    - Data types: Result, TableStruct, ViewStruct.
    - Misc utility functions.
- [**fmt.go**](https://github.com/bokwoon95/sq/blob/main/fmt.go)
    - Two important string building functions that everything else is built on: [Writef](https://pkg.go.dev/github.com/bokwoon95/sq#Writef) and [WriteValue](https://pkg.go.dev/github.com/bokwoon95/sq#WriteValue).
    - Data types: Parameter, BinaryParameter, BooleanParameter, NumberParameter, StringParameter, TimeParameter.
    - Utility functions: QuoteIdentifier, EscapeQuote, Sprintf, Sprint.
- [**builtins.go**](https://github.com/bokwoon95/sq/blob/main/builtins.go)
    - Builtin data types that are built on top of Writef and WriteValue: Expression (Expr), CustomQuery (Queryf), VariadicPredicate, assignment, RowValue, RowValues, Fields.
    - Builtin functions that are built on top of Writef and WriteValue: Eq, Ne, Lt, Le, Gt, Ge, Exists, NotExists, In.
- [**fields.go**](https://github.com/bokwoon95/sq/blob/main/fields.go)
    - All of the field types: AnyField, ArrayField, BinaryField, BooleanField, EnumField, JSONField, NumberField, StringField, UUIDField, TimeField.
    - Data types: Identifier, Timestamp.
    - Functions: [New](https://pkg.go.dev/github.com/bokwoon95/sq#New), ArrayValue, EnumValue, JSONValue, UUIDValue.
- [**cte.go**](https://github.com/bokwoon95/sq/blob/main/cte.go)
    - CTE represents an SQL common table expression (CTE).
    - UNION, INTERSECT, EXCEPT.
- [**joins.go**](https://github.com/bokwoon95/sq/blob/main/joins.go)
    - The various SQL joins.
- [**row_column.go**](https://github.com/bokwoon95/sq/blob/main/row_column.go)
    - Row and Column methods.
- [**window.go**](https://github.com/bokwoon95/sq/blob/main/window.go)
    - SQL windows and window functions.
- [**select_query.go**](https://github.com/bokwoon95/sq/blob/main/select_query.go)
    - SQL SELECT query builder.
- [**insert_query.go**](https://github.com/bokwoon95/sq/blob/main/insert_query.go)
    - SQL INSERT query builder.
- [**update_query.go**](https://github.com/bokwoon95/sq/blob/main/update_query.go)
    - SQL UPDATE query builder.
- [**delete_query.go**](https://github.com/bokwoon95/sq/blob/main/delete_query.go)
    - SQL DELETE query builder.
- [**logger.go**](https://github.com/bokwoon95/sq/blob/main/logger.go)
    - sq.Log and sq.VerboseLog.
- [**fetch_exec.go**](https://github.com/bokwoon95/sq/blob/main/fetch_exec.go)
    - FetchCursor, FetchOne, FetchAll, Exec.
    - CompiledFetch, CompiledExec.
    - PreparedFetch, PreparedExec.
- [**misc.go**](https://github.com/bokwoon95/sq/blob/main/misc.go)
    - Misc SQL constructs.
    - ValueExpression, LiteralValue, DialectExpression, CaseExpression, SimpleCaseExpression.
    - SelectValues (`SELECT ... UNION ALL SELECT ... UNION ALL SELECT ...`)
    - TableValues (`VALUES (...), (...), (...)`).
- [**integration_test.go**](https://github.com/bokwoon95/sq/blob/main/integration_test.go)
    - Tests that interact with a live database i.e. SQLite, Postgres, MySQL and SQL Server.

## Testing

Add tests if you add code.

To run tests, use:

```shell
$ go test . # -failfast -shuffle=on -coverprofile=coverage
```

There are tests that require a live database connection. They will only run if you provide the corresponding database URL in the test flags:

```shell
$ go test . -postgres $POSTGRES_URL -mysql $MYSQL_URL -sqlserver $SQLSERVER_URL # -failfast -shuffle=on -coverprofile=coverage
```

You can consider using the [docker-compose.yml defined in the sqddl repo](https://github.com/bokwoon95/sqddl/blob/main/docker-compose.yml) to spin up Postgres, MySQL and SQL Server databases that are reachable at the following URLs:

```shell
# docker-compose up -d
POSTGRES_URL='postgres://user1:Hunter2!@localhost:5456/sakila?sslmode=disable'
MYSQL_URL='root:Hunter2!@tcp(localhost:3330)/sakila?multiStatements=true&parseTime=true'
MARIADB_URL='root:Hunter2!@tcp(localhost:3340)/sakila?multiStatements=true&parseTime=true'
SQLSERVER_URL='sqlserver://sa:Hunter2!@localhost:1447'
```

## Documentation

Documentation is contained entirely within [sq.md](https://github.com/bokwoon95/sq/blob/main/sq.md) in the project root directory. You can view the output at [https://bokwoon.neocities.org/sq.html](https://bokwoon.neocities.org/sq.html). The documentation is regenerated everytime a new commit is pushed to the main branch, so to change the documentation just change sq.md and submit a pull request.

You can preview the output of sq.md locally by installing [github.com/bokwoon95/mddocs](https://github.com/bokwoon95/mddocs) and running it with sq.md as the argument.

```shell
$ go install github/bokwoon95/mddocs@latest
$ mddocs
Usage:
mddocs project.md              # serves project.md on a localhost connection
mddocs project.md project.html # render project.md into project.html

$ mddocs sq.md
serving sq.md at localhost:6060
```

To add a new section and register it in the table of contents, append a `#headerID` to the end of a header (replace `headerID` with the actual header ID). The header ID should only contain unicode letters, digits, hyphen `-` and underscore `_`.

```text
## This is a header.

## This is a header with a headerID. #header-id <-- added to table of contents
```


================================================
FILE: builtins.go
================================================
package sq

import (
	"bytes"
	"context"
	"fmt"
	"strings"
)

// Expression is an SQL expression that satisfies the Table, Field, Predicate,
// Binary, Boolean, Number, String and Time interfaces.
type Expression struct {
	format string
	values []any
	alias  string
}

var _ interface {
	Table
	Field
	Predicate
	Any
	Assignment
} = (*Expression)(nil)

// Expr creates a new Expression using Writef syntax.
func Expr(format string, values ...any) Expression {
	return Expression{format: format, values: values}
}

// WriteSQL implements the SQLWriter interface.
func (expr Expression) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	err := Writef(ctx, dialect, buf, args, params, expr.format, expr.values)
	if err != nil {
		return err
	}
	return nil
}

// As returns a new Expression with the given alias.
func (expr Expression) As(alias string) Expression {
	expr.alias = alias
	return expr
}

// In returns an 'expr IN (value)' Predicate.
func (expr Expression) In(value any) Predicate { return In(expr, value) }

// In returns an 'expr NOT IN (value)' Predicate.
func (expr Expression) NotIn(value any) Predicate { return NotIn(expr, value) }

// Eq returns an 'expr = value' Predicate.
func (expr Expression) Eq(value any) Predicate { return cmp("=", expr, value) }

// Ne returns an 'expr <> value' Predicate.
func (expr Expression) Ne(value any) Predicate { return cmp("<>", expr, value) }

// Lt returns an 'expr < value' Predicate.
func (expr Expression) Lt(value any) Predicate { return cmp("<", expr, value) }

// Le returns an 'expr <= value' Predicate.
func (expr Expression) Le(value any) Predicate { return cmp("<=", expr, value) }

// Gt returns an 'expr > value' Predicate.
func (expr Expression) Gt(value any) Predicate { return cmp(">", expr, value) }

// Ge returns an 'expr >= value' Predicate.
func (expr Expression) Ge(value any) Predicate { return cmp(">=", expr, value) }

// GetAlias returns the alias of the Expression.
func (expr Expression) GetAlias() string { return expr.alias }

// IsTable implements the Table interface.
func (expr Expression) IsTable() {}

// IsField implements the Field interface.
func (expr Expression) IsField() {}

// IsArray implements the Array interface.
func (expr Expression) IsArray() {}

// IsBinary implements the Binary interface.
func (expr Expression) IsBinary() {}

// IsBoolean implements the Boolean interface.
func (expr Expression) IsBoolean() {}

// IsEnum implements the Enum interface.
func (expr Expression) IsEnum() {}

// IsJSON implements the JSON interface.
func (expr Expression) IsJSON() {}

// IsNumber implements the Number interface.
func (expr Expression) IsNumber() {}

// IsString implements the String interface.
func (expr Expression) IsString() {}

// IsTime implements the Time interface.
func (expr Expression) IsTime() {}

// IsUUID implements the UUID interface.
func (expr Expression) IsUUID() {}

func (e Expression) IsAssignment() {}

// CustomQuery represents a user-defined query.
type CustomQuery struct {
	Dialect string
	Format  string
	Values  []any
	fields  []Field
}

var _ Query = (*CustomQuery)(nil)

// Queryf creates a new query using Writef syntax.
func Queryf(format string, values ...any) CustomQuery {
	return CustomQuery{Format: format, Values: values}
}

// Queryf creates a new SQLite query using Writef syntax.
func (b sqliteQueryBuilder) Queryf(format string, values ...any) CustomQuery {
	return CustomQuery{Dialect: DialectSQLite, Format: format, Values: values}
}

// Queryf creates a new Postgres query using Writef syntax.
func (b postgresQueryBuilder) Queryf(format string, values ...any) CustomQuery {
	return CustomQuery{Dialect: DialectPostgres, Format: format, Values: values}
}

// Queryf creates a new MySQL query using Writef syntax.
func (b mysqlQueryBuilder) Queryf(format string, values ...any) CustomQuery {
	return CustomQuery{Dialect: DialectMySQL, Format: format, Values: values}
}

// Queryf creates a new SQL Server query using Writef syntax.
func (b sqlserverQueryBuilder) Queryf(format string, values ...any) CustomQuery {
	return CustomQuery{Dialect: DialectSQLServer, Format: format, Values: values}
}

// Append returns a new CustomQuery with the format string and values slice
// appended to the current CustomQuery.
func (q CustomQuery) Append(format string, values ...any) CustomQuery {
	q.Format += " " + format
	q.Values = append(q.Values, values...)
	return q
}

// WriteSQL implements the SQLWriter interface.
func (q CustomQuery) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	var err error
	format := q.Format
	splitAt := -1
	for i := strings.IndexByte(format, '{'); i >= 0; i = strings.IndexByte(format, '{') {
		if i+2 <= len(format) && format[i:i+2] == "{{" {
			format = format[i+2:]
			continue
		}
		if i+3 <= len(format) && format[i:i+3] == "{*}" {
			splitAt = len(q.Format) - len(format[i:])
			break
		}
		format = format[i+1:]
	}
	if splitAt < 0 {
		return Writef(ctx, dialect, buf, args, params, q.Format, q.Values)
	}
	runningValuesIndex := 0
	ordinalIndices := make(map[int]int)
	err = writef(ctx, dialect, buf, args, params, q.Format[:splitAt], q.Values, &runningValuesIndex, ordinalIndices)
	if err != nil {
		return err
	}
	err = writeFields(ctx, dialect, buf, args, params, q.fields, true)
	if err != nil {
		return err
	}
	err = writef(ctx, dialect, buf, args, params, q.Format[splitAt+3:], q.Values, &runningValuesIndex, ordinalIndices)
	if err != nil {
		return err
	}
	return nil
}

// SetFetchableFields sets the fetchable fields of the query.
func (q CustomQuery) SetFetchableFields(fields []Field) (query Query, ok bool) {
	format := q.Format
	for i := strings.IndexByte(format, '{'); i >= 0; i = strings.IndexByte(format, '{') {
		if i+2 <= len(format) && format[i:i+2] == "{{" {
			format = format[i+2:]
			continue
		}
		if i+3 <= len(format) && format[i:i+3] == "{*}" {
			q.fields = fields
			return q, true
		}
		format = format[i+1:]
	}
	return q, false
}

// GetFetchableFields gets the fetchable fields of the query.
func (q CustomQuery) GetFetchableFields() []Field {
	return q.fields
}

// GetDialect gets the dialect of the query.
func (q CustomQuery) GetDialect() string { return q.Dialect }

// SetDialect sets the dialect of the query.
func (q CustomQuery) SetDialect(dialect string) CustomQuery {
	q.Dialect = dialect
	return q
}

// VariadicPredicate represents the 'x AND y AND z...' or 'x OR Y OR z...' SQL
// construct.
type VariadicPredicate struct {
	// Toplevel indicates if the VariadicPredicate can skip writing the
	// (surrounding brackets).
	Toplevel bool
	alias    string
	// If IsDisjunction is true, the Predicates are joined using OR. If false,
	// the Predicates are joined using AND. The default is AND.
	IsDisjunction bool
	// Predicates holds the predicates inside the VariadicPredicate
	Predicates []Predicate
}

var _ Predicate = (*VariadicPredicate)(nil)

// And joins the predicates together with the AND operator.
func And(predicates ...Predicate) VariadicPredicate {
	return VariadicPredicate{IsDisjunction: false, Predicates: predicates}
}

// Or joins the predicates together with the OR operator.
func Or(predicates ...Predicate) VariadicPredicate {
	return VariadicPredicate{IsDisjunction: true, Predicates: predicates}
}

// WriteSQL implements the SQLWriter interface.
func (p VariadicPredicate) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	var err error
	if len(p.Predicates) == 0 {
		return fmt.Errorf("VariadicPredicate empty")
	}

	if len(p.Predicates) == 1 {
		switch p1 := p.Predicates[0].(type) {
		case nil:
			return fmt.Errorf("predicate #1 is nil")
		case VariadicPredicate:
			p1.Toplevel = p.Toplevel
			err = p1.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return err
			}
		default:
			err = p.Predicates[0].WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return err
			}
		}
		return nil
	}

	if !p.Toplevel {
		buf.WriteString("(")
	}
	for i, predicate := range p.Predicates {
		if i > 0 {
			if p.IsDisjunction {
				buf.WriteString(" OR ")
			} else {
				buf.WriteString(" AND ")
			}
		}
		switch predicate := predicate.(type) {
		case nil:
			return fmt.Errorf("predicate #%d is nil", i+1)
		case VariadicPredicate:
			predicate.Toplevel = false
			err = predicate.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return fmt.Errorf("predicate #%d: %w", i+1, err)
			}
		default:
			err = predicate.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return fmt.Errorf("predicate #%d: %w", i+1, err)
			}
		}
	}
	if !p.Toplevel {
		buf.WriteString(")")
	}
	return nil
}

// As returns a new VariadicPredicate with the given alias.
func (p VariadicPredicate) As(alias string) VariadicPredicate {
	p.alias = alias
	return p
}

// GetAlias returns the alias of the VariadicPredicate.
func (p VariadicPredicate) GetAlias() string { return p.alias }

// IsField implements the Field interface.
func (p VariadicPredicate) IsField() {}

// IsBooleanType implements the Predicate interface.
func (p VariadicPredicate) IsBoolean() {}

// assignment represents assigning a value to a Field.
type assignment struct {
	field Field
	value any
}

var _ Assignment = (*assignment)(nil)

// Set creates a new Assignment assigning the value to a field.
func Set(field Field, value any) Assignment {
	return assignment{field: field, value: value}
}

// Setf creates a new Assignment assigning a custom expression to a Field.
func Setf(field Field, format string, values ...any) Assignment {
	return assignment{field: field, value: Expr(format, values...)}
}

// WriteSQL implements the SQLWriter interface.
func (a assignment) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	if a.field == nil {
		return fmt.Errorf("field is nil")
	}
	var err error
	if dialect == DialectMySQL {
		err = a.field.WriteSQL(ctx, dialect, buf, args, params)
		if err != nil {
			return err
		}
	} else {
		err = withPrefix(a.field, "").WriteSQL(ctx, dialect, buf, args, params)
		if err != nil {
			return err
		}
	}
	buf.WriteString(" = ")
	_, isQuery := a.value.(Query)
	if isQuery {
		buf.WriteString("(")
	}
	err = WriteValue(ctx, dialect, buf, args, params, a.value)
	if err != nil {
		return err
	}
	if isQuery {
		buf.WriteString(")")
	}
	return nil
}

// IsAssignment implements the Assignment interface.
func (a assignment) IsAssignment() {}

// Assignments represents a list of Assignments e.g. x = 1, y = 2, z = 3.
type Assignments []Assignment

// WriteSQL implements the SQLWriter interface.
func (as Assignments) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	var err error
	for i, assignment := range as {
		if assignment == nil {
			return fmt.Errorf("assignment #%d is nil", i+1)
		}
		if i > 0 {
			buf.WriteString(", ")
		}
		err = assignment.WriteSQL(ctx, dialect, buf, args, params)
		if err != nil {
			return fmt.Errorf("assignment #%d: %w", i+1, err)
		}
	}
	return nil
}

// RowValue represents an SQL row value expression e.g. (x, y, z).
type RowValue []any

// WriteSQL implements the SQLWriter interface.
func (r RowValue) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	buf.WriteString("(")
	var err error
	for i, value := range r {
		if i > 0 {
			buf.WriteString(", ")
		}
		_, isQuery := value.(Query)
		if isQuery {
			buf.WriteString("(")
		}
		err = WriteValue(ctx, dialect, buf, args, params, value)
		if err != nil {
			return fmt.Errorf("rowvalue #%d: %w", i+1, err)
		}
		if isQuery {
			buf.WriteString(")")
		}
	}
	buf.WriteString(")")
	return nil
}

// In returns an 'rowvalue IN (value)' Predicate.
func (r RowValue) In(v any) Predicate { return In(r, v) }

// NotIn returns an 'rowvalue NOT IN (value)' Predicate.
func (r RowValue) NotIn(v any) Predicate { return NotIn(r, v) }

// Eq returns an 'rowvalue = value' Predicate.
func (r RowValue) Eq(v any) Predicate { return cmp("=", r, v) }

// RowValues represents a list of RowValues e.g. (x, y, z), (a, b, c).
type RowValues []RowValue

// WriteSQL implements the SQLWriter interface.
func (rs RowValues) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	var err error
	for i, r := range rs {
		if i > 0 {
			buf.WriteString(", ")
		}
		err = r.WriteSQL(ctx, dialect, buf, args, params)
		if err != nil {
			return fmt.Errorf("rowvalues #%d: %w", i+1, err)
		}
	}
	return nil
}

// Fields represents a list of Fields e.g. tbl.field1, tbl.field2, tbl.field3.
type Fields []Field

// WriteSQL implements the SQLWriter interface.
func (fs Fields) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	var err error
	for i, field := range fs {
		if field == nil {
			return fmt.Errorf("field #%d is nil", i+1)
		}
		if i > 0 {
			buf.WriteString(", ")
		}
		_, isQuery := field.(Query)
		if isQuery {
			buf.WriteString("(")
		}
		err = field.WriteSQL(ctx, dialect, buf, args, params)
		if err != nil {
			return fmt.Errorf("field #%d: %w", i+1, err)
		}
		if isQuery {
			buf.WriteString(")")
		}
	}
	return nil
}

type (
	sqliteQueryBuilder    struct{ ctes []CTE }
	postgresQueryBuilder  struct{ ctes []CTE }
	mysqlQueryBuilder     struct{ ctes []CTE }
	sqlserverQueryBuilder struct{ ctes []CTE }
)

// Dialect-specific query builder variables.
var (
	SQLite    sqliteQueryBuilder
	Postgres  postgresQueryBuilder
	MySQL     mysqlQueryBuilder
	SQLServer sqlserverQueryBuilder
)

// With sets the CTEs in the SQLiteQueryBuilder.
func (b sqliteQueryBuilder) With(ctes ...CTE) sqliteQueryBuilder {
	b.ctes = ctes
	return b
}

// With sets the CTEs in the PostgresQueryBuilder.
func (b postgresQueryBuilder) With(ctes ...CTE) postgresQueryBuilder {
	b.ctes = ctes
	return b
}

// With sets the CTEs in the MySQLQueryBuilder.
func (b mysqlQueryBuilder) With(ctes ...CTE) mysqlQueryBuilder {
	b.ctes = ctes
	return b
}

// With sets the CTEs in the SQLServerQueryBuilder.
func (b sqlserverQueryBuilder) With(ctes ...CTE) sqlserverQueryBuilder {
	b.ctes = ctes
	return b
}

// ToSQL converts an SQLWriter into a query string and args slice.
//
// The params map is used to hold the mappings between named parameters in the
// query to the corresponding index in the args slice and is used for rebinding
// args by their parameter name. If you don't need to track this, you can pass
// in a nil map.
func ToSQL(dialect string, w SQLWriter, params map[string][]int) (query string, args []any, err error) {
	return ToSQLContext(context.Background(), dialect, w, params)
}

// ToSQLContext is like ToSQL but additionally requires a context.Context.
func ToSQLContext(ctx context.Context, dialect string, w SQLWriter, params map[string][]int) (query string, args []any, err error) {
	if w == nil {
		return "", nil, fmt.Errorf("SQLWriter is nil")
	}
	if dialect == "" {
		if q, ok := w.(Query); ok {
			dialect = q.GetDialect()
		}
	}
	buf := bufpool.Get().(*bytes.Buffer)
	buf.Reset()
	defer bufpool.Put(buf)
	err = w.WriteSQL(ctx, dialect, buf, &args, params)
	query = buf.String()
	if err != nil {
		return query, args, err
	}
	return query, args, nil
}

// Eq returns an 'x = y' Predicate.
func Eq(x, y any) Predicate { return cmp("=", x, y) }

// Ne returns an 'x <> y' Predicate.
func Ne(x, y any) Predicate { return cmp("<>", x, y) }

// Lt returns an 'x < y' Predicate.
func Lt(x, y any) Predicate { return cmp("<", x, y) }

// Le returns an 'x <= y' Predicate.
func Le(x, y any) Predicate { return cmp("<=", x, y) }

// Gt returns an 'x > y' Predicate.
func Gt(x, y any) Predicate { return cmp(">", x, y) }

// Ge returns an 'x >= y' Predicate.
func Ge(x, y any) Predicate { return cmp(">=", x, y) }

// Exists returns an 'EXISTS (query)' Predicate.
func Exists(query Query) Predicate { return Expr("EXISTS ({})", query) }

// NotExists returns a 'NOT EXISTS (query)' Predicate.
func NotExists(query Query) Predicate { return Expr("NOT EXISTS ({})", query) }

// In returns an 'x IN (y)' Predicate.
func In(x, y any) Predicate {
	_, isQueryA := x.(Query)
	_, isRowValueB := y.(RowValue)
	if !isQueryA && !isRowValueB {
		return Expr("{} IN ({})", x, y)
	} else if !isQueryA && isRowValueB {
		return Expr("{} IN {}", x, y)
	} else if isQueryA && !isRowValueB {
		return Expr("({}) IN ({})", x, y)
	} else {
		return Expr("({}) IN {}", x, y)
	}
}

// NotIn returns an 'x NOT IN (y)' Predicate.
func NotIn(x, y any) Predicate {
	_, isQueryA := x.(Query)
	_, isRowValueB := y.(RowValue)
	if !isQueryA && !isRowValueB {
		return Expr("{} NOT IN ({})", x, y)
	} else if !isQueryA && isRowValueB {
		return Expr("{} NOT IN {}", x, y)
	} else if isQueryA && !isRowValueB {
		return Expr("({}) NOT IN ({})", x, y)
	} else {
		return Expr("({}) NOT IN {}", x, y)
	}
}

// cmp returns an 'x <operator> y' Predicate.
func cmp(operator string, x, y any) Expression {
	_, isQueryA := x.(Query)
	_, isQueryB := y.(Query)
	if !isQueryA && !isQueryB {
		return Expr("{} "+operator+" {}", x, y)
	} else if !isQueryA && isQueryB {
		return Expr("{} "+operator+" ({})", x, y)
	} else if isQueryA && !isQueryB {
		return Expr("({}) "+operator+" {}", x, y)
	} else {
		return Expr("({}) "+operator+" ({})", x, y)
	}
}

// appendPolicy will append a policy from a Table (if it implements
// PolicyTable) to a slice of policies. The resultant slice is returned.
func appendPolicy(ctx context.Context, dialect string, policies []Predicate, table Table) ([]Predicate, error) {
	policyTable, ok := table.(PolicyTable)
	if !ok {
		return policies, nil
	}
	policy, err := policyTable.Policy(ctx, dialect)
	if err != nil {
		return nil, err
	}
	if policy != nil {
		policies = append(policies, policy)
	}
	return policies, nil
}

// appendPredicates will append a slices of predicates into a predicate.
func appendPredicates(predicate Predicate, predicates []Predicate) VariadicPredicate {
	if predicate == nil {
		return And(predicates...)
	}
	if p1, ok := predicate.(VariadicPredicate); ok && !p1.IsDisjunction {
		p1.Predicates = append(p1.Predicates, predicates...)
		return p1
	}
	p2 := VariadicPredicate{Predicates: make([]Predicate, 1+len(predicates))}
	p2.Predicates[0] = predicate
	copy(p2.Predicates[1:], predicates)
	return p2
}

func writeTop(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int, topLimit, topPercentLimit any, withTies bool) error {
	var err error
	if topLimit != nil {
		buf.WriteString("TOP (")
		err = WriteValue(ctx, dialect, buf, args, params, topLimit)
		if err != nil {
			return fmt.Errorf("TOP: %w", err)
		}
		buf.WriteString(") ")
	} else if topPercentLimit != nil {
		buf.WriteString("TOP (")
		err = WriteValue(ctx, dialect, buf, args, params, topPercentLimit)
		if err != nil {
			return fmt.Errorf("TOP PERCENT: %w", err)
		}
		buf.WriteString(") PERCENT ")
	}
	if (topLimit != nil || topPercentLimit != nil) && withTies {
		buf.WriteString("WITH TIES ")
	}
	return nil
}


================================================
FILE: builtins_test.go
================================================
package sq

import (
	"bytes"
	"context"
	"database/sql"
	"errors"
	"testing"

	"github.com/bokwoon95/sq/internal/testutil"
)

func TestExpression(t *testing.T) {
	t.Run("schema, name and alias", func(t *testing.T) {
		t.Parallel()
		expr := Expr("COUNT(*)").As("total")
		if diff := testutil.Diff(expr.GetAlias(), "total"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})

	tests := []TestTable{{
		description: "basic",
		dialect:     DialectSQLServer,
		item:        Expr("CONCAT(CONCAT(name, {}), {})", "abc", sql.Named("xyz", "def")),
		wantQuery:   "CONCAT(CONCAT(name, @p1), @xyz)",
		wantArgs:    []any{"abc", sql.Named("xyz", "def")},
		wantParams:  map[string][]int{"xyz": {1}},
	}, {
		description: "In", item: Expr("age").In([]int{18, 21, 32}),
		wantQuery: "age IN (?, ?, ?)", wantArgs: []any{18, 21, 32},
	}, {
		description: "NotIn", item: Expr("age").NotIn([]int{18, 21, 32}),
		wantQuery: "age NOT IN (?, ?, ?)", wantArgs: []any{18, 21, 32},
	}, {
		description: "Eq", item: Expr("age").Eq(34),
		wantQuery: "age = ?", wantArgs: []any{34},
	}, {
		description: "Ne", item: Expr("age").Ne(34),
		wantQuery: "age <> ?", wantArgs: []any{34},
	}, {
		description: "Lt", item: Expr("age").Lt(34),
		wantQuery: "age < ?", wantArgs: []any{34},
	}, {
		description: "Le", item: Expr("age").Le(34),
		wantQuery: "age <= ?", wantArgs: []any{34},
	}, {
		description: "Gt", item: Expr("age").Gt(34),
		wantQuery: "age > ?", wantArgs: []any{34},
	}, {
		description: "Ge", item: Expr("age").Ge(34),
		wantQuery: "age >= ?", wantArgs: []any{34},
	}, {
		description: "Exists", item: Exists(Queryf("SELECT 1 FROM tbl WHERE 1 = 1")),
		wantQuery: "EXISTS (SELECT 1 FROM tbl WHERE 1 = 1)",
	}, {
		description: "NotExists", item: NotExists(Queryf("SELECT 1 FROM tbl WHERE 1 = 1")),
		wantQuery: "NOT EXISTS (SELECT 1 FROM tbl WHERE 1 = 1)",
	}, {
		description: "Count", item: Count(Expr("name")), wantQuery: "COUNT(name)",
	}, {
		description: "CountStar", item: CountStar(), wantQuery: "COUNT(*)",
	}, {
		description: "Sum", item: Sum(Expr("score")), wantQuery: "SUM(score)",
	}, {
		description: "Avg", item: Avg(Expr("score")), wantQuery: "AVG(score)",
	}, {
		description: "Min", item: Min(Expr("score")), wantQuery: "MIN(score)",
	}, {
		description: "Max", item: Max(Expr("score")), wantQuery: "MAX(score)",
	}}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			tt.assert(t)
		})
	}

	t.Run("FaultySQL", func(t *testing.T) {
		t.Parallel()
		TestTable{item: Expr("SELECT {}", FaultySQL{})}.assertNotOK(t)
	})
}

func TestVariadicPredicate(t *testing.T) {
	t.Run("name and alias", func(t *testing.T) {
		t.Parallel()
		p := And(Expr("True"), Expr("FALSE")).As("is_false")
		if diff := testutil.Diff(p.GetAlias(), "is_false"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})

	t.Run("empty", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = VariadicPredicate{}
		tt.assertNotOK(t)
	})

	t.Run("nil predicate", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = And(nil)
		tt.assertNotOK(t)
	})

	t.Run("1 predicate", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = And(cmp("=", Expr("score"), 21))
		tt.wantQuery = "score = ?"
		tt.wantArgs = []any{21}
		tt.assert(t)
	})

	t.Run("2 predicate", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = And(cmp("=", Expr("score"), 21), cmp("=", Expr("name"), "bob"))
		tt.wantQuery = "(score = ? AND name = ?)"
		tt.wantArgs = []any{21, "bob"}
		tt.assert(t)
	})

	t.Run("multiple nested VariadicPredicate collapses into one", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = And(And(And(And(cmp("=", Expr("score"), 21)))))
		tt.wantQuery = "score = ?"
		tt.wantArgs = []any{21}
		tt.assert(t)
	})

	t.Run("multiple predicates", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		user_id, name, age := Expr("user_id"), Expr("name"), Expr("age")
		tt.item = Or(
			Expr("{} IS NULL", name),
			cmp("=", age, age),
			And(cmp("=", age, age)),
			And(
				cmp("=", user_id, 1),
				cmp("<>", user_id, 2),
				cmp("<", user_id, 3),
				cmp("<=", user_id, 4),
				cmp(">", user_id, 5),
				cmp(">=", user_id, 6),
			),
		)
		tt.wantQuery = "(name IS NULL" +
			" OR age = age" +
			" OR age = age" +
			" OR (" +
			"user_id = ?" +
			" AND user_id <> ?" +
			" AND user_id < ?" +
			" AND user_id <= ?" +
			" AND user_id > ?" +
			" AND user_id >= ?" +
			"))"
		tt.wantArgs = []any{1, 2, 3, 4, 5, 6}
		tt.assert(t)
	})

	t.Run("multiple predicates with nil", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = Or(
			Expr("1 = 1"),
			And(Expr("TRUE"), Predicate(nil)),
		)
		tt.assertNotOK(t)
	})

	t.Run("VariadicPredicate alias", func(t *testing.T) {
		t.Parallel()
		p1 := And(Expr("TRUE")).As("abc")
		if diff := testutil.Diff(p1.GetAlias(), "abc"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		p2 := p1.As("def")
		if diff := testutil.Diff(p1.GetAlias(), "abc"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		if diff := testutil.Diff(p2.GetAlias(), "def"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})

	t.Run("VariadicPredicate FaultySQL", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		// AND, 1 predicate
		tt.item = And(FaultySQL{})
		tt.assertErr(t, ErrFaultySQL)
		// AND, multiple predicates
		tt.item = And(Expr("FALSE"), FaultySQL{})
		tt.assertErr(t, ErrFaultySQL)
		// nested AND
		tt.item = And(And(FaultySQL{}))
		tt.assertErr(t, ErrFaultySQL)
	})
}

func TestQueryf(t *testing.T) {
	t.Run("basic", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = Queryf("SELECT {field} FROM {table} WHERE {predicate}",
			sql.Named("field", Expr("name")),
			sql.Named("table", Expr("users")),
			sql.Named("predicate", Expr("user_id = {}", 5)),
		)
		tt.wantQuery = "SELECT name FROM users WHERE user_id = ?"
		tt.wantArgs = []any{5}
		tt.assert(t)
	})

	t.Run("select star", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		q := Queryf("SELECT {*} FROM {table} WHERE {predicate}",
			sql.Named("table", Expr("users")),
			sql.Named("predicate", Expr("user_id = {}", 5)),
		)
		if diff := testutil.Diff(q.GetDialect(), ""); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		q2, ok := q.SetFetchableFields([]Field{Expr("name"), Expr("age")})
		if !ok {
			t.Fatal(testutil.Callers(), "not ok")
		}
		tt.item = q2
		tt.wantQuery = "SELECT name, age FROM users WHERE user_id = ?"
		tt.wantArgs = []any{5}
		tt.assert(t)
	})

	t.Run("escape curly brace", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		q := Queryf(`WITH cte AS (SELECT '{{*}' AS name) SELECT {*} FROM cte`)
		q2, ok := q.SetFetchableFields([]Field{Expr("name")})
		if !ok {
			t.Fatal(testutil.Callers(), "not ok")
		}
		tt.item = q2
		tt.wantQuery = "WITH cte AS (SELECT '{*}' AS name) SELECT name FROM cte"
		tt.assert(t)
	})

	t.Run("mixed", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		q := Queryf(`{1} {3} {name} {} SELECT {*} FROM {1} {} {name} {}`, 5, sql.Named("name", "bob"), 10)
		q2, ok := q.SetFetchableFields([]Field{Expr("alpha"), Expr("SUBSTR({}, {})", "apple", 77), Expr("beta")})
		if !ok {
			t.Fatal(testutil.Callers(), "not ok")
		}
		tt.dialect = DialectPostgres
		tt.item = q2
		tt.wantQuery = "$1 $2 $3 $4 SELECT alpha, SUBSTR($5, $6), beta FROM $1 $3 $3 $7"
		tt.wantArgs = []any{5, 10, "bob", 5, "apple", 77, 10}
		tt.wantParams = map[string][]int{"name": {2}}
		tt.assert(t)
	})

	t.Run("append", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		q := Queryf("SELECT {*} FROM tbl WHERE 1 = 1")
		q = q.Append("AND name = {}", "bob")
		q = q.Append("AND email = {email}", sql.Named("email", "bob@email.com"))
		q = q.Append("AND age = {age}", sql.Named("age", 27))
		q2, ok := q.SetFetchableFields([]Field{Expr("name"), Expr("email")})
		if !ok {
			t.Fatal(testutil.Callers(), "not ok")
		}
		tt.item = q2
		tt.wantQuery = "SELECT name, email FROM tbl WHERE 1 = 1 AND name = ? AND email = ? AND age = ?"
		tt.wantArgs = []any{"bob", "bob@email.com", 27}
		tt.wantParams = map[string][]int{"email": {1}, "age": {2}}
		tt.assert(t)
	})
}

func TestAssign(t *testing.T) {
	t.Run("AssignValue nil field", func(t *testing.T) {
		t.Parallel()
		_, _, err := ToSQL("", Set(nil, 1), nil)
		if err == nil {
			t.Error(testutil.Callers(), "expected error but got nil")
		}
	})

	t.Run("AssignValue", func(t *testing.T) {
		t.Parallel()
		TestTable{
			item:      Set(tmpfield("tbl.field"), 1),
			wantQuery: "field = ?", wantArgs: []any{1},
		}.assert(t)
	})

	t.Run("mysql AssignValue", func(t *testing.T) {
		t.Parallel()
		TestTable{
			dialect:   DialectMySQL,
			item:      Set(tmpfield("tbl.field"), 1),
			wantQuery: "tbl.field = ?", wantArgs: []any{1},
		}.assert(t)
	})

	t.Run("AssignValue err", func(t *testing.T) {
		t.Parallel()
		TestTable{
			item: Set(tmpfield("tbl.field"), FaultySQL{}),
		}.assertErr(t, ErrFaultySQL)
	})

	t.Run("Assignf nil field", func(t *testing.T) {
		t.Parallel()
		_, _, err := ToSQL("", Setf(nil, ""), nil)
		if err == nil {
			t.Error(testutil.Callers(), "expected error but got nil")
		}
	})

	t.Run("Assignf", func(t *testing.T) {
		t.Parallel()
		TestTable{
			item:      Setf(tmpfield("tbl.field"), "EXCLUDED.field"),
			wantQuery: "field = EXCLUDED.field",
		}.assert(t)
	})

	t.Run("Assignf err", func(t *testing.T) {
		t.Parallel()
		TestTable{
			item: Setf(tmpfield("tbl.field"), "EXCLUDED.{}", FaultySQL{}),
		}.assertErr(t, ErrFaultySQL)
	})
}

func TestRowValuesFieldsAssignments(t *testing.T) {
	tests := []TestTable{{
		description: "RowValue", item: RowValue{1, 2, 3},
		wantQuery: "(?, ?, ?)", wantArgs: []any{1, 2, 3},
	}, {
		description: "RowValue with query",
		item:        RowValue{1, 2, Queryf("SELECT {}", 3)},
		wantQuery:   "(?, ?, (SELECT ?))",
		wantArgs:    []any{1, 2, 3},
	}, {
		description: "RowValue In",
		item:        RowValue{1, 2, 3}.In(RowValues{{4, 5, 6}, {7, 8, 9}}),
		wantQuery:   "(?, ?, ?) IN ((?, ?, ?), (?, ?, ?))",
		wantArgs:    []any{1, 2, 3, 4, 5, 6, 7, 8, 9},
	}, {
		description: "RowValue NotIn",
		item:        RowValue{1, 2, 3}.NotIn(RowValues{{4, 5, 6}, {7, 8, 9}}),
		wantQuery:   "(?, ?, ?) NOT IN ((?, ?, ?), (?, ?, ?))",
		wantArgs:    []any{1, 2, 3, 4, 5, 6, 7, 8, 9},
	}, {
		description: "RowValue Eq",
		item:        RowValue{1, 2, 3}.Eq(RowValue{4, 5, 6}),
		wantQuery:   "(?, ?, ?) = (?, ?, ?)",
		wantArgs:    []any{1, 2, 3, 4, 5, 6},
	}, {
		description: "Fields",
		item:        Fields{Expr("tbl.f1"), Expr("tbl.f2"), Expr("tbl.f3")},
		wantQuery:   "tbl.f1, tbl.f2, tbl.f3",
	}, {
		description: "Assignments",
		item:        Assignments{Set(Expr("f1"), 1), Set(Expr("f2"), 2), Set(Expr("f3"), 3)},
		wantQuery:   "f1 = ?, f2 = ?, f3 = ?", wantArgs: []any{1, 2, 3},
	}}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			tt.assert(t)
		})
	}

	t.Run("nil fields/assignments", func(t *testing.T) {
		t.Parallel()
		// Fields
		TestTable{item: Fields{Expr("f1"), Expr("f2"), nil}}.assertNotOK(t)
		// Assignments
		TestTable{item: Assignments{Set(Expr("f1"), 1), Set(Expr("f2"), 2), nil}}.assertNotOK(t)
	})

	errTests := []TestTable{{
		description: "RowValue err", item: RowValue{1, 2, FaultySQL{}},
	}, {
		description: "RowValues err", item: RowValues{{1, 2, FaultySQL{}}},
	}, {
		description: "Fields err", item: Fields{Expr("f1"), Expr("f2"), FaultySQL{}},
	}, {
		description: "Assignments err",
		item:        Assignments{Set(Expr("f1"), 1), Set(Expr("f2"), 2), FaultySQL{}},
	}}

	for _, tt := range errTests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			tt.assertErr(t, ErrFaultySQL)
		})
	}
}

func TestToSQL(t *testing.T) {
	t.Run("basic", func(t *testing.T) {
		gotQuery, _, err := ToSQL("", Queryf("SELECT {fields} FROM {table}",
			sql.Named("fields", Fields{Expr("f1"), Expr("f2"), Expr("f3")}),
			sql.Named("table", Expr("tbl")),
		), nil)
		if err != nil {
			t.Error(testutil.Callers(), err)
		}
		wantQuery := "SELECT f1, f2, f3 FROM tbl"
		if diff := testutil.Diff(gotQuery, wantQuery); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})

	t.Run("nil SQLWriter", func(t *testing.T) {
		_, _, err := ToSQL("", nil, nil)
		if err == nil {
			t.Error(testutil.Callers(), "expected error but got nil")
		}
	})

	t.Run("err", func(t *testing.T) {
		_, _, err := ToSQL("", Queryf("SELECT {}", FaultySQL{}), nil)
		if !errors.Is(err, ErrFaultySQL) {
			t.Errorf(testutil.Callers()+"expected '%v' but got '%v'", ErrFaultySQL, err)
		}
	})
}

func Test_in_cmp(t *testing.T) {
	tests := []TestTable{{
		description: "!Query IN !RowValue",
		item:        In(Expr("{}", "tom"), Queryf("SELECT name FROM users WHERE name LIKE {}", "t%")),
		wantQuery:   "? IN (SELECT name FROM users WHERE name LIKE ?)", wantArgs: []any{"tom", "t%"},
	}, {
		description: "!Query IN RowValue", item: In(Expr("name"), RowValue{"tom", "dick", "harry"}),
		wantQuery: "name IN (?, ?, ?)", wantArgs: []any{"tom", "dick", "harry"},
	}, {
		description: "Query IN !RowValue", item: In(Queryf("SELECT {}", "tom"), []string{"tom", "dick", "harry"}),
		wantQuery: "(SELECT ?) IN (?, ?, ?)", wantArgs: []any{"tom", "tom", "dick", "harry"},
	}, {
		description: "Query IN RowValue", item: In(Queryf("SELECT {}", "tom"), RowValue{"tom", "dick", "harry"}),
		wantQuery: "(SELECT ?) IN (?, ?, ?)", wantArgs: []any{"tom", "tom", "dick", "harry"},
	}, {
		description: "!Query NOT IN !RowValue",
		item:        NotIn(Expr("{}", "tom"), Queryf("SELECT name FROM users WHERE name LIKE {}", "t%")),
		wantQuery:   "? NOT IN (SELECT name FROM users WHERE name LIKE ?)", wantArgs: []any{"tom", "t%"},
	}, {
		description: "!Query NOT IN RowValue", item: NotIn(Expr("name"), RowValue{"tom", "dick", "harry"}),
		wantQuery: "name NOT IN (?, ?, ?)", wantArgs: []any{"tom", "dick", "harry"},
	}, {
		description: "Query NOT IN !RowValue", item: NotIn(Queryf("SELECT {}", "tom"), []string{"tom", "dick", "harry"}),
		wantQuery: "(SELECT ?) NOT IN (?, ?, ?)", wantArgs: []any{"tom", "tom", "dick", "harry"},
	}, {
		description: "Query NOT IN RowValue", item: NotIn(Queryf("SELECT {}", "tom"), RowValue{"tom", "dick", "harry"}),
		wantQuery: "(SELECT ?) NOT IN (?, ?, ?)", wantArgs: []any{"tom", "tom", "dick", "harry"},
	}, {
		description: "!Query = !Query", item: cmp("=", 1, 1),
		wantQuery: "? = ?", wantArgs: []any{1, 1},
	}, {
		description: "!Query = Query", item: cmp("=", Expr("score"), Queryf("SELECT score FROM users WHERE id = {}", 5)),
		wantQuery: "score = (SELECT score FROM users WHERE id = ?)", wantArgs: []any{5},
	}, {
		description: "Query = !Query", item: cmp("=", Queryf("SELECT score FROM users WHERE id = {}", 5), Expr("{}", 7)),
		wantQuery: "(SELECT score FROM users WHERE id = ?) = ?", wantArgs: []any{5, 7},
	}, {
		description: "Query = Query", item: cmp("=", Queryf("SELECT 1"), Queryf("SELECT 2")),
		wantQuery: "(SELECT 1) = (SELECT 2)",
	}}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			tt.assert(t)
		})
	}
}

type policyTableStub struct {
	policy Predicate
	err    error
}

var _ PolicyTable = (*policyTableStub)(nil)

func (tbl policyTableStub) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	buf.WriteString("policy_table_stub")
	return nil
}

func (tbl policyTableStub) GetAlias() string { return "" }

func (tbl policyTableStub) Policy(ctx context.Context, dialect string) (Predicate, error) {
	return tbl.policy, tbl.err
}

func (tbl policyTableStub) IsTable() {}

func Test_appendPolicy(t *testing.T) {
	type TT struct {
		description  string
		table        Table
		wantPolicies []Predicate
		wantErr      error
	}

	tests := []TT{{
		description: "table doesn't implement PolicyTable",
		table:       Expr("tbl"),
	}, {
		description: "PolicyTable returns err",
		table:       policyTableStub{err: ErrFaultySQL},
		wantErr:     ErrFaultySQL,
	}, {
		description:  "PolicyTable returns policy",
		table:        policyTableStub{policy: Expr("TRUE")},
		wantPolicies: []Predicate{Expr("TRUE")},
	}, {
		description: "PolicyTable returns nil policy",
		table:       policyTableStub{},
	}}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			policies, err := appendPolicy(context.Background(), "", nil, tt.table)
			if !errors.Is(err, tt.wantErr) {
				t.Errorf(testutil.Callers()+"expected error '%v' but got '%v'", tt.wantErr, err)
			}
			if diff := testutil.Diff(policies, tt.wantPolicies); diff != "" {
				t.Error(testutil.Callers(), diff)
			}
		})
	}
}

func Test_appendPredicates(t *testing.T) {
	type TT struct {
		description   string
		predicate     Predicate
		predicates    []Predicate
		wantPredicate VariadicPredicate
	}

	p1, p2, p3 := Expr("p1"), Expr("p2"), Expr("p3")
	tests := []TT{{
		description: "nil predicate",
		predicate:   nil, predicates: []Predicate{p2, p3},
		wantPredicate: And(p2, p3),
	}, {
		description: "AND predicate",
		predicate:   And(p1), predicates: []Predicate{p2, p3},
		wantPredicate: And(p1, p2, p3),
	}, {
		description: "OR predicate",
		predicate:   Or(p1), predicates: []Predicate{p2, p3},
		wantPredicate: And(Or(p1), p2, p3),
	}, {
		description: "non-VariadicPredicate predicate",
		predicate:   p1, predicates: []Predicate{p2, p3},
		wantPredicate: And(p1, p2, p3),
	}}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			gotPredicate := appendPredicates(tt.predicate, tt.predicates)
			if diff := testutil.Diff(gotPredicate, tt.wantPredicate); diff != "" {
				t.Error(testutil.Callers(), diff)
			}
		})
	}
}

func Test_writeTop(t *testing.T) {
	type TT struct {
		description     string
		topLimit        any
		topPercentLimit any
		withTies        bool
		wantQuery       string
		wantArgs        []any
		wantParams      map[string][]int
	}

	t.Run("err", func(t *testing.T) {
		t.Parallel()
		ctx := context.Background()
		dialect := DialectSQLServer
		buf := &bytes.Buffer{}
		args := &[]any{}
		params := make(map[string][]int)
		// topLimit
		err := writeTop(ctx, dialect, buf, args, params, FaultySQL{}, nil, false)
		if !errors.Is(err, ErrFaultySQL) {
			t.Errorf(testutil.Callers()+"expected error '%v' but got '%v'", ErrFaultySQL, err)
		}
		// topPercentLimit
		err = writeTop(ctx, dialect, buf, args, params, nil, FaultySQL{}, false)
		if !errors.Is(err, ErrFaultySQL) {
			t.Errorf(testutil.Callers()+"expected error '%v' but got '%v'", ErrFaultySQL, err)
		}
	})

	tests := []TT{{
		description: "empty", topLimit: nil, topPercentLimit: nil, withTies: true,
		wantQuery: "", wantArgs: nil, wantParams: nil,
	}, {
		description: "TOP n", topLimit: 5,
		wantQuery: "TOP (@p1) ", wantArgs: []any{5},
	}, {
		description: "TOP n PERCENT", topPercentLimit: 10,
		wantQuery: "TOP (@p1) PERCENT ", wantArgs: []any{10},
	}, {
		description: "TOP n WITH TIES", topLimit: 5, withTies: true,
		wantQuery: "TOP (@p1) WITH TIES ", wantArgs: []any{5},
	}, {
		description: "TOP expr", topLimit: Expr("5"),
		wantQuery: "TOP (5) ",
	}, {
		description: "TOP param", topLimit: IntParam("limit", 5),
		wantQuery: "TOP (@limit) ", wantArgs: []any{sql.Named("limit", 5)},
		wantParams: map[string][]int{"limit": {0}},
	}}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			ctx := context.Background()
			dialect := DialectSQLServer
			buf := &bytes.Buffer{}
			args := &[]any{}
			params := make(map[string][]int)
			err := writeTop(ctx, dialect, buf, args, params, tt.topLimit, tt.topPercentLimit, tt.withTies)
			if err != nil {
				t.Error(testutil.Callers(), err)
			}
			if diff := testutil.Diff(buf.String(), tt.wantQuery); diff != "" {
				t.Error(testutil.Callers(), diff)
			}
			if diff := testutil.Diff(*args, tt.wantArgs); diff != "" {
				t.Error(testutil.Callers(), diff)
			}
			if len(params) > 0 || len(tt.wantParams) > 0 {
				if diff := testutil.Diff(params, tt.wantParams); diff != "" {
					t.Error(testutil.Callers(), diff)
				}
			}
		})
	}
}

// TODO: remove all uses of TestTable, manually write each assert. Fewer levels
// of BS indirection when you need to debug something.
type TestTable struct {
	description string
	ctx         context.Context
	dialect     string
	item        any
	wantQuery   string
	wantArgs    []any
	wantParams  map[string][]int
}

func (tt TestTable) assert(t *testing.T) {
	if tt.ctx == nil {
		tt.ctx = context.Background()
	}
	if tt.dialect == "" {
		if query, ok := tt.item.(Query); ok {
			tt.dialect = query.GetDialect()
		}
	}
	buf := &bytes.Buffer{}
	args := &[]any{}
	params := make(map[string][]int)
	err := WriteValue(tt.ctx, tt.dialect, buf, args, params, tt.item)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(buf.String(), tt.wantQuery); diff != "" {
		t.Error(testutil.Callers(), diff)
	}
	if len(*args) > 0 || len(tt.wantArgs) > 0 {
		if diff := testutil.Diff(*args, tt.wantArgs); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	}
	if len(params) > 0 || len(tt.wantParams) > 0 {
		if diff := testutil.Diff(params, tt.wantParams); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	}
}

func (tt TestTable) assertErr(t *testing.T, wantErr error) {
	if tt.ctx == nil {
		tt.ctx = context.Background()
	}
	if tt.dialect == "" {
		if query, ok := tt.item.(Query); ok {
			tt.dialect = query.GetDialect()
		}
	}
	buf := &bytes.Buffer{}
	args := &[]any{}
	params := make(map[string][]int)
	gotErr := WriteValue(tt.ctx, tt.dialect, buf, args, params, tt.item)
	if !errors.Is(gotErr, wantErr) {
		t.Fatalf(testutil.Callers()+"expected error '%v' but got '%v'", wantErr, gotErr)
	}
}

func (tt TestTable) assertNotOK(t *testing.T) {
	if tt.ctx == nil {
		tt.ctx = context.Background()
	}
	if tt.dialect == "" {
		if query, ok := tt.item.(Query); ok {
			tt.dialect = query.GetDialect()
		}
	}
	buf := &bytes.Buffer{}
	args := &[]any{}
	params := make(map[string][]int)
	gotErr := WriteValue(tt.ctx, tt.dialect, buf, args, params, tt.item)
	if gotErr == nil {
		t.Fatal(testutil.Callers(), "expected error but got nil")
	}
}


================================================
FILE: colors.go
================================================
//go:build windows

package sq

import (
	"os"
	"syscall"
)

func init() {
	// https://stackoverflow.com/a/69542231
	const ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4
	var stderrMode uint32
	stderr := syscall.Handle(os.Stderr.Fd())
	syscall.GetConsoleMode(stderr, &stderrMode)
	syscall.MustLoadDLL("kernel32").MustFindProc("SetConsoleMode").Call(uintptr(stderr), uintptr(stderrMode|ENABLE_VIRTUAL_TERMINAL_PROCESSING))
	var stdoutMode uint32
	stdout := syscall.Handle(os.Stdout.Fd())
	syscall.GetConsoleMode(stdout, &stdoutMode)
	syscall.MustLoadDLL("kernel32").MustFindProc("SetConsoleMode").Call(uintptr(stdout), uintptr(stdoutMode|ENABLE_VIRTUAL_TERMINAL_PROCESSING))
}


================================================
FILE: cte.go
================================================
package sq

import (
	"bytes"
	"context"
	"database/sql"
	"fmt"
)

// CTE represents an SQL common table expression (CTE).
type CTE struct {
	query        Query
	columns      []string
	recursive    bool
	materialized sql.NullBool
	name         string
	alias        string
}

var _ Table = (*CTE)(nil)

// NewCTE creates a new CTE.
func NewCTE(name string, columns []string, query Query) CTE {
	return CTE{name: name, columns: columns, query: query}
}

// NewRecursiveCTE creates a new recursive CTE.
func NewRecursiveCTE(name string, columns []string, query Query) CTE {
	return CTE{name: name, columns: columns, query: query, recursive: true}
}

// WriteSQL implements the SQLWriter interface.
func (cte CTE) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	buf.WriteString(QuoteIdentifier(dialect, cte.name))
	return nil
}

// As returns a new CTE with the given alias.
func (cte CTE) As(alias string) CTE {
	cte.alias = alias
	return cte
}

// Materialized returns a new CTE marked as MATERIALIZED. This only works on
// postgres.
func (cte CTE) Materialized() CTE {
	cte.materialized.Valid = true
	cte.materialized.Bool = true
	return cte
}

// Materialized returns a new CTE marked as NOT MATERIALIZED. This only works
// on postgres.
func (cte CTE) NotMaterialized() CTE {
	cte.materialized.Valid = true
	cte.materialized.Bool = false
	return cte
}

// Field returns a Field from the CTE.
func (cte CTE) Field(name string) AnyField {
	return NewAnyField(name, NewTableStruct("", cte.name, cte.alias))
}

// GetAlias returns the alias of the CTE.
func (cte CTE) GetAlias() string { return cte.alias }

// AssertTable implements the Table interface.
func (cte CTE) IsTable() {}

func writeCTEs(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int, ctes []CTE) error {
	var hasRecursiveCTE bool
	for _, cte := range ctes {
		if cte.recursive {
			hasRecursiveCTE = true
			break
		}
	}
	if hasRecursiveCTE {
		buf.WriteString("WITH RECURSIVE ")
	} else {
		buf.WriteString("WITH ")
	}
	for i, cte := range ctes {
		if i > 0 {
			buf.WriteString(", ")
		}
		if cte.name == "" {
			return fmt.Errorf("CTE #%d has no name", i+1)
		}
		buf.WriteString(QuoteIdentifier(dialect, cte.name))
		if len(cte.columns) > 0 {
			buf.WriteString(" (")
			for j, column := range cte.columns {
				if j > 0 {
					buf.WriteString(", ")
				}
				buf.WriteString(QuoteIdentifier(dialect, column))
			}
			buf.WriteString(")")
		}
		buf.WriteString(" AS ")
		if dialect == DialectPostgres && cte.materialized.Valid {
			if cte.materialized.Bool {
				buf.WriteString("MATERIALIZED ")
			} else {
				buf.WriteString("NOT MATERIALIZED ")
			}
		}
		buf.WriteString("(")
		switch query := cte.query.(type) {
		case nil:
			return fmt.Errorf("CTE #%d query is nil", i+1)
		case VariadicQuery:
			query.Toplevel = true
			err := query.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return fmt.Errorf("CTE #%d failed to build query: %w", i+1, err)
			}
		default:
			err := query.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return fmt.Errorf("CTE #%d failed to build query: %w", i+1, err)
			}
		}
		buf.WriteString(")")
	}
	buf.WriteString(" ")
	return nil
}

// VariadicQueryOperator represents a variadic query operator.
type VariadicQueryOperator string

// VariadicQuery operators.
const (
	QueryUnion        VariadicQueryOperator = "UNION"
	QueryUnionAll     VariadicQueryOperator = "UNION ALL"
	QueryIntersect    VariadicQueryOperator = "INTERSECT"
	QueryIntersectAll VariadicQueryOperator = "INTERSECT ALL"
	QueryExcept       VariadicQueryOperator = "EXCEPT"
	QueryExceptAll    VariadicQueryOperator = "EXCEPT ALL"
)

// VariadicQuery represents the 'x UNION y UNION z...' etc SQL constructs.
type VariadicQuery struct {
	Toplevel bool
	Operator VariadicQueryOperator
	Queries  []Query
}

var _ Query = (*VariadicQuery)(nil)

// Union joins the queries together with the UNION operator.
func Union(queries ...Query) VariadicQuery {
	return VariadicQuery{Operator: QueryUnion, Queries: queries}
}

// UnionAll joins the queries together with the UNION ALL operator.
func UnionAll(queries ...Query) VariadicQuery {
	return VariadicQuery{Operator: QueryUnionAll, Queries: queries}
}

// Intersect joins the queries together with the INTERSECT operator.
func Intersect(queries ...Query) VariadicQuery {
	return VariadicQuery{Operator: QueryIntersect, Queries: queries}
}

// IntersectAll joins the queries together with the INTERSECT ALL operator.
func IntersectAll(queries ...Query) VariadicQuery {
	return VariadicQuery{Operator: QueryIntersectAll, Queries: queries}
}

// Except joins the queries together with the EXCEPT operator.
func Except(queries ...Query) VariadicQuery {
	return VariadicQuery{Operator: QueryExcept, Queries: queries}
}

// ExceptAll joins the queries together with the EXCEPT ALL operator.
func ExceptAll(queries ...Query) VariadicQuery {
	return VariadicQuery{Operator: QueryExceptAll, Queries: queries}
}

// WriteSQL implements the SQLWriter interface.
func (q VariadicQuery) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	var err error
	if q.Operator == "" {
		q.Operator = QueryUnion
	}
	if len(q.Queries) == 0 {
		return fmt.Errorf("VariadicQuery empty")
	}

	if len(q.Queries) == 1 {
		switch q1 := q.Queries[0].(type) {
		case nil:
			return fmt.Errorf("query #1 is nil")
		case VariadicQuery:
			q1.Toplevel = q.Toplevel
			err = q1.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return err
			}
		default:
			err = q.Queries[0].WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return err
			}
		}
		return nil
	}

	if !q.Toplevel {
		buf.WriteString("(")
	}
	for i, query := range q.Queries {
		if i > 0 {
			buf.WriteString(" " + string(q.Operator) + " ")
		}
		if query == nil {
			return fmt.Errorf("query #%d is nil", i+1)
		}
		err = query.WriteSQL(ctx, dialect, buf, args, params)
		if err != nil {
			return fmt.Errorf("query #%d: %w", i+1, err)
		}
	}
	if !q.Toplevel {
		buf.WriteString(")")
	}
	return nil
}

// SetFetchableFields implements the Query interface.
func (q VariadicQuery) SetFetchableFields(fields []Field) (query Query, ok bool) {
	return q, false
}

// GetFetchableFields implements the Query interface.
func (q VariadicQuery) GetFetchableFields() []Field {
	return nil
}

// GetDialect returns the SQL dialect of the VariadicQuery.
func (q VariadicQuery) GetDialect() string {
	if len(q.Queries) == 0 {
		return ""
	}
	q1 := q.Queries[0]
	if q1 == nil {
		return ""
	}
	return q1.GetDialect()
}


================================================
FILE: cte_test.go
================================================
package sq

import (
	"bytes"
	"context"
	"database/sql"
	"errors"
	"testing"

	"github.com/bokwoon95/sq/internal/testutil"
)

func TestCTE(t *testing.T) {
	t.Run("basic", func(t *testing.T) {
		cte := NewCTE("cte", []string{"n"}, Queryf("SELECT 1")).Materialized().NotMaterialized().As("c")
		TestTable{item: cte, wantQuery: "cte"}.assert(t)
		field := NewAnyField("ff", TableStruct{name: "cte", alias: "c"})
		if diff := testutil.Diff(cte.Field("ff"), field); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		if diff := testutil.Diff(cte.materialized, sql.NullBool{Valid: true, Bool: false}); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		if diff := testutil.Diff(cte.GetAlias(), "c"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})
}

func TestCTEs(t *testing.T) {
	type TT struct {
		description string
		dialect     string
		ctes        []CTE
		wantQuery   string
		wantArgs    []any
		wantParams  map[string][]int
	}

	tests := []TT{{
		description: "basic",
		ctes:        []CTE{NewCTE("cte", nil, Queryf("SELECT 1"))},
		wantQuery:   "WITH cte AS (SELECT 1) ",
	}, {
		description: "recursive",
		ctes: []CTE{
			NewCTE("cte", nil, Queryf("SELECT 1")),
			NewRecursiveCTE("nums", []string{"n"}, Union(
				Queryf("SELECT 1"),
				Queryf("SELECT n+1 FROM nums WHERE n < 10"),
			)),
		},
		wantQuery: "WITH RECURSIVE cte AS (SELECT 1)" +
			", nums (n) AS (SELECT 1 UNION SELECT n+1 FROM nums WHERE n < 10) ",
	}, {
		description: "mysql materialized",
		dialect:     DialectMySQL,
		ctes:        []CTE{NewCTE("cte", nil, Queryf("SELECT 1")).Materialized()},
		wantQuery:   "WITH cte AS (SELECT 1) ",
	}, {
		description: "postgres materialized",
		dialect:     DialectPostgres,
		ctes:        []CTE{NewCTE("cte", nil, Queryf("SELECT 1")).Materialized()},
		wantQuery:   "WITH cte AS MATERIALIZED (SELECT 1) ",
	}, {
		description: "postgres not materialized",
		dialect:     DialectPostgres,
		ctes:        []CTE{NewCTE("cte", nil, Queryf("SELECT 1")).NotMaterialized()},
		wantQuery:   "WITH cte AS NOT MATERIALIZED (SELECT 1) ",
	}}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			buf, args, params := bufpool.Get().(*bytes.Buffer), &[]any{}, make(map[string][]int)
			buf.Reset()
			defer bufpool.Put(buf)
			err := writeCTEs(context.Background(), tt.dialect, buf, args, params, tt.ctes)
			if err != nil {
				t.Fatal(testutil.Callers(), err)
			}
			if diff := testutil.Diff(buf.String(), tt.wantQuery); diff != "" {
				t.Error(testutil.Callers(), diff)
			}
			if diff := testutil.Diff(*args, tt.wantArgs); diff != "" {
				t.Error(testutil.Callers(), diff)
			}
			if diff := testutil.Diff(params, tt.wantParams); diff != "" {
				t.Error(testutil.Callers(), diff)
			}
		})
	}

	t.Run("invalid cte", func(t *testing.T) {
		t.Parallel()
		buf, args, params := bufpool.Get().(*bytes.Buffer), &[]any{}, make(map[string][]int)
		buf.Reset()
		defer bufpool.Put(buf)
		// no name
		err := writeCTEs(context.Background(), "", buf, args, params, []CTE{
			NewCTE("", nil, Queryf("SELECT 1")),
		})
		if err == nil {
			t.Fatal(testutil.Callers(), "expected error but got nil")
		}
		// no query
		err = writeCTEs(context.Background(), "", buf, args, params, []CTE{
			NewCTE("cte", nil, nil),
		})
		if err == nil {
			t.Fatal(testutil.Callers(), "expected error but got nil")
		}
	})

	t.Run("err", func(t *testing.T) {
		t.Parallel()
		buf, args, params := bufpool.Get().(*bytes.Buffer), &[]any{}, make(map[string][]int)
		buf.Reset()
		defer bufpool.Put(buf)
		// VariadicQuery
		err := writeCTEs(context.Background(), "", buf, args, params, []CTE{
			NewCTE("cte", nil, Union(
				Queryf("SELECT 1"),
				Queryf("SELECT {}", FaultySQL{}),
			)),
		})
		if !errors.Is(err, ErrFaultySQL) {
			t.Errorf(testutil.Callers()+"expected error %q but got %q", ErrFaultySQL, err)
		}
		// Query
		err = writeCTEs(context.Background(), "", buf, args, params, []CTE{
			NewCTE("cte", nil, Queryf("SELECT {}", FaultySQL{})),
		})
		if !errors.Is(err, ErrFaultySQL) {
			t.Errorf(testutil.Callers()+"expected error %q but got %q", ErrFaultySQL, err)
		}
	})
}

func TestVariadicQuery(t *testing.T) {
	q1, q2, q3 := Queryf("SELECT 1"), Queryf("SELECT 2"), Queryf("SELECT 3")
	tests := []TestTable{{
		description: "Union",
		item:        Union(q1, q2, q3),
		wantQuery:   "(SELECT 1 UNION SELECT 2 UNION SELECT 3)",
	}, {
		description: "UnionAll",
		item:        UnionAll(q1, q2, q3),
		wantQuery:   "(SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3)",
	}, {
		description: "Intersect",
		item:        Intersect(q1, q2, q3),
		wantQuery:   "(SELECT 1 INTERSECT SELECT 2 INTERSECT SELECT 3)",
	}, {
		description: "IntersectAll",
		item:        IntersectAll(q1, q2, q3),
		wantQuery:   "(SELECT 1 INTERSECT ALL SELECT 2 INTERSECT ALL SELECT 3)",
	}, {
		description: "Except",
		item:        Except(q1, q2, q3),
		wantQuery:   "(SELECT 1 EXCEPT SELECT 2 EXCEPT SELECT 3)",
	}, {
		description: "ExceptAll",
		item:        ExceptAll(q1, q2, q3),
		wantQuery:   "(SELECT 1 EXCEPT ALL SELECT 2 EXCEPT ALL SELECT 3)",
	}, {
		description: "No operator specified",
		item:        VariadicQuery{Queries: []Query{q1, q2, q3}},
		wantQuery:   "(SELECT 1 UNION SELECT 2 UNION SELECT 3)",
	}, {
		description: "nested VariadicQuery",
		item:        Union(Union(Union(q1, q2, q3))),
		wantQuery:   "(SELECT 1 UNION SELECT 2 UNION SELECT 3)",
	}, {
		description: "1 query",
		item:        Union(q1),
		wantQuery:   "SELECT 1",
	}}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			tt.assert(t)
		})
	}

	t.Run("invalid VariadicQuery", func(t *testing.T) {
		t.Parallel()
		// empty
		TestTable{item: Union()}.assertNotOK(t)
		// nil query
		TestTable{item: Union(nil)}.assertNotOK(t)
		// nil query
		TestTable{item: Union(q1, q2, nil)}.assertNotOK(t)
	})

	t.Run("err", func(t *testing.T) {
		t.Parallel()
		// VariadicQuery
		TestTable{
			item: Union(
				Union(
					Queryf("SELECT 1"),
					Queryf("SELECT {}", FaultySQL{}),
				),
			),
		}.assertErr(t, ErrFaultySQL)
		// Query
		TestTable{
			item: Union(Queryf("SELECT {}", FaultySQL{})),
		}.assertErr(t, ErrFaultySQL)
	})

	t.Run("SetFetchableFields", func(t *testing.T) {
		t.Parallel()
		_, ok := Union().SetFetchableFields([]Field{Expr("f1")})
		if ok {
			t.Error(testutil.Callers(), "expected not ok but got ok")
		}
	})

	t.Run("GetDialect", func(t *testing.T) {
		// empty VariadicQuery
		if diff := testutil.Diff(Union().GetDialect(), ""); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		// nil query
		if diff := testutil.Diff(Union(nil).GetDialect(), ""); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		// empty dialect propagated
		if diff := testutil.Diff(Union(Queryf("SELECT 1")).GetDialect(), ""); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})
}


================================================
FILE: delete_query.go
================================================
package sq

import (
	"bytes"
	"context"
	"fmt"
)

// DeleteQuery represents an SQL DELETE query.
type DeleteQuery struct {
	Dialect string
	// WITH
	CTEs []CTE
	// DELETE FROM
	DeleteTable  Table
	DeleteTables []Table
	// USING
	UsingTable Table
	JoinTables []JoinTable
	// WHERE
	WherePredicate Predicate
	// ORDER BY
	OrderByFields Fields
	// LIMIT
	LimitRows any
	// OFFSET
	OffsetRows any
	// RETURNING
	ReturningFields []Field
}

var _ Query = (*DeleteQuery)(nil)

// WriteSQL implements the SQLWriter interface.
func (q DeleteQuery) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	var err error
	// Table Policies
	var policies []Predicate
	policies, err = appendPolicy(ctx, dialect, policies, q.DeleteTable)
	if err != nil {
		return fmt.Errorf("DELETE FROM %s Policy: %w", toString(q.Dialect, q.DeleteTable), err)
	}
	policies, err = appendPolicy(ctx, dialect, policies, q.UsingTable)
	if err != nil {
		return fmt.Errorf("USING %s Policy: %w", toString(q.Dialect, q.UsingTable), err)
	}
	for _, joinTable := range q.JoinTables {
		policies, err = appendPolicy(ctx, dialect, policies, joinTable.Table)
		if err != nil {
			return fmt.Errorf("%s %s Policy: %w", joinTable.JoinOperator, joinTable.Table, err)
		}
	}
	if len(policies) > 0 {
		if q.WherePredicate != nil {
			policies = append(policies, q.WherePredicate)
		}
		q.WherePredicate = And(policies...)
	}
	// WITH
	if len(q.CTEs) > 0 {
		err = writeCTEs(ctx, dialect, buf, args, params, q.CTEs)
		if err != nil {
			return fmt.Errorf("WITH: %w", err)
		}
	}
	// DELETE FROM
	if (dialect == DialectMySQL || dialect == DialectSQLServer) && len(q.DeleteTables) > 0 {
		buf.WriteString("DELETE ")
		if len(q.DeleteTables) > 1 && dialect != DialectMySQL {
			return fmt.Errorf("dialect %q does not support multi-table DELETE", dialect)
		}
		for i, table := range q.DeleteTables {
			if i > 0 {
				buf.WriteString(", ")
			}
			if alias := getAlias(table); alias != "" {
				buf.WriteString(alias)
			} else {
				err = table.WriteSQL(ctx, dialect, buf, args, params)
				if err != nil {
					return fmt.Errorf("table #%d: %w", i+1, err)
				}
			}
		}
	} else {
		buf.WriteString("DELETE FROM ")
		if q.DeleteTable == nil {
			return fmt.Errorf("no table provided to DELETE FROM")
		}
		err = q.DeleteTable.WriteSQL(ctx, dialect, buf, args, params)
		if err != nil {
			return fmt.Errorf("DELETE FROM: %w", err)
		}
		if dialect != DialectSQLServer {
			if alias := getAlias(q.DeleteTable); alias != "" {
				buf.WriteString(" AS " + QuoteIdentifier(dialect, alias))
			}
		}
	}
	if q.UsingTable != nil || len(q.JoinTables) > 0 {
		if dialect != DialectPostgres && dialect != DialectMySQL && dialect != DialectSQLServer {
			return fmt.Errorf("%s DELETE does not support JOIN", dialect)
		}
	}
	// OUTPUT
	if len(q.ReturningFields) > 0 && dialect == DialectSQLServer {
		buf.WriteString(" OUTPUT ")
		err = writeFieldsWithPrefix(ctx, dialect, buf, args, params, q.ReturningFields, "DELETED", true)
		if err != nil {
			return err
		}
	}
	// USING/FROM
	if q.UsingTable != nil {
		switch dialect {
		case DialectPostgres:
			buf.WriteString(" USING ")
			err = q.UsingTable.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return fmt.Errorf("USING: %w", err)
			}
		case DialectMySQL, DialectSQLServer:
			buf.WriteString(" FROM ")
			err = q.UsingTable.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return fmt.Errorf("FROM: %w", err)
			}
		}
		if alias := getAlias(q.UsingTable); alias != "" {
			buf.WriteString(" AS " + QuoteIdentifier(dialect, alias))
		}
	}
	// JOIN
	if len(q.JoinTables) > 0 {
		if q.UsingTable == nil {
			return fmt.Errorf("%s can't JOIN without a USING/FROM table", dialect)
		}
		buf.WriteString(" ")
		err = writeJoinTables(ctx, dialect, buf, args, params, q.JoinTables)
		if err != nil {
			return fmt.Errorf("JOIN: %w", err)
		}
	}
	// WHERE
	if q.WherePredicate != nil {
		buf.WriteString(" WHERE ")
		switch predicate := q.WherePredicate.(type) {
		case VariadicPredicate:
			predicate.Toplevel = true
			err = predicate.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return fmt.Errorf("WHERE: %w", err)
			}
		default:
			err = q.WherePredicate.WriteSQL(ctx, dialect, buf, args, params)
			if err != nil {
				return fmt.Errorf("WHERE: %w", err)
			}
		}
	}
	// ORDER BY
	if len(q.OrderByFields) > 0 {
		if dialect != DialectMySQL {
			return fmt.Errorf("%s UPDATE does not support ORDER BY", dialect)
		}
		buf.WriteString(" ORDER BY ")
		err = q.OrderByFields.WriteSQL(ctx, dialect, buf, args, params)
		if err != nil {
			return fmt.Errorf("ORDER BY: %w", err)
		}
	}
	// LIMIT
	if q.LimitRows != nil {
		if dialect != DialectMySQL {
			return fmt.Errorf("%s UPDATE does not support LIMIT", dialect)
		}
		buf.WriteString(" LIMIT ")
		err = WriteValue(ctx, dialect, buf, args, params, q.LimitRows)
		if err != nil {
			return fmt.Errorf("LIMIT: %w", err)
		}
	}
	// RETURNING
	if len(q.ReturningFields) > 0 && dialect != DialectSQLServer {
		if dialect != DialectPostgres && dialect != DialectSQLite && dialect != DialectMySQL {
			return fmt.Errorf("%s UPDATE does not support RETURNING", dialect)
		}
		buf.WriteString(" RETURNING ")
		err = writeFields(ctx, dialect, buf, args, params, q.ReturningFields, true)
		if err != nil {
			return fmt.Errorf("RETURNING: %w", err)
		}
	}
	return nil
}

// DeleteFrom returns a new DeleteQuery.
func DeleteFrom(table Table) DeleteQuery {
	return DeleteQuery{DeleteTable: table}
}

// Where appends to the WherePredicate field of the DeleteQuery.
func (q DeleteQuery) Where(predicates ...Predicate) DeleteQuery {
	q.WherePredicate = appendPredicates(q.WherePredicate, predicates)
	return q
}

// SetFetchableFields implements the Query interface.
func (q DeleteQuery) SetFetchableFields(fields []Field) (query Query, ok bool) {
	switch q.Dialect {
	case DialectPostgres, DialectSQLite:
		if len(q.ReturningFields) == 0 {
			q.ReturningFields = fields
			return q, true
		}
		return q, false
	default:
		return q, false
	}
}

// GetFetchableFields returns the fetchable fields of the query.
func (q DeleteQuery) GetFetchableFields() []Field {
	switch q.Dialect {
	case DialectPostgres, DialectSQLite:
		return q.ReturningFields
	default:
		return nil
	}
}

// GetDialect implements the Query interface.
func (q DeleteQuery) GetDialect() string { return q.Dialect }

// SetDialect sets the dialect of the query.
func (q DeleteQuery) SetDialect(dialect string) DeleteQuery {
	q.Dialect = dialect
	return q
}

// SQLiteDeleteQuery represents an SQLite DELETE query.
type SQLiteDeleteQuery DeleteQuery

var _ Query = (*SQLiteDeleteQuery)(nil)

// WriteSQL implements the SQLWriter interface.
func (q SQLiteDeleteQuery) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	return DeleteQuery(q).WriteSQL(ctx, dialect, buf, args, params)
}

// DeleteFrom returns a new SQLiteDeleteQuery.
func (b sqliteQueryBuilder) DeleteFrom(table Table) SQLiteDeleteQuery {
	return SQLiteDeleteQuery{
		Dialect:     DialectSQLite,
		CTEs:        b.ctes,
		DeleteTable: table,
	}
}

// Where appends to the WherePredicate field of the SQLiteDeleteQuery.
func (q SQLiteDeleteQuery) Where(predicates ...Predicate) SQLiteDeleteQuery {
	q.WherePredicate = appendPredicates(q.WherePredicate, predicates)
	return q
}

// Returning appends fields to the RETURNING clause of the SQLiteDeleteQuery.
func (q SQLiteDeleteQuery) Returning(fields ...Field) SQLiteDeleteQuery {
	q.ReturningFields = append(q.ReturningFields, fields...)
	return q
}

// SetFetchableFields implements the Query interface.
func (q SQLiteDeleteQuery) SetFetchableFields(fields []Field) (query Query, ok bool) {
	return DeleteQuery(q).SetFetchableFields(fields)
}

// GetFetchableFields returns the fetchable fields of the query.
func (q SQLiteDeleteQuery) GetFetchableFields() []Field {
	return DeleteQuery(q).GetFetchableFields()
}

// GetDialect implements the Query interface.
func (q SQLiteDeleteQuery) GetDialect() string { return q.Dialect }

// SetDialect sets the dialect of the query.
func (q SQLiteDeleteQuery) SetDialect(dialect string) SQLiteDeleteQuery {
	q.Dialect = dialect
	return q
}

// PostgresDeleteQuery represents a Postgres DELETE query.
type PostgresDeleteQuery DeleteQuery

var _ Query = (*PostgresDeleteQuery)(nil)

// WriteSQL implements the SQLWriter interface.
func (q PostgresDeleteQuery) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	return DeleteQuery(q).WriteSQL(ctx, dialect, buf, args, params)
}

// DeleteFrom returns a new PostgresDeleteQuery.
func (b postgresQueryBuilder) DeleteFrom(table Table) PostgresDeleteQuery {
	return PostgresDeleteQuery{
		Dialect:     DialectPostgres,
		CTEs:        b.ctes,
		DeleteTable: table,
	}
}

// Using sets the UsingTable field of the PostgresDeleteQuery.
func (q PostgresDeleteQuery) Using(table Table) PostgresDeleteQuery {
	q.UsingTable = table
	return q
}

// Join joins a new Table to the PostgresDeleteQuery.
func (q PostgresDeleteQuery) Join(table Table, predicates ...Predicate) PostgresDeleteQuery {
	q.JoinTables = append(q.JoinTables, Join(table, predicates...))
	return q
}

// LeftJoin left joins a new Table to the PostgresDeleteQuery.
func (q PostgresDeleteQuery) LeftJoin(table Table, predicates ...Predicate) PostgresDeleteQuery {
	q.JoinTables = append(q.JoinTables, LeftJoin(table, predicates...))
	return q
}

// FullJoin full joins a new Table to the PostgresDeleteQuery.
func (q PostgresDeleteQuery) FullJoin(table Table, predicates ...Predicate) PostgresDeleteQuery {
	q.JoinTables = append(q.JoinTables, FullJoin(table, predicates...))
	return q
}

// CrossJoin cross joins a new Table to the PostgresDeleteQuery.
func (q PostgresDeleteQuery) CrossJoin(table Table) PostgresDeleteQuery {
	q.JoinTables = append(q.JoinTables, CrossJoin(table))
	return q
}

// CustomJoin joins a new Table to the PostgresDeleteQuery with a custom join
// operator.
func (q PostgresDeleteQuery) CustomJoin(joinOperator string, table Table, predicates ...Predicate) PostgresDeleteQuery {
	q.JoinTables = append(q.JoinTables, CustomJoin(joinOperator, table, predicates...))
	return q
}

// JoinUsing joins a new Table to the PostgresDeleteQuery with the USING operator.
func (q PostgresDeleteQuery) JoinUsing(table Table, fields ...Field) PostgresDeleteQuery {
	q.JoinTables = append(q.JoinTables, JoinUsing(table, fields...))
	return q
}

// Where appends to the WherePredicate field of the PostgresDeleteQuery.
func (q PostgresDeleteQuery) Where(predicates ...Predicate) PostgresDeleteQuery {
	q.WherePredicate = appendPredicates(q.WherePredicate, predicates)
	return q
}

// Returning appends fields to the RETURNING clause of the PostgresDeleteQuery.
func (q PostgresDeleteQuery) Returning(fields ...Field) PostgresDeleteQuery {
	q.ReturningFields = append(q.ReturningFields, fields...)
	return q
}

// SetFetchableFields implements the Query interface.
func (q PostgresDeleteQuery) SetFetchableFields(fields []Field) (query Query, ok bool) {
	return DeleteQuery(q).SetFetchableFields(fields)
}

// GetFetchableFields returns the fetchable fields of the query.
func (q PostgresDeleteQuery) GetFetchableFields() []Field {
	return DeleteQuery(q).GetFetchableFields()
}

// GetDialect implements the Query interface.
func (q PostgresDeleteQuery) GetDialect() string { return q.Dialect }

// SetDialect sets the dialect of the query.
func (q PostgresDeleteQuery) SetDialect(dialect string) PostgresDeleteQuery {
	q.Dialect = dialect
	return q
}

// MySQLDeleteQuery represents a MySQL DELETE query.
type MySQLDeleteQuery DeleteQuery

var _ Query = (*MySQLDeleteQuery)(nil)

// WriteSQL implements the SQLWriter interface.
func (q MySQLDeleteQuery) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	return DeleteQuery(q).WriteSQL(ctx, dialect, buf, args, params)
}

// DeleteFrom returns a new MySQLDeleteQuery.
func (b mysqlQueryBuilder) DeleteFrom(table Table) MySQLDeleteQuery {
	return MySQLDeleteQuery{
		Dialect:     DialectMySQL,
		CTEs:        b.ctes,
		DeleteTable: table,
	}
}

// Delete returns a new MySQLDeleteQuery.
func (b mysqlQueryBuilder) Delete(tables ...Table) MySQLDeleteQuery {
	return MySQLDeleteQuery{
		Dialect:      DialectMySQL,
		CTEs:         b.ctes,
		DeleteTables: tables,
	}
}

// From sets the UsingTable of the MySQLDeleteQuery.
func (q MySQLDeleteQuery) From(table Table) MySQLDeleteQuery {
	q.UsingTable = table
	return q
}

// Join joins a new Table to the MySQLDeleteQuery.
func (q MySQLDeleteQuery) Join(table Table, predicates ...Predicate) MySQLDeleteQuery {
	q.JoinTables = append(q.JoinTables, Join(table, predicates...))
	return q
}

// LeftJoin left joins a new Table to the MySQLDeleteQuery.
func (q MySQLDeleteQuery) LeftJoin(table Table, predicates ...Predicate) MySQLDeleteQuery {
	q.JoinTables = append(q.JoinTables, LeftJoin(table, predicates...))
	return q
}

// FullJoin full joins a new Table to the MySQLDeleteQuery.
func (q MySQLDeleteQuery) FullJoin(table Table, predicates ...Predicate) MySQLDeleteQuery {
	q.JoinTables = append(q.JoinTables, FullJoin(table, predicates...))
	return q
}

// CrossJoin cross joins a new Table to the MySQLDeleteQuery.
func (q MySQLDeleteQuery) CrossJoin(table Table) MySQLDeleteQuery {
	q.JoinTables = append(q.JoinTables, CrossJoin(table))
	return q
}

// CustomJoin joins a new Table to the MySQLDeleteQuery with a custom join
// operator.
func (q MySQLDeleteQuery) CustomJoin(joinOperator string, table Table, predicates ...Predicate) MySQLDeleteQuery {
	q.JoinTables = append(q.JoinTables, CustomJoin(joinOperator, table, predicates...))
	return q
}

// JoinUsing joins a new Table to the MySQLDeleteQuery with the USING operator.
func (q MySQLDeleteQuery) JoinUsing(table Table, fields ...Field) MySQLDeleteQuery {
	q.JoinTables = append(q.JoinTables, JoinUsing(table, fields...))
	return q
}

// Where appends to the WherePredicate field of the MySQLDeleteQuery.
func (q MySQLDeleteQuery) Where(predicates ...Predicate) MySQLDeleteQuery {
	q.WherePredicate = appendPredicates(q.WherePredicate, predicates)
	return q
}

// OrderBy sets the OrderByFields field of the MySQLDeleteQuery.
func (q MySQLDeleteQuery) OrderBy(fields ...Field) MySQLDeleteQuery {
	q.OrderByFields = append(q.OrderByFields, fields...)
	return q
}

// Limit sets the LimitRows field of the MySQLDeleteQuery.
func (q MySQLDeleteQuery) Limit(limit any) MySQLDeleteQuery {
	q.LimitRows = limit
	return q
}

// Returning appends fields to the RETURNING clause of the MySQLDeleteQuery.
func (q MySQLDeleteQuery) Returning(fields ...Field) MySQLDeleteQuery {
	q.ReturningFields = append(q.ReturningFields, fields...)
	return q
}

// SetFetchableFields implements the Query interface.
func (q MySQLDeleteQuery) SetFetchableFields(fields []Field) (query Query, ok bool) {
	return DeleteQuery(q).SetFetchableFields(fields)
}

// GetFetchableFields returns the fetchable fields of the query.
func (q MySQLDeleteQuery) GetFetchableFields() []Field {
	return DeleteQuery(q).GetFetchableFields()
}

// GetDialect implements the Query interface.
func (q MySQLDeleteQuery) GetDialect() string { return q.Dialect }

// SetDialect sets the dialect of the query.
func (q MySQLDeleteQuery) SetDialect(dialect string) MySQLDeleteQuery {
	q.Dialect = dialect
	return q
}

// SQLServerDeleteQuery represents an SQL Server DELETE query.
type SQLServerDeleteQuery DeleteQuery

var _ Query = (*SQLServerDeleteQuery)(nil)

// WriteSQL implements the SQLWriter interface.
func (q SQLServerDeleteQuery) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	return DeleteQuery(q).WriteSQL(ctx, dialect, buf, args, params)
}

// DeleteFrom returns a new SQLServerDeleteQuery.
func (b sqlserverQueryBuilder) DeleteFrom(table Table) SQLServerDeleteQuery {
	return SQLServerDeleteQuery{
		Dialect:     DialectSQLServer,
		CTEs:        b.ctes,
		DeleteTable: table,
	}
}

// Delete returns a new SQLServerDeleteQuery.
func (b sqlserverQueryBuilder) Delete(table Table) SQLServerDeleteQuery {
	return SQLServerDeleteQuery{
		Dialect:      DialectSQLServer,
		CTEs:         b.ctes,
		DeleteTables: []Table{table},
	}
}

// From sets the UsingTable of the SQLServerDeleteQuery.
func (q SQLServerDeleteQuery) From(table Table) SQLServerDeleteQuery {
	q.UsingTable = table
	return q
}

// Join joins a new Table to the SQLServerDeleteQuery.
func (q SQLServerDeleteQuery) Join(table Table, predicates ...Predicate) SQLServerDeleteQuery {
	q.JoinTables = append(q.JoinTables, Join(table, predicates...))
	return q
}

// LeftJoin left joins a new Table to the SQLServerDeleteQuery.
func (q SQLServerDeleteQuery) LeftJoin(table Table, predicates ...Predicate) SQLServerDeleteQuery {
	q.JoinTables = append(q.JoinTables, LeftJoin(table, predicates...))
	return q
}

// FullJoin full joins a new Table to the SQLServerDeleteQuery.
func (q SQLServerDeleteQuery) FullJoin(table Table, predicates ...Predicate) SQLServerDeleteQuery {
	q.JoinTables = append(q.JoinTables, FullJoin(table, predicates...))
	return q
}

// CrossJoin cross joins a new Table to the SQLServerDeleteQuery.
func (q SQLServerDeleteQuery) CrossJoin(table Table) SQLServerDeleteQuery {
	q.JoinTables = append(q.JoinTables, CrossJoin(table))
	return q
}

// CustomJoin joins a new Table to the SQLServerDeleteQuery with a custom join
// operator.
func (q SQLServerDeleteQuery) CustomJoin(joinOperator string, table Table, predicates ...Predicate) SQLServerDeleteQuery {
	q.JoinTables = append(q.JoinTables, CustomJoin(joinOperator, table, predicates...))
	return q
}

// Where appends to the WherePredicate field of the SQLServerDeleteQuery.
func (q SQLServerDeleteQuery) Where(predicates ...Predicate) SQLServerDeleteQuery {
	q.WherePredicate = appendPredicates(q.WherePredicate, predicates)
	return q
}

// SetFetchableFields implements the Query interface.
func (q SQLServerDeleteQuery) SetFetchableFields(fields []Field) (query Query, ok bool) {
	return DeleteQuery(q).SetFetchableFields(fields)
}

// GetFetchableFields returns the fetchable fields of the query.
func (q SQLServerDeleteQuery) GetFetchableFields() []Field {
	return DeleteQuery(q).GetFetchableFields()
}

// GetDialect implements the Query interface.
func (q SQLServerDeleteQuery) GetDialect() string { return q.Dialect }

// SetDialect sets the dialect of the query.
func (q SQLServerDeleteQuery) SetDialect(dialect string) SQLServerDeleteQuery {
	q.Dialect = dialect
	return q
}


================================================
FILE: delete_query_test.go
================================================
package sq

import (
	"testing"

	"github.com/bokwoon95/sq/internal/testutil"
)

func TestSQLiteDeleteQuery(t *testing.T) {
	type ACTOR struct {
		TableStruct
		ACTOR_ID    NumberField
		FIRST_NAME  StringField
		LAST_NAME   StringField
		LAST_UPDATE TimeField
	}
	a := New[ACTOR]("a")

	t.Run("basic", func(t *testing.T) {
		t.Parallel()
		q1 := SQLite.DeleteFrom(a).Returning(a.FIRST_NAME).SetDialect("lorem ipsum")
		if diff := testutil.Diff(q1.GetDialect(), "lorem ipsum"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		q1 = q1.SetDialect(DialectSQLite)
		fields := q1.GetFetchableFields()
		if diff := testutil.Diff(fields, []Field{a.FIRST_NAME}); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		_, ok := q1.SetFetchableFields([]Field{a.LAST_NAME})
		if ok {
			t.Fatal(testutil.Callers(), "field should not have been set")
		}
		q1.ReturningFields = q1.ReturningFields[:0]
		_, ok = q1.SetFetchableFields([]Field{a.LAST_NAME})
		if !ok {
			t.Fatal(testutil.Callers(), "field should have been set")
		}
	})

	t.Run("Delete Returning", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = SQLite.
			With(NewCTE("cte", nil, Queryf("SELECT 1"))).
			DeleteFrom(a).
			Where(a.ACTOR_ID.EqInt(1)).
			Returning(a.FIRST_NAME, a.LAST_NAME)
		tt.wantQuery = "WITH cte AS (SELECT 1)" +
			" DELETE FROM actor AS a" +
			" WHERE a.actor_id = $1" +
			" RETURNING a.first_name, a.last_name"
		tt.wantArgs = []any{1}
		tt.assert(t)
	})
}

func TestPostgresDeleteQuery(t *testing.T) {
	type ACTOR struct {
		TableStruct
		ACTOR_ID    NumberField
		FIRST_NAME  StringField
		LAST_NAME   StringField
		LAST_UPDATE TimeField
	}
	a := New[ACTOR]("a")

	t.Run("basic", func(t *testing.T) {
		t.Parallel()
		q1 := Postgres.DeleteFrom(a).Returning(a.FIRST_NAME).SetDialect("lorem ipsum")
		if diff := testutil.Diff(q1.GetDialect(), "lorem ipsum"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		q1 = q1.SetDialect(DialectPostgres)
		fields := q1.GetFetchableFields()
		if diff := testutil.Diff(fields, []Field{a.FIRST_NAME}); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		_, ok := q1.SetFetchableFields([]Field{a.LAST_NAME})
		if ok {
			t.Fatal(testutil.Callers(), "field should not have been set")
		}
		q1.ReturningFields = q1.ReturningFields[:0]
		_, ok = q1.SetFetchableFields([]Field{a.LAST_NAME})
		if !ok {
			t.Fatal(testutil.Callers(), "field should have been set")
		}
	})

	t.Run("Delete Returning", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = Postgres.
			With(NewCTE("cte", nil, Queryf("SELECT 1"))).
			DeleteFrom(a).
			Where(a.ACTOR_ID.EqInt(1)).
			Returning(a.FIRST_NAME, a.LAST_NAME)
		tt.wantQuery = "WITH cte AS (SELECT 1)" +
			" DELETE FROM actor AS a" +
			" WHERE a.actor_id = $1" +
			" RETURNING a.first_name, a.last_name"
		tt.wantArgs = []any{1}
		tt.assert(t)
	})

	t.Run("Join", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = Postgres.
			DeleteFrom(a).
			Using(a).
			Join(a, Expr("1 = 1")).
			LeftJoin(a, Expr("1 = 1")).
			FullJoin(a, Expr("1 = 1")).
			CrossJoin(a).
			CustomJoin(",", a).
			JoinUsing(a, a.FIRST_NAME, a.LAST_NAME)
		tt.wantQuery = "DELETE FROM actor AS a" +
			" USING actor AS a" +
			" JOIN actor AS a ON 1 = 1" +
			" LEFT JOIN actor AS a ON 1 = 1" +
			" FULL JOIN actor AS a ON 1 = 1" +
			" CROSS JOIN actor AS a" +
			" , actor AS a" +
			" JOIN actor AS a USING (first_name, last_name)"
		tt.assert(t)
	})
}

func TestMySQLDeleteQuery(t *testing.T) {
	type ACTOR struct {
		TableStruct
		ACTOR_ID    NumberField
		FIRST_NAME  StringField
		LAST_NAME   StringField
		LAST_UPDATE TimeField
	}
	a := New[ACTOR]("")

	t.Run("basic", func(t *testing.T) {
		t.Parallel()
		q1 := MySQL.DeleteFrom(a).SetDialect("lorem ipsum")
		if diff := testutil.Diff(q1.GetDialect(), "lorem ipsum"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		q1 = q1.SetDialect(DialectMySQL)
		fields := q1.GetFetchableFields()
		if len(fields) != 0 {
			t.Error(testutil.Callers(), "expected 0 fields but got %v", fields)
		}
		_, ok := q1.SetFetchableFields([]Field{a.LAST_NAME})
		if ok {
			t.Fatal(testutil.Callers(), "field should not have been set")
		}
		q1.ReturningFields = q1.ReturningFields[:0]
		_, ok = q1.SetFetchableFields([]Field{a.LAST_NAME})
		if ok {
			t.Fatal(testutil.Callers(), "field should not have been set")
		}
	})

	t.Run("Where", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = MySQL.
			With(NewCTE("cte", nil, Queryf("SELECT 1"))).
			DeleteFrom(a).
			Where(a.ACTOR_ID.EqInt(1))
		tt.wantQuery = "WITH cte AS (SELECT 1)" +
			" DELETE FROM actor" +
			" WHERE actor.actor_id = ?"
		tt.wantArgs = []any{1}
		tt.assert(t)
	})

	t.Run("OrderBy Limit", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = MySQL.
			DeleteFrom(a).
			OrderBy(a.ACTOR_ID).
			Limit(5)
		tt.wantQuery = "DELETE FROM actor" +
			" ORDER BY actor.actor_id" +
			" LIMIT ?"
		tt.wantArgs = []any{5}
		tt.assert(t)
	})

	t.Run("Delete Returning", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = MySQL.
			With(NewCTE("cte", nil, Queryf("SELECT 1"))).
			DeleteFrom(a).
			Where(a.ACTOR_ID.EqInt(1)).
			Returning(a.FIRST_NAME, a.LAST_NAME)
		tt.wantQuery = "WITH cte AS (SELECT 1)" +
			" DELETE FROM actor" +
			" WHERE actor.actor_id = ?" +
			" RETURNING actor.first_name, actor.last_name"
		tt.wantArgs = []any{1}
		tt.assert(t)
	})

	t.Run("Join", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = MySQL.
			Delete(a).
			From(a).
			Join(a, Expr("1 = 1")).
			LeftJoin(a, Expr("1 = 1")).
			FullJoin(a, Expr("1 = 1")).
			CrossJoin(a).
			CustomJoin(",", a).
			JoinUsing(a, a.FIRST_NAME, a.LAST_NAME)
		tt.wantQuery = "DELETE actor" +
			" FROM actor" +
			" JOIN actor ON 1 = 1" +
			" LEFT JOIN actor ON 1 = 1" +
			" FULL JOIN actor ON 1 = 1" +
			" CROSS JOIN actor" +
			" , actor" +
			" JOIN actor USING (first_name, last_name)"
		tt.assert(t)
	})
}

func TestSQLServerDeleteQuery(t *testing.T) {
	type ACTOR struct {
		TableStruct
		ACTOR_ID    NumberField
		FIRST_NAME  StringField
		LAST_NAME   StringField
		LAST_UPDATE TimeField
	}
	a := New[ACTOR]("")

	t.Run("basic", func(t *testing.T) {
		t.Parallel()
		q1 := SQLServer.DeleteFrom(a).SetDialect("lorem ipsum")
		if diff := testutil.Diff(q1.GetDialect(), "lorem ipsum"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
		q1 = q1.SetDialect(DialectSQLServer)
		q1 = q1.SetDialect(DialectMySQL)
		fields := q1.GetFetchableFields()
		if len(fields) != 0 {
			t.Error(testutil.Callers(), "expected 0 fields but got %v", fields)
		}
		_, ok := q1.SetFetchableFields([]Field{a.LAST_NAME})
		if ok {
			t.Fatal(testutil.Callers(), "field should not have been set")
		}
		q1.ReturningFields = q1.ReturningFields[:0]
		_, ok = q1.SetFetchableFields([]Field{a.LAST_NAME})
		if ok {
			t.Fatal(testutil.Callers(), "field should not have been set")
		}
	})

	t.Run("Where", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = SQLServer.
			With(NewCTE("cte", nil, Queryf("SELECT 1"))).
			DeleteFrom(a).
			Where(a.ACTOR_ID.EqInt(1))
		tt.wantQuery = "WITH cte AS (SELECT 1)" +
			" DELETE FROM actor" +
			" WHERE actor.actor_id = @p1"
		tt.wantArgs = []any{1}
		tt.assert(t)
	})

	t.Run("Join", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = SQLServer.
			DeleteFrom(a).
			From(a).
			Join(a, Expr("1 = 1")).
			LeftJoin(a, Expr("1 = 1")).
			FullJoin(a, Expr("1 = 1")).
			CrossJoin(a).
			CustomJoin(",", a)
		tt.wantQuery = "DELETE FROM actor" +
			" FROM actor" +
			" JOIN actor ON 1 = 1" +
			" LEFT JOIN actor ON 1 = 1" +
			" FULL JOIN actor ON 1 = 1" +
			" CROSS JOIN actor" +
			" , actor"
		tt.assert(t)
	})
}

func TestDeleteQuery(t *testing.T) {
	t.Run("basic", func(t *testing.T) {
		t.Parallel()
		q1 := DeleteQuery{DeleteTable: Expr("tbl"), Dialect: "lorem ipsum"}
		if diff := testutil.Diff(q1.GetDialect(), "lorem ipsum"); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})

	t.Run("PolicyTable", func(t *testing.T) {
		t.Parallel()
		var tt TestTable
		tt.item = DeleteQuery{
			DeleteTable:    policyTableStub{policy: And(Expr("1 = 1"), Expr("2 = 2"))},
			WherePredicate: Expr("3 = 3"),
		}
		tt.wantQuery = "DELETE FROM policy_table_stub WHERE (1 = 1 AND 2 = 2) AND 3 = 3"
		tt.assert(t)
	})

	notOKTests := []TestTable{{
		description: "nil FromTable not allowed",
		item: DeleteQuery{
			DeleteTable: nil,
		},
	}, {
		description: "sqlite does not support JOIN",
		item: DeleteQuery{
			Dialect:     DialectSQLite,
			DeleteTable: Expr("tbl"),
			UsingTable:  Expr("tbl"),
			JoinTables: []JoinTable{
				Join(Expr("tbl"), Expr("1 = 1")),
			},
		},
	}, {
		description: "postgres does not allow JOIN without USING",
		item: DeleteQuery{
			Dialect:     DialectPostgres,
			DeleteTable: Expr("tbl"),
			JoinTables: []JoinTable{
				Join(Expr("tbl"), Expr("1 = 1")),
			},
		},
	}, {
		description: "dialect does not support ORDER BY",
		item: DeleteQuery{
			Dialect:       DialectPostgres,
			DeleteTable:   Expr("tbl"),
			OrderByFields: Fields{Expr("f1")},
		},
	}, {
		description: "dialect does not support LIMIT",
		item: DeleteQuery{
			Dialect:     DialectPostgres,
			DeleteTable: Expr("tbl"),
			LimitRows:   5,
		},
	}}

	for _, tt := range notOKTests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			tt.assertNotOK(t)
		})
	}

	errTests := []TestTable{{
		description: "FromTable Policy err",
		item: DeleteQuery{
			DeleteTable: policyTableStub{err: ErrFaultySQL},
		},
	}, {
		description: "UsingTable Policy err",
		item: DeleteQuery{
			DeleteTable: Expr("tbl"),
			UsingTable:  policyTableStub{err: ErrFaultySQL},
		},
	}, {
		description: "JoinTables Policy err",
		item: DeleteQuery{
			DeleteTable: Expr("tbl"),
			UsingTable:  Expr("tbl"),
			JoinTables: []JoinTable{
				Join(policyTableStub{err: ErrFaultySQL}, Expr("1 = 1")),
			},
		},
	}, {
		description: "CTEs err",
		item: DeleteQuery{
			CTEs:        []CTE{NewCTE("cte", nil, Queryf("SELECT {}", FaultySQL{}))},
			DeleteTable: Expr("tbl"),
		},
	}, {
		description: "FromTable err",
		item: DeleteQuery{
			DeleteTable: FaultySQL{},
		},
	}, {
		description: "postgres UsingTable err",
		item: DeleteQuery{
			Dialect:     DialectPostgres,
			DeleteTable: Expr("tbl"),
			UsingTable:  FaultySQL{},
		},
	}, {
		description: "sqlserver UsingTable err",
		item: DeleteQuery{
			Dialect:     DialectSQLServer,
			DeleteTable: Expr("tbl"),
			UsingTable:  FaultySQL{},
		},
	}, {
		description: "JoinTables err",
		item: DeleteQuery{
			Dialect:     DialectPostgres,
			DeleteTable: Expr("tbl"),
			UsingTable:  Expr("tbl"),
			JoinTables: []JoinTable{
				Join(Expr("tbl"), FaultySQL{}),
			},
		},
	}, {
		description: "WherePredicate Variadic err",
		item: DeleteQuery{
			DeleteTable:    Expr("tbl"),
			WherePredicate: And(FaultySQL{}),
		},
	}, {
		description: "WherePredicate err",
		item: DeleteQuery{
			DeleteTable:    Expr("tbl"),
			WherePredicate: FaultySQL{},
		},
	}, {
		description: "OrderByFields err",
		item: DeleteQuery{
			Dialect:       DialectMySQL,
			DeleteTable:   Expr("tbl"),
			OrderByFields: Fields{FaultySQL{}},
		},
	}, {
		description: "LimitRows err",
		item: DeleteQuery{
			Dialect:       DialectMySQL,
			DeleteTable:   Expr("tbl"),
			OrderByFields: Fields{Expr("f1")},
			LimitRows:     FaultySQL{},
		},
	}, {
		description: "ReturningFields err",
		item: DeleteQuery{
			Dialect:         DialectPostgres,
			DeleteTable:     Expr("tbl"),
			ReturningFields: Fields{FaultySQL{}},
		},
	}}

	for _, tt := range errTests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			tt.assertErr(t, ErrFaultySQL)
		})
	}
}


================================================
FILE: fetch_exec.go
================================================
package sq

import (
	"bytes"
	"context"
	"database/sql"
	"fmt"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"sync/atomic"
	"time"
)

// Default dialect used by all queries (if no dialect is explicitly provided).
var DefaultDialect atomic.Pointer[string]

// A Cursor represents a database cursor.
type Cursor[T any] struct {
	ctx           context.Context
	row           *Row
	rowmapper     func(*Row) T
	queryStats    QueryStats
	logSettings   LogSettings
	logger        SqLogger
	logged        int32
	fieldNames    []string
	resultsBuffer *bytes.Buffer
}

// FetchCursor returns a new cursor.
func FetchCursor[T any](db DB, query Query, rowmapper func(*Row) T) (*Cursor[T], error) {
	return fetchCursor(context.Background(), db, query, rowmapper, 1)
}

// FetchCursorContext is like FetchCursor but additionally requires a context.Context.
func FetchCursorContext[T any](ctx context.Context, db DB, query Query, rowmapper func(*Row) T) (*Cursor[T], error) {
	return fetchCursor(ctx, db, query, rowmapper, 1)
}

func fetchCursor[T any](ctx context.Context, db DB, query Query, rowmapper func(*Row) T, skip int) (cursor *Cursor[T], err error) {
	if db == nil {
		return nil, fmt.Errorf("db is nil")
	}
	if query == nil {
		return nil, fmt.Errorf("query is nil")
	}
	if rowmapper == nil {
		return nil, fmt.Errorf("rowmapper is nil")
	}
	dialect := query.GetDialect()
	if dialect == "" {
		defaultDialect := DefaultDialect.Load()
		if defaultDialect != nil {
			dialect = *defaultDialect
		}
	}
	// If we can't set the fetchable fields, the query is static.
	_, ok := query.SetFetchableFields(nil)
	cursor = &Cursor[T]{
		ctx:       ctx,
		rowmapper: rowmapper,
		row: &Row{
			dialect:       dialect,
			queryIsStatic: !ok,
		},
		queryStats: QueryStats{
			Dialect:  dialect,
			Params:   make(map[string][]int),
			RowCount: sql.NullInt64{Valid: true},
		},
	}

	// If the query is dynamic, call the rowmapper to populate row.fields and
	// row.scanDest. Then, insert those fields back into the query.
	if !cursor.row.queryIsStatic {
		defer mapperFunctionPanicked(&err)
		_ = cursor.rowmapper(cursor.row)
		query, _ = query.SetFetchableFields(cursor.row.fields)
	}

	// Build query.
	buf := bufpool.Get().(*bytes.Buffer)
	buf.Reset()
	defer bufpool.Put(buf)
	err = query.WriteSQL(ctx, dialect, buf, &cursor.queryStats.Args, cursor.queryStats.Params)
	cursor.queryStats.Query = buf.String()
	if err != nil {
		return nil, err
	}

	// Setup logger.
	cursor.logger, _ = db.(SqLogger)
	if cursor.logger == nil {
		logQuery, _ := defaultLogQuery.Load().(func(context.Context, QueryStats))
		if logQuery != nil {
			logSettings, _ := defaultLogSettings.Load().(func(context.Context, *LogSettings))
			cursor.logger = &sqLogStruct{
				logSettings: logSettings,
				logQuery:    logQuery,
			}
		}
	}
	if cursor.logger != nil {
		cursor.logger.SqLogSettings(ctx, &cursor.logSettings)
		if cursor.logSettings.IncludeCaller {
			cursor.queryStats.CallerFile, cursor.queryStats.CallerLine, cursor.queryStats.CallerFunction = caller(skip + 1)
		}
	}

	// Run query.
	if cursor.logSettings.IncludeTime {
		cursor.queryStats.StartedAt = time.Now()
	}
	cursor.row.sqlRows, cursor.queryStats.Err = db.QueryContext(ctx, cursor.queryStats.Query, cursor.queryStats.Args...)
	if cursor.logSettings.IncludeTime {
		cursor.queryStats.TimeTaken = time.Since(cursor.queryStats.StartedAt)
	}
	if cursor.queryStats.Err != nil {
		cursor.log()
		return nil, cursor.queryStats.Err
	}

	// If the query is static, we now know the number of columns returned by
	// the query and can allocate the values slice and scanDest slice for
	// scanning later.
	if cursor.row.queryIsStatic {
		cursor.row.columns, err = cursor.row.sqlRows.Columns()
		if err != nil {
			return nil, err
		}
		cursor.row.columnTypes, err = cursor.row.sqlRows.ColumnTypes()
		if err != nil {
			return nil, err
		}
		cursor.row.columnIndex = make(map[string]int)
		for index, column := range cursor.row.columns {
			cursor.row.columnIndex[column] = index
		}
		cursor.row.values = make([]any, len(cursor.row.columns))
		cursor.row.scanDest = make([]any, len(cursor.row.columns))
		for index := range cursor.row.values {
			cursor.row.scanDest[index] = &cursor.row.values[index]
		}
	}

	// Allocate the resultsBuffer.
	if cursor.logSettings.IncludeResults > 0 {
		cursor.resultsBuffer = bufpool.Get().(*bytes.Buffer)
		cursor.resultsBuffer.Reset()
	}
	return cursor, nil
}

// Next advances the cursor to the next result.
func (cursor *Cursor[T]) Next() bool {
	hasNext := cursor.row.sqlRows.Next()
	if hasNext {
		cursor.queryStats.RowCount.Int64++
	} else {
		cursor.log()
	}
	return hasNext
}

// RowCount returns the current row number so far.
func (cursor *Cursor[T]) RowCount() int64 { return cursor.queryStats.RowCount.Int64 }

// Result returns the cursor result.
func (cursor *Cursor[T]) Result() (result T, err error) {
	err = cursor.row.sqlRows.Scan(cursor.row.scanDest...)
	if err != nil {
		cursor.log()
		fieldMappings := getFieldMappings(cursor.queryStats.Dialect, cursor.row.fields, cursor.row.scanDest)
		return result, fmt.Errorf("please check if your mapper function is correct:%s\n%w", fieldMappings, err)
	}
	// If results should be logged, write the row into the resultsBuffer.
	if cursor.resultsBuffer != nil && cursor.queryStats.RowCount.Int64 <= int64(cursor.logSettings.IncludeResults) {
		if len(cursor.fieldNames) == 0 {
			cursor.fieldNames = getFieldNames(cursor.ctx, cursor.row)
		}
		cursor.resultsBuffer.WriteString("\n----[ Row " + strconv.FormatInt(cursor.queryStats.RowCount.Int64, 10) + " ]----")
		for i := range cursor.row.scanDest {
			cursor.resultsBuffer.WriteString("\n")
			if i < len(cursor.fieldNames) {
				cursor.resultsBuffer.WriteString(cursor.fieldNames[i])
			}
			cursor.resultsBuffer.WriteString(": ")
			scanDest := cursor.row.scanDest[i]
			rhs, err := Sprint(cursor.queryStats.Dialect, scanDest)
			if err != nil {
				cursor.resultsBuffer.WriteString("%!(error=" + err.Error() + ")")
				continue
			}
			cursor.resultsBuffer.WriteString(rhs)
		}
	}
	cursor.row.runningIndex = 0
	defer mapperFunctionPanicked(&err)
	result = cursor.rowmapper(cursor.row)
	return result, nil
}

func (cursor *Cursor[T]) log() {
	if !atomic.CompareAndSwapInt32(&cursor.logged, 0, 1) {
		return
	}
	if cursor.resultsBuffer != nil {
		cursor.queryStats.Results = cursor.resultsBuffer.String()
		bufpool.Put(cursor.resultsBuffer)
	}
	if cursor.logger == nil {
		return
	}
	if cursor.logSettings.LogAsynchronously {
		go cursor.logger.SqLogQuery(cursor.ctx, cursor.queryStats)
	} else {
		cursor.logger.SqLogQuery(cursor.ctx, cursor.queryStats)
	}
}

// Close closes the cursor.
func (cursor *Cursor[T]) Close() error {
	cursor.log()
	if err := cursor.row.sqlRows.Close(); err != nil {
		return err
	}
	if err := cursor.row.sqlRows.Err(); err != nil {
		return err
	}
	return nil
}

// FetchOne returns the first result from running the given Query on the given
// DB.
func FetchOne[T any](db DB, query Query, rowmapper func(*Row) T) (T, error) {
	cursor, err := fetchCursor(context.Background(), db, query, rowmapper, 1)
	if err != nil {
		return *new(T), err
	}
	defer cursor.Close()
	return cursorResult(cursor)
}

// FetchOneContext is like FetchOne but additionally requires a context.Context.
func FetchOneContext[T any](ctx context.Context, db DB, query Query, rowmapper func(*Row) T) (T, error) {
	cursor, err := fetchCursor(ctx, db, query, rowmapper, 1)
	if err != nil {
		return *new(T), err
	}
	defer cursor.Close()
	return cursorResult(cursor)
}

// FetchAll returns all results from running the given Query on the given DB.
func FetchAll[T any](db DB, query Query, rowmapper func(*Row) T) ([]T, error) {
	cursor, err := fetchCursor(context.Background(), db, query, rowmapper, 1)
	if err != nil {
		return nil, err
	}
	defer cursor.Close()
	return cursorResults(cursor)
}

// FetchAllContext is like FetchAll but additionally requires a context.Context.
func FetchAllContext[T any](ctx context.Context, db DB, query Query, rowmapper func(*Row) T) ([]T, error) {
	cursor, err := fetchCursor(ctx, db, query, rowmapper, 1)
	if err != nil {
		return nil, err
	}
	defer cursor.Close()
	return cursorResults(cursor)
}

// CompiledFetch is the result of compiling a Query down into a query string
// and args slice. A CompiledFetch can be safely executed in parallel.
type CompiledFetch[T any] struct {
	dialect   string
	query     string
	args      []any
	params    map[string][]int
	rowmapper func(*Row) T
	// if queryIsStatic is true, the rowmapper doesn't actually know what
	// columns are in the query and it must be determined at runtime after
	// running the query.
	queryIsStatic bool
}

// NewCompiledFetch returns a new CompiledFetch.
func NewCompiledFetch[T any](dialect string, query string, args []any, params map[string][]int, rowmapper func(*Row) T) *CompiledFetch[T] {
	return &CompiledFetch[T]{
		dialect:   dialect,
		query:     query,
		args:      args,
		params:    params,
		rowmapper: rowmapper,
	}
}

// CompileFetch returns a new CompileFetch.
func CompileFetch[T any](q Query, rowmapper func(*Row) T) (*CompiledFetch[T], error) {
	return CompileFetchContext(context.Background(), q, rowmapper)
}

// CompileFetchContext is like CompileFetch but accepts a context.Context.
func CompileFetchContext[T any](ctx context.Context, query Query, rowmapper func(*Row) T) (compiledFetch *CompiledFetch[T], err error) {
	if query == nil {
		return nil, fmt.Errorf("query is nil")
	}
	if rowmapper == nil {
		return nil, fmt.Errorf("rowmapper is nil")
	}
	dialect := query.GetDialect()
	if dialect == "" {
		defaultDialect := DefaultDialect.Load()
		if defaultDialect != nil {
			dialect = *defaultDialect
		}
	}
	// If we can't set the fetchable fields, the query is static.
	_, ok := query.SetFetchableFields(nil)
	compiledFetch = &CompiledFetch[T]{
		dialect:       dialect,
		params:        make(map[string][]int),
		rowmapper:     rowmapper,
		queryIsStatic: !ok,
	}
	row := &Row{
		dialect:       dialect,
		queryIsStatic: !ok,
	}

	// If the query is dynamic, call the rowmapper to populate row.fields.
	// Then, insert those fields back into the query.
	if !row.queryIsStatic {
		defer mapperFunctionPanicked(&err)
		_ = rowmapper(row)
		query, _ = query.SetFetchableFields(row.fields)
	}

	// Build query.
	buf := bufpool.Get().(*bytes.Buffer)
	buf.Reset()
	defer bufpool.Put(buf)
	err = query.WriteSQL(ctx, dialect, buf, &compiledFetch.args, compiledFetch.params)
	compiledFetch.query = buf.String()
	if err != nil {
		return nil, err
	}
	return compiledFetch, nil
}

// FetchCursor returns a new cursor.
func (compiledFetch *CompiledFetch[T]) FetchCursor(db DB, params Params) (*Cursor[T], error) {
	return compiledFetch.fetchCursor(context.Background(), db, params, 1)
}

// FetchCursorContext is like FetchCursor but additionally requires a context.Context.
func (compiledFetch *CompiledFetch[T]) FetchCursorContext(ctx context.Context, db DB, params Params) (*Cursor[T], error) {
	return compiledFetch.fetchCursor(ctx, db, params, 1)
}

func (compiledFetch *CompiledFetch[T]) fetchCursor(ctx context.Context, db DB, params Params, skip int) (cursor *Cursor[T], err error) {
	if db == nil {
		return nil, fmt.Errorf("db is nil")
	}
	cursor = &Cursor[T]{
		ctx:       ctx,
		rowmapper: compiledFetch.rowmapper,
		row: &Row{
			dialect:       compiledFetch.dialect,
			queryIsStatic: compiledFetch.queryIsStatic,
		},
		queryStats: QueryStats{
			Dialect: compiledFetch.dialect,
			Query:   compiledFetch.query,
			Args:    compiledFetch.args,
			Params:  compiledFetch.params,
		},
	}

	// Call the rowmapper to populate row.scanDest.
	if !cursor.row.queryIsStatic {
		defer mapperFunctionPanicked(&err)
		_ = cursor.rowmapper(cursor.row)
	}

	// Substitute params.
	cursor.queryStats.Args, err = substituteParams(cursor.queryStats.Dialect, cursor.queryStats.Args, cursor.queryStats.Params, params)
	if err != nil {
		return nil, err
	}

	// Setup logger.
	cursor.queryStats.RowCount.Valid = true
	cursor.logger, _ = db.(SqLogger)
	if cursor.logger == nil {
		logQuery, _ := defaultLogQuery.Load().(func(context.Context, QueryStats))
		if logQuery != nil {
			logSettings, _ := defaultLogSettings.Load().(func(context.Context, *LogSettings))
			cursor.logger = &sqLogStruct{
				logSettings: logSettings,
				logQuery:    logQuery,
			}
		}
	}
	if cursor.logger != nil {
		cursor.logger.SqLogSettings(ctx, &cursor.logSettings)
		if cursor.logSettings.IncludeCaller {
			cursor.queryStats.CallerFile, cursor.queryStats.CallerLine, cursor.queryStats.CallerFunction = caller(skip + 1)
		}
	}

	// Run query.
	if cursor.logSettings.IncludeTime {
		cursor.queryStats.StartedAt = time.Now()
	}
	cursor.row.sqlRows, cursor.queryStats.Err = db.QueryContext(ctx, cursor.queryStats.Query, cursor.queryStats.Args...)
	if cursor.logSettings.IncludeTime {
		cursor.queryStats.TimeTaken = time.Since(cursor.queryStats.StartedAt)
	}
	if cursor.queryStats.Err != nil {
		return nil, cursor.queryStats.Err
	}

	// If the query is static, we now know the number of columns returned by
	// the query and can allocate the values slice and scanDest slice for
	// scanning later.
	if cursor.row.queryIsStatic {
		cursor.row.columns, err = cursor.row.sqlRows.Columns()
		if err != nil {
			return nil, err
		}
		cursor.row.columnTypes, err = cursor.row.sqlRows.ColumnTypes()
		if err != nil {
			return nil, err
		}
		cursor.row.columnIndex = make(map[string]int)
		for index, column := range cursor.row.columns {
			cursor.row.columnIndex[column] = index
		}
		cursor.row.values = make([]any, len(cursor.row.columns))
		cursor.row.scanDest = make([]any, len(cursor.row.columns))
		for index := range cursor.row.values {
			cursor.row.scanDest[index] = &cursor.row.values[index]
		}
	}

	// Allocate the resultsBuffer.
	if cursor.logSettings.IncludeResults > 0 {
		cursor.resultsBuffer = bufpool.Get().(*bytes.Buffer)
		cursor.resultsBuffer.Reset()
	}
	return cursor, nil
}

// FetchOne returns the first result from running the CompiledFetch on the
// given DB with the give params.
func (compiledFetch *CompiledFetch[T]) FetchOne(db DB, params Params) (T, error) {
	cursor, err := compiledFetch.fetchCursor(context.Background(), db, params, 1)
	if err != nil {
		return *new(T), err
	}
	defer cursor.Close()
	return cursorResult(cursor)
}

// FetchOneContext is like FetchOne but additionally requires a context.Context.
func (compiledFetch *CompiledFetch[T]) FetchOneContext(ctx context.Context, db DB, params Params) (T, error) {
	cursor, err := compiledFetch.fetchCursor(ctx, db, params, 1)
	if err != nil {
		return *new(T), err
	}
	defer cursor.Close()
	return cursorResult(cursor)
}

// FetchAll returns all the results from running the CompiledFetch on the given
// DB with the give params.
func (compiledFetch *CompiledFetch[T]) FetchAll(db DB, params Params) ([]T, error) {
	cursor, err := compiledFetch.fetchCursor(context.Background(), db, params, 1)
	if err != nil {
		return nil, err
	}
	defer cursor.Close()
	return cursorResults(cursor)
}

// FetchAllContext is like FetchAll but additionally requires a context.Context.
func (compiledFetch *CompiledFetch[T]) FetchAllContext(ctx context.Context, db DB, params Params) ([]T, error) {
	cursor, err := compiledFetch.fetchCursor(ctx, db, params, 1)
	if err != nil {
		return nil, err
	}
	defer cursor.Close()
	return cursorResults(cursor)
}

// GetSQL returns a copy of the dialect, query, args, params and rowmapper that
// make up the CompiledFetch.
func (compiledFetch *CompiledFetch[T]) GetSQL() (dialect string, query string, args []any, params map[string][]int, rowmapper func(*Row) T) {
	dialect = compiledFetch.dialect
	query = compiledFetch.query
	args = make([]any, len(compiledFetch.args))
	params = make(map[string][]int)
	copy(args, compiledFetch.args)
	for name, indexes := range compiledFetch.params {
		indexes2 := make([]int, len(indexes))
		copy(indexes2, indexes)
		params[name] = indexes2
	}
	return dialect, query, args, params, compiledFetch.rowmapper
}

// Prepare creates a PreparedFetch from a CompiledFetch by preparing it on
// the given DB.
func (compiledFetch *CompiledFetch[T]) Prepare(db DB) (*PreparedFetch[T], error) {
	return compiledFetch.PrepareContext(context.Background(), db)
}

// PrepareContext is like Prepare but additionally requires a context.Context.
func (compiledFetch *CompiledFetch[T]) PrepareContext(ctx context.Context, db DB) (*PreparedFetch[T], error) {
	var err error
	preparedFetch := &PreparedFetch[T]{
		compiledFetch: NewCompiledFetch(compiledFetch.GetSQL()),
	}
	preparedFetch.compiledFetch.queryIsStatic = compiledFetch.queryIsStatic
	if db == nil {
		return nil, fmt.Errorf("db is nil")
	}
	preparedFetch.stmt, err = db.PrepareContext(ctx, compiledFetch.query)
	if err != nil {
		return nil, err
	}
	preparedFetch.logger, _ = db.(SqLogger)
	if preparedFetch.logger == nil {
		logQuery, _ := defaultLogQuery.Load().(func(context.Context, QueryStats))
		if logQuery != nil {
			logSettings, _ := defaultLogSettings.Load().(func(context.Context, *LogSettings))
			preparedFetch.logger = &sqLogStruct{
				logSettings: logSettings,
				logQuery:    logQuery,
			}
		}
	}
	return preparedFetch, nil
}

// PreparedFetch is the result of preparing a CompiledFetch on a DB.
type PreparedFetch[T any] struct {
	compiledFetch *CompiledFetch[T]
	stmt          *sql.Stmt
	logger        SqLogger
}

// PrepareFetch returns a new PreparedFetch.
func PrepareFetch[T any](db DB, q Query, rowmapper func(*Row) T) (*PreparedFetch[T], error) {
	return PrepareFetchContext(context.Background(), db, q, rowmapper)
}

// PrepareFetchContext is like PrepareFetch but additionally requires a context.Context.
func PrepareFetchContext[T any](ctx context.Context, db DB, q Query, rowmapper func(*Row) T) (*PreparedFetch[T], error) {
	compiledFetch, err := CompileFetchContext(ctx, q, rowmapper)
	if err != nil {
		return nil, err
	}
	return compiledFetch.PrepareContext(ctx, db)
}

// FetchCursor returns a new cursor.
func (preparedFetch PreparedFetch[T]) FetchCursor(params Params) (*Cursor[T], error) {
	return preparedFetch.fetchCursor(context.Background(), params, 1)
}

// FetchCursorContext is like FetchCursor but additionally requires a context.Context.
func (preparedFetch PreparedFetch[T]) FetchCursorContext(ctx context.Context, params Params) (*Cursor[T], error) {
	return preparedFetch.fetchCursor(ctx, params, 1)
}

func (preparedFetch *PreparedFetch[T]) fetchCursor(ctx context.Context, params Params, skip int) (cursor *Cursor[T], err error) {
	cursor = &Cursor[T]{
		ctx:       ctx,
		rowmapper: preparedFetch.compiledFetch.rowmapper,
		row: &Row{
			dialect:       preparedFetch.compiledFetch.dialect,
			queryIsStatic: preparedFetch.compiledFetch.queryIsStatic,
		},
		queryStats: QueryStats{
			Dialect:  preparedFetch.compiledFetch.dialect,
			Query:    preparedFetch.compiledFetch.query,
			Args:     preparedFetch.compiledFetch.args,
			Params:   preparedFetch.compiledFetch.params,
			RowCount: sql.NullInt64{Valid: true},
		},
		logger: preparedFetch.logger,
	}

	// If the query is dynamic, call the rowmapper to populate row.scanDest.
	if !cursor.row.queryIsStatic {
		defer mapperFunctionPanicked(&err)
		_ = cursor.rowmapper(cursor.row)
	}

	// Substitute params.
	cursor.queryStats.Args, err = substituteParams(cursor.queryStats.Dialect, cursor.queryStats.Args, cursor.queryStats.Params, params)
	if err != nil {
		return nil, err
	}

	// Setup logger.
	if cursor.logger != nil {
		cursor.logger.SqLogSettings(ctx, &cursor.logSettings)
		if cursor.logSettings.IncludeCaller {
			cursor.queryStats.CallerFile, cursor.queryStats.CallerLine, cursor.queryStats.CallerFunction = caller(skip + 1)
		}
	}

	// Run query.
	if cursor.logSettings.IncludeTime {
		cursor.queryStats.StartedAt = time.Now()
	}
	cursor.row.sqlRows, cursor.queryStats.Err = preparedFetch.stmt.QueryContext(ctx, cursor.queryStats.Args...)
	if cursor.logSettings.IncludeTime {
		cursor.queryStats.TimeTaken = time.Since(cursor.queryStats.StartedAt)
	}
	if cursor.queryStats.Err != nil {
		return nil, cursor.queryStats.Err
	}

	// If the query is static, we now know the number of columns returned by
	// the query and can allocate the values slice and scanDest slice for
	// scanning later.
	if cursor.row.queryIsStatic {
		cursor.row.columns, err = cursor.row.sqlRows.Columns()
		if err != nil {
			return nil, err
		}
		cursor.row.columnTypes, err = cursor.row.sqlRows.ColumnTypes()
		if err != nil {
			return nil, err
		}
		cursor.row.columnIndex = make(map[string]int)
		for index, column := range cursor.row.columns {
			cursor.row.columnIndex[column] = index
		}
		cursor.row.values = make([]any, len(cursor.row.columns))
		cursor.row.scanDest = make([]any, len(cursor.row.columns))
		for index := range cursor.row.values {
			cursor.row.scanDest[index] = &cursor.row.values[index]
		}
	}

	// Allocate the resultsBuffer.
	if cursor.logSettings.IncludeResults > 0 {
		cursor.resultsBuffer = bufpool.Get().(*bytes.Buffer)
		cursor.resultsBuffer.Reset()
	}
	return cursor, nil
}

// FetchOne returns the first result from running the PreparedFetch with the
// give params.
func (preparedFetch *PreparedFetch[T]) FetchOne(params Params) (T, error) {
	cursor, err := preparedFetch.fetchCursor(context.Background(), params, 1)
	if err != nil {
		return *new(T), err
	}
	defer cursor.Close()
	return cursorResult(cursor)
}

// FetchOneContext is like FetchOne but additionally requires a context.Context.
func (preparedFetch *PreparedFetch[T]) FetchOneContext(ctx context.Context, params Params) (T, error) {
	cursor, err := preparedFetch.fetchCursor(ctx, params, 1)
	if err != nil {
		return *new(T), err
	}
	defer cursor.Close()
	return cursorResult(cursor)
}

// FetchAll returns all the results from running the PreparedFetch with the
// give params.
func (preparedFetch *PreparedFetch[T]) FetchAll(params Params) ([]T, error) {
	cursor, err := preparedFetch.fetchCursor(context.Background(), params, 1)
	if err != nil {
		return nil, err
	}
	defer cursor.Close()
	return cursorResults(cursor)
}

// FetchAllContext is like FetchAll but additionally requires a context.Context.
func (preparedFetch *PreparedFetch[T]) FetchAllContext(ctx context.Context, params Params) ([]T, error) {
	cursor, err := preparedFetch.fetchCursor(ctx, params, 1)
	if err != nil {
		return nil, err
	}
	defer cursor.Close()
	return cursorResults(cursor)
}

// GetCompiled returns a copy of the underlying CompiledFetch.
func (preparedFetch *PreparedFetch[T]) GetCompiled() *CompiledFetch[T] {
	compiledFetch := NewCompiledFetch(preparedFetch.compiledFetch.GetSQL())
	compiledFetch.queryIsStatic = preparedFetch.compiledFetch.queryIsStatic
	return compiledFetch
}

// Close closes the PreparedFetch.
func (preparedFetch *PreparedFetch[T]) Close() error {
	if preparedFetch.stmt == nil {
		return nil
	}
	return preparedFetch.stmt.Close()
}

// Exec executes the given Query on the given DB.
func Exec(db DB, query Query) (Result, error) {
	return exec(context.Background(), db, query, 1)
}

// ExecContext is like Exec but additionally requires a context.Context.
func ExecContext(ctx context.Context, db DB, query Query) (Result, error) {
	return exec(ctx, db, query, 1)
}

func exec(ctx context.Context, db DB, query Query, skip int) (result Result, err error) {
	if db == nil {
		return result, fmt.Errorf("db is nil")
	}
	if query == nil {
		return result, fmt.Errorf("query is nil")
	}
	dialect := query.GetDialect()
	if dialect == "" {
		defaultDialect := DefaultDialect.Load()
		if defaultDialect != nil {
			dialect = *defaultDialect
		}
	}
	queryStats := QueryStats{
		Dialect: dialect,
		Params:  make(map[string][]int),
	}

	// Build query.
	buf := bufpool.Get().(*bytes.Buffer)
	buf.Reset()
	defer bufpool.Put(buf)
	err = query.WriteSQL(ctx, dialect, buf, &queryStats.Args, queryStats.Params)
	queryStats.Query = buf.String()
	if err != nil {
		return result, err
	}

	// Setup logger.
	var logSettings LogSettings
	logger, _ := db.(SqLogger)
	if logger == nil {
		logQuery, _ := defaultLogQuery.Load().(func(context.Context, QueryStats))
		if logQuery != nil {
			logSettings, _ := defaultLogSettings.Load().(func(context.Context, *LogSettings))
			logger = &sqLogStruct{
				logSettings: logSettings,
				logQuery:    logQuery,
			}
		}
	}
	if logger != nil {
		logger.SqLogSettings(ctx, &logSettings)
		if logSettings.IncludeCaller {
			queryStats.CallerFile, queryStats.CallerLine, queryStats.CallerFunction = caller(skip + 1)
		}
		defer func() {
			if logSettings.LogAsynchronously {
				go logger.SqLogQuery(ctx, queryStats)
			} else {
				logger.SqLogQuery(ctx, queryStats)
			}
		}()
	}

	// Run query.
	if logSettings.IncludeTime {
		queryStats.StartedAt = time.Now()
	}
	var sqlResult sql.Result
	sqlResult, queryStats.Err = db.ExecContext(ctx, queryStats.Query, queryStats.Args...)
	if logSettings.IncludeTime {
		queryStats.TimeTaken = time.Since(queryStats.StartedAt)
	}
	if queryStats.Err != nil {
		return result, queryStats.Err
	}
	return execResult(sqlResult, &queryStats)
}

// CompiledExec is the result of compiling a Query down into a query string and
// args slice. A CompiledExec can be safely executed in parallel.
type CompiledExec struct {
	dialect string
	query   string
	args    []any
	params  map[string][]int
}

// NewCompiledExec returns a new CompiledExec.
func NewCompiledExec(dialect string, query string, args []any, params map[string][]int) *CompiledExec {
	return &CompiledExec{
		dialect: dialect,
		query:   query,
		args:    args,
		params:  params,
	}
}

// CompileExec returns a new CompiledExec.
func CompileExec(query Query) (*CompiledExec, error) {
	return CompileExecContext(context.Background(), query)
}

// CompileExecContext is like CompileExec but additionally requires a context.Context.
func CompileExecContext(ctx context.Context, query Query) (*CompiledExec, error) {
	if query == nil {
		return nil, fmt.Errorf("query is nil")
	}
	dialect := query.GetDialect()
	if dialect == "" {
		defaultDialect := DefaultDialect.Load()
		if defaultDialect != nil {
			dialect = *defaultDialect
		}
	}
	compiledExec := &CompiledExec{
		dialect: dialect,
		params:  make(map[string][]int),
	}

	// Build query.
	buf := bufpool.Get().(*bytes.Buffer)
	buf.Reset()
	defer bufpool.Put(buf)
	err := query.WriteSQL(ctx, dialect, buf, &compiledExec.args, compiledExec.params)
	compiledExec.query = buf.String()
	if err != nil {
		return nil, err
	}
	return compiledExec, nil
}

// Exec executes the CompiledExec on the given DB with the given params.
func (compiledExec *CompiledExec) Exec(db DB, params Params) (Result, error) {
	return compiledExec.exec(context.Background(), db, params, 1)
}

// ExecContext is like Exec but additionally requires a context.Context.
func (compiledExec *CompiledExec) ExecContext(ctx context.Context, db DB, params Params) (Result, error) {
	return compiledExec.exec(ctx, db, params, 1)
}

func (compiledExec *CompiledExec) exec(ctx context.Context, db DB, params Params, skip int) (result Result, err error) {
	if db == nil {
		return result, fmt.Errorf("db is nil")
	}
	queryStats := QueryStats{
		Dialect: compiledExec.dialect,
		Query:   compiledExec.query,
		Args:    compiledExec.args,
		Params:  compiledExec.params,
	}

	// Setup logger.
	var logSettings LogSettings
	logger, _ := db.(SqLogger)
	if logger == nil {
		logQuery, _ := defaultLogQuery.Load().(func(context.Context, QueryStats))
		if logQuery != nil {
			logSettings, _ := defaultLogSettings.Load().(func(context.Context, *LogSettings))
			logger = &sqLogStruct{
				logSettings: logSettings,
				logQuery:    logQuery,
			}
		}
	}
	if logger != nil {
		logger.SqLogSettings(ctx, &logSettings)
		if logSettings.IncludeCaller {
			queryStats.CallerFile, queryStats.CallerLine, queryStats.CallerFunction = caller(skip + 1)
		}
		defer func() {
			if logSettings.LogAsynchronously {
				go logger.SqLogQuery(ctx, queryStats)
			} else {
				logger.SqLogQuery(ctx, queryStats)
			}
		}()
	}

	// Substitute params.
	queryStats.Args, err = substituteParams(queryStats.Dialect, queryStats.Args, queryStats.Params, params)
	if err != nil {
		return result, err
	}

	// Run query.
	if logSettings.IncludeTime {
		queryStats.StartedAt = time.Now()
	}
	var sqlResult sql.Result
	sqlResult, queryStats.Err = db.ExecContext(ctx, queryStats.Query, queryStats.Args...)
	if logSettings.IncludeTime {
		queryStats.TimeTaken = time.Since(queryStats.StartedAt)
	}
	if queryStats.Err != nil {
		return result, queryStats.Err
	}
	return execResult(sqlResult, &queryStats)
}

// GetSQL returns a copy of the dialect, query, args, params and rowmapper that
// make up the CompiledExec.
func (compiledExec *CompiledExec) GetSQL() (dialect string, query string, args []any, params map[string][]int) {
	dialect = compiledExec.dialect
	query = compiledExec.query
	args = make([]any, len(compiledExec.args))
	params = make(map[string][]int)
	copy(args, compiledExec.args)
	for name, indexes := range compiledExec.params {
		indexes2 := make([]int, len(indexes))
		copy(indexes2, indexes)
		params[name] = indexes2
	}
	return dialect, query, args, params
}

// Prepare creates a PreparedExec from a CompiledExec by preparing it on the
// given DB.
func (compiledExec *CompiledExec) Prepare(db DB) (*PreparedExec, error) {
	return compiledExec.PrepareContext(context.Background(), db)
}

// PrepareContext is like Prepare but additionally requires a context.Context.
func (compiledExec *CompiledExec) PrepareContext(ctx context.Context, db DB) (*PreparedExec, error) {
	var err error
	preparedExec := &PreparedExec{
		compiledExec: NewCompiledExec(compiledExec.GetSQL()),
	}
	preparedExec.stmt, err = db.PrepareContext(ctx, compiledExec.query)
	if err != nil {
		return nil, err
	}
	preparedExec.logger, _ = db.(SqLogger)
	if preparedExec.logger == nil {
		logQuery, _ := defaultLogQuery.Load().(func(context.Context, QueryStats))
		if logQuery != nil {
			logSettings, _ := defaultLogSettings.Load().(func(context.Context, *LogSettings))
			preparedExec.logger = &sqLogStruct{
				logSettings: logSettings,
				logQuery:    logQuery,
			}
		}
	}
	return preparedExec, nil
}

// PrepareExec is the result of preparing a CompiledExec on a DB.
type PreparedExec struct {
	compiledExec *CompiledExec
	stmt         *sql.Stmt
	logger       SqLogger
}

// PrepareExec returns a new PreparedExec.
func PrepareExec(db DB, q Query) (*PreparedExec, error) {
	return PrepareExecContext(context.Background(), db, q)
}

// PrepareExecContext is like PrepareExec but additionally requires a
// context.Context.
func PrepareExecContext(ctx context.Context, db DB, q Query) (*PreparedExec, error) {
	compiledExec, err := CompileExecContext(ctx, q)
	if err != nil {
		return nil, err
	}
	return compiledExec.PrepareContext(ctx, db)
}

// Close closes the PreparedExec.
func (preparedExec *PreparedExec) Close() error {
	if preparedExec.stmt == nil {
		return nil
	}
	return preparedExec.stmt.Close()
}

// Exec executes the PreparedExec with the given params.
func (preparedExec *PreparedExec) Exec(params Params) (Result, error) {
	return preparedExec.exec(context.Background(), params, 1)
}

// ExecContext is like Exec but additionally requires a context.Context.
func (preparedExec *PreparedExec) ExecContext(ctx context.Context, params Params) (Result, error) {
	return preparedExec.exec(ctx, params, 1)
}

func (preparedExec *PreparedExec) exec(ctx context.Context, params Params, skip int) (result Result, err error) {
	queryStats := QueryStats{
		Dialect: preparedExec.compiledExec.dialect,
		Query:   preparedExec.compiledExec.query,
		Args:    preparedExec.compiledExec.args,
		Params:  preparedExec.compiledExec.params,
	}

	// Setup logger.
	var logSettings LogSettings
	if preparedExec.logger != nil {
		preparedExec.logger.SqLogSettings(ctx, &logSettings)
		if logSettings.IncludeCaller {
			queryStats.CallerFile, queryStats.CallerLine, queryStats.CallerFunction = caller(skip + 1)
		}
		defer func() {
			if logSettings.LogAsynchronously {
				go preparedExec.logger.SqLogQuery(ctx, queryStats)
			} else {
				preparedExec.logger.SqLogQuery(ctx, queryStats)
			}
		}()
	}

	// Substitute params.
	queryStats.Args, err = substituteParams(queryStats.Dialect, queryStats.Args, queryStats.Params, params)
	if err != nil {
		return result, err
	}

	// Run query.
	if logSettings.IncludeTime {
		queryStats.StartedAt = time.Now()
	}
	var sqlResult sql.Result
	sqlResult, queryStats.Err = preparedExec.stmt.ExecContext(ctx, queryStats.Args...)
	if logSettings.IncludeTime {
		queryStats.TimeTaken = time.Since(queryStats.StartedAt)
	}
	if queryStats.Err != nil {
		return result, queryStats.Err
	}
	return execResult(sqlResult, &queryStats)
}

func getFieldNames(ctx context.Context, row *Row) []string {
	if len(row.fields) == 0 {
		columns, _ := row.sqlRows.Columns()
		return columns
	}
	buf := bufpool.Get().(*bytes.Buffer)
	buf.Reset()
	defer bufpool.Put(buf)
	var args []any
	fieldNames := make([]string, 0, len(row.fields))
	for _, field := range row.fields {
		if alias := getAlias(field); alias != "" {
			fieldNames = append(fieldNames, alias)
			continue
		}
		buf.Reset()
		args = args[:0]
		err := field.WriteSQL(ctx, row.dialect, buf, &args, nil)
		if err != nil {
			fieldNames = append(fieldNames, "%!(error="+err.Error()+")")
			continue
		}
		fieldName, err := Sprintf(row.dialect, buf.String(), args)
		if err != nil {
			fieldNames = append(fieldNames, "%!(error="+err.Error()+")")
			continue
		}
		fieldNames = append(fieldNames, fieldName)
	}
	return fieldNames
}

func getFieldMappings(dialect string, fields []Field, scanDest []any) string {
	var buf bytes.Buffer
	var args []any
	var b strings.Builder
	for i, field := range fields {
		b.WriteString(fmt.Sprintf("\n %02d. ", i+1))
		buf.Reset()
		args = args[:0]
		err := field.WriteSQL(context.Background(), dialect, &buf, &args, nil)
		if err != nil {
			buf.WriteString("%!(error=" + err.Error() + ")")
			continue
		}
		fieldName, err := Sprintf(dialect, buf.String(), args)
		if err != nil {
			b.WriteString("%!(error=" + err.Error() + ")")
			continue
		}
		b.WriteString(fieldName + " => " + reflect.TypeOf(scanDest[i]).String())
	}
	return b.String()
}

// TODO: inline cursorResult, cursorResults and execResult.

func cursorResult[T any](cursor *Cursor[T]) (result T, err error) {
	for cursor.Next() {
		result, err = cursor.Result()
		if err != nil {
			return result, err
		}
		break
	}
	if cursor.RowCount() == 0 {
		return result, sql.ErrNoRows
	}
	return result, cursor.Close()
}

func cursorResults[T any](cursor *Cursor[T]) (results []T, err error) {
	var result T
	for cursor.Next() {
		result, err = cursor.Result()
		if err != nil {
			return results, err
		}
		results = append(results, result)
	}
	return results, cursor.Close()
}

func execResult(sqlResult sql.Result, queryStats *QueryStats) (Result, error) {
	var err error
	var result Result
	if queryStats.Dialect == DialectSQLite || queryStats.Dialect == DialectMySQL {
		result.LastInsertId, err = sqlResult.LastInsertId()
		if err != nil {
			return result, err
		}
		queryStats.LastInsertId.Valid = true
		queryStats.LastInsertId.Int64 = result.LastInsertId
	}
	result.RowsAffected, err = sqlResult.RowsAffected()
	if err != nil {
		return result, err
	}
	queryStats.RowsAffected.Valid = true
	queryStats.RowsAffected.Int64 = result.RowsAffected
	return result, nil
}

// FetchExists returns a boolean indicating if running the given Query on the
// given DB returned any results.
func FetchExists(db DB, query Query) (exists bool, err error) {
	return fetchExists(context.Background(), db, query, 1)
}

// FetchExistsContext is like FetchExists but additionally requires a
// context.Context.
func FetchExistsContext(ctx context.Context, db DB, query Query) (exists bool, err error) {
	return fetchExists(ctx, db, query, 1)
}

func fetchExists(ctx context.Context, db DB, query Query, skip int) (exists bool, err error) {
	dialect := query.GetDialect()
	if dialect == "" {
		defaultDialect := DefaultDialect.Load()
		if defaultDialect != nil {
			dialect = *defaultDialect
		}
	}
	queryStats := QueryStats{
		Dialect: dialect,
		Params:  make(map[string][]int),
		Exists:  sql.NullBool{Valid: true},
	}

	// Build query.
	buf := bufpool.Get().(*bytes.Buffer)
	buf.Reset()
	defer bufpool.Put(buf)
	if dialect == DialectSQLServer {
		query = Queryf("SELECT CASE WHEN EXISTS ({}) THEN 1 ELSE 0 END", query)
	} else {
		query = Queryf("SELECT EXISTS ({})", query)
	}
	err = query.WriteSQL(ctx, dialect, buf, &queryStats.Args, queryStats.Params)
	queryStats.Query = buf.String()
	if err != nil {
		return false, err
	}

	// Setup logger.
	var logSettings LogSettings
	logger, _ := db.(SqLogger)
	if logger == nil {
		logQuery, _ := defaultLogQuery.Load().(func(context.Context, QueryStats))
		if logQuery != nil {
			logSettings, _ := defaultLogSettings.Load().(func(context.Context, *LogSettings))
			logger = &sqLogStruct{
				logSettings: logSettings,
				logQuery:    logQuery,
			}
		}
	}
	if logger != nil {
		logger.SqLogSettings(ctx, &logSettings)
		if logSettings.IncludeCaller {
			queryStats.CallerFile, queryStats.CallerLine, queryStats.CallerFunction = caller(skip + 1)
		}
		defer func() {
			if logSettings.LogAsynchronously {
				go logger.SqLogQuery(ctx, queryStats)
			} else {
				logger.SqLogQuery(ctx, queryStats)
			}
		}()
	}

	// Run query.
	if logSettings.IncludeTime {
		queryStats.StartedAt = time.Now()
	}
	var sqlRows *sql.Rows
	sqlRows, queryStats.Err = db.QueryContext(ctx, queryStats.Query, queryStats.Args...)
	if logSettings.IncludeTime {
		queryStats.TimeTaken = time.Since(queryStats.StartedAt)
	}
	if queryStats.Err != nil {
		return false, queryStats.Err
	}

	for sqlRows.Next() {
		err = sqlRows.Scan(&exists)
		if err != nil {
			return false, err
		}
		break
	}
	queryStats.Exists.Bool = exists

	if err := sqlRows.Close(); err != nil {
		return exists, err
	}
	if err := sqlRows.Err(); err != nil {
		return exists, err
	}
	return exists, nil
}

// substituteParams will return a new args slice by substituting values from
// the given paramValues. The input args slice is untouched.
func substituteParams(dialect string, args []any, paramIndexes map[string][]int, paramValues map[string]any) ([]any, error) {
	if len(paramValues) == 0 {
		return args, nil
	}
	newArgs := make([]any, len(args))
	copy(newArgs, args)
	var err error
	for name, value := range paramValues {
		indexes := paramIndexes[name]
		for _, index := range indexes {
			switch arg := newArgs[index].(type) {
			case sql.NamedArg:
				arg.Value, err = preprocessValue(dialect, value)
				if err != nil {
					return nil, err
				}
				newArgs[index] = arg
			default:
				value, err = preprocessValue(dialect, value)
				if err != nil {
					return nil, err
				}
				newArgs[index] = value
			}
		}
	}
	return newArgs, nil
}

func caller(skip int) (file string, line int, function string) {
	pc, file, line, _ := runtime.Caller(skip + 1)
	fn := runtime.FuncForPC(pc)
	function = fn.Name()
	return file, line, function
}


================================================
FILE: fetch_exec_test.go
================================================
package sq

import (
	"database/sql"
	"testing"
	"time"

	"github.com/bokwoon95/sq/internal/testutil"
	_ "github.com/mattn/go-sqlite3"
)

var ACTOR = New[struct {
	TableStruct `sq:"actor"`
	ACTOR_ID    NumberField
	FIRST_NAME  StringField
	LAST_NAME   StringField
	LAST_UPDATE TimeField
}]("")

type Actor struct {
	ActorID    int
	FirstName  string
	LastName   string
	LastUpdate time.Time
}

func actorRowMapper(row *Row) Actor {
	var actor Actor
	actorID, _ := row.Value("actor.actor_id").(int64)
	actor.ActorID = int(actorID)
	actor.FirstName = row.StringField(ACTOR.FIRST_NAME)
	actor.LastName = row.StringField(ACTOR.LAST_NAME)
	actor.LastUpdate, _ = row.Value("actor.last_update").(time.Time)
	return actor
}

func actorRowMapperRawSQL(row *Row) Actor {
	result := make(map[string]any)
	values := row.Values()
	for i, column := range row.Columns() {
		result[column] = values[i]
	}
	var actor Actor
	actorID, _ := result["actor_id"].(int64)
	actor.ActorID = int(actorID)
	actor.FirstName, _ = result["first_name"].(string)
	actor.LastName, _ = result["last_name"].(string)
	actor.LastUpdate, _ = result["last_update"].(time.Time)
	return actor
}

func Test_substituteParams(t *testing.T) {
	t.Run("no params provided", func(t *testing.T) {
		t.Parallel()
		args := []any{1, 2, 3}
		params := map[string][]int{"one": {0}, "two": {1}, "three": {2}}
		gotArgs, err := substituteParams("", args, params, nil)
		if err != nil {
			t.Fatal(testutil.Callers(), err)
		}
		wantArgs := []any{1, 2, 3}
		if diff := testutil.Diff(gotArgs, wantArgs); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})

	t.Run("not all params provided", func(t *testing.T) {
		t.Parallel()
		args := []any{1, 2, 3}
		params := map[string][]int{"one": {0}, "two": {1}, "three": {2}}
		paramValues := Params{"one": "One", "two": "Two"}
		gotArgs, err := substituteParams("", args, params, paramValues)
		if err != nil {
			t.Fatal(testutil.Callers(), err)
		}
		wantArgs := []any{"One", "Two", 3}
		if diff := testutil.Diff(gotArgs, wantArgs); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})

	t.Run("params substituted", func(t *testing.T) {
		t.Parallel()
		type Data struct {
			id   int
			name string
		}
		args := []any{
			0,
			sql.Named("one", 1),
			sql.Named("two", 2),
			3,
		}
		params := map[string][]int{
			"zero":  {0},
			"one":   {1},
			"two":   {2},
			"three": {3},
		}
		paramValues := Params{
			"one":   "[one]",
			"two":   "[two]",
			"three": "[three]",
		}
		wantArgs := []any{
			0,
			sql.Named("one", "[one]"),
			sql.Named("two", "[two]"),
			"[three]",
		}
		gotArgs, err := substituteParams("", args, params, paramValues)
		if err != nil {
			t.Fatal(testutil.Callers(), err)
		}
		if diff := testutil.Diff(gotArgs, wantArgs); diff != "" {
			t.Error(testutil.Callers(), diff)
		}
	})
}

func Test_getFieldMappings(t *testing.T) {
	type TestTable struct {
		description       string
		dialect           string
		fields            []Field
		scanDest          []any
		wantFieldMappings string
	}

	var tests = []TestTable{{
		description:       "empty",
		wantFieldMappings: "",
	}, {
		description: "basic",
		fields: []Field{
			Expr("actor_id"),
			Expr("first_name || {} || last_name", " "),
			Expr("last_update"),
		},
		scanDest: []any{
			&sql.NullInt64{},
			&sql.NullString{},
			&sql.NullTime{},
		},
		wantFieldMappings: "" +
			"\n 01. actor_id => *sql.NullInt64" +
			"\n 02. first_name || ' ' || last_name => *sql.NullString" +
			"\n 03. last_update => *sql.NullTime",
	}}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()
			gotFieldMappings := getFieldMappings(tt.dialect, tt.fields, tt.scanDest)
			if diff := testutil.Diff(gotFieldMappings, tt.wantFieldMappings); diff != "" {
				t.Error(testutil.Callers(), diff)
			}
		})
	}
}

func TestFetchExec(t *testing.T) {
	t.Parallel()
	db := newDB(t)

	var referenceActors = []Actor{
		{ActorID: 1, FirstName: "PENELOPE", LastName: "GUINESS", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 2, FirstName: "NICK", LastName: "WAHLBERG", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 3, FirstName: "ED", LastName: "CHASE", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 4, FirstName: "JENNIFER", LastName: "DAVIS", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 5, FirstName: "JOHNNY", LastName: "LOLLOBRIGIDA", LastUpdate: time.Unix(1, 0).UTC()},
	}

	// Exec.
	res, err := Exec(Log(db), SQLite.
		InsertInto(ACTOR).
		ColumnValues(func(col *Column) {
			for _, actor := range referenceActors {
				col.SetInt(ACTOR.ACTOR_ID, actor.ActorID)
				col.SetString(ACTOR.FIRST_NAME, actor.FirstName)
				col.SetString(ACTOR.LAST_NAME, actor.LastName)
				col.SetTime(ACTOR.LAST_UPDATE, actor.LastUpdate)
			}
		}),
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(res.RowsAffected, int64(len(referenceActors))); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}

	// FetchOne.
	actor, err := FetchOne(Log(db), SQLite.
		From(ACTOR).
		Where(ACTOR.ACTOR_ID.EqInt(1)),
		actorRowMapper,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actor, referenceActors[0]); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}

	// FetchOne (Raw SQL).
	actor, err = FetchOne(Log(db),
		SQLite.Queryf("SELECT * FROM actor WHERE actor_id = {}", 1),
		actorRowMapperRawSQL,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actor, referenceActors[0]); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}

	// FetchAll.
	actors, err := FetchAll(VerboseLog(db), SQLite.
		From(ACTOR).
		OrderBy(ACTOR.ACTOR_ID),
		actorRowMapper,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actors, referenceActors); diff != "" {
		t.Fatal(testutil.Callers(), err)
	}

	// FetchAll (RawSQL).
	actors, err = FetchAll(VerboseLog(db),
		SQLite.Queryf("SELECT * FROM actor ORDER BY actor_id"),
		actorRowMapperRawSQL,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actors, referenceActors); diff != "" {
		t.Fatal(testutil.Callers(), err)
	}
}

func TestCompiledFetchExec(t *testing.T) {
	t.Parallel()
	db := newDB(t)
	var referenceActors = []Actor{
		{ActorID: 1, FirstName: "PENELOPE", LastName: "GUINESS", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 2, FirstName: "NICK", LastName: "WAHLBERG", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 3, FirstName: "ED", LastName: "CHASE", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 4, FirstName: "JENNIFER", LastName: "DAVIS", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 5, FirstName: "JOHNNY", LastName: "LOLLOBRIGIDA", LastUpdate: time.Unix(1, 0).UTC()},
	}

	// CompiledExec.
	compiledExec, err := CompileExec(SQLite.
		InsertInto(ACTOR).
		ColumnValues(func(col *Column) {
			col.Set(ACTOR.ACTOR_ID, IntParam("actor_id", 0))
			col.Set(ACTOR.FIRST_NAME, StringParam("first_name", ""))
			col.Set(ACTOR.LAST_NAME, StringParam("last_name", ""))
			col.Set(ACTOR.LAST_UPDATE, TimeParam("last_update", time.Time{}))
		}),
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	for _, actor := range referenceActors {
		_, err = compiledExec.Exec(Log(db), Params{
			"actor_id":    actor.ActorID,
			"first_name":  actor.FirstName,
			"last_name":   actor.LastName,
			"last_update": actor.LastUpdate,
		})
		if err != nil {
			t.Fatal(testutil.Callers(), err)
		}
	}

	// CompiledFetch FetchOne.
	compiledFetch, err := CompileFetch(SQLite.
		From(ACTOR).
		Where(ACTOR.ACTOR_ID.Eq(IntParam("actor_id", 0))),
		actorRowMapper,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	actor, err := compiledFetch.FetchOne(Log(db), Params{"actor_id": 1})
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actor, referenceActors[0]); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}

	// CompiledFetch FetchOne (Raw SQL).
	compiledFetch, err = CompileFetch(
		SQLite.Queryf("SELECT * FROM actor WHERE actor_id = {actor_id}", IntParam("actor_id", 0)),
		actorRowMapperRawSQL,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	actor, err = compiledFetch.FetchOne(Log(db), Params{"actor_id": 1})
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actor, referenceActors[0]); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}

	// CompiledFetch FetchAll.
	compiledFetch, err = CompileFetch(SQLite.
		From(ACTOR).
		OrderBy(ACTOR.ACTOR_ID),
		actorRowMapper,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	actors, err := compiledFetch.FetchAll(VerboseLog(db), nil)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actors, referenceActors); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}

	// CompiledFetch FetchAll (Raw SQL).
	compiledFetch, err = CompileFetch(
		SQLite.Queryf("SELECT * FROM actor ORDER BY actor_id"),
		actorRowMapperRawSQL,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	actors, err = compiledFetch.FetchAll(VerboseLog(db), nil)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actors, referenceActors); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}
}

func TestPreparedFetchExec(t *testing.T) {
	t.Parallel()
	db := newDB(t)

	var referenceActors = []Actor{
		{ActorID: 1, FirstName: "PENELOPE", LastName: "GUINESS", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 2, FirstName: "NICK", LastName: "WAHLBERG", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 3, FirstName: "ED", LastName: "CHASE", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 4, FirstName: "JENNIFER", LastName: "DAVIS", LastUpdate: time.Unix(1, 0).UTC()},
		{ActorID: 5, FirstName: "JOHNNY", LastName: "LOLLOBRIGIDA", LastUpdate: time.Unix(1, 0).UTC()},
	}

	// PreparedExec.
	preparedExec, err := PrepareExec(Log(db), SQLite.
		InsertInto(ACTOR).
		ColumnValues(func(col *Column) {
			col.Set(ACTOR.ACTOR_ID, IntParam("actor_id", 0))
			col.Set(ACTOR.FIRST_NAME, StringParam("first_name", ""))
			col.Set(ACTOR.LAST_NAME, StringParam("last_name", ""))
			col.Set(ACTOR.LAST_UPDATE, TimeParam("last_update", time.Time{}))
		}),
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	for _, actor := range referenceActors {
		_, err = preparedExec.Exec(Params{
			"actor_id":    actor.ActorID,
			"first_name":  actor.FirstName,
			"last_name":   actor.LastName,
			"last_update": actor.LastUpdate,
		})
		if err != nil {
			t.Fatal(testutil.Callers(), err)
		}
	}

	// PreparedFetch FetchOne.
	preparedFetch, err := PrepareFetch(Log(db), SQLite.
		From(ACTOR).
		Where(ACTOR.ACTOR_ID.Eq(IntParam("actor_id", 0))),
		actorRowMapper,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	actor, err := preparedFetch.FetchOne(Params{"actor_id": 1})
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actor, referenceActors[0]); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}

	// PreparedFetch FetchOne (Raw SQL).
	preparedFetch, err = PrepareFetch(
		Log(db),
		SQLite.Queryf("SELECT * FROM actor WHERE actor_id = {actor_id}", IntParam("actor_id", 0)),
		actorRowMapperRawSQL,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	actor, err = preparedFetch.FetchOne(Params{"actor_id": 1})
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actor, referenceActors[0]); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}

	// PreparedFetch FetchAll.
	preparedFetch, err = PrepareFetch(VerboseLog(db), SQLite.
		From(ACTOR).
		OrderBy(ACTOR.ACTOR_ID),
		actorRowMapper,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	actors, err := preparedFetch.FetchAll(nil)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actors, referenceActors); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}

	// PreparedFetch FetchAll (Raw SQL).
	preparedFetch, err = PrepareFetch(
		VerboseLog(db),
		SQLite.Queryf("SELECT * FROM actor ORDER BY actor_id"),
		actorRowMapperRawSQL,
	)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	actors, err = preparedFetch.FetchAll(nil)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	if diff := testutil.Diff(actors, referenceActors); diff != "" {
		t.Fatal(testutil.Callers(), diff)
	}
}

func newDB(t *testing.T) *sql.DB {
	db, err := sql.Open("sqlite3", ":memory:")
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	_, err = db.Exec(`CREATE TABLE actor (
    actor_id INTEGER PRIMARY KEY AUTOINCREMENT
    ,first_name TEXT NOT NULL
    ,last_name TEXT NOT NULL
    ,last_update DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
)`)
	if err != nil {
		t.Fatal(testutil.Callers(), err)
	}
	return db
}


================================================
FILE: fields.go
================================================
package sq

import (
	"bytes"
	"context"
	"database/sql"
	"database/sql/driver"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// Identifier represents an SQL identifier. If necessary, it will be quoted
// according to the dialect.
type Identifier string

var _ Field = (*Identifier)(nil)

// WriteSQL implements the SQLWriter interface.
func (id Identifier) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	buf.WriteString(QuoteIdentifier(dialect, string(id)))
	return nil
}

// IsField implements the Field interface.
func (id Identifier) IsField() {}

// AnyField is a catch-all field type that satisfies the Any interface.
type AnyField struct {
	table      TableStruct
	name       string
	alias      string
	desc       sql.NullBool
	nullsfirst sql.NullBool
}

var _ interface {
	Field
	Any
	WithPrefix(string) Field
} = (*AnyField)(nil)

// NewAnyField returns a new AnyField.
func NewAnyField(name string, tbl TableStruct) AnyField {
	return AnyField{table: tbl, name: name}
}

// WriteSQL implements the SQLWriter interface.
func (field AnyField) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	writeFieldIdentifier(ctx, dialect, buf, args, params, field.table, field.name)
	writeFieldOrder(ctx, dialect, buf, args, params, field.desc, field.nullsfirst)
	return nil
}

// As returns a new AnyField with the given alias.
func (field AnyField) As(alias string) AnyField {
	field.alias = alias
	return field
}

// Asc returns a new AnyField indicating that it should be ordered in ascending
// order i.e. 'ORDER BY field ASC'.
func (field AnyField) Asc() AnyField {
	field.desc.Valid = true
	field.desc.Bool = false
	return field
}

// Desc returns a new AnyField indicating that it should be ordered in descending
// order i.e. 'ORDER BY field DESC'.
func (field AnyField) Desc() AnyField {
	field.desc.Valid = true
	field.desc.Bool = true
	return field
}

// NullsLast returns a new NumberField indicating that it should be ordered
// with nulls last i.e. 'ORDER BY field NULLS LAST'.
func (field AnyField) NullsLast() AnyField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = false
	return field
}

// NullsFirst returns a new NumberField indicating that it should be ordered
// with nulls first i.e. 'ORDER BY field NULLS FIRST'.
func (field AnyField) NullsFirst() AnyField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = true
	return field
}

// WithPrefix returns a new Field that with the given prefix.
func (field AnyField) WithPrefix(prefix string) Field {
	field.table.alias = ""
	field.table.name = prefix
	return field
}

// IsNull returns a 'field IS NULL' Predicate.
func (field AnyField) IsNull() Predicate { return Expr("{} IS NULL", field) }

// IsNotNull returns a 'field IS NOT NULL' Predicate.
func (field AnyField) IsNotNull() Predicate { return Expr("{} IS NOT NULL", field) }

// In returns a 'field IN (value)' Predicate. The value can be a slice, which
// corresponds to the expression 'field IN (x, y, z)'.
func (field AnyField) In(value any) Predicate { return In(field, value) }

// In returns a 'field NOT IN (value)' Predicate. The value can be a slice, which
// corresponds to the expression 'field NOT IN (x, y, z)'.
func (field AnyField) NotIn(value any) Predicate { return NotIn(field, value) }

// Eq returns a 'field = value' Predicate.
func (field AnyField) Eq(value any) Predicate { return Eq(field, value) }

// Ne returns a 'field <> value' Predicate.
func (field AnyField) Ne(value any) Predicate { return Ne(field, value) }

// Lt returns a 'field < value' Predicate.
func (field AnyField) Lt(value any) Predicate { return Lt(field, value) }

// Le returns a 'field <= value' Predicate.
func (field AnyField) Le(value any) Predicate { return Le(field, value) }

// Gt returns a 'field > value' Predicate.
func (field AnyField) Gt(value any) Predicate { return Gt(field, value) }

// Ge returns a 'field >= value' Predicate.
func (field AnyField) Ge(value any) Predicate { return Ge(field, value) }

// Expr returns an expression where the field is prepended to the front of the
// expression.
func (field AnyField) Expr(format string, values ...any) Expression {
	values = append(values, field)
	ordinal := len(values)
	return Expr("{"+strconv.Itoa(ordinal)+"} "+format, values...)
}

// Set returns an Assignment assigning the value to the field.
func (field AnyField) Set(value any) Assignment {
	return Set(field, value)
}

// Setf returns an Assignment assigning an expression to the field.
func (field AnyField) Setf(format string, values ...any) Assignment {
	return Setf(field, format, values...)
}

// GetAlias returns the alias of the AnyField.
func (field AnyField) GetAlias() string { return field.alias }

// IsField implements the Field interface.
func (field AnyField) IsField() {}

// IsArray implements the Array interface.
func (field AnyField) IsArray() {}

// IsBinary implements the Binary interface.
func (field AnyField) IsBinary() {}

// IsBoolean implements the Boolean interface.
func (field AnyField) IsBoolean() {}

// IsEnum implements the Enum interface.
func (field AnyField) IsEnum() {}

// IsJSON implements the JSONValue interface.
func (field AnyField) IsJSON() {}

// IsNumber implements the Number interface.
func (field AnyField) IsNumber() {}

// IsString implements the String interface.
func (field AnyField) IsString() {}

// IsTime implements the Time interface.
func (field AnyField) IsTime() {}

// IsUUIDType implements the UUID interface.
func (field AnyField) IsUUID() {}

// ArrayField represents an SQL array field.
type ArrayField struct {
	table TableStruct
	name  string
	alias string
}

var _ interface {
	Field
	Array
	WithPrefix(string) Field
} = (*ArrayField)(nil)

// NewArrayField returns a new ArrayField.
func NewArrayField(fieldName string, tableName TableStruct) ArrayField {
	return ArrayField{table: tableName, name: fieldName}
}

// WriteSQL implements the SQLWriter interface.
func (field ArrayField) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	writeFieldIdentifier(ctx, dialect, buf, args, params, field.table, field.name)
	return nil
}

// As returns a new ArrayField with the given alias.
func (field ArrayField) As(alias string) ArrayField {
	field.alias = alias
	return field
}

// WithPrefix returns a new Field that with the given prefix.
func (field ArrayField) WithPrefix(prefix string) Field {
	field.table.alias = ""
	field.table.name = prefix
	return field
}

// IsNull returns a 'field IS NULL' Predicate.
func (field ArrayField) IsNull() Predicate { return Expr("{} IS NULL", field) }

// IsNull returns a 'field IS NOT NULL' Predicate.
func (field ArrayField) IsNotNull() Predicate { return Expr("{} IS NOT NULL", field) }

// Set returns an Assignment assigning the value to the field.
func (field ArrayField) Set(value any) Assignment {
	switch value.(type) {
	case SQLWriter:
		return Set(field, value)
	case []string, []int, []int64, []int32, []float64, []float32, []bool:
		return Set(field, ArrayValue(value))
	}
	return Set(field, value)
}

// SetArray returns an Assignment assigning the value to the field. It wraps
// the value with ArrayValue().
func (field ArrayField) SetArray(value any) Assignment {
	return Set(field, ArrayValue(value))
}

// Setf returns an Assignment assigning an expression to the field.
func (field ArrayField) Setf(format string, values ...any) Assignment {
	return Set(field, Expr(format, values...))
}

// GetAlias returns the alias of the ArrayField.
func (field ArrayField) GetAlias() string { return field.alias }

// IsField implements the Field interface.
func (field ArrayField) IsField() {}

// IsArray implements the Array interface.
func (field ArrayField) IsArray() {}

// BinaryField represents an SQL binary field.
type BinaryField struct {
	table      TableStruct
	name       string
	alias      string
	desc       sql.NullBool
	nullsfirst sql.NullBool
}

var _ interface {
	Field
	Binary
	WithPrefix(string) Field
} = (*BinaryField)(nil)

// NewBinaryField returns a new BinaryField.
func NewBinaryField(fieldName string, tableName TableStruct) BinaryField {
	return BinaryField{table: tableName, name: fieldName}
}

// WriteSQL implements the SQLWriter interface.
func (field BinaryField) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	writeFieldIdentifier(ctx, dialect, buf, args, params, field.table, field.name)
	writeFieldOrder(ctx, dialect, buf, args, params, field.desc, field.nullsfirst)
	return nil
}

// As returns a new BinaryField with the given alias.
func (field BinaryField) As(alias string) BinaryField {
	field.alias = alias
	return field
}

// Asc returns a new BinaryField indicating that it should be ordered in ascending
// order i.e. 'ORDER BY field ASC'.
func (field BinaryField) Asc() BinaryField {
	field.desc.Valid = true
	field.desc.Bool = false
	return field
}

// Desc returns a new BinaryField indicating that it should be ordered in ascending
// order i.e. 'ORDER BY field DESC'.
func (field BinaryField) Desc() BinaryField {
	field.desc.Valid = true
	field.desc.Bool = true
	return field
}

// NullsLast returns a new BinaryField indicating that it should be ordered
// with nulls last i.e. 'ORDER BY field NULLS LAST'.
func (field BinaryField) NullsLast() BinaryField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = false
	return field
}

// NullsFirst returns a new BinaryField indicating that it should be ordered
// with nulls first i.e. 'ORDER BY field NULLS FIRST'.
func (field BinaryField) NullsFirst() BinaryField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = true
	return field
}

// WithPrefix returns a new Field that with the given prefix.
func (field BinaryField) WithPrefix(prefix string) Field {
	field.table.alias = ""
	field.table.name = prefix
	return field
}

// IsNull returns a 'field IS NULL' Predicate.
func (field BinaryField) IsNull() Predicate { return Expr("{} IS NULL", field) }

// IsNotNull returns a 'field IS NOT NULL' Predicate.
func (field BinaryField) IsNotNull() Predicate { return Expr("{} IS NOT NULL", field) }

// Eq returns a 'field = value' Predicate.
func (field BinaryField) Eq(value Binary) Predicate { return Eq(field, value) }

// Ne returns a 'field <> value' Predicate.
func (field BinaryField) Ne(value Binary) Predicate { return Ne(field, value) }

// EqBytes returns a 'field = b' Predicate.
func (field BinaryField) EqBytes(b []byte) Predicate { return Eq(field, b) }

// NeBytes returns a 'field <> b' Predicate.
func (field BinaryField) NeBytes(b []byte) Predicate { return Ne(field, b) }

// Set returns an Assignment assigning the value to the field.
func (field BinaryField) Set(value any) Assignment {
	return Set(field, value)
}

// Setf returns an Assignment assigning an expression to the field.
func (field BinaryField) Setf(format string, values ...any) Assignment {
	return Setf(field, format, values...)
}

// SetBytes returns an Assignment assigning a []byte to the field.
func (field BinaryField) SetBytes(b []byte) Assignment { return Set(field, b) }

// GetAlias returns the alias of the BinaryField.
func (field BinaryField) GetAlias() string { return field.alias }

// IsField implements the Field interface.
func (field BinaryField) IsField() {}

// IsBinary implements the Binary interface.
func (field BinaryField) IsBinary() {}

// BooleanField represents an SQL boolean field.
type BooleanField struct {
	table      TableStruct
	name       string
	alias      string
	desc       sql.NullBool
	nullsfirst sql.NullBool
}

var _ interface {
	Field
	Boolean
	Predicate
	WithPrefix(string) Field
} = (*BooleanField)(nil)

// NewBooleanField returns a new BooleanField.
func NewBooleanField(fieldName string, tableName TableStruct) BooleanField {
	return BooleanField{table: tableName, name: fieldName}
}

// WriteSQL implements the SQLWriter interface.
func (field BooleanField) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	writeFieldIdentifier(ctx, dialect, buf, args, params, field.table, field.name)
	writeFieldOrder(ctx, dialect, buf, args, params, field.desc, field.nullsfirst)
	return nil
}

// As returns a new BooleanField with the given alias.
func (field BooleanField) As(alias string) BooleanField {
	field.alias = alias
	return field
}

// Asc returns a new BooleanField indicating that it should be ordered in ascending
// order i.e. 'ORDER BY field ASC'.
func (field BooleanField) Asc() BooleanField {
	field.desc.Valid = true
	field.desc.Bool = false
	return field
}

// Desc returns a new BooleanField indicating that it should be ordered in
// descending order i.e. 'ORDER BY field DESC'.
func (f BooleanField) Desc() BooleanField {
	f.desc.Valid = true
	f.desc.Bool = true
	return f
}

// NullsLast returns a new BooleanField indicating that it should be ordered
// with nulls last i.e. 'ORDER BY field NULLS LAST'.
func (field BooleanField) NullsLast() BooleanField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = false
	return field
}

// NullsFirst returns a new BooleanField indicating that it should be ordered
// with nulls first i.e. 'ORDER BY field NULLS FIRST'.
func (field BooleanField) NullsFirst() BooleanField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = true
	return field
}

// WithPrefix returns a new Field that with the given prefix.
func (field BooleanField) WithPrefix(prefix string) Field {
	field.table.alias = ""
	field.table.name = prefix
	return field
}

// IsNull returns a 'field IS NULL' Predicate.
func (field BooleanField) IsNull() Predicate { return Expr("{} IS NULL", field) }

// IsNotNull returns a 'field IS NOT NULL' Predicate.
func (field BooleanField) IsNotNull() Predicate { return Expr("{} IS NOT NULL", field) }

// Eq returns a 'field = value' Predicate.
func (field BooleanField) Eq(value Boolean) Predicate { return Eq(field, value) }

// Ne returns a 'field <> value' Predicate.
func (field BooleanField) Ne(value Boolean) Predicate { return Ne(field, value) }

// EqBool returns a 'field = b' Predicate.
func (field BooleanField) EqBool(b bool) Predicate { return Eq(field, b) }

// NeBool returns a 'field <> b' Predicate.
func (field BooleanField) NeBool(b bool) Predicate { return Ne(field, b) }

// Set returns an Assignment assigning the value to the field.
func (field BooleanField) Set(value any) Assignment {
	return Set(field, value)
}

// Setf returns an Assignment assigning an expression to the field.
func (field BooleanField) Setf(format string, values ...any) Assignment {
	return Setf(field, format, values...)
}

// SetBool returns an Assignment assigning a bool to the field i.e. 'field =
// b'.
func (field BooleanField) SetBool(b bool) Assignment { return Set(field, b) }

// GetAlias returns the alias of the BooleanField.
func (field BooleanField) GetAlias() string { return field.alias }

// IsField implements the Field interface.
func (field BooleanField) IsField() {}

// IsBoolean implements the Boolean interface.
func (field BooleanField) IsBoolean() {}

// EnumField represents an SQL enum field.
type EnumField struct {
	table TableStruct
	name  string
	alias string
}

var _ interface {
	Field
	Enum
	WithPrefix(string) Field
} = (*EnumField)(nil)

// NewEnumField returns a new EnumField.
func NewEnumField(name string, tbl TableStruct) EnumField {
	return EnumField{table: tbl, name: name}
}

// WriteSQL implements the SQLWriter interface.
func (field EnumField) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	writeFieldIdentifier(ctx, dialect, buf, args, params, field.table, field.name)
	return nil
}

// As returns a new EnumField with the given alias.
func (field EnumField) As(alias string) EnumField {
	field.alias = alias
	return field
}

// WithPrefix returns a new Field that with the given prefix.
func (field EnumField) WithPrefix(prefix string) Field {
	field.table.alias = ""
	field.table.name = prefix
	return field
}

// IsNull returns a 'field IS NULL' Predicate.
func (field EnumField) IsNull() Predicate { return Expr("{} IS NULL", field) }

// IsNotNull returns a 'field IS NOT NULL' Predicate.
func (field EnumField) IsNotNull() Predicate { return Expr("{} IS NOT NULL", field) }

// In returns a 'field IN (value)' Predicate. The value can be a slice, which
// corresponds to the expression 'field IN (x, y, z)'.
func (field EnumField) In(value any) Predicate { return In(field, value) }

// NotIn returns a 'field NOT IN (value)' Predicate. The value can be a slice, which
// corresponds to the expression 'field NOT IN (x, y, z)'.
func (field EnumField) NotIn(value any) Predicate { return NotIn(field, value) }

// Eq returns a 'field = value' Predicate.
func (field EnumField) Eq(value any) Predicate { return Eq(field, value) }

// Ne returns a 'field <> value' Predicate.
func (field EnumField) Ne(value any) Predicate { return Ne(field, value) }

// EqEnum returns a 'field = value' Predicate. It wraps the value with
// EnumValue().
func (field EnumField) EqEnum(value Enumeration) Predicate { return Eq(field, EnumValue(value)) }

// NeEnum returns a 'field <> value' Predicate. it wraps the value with
// EnumValue().
func (field EnumField) NeEnum(value Enumeration) Predicate { return Ne(field, EnumValue(value)) }

// Set returns an Assignment assigning the value to the field.
func (field EnumField) Set(value any) Assignment {
	return Set(field, value)
}

// SetEnum returns an Assignment assigning the value to the field. It wraps the
// value with EnumValue().
func (field EnumField) SetEnum(value Enumeration) Assignment {
	return Set(field, EnumValue(value))
}

// Setf returns an Assignment assigning an expression to the field.
func (field EnumField) Setf(format string, values ...any) Assignment {
	return Setf(field, format, values...)
}

// GetAlias returns the alias of the EnumField.
func (field EnumField) GetAlias() string { return field.alias }

// IsField implements the Field interface.
func (field EnumField) IsField() {}

// IsEnum implements the Enum interface.
func (field EnumField) IsEnum() {}

// JSONField represents an SQL JSON field.
type JSONField struct {
	table TableStruct
	name  string
	alias string
}

var _ interface {
	Field
	Binary
	JSON
	String
	WithPrefix(string) Field
} = (*JSONField)(nil)

// NewJSONField returns a new JSONField.
func NewJSONField(name string, tbl TableStruct) JSONField {
	return JSONField{table: tbl, name: name}
}

// WriteSQL implements the SQLWriter interface.
func (field JSONField) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	writeFieldIdentifier(ctx, dialect, buf, args, params, field.table, field.name)
	return nil
}

// As returns a new JSONField with the given alias.
func (field JSONField) As(alias string) JSONField {
	field.alias = alias
	return field
}

// WithPrefix returns a new Field that with the given prefix.
func (field JSONField) WithPrefix(prefix string) Field {
	field.table.alias = ""
	field.table.name = prefix
	return field
}

// IsNull returns a 'field IS NULL' Predicate.
func (field JSONField) IsNull() Predicate { return Expr("{} IS NULL", field) }

// IsNotNull returns a 'field IS NOT NULL' Predicate.
func (field JSONField) IsNotNull() Predicate { return Expr("{} IS NOT NULL", field) }

// Set returns an Assignment assigning the value to the field.
func (field JSONField) Set(value any) Assignment {
	switch value.(type) {
	case []byte, driver.Valuer, SQLWriter:
		return Set(field, value)
	}
	switch reflect.TypeOf(value).Kind() {
	case reflect.Map, reflect.Struct, reflect.Slice, reflect.Array:
		return Set(field, JSONValue(value))
	}
	return Set(field, value)
}

// SetJSON returns an Assignment assigning the value to the field. It wraps the
// value in JSONValue().
func (field JSONField) SetJSON(value any) Assignment {
	return Set(field, JSONValue(value))
}

// Setf returns an Assignment assigning an expression to the field.
func (field JSONField) Setf(format string, values ...any) Assignment {
	return Setf(field, format, values...)
}

// GetAlias returns the alias of the JSONField.
func (field JSONField) GetAlias() string { return field.alias }

// IsField implements the Field interface.
func (field JSONField) IsField() {}

// IsBinary implements the Binary interface.
func (field JSONField) IsBinary() {}

// IsJSON implements the JSON interface.
func (field JSONField) IsJSON() {}

// IsString implements the String interface.
func (field JSONField) IsString() {}

// NumberField represents an SQL number field.
type NumberField struct {
	table      TableStruct
	name       string
	alias      string
	desc       sql.NullBool
	nullsfirst sql.NullBool
}

var _ interface {
	Field
	Number
	WithPrefix(string) Field
} = (*NumberField)(nil)

// NewNumberField returns a new NumberField.
func NewNumberField(name string, tbl TableStruct) NumberField {
	return NumberField{table: tbl, name: name}
}

// WriteSQL implements the SQLWriter interface.
func (field NumberField) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	writeFieldIdentifier(ctx, dialect, buf, args, params, field.table, field.name)
	writeFieldOrder(ctx, dialect, buf, args, params, field.desc, field.nullsfirst)
	return nil
}

// As returns a new NumberField with the given alias.
func (field NumberField) As(alias string) NumberField {
	field.alias = alias
	return field
}

// Asc returns a new NumberField indicating that it should be ordered in ascending
// order i.e. 'ORDER BY field ASC'.
func (field NumberField) Asc() NumberField {
	field.desc.Valid = true
	field.desc.Bool = false
	return field
}

// Desc returns a new NumberField indicating that it should be ordered in ascending
// order i.e. 'ORDER BY field DESC'.
func (field NumberField) Desc() NumberField {
	field.desc.Valid = true
	field.desc.Bool = true
	return field
}

// NullsLast returns a new NumberField indicating that it should be ordered
// with nulls last i.e. 'ORDER BY field NULLS LAST'.
func (field NumberField) NullsLast() NumberField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = false
	return field
}

// NullsFirst returns a new NumberField indicating that it should be ordered
// with nulls first i.e. 'ORDER BY field NULLS FIRST'.
func (field NumberField) NullsFirst() NumberField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = true
	return field
}

// WithPrefix returns a new Field that with the given prefix.
func (field NumberField) WithPrefix(prefix string) Field {
	field.table.alias = ""
	field.table.name = prefix
	return field
}

// IsNull returns a 'field IS NULL' Predicate.
func (field NumberField) IsNull() Predicate { return Expr("{} IS NULL", field) }

// IsNotNull returns a 'field IS NOT NULL' Predicate.
func (field NumberField) IsNotNull() Predicate { return Expr("{} IS NOT NULL", field) }

// In returns a 'field IN (value)' Predicate. The value can be a slice, which
// corresponds to the expression 'field IN (x, y, z)'.
func (field NumberField) In(value any) Predicate { return In(field, value) }

// NotIn returns a 'field NOT IN (value)' Predicate. The value can be a slice,
// which corresponds to the expression 'field IN (x, y, z)'.
func (field NumberField) NotIn(value any) Predicate { return NotIn(field, value) }

// Eq returns a 'field = value' Predicate.
func (field NumberField) Eq(value Number) Predicate { return Eq(field, value) }

// Ne returns a 'field <> value' Predicate.
func (field NumberField) Ne(value Number) Predicate { return Ne(field, value) }

// Lt returns a 'field < value' Predicate.
func (field NumberField) Lt(value Number) Predicate { return Lt(field, value) }

// Le returns a 'field <= value' Predicate.
func (field NumberField) Le(value Number) Predicate { return Le(field, value) }

// Gt returns a 'field > value' Predicate.
func (field NumberField) Gt(value Number) Predicate { return Gt(field, value) }

// Ge returns a 'field >= value' Predicate.
func (field NumberField) Ge(value Number) Predicate { return Ge(field, value) }

// EqInt returns a 'field = num' Predicate.
func (field NumberField) EqInt(num int) Predicate { return Eq(field, num) }

// NeInt returns a 'field <> num' Predicate.
func (field NumberField) NeInt(num int) Predicate { return Ne(field, num) }

// LtInt returns a 'field < num' Predicate.
func (field NumberField) LtInt(num int) Predicate { return Lt(field, num) }

// LeInt returns a 'field <= num' Predicate.
func (field NumberField) LeInt(num int) Predicate { return Le(field, num) }

// GtInt returns a 'field > num' Predicate.
func (field NumberField) GtInt(num int) Predicate { return Gt(field, num) }

// GeInt returns a 'field >= num' Predicate.
func (field NumberField) GeInt(num int) Predicate { return Ge(field, num) }

// EqInt64 returns a 'field = num' Predicate.
func (field NumberField) EqInt64(num int64) Predicate { return Eq(field, num) }

// NeInt64 returns a 'field <> num' Predicate.
func (field NumberField) NeInt64(num int64) Predicate { return Ne(field, num) }

// LtInt64 returns a 'field < num' Predicate.
func (field NumberField) LtInt64(num int64) Predicate { return Lt(field, num) }

// LeInt64 returns a 'field <= num' Predicate.
func (field NumberField) LeInt64(num int64) Predicate { return Le(field, num) }

// GtInt64 returns a 'field > num' Predicate.
func (field NumberField) GtInt64(num int64) Predicate { return Gt(field, num) }

// GeInt64 returns a 'field >= num' Predicate.
func (field NumberField) GeInt64(num int64) Predicate { return Ge(field, num) }

// EqFloat64 returns a 'field = num' Predicate.
func (field NumberField) EqFloat64(num float64) Predicate { return Eq(field, num) }

// NeFloat64 returns a 'field <> num' Predicate.
func (field NumberField) NeFloat64(num float64) Predicate { return Ne(field, num) }

// LtFloat64 returns a 'field < num' Predicate.
func (field NumberField) LtFloat64(num float64) Predicate { return Lt(field, num) }

// LeFloat64 returns a 'field <= num' Predicate.
func (field NumberField) LeFloat64(num float64) Predicate { return Le(field, num) }

// GtFloat64 returns a 'field > num' Predicate.
func (field NumberField) GtFloat64(num float64) Predicate { return Gt(field, num) }

// GeFloat64 returns a 'field >= num' Predicate.
func (field NumberField) GeFloat64(num float64) Predicate { return Ge(field, num) }

// Set returns an Assignment assigning the value to the field.
func (field NumberField) Set(value any) Assignment {
	return Set(field, value)
}

// Setf returns an Assignment assigning an expression to the field.
func (field NumberField) Setf(format string, values ...any) Assignment {
	return Setf(field, format, values...)
}

// SetBytes returns an Assignment assigning an int to the field.
func (field NumberField) SetInt(num int) Assignment { return Set(field, num) }

// SetBytes returns an Assignment assigning an int64 to the field.
func (field NumberField) SetInt64(num int64) Assignment { return Set(field, num) }

// SetBytes returns an Assignment assigning an float64 to the field.
func (field NumberField) SetFloat64(num float64) Assignment { return Set(field, num) }

// GetAlias returns the alias of the NumberField.
func (field NumberField) GetAlias() string { return field.alias }

// IsField implements the Field interface.
func (field NumberField) IsField() {}

// IsNumber implements the Number interface.
func (field NumberField) IsNumber() {}

// StringField represents an SQL string field.
type StringField struct {
	table      TableStruct
	name       string
	alias      string
	collation  string
	desc       sql.NullBool
	nullsfirst sql.NullBool
}

var _ interface {
	Field
	String
	WithPrefix(string) Field
} = (*StringField)(nil)

// NewStringField returns a new StringField.
func NewStringField(name string, tbl TableStruct) StringField {
	return StringField{table: tbl, name: name}
}

// WriteSQL implements the SQLWriter interface.
func (field StringField) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	writeFieldIdentifier(ctx, dialect, buf, args, params, field.table, field.name)
	if field.collation != "" {
		buf.WriteString(" COLLATE ")
		if dialect == DialectPostgres {
			buf.WriteString(`"` + EscapeQuote(field.collation, '"') + `"`)
		} else {
			buf.WriteString(QuoteIdentifier(dialect, field.collation))
		}
	}
	writeFieldOrder(ctx, dialect, buf, args, params, field.desc, field.nullsfirst)
	return nil
}

// As returns a new StringField with the given alias.
func (field StringField) As(alias string) StringField {
	field.alias = alias
	return field
}

// Collate returns a new StringField using the given collation.
func (field StringField) Collate(collation string) StringField {
	field.collation = collation
	return field
}

// Asc returns a new StringField indicating that it should be ordered in
// ascending order i.e. 'ORDER BY field ASC'.
func (field StringField) Asc() StringField {
	field.desc.Valid = true
	field.desc.Bool = false
	return field
}

// Desc returns a new StringField indicating that it should be ordered in
// descending order i.e. 'ORDER BY field DESC'.
func (field StringField) Desc() StringField {
	field.desc.Valid = true
	field.desc.Bool = true
	return field
}

// NullsLast returns a new StringField indicating that it should be ordered
// with nulls last i.e. 'ORDER BY field NULLS LAST'.
func (field StringField) NullsLast() StringField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = false
	return field
}

// NullsFirst returns a new StringField indicating that it should be ordered
// with nulls first i.e. 'ORDER BY field NULLS FIRST'.
func (field StringField) NullsFirst() StringField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = true
	return field
}

// WithPrefix returns a new Field that with the given prefix.
func (field StringField) WithPrefix(prefix string) Field {
	field.table.alias = ""
	field.table.name = prefix
	return field
}

// IsNull returns a 'field IS NULL' Predicate.
func (field StringField) IsNull() Predicate { return Expr("{} IS NULL", field) }

// IsNotNull returns a 'field IS NOT NULL' Predicate.
func (field StringField) IsNotNull() Predicate { return Expr("{} IS NOT NULL", field) }

// In returns a 'field IN (value)' Predicate. The value can be a slice, which
// corresponds to the expression 'field IN (x, y, z)'.
func (field StringField) In(value any) Predicate { return In(field, value) }

// In returns a 'field NOT IN (value)' Predicate. The value can be a slice,
// which corresponds to the expression 'field NOT IN (x, y, z)'.
func (field StringField) NotIn(value any) Predicate { return NotIn(field, value) }

// Eq returns a 'field = value' Predicate.
func (field StringField) Eq(value String) Predicate { return Eq(field, value) }

// Ne returns a 'field <> value' Predicate.
func (field StringField) Ne(value String) Predicate { return Ne(field, value) }

// Lt returns a 'field < value' Predicate.
func (field StringField) Lt(value String) Predicate { return Lt(field, value) }

// Le returns a 'field <= value' Predicate.
func (field StringField) Le(value String) Predicate { return Le(field, value) }

// Gt returns a 'field > value' Predicate.
func (field StringField) Gt(value String) Predicate { return Gt(field, value) }

// Ge returns a 'field >= value' Predicate.
func (field StringField) Ge(value String) Predicate { return Ge(field, value) }

// EqString returns a 'field = str' Predicate.
func (field StringField) EqString(str string) Predicate { return Eq(field, str) }

// NeString returns a 'field <> str' Predicate.
func (field StringField) NeString(str string) Predicate { return Ne(field, str) }

// LtString returns a 'field < str' Predicate.
func (field StringField) LtString(str string) Predicate { return Lt(field, str) }

// LeString returns a 'field <= str' Predicate.
func (field StringField) LeString(str string) Predicate { return Le(field, str) }

// GtString returns a 'field > str' Predicate.
func (field StringField) GtString(str string) Predicate { return Gt(field, str) }

// GeString returns a 'field >= str' Predicate.
func (field StringField) GeString(str string) Predicate { return Ge(field, str) }

// LikeString returns a 'field LIKE str' Predicate.
func (field StringField) LikeString(str string) Predicate {
	return Expr("{} LIKE {}", field, str)
}

// NotLikeString returns a 'field NOT LIKE str' Predicate.
func (field StringField) NotLikeString(str string) Predicate {
	return Expr("{} NOT LIKE {}", field, str)
}

// ILikeString returns a 'field ILIKE str' Predicate.
func (field StringField) ILikeString(str string) Predicate {
	return Expr("{} ILIKE {}", field, str)
}

// NotILikeString returns a 'field NOT ILIKE str' Predicate.
func (field StringField) NotILikeString(str string) Predicate {
	return Expr("{} NOT ILIKE {}", field, str)
}

// Set returns an Assignment assigning the value to the field.
func (field StringField) Set(value any) Assignment {
	return Set(field, value)
}

// Setf returns an Assignment assigning an expression to the field.
func (field StringField) Setf(format string, values ...any) Assignment {
	return Setf(field, format, values...)
}

// SetString returns an Assignment assigning a string to the field.
func (field StringField) SetString(str string) Assignment { return Set(field, str) }

// GetAlias returns the alias of the StringField.
func (field StringField) GetAlias() string { return field.alias }

// IsField implements the Field interface.
func (field StringField) IsField() {}

// IsString implements the String interface.
func (field StringField) IsString() {}

// TimeField represents an SQL time field.
type TimeField struct {
	table      TableStruct
	name       string
	alias      string
	desc       sql.NullBool
	nullsfirst sql.NullBool
}

var _ interface {
	Field
	Time
	WithPrefix(string) Field
} = (*TimeField)(nil)

// NewTimeField returns a new TimeField.
func NewTimeField(name string, tbl TableStruct) TimeField {
	return TimeField{table: tbl, name: name}
}

// WriteSQL implements the SQLWriter interface.
func (field TimeField) WriteSQL(ctx context.Context, dialect string, buf *bytes.Buffer, args *[]any, params map[string][]int) error {
	writeFieldIdentifier(ctx, dialect, buf, args, params, field.table, field.name)
	writeFieldOrder(ctx, dialect, buf, args, params, field.desc, field.nullsfirst)
	return nil
}

// As returns a new TimeField with the given alias.
func (field TimeField) As(alias string) TimeField {
	field.alias = alias
	return field
}

// Asc returns a new TimeField indicating that it should be ordered in ascending
// order i.e. 'ORDER BY field ASC'.
func (field TimeField) Asc() TimeField {
	field.desc.Valid = true
	field.desc.Bool = false
	return field
}

// Desc returns a new TimeField indicating that it should be ordered in ascending
// order i.e. 'ORDER BY field DESC'.
func (field TimeField) Desc() TimeField {
	field.desc.Valid = true
	field.desc.Bool = true
	return field
}

// NullsLast returns a new TimeField indicating that it should be ordered
// with nulls last i.e. 'ORDER BY field NULLS LAST'.
func (field TimeField) NullsLast() TimeField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = false
	return field
}

// NullsFirst returns a new TimeField indicating that it should be ordered
// with nulls first i.e. 'ORDER BY field NULLS FIRST'.
func (field TimeField) NullsFirst() TimeField {
	field.nullsfirst.Valid = true
	field.nullsfirst.Bool = true
	return field
}

// WithPrefix returns a new Field that with the given prefix.
func (field TimeField) WithPrefix(prefix string) Field {
	field.table.alias = ""
	field.table.name = prefix
	return field
}

// IsNull returns a 'field IS NULL' Predicate.
func (field TimeField) IsNull() Predicate { return Expr("{} IS NULL", field) }

// IsNotNull returns a 'field IS NOT NULL' Predicate.
func (field TimeField) IsNotNull() Predicate { return Expr("{} IS NOT NULL", field) }

// In returns a 'field IN (value)' Predicate. The value can be a slice, which
// corresponds to the expression 'field IN (x, y, z)'.
func (field TimeField) In(value any) Predicate { return In(field, value) }

// NotIn returns a 'field NOT IN (value)' Predicate. The value can be a slice,
// which corresponds to the expression 'field NOT IN (x, y, z)'.
func (field TimeField) NotIn(value any) Predicate { return NotIn(field, value) }

// Eq returns a 'field = value' Predicate.
func (field TimeField) Eq(value Time) Predicate { return Eq(field, value) }

// Ne returns a 'field <> value' Predicate.
func (field TimeField) Ne(value Time) Predicate { return Ne(field, value) }

// Lt returns a 'field < value' Predicate.
func (field TimeField) Lt(value Time) Predicate { return Lt(field, value) }

// Le returns a 'field <= value' Predicate.
func (field TimeField) Le(value Time) Predicate { return Le(field, value) }

// Gt returns a 'field > value' Predicate.
func (field TimeField) Gt(value Time) Predicate { return Gt(field, value) }

// Ge returns a 'field >= value' Predicate.
func (field TimeField) Ge(value Time) Predicate { return Ge(field, value) }

// EqTime returns a 'field = t' Predicate.
func (field TimeField) EqTime(t time.Time) Predicate { return Eq(field, t) }

// NeTime returns a 'field <> t' Predicate.
func (field TimeField) NeTime(t time.Time) Predicate { return Ne(field, t) }

// LtTime returns a 'field < t' Predicate.
func (field TimeField) LtTime(t time.Time) Predicate { return Lt(field, t) }

// LeTime returns a 'field <= t' Predicate.
func (field TimeField) LeTime(t time.Time) Predicate { return Le(field, t) }

// GtTime returns a 'field > t' Predicate.
func (field TimeField) GtTime(t time.Time) Predicate { return Gt(field, t) }

// GeTime returns a 'field >= t' Predicate.
func (field TimeField) GeTime(t time.Time) Predicate { return Ge(field, t) }

// Set returns an Assignment assigning the value to the field.
func (field TimeField) Set(value any) Assignment {
	return Set(field, value)
}

// Setf returns an Assignment assigning an expression to the field.
func (field TimeField) Setf(format string, values ...any) Assignment {
	return Setf(field, format, values...)
}

// SetTime returns an Assignment assigning a time.Time to the field.
func (field TimeField) SetTime(t time.Time) Assignment { return Set(field, t) }

// GetAlias returns the alias of the TimeField.
func (field TimeField) GetAlias() string { return field.alias }

// IsField implements the Field interface.
func (field TimeField) IsField() {}

// IsTime implements the Time interface.
func (field TimeField) IsTime() {}

// Timestamp is as a replacement for sql.NullTime but with the following
// enhancements:
//
// 1. Timestamp.Value() returns an int64 unix timestamp if the dialect is
// SQLite, otherwise it returns a time.Time (similar to sql.NullTime).
//
// 2. Timestamp.Scan() additionally supports scanning from int64 and text
// (string/[]byte) values on top of what sql.NullTime already supports. The
// following text timestamp formats are supported:
//
//	var timestampFormats = []string{
//		"2006-01-02 15:04:05.999999999-07:00",
//		"2006-01-02T15:04:05.999999999-07:00",
//		"2006-01-02 15:04:05.999999999",
//		"2006-01-02T15:04:05.999999999",
//		"2006-01-02 15:04:05",
//		"2006-01-02T15:04:05",
//		"2006-01-02 15:04",
//		"2006-01-02T15:04",
//		"2006-01-02",
//	}
type Timestamp struct {
	time.Time
	Valid   bool
	dialect string
}

// NewTimestamp creates a new Timestamp from a time.Time.
func NewTimestamp(t time.Time) Timestamp {
	return Timestamp{Time: t, Valid: true}
}

// copied from https://pkg.go.dev/github.com/mattn/go-sqlite3#pkg-variables
var timestampFormats = []string{
	"2006-01-02 15:04:05.999999999-07:00",
	"2006-01-02T15:04:05.999999999-07:00",
	"2006-01-02 15:04:05.999999999",
	"2006-01-02T15:04:05.999999999",
	"2006-01-02 15:04:05",
	"2006-01-02T15:04:05",
	"2006-01-02 15:04",
	"2006-01-02T15:04",
	"2006-01-02",
}

// Scan implements the sql.Scanner interface. It additionally supports scanning
// from int64 and text (string/[]byte) values on top of what sql.NullTime
// already supports. The following text timestamp formats are supported:
//
//	var timestampFormats = []string{
//		"2006-01-02 15:04:05.999999999-07:00",
//		"2006-01-02T15:04:05.999999999-07:00",
//		"2006-01-02 15:04:05.999999999",
//		"2006-01-02T15:04:05.999999999",
//		"2006-01-02 15:04:05",
//		"2006-01-02T15:04:05",
//		"2006-01-02 15:04",
//		"2006-01-02T15:04",
//		"2006-01-02",
//	}
func (ts *Timestamp) Scan(value any) error {
	if value == nil {
		ts.Time, ts.Valid = time.Time{}, false
		return nil
	}
	// int64 and string handling copied from
	// https://github.com/mattn/go-sqlite3/issues/748#issuecomment-538643131
	switch value := value.(type) {
	case int64:
		// Assume a millisecond unix timestamp if it's 13 digits -- too
		// large to be a reasonable timestamp in seconds.
		if value > 1e12 || value < -1e12 {
			value *= int64(time.Millisecond) // convert ms to nsec
			ts.Time = time.Unix(0, value)
		} else {
			ts.Time = time.Unix(value, 0)
		}
		ts.Valid = true
		return nil
	case string:
		if len(value) == 0 {
			ts.Time, ts.Valid = time.Time{}, false
			return nil
		}
		var err error
		var timeVal time.Time
		value = strings.TrimSuffix(value, "Z")
		for _, format := range times
Download .txt
gitextract_lej4qbg4/

├── .github/
│   ├── mddocs
│   └── workflows/
│       ├── neocities.yml
│       └── tests.yml
├── .gitignore
├── LICENSE
├── README.md
├── START_HERE.md
├── builtins.go
├── builtins_test.go
├── colors.go
├── cte.go
├── cte_test.go
├── delete_query.go
├── delete_query_test.go
├── fetch_exec.go
├── fetch_exec_test.go
├── fields.go
├── fields_test.go
├── fmt.go
├── fmt_test.go
├── go.mod
├── go.sum
├── insert_query.go
├── insert_query_test.go
├── integration_test.go
├── internal/
│   ├── googleuuid/
│   │   └── googleuuid.go
│   ├── pqarray/
│   │   └── pqarray.go
│   └── testutil/
│       └── testutil.go
├── joins.go
├── joins_test.go
├── logger.go
├── logger_test.go
├── misc.go
├── misc_test.go
├── row_column.go
├── select_query.go
├── select_query_test.go
├── sq.go
├── sq.md
├── sq_test.go
├── update_query.go
├── update_query_test.go
├── window.go
└── window_test.go
Download .txt
SYMBOL INDEX (1594 symbols across 34 files)

FILE: builtins.go
  type Expression (line 12) | type Expression struct
    method WriteSQL (line 32) | func (expr Expression) WriteSQL(ctx context.Context, dialect string, b...
    method As (line 41) | func (expr Expression) As(alias string) Expression {
    method In (line 47) | func (expr Expression) In(value any) Predicate { return In(expr, value) }
    method NotIn (line 50) | func (expr Expression) NotIn(value any) Predicate { return NotIn(expr,...
    method Eq (line 53) | func (expr Expression) Eq(value any) Predicate { return cmp("=", expr,...
    method Ne (line 56) | func (expr Expression) Ne(value any) Predicate { return cmp("<>", expr...
    method Lt (line 59) | func (expr Expression) Lt(value any) Predicate { return cmp("<", expr,...
    method Le (line 62) | func (expr Expression) Le(value any) Predicate { return cmp("<=", expr...
    method Gt (line 65) | func (expr Expression) Gt(value any) Predicate { return cmp(">", expr,...
    method Ge (line 68) | func (expr Expression) Ge(value any) Predicate { return cmp(">=", expr...
    method GetAlias (line 71) | func (expr Expression) GetAlias() string { return expr.alias }
    method IsTable (line 74) | func (expr Expression) IsTable() {}
    method IsField (line 77) | func (expr Expression) IsField() {}
    method IsArray (line 80) | func (expr Expression) IsArray() {}
    method IsBinary (line 83) | func (expr Expression) IsBinary() {}
    method IsBoolean (line 86) | func (expr Expression) IsBoolean() {}
    method IsEnum (line 89) | func (expr Expression) IsEnum() {}
    method IsJSON (line 92) | func (expr Expression) IsJSON() {}
    method IsNumber (line 95) | func (expr Expression) IsNumber() {}
    method IsString (line 98) | func (expr Expression) IsString() {}
    method IsTime (line 101) | func (expr Expression) IsTime() {}
    method IsUUID (line 104) | func (expr Expression) IsUUID() {}
    method IsAssignment (line 106) | func (e Expression) IsAssignment() {}
  function Expr (line 27) | func Expr(format string, values ...any) Expression {
  type CustomQuery (line 109) | type CustomQuery struct
    method Append (line 145) | func (q CustomQuery) Append(format string, values ...any) CustomQuery {
    method WriteSQL (line 152) | func (q CustomQuery) WriteSQL(ctx context.Context, dialect string, buf...
    method SetFetchableFields (line 188) | func (q CustomQuery) SetFetchableFields(fields []Field) (query Query, ...
    method GetFetchableFields (line 205) | func (q CustomQuery) GetFetchableFields() []Field {
    method GetDialect (line 210) | func (q CustomQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 213) | func (q CustomQuery) SetDialect(dialect string) CustomQuery {
  function Queryf (line 119) | func Queryf(format string, values ...any) CustomQuery {
  type VariadicPredicate (line 220) | type VariadicPredicate struct
    method WriteSQL (line 245) | func (p VariadicPredicate) WriteSQL(ctx context.Context, dialect strin...
    method As (line 304) | func (p VariadicPredicate) As(alias string) VariadicPredicate {
    method GetAlias (line 310) | func (p VariadicPredicate) GetAlias() string { return p.alias }
    method IsField (line 313) | func (p VariadicPredicate) IsField() {}
    method IsBoolean (line 316) | func (p VariadicPredicate) IsBoolean() {}
  function And (line 235) | func And(predicates ...Predicate) VariadicPredicate {
  function Or (line 240) | func Or(predicates ...Predicate) VariadicPredicate {
  type assignment (line 319) | type assignment struct
    method WriteSQL (line 337) | func (a assignment) WriteSQL(ctx context.Context, dialect string, buf ...
    method IsAssignment (line 369) | func (a assignment) IsAssignment() {}
  function Set (line 327) | func Set(field Field, value any) Assignment {
  function Setf (line 332) | func Setf(field Field, format string, values ...any) Assignment {
  type Assignments (line 372) | type Assignments
    method WriteSQL (line 375) | func (as Assignments) WriteSQL(ctx context.Context, dialect string, bu...
  type RowValue (line 393) | type RowValue
    method WriteSQL (line 396) | func (r RowValue) WriteSQL(ctx context.Context, dialect string, buf *b...
    method In (line 420) | func (r RowValue) In(v any) Predicate { return In(r, v) }
    method NotIn (line 423) | func (r RowValue) NotIn(v any) Predicate { return NotIn(r, v) }
    method Eq (line 426) | func (r RowValue) Eq(v any) Predicate { return cmp("=", r, v) }
  type RowValues (line 429) | type RowValues
    method WriteSQL (line 432) | func (rs RowValues) WriteSQL(ctx context.Context, dialect string, buf ...
  type Fields (line 447) | type Fields
    method WriteSQL (line 450) | func (fs Fields) WriteSQL(ctx context.Context, dialect string, buf *by...
  type sqliteQueryBuilder (line 475) | type sqliteQueryBuilder struct
    method Queryf (line 124) | func (b sqliteQueryBuilder) Queryf(format string, values ...any) Custo...
    method With (line 490) | func (b sqliteQueryBuilder) With(ctes ...CTE) sqliteQueryBuilder {
  type postgresQueryBuilder (line 476) | type postgresQueryBuilder struct
    method Queryf (line 129) | func (b postgresQueryBuilder) Queryf(format string, values ...any) Cus...
    method With (line 496) | func (b postgresQueryBuilder) With(ctes ...CTE) postgresQueryBuilder {
  type mysqlQueryBuilder (line 477) | type mysqlQueryBuilder struct
    method Queryf (line 134) | func (b mysqlQueryBuilder) Queryf(format string, values ...any) Custom...
    method With (line 502) | func (b mysqlQueryBuilder) With(ctes ...CTE) mysqlQueryBuilder {
  type sqlserverQueryBuilder (line 478) | type sqlserverQueryBuilder struct
    method Queryf (line 139) | func (b sqlserverQueryBuilder) Queryf(format string, values ...any) Cu...
    method With (line 508) | func (b sqlserverQueryBuilder) With(ctes ...CTE) sqlserverQueryBuilder {
  function ToSQL (line 519) | func ToSQL(dialect string, w SQLWriter, params map[string][]int) (query ...
  function ToSQLContext (line 524) | func ToSQLContext(ctx context.Context, dialect string, w SQLWriter, para...
  function Eq (line 545) | func Eq(x, y any) Predicate { return cmp("=", x, y) }
  function Ne (line 548) | func Ne(x, y any) Predicate { return cmp("<>", x, y) }
  function Lt (line 551) | func Lt(x, y any) Predicate { return cmp("<", x, y) }
  function Le (line 554) | func Le(x, y any) Predicate { return cmp("<=", x, y) }
  function Gt (line 557) | func Gt(x, y any) Predicate { return cmp(">", x, y) }
  function Ge (line 560) | func Ge(x, y any) Predicate { return cmp(">=", x, y) }
  function Exists (line 563) | func Exists(query Query) Predicate { return Expr("EXISTS ({})", query) }
  function NotExists (line 566) | func NotExists(query Query) Predicate { return Expr("NOT EXISTS ({})", q...
  function In (line 569) | func In(x, y any) Predicate {
  function NotIn (line 584) | func NotIn(x, y any) Predicate {
  function cmp (line 599) | func cmp(operator string, x, y any) Expression {
  function appendPolicy (line 615) | func appendPolicy(ctx context.Context, dialect string, policies []Predic...
  function appendPredicates (line 631) | func appendPredicates(predicate Predicate, predicates []Predicate) Varia...
  function writeTop (line 645) | func writeTop(ctx context.Context, dialect string, buf *bytes.Buffer, ar...

FILE: builtins_test.go
  function TestExpression (line 13) | func TestExpression(t *testing.T) {
  function TestVariadicPredicate (line 87) | func TestVariadicPredicate(t *testing.T) {
  function TestQueryf (line 209) | func TestQueryf(t *testing.T) {
  function TestAssign (line 291) | func TestAssign(t *testing.T) {
  function TestRowValuesFieldsAssignments (line 348) | func TestRowValuesFieldsAssignments(t *testing.T) {
  function TestToSQL (line 418) | func TestToSQL(t *testing.T) {
  function Test_in_cmp (line 448) | func Test_in_cmp(t *testing.T) {
  type policyTableStub (line 498) | type policyTableStub struct
    method WriteSQL (line 505) | func (tbl policyTableStub) WriteSQL(ctx context.Context, dialect strin...
    method GetAlias (line 510) | func (tbl policyTableStub) GetAlias() string { return "" }
    method Policy (line 512) | func (tbl policyTableStub) Policy(ctx context.Context, dialect string)...
    method IsTable (line 516) | func (tbl policyTableStub) IsTable() {}
  function Test_appendPolicy (line 518) | func Test_appendPolicy(t *testing.T) {
  function Test_appendPredicates (line 557) | func Test_appendPredicates(t *testing.T) {
  function Test_writeTop (line 596) | func Test_writeTop(t *testing.T) {
  type TestTable (line 677) | type TestTable struct
    method assert (line 687) | func (tt TestTable) assert(t *testing.T) {
    method assertErr (line 718) | func (tt TestTable) assertErr(t *testing.T, wantErr error) {
    method assertNotOK (line 736) | func (tt TestTable) assertNotOK(t *testing.T) {

FILE: colors.go
  function init (line 10) | func init() {

FILE: cte.go
  type CTE (line 11) | type CTE struct
    method WriteSQL (line 33) | func (cte CTE) WriteSQL(ctx context.Context, dialect string, buf *byte...
    method As (line 39) | func (cte CTE) As(alias string) CTE {
    method Materialized (line 46) | func (cte CTE) Materialized() CTE {
    method NotMaterialized (line 54) | func (cte CTE) NotMaterialized() CTE {
    method Field (line 61) | func (cte CTE) Field(name string) AnyField {
    method GetAlias (line 66) | func (cte CTE) GetAlias() string { return cte.alias }
    method IsTable (line 69) | func (cte CTE) IsTable() {}
  function NewCTE (line 23) | func NewCTE(name string, columns []string, query Query) CTE {
  function NewRecursiveCTE (line 28) | func NewRecursiveCTE(name string, columns []string, query Query) CTE {
  function writeCTEs (line 71) | func writeCTEs(ctx context.Context, dialect string, buf *bytes.Buffer, a...
  type VariadicQueryOperator (line 133) | type VariadicQueryOperator
  constant QueryUnion (line 137) | QueryUnion        VariadicQueryOperator = "UNION"
  constant QueryUnionAll (line 138) | QueryUnionAll     VariadicQueryOperator = "UNION ALL"
  constant QueryIntersect (line 139) | QueryIntersect    VariadicQueryOperator = "INTERSECT"
  constant QueryIntersectAll (line 140) | QueryIntersectAll VariadicQueryOperator = "INTERSECT ALL"
  constant QueryExcept (line 141) | QueryExcept       VariadicQueryOperator = "EXCEPT"
  constant QueryExceptAll (line 142) | QueryExceptAll    VariadicQueryOperator = "EXCEPT ALL"
  type VariadicQuery (line 146) | type VariadicQuery struct
    method WriteSQL (line 185) | func (q VariadicQuery) WriteSQL(ctx context.Context, dialect string, b...
    method SetFetchableFields (line 235) | func (q VariadicQuery) SetFetchableFields(fields []Field) (query Query...
    method GetFetchableFields (line 240) | func (q VariadicQuery) GetFetchableFields() []Field {
    method GetDialect (line 245) | func (q VariadicQuery) GetDialect() string {
  function Union (line 155) | func Union(queries ...Query) VariadicQuery {
  function UnionAll (line 160) | func UnionAll(queries ...Query) VariadicQuery {
  function Intersect (line 165) | func Intersect(queries ...Query) VariadicQuery {
  function IntersectAll (line 170) | func IntersectAll(queries ...Query) VariadicQuery {
  function Except (line 175) | func Except(queries ...Query) VariadicQuery {
  function ExceptAll (line 180) | func ExceptAll(queries ...Query) VariadicQuery {

FILE: cte_test.go
  function TestCTE (line 13) | func TestCTE(t *testing.T) {
  function TestCTEs (line 30) | func TestCTEs(t *testing.T) {
  function TestVariadicQuery (line 141) | func TestVariadicQuery(t *testing.T) {

FILE: delete_query.go
  type DeleteQuery (line 10) | type DeleteQuery struct
    method WriteSQL (line 35) | func (q DeleteQuery) WriteSQL(ctx context.Context, dialect string, buf...
    method Where (line 203) | func (q DeleteQuery) Where(predicates ...Predicate) DeleteQuery {
    method SetFetchableFields (line 209) | func (q DeleteQuery) SetFetchableFields(fields []Field) (query Query, ...
    method GetFetchableFields (line 223) | func (q DeleteQuery) GetFetchableFields() []Field {
    method GetDialect (line 233) | func (q DeleteQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 236) | func (q DeleteQuery) SetDialect(dialect string) DeleteQuery {
  function DeleteFrom (line 198) | func DeleteFrom(table Table) DeleteQuery {
  type SQLiteDeleteQuery (line 242) | type SQLiteDeleteQuery
    method WriteSQL (line 247) | func (q SQLiteDeleteQuery) WriteSQL(ctx context.Context, dialect strin...
    method Where (line 261) | func (q SQLiteDeleteQuery) Where(predicates ...Predicate) SQLiteDelete...
    method Returning (line 267) | func (q SQLiteDeleteQuery) Returning(fields ...Field) SQLiteDeleteQuery {
    method SetFetchableFields (line 273) | func (q SQLiteDeleteQuery) SetFetchableFields(fields []Field) (query Q...
    method GetFetchableFields (line 278) | func (q SQLiteDeleteQuery) GetFetchableFields() []Field {
    method GetDialect (line 283) | func (q SQLiteDeleteQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 286) | func (q SQLiteDeleteQuery) SetDialect(dialect string) SQLiteDeleteQuery {
  method DeleteFrom (line 252) | func (b sqliteQueryBuilder) DeleteFrom(table Table) SQLiteDeleteQuery {
  type PostgresDeleteQuery (line 292) | type PostgresDeleteQuery
    method WriteSQL (line 297) | func (q PostgresDeleteQuery) WriteSQL(ctx context.Context, dialect str...
    method Using (line 311) | func (q PostgresDeleteQuery) Using(table Table) PostgresDeleteQuery {
    method Join (line 317) | func (q PostgresDeleteQuery) Join(table Table, predicates ...Predicate...
    method LeftJoin (line 323) | func (q PostgresDeleteQuery) LeftJoin(table Table, predicates ...Predi...
    method FullJoin (line 329) | func (q PostgresDeleteQuery) FullJoin(table Table, predicates ...Predi...
    method CrossJoin (line 335) | func (q PostgresDeleteQuery) CrossJoin(table Table) PostgresDeleteQuery {
    method CustomJoin (line 342) | func (q PostgresDeleteQuery) CustomJoin(joinOperator string, table Tab...
    method JoinUsing (line 348) | func (q PostgresDeleteQuery) JoinUsing(table Table, fields ...Field) P...
    method Where (line 354) | func (q PostgresDeleteQuery) Where(predicates ...Predicate) PostgresDe...
    method Returning (line 360) | func (q PostgresDeleteQuery) Returning(fields ...Field) PostgresDelete...
    method SetFetchableFields (line 366) | func (q PostgresDeleteQuery) SetFetchableFields(fields []Field) (query...
    method GetFetchableFields (line 371) | func (q PostgresDeleteQuery) GetFetchableFields() []Field {
    method GetDialect (line 376) | func (q PostgresDeleteQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 379) | func (q PostgresDeleteQuery) SetDialect(dialect string) PostgresDelete...
  method DeleteFrom (line 302) | func (b postgresQueryBuilder) DeleteFrom(table Table) PostgresDeleteQuery {
  type MySQLDeleteQuery (line 385) | type MySQLDeleteQuery
    method WriteSQL (line 390) | func (q MySQLDeleteQuery) WriteSQL(ctx context.Context, dialect string...
    method From (line 413) | func (q MySQLDeleteQuery) From(table Table) MySQLDeleteQuery {
    method Join (line 419) | func (q MySQLDeleteQuery) Join(table Table, predicates ...Predicate) M...
    method LeftJoin (line 425) | func (q MySQLDeleteQuery) LeftJoin(table Table, predicates ...Predicat...
    method FullJoin (line 431) | func (q MySQLDeleteQuery) FullJoin(table Table, predicates ...Predicat...
    method CrossJoin (line 437) | func (q MySQLDeleteQuery) CrossJoin(table Table) MySQLDeleteQuery {
    method CustomJoin (line 444) | func (q MySQLDeleteQuery) CustomJoin(joinOperator string, table Table,...
    method JoinUsing (line 450) | func (q MySQLDeleteQuery) JoinUsing(table Table, fields ...Field) MySQ...
    method Where (line 456) | func (q MySQLDeleteQuery) Where(predicates ...Predicate) MySQLDeleteQu...
    method OrderBy (line 462) | func (q MySQLDeleteQuery) OrderBy(fields ...Field) MySQLDeleteQuery {
    method Limit (line 468) | func (q MySQLDeleteQuery) Limit(limit any) MySQLDeleteQuery {
    method Returning (line 474) | func (q MySQLDeleteQuery) Returning(fields ...Field) MySQLDeleteQuery {
    method SetFetchableFields (line 480) | func (q MySQLDeleteQuery) SetFetchableFields(fields []Field) (query Qu...
    method GetFetchableFields (line 485) | func (q MySQLDeleteQuery) GetFetchableFields() []Field {
    method GetDialect (line 490) | func (q MySQLDeleteQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 493) | func (q MySQLDeleteQuery) SetDialect(dialect string) MySQLDeleteQuery {
  method DeleteFrom (line 395) | func (b mysqlQueryBuilder) DeleteFrom(table Table) MySQLDeleteQuery {
  method Delete (line 404) | func (b mysqlQueryBuilder) Delete(tables ...Table) MySQLDeleteQuery {
  type SQLServerDeleteQuery (line 499) | type SQLServerDeleteQuery
    method WriteSQL (line 504) | func (q SQLServerDeleteQuery) WriteSQL(ctx context.Context, dialect st...
    method From (line 527) | func (q SQLServerDeleteQuery) From(table Table) SQLServerDeleteQuery {
    method Join (line 533) | func (q SQLServerDeleteQuery) Join(table Table, predicates ...Predicat...
    method LeftJoin (line 539) | func (q SQLServerDeleteQuery) LeftJoin(table Table, predicates ...Pred...
    method FullJoin (line 545) | func (q SQLServerDeleteQuery) FullJoin(table Table, predicates ...Pred...
    method CrossJoin (line 551) | func (q SQLServerDeleteQuery) CrossJoin(table Table) SQLServerDeleteQu...
    method CustomJoin (line 558) | func (q SQLServerDeleteQuery) CustomJoin(joinOperator string, table Ta...
    method Where (line 564) | func (q SQLServerDeleteQuery) Where(predicates ...Predicate) SQLServer...
    method SetFetchableFields (line 570) | func (q SQLServerDeleteQuery) SetFetchableFields(fields []Field) (quer...
    method GetFetchableFields (line 575) | func (q SQLServerDeleteQuery) GetFetchableFields() []Field {
    method GetDialect (line 580) | func (q SQLServerDeleteQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 583) | func (q SQLServerDeleteQuery) SetDialect(dialect string) SQLServerDele...
  method DeleteFrom (line 509) | func (b sqlserverQueryBuilder) DeleteFrom(table Table) SQLServerDeleteQu...
  method Delete (line 518) | func (b sqlserverQueryBuilder) Delete(table Table) SQLServerDeleteQuery {

FILE: delete_query_test.go
  function TestSQLiteDeleteQuery (line 9) | func TestSQLiteDeleteQuery(t *testing.T) {
  function TestPostgresDeleteQuery (line 58) | func TestPostgresDeleteQuery(t *testing.T) {
  function TestMySQLDeleteQuery (line 130) | func TestMySQLDeleteQuery(t *testing.T) {
  function TestSQLServerDeleteQuery (line 230) | func TestSQLServerDeleteQuery(t *testing.T) {
  function TestDeleteQuery (line 299) | func TestDeleteQuery(t *testing.T) {

FILE: fetch_exec.go
  type Cursor (line 20) | type Cursor struct
  function FetchCursor (line 33) | func FetchCursor[T any](db DB, query Query, rowmapper func(*Row) T) (*Cu...
  function FetchCursorContext (line 38) | func FetchCursorContext[T any](ctx context.Context, db DB, query Query, ...
  function fetchCursor (line 42) | func fetchCursor[T any](ctx context.Context, db DB, query Query, rowmapp...
  method Next (line 157) | func (cursor *Cursor[T]) Next() bool {
  method RowCount (line 168) | func (cursor *Cursor[T]) RowCount() int64 { return cursor.queryStats.Row...
  method Result (line 171) | func (cursor *Cursor[T]) Result() (result T, err error) {
  method log (line 205) | func (cursor *Cursor[T]) log() {
  method Close (line 224) | func (cursor *Cursor[T]) Close() error {
  function FetchOne (line 237) | func FetchOne[T any](db DB, query Query, rowmapper func(*Row) T) (T, err...
  function FetchOneContext (line 247) | func FetchOneContext[T any](ctx context.Context, db DB, query Query, row...
  function FetchAll (line 257) | func FetchAll[T any](db DB, query Query, rowmapper func(*Row) T) ([]T, e...
  function FetchAllContext (line 267) | func FetchAllContext[T any](ctx context.Context, db DB, query Query, row...
  type CompiledFetch (line 278) | type CompiledFetch struct
  function NewCompiledFetch (line 291) | func NewCompiledFetch[T any](dialect string, query string, args []any, p...
  function CompileFetch (line 302) | func CompileFetch[T any](q Query, rowmapper func(*Row) T) (*CompiledFetc...
  function CompileFetchContext (line 307) | func CompileFetchContext[T any](ctx context.Context, query Query, rowmap...
  method FetchCursor (line 355) | func (compiledFetch *CompiledFetch[T]) FetchCursor(db DB, params Params)...
  method FetchCursorContext (line 360) | func (compiledFetch *CompiledFetch[T]) FetchCursorContext(ctx context.Co...
  method fetchCursor (line 364) | func (compiledFetch *CompiledFetch[T]) fetchCursor(ctx context.Context, ...
  method FetchOne (line 460) | func (compiledFetch *CompiledFetch[T]) FetchOne(db DB, params Params) (T...
  method FetchOneContext (line 470) | func (compiledFetch *CompiledFetch[T]) FetchOneContext(ctx context.Conte...
  method FetchAll (line 481) | func (compiledFetch *CompiledFetch[T]) FetchAll(db DB, params Params) ([...
  method FetchAllContext (line 491) | func (compiledFetch *CompiledFetch[T]) FetchAllContext(ctx context.Conte...
  method GetSQL (line 502) | func (compiledFetch *CompiledFetch[T]) GetSQL() (dialect string, query s...
  method Prepare (line 518) | func (compiledFetch *CompiledFetch[T]) Prepare(db DB) (*PreparedFetch[T]...
  method PrepareContext (line 523) | func (compiledFetch *CompiledFetch[T]) PrepareContext(ctx context.Contex...
  type PreparedFetch (line 551) | type PreparedFetch struct
  function PrepareFetch (line 558) | func PrepareFetch[T any](db DB, q Query, rowmapper func(*Row) T) (*Prepa...
  function PrepareFetchContext (line 563) | func PrepareFetchContext[T any](ctx context.Context, db DB, q Query, row...
  method FetchCursor (line 572) | func (preparedFetch PreparedFetch[T]) FetchCursor(params Params) (*Curso...
  method FetchCursorContext (line 577) | func (preparedFetch PreparedFetch[T]) FetchCursorContext(ctx context.Con...
  method fetchCursor (line 581) | func (preparedFetch *PreparedFetch[T]) fetchCursor(ctx context.Context, ...
  method FetchOne (line 664) | func (preparedFetch *PreparedFetch[T]) FetchOne(params Params) (T, error) {
  method FetchOneContext (line 674) | func (preparedFetch *PreparedFetch[T]) FetchOneContext(ctx context.Conte...
  method FetchAll (line 685) | func (preparedFetch *PreparedFetch[T]) FetchAll(params Params) ([]T, err...
  method FetchAllContext (line 695) | func (preparedFetch *PreparedFetch[T]) FetchAllContext(ctx context.Conte...
  method GetCompiled (line 705) | func (preparedFetch *PreparedFetch[T]) GetCompiled() *CompiledFetch[T] {
  method Close (line 712) | func (preparedFetch *PreparedFetch[T]) Close() error {
  function Exec (line 720) | func Exec(db DB, query Query) (Result, error) {
  function ExecContext (line 725) | func ExecContext(ctx context.Context, db DB, query Query) (Result, error) {
  function exec (line 729) | func exec(ctx context.Context, db DB, query Query, skip int) (result Res...
  type CompiledExec (line 802) | type CompiledExec struct
    method Exec (line 854) | func (compiledExec *CompiledExec) Exec(db DB, params Params) (Result, ...
    method ExecContext (line 859) | func (compiledExec *CompiledExec) ExecContext(ctx context.Context, db ...
    method exec (line 863) | func (compiledExec *CompiledExec) exec(ctx context.Context, db DB, par...
    method GetSQL (line 924) | func (compiledExec *CompiledExec) GetSQL() (dialect string, query stri...
    method Prepare (line 940) | func (compiledExec *CompiledExec) Prepare(db DB) (*PreparedExec, error) {
    method PrepareContext (line 945) | func (compiledExec *CompiledExec) PrepareContext(ctx context.Context, ...
  function NewCompiledExec (line 810) | func NewCompiledExec(dialect string, query string, args []any, params ma...
  function CompileExec (line 820) | func CompileExec(query Query) (*CompiledExec, error) {
  function CompileExecContext (line 825) | func CompileExecContext(ctx context.Context, query Query) (*CompiledExec...
  type PreparedExec (line 969) | type PreparedExec struct
    method Close (line 991) | func (preparedExec *PreparedExec) Close() error {
    method Exec (line 999) | func (preparedExec *PreparedExec) Exec(params Params) (Result, error) {
    method ExecContext (line 1004) | func (preparedExec *PreparedExec) ExecContext(ctx context.Context, par...
    method exec (line 1008) | func (preparedExec *PreparedExec) exec(ctx context.Context, params Par...
  function PrepareExec (line 976) | func PrepareExec(db DB, q Query) (*PreparedExec, error) {
  function PrepareExecContext (line 982) | func PrepareExecContext(ctx context.Context, db DB, q Query) (*PreparedE...
  function getFieldNames (line 1053) | func getFieldNames(ctx context.Context, row *Row) []string {
  function getFieldMappings (line 1085) | func getFieldMappings(dialect string, fields []Field, scanDest []any) st...
  function cursorResult (line 1110) | func cursorResult[T any](cursor *Cursor[T]) (result T, err error) {
  function cursorResults (line 1124) | func cursorResults[T any](cursor *Cursor[T]) (results []T, err error) {
  function execResult (line 1136) | func execResult(sqlResult sql.Result, queryStats *QueryStats) (Result, e...
  function FetchExists (line 1158) | func FetchExists(db DB, query Query) (exists bool, err error) {
  function FetchExistsContext (line 1164) | func FetchExistsContext(ctx context.Context, db DB, query Query) (exists...
  function fetchExists (line 1168) | func fetchExists(ctx context.Context, db DB, query Query, skip int) (exi...
  function substituteParams (line 1257) | func substituteParams(dialect string, args []any, paramIndexes map[strin...
  function caller (line 1286) | func caller(skip int) (file string, line int, function string) {

FILE: fetch_exec_test.go
  type Actor (line 20) | type Actor struct
  function actorRowMapper (line 27) | func actorRowMapper(row *Row) Actor {
  function actorRowMapperRawSQL (line 37) | func actorRowMapperRawSQL(row *Row) Actor {
  function Test_substituteParams (line 52) | func Test_substituteParams(t *testing.T) {
  function Test_getFieldMappings (line 121) | func Test_getFieldMappings(t *testing.T) {
  function TestFetchExec (line 163) | func TestFetchExec(t *testing.T) {
  function TestCompiledFetchExec (line 245) | func TestCompiledFetchExec(t *testing.T) {
  function TestPreparedFetchExec (line 348) | func TestPreparedFetchExec(t *testing.T) {
  function newDB (line 454) | func newDB(t *testing.T) *sql.DB {

FILE: fields.go
  type Identifier (line 17) | type Identifier
    method WriteSQL (line 22) | func (id Identifier) WriteSQL(ctx context.Context, dialect string, buf...
    method IsField (line 28) | func (id Identifier) IsField() {}
  type AnyField (line 31) | type AnyField struct
    method WriteSQL (line 51) | func (field AnyField) WriteSQL(ctx context.Context, dialect string, bu...
    method As (line 58) | func (field AnyField) As(alias string) AnyField {
    method Asc (line 65) | func (field AnyField) Asc() AnyField {
    method Desc (line 73) | func (field AnyField) Desc() AnyField {
    method NullsLast (line 81) | func (field AnyField) NullsLast() AnyField {
    method NullsFirst (line 89) | func (field AnyField) NullsFirst() AnyField {
    method WithPrefix (line 96) | func (field AnyField) WithPrefix(prefix string) Field {
    method IsNull (line 103) | func (field AnyField) IsNull() Predicate { return Expr("{} IS NULL", f...
    method IsNotNull (line 106) | func (field AnyField) IsNotNull() Predicate { return Expr("{} IS NOT N...
    method In (line 110) | func (field AnyField) In(value any) Predicate { return In(field, value) }
    method NotIn (line 114) | func (field AnyField) NotIn(value any) Predicate { return NotIn(field,...
    method Eq (line 117) | func (field AnyField) Eq(value any) Predicate { return Eq(field, value) }
    method Ne (line 120) | func (field AnyField) Ne(value any) Predicate { return Ne(field, value) }
    method Lt (line 123) | func (field AnyField) Lt(value any) Predicate { return Lt(field, value) }
    method Le (line 126) | func (field AnyField) Le(value any) Predicate { return Le(field, value) }
    method Gt (line 129) | func (field AnyField) Gt(value any) Predicate { return Gt(field, value) }
    method Ge (line 132) | func (field AnyField) Ge(value any) Predicate { return Ge(field, value) }
    method Expr (line 136) | func (field AnyField) Expr(format string, values ...any) Expression {
    method Set (line 143) | func (field AnyField) Set(value any) Assignment {
    method Setf (line 148) | func (field AnyField) Setf(format string, values ...any) Assignment {
    method GetAlias (line 153) | func (field AnyField) GetAlias() string { return field.alias }
    method IsField (line 156) | func (field AnyField) IsField() {}
    method IsArray (line 159) | func (field AnyField) IsArray() {}
    method IsBinary (line 162) | func (field AnyField) IsBinary() {}
    method IsBoolean (line 165) | func (field AnyField) IsBoolean() {}
    method IsEnum (line 168) | func (field AnyField) IsEnum() {}
    method IsJSON (line 171) | func (field AnyField) IsJSON() {}
    method IsNumber (line 174) | func (field AnyField) IsNumber() {}
    method IsString (line 177) | func (field AnyField) IsString() {}
    method IsTime (line 180) | func (field AnyField) IsTime() {}
    method IsUUID (line 183) | func (field AnyField) IsUUID() {}
  function NewAnyField (line 46) | func NewAnyField(name string, tbl TableStruct) AnyField {
  type ArrayField (line 186) | type ArrayField struct
    method WriteSQL (line 204) | func (field ArrayField) WriteSQL(ctx context.Context, dialect string, ...
    method As (line 210) | func (field ArrayField) As(alias string) ArrayField {
    method WithPrefix (line 216) | func (field ArrayField) WithPrefix(prefix string) Field {
    method IsNull (line 223) | func (field ArrayField) IsNull() Predicate { return Expr("{} IS NULL",...
    method IsNotNull (line 226) | func (field ArrayField) IsNotNull() Predicate { return Expr("{} IS NOT...
    method Set (line 229) | func (field ArrayField) Set(value any) Assignment {
    method SetArray (line 241) | func (field ArrayField) SetArray(value any) Assignment {
    method Setf (line 246) | func (field ArrayField) Setf(format string, values ...any) Assignment {
    method GetAlias (line 251) | func (field ArrayField) GetAlias() string { return field.alias }
    method IsField (line 254) | func (field ArrayField) IsField() {}
    method IsArray (line 257) | func (field ArrayField) IsArray() {}
  function NewArrayField (line 199) | func NewArrayField(fieldName string, tableName TableStruct) ArrayField {
  type BinaryField (line 260) | type BinaryField struct
    method WriteSQL (line 280) | func (field BinaryField) WriteSQL(ctx context.Context, dialect string,...
    method As (line 287) | func (field BinaryField) As(alias string) BinaryField {
    method Asc (line 294) | func (field BinaryField) Asc() BinaryField {
    method Desc (line 302) | func (field BinaryField) Desc() BinaryField {
    method NullsLast (line 310) | func (field BinaryField) NullsLast() BinaryField {
    method NullsFirst (line 318) | func (field BinaryField) NullsFirst() BinaryField {
    method WithPrefix (line 325) | func (field BinaryField) WithPrefix(prefix string) Field {
    method IsNull (line 332) | func (field BinaryField) IsNull() Predicate { return Expr("{} IS NULL"...
    method IsNotNull (line 335) | func (field BinaryField) IsNotNull() Predicate { return Expr("{} IS NO...
    method Eq (line 338) | func (field BinaryField) Eq(value Binary) Predicate { return Eq(field,...
    method Ne (line 341) | func (field BinaryField) Ne(value Binary) Predicate { return Ne(field,...
    method EqBytes (line 344) | func (field BinaryField) EqBytes(b []byte) Predicate { return Eq(field...
    method NeBytes (line 347) | func (field BinaryField) NeBytes(b []byte) Predicate { return Ne(field...
    method Set (line 350) | func (field BinaryField) Set(value any) Assignment {
    method Setf (line 355) | func (field BinaryField) Setf(format string, values ...any) Assignment {
    method SetBytes (line 360) | func (field BinaryField) SetBytes(b []byte) Assignment { return Set(fi...
    method GetAlias (line 363) | func (field BinaryField) GetAlias() string { return field.alias }
    method IsField (line 366) | func (field BinaryField) IsField() {}
    method IsBinary (line 369) | func (field BinaryField) IsBinary() {}
  function NewBinaryField (line 275) | func NewBinaryField(fieldName string, tableName TableStruct) BinaryField {
  type BooleanField (line 372) | type BooleanField struct
    method WriteSQL (line 393) | func (field BooleanField) WriteSQL(ctx context.Context, dialect string...
    method As (line 400) | func (field BooleanField) As(alias string) BooleanField {
    method Asc (line 407) | func (field BooleanField) Asc() BooleanField {
    method Desc (line 415) | func (f BooleanField) Desc() BooleanField {
    method NullsLast (line 423) | func (field BooleanField) NullsLast() BooleanField {
    method NullsFirst (line 431) | func (field BooleanField) NullsFirst() BooleanField {
    method WithPrefix (line 438) | func (field BooleanField) WithPrefix(prefix string) Field {
    method IsNull (line 445) | func (field BooleanField) IsNull() Predicate { return Expr("{} IS NULL...
    method IsNotNull (line 448) | func (field BooleanField) IsNotNull() Predicate { return Expr("{} IS N...
    method Eq (line 451) | func (field BooleanField) Eq(value Boolean) Predicate { return Eq(fiel...
    method Ne (line 454) | func (field BooleanField) Ne(value Boolean) Predicate { return Ne(fiel...
    method EqBool (line 457) | func (field BooleanField) EqBool(b bool) Predicate { return Eq(field, ...
    method NeBool (line 460) | func (field BooleanField) NeBool(b bool) Predicate { return Ne(field, ...
    method Set (line 463) | func (field BooleanField) Set(value any) Assignment {
    method Setf (line 468) | func (field BooleanField) Setf(format string, values ...any) Assignment {
    method SetBool (line 474) | func (field BooleanField) SetBool(b bool) Assignment { return Set(fiel...
    method GetAlias (line 477) | func (field BooleanField) GetAlias() string { return field.alias }
    method IsField (line 480) | func (field BooleanField) IsField() {}
    method IsBoolean (line 483) | func (field BooleanField) IsBoolean() {}
  function NewBooleanField (line 388) | func NewBooleanField(fieldName string, tableName TableStruct) BooleanFie...
  type EnumField (line 486) | type EnumField struct
    method WriteSQL (line 504) | func (field EnumField) WriteSQL(ctx context.Context, dialect string, b...
    method As (line 510) | func (field EnumField) As(alias string) EnumField {
    method WithPrefix (line 516) | func (field EnumField) WithPrefix(prefix string) Field {
    method IsNull (line 523) | func (field EnumField) IsNull() Predicate { return Expr("{} IS NULL", ...
    method IsNotNull (line 526) | func (field EnumField) IsNotNull() Predicate { return Expr("{} IS NOT ...
    method In (line 530) | func (field EnumField) In(value any) Predicate { return In(field, valu...
    method NotIn (line 534) | func (field EnumField) NotIn(value any) Predicate { return NotIn(field...
    method Eq (line 537) | func (field EnumField) Eq(value any) Predicate { return Eq(field, valu...
    method Ne (line 540) | func (field EnumField) Ne(value any) Predicate { return Ne(field, valu...
    method EqEnum (line 544) | func (field EnumField) EqEnum(value Enumeration) Predicate { return Eq...
    method NeEnum (line 548) | func (field EnumField) NeEnum(value Enumeration) Predicate { return Ne...
    method Set (line 551) | func (field EnumField) Set(value any) Assignment {
    method SetEnum (line 557) | func (field EnumField) SetEnum(value Enumeration) Assignment {
    method Setf (line 562) | func (field EnumField) Setf(format string, values ...any) Assignment {
    method GetAlias (line 567) | func (field EnumField) GetAlias() string { return field.alias }
    method IsField (line 570) | func (field EnumField) IsField() {}
    method IsEnum (line 573) | func (field EnumField) IsEnum() {}
  function NewEnumField (line 499) | func NewEnumField(name string, tbl TableStruct) EnumField {
  type JSONField (line 576) | type JSONField struct
    method WriteSQL (line 596) | func (field JSONField) WriteSQL(ctx context.Context, dialect string, b...
    method As (line 602) | func (field JSONField) As(alias string) JSONField {
    method WithPrefix (line 608) | func (field JSONField) WithPrefix(prefix string) Field {
    method IsNull (line 615) | func (field JSONField) IsNull() Predicate { return Expr("{} IS NULL", ...
    method IsNotNull (line 618) | func (field JSONField) IsNotNull() Predicate { return Expr("{} IS NOT ...
    method Set (line 621) | func (field JSONField) Set(value any) Assignment {
    method SetJSON (line 635) | func (field JSONField) SetJSON(value any) Assignment {
    method Setf (line 640) | func (field JSONField) Setf(format string, values ...any) Assignment {
    method GetAlias (line 645) | func (field JSONField) GetAlias() string { return field.alias }
    method IsField (line 648) | func (field JSONField) IsField() {}
    method IsBinary (line 651) | func (field JSONField) IsBinary() {}
    method IsJSON (line 654) | func (field JSONField) IsJSON() {}
    method IsString (line 657) | func (field JSONField) IsString() {}
  function NewJSONField (line 591) | func NewJSONField(name string, tbl TableStruct) JSONField {
  type NumberField (line 660) | type NumberField struct
    method WriteSQL (line 680) | func (field NumberField) WriteSQL(ctx context.Context, dialect string,...
    method As (line 687) | func (field NumberField) As(alias string) NumberField {
    method Asc (line 694) | func (field NumberField) Asc() NumberField {
    method Desc (line 702) | func (field NumberField) Desc() NumberField {
    method NullsLast (line 710) | func (field NumberField) NullsLast() NumberField {
    method NullsFirst (line 718) | func (field NumberField) NullsFirst() NumberField {
    method WithPrefix (line 725) | func (field NumberField) WithPrefix(prefix string) Field {
    method IsNull (line 732) | func (field NumberField) IsNull() Predicate { return Expr("{} IS NULL"...
    method IsNotNull (line 735) | func (field NumberField) IsNotNull() Predicate { return Expr("{} IS NO...
    method In (line 739) | func (field NumberField) In(value any) Predicate { return In(field, va...
    method NotIn (line 743) | func (field NumberField) NotIn(value any) Predicate { return NotIn(fie...
    method Eq (line 746) | func (field NumberField) Eq(value Number) Predicate { return Eq(field,...
    method Ne (line 749) | func (field NumberField) Ne(value Number) Predicate { return Ne(field,...
    method Lt (line 752) | func (field NumberField) Lt(value Number) Predicate { return Lt(field,...
    method Le (line 755) | func (field NumberField) Le(value Number) Predicate { return Le(field,...
    method Gt (line 758) | func (field NumberField) Gt(value Number) Predicate { return Gt(field,...
    method Ge (line 761) | func (field NumberField) Ge(value Number) Predicate { return Ge(field,...
    method EqInt (line 764) | func (field NumberField) EqInt(num int) Predicate { return Eq(field, n...
    method NeInt (line 767) | func (field NumberField) NeInt(num int) Predicate { return Ne(field, n...
    method LtInt (line 770) | func (field NumberField) LtInt(num int) Predicate { return Lt(field, n...
    method LeInt (line 773) | func (field NumberField) LeInt(num int) Predicate { return Le(field, n...
    method GtInt (line 776) | func (field NumberField) GtInt(num int) Predicate { return Gt(field, n...
    method GeInt (line 779) | func (field NumberField) GeInt(num int) Predicate { return Ge(field, n...
    method EqInt64 (line 782) | func (field NumberField) EqInt64(num int64) Predicate { return Eq(fiel...
    method NeInt64 (line 785) | func (field NumberField) NeInt64(num int64) Predicate { return Ne(fiel...
    method LtInt64 (line 788) | func (field NumberField) LtInt64(num int64) Predicate { return Lt(fiel...
    method LeInt64 (line 791) | func (field NumberField) LeInt64(num int64) Predicate { return Le(fiel...
    method GtInt64 (line 794) | func (field NumberField) GtInt64(num int64) Predicate { return Gt(fiel...
    method GeInt64 (line 797) | func (field NumberField) GeInt64(num int64) Predicate { return Ge(fiel...
    method EqFloat64 (line 800) | func (field NumberField) EqFloat64(num float64) Predicate { return Eq(...
    method NeFloat64 (line 803) | func (field NumberField) NeFloat64(num float64) Predicate { return Ne(...
    method LtFloat64 (line 806) | func (field NumberField) LtFloat64(num float64) Predicate { return Lt(...
    method LeFloat64 (line 809) | func (field NumberField) LeFloat64(num float64) Predicate { return Le(...
    method GtFloat64 (line 812) | func (field NumberField) GtFloat64(num float64) Predicate { return Gt(...
    method GeFloat64 (line 815) | func (field NumberField) GeFloat64(num float64) Predicate { return Ge(...
    method Set (line 818) | func (field NumberField) Set(value any) Assignment {
    method Setf (line 823) | func (field NumberField) Setf(format string, values ...any) Assignment {
    method SetInt (line 828) | func (field NumberField) SetInt(num int) Assignment { return Set(field...
    method SetInt64 (line 831) | func (field NumberField) SetInt64(num int64) Assignment { return Set(f...
    method SetFloat64 (line 834) | func (field NumberField) SetFloat64(num float64) Assignment { return S...
    method GetAlias (line 837) | func (field NumberField) GetAlias() string { return field.alias }
    method IsField (line 840) | func (field NumberField) IsField() {}
    method IsNumber (line 843) | func (field NumberField) IsNumber() {}
  function NewNumberField (line 675) | func NewNumberField(name string, tbl TableStruct) NumberField {
  type StringField (line 846) | type StringField struct
    method WriteSQL (line 867) | func (field StringField) WriteSQL(ctx context.Context, dialect string,...
    method As (line 882) | func (field StringField) As(alias string) StringField {
    method Collate (line 888) | func (field StringField) Collate(collation string) StringField {
    method Asc (line 895) | func (field StringField) Asc() StringField {
    method Desc (line 903) | func (field StringField) Desc() StringField {
    method NullsLast (line 911) | func (field StringField) NullsLast() StringField {
    method NullsFirst (line 919) | func (field StringField) NullsFirst() StringField {
    method WithPrefix (line 926) | func (field StringField) WithPrefix(prefix string) Field {
    method IsNull (line 933) | func (field StringField) IsNull() Predicate { return Expr("{} IS NULL"...
    method IsNotNull (line 936) | func (field StringField) IsNotNull() Predicate { return Expr("{} IS NO...
    method In (line 940) | func (field StringField) In(value any) Predicate { return In(field, va...
    method NotIn (line 944) | func (field StringField) NotIn(value any) Predicate { return NotIn(fie...
    method Eq (line 947) | func (field StringField) Eq(value String) Predicate { return Eq(field,...
    method Ne (line 950) | func (field StringField) Ne(value String) Predicate { return Ne(field,...
    method Lt (line 953) | func (field StringField) Lt(value String) Predicate { return Lt(field,...
    method Le (line 956) | func (field StringField) Le(value String) Predicate { return Le(field,...
    method Gt (line 959) | func (field StringField) Gt(value String) Predicate { return Gt(field,...
    method Ge (line 962) | func (field StringField) Ge(value String) Predicate { return Ge(field,...
    method EqString (line 965) | func (field StringField) EqString(str string) Predicate { return Eq(fi...
    method NeString (line 968) | func (field StringField) NeString(str string) Predicate { return Ne(fi...
    method LtString (line 971) | func (field StringField) LtString(str string) Predicate { return Lt(fi...
    method LeString (line 974) | func (field StringField) LeString(str string) Predicate { return Le(fi...
    method GtString (line 977) | func (field StringField) GtString(str string) Predicate { return Gt(fi...
    method GeString (line 980) | func (field StringField) GeString(str string) Predicate { return Ge(fi...
    method LikeString (line 983) | func (field StringField) LikeString(str string) Predicate {
    method NotLikeString (line 988) | func (field StringField) NotLikeString(str string) Predicate {
    method ILikeString (line 993) | func (field StringField) ILikeString(str string) Predicate {
    method NotILikeString (line 998) | func (field StringField) NotILikeString(str string) Predicate {
    method Set (line 1003) | func (field StringField) Set(value any) Assignment {
    method Setf (line 1008) | func (field StringField) Setf(format string, values ...any) Assignment {
    method SetString (line 1013) | func (field StringField) SetString(str string) Assignment { return Set...
    method GetAlias (line 1016) | func (field StringField) GetAlias() string { return field.alias }
    method IsField (line 1019) | func (field StringField) IsField() {}
    method IsString (line 1022) | func (field StringField) IsString() {}
  function NewStringField (line 862) | func NewStringField(name string, tbl TableStruct) StringField {
  type TimeField (line 1025) | type TimeField struct
    method WriteSQL (line 1045) | func (field TimeField) WriteSQL(ctx context.Context, dialect string, b...
    method As (line 1052) | func (field TimeField) As(alias string) TimeField {
    method Asc (line 1059) | func (field TimeField) Asc() TimeField {
    method Desc (line 1067) | func (field TimeField) Desc() TimeField {
    method NullsLast (line 1075) | func (field TimeField) NullsLast() TimeField {
    method NullsFirst (line 1083) | func (field TimeField) NullsFirst() TimeField {
    method WithPrefix (line 1090) | func (field TimeField) WithPrefix(prefix string) Field {
    method IsNull (line 1097) | func (field TimeField) IsNull() Predicate { return Expr("{} IS NULL", ...
    method IsNotNull (line 1100) | func (field TimeField) IsNotNull() Predicate { return Expr("{} IS NOT ...
    method In (line 1104) | func (field TimeField) In(value any) Predicate { return In(field, valu...
    method NotIn (line 1108) | func (field TimeField) NotIn(value any) Predicate { return NotIn(field...
    method Eq (line 1111) | func (field TimeField) Eq(value Time) Predicate { return Eq(field, val...
    method Ne (line 1114) | func (field TimeField) Ne(value Time) Predicate { return Ne(field, val...
    method Lt (line 1117) | func (field TimeField) Lt(value Time) Predicate { return Lt(field, val...
    method Le (line 1120) | func (field TimeField) Le(value Time) Predicate { return Le(field, val...
    method Gt (line 1123) | func (field TimeField) Gt(value Time) Predicate { return Gt(field, val...
    method Ge (line 1126) | func (field TimeField) Ge(value Time) Predicate { return Ge(field, val...
    method EqTime (line 1129) | func (field TimeField) EqTime(t time.Time) Predicate { return Eq(field...
    method NeTime (line 1132) | func (field TimeField) NeTime(t time.Time) Predicate { return Ne(field...
    method LtTime (line 1135) | func (field TimeField) LtTime(t time.Time) Predicate { return Lt(field...
    method LeTime (line 1138) | func (field TimeField) LeTime(t time.Time) Predicate { return Le(field...
    method GtTime (line 1141) | func (field TimeField) GtTime(t time.Time) Predicate { return Gt(field...
    method GeTime (line 1144) | func (field TimeField) GeTime(t time.Time) Predicate { return Ge(field...
    method Set (line 1147) | func (field TimeField) Set(value any) Assignment {
    method Setf (line 1152) | func (field TimeField) Setf(format string, values ...any) Assignment {
    method SetTime (line 1157) | func (field TimeField) SetTime(t time.Time) Assignment { return Set(fi...
    method GetAlias (line 1160) | func (field TimeField) GetAlias() string { return field.alias }
    method IsField (line 1163) | func (field TimeField) IsField() {}
    method IsTime (line 1166) | func (field TimeField) IsTime() {}
  function NewTimeField (line 1040) | func NewTimeField(name string, tbl TableStruct) TimeField {
  type Timestamp (line 1189) | type Timestamp struct
    method Scan (line 1228) | func (ts *Timestamp) Scan(value any) error {
    method Value (line 1291) | func (ts Timestamp) Value() (driver.Value, error) {
    method DialectValuer (line 1302) | func (ts Timestamp) DialectValuer(dialect string) (driver.Valuer, erro...
  function NewTimestamp (line 1196) | func NewTimestamp(t time.Time) Timestamp {
  type UUIDField (line 1308) | type UUIDField struct
    method WriteSQL (line 1328) | func (field UUIDField) WriteSQL(ctx context.Context, dialect string, b...
    method As (line 1335) | func (field UUIDField) As(alias string) UUIDField {
    method Asc (line 1342) | func (field UUIDField) Asc() UUIDField {
    method Desc (line 1350) | func (field UUIDField) Desc() UUIDField {
    method NullsLast (line 1358) | func (field UUIDField) NullsLast() UUIDField {
    method NullsFirst (line 1366) | func (field UUIDField) NullsFirst() UUIDField {
    method WithPrefix (line 1373) | func (field UUIDField) WithPrefix(prefix string) Field {
    method IsNull (line 1380) | func (field UUIDField) IsNull() Predicate { return Expr("{} IS NULL", ...
    method IsNotNull (line 1383) | func (field UUIDField) IsNotNull() Predicate { return Expr("{} IS NOT ...
    method In (line 1387) | func (field UUIDField) In(value any) Predicate { return In(field, valu...
    method NotIn (line 1391) | func (field UUIDField) NotIn(value any) Predicate { return NotIn(field...
    method Eq (line 1394) | func (field UUIDField) Eq(value any) Predicate { return Eq(field, valu...
    method Ne (line 1397) | func (field UUIDField) Ne(value any) Predicate { return Ne(field, valu...
    method EqUUID (line 1401) | func (field UUIDField) EqUUID(value any) Predicate { return Eq(field, ...
    method NeUUID (line 1405) | func (field UUIDField) NeUUID(value any) Predicate { return Ne(field, ...
    method Set (line 1408) | func (field UUIDField) Set(value any) Assignment {
    method SetUUID (line 1414) | func (field UUIDField) SetUUID(value any) Assignment {
    method Setf (line 1419) | func (field UUIDField) Setf(format string, values ...any) Assignment {
    method GetAlias (line 1424) | func (field UUIDField) GetAlias() string { return field.alias }
    method IsField (line 1427) | func (field UUIDField) IsField() {}
    method IsUUID (line 1430) | func (field UUIDField) IsUUID() {}
  function NewUUIDField (line 1323) | func NewUUIDField(name string, tbl TableStruct) UUIDField {
  function New (line 1434) | func New[T Table](alias string) T {
  function writeFieldIdentifier (line 1506) | func writeFieldIdentifier(ctx context.Context, dialect string, buf *byte...
  function writeFieldOrder (line 1518) | func writeFieldOrder(ctx context.Context, dialect string, buf *bytes.Buf...

FILE: fields_test.go
  function TestTableStruct (line 15) | func TestTableStruct(t *testing.T) {
  function TestArrayField (line 30) | func TestArrayField(t *testing.T) {
  function TestBinaryField (line 91) | func TestBinaryField(t *testing.T) {
  function TestBooleanField (line 154) | func TestBooleanField(t *testing.T) {
  function TestCustomField (line 217) | func TestCustomField(t *testing.T) {
  function TestEnumField (line 292) | func TestEnumField(t *testing.T) {
  function TestJSONField (line 358) | func TestJSONField(t *testing.T) {
  function TestNumberField (line 409) | func TestNumberField(t *testing.T) {
  function TestStringField (line 544) | func TestStringField(t *testing.T) {
  function TestTimeField (line 656) | func TestTimeField(t *testing.T) {
  function TestTimestamp (line 750) | func TestTimestamp(t *testing.T) {
  function TestUUIDField (line 876) | func TestUUIDField(t *testing.T) {
  type DummyTable (line 1022) | type DummyTable struct
    method WriteSQL (line 1026) | func (t DummyTable) WriteSQL(ctx context.Context, dialect string, buf ...
    method GetAlias (line 1030) | func (t DummyTable) GetAlias() string { return "" }
    method IsTable (line 1032) | func (t DummyTable) IsTable() {}
  function TestNew (line 1034) | func TestNew(t *testing.T) {

FILE: fmt.go
  function Writef (line 38) | func Writef(ctx context.Context, dialect string, buf *bytes.Buffer, args...
  function writef (line 42) | func writef(ctx context.Context, dialect string, buf *bytes.Buffer, args...
  function WriteValue (line 169) | func WriteValue(ctx context.Context, dialect string, buf *bytes.Buffer, ...
  function QuoteIdentifier (line 198) | func QuoteIdentifier(dialect string, identifier string) string {
  function EscapeQuote (line 253) | func EscapeQuote(str string, quote byte) string {
  function Sprintf (line 279) | func Sprintf(dialect string, query string, args []any) (string, error) {
  function Sprint (line 411) | func Sprint(dialect string, v any) (string, error) {
  function isExpandableSlice (line 595) | func isExpandableSlice(value any) bool {
  function expandSlice (line 609) | func expandSlice(ctx context.Context, dialect string, buf *bytes.Buffer,...
  function writeNamedArg (line 642) | func writeNamedArg(ctx context.Context, dialect string, buf *bytes.Buffe...
  function writeOrdinalValue (line 712) | func writeOrdinalValue(ctx context.Context, dialect string, buf *bytes.B...
  function lookupParam (line 757) | func lookupParam(dialect string, args []any, paramName []rune, namedIndi...
  function quoteTableColumns (line 810) | func quoteTableColumns(dialect string, table Table) string {
  type Parameter (line 835) | type Parameter
    method WriteSQL (line 845) | func (p Parameter) WriteSQL(ctx context.Context, dialect string, buf *...
    method IsField (line 850) | func (p Parameter) IsField() {}
  function Param (line 840) | func Param(name string, value any) Parameter {
  type ArrayParameter (line 853) | type ArrayParameter
    method WriteSQL (line 864) | func (p ArrayParameter) WriteSQL(ctx context.Context, dialect string, ...
    method IsField (line 869) | func (p ArrayParameter) IsField() {}
    method IsArray (line 872) | func (p ArrayParameter) IsArray() {}
  function ArrayParam (line 859) | func ArrayParam(name string, value any) ArrayParameter {
  type BinaryParameter (line 876) | type BinaryParameter
    method WriteSQL (line 886) | func (p BinaryParameter) WriteSQL(ctx context.Context, dialect string,...
    method IsField (line 891) | func (p BinaryParameter) IsField() {}
    method IsBinary (line 894) | func (p BinaryParameter) IsBinary() {}
  function BytesParam (line 881) | func BytesParam(name string, b []byte) BinaryParameter {
  type BooleanParameter (line 898) | type BooleanParameter
    method WriteSQL (line 908) | func (p BooleanParameter) WriteSQL(ctx context.Context, dialect string...
    method IsField (line 913) | func (p BooleanParameter) IsField() {}
    method IsBoolean (line 916) | func (p BooleanParameter) IsBoolean() {}
  function BoolParam (line 903) | func BoolParam(name string, b bool) BooleanParameter {
  type EnumParameter (line 920) | type EnumParameter
    method WriteSQL (line 930) | func (p EnumParameter) WriteSQL(ctx context.Context, dialect string, b...
    method IsField (line 935) | func (p EnumParameter) IsField() {}
    method IsEnum (line 938) | func (p EnumParameter) IsEnum() {}
  function EnumParam (line 925) | func EnumParam(name string, value Enumeration) EnumParameter {
  type JSONParameter (line 942) | type JSONParameter
    method WriteSQL (line 952) | func (p JSONParameter) WriteSQL(ctx context.Context, dialect string, b...
    method IsField (line 957) | func (p JSONParameter) IsField() {}
    method IsJSON (line 960) | func (p JSONParameter) IsJSON() {}
  function JSONParam (line 947) | func JSONParam(name string, value any) JSONParameter {
  type NumberParameter (line 964) | type NumberParameter
    method WriteSQL (line 984) | func (p NumberParameter) WriteSQL(ctx context.Context, dialect string,...
    method IsField (line 989) | func (p NumberParameter) IsField() {}
    method IsNumber (line 992) | func (p NumberParameter) IsNumber() {}
  function IntParam (line 969) | func IntParam(name string, num int) NumberParameter {
  function Int64Param (line 974) | func Int64Param(name string, num int64) NumberParameter {
  function Float64Param (line 979) | func Float64Param(name string, num float64) NumberParameter {
  type StringParameter (line 996) | type StringParameter
    method WriteSQL (line 1006) | func (p StringParameter) WriteSQL(ctx context.Context, dialect string,...
    method IsField (line 1011) | func (p StringParameter) IsField() {}
    method IsString (line 1014) | func (p StringParameter) IsString() {}
  function StringParam (line 1001) | func StringParam(name string, s string) StringParameter {
  type TimeParameter (line 1018) | type TimeParameter
    method WriteSQL (line 1028) | func (p TimeParameter) WriteSQL(ctx context.Context, dialect string, b...
    method IsField (line 1033) | func (p TimeParameter) IsField() {}
    method IsTime (line 1036) | func (p TimeParameter) IsTime() {}
  function TimeParam (line 1023) | func TimeParam(name string, t time.Time) TimeParameter {
  type UUIDParameter (line 1040) | type UUIDParameter
    method WriteSQL (line 1050) | func (p UUIDParameter) WriteSQL(ctx context.Context, dialect string, b...
    method IsField (line 1055) | func (p UUIDParameter) IsField() {}
    method IsUUID (line 1058) | func (p UUIDParameter) IsUUID() {}
  function UUIDParam (line 1045) | func UUIDParam(name string, value any) UUIDParameter {

FILE: fmt_test.go
  function TestWritef (line 23) | func TestWritef(t *testing.T) {
  function TestSprintf (line 759) | func TestSprintf(t *testing.T) {
  function TestSprint (line 1086) | func TestSprint(t *testing.T) {
  type tmptable (line 1408) | type tmptable
    method WriteSQL (line 1412) | func (t tmptable) WriteSQL(ctx context.Context, dialect string, buf *b...
    method GetAlias (line 1424) | func (t tmptable) GetAlias() string { return "" }
    method IsTable (line 1426) | func (t tmptable) IsTable() {}
  type tmpfield (line 1428) | type tmpfield
    method WriteSQL (line 1432) | func (f tmpfield) WriteSQL(ctx context.Context, dialect string, buf *b...
    method WithPrefix (line 1444) | func (f tmpfield) WithPrefix(prefix string) Field {
    method GetAlias (line 1455) | func (f tmpfield) GetAlias() string { return "" }
    method IsField (line 1457) | func (f tmpfield) IsField() {}
  type FaultySQLError (line 1459) | type FaultySQLError struct
    method Error (line 1461) | func (e FaultySQLError) Error() string { return "sql broke" }
  type FaultySQL (line 1473) | type FaultySQL struct
    method WriteSQL (line 1475) | func (q FaultySQL) WriteSQL(ctx context.Context, dialect string, buf *...
    method SetFetchableFields (line 1479) | func (q FaultySQL) SetFetchableFields([]Field) (Query, bool) { return ...
    method GetFetchableFields (line 1481) | func (q FaultySQL) GetFetchableFields() ([]Field, bool) { return nil, ...
    method GetAlias (line 1483) | func (q FaultySQL) GetAlias() string { return "" }
    method GetDialect (line 1485) | func (q FaultySQL) GetDialect() string { return "" }
    method IsBoolean (line 1487) | func (q FaultySQL) IsBoolean() {}
    method IsTable (line 1489) | func (q FaultySQL) IsTable() {}
    method IsField (line 1491) | func (q FaultySQL) IsField() {}
    method IsAssignment (line 1493) | func (q FaultySQL) IsAssignment() {}
  type driverValuer (line 1495) | type driverValuer struct
    method Value (line 1497) | func (v driverValuer) Value() (driver.Value, error) { return v.value, ...
  type dialectValuer (line 1499) | type dialectValuer struct
    method DialectValuer (line 1504) | func (v dialectValuer) DialectValuer(dialect string) (driver.Valuer, e...

FILE: insert_query.go
  type InsertQuery (line 10) | type InsertQuery struct
    method WriteSQL (line 33) | func (q InsertQuery) WriteSQL(ctx context.Context, dialect string, buf...
    method Columns (line 150) | func (q InsertQuery) Columns(fields ...Field) InsertQuery {
    method Values (line 156) | func (q InsertQuery) Values(values ...any) InsertQuery {
    method ColumnValues (line 162) | func (q InsertQuery) ColumnValues(colmapper func(*Column)) InsertQuery {
    method Select (line 168) | func (q InsertQuery) Select(query Query) InsertQuery {
    method SetFetchableFields (line 259) | func (q InsertQuery) SetFetchableFields(fields []Field) (query Query, ...
    method GetFetchableFields (line 273) | func (q InsertQuery) GetFetchableFields() []Field {
    method GetDialect (line 283) | func (q InsertQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 286) | func (q InsertQuery) SetDialect(dialect string) InsertQuery {
  function InsertInto (line 145) | func InsertInto(table Table) InsertQuery {
  type ConflictClause (line 175) | type ConflictClause struct
    method WriteSQL (line 185) | func (c ConflictClause) WriteSQL(ctx context.Context, dialect string, ...
  type SQLiteInsertQuery (line 292) | type SQLiteInsertQuery
    method WriteSQL (line 297) | func (q SQLiteInsertQuery) WriteSQL(ctx context.Context, dialect strin...
    method Columns (line 311) | func (q SQLiteInsertQuery) Columns(fields ...Field) SQLiteInsertQuery {
    method Values (line 317) | func (q SQLiteInsertQuery) Values(values ...any) SQLiteInsertQuery {
    method ColumnValues (line 323) | func (q SQLiteInsertQuery) ColumnValues(colmapper func(*Column)) SQLit...
    method Select (line 329) | func (q SQLiteInsertQuery) Select(query Query) SQLiteInsertQuery {
    method OnConflict (line 337) | func (q SQLiteInsertQuery) OnConflict(fields ...Field) sqliteInsertCon...
    method Where (line 362) | func (q SQLiteInsertQuery) Where(predicates ...Predicate) SQLiteInsert...
    method Returning (line 368) | func (q SQLiteInsertQuery) Returning(fields ...Field) SQLiteInsertQuery {
    method SetFetchableFields (line 374) | func (q SQLiteInsertQuery) SetFetchableFields(fields []Field) (query Q...
    method GetFetchableFields (line 379) | func (q SQLiteInsertQuery) GetFetchableFields() []Field {
    method GetDialect (line 384) | func (q SQLiteInsertQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 387) | func (q SQLiteInsertQuery) SetDialect(dialect string) SQLiteInsertQuery {
  method InsertInto (line 302) | func (b sqliteQueryBuilder) InsertInto(table Table) SQLiteInsertQuery {
  type sqliteInsertConflict (line 334) | type sqliteInsertConflict struct
    method Where (line 343) | func (c sqliteInsertConflict) Where(predicates ...Predicate) sqliteIns...
    method DoNothing (line 350) | func (c sqliteInsertConflict) DoNothing() SQLiteInsertQuery {
    method DoUpdateSet (line 356) | func (c sqliteInsertConflict) DoUpdateSet(assignments ...Assignment) S...
  type PostgresInsertQuery (line 393) | type PostgresInsertQuery
    method WriteSQL (line 398) | func (q PostgresInsertQuery) WriteSQL(ctx context.Context, dialect str...
    method Columns (line 412) | func (q PostgresInsertQuery) Columns(fields ...Field) PostgresInsertQu...
    method Values (line 418) | func (q PostgresInsertQuery) Values(values ...any) PostgresInsertQuery {
    method ColumnValues (line 424) | func (q PostgresInsertQuery) ColumnValues(colmapper func(*Column)) Pos...
    method Select (line 430) | func (q PostgresInsertQuery) Select(query Query) PostgresInsertQuery {
    method OnConflict (line 438) | func (q PostgresInsertQuery) OnConflict(fields ...Field) postgresInser...
    method OnConflictOnConstraint (line 444) | func (q PostgresInsertQuery) OnConflictOnConstraint(constraintName str...
    method Where (line 469) | func (q PostgresInsertQuery) Where(predicates ...Predicate) PostgresIn...
    method Returning (line 475) | func (q PostgresInsertQuery) Returning(fields ...Field) PostgresInsert...
    method SetFetchableFields (line 481) | func (q PostgresInsertQuery) SetFetchableFields(fields []Field) (query...
    method GetFetchableFields (line 486) | func (q PostgresInsertQuery) GetFetchableFields() []Field {
    method GetDialect (line 491) | func (q PostgresInsertQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 494) | func (q PostgresInsertQuery) SetDialect(dialect string) PostgresInsert...
  method InsertInto (line 403) | func (b postgresQueryBuilder) InsertInto(table Table) PostgresInsertQuery {
  type postgresInsertConflict (line 435) | type postgresInsertConflict struct
    method Where (line 450) | func (c postgresInsertConflict) Where(predicates ...Predicate) postgre...
    method DoNothing (line 457) | func (c postgresInsertConflict) DoNothing() PostgresInsertQuery {
    method DoUpdateSet (line 463) | func (c postgresInsertConflict) DoUpdateSet(assignments ...Assignment)...
  type MySQLInsertQuery (line 500) | type MySQLInsertQuery
    method WriteSQL (line 505) | func (q MySQLInsertQuery) WriteSQL(ctx context.Context, dialect string...
    method Columns (line 529) | func (q MySQLInsertQuery) Columns(fields ...Field) MySQLInsertQuery {
    method Values (line 535) | func (q MySQLInsertQuery) Values(values ...any) MySQLInsertQuery {
    method As (line 541) | func (q MySQLInsertQuery) As(rowAlias string) MySQLInsertQuery {
    method ColumnValues (line 547) | func (q MySQLInsertQuery) ColumnValues(colmapper func(*Column)) MySQLI...
    method Select (line 553) | func (q MySQLInsertQuery) Select(query Query) MySQLInsertQuery {
    method OnDuplicateKeyUpdate (line 560) | func (q MySQLInsertQuery) OnDuplicateKeyUpdate(assignments ...Assignme...
    method Returning (line 566) | func (q MySQLInsertQuery) Returning(fields ...Field) MySQLInsertQuery {
    method SetFetchableFields (line 572) | func (q MySQLInsertQuery) SetFetchableFields(fields []Field) (query Qu...
    method GetFetchableFields (line 577) | func (q MySQLInsertQuery) GetFetchableFields() []Field {
    method GetDialect (line 582) | func (q MySQLInsertQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 585) | func (q MySQLInsertQuery) SetDialect(dialect string) MySQLInsertQuery {
  method InsertInto (line 510) | func (b mysqlQueryBuilder) InsertInto(table Table) MySQLInsertQuery {
  method InsertIgnoreInto (line 519) | func (b mysqlQueryBuilder) InsertIgnoreInto(table Table) MySQLInsertQuery {
  type SQLServerInsertQuery (line 591) | type SQLServerInsertQuery
    method WriteSQL (line 596) | func (q SQLServerInsertQuery) WriteSQL(ctx context.Context, dialect st...
    method Columns (line 610) | func (q SQLServerInsertQuery) Columns(fields ...Field) SQLServerInsert...
    method Values (line 616) | func (q SQLServerInsertQuery) Values(values ...any) SQLServerInsertQue...
    method ColumnValues (line 622) | func (q SQLServerInsertQuery) ColumnValues(colmapper func(*Column)) SQ...
    method Select (line 628) | func (q SQLServerInsertQuery) Select(query Query) SQLServerInsertQuery {
    method SetFetchableFields (line 634) | func (q SQLServerInsertQuery) SetFetchableFields(fields []Field) (quer...
    method GetFetchableFields (line 639) | func (q SQLServerInsertQuery) GetFetchableFields() []Field {
    method GetDialect (line 644) | func (q SQLServerInsertQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 647) | func (q SQLServerInsertQuery) SetDialect(dialect string) SQLServerInse...
  method InsertInto (line 601) | func (b sqlserverQueryBuilder) InsertInto(table Table) SQLServerInsertQu...

FILE: insert_query_test.go
  function TestSQLiteInsertQuery (line 9) | func TestSQLiteInsertQuery(t *testing.T) {
  function TestPostgresInsertQuery (line 142) | func TestPostgresInsertQuery(t *testing.T) {
  function TestMySQLInsertQuery (line 275) | func TestMySQLInsertQuery(t *testing.T) {
  function TestSQLServerInsertQuery (line 403) | func TestSQLServerInsertQuery(t *testing.T) {
  function TestInsertQuery (line 487) | func TestInsertQuery(t *testing.T) {

FILE: integration_test.go
  type Color (line 19) | type Color
    method Enumerate (line 35) | func (c Color) Enumerate() []string { return colorNames[:] }
  constant ColorInvalid (line 22) | ColorInvalid Color = iota
  constant ColorRed (line 23) | ColorRed
  constant ColorGreen (line 24) | ColorGreen
  constant ColorBlue (line 25) | ColorBlue
  type Direction (line 37) | type Direction
    method Enumerate (line 47) | func (d Direction) Enumerate() []string {
  constant DirectionInvalid (line 40) | DirectionInvalid = Direction("")
  constant DirectionNorth (line 41) | DirectionNorth   = Direction("north")
  constant DirectionSouth (line 42) | DirectionSouth   = Direction("south")
  constant DirectionEast (line 43) | DirectionEast    = Direction("east")
  constant DirectionWest (line 44) | DirectionWest    = Direction("west")
  function TestRow (line 57) | func TestRow(t *testing.T) {
  function TestRowScan (line 451) | func TestRowScan(t *testing.T) {
  function preprocessDSN (line 783) | func preprocessDSN(dialect string, dsn string) string {

FILE: internal/googleuuid/googleuuid.go
  function ParseBytes (line 42) | func ParseBytes(b []byte) (uuid [16]byte, err error) {
  function Parse (line 85) | func Parse(s string) (uuid [16]byte, err error) {
  function xtob (line 135) | func xtob(x1, x2 byte) (byte, bool) {
  function EncodeHex (line 142) | func EncodeHex(dst []byte, uuid [16]byte) {

FILE: internal/pqarray/pqarray.go
  function Array (line 39) | func Array(a interface{}) interface {
  type ArrayDelimiter (line 80) | type ArrayDelimiter interface
  type BoolArray (line 86) | type BoolArray
    method Scan (line 89) | func (a *BoolArray) Scan(src interface{}) error {
    method scanBytes (line 103) | func (a *BoolArray) scanBytes(src []byte) error {
    method Value (line 131) | func (a BoolArray) Value() (driver.Value, error) {
  type ByteaArray (line 160) | type ByteaArray
    method Scan (line 163) | func (a *ByteaArray) Scan(src interface{}) error {
    method scanBytes (line 177) | func (a *ByteaArray) scanBytes(src []byte) error {
    method Value (line 199) | func (a ByteaArray) Value() (driver.Value, error) {
  type Float64Array (line 232) | type Float64Array
    method Scan (line 235) | func (a *Float64Array) Scan(src interface{}) error {
    method scanBytes (line 249) | func (a *Float64Array) scanBytes(src []byte) error {
    method Value (line 269) | func (a Float64Array) Value() (driver.Value, error) {
  type Float32Array (line 294) | type Float32Array
    method Scan (line 297) | func (a *Float32Array) Scan(src interface{}) error {
    method scanBytes (line 311) | func (a *Float32Array) scanBytes(src []byte) error {
    method Value (line 333) | func (a Float32Array) Value() (driver.Value, error) {
  type GenericArray (line 358) | type GenericArray struct
    method evaluateDestination (line 360) | func (GenericArray) evaluateDestination(rt reflect.Type) (reflect.Type...
    method Scan (line 396) | func (a GenericArray) Scan(src interface{}) error {
    method scanBytes (line 428) | func (a GenericArray) scanBytes(src []byte, dv reflect.Value) error {
    method Value (line 482) | func (a GenericArray) Value() (driver.Value, error) {
  type Int64Array (line 512) | type Int64Array
    method Scan (line 515) | func (a *Int64Array) Scan(src interface{}) error {
    method scanBytes (line 529) | func (a *Int64Array) scanBytes(src []byte) error {
    method Value (line 549) | func (a Int64Array) Value() (driver.Value, error) {
  type Int32Array (line 573) | type Int32Array
    method Scan (line 576) | func (a *Int32Array) Scan(src interface{}) error {
    method scanBytes (line 590) | func (a *Int32Array) scanBytes(src []byte) error {
    method Value (line 612) | func (a Int32Array) Value() (driver.Value, error) {
  type StringArray (line 636) | type StringArray
    method Scan (line 639) | func (a *StringArray) Scan(src interface{}) error {
    method scanBytes (line 653) | func (a *StringArray) scanBytes(src []byte) error {
    method Value (line 673) | func (a StringArray) Value() (driver.Value, error) {
  function appendArray (line 700) | func appendArray(b []byte, rv reflect.Value, n int) ([]byte, string, err...
  function appendArrayElement (line 728) | func appendArrayElement(b []byte, rv reflect.Value) ([]byte, string, err...
  function appendArrayQuotedBytes (line 764) | func appendArrayQuotedBytes(b, v []byte) []byte {
  function appendValue (line 781) | func appendValue(b []byte, v driver.Value) ([]byte, error) {
  function parseArray (line 791) | func parseArray(src, del []byte) (dims []int, elems [][]byte, err error) {
  function scanLinearArray (line 896) | func scanLinearArray(src, del []byte, typ string) (elems [][]byte, err e...
  function parseBytea (line 907) | func parseBytea(s []byte) (result []byte, err error) {
  function encode (line 953) | func encode(parameterStatus *parameterStatus, x interface{}, pgtypOid Oi...
  type parameterStatus (line 981) | type parameterStatus struct
  function encodeBytea (line 991) | func encodeBytea(serverVersion int, v []byte) (result []byte) {
  function formatTs (line 1019) | func formatTs(t time.Time) []byte {
  function FormatTimestamp (line 1034) | func FormatTimestamp(t time.Time) []byte {
  type Oid (line 1068) | type Oid
  constant T_bool (line 1071) | T_bool             Oid = 16
  constant T_bytea (line 1072) | T_bytea            Oid = 17
  constant T_char (line 1073) | T_char             Oid = 18
  constant T_name (line 1074) | T_name             Oid = 19
  constant T_int8 (line 1075) | T_int8             Oid = 20
  constant T_int2 (line 1076) | T_int2             Oid = 21
  constant T_int2vector (line 1077) | T_int2vector       Oid = 22
  constant T_int4 (line 1078) | T_int4             Oid = 23
  constant T_regproc (line 1079) | T_regproc          Oid = 24
  constant T_text (line 1080) | T_text             Oid = 25
  constant T_oid (line 1081) | T_oid              Oid = 26
  constant T_tid (line 1082) | T_tid              Oid = 27
  constant T_xid (line 1083) | T_xid              Oid = 28
  constant T_cid (line 1084) | T_cid              Oid = 29
  constant T_oidvector (line 1085) | T_oidvector        Oid = 30
  constant T_pg_ddl_command (line 1086) | T_pg_ddl_command   Oid = 32
  constant T_pg_type (line 1087) | T_pg_type          Oid = 71
  constant T_pg_attribute (line 1088) | T_pg_attribute     Oid = 75
  constant T_pg_proc (line 1089) | T_pg_proc          Oid = 81
  constant T_pg_class (line 1090) | T_pg_class         Oid = 83
  constant T_json (line 1091) | T_json             Oid = 114
  constant T_xml (line 1092) | T_xml              Oid = 142
  constant T__xml (line 1093) | T__xml             Oid = 143
  constant T_pg_node_tree (line 1094) | T_pg_node_tree     Oid = 194
  constant T__json (line 1095) | T__json            Oid = 199
  constant T_smgr (line 1096) | T_smgr             Oid = 210
  constant T_index_am_handler (line 1097) | T_index_am_handler Oid = 325
  constant T_point (line 1098) | T_point            Oid = 600
  constant T_lseg (line 1099) | T_lseg             Oid = 601
  constant T_path (line 1100) | T_path             Oid = 602
  constant T_box (line 1101) | T_box              Oid = 603
  constant T_polygon (line 1102) | T_polygon          Oid = 604
  constant T_line (line 1103) | T_line             Oid = 628
  constant T__line (line 1104) | T__line            Oid = 629
  constant T_cidr (line 1105) | T_cidr             Oid = 650
  constant T__cidr (line 1106) | T__cidr            Oid = 651
  constant T_float4 (line 1107) | T_float4           Oid = 700
  constant T_float8 (line 1108) | T_float8           Oid = 701
  constant T_abstime (line 1109) | T_abstime          Oid = 702
  constant T_reltime (line 1110) | T_reltime          Oid = 703
  constant T_tinterval (line 1111) | T_tinterval        Oid = 704
  constant T_unknown (line 1112) | T_unknown          Oid = 705
  constant T_circle (line 1113) | T_circle           Oid = 718
  constant T__circle (line 1114) | T__circle          Oid = 719
  constant T_money (line 1115) | T_money            Oid = 790
  constant T__money (line 1116) | T__money           Oid = 791
  constant T_macaddr (line 1117) | T_macaddr          Oid = 829
  constant T_inet (line 1118) | T_inet             Oid = 869
  constant T__bool (line 1119) | T__bool            Oid = 1000
  constant T__bytea (line 1120) | T__bytea           Oid = 1001
  constant T__char (line 1121) | T__char            Oid = 1002
  constant T__name (line 1122) | T__name            Oid = 1003
  constant T__int2 (line 1123) | T__int2            Oid = 1005
  constant T__int2vector (line 1124) | T__int2vector      Oid = 1006
  constant T__int4 (line 1125) | T__int4            Oid = 1007
  constant T__regproc (line 1126) | T__regproc         Oid = 1008
  constant T__text (line 1127) | T__text            Oid = 1009
  constant T__tid (line 1128) | T__tid             Oid = 1010
  constant T__xid (line 1129) | T__xid             Oid = 1011
  constant T__cid (line 1130) | T__cid             Oid = 1012
  constant T__oidvector (line 1131) | T__oidvector       Oid = 1013
  constant T__bpchar (line 1132) | T__bpchar          Oid = 1014
  constant T__varchar (line 1133) | T__varchar         Oid = 1015
  constant T__int8 (line 1134) | T__int8            Oid = 1016
  constant T__point (line 1135) | T__point           Oid = 1017
  constant T__lseg (line 1136) | T__lseg            Oid = 1018
  constant T__path (line 1137) | T__path            Oid = 1019
  constant T__box (line 1138) | T__box             Oid = 1020
  constant T__float4 (line 1139) | T__float4          Oid = 1021
  constant T__float8 (line 1140) | T__float8          Oid = 1022
  constant T__abstime (line 1141) | T__abstime         Oid = 1023
  constant T__reltime (line 1142) | T__reltime         Oid = 1024
  constant T__tinterval (line 1143) | T__tinterval       Oid = 1025
  constant T__polygon (line 1144) | T__polygon         Oid = 1027
  constant T__oid (line 1145) | T__oid             Oid = 1028
  constant T_aclitem (line 1146) | T_aclitem          Oid = 1033
  constant T__aclitem (line 1147) | T__aclitem         Oid = 1034
  constant T__macaddr (line 1148) | T__macaddr         Oid = 1040
  constant T__inet (line 1149) | T__inet            Oid = 1041
  constant T_bpchar (line 1150) | T_bpchar           Oid = 1042
  constant T_varchar (line 1151) | T_varchar          Oid = 1043
  constant T_date (line 1152) | T_date             Oid = 1082
  constant T_time (line 1153) | T_time             Oid = 1083
  constant T_timestamp (line 1154) | T_timestamp        Oid = 1114
  constant T__timestamp (line 1155) | T__timestamp       Oid = 1115
  constant T__date (line 1156) | T__date            Oid = 1182
  constant T__time (line 1157) | T__time            Oid = 1183
  constant T_timestamptz (line 1158) | T_timestamptz      Oid = 1184
  constant T__timestamptz (line 1159) | T__timestamptz     Oid = 1185
  constant T_interval (line 1160) | T_interval         Oid = 1186
  constant T__interval (line 1161) | T__interval        Oid = 1187
  constant T__numeric (line 1162) | T__numeric         Oid = 1231
  constant T_pg_database (line 1163) | T_pg_database      Oid = 1248
  constant T__cstring (line 1164) | T__cstring         Oid = 1263
  constant T_timetz (line 1165) | T_timetz           Oid = 1266
  constant T__timetz (line 1166) | T__timetz          Oid = 1270
  constant T_bit (line 1167) | T_bit              Oid = 1560
  constant T__bit (line 1168) | T__bit             Oid = 1561
  constant T_varbit (line 1169) | T_varbit           Oid = 1562
  constant T__varbit (line 1170) | T__varbit          Oid = 1563
  constant T_numeric (line 1171) | T_numeric          Oid = 1700
  constant T_refcursor (line 1172) | T_refcursor        Oid = 1790
  constant T__refcursor (line 1173) | T__refcursor       Oid = 2201
  constant T_regprocedure (line 1174) | T_regprocedure     Oid = 2202
  constant T_regoper (line 1175) | T_regoper          Oid = 2203
  constant T_regoperator (line 1176) | T_regoperator      Oid = 2204
  constant T_regclass (line 1177) | T_regclass         Oid = 2205
  constant T_regtype (line 1178) | T_regtype          Oid = 2206
  constant T__regprocedure (line 1179) | T__regprocedure    Oid = 2207
  constant T__regoper (line 1180) | T__regoper         Oid = 2208
  constant T__regoperator (line 1181) | T__regoperator     Oid = 2209
  constant T__regclass (line 1182) | T__regclass        Oid = 2210
  constant T__regtype (line 1183) | T__regtype         Oid = 2211
  constant T_record (line 1184) | T_record           Oid = 2249
  constant T_cstring (line 1185) | T_cstring          Oid = 2275
  constant T_any (line 1186) | T_any              Oid = 2276
  constant T_anyarray (line 1187) | T_anyarray         Oid = 2277
  constant T_void (line 1188) | T_void             Oid = 2278
  constant T_trigger (line 1189) | T_trigger          Oid = 2279
  constant T_language_handler (line 1190) | T_language_handler Oid = 2280
  constant T_internal (line 1191) | T_internal         Oid = 2281
  constant T_opaque (line 1192) | T_opaque           Oid = 2282
  constant T_anyelement (line 1193) | T_anyelement       Oid = 2283
  constant T__record (line 1194) | T__record          Oid = 2287
  constant T_anynonarray (line 1195) | T_anynonarray      Oid = 2776
  constant T_pg_authid (line 1196) | T_pg_authid        Oid = 2842
  constant T_pg_auth_members (line 1197) | T_pg_auth_members  Oid = 2843
  constant T__txid_snapshot (line 1198) | T__txid_snapshot   Oid = 2949
  constant T_uuid (line 1199) | T_uuid             Oid = 2950
  constant T__uuid (line 1200) | T__uuid            Oid = 2951
  constant T_txid_snapshot (line 1201) | T_txid_snapshot    Oid = 2970
  constant T_fdw_handler (line 1202) | T_fdw_handler      Oid = 3115
  constant T_pg_lsn (line 1203) | T_pg_lsn           Oid = 3220
  constant T__pg_lsn (line 1204) | T__pg_lsn          Oid = 3221
  constant T_tsm_handler (line 1205) | T_tsm_handler      Oid = 3310
  constant T_anyenum (line 1206) | T_anyenum          Oid = 3500
  constant T_tsvector (line 1207) | T_tsvector         Oid = 3614
  constant T_tsquery (line 1208) | T_tsquery          Oid = 3615
  constant T_gtsvector (line 1209) | T_gtsvector        Oid = 3642
  constant T__tsvector (line 1210) | T__tsvector        Oid = 3643
  constant T__gtsvector (line 1211) | T__gtsvector       Oid = 3644
  constant T__tsquery (line 1212) | T__tsquery         Oid = 3645
  constant T_regconfig (line 1213) | T_regconfig        Oid = 3734
  constant T__regconfig (line 1214) | T__regconfig       Oid = 3735
  constant T_regdictionary (line 1215) | T_regdictionary    Oid = 3769
  constant T__regdictionary (line 1216) | T__regdictionary   Oid = 3770
  constant T_jsonb (line 1217) | T_jsonb            Oid = 3802
  constant T__jsonb (line 1218) | T__jsonb           Oid = 3807
  constant T_anyrange (line 1219) | T_anyrange         Oid = 3831
  constant T_event_trigger (line 1220) | T_event_trigger    Oid = 3838
  constant T_int4range (line 1221) | T_int4range        Oid = 3904
  constant T__int4range (line 1222) | T__int4range       Oid = 3905
  constant T_numrange (line 1223) | T_numrange         Oid = 3906
  constant T__numrange (line 1224) | T__numrange        Oid = 3907
  constant T_tsrange (line 1225) | T_tsrange          Oid = 3908
  constant T__tsrange (line 1226) | T__tsrange         Oid = 3909
  constant T_tstzrange (line 1227) | T_tstzrange        Oid = 3910
  constant T__tstzrange (line 1228) | T__tstzrange       Oid = 3911
  constant T_daterange (line 1229) | T_daterange        Oid = 3912
  constant T__daterange (line 1230) | T__daterange       Oid = 3913
  constant T_int8range (line 1231) | T_int8range        Oid = 3926
  constant T__int8range (line 1232) | T__int8range       Oid = 3927
  constant T_pg_shseclabel (line 1233) | T_pg_shseclabel    Oid = 4066
  constant T_regnamespace (line 1234) | T_regnamespace     Oid = 4089
  constant T__regnamespace (line 1235) | T__regnamespace    Oid = 4090
  constant T_regrole (line 1236) | T_regrole          Oid = 4096
  constant T__regrole (line 1237) | T__regrole         Oid = 4097

FILE: internal/testutil/testutil.go
  function Diff (line 14) | func Diff[T any](got, want T) string {
  function Callers (line 26) | func Callers() string {

FILE: joins.go
  constant JoinInner (line 11) | JoinInner = "JOIN"
  constant JoinLeft (line 12) | JoinLeft  = "LEFT JOIN"
  constant JoinRight (line 13) | JoinRight = "RIGHT JOIN"
  constant JoinFull (line 14) | JoinFull  = "FULL JOIN"
  constant JoinCross (line 15) | JoinCross = "CROSS JOIN"
  type JoinTable (line 19) | type JoinTable struct
    method WriteSQL (line 64) | func (join JoinTable) WriteSQL(ctx context.Context, dialect string, bu...
  function JoinUsing (line 27) | func JoinUsing(table Table, fields ...Field) JoinTable {
  function Join (line 32) | func Join(table Table, predicates ...Predicate) JoinTable {
  function LeftJoin (line 37) | func LeftJoin(table Table, predicates ...Predicate) JoinTable {
  function FullJoin (line 42) | func FullJoin(table Table, predicates ...Predicate) JoinTable {
  function CrossJoin (line 47) | func CrossJoin(table Table) JoinTable {
  function CustomJoin (line 52) | func CustomJoin(joinOperator string, table Table, predicates ...Predicat...
  function writeJoinTables (line 135) | func writeJoinTables(ctx context.Context, dialect string, buf *bytes.Buf...

FILE: joins_test.go
  function TestJoinTables (line 5) | func TestJoinTables(t *testing.T) {

FILE: logger.go
  type QueryStats (line 19) | type QueryStats struct
  type LogSettings (line 69) | type LogSettings struct
  type SqLogger (line 84) | type SqLogger interface
  type sqLogger (line 93) | type sqLogger struct
    method SqLogSettings (line 150) | func (l *sqLogger) SqLogSettings(ctx context.Context, settings *LogSet...
    method SqLogQuery (line 158) | func (l *sqLogger) SqLogQuery(ctx context.Context, queryStats QuerySta...
  type LoggerConfig (line 99) | type LoggerConfig struct
  function NewLogger (line 142) | func NewLogger(w io.Writer, prefix string, flag int, config LoggerConfig...
  function Log (line 249) | func Log(db DB) interface {
  function VerboseLog (line 260) | func VerboseLog(db DB) interface {
  function SetDefaultLogSettings (line 275) | func SetDefaultLogSettings(logSettings func(context.Context, *LogSetting...
  function SetDefaultLogQuery (line 283) | func SetDefaultLogQuery(logQuery func(context.Context, QueryStats)) {
  type sqLogStruct (line 287) | type sqLogStruct struct
    method SqLogSettings (line 294) | func (l *sqLogStruct) SqLogSettings(ctx context.Context, logSettings *...
    method SqLogQuery (line 301) | func (l *sqLogStruct) SqLogQuery(ctx context.Context, queryStats Query...
  constant colorReset (line 309) | colorReset  = "\x1b[0m"
  constant colorRed (line 310) | colorRed    = "\x1b[91m"
  constant colorGreen (line 311) | colorGreen  = "\x1b[92m"
  constant colorYellow (line 312) | colorYellow = "\x1b[93m"
  constant colorBlue (line 313) | colorBlue   = "\x1b[94m"
  constant colorPurple (line 314) | colorPurple = "\x1b[95m"
  constant colorCyan (line 315) | colorCyan   = "\x1b[96m"
  constant colorGray (line 316) | colorGray   = "\x1b[97m"
  constant colorWhite (line 317) | colorWhite  = "\x1b[97m"

FILE: logger_test.go
  function TestLogger (line 15) | func TestLogger(t *testing.T) {

FILE: misc.go
  type ValueExpression (line 12) | type ValueExpression struct
    method WriteSQL (line 27) | func (e ValueExpression) WriteSQL(ctx context.Context, dialect string,...
    method As (line 32) | func (e ValueExpression) As(alias string) ValueExpression {
    method In (line 38) | func (e ValueExpression) In(val any) Predicate { return In(e.value, va...
    method Eq (line 41) | func (e ValueExpression) Eq(val any) Predicate { return Eq(e.value, va...
    method Ne (line 44) | func (e ValueExpression) Ne(val any) Predicate { return Ne(e.value, va...
    method Lt (line 47) | func (e ValueExpression) Lt(val any) Predicate { return Lt(e.value, va...
    method Le (line 50) | func (e ValueExpression) Le(val any) Predicate { return Le(e.value, va...
    method Gt (line 53) | func (e ValueExpression) Gt(val any) Predicate { return Gt(e.value, va...
    method Ge (line 56) | func (e ValueExpression) Ge(val any) Predicate { return Ge(e.value, va...
    method GetAlias (line 59) | func (e ValueExpression) GetAlias() string { return e.alias }
    method IsField (line 62) | func (e ValueExpression) IsField() {}
    method IsArray (line 65) | func (e ValueExpression) IsArray() {}
    method IsBinary (line 68) | func (e ValueExpression) IsBinary() {}
    method IsBoolean (line 71) | func (e ValueExpression) IsBoolean() {}
    method IsEnum (line 74) | func (e ValueExpression) IsEnum() {}
    method IsJSON (line 77) | func (e ValueExpression) IsJSON() {}
    method IsNumber (line 80) | func (e ValueExpression) IsNumber() {}
    method IsString (line 83) | func (e ValueExpression) IsString() {}
    method IsTime (line 86) | func (e ValueExpression) IsTime() {}
    method IsUUID (line 89) | func (e ValueExpression) IsUUID() {}
  function Value (line 24) | func Value(value any) ValueExpression { return ValueExpression{value: va...
  type LiteralValue (line 94) | type LiteralValue struct
    method WriteSQL (line 113) | func (v LiteralValue) WriteSQL(ctx context.Context, dialect string, bu...
    method As (line 123) | func (v LiteralValue) As(alias string) LiteralValue {
    method In (line 129) | func (v LiteralValue) In(val any) Predicate { return In(v, val) }
    method Eq (line 132) | func (v LiteralValue) Eq(val any) Predicate { return Eq(v, val) }
    method Ne (line 135) | func (v LiteralValue) Ne(val any) Predicate { return Ne(v, val) }
    method Lt (line 138) | func (v LiteralValue) Lt(val any) Predicate { return Lt(v, val) }
    method Le (line 141) | func (v LiteralValue) Le(val any) Predicate { return Le(v, val) }
    method Gt (line 144) | func (v LiteralValue) Gt(val any) Predicate { return Gt(v, val) }
    method Ge (line 147) | func (v LiteralValue) Ge(val any) Predicate { return Ge(v, val) }
    method GetAlias (line 150) | func (v LiteralValue) GetAlias() string { return v.alias }
    method IsField (line 153) | func (v LiteralValue) IsField() {}
    method IsBinary (line 156) | func (v LiteralValue) IsBinary() {}
    method IsBoolean (line 159) | func (v LiteralValue) IsBoolean() {}
    method IsNumber (line 162) | func (v LiteralValue) IsNumber() {}
    method IsString (line 165) | func (v LiteralValue) IsString() {}
    method IsTime (line 168) | func (v LiteralValue) IsTime() {}
  function Literal (line 110) | func Literal(value any) LiteralValue { return LiteralValue{value: value} }
  type DialectExpression (line 172) | type DialectExpression struct
    method WriteSQL (line 207) | func (e DialectExpression) WriteSQL(ctx context.Context, dialect strin...
    method DialectValue (line 217) | func (e DialectExpression) DialectValue(dialect string, value any) Dia...
    method DialectExpr (line 223) | func (e DialectExpression) DialectExpr(dialect string, format string, ...
    method IsTable (line 229) | func (e DialectExpression) IsTable() {}
    method IsField (line 232) | func (e DialectExpression) IsField() {}
    method IsArray (line 235) | func (e DialectExpression) IsArray() {}
    method IsBinary (line 238) | func (e DialectExpression) IsBinary() {}
    method IsBoolean (line 241) | func (e DialectExpression) IsBoolean() {}
    method IsEnum (line 244) | func (e DialectExpression) IsEnum() {}
    method IsJSON (line 247) | func (e DialectExpression) IsJSON() {}
    method IsNumber (line 250) | func (e DialectExpression) IsNumber() {}
    method IsString (line 253) | func (e DialectExpression) IsString() {}
    method IsTime (line 256) | func (e DialectExpression) IsTime() {}
    method IsUUID (line 259) | func (e DialectExpression) IsUUID() {}
  type DialectCase (line 182) | type DialectCase struct
  function DialectValue (line 196) | func DialectValue(value any) DialectExpression {
  function DialectExpr (line 202) | func DialectExpr(format string, values ...any) DialectExpression {
  type CaseExpression (line 262) | type CaseExpression struct
    method WriteSQL (line 291) | func (e CaseExpression) WriteSQL(ctx context.Context, dialect string, ...
    method When (line 321) | func (e CaseExpression) When(predicate Predicate, result any) CaseExpr...
    method Else (line 327) | func (e CaseExpression) Else(fallback any) CaseExpression {
    method As (line 333) | func (e CaseExpression) As(alias string) CaseExpression {
    method GetAlias (line 339) | func (e CaseExpression) GetAlias() string { return e.alias }
    method IsField (line 342) | func (e CaseExpression) IsField() {}
    method IsArray (line 345) | func (e CaseExpression) IsArray() {}
    method IsBinary (line 348) | func (e CaseExpression) IsBinary() {}
    method IsBoolean (line 351) | func (e CaseExpression) IsBoolean() {}
    method IsEnum (line 354) | func (e CaseExpression) IsEnum() {}
    method IsJSON (line 357) | func (e CaseExpression) IsJSON() {}
    method IsNumber (line 360) | func (e CaseExpression) IsNumber() {}
    method IsString (line 363) | func (e CaseExpression) IsString() {}
    method IsTime (line 366) | func (e CaseExpression) IsTime() {}
    method IsUUID (line 369) | func (e CaseExpression) IsUUID() {}
  type PredicateCase (line 273) | type PredicateCase struct
  function CaseWhen (line 284) | func CaseWhen(predicate Predicate, result any) CaseExpression {
  type SimpleCaseExpression (line 372) | type SimpleCaseExpression struct
    method WriteSQL (line 400) | func (e SimpleCaseExpression) WriteSQL(ctx context.Context, dialect st...
    method When (line 434) | func (e SimpleCaseExpression) When(value any, result any) SimpleCaseEx...
    method Else (line 440) | func (e SimpleCaseExpression) Else(fallback any) SimpleCaseExpression {
    method As (line 446) | func (e SimpleCaseExpression) As(alias string) SimpleCaseExpression {
    method GetAlias (line 452) | func (e SimpleCaseExpression) GetAlias() string { return e.alias }
    method IsField (line 455) | func (e SimpleCaseExpression) IsField() {}
    method IsArray (line 458) | func (e SimpleCaseExpression) IsArray() {}
    method IsBinary (line 461) | func (e SimpleCaseExpression) IsBinary() {}
    method IsBoolean (line 464) | func (e SimpleCaseExpression) IsBoolean() {}
    method IsEnum (line 467) | func (e SimpleCaseExpression) IsEnum() {}
    method IsJSON (line 470) | func (e SimpleCaseExpression) IsJSON() {}
    method IsNumber (line 473) | func (e SimpleCaseExpression) IsNumber() {}
    method IsString (line 476) | func (e SimpleCaseExpression) IsString() {}
    method IsTime (line 479) | func (e SimpleCaseExpression) IsTime() {}
    method IsUUID (line 482) | func (e SimpleCaseExpression) IsUUID() {}
  type SimpleCase (line 384) | type SimpleCase struct
  function Case (line 395) | func Case(expression any) SimpleCaseExpression {
  function Count (line 485) | func Count(field Field) Expression { return Expr("COUNT({})", field) }
  function CountStar (line 488) | func CountStar() Expression { return Expr("COUNT(*)") }
  function Sum (line 491) | func Sum(num Number) Expression { return Expr("SUM({})", num) }
  function Avg (line 494) | func Avg(num Number) Expression { return Expr("AVG({})", num) }
  function Min (line 497) | func Min(field Field) Expression { return Expr("MIN({})", field) }
  function Max (line 500) | func Max(field Field) Expression { return Expr("MAX({})", field) }
  type SelectValues (line 510) | type SelectValues struct
    method WriteSQL (line 522) | func (vs SelectValues) WriteSQL(ctx context.Context, dialect string, b...
    method Field (line 549) | func (vs SelectValues) Field(name string) AnyField {
    method SetFetchableFields (line 555) | func (vs SelectValues) SetFetchableFields([]Field) (query Query, ok bo...
    method GetDialect (line 559) | func (vs SelectValues) GetDialect() string { return "" }
    method GetAlias (line 562) | func (vs SelectValues) GetAlias() string { return vs.Alias }
    method IsTable (line 565) | func (vs SelectValues) IsTable() {}
  type TableValues (line 574) | type TableValues struct
    method WriteSQL (line 586) | func (vs TableValues) WriteSQL(ctx context.Context, dialect string, bu...
    method Field (line 619) | func (vs TableValues) Field(name string) AnyField {
    method SetFetchableFields (line 625) | func (vs TableValues) SetFetchableFields([]Field) (query Query, ok boo...
    method GetDialect (line 629) | func (vs TableValues) GetDialect() string { return "" }
    method GetAlias (line 632) | func (vs TableValues) GetAlias() string { return vs.Alias }
    method GetColumns (line 635) | func (vs TableValues) GetColumns() []string { return vs.Columns }
    method IsTable (line 638) | func (vs TableValues) IsTable() {}

FILE: misc_test.go
  function TestValueExpression (line 12) | func TestValueExpression(t *testing.T) {
  function TestLiteralExpression (line 59) | func TestLiteralExpression(t *testing.T) {
  function TestDialectExpression (line 107) | func TestDialectExpression(t *testing.T) {
  function TestCaseExpressions (line 137) | func TestCaseExpressions(t *testing.T) {
  function TestSelectValues (line 205) | func TestSelectValues(t *testing.T) {
  function TestTableValues (line 290) | func TestTableValues(t *testing.T) {

FILE: row_column.go
  type Row (line 20) | type Row struct
    method Columns (line 36) | func (row *Row) Columns() []string {
    method ColumnTypes (line 53) | func (row *Row) ColumnTypes() []*sql.ColumnType {
    method Values (line 70) | func (row *Row) Values() []any {
    method Value (line 99) | func (row *Row) Value(format string, values ...any) any {
    method Scan (line 121) | func (row *Row) Scan(destPtr any, format string, values ...any) {
    method ScanField (line 129) | func (row *Row) ScanField(destPtr any, field Field) {
    method scan (line 136) | func (row *Row) scan(destPtr any, field Field, skip int) {
    method Array (line 212) | func (row *Row) Array(destPtr any, format string, values ...any) {
    method ArrayField (line 221) | func (row *Row) ArrayField(destPtr any, field Array) {
    method array (line 228) | func (row *Row) array(destPtr any, field Array, skip int) {
    method Bytes (line 325) | func (row *Row) Bytes(format string, values ...any) []byte {
    method BytesField (line 371) | func (row *Row) BytesField(field Binary) []byte {
    method Bool (line 397) | func (row *Row) Bool(format string, values ...any) bool {
    method BoolField (line 440) | func (row *Row) BoolField(field Boolean) bool {
    method NullBool (line 448) | func (row *Row) NullBool(format string, values ...any) sql.NullBool {
    method NullBoolField (line 491) | func (row *Row) NullBoolField(field Boolean) sql.NullBool {
    method Enum (line 508) | func (row *Row) Enum(destPtr Enumeration, format string, values ...any) {
    method EnumField (line 516) | func (row *Row) EnumField(destPtr Enumeration, field Enum) {
    method enum (line 523) | func (row *Row) enum(destPtr Enumeration, field Enum, skip int) {
    method Float64 (line 564) | func (row *Row) Float64(format string, values ...any) float64 {
    method Float64Field (line 599) | func (row *Row) Float64Field(field Number) float64 {
    method NullFloat64 (line 607) | func (row *Row) NullFloat64(format string, values ...any) sql.NullFloa...
    method NullFloat64Field (line 642) | func (row *Row) NullFloat64Field(field Number) sql.NullFloat64 {
    method Int (line 659) | func (row *Row) Int(format string, values ...any) int {
    method IntField (line 694) | func (row *Row) IntField(field Number) int {
    method Int64 (line 702) | func (row *Row) Int64(format string, values ...any) int64 {
    method Int64Field (line 737) | func (row *Row) Int64Field(field Number) int64 {
    method NullInt64 (line 745) | func (row *Row) NullInt64(format string, values ...any) sql.NullInt64 {
    method NullInt64Field (line 780) | func (row *Row) NullInt64Field(field Number) sql.NullInt64 {
    method JSON (line 797) | func (row *Row) JSON(destPtr any, format string, values ...any) {
    method JSONField (line 805) | func (row *Row) JSONField(destPtr any, field JSON) {
    method json (line 812) | func (row *Row) json(destPtr any, field JSON, skip int) {
    method String (line 838) | func (row *Row) String(format string, values ...any) string {
    method StringField (line 868) | func (row *Row) StringField(field String) string {
    method NullString (line 876) | func (row *Row) NullString(format string, values ...any) sql.NullString {
    method NullStringField (line 906) | func (row *Row) NullStringField(field String) sql.NullString {
    method Time (line 936) | func (row *Row) Time(format string, values ...any) time.Time {
    method TimeField (line 973) | func (row *Row) TimeField(field Time) time.Time {
    method NullTime (line 981) | func (row *Row) NullTime(format string, values ...any) sql.NullTime {
    method NullTimeField (line 1018) | func (row *Row) NullTimeField(field Time) sql.NullTime {
    method UUID (line 1035) | func (row *Row) UUID(destPtr any, format string, values ...any) {
    method UUIDField (line 1043) | func (row *Row) UUIDField(destPtr any, field UUID) {
    method uuid (line 1050) | func (row *Row) uuid(destPtr any, field UUID, skip int) {
  type Column (line 1094) | type Column struct
    method Set (line 1109) | func (col *Column) Set(field Field, value any) {
    method SetBytes (line 1147) | func (col *Column) SetBytes(field Binary, value []byte) { col.Set(fiel...
    method SetBool (line 1150) | func (col *Column) SetBool(field Boolean, value bool) { col.Set(field,...
    method SetFloat64 (line 1153) | func (col *Column) SetFloat64(field Number, value float64) { col.Set(f...
    method SetInt (line 1156) | func (col *Column) SetInt(field Number, value int) { col.Set(field, va...
    method SetInt64 (line 1159) | func (col *Column) SetInt64(field Number, value int64) { col.Set(field...
    method SetString (line 1162) | func (col *Column) SetString(field String, value string) { col.Set(fie...
    method SetTime (line 1165) | func (col *Column) SetTime(field Time, value time.Time) { col.Set(fiel...
    method SetArray (line 1169) | func (col *Column) SetArray(field Array, value any) { col.Set(field, A...
    method SetEnum (line 1172) | func (col *Column) SetEnum(field Enum, value Enumeration) { col.Set(fi...
    method SetJSON (line 1176) | func (col *Column) SetJSON(field JSON, value any) { col.Set(field, JSO...
    method SetUUID (line 1180) | func (col *Column) SetUUID(field UUID, value any) { col.Set(field, UUI...
  function callsite (line 1182) | func callsite(skip int) string {
  type displayType (line 1190) | type displayType
  constant displayTypeBinary (line 1193) | displayTypeBinary displayType = iota
  constant displayTypeString (line 1194) | displayTypeString
  constant displayTypeUUID (line 1195) | displayTypeUUID
  type nullBytes (line 1204) | type nullBytes struct
    method Scan (line 1211) | func (n *nullBytes) Scan(value any) error {
    method Value (line 1228) | func (n *nullBytes) Value() (driver.Value, error) {

FILE: select_query.go
  type SelectQuery (line 10) | type SelectQuery struct
    method WriteSQL (line 58) | func (q SelectQuery) WriteSQL(ctx context.Context, dialect string, buf...
    method Select (line 308) | func (q SelectQuery) Select(fields ...Field) SelectQuery {
    method SelectDistinct (line 314) | func (q SelectQuery) SelectDistinct(fields ...Field) SelectQuery {
    method SelectOne (line 321) | func (q SelectQuery) SelectOne(fields ...Field) SelectQuery {
    method From (line 327) | func (q SelectQuery) From(table Table) SelectQuery {
    method Join (line 333) | func (q SelectQuery) Join(table Table, predicates ...Predicate) Select...
    method LeftJoin (line 339) | func (q SelectQuery) LeftJoin(table Table, predicates ...Predicate) Se...
    method CrossJoin (line 345) | func (q SelectQuery) CrossJoin(table Table) SelectQuery {
    method CustomJoin (line 351) | func (q SelectQuery) CustomJoin(joinOperator string, table Table, pred...
    method JoinUsing (line 357) | func (q SelectQuery) JoinUsing(table Table, fields ...Field) SelectQue...
    method Where (line 363) | func (q SelectQuery) Where(predicates ...Predicate) SelectQuery {
    method GroupBy (line 369) | func (q SelectQuery) GroupBy(fields ...Field) SelectQuery {
    method Having (line 375) | func (q SelectQuery) Having(predicates ...Predicate) SelectQuery {
    method OrderBy (line 381) | func (q SelectQuery) OrderBy(fields ...Field) SelectQuery {
    method Limit (line 387) | func (q SelectQuery) Limit(limit any) SelectQuery {
    method Offset (line 393) | func (q SelectQuery) Offset(offset any) SelectQuery {
    method As (line 400) | func (q SelectQuery) As(alias string, columns ...string) SelectQuery {
    method Field (line 407) | func (q SelectQuery) Field(name string) AnyField {
    method SetFetchableFields (line 412) | func (q SelectQuery) SetFetchableFields(fields []Field) (query Query, ...
    method GetFetchableFields (line 421) | func (q SelectQuery) GetFetchableFields() []Field {
    method GetDialect (line 426) | func (q SelectQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 429) | func (q SelectQuery) SetDialect(dialect string) SelectQuery {
    method GetAlias (line 435) | func (q SelectQuery) GetAlias() string { return q.Alias }
    method GetColumns (line 438) | func (q SelectQuery) GetColumns() []string { return q.Columns }
    method IsTable (line 441) | func (q SelectQuery) IsTable() {}
    method IsField (line 444) | func (q SelectQuery) IsField() {}
    method IsArray (line 447) | func (q SelectQuery) IsArray() {}
    method IsBinary (line 450) | func (q SelectQuery) IsBinary() {}
    method IsBoolean (line 453) | func (q SelectQuery) IsBoolean() {}
    method IsEnum (line 456) | func (q SelectQuery) IsEnum() {}
    method IsJSON (line 459) | func (q SelectQuery) IsJSON() {}
    method IsNumber (line 462) | func (q SelectQuery) IsNumber() {}
    method IsString (line 465) | func (q SelectQuery) IsString() {}
    method IsTime (line 468) | func (q SelectQuery) IsTime() {}
    method IsUUID (line 471) | func (q SelectQuery) IsUUID() {}
  function Select (line 285) | func Select(fields ...Field) SelectQuery {
  function SelectDistinct (line 290) | func SelectDistinct(fields ...Field) SelectQuery {
  function SelectOne (line 298) | func SelectOne() SelectQuery {
  function From (line 303) | func From(table Table) SelectQuery {
  type SQLiteSelectQuery (line 474) | type SQLiteSelectQuery
    method WriteSQL (line 484) | func (q SQLiteSelectQuery) WriteSQL(ctx context.Context, dialect strin...
    method Select (line 526) | func (q SQLiteSelectQuery) Select(fields ...Field) SQLiteSelectQuery {
    method SelectDistinct (line 532) | func (q SQLiteSelectQuery) SelectDistinct(fields ...Field) SQLiteSelec...
    method SelectOne (line 539) | func (q SQLiteSelectQuery) SelectOne(fields ...Field) SQLiteSelectQuery {
    method From (line 545) | func (q SQLiteSelectQuery) From(table Table) SQLiteSelectQuery {
    method Join (line 551) | func (q SQLiteSelectQuery) Join(table Table, predicates ...Predicate) ...
    method LeftJoin (line 557) | func (q SQLiteSelectQuery) LeftJoin(table Table, predicates ...Predica...
    method CrossJoin (line 563) | func (q SQLiteSelectQuery) CrossJoin(table Table) SQLiteSelectQuery {
    method CustomJoin (line 570) | func (q SQLiteSelectQuery) CustomJoin(joinOperator string, table Table...
    method JoinUsing (line 576) | func (q SQLiteSelectQuery) JoinUsing(table Table, fields ...Field) SQL...
    method Where (line 582) | func (q SQLiteSelectQuery) Where(predicates ...Predicate) SQLiteSelect...
    method GroupBy (line 588) | func (q SQLiteSelectQuery) GroupBy(fields ...Field) SQLiteSelectQuery {
    method Having (line 594) | func (q SQLiteSelectQuery) Having(predicates ...Predicate) SQLiteSelec...
    method OrderBy (line 600) | func (q SQLiteSelectQuery) OrderBy(fields ...Field) SQLiteSelectQuery {
    method Limit (line 606) | func (q SQLiteSelectQuery) Limit(limit any) SQLiteSelectQuery {
    method Offset (line 612) | func (q SQLiteSelectQuery) Offset(offset any) SQLiteSelectQuery {
    method As (line 619) | func (q SQLiteSelectQuery) As(alias string, columns ...string) SQLiteS...
    method Field (line 626) | func (q SQLiteSelectQuery) Field(name string) AnyField {
    method SetFetchableFields (line 631) | func (q SQLiteSelectQuery) SetFetchableFields(fields []Field) (query Q...
    method GetFetchableFields (line 640) | func (q SQLiteSelectQuery) GetFetchableFields() []Field {
    method GetDialect (line 645) | func (q SQLiteSelectQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 648) | func (q SQLiteSelectQuery) SetDialect(dialect string) SQLiteSelectQuery {
    method GetAlias (line 654) | func (q SQLiteSelectQuery) GetAlias() string { return q.Alias }
    method IsTable (line 657) | func (q SQLiteSelectQuery) IsTable() {}
    method IsField (line 660) | func (q SQLiteSelectQuery) IsField() {}
    method IsArray (line 663) | func (q SQLiteSelectQuery) IsArray() {}
    method IsBinary (line 666) | func (q SQLiteSelectQuery) IsBinary() {}
    method IsBoolean (line 669) | func (q SQLiteSelectQuery) IsBoolean() {}
    method IsEnum (line 672) | func (q SQLiteSelectQuery) IsEnum() {}
    method IsJSON (line 675) | func (q SQLiteSelectQuery) IsJSON() {}
    method IsNumber (line 678) | func (q SQLiteSelectQuery) IsNumber() {}
    method IsString (line 681) | func (q SQLiteSelectQuery) IsString() {}
    method IsTime (line 684) | func (q SQLiteSelectQuery) IsTime() {}
    method IsUUID (line 687) | func (q SQLiteSelectQuery) IsUUID() {}
  method Select (line 489) | func (b sqliteQueryBuilder) Select(fields ...Field) SQLiteSelectQuery {
  method SelectDistinct (line 498) | func (b sqliteQueryBuilder) SelectDistinct(fields ...Field) SQLiteSelect...
  method SelectOne (line 508) | func (b sqliteQueryBuilder) SelectOne() SQLiteSelectQuery {
  method From (line 517) | func (b sqliteQueryBuilder) From(table Table) SQLiteSelectQuery {
  type PostgresSelectQuery (line 690) | type PostgresSelectQuery
    method WriteSQL (line 700) | func (q PostgresSelectQuery) WriteSQL(ctx context.Context, dialect str...
    method Select (line 754) | func (q PostgresSelectQuery) Select(fields ...Field) PostgresSelectQue...
    method SelectDistinct (line 760) | func (q PostgresSelectQuery) SelectDistinct(fields ...Field) PostgresS...
    method DistinctOn (line 767) | func (q PostgresSelectQuery) DistinctOn(fields ...Field) PostgresSelec...
    method SelectOne (line 773) | func (q PostgresSelectQuery) SelectOne(fields ...Field) PostgresSelect...
    method From (line 779) | func (q PostgresSelectQuery) From(table Table) PostgresSelectQuery {
    method Join (line 785) | func (q PostgresSelectQuery) Join(table Table, predicates ...Predicate...
    method LeftJoin (line 791) | func (q PostgresSelectQuery) LeftJoin(table Table, predicates ...Predi...
    method FullJoin (line 797) | func (q PostgresSelectQuery) FullJoin(table Table, predicates ...Predi...
    method CrossJoin (line 803) | func (q PostgresSelectQuery) CrossJoin(table Table) PostgresSelectQuery {
    method CustomJoin (line 810) | func (q PostgresSelectQuery) CustomJoin(joinOperator string, table Tab...
    method JoinUsing (line 816) | func (q PostgresSelectQuery) JoinUsing(table Table, fields ...Field) P...
    method Where (line 822) | func (q PostgresSelectQuery) Where(predicates ...Predicate) PostgresSe...
    method GroupBy (line 828) | func (q PostgresSelectQuery) GroupBy(fields ...Field) PostgresSelectQu...
    method Having (line 834) | func (q PostgresSelectQuery) Having(predicates ...Predicate) PostgresS...
    method OrderBy (line 840) | func (q PostgresSelectQuery) OrderBy(fields ...Field) PostgresSelectQu...
    method Limit (line 846) | func (q PostgresSelectQuery) Limit(limit any) PostgresSelectQuery {
    method Offset (line 852) | func (q PostgresSelectQuery) Offset(offset any) PostgresSelectQuery {
    method FetchNext (line 858) | func (q PostgresSelectQuery) FetchNext(n any) PostgresSelectQuery {
    method WithTies (line 864) | func (q PostgresSelectQuery) WithTies() PostgresSelectQuery {
    method LockRows (line 870) | func (q PostgresSelectQuery) LockRows(lockClause string, lockValues .....
    method As (line 878) | func (q PostgresSelectQuery) As(alias string, columns ...string) Postg...
    method Field (line 885) | func (q PostgresSelectQuery) Field(name string) AnyField {
    method SetFetchableFields (line 890) | func (q PostgresSelectQuery) SetFetchableFields(fields []Field) (query...
    method GetFetchableFields (line 899) | func (q PostgresSelectQuery) GetFetchableFields() []Field {
    method GetDialect (line 904) | func (q PostgresSelectQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 907) | func (q PostgresSelectQuery) SetDialect(dialect string) PostgresSelect...
    method GetAlias (line 913) | func (q PostgresSelectQuery) GetAlias() string { return q.Alias }
    method IsTable (line 916) | func (q PostgresSelectQuery) IsTable() {}
    method IsField (line 919) | func (q PostgresSelectQuery) IsField() {}
    method IsArray (line 922) | func (q PostgresSelectQuery) IsArray() {}
    method IsBinary (line 925) | func (q PostgresSelectQuery) IsBinary() {}
    method IsBoolean (line 928) | func (q PostgresSelectQuery) IsBoolean() {}
    method IsEnum (line 931) | func (q PostgresSelectQuery) IsEnum() {}
    method IsJSON (line 934) | func (q PostgresSelectQuery) IsJSON() {}
    method IsNumber (line 937) | func (q PostgresSelectQuery) IsNumber() {}
    method IsString (line 940) | func (q PostgresSelectQuery) IsString() {}
    method IsTime (line 943) | func (q PostgresSelectQuery) IsTime() {}
    method IsUUID (line 946) | func (q PostgresSelectQuery) IsUUID() {}
  method Select (line 705) | func (b postgresQueryBuilder) Select(fields ...Field) PostgresSelectQuery {
  method SelectDistinct (line 717) | func (b postgresQueryBuilder) SelectDistinct(fields ...Field) PostgresSe...
  method SelectOne (line 730) | func (b postgresQueryBuilder) SelectOne() PostgresSelectQuery {
  method From (line 742) | func (b postgresQueryBuilder) From(table Table) PostgresSelectQuery {
  type MySQLSelectQuery (line 949) | type MySQLSelectQuery
    method WriteSQL (line 959) | func (q MySQLSelectQuery) WriteSQL(ctx context.Context, dialect string...
    method Select (line 1013) | func (q MySQLSelectQuery) Select(fields ...Field) MySQLSelectQuery {
    method SelectDistinct (line 1019) | func (q MySQLSelectQuery) SelectDistinct(fields ...Field) MySQLSelectQ...
    method SelectOne (line 1026) | func (q MySQLSelectQuery) SelectOne(fields ...Field) MySQLSelectQuery {
    method From (line 1032) | func (q MySQLSelectQuery) From(table Table) MySQLSelectQuery {
    method Join (line 1038) | func (q MySQLSelectQuery) Join(table Table, predicates ...Predicate) M...
    method LeftJoin (line 1044) | func (q MySQLSelectQuery) LeftJoin(table Table, predicates ...Predicat...
    method FullJoin (line 1050) | func (q MySQLSelectQuery) FullJoin(table Table, predicates ...Predicat...
    method CrossJoin (line 1056) | func (q MySQLSelectQuery) CrossJoin(table Table) MySQLSelectQuery {
    method CustomJoin (line 1063) | func (q MySQLSelectQuery) CustomJoin(joinOperator string, table Table,...
    method JoinUsing (line 1069) | func (q MySQLSelectQuery) JoinUsing(table Table, fields ...Field) MySQ...
    method Where (line 1075) | func (q MySQLSelectQuery) Where(predicates ...Predicate) MySQLSelectQu...
    method GroupBy (line 1081) | func (q MySQLSelectQuery) GroupBy(fields ...Field) MySQLSelectQuery {
    method Having (line 1087) | func (q MySQLSelectQuery) Having(predicates ...Predicate) MySQLSelectQ...
    method OrderBy (line 1093) | func (q MySQLSelectQuery) OrderBy(fields ...Field) MySQLSelectQuery {
    method Limit (line 1099) | func (q MySQLSelectQuery) Limit(limit any) MySQLSelectQuery {
    method Offset (line 1105) | func (q MySQLSelectQuery) Offset(offset any) MySQLSelectQuery {
    method LockRows (line 1111) | func (q MySQLSelectQuery) LockRows(lockClause string, lockValues ...an...
    method As (line 1119) | func (q MySQLSelectQuery) As(alias string, columns ...string) MySQLSel...
    method Field (line 1126) | func (q MySQLSelectQuery) Field(name string) AnyField {
    method SetFetchableFields (line 1131) | func (q MySQLSelectQuery) SetFetchableFields(fields []Field) (query Qu...
    method GetFetchableFields (line 1140) | func (q MySQLSelectQuery) GetFetchableFields() []Field {
    method GetDialect (line 1145) | func (q MySQLSelectQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 1148) | func (q MySQLSelectQuery) SetDialect(dialect string) MySQLSelectQuery {
    method GetAlias (line 1154) | func (q MySQLSelectQuery) GetAlias() string { return q.Alias }
    method IsTable (line 1157) | func (q MySQLSelectQuery) IsTable() {}
    method IsField (line 1160) | func (q MySQLSelectQuery) IsField() {}
    method IsArray (line 1163) | func (q MySQLSelectQuery) IsArray() {}
    method IsBinary (line 1166) | func (q MySQLSelectQuery) IsBinary() {}
    method IsBoolean (line 1169) | func (q MySQLSelectQuery) IsBoolean() {}
    method IsEnum (line 1172) | func (q MySQLSelectQuery) IsEnum() {}
    method IsJSON (line 1175) | func (q MySQLSelectQuery) IsJSON() {}
    method IsNumber (line 1178) | func (q MySQLSelectQuery) IsNumber() {}
    method IsString (line 1181) | func (q MySQLSelectQuery) IsString() {}
    method IsTime (line 1184) | func (q MySQLSelectQuery) IsTime() {}
    method IsUUID (line 1187) | func (q MySQLSelectQuery) IsUUID() {}
  method Select (line 964) | func (b mysqlQueryBuilder) Select(fields ...Field) MySQLSelectQuery {
  method SelectDistinct (line 976) | func (b mysqlQueryBuilder) SelectDistinct(fields ...Field) MySQLSelectQu...
  method SelectOne (line 989) | func (b mysqlQueryBuilder) SelectOne() MySQLSelectQuery {
  method From (line 1001) | func (b mysqlQueryBuilder) From(table Table) MySQLSelectQuery {
  type SQLServerSelectQuery (line 1190) | type SQLServerSelectQuery
    method WriteSQL (line 1200) | func (q SQLServerSelectQuery) WriteSQL(ctx context.Context, dialect st...
    method Select (line 1254) | func (q SQLServerSelectQuery) Select(fields ...Field) SQLServerSelectQ...
    method SelectDistinct (line 1260) | func (q SQLServerSelectQuery) SelectDistinct(fields ...Field) SQLServe...
    method SelectOne (line 1267) | func (q SQLServerSelectQuery) SelectOne(fields ...Field) SQLServerSele...
    method Top (line 1273) | func (q SQLServerSelectQuery) Top(limit any) SQLServerSelectQuery {
    method TopPercent (line 1279) | func (q SQLServerSelectQuery) TopPercent(percentLimit any) SQLServerSe...
    method From (line 1285) | func (q SQLServerSelectQuery) From(table Table) SQLServerSelectQuery {
    method Join (line 1291) | func (q SQLServerSelectQuery) Join(table Table, predicates ...Predicat...
    method LeftJoin (line 1297) | func (q SQLServerSelectQuery) LeftJoin(table Table, predicates ...Pred...
    method FullJoin (line 1303) | func (q SQLServerSelectQuery) FullJoin(table Table, predicates ...Pred...
    method CrossJoin (line 1309) | func (q SQLServerSelectQuery) CrossJoin(table Table) SQLServerSelectQu...
    method CustomJoin (line 1316) | func (q SQLServerSelectQuery) CustomJoin(joinOperator string, table Ta...
    method Where (line 1322) | func (q SQLServerSelectQuery) Where(predicates ...Predicate) SQLServer...
    method GroupBy (line 1328) | func (q SQLServerSelectQuery) GroupBy(fields ...Field) SQLServerSelect...
    method Having (line 1334) | func (q SQLServerSelectQuery) Having(predicates ...Predicate) SQLServe...
    method OrderBy (line 1340) | func (q SQLServerSelectQuery) OrderBy(fields ...Field) SQLServerSelect...
    method Offset (line 1346) | func (q SQLServerSelectQuery) Offset(offset any) SQLServerSelectQuery {
    method FetchNext (line 1352) | func (q SQLServerSelectQuery) FetchNext(n any) SQLServerSelectQuery {
    method WithTies (line 1358) | func (q SQLServerSelectQuery) WithTies() SQLServerSelectQuery {
    method As (line 1365) | func (q SQLServerSelectQuery) As(alias string, columns ...string) SQLS...
    method Field (line 1372) | func (q SQLServerSelectQuery) Field(name string) AnyField {
    method SetFetchableFields (line 1377) | func (q SQLServerSelectQuery) SetFetchableFields(fields []Field) (quer...
    method GetFetchableFields (line 1386) | func (q SQLServerSelectQuery) GetFetchableFields() []Field {
    method GetDialect (line 1391) | func (q SQLServerSelectQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 1394) | func (q SQLServerSelectQuery) SetDialect(dialect string) SQLServerSele...
    method GetAlias (line 1400) | func (q SQLServerSelectQuery) GetAlias() string { return q.Alias }
    method IsTable (line 1403) | func (q SQLServerSelectQuery) IsTable() {}
    method IsField (line 1406) | func (q SQLServerSelectQuery) IsField() {}
    method IsArray (line 1409) | func (q SQLServerSelectQuery) IsArray() {}
    method IsBinary (line 1412) | func (q SQLServerSelectQuery) IsBinary() {}
    method IsBoolean (line 1415) | func (q SQLServerSelectQuery) IsBoolean() {}
    method IsEnum (line 1418) | func (q SQLServerSelectQuery) IsEnum() {}
    method IsJSON (line 1421) | func (q SQLServerSelectQuery) IsJSON() {}
    method IsNumber (line 1424) | func (q SQLServerSelectQuery) IsNumber() {}
    method IsString (line 1427) | func (q SQLServerSelectQuery) IsString() {}
    method IsTime (line 1430) | func (q SQLServerSelectQuery) IsTime() {}
    method IsUUID (line 1433) | func (q SQLServerSelectQuery) IsUUID() {}
  method Select (line 1205) | func (b sqlserverQueryBuilder) Select(fields ...Field) SQLServerSelectQu...
  method SelectDistinct (line 1217) | func (b sqlserverQueryBuilder) SelectDistinct(fields ...Field) SQLServer...
  method SelectOne (line 1230) | func (b sqlserverQueryBuilder) SelectOne() SQLServerSelectQuery {
  method From (line 1242) | func (b sqlserverQueryBuilder) From(table Table) SQLServerSelectQuery {

FILE: select_query_test.go
  function TestSQLiteSelectQuery (line 9) | func TestSQLiteSelectQuery(t *testing.T) {
  function TestPostgresSelectQuery (line 90) | func TestPostgresSelectQuery(t *testing.T) {
  function TestMySQLSelectQuery (line 206) | func TestMySQLSelectQuery(t *testing.T) {
  function TestSQLServerSelectQuery (line 307) | func TestSQLServerSelectQuery(t *testing.T) {
  function TestSelectQuery (line 418) | func TestSelectQuery(t *testing.T) {

FILE: sq.go
  constant DialectSQLite (line 24) | DialectSQLite    = "sqlite"
  constant DialectPostgres (line 25) | DialectPostgres  = "postgres"
  constant DialectMySQL (line 26) | DialectMySQL     = "mysql"
  constant DialectSQLServer (line 27) | DialectSQLServer = "sqlserver"
  type SQLWriter (line 31) | type SQLWriter interface
  type DB (line 44) | type DB interface
  type Result (line 51) | type Result struct
  type Query (line 57) | type Query interface
  type Table (line 67) | type Table interface
  type PolicyTable (line 76) | type PolicyTable interface
  type Window (line 82) | type Window interface
  type Field (line 88) | type Field interface
  type Predicate (line 94) | type Predicate interface
  type Assignment (line 99) | type Assignment interface
  type Any (line 105) | type Any interface
  type Enumeration (line 118) | type Enumeration interface
  type Array (line 132) | type Array interface
  type Binary (line 138) | type Binary interface
  type Boolean (line 144) | type Boolean interface
  type Enum (line 150) | type Enum interface
  type JSON (line 156) | type JSON interface
  type Number (line 162) | type Number interface
  type String (line 168) | type String interface
  type Time (line 174) | type Time interface
  type UUID (line 180) | type UUID interface
  type DialectValuer (line 187) | type DialectValuer interface
  type TableStruct (line 193) | type TableStruct struct
    method WriteSQL (line 210) | func (ts TableStruct) WriteSQL(ctx context.Context, dialect string, bu...
    method GetAlias (line 219) | func (ts TableStruct) GetAlias() string { return ts.alias }
    method IsTable (line 222) | func (ts TableStruct) IsTable() {}
  function NewTableStruct (line 205) | func NewTableStruct(schema, name, alias string) TableStruct {
  function withPrefix (line 224) | func withPrefix(w SQLWriter, prefix string) SQLWriter {
  function getAlias (line 234) | func getAlias(w SQLWriter) string {
  function toString (line 241) | func toString(dialect string, w SQLWriter) string {
  function writeFieldsWithPrefix (line 250) | func writeFieldsWithPrefix(ctx context.Context, dialect string, buf *byt...
  function writeFields (line 273) | func writeFields(ctx context.Context, dialect string, buf *bytes.Buffer,...
  function mapperFunctionPanicked (line 308) | func mapperFunctionPanicked(err *error) {
  function ArrayValue (line 323) | func ArrayValue(value any) driver.Valuer {
  type arrayValue (line 327) | type arrayValue struct
    method Value (line 333) | func (v *arrayValue) Value() (driver.Value, error) {
    method DialectValuer (line 359) | func (v *arrayValue) DialectValuer(dialect string) (driver.Valuer, err...
  function EnumValue (line 367) | func EnumValue(value Enumeration) driver.Valuer {
  type enumValue (line 371) | type enumValue struct
    method Value (line 376) | func (v *enumValue) Value() (driver.Value, error) {
  function getEnumIndex (line 418) | func getEnumIndex(name string, names []string, typ reflect.Type) int {
  function JSONValue (line 454) | func JSONValue(value any) driver.Valuer {
  type jsonValue (line 458) | type jsonValue struct
    method Value (line 463) | func (v *jsonValue) Value() (driver.Value, error) {
  function UUIDValue (line 471) | func UUIDValue(value any) driver.Valuer {
  type uuidValue (line 475) | type uuidValue struct
    method Value (line 481) | func (v *uuidValue) Value() (driver.Value, error) {
    method DialectValuer (line 505) | func (v *uuidValue) DialectValuer(dialect string) (driver.Valuer, erro...
  function preprocessValue (line 510) | func preprocessValue(dialect string, value any) (any, error) {

FILE: sq_test.go
  type Weekday (line 11) | type Weekday
    method Enumerate (line 24) | func (d Weekday) Enumerate() []string {
  constant WeekdayInvalid (line 14) | WeekdayInvalid Weekday = iota
  constant Sunday (line 15) | Sunday
  constant Monday (line 16) | Monday
  constant Tuesday (line 17) | Tuesday
  constant Wednesday (line 18) | Wednesday
  constant Thursday (line 19) | Thursday
  constant Friday (line 20) | Friday
  constant Saturday (line 21) | Saturday
  function Test_preprocessValue (line 37) | func Test_preprocessValue(t *testing.T) {

FILE: update_query.go
  type UpdateQuery (line 10) | type UpdateQuery struct
    method WriteSQL (line 35) | func (q UpdateQuery) WriteSQL(ctx context.Context, dialect string, buf...
    method Set (line 202) | func (q UpdateQuery) Set(assignments ...Assignment) UpdateQuery {
    method SetFunc (line 208) | func (q UpdateQuery) SetFunc(colmapper func(*Column)) UpdateQuery {
    method Where (line 214) | func (q UpdateQuery) Where(predicates ...Predicate) UpdateQuery {
    method SetFetchableFields (line 220) | func (q UpdateQuery) SetFetchableFields(fields []Field) (query Query, ...
    method GetFetchableFields (line 234) | func (q UpdateQuery) GetFetchableFields() []Field {
    method GetDialect (line 244) | func (q UpdateQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 247) | func (q UpdateQuery) SetDialect(dialect string) UpdateQuery {
  function Update (line 197) | func Update(table Table) UpdateQuery {
  type SQLiteUpdateQuery (line 253) | type SQLiteUpdateQuery
    method WriteSQL (line 258) | func (q SQLiteUpdateQuery) WriteSQL(ctx context.Context, dialect strin...
    method Set (line 272) | func (q SQLiteUpdateQuery) Set(assignments ...Assignment) SQLiteUpdate...
    method SetFunc (line 278) | func (q SQLiteUpdateQuery) SetFunc(colmapper func(*Column)) SQLiteUpda...
    method From (line 284) | func (q SQLiteUpdateQuery) From(table Table) SQLiteUpdateQuery {
    method Join (line 290) | func (q SQLiteUpdateQuery) Join(table Table, predicates ...Predicate) ...
    method LeftJoin (line 296) | func (q SQLiteUpdateQuery) LeftJoin(table Table, predicates ...Predica...
    method CrossJoin (line 302) | func (q SQLiteUpdateQuery) CrossJoin(table Table) SQLiteUpdateQuery {
    method CustomJoin (line 309) | func (q SQLiteUpdateQuery) CustomJoin(joinOperator string, table Table...
    method JoinUsing (line 315) | func (q SQLiteUpdateQuery) JoinUsing(table Table, fields ...Field) SQL...
    method Where (line 321) | func (q SQLiteUpdateQuery) Where(predicates ...Predicate) SQLiteUpdate...
    method Returning (line 327) | func (q SQLiteUpdateQuery) Returning(fields ...Field) SQLiteUpdateQuery {
    method SetFetchableFields (line 333) | func (q SQLiteUpdateQuery) SetFetchableFields(fields []Field) (query Q...
    method GetFetchableFields (line 338) | func (q SQLiteUpdateQuery) GetFetchableFields() []Field {
    method GetDialect (line 343) | func (q SQLiteUpdateQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 346) | func (q SQLiteUpdateQuery) SetDialect(dialect string) SQLiteUpdateQuery {
  method Update (line 263) | func (b sqliteQueryBuilder) Update(table Table) SQLiteUpdateQuery {
  type PostgresUpdateQuery (line 352) | type PostgresUpdateQuery
    method WriteSQL (line 357) | func (q PostgresUpdateQuery) WriteSQL(ctx context.Context, dialect str...
    method Set (line 371) | func (q PostgresUpdateQuery) Set(assignments ...Assignment) PostgresUp...
    method SetFunc (line 377) | func (q PostgresUpdateQuery) SetFunc(colmapper func(*Column)) Postgres...
    method From (line 383) | func (q PostgresUpdateQuery) From(table Table) PostgresUpdateQuery {
    method Join (line 389) | func (q PostgresUpdateQuery) Join(table Table, predicates ...Predicate...
    method LeftJoin (line 395) | func (q PostgresUpdateQuery) LeftJoin(table Table, predicates ...Predi...
    method FullJoin (line 401) | func (q PostgresUpdateQuery) FullJoin(table Table, predicates ...Predi...
    method CrossJoin (line 407) | func (q PostgresUpdateQuery) CrossJoin(table Table) PostgresUpdateQuery {
    method CustomJoin (line 414) | func (q PostgresUpdateQuery) CustomJoin(joinOperator string, table Tab...
    method JoinUsing (line 420) | func (q PostgresUpdateQuery) JoinUsing(table Table, fields ...Field) P...
    method Where (line 426) | func (q PostgresUpdateQuery) Where(predicates ...Predicate) PostgresUp...
    method Returning (line 432) | func (q PostgresUpdateQuery) Returning(fields ...Field) PostgresUpdate...
    method SetFetchableFields (line 438) | func (q PostgresUpdateQuery) SetFetchableFields(fields []Field) (query...
    method GetFetchableFields (line 443) | func (q PostgresUpdateQuery) GetFetchableFields() []Field {
    method GetDialect (line 448) | func (q PostgresUpdateQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 451) | func (q PostgresUpdateQuery) SetDialect(dialect string) PostgresUpdate...
  method Update (line 362) | func (b postgresQueryBuilder) Update(table Table) PostgresUpdateQuery {
  type MySQLUpdateQuery (line 457) | type MySQLUpdateQuery
    method WriteSQL (line 462) | func (q MySQLUpdateQuery) WriteSQL(ctx context.Context, dialect string...
    method Join (line 477) | func (q MySQLUpdateQuery) Join(table Table, predicates ...Predicate) M...
    method LeftJoin (line 483) | func (q MySQLUpdateQuery) LeftJoin(table Table, predicates ...Predicat...
    method FullJoin (line 489) | func (q MySQLUpdateQuery) FullJoin(table Table, predicates ...Predicat...
    method CrossJoin (line 495) | func (q MySQLUpdateQuery) CrossJoin(table Table) MySQLUpdateQuery {
    method CustomJoin (line 502) | func (q MySQLUpdateQuery) CustomJoin(joinOperator string, table Table,...
    method JoinUsing (line 508) | func (q MySQLUpdateQuery) JoinUsing(table Table, fields ...Field) MySQ...
    method Set (line 514) | func (q MySQLUpdateQuery) Set(assignments ...Assignment) MySQLUpdateQu...
    method SetFunc (line 520) | func (q MySQLUpdateQuery) SetFunc(colmapper func(*Column)) MySQLUpdate...
    method Where (line 526) | func (q MySQLUpdateQuery) Where(predicates ...Predicate) MySQLUpdateQu...
    method OrderBy (line 532) | func (q MySQLUpdateQuery) OrderBy(fields ...Field) MySQLUpdateQuery {
    method Limit (line 538) | func (q MySQLUpdateQuery) Limit(limit any) MySQLUpdateQuery {
    method SetFetchableFields (line 544) | func (q MySQLUpdateQuery) SetFetchableFields(fields []Field) (query Qu...
    method GetFetchableFields (line 549) | func (q MySQLUpdateQuery) GetFetchableFields() []Field {
    method GetDialect (line 554) | func (q MySQLUpdateQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 557) | func (q MySQLUpdateQuery) SetDialect(dialect string) MySQLUpdateQuery {
  method Update (line 467) | func (b mysqlQueryBuilder) Update(table Table) MySQLUpdateQuery {
  type SQLServerUpdateQuery (line 563) | type SQLServerUpdateQuery
    method WriteSQL (line 568) | func (q SQLServerUpdateQuery) WriteSQL(ctx context.Context, dialect st...
    method Set (line 582) | func (q SQLServerUpdateQuery) Set(assignments ...Assignment) SQLServer...
    method SetFunc (line 588) | func (q SQLServerUpdateQuery) SetFunc(colmapper func(*Column)) SQLServ...
    method From (line 594) | func (q SQLServerUpdateQuery) From(table Table) SQLServerUpdateQuery {
    method Join (line 600) | func (q SQLServerUpdateQuery) Join(table Table, predicates ...Predicat...
    method LeftJoin (line 606) | func (q SQLServerUpdateQuery) LeftJoin(table Table, predicates ...Pred...
    method FullJoin (line 612) | func (q SQLServerUpdateQuery) FullJoin(table Table, predicates ...Pred...
    method CrossJoin (line 618) | func (q SQLServerUpdateQuery) CrossJoin(table Table) SQLServerUpdateQu...
    method CustomJoin (line 625) | func (q SQLServerUpdateQuery) CustomJoin(joinOperator string, table Ta...
    method Where (line 631) | func (q SQLServerUpdateQuery) Where(predicates ...Predicate) SQLServer...
    method SetFetchableFields (line 637) | func (q SQLServerUpdateQuery) SetFetchableFields(fields []Field) (quer...
    method GetFetchableFields (line 642) | func (q SQLServerUpdateQuery) GetFetchableFields() []Field {
    method GetDialect (line 647) | func (q SQLServerUpdateQuery) GetDialect() string { return q.Dialect }
    method SetDialect (line 650) | func (q SQLServerUpdateQuery) SetDialect(dialect string) SQLServerUpda...
  method Update (line 573) | func (b sqlserverQueryBuilder) Update(table Table) SQLServerUpdateQuery {

FILE: update_query_test.go
  function TestSQLiteUpdateQuery (line 9) | func TestSQLiteUpdateQuery(t *testing.T) {
  function TestPostgresUpdateQuery (line 111) | func TestPostgresUpdateQuery(t *testing.T) {
  function TestMySQLUpdateQuery (line 215) | func TestMySQLUpdateQuery(t *testing.T) {
  function TestSQLServerUpdateQuery (line 319) | func TestSQLServerUpdateQuery(t *testing.T) {
  function TestUpdateQuery (line 419) | func TestUpdateQuery(t *testing.T) {

FILE: window.go
  type NamedWindow (line 10) | type NamedWindow struct
    method WriteSQL (line 18) | func (w NamedWindow) WriteSQL(ctx context.Context, dialect string, buf...
    method IsWindow (line 24) | func (w NamedWindow) IsWindow() {}
  type WindowDefinition (line 27) | type WindowDefinition struct
    method WriteSQL (line 53) | func (w WindowDefinition) WriteSQL(ctx context.Context, dialect string...
    method PartitionBy (line 94) | func (w WindowDefinition) PartitionBy(fields ...Field) WindowDefinition {
    method OrderBy (line 100) | func (w WindowDefinition) OrderBy(fields ...Field) WindowDefinition {
    method Frame (line 106) | func (w WindowDefinition) Frame(frameSpec string, frameValues ...any) ...
    method IsWindow (line 113) | func (w WindowDefinition) IsWindow() {}
  function BaseWindow (line 38) | func BaseWindow(w NamedWindow) WindowDefinition {
  function PartitionBy (line 43) | func PartitionBy(fields ...Field) WindowDefinition {
  function OrderBy (line 48) | func OrderBy(fields ...Field) WindowDefinition {
  type NamedWindows (line 116) | type NamedWindows
    method WriteSQL (line 119) | func (ws NamedWindows) WriteSQL(ctx context.Context, dialect string, b...
  function CountOver (line 135) | func CountOver(field Field, window Window) Expression {
  function CountStarOver (line 143) | func CountStarOver(window Window) Expression {
  function SumOver (line 151) | func SumOver(num Number, window Window) Expression {
  function AvgOver (line 159) | func AvgOver(num Number, window Window) Expression {
  function MinOver (line 167) | func MinOver(field Field, window Window) Expression {
  function MaxOver (line 175) | func MaxOver(field Field, window Window) Expression {
  function RowNumberOver (line 183) | func RowNumberOver(window Window) Expression {
  function RankOver (line 191) | func RankOver(window Window) Expression {
  function DenseRankOver (line 199) | func DenseRankOver(window Window) Expression {
  function CumeDistOver (line 207) | func CumeDistOver(window Window) Expression {
  function FirstValueOver (line 215) | func FirstValueOver(field Field, window Window) Expression {
  function LastValueOver (line 224) | func LastValueOver(field Field, window Window) Expression {

FILE: window_test.go
  function TestWindow (line 5) | func TestWindow(t *testing.T) {
Condensed preview — 44 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (834K chars).
[
  {
    "path": ".github/workflows/neocities.yml",
    "chars": 429,
    "preview": "name: Deploy docs to Neocities\non:\n  push:\n    branches: [main]\njobs:\n  deploy_to_neocities:\n    runs-on: ubuntu-latest\n"
  },
  {
    "path": ".github/workflows/tests.yml",
    "chars": 2198,
    "preview": "name: tests\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\njobs:\n  run_sq_tests:\n    runs-on: ubu"
  },
  {
    "path": ".gitignore",
    "chars": 38,
    "preview": "*.sqlite*\n.idea\ncoverage.out\ncoverage\n"
  },
  {
    "path": "LICENSE",
    "chars": 1070,
    "preview": "MIT License\n\nCopyright (c) 2022 Chua Bok Woon\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
  },
  {
    "path": "README.md",
    "chars": 9022,
    "preview": "[![GoDoc](https://img.shields.io/badge/pkg.go.dev-sq-blue)](https://pkg.go.dev/github.com/bokwoon95/sq)\n![tests](https:/"
  },
  {
    "path": "START_HERE.md",
    "chars": 6058,
    "preview": "This document describes how the codebase is organized. It is meant for people who are contributing to the codebase (or a"
  },
  {
    "path": "builtins.go",
    "chars": 19203,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// Expression is an SQL expression that satisfies the Tabl"
  },
  {
    "path": "builtins_test.go",
    "chars": 22190,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"errors\"\n\t\"testing\"\n\n\t\"github.com/bokwoon95/sq/internal/testut"
  },
  {
    "path": "colors.go",
    "chars": 670,
    "preview": "//go:build windows\n\npackage sq\n\nimport (\n\t\"os\"\n\t\"syscall\"\n)\n\nfunc init() {\n\t// https://stackoverflow.com/a/69542231\n\tcon"
  },
  {
    "path": "cte.go",
    "chars": 6683,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n)\n\n// CTE represents an SQL common table expression (CTE"
  },
  {
    "path": "cte_test.go",
    "chars": 6876,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"errors\"\n\t\"testing\"\n\n\t\"github.com/bokwoon95/sq/internal/testut"
  },
  {
    "path": "delete_query.go",
    "chars": 18668,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n)\n\n// DeleteQuery represents an SQL DELETE query.\ntype DeleteQuery struc"
  },
  {
    "path": "delete_query_test.go",
    "chars": 11718,
    "preview": "package sq\n\nimport (\n\t\"testing\"\n\n\t\"github.com/bokwoon95/sq/internal/testutil\"\n)\n\nfunc TestSQLiteDeleteQuery(t *testing.T"
  },
  {
    "path": "fetch_exec.go",
    "chars": 39073,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync/atomi"
  },
  {
    "path": "fetch_exec_test.go",
    "chars": 12660,
    "preview": "package sq\n\nimport (\n\t\"database/sql\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/bokwoon95/sq/internal/testutil\"\n\t_ \"github.com/mat"
  },
  {
    "path": "fields.go",
    "chars": 49921,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n"
  },
  {
    "path": "fields_test.go",
    "chars": 33987,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql/driver\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/bokwoon95/sq"
  },
  {
    "path": "fmt.go",
    "chars": 43119,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"sort"
  },
  {
    "path": "fmt_test.go",
    "chars": 40087,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"errors\"\n\t\"flag\"\n\t\"strings\"\n\t\"testing\"\n"
  },
  {
    "path": "go.mod",
    "chars": 441,
    "preview": "module github.com/bokwoon95/sq\n\ngo 1.19\n\nrequire (\n\tgithub.com/denisenkom/go-mssqldb v0.12.3\n\tgithub.com/go-sql-driver/m"
  },
  {
    "path": "go.sum",
    "chars": 4841,
    "preview": "github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=\ngithub.com/A"
  },
  {
    "path": "insert_query.go",
    "chars": 20067,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n)\n\n// InsertQuery represents an SQL INSERT query.\ntype InsertQuery struc"
  },
  {
    "path": "insert_query_test.go",
    "chars": 20342,
    "preview": "package sq\n\nimport (\n\t\"testing\"\n\n\t\"github.com/bokwoon95/sq/internal/testutil\"\n)\n\nfunc TestSQLiteInsertQuery(t *testing.T"
  },
  {
    "path": "integration_test.go",
    "chars": 25203,
    "preview": "package sq\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/bokwoon95/sq/internal"
  },
  {
    "path": "internal/googleuuid/googleuuid.go",
    "chars": 5490,
    "preview": "// Copyright (c) 2009,2014 Google Inc. All rights reserved.\n//\n// Redistribution and use in source and binary forms, wit"
  },
  {
    "path": "internal/pqarray/pqarray.go",
    "chars": 36370,
    "preview": "// Copyright (c) 2011-2013, 'pq' Contributors Portions Copyright (C) 2011 Blake Mizerany\n//\n// Permission is hereby gran"
  },
  {
    "path": "internal/testutil/testutil.go",
    "chars": 1066,
    "preview": "package testutil\n\nimport (\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/google/go-cmp/cmp\""
  },
  {
    "path": "joins.go",
    "chars": 4371,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n)\n\n// Join operators.\nconst (\n\tJoinInner = \"JOIN\"\n\tJoinLeft  = \"LEFT JOI"
  },
  {
    "path": "joins_test.go",
    "chars": 2476,
    "preview": "package sq\n\nimport \"testing\"\n\nfunc TestJoinTables(t *testing.T) {\n\ttype ACTOR struct {\n\t\tTableStruct\n\t\tACTOR_ID    Numbe"
  },
  {
    "path": "logger.go",
    "chars": 8734,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings"
  },
  {
    "path": "logger_test.go",
    "chars": 4021,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"log\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/bokwoon95/sq/int"
  },
  {
    "path": "misc.go",
    "chars": 18493,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// ValueExpression represents an SQL value that is passed "
  },
  {
    "path": "misc_test.go",
    "chars": 10183,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/bokwoon95/sq/internal/testutil\"\n)\n\nfunc TestVa"
  },
  {
    "path": "row_column.go",
    "chars": 39315,
    "preview": "package sq\n\nimport (\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtim"
  },
  {
    "path": "select_query.go",
    "chars": 42084,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n)\n\n// SelectQuery represents an SQL SELECT query.\ntype SelectQuery struc"
  },
  {
    "path": "select_query_test.go",
    "chars": 21095,
    "preview": "package sq\n\nimport (\n\t\"testing\"\n\n\t\"github.com/bokwoon95/sq/internal/testutil\"\n)\n\nfunc TestSQLiteSelectQuery(t *testing.T"
  },
  {
    "path": "sq.go",
    "chars": 13800,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"str"
  },
  {
    "path": "sq.md",
    "chars": 110749,
    "preview": "# sq (Structured Query)\n\n<center>\n  <img src=\"https://i.imgur.com/GAxInSb.png\" title=\"code example of a select query usi"
  },
  {
    "path": "sq_test.go",
    "chars": 2630,
    "preview": "package sq\n\nimport (\n\t\"database/sql\"\n\t\"testing\"\n\n\t\"github.com/bokwoon95/sq/internal/testutil\"\n\t\"github.com/google/uuid\"\n"
  },
  {
    "path": "update_query.go",
    "chars": 20941,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n)\n\n// UpdateQuery represents an SQL UPDATE query.\ntype UpdateQuery struc"
  },
  {
    "path": "update_query_test.go",
    "chars": 16979,
    "preview": "package sq\n\nimport (\n\t\"testing\"\n\n\t\"github.com/bokwoon95/sq/internal/testutil\"\n)\n\nfunc TestSQLiteUpdateQuery(t *testing.T"
  },
  {
    "path": "window.go",
    "chars": 6508,
    "preview": "package sq\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n)\n\n// NamedWindow represents an SQL named window.\ntype NamedWindow struc"
  },
  {
    "path": "window_test.go",
    "chars": 3857,
    "preview": "package sq\n\nimport \"testing\"\n\nfunc TestWindow(t *testing.T) {\n\tt.Run(\"basic\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tf1, "
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the bokwoon95/sq GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 44 files (745.8 KB), approximately 221.1k tokens, and a symbol index with 1594 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!