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
137 lines
4.6 KiB
Go
137 lines
4.6 KiB
Go
package sqlite
|
|
|
|
import "github.com/sqlc-dev/sqlc/internal/goldeneye/dialect"
|
|
|
|
// signature is what a function returns and what its arguments hold, read
|
|
// from the amalgamation by source.signature. Args types the leading
|
|
// arguments in order; a position it does not cover is "any", which the
|
|
// analyzer resolves to the argument's own type. Variadic types the
|
|
// arguments an overload of variable arity repeats, "any" when empty. How
|
|
// many arguments an overload takes, and how many of them it requires,
|
|
// comes from the shell. Nullable is decided afterwards: for an aggregate by
|
|
// running it over no rows, for a scalar by the nullable list below.
|
|
// Numeric says the function returns an integer for an integer argument
|
|
// and a real for a real one, and Returns what it returns for anything
|
|
// else.
|
|
type signature struct {
|
|
Args []string
|
|
Variadic string
|
|
Returns string
|
|
Numeric bool
|
|
Nullable bool
|
|
}
|
|
|
|
// args builds an overload's parameters from the shell's argument count. A
|
|
// fixed count is that many parameters; a negative count is the required
|
|
// leading parameters, any further ones the signature types marked as
|
|
// having a default, and a variadic tail.
|
|
func (s signature) args(narg int) []dialect.Arg {
|
|
if narg >= 0 {
|
|
args := make([]dialect.Arg, narg)
|
|
for i := range args {
|
|
args[i] = dialect.Arg{Type: s.argType(i)}
|
|
}
|
|
return args
|
|
}
|
|
required := minArgs(narg)
|
|
n := max(required, len(s.Args))
|
|
args := make([]dialect.Arg, 0, n+1)
|
|
for i := 0; i < n; i++ {
|
|
args = append(args, dialect.Arg{Type: s.argType(i), HasDefault: i >= required})
|
|
}
|
|
tail := s.Variadic
|
|
if tail == "" {
|
|
tail = "any"
|
|
}
|
|
return append(args, dialect.Arg{Type: tail, Mode: "v"})
|
|
}
|
|
|
|
func (s signature) argType(i int) string {
|
|
if i < len(s.Args) {
|
|
return s.Args[i]
|
|
}
|
|
return "any"
|
|
}
|
|
|
|
// inlineReturns is what the functions the VDBE implements in bytecode
|
|
// return, by the INLINEFUNC_* constant their registration carries. All but
|
|
// one hand back one of their arguments, which is what the default of "any"
|
|
// says; sqlite_offset is a byte offset.
|
|
var inlineReturns = map[string]string{
|
|
"INLINEFUNC_sqlite_offset": "integer",
|
|
}
|
|
|
|
// realResults are the functions that return an integer or a real on
|
|
// something other than which their argument is, and so are typed real
|
|
// alone: unixepoch takes a time string and returns a real only with the
|
|
// 'subsec' modifier.
|
|
var realResults = map[string]bool{
|
|
"unixepoch": true,
|
|
}
|
|
|
|
// omitted are functions the dialect leaves out: ones that exist for their
|
|
// side effect and return nothing a query can use, and ones an extension
|
|
// uses to pass pointers to itself.
|
|
var omitted = map[string]bool{
|
|
// Loads a shared library and returns NULL.
|
|
"load_extension": true,
|
|
// Writes to the error log and returns NULL.
|
|
"sqlite_log": true,
|
|
// FTS3's and FTS5's ways of passing pointers to their virtual tables,
|
|
// not functions a query calls.
|
|
"fts3_tokenizer": true,
|
|
"fts5": true,
|
|
// A debugging aid of GEOPOLY's.
|
|
"geopoly_debug": true,
|
|
}
|
|
|
|
// nullable are the scalar functions that return NULL for arguments that
|
|
// are not: a lookup that finds nothing, an input that does not parse, a
|
|
// value with no sign. The source cannot say this — a SQLite function
|
|
// returns NULL as often by setting no result as by calling
|
|
// sqlite3_result_null — so it is listed by the documentation of each.
|
|
// Aggregates are not listed: whether one returns NULL over no rows is
|
|
// found by running it over none.
|
|
var nullable = map[string]bool{
|
|
// Core functions.
|
|
"nullif": true,
|
|
"sign": true,
|
|
"sqlite_compileoption_get": true,
|
|
"sqlite_offset": true,
|
|
"unhex": true,
|
|
// Date and time functions, for a time value they cannot parse.
|
|
"date": true,
|
|
"datetime": true,
|
|
"julianday": true,
|
|
"strftime": true,
|
|
"time": true,
|
|
"timediff": true,
|
|
"unixepoch": true,
|
|
// JSON functions, for a path that leads nowhere.
|
|
"->": true,
|
|
"->>": true,
|
|
"json_array_length": true,
|
|
"json_extract": true,
|
|
"json_type": true,
|
|
"jsonb_extract": true,
|
|
// Window functions, for a row outside the frame.
|
|
"first_value": true,
|
|
"lag": true,
|
|
"last_value": true,
|
|
"lead": true,
|
|
"nth_value": true,
|
|
// FTS5, for a table with no locale.
|
|
"fts5_get_locale": true,
|
|
// GEOPOLY functions, for an argument that is not a polygon.
|
|
"geopoly_area": true,
|
|
"geopoly_bbox": true,
|
|
"geopoly_blob": true,
|
|
"geopoly_ccw": true,
|
|
"geopoly_contains_point": true,
|
|
"geopoly_json": true,
|
|
"geopoly_overlap": true,
|
|
"geopoly_svg": true,
|
|
"geopoly_within": true,
|
|
"geopoly_xform": true,
|
|
}
|