snapshot of https://github.com/sqlc-dev/sqlc.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled
This commit is contained in:
169
internal/sql/ast/CLAUDE.md
Normal file
169
internal/sql/ast/CLAUDE.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# AST Package - Claude Code Guide
|
||||
|
||||
This package defines the Abstract Syntax Tree (AST) nodes used by sqlc to represent SQL statements across all supported databases (PostgreSQL, MySQL, SQLite).
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Node Interface
|
||||
All AST nodes implement the `Node` interface with:
|
||||
- `Pos() int` - returns the source position
|
||||
- `Format(buf *TrackedBuffer, d format.Dialect)` - formats the node back to SQL
|
||||
|
||||
### TrackedBuffer
|
||||
The `TrackedBuffer` type (`print.go`) handles SQL formatting with dialect-specific behavior:
|
||||
- `astFormat(node Node)` - formats any AST node
|
||||
- `join(list *List, sep string)` - joins list items with separator
|
||||
- `WriteString(s string)` - writes raw SQL
|
||||
- `QuoteIdent(name string)` - quotes identifiers (dialect-specific)
|
||||
- `TypeName(ns, name string)` - formats type names (dialect-specific)
|
||||
|
||||
### Pretty printing
|
||||
The doc renderer lives in `ast/printer` (`printer.Buffer`), which knows
|
||||
nothing about AST nodes; `TrackedBuffer` embeds it and adds the
|
||||
AST-facing layer (`astFormat`, comment emission, anchors).
|
||||
`TrackedBuffer` records a Wadler-style document (the model behind Prettier
|
||||
and ruff): Format methods emit text plus layout tokens, and the renderer
|
||||
decides which break opportunities become newlines.
|
||||
|
||||
- `Line()` - a space when the group fits on one line, a newline otherwise
|
||||
- `Softline()` - nothing when the group fits, a newline otherwise
|
||||
- `Group()` / `EndGroup()` - a region laid out flat when its width fits
|
||||
- `Indent()` / `EndIndent()` - one level deeper (2 spaces) after breaks
|
||||
- `Breaker()` - forces every enclosing group to break (measures as
|
||||
infinitely wide)
|
||||
- `joinComma(list)` - joins items with `,` + `Line()`
|
||||
- `condition(node)` - clause-level AND/OR chain without outer parentheses,
|
||||
one branch per line when broken
|
||||
|
||||
`ast.Format(n, d)` renders on a single line (all breaks collapse);
|
||||
`ast.Pretty(n, d, width)` breaks lines to fit `width` columns. Statement
|
||||
Format methods open a group and put `Line()` before each clause keyword
|
||||
(`FROM`, `WHERE`, ...), so a statement that fits stays on one line and a
|
||||
long one breaks at clause boundaries. When adding a Format method, write
|
||||
tokens so the flat rendering is correct SQL; layout tokens are optional.
|
||||
|
||||
The fmt command does not pass a real width: like gofmt it never rewraps
|
||||
on its own, so it prints with an effectively infinite width and defers
|
||||
to the author's line breaks instead. `AttachComments` records, for each
|
||||
emission-point marker, whether its neighbouring printed nodes sat on
|
||||
different source lines; when they did, `boundary()` emits a `Breaker()`
|
||||
there on the real print, so the group the author broke stays broken and
|
||||
everything else stays flat.
|
||||
|
||||
### Comments
|
||||
`ast.File{Stmts, Comments}` is what a comment-surfacing parser returns
|
||||
(SQLite via meyer's ParseFile). `AttachComments(raw, d, comments, src)`
|
||||
classifies each comment once, against a dry-run of the printer: source
|
||||
positions and line numbers decide trailing (same line as the code
|
||||
before) vs leading, and each comment is attached to the emission point
|
||||
— node or clause/list boundary — where the printer will reach it. From
|
||||
then on positions are never consulted: `PrettyWithComments(n, d, width,
|
||||
table)` emits by node identity, which is what lets edited or synthetic
|
||||
trees print their comments correctly (the dave/dst model; each record
|
||||
also keeps the node the comment followed, for future rewriting tools).
|
||||
A line comment forces every enclosing group to break — `hardline` and
|
||||
`breaker` tokens measure as infinitely wide — so commented statements
|
||||
format instead of collapsing. Emission points (`beforeClause`,
|
||||
`boundary` in joinComma/condition) double as classification markers on
|
||||
the dry run, guaranteeing attach-time decisions and print-time emission
|
||||
agree.
|
||||
|
||||
### Dialect Interface
|
||||
Dialect-specific formatting is handled via the `Dialect` interface:
|
||||
```go
|
||||
type Dialect interface {
|
||||
QuoteIdent(string) string
|
||||
TypeName(ns, name string) string
|
||||
Param(int) string // $1 for PostgreSQL, ? for MySQL
|
||||
NamedParam(string) string // @name for PostgreSQL, :name for SQLite
|
||||
Cast(string) string
|
||||
}
|
||||
```
|
||||
|
||||
## Adding New AST Nodes
|
||||
|
||||
When adding a new AST node type:
|
||||
|
||||
1. **Create the node file** (e.g., `variable_expr.go`):
|
||||
```go
|
||||
package ast
|
||||
|
||||
type VariableExpr struct {
|
||||
Name string
|
||||
Location int
|
||||
}
|
||||
|
||||
func (n *VariableExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *VariableExpr) Format(buf *TrackedBuffer) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
buf.WriteString("@")
|
||||
buf.WriteString(n.Name)
|
||||
}
|
||||
```
|
||||
|
||||
2. **Add to `astutils/walk.go`** - Add a case in the Walk function:
|
||||
```go
|
||||
case *ast.VariableExpr:
|
||||
// Leaf node - no children to traverse
|
||||
```
|
||||
|
||||
3. **Add to `astutils/rewrite.go`** - Add a case in the Apply function:
|
||||
```go
|
||||
case *ast.VariableExpr:
|
||||
// Leaf node - no children to traverse
|
||||
```
|
||||
|
||||
4. **Update the parser/converter** - In the relevant engine (e.g., `dolphin/convert.go` for MySQL)
|
||||
|
||||
## Helper Functions for Format Methods
|
||||
|
||||
- `set(node Node) bool` - returns true if node is non-nil and not an empty List
|
||||
- `items(list *List) bool` - returns true if list has items
|
||||
- `todo(node) Node` - placeholder for unimplemented conversions (returns nil)
|
||||
|
||||
## Common Node Types
|
||||
|
||||
### Statements
|
||||
- `SelectStmt` - SELECT queries with FromClause, WhereClause, etc.
|
||||
- `InsertStmt` - INSERT with Relation, Cols, SelectStmt, OnConflictClause
|
||||
- `UpdateStmt` - UPDATE with Relations, TargetList, WhereClause
|
||||
- `DeleteStmt` - DELETE with Relations, FromClause (for JOINs), Targets
|
||||
|
||||
### Expressions
|
||||
- `A_Expr` - General expression with operator (e.g., `a + b`, `@param`)
|
||||
- `ColumnRef` - Column reference with Fields list
|
||||
- `FuncCall` - Function call with Func, Args, aggregation options
|
||||
- `TypeCast` - Type cast with Arg and TypeName
|
||||
- `ParenExpr` - Parenthesized expression
|
||||
- `VariableExpr` - MySQL user variable (e.g., `@user_id`)
|
||||
|
||||
### Table References
|
||||
- `RangeVar` - Table reference with schema, name, alias
|
||||
- `JoinExpr` - JOIN with Larg, Rarg, Jointype, Quals/UsingClause
|
||||
|
||||
## MySQL-Specific Nodes
|
||||
|
||||
- `VariableExpr` - User variables (`@var`), distinct from sqlc's `@param` syntax
|
||||
- `IntervalExpr` - INTERVAL expressions
|
||||
- `OnDuplicateKeyUpdate` - MySQL's ON DUPLICATE KEY UPDATE clause
|
||||
- `ParenExpr` - Explicit parentheses (TiDB parser wraps expressions)
|
||||
|
||||
## Important Distinctions
|
||||
|
||||
### MySQL @variable vs sqlc @param
|
||||
- sqlc named parameters (`@param`) never reach the AST: `internal/sql/preprocess`
|
||||
replaces them with the dialect's native placeholder before parsing, so engines
|
||||
only ever see a `ParamRef`
|
||||
- `@name` is only sqlc syntax where the preprocessor's dialect says so. MySQL is
|
||||
excluded, so `@user_id` there stays a user variable (`VariableExpr`)
|
||||
|
||||
### Type Modifiers
|
||||
- `TypeName.Typmods` holds type modifiers like `varchar(255)`
|
||||
- For MySQL, only populate Typmods for types where length is user-specified:
|
||||
- VARCHAR, CHAR, VARBINARY, BINARY - need length
|
||||
- DATETIME, TIMESTAMP, DATE - internal flen should NOT be output
|
||||
23
internal/sql/ast/a_array_expr.go
Normal file
23
internal/sql/ast/a_array_expr.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type A_ArrayExpr struct {
|
||||
Tag NodeTag[A_ArrayExpr] `json:"tag"`
|
||||
|
||||
Elements *List `json:"elements,omitempty"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *A_ArrayExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *A_ArrayExpr) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
buf.WriteString("ARRAY[")
|
||||
buf.join(n.Elements, d, ", ")
|
||||
buf.WriteString("]")
|
||||
}
|
||||
27
internal/sql/ast/a_const.go
Normal file
27
internal/sql/ast/a_const.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type A_Const struct {
|
||||
Tag NodeTag[A_Const] `json:"tag"`
|
||||
|
||||
Val Node `json:"val,omitempty"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *A_Const) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *A_Const) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
if _, ok := n.Val.(*String); ok {
|
||||
buf.WriteString("'")
|
||||
buf.astFormat(n.Val, d)
|
||||
buf.WriteString("'")
|
||||
} else {
|
||||
buf.astFormat(n.Val, d)
|
||||
}
|
||||
}
|
||||
178
internal/sql/ast/a_expr.go
Normal file
178
internal/sql/ast/a_expr.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
)
|
||||
|
||||
type A_Expr struct {
|
||||
Tag NodeTag[A_Expr] `json:"tag"`
|
||||
|
||||
Kind A_Expr_Kind `json:"kind"`
|
||||
// Name is the operator, as a list of String nodes: PostgreSQL's
|
||||
// operator space is open (user-defined and schema-qualified operators),
|
||||
// so the shared tree keeps pg_query's shape rather than an enum. Each
|
||||
// engine's converter writes the operator as its parser saw it — for an
|
||||
// engine that accepts more than one spelling of the same operator
|
||||
// (SQLite's != for <>, == for =), that is the author's spelling, which
|
||||
// is how the printer preserves it.
|
||||
Name *List `json:"name,omitempty"`
|
||||
Lexpr Node `json:"lexpr,omitempty"`
|
||||
Rexpr Node `json:"rexpr,omitempty"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *A_Expr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
// isNamedParam reports whether this A_Expr represents a named parameter,
|
||||
// returning its sigil and name. Engines encode a named parameter as a
|
||||
// prefix pseudo-operator carrying the sigil the author wrote (@name for
|
||||
// most engines; SQLite also spells :name and $name). The spellings mean
|
||||
// different things to sqlc, so the printer emits the one it was given.
|
||||
func (n *A_Expr) isNamedParam() (sigil, name string, ok bool) {
|
||||
if n.Name == nil || len(n.Name.Items) != 1 {
|
||||
return "", "", false
|
||||
}
|
||||
s, sok := n.Name.Items[0].(*String)
|
||||
if !sok || (s.Str != "@" && s.Str != ":" && s.Str != "$") {
|
||||
return "", "", false
|
||||
}
|
||||
if set(n.Lexpr) || !set(n.Rexpr) {
|
||||
return "", "", false
|
||||
}
|
||||
if nameStr, sok := n.Rexpr.(*String); sok {
|
||||
return s.Str, nameStr.Str, true
|
||||
}
|
||||
// Before the compiler rewrites named parameters, @name parses as the @
|
||||
// operator applied to a bare column reference.
|
||||
if col, sok := n.Rexpr.(*ColumnRef); sok && col.Fields != nil && len(col.Fields.Items) == 1 {
|
||||
if f, sok := col.Fields.Items[0].(*String); sok {
|
||||
return s.Str, f.Str, true
|
||||
}
|
||||
}
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
// gluePrefix reports that this prefix expression must print with no space
|
||||
// between the operator and its operand. `@name::type` is a sqlc named
|
||||
// parameter with a cast: the cast binds tighter than the operator, so the
|
||||
// parse is @ applied to a TypeCast and isNamedParam does not see it — but
|
||||
// `@ name::type` would break the parameter apart for sqlc's scanner. Glue
|
||||
// the sigils onto any operand that starts with an identifier, which also
|
||||
// keeps a genuine prefix operator like pg's absolute-value @ meaning the
|
||||
// same thing.
|
||||
func (n *A_Expr) gluePrefix() bool {
|
||||
if set(n.Lexpr) || n.Name == nil || len(n.Name.Items) != 1 {
|
||||
return false
|
||||
}
|
||||
s, ok := n.Name.Items[0].(*String)
|
||||
if !ok || (s.Str != "@" && s.Str != ":" && s.Str != "$") {
|
||||
return false
|
||||
}
|
||||
operand := n.Rexpr
|
||||
if tc, ok := operand.(*TypeCast); ok {
|
||||
operand = tc.Arg
|
||||
}
|
||||
switch operand.(type) {
|
||||
case *ColumnRef, *FuncCall:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// negated returns true when the expression's operator carries the negated
|
||||
// spelling of a pattern-match operator (e.g. "!~~" for NOT LIKE).
|
||||
func (n *A_Expr) negated() bool {
|
||||
if n.Name == nil || len(n.Name.Items) != 1 {
|
||||
return false
|
||||
}
|
||||
s, ok := n.Name.Items[0].(*String)
|
||||
return ok && strings.HasPrefix(s.Str, "!")
|
||||
}
|
||||
|
||||
func (n *A_Expr) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check for named parameter first (works regardless of Kind)
|
||||
if sigil, name, ok := n.isNamedParam(); ok {
|
||||
buf.WriteString(sigil)
|
||||
buf.WriteString(name)
|
||||
return
|
||||
}
|
||||
|
||||
switch n.Kind {
|
||||
case A_Expr_Kind_IN:
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
buf.WriteString(" IN (")
|
||||
buf.astFormat(n.Rexpr, d)
|
||||
buf.WriteString(")")
|
||||
case A_Expr_Kind_LIKE:
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
if n.negated() {
|
||||
buf.WriteString(" NOT LIKE ")
|
||||
} else {
|
||||
buf.WriteString(" LIKE ")
|
||||
}
|
||||
buf.astFormat(n.Rexpr, d)
|
||||
case A_Expr_Kind_ILIKE:
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
if n.negated() {
|
||||
buf.WriteString(" NOT ILIKE ")
|
||||
} else {
|
||||
buf.WriteString(" ILIKE ")
|
||||
}
|
||||
buf.astFormat(n.Rexpr, d)
|
||||
case A_Expr_Kind_SIMILAR:
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
buf.WriteString(" SIMILAR TO ")
|
||||
buf.astFormat(n.Rexpr, d)
|
||||
case A_Expr_Kind_BETWEEN:
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
buf.WriteString(" BETWEEN ")
|
||||
if l, ok := n.Rexpr.(*List); ok && len(l.Items) == 2 {
|
||||
buf.astFormat(l.Items[0], d)
|
||||
buf.WriteString(" AND ")
|
||||
buf.astFormat(l.Items[1], d)
|
||||
}
|
||||
case A_Expr_Kind_NOT_BETWEEN:
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
buf.WriteString(" NOT BETWEEN ")
|
||||
if l, ok := n.Rexpr.(*List); ok && len(l.Items) == 2 {
|
||||
buf.astFormat(l.Items[0], d)
|
||||
buf.WriteString(" AND ")
|
||||
buf.astFormat(l.Items[1], d)
|
||||
}
|
||||
case A_Expr_Kind_DISTINCT:
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
buf.WriteString(" IS DISTINCT FROM ")
|
||||
buf.astFormat(n.Rexpr, d)
|
||||
case A_Expr_Kind_NOT_DISTINCT:
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
buf.WriteString(" IS NOT DISTINCT FROM ")
|
||||
buf.astFormat(n.Rexpr, d)
|
||||
case A_Expr_Kind_NULLIF:
|
||||
buf.WriteString("NULLIF(")
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
buf.WriteString(", ")
|
||||
buf.astFormat(n.Rexpr, d)
|
||||
buf.WriteString(")")
|
||||
default:
|
||||
// Standard operator (including A_Expr_Kind_OP)
|
||||
if set(n.Lexpr) {
|
||||
buf.astFormat(n.Lexpr, d)
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
buf.astFormat(n.Name, d)
|
||||
if set(n.Rexpr) {
|
||||
if !n.gluePrefix() {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
buf.astFormat(n.Rexpr, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
24
internal/sql/ast/a_expr_kind.go
Normal file
24
internal/sql/ast/a_expr_kind.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package ast
|
||||
|
||||
type A_Expr_Kind uint
|
||||
|
||||
const (
|
||||
A_Expr_Kind_OP A_Expr_Kind = 1
|
||||
A_Expr_Kind_OP_ANY A_Expr_Kind = 2
|
||||
A_Expr_Kind_OP_ALL A_Expr_Kind = 3
|
||||
A_Expr_Kind_DISTINCT A_Expr_Kind = 4
|
||||
A_Expr_Kind_NOT_DISTINCT A_Expr_Kind = 5
|
||||
A_Expr_Kind_NULLIF A_Expr_Kind = 6
|
||||
A_Expr_Kind_IN A_Expr_Kind = 7
|
||||
A_Expr_Kind_LIKE A_Expr_Kind = 8
|
||||
A_Expr_Kind_ILIKE A_Expr_Kind = 9
|
||||
A_Expr_Kind_SIMILAR A_Expr_Kind = 10
|
||||
A_Expr_Kind_BETWEEN A_Expr_Kind = 11
|
||||
A_Expr_Kind_NOT_BETWEEN A_Expr_Kind = 12
|
||||
A_Expr_Kind_BETWEEN_SYM A_Expr_Kind = 13
|
||||
A_Expr_Kind_NOT_BETWEEN_SYM A_Expr_Kind = 14
|
||||
)
|
||||
|
||||
func (n *A_Expr_Kind) Pos() int {
|
||||
return 0
|
||||
}
|
||||
34
internal/sql/ast/a_indices.go
Normal file
34
internal/sql/ast/a_indices.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type A_Indices struct {
|
||||
Tag NodeTag[A_Indices] `json:"tag"`
|
||||
|
||||
IsSlice bool `json:"is_slice"`
|
||||
Lidx Node `json:"lidx,omitempty"`
|
||||
Uidx Node `json:"uidx,omitempty"`
|
||||
}
|
||||
|
||||
func (n *A_Indices) Pos() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (n *A_Indices) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
buf.WriteString("[")
|
||||
if n.IsSlice {
|
||||
if set(n.Lidx) {
|
||||
buf.astFormat(n.Lidx, d)
|
||||
}
|
||||
buf.WriteString(":")
|
||||
if set(n.Uidx) {
|
||||
buf.astFormat(n.Uidx, d)
|
||||
}
|
||||
} else {
|
||||
buf.astFormat(n.Uidx, d)
|
||||
}
|
||||
buf.WriteString("]")
|
||||
}
|
||||
12
internal/sql/ast/a_indirection.go
Normal file
12
internal/sql/ast/a_indirection.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type A_Indirection struct {
|
||||
Tag NodeTag[A_Indirection] `json:"tag"`
|
||||
|
||||
Arg Node `json:"arg,omitempty"`
|
||||
Indirection *List `json:"indirection,omitempty"`
|
||||
}
|
||||
|
||||
func (n *A_Indirection) Pos() int {
|
||||
return 0
|
||||
}
|
||||
18
internal/sql/ast/a_star.go
Normal file
18
internal/sql/ast/a_star.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type A_Star struct {
|
||||
Tag NodeTag[A_Star] `json:"tag"`
|
||||
}
|
||||
|
||||
func (n *A_Star) Pos() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (n *A_Star) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
buf.WriteRune('*')
|
||||
}
|
||||
12
internal/sql/ast/access_priv.go
Normal file
12
internal/sql/ast/access_priv.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AccessPriv struct {
|
||||
Tag NodeTag[AccessPriv] `json:"tag"`
|
||||
|
||||
PrivName *string `json:"priv_name,omitempty"`
|
||||
Cols *List `json:"cols,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AccessPriv) Pos() int {
|
||||
return 0
|
||||
}
|
||||
7
internal/sql/ast/agg_split.go
Normal file
7
internal/sql/ast/agg_split.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast
|
||||
|
||||
type AggSplit uint
|
||||
|
||||
func (n *AggSplit) Pos() int {
|
||||
return 0
|
||||
}
|
||||
7
internal/sql/ast/agg_strategy.go
Normal file
7
internal/sql/ast/agg_strategy.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast
|
||||
|
||||
type AggStrategy uint
|
||||
|
||||
func (n *AggStrategy) Pos() int {
|
||||
return 0
|
||||
}
|
||||
27
internal/sql/ast/aggref.go
Normal file
27
internal/sql/ast/aggref.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package ast
|
||||
|
||||
type Aggref struct {
|
||||
Tag NodeTag[Aggref] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Aggfnoid Oid `json:"aggfnoid"`
|
||||
Aggtype Oid `json:"aggtype"`
|
||||
Aggcollid Oid `json:"aggcollid"`
|
||||
Inputcollid Oid `json:"inputcollid"`
|
||||
Aggargtypes *List `json:"aggargtypes,omitempty"`
|
||||
Aggdirectargs *List `json:"aggdirectargs,omitempty"`
|
||||
Args *List `json:"args,omitempty"`
|
||||
Aggorder *List `json:"aggorder,omitempty"`
|
||||
Aggdistinct *List `json:"aggdistinct,omitempty"`
|
||||
Aggfilter Node `json:"aggfilter,omitempty"`
|
||||
Aggstar bool `json:"aggstar"`
|
||||
Aggvariadic bool `json:"aggvariadic"`
|
||||
Aggkind byte `json:"aggkind"`
|
||||
Agglevelsup Index `json:"agglevelsup"`
|
||||
Aggsplit AggSplit `json:"aggsplit"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *Aggref) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
28
internal/sql/ast/alias.go
Normal file
28
internal/sql/ast/alias.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type Alias struct {
|
||||
Tag NodeTag[Alias] `json:"tag"`
|
||||
|
||||
Aliasname *string `json:"aliasname,omitempty"`
|
||||
Colnames *List `json:"colnames,omitempty"`
|
||||
}
|
||||
|
||||
func (n *Alias) Pos() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (n *Alias) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
if n.Aliasname != nil {
|
||||
buf.WriteString(*n.Aliasname)
|
||||
}
|
||||
if items(n.Colnames) {
|
||||
buf.WriteString("(")
|
||||
buf.astFormat(n.Colnames, d)
|
||||
buf.WriteString(")")
|
||||
}
|
||||
}
|
||||
11
internal/sql/ast/alter_collation_stmt.go
Normal file
11
internal/sql/ast/alter_collation_stmt.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package ast
|
||||
|
||||
type AlterCollationStmt struct {
|
||||
Tag NodeTag[AlterCollationStmt] `json:"tag"`
|
||||
|
||||
Collname *List `json:"collname,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterCollationStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alter_database_set_stmt.go
Normal file
12
internal/sql/ast/alter_database_set_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlterDatabaseSetStmt struct {
|
||||
Tag NodeTag[AlterDatabaseSetStmt] `json:"tag"`
|
||||
|
||||
Dbname *string `json:"dbname,omitempty"`
|
||||
Setstmt *VariableSetStmt `json:"setstmt,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterDatabaseSetStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alter_database_stmt.go
Normal file
12
internal/sql/ast/alter_database_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlterDatabaseStmt struct {
|
||||
Tag NodeTag[AlterDatabaseStmt] `json:"tag"`
|
||||
|
||||
Dbname *string `json:"dbname,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterDatabaseStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alter_default_privileges_stmt.go
Normal file
12
internal/sql/ast/alter_default_privileges_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlterDefaultPrivilegesStmt struct {
|
||||
Tag NodeTag[AlterDefaultPrivilegesStmt] `json:"tag"`
|
||||
|
||||
Options *List `json:"options,omitempty"`
|
||||
Action *GrantStmt `json:"action,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterDefaultPrivilegesStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
16
internal/sql/ast/alter_domain_stmt.go
Normal file
16
internal/sql/ast/alter_domain_stmt.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package ast
|
||||
|
||||
type AlterDomainStmt struct {
|
||||
Tag NodeTag[AlterDomainStmt] `json:"tag"`
|
||||
|
||||
Subtype byte `json:"subtype"`
|
||||
TypeName *List `json:"type_name,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Def Node `json:"def,omitempty"`
|
||||
Behavior DropBehavior `json:"behavior"`
|
||||
MissingOk bool `json:"missing_ok"`
|
||||
}
|
||||
|
||||
func (n *AlterDomainStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
16
internal/sql/ast/alter_enum_stmt.go
Normal file
16
internal/sql/ast/alter_enum_stmt.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package ast
|
||||
|
||||
type AlterEnumStmt struct {
|
||||
Tag NodeTag[AlterEnumStmt] `json:"tag"`
|
||||
|
||||
TypeName *List `json:"type_name,omitempty"`
|
||||
OldVal *string `json:"old_val,omitempty"`
|
||||
NewVal *string `json:"new_val,omitempty"`
|
||||
NewValNeighbor *string `json:"new_val_neighbor,omitempty"`
|
||||
NewValIsAfter bool `json:"new_val_is_after"`
|
||||
SkipIfNewValExists bool `json:"skip_if_new_val_exists"`
|
||||
}
|
||||
|
||||
func (n *AlterEnumStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alter_event_trig_stmt.go
Normal file
12
internal/sql/ast/alter_event_trig_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlterEventTrigStmt struct {
|
||||
Tag NodeTag[AlterEventTrigStmt] `json:"tag"`
|
||||
|
||||
Trigname *string `json:"trigname,omitempty"`
|
||||
Tgenabled byte `json:"tgenabled"`
|
||||
}
|
||||
|
||||
func (n *AlterEventTrigStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
14
internal/sql/ast/alter_extension_contents_stmt.go
Normal file
14
internal/sql/ast/alter_extension_contents_stmt.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type AlterExtensionContentsStmt struct {
|
||||
Tag NodeTag[AlterExtensionContentsStmt] `json:"tag"`
|
||||
|
||||
Extname *string `json:"extname,omitempty"`
|
||||
Action int `json:"action"`
|
||||
Objtype ObjectType `json:"objtype"`
|
||||
Object Node `json:"object,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterExtensionContentsStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alter_extension_stmt.go
Normal file
12
internal/sql/ast/alter_extension_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlterExtensionStmt struct {
|
||||
Tag NodeTag[AlterExtensionStmt] `json:"tag"`
|
||||
|
||||
Extname *string `json:"extname,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterExtensionStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/alter_fdw_stmt.go
Normal file
13
internal/sql/ast/alter_fdw_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type AlterFdwStmt struct {
|
||||
Tag NodeTag[AlterFdwStmt] `json:"tag"`
|
||||
|
||||
Fdwname *string `json:"fdwname,omitempty"`
|
||||
FuncOptions *List `json:"func_options,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterFdwStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
14
internal/sql/ast/alter_foreign_server_stmt.go
Normal file
14
internal/sql/ast/alter_foreign_server_stmt.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type AlterForeignServerStmt struct {
|
||||
Tag NodeTag[AlterForeignServerStmt] `json:"tag"`
|
||||
|
||||
Servername *string `json:"servername,omitempty"`
|
||||
Version *string `json:"version,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
HasVersion bool `json:"has_version"`
|
||||
}
|
||||
|
||||
func (n *AlterForeignServerStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alter_function_stmt.go
Normal file
12
internal/sql/ast/alter_function_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlterFunctionStmt struct {
|
||||
Tag NodeTag[AlterFunctionStmt] `json:"tag"`
|
||||
|
||||
Func *ObjectWithArgs `json:"func,omitempty"`
|
||||
Actions *List `json:"actions,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterFunctionStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
14
internal/sql/ast/alter_object_depends_stmt.go
Normal file
14
internal/sql/ast/alter_object_depends_stmt.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type AlterObjectDependsStmt struct {
|
||||
Tag NodeTag[AlterObjectDependsStmt] `json:"tag"`
|
||||
|
||||
ObjectType ObjectType `json:"object_type"`
|
||||
Relation *RangeVar `json:"relation,omitempty"`
|
||||
Object Node `json:"object,omitempty"`
|
||||
Extname Node `json:"extname,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterObjectDependsStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
15
internal/sql/ast/alter_object_schema_stmt.go
Normal file
15
internal/sql/ast/alter_object_schema_stmt.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package ast
|
||||
|
||||
type AlterObjectSchemaStmt struct {
|
||||
Tag NodeTag[AlterObjectSchemaStmt] `json:"tag"`
|
||||
|
||||
ObjectType ObjectType `json:"object_type"`
|
||||
Relation *RangeVar `json:"relation,omitempty"`
|
||||
Object Node `json:"object,omitempty"`
|
||||
Newschema *string `json:"newschema,omitempty"`
|
||||
MissingOk bool `json:"missing_ok"`
|
||||
}
|
||||
|
||||
func (n *AlterObjectSchemaStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
14
internal/sql/ast/alter_op_family_stmt.go
Normal file
14
internal/sql/ast/alter_op_family_stmt.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type AlterOpFamilyStmt struct {
|
||||
Tag NodeTag[AlterOpFamilyStmt] `json:"tag"`
|
||||
|
||||
Opfamilyname *List `json:"opfamilyname,omitempty"`
|
||||
Amname *string `json:"amname,omitempty"`
|
||||
IsDrop bool `json:"is_drop"`
|
||||
Items *List `json:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterOpFamilyStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alter_operator_stmt.go
Normal file
12
internal/sql/ast/alter_operator_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlterOperatorStmt struct {
|
||||
Tag NodeTag[AlterOperatorStmt] `json:"tag"`
|
||||
|
||||
Opername *ObjectWithArgs `json:"opername,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterOperatorStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
14
internal/sql/ast/alter_owner_stmt.go
Normal file
14
internal/sql/ast/alter_owner_stmt.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type AlterOwnerStmt struct {
|
||||
Tag NodeTag[AlterOwnerStmt] `json:"tag"`
|
||||
|
||||
ObjectType ObjectType `json:"object_type"`
|
||||
Relation *RangeVar `json:"relation,omitempty"`
|
||||
Object Node `json:"object,omitempty"`
|
||||
Newowner *RoleSpec `json:"newowner,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterOwnerStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
15
internal/sql/ast/alter_policy_stmt.go
Normal file
15
internal/sql/ast/alter_policy_stmt.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package ast
|
||||
|
||||
type AlterPolicyStmt struct {
|
||||
Tag NodeTag[AlterPolicyStmt] `json:"tag"`
|
||||
|
||||
PolicyName *string `json:"policy_name,omitempty"`
|
||||
Table *RangeVar `json:"table,omitempty"`
|
||||
Roles *List `json:"roles,omitempty"`
|
||||
Qual Node `json:"qual,omitempty"`
|
||||
WithCheck Node `json:"with_check,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterPolicyStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
15
internal/sql/ast/alter_publication_stmt.go
Normal file
15
internal/sql/ast/alter_publication_stmt.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package ast
|
||||
|
||||
type AlterPublicationStmt struct {
|
||||
Tag NodeTag[AlterPublicationStmt] `json:"tag"`
|
||||
|
||||
Pubname *string `json:"pubname,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
Tables *List `json:"tables,omitempty"`
|
||||
ForAllTables bool `json:"for_all_tables"`
|
||||
TableAction DefElemAction `json:"table_action"`
|
||||
}
|
||||
|
||||
func (n *AlterPublicationStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/alter_role_set_stmt.go
Normal file
13
internal/sql/ast/alter_role_set_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type AlterRoleSetStmt struct {
|
||||
Tag NodeTag[AlterRoleSetStmt] `json:"tag"`
|
||||
|
||||
Role *RoleSpec `json:"role,omitempty"`
|
||||
Database *string `json:"database,omitempty"`
|
||||
Setstmt *VariableSetStmt `json:"setstmt,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterRoleSetStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/alter_role_stmt.go
Normal file
13
internal/sql/ast/alter_role_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type AlterRoleStmt struct {
|
||||
Tag NodeTag[AlterRoleStmt] `json:"tag"`
|
||||
|
||||
Role *RoleSpec `json:"role,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
Action int `json:"action"`
|
||||
}
|
||||
|
||||
func (n *AlterRoleStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
14
internal/sql/ast/alter_seq_stmt.go
Normal file
14
internal/sql/ast/alter_seq_stmt.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type AlterSeqStmt struct {
|
||||
Tag NodeTag[AlterSeqStmt] `json:"tag"`
|
||||
|
||||
Sequence *RangeVar `json:"sequence,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
ForIdentity bool `json:"for_identity"`
|
||||
MissingOk bool `json:"missing_ok"`
|
||||
}
|
||||
|
||||
func (n *AlterSeqStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
15
internal/sql/ast/alter_subscription_stmt.go
Normal file
15
internal/sql/ast/alter_subscription_stmt.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package ast
|
||||
|
||||
type AlterSubscriptionStmt struct {
|
||||
Tag NodeTag[AlterSubscriptionStmt] `json:"tag"`
|
||||
|
||||
Kind AlterSubscriptionType `json:"kind"`
|
||||
Subname *string `json:"subname,omitempty"`
|
||||
Conninfo *string `json:"conninfo,omitempty"`
|
||||
Publication *List `json:"publication,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterSubscriptionStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
7
internal/sql/ast/alter_subscription_type.go
Normal file
7
internal/sql/ast/alter_subscription_type.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast
|
||||
|
||||
type AlterSubscriptionType uint
|
||||
|
||||
func (n *AlterSubscriptionType) Pos() int {
|
||||
return 0
|
||||
}
|
||||
11
internal/sql/ast/alter_system_stmt.go
Normal file
11
internal/sql/ast/alter_system_stmt.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package ast
|
||||
|
||||
type AlterSystemStmt struct {
|
||||
Tag NodeTag[AlterSystemStmt] `json:"tag"`
|
||||
|
||||
Setstmt *VariableSetStmt `json:"setstmt,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterSystemStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
59
internal/sql/ast/alter_table_cmd.go
Normal file
59
internal/sql/ast/alter_table_cmd.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
const (
|
||||
AT_AddColumn AlterTableType = iota
|
||||
AT_AlterColumnType
|
||||
AT_DropColumn
|
||||
AT_DropNotNull
|
||||
AT_SetNotNull
|
||||
)
|
||||
|
||||
type AlterTableType int
|
||||
|
||||
func (t AlterTableType) String() string {
|
||||
switch t {
|
||||
case AT_AddColumn:
|
||||
return "AddColumn"
|
||||
case AT_AlterColumnType:
|
||||
return "AlterColumnType"
|
||||
case AT_DropColumn:
|
||||
return "DropColumn"
|
||||
case AT_DropNotNull:
|
||||
return "DropNotNull"
|
||||
case AT_SetNotNull:
|
||||
return "SetNotNull"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
type AlterTableCmd struct {
|
||||
Tag NodeTag[AlterTableCmd] `json:"tag"`
|
||||
|
||||
Subtype AlterTableType `json:"subtype"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Def *ColumnDef `json:"def,omitempty"`
|
||||
Newowner *RoleSpec `json:"newowner,omitempty"`
|
||||
Behavior DropBehavior `json:"behavior"`
|
||||
MissingOk bool `json:"missing_ok"`
|
||||
}
|
||||
|
||||
func (n *AlterTableCmd) Pos() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (n *AlterTableCmd) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
switch n.Subtype {
|
||||
case AT_AddColumn:
|
||||
buf.WriteString(" ADD COLUMN ")
|
||||
case AT_DropColumn:
|
||||
buf.WriteString(" DROP COLUMN ")
|
||||
}
|
||||
|
||||
buf.astFormat(n.Def, d)
|
||||
}
|
||||
15
internal/sql/ast/alter_table_move_all_stmt.go
Normal file
15
internal/sql/ast/alter_table_move_all_stmt.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package ast
|
||||
|
||||
type AlterTableMoveAllStmt struct {
|
||||
Tag NodeTag[AlterTableMoveAllStmt] `json:"tag"`
|
||||
|
||||
OrigTablespacename *string `json:"orig_tablespacename,omitempty"`
|
||||
Objtype ObjectType `json:"objtype"`
|
||||
Roles *List `json:"roles,omitempty"`
|
||||
NewTablespacename *string `json:"new_tablespacename,omitempty"`
|
||||
Nowait bool `json:"nowait"`
|
||||
}
|
||||
|
||||
func (n *AlterTableMoveAllStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/alter_table_set_schema_stmt.go
Normal file
13
internal/sql/ast/alter_table_set_schema_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type AlterTableSetSchemaStmt struct {
|
||||
Tag NodeTag[AlterTableSetSchemaStmt] `json:"tag"`
|
||||
|
||||
Table *TableName `json:"table,omitempty"`
|
||||
NewSchema *string `json:"new_schema,omitempty"`
|
||||
MissingOk bool `json:"missing_ok"`
|
||||
}
|
||||
|
||||
func (n *AlterTableSetSchemaStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/alter_table_space_options_stmt.go
Normal file
13
internal/sql/ast/alter_table_space_options_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type AlterTableSpaceOptionsStmt struct {
|
||||
Tag NodeTag[AlterTableSpaceOptionsStmt] `json:"tag"`
|
||||
|
||||
Tablespacename *string `json:"tablespacename,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
IsReset bool `json:"is_reset"`
|
||||
}
|
||||
|
||||
func (n *AlterTableSpaceOptionsStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
38
internal/sql/ast/alter_table_stmt.go
Normal file
38
internal/sql/ast/alter_table_stmt.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type AlterTableStmt struct {
|
||||
Tag NodeTag[AlterTableStmt] `json:"tag"`
|
||||
|
||||
// TODO: Only TableName or Relation should be defined
|
||||
Relation *RangeVar `json:"relation,omitempty"`
|
||||
Table *TableName `json:"table,omitempty"`
|
||||
Cmds *List `json:"cmds,omitempty"`
|
||||
MissingOk bool `json:"missing_ok"`
|
||||
Relkind ObjectType `json:"relkind"`
|
||||
// Incomplete marks a statement whose source carried syntax this node
|
||||
// does not model, such as column constraints beyond plain NOT NULL and
|
||||
// PRIMARY KEY on an added column. No faithful rendering exists for it.
|
||||
Incomplete bool `json:"incomplete"`
|
||||
}
|
||||
|
||||
func (n *AlterTableStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (n *AlterTableStmt) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
// An incomplete statement cannot be printed back: part of its source
|
||||
// was parsed away. Render nothing, which no verification accepts, so
|
||||
// the formatter keeps the statement as written.
|
||||
if n.Incomplete {
|
||||
return
|
||||
}
|
||||
buf.WriteString("ALTER TABLE ")
|
||||
buf.astFormat(n.Relation, d)
|
||||
buf.astFormat(n.Table, d)
|
||||
buf.astFormat(n.Cmds, d)
|
||||
}
|
||||
7
internal/sql/ast/alter_table_type.go
Normal file
7
internal/sql/ast/alter_table_type.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast
|
||||
|
||||
type AlterTableType_PG uint
|
||||
|
||||
func (n *AlterTableType_PG) Pos() int {
|
||||
return 0
|
||||
}
|
||||
7
internal/sql/ast/alter_ts_config_type.go
Normal file
7
internal/sql/ast/alter_ts_config_type.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast
|
||||
|
||||
type AlterTSConfigType uint
|
||||
|
||||
func (n *AlterTSConfigType) Pos() int {
|
||||
return 0
|
||||
}
|
||||
17
internal/sql/ast/alter_ts_configuration_stmt.go
Normal file
17
internal/sql/ast/alter_ts_configuration_stmt.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package ast
|
||||
|
||||
type AlterTSConfigurationStmt struct {
|
||||
Tag NodeTag[AlterTSConfigurationStmt] `json:"tag"`
|
||||
|
||||
Kind AlterTSConfigType `json:"kind"`
|
||||
Cfgname *List `json:"cfgname,omitempty"`
|
||||
Tokentype *List `json:"tokentype,omitempty"`
|
||||
Dicts *List `json:"dicts,omitempty"`
|
||||
Override bool `json:"override"`
|
||||
Replace bool `json:"replace"`
|
||||
MissingOk bool `json:"missing_ok"`
|
||||
}
|
||||
|
||||
func (n *AlterTSConfigurationStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alter_ts_dictionary_stmt.go
Normal file
12
internal/sql/ast/alter_ts_dictionary_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlterTSDictionaryStmt struct {
|
||||
Tag NodeTag[AlterTSDictionaryStmt] `json:"tag"`
|
||||
|
||||
Dictname *List `json:"dictname,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterTSDictionaryStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
16
internal/sql/ast/alter_type_add_value_stmt.go
Normal file
16
internal/sql/ast/alter_type_add_value_stmt.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package ast
|
||||
|
||||
type AlterTypeAddValueStmt struct {
|
||||
Tag NodeTag[AlterTypeAddValueStmt] `json:"tag"`
|
||||
|
||||
Type *TypeName `json:"type,omitempty"`
|
||||
NewValue *string `json:"new_value,omitempty"`
|
||||
NewValHasNeighbor bool `json:"new_val_has_neighbor"`
|
||||
NewValNeighbor *string `json:"new_val_neighbor,omitempty"`
|
||||
NewValIsAfter bool `json:"new_val_is_after"`
|
||||
SkipIfNewValExists bool `json:"skip_if_new_val_exists"`
|
||||
}
|
||||
|
||||
func (n *AlterTypeAddValueStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/alter_type_rename_value_stmt.go
Normal file
13
internal/sql/ast/alter_type_rename_value_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type AlterTypeRenameValueStmt struct {
|
||||
Tag NodeTag[AlterTypeRenameValueStmt] `json:"tag"`
|
||||
|
||||
Type *TypeName `json:"type,omitempty"`
|
||||
OldValue *string `json:"old_value,omitempty"`
|
||||
NewValue *string `json:"new_value,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterTypeRenameValueStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alter_type_set_schema_stmt.go
Normal file
12
internal/sql/ast/alter_type_set_schema_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlterTypeSetSchemaStmt struct {
|
||||
Tag NodeTag[AlterTypeSetSchemaStmt] `json:"tag"`
|
||||
|
||||
Type *TypeName `json:"type,omitempty"`
|
||||
NewSchema *string `json:"new_schema,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterTypeSetSchemaStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/alter_user_mapping_stmt.go
Normal file
13
internal/sql/ast/alter_user_mapping_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type AlterUserMappingStmt struct {
|
||||
Tag NodeTag[AlterUserMappingStmt] `json:"tag"`
|
||||
|
||||
User *RoleSpec `json:"user,omitempty"`
|
||||
Servername *string `json:"servername,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlterUserMappingStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/alternative_sub_plan.go
Normal file
12
internal/sql/ast/alternative_sub_plan.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type AlternativeSubPlan struct {
|
||||
Tag NodeTag[AlternativeSubPlan] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Subplans *List `json:"subplans,omitempty"`
|
||||
}
|
||||
|
||||
func (n *AlternativeSubPlan) Pos() int {
|
||||
return 0
|
||||
}
|
||||
19
internal/sql/ast/array_coerce_expr.go
Normal file
19
internal/sql/ast/array_coerce_expr.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package ast
|
||||
|
||||
type ArrayCoerceExpr struct {
|
||||
Tag NodeTag[ArrayCoerceExpr] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Arg Node `json:"arg,omitempty"`
|
||||
Elemfuncid Oid `json:"elemfuncid"`
|
||||
Resulttype Oid `json:"resulttype"`
|
||||
Resulttypmod int32 `json:"resulttypmod"`
|
||||
Resultcollid Oid `json:"resultcollid"`
|
||||
IsExplicit bool `json:"is_explicit"`
|
||||
Coerceformat CoercionForm `json:"coerceformat"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *ArrayCoerceExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
17
internal/sql/ast/array_expr.go
Normal file
17
internal/sql/ast/array_expr.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package ast
|
||||
|
||||
type ArrayExpr struct {
|
||||
Tag NodeTag[ArrayExpr] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
ArrayTypeid Oid `json:"array_typeid"`
|
||||
ArrayCollid Oid `json:"array_collid"`
|
||||
ElementTypeid Oid `json:"element_typeid"`
|
||||
Elements *List `json:"elements,omitempty"`
|
||||
Multidims bool `json:"multidims"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *ArrayExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
19
internal/sql/ast/array_ref.go
Normal file
19
internal/sql/ast/array_ref.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package ast
|
||||
|
||||
type ArrayRef struct {
|
||||
Tag NodeTag[ArrayRef] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Refarraytype Oid `json:"refarraytype"`
|
||||
Refelemtype Oid `json:"refelemtype"`
|
||||
Reftypmod int32 `json:"reftypmod"`
|
||||
Refcollid Oid `json:"refcollid"`
|
||||
Refupperindexpr *List `json:"refupperindexpr,omitempty"`
|
||||
Reflowerindexpr *List `json:"reflowerindexpr,omitempty"`
|
||||
Refexpr Node `json:"refexpr,omitempty"`
|
||||
Refassgnexpr Node `json:"refassgnexpr,omitempty"`
|
||||
}
|
||||
|
||||
func (n *ArrayRef) Pos() int {
|
||||
return 0
|
||||
}
|
||||
36
internal/sql/ast/between_expr.go
Normal file
36
internal/sql/ast/between_expr.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type BetweenExpr struct {
|
||||
Tag NodeTag[BetweenExpr] `json:"tag"`
|
||||
|
||||
// Expr is the value expression to be compared.
|
||||
Expr Node `json:"expr,omitempty"`
|
||||
// Left is the left expression in the between statement.
|
||||
Left Node `json:"left,omitempty"`
|
||||
// Right is the right expression in the between statement.
|
||||
Right Node `json:"right,omitempty"`
|
||||
// Not is true, the expression is "not between".
|
||||
Not bool `json:"not"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *BetweenExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *BetweenExpr) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
buf.astFormat(n.Expr, d)
|
||||
if n.Not {
|
||||
buf.WriteString(" NOT BETWEEN ")
|
||||
} else {
|
||||
buf.WriteString(" BETWEEN ")
|
||||
}
|
||||
buf.astFormat(n.Left, d)
|
||||
buf.WriteString(" AND ")
|
||||
buf.astFormat(n.Right, d)
|
||||
}
|
||||
11
internal/sql/ast/bit_string.go
Normal file
11
internal/sql/ast/bit_string.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package ast
|
||||
|
||||
type BitString struct {
|
||||
Tag NodeTag[BitString] `json:"tag"`
|
||||
|
||||
Str string `json:"str"`
|
||||
}
|
||||
|
||||
func (n *BitString) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/block_id_data.go
Normal file
12
internal/sql/ast/block_id_data.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type BlockIdData struct {
|
||||
Tag NodeTag[BlockIdData] `json:"tag"`
|
||||
|
||||
BiHi uint16 `json:"bi_hi"`
|
||||
BiLo uint16 `json:"bi_lo"`
|
||||
}
|
||||
|
||||
func (n *BlockIdData) Pos() int {
|
||||
return 0
|
||||
}
|
||||
70
internal/sql/ast/bool_expr.go
Normal file
70
internal/sql/ast/bool_expr.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type BoolExpr struct {
|
||||
Tag NodeTag[BoolExpr] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Boolop BoolExprType `json:"boolop"`
|
||||
Args *List `json:"args,omitempty"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *BoolExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *BoolExpr) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
switch n.Boolop {
|
||||
case BoolExprTypeIsNull:
|
||||
if items(n.Args) && len(n.Args.Items) > 0 {
|
||||
buf.astFormat(n.Args.Items[0], d)
|
||||
}
|
||||
buf.WriteString(" IS NULL")
|
||||
case BoolExprTypeIsNotNull:
|
||||
if items(n.Args) && len(n.Args.Items) > 0 {
|
||||
buf.astFormat(n.Args.Items[0], d)
|
||||
}
|
||||
buf.WriteString(" IS NOT NULL")
|
||||
case BoolExprTypeNot:
|
||||
// NOT expression: format as NOT <arg>
|
||||
buf.WriteString("NOT ")
|
||||
if items(n.Args) && len(n.Args.Items) > 0 {
|
||||
buf.astFormat(n.Args.Items[0], d)
|
||||
}
|
||||
default:
|
||||
var op string
|
||||
switch n.Boolop {
|
||||
case BoolExprTypeAnd:
|
||||
op = "AND "
|
||||
case BoolExprTypeOr:
|
||||
op = "OR "
|
||||
}
|
||||
buf.WriteString("(")
|
||||
buf.Group()
|
||||
buf.Indent()
|
||||
buf.Softline()
|
||||
if items(n.Args) && op != "" {
|
||||
first := true
|
||||
for _, item := range n.Args.Items {
|
||||
if _, ok := item.(*TODO); ok {
|
||||
continue
|
||||
}
|
||||
if !first {
|
||||
buf.Line()
|
||||
buf.WriteString(op)
|
||||
}
|
||||
first = false
|
||||
buf.astFormat(item, d)
|
||||
}
|
||||
}
|
||||
buf.EndIndent()
|
||||
buf.Softline()
|
||||
buf.EndGroup()
|
||||
buf.WriteString(")")
|
||||
}
|
||||
}
|
||||
19
internal/sql/ast/bool_expr_type.go
Normal file
19
internal/sql/ast/bool_expr_type.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package ast
|
||||
|
||||
// https://github.com/pganalyze/libpg_query/blob/13-latest/protobuf/pg_query.proto#L2783-L2789
|
||||
const (
|
||||
_ BoolExprType = iota
|
||||
BoolExprTypeAnd
|
||||
BoolExprTypeOr
|
||||
BoolExprTypeNot
|
||||
|
||||
// Added for MySQL
|
||||
BoolExprTypeIsNull
|
||||
BoolExprTypeIsNotNull
|
||||
)
|
||||
|
||||
type BoolExprType uint
|
||||
|
||||
func (n *BoolExprType) Pos() int {
|
||||
return 0
|
||||
}
|
||||
7
internal/sql/ast/bool_test_type.go
Normal file
7
internal/sql/ast/bool_test_type.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast
|
||||
|
||||
type BoolTestType uint
|
||||
|
||||
func (n *BoolTestType) Pos() int {
|
||||
return 0
|
||||
}
|
||||
28
internal/sql/ast/boolean.go
Normal file
28
internal/sql/ast/boolean.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
)
|
||||
|
||||
type Boolean struct {
|
||||
Tag NodeTag[Boolean] `json:"tag"`
|
||||
|
||||
Boolval bool `json:"boolval"`
|
||||
}
|
||||
|
||||
func (n *Boolean) Pos() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (n *Boolean) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
if n.Boolval {
|
||||
fmt.Fprintf(buf, "true")
|
||||
} else {
|
||||
fmt.Fprintf(buf, "false")
|
||||
}
|
||||
}
|
||||
14
internal/sql/ast/boolean_test_expr.go
Normal file
14
internal/sql/ast/boolean_test_expr.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type BooleanTest struct {
|
||||
Tag NodeTag[BooleanTest] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Arg Node `json:"arg,omitempty"`
|
||||
Booltesttype BoolTestType `json:"booltesttype"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *BooleanTest) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
21
internal/sql/ast/call_stmt.go
Normal file
21
internal/sql/ast/call_stmt.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type CallStmt struct {
|
||||
Tag NodeTag[CallStmt] `json:"tag"`
|
||||
|
||||
FuncCall *FuncCall `json:"func_call,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CallStmt) Pos() int {
|
||||
if n.FuncCall == nil {
|
||||
return 0
|
||||
}
|
||||
return n.FuncCall.Pos()
|
||||
}
|
||||
|
||||
func (n *CallStmt) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
buf.WriteString("CALL ")
|
||||
buf.astFormat(n.FuncCall, d)
|
||||
}
|
||||
36
internal/sql/ast/case_expr.go
Normal file
36
internal/sql/ast/case_expr.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type CaseExpr struct {
|
||||
Tag NodeTag[CaseExpr] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Casetype Oid `json:"casetype"`
|
||||
Casecollid Oid `json:"casecollid"`
|
||||
Arg Node `json:"arg,omitempty"`
|
||||
Args *List `json:"args,omitempty"`
|
||||
Defresult Node `json:"defresult,omitempty"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *CaseExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *CaseExpr) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
buf.WriteString("CASE ")
|
||||
if set(n.Arg) {
|
||||
buf.astFormat(n.Arg, d)
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
buf.join(n.Args, d, " ")
|
||||
if set(n.Defresult) {
|
||||
buf.WriteString(" ELSE ")
|
||||
buf.astFormat(n.Defresult, d)
|
||||
}
|
||||
buf.WriteString(" END")
|
||||
}
|
||||
14
internal/sql/ast/case_test_expr.go
Normal file
14
internal/sql/ast/case_test_expr.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type CaseTestExpr struct {
|
||||
Tag NodeTag[CaseTestExpr] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
TypeId Oid `json:"type_id"`
|
||||
TypeMod int32 `json:"type_mod"`
|
||||
Collation Oid `json:"collation"`
|
||||
}
|
||||
|
||||
func (n *CaseTestExpr) Pos() int {
|
||||
return 0
|
||||
}
|
||||
26
internal/sql/ast/case_when.go
Normal file
26
internal/sql/ast/case_when.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type CaseWhen struct {
|
||||
Tag NodeTag[CaseWhen] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Expr Node `json:"expr,omitempty"`
|
||||
Result Node `json:"result,omitempty"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *CaseWhen) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *CaseWhen) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
buf.WriteString("WHEN ")
|
||||
buf.astFormat(n.Expr, d)
|
||||
buf.WriteString(" THEN ")
|
||||
buf.astFormat(n.Result, d)
|
||||
}
|
||||
9
internal/sql/ast/check_point_stmt.go
Normal file
9
internal/sql/ast/check_point_stmt.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package ast
|
||||
|
||||
type CheckPointStmt struct {
|
||||
Tag NodeTag[CheckPointStmt] `json:"tag"`
|
||||
}
|
||||
|
||||
func (n *CheckPointStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
11
internal/sql/ast/close_portal_stmt.go
Normal file
11
internal/sql/ast/close_portal_stmt.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package ast
|
||||
|
||||
type ClosePortalStmt struct {
|
||||
Tag NodeTag[ClosePortalStmt] `json:"tag"`
|
||||
|
||||
Portalname *string `json:"portalname,omitempty"`
|
||||
}
|
||||
|
||||
func (n *ClosePortalStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/cluster_stmt.go
Normal file
13
internal/sql/ast/cluster_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type ClusterStmt struct {
|
||||
Tag NodeTag[ClusterStmt] `json:"tag"`
|
||||
|
||||
Relation *RangeVar `json:"relation,omitempty"`
|
||||
Indexname *string `json:"indexname,omitempty"`
|
||||
Verbose bool `json:"verbose"`
|
||||
}
|
||||
|
||||
func (n *ClusterStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
7
internal/sql/ast/cmd_type.go
Normal file
7
internal/sql/ast/cmd_type.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast
|
||||
|
||||
type CmdType uint
|
||||
|
||||
func (n *CmdType) Pos() int {
|
||||
return 0
|
||||
}
|
||||
28
internal/sql/ast/coalesce_expr.go
Normal file
28
internal/sql/ast/coalesce_expr.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type CoalesceExpr struct {
|
||||
Tag NodeTag[CoalesceExpr] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Coalescetype Oid `json:"coalescetype"`
|
||||
Coalescecollid Oid `json:"coalescecollid"`
|
||||
Args *List `json:"args,omitempty"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *CoalesceExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *CoalesceExpr) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
// Lower case, like every other function name: the printer upper-cases
|
||||
// keywords, and function names are identifiers, which fold lower.
|
||||
buf.WriteString("coalesce(")
|
||||
buf.astFormat(n.Args, d)
|
||||
buf.WriteString(")")
|
||||
}
|
||||
17
internal/sql/ast/coerce_to_domain.go
Normal file
17
internal/sql/ast/coerce_to_domain.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package ast
|
||||
|
||||
type CoerceToDomain struct {
|
||||
Tag NodeTag[CoerceToDomain] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Arg Node `json:"arg,omitempty"`
|
||||
Resulttype Oid `json:"resulttype"`
|
||||
Resulttypmod int32 `json:"resulttypmod"`
|
||||
Resultcollid Oid `json:"resultcollid"`
|
||||
Coercionformat CoercionForm `json:"coercionformat"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *CoerceToDomain) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
15
internal/sql/ast/coerce_to_domain_value.go
Normal file
15
internal/sql/ast/coerce_to_domain_value.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package ast
|
||||
|
||||
type CoerceToDomainValue struct {
|
||||
Tag NodeTag[CoerceToDomainValue] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
TypeId Oid `json:"type_id"`
|
||||
TypeMod int32 `json:"type_mod"`
|
||||
Collation Oid `json:"collation"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *CoerceToDomainValue) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
16
internal/sql/ast/coerce_via_io.go
Normal file
16
internal/sql/ast/coerce_via_io.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package ast
|
||||
|
||||
type CoerceViaIO struct {
|
||||
Tag NodeTag[CoerceViaIO] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Arg Node `json:"arg,omitempty"`
|
||||
Resulttype Oid `json:"resulttype"`
|
||||
Resultcollid Oid `json:"resultcollid"`
|
||||
Coerceformat CoercionForm `json:"coerceformat"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *CoerceViaIO) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
7
internal/sql/ast/coercion_context.go
Normal file
7
internal/sql/ast/coercion_context.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast
|
||||
|
||||
type CoercionContext uint
|
||||
|
||||
func (n *CoercionContext) Pos() int {
|
||||
return 0
|
||||
}
|
||||
7
internal/sql/ast/coercion_form.go
Normal file
7
internal/sql/ast/coercion_form.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast
|
||||
|
||||
type CoercionForm uint
|
||||
|
||||
func (n *CoercionForm) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/collate_clause.go
Normal file
13
internal/sql/ast/collate_clause.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type CollateClause struct {
|
||||
Tag NodeTag[CollateClause] `json:"tag"`
|
||||
|
||||
Arg Node `json:"arg,omitempty"`
|
||||
Collname *List `json:"collname,omitempty"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *CollateClause) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
25
internal/sql/ast/collate_expr.go
Normal file
25
internal/sql/ast/collate_expr.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type CollateExpr struct {
|
||||
Tag NodeTag[CollateExpr] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Arg Node `json:"arg,omitempty"`
|
||||
CollOid Oid `json:"coll_oid"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *CollateExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *CollateExpr) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
buf.astFormat(n.Xpr, d)
|
||||
buf.WriteString(" COLLATE ")
|
||||
buf.astFormat(n.Arg, d)
|
||||
}
|
||||
72
internal/sql/ast/column_def.go
Normal file
72
internal/sql/ast/column_def.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type ColumnDef struct {
|
||||
Tag NodeTag[ColumnDef] `json:"tag"`
|
||||
|
||||
Colname string `json:"colname"`
|
||||
// TypeName is the column's type for the catalog. When Typeless is set
|
||||
// the author wrote no type at all — SQLite allows it — and the column
|
||||
// prints without one, whatever TypeName carries.
|
||||
TypeName *TypeName `json:"type_name,omitempty"`
|
||||
Typeless bool `json:"typeless"`
|
||||
IsNotNull bool `json:"is_not_null"`
|
||||
IsUnsigned bool `json:"is_unsigned"`
|
||||
IsArray bool `json:"is_array"`
|
||||
ArrayDims int `json:"array_dims"`
|
||||
Vals *List `json:"vals,omitempty"`
|
||||
Length *int `json:"length,omitempty"`
|
||||
PrimaryKey bool `json:"primary_key"`
|
||||
// IsHidden marks a column a relation offers by name without listing it,
|
||||
// like the column an sqlite fts5 table names after itself. The legacy
|
||||
// catalog drops hidden columns; the core catalog keeps them out of star
|
||||
// expansions and models.
|
||||
IsHidden bool `json:"is_hidden"`
|
||||
|
||||
// From pg.ColumnDef
|
||||
Inhcount int `json:"inhcount"`
|
||||
IsLocal bool `json:"is_local"`
|
||||
IsFromType bool `json:"is_from_type"`
|
||||
IsFromParent bool `json:"is_from_parent"`
|
||||
Storage byte `json:"storage"`
|
||||
RawDefault Node `json:"raw_default,omitempty"`
|
||||
CookedDefault Node `json:"cooked_default,omitempty"`
|
||||
Identity byte `json:"identity"`
|
||||
CollClause *CollateClause `json:"coll_clause,omitempty"`
|
||||
CollOid Oid `json:"coll_oid"`
|
||||
Constraints *List `json:"constraints,omitempty"`
|
||||
Fdwoptions *List `json:"fdwoptions,omitempty"`
|
||||
Location int `json:"location"`
|
||||
Comment string `json:"comment"`
|
||||
}
|
||||
|
||||
func (n *ColumnDef) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *ColumnDef) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
buf.WriteString(n.Colname)
|
||||
if !n.Typeless {
|
||||
buf.WriteString(" ")
|
||||
buf.astFormat(n.TypeName, d)
|
||||
// MySQL integer types: signedness is part of the type.
|
||||
if n.IsUnsigned {
|
||||
buf.WriteString(" unsigned")
|
||||
}
|
||||
}
|
||||
// Use IsArray from ColumnDef since TypeName.ArrayBounds may not be set
|
||||
// (for type resolution compatibility)
|
||||
if n.IsArray && !items(n.TypeName.ArrayBounds) {
|
||||
buf.WriteString("[]")
|
||||
}
|
||||
if n.PrimaryKey {
|
||||
buf.WriteString(" PRIMARY KEY")
|
||||
} else if n.IsNotNull {
|
||||
buf.WriteString(" NOT NULL")
|
||||
}
|
||||
buf.astFormat(n.Constraints, d)
|
||||
}
|
||||
40
internal/sql/ast/column_ref.go
Normal file
40
internal/sql/ast/column_ref.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
)
|
||||
|
||||
type ColumnRef struct {
|
||||
Tag NodeTag[ColumnRef] `json:"tag"`
|
||||
|
||||
Name string `json:"name"`
|
||||
|
||||
// From pg.ColumnRef
|
||||
Fields *List `json:"fields,omitempty"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *ColumnRef) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *ColumnRef) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if n.Fields != nil {
|
||||
var items []string
|
||||
for _, item := range n.Fields.Items {
|
||||
switch nn := item.(type) {
|
||||
case *String:
|
||||
items = append(items, d.QuoteIdent(nn.Str))
|
||||
case *A_Star:
|
||||
items = append(items, "*")
|
||||
}
|
||||
}
|
||||
buf.WriteString(strings.Join(items, "."))
|
||||
}
|
||||
}
|
||||
235
internal/sql/ast/comment.go
Normal file
235
internal/sql/ast/comment.go
Normal file
@@ -0,0 +1,235 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
)
|
||||
|
||||
// File is a parsed query file: its statements together with the comments
|
||||
// the parser's lexer saw. Engines whose parsers surface their trivia — the
|
||||
// lexical channel of whitespace and comments the grammar never sees, in
|
||||
// Roslyn's terminology — return it from ParseFile, so the formatter gets
|
||||
// statements and comments from one lexer pass.
|
||||
type File struct {
|
||||
Stmts []Statement
|
||||
Comments []Comment
|
||||
}
|
||||
|
||||
// Comment is a single SQL comment, positioned by byte offsets into the
|
||||
// source the statement was parsed from — the same coordinates the engine
|
||||
// parsers stamp on nodes.
|
||||
type Comment struct {
|
||||
// Text is the comment as written, marker included ("-- x", "/* x */").
|
||||
Text string
|
||||
Start int
|
||||
End int
|
||||
// OwnLine reports that only blank space preceded the comment on its
|
||||
// line, so it leads the code after it rather than trailing the code
|
||||
// before it.
|
||||
OwnLine bool
|
||||
}
|
||||
|
||||
// Line reports whether the comment runs to the end of its line (-- or #),
|
||||
// so nothing may be printed after it on the same line.
|
||||
func (c Comment) Line() bool {
|
||||
return len(c.Text) < 2 || c.Text[0] != '/' || c.Text[1] != '*'
|
||||
}
|
||||
|
||||
// commentRec is one attached comment: the anchor nodes on either side of it
|
||||
// in print order, and whether it trails the code before it (same source
|
||||
// line) or leads the code after it (its own line).
|
||||
//
|
||||
// The next anchor is where the printer emits the comment; the prev anchor
|
||||
// is the node the comment belongs to when the tree is edited — a trailing
|
||||
// comment travels with the node it annotates, the way dave/dst attaches
|
||||
// decorations in the Go ecosystem.
|
||||
type commentRec struct {
|
||||
c Comment
|
||||
prev, next Node
|
||||
trailing bool
|
||||
}
|
||||
|
||||
// CommentTable holds a statement's comments attached to its nodes. It is
|
||||
// built once by AttachComments, before any printing (or, later, editing):
|
||||
// each comment is classified against the statement's anchor nodes by source
|
||||
// position and line, and from then on positions are never consulted again —
|
||||
// the printer emits comments by node identity, which is what lets an edited
|
||||
// or synthetic tree print its comments correctly.
|
||||
type CommentTable struct {
|
||||
recs []commentRec
|
||||
// byNext indexes recs by their next anchor, in source order; end holds
|
||||
// the comments with no anchor after them, which trail the statement.
|
||||
byNext map[Node][]int
|
||||
end []int
|
||||
taken []bool
|
||||
nTaken int
|
||||
// breaks marks the emission points where the author broke the line:
|
||||
// the printer keeps those breaks, gofmt-style, instead of imposing a
|
||||
// line width.
|
||||
breaks map[Node]bool
|
||||
}
|
||||
|
||||
// breakAt reports whether the author broke the line at this emission point.
|
||||
func (t *CommentTable) breakAt(n Node) bool {
|
||||
return t != nil && t.breaks[n]
|
||||
}
|
||||
|
||||
// Exhausted reports whether every attached comment was printed.
|
||||
func (t *CommentTable) Exhausted() bool {
|
||||
return t == nil || t.nTaken == len(t.recs)
|
||||
}
|
||||
|
||||
// take returns and consumes the comments anchored to n, in order.
|
||||
func (t *CommentTable) take(n Node) []commentRec {
|
||||
if t == nil || n == nil {
|
||||
return nil
|
||||
}
|
||||
idxs := t.byNext[n]
|
||||
if len(idxs) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := make([]commentRec, 0, len(idxs))
|
||||
for _, i := range idxs {
|
||||
if t.taken[i] {
|
||||
continue
|
||||
}
|
||||
t.taken[i] = true
|
||||
t.nTaken++
|
||||
out = append(out, t.recs[i])
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// takeRemaining returns and consumes every comment not yet printed; the
|
||||
// statement is over, so everything left trails it.
|
||||
func (t *CommentTable) takeRemaining() []commentRec {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
var out []commentRec
|
||||
for i := range t.recs {
|
||||
if t.taken[i] {
|
||||
continue
|
||||
}
|
||||
t.taken[i] = true
|
||||
t.nTaken++
|
||||
out = append(out, t.recs[i])
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// AttachComments classifies a statement's interior comments against its
|
||||
// nodes, producing the table the printer (and any future rewriting tool)
|
||||
// works from. Placement follows gofmt's rules, decided here once from
|
||||
// source positions and lines: a comment on the same line as the code before
|
||||
// it trails that code; any other comment leads the first node printed after
|
||||
// it; a comment after the last node trails the statement.
|
||||
func AttachComments(raw *RawStmt, d format.Dialect, comments []Comment, src string) *CommentTable {
|
||||
anchors := collectAnchors(raw, d)
|
||||
lines := []int{0}
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] == '\n' {
|
||||
lines = append(lines, i+1)
|
||||
}
|
||||
}
|
||||
lineOf := func(pos int) int {
|
||||
return sort.SearchInts(lines, pos+1) - 1
|
||||
}
|
||||
|
||||
table := &CommentTable{byNext: make(map[Node][]int, len(anchors))}
|
||||
for _, c := range comments {
|
||||
// prev: the printed node with the greatest position before the
|
||||
// comment (for the trailing/leading call). next: the emission point
|
||||
// for the first printed node after the comment — the node itself,
|
||||
// or, when boundary markers immediately precede it in print order,
|
||||
// the earliest of those markers, which is where the printer will
|
||||
// look for this comment first.
|
||||
var prev, next Node
|
||||
prevPos := -1
|
||||
for _, a := range anchors {
|
||||
if !a.marker && a.pos < c.Start && a.pos > prevPos {
|
||||
prev, prevPos = a.node, a.pos
|
||||
}
|
||||
}
|
||||
for i, a := range anchors {
|
||||
if a.marker || a.pos <= c.Start {
|
||||
continue
|
||||
}
|
||||
j := i
|
||||
for j > 0 && anchors[j-1].marker {
|
||||
j--
|
||||
}
|
||||
next = anchors[j].node
|
||||
break
|
||||
}
|
||||
rec := commentRec{
|
||||
c: c,
|
||||
prev: prev,
|
||||
next: next,
|
||||
trailing: !c.OwnLine && prev != nil && lineOf(prevPos) == lineOf(c.Start),
|
||||
}
|
||||
table.recs = append(table.recs, rec)
|
||||
i := len(table.recs) - 1
|
||||
if next == nil {
|
||||
table.end = append(table.end, i)
|
||||
} else {
|
||||
table.byNext[next] = append(table.byNext[next], i)
|
||||
}
|
||||
}
|
||||
table.taken = make([]bool, len(table.recs))
|
||||
|
||||
// Record where the author broke the line: an emission point whose
|
||||
// neighbouring printed nodes sit on different source lines. The printer
|
||||
// keeps these breaks (and only imposes new ones for comments), so the
|
||||
// statement's shape stays the author's.
|
||||
table.breaks = make(map[Node]bool)
|
||||
for i, a := range anchors {
|
||||
if !a.marker {
|
||||
continue
|
||||
}
|
||||
prevPos, nextPos := -1, -1
|
||||
for j := i - 1; j >= 0; j-- {
|
||||
if !anchors[j].marker {
|
||||
prevPos = anchors[j].pos
|
||||
break
|
||||
}
|
||||
}
|
||||
for j := i + 1; j < len(anchors); j++ {
|
||||
if !anchors[j].marker {
|
||||
nextPos = anchors[j].pos
|
||||
break
|
||||
}
|
||||
}
|
||||
if prevPos >= 0 && nextPos >= 0 && lineOf(prevPos) != lineOf(nextPos) {
|
||||
table.breaks[a.node] = true
|
||||
}
|
||||
}
|
||||
return table
|
||||
}
|
||||
|
||||
type anchor struct {
|
||||
node Node
|
||||
pos int
|
||||
// marker anchors are emission points (beforeClause, list boundaries)
|
||||
// rather than printed nodes; they carry no position of their own.
|
||||
marker bool
|
||||
}
|
||||
|
||||
// collectAnchors renders the statement once, flat, recording every
|
||||
// positioned node in the order the printer visits them. Print order is what
|
||||
// comment emission is defined against, so classifying against it keeps the
|
||||
// attach-time decision and the print-time emission point identical.
|
||||
func collectAnchors(n Node, d format.Dialect) (out []anchor) {
|
||||
defer func() {
|
||||
// A formatter panic here surfaces later, on the real print; anchors
|
||||
// collected so far still place most comments.
|
||||
recover()
|
||||
}()
|
||||
tb := NewTrackedBuffer()
|
||||
tb.anchors = &out
|
||||
if ft, ok := n.(nodeFormatter); ok {
|
||||
ft.Format(tb, d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
13
internal/sql/ast/comment_on_column_stmt.go
Normal file
13
internal/sql/ast/comment_on_column_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type CommentOnColumnStmt struct {
|
||||
Tag NodeTag[CommentOnColumnStmt] `json:"tag"`
|
||||
|
||||
Table *TableName `json:"table,omitempty"`
|
||||
Col *ColumnRef `json:"col,omitempty"`
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CommentOnColumnStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/comment_on_schema_stmt.go
Normal file
12
internal/sql/ast/comment_on_schema_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type CommentOnSchemaStmt struct {
|
||||
Tag NodeTag[CommentOnSchemaStmt] `json:"tag"`
|
||||
|
||||
Schema *String `json:"schema,omitempty"`
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CommentOnSchemaStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/comment_on_table_stmt.go
Normal file
12
internal/sql/ast/comment_on_table_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type CommentOnTableStmt struct {
|
||||
Tag NodeTag[CommentOnTableStmt] `json:"tag"`
|
||||
|
||||
Table *TableName `json:"table,omitempty"`
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CommentOnTableStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/comment_on_type_stmt.go
Normal file
12
internal/sql/ast/comment_on_type_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type CommentOnTypeStmt struct {
|
||||
Tag NodeTag[CommentOnTypeStmt] `json:"tag"`
|
||||
|
||||
Type *TypeName `json:"type,omitempty"`
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CommentOnTypeStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
12
internal/sql/ast/comment_on_view_stmt.go
Normal file
12
internal/sql/ast/comment_on_view_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type CommentOnViewStmt struct {
|
||||
Tag NodeTag[CommentOnViewStmt] `json:"tag"`
|
||||
|
||||
View *TableName `json:"view,omitempty"`
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CommentOnViewStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/comment_stmt.go
Normal file
13
internal/sql/ast/comment_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type CommentStmt struct {
|
||||
Tag NodeTag[CommentStmt] `json:"tag"`
|
||||
|
||||
Objtype ObjectType `json:"objtype"`
|
||||
Object Node `json:"object,omitempty"`
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CommentStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
49
internal/sql/ast/common_table_expr.go
Normal file
49
internal/sql/ast/common_table_expr.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package ast
|
||||
|
||||
import "github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
|
||||
type CommonTableExpr struct {
|
||||
Tag NodeTag[CommonTableExpr] `json:"tag"`
|
||||
|
||||
Ctename *string `json:"ctename,omitempty"`
|
||||
Aliascolnames *List `json:"aliascolnames,omitempty"`
|
||||
Ctequery Node `json:"ctequery,omitempty"`
|
||||
Location int `json:"location"`
|
||||
Cterecursive bool `json:"cterecursive"`
|
||||
Cterefcount int `json:"cterefcount"`
|
||||
Ctecolnames *List `json:"ctecolnames,omitempty"`
|
||||
Ctecoltypes *List `json:"ctecoltypes,omitempty"`
|
||||
Ctecoltypmods *List `json:"ctecoltypmods,omitempty"`
|
||||
Ctecolcollations *List `json:"ctecolcollations,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CommonTableExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
|
||||
func (n *CommonTableExpr) Format(buf *TrackedBuffer, d format.Dialect) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
if n.Ctename != nil {
|
||||
buf.WriteString(*n.Ctename)
|
||||
}
|
||||
if items(n.Aliascolnames) {
|
||||
buf.WriteString("(")
|
||||
buf.join(n.Aliascolnames, d, ", ")
|
||||
buf.WriteString(")")
|
||||
}
|
||||
buf.WriteString(" AS (")
|
||||
buf.Group()
|
||||
buf.Indent()
|
||||
// The body's boundary: a comment at the top of the CTE prints here, and
|
||||
// an author who broke the line after the parenthesis keeps the CTE — and
|
||||
// therefore the statement around it — broken open.
|
||||
buf.boundary(n.Ctequery)
|
||||
buf.Softline()
|
||||
buf.astFormat(n.Ctequery, d)
|
||||
buf.EndIndent()
|
||||
buf.Softline()
|
||||
buf.EndGroup()
|
||||
buf.WriteString(")")
|
||||
}
|
||||
13
internal/sql/ast/composite_type_stmt.go
Normal file
13
internal/sql/ast/composite_type_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type CompositeTypeStmt struct {
|
||||
Tag NodeTag[CompositeTypeStmt] `json:"tag"`
|
||||
|
||||
TypeName *TypeName `json:"type_name,omitempty"`
|
||||
// Coldeflist is the type's fields, each a ColumnDef.
|
||||
Coldeflist *List `json:"coldeflist,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CompositeTypeStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
19
internal/sql/ast/const.go
Normal file
19
internal/sql/ast/const.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package ast
|
||||
|
||||
type Const struct {
|
||||
Tag NodeTag[Const] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Consttype Oid `json:"consttype"`
|
||||
Consttypmod int32 `json:"consttypmod"`
|
||||
Constcollid Oid `json:"constcollid"`
|
||||
Constlen int `json:"constlen"`
|
||||
Constvalue Datum `json:"constvalue"`
|
||||
Constisnull bool `json:"constisnull"`
|
||||
Constbyval bool `json:"constbyval"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *Const) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
14
internal/sql/ast/constr_type.go
Normal file
14
internal/sql/ast/constr_type.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type ConstrType uint
|
||||
|
||||
func (n *ConstrType) Pos() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// The constraint kinds the analysis reads, numbered as PostgreSQL's parser
|
||||
// numbers them, which is what an engine's converter records.
|
||||
const (
|
||||
ConstrTypeNull ConstrType = 1
|
||||
ConstrTypeNotNull ConstrType = 2
|
||||
)
|
||||
36
internal/sql/ast/constraint.go
Normal file
36
internal/sql/ast/constraint.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package ast
|
||||
|
||||
type Constraint struct {
|
||||
Tag NodeTag[Constraint] `json:"tag"`
|
||||
|
||||
Contype ConstrType `json:"contype"`
|
||||
Conname *string `json:"conname,omitempty"`
|
||||
Deferrable bool `json:"deferrable"`
|
||||
Initdeferred bool `json:"initdeferred"`
|
||||
Location int `json:"location"`
|
||||
IsNoInherit bool `json:"is_no_inherit"`
|
||||
RawExpr Node `json:"raw_expr,omitempty"`
|
||||
CookedExpr *string `json:"cooked_expr,omitempty"`
|
||||
GeneratedWhen byte `json:"generated_when"`
|
||||
Keys *List `json:"keys,omitempty"`
|
||||
Exclusions *List `json:"exclusions,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
Indexname *string `json:"indexname,omitempty"`
|
||||
Indexspace *string `json:"indexspace,omitempty"`
|
||||
AccessMethod *string `json:"access_method,omitempty"`
|
||||
WhereClause Node `json:"where_clause,omitempty"`
|
||||
Pktable *RangeVar `json:"pktable,omitempty"`
|
||||
FkAttrs *List `json:"fk_attrs,omitempty"`
|
||||
PkAttrs *List `json:"pk_attrs,omitempty"`
|
||||
FkMatchtype byte `json:"fk_matchtype"`
|
||||
FkUpdAction byte `json:"fk_upd_action"`
|
||||
FkDelAction byte `json:"fk_del_action"`
|
||||
OldConpfeqop *List `json:"old_conpfeqop,omitempty"`
|
||||
OldPktableOid Oid `json:"old_pktable_oid"`
|
||||
SkipValidation bool `json:"skip_validation"`
|
||||
InitiallyValid bool `json:"initially_valid"`
|
||||
}
|
||||
|
||||
func (n *Constraint) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
12
internal/sql/ast/constraints_set_stmt.go
Normal file
12
internal/sql/ast/constraints_set_stmt.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package ast
|
||||
|
||||
type ConstraintsSetStmt struct {
|
||||
Tag NodeTag[ConstraintsSetStmt] `json:"tag"`
|
||||
|
||||
Constraints *List `json:"constraints,omitempty"`
|
||||
Deferred bool `json:"deferred"`
|
||||
}
|
||||
|
||||
func (n *ConstraintsSetStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
15
internal/sql/ast/convert_rowtype_expr.go
Normal file
15
internal/sql/ast/convert_rowtype_expr.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package ast
|
||||
|
||||
type ConvertRowtypeExpr struct {
|
||||
Tag NodeTag[ConvertRowtypeExpr] `json:"tag"`
|
||||
|
||||
Xpr Node `json:"xpr,omitempty"`
|
||||
Arg Node `json:"arg,omitempty"`
|
||||
Resulttype Oid `json:"resulttype"`
|
||||
Convertformat CoercionForm `json:"convertformat"`
|
||||
Location int `json:"location"`
|
||||
}
|
||||
|
||||
func (n *ConvertRowtypeExpr) Pos() int {
|
||||
return n.Location
|
||||
}
|
||||
17
internal/sql/ast/copy_stmt.go
Normal file
17
internal/sql/ast/copy_stmt.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package ast
|
||||
|
||||
type CopyStmt struct {
|
||||
Tag NodeTag[CopyStmt] `json:"tag"`
|
||||
|
||||
Relation *RangeVar `json:"relation,omitempty"`
|
||||
Query Node `json:"query,omitempty"`
|
||||
Attlist *List `json:"attlist,omitempty"`
|
||||
IsFrom bool `json:"is_from"`
|
||||
IsProgram bool `json:"is_program"`
|
||||
Filename *string `json:"filename,omitempty"`
|
||||
Options *List `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CopyStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
13
internal/sql/ast/create_am_stmt.go
Normal file
13
internal/sql/ast/create_am_stmt.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast
|
||||
|
||||
type CreateAmStmt struct {
|
||||
Tag NodeTag[CreateAmStmt] `json:"tag"`
|
||||
|
||||
Amname *string `json:"amname,omitempty"`
|
||||
HandlerName *List `json:"handler_name,omitempty"`
|
||||
Amtype byte `json:"amtype"`
|
||||
}
|
||||
|
||||
func (n *CreateAmStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
15
internal/sql/ast/create_cast_stmt.go
Normal file
15
internal/sql/ast/create_cast_stmt.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package ast
|
||||
|
||||
type CreateCastStmt struct {
|
||||
Tag NodeTag[CreateCastStmt] `json:"tag"`
|
||||
|
||||
Sourcetype *TypeName `json:"sourcetype,omitempty"`
|
||||
Targettype *TypeName `json:"targettype,omitempty"`
|
||||
Func *ObjectWithArgs `json:"func,omitempty"`
|
||||
Context CoercionContext `json:"context"`
|
||||
Inout bool `json:"inout"`
|
||||
}
|
||||
|
||||
func (n *CreateCastStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
15
internal/sql/ast/create_conversion_stmt.go
Normal file
15
internal/sql/ast/create_conversion_stmt.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package ast
|
||||
|
||||
type CreateConversionStmt struct {
|
||||
Tag NodeTag[CreateConversionStmt] `json:"tag"`
|
||||
|
||||
ConversionName *List `json:"conversion_name,omitempty"`
|
||||
ForEncodingName *string `json:"for_encoding_name,omitempty"`
|
||||
ToEncodingName *string `json:"to_encoding_name,omitempty"`
|
||||
FuncName *List `json:"func_name,omitempty"`
|
||||
Def bool `json:"def"`
|
||||
}
|
||||
|
||||
func (n *CreateConversionStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
14
internal/sql/ast/create_domain_stmt.go
Normal file
14
internal/sql/ast/create_domain_stmt.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast
|
||||
|
||||
type CreateDomainStmt struct {
|
||||
Tag NodeTag[CreateDomainStmt] `json:"tag"`
|
||||
|
||||
Domainname *List `json:"domainname,omitempty"`
|
||||
TypeName *TypeName `json:"type_name,omitempty"`
|
||||
CollClause *CollateClause `json:"coll_clause,omitempty"`
|
||||
Constraints *List `json:"constraints,omitempty"`
|
||||
}
|
||||
|
||||
func (n *CreateDomainStmt) Pos() int {
|
||||
return 0
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user