Skip to content

Commit 4c021f8

Browse files
committed
Merge remote-tracking branch 'github/main' into feat/d272-obligations
2 parents 8448dea + 9ecf9fe commit 4c021f8

201 files changed

Lines changed: 8303 additions & 673 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ A `VALUES` list of more than 1,000 rows is refused for now.
107107
session parameters yet and convert under `utc-v1`.
108108

109109
`convert`, `function`, `census` and `index` read `sqlquack.toml` (or `--policy`); without one they
110-
exit 2 unless `--builtin-policy` asks for the built-in default, which refuses every known divergence.
110+
use the built-in policy, which refuses every known divergence, as `--builtin-policy` asks for.
111111
They share the policy flags (`--policy`, `--builtin-policy`, `--strict`, `--utc-session`,
112112
`--confirm-declared-offsets`, `--python-runtime` and `--loud-divergences-only`, which relies only
113113
on divergences whose converted SQL raises rather than returns another value). Every command with a report takes
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# The names Snowflake gives unaliased ROUND and current-time items, as a playground query writes them.
2+
# The recorded column names are the receipts for naming them.
3+
category = "relational"
4+
construct = "node:alias"
5+
session_profile = "utc-v1"
6+
7+
[[case]]
8+
id = "unaliased_round"
9+
description = "Unaliased ROUND with one and two arguments, in upper and lower case and with inner spaces, over a NULL, a half and a negative."
10+
columns = [{ name = "n", type = "NUMBER(10,2)" }]
11+
rows = [
12+
["1.25"],
13+
["1.25"],
14+
["-2.55"],
15+
["NULL"],
16+
]
17+
query = "SELECT ROUND(n, 1), ROUND(n), round( n, 0 ) FROM input"
18+
order = "ordered"
19+
tags = ["null", "boundary", "duplicates"]
20+
21+
[[case]]
22+
id = "unaliased_round_no_rows"
23+
description = "Unaliased ROUND over no rows still names its columns."
24+
columns = [{ name = "n", type = "NUMBER(10,2)" }]
25+
rows = [
26+
["1.00"],
27+
]
28+
query = "SELECT ROUND(n, 1), ROUND(n) FROM input WHERE n > 5"
29+
order = "ordered"
30+
tags = ["empty-input"]
31+
32+
[[case]]
33+
id = "unaliased_current_time"
34+
description = "Unaliased CURRENT_DATE(), CURRENT_DATE and CURRENT_TIMESTAMP(): only the column names and types are the receipt; the values read the clock, so it is typing evidence."
35+
evidence = "typing"
36+
columns = [{ name = "n", type = "NUMBER(10,2)" }]
37+
rows = [
38+
["1.00"],
39+
]
40+
query = "SELECT CURRENT_DATE(), CURRENT_DATE, CURRENT_TIMESTAMP() FROM input"
41+
order = "ordered"
42+
tags = ["boundary"]
43+
44+
[[case]]
45+
id = "unaliased_distinct_aggregates"
46+
description = "Unaliased SUM, MAX and AVG over DISTINCT, over a duplicate and a NULL. The aggregates are one query and the row expressions another, since one select list cannot hold both without GROUP BY; each item is written as given."
47+
columns = [{ name = "n", type = "NUMBER(10,2)" }, { name = "g", type = "VARCHAR" }]
48+
rows = [
49+
["1.50", "'12'"],
50+
["1.50", "'12'"],
51+
["NULL", "NULL"],
52+
["-2.25", "'-3'"],
53+
]
54+
query = "SELECT SUM(DISTINCT n), MAX(DISTINCT n), AVG(DISTINCT n) FROM input"
55+
order = "ordered"
56+
tags = ["null", "duplicates"]
57+
58+
[[case]]
59+
id = "unaliased_distinct_aggregates_no_rows"
60+
description = "The unaliased DISTINCT aggregates over no rows still name their columns."
61+
columns = [{ name = "n", type = "NUMBER(10,2)" }, { name = "g", type = "VARCHAR" }]
62+
rows = [
63+
["1.00", "'1'"],
64+
]
65+
query = "SELECT SUM(DISTINCT n), MAX(DISTINCT n), AVG(DISTINCT n) FROM input WHERE n > 5"
66+
order = "ordered"
67+
tags = ["empty-input"]
68+
69+
[[case]]
70+
id = "unaliased_row_expressions"
71+
description = "Unaliased COALESCE with a column and with literals only, CAST of numeric text to INTEGER, and lower with a space before its closing parenthesis, over a duplicate and a NULL."
72+
columns = [{ name = "n", type = "NUMBER(10,2)" }, { name = "g", type = "VARCHAR" }]
73+
rows = [
74+
["1.50", "'12'"],
75+
["1.50", "'12'"],
76+
["NULL", "NULL"],
77+
["-2.25", "'-3'"],
78+
]
79+
query = "SELECT COALESCE(n, 0, 1), COALESCE(1, 2), CAST(g AS INTEGER), lower(g ) FROM input"
80+
order = "bag"
81+
tags = ["null", "duplicates"]
82+
83+
[[case]]
84+
id = "unaliased_row_expressions_no_rows"
85+
description = "The unaliased row expressions over no rows still name their columns."
86+
columns = [{ name = "n", type = "NUMBER(10,2)" }, { name = "g", type = "VARCHAR" }]
87+
rows = [
88+
["1.00", "'1'"],
89+
]
90+
query = "SELECT COALESCE(n, 0, 1), COALESCE(1, 2), CAST(g AS INTEGER), lower(g ) FROM input WHERE n > 5"
91+
order = "bag"
92+
tags = ["empty-input"]
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
category = "translation"
2+
construct = "sf.expressions.data-types-datetime.time"
3+
session_profile = "utc-v1"
4+
5+
[[case]]
6+
id = "t001_precision"
7+
description = "TIME keeps all nine fractional digits by default; TIME(3) keeps three and TIME(0) none, read here as the nanosecond part, since the connector carries TIME only to microseconds. Whether the cut rounds or truncates is not on the page, so the recording decides. Catches: the default read as 6 digits or 0, or the precision ignored"
8+
columns = [{ name = "a", type = "VARCHAR" }]
9+
rows = [
10+
["'13:45:10.123456789'"],
11+
["'00:00:01.9996'"],
12+
]
13+
query = "SELECT ordinal, DATE_PART(nanosecond, CAST(a AS TIME)) AS ns9, DATE_PART(nanosecond, CAST(a AS TIME(3))) AS ns3, DATE_PART(second, CAST(a AS TIME(0))) AS s0, DATE_PART(nanosecond, CAST(a AS TIME(0))) AS ns0 FROM input ORDER BY ordinal"
14+
order = "ordered"
15+
tags = ["type-combination"]
16+
17+
[[case]]
18+
id = "t002_range_edges"
19+
description = "The page: TIME values lie between 00:00:00 and 23:59:59.999999999; both ends cast unchanged, read here as hour, second and nanosecond parts. Catches: the last nanosecond rounded to the next day, or cut to microseconds"
20+
columns = [{ name = "a", type = "VARCHAR" }]
21+
rows = [
22+
["'00:00:00'"],
23+
["'23:59:59.999999999'"],
24+
]
25+
query = "SELECT ordinal, DATE_PART(hour, CAST(a AS TIME)) AS h, DATE_PART(second, CAST(a AS TIME)) AS s, DATE_PART(nanosecond, CAST(a AS TIME)) AS ns FROM input ORDER BY ordinal"
26+
order = "ordered"
27+
tags = ["boundary"]
28+
29+
[[case]]
30+
id = "t003_null"
31+
description = "NULL beside a set row, cast to the type; the page gives no special rule, so standard NULL handling applies. Catches: NULL replaced by a value, or the cast raising for NULL"
32+
columns = [{ name = "a", type = "VARCHAR" }]
33+
rows = [
34+
["NULL"],
35+
["'12:00:00'"],
36+
]
37+
query = "SELECT ordinal, CAST(a AS TIME) AS r FROM input ORDER BY ordinal"
38+
order = "ordered"
39+
tags = ["null"]
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
category = "translation"
2+
construct = "sf.expressions.data-types-datetime.timestamp"
3+
session_profile = "utc-v1"
4+
5+
[[case]]
6+
id = "t001_alias_ntz"
7+
description = "The page: TIMESTAMP is TIMESTAMP_NTZ by default, so the wall-clock time is kept and equals the NTZ cast. Catches: TIMESTAMP read as a zoned type, so an offset is applied or the session zone attached"
8+
columns = [{ name = "a", type = "VARCHAR" }]
9+
rows = [
10+
["'2024-03-10 02:30:00'"],
11+
["'1999-12-31 23:59:59.123456789'"],
12+
]
13+
query = "SELECT ordinal, CAST(a AS TIMESTAMP) AS r, CAST(a AS TIMESTAMP) = CAST(a AS TIMESTAMP_NTZ) AS same FROM input ORDER BY ordinal"
14+
order = "ordered"
15+
tags = ["type-combination"]
16+
17+
[[case]]
18+
id = "t002_precision"
19+
description = "The page: the precision is 0 to 9 fractional digits, 9 by default; whether the cut rounds or truncates is not on the page, so the recording decides. Catches: the precision ignored, or the default read as 6"
20+
columns = [{ name = "a", type = "VARCHAR" }]
21+
rows = [
22+
["'2024-01-01 10:00:00.987654321'"],
23+
]
24+
query = "SELECT ordinal, CAST(a AS TIMESTAMP) AS t9, CAST(a AS TIMESTAMP(3)) AS t3, CAST(a AS TIMESTAMP(0)) AS t0 FROM input ORDER BY ordinal"
25+
order = "ordered"
26+
tags = ["type-combination"]
27+
28+
[[case]]
29+
id = "t003_null"
30+
description = "NULL beside a set row, cast to the type; the page gives no special rule, so standard NULL handling applies. Catches: NULL replaced by a value, or the cast raising for NULL"
31+
columns = [{ name = "a", type = "VARCHAR" }]
32+
rows = [
33+
["NULL"],
34+
["'2024-01-01 00:00:00'"],
35+
]
36+
query = "SELECT ordinal, CAST(a AS TIMESTAMP) AS r FROM input ORDER BY ordinal"
37+
order = "ordered"
38+
tags = ["null"]
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
category = "translation"
2+
construct = "sf.expressions.data-types-logical"
3+
session_profile = "utc-v1"
4+
5+
[[case]]
6+
id = "t001_from_text"
7+
description = "The page's twelve strings, in mixed case: the first six convert to TRUE and the last six to FALSE. Catches: only 'true' and 'false' accepted, or the match made case-sensitive"
8+
columns = [{ name = "a", type = "VARCHAR" }]
9+
rows = [
10+
["'true'"],
11+
["'T'"],
12+
["'Yes'"],
13+
["'y'"],
14+
["'ON'"],
15+
["'1'"],
16+
["'FALSE'"],
17+
["'f'"],
18+
["'no'"],
19+
["'N'"],
20+
["'Off'"],
21+
["'0'"],
22+
]
23+
query = "SELECT ordinal, CAST(a AS BOOLEAN) AS r FROM input ORDER BY ordinal"
24+
order = "ordered"
25+
tags = ["type-combination"]
26+
27+
[[case]]
28+
id = "t002_from_number"
29+
description = "The page: zero converts to FALSE and any non-zero value, negative or fractional, to TRUE. Catches: only 1 read as TRUE, or a fraction truncated to 0 first"
30+
columns = [{ name = "n", type = "NUMBER(10,2)" }]
31+
rows = [
32+
["0"],
33+
["-2.5"],
34+
["-0.25"],
35+
["1"],
36+
]
37+
query = "SELECT ordinal, CAST(n AS BOOLEAN) AS b FROM input ORDER BY ordinal"
38+
order = "ordered"
39+
tags = ["type-combination"]
40+
41+
[[case]]
42+
id = "t003_to_text_and_number"
43+
description = "The page: TRUE casts to 'true' and 1, FALSE to 'false' and 0. Catches: upper-case 'TRUE', or 't', or -1 for TRUE"
44+
columns = [{ name = "a", type = "VARCHAR" }]
45+
rows = [
46+
["'yes'"],
47+
["'no'"],
48+
]
49+
query = "SELECT ordinal, CAST(CAST(a AS BOOLEAN) AS VARCHAR) AS s, CAST(CAST(a AS BOOLEAN) AS NUMBER) AS n FROM input ORDER BY ordinal"
50+
order = "ordered"
51+
tags = ["type-combination"]
52+
53+
[[case]]
54+
id = "t004_other_text"
55+
description = "The page: other text strings can't be converted to BOOLEAN, so the cast raises. Catches: the string read as FALSE or NULL"
56+
columns = [{ name = "a", type = "VARCHAR" }]
57+
rows = [
58+
["'maybe'"],
59+
]
60+
query = "SELECT ordinal, CAST(a AS BOOLEAN) AS r FROM input ORDER BY ordinal"
61+
order = "ordered"
62+
tags = ["error"]
63+
64+
[[case]]
65+
id = "t005_implicit_from_text"
66+
description = "The page: implicitly, only 'true' and 'false' convert, case-insensitively, so a VARCHAR column in AND converts without a cast. Catches: the implicit conversion refused, or done case-sensitively"
67+
columns = [{ name = "a", type = "VARCHAR" }]
68+
rows = [
69+
["'true'"],
70+
["'FALSE'"],
71+
["'True'"],
72+
]
73+
query = "SELECT ordinal, a AND TRUE AS r, NOT a AS n FROM input ORDER BY ordinal"
74+
order = "ordered"
75+
tags = ["type-combination"]
76+
77+
[[case]]
78+
id = "t006_implicit_from_number"
79+
description = "The page: implicitly, zero converts to FALSE and any other number to TRUE. Catches: the implicit conversion refused, or only 1 read as TRUE"
80+
columns = [{ name = "n", type = "NUMBER(38,0)" }]
81+
rows = [
82+
["0"],
83+
["1"],
84+
["-3"],
85+
]
86+
query = "SELECT ordinal, n AND TRUE AS r, NOT n AS x FROM input ORDER BY ordinal"
87+
order = "ordered"
88+
tags = ["type-combination"]
89+
90+
[[case]]
91+
id = "t007_implicit_to_text"
92+
description = "The page: a BOOLEAN column or literal concatenated with || converts to 'true' or 'false'. Catches: upper-case TRUE, 't' or 1 in the text"
93+
columns = [{ name = "b", type = "BOOLEAN" }]
94+
rows = [
95+
["TRUE"],
96+
["FALSE"],
97+
]
98+
query = "SELECT ordinal, 'is ' || b AS col, 'lit ' || TRUE AS lit FROM input ORDER BY ordinal"
99+
order = "ordered"
100+
tags = ["type-combination"]
101+
102+
[[case]]
103+
id = "t009_null"
104+
description = "NULL is the unknown BOOLEAN value, kept through the cast. Catches: NULL replaced by a value, or the cast raising for NULL"
105+
columns = [{ name = "a", type = "VARCHAR" }]
106+
rows = [
107+
["NULL"],
108+
["'on'"],
109+
]
110+
query = "SELECT ordinal, CAST(a AS BOOLEAN) AS r FROM input ORDER BY ordinal"
111+
order = "ordered"
112+
tags = ["null"]
113+
114+
[[case]]
115+
id = "t010_from_float"
116+
compile_error = true
117+
description = "The page's numeric conversion does not exclude FLOAT, but Snowflake refuses a FLOAT argument at compile time (recorded as 1007/22023, invalid type for parameter 'TO_BOOLEAN'); this case keeps that behaviour. Catches: the FLOAT converted as a number"
118+
columns = [{ name = "f", type = "FLOAT" }]
119+
rows = [
120+
["0"],
121+
["0.001"],
122+
]
123+
query = "SELECT ordinal, CAST(f AS BOOLEAN) AS b FROM input ORDER BY ordinal"
124+
order = "ordered"
125+
tags = ["error"]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
category = "translation"
2+
construct = "sf.expressions.data-types-numeric.double"
3+
session_profile = "utc-v1"
4+
5+
[[case]]
6+
id = "t001_synonyms"
7+
description = "The page: all three are FLOAT, so each equals the FLOAT cast of the same text, with full double precision. Catches: REAL read as a 32-bit float (0.1 losing digits), or a decimal type"
8+
columns = [{ name = "a", type = "VARCHAR" }]
9+
rows = [
10+
["'0.1'"],
11+
["'1e300'"],
12+
["'-2.5'"],
13+
]
14+
query = "SELECT ordinal, CAST(a AS DOUBLE) AS d, CAST(a AS DOUBLE PRECISION) = CAST(a AS FLOAT) AS dp_same, CAST(a AS REAL) = CAST(a AS FLOAT) AS real_same FROM input ORDER BY ordinal"
15+
order = "ordered"
16+
tags = ["type-combination"]
17+
18+
[[case]]
19+
id = "t002_special_values"
20+
description = "The page: the quoted special values are case-insensitive; 'NaN' equals 'NaN' and is greater than infinity. Catches: NaN unequal to itself (IEEE), NaN smaller than infinity, or the mixed-case spellings rejected"
21+
columns = [{ name = "a", type = "VARCHAR" }]
22+
rows = [
23+
["'NaN'"],
24+
["'INF'"],
25+
["'-inf'"],
26+
]
27+
query = "SELECT ordinal, CAST(a AS DOUBLE) AS d, CAST(a AS DOUBLE) = CAST('nan' AS DOUBLE) AS eq_nan, CAST('NaN' AS DOUBLE) > CAST(a AS DOUBLE) AS nan_greater FROM input ORDER BY ordinal"
28+
order = "ordered"
29+
tags = ["type-combination"]
30+
31+
[[case]]
32+
id = "t003_null"
33+
description = "NULL beside a set row, cast to the type; the page gives no special rule, so standard NULL handling applies. Catches: NULL replaced by a value, or the cast raising for NULL"
34+
columns = [{ name = "a", type = "VARCHAR" }]
35+
rows = [
36+
["NULL"],
37+
["'1.5'"],
38+
]
39+
query = "SELECT ordinal, CAST(a AS REAL) AS r FROM input ORDER BY ordinal"
40+
order = "ordered"
41+
tags = ["null"]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
category = "translation"
2+
construct = "sf.expressions.data-types-numeric.int"
3+
session_profile = "utc-v1"
4+
5+
[[case]]
6+
id = "t001_synonyms_wide"
7+
description = "A 21-digit integer cast to each spelling keeps every digit, since all are NUMBER(38, 0). Catches: BIGINT read as 64-bit, or SMALLINT, TINYINT or BYTEINT as 16 or 8 bits (overflow or wrap-around)"
8+
columns = [{ name = "a", type = "VARCHAR" }]
9+
rows = [
10+
["'123456789012345678901'"],
11+
["'-300'"],
12+
]
13+
query = "SELECT ordinal, CAST(a AS INT) AS i, CAST(a AS INTEGER) AS ig, CAST(a AS BIGINT) AS bi, CAST(a AS SMALLINT) AS si, CAST(a AS TINYINT) AS ti, CAST(a AS BYTEINT) AS byi FROM input ORDER BY ordinal"
14+
order = "ordered"
15+
tags = ["type-combination"]
16+
17+
[[case]]
18+
id = "t002_thirty_eight_digits"
19+
description = "The page: the range of every integer type is -(10^38 - 1) to 10^38 - 1, so both ends cast unchanged. Catches: the value rejected or rounded through a float"
20+
columns = [{ name = "a", type = "VARCHAR" }]
21+
rows = [
22+
["'99999999999999999999999999999999999999'"],
23+
["'-99999999999999999999999999999999999999'"],
24+
]
25+
query = "SELECT ordinal, CAST(a AS INT) AS r FROM input ORDER BY ordinal"
26+
order = "ordered"
27+
tags = ["boundary"]
28+
29+
[[case]]
30+
id = "t003_past_38_digits"
31+
description = "The page: the integer types hold at most 38 digits, so 10^38 is out of range and the cast raises. Catches: the value kept or rounded"
32+
columns = [{ name = "a", type = "VARCHAR" }]
33+
rows = [
34+
["'100000000000000000000000000000000000000'"],
35+
]
36+
query = "SELECT ordinal, CAST(a AS INT) AS r FROM input ORDER BY ordinal"
37+
order = "ordered"
38+
tags = ["error"]
39+
40+
[[case]]
41+
id = "t004_null"
42+
description = "NULL beside a set row, cast to the type; the page gives no special rule, so standard NULL handling applies. Catches: NULL replaced by a value, or the cast raising for NULL"
43+
columns = [{ name = "a", type = "VARCHAR" }]
44+
rows = [
45+
["NULL"],
46+
["'7'"],
47+
]
48+
query = "SELECT ordinal, CAST(a AS SMALLINT) AS r FROM input ORDER BY ordinal"
49+
order = "ordered"
50+
tags = ["null"]

0 commit comments

Comments
 (0)