Skip to content

Commit 8551ef1

Browse files
committed
goldeneye: generate Spanner's types, functions and operators
Spanner keeps no catalog of its library, so goldeneye now reads it by asking. spanner/library.jsonl lists the function signatures to try; each is compiled in PLAN mode against a probe database, and the ones Spanner accepts are written to functions.jsonl with the type it reports. A polymorphic signature is tried with INT64 and STRING and its result must hold for both. Calls a select list cannot make are compiled the way they can be: SEARCH in a WHERE clause, SCORE over a search index, PENDING_COMMIT_TIMESTAMP in an INSERT. operators.jsonl is every binary operator Spanner accepts over the operands tried, and types.jsonl the types the dialect lists, each one Spanner has checked by a cast; the GoogleSQL types only BigQuery has are kept as they are. The generated files hold the same records the seed already did; they are rewritten in goldeneye's compact form, and TestDialect now checks all four files against Spanner. The dialect package's Function gains never_null, which the seed already reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L8QoGi6VRtADkb4jL3BFHP
1 parent ddc27a3 commit 8551ef1

8 files changed

Lines changed: 1187 additions & 407 deletions

File tree

‎internal/engine/googlesql/dialect/functions.jsonl‎

Lines changed: 291 additions & 291 deletions
Large diffs are not rendered by default.
Lines changed: 83 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,83 @@
1-
{"name": "+", "left": "int64", "right": "int64", "result": "int64"}
2-
{"name": "+", "left": "int64", "right": "float64", "result": "float64"}
3-
{"name": "+", "left": "int64", "right": "float32", "result": "float64"}
4-
{"name": "+", "left": "int64", "right": "numeric", "result": "numeric"}
5-
{"name": "+", "left": "float64", "right": "int64", "result": "float64"}
6-
{"name": "+", "left": "float64", "right": "float64", "result": "float64"}
7-
{"name": "+", "left": "float64", "right": "float32", "result": "float64"}
8-
{"name": "+", "left": "float64", "right": "numeric", "result": "float64"}
9-
{"name": "+", "left": "float32", "right": "int64", "result": "float64"}
10-
{"name": "+", "left": "float32", "right": "float64", "result": "float64"}
11-
{"name": "+", "left": "float32", "right": "float32", "result": "float64"}
12-
{"name": "+", "left": "float32", "right": "numeric", "result": "float64"}
13-
{"name": "+", "left": "numeric", "right": "int64", "result": "numeric"}
14-
{"name": "+", "left": "numeric", "right": "float64", "result": "float64"}
15-
{"name": "+", "left": "numeric", "right": "float32", "result": "float64"}
16-
{"name": "+", "left": "numeric", "right": "numeric", "result": "numeric"}
17-
{"name": "-", "left": "int64", "right": "int64", "result": "int64"}
18-
{"name": "-", "left": "int64", "right": "float64", "result": "float64"}
19-
{"name": "-", "left": "int64", "right": "float32", "result": "float64"}
20-
{"name": "-", "left": "int64", "right": "numeric", "result": "numeric"}
21-
{"name": "-", "left": "float64", "right": "int64", "result": "float64"}
22-
{"name": "-", "left": "float64", "right": "float64", "result": "float64"}
23-
{"name": "-", "left": "float64", "right": "float32", "result": "float64"}
24-
{"name": "-", "left": "float64", "right": "numeric", "result": "float64"}
25-
{"name": "-", "left": "float32", "right": "int64", "result": "float64"}
26-
{"name": "-", "left": "float32", "right": "float64", "result": "float64"}
27-
{"name": "-", "left": "float32", "right": "float32", "result": "float64"}
28-
{"name": "-", "left": "float32", "right": "numeric", "result": "float64"}
29-
{"name": "-", "left": "numeric", "right": "int64", "result": "numeric"}
30-
{"name": "-", "left": "numeric", "right": "float64", "result": "float64"}
31-
{"name": "-", "left": "numeric", "right": "float32", "result": "float64"}
32-
{"name": "-", "left": "numeric", "right": "numeric", "result": "numeric"}
33-
{"name": "*", "left": "int64", "right": "int64", "result": "int64"}
34-
{"name": "*", "left": "int64", "right": "float64", "result": "float64"}
35-
{"name": "*", "left": "int64", "right": "float32", "result": "float64"}
36-
{"name": "*", "left": "int64", "right": "numeric", "result": "numeric"}
37-
{"name": "*", "left": "float64", "right": "int64", "result": "float64"}
38-
{"name": "*", "left": "float64", "right": "float64", "result": "float64"}
39-
{"name": "*", "left": "float64", "right": "float32", "result": "float64"}
40-
{"name": "*", "left": "float64", "right": "numeric", "result": "float64"}
41-
{"name": "*", "left": "float32", "right": "int64", "result": "float64"}
42-
{"name": "*", "left": "float32", "right": "float64", "result": "float64"}
43-
{"name": "*", "left": "float32", "right": "float32", "result": "float64"}
44-
{"name": "*", "left": "float32", "right": "numeric", "result": "float64"}
45-
{"name": "*", "left": "numeric", "right": "int64", "result": "numeric"}
46-
{"name": "*", "left": "numeric", "right": "float64", "result": "float64"}
47-
{"name": "*", "left": "numeric", "right": "float32", "result": "float64"}
48-
{"name": "*", "left": "numeric", "right": "numeric", "result": "numeric"}
49-
{"name": "/", "left": "int64", "right": "int64", "result": "float64"}
50-
{"name": "/", "left": "int64", "right": "float64", "result": "float64"}
51-
{"name": "/", "left": "int64", "right": "float32", "result": "float64"}
52-
{"name": "/", "left": "int64", "right": "numeric", "result": "numeric"}
53-
{"name": "/", "left": "float64", "right": "int64", "result": "float64"}
54-
{"name": "/", "left": "float64", "right": "float64", "result": "float64"}
55-
{"name": "/", "left": "float64", "right": "float32", "result": "float64"}
56-
{"name": "/", "left": "float64", "right": "numeric", "result": "float64"}
57-
{"name": "/", "left": "float32", "right": "int64", "result": "float64"}
58-
{"name": "/", "left": "float32", "right": "float64", "result": "float64"}
59-
{"name": "/", "left": "float32", "right": "float32", "result": "float64"}
60-
{"name": "/", "left": "float32", "right": "numeric", "result": "float64"}
61-
{"name": "/", "left": "numeric", "right": "int64", "result": "numeric"}
62-
{"name": "/", "left": "numeric", "right": "float64", "result": "float64"}
63-
{"name": "/", "left": "numeric", "right": "float32", "result": "float64"}
64-
{"name": "/", "left": "numeric", "right": "numeric", "result": "numeric"}
65-
{"name": "||", "left": "string", "right": "string", "result": "string"}
66-
{"name": "||", "left": "bytes", "right": "bytes", "result": "bytes"}
67-
{"name": "+", "left": "timestamp", "right": "interval", "result": "timestamp"}
68-
{"name": "-", "left": "timestamp", "right": "interval", "result": "timestamp"}
69-
{"name": "+", "left": "interval", "right": "timestamp", "result": "timestamp"}
70-
{"name": "-", "left": "date", "right": "date", "result": "interval"}
71-
{"name": "-", "left": "timestamp", "right": "timestamp", "result": "interval"}
72-
{"name": "+", "left": "interval", "right": "interval", "result": "interval"}
73-
{"name": "-", "left": "interval", "right": "interval", "result": "interval"}
74-
{"name": "*", "left": "interval", "right": "int64", "result": "interval"}
75-
{"name": "/", "left": "interval", "right": "int64", "result": "interval"}
76-
{"name": "&", "left": "int64", "right": "int64", "result": "int64"}
77-
{"name": "|", "left": "int64", "right": "int64", "result": "int64"}
78-
{"name": "^", "left": "int64", "right": "int64", "result": "int64"}
79-
{"name": "<<", "left": "int64", "right": "int64", "result": "int64"}
80-
{"name": ">>", "left": "int64", "right": "int64", "result": "int64"}
81-
{"name": "&", "left": "bytes", "right": "bytes", "result": "bytes"}
82-
{"name": "|", "left": "bytes", "right": "bytes", "result": "bytes"}
83-
{"name": "^", "left": "bytes", "right": "bytes", "result": "bytes"}
1+
{"name":"+","left":"int64","right":"int64","result":"int64"}
2+
{"name":"+","left":"int64","right":"float64","result":"float64"}
3+
{"name":"+","left":"int64","right":"float32","result":"float64"}
4+
{"name":"+","left":"int64","right":"numeric","result":"numeric"}
5+
{"name":"+","left":"float64","right":"int64","result":"float64"}
6+
{"name":"+","left":"float64","right":"float64","result":"float64"}
7+
{"name":"+","left":"float64","right":"float32","result":"float64"}
8+
{"name":"+","left":"float64","right":"numeric","result":"float64"}
9+
{"name":"+","left":"float32","right":"int64","result":"float64"}
10+
{"name":"+","left":"float32","right":"float64","result":"float64"}
11+
{"name":"+","left":"float32","right":"float32","result":"float64"}
12+
{"name":"+","left":"float32","right":"numeric","result":"float64"}
13+
{"name":"+","left":"numeric","right":"int64","result":"numeric"}
14+
{"name":"+","left":"numeric","right":"float64","result":"float64"}
15+
{"name":"+","left":"numeric","right":"float32","result":"float64"}
16+
{"name":"+","left":"numeric","right":"numeric","result":"numeric"}
17+
{"name":"-","left":"int64","right":"int64","result":"int64"}
18+
{"name":"-","left":"int64","right":"float64","result":"float64"}
19+
{"name":"-","left":"int64","right":"float32","result":"float64"}
20+
{"name":"-","left":"int64","right":"numeric","result":"numeric"}
21+
{"name":"-","left":"float64","right":"int64","result":"float64"}
22+
{"name":"-","left":"float64","right":"float64","result":"float64"}
23+
{"name":"-","left":"float64","right":"float32","result":"float64"}
24+
{"name":"-","left":"float64","right":"numeric","result":"float64"}
25+
{"name":"-","left":"float32","right":"int64","result":"float64"}
26+
{"name":"-","left":"float32","right":"float64","result":"float64"}
27+
{"name":"-","left":"float32","right":"float32","result":"float64"}
28+
{"name":"-","left":"float32","right":"numeric","result":"float64"}
29+
{"name":"-","left":"numeric","right":"int64","result":"numeric"}
30+
{"name":"-","left":"numeric","right":"float64","result":"float64"}
31+
{"name":"-","left":"numeric","right":"float32","result":"float64"}
32+
{"name":"-","left":"numeric","right":"numeric","result":"numeric"}
33+
{"name":"*","left":"int64","right":"int64","result":"int64"}
34+
{"name":"*","left":"int64","right":"float64","result":"float64"}
35+
{"name":"*","left":"int64","right":"float32","result":"float64"}
36+
{"name":"*","left":"int64","right":"numeric","result":"numeric"}
37+
{"name":"*","left":"float64","right":"int64","result":"float64"}
38+
{"name":"*","left":"float64","right":"float64","result":"float64"}
39+
{"name":"*","left":"float64","right":"float32","result":"float64"}
40+
{"name":"*","left":"float64","right":"numeric","result":"float64"}
41+
{"name":"*","left":"float32","right":"int64","result":"float64"}
42+
{"name":"*","left":"float32","right":"float64","result":"float64"}
43+
{"name":"*","left":"float32","right":"float32","result":"float64"}
44+
{"name":"*","left":"float32","right":"numeric","result":"float64"}
45+
{"name":"*","left":"numeric","right":"int64","result":"numeric"}
46+
{"name":"*","left":"numeric","right":"float64","result":"float64"}
47+
{"name":"*","left":"numeric","right":"float32","result":"float64"}
48+
{"name":"*","left":"numeric","right":"numeric","result":"numeric"}
49+
{"name":"/","left":"int64","right":"int64","result":"float64"}
50+
{"name":"/","left":"int64","right":"float64","result":"float64"}
51+
{"name":"/","left":"int64","right":"float32","result":"float64"}
52+
{"name":"/","left":"int64","right":"numeric","result":"numeric"}
53+
{"name":"/","left":"float64","right":"int64","result":"float64"}
54+
{"name":"/","left":"float64","right":"float64","result":"float64"}
55+
{"name":"/","left":"float64","right":"float32","result":"float64"}
56+
{"name":"/","left":"float64","right":"numeric","result":"float64"}
57+
{"name":"/","left":"float32","right":"int64","result":"float64"}
58+
{"name":"/","left":"float32","right":"float64","result":"float64"}
59+
{"name":"/","left":"float32","right":"float32","result":"float64"}
60+
{"name":"/","left":"float32","right":"numeric","result":"float64"}
61+
{"name":"/","left":"numeric","right":"int64","result":"numeric"}
62+
{"name":"/","left":"numeric","right":"float64","result":"float64"}
63+
{"name":"/","left":"numeric","right":"float32","result":"float64"}
64+
{"name":"/","left":"numeric","right":"numeric","result":"numeric"}
65+
{"name":"||","left":"string","right":"string","result":"string"}
66+
{"name":"||","left":"bytes","right":"bytes","result":"bytes"}
67+
{"name":"+","left":"timestamp","right":"interval","result":"timestamp"}
68+
{"name":"+","left":"interval","right":"interval","result":"interval"}
69+
{"name":"-","left":"timestamp","right":"interval","result":"timestamp"}
70+
{"name":"-","left":"interval","right":"interval","result":"interval"}
71+
{"name":"+","left":"interval","right":"timestamp","result":"timestamp"}
72+
{"name":"-","left":"date","right":"date","result":"interval"}
73+
{"name":"-","left":"timestamp","right":"timestamp","result":"interval"}
74+
{"name":"*","left":"interval","right":"int64","result":"interval"}
75+
{"name":"/","left":"interval","right":"int64","result":"interval"}
76+
{"name":"\u0026","left":"int64","right":"int64","result":"int64"}
77+
{"name":"|","left":"int64","right":"int64","result":"int64"}
78+
{"name":"^","left":"int64","right":"int64","result":"int64"}
79+
{"name":"\u003c\u003c","left":"int64","right":"int64","result":"int64"}
80+
{"name":"\u003e\u003e","left":"int64","right":"int64","result":"int64"}
81+
{"name":"\u0026","left":"bytes","right":"bytes","result":"bytes"}
82+
{"name":"|","left":"bytes","right":"bytes","result":"bytes"}
83+
{"name":"^","left":"bytes","right":"bytes","result":"bytes"}
Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
{"name": "bool", "category": "B"}
2-
{"name": "int64", "category": "N"}
3-
{"name": "float32", "category": "N"}
4-
{"name": "float64", "category": "N"}
5-
{"name": "numeric", "category": "N"}
6-
{"name": "bignumeric", "category": "N"}
7-
{"name": "string", "category": "S"}
8-
{"name": "bytes", "category": "S"}
9-
{"name": "uuid", "category": "S"}
10-
{"name": "date", "category": "D"}
11-
{"name": "datetime", "category": "D"}
12-
{"name": "time", "category": "D"}
13-
{"name": "timestamp", "category": "D"}
14-
{"name": "interval", "category": "T"}
15-
{"name": "json", "category": "U"}
16-
{"name": "geography", "category": "U"}
17-
{"name": "struct", "category": "U"}
18-
{"name": "enum", "category": "U"}
19-
{"name": "proto", "category": "U"}
20-
{"name": "tokenlist", "category": "U"}
21-
{"name": "array", "category": "A"}
22-
{"name": "range", "category": "U"}
23-
{"name": "map", "category": "U"}
1+
{"name":"bool","category":"B"}
2+
{"name":"int64","category":"N"}
3+
{"name":"float32","category":"N"}
4+
{"name":"float64","category":"N"}
5+
{"name":"numeric","category":"N"}
6+
{"name":"bignumeric","category":"N"}
7+
{"name":"string","category":"S"}
8+
{"name":"bytes","category":"S"}
9+
{"name":"uuid","category":"S"}
10+
{"name":"date","category":"D"}
11+
{"name":"datetime","category":"D"}
12+
{"name":"time","category":"D"}
13+
{"name":"timestamp","category":"D"}
14+
{"name":"interval","category":"T"}
15+
{"name":"json","category":"U"}
16+
{"name":"geography","category":"U"}
17+
{"name":"struct","category":"U"}
18+
{"name":"enum","category":"U"}
19+
{"name":"proto","category":"U"}
20+
{"name":"tokenlist","category":"U"}
21+
{"name":"array","category":"A"}
22+
{"name":"range","category":"U"}
23+
{"name":"map","category":"U"}

‎internal/goldeneye/README.md‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,15 @@ the hand-written files alone, and the checks do not look at them.
110110
the gRPC endpoint such as `localhost:15000`, reached without TLS or
111111
credentials as Omni is, and writes into `internal/engine/googlesql/dialect`,
112112
since sqlc's engine is named after the language Spanner speaks. Spanner
113-
keeps no catalog of its types, functions or operators, so `types.jsonl`,
114-
`functions.jsonl` and `operators.jsonl` are hand-written. What it does
115-
describe is its information schema: `relations.jsonl` is every view of
113+
keeps no catalog of its types, functions or operators, so they are read
114+
by asking: `spanner/library.jsonl` lists the function signatures to try,
115+
and each is compiled in PLAN mode against a probe database, the ones
116+
Spanner accepts written to `functions.jsonl` with the type it reports;
117+
`operators.jsonl` is every binary operator Spanner accepts over the
118+
operands tried, and `types.jsonl` the types the dialect lists, each one
119+
Spanner has checked by a cast. Whether a result can be NULL is what
120+
Spanner does not say, so `library.jsonl` says it. Spanner also
121+
describes its information schema: `relations.jsonl` is every view of
116122
`INFORMATION_SCHEMA` and `SPANNER_SYS`, read from `INFORMATION_SCHEMA`
117123
itself in a database created for the purpose in the instance Omni's
118124
single server provides, `projects/default/instances/default`. Names are

‎internal/goldeneye/dialect/dialect.go‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ type Function struct {
6969
Args []Arg `json:"args,omitempty"`
7070
Returns string `json:"returns"`
7171
Nullable bool `json:"nullable,omitempty"`
72+
// NeverNull marks a result that is never NULL even when an argument
73+
// is, in a dialect that propagates nullability.
74+
NeverNull bool `json:"never_null,omitempty"`
7275
}
7376

7477
// Arg is one of a function's parameters. Mode is 'i'n, 'o'ut, 'b'oth,

0 commit comments

Comments
 (0)