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:
144
internal/engine/sqlite/utils.go
Normal file
144
internal/engine/sqlite/utils.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
meyer "github.com/sqlc-dev/meyer/ast"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/sql/ast"
|
||||
)
|
||||
|
||||
// identifier folds a name the way SQLite resolves one: an unquoted name is
|
||||
// case-insensitive and normalizes to lower case, while a quoted name keeps
|
||||
// the spelling that appeared between the quotes.
|
||||
func identifier(n *meyer.Ident) string {
|
||||
if n == nil {
|
||||
return ""
|
||||
}
|
||||
if n.Quote == meyer.QuoteNone {
|
||||
return strings.ToLower(n.Name)
|
||||
}
|
||||
return n.Name
|
||||
}
|
||||
|
||||
// NewIdentifier returns the folded name of id as an ast.String, the shape
|
||||
// sqlc uses for the parts of a ColumnRef or a function name.
|
||||
func NewIdentifier(id *meyer.Ident) *ast.String {
|
||||
return &ast.String{Str: identifier(id)}
|
||||
}
|
||||
|
||||
func parseTableName(n *meyer.QualifiedName) *ast.TableName {
|
||||
if n == nil {
|
||||
return &ast.TableName{}
|
||||
}
|
||||
return &ast.TableName{
|
||||
Schema: identifier(n.Schema),
|
||||
Name: identifier(n.Name),
|
||||
}
|
||||
}
|
||||
|
||||
// parseRangeVar builds the relation reference sqlc expects for a table named
|
||||
// in a FROM, INSERT, UPDATE or DELETE clause.
|
||||
func parseRangeVar(n *meyer.QualifiedName, alias *meyer.Ident) *ast.RangeVar {
|
||||
rv := &ast.RangeVar{}
|
||||
if n == nil {
|
||||
return rv
|
||||
}
|
||||
rv.Location = n.Pos()
|
||||
name := identifier(n.Name)
|
||||
rv.Relname = &name
|
||||
if n.Schema != nil {
|
||||
schema := identifier(n.Schema)
|
||||
rv.Schemaname = &schema
|
||||
}
|
||||
if alias != nil {
|
||||
aliasName := identifier(alias)
|
||||
rv.Alias = &ast.Alias{Aliasname: &aliasName}
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
// typeName renders a type the way sqlc's type resolution expects to see it:
|
||||
// the tokens joined without separators, matching what the ANTLR parser's
|
||||
// GetText produced. "UNSIGNED BIG INT" becomes "UNSIGNEDBIGINT" and
|
||||
// "DECIMAL(10, 5)" becomes "DECIMAL(10,5)".
|
||||
func typeName(n *meyer.TypeName) string {
|
||||
if n == nil {
|
||||
return ""
|
||||
}
|
||||
var sb strings.Builder
|
||||
sb.WriteString(strings.ReplaceAll(n.Name, " ", ""))
|
||||
if len(n.Args) > 0 {
|
||||
sb.WriteString("(")
|
||||
sb.WriteString(strings.Join(n.Args, ","))
|
||||
sb.WriteString(")")
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// typeSpelling returns the type as the author wrote it — identifier tokens
|
||||
// space-joined, arguments as written — for the formatter to print back.
|
||||
// typeName folds the spaces out for catalog matching.
|
||||
func typeSpelling(n *meyer.TypeName) string {
|
||||
if n == nil {
|
||||
return ""
|
||||
}
|
||||
var sb strings.Builder
|
||||
sb.WriteString(n.Name)
|
||||
if len(n.Args) > 0 {
|
||||
sb.WriteString("(")
|
||||
sb.WriteString(strings.Join(n.Args, ","))
|
||||
sb.WriteString(")")
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// representableColumn reports whether a column definition round-trips
|
||||
// through the fields ast.ColumnDef models: a plain NOT NULL, a plain
|
||||
// PRIMARY KEY, or nothing. Anything else — a named constraint, a conflict
|
||||
// clause, ASC/DESC or AUTOINCREMENT, DEFAULT, UNIQUE, CHECK, COLLATE,
|
||||
// REFERENCES, GENERATED — is parsed away, so a statement printing such a
|
||||
// column would lose it. NOT NULL next to PRIMARY KEY is also beyond the
|
||||
// node: SQLite's PRIMARY KEY does not imply NOT NULL, and the printed form
|
||||
// carries only one of the pair.
|
||||
func representableColumn(def *meyer.ColumnDef) bool {
|
||||
var notNull, primary bool
|
||||
for _, con := range def.Constraints {
|
||||
switch {
|
||||
case con.Name != nil:
|
||||
return false
|
||||
case con.Kind == meyer.ColumnNotNull && con.OnConflict == meyer.ConflictDefault:
|
||||
notNull = true
|
||||
case con.Kind == meyer.ColumnPrimaryKey && con.OnConflict == meyer.ConflictDefault &&
|
||||
con.Order == meyer.SortDefault && !con.AutoIncrement:
|
||||
primary = true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return !(notNull && primary)
|
||||
}
|
||||
|
||||
// hasPrimaryKeyConstraint reports whether a column definition carries a
|
||||
// PRIMARY KEY constraint.
|
||||
func hasPrimaryKeyConstraint(constraints []*meyer.ColumnConstraint) bool {
|
||||
for _, constraint := range constraints {
|
||||
if constraint.Kind == meyer.ColumnPrimaryKey {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// hasNotNullConstraint reports whether a column definition guarantees a
|
||||
// value. A PRIMARY KEY implies NOT NULL for the purposes of code
|
||||
// generation, matching the behavior of the previous parser.
|
||||
func hasNotNullConstraint(constraints []*meyer.ColumnConstraint) bool {
|
||||
for _, constraint := range constraints {
|
||||
switch constraint.Kind {
|
||||
case meyer.ColumnNotNull, meyer.ColumnPrimaryKey:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user