diff --git a/cases/translation/functions/add-months.toml b/cases/translation/functions/add-months.toml index dc11ff354..1aa78b9ee 100644 --- a/cases/translation/functions/add-months.toml +++ b/cases/translation/functions/add-months.toml @@ -86,3 +86,18 @@ rows = [ query = "SELECT ADD_MONTHS('2024-01-15'::DATE, n) AS r FROM input ORDER BY ordinal" order = "ordered" tags = ["boundary"] + +[[case]] +id = "t008_negative_and_day_31" +description = "Negative counts from month ends and day 31 into shorter months, across a year. Catches: the month end lost going backwards, or day 31 overflowing into the next month" +columns = [{ name = "d", type = "DATE" }] +rows = [ + ["'2024-03-31'"], + ["'2024-01-31'"], + ["'2024-05-31'"], + ["'2023-01-29'"], + ["'2024-12-15'"], +] +query = "SELECT ADD_MONTHS(d, -1) AS m1, ADD_MONTHS(d, 1) AS p1, ADD_MONTHS(d, -13) AS m13 FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/corr.corr.toml b/cases/translation/functions/corr.corr.toml index 48f105726..ca0d9bd4b 100644 --- a/cases/translation/functions/corr.corr.toml +++ b/cases/translation/functions/corr.corr.toml @@ -83,3 +83,30 @@ rows = [ query = "SELECT CORR(y, x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t007_large_mean" +description = "Pairs near 1e9 with small spreads. Catches: a sum-of-products formula losing the digits of the spread" +columns = [{ name = "y", type = "NUMBER(38,0)" }, { name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000002", "1000000001"], + ["1000000004", "1000000002"], + ["1000000005", "1000000003"], + ["1000000009", "1000000004"], +] +query = "SELECT CORR(y, x) AS r FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t008_decimal" +description = "NUMBER(10,2) columns. Catches: the result type or scale of decimal inputs" +columns = [{ name = "y", type = "NUMBER(10,2)" }, { name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25", "2.50"], + ["2.50", "2.75"], + ["4.10", "3.00"], +] +query = "SELECT CORR(y, x) AS r, SYSTEM$TYPEOF(CORR(y, x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/covar-pop.covar-pop.toml b/cases/translation/functions/covar-pop.covar-pop.toml index 5beba504c..e2fcf8403 100644 --- a/cases/translation/functions/covar-pop.covar-pop.toml +++ b/cases/translation/functions/covar-pop.covar-pop.toml @@ -70,3 +70,31 @@ rows = [ query = "SELECT COVAR_POP(y, x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t006_large_mean" +description = "Pairs near 1e9 with small spreads. Catches: a sum-of-products formula losing the digits of the spread" +columns = [{ name = "y", type = "NUMBER(38,0)" }, { name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000002", "1000000001"], + ["1000000004", "1000000002"], + ["1000000005", "1000000003"], + ["1000000009", "1000000004"], +] +query = "SELECT COVAR_POP(y, x) AS r FROM input" +order = "ordered" +expected_divergence = "float_sum_order" +tags = ["type-combination"] + +[[case]] +id = "t007_decimal" +description = "NUMBER(10,2) columns. Catches: the result type or scale of decimal inputs" +columns = [{ name = "y", type = "NUMBER(10,2)" }, { name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25", "2.50"], + ["2.50", "2.75"], + ["4.10", "3.00"], +] +query = "SELECT COVAR_POP(y, x) AS r, SYSTEM$TYPEOF(COVAR_POP(y, x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/covar-samp.covar-samp.toml b/cases/translation/functions/covar-samp.covar-samp.toml index eedac2bc3..b751b9549 100644 --- a/cases/translation/functions/covar-samp.covar-samp.toml +++ b/cases/translation/functions/covar-samp.covar-samp.toml @@ -70,3 +70,31 @@ rows = [ query = "SELECT COVAR_SAMP(y, x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t006_large_mean" +description = "Pairs near 1e9 with small spreads. Catches: a sum-of-products formula losing the digits of the spread" +columns = [{ name = "y", type = "NUMBER(38,0)" }, { name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000002", "1000000001"], + ["1000000004", "1000000002"], + ["1000000005", "1000000003"], + ["1000000009", "1000000004"], +] +query = "SELECT COVAR_SAMP(y, x) AS r FROM input" +order = "ordered" +expected_divergence = "float_sum_order" +tags = ["type-combination"] + +[[case]] +id = "t007_decimal" +description = "NUMBER(10,2) columns. Catches: the result type or scale of decimal inputs" +columns = [{ name = "y", type = "NUMBER(10,2)" }, { name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25", "2.50"], + ["2.50", "2.75"], + ["4.10", "3.00"], +] +query = "SELECT COVAR_SAMP(y, x) AS r, SYSTEM$TYPEOF(COVAR_SAMP(y, x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/months-between.toml b/cases/translation/functions/months-between.toml index 353a6499c..a878b8a4c 100644 --- a/cases/translation/functions/months-between.toml +++ b/cases/translation/functions/months-between.toml @@ -84,3 +84,29 @@ rows = [ query = "SELECT MONTHS_BETWEEN(a, b) AS r FROM input ORDER BY ordinal" order = "ordered" tags = ["boundary"] + +[[case]] +id = "t008_month_ends_with_time" +description = "Timestamps on month ends and on equal days, with times of day. Catches: the time counted when both are month ends or share a day, or the fraction taken over the month length instead of 31 days" +columns = [{ name = "a", type = "TIMESTAMP_NTZ" }, { name = "b", type = "TIMESTAMP_NTZ" }] +rows = [ + ["'2019-03-31 23:00:00'", "'2019-02-28 01:00:00'"], + ["'2024-04-30 00:00:00'", "'2024-03-30 12:00:00'"], + ["'2024-01-31 06:00:00'", "'2024-02-29 18:00:00'"], + ["'2024-01-10 06:00:00'", "'2024-02-20 18:00:00'"], +] +query = "SELECT MONTHS_BETWEEN(a, b) AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t009_long_negative" +description = "A span of years, negative. Catches: the whole months or the fraction miscounted far apart" +columns = [{ name = "a", type = "DATE" }, { name = "b", type = "DATE" }] +rows = [ + ["'2000-01-15'", "'2024-07-20'"], + ["'2024-07-20'", "'1999-12-31'"], +] +query = "SELECT MONTHS_BETWEEN(a, b) AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/stddev-pop.stddev-pop.toml b/cases/translation/functions/stddev-pop.stddev-pop.toml index 1d15690fb..3983d2652 100644 --- a/cases/translation/functions/stddev-pop.stddev-pop.toml +++ b/cases/translation/functions/stddev-pop.stddev-pop.toml @@ -104,3 +104,30 @@ rows = [ query = "SELECT STDDEV_POP(x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t007_large_mean" +description = "Values near 1e9 with a spread of 1. Catches: a sum-of-squares formula losing the digits of the spread" +columns = [{ name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000001"], + ["1000000002"], + ["1000000003"], + ["1000000004"], +] +query = "SELECT STDDEV_POP(x) AS r FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t008_decimal" +description = "A NUMBER(10,2) column. Catches: the result type or scale of a decimal input" +columns = [{ name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25"], + ["2.50"], + ["4.10"], +] +query = "SELECT STDDEV_POP(x) AS r, SYSTEM$TYPEOF(STDDEV_POP(x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/stddev.stddev-samp.toml b/cases/translation/functions/stddev.stddev-samp.toml index 4929e5cc1..def96fe5a 100644 --- a/cases/translation/functions/stddev.stddev-samp.toml +++ b/cases/translation/functions/stddev.stddev-samp.toml @@ -104,3 +104,30 @@ rows = [ query = "SELECT STDDEV_SAMP(x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t007_large_mean" +description = "Values near 1e9 with a spread of 1. Catches: a sum-of-squares formula losing the digits of the spread" +columns = [{ name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000001"], + ["1000000002"], + ["1000000003"], + ["1000000004"], +] +query = "SELECT STDDEV_SAMP(x) AS r FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t008_decimal" +description = "A NUMBER(10,2) column. Catches: the result type or scale of a decimal input" +columns = [{ name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25"], + ["2.50"], + ["4.10"], +] +query = "SELECT STDDEV_SAMP(x) AS r, SYSTEM$TYPEOF(STDDEV_SAMP(x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/stddev.stddev.toml b/cases/translation/functions/stddev.stddev.toml index 615f253fd..14b530681 100644 --- a/cases/translation/functions/stddev.stddev.toml +++ b/cases/translation/functions/stddev.stddev.toml @@ -104,3 +104,30 @@ rows = [ query = "SELECT STDDEV(x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t007_large_mean" +description = "Values near 1e9 with a spread of 1. Catches: a sum-of-squares formula losing the digits of the spread" +columns = [{ name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000001"], + ["1000000002"], + ["1000000003"], + ["1000000004"], +] +query = "SELECT STDDEV(x) AS r FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t008_decimal" +description = "A NUMBER(10,2) column. Catches: the result type or scale of a decimal input" +columns = [{ name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25"], + ["2.50"], + ["4.10"], +] +query = "SELECT STDDEV(x) AS r, SYSTEM$TYPEOF(STDDEV(x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/var-pop.var-pop.toml b/cases/translation/functions/var-pop.var-pop.toml index 8b3225b03..21989dd73 100644 --- a/cases/translation/functions/var-pop.var-pop.toml +++ b/cases/translation/functions/var-pop.var-pop.toml @@ -104,3 +104,30 @@ rows = [ query = "SELECT VAR_POP(x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t007_large_mean" +description = "Values near 1e9 with a spread of 1. Catches: a sum-of-squares formula losing the digits of the spread" +columns = [{ name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000001"], + ["1000000002"], + ["1000000003"], + ["1000000004"], +] +query = "SELECT VAR_POP(x) AS r FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t008_decimal" +description = "A NUMBER(10,2) column. Catches: the result type or scale of a decimal input" +columns = [{ name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25"], + ["2.50"], + ["4.10"], +] +query = "SELECT VAR_POP(x) AS r, SYSTEM$TYPEOF(VAR_POP(x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/var-samp.var-samp.toml b/cases/translation/functions/var-samp.var-samp.toml index a128def19..7998b651c 100644 --- a/cases/translation/functions/var-samp.var-samp.toml +++ b/cases/translation/functions/var-samp.var-samp.toml @@ -104,3 +104,30 @@ rows = [ query = "SELECT VAR_SAMP(x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t007_large_mean" +description = "Values near 1e9 with a spread of 1. Catches: a sum-of-squares formula losing the digits of the spread" +columns = [{ name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000001"], + ["1000000002"], + ["1000000003"], + ["1000000004"], +] +query = "SELECT VAR_SAMP(x) AS r FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t008_decimal" +description = "A NUMBER(10,2) column. Catches: the result type or scale of a decimal input" +columns = [{ name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25"], + ["2.50"], + ["4.10"], +] +query = "SELECT VAR_SAMP(x) AS r, SYSTEM$TYPEOF(VAR_SAMP(x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/variance-pop.variance-pop.toml b/cases/translation/functions/variance-pop.variance-pop.toml index f0bfc6920..bf1987463 100644 --- a/cases/translation/functions/variance-pop.variance-pop.toml +++ b/cases/translation/functions/variance-pop.variance-pop.toml @@ -104,3 +104,30 @@ rows = [ query = "SELECT VARIANCE_POP(x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t007_large_mean" +description = "Values near 1e9 with a spread of 1. Catches: a sum-of-squares formula losing the digits of the spread" +columns = [{ name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000001"], + ["1000000002"], + ["1000000003"], + ["1000000004"], +] +query = "SELECT VARIANCE_POP(x) AS r FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t008_decimal" +description = "A NUMBER(10,2) column. Catches: the result type or scale of a decimal input" +columns = [{ name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25"], + ["2.50"], + ["4.10"], +] +query = "SELECT VARIANCE_POP(x) AS r, SYSTEM$TYPEOF(VARIANCE_POP(x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/variance.variance.toml b/cases/translation/functions/variance.variance.toml index b6a3f87be..a7c2f907a 100644 --- a/cases/translation/functions/variance.variance.toml +++ b/cases/translation/functions/variance.variance.toml @@ -105,3 +105,196 @@ rows = [ query = "SELECT VARIANCE(x) AS r FROM input WHERE ordinal < 0" order = "ordered" tags = ["empty-input"] + +[[case]] +id = "t007_large_mean" +description = "Values near 1e9 with a spread of 1. Catches: a sum-of-squares formula losing the digits of the spread" +columns = [{ name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1000000001"], + ["1000000002"], + ["1000000003"], + ["1000000004"], +] +query = "SELECT VARIANCE(x) AS r FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t008_decimal" +description = "A NUMBER(10,2) column. Catches: the result type or scale of a decimal input" +columns = [{ name = "x", type = "NUMBER(10,2)" }] +rows = [ + ["1.25"], + ["2.50"], + ["4.10"], +] +query = "SELECT VARIANCE(x) AS r, SYSTEM$TYPEOF(VARIANCE(x)) AS t FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t009_rounding_tie" +description = "One 1 and 127 zeros: the sample variance is exactly 1/128 = 0.0078125, a tie at six decimals, with STDDEV beside it. Catches: half-to-even (0.007812) instead of half-up (0.007813), and STDDEV taken from the unrounded variance" +columns = [{ name = "x", type = "NUMBER(38,0)" }] +rows = [ + ["1"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], + ["0"], +] +query = "SELECT VARIANCE(x) AS v, VAR_POP(x) AS p, STDDEV(x) AS s FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t010_scales" +description = "VARIANCE and VAR_POP of NUMBER columns of scales 1, 3, 5 and 12, with their types. Catches: the result scale rule (6 for scale 0 and 10 for scale 2 are recorded) misread" +columns = [{ name = "a", type = "NUMBER(38,1)" }, { name = "b", type = "NUMBER(38,3)" }, { name = "c", type = "NUMBER(38,5)" }, { name = "d", type = "NUMBER(38,12)" }] +rows = [ + ["1.5", "1.125", "1.00001", "1.000000000001"], + ["2.0", "2.500", "2.00003", "2.000000000005"], + ["4.5", "4.875", "4.00007", "4.000000000007"], +] +query = "SELECT VARIANCE(a) AS va, SYSTEM$TYPEOF(VARIANCE(a)) AS ta, VARIANCE(b) AS vb, SYSTEM$TYPEOF(VARIANCE(b)) AS tb, VARIANCE(c) AS vc, SYSTEM$TYPEOF(VARIANCE(c)) AS tc, VARIANCE(d) AS vd, SYSTEM$TYPEOF(VARIANCE(d)) AS td, VAR_POP(b) AS pb, SYSTEM$TYPEOF(VAR_POP(b)) AS tpb FROM input" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t011_float_large_mean" +description = "A FLOAT column near 1e9 with a spread of 1, and a negative one. Catches: a stable algorithm where Snowflake cancels, or the reverse" +columns = [{ name = "x", type = "FLOAT" }] +rows = [ + ["1000000001"], + ["1000000002"], + ["1000000003"], + ["1000000004"], +] +query = "SELECT VARIANCE(x) AS v, VAR_POP(x) AS p, STDDEV(x) AS s, VARIANCE(-x) AS n FROM input" +order = "ordered" +expected_divergence = "float_sum_order" +tags = ["type-combination"] diff --git a/coverage/translation/results-baseline.json b/coverage/translation/results-baseline.json index fd328a67b..8e22ff07d 100644 --- a/coverage/translation/results-baseline.json +++ b/coverage/translation/results-baseline.json @@ -5163,8 +5163,8 @@ "generated/null_positions/nullif.toml#nullif_same_types": "matching", "generated/null_positions/nvl.toml#nvl_mixed_types": "matching", "generated/null_positions/nvl.toml#nvl_same_types": "matching", - "generated/null_positions/nvl2.toml#nvl2_mixed_types": "refused", - "generated/null_positions/nvl2.toml#nvl2_same_types": "refused", + "generated/null_positions/nvl2.toml#nvl2_mixed_types": "matching", + "generated/null_positions/nvl2.toml#nvl2_same_types": "matching", "generated/null_positions/pipes.toml#pipes_texts": "matching", "generated/null_positions/zeroifnull.toml#zeroifnull_mixed_types": "matching", "generated/null_positions/zeroifnull.toml#zeroifnull_same_types": "matching", @@ -8677,13 +8677,14 @@ "translation/functions/acosh.toml#t003_null": "refused", "translation/functions/acosh.toml#t004_edge": "refused", "translation/functions/acosh.toml#t005_below_one": "refused", - "translation/functions/add-months.toml#t001_date": "refused", - "translation/functions/add-months.toml#t002_timestamp": "refused", + "translation/functions/add-months.toml#t001_date": "matching", + "translation/functions/add-months.toml#t002_timestamp": "matching", "translation/functions/add-months.toml#t003_timestamp_tz": "refused", - "translation/functions/add-months.toml#t004_null_date_or_timestamp_expr": "refused", - "translation/functions/add-months.toml#t005_null_num_months_expr": "refused", - "translation/functions/add-months.toml#t006_month_end": "refused", - "translation/functions/add-months.toml#t007_fractional": "refused", + "translation/functions/add-months.toml#t004_null_date_or_timestamp_expr": "matching", + "translation/functions/add-months.toml#t005_null_num_months_expr": "matching", + "translation/functions/add-months.toml#t006_month_end": "matching", + "translation/functions/add-months.toml#t007_fractional": "matching", + "translation/functions/add-months.toml#t008_negative_and_day_31": "matching", "translation/functions/any-value.any-value-over.toml#t001_partition": "refused", "translation/functions/any-value.any-value-over.toml#t002_empty_over": "refused", "translation/functions/any-value.any-value-over.toml#t003_null_expr1": "refused", @@ -9283,6 +9284,8 @@ "translation/functions/corr.corr.toml#t004_null_y": "refused", "translation/functions/corr.corr.toml#t005_null_x": "refused", "translation/functions/corr.corr.toml#t006_empty_input": "refused", + "translation/functions/corr.corr.toml#t007_large_mean": "refused", + "translation/functions/corr.corr.toml#t008_decimal": "refused", "translation/functions/corr.x-over.toml#t001_partition": "refused", "translation/functions/corr.x-over.toml#t002_empty_over": "refused", "translation/functions/corr.x-over.toml#t003_null_y": "refused", @@ -9325,24 +9328,28 @@ "translation/functions/count.count.toml#t003_distinct_multi": "matching", "translation/functions/count.count.toml#t007_null_expr1": "matching", "translation/functions/count.count.toml#t008_empty_input": "matching", - "translation/functions/covar-pop.covar-pop.toml#t001_pairs": "refused", - "translation/functions/covar-pop.covar-pop.toml#t002_float": "refused", - "translation/functions/covar-pop.covar-pop.toml#t003_null_y": "refused", - "translation/functions/covar-pop.covar-pop.toml#t004_null_x": "refused", - "translation/functions/covar-pop.covar-pop.toml#t005_empty_input": "refused", - "translation/functions/covar-pop.x-over.toml#t001_partition": "refused", - "translation/functions/covar-pop.x-over.toml#t002_empty_over": "refused", - "translation/functions/covar-pop.x-over.toml#t003_null_y": "refused", - "translation/functions/covar-pop.x-over.toml#t004_null_partition_key": "refused", - "translation/functions/covar-samp.covar-samp.toml#t001_pairs": "refused", - "translation/functions/covar-samp.covar-samp.toml#t002_float": "refused", - "translation/functions/covar-samp.covar-samp.toml#t003_null_y": "refused", - "translation/functions/covar-samp.covar-samp.toml#t004_null_x": "refused", - "translation/functions/covar-samp.covar-samp.toml#t005_empty_input": "refused", - "translation/functions/covar-samp.x-over.toml#t001_partition": "refused", - "translation/functions/covar-samp.x-over.toml#t002_empty_over": "refused", - "translation/functions/covar-samp.x-over.toml#t003_null_y": "refused", - "translation/functions/covar-samp.x-over.toml#t004_null_partition_key": "refused", + "translation/functions/covar-pop.covar-pop.toml#t001_pairs": "matching", + "translation/functions/covar-pop.covar-pop.toml#t002_float": "matching", + "translation/functions/covar-pop.covar-pop.toml#t003_null_y": "matching", + "translation/functions/covar-pop.covar-pop.toml#t004_null_x": "matching", + "translation/functions/covar-pop.covar-pop.toml#t005_empty_input": "matching", + "translation/functions/covar-pop.covar-pop.toml#t006_large_mean": "declared_divergence", + "translation/functions/covar-pop.covar-pop.toml#t007_decimal": "refused", + "translation/functions/covar-pop.x-over.toml#t001_partition": "matching", + "translation/functions/covar-pop.x-over.toml#t002_empty_over": "matching", + "translation/functions/covar-pop.x-over.toml#t003_null_y": "matching", + "translation/functions/covar-pop.x-over.toml#t004_null_partition_key": "matching", + "translation/functions/covar-samp.covar-samp.toml#t001_pairs": "matching", + "translation/functions/covar-samp.covar-samp.toml#t002_float": "matching", + "translation/functions/covar-samp.covar-samp.toml#t003_null_y": "matching", + "translation/functions/covar-samp.covar-samp.toml#t004_null_x": "matching", + "translation/functions/covar-samp.covar-samp.toml#t005_empty_input": "matching", + "translation/functions/covar-samp.covar-samp.toml#t006_large_mean": "declared_divergence", + "translation/functions/covar-samp.covar-samp.toml#t007_decimal": "refused", + "translation/functions/covar-samp.x-over.toml#t001_partition": "matching", + "translation/functions/covar-samp.x-over.toml#t002_empty_over": "matching", + "translation/functions/covar-samp.x-over.toml#t003_null_y": "matching", + "translation/functions/covar-samp.x-over.toml#t004_null_partition_key": "matching", "translation/functions/cume-dist.toml#t001_ties": "refused", "translation/functions/cume-dist.toml#t002_frame": "refused", "translation/functions/cume-dist.toml#t003_null_order_expr": "refused", @@ -10224,13 +10231,15 @@ "translation/functions/monthname.toml#t001_date": "refused", "translation/functions/monthname.toml#t002_timestamp_tz": "refused", "translation/functions/monthname.toml#t003_null_date_or_timestamp_expr": "refused", - "translation/functions/months-between.toml#t001_date": "refused", - "translation/functions/months-between.toml#t002_timestamp": "refused", - "translation/functions/months-between.toml#t003_mixed": "refused", - "translation/functions/months-between.toml#t004_null_date_expr1": "refused", - "translation/functions/months-between.toml#t005_null_date_expr2": "refused", - "translation/functions/months-between.toml#t006_reversed": "refused", - "translation/functions/months-between.toml#t007_leap": "refused", + "translation/functions/months-between.toml#t001_date": "matching", + "translation/functions/months-between.toml#t002_timestamp": "matching", + "translation/functions/months-between.toml#t003_mixed": "matching", + "translation/functions/months-between.toml#t004_null_date_expr1": "matching", + "translation/functions/months-between.toml#t005_null_date_expr2": "matching", + "translation/functions/months-between.toml#t006_reversed": "matching", + "translation/functions/months-between.toml#t007_leap": "matching", + "translation/functions/months-between.toml#t008_month_ends_with_time": "matching", + "translation/functions/months-between.toml#t009_long_negative": "matching", "translation/functions/next-day.toml#t001_date": "refused", "translation/functions/next-day.toml#t002_day_name_forms": "refused", "translation/functions/next-day.toml#t003_timestamp": "refused", @@ -10260,10 +10269,10 @@ "translation/functions/nvl.toml#t003_null_expr1": "matching", "translation/functions/nvl.toml#t004_null_expr2": "matching", "translation/functions/nvl.toml#t005_unconvertible": "matching_error", - "translation/functions/nvl2.toml#t001_mixed": "refused", - "translation/functions/nvl2.toml#t002_null_expr1": "refused", - "translation/functions/nvl2.toml#t003_null_expr2": "refused", - "translation/functions/nvl2.toml#t004_null_expr3": "refused", + "translation/functions/nvl2.toml#t001_mixed": "matching", + "translation/functions/nvl2.toml#t002_null_expr1": "matching", + "translation/functions/nvl2.toml#t003_null_expr2": "matching", + "translation/functions/nvl2.toml#t004_null_expr3": "matching", "translation/functions/object-agg.object-agg-over.toml#t001_partition": "refused", "translation/functions/object-agg.object-agg-over.toml#t002_empty_over": "refused", "translation/functions/object-agg.object-agg-over.toml#t003_null_value": "refused", @@ -11098,51 +11107,57 @@ "translation/functions/startswith.toml#t002_null_expr1": "matching", "translation/functions/startswith.toml#t003_null_expr2": "matching", "translation/functions/startswith.toml#t004_empty": "matching", - "translation/functions/stddev-pop.stddev-pop-over.toml#t001_partition": "refused", - "translation/functions/stddev-pop.stddev-pop-over.toml#t002_empty_over": "refused", - "translation/functions/stddev-pop.stddev-pop-over.toml#t003_order_ties": "refused", - "translation/functions/stddev-pop.stddev-pop-over.toml#t004_order_desc": "refused", - "translation/functions/stddev-pop.stddev-pop-over.toml#t005_nulls_first_frame": "refused", - "translation/functions/stddev-pop.stddev-pop-over.toml#t006_null_expr1": "refused", - "translation/functions/stddev-pop.stddev-pop-over.toml#t007_null_partition_key": "refused", + "translation/functions/stddev-pop.stddev-pop-over.toml#t001_partition": "matching", + "translation/functions/stddev-pop.stddev-pop-over.toml#t002_empty_over": "matching", + "translation/functions/stddev-pop.stddev-pop-over.toml#t003_order_ties": "matching", + "translation/functions/stddev-pop.stddev-pop-over.toml#t004_order_desc": "matching", + "translation/functions/stddev-pop.stddev-pop-over.toml#t005_nulls_first_frame": "matching", + "translation/functions/stddev-pop.stddev-pop-over.toml#t006_null_expr1": "matching", + "translation/functions/stddev-pop.stddev-pop-over.toml#t007_null_partition_key": "matching", "translation/functions/stddev-pop.stddev-pop-over.toml#t008_distinct_order": "refused", - "translation/functions/stddev-pop.stddev-pop-over.toml#t009_distinct_partition": "refused", - "translation/functions/stddev-pop.stddev-pop.toml#t001_number": "refused", - "translation/functions/stddev-pop.stddev-pop.toml#t002_single_row": "refused", - "translation/functions/stddev-pop.stddev-pop.toml#t003_varchar": "refused", - "translation/functions/stddev-pop.stddev-pop.toml#t004_distinct": "refused", - "translation/functions/stddev-pop.stddev-pop.toml#t005_null_expr1": "refused", - "translation/functions/stddev-pop.stddev-pop.toml#t006_empty_input": "refused", - "translation/functions/stddev.stddev-over.toml#t001_partition": "refused", - "translation/functions/stddev.stddev-over.toml#t002_empty_over": "refused", - "translation/functions/stddev.stddev-over.toml#t003_order_ties": "refused", - "translation/functions/stddev.stddev-over.toml#t004_order_desc": "refused", - "translation/functions/stddev.stddev-over.toml#t005_nulls_first_frame": "refused", - "translation/functions/stddev.stddev-over.toml#t006_null_expr1": "refused", - "translation/functions/stddev.stddev-over.toml#t007_null_partition_key": "refused", + "translation/functions/stddev-pop.stddev-pop-over.toml#t009_distinct_partition": "matching", + "translation/functions/stddev-pop.stddev-pop.toml#t001_number": "matching", + "translation/functions/stddev-pop.stddev-pop.toml#t002_single_row": "matching", + "translation/functions/stddev-pop.stddev-pop.toml#t003_varchar": "matching", + "translation/functions/stddev-pop.stddev-pop.toml#t004_distinct": "matching", + "translation/functions/stddev-pop.stddev-pop.toml#t005_null_expr1": "matching", + "translation/functions/stddev-pop.stddev-pop.toml#t006_empty_input": "matching", + "translation/functions/stddev-pop.stddev-pop.toml#t007_large_mean": "matching", + "translation/functions/stddev-pop.stddev-pop.toml#t008_decimal": "refused", + "translation/functions/stddev.stddev-over.toml#t001_partition": "matching", + "translation/functions/stddev.stddev-over.toml#t002_empty_over": "matching", + "translation/functions/stddev.stddev-over.toml#t003_order_ties": "matching", + "translation/functions/stddev.stddev-over.toml#t004_order_desc": "matching", + "translation/functions/stddev.stddev-over.toml#t005_nulls_first_frame": "matching", + "translation/functions/stddev.stddev-over.toml#t006_null_expr1": "matching", + "translation/functions/stddev.stddev-over.toml#t007_null_partition_key": "matching", "translation/functions/stddev.stddev-over.toml#t008_distinct_order": "refused", - "translation/functions/stddev.stddev-over.toml#t009_distinct_partition": "refused", - "translation/functions/stddev.stddev-samp-over.toml#t001_partition": "refused", - "translation/functions/stddev.stddev-samp-over.toml#t002_empty_over": "refused", - "translation/functions/stddev.stddev-samp-over.toml#t003_order_ties": "refused", - "translation/functions/stddev.stddev-samp-over.toml#t004_order_desc": "refused", - "translation/functions/stddev.stddev-samp-over.toml#t005_nulls_first_frame": "refused", - "translation/functions/stddev.stddev-samp-over.toml#t006_null_expr1": "refused", - "translation/functions/stddev.stddev-samp-over.toml#t007_null_partition_key": "refused", + "translation/functions/stddev.stddev-over.toml#t009_distinct_partition": "matching", + "translation/functions/stddev.stddev-samp-over.toml#t001_partition": "matching", + "translation/functions/stddev.stddev-samp-over.toml#t002_empty_over": "matching", + "translation/functions/stddev.stddev-samp-over.toml#t003_order_ties": "matching", + "translation/functions/stddev.stddev-samp-over.toml#t004_order_desc": "matching", + "translation/functions/stddev.stddev-samp-over.toml#t005_nulls_first_frame": "matching", + "translation/functions/stddev.stddev-samp-over.toml#t006_null_expr1": "matching", + "translation/functions/stddev.stddev-samp-over.toml#t007_null_partition_key": "matching", "translation/functions/stddev.stddev-samp-over.toml#t008_distinct_order": "refused", - "translation/functions/stddev.stddev-samp-over.toml#t009_distinct_partition": "refused", - "translation/functions/stddev.stddev-samp.toml#t001_number": "refused", - "translation/functions/stddev.stddev-samp.toml#t002_single_row": "refused", - "translation/functions/stddev.stddev-samp.toml#t003_varchar": "refused", - "translation/functions/stddev.stddev-samp.toml#t004_distinct": "refused", - "translation/functions/stddev.stddev-samp.toml#t005_null_expr1": "refused", - "translation/functions/stddev.stddev-samp.toml#t006_empty_input": "refused", - "translation/functions/stddev.stddev.toml#t001_number": "refused", - "translation/functions/stddev.stddev.toml#t002_single_row": "refused", - "translation/functions/stddev.stddev.toml#t003_varchar": "refused", - "translation/functions/stddev.stddev.toml#t004_distinct": "refused", - "translation/functions/stddev.stddev.toml#t005_null_expr1": "refused", - "translation/functions/stddev.stddev.toml#t006_empty_input": "refused", + "translation/functions/stddev.stddev-samp-over.toml#t009_distinct_partition": "matching", + "translation/functions/stddev.stddev-samp.toml#t001_number": "matching", + "translation/functions/stddev.stddev-samp.toml#t002_single_row": "matching", + "translation/functions/stddev.stddev-samp.toml#t003_varchar": "matching", + "translation/functions/stddev.stddev-samp.toml#t004_distinct": "matching", + "translation/functions/stddev.stddev-samp.toml#t005_null_expr1": "matching", + "translation/functions/stddev.stddev-samp.toml#t006_empty_input": "matching", + "translation/functions/stddev.stddev-samp.toml#t007_large_mean": "matching", + "translation/functions/stddev.stddev-samp.toml#t008_decimal": "refused", + "translation/functions/stddev.stddev.toml#t001_number": "matching", + "translation/functions/stddev.stddev.toml#t002_single_row": "matching", + "translation/functions/stddev.stddev.toml#t003_varchar": "matching", + "translation/functions/stddev.stddev.toml#t004_distinct": "matching", + "translation/functions/stddev.stddev.toml#t005_null_expr1": "matching", + "translation/functions/stddev.stddev.toml#t006_empty_input": "matching", + "translation/functions/stddev.stddev.toml#t007_large_mean": "matching", + "translation/functions/stddev.stddev.toml#t008_decimal": "refused", "translation/functions/strip-null-value.toml#t001_json_null": "matching", "translation/functions/strip-null-value.toml#t002_nested": "matching", "translation/functions/strip-null-value.toml#t003_null_variant_expr": "matching", @@ -11594,64 +11609,75 @@ "translation/functions/uuid-string.toml#t001_random": "refused", "translation/functions/uuid-string.toml#t002_named": "refused", "translation/functions/uuid-string.toml#t003_null_name": "refused", - "translation/functions/var-pop.var-pop-over.toml#t001_partition": "refused", - "translation/functions/var-pop.var-pop-over.toml#t002_empty_over": "refused", - "translation/functions/var-pop.var-pop-over.toml#t003_order_ties": "refused", - "translation/functions/var-pop.var-pop-over.toml#t004_order_desc": "refused", - "translation/functions/var-pop.var-pop-over.toml#t005_nulls_first_frame": "refused", - "translation/functions/var-pop.var-pop-over.toml#t006_null_expr1": "refused", - "translation/functions/var-pop.var-pop-over.toml#t007_null_partition_key": "refused", + "translation/functions/var-pop.var-pop-over.toml#t001_partition": "matching", + "translation/functions/var-pop.var-pop-over.toml#t002_empty_over": "matching", + "translation/functions/var-pop.var-pop-over.toml#t003_order_ties": "matching", + "translation/functions/var-pop.var-pop-over.toml#t004_order_desc": "matching", + "translation/functions/var-pop.var-pop-over.toml#t005_nulls_first_frame": "matching", + "translation/functions/var-pop.var-pop-over.toml#t006_null_expr1": "matching", + "translation/functions/var-pop.var-pop-over.toml#t007_null_partition_key": "matching", "translation/functions/var-pop.var-pop-over.toml#t008_distinct_order": "refused", - "translation/functions/var-pop.var-pop-over.toml#t009_distinct_partition": "refused", - "translation/functions/var-pop.var-pop.toml#t001_number": "refused", - "translation/functions/var-pop.var-pop.toml#t002_single_row": "refused", - "translation/functions/var-pop.var-pop.toml#t003_varchar": "refused", - "translation/functions/var-pop.var-pop.toml#t004_distinct": "refused", - "translation/functions/var-pop.var-pop.toml#t005_null_expr1": "refused", - "translation/functions/var-pop.var-pop.toml#t006_empty_input": "refused", - "translation/functions/var-samp.var-samp-over.toml#t001_partition": "refused", - "translation/functions/var-samp.var-samp-over.toml#t002_empty_over": "refused", - "translation/functions/var-samp.var-samp-over.toml#t003_order_ties": "refused", - "translation/functions/var-samp.var-samp-over.toml#t004_order_desc": "refused", - "translation/functions/var-samp.var-samp-over.toml#t005_nulls_first_frame": "refused", - "translation/functions/var-samp.var-samp-over.toml#t006_null_expr1": "refused", - "translation/functions/var-samp.var-samp-over.toml#t007_null_partition_key": "refused", - "translation/functions/var-samp.var-samp-over.toml#t008_distinct_ignored": "refused", - "translation/functions/var-samp.var-samp.toml#t001_number": "refused", - "translation/functions/var-samp.var-samp.toml#t002_single_row": "refused", - "translation/functions/var-samp.var-samp.toml#t003_varchar": "refused", - "translation/functions/var-samp.var-samp.toml#t004_distinct": "refused", - "translation/functions/var-samp.var-samp.toml#t005_null_expr1": "refused", - "translation/functions/var-samp.var-samp.toml#t006_empty_input": "refused", - "translation/functions/variance-pop.variance-pop-over.toml#t001_partition": "refused", - "translation/functions/variance-pop.variance-pop-over.toml#t002_empty_over": "refused", - "translation/functions/variance-pop.variance-pop-over.toml#t003_order_ties": "refused", - "translation/functions/variance-pop.variance-pop-over.toml#t004_order_desc": "refused", - "translation/functions/variance-pop.variance-pop-over.toml#t005_nulls_first_frame": "refused", - "translation/functions/variance-pop.variance-pop-over.toml#t006_null_expr1": "refused", - "translation/functions/variance-pop.variance-pop-over.toml#t007_null_partition_key": "refused", + "translation/functions/var-pop.var-pop-over.toml#t009_distinct_partition": "matching", + "translation/functions/var-pop.var-pop.toml#t001_number": "matching", + "translation/functions/var-pop.var-pop.toml#t002_single_row": "matching", + "translation/functions/var-pop.var-pop.toml#t003_varchar": "matching", + "translation/functions/var-pop.var-pop.toml#t004_distinct": "matching", + "translation/functions/var-pop.var-pop.toml#t005_null_expr1": "matching", + "translation/functions/var-pop.var-pop.toml#t006_empty_input": "matching", + "translation/functions/var-pop.var-pop.toml#t007_large_mean": "matching", + "translation/functions/var-pop.var-pop.toml#t008_decimal": "refused", + "translation/functions/var-samp.var-samp-over.toml#t001_partition": "matching", + "translation/functions/var-samp.var-samp-over.toml#t002_empty_over": "matching", + "translation/functions/var-samp.var-samp-over.toml#t003_order_ties": "matching", + "translation/functions/var-samp.var-samp-over.toml#t004_order_desc": "matching", + "translation/functions/var-samp.var-samp-over.toml#t005_nulls_first_frame": "matching", + "translation/functions/var-samp.var-samp-over.toml#t006_null_expr1": "matching", + "translation/functions/var-samp.var-samp-over.toml#t007_null_partition_key": "matching", + "translation/functions/var-samp.var-samp-over.toml#t008_distinct_ignored": "matching", + "translation/functions/var-samp.var-samp.toml#t001_number": "matching", + "translation/functions/var-samp.var-samp.toml#t002_single_row": "matching", + "translation/functions/var-samp.var-samp.toml#t003_varchar": "matching", + "translation/functions/var-samp.var-samp.toml#t004_distinct": "matching", + "translation/functions/var-samp.var-samp.toml#t005_null_expr1": "matching", + "translation/functions/var-samp.var-samp.toml#t006_empty_input": "matching", + "translation/functions/var-samp.var-samp.toml#t007_large_mean": "matching", + "translation/functions/var-samp.var-samp.toml#t008_decimal": "refused", + "translation/functions/variance-pop.variance-pop-over.toml#t001_partition": "matching", + "translation/functions/variance-pop.variance-pop-over.toml#t002_empty_over": "matching", + "translation/functions/variance-pop.variance-pop-over.toml#t003_order_ties": "matching", + "translation/functions/variance-pop.variance-pop-over.toml#t004_order_desc": "matching", + "translation/functions/variance-pop.variance-pop-over.toml#t005_nulls_first_frame": "matching", + "translation/functions/variance-pop.variance-pop-over.toml#t006_null_expr1": "matching", + "translation/functions/variance-pop.variance-pop-over.toml#t007_null_partition_key": "matching", "translation/functions/variance-pop.variance-pop-over.toml#t008_distinct_order": "refused", - "translation/functions/variance-pop.variance-pop-over.toml#t009_distinct_partition": "refused", - "translation/functions/variance-pop.variance-pop.toml#t001_number": "refused", - "translation/functions/variance-pop.variance-pop.toml#t002_single_row": "refused", - "translation/functions/variance-pop.variance-pop.toml#t003_varchar": "refused", - "translation/functions/variance-pop.variance-pop.toml#t004_distinct": "refused", - "translation/functions/variance-pop.variance-pop.toml#t005_null_expr1": "refused", - "translation/functions/variance-pop.variance-pop.toml#t006_empty_input": "refused", - "translation/functions/variance.variance-over.toml#t001_partition": "refused", - "translation/functions/variance.variance-over.toml#t002_empty_over": "refused", - "translation/functions/variance.variance-over.toml#t003_order_ties": "refused", - "translation/functions/variance.variance-over.toml#t004_order_desc": "refused", - "translation/functions/variance.variance-over.toml#t005_nulls_first_frame": "refused", - "translation/functions/variance.variance-over.toml#t006_null_expr1": "refused", - "translation/functions/variance.variance-over.toml#t007_null_partition_key": "refused", + "translation/functions/variance-pop.variance-pop-over.toml#t009_distinct_partition": "matching", + "translation/functions/variance-pop.variance-pop.toml#t001_number": "matching", + "translation/functions/variance-pop.variance-pop.toml#t002_single_row": "matching", + "translation/functions/variance-pop.variance-pop.toml#t003_varchar": "matching", + "translation/functions/variance-pop.variance-pop.toml#t004_distinct": "matching", + "translation/functions/variance-pop.variance-pop.toml#t005_null_expr1": "matching", + "translation/functions/variance-pop.variance-pop.toml#t006_empty_input": "matching", + "translation/functions/variance-pop.variance-pop.toml#t007_large_mean": "matching", + "translation/functions/variance-pop.variance-pop.toml#t008_decimal": "refused", + "translation/functions/variance.variance-over.toml#t001_partition": "matching", + "translation/functions/variance.variance-over.toml#t002_empty_over": "matching", + "translation/functions/variance.variance-over.toml#t003_order_ties": "matching", + "translation/functions/variance.variance-over.toml#t004_order_desc": "matching", + "translation/functions/variance.variance-over.toml#t005_nulls_first_frame": "matching", + "translation/functions/variance.variance-over.toml#t006_null_expr1": "matching", + "translation/functions/variance.variance-over.toml#t007_null_partition_key": "matching", "translation/functions/variance.variance-over.toml#t008_distinct_order": "refused", - "translation/functions/variance.variance.toml#t001_number": "refused", - "translation/functions/variance.variance.toml#t002_single_row": "refused", - "translation/functions/variance.variance.toml#t003_varchar": "refused", + "translation/functions/variance.variance.toml#t001_number": "matching", + "translation/functions/variance.variance.toml#t002_single_row": "matching", + "translation/functions/variance.variance.toml#t003_varchar": "matching", "translation/functions/variance.variance.toml#t004_distinct": "refused", - "translation/functions/variance.variance.toml#t005_null_expr1": "refused", - "translation/functions/variance.variance.toml#t006_empty_input": "refused", + "translation/functions/variance.variance.toml#t005_null_expr1": "matching", + "translation/functions/variance.variance.toml#t006_empty_input": "matching", + "translation/functions/variance.variance.toml#t007_large_mean": "matching", + "translation/functions/variance.variance.toml#t008_decimal": "refused", + "translation/functions/variance.variance.toml#t009_rounding_tie": "matching", + "translation/functions/variance.variance.toml#t010_scales": "refused", + "translation/functions/variance.variance.toml#t011_float_large_mean": "declared_divergence", "translation/functions/vector-avg.toml#t001_float": "refused", "translation/functions/vector-avg.toml#t002_int": "refused", "translation/functions/vector-avg.toml#t003_null_vector_column": "refused", @@ -13405,9 +13431,9 @@ "sf.functions.count.count": "refused", "sf.functions.count.count-over": "refused", "sf.functions.covar-pop.covar-pop": "refused", - "sf.functions.covar-pop.x-over": "refused", + "sf.functions.covar-pop.x-over": "matching", "sf.functions.covar-samp.covar-samp": "refused", - "sf.functions.covar-samp.x-over": "refused", + "sf.functions.covar-samp.x-over": "matching", "sf.functions.cume-dist": "refused", "sf.functions.cumulative-privacy-losses": "not_translatable", "sf.functions.current-account": "not_translatable", @@ -13942,7 +13968,7 @@ "sf.functions.model-monitor-stat-metric.model-monitor-stat-metric": "not_translatable", "sf.functions.model-monitor-stat-metric.model-monitor-stat-metric-service": "not_translatable", "sf.functions.monthname": "refused", - "sf.functions.months-between": "refused", + "sf.functions.months-between": "matching", "sf.functions.my-budget-summary-snowflake-local": "not_translatable", "sf.functions.network-rule-references.container-name-container-type": "not_translatable", "sf.functions.network-rule-references.network-rule-name": "not_translatable", @@ -13954,7 +13980,7 @@ "sf.functions.nullif": "unmet_obligations", "sf.functions.nullifzero": "matching", "sf.functions.nvl": "matching", - "sf.functions.nvl2": "refused", + "sf.functions.nvl2": "matching", "sf.functions.object-agg.object-agg": "refused", "sf.functions.object-agg.object-agg-over": "refused", "sf.functions.object-construct": "refused", @@ -14192,11 +14218,11 @@ "sf.functions.stage-directory-file-registration-history": "not_translatable", "sf.functions.stage-storage-usage-history": "not_translatable", "sf.functions.startswith": "matching", - "sf.functions.stddev-pop.stddev-pop": "refused", + "sf.functions.stddev-pop.stddev-pop": "matching", "sf.functions.stddev-pop.stddev-pop-over": "refused", "sf.functions.stddev.stddev": "refused", "sf.functions.stddev.stddev-over": "refused", - "sf.functions.stddev.stddev-samp": "refused", + "sf.functions.stddev.stddev-samp": "matching", "sf.functions.stddev.stddev-samp-over": "refused", "sf.functions.storage-lifecycle-policy-history.policy-name": "not_translatable", "sf.functions.storage-lifecycle-policy-history.ref-entity-name-ref-entity-domain": "not_translatable", @@ -14589,9 +14615,9 @@ "sf.functions.validate-pipe-load": "not_translatable", "sf.functions.var-pop.var-pop": "refused", "sf.functions.var-pop.var-pop-over": "refused", - "sf.functions.var-samp.var-samp": "refused", - "sf.functions.var-samp.var-samp-over": "refused", - "sf.functions.variance-pop.variance-pop": "refused", + "sf.functions.var-samp.var-samp": "matching", + "sf.functions.var-samp.var-samp-over": "matching", + "sf.functions.variance-pop.variance-pop": "matching", "sf.functions.variance-pop.variance-pop-over": "refused", "sf.functions.variance.variance": "refused", "sf.functions.variance.variance-over": "refused", @@ -15638,13 +15664,13 @@ "sf.functions.acosh.t003": "unmet", "sf.functions.acosh.t004": "unmet", "sf.functions.acosh.t005": "unmet", - "sf.functions.add-months.t001": "unmet", - "sf.functions.add-months.t002": "unmet", + "sf.functions.add-months.t001": "met", + "sf.functions.add-months.t002": "met", "sf.functions.add-months.t003": "unmet", - "sf.functions.add-months.t004": "unmet", - "sf.functions.add-months.t005": "unmet", - "sf.functions.add-months.t006": "unmet", - "sf.functions.add-months.t007": "unmet", + "sf.functions.add-months.t004": "met", + "sf.functions.add-months.t005": "met", + "sf.functions.add-months.t006": "met", + "sf.functions.add-months.t007": "met", "sf.functions.any-value.any-value-over.t001": "unmet", "sf.functions.any-value.any-value-over.t002": "unmet", "sf.functions.any-value.any-value-over.t003": "unmet", @@ -16290,24 +16316,24 @@ "sf.functions.count.count.t006": "held", "sf.functions.count.count.t007": "met", "sf.functions.count.count.t008": "met", - "sf.functions.covar-pop.covar-pop.t001": "unmet", - "sf.functions.covar-pop.covar-pop.t002": "unmet", - "sf.functions.covar-pop.covar-pop.t003": "unmet", - "sf.functions.covar-pop.covar-pop.t004": "unmet", - "sf.functions.covar-pop.covar-pop.t005": "unmet", - "sf.functions.covar-pop.x-over.t001": "unmet", - "sf.functions.covar-pop.x-over.t002": "unmet", - "sf.functions.covar-pop.x-over.t003": "unmet", - "sf.functions.covar-pop.x-over.t004": "unmet", - "sf.functions.covar-samp.covar-samp.t001": "unmet", - "sf.functions.covar-samp.covar-samp.t002": "unmet", - "sf.functions.covar-samp.covar-samp.t003": "unmet", - "sf.functions.covar-samp.covar-samp.t004": "unmet", - "sf.functions.covar-samp.covar-samp.t005": "unmet", - "sf.functions.covar-samp.x-over.t001": "unmet", - "sf.functions.covar-samp.x-over.t002": "unmet", - "sf.functions.covar-samp.x-over.t003": "unmet", - "sf.functions.covar-samp.x-over.t004": "unmet", + "sf.functions.covar-pop.covar-pop.t001": "met", + "sf.functions.covar-pop.covar-pop.t002": "met", + "sf.functions.covar-pop.covar-pop.t003": "met", + "sf.functions.covar-pop.covar-pop.t004": "met", + "sf.functions.covar-pop.covar-pop.t005": "met", + "sf.functions.covar-pop.x-over.t001": "met", + "sf.functions.covar-pop.x-over.t002": "met", + "sf.functions.covar-pop.x-over.t003": "met", + "sf.functions.covar-pop.x-over.t004": "met", + "sf.functions.covar-samp.covar-samp.t001": "met", + "sf.functions.covar-samp.covar-samp.t002": "met", + "sf.functions.covar-samp.covar-samp.t003": "met", + "sf.functions.covar-samp.covar-samp.t004": "met", + "sf.functions.covar-samp.covar-samp.t005": "met", + "sf.functions.covar-samp.x-over.t001": "met", + "sf.functions.covar-samp.x-over.t002": "met", + "sf.functions.covar-samp.x-over.t003": "met", + "sf.functions.covar-samp.x-over.t004": "met", "sf.functions.cume-dist.t001": "unmet", "sf.functions.cume-dist.t002": "unmet", "sf.functions.cume-dist.t003": "unmet", @@ -17195,13 +17221,13 @@ "sf.functions.monthname.t001": "unmet", "sf.functions.monthname.t002": "unmet", "sf.functions.monthname.t003": "unmet", - "sf.functions.months-between.t001": "unmet", - "sf.functions.months-between.t002": "unmet", - "sf.functions.months-between.t003": "unmet", - "sf.functions.months-between.t004": "unmet", - "sf.functions.months-between.t005": "unmet", - "sf.functions.months-between.t006": "unmet", - "sf.functions.months-between.t007": "unmet", + "sf.functions.months-between.t001": "met", + "sf.functions.months-between.t002": "met", + "sf.functions.months-between.t003": "met", + "sf.functions.months-between.t004": "met", + "sf.functions.months-between.t005": "met", + "sf.functions.months-between.t006": "met", + "sf.functions.months-between.t007": "met", "sf.functions.next-day.t001": "unmet", "sf.functions.next-day.t002": "unmet", "sf.functions.next-day.t003": "unmet", @@ -17232,10 +17258,10 @@ "sf.functions.nvl.t003": "met", "sf.functions.nvl.t004": "met", "sf.functions.nvl.t005": "met", - "sf.functions.nvl2.t001": "unmet", - "sf.functions.nvl2.t002": "unmet", - "sf.functions.nvl2.t003": "unmet", - "sf.functions.nvl2.t004": "unmet", + "sf.functions.nvl2.t001": "met", + "sf.functions.nvl2.t002": "met", + "sf.functions.nvl2.t003": "met", + "sf.functions.nvl2.t004": "met", "sf.functions.object-agg.object-agg-over.t001": "unmet", "sf.functions.object-agg.object-agg-over.t002": "unmet", "sf.functions.object-agg.object-agg-over.t003": "unmet", @@ -18070,51 +18096,51 @@ "sf.functions.startswith.t002": "met", "sf.functions.startswith.t003": "met", "sf.functions.startswith.t004": "met", - "sf.functions.stddev-pop.stddev-pop-over.t001": "unmet", - "sf.functions.stddev-pop.stddev-pop-over.t002": "unmet", - "sf.functions.stddev-pop.stddev-pop-over.t003": "unmet", - "sf.functions.stddev-pop.stddev-pop-over.t004": "unmet", - "sf.functions.stddev-pop.stddev-pop-over.t005": "unmet", - "sf.functions.stddev-pop.stddev-pop-over.t006": "unmet", - "sf.functions.stddev-pop.stddev-pop-over.t007": "unmet", + "sf.functions.stddev-pop.stddev-pop-over.t001": "met", + "sf.functions.stddev-pop.stddev-pop-over.t002": "met", + "sf.functions.stddev-pop.stddev-pop-over.t003": "met", + "sf.functions.stddev-pop.stddev-pop-over.t004": "met", + "sf.functions.stddev-pop.stddev-pop-over.t005": "met", + "sf.functions.stddev-pop.stddev-pop-over.t006": "met", + "sf.functions.stddev-pop.stddev-pop-over.t007": "met", "sf.functions.stddev-pop.stddev-pop-over.t008": "unmet", - "sf.functions.stddev-pop.stddev-pop-over.t009": "unmet", - "sf.functions.stddev-pop.stddev-pop.t001": "unmet", - "sf.functions.stddev-pop.stddev-pop.t002": "unmet", - "sf.functions.stddev-pop.stddev-pop.t003": "unmet", - "sf.functions.stddev-pop.stddev-pop.t004": "unmet", - "sf.functions.stddev-pop.stddev-pop.t005": "unmet", - "sf.functions.stddev-pop.stddev-pop.t006": "unmet", - "sf.functions.stddev.stddev-over.t001": "unmet", - "sf.functions.stddev.stddev-over.t002": "unmet", - "sf.functions.stddev.stddev-over.t003": "unmet", - "sf.functions.stddev.stddev-over.t004": "unmet", - "sf.functions.stddev.stddev-over.t005": "unmet", - "sf.functions.stddev.stddev-over.t006": "unmet", - "sf.functions.stddev.stddev-over.t007": "unmet", + "sf.functions.stddev-pop.stddev-pop-over.t009": "met", + "sf.functions.stddev-pop.stddev-pop.t001": "met", + "sf.functions.stddev-pop.stddev-pop.t002": "met", + "sf.functions.stddev-pop.stddev-pop.t003": "met", + "sf.functions.stddev-pop.stddev-pop.t004": "met", + "sf.functions.stddev-pop.stddev-pop.t005": "met", + "sf.functions.stddev-pop.stddev-pop.t006": "met", + "sf.functions.stddev.stddev-over.t001": "met", + "sf.functions.stddev.stddev-over.t002": "met", + "sf.functions.stddev.stddev-over.t003": "met", + "sf.functions.stddev.stddev-over.t004": "met", + "sf.functions.stddev.stddev-over.t005": "met", + "sf.functions.stddev.stddev-over.t006": "met", + "sf.functions.stddev.stddev-over.t007": "met", "sf.functions.stddev.stddev-over.t008": "unmet", - "sf.functions.stddev.stddev-over.t009": "unmet", - "sf.functions.stddev.stddev-samp-over.t001": "unmet", - "sf.functions.stddev.stddev-samp-over.t002": "unmet", - "sf.functions.stddev.stddev-samp-over.t003": "unmet", - "sf.functions.stddev.stddev-samp-over.t004": "unmet", - "sf.functions.stddev.stddev-samp-over.t005": "unmet", - "sf.functions.stddev.stddev-samp-over.t006": "unmet", - "sf.functions.stddev.stddev-samp-over.t007": "unmet", + "sf.functions.stddev.stddev-over.t009": "met", + "sf.functions.stddev.stddev-samp-over.t001": "met", + "sf.functions.stddev.stddev-samp-over.t002": "met", + "sf.functions.stddev.stddev-samp-over.t003": "met", + "sf.functions.stddev.stddev-samp-over.t004": "met", + "sf.functions.stddev.stddev-samp-over.t005": "met", + "sf.functions.stddev.stddev-samp-over.t006": "met", + "sf.functions.stddev.stddev-samp-over.t007": "met", "sf.functions.stddev.stddev-samp-over.t008": "unmet", - "sf.functions.stddev.stddev-samp-over.t009": "unmet", - "sf.functions.stddev.stddev-samp.t001": "unmet", - "sf.functions.stddev.stddev-samp.t002": "unmet", - "sf.functions.stddev.stddev-samp.t003": "unmet", - "sf.functions.stddev.stddev-samp.t004": "unmet", - "sf.functions.stddev.stddev-samp.t005": "unmet", - "sf.functions.stddev.stddev-samp.t006": "unmet", - "sf.functions.stddev.stddev.t001": "unmet", - "sf.functions.stddev.stddev.t002": "unmet", - "sf.functions.stddev.stddev.t003": "unmet", - "sf.functions.stddev.stddev.t004": "unmet", - "sf.functions.stddev.stddev.t005": "unmet", - "sf.functions.stddev.stddev.t006": "unmet", + "sf.functions.stddev.stddev-samp-over.t009": "met", + "sf.functions.stddev.stddev-samp.t001": "met", + "sf.functions.stddev.stddev-samp.t002": "met", + "sf.functions.stddev.stddev-samp.t003": "met", + "sf.functions.stddev.stddev-samp.t004": "met", + "sf.functions.stddev.stddev-samp.t005": "met", + "sf.functions.stddev.stddev-samp.t006": "met", + "sf.functions.stddev.stddev.t001": "met", + "sf.functions.stddev.stddev.t002": "met", + "sf.functions.stddev.stddev.t003": "met", + "sf.functions.stddev.stddev.t004": "met", + "sf.functions.stddev.stddev.t005": "met", + "sf.functions.stddev.stddev.t006": "met", "sf.functions.strip-null-value.t001": "met", "sf.functions.strip-null-value.t002": "met", "sf.functions.strip-null-value.t003": "met", @@ -18567,64 +18593,64 @@ "sf.functions.uuid-string.t001": "unmet", "sf.functions.uuid-string.t002": "unmet", "sf.functions.uuid-string.t003": "unmet", - "sf.functions.var-pop.var-pop-over.t001": "unmet", - "sf.functions.var-pop.var-pop-over.t002": "unmet", - "sf.functions.var-pop.var-pop-over.t003": "unmet", - "sf.functions.var-pop.var-pop-over.t004": "unmet", - "sf.functions.var-pop.var-pop-over.t005": "unmet", - "sf.functions.var-pop.var-pop-over.t006": "unmet", - "sf.functions.var-pop.var-pop-over.t007": "unmet", + "sf.functions.var-pop.var-pop-over.t001": "met", + "sf.functions.var-pop.var-pop-over.t002": "met", + "sf.functions.var-pop.var-pop-over.t003": "met", + "sf.functions.var-pop.var-pop-over.t004": "met", + "sf.functions.var-pop.var-pop-over.t005": "met", + "sf.functions.var-pop.var-pop-over.t006": "met", + "sf.functions.var-pop.var-pop-over.t007": "met", "sf.functions.var-pop.var-pop-over.t008": "unmet", - "sf.functions.var-pop.var-pop-over.t009": "unmet", - "sf.functions.var-pop.var-pop.t001": "unmet", - "sf.functions.var-pop.var-pop.t002": "unmet", - "sf.functions.var-pop.var-pop.t003": "unmet", - "sf.functions.var-pop.var-pop.t004": "unmet", - "sf.functions.var-pop.var-pop.t005": "unmet", - "sf.functions.var-pop.var-pop.t006": "unmet", - "sf.functions.var-samp.var-samp-over.t001": "unmet", - "sf.functions.var-samp.var-samp-over.t002": "unmet", - "sf.functions.var-samp.var-samp-over.t003": "unmet", - "sf.functions.var-samp.var-samp-over.t004": "unmet", - "sf.functions.var-samp.var-samp-over.t005": "unmet", - "sf.functions.var-samp.var-samp-over.t006": "unmet", - "sf.functions.var-samp.var-samp-over.t007": "unmet", - "sf.functions.var-samp.var-samp-over.t008": "unmet", - "sf.functions.var-samp.var-samp.t001": "unmet", - "sf.functions.var-samp.var-samp.t002": "unmet", - "sf.functions.var-samp.var-samp.t003": "unmet", - "sf.functions.var-samp.var-samp.t004": "unmet", - "sf.functions.var-samp.var-samp.t005": "unmet", - "sf.functions.var-samp.var-samp.t006": "unmet", - "sf.functions.variance-pop.variance-pop-over.t001": "unmet", - "sf.functions.variance-pop.variance-pop-over.t002": "unmet", - "sf.functions.variance-pop.variance-pop-over.t003": "unmet", - "sf.functions.variance-pop.variance-pop-over.t004": "unmet", - "sf.functions.variance-pop.variance-pop-over.t005": "unmet", - "sf.functions.variance-pop.variance-pop-over.t006": "unmet", - "sf.functions.variance-pop.variance-pop-over.t007": "unmet", + "sf.functions.var-pop.var-pop-over.t009": "met", + "sf.functions.var-pop.var-pop.t001": "met", + "sf.functions.var-pop.var-pop.t002": "met", + "sf.functions.var-pop.var-pop.t003": "met", + "sf.functions.var-pop.var-pop.t004": "met", + "sf.functions.var-pop.var-pop.t005": "met", + "sf.functions.var-pop.var-pop.t006": "met", + "sf.functions.var-samp.var-samp-over.t001": "met", + "sf.functions.var-samp.var-samp-over.t002": "met", + "sf.functions.var-samp.var-samp-over.t003": "met", + "sf.functions.var-samp.var-samp-over.t004": "met", + "sf.functions.var-samp.var-samp-over.t005": "met", + "sf.functions.var-samp.var-samp-over.t006": "met", + "sf.functions.var-samp.var-samp-over.t007": "met", + "sf.functions.var-samp.var-samp-over.t008": "met", + "sf.functions.var-samp.var-samp.t001": "met", + "sf.functions.var-samp.var-samp.t002": "met", + "sf.functions.var-samp.var-samp.t003": "met", + "sf.functions.var-samp.var-samp.t004": "met", + "sf.functions.var-samp.var-samp.t005": "met", + "sf.functions.var-samp.var-samp.t006": "met", + "sf.functions.variance-pop.variance-pop-over.t001": "met", + "sf.functions.variance-pop.variance-pop-over.t002": "met", + "sf.functions.variance-pop.variance-pop-over.t003": "met", + "sf.functions.variance-pop.variance-pop-over.t004": "met", + "sf.functions.variance-pop.variance-pop-over.t005": "met", + "sf.functions.variance-pop.variance-pop-over.t006": "met", + "sf.functions.variance-pop.variance-pop-over.t007": "met", "sf.functions.variance-pop.variance-pop-over.t008": "unmet", - "sf.functions.variance-pop.variance-pop-over.t009": "unmet", - "sf.functions.variance-pop.variance-pop.t001": "unmet", - "sf.functions.variance-pop.variance-pop.t002": "unmet", - "sf.functions.variance-pop.variance-pop.t003": "unmet", - "sf.functions.variance-pop.variance-pop.t004": "unmet", - "sf.functions.variance-pop.variance-pop.t005": "unmet", - "sf.functions.variance-pop.variance-pop.t006": "unmet", - "sf.functions.variance.variance-over.t001": "unmet", - "sf.functions.variance.variance-over.t002": "unmet", - "sf.functions.variance.variance-over.t003": "unmet", - "sf.functions.variance.variance-over.t004": "unmet", - "sf.functions.variance.variance-over.t005": "unmet", - "sf.functions.variance.variance-over.t006": "unmet", - "sf.functions.variance.variance-over.t007": "unmet", + "sf.functions.variance-pop.variance-pop-over.t009": "met", + "sf.functions.variance-pop.variance-pop.t001": "met", + "sf.functions.variance-pop.variance-pop.t002": "met", + "sf.functions.variance-pop.variance-pop.t003": "met", + "sf.functions.variance-pop.variance-pop.t004": "met", + "sf.functions.variance-pop.variance-pop.t005": "met", + "sf.functions.variance-pop.variance-pop.t006": "met", + "sf.functions.variance.variance-over.t001": "met", + "sf.functions.variance.variance-over.t002": "met", + "sf.functions.variance.variance-over.t003": "met", + "sf.functions.variance.variance-over.t004": "met", + "sf.functions.variance.variance-over.t005": "met", + "sf.functions.variance.variance-over.t006": "met", + "sf.functions.variance.variance-over.t007": "met", "sf.functions.variance.variance-over.t008": "unmet", - "sf.functions.variance.variance.t001": "unmet", - "sf.functions.variance.variance.t002": "unmet", - "sf.functions.variance.variance.t003": "unmet", + "sf.functions.variance.variance.t001": "met", + "sf.functions.variance.variance.t002": "met", + "sf.functions.variance.variance.t003": "met", "sf.functions.variance.variance.t004": "unmet", - "sf.functions.variance.variance.t005": "unmet", - "sf.functions.variance.variance.t006": "unmet", + "sf.functions.variance.variance.t005": "met", + "sf.functions.variance.variance.t006": "met", "sf.functions.vector-avg.t001": "unmet", "sf.functions.vector-avg.t002": "unmet", "sf.functions.vector-avg.t003": "unmet", diff --git a/crates/sqlquack-rules/src/catalogue/constants.rs b/crates/sqlquack-rules/src/catalogue/constants.rs index 1d6212b15..ff3328b57 100644 --- a/crates/sqlquack-rules/src/catalogue/constants.rs +++ b/crates/sqlquack-rules/src/catalogue/constants.rs @@ -17,7 +17,7 @@ use sqlquack_snowflake::typing::constants::VARIANT_COMMON_TYPE; pub const NOT_EXPRESSIBLE: &[NotExpressibleDeclaration] = &[]; use crate::conversion::constants::{ - ALIAS, ARRAY_AGG_RULE, ARRAY_APPEND_RULE, ARRAY_CAT_RULE, ARRAY_COMPACT_RULE, + ADD_MONTHS_RULE, ALIAS, ARRAY_AGG_RULE, ARRAY_APPEND_RULE, ARRAY_CAT_RULE, ARRAY_COMPACT_RULE, ARRAY_CONSTRUCT_COMPACT_RULE, ARRAY_CONSTRUCT_RULE, ARRAY_CONTAINS_RULE, ARRAY_EXCEPT_RULE, ARRAY_EXTREME_RULE, ARRAY_FLATTEN_RULE, ARRAY_POSITION_RULE, ARRAY_RANGE_RULE, ARRAY_REVERSE_RULE, ARRAY_SET_RULE, ARRAY_SIZE_RULE, ARRAY_SLICE_RULE, ARRAY_SORT_RULE, @@ -25,7 +25,7 @@ use crate::conversion::constants::{ CAST_BOOLEAN, CAST_NUMERIC, CAST_PARSED_TEXT, CAST_SAME_TYPE, CAST_TEMPORAL, CAST_TEXT_LITERAL, CAST_TEXT_TIME, CAST_TEXT_TIMESTAMP, CAST_TO_TEXT, CAST_UTC_ZONED, COALESCE, COLUMN, COMMENT, COMMON_TABLE, COMPARISON, COMPUTED_SUBSTR_LENGTH, CONCAT, CONCAT_WS, CONSTANT_LITERAL, COUNT, - CURRENT_TIME_RULE, DATE_ARITHMETIC, DATE_DAY_ARITHMETIC, DATE_FORMAT_RULE, + COVARIANCE_RULE, CURRENT_TIME_RULE, DATE_ARITHMETIC, DATE_DAY_ARITHMETIC, DATE_FORMAT_RULE, DATE_LITERAL_COMPARISON, DATE_PART_RULE, DAY_NAME_RULE, DECIMAL_ARITHMETIC, DECIMAL_DIVISION, DECIMAL_EPOCH_RULE, DECIMAL_MODULO, DECODE_RULE, DISTINCT, DIV0_RULE, EDIT_DISTANCE, EXISTS, FLATTEN_RULE, FLOAT_ARITHMETIC, FLOAT_MODULO, FLOAT_TO_DOUBLE, FRACTIONAL_DATE_AMOUNT, @@ -33,9 +33,9 @@ use crate::conversion::constants::{ HASH_RULE, HAVING, HIERARCHY_RULE, IFF, ILIKE_FOLDING, IN_LIST, IN_SUBQUERY, INTERVAL_ARITHMETIC, IS_NULL, JARO_WINKLER, JOIN_CROSS, JOIN_ON, JOIN_USING, LAMBDA_RULE, LAST_DAY_RULE, LATERAL_SUBQUERY, LEAST_GREATEST, LIKE, LIMIT, LISTAGG_RULE, LOGARITHM, LOGIC, - MEDIAN_RULE, MIN_MAX, MIN_MAX_FLOAT, MODE_RULE, NAMED_AGGREGATES, NEGATE, NOT_IN_SUBQUERY, - NULL_ARITHMETIC, NULL_BRANCHES, NULL_IF_ZERO_RULE, NULL_SAFE_COMPARISON, NULLIF, - NUMBER_LITERAL, NUMBER_TEXT_FORMAT, NUMERIC_FUNCTION, OBJECT_CONSTRUCT_RULE, + MEDIAN_RULE, MIN_MAX, MIN_MAX_FLOAT, MODE_RULE, MONTHS_BETWEEN_RULE, NAMED_AGGREGATES, NEGATE, + NOT_IN_SUBQUERY, NULL_ARITHMETIC, NULL_BRANCHES, NULL_IF_ZERO_RULE, NULL_SAFE_COMPARISON, + NULLIF, NUMBER_LITERAL, NUMBER_TEXT_FORMAT, NUMERIC_FUNCTION, NVL2_RULE, OBJECT_CONSTRUCT_RULE, OBJECT_DELETE_RULE, OBJECT_INSERT_RULE, OBJECT_KEYS_RULE, OBJECT_PICK_RULE, ORDER_BY, PARENTHESES, PARSE_JSON_RULE, PARSE_JSON_VARIANT, PARSE_URL_RULE, PERCENTILE_RULE, PIVOT_RULE, POSITIONAL_COLUMN, POWER_RULE, PROJECT_FUNCTION_CALL, PROJECT_TABLE_FUNCTION, QUALIFY, @@ -48,11 +48,12 @@ use crate::conversion::constants::{ TIME_ARITHMETIC, TIME_CAST, TIME_ZONE_CONVERSION, TIMESTAMP_FORMAT_RULE, TIMESTAMP_TIME_RULE, TO_ARRAY_RULE, TO_BOOLEAN_RULE, TO_DATE_TEMPORAL, TO_TIMESTAMP_TEMPORAL, TO_VARIANT_RULE, TRIM, UNION_BY_NAME, USER_OVERRIDE_RULE, UTC_OFFSET_ARITHMETIC, VALUE_AT_EXTREME_KEY, VALUES_ROWS, - VARIANT_CAST, VARIANT_COMPUTED_GET, VARIANT_EQUALITY, VARIANT_EQUALITY_BY_TEXT, - VARIANT_INSPECT, VARIANT_KIND_CAST, VARIANT_KIND_RULE, VARIANT_MAX, VARIANT_ORDER_KEY, - VARIANT_PARTITION, VARIANT_PATH, VARIANT_TEXT_BRANCHES, VARIANT_TO_VARCHAR, VARIANT_TYPE_NAME, - VARIANT_TYPED_CHECK, WHERE, WINDOW_AGGREGATE, WINDOW_FIRST_LAST, WINDOW_OFFSET, WINDOW_RANKING, - WINDOW_VALUE_FRAME, ZERO_IF_NULL_RULE, ZONE_COLUMNS, ZONED_PARTS, + VARIANCE_FLOAT_RULE, VARIANCE_RULE, VARIANT_CAST, VARIANT_COMPUTED_GET, VARIANT_EQUALITY, + VARIANT_EQUALITY_BY_TEXT, VARIANT_INSPECT, VARIANT_KIND_CAST, VARIANT_KIND_RULE, VARIANT_MAX, + VARIANT_ORDER_KEY, VARIANT_PARTITION, VARIANT_PATH, VARIANT_TEXT_BRANCHES, VARIANT_TO_VARCHAR, + VARIANT_TYPE_NAME, VARIANT_TYPED_CHECK, WHERE, WINDOW_AGGREGATE, WINDOW_FIRST_LAST, + WINDOW_OFFSET, WINDOW_RANKING, WINDOW_VALUE_FRAME, ZERO_IF_NULL_RULE, ZONE_COLUMNS, + ZONED_PARTS, }; use crate::conversion::models::RuleSpec; @@ -399,6 +400,61 @@ pub const RULES: &[RuleSpec] = &[ conditions: "A BOOLEAN condition; branches unify.", failures: &[], }, + RuleSpec { + id: ADD_MONTHS_RULE, + constructs: &["fn:ADD_MONTHS"], + conditions: "ADD_MONTHS of a DATE, a TIMESTAMP_NTZ, or a TIMESTAMP_TZ with its UTC offset known, and a NUMBER of months rounded half away from zero, as DATEADD by month: the day clamped to the month's end, and a month's last day moved on to the last day of the month it lands in, the time of day kept, as recorded; a TIMESTAMP_TZ moves on its wall clock. NULL where either argument is NULL.", + failures: &[], + }, + RuleSpec { + id: MONTHS_BETWEEN_RULE, + constructs: &["fn:MONTHS_BETWEEN"], + conditions: "MONTHS_BETWEEN of DATEs and TIMESTAMP_NTZs, as NUMBER(27,6): the whole months between their calendar months where their days of month match or both are a month's last day, the clock ignored; otherwise those months plus the difference of their days and clocks over 31 days, rounded half away from zero at six decimals, as recorded. DATE inputs never tie; a timestamp tie at the sixth decimal no recording shows. NULL where either is NULL.", + failures: &[], + }, + RuleSpec { + id: VARIANCE_RULE, + constructs: &[ + "fn:VARIANCE", + "fn:VAR_SAMP", + "fn:VAR_POP", + "fn:VARIANCE_POP", + "fn:STDDEV", + "fn:STDDEV_SAMP", + "fn:STDDEV_POP", + ], + conditions: "Of a NUMBER of scale s at most 12, as an aggregate or over a window with an unordered, running or ROWS frame, DISTINCT included except for VARIANCE, which Snowflake rejects, and except over an ordered window: the exact (n·Σx² − (Σx)²) / (n(n−1)), or / n² for the population, rounded half up to NUMBER(38, min(6 + 2s, 12)), NULL below two values (one for the population), as recorded; the standard deviations are the square root of that rounded variance, as a FLOAT. A total beyond 38 digits raises numeric_range.", + failures: &[FailureMode { + kind: ErrorKind::NumericOverflow, + snowflake: &[NUMBER_OUT_OF_RANGE], + }], + }, + RuleSpec { + id: VARIANCE_FLOAT_RULE, + constructs: &[ + "fn:VARIANCE", + "fn:VAR_SAMP", + "fn:VAR_POP", + "fn:VARIANCE_POP", + "fn:STDDEV", + "fn:STDDEV_SAMP", + "fn:STDDEV_POP", + ], + conditions: "Of a FLOAT, or text cast to FLOAT, without DISTINCT: (n·Σx² − (Σx)²) / (n(n−1)), or / n² for the population, in doubles, cancelling as Snowflake was recorded cancelling, relying on float_sum_order for the sums; NULL below two values (one for the population); the standard deviations are its square root.", + failures: &[], + }, + RuleSpec { + id: COVARIANCE_RULE, + constructs: &["fn:COVAR_SAMP", "fn:COVAR_POP"], + conditions: "Of NUMBER or FLOAT pairs, without DISTINCT, as an aggregate or over a window, pairs with a NULL skipped: (Σxy − Σx·Σy / n) / (n − 1), or / n for the population, in doubles, relying on float_sum_order for the sums; NULL below two pairs (one for the population), as recorded.", + failures: &[], + }, + RuleSpec { + id: NVL2_RULE, + constructs: &["fn:NVL2"], + conditions: "Exactly three arguments, the first not semi-structured: the second where the first is not NULL, else the third; branches unify as recorded for NUMBER, FLOAT, text and untyped NULL branches, and text beside another type refuses.", + failures: &[], + }, RuleSpec { id: NULLIF, constructs: &["fn:NULLIF"], diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/calls.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/calls.rs index a10eb1062..85dfb8251 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/calls.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/calls.rs @@ -27,7 +27,7 @@ use crate::conversion::_helpers::expressions::casts::{ }; use crate::conversion::_helpers::expressions::conditionals::unified; use crate::conversion::_helpers::expressions::conditionals::{ - decode, div0, null_if_zero, zero_if_null, + decode, div0, null_if_zero, nvl2, zero_if_null, }; use crate::conversion::_helpers::expressions::hashing::hash_call; use crate::conversion::_helpers::expressions::lambdas::{lambda_call, reduce_call}; @@ -49,9 +49,9 @@ use crate::conversion::_helpers::expressions::strings::{ try_hex_decode, }; use crate::conversion::_helpers::expressions::temporal_functions::{ - convert_timezone, current_time, date_add, date_diff_call, date_from_parts_call, date_part, - date_trunc, day_name, last_day, temporal_text, timestamp_from_parts_call, to_time, - to_timestamp, to_timestamp_tz, + add_months, convert_timezone, current_time, date_add, date_diff_call, date_from_parts_call, + date_part, date_trunc, day_name, last_day, months_between, temporal_text, + timestamp_from_parts_call, to_time, to_timestamp, to_timestamp_tz, }; use crate::conversion::_helpers::expressions::text_functions::{ left_right, pad, regexp, replace, split_part, stripped_type_name, suffixed_column, @@ -268,6 +268,8 @@ pub(crate) fn convert_function(payload: &Value, site: Site<'_>) -> Result date_trunc(unit, value, &construct, site), ("DAYNAME", parts) => day_name(parts, &construct, site), ("LAST_DAY", parts) => last_day(parts, &construct, site), + ("ADD_MONTHS", parts) => add_months(parts, &construct, site), + ("MONTHS_BETWEEN", parts) => months_between(parts, &construct, site), ("DATEADD" | "TIMEADD" | "TIMESTAMPADD", [unit, amount, value]) => { date_add((unit, amount, value), &construct, site) } @@ -327,6 +329,9 @@ pub(crate) fn convert_function(payload: &Value, site: Site<'_>) -> Result { zoned_text_call(&name, value, &construct, site) } + ("NVL2", [tested, when_set, otherwise]) => { + nvl2((tested, when_set, otherwise), &construct, site) + } ("LEAST" | "GREATEST", parts) if !parts.is_empty() => { least_greatest(&name, parts, &construct, site) } diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/casts.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/casts.rs index d55811335..a9fed0877 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/casts.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/casts.rs @@ -62,11 +62,12 @@ use crate::conversion::constants::{ CAST_BOOLEAN, CAST_NUMERIC, CAST_PARSED_TEXT, CAST_SAME_TYPE, CAST_TEMPORAL, CAST_TEXT_LITERAL, CAST_TEXT_TIME, CAST_TEXT_TIMESTAMP, CAST_TO_TEXT, CAST_UTC_ZONED, FLOAT_SCALE_FACET, FLOAT_TO_DOUBLE, KEEP_NULL_CONSTRUCTOR, KIND_CAST_TARGETS, MICROSECOND_DIGITS, - NTZ_OUTPUT_PATTERN, OBJECT_CONSTRUCTOR, OBJECT_TYPE_NAME, TARGET_FACET, TEXT_TYPE_PAIR, - TEXT_TYPE_SPELLINGS, TIME_CAST, TIMESTAMP_TIME_RULE, TO_BOOLEAN_RULE, TO_DOUBLE_PAIR, - TO_NUMBER_PAIR, TO_VARCHAR_PAIR, TO_VARIANT_RULE, VARIANT_CAST, VARIANT_KIND_CAST, - VARIANT_NAME, VARIANT_TEXT_FUNCTION, VARIANT_TO_VARCHAR, + OBJECT_CONSTRUCTOR, OBJECT_TYPE_NAME, TARGET_FACET, TEXT_TYPE_PAIR, TEXT_TYPE_SPELLINGS, + TIME_CAST, TIMESTAMP_TIME_RULE, TO_BOOLEAN_RULE, TO_DOUBLE_PAIR, TO_NUMBER_PAIR, + TO_VARCHAR_PAIR, TO_VARIANT_RULE, VARIANT_CAST, VARIANT_KIND_CAST, VARIANT_NAME, + VARIANT_TEXT_FUNCTION, VARIANT_TO_VARCHAR, }; +use crate::text_formats::constants::NTZ_OUTPUT_PATTERN; use sqlquack_policy::policy::constants::{ DATE_TEXT_SPELLING, SESSION_TIMEZONE_UTC, TIMESTAMP_RANGE, TIMESTAMP_TEXT_ROUNDING, TIMESTAMP_TZ_OFFSET, diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/conditionals.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/conditionals.rs index f5e28e313..331b67481 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/conditionals.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/conditionals.rs @@ -23,7 +23,7 @@ use crate::conversion::_helpers::support::tree::{ }; use crate::conversion::constants::{ CASE, CASE_SUBJECT, COALESCE, DECODE_RULE, DIV0_RULE, IFF, NULL_BRANCHES, NULL_IF_ZERO_RULE, - SEMI_STRUCTURED_HOLDING, TEXT_BRANCHES, ZERO_IF_NULL_RULE, + NVL2_RULE, SEMI_STRUCTURED_HOLDING, TEXT_BRANCHES, ZERO_IF_NULL_RULE, }; /// The branches cast to their unified type, and that type; text beside other types refuses. @@ -238,6 +238,34 @@ pub(crate) fn iff(payload: &Value, site: Site<'_>) -> Result { }) } +/// NVL2: the second argument where the first is not NULL, else the third; text beside other types refuses. +pub(crate) fn nvl2( + (tested, when_set, otherwise): (&Value, &Value, &Value), + construct: &Construct, + site: Site<'_>, +) -> Result { + let _rule = site.context.log.rule(NVL2_RULE); + let tested = convert_expression(tested, site)?; + if tested.data_type == SnowflakeType::SemiStructured { + return Err(outside_conditions( + construct.clone(), + "NVL2 of a semi-structured value, whose JSON null no recording shows".to_owned(), + )); + } + let branches = [ + convert_expression(when_set, site)?, + convert_expression(otherwise, site)?, + ]; + let (cast_branches, target) = unified(&branches, construct, site.context)?; + Ok(Emitted::new( + format!( + "(CASE WHEN ({}) IS NOT NULL THEN {} ELSE {} END)", + tested.sql, cast_branches[0], cast_branches[1] + ), + target, + )) +} + /// Searched and simple CASE. pub(crate) fn case_expression(payload: &Value, site: Site<'_>) -> Result { let construct = node_construct("case"); diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/mod.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/mod.rs index b12a65b7f..d0b0d7b18 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/mod.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/mod.rs @@ -18,6 +18,7 @@ pub(crate) mod result_types; pub(crate) mod scalar; pub(crate) mod semi_structured; pub(crate) mod spellings; +pub(crate) mod statistics; pub(crate) mod strings; pub(crate) mod temporal; pub(crate) mod temporal_functions; diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/named_aggregates.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/named_aggregates.rs index f55ed3e32..5114b24c7 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/named_aggregates.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/named_aggregates.rs @@ -22,6 +22,7 @@ use sqlquack_snowflake::typing::main::count::count; use sqlquack_snowflake::typing::models::SnowflakeType; use crate::conversion::_helpers::expressions::scalar::convert_expression; +use crate::conversion::_helpers::expressions::statistics::{is_statistic, statistic}; use crate::conversion::_helpers::expressions::variants::to_variant; use crate::conversion::_helpers::support::divergence::diverge; use crate::conversion::_helpers::support::scope::Emitted; @@ -41,7 +42,7 @@ use sqlquack_policy::policy::constants::{ /// Whether `name` is an aggregate converted here. pub(crate) fn is_named_aggregate(name: &str) -> bool { - NAMED_AGGREGATE_NAMES.contains(&name) + NAMED_AGGREGATE_NAMES.contains(&name) || is_statistic(name) } /// One named aggregate; `window` is the OVER clause when used as a window function. @@ -57,13 +58,13 @@ pub(crate) fn named_aggregate( let payload = payload_object(payload, &construct)?; require_understood(payload, &["name", "args", "distinct"], &construct)?; let distinct = flag(payload, "distinct"); - if distinct != (name == MULTI_COUNT) { + if distinct != (name == MULTI_COUNT) && !is_statistic(name) { return Err(refuse(format!( "{name} with or without DISTINCT as written" ))); } let over = window.map_or_else(String::new, |window| format!(" OVER ({window})")); - if window.is_some() && !WINDOWED_NAMED_AGGREGATES.contains(&name) { + if window.is_some() && !WINDOWED_NAMED_AGGREGATES.contains(&name) && !is_statistic(name) { return Err(refuse(format!("{name} over a window"))); } let site = site.placed(Placement::ROW); @@ -73,6 +74,12 @@ pub(crate) fn named_aggregate( .collect::>()?; let log = site.context.log; match (name, arguments.as_slice()) { + (name, arguments) if is_statistic(name) => statistic( + name, + arguments, + (distinct, &over), + (&construct, site.context), + ), ("ANY_VALUE", [value]) if value.data_type != SnowflakeType::Null => { diverge(site.context, ANY_VALUE_CHOICE, &construct)?; compared_value(value, &construct, site.context)?; diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/scalar.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/scalar.rs index 501895865..5432d8c0c 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/scalar.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/scalar.rs @@ -33,6 +33,7 @@ use crate::conversion::_helpers::expressions::predicates::{ use crate::conversion::_helpers::expressions::result_types::result_type; use crate::conversion::_helpers::expressions::semi_structured::{variant_path, variant_subscript}; use crate::conversion::_helpers::expressions::spellings::{as_typed, as_written, rlike_as_call}; +use crate::conversion::_helpers::expressions::statistics::is_statistic; use crate::conversion::_helpers::expressions::strings::{ case_mapping, concat_operator, text_affix, trim, }; @@ -348,7 +349,9 @@ fn convert_kind(node: &Value, site: Site<'_>) -> Result { .adopt(&typed, arguments.map_or(&[], Vec::as_slice)); convert_expression(&typed, site).map_err(|refusal| as_written(refusal, spelling)) } - None if kind == CALL_KIND => convert_function(payload, site), + None if kind == CALL_KIND && !is_statistic(&call_name(payload)) => { + convert_function(payload, site) + } None if is_named_aggregate(&call_name(payload)) => { if !site.placement.aggregates { return Err(outside_conditions( diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/statistics.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/statistics.rs new file mode 100644 index 000000000..e573efdf1 --- /dev/null +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/statistics.rs @@ -0,0 +1,318 @@ +//! Variance, standard deviation and covariance aggregates, computed the way Snowflake was recorded. + +use sqlquack_core::classification::models::Construct; +use sqlquack_core::refusals::main::outside_conditions::outside_conditions; +use sqlquack_core::refusals::models::Refusal; +use sqlquack_duckdb::blocks::main::exact_decimal_divide::exact_decimal_divide; +use sqlquack_duckdb::floats::constants::FLOAT_SUM_ORDER; +use sqlquack_duckdb::floats::main::exact_float_sum::exact_float_sum; +use sqlquack_policy::policy::constants::NUMERIC_RANGE; +use sqlquack_snowflake::typing::constants::MAX_PRECISION; +use sqlquack_snowflake::typing::models::SnowflakeType; + +use crate::conversion::_helpers::expressions::casts::cast_to; +use crate::conversion::_helpers::support::divergence::diverge; +use crate::conversion::_helpers::support::scope::{Context, Emitted}; +use crate::conversion::constants::{COVARIANCE_RULE, VARIANCE_FLOAT_RULE, VARIANCE_RULE}; + +/// Variances and standard deviations: the name, whether over the population, and whether a root. +const VARIANCE_AGGREGATES: &[(&str, bool, bool)] = &[ + ("VARIANCE", false, false), + ("VAR_SAMP", false, false), + ("VAR_POP", true, false), + ("VARIANCE_POP", true, false), + ("STDDEV", false, true), + ("STDDEV_SAMP", false, true), + ("STDDEV_POP", true, true), +]; +/// Covariances, and whether over the population. +const COVARIANCE_AGGREGATES: &[(&str, bool)] = &[("COVAR_SAMP", false), ("COVAR_POP", true)]; +/// The variance Snowflake rejects with DISTINCT, though its other spellings accept it. +const NO_DISTINCT_VARIANCE: &str = "VARIANCE"; +/// An exact variance's result scale: this base plus twice the input's scale, at most the widest. +const VARIANCE_SCALES: (u8, u8) = (6, 12); +/// The lambda parameter squaring each distinct value of an exact variance. +const SQUARED_PARAMETER: &str = "__sqlquack_squared"; +/// The type name statistics cast NUMBER and text arguments to. +const FLOAT_TYPE_NAME: &str = "FLOAT"; + +/// Whether `name` is a variance, standard deviation or covariance aggregate converted here. +pub(crate) fn is_statistic(name: &str) -> bool { + VARIANCE_AGGREGATES + .iter() + .any(|(known, _, _)| *known == name) + || COVARIANCE_AGGREGATES + .iter() + .any(|(known, _)| *known == name) +} + +/// One statistic of converted `arguments`; `over` is its OVER clause, or empty. +pub(crate) fn statistic( + name: &str, + arguments: &[Emitted], + (distinct, over): (bool, &str), + (construct, context): (&Construct, &Context<'_>), +) -> Result { + let refuse = |reason: String| outside_conditions(construct.clone(), reason); + if distinct && name == NO_DISTINCT_VARIANCE { + return Err(refuse(format!( + "{name}(DISTINCT), which Snowflake rejects as an unsupported feature" + ))); + } + let variance = VARIANCE_AGGREGATES + .iter() + .find(|(known, _, _)| *known == name); + let covariance = COVARIANCE_AGGREGATES + .iter() + .find(|(known, _)| *known == name); + match (variance, covariance, arguments) { + (Some((_, population, root)), _, [value]) => { + let shape = Shape { + population: *population, + distinct, + over, + }; + let sql = match value.data_type { + SnowflakeType::Number { scale, .. } => { + exact_variance(&value.sql, scale, shape, (construct, context))? + } + SnowflakeType::Float | SnowflakeType::Varchar if !distinct => { + let float = as_float(value, (construct, context))?; + float_variance(&float, shape, (construct, context))? + } + other => { + return Err(refuse(format!( + "{name}{} of {other}, which no recording shows", + distinct_text(distinct) + ))); + } + }; + Ok(match (root, value.data_type) { + (true, SnowflakeType::Number { .. }) => { + Emitted::new(format!("sqrt(CAST({sql} AS DOUBLE))"), SnowflakeType::Float) + } + (true, _) => Emitted::new(format!("sqrt({sql})"), SnowflakeType::Float), + (false, SnowflakeType::Number { scale, .. }) => Emitted::new( + sql, + SnowflakeType::Number { + precision: MAX_PRECISION, + scale: variance_scale(scale), + }, + ), + (false, _) => Emitted::new(sql, SnowflakeType::Float), + }) + } + (_, Some((_, population)), [y, x]) if !distinct && numeric(y) && numeric(x) => { + let shape = Shape { + population: *population, + distinct, + over, + }; + let pair = ( + as_float(y, (construct, context))?, + as_float(x, (construct, context))?, + ); + Ok(Emitted::new( + float_covariance((&y.sql, &x.sql), pair, shape, (construct, context))?, + SnowflakeType::Float, + )) + } + (_, _, arguments) => Err(refuse(format!( + "{name}{} of {}, which no recording shows", + distinct_text(distinct), + arguments + .iter() + .map(|argument| argument.data_type.to_string()) + .collect::>() + .join(", ") + ))), + } +} + +/// How a statistic aggregates: over the population or a sample, its distinct values, its window. +#[derive(Clone, Copy)] +struct Shape<'a> { + population: bool, + distinct: bool, + over: &'a str, +} + +impl Shape<'_> { + /// The fewest values with a result: one for a population, two for a sample. + fn fewest(self) -> u8 { + match self.population { + true => 1, + false => 2, + } + } +} + +/// The recorded result scale of the variance of a NUMBER of `scale`. +fn variance_scale(scale: u8) -> u8 { + let (base, widest) = VARIANCE_SCALES; + (base + 2 * scale).min(widest) +} + +/// The exact variance of a NUMBER of `scale`, rounded half up to its recorded scale. +fn exact_variance( + value: &str, + scale: u8, + shape: Shape<'_>, + (construct, context): (&Construct, &Context<'_>), +) -> Result { + let log = context.log; + let _rule = log.rule(VARIANCE_RULE); + let refuse = |reason: String| outside_conditions(construct.clone(), reason); + let (_, widest) = VARIANCE_SCALES; + if scale > widest { + return Err(refuse(format!( + "the variance of a NUMBER of scale {scale}, above the widest recorded ({widest})" + ))); + } + diverge(context, NUMERIC_RANGE, construct)?; + let over = shape.over; + let squares = 2 * scale; + let decimal = |sql: &str, scale: u8| format!("CAST({sql} AS DECIMAL(38,{scale}))"); + let (count, total, sum_of_squares) = match shape.distinct { + true => ( + format!("count(DISTINCT {value}){over}"), + format!("sum(DISTINCT {value}){over}"), + format!( + "list_sum(list_transform(list(DISTINCT {value}){over}, \ + lambda {SQUARED_PARAMETER}: {} * {}))", + decimal(SQUARED_PARAMETER, scale), + decimal(SQUARED_PARAMETER, scale) + ), + ), + false => ( + format!("count({value}){over}"), + format!("sum({value}){over}"), + format!( + "sum({} * {}){over}", + decimal(value, scale), + decimal(value, scale) + ), + ), + }; + let numerator = decimal( + &format!( + "{} * {} - {} * {}", + decimal(&count, 0), + decimal(&sum_of_squares, squares), + decimal(&total, scale), + decimal(&total, scale) + ), + squares, + ); + let result = variance_scale(scale); + let divisor_scale = squares.saturating_sub(result); + let pairs = match shape.population { + true => format!("{count} * {count}"), + false => format!("{count} * ({count} - 1)"), + }; + let (divided, _) = exact_decimal_divide( + (&numerator, MAX_PRECISION, squares), + ( + &decimal(&pairs, divisor_scale), + MAX_PRECISION, + divisor_scale, + ), + ( + SnowflakeType::Number { + precision: MAX_PRECISION, + scale: result, + }, + false, + ), + log, + ) + .map_err(refuse)?; + Ok(format!( + "(CASE WHEN {count} < {} THEN NULL ELSE {divided} END)", + shape.fewest() + )) +} + +/// The variance of FLOAT values `value`, as (n·Σx² − (Σx)²) / (n·d) with exact sums. +fn float_variance( + value: &str, + shape: Shape<'_>, + (construct, context): (&Construct, &Context<'_>), +) -> Result { + let log = context.log; + let _rule = log.rule(VARIANCE_FLOAT_RULE); + diverge(context, FLOAT_SUM_ORDER, construct)?; + let over = shape.over; + let count = format!("count({value}){over}"); + let values = format!("CAST({count} AS DOUBLE)"); + let total = exact_float_sum(value, "", over, log); + let squares = exact_float_sum(&format!("({value}) * ({value})"), "", over, log); + Ok(format!( + "(CASE WHEN {count} < {} THEN NULL ELSE ({values} * {squares} - {total} * {total}) / \ + ({values} * {}) END)", + shape.fewest(), + degrees(&values, shape) + )) +} + +/// The covariance of FLOAT pairs, as (Σxy − Σx·Σy / n) / d with exact sums over complete pairs. +fn float_covariance( + (y_sql, x_sql): (&str, &str), + (y, x): (String, String), + shape: Shape<'_>, + (construct, context): (&Construct, &Context<'_>), +) -> Result { + let log = context.log; + let _rule = log.rule(COVARIANCE_RULE); + diverge(context, FLOAT_SUM_ORDER, construct)?; + let over = shape.over; + let complete = format!("{y_sql} IS NOT NULL AND {x_sql} IS NOT NULL"); + let kept = |sql: &str| format!("CASE WHEN {complete} THEN {sql} END"); + let count = format!("count({}){over}", kept("1")); + let values = format!("CAST({count} AS DOUBLE)"); + let sum = |sql: &str| exact_float_sum(&kept(sql), "", over, log); + Ok(format!( + "(CASE WHEN {count} < {} THEN NULL ELSE ({} - {} * {} / {values}) / {} END)", + shape.fewest(), + sum(&format!("({y}) * ({x})")), + sum(&x), + sum(&y), + degrees(&values, shape) + )) +} + +/// The divisor's degrees of freedom: n for a population, n − 1 for a sample. +fn degrees(values: &str, shape: Shape<'_>) -> String { + match shape.population { + true => values.to_owned(), + false => format!("({values} - 1)"), + } +} + +/// `value` as a FLOAT: as it is, or cast as Snowflake casts a NUMBER or text argument. +fn as_float( + value: &Emitted, + (construct, context): (&Construct, &Context<'_>), +) -> Result { + match value.data_type { + SnowflakeType::Float => Ok(value.sql.clone()), + _ => cast_to(value, FLOAT_TYPE_NAME, false, (context, construct)) + .map_err(|reason| outside_conditions(construct.clone(), reason)), + } +} + +/// Whether a covariance argument is of a type its recordings show: NUMBER or FLOAT. +fn numeric(value: &Emitted) -> bool { + matches!( + value.data_type, + SnowflakeType::Number { .. } | SnowflakeType::Float + ) +} + +/// " (DISTINCT)" when `distinct`, for refusal reasons. +fn distinct_text(distinct: bool) -> &'static str { + match distinct { + true => "(DISTINCT)", + false => "", + } +} diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/temporal_functions.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/temporal_functions.rs index cb25e49cd..4ac1d04b8 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/temporal_functions.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/temporal_functions.rs @@ -7,6 +7,7 @@ use sqlquack_core::refusals::main::outside_conditions::outside_conditions; use sqlquack_core::refusals::models::Refusal; use sqlquack_duckdb::blocks::constants::NANOSECOND_DIGITS; use sqlquack_duckdb::blocks::main::cast::cast; +use sqlquack_duckdb::blocks::main::exact_decimal_divide::exact_decimal_divide; use sqlquack_duckdb::blocks::main::string_literal::string_literal; use sqlquack_duckdb::blocks::models::TextFailure; use sqlquack_duckdb::temporal::constants::DATE_FORMATS; @@ -58,16 +59,18 @@ use crate::conversion::_helpers::support::tree::{ field, node_construct, payload_object, require_understood, }; use crate::conversion::constants::{ - BARE_FRACTION, BARE_FRACTION_PATTERNS, CLOCK_FORMAT_FIELDS, CURRENT_TIME_RULE, DATE_ARITHMETIC, - DATE_FORMAT_RULE, DATE_NAME, DATE_PART_RULE, DATE_PARTS, DAY_NAME_RULE, DECIMAL_EPOCH_RULE, + ADD_MONTHS_RULE, CURRENT_TIME_RULE, DATE_ARITHMETIC, DATE_FORMAT_RULE, DATE_NAME, + DATE_PART_RULE, DATE_PARTS, DAY_NAME_RULE, DAY_UNIT, DECIMAL_EPOCH_RULE, FRACTIONAL_DATE_AMOUNT, FROM_PARTS, LAST_DAY_RULE, MAX_FRACTION_DIGITS_U8, MICROSECOND_DIGITS, - MONTH_NAME_FIELDS, MONTH_NAME_FOLLOWERS, NULL_BRANCHES, NUMBER_TEXT_FORMAT, OFFSET_FREE_UNITS, - RECORDED_TIME_ZONES, SCALE_DIGITS, TEMPORAL_TEXT_FIELDS, TEMPORAL_TEXT_FORMAT, - TEMPORAL_TEXT_SEPARATORS, TEXT_TO_TIME_RULE, TEXT_TO_TIMESTAMP_RULE, TIME_ARITHMETIC, + MONTH_UNIT, MONTHS_BETWEEN_MONTH_NANOSECONDS, MONTHS_BETWEEN_RULE, MONTHS_BETWEEN_TYPE, + NULL_BRANCHES, NUMBER_TEXT_FORMAT, OFFSET_FREE_UNITS, RECORDED_TIME_ZONES, SCALE_DIGITS, + TEMPORAL_TEXT_FORMAT, TEXT_TO_TIME_RULE, TEXT_TO_TIMESTAMP_RULE, TIME_ARITHMETIC, TIME_ZONE_CONVERSION, TIMESTAMP_FORMAT_RULE, TIMESTAMP_NTZ_NAME, TIMESTAMP_TIME_RULE, TO_DATE_TEMPORAL, TO_TIMESTAMP_TEMPORAL, UTC_OFFSET_ARITHMETIC, UTC_ZONE, ZONE_COLUMNS, ZONED_PARTS, }; +use crate::text_formats::main::clock_format::clock_format; +use crate::text_formats::main::strftime_pattern::strftime_pattern; use sqlquack_duckdb::raises::main::raised::raised; use sqlquack_duckdb::temporal::constants::{DUCKDB_CURRENT_DATE, DUCKDB_CURRENT_TIMESTAMP}; use sqlquack_policy::policy::constants::{ @@ -359,7 +362,102 @@ pub(crate) fn date_add( let _rule = site.context.log.rule(DATE_ARITHMETIC); let refuse = |reason: String| outside_conditions(construct.clone(), reason); let unit = unit_name(unit).ok_or_else(|| refuse("an unreadable unit".to_owned()))?; - let mut amount = convert_expression(amount, site)?; + let amount = convert_expression(amount, site)?; + let operand = convert_expression(value, site)?; + shift((&unit, amount), operand, false, (construct, site)) +} + +/// ADD_MONTHS(value, months): DATEADD of the rounded months, a month's last day kept the last day. +pub(crate) fn add_months( + parts: &[Value], + construct: &Construct, + site: Site<'_>, +) -> Result { + let _rule = site.context.log.rule(ADD_MONTHS_RULE); + let refuse = |reason: String| outside_conditions(construct.clone(), reason); + let [value, amount] = parts else { + return Err(refuse(format!("ADD_MONTHS of {} arguments", parts.len()))); + }; + let operand = convert_expression(value, site)?; + let amount = convert_expression(amount, site)?; + match (operand.data_type, amount.data_type) { + ( + SnowflakeType::Date + | SnowflakeType::TimestampNtz { .. } + | SnowflakeType::TimestampTz { .. }, + SnowflakeType::Number { .. } | SnowflakeType::Null, + ) => shift((MONTH_UNIT, amount), operand, true, (construct, site)), + (operand, amount) => Err(refuse(format!( + "ADD_MONTHS of {operand} and {amount}, which no recording shows" + ))), + } +} + +/// MONTHS_BETWEEN(a, b) of DATEs and naive timestamps, whole or over a 31-day month, as recorded. +pub(crate) fn months_between( + parts: &[Value], + construct: &Construct, + site: Site<'_>, +) -> Result { + let log = site.context.log; + let _rule = log.rule(MONTHS_BETWEEN_RULE); + let refuse = |reason: String| outside_conditions(construct.clone(), reason); + let [later, earlier] = parts else { + return Err(refuse(format!( + "MONTHS_BETWEEN of {} arguments", + parts.len() + ))); + }; + let (later, earlier) = ( + convert_expression(later, site)?, + convert_expression(earlier, site)?, + ); + let read = |value: &Emitted| match value.data_type { + SnowflakeType::Date => Ok((value.sql.clone(), "0".to_owned())), + SnowflakeType::TimestampNtz { precision } => { + let day = truncate_timestamp_to_date(&value.sql, precision, log); + let clock = format!( + "(epoch_ns({}) - epoch_ns(CAST({day} AS TIMESTAMP)))", + value.sql + ); + Ok((day, clock)) + } + other => Err(refuse(format!( + "MONTHS_BETWEEN of a {other}, which no recording shows" + ))), + }; + let ((a, a_clock), (b, b_clock)) = (read(&later)?, read(&earlier)?); + let whole = format!("((year({a}) - year({b})) * 12 + month({a}) - month({b}))"); + let whole_only = + format!("(day({a}) = day({b}) OR (last_day({a}) = {a} AND last_day({b}) = {b}))"); + let month = MONTHS_BETWEEN_MONTH_NANOSECONDS; + let numerator = format!( + "(CAST({whole} AS HUGEINT) * {month} + CAST(day({a}) - day({b}) AS HUGEINT) * {} \ + + CAST({a_clock} AS HUGEINT) - CAST({b_clock} AS HUGEINT))", + month / 31 + ); + let (divided, _) = exact_decimal_divide( + (&numerator, MAX_PRECISION, 0), + (&month.to_string(), MAX_PRECISION, 0), + (MONTHS_BETWEEN_TYPE, false), + log, + ) + .map_err(refuse)?; + let whole = cast(whole.as_str(), MONTHS_BETWEEN_TYPE, log).map_err(refuse)?; + Ok(Emitted::new( + format!("(CASE WHEN {whole_only} THEN {whole} ELSE {divided} END)"), + MONTHS_BETWEEN_TYPE, + )) +} + +/// `operand` moved by `amount` of `unit`; with `month_end`, a month's last day stays a last day. +fn shift( + (unit, mut amount): (&str, Emitted), + operand: Emitted, + month_end: bool, + (construct, site): (&Construct, Site<'_>), +) -> Result { + let refuse = |reason: String| outside_conditions(construct.clone(), reason); match amount.data_type { SnowflakeType::Number { scale: 0, .. } => {} SnowflakeType::Number { .. } | SnowflakeType::Float => { @@ -372,9 +470,9 @@ pub(crate) fn date_add( }, ); } + SnowflakeType::Null if month_end => {} other => return Err(refuse(format!("a {other} amount"))), } - let operand = convert_expression(value, site)?; let operand = match operand.data_type { SnowflakeType::Varchar => { let ntz = SnowflakeType::TimestampNtz { precision: 9 }; @@ -395,7 +493,7 @@ pub(crate) fn date_add( if let SnowflakeType::Time { .. } = operand.data_type { let _time = site.context.log.rule(TIME_ARITHMETIC); let sql = - time_add_value(&operand.sql, (&unit, &amount.sql), site.context.log).map_err(refuse)?; + time_add_value(&operand.sql, (unit, &amount.sql), site.context.log).map_err(refuse)?; return Ok(Emitted::new(sql, operand.data_type)); } if let SnowflakeType::TimestampNtz { precision } = operand.data_type @@ -405,11 +503,16 @@ pub(crate) fn date_add( } let sql = date_add_value( &operand.sql, - (&unit, &format!("CAST({} AS BIGINT)", amount.sql)), + (unit, &format!("CAST({} AS BIGINT)", amount.sql)), operand.data_type, site.context.log, ) .map_err(refuse)?; + let sql = match month_end { + true => kept_month_end((&operand.sql, sql), operand.data_type, site.context.log) + .map_err(refuse)?, + false => sql, + }; let (sql, data_type) = match operand.data_type { SnowflakeType::TimestampNtz { precision } if precision < MAX_FRACTION_DIGITS_U8 => { let nanoseconds = SnowflakeType::TimestampNtz { @@ -435,6 +538,26 @@ pub(crate) fn date_add( )) } +/// `shifted` moved on to its month's last day where `original`, of `data_type`, is a month's last day. +fn kept_month_end( + (original, shifted): (&str, String), + data_type: SnowflakeType, + log: &ProvenanceLog, +) -> Result { + let day = |sql: &str| match data_type { + SnowflakeType::TimestampNtz { precision } => { + truncate_timestamp_to_date(sql, precision, log) + } + _ => sql.to_owned(), + }; + let (before, after) = (day(original), day(&shifted)); + let days = format!( + "CASE WHEN last_day({before}) = {before} \ + THEN datediff('day', {after}, last_day({after})) ELSE 0 END" + ); + date_add_value(&shifted, (DAY_UNIT, &days), data_type, log) +} + /// DATEDIFF(unit, start, end) with a keyword unit. pub(crate) fn date_diff(payload: &Value, site: Site<'_>) -> Result { let construct = node_construct("date_diff"); @@ -953,21 +1076,6 @@ pub(crate) fn temporal_text( )) } -/// Whether a format names only clock fields, HH24, MI, SS and up to six fraction digits. -fn clock_format(written: &str) -> bool { - let mut rest = written; - while !rest.is_empty() { - let Some(field) = CLOCK_FORMAT_FIELDS - .iter() - .find(|field| rest.starts_with(**field)) - else { - return false; - }; - rest = &rest[field.len()..]; - } - true -} - /// TO_CHAR of a NUMBER with a format `FM9...90.0...0` its whole digits always hold. fn number_text( (sql, precision, scale): (&str, u8, u8), @@ -1020,76 +1128,6 @@ fn fixed_number_format(written: &str) -> Option<(u8, u8)> { Some((whole, fraction)) } -/// The strftime pattern of a format of known fields between separators, or None. -fn strftime_pattern(format: &str, precision: Option) -> Option { - let with_time = precision.is_some(); - let upper = format.to_ascii_uppercase(); - let mut rest = upper.as_str(); - let mut pattern = String::new(); - let mut last_letter: Option = None; - let mut previous: Option<&str> = None; - while !rest.is_empty() { - let written = &format[format.len() - rest.len()..]; - if let Some(after) = rest.strip_prefix(BARE_FRACTION) - && !after.starts_with(|next: char| next.is_ascii_digit()) - { - if !adjacency_recorded(previous, BARE_FRACTION) { - return None; - } - let (_, digits) = BARE_FRACTION_PATTERNS - .iter() - .find(|(digits, _)| Some(*digits) == precision)?; - pattern.push_str(digits); - rest = after; - last_letter = None; - previous = Some(BARE_FRACTION); - continue; - } - let field = TEMPORAL_TEXT_FIELDS - .iter() - .find(|(token, _, time)| rest.starts_with(token) && (with_time || !time)); - match field { - Some((token, replacement, _)) => { - if last_letter.is_some_and(|letter| token.starts_with(letter)) - || !adjacency_recorded(previous, token) - || (MONTH_NAME_FIELDS.contains(token) && !written.starts_with(token)) - { - return None; - } - pattern.push_str(replacement); - rest = &rest[token.len()..]; - last_letter = token.chars().last().filter(char::is_ascii_alphabetic); - previous = Some(token); - } - None => { - last_letter = None; - previous = None; - let separator = rest.chars().next()?; - if !TEMPORAL_TEXT_SEPARATORS.contains(separator) { - return None; - } - pattern.push(separator); - rest = &rest[separator.len_utf8()..]; - } - } - } - Some(pattern) -} - -/// Whether `next` may follow the field `previous` with no separator between, as recordings show. -fn adjacency_recorded(previous: Option<&str>, next: &str) -> bool { - match previous { - None => true, - Some(previous) => match MONTH_NAME_FOLLOWERS - .iter() - .find(|(name, _)| *name == previous) - { - Some((_, followers)) => followers.contains(&next), - None => !MONTH_NAME_FIELDS.contains(&next), - }, - } -} - /// The value of up to two decimal digits. fn small_integer(digits: &str) -> Option { if digits.is_empty() || digits.len() > SCALE_DIGITS { diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/windows.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/windows.rs index 9b8676656..86d67174f 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/windows.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/windows.rs @@ -23,6 +23,7 @@ use crate::conversion::_helpers::expressions::named_aggregates::named_aggregate; use crate::conversion::_helpers::expressions::ordered_aggregates::within_group; use crate::conversion::_helpers::expressions::scalar::{call_name, convert_expression}; use crate::conversion::_helpers::expressions::spellings::{as_typed, as_written}; +use crate::conversion::_helpers::expressions::statistics::is_statistic; use crate::conversion::_helpers::support::declared::merged; use crate::conversion::_helpers::support::divergence::diverge; use crate::conversion::_helpers::support::scope::{Context, Emitted}; @@ -124,7 +125,8 @@ pub(crate) fn convert_window(payload: &Value, site: Site<'_>) -> Result WINDOW_FIRST_LAST, "count" | "sum" | "avg" | "min" | "max" | "within_group" => WINDOW_AGGREGATE, "function" | "aggregate_function" - if WINDOWED_NAMED_AGGREGATES.contains(&call_name(function_payload).as_str()) => + if WINDOWED_NAMED_AGGREGATES.contains(&call_name(function_payload).as_str()) + || is_statistic(&call_name(function_payload)) => { WINDOW_AGGREGATE } @@ -182,14 +184,24 @@ pub(crate) fn convert_window(payload: &Value, site: Site<'_>) -> Result ordered_window(function_payload, &over, site), "function" | "aggregate_function" => { let name = call_name(function_payload); + let statistic = is_statistic(&name); if over.frame.is_some_and(|frame| { - name != COUNT_IF_NAME || !is_running(frame) || over.order.is_empty() + let running_count = name == COUNT_IF_NAME && is_running(frame); + let rows = frame.get("kind").and_then(Value::as_str) == Some(ROWS); + !(statistic && rows) && (!running_count || over.order.is_empty()) }) { return Err(outside_conditions( function_construct(&name), format!("{name} over an explicit frame, which no recording shows"), )); } + let distinct = function_payload.get("distinct").and_then(Value::as_bool) == Some(true); + if statistic && distinct && !over.order.is_empty() { + return Err(outside_conditions( + function_construct(&name), + format!("{name}(DISTINCT) over an ordered window, which Snowflake rejects"), + )); + } if UNORDERED_WINDOW_AGGREGATES.contains(&name.as_str()) && !over.order.is_empty() { return Err(outside_conditions( function_construct(&name), diff --git a/crates/sqlquack-rules/src/conversion/constants.rs b/crates/sqlquack-rules/src/conversion/constants.rs index c0a81f28c..8d3a4edb0 100644 --- a/crates/sqlquack-rules/src/conversion/constants.rs +++ b/crates/sqlquack-rules/src/conversion/constants.rs @@ -605,6 +605,27 @@ pub const CASE: &str = "rule.case"; pub const COALESCE: &str = "rule.coalesce"; /// IFF. pub const IFF: &str = "rule.iff"; +/// VARIANCE, VAR_POP and STDDEV of a NUMBER, exact and rounded half up to the recorded scale. +pub const VARIANCE_RULE: &str = "rule.variance"; +/// VARIANCE, VAR_POP and STDDEV of a FLOAT or text, with exact sums. +pub const VARIANCE_FLOAT_RULE: &str = "rule.variance_float"; +/// COVAR_SAMP and COVAR_POP of NUMBER or FLOAT pairs, with exact sums. +pub const COVARIANCE_RULE: &str = "rule.covariance"; +/// ADD_MONTHS of a DATE or timestamp: DATEADD of the rounded months, a month's last day kept. +pub const ADD_MONTHS_RULE: &str = "rule.add_months"; +/// MONTHS_BETWEEN of DATEs and naive timestamps. +pub const MONTHS_BETWEEN_RULE: &str = "rule.months_between"; +/// MONTHS_BETWEEN's recorded type. +pub const MONTHS_BETWEEN_TYPE: SnowflakeType = SnowflakeType::Number { + precision: 27, + scale: 6, +}; +/// The month MONTHS_BETWEEN divides a partial month by: 31 days, in nanoseconds. +pub(crate) const MONTHS_BETWEEN_MONTH_NANOSECONDS: i128 = 31 * 86_400 * 1_000_000_000; +/// The DATEADD unit ADD_MONTHS moves by. +pub(crate) const MONTH_UNIT: &str = "MONTH"; +/// NVL2 of a non-semi-structured value and two branches that unify without reading text. +pub const NVL2_RULE: &str = "rule.nvl2"; /// NULLIF. pub const NULLIF: &str = "rule.nullif"; /// Casts between NUMBER and FLOAT. @@ -879,33 +900,6 @@ pub const TO_NUMBER_PAIR: &str = "to_number_to_cast"; pub const TO_VARCHAR_PAIR: &str = "to_varchar_to_cast"; /// TO_VARCHAR and TO_CHAR of a date or timestamp with a literal format. pub const TEMPORAL_TEXT_FORMAT: &str = "rule.temporal_text_format"; -/// Format fields: the Snowflake token, its strftime spelling, and whether it is a time field. -pub const TEMPORAL_TEXT_FIELDS: &[(&str, &str, bool)] = &[ - ("YYYY", "%Y", false), - ("MMMM", "%B", false), - ("MON", "%b", false), - ("MM", "%m", false), - ("DD", "%d", false), - ("HH24", "%H", true), - ("MI", "%M", true), - ("SS", "%S", true), - ("FF9", "%n", true), - ("FF6", "%f", true), - ("FF3", "%g", true), -]; -/// Fields writing an English month name, recorded only as written in upper case. -pub(crate) const MONTH_NAME_FIELDS: &[&str] = &["MMMM", "MON"]; -/// The fields recorded directly after each month name: none after MON, whose MONMM writes the full name. -pub(crate) const MONTH_NAME_FOLLOWERS: &[(&str, &[&str])] = &[("MON", &[]), ("MMMM", &["DD"])]; -/// The format element writing as many fraction digits as the timestamp's precision. -pub(crate) const BARE_FRACTION: &str = "FF"; -/// What FF writes for each precision recorded: none for 0, then milli-, micro- and nanoseconds. -pub(crate) const BARE_FRACTION_PATTERNS: &[(u8, &str)] = - &[(0, ""), (3, "%g"), (6, "%f"), (9, "%n")]; -/// Snowflake's TIMESTAMP_NTZ output format, YYYY-MM-DD HH24:MI:SS.FF3, as a strftime pattern. -pub const NTZ_OUTPUT_PATTERN: &str = "%Y-%m-%d %H:%M:%S.%g"; -/// Characters a format may hold between fields, written as they are. -pub const TEMPORAL_TEXT_SEPARATORS: &str = "-_/:. "; /// The pair behind converting `TO_DOUBLE` and `TRY_TO_DOUBLE` as a cast to FLOAT. pub const TO_DOUBLE_PAIR: &str = "to_double_to_cast"; /// The pair behind converting `MOD(a, b)` as `a % b`. @@ -1355,10 +1349,6 @@ pub const DOLLAR_STRING_KIND: &str = "dollar_string"; pub const NULL_ARITHMETIC: &str = "rule.null_arithmetic"; /// The precision an untyped NULL widens a sum to, as recorded. pub const NULL_SUM_PRECISION: u8 = 18; -/// The pieces of a TIME format recorded through TO_VARCHAR: clock fields and separators. -pub const CLOCK_FORMAT_FIELDS: &[&str] = &[ - "HH24", "MI", "SS", "FF1", "FF2", "FF3", "FF4", "FF5", "FF6", ":", ".", -]; /// IFF, which passes either branch up as it is. pub const IFF_NAME: &str = "IFF"; /// Text every converted window function holds, which a window cannot hold inside its partition. diff --git a/crates/sqlquack-rules/src/lib.rs b/crates/sqlquack-rules/src/lib.rs index 4c23bf847..121a48d53 100644 --- a/crates/sqlquack-rules/src/lib.rs +++ b/crates/sqlquack-rules/src/lib.rs @@ -5,3 +5,4 @@ pub mod catalogue; pub mod conversion; pub mod session; +pub(crate) mod text_formats; diff --git a/crates/sqlquack-rules/src/text_formats/_helpers/adjacency.rs b/crates/sqlquack-rules/src/text_formats/_helpers/adjacency.rs new file mode 100644 index 000000000..3fb64ad6d --- /dev/null +++ b/crates/sqlquack-rules/src/text_formats/_helpers/adjacency.rs @@ -0,0 +1,60 @@ +//! Which format fields may follow one another with no separator between. + +use crate::text_formats::constants::{ + BARE_FRACTION, BARE_FRACTION_PATTERNS, MONTH_NAME_FIELDS, MONTH_NAME_FOLLOWERS, + TEMPORAL_TEXT_FIELDS, TEMPORAL_TEXT_SEPARATORS, +}; + +/// Whether `next` may follow the field `previous` with no separator between, as recordings show. +pub(crate) fn adjacency_recorded(previous: Option<&str>, next: &str) -> bool { + match previous { + None => true, + Some(previous) => match MONTH_NAME_FOLLOWERS + .iter() + .find(|(name, _)| *name == previous) + { + Some((_, followers)) => followers.contains(&next), + None => !MONTH_NAME_FIELDS.contains(&next), + }, + } +} + +/// What a bare FF writes after `previous` at `precision`, or None where no recording shows it. +pub(crate) fn bare_fraction(previous: Option<&str>, precision: Option) -> Option<&'static str> { + if !adjacency_recorded(previous, BARE_FRACTION) { + return None; + } + BARE_FRACTION_PATTERNS + .iter() + .find(|(digits, _)| Some(*digits) == precision) + .map(|(_, pattern)| *pattern) +} + +/// Whether `token` may stand here, after `previous`, written as recorded (month names upper case). +pub(crate) fn field_recorded( + token: &str, + last_letter: Option, + previous: Option<&str>, + written: &str, +) -> bool { + !(last_letter.is_some_and(|letter| token.starts_with(letter)) + || !adjacency_recorded(previous, token) + || (MONTH_NAME_FIELDS.contains(&token) && !written.starts_with(token))) +} + +/// The field `rest` starts with: its token, strftime spelling and whether it is a time field. +pub(crate) fn field_at( + rest: &str, + with_time: bool, +) -> Option<&'static (&'static str, &'static str, bool)> { + TEMPORAL_TEXT_FIELDS + .iter() + .find(|(token, _, time)| rest.starts_with(token) && (with_time || !time)) +} + +/// The separator `rest` starts with, or None when it starts with no recorded separator. +pub(crate) fn separator_at(rest: &str) -> Option { + rest.chars() + .next() + .filter(|separator| TEMPORAL_TEXT_SEPARATORS.contains(*separator)) +} diff --git a/crates/sqlquack-rules/src/text_formats/_helpers/mod.rs b/crates/sqlquack-rules/src/text_formats/_helpers/mod.rs new file mode 100644 index 000000000..59129057f --- /dev/null +++ b/crates/sqlquack-rules/src/text_formats/_helpers/mod.rs @@ -0,0 +1 @@ +pub(crate) mod adjacency; diff --git a/crates/sqlquack-rules/src/text_formats/constants.rs b/crates/sqlquack-rules/src/text_formats/constants.rs new file mode 100644 index 000000000..ed0e26dad --- /dev/null +++ b/crates/sqlquack-rules/src/text_formats/constants.rs @@ -0,0 +1,33 @@ +//! Format elements: their strftime spellings, the month names, fractions and separators. + +/// Format fields: the Snowflake token, its strftime spelling, and whether it is a time field. +pub(crate) const TEMPORAL_TEXT_FIELDS: &[(&str, &str, bool)] = &[ + ("YYYY", "%Y", false), + ("MMMM", "%B", false), + ("MON", "%b", false), + ("MM", "%m", false), + ("DD", "%d", false), + ("HH24", "%H", true), + ("MI", "%M", true), + ("SS", "%S", true), + ("FF9", "%n", true), + ("FF6", "%f", true), + ("FF3", "%g", true), +]; +/// Fields writing an English month name, recorded only as written in upper case. +pub(crate) const MONTH_NAME_FIELDS: &[&str] = &["MMMM", "MON"]; +/// The fields recorded directly after each month name: none after MON, whose MONMM writes the full name. +pub(crate) const MONTH_NAME_FOLLOWERS: &[(&str, &[&str])] = &[("MON", &[]), ("MMMM", &["DD"])]; +/// The format element writing as many fraction digits as the timestamp's precision. +pub(crate) const BARE_FRACTION: &str = "FF"; +/// What FF writes for each precision recorded: none for 0, then milli-, micro- and nanoseconds. +pub(crate) const BARE_FRACTION_PATTERNS: &[(u8, &str)] = + &[(0, ""), (3, "%g"), (6, "%f"), (9, "%n")]; +/// Snowflake's TIMESTAMP_NTZ output format, YYYY-MM-DD HH24:MI:SS.FF3, as a strftime pattern. +pub(crate) const NTZ_OUTPUT_PATTERN: &str = "%Y-%m-%d %H:%M:%S.%g"; +/// Characters a format may hold between fields, written as they are. +pub(crate) const TEMPORAL_TEXT_SEPARATORS: &str = "-_/:. "; +/// The pieces of a TIME format recorded through TO_VARCHAR: clock fields and separators. +pub(crate) const CLOCK_FORMAT_FIELDS: &[&str] = &[ + "HH24", "MI", "SS", "FF1", "FF2", "FF3", "FF4", "FF5", "FF6", ":", ".", +]; diff --git a/crates/sqlquack-rules/src/text_formats/main/clock_format.rs b/crates/sqlquack-rules/src/text_formats/main/clock_format.rs new file mode 100644 index 000000000..c92160a77 --- /dev/null +++ b/crates/sqlquack-rules/src/text_formats/main/clock_format.rs @@ -0,0 +1,18 @@ +//! `clock_format`: whether a TIME format names only recorded clock fields. + +use crate::text_formats::constants::CLOCK_FORMAT_FIELDS; + +/// Whether a format names only clock fields, HH24, MI, SS and up to six fraction digits. +pub(crate) fn clock_format(written: &str) -> bool { + let mut rest = written; + while !rest.is_empty() { + let Some(field) = CLOCK_FORMAT_FIELDS + .iter() + .find(|field| rest.starts_with(**field)) + else { + return false; + }; + rest = &rest[field.len()..]; + } + true +} diff --git a/crates/sqlquack-rules/src/text_formats/main/mod.rs b/crates/sqlquack-rules/src/text_formats/main/mod.rs new file mode 100644 index 000000000..0e8d35267 --- /dev/null +++ b/crates/sqlquack-rules/src/text_formats/main/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod clock_format; +pub(crate) mod strftime_pattern; diff --git a/crates/sqlquack-rules/src/text_formats/main/strftime_pattern.rs b/crates/sqlquack-rules/src/text_formats/main/strftime_pattern.rs new file mode 100644 index 000000000..ed95c8ef9 --- /dev/null +++ b/crates/sqlquack-rules/src/text_formats/main/strftime_pattern.rs @@ -0,0 +1,47 @@ +//! `strftime_pattern`: a date or timestamp format as a strftime pattern, or None. + +use crate::text_formats::_helpers::adjacency::{ + bare_fraction, field_at, field_recorded, separator_at, +}; +use crate::text_formats::constants::BARE_FRACTION; + +/// The strftime pattern of a format of known fields between separators, or None. +pub(crate) fn strftime_pattern(format: &str, precision: Option) -> Option { + let with_time = precision.is_some(); + let upper = format.to_ascii_uppercase(); + let mut rest = upper.as_str(); + let mut pattern = String::new(); + let mut last_letter: Option = None; + let mut previous: Option<&str> = None; + while !rest.is_empty() { + let written = &format[format.len() - rest.len()..]; + if let Some(after) = rest.strip_prefix(BARE_FRACTION) + && !after.starts_with(|next: char| next.is_ascii_digit()) + { + pattern.push_str(bare_fraction(previous, precision)?); + rest = after; + last_letter = None; + previous = Some(BARE_FRACTION); + continue; + } + match field_at(rest, with_time) { + Some((token, replacement, _)) => { + if !field_recorded(token, last_letter, previous, written) { + return None; + } + pattern.push_str(replacement); + rest = &rest[token.len()..]; + last_letter = token.chars().last().filter(char::is_ascii_alphabetic); + previous = Some(token); + } + None => { + last_letter = None; + previous = None; + let separator = separator_at(rest)?; + pattern.push(separator); + rest = &rest[separator.len_utf8()..]; + } + } + } + Some(pattern) +} diff --git a/crates/sqlquack-rules/src/text_formats/mod.rs b/crates/sqlquack-rules/src/text_formats/mod.rs new file mode 100644 index 000000000..059c0308e --- /dev/null +++ b/crates/sqlquack-rules/src/text_formats/mod.rs @@ -0,0 +1,5 @@ +//! Snowflake date and time format strings, read as the strftime patterns DuckDB writes text with. + +pub(crate) mod _helpers; +pub(crate) mod constants; +pub(crate) mod main; diff --git a/crates/sqlquack/src/analysis/tests/test_coverage_batch.rs b/crates/sqlquack/src/analysis/tests/test_coverage_batch.rs index 6e187592b..a51ff7a43 100644 --- a/crates/sqlquack/src/analysis/tests/test_coverage_batch.rs +++ b/crates/sqlquack/src/analysis/tests/test_coverage_batch.rs @@ -1402,6 +1402,58 @@ fn given_urls_when_converting_parse_url_then_parts_and_parameters_are_read_as_re } } +#[test] +fn given_nvl2_when_converting_then_the_branch_follows_whether_the_first_is_null_or_it_refuses() { + let test_cases = [ + FirstValueTestCase { + description: "the second argument where the first is not NULL", + sql: "SELECT NVL2(1, 'set', 'unset') AS v", + expected_outcome: Ok("set"), + }, + FirstValueTestCase { + description: "the third argument where the first is NULL", + sql: "SELECT NVL2(NULL, 'set', 'unset') AS v", + expected_outcome: Ok("unset"), + }, + FirstValueTestCase { + description: "a NUMBER and a FLOAT branch unify to FLOAT", + sql: "SELECT NVL2(NULL, 1, 2.5::FLOAT) AS v", + expected_outcome: Ok("2.5"), + }, + FirstValueTestCase { + description: "text beside a NUMBER, whose reading no recording shows", + sql: "SELECT NVL2(1, '7', 8) AS v", + expected_outcome: Err("no proven common type"), + }, + FirstValueTestCase { + description: "a semi-structured first argument", + sql: "SELECT NVL2(PARSE_JSON('null'), 1, 2) AS v", + expected_outcome: Err("semi-structured"), + }, + FirstValueTestCase { + description: "four arguments, which Snowflake rejects", + sql: "SELECT NVL2(1, 2, 3, 4) AS v", + expected_outcome: Err("NVL2"), + }, + FirstValueTestCase { + description: "two arguments, which Snowflake rejects", + sql: "SELECT NVL2(1, 2) AS v", + expected_outcome: Err("NVL2"), + }, + ]; + for test_case in test_cases { + assert_eq!( + shop_first_outcome(test_case.sql, test_case.expected_outcome), + test_case + .expected_outcome + .map(str::to_owned) + .map_err(str::to_owned), + "{}", + test_case.description + ); + } +} + #[test] fn given_each_documented_format_element_when_writing_text_then_it_converts_as_recorded_or_refuses() { diff --git a/evidence/results/099308c1bd4e67acacdcd0c066c85c58276b6a341822ad6b82d27cb34e606958.arrow b/evidence/results/099308c1bd4e67acacdcd0c066c85c58276b6a341822ad6b82d27cb34e606958.arrow new file mode 100644 index 000000000..8d11afb8e Binary files /dev/null and b/evidence/results/099308c1bd4e67acacdcd0c066c85c58276b6a341822ad6b82d27cb34e606958.arrow differ diff --git a/evidence/results/099308c1bd4e67acacdcd0c066c85c58276b6a341822ad6b82d27cb34e606958.json b/evidence/results/099308c1bd4e67acacdcd0c066c85c58276b6a341822ad6b82d27cb34e606958.json new file mode 100644 index 000000000..08d8d087e --- /dev/null +++ b/evidence/results/099308c1bd4e67acacdcd0c066c85c58276b6a341822ad6b82d27cb34e606958.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "694f720c7620559391a91df48bfeee2ae2e2010e89778fda6c53f772a405975d", + "case_hash": "099308c1bd4e67acacdcd0c066c85c58276b6a341822ad6b82d27cb34e606958", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "a1bcdbfffc4621116af9a3ee892e1277176c00dfc6be7d21ac94fc88f60bd27b", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/0a497e88e5913300bf33c6efde4a6468260d9502464935759ce5f11b3daa0620.arrow b/evidence/results/0a497e88e5913300bf33c6efde4a6468260d9502464935759ce5f11b3daa0620.arrow new file mode 100644 index 000000000..21a649899 Binary files /dev/null and b/evidence/results/0a497e88e5913300bf33c6efde4a6468260d9502464935759ce5f11b3daa0620.arrow differ diff --git a/evidence/results/0a497e88e5913300bf33c6efde4a6468260d9502464935759ce5f11b3daa0620.json b/evidence/results/0a497e88e5913300bf33c6efde4a6468260d9502464935759ce5f11b3daa0620.json new file mode 100644 index 000000000..a602b0141 --- /dev/null +++ b/evidence/results/0a497e88e5913300bf33c6efde4a6468260d9502464935759ce5f11b3daa0620.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "9a747da48e1ff19933594429191238e321d830d319644c6f4c93dce045e8e1f6", + "case_hash": "0a497e88e5913300bf33c6efde4a6468260d9502464935759ce5f11b3daa0620", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": false, + "precision": 27, + "scale": 6, + "type_code": 0, + "type_name": "FIXED" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "59ddd17718e3facf69be4fbf2c9d5de585ef51ecc7d15c53cee715f644fbf605", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 4, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/2dac89cd88bbc44396c19dd809e7695a058bf92dd79586043bcb675d524d5e18.arrow b/evidence/results/2dac89cd88bbc44396c19dd809e7695a058bf92dd79586043bcb675d524d5e18.arrow new file mode 100644 index 000000000..5b1db6aa8 Binary files /dev/null and b/evidence/results/2dac89cd88bbc44396c19dd809e7695a058bf92dd79586043bcb675d524d5e18.arrow differ diff --git a/evidence/results/2dac89cd88bbc44396c19dd809e7695a058bf92dd79586043bcb675d524d5e18.json b/evidence/results/2dac89cd88bbc44396c19dd809e7695a058bf92dd79586043bcb675d524d5e18.json new file mode 100644 index 000000000..ad443e887 --- /dev/null +++ b/evidence/results/2dac89cd88bbc44396c19dd809e7695a058bf92dd79586043bcb675d524d5e18.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "f2971000f2850ad20a752c62bf528cd8fb055ddebec0a796b7be4797a69360ab", + "case_hash": "2dac89cd88bbc44396c19dd809e7695a058bf92dd79586043bcb675d524d5e18", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "9464296322c817d4faec4a7af874e57550c2706cefa177c8a0182d1f9e5d8e1b", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/32abfb26d0c8d0c1c6cfdf62cd154f45e60471601cbae8c552ebaeccb5d49770.arrow b/evidence/results/32abfb26d0c8d0c1c6cfdf62cd154f45e60471601cbae8c552ebaeccb5d49770.arrow new file mode 100644 index 000000000..bf5b426f0 Binary files /dev/null and b/evidence/results/32abfb26d0c8d0c1c6cfdf62cd154f45e60471601cbae8c552ebaeccb5d49770.arrow differ diff --git a/evidence/results/32abfb26d0c8d0c1c6cfdf62cd154f45e60471601cbae8c552ebaeccb5d49770.json b/evidence/results/32abfb26d0c8d0c1c6cfdf62cd154f45e60471601cbae8c552ebaeccb5d49770.json new file mode 100644 index 000000000..60d768dd9 --- /dev/null +++ b/evidence/results/32abfb26d0c8d0c1c6cfdf62cd154f45e60471601cbae8c552ebaeccb5d49770.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "96a9716431aa8de1821a3b8bd38638d666e61229d2c90c1ef3afa88706fd1c9e", + "case_hash": "32abfb26d0c8d0c1c6cfdf62cd154f45e60471601cbae8c552ebaeccb5d49770", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": 38, + "scale": 6, + "type_code": 0, + "type_name": "FIXED" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "9537bec834fe581a390f6291dbbbcf08c0cb3f10a97fd3258fd78bcc2d34f2a9", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/3f25ef5a06b3655830e93b4ab99ddedf722467bdc706043dba1855a3f9671f7b.arrow b/evidence/results/3f25ef5a06b3655830e93b4ab99ddedf722467bdc706043dba1855a3f9671f7b.arrow new file mode 100644 index 000000000..b9309d6a1 Binary files /dev/null and b/evidence/results/3f25ef5a06b3655830e93b4ab99ddedf722467bdc706043dba1855a3f9671f7b.arrow differ diff --git a/evidence/results/3f25ef5a06b3655830e93b4ab99ddedf722467bdc706043dba1855a3f9671f7b.json b/evidence/results/3f25ef5a06b3655830e93b4ab99ddedf722467bdc706043dba1855a3f9671f7b.json new file mode 100644 index 000000000..ef40a44ad --- /dev/null +++ b/evidence/results/3f25ef5a06b3655830e93b4ab99ddedf722467bdc706043dba1855a3f9671f7b.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "4d1567221ce2cce4d9a7c55af07b1fb7da4ab6b0d58b497f5feb765b0d844cd5", + "case_hash": "3f25ef5a06b3655830e93b4ab99ddedf722467bdc706043dba1855a3f9671f7b", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "3c0739c0ba8a6c79db0efd6751ad81e65876c84ce8a3a450af0ab6d2cb22a7fd", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/42175beaf6e79d91cc3c9c0b0e3bee882c13e5235d0c7171cded8bfcc8f6039a.arrow b/evidence/results/42175beaf6e79d91cc3c9c0b0e3bee882c13e5235d0c7171cded8bfcc8f6039a.arrow new file mode 100644 index 000000000..21823bec2 Binary files /dev/null and b/evidence/results/42175beaf6e79d91cc3c9c0b0e3bee882c13e5235d0c7171cded8bfcc8f6039a.arrow differ diff --git a/evidence/results/42175beaf6e79d91cc3c9c0b0e3bee882c13e5235d0c7171cded8bfcc8f6039a.json b/evidence/results/42175beaf6e79d91cc3c9c0b0e3bee882c13e5235d0c7171cded8bfcc8f6039a.json new file mode 100644 index 000000000..f7ca16a7c --- /dev/null +++ b/evidence/results/42175beaf6e79d91cc3c9c0b0e3bee882c13e5235d0c7171cded8bfcc8f6039a.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "892ec1e4e758450c3746009c108e9b497e8bef866660d12544c24207257928fa", + "case_hash": "42175beaf6e79d91cc3c9c0b0e3bee882c13e5235d0c7171cded8bfcc8f6039a", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": 38, + "scale": 6, + "type_code": 0, + "type_name": "FIXED" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "7ff0bf4af9164a38f67054747a6f1c372d924b5359adb64a80e3e97db5346032", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/456e76029907c2304740f8faf8aba301b7d4c3fd0e58c927ac270314973573d6.arrow b/evidence/results/456e76029907c2304740f8faf8aba301b7d4c3fd0e58c927ac270314973573d6.arrow new file mode 100644 index 000000000..580a76ea0 Binary files /dev/null and b/evidence/results/456e76029907c2304740f8faf8aba301b7d4c3fd0e58c927ac270314973573d6.arrow differ diff --git a/evidence/results/456e76029907c2304740f8faf8aba301b7d4c3fd0e58c927ac270314973573d6.json b/evidence/results/456e76029907c2304740f8faf8aba301b7d4c3fd0e58c927ac270314973573d6.json new file mode 100644 index 000000000..b9c020a3a --- /dev/null +++ b/evidence/results/456e76029907c2304740f8faf8aba301b7d4c3fd0e58c927ac270314973573d6.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "ab294485001c4f806ee452218e5d770eb25b300ed0907fb8d6038002402a10fa", + "case_hash": "456e76029907c2304740f8faf8aba301b7d4c3fd0e58c927ac270314973573d6", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": 38, + "scale": 10, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "b033b93a96346eae4bc6b508029f8f5b3aebb3746276aef753b8a98ec6f18471", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/502b3426fb59b9896c7f33fc08294d78c52cd88d120c50aae51850fb611e8475.arrow b/evidence/results/502b3426fb59b9896c7f33fc08294d78c52cd88d120c50aae51850fb611e8475.arrow new file mode 100644 index 000000000..9aa623efb Binary files /dev/null and b/evidence/results/502b3426fb59b9896c7f33fc08294d78c52cd88d120c50aae51850fb611e8475.arrow differ diff --git a/evidence/results/502b3426fb59b9896c7f33fc08294d78c52cd88d120c50aae51850fb611e8475.json b/evidence/results/502b3426fb59b9896c7f33fc08294d78c52cd88d120c50aae51850fb611e8475.json new file mode 100644 index 000000000..f44303ad5 --- /dev/null +++ b/evidence/results/502b3426fb59b9896c7f33fc08294d78c52cd88d120c50aae51850fb611e8475.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "8d9f51ccb0c3e5524821a4bebdce7d900f38aa77e42fc176c1c295a8dbb0dbc4", + "case_hash": "502b3426fb59b9896c7f33fc08294d78c52cd88d120c50aae51850fb611e8475", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "17d10dce56b90407c45017bb5e18e47c27b8979beef11070dc07d28358c7c40e", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/5ede4a0cc5e10697a9295b31e2984557f240ef1e7365ef46c70efce35eacbb71.arrow b/evidence/results/5ede4a0cc5e10697a9295b31e2984557f240ef1e7365ef46c70efce35eacbb71.arrow new file mode 100644 index 000000000..0de67f8f5 Binary files /dev/null and b/evidence/results/5ede4a0cc5e10697a9295b31e2984557f240ef1e7365ef46c70efce35eacbb71.arrow differ diff --git a/evidence/results/5ede4a0cc5e10697a9295b31e2984557f240ef1e7365ef46c70efce35eacbb71.json b/evidence/results/5ede4a0cc5e10697a9295b31e2984557f240ef1e7365ef46c70efce35eacbb71.json new file mode 100644 index 000000000..aab33cc57 --- /dev/null +++ b/evidence/results/5ede4a0cc5e10697a9295b31e2984557f240ef1e7365ef46c70efce35eacbb71.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "376b8baf826e519f078ae0fb93671229dade5a8916a87159412b4f0b99e82f0d", + "case_hash": "5ede4a0cc5e10697a9295b31e2984557f240ef1e7365ef46c70efce35eacbb71", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "0d73771b6b0b8239400f759900c0ad000eeab08a30254161d7e50019c820aa6d", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/6ef46e4d8df1537126d4962d6461644a083325d6aec4bd3045c3c04e331339da.arrow b/evidence/results/6ef46e4d8df1537126d4962d6461644a083325d6aec4bd3045c3c04e331339da.arrow new file mode 100644 index 000000000..7eb2fa392 Binary files /dev/null and b/evidence/results/6ef46e4d8df1537126d4962d6461644a083325d6aec4bd3045c3c04e331339da.arrow differ diff --git a/evidence/results/6ef46e4d8df1537126d4962d6461644a083325d6aec4bd3045c3c04e331339da.json b/evidence/results/6ef46e4d8df1537126d4962d6461644a083325d6aec4bd3045c3c04e331339da.json new file mode 100644 index 000000000..44d099b44 --- /dev/null +++ b/evidence/results/6ef46e4d8df1537126d4962d6461644a083325d6aec4bd3045c3c04e331339da.json @@ -0,0 +1,79 @@ +{ + "arrow_sha256": "16e82fbeb06392fad1ea6fda6b9d1946200f53c9fb5fa6147b3ff95f68398ab6", + "case_hash": "6ef46e4d8df1537126d4962d6461644a083325d6aec4bd3045c3c04e331339da", + "columns": [ + { + "internal_size": null, + "name": "V", + "nullable": true, + "precision": 38, + "scale": 6, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": null, + "name": "P", + "nullable": true, + "precision": 38, + "scale": 6, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": null, + "name": "S", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "d83cafa25756a6e76aa011c40b6d8515416f29507494e9adce3cd5352511231d", + "recorded_at": "2026-11-06T13:53:43.897300+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/74a21c66ba08e085d86acc7fed71c5b94e6dd92799fa7b6feb41289331ea8614.arrow b/evidence/results/74a21c66ba08e085d86acc7fed71c5b94e6dd92799fa7b6feb41289331ea8614.arrow new file mode 100644 index 000000000..c633009e5 Binary files /dev/null and b/evidence/results/74a21c66ba08e085d86acc7fed71c5b94e6dd92799fa7b6feb41289331ea8614.arrow differ diff --git a/evidence/results/74a21c66ba08e085d86acc7fed71c5b94e6dd92799fa7b6feb41289331ea8614.json b/evidence/results/74a21c66ba08e085d86acc7fed71c5b94e6dd92799fa7b6feb41289331ea8614.json new file mode 100644 index 000000000..0ce99869c --- /dev/null +++ b/evidence/results/74a21c66ba08e085d86acc7fed71c5b94e6dd92799fa7b6feb41289331ea8614.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "b4a7abd299dbf7362643458ee4c7b756890cd776f41233a6f98628ccd2fef01a", + "case_hash": "74a21c66ba08e085d86acc7fed71c5b94e6dd92799fa7b6feb41289331ea8614", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": false, + "precision": 27, + "scale": 6, + "type_code": 0, + "type_name": "FIXED" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "2ace2b939c53e7e7432e21a3b29dd7d1375e2305a9b6de5074b7f3f4ea81f023", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 2, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/76356a69488e7d2ff157faaec04a26b498466b88727498b18c798646499b7039.arrow b/evidence/results/76356a69488e7d2ff157faaec04a26b498466b88727498b18c798646499b7039.arrow new file mode 100644 index 000000000..2f0188bf9 Binary files /dev/null and b/evidence/results/76356a69488e7d2ff157faaec04a26b498466b88727498b18c798646499b7039.arrow differ diff --git a/evidence/results/76356a69488e7d2ff157faaec04a26b498466b88727498b18c798646499b7039.json b/evidence/results/76356a69488e7d2ff157faaec04a26b498466b88727498b18c798646499b7039.json new file mode 100644 index 000000000..63641ccd7 --- /dev/null +++ b/evidence/results/76356a69488e7d2ff157faaec04a26b498466b88727498b18c798646499b7039.json @@ -0,0 +1,88 @@ +{ + "arrow_sha256": "0d37df618c4099348a4ef009fe33e0ea5c47a14037864aee82fa8bf80ec090d4", + "case_hash": "76356a69488e7d2ff157faaec04a26b498466b88727498b18c798646499b7039", + "columns": [ + { + "internal_size": null, + "name": "V", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + }, + { + "internal_size": null, + "name": "P", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + }, + { + "internal_size": null, + "name": "S", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + }, + { + "internal_size": null, + "name": "N", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "a69256a8d928db3f7de91f984112dbbc38c12c7f927758a71320166c1a624eaf", + "recorded_at": "2026-11-06T13:53:43.897300+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/76b7bdaee975a7500d5b430aa695db4765ffc346b545b0bd74b3b52cad4ba2db.arrow b/evidence/results/76b7bdaee975a7500d5b430aa695db4765ffc346b545b0bd74b3b52cad4ba2db.arrow new file mode 100644 index 000000000..a5183d9e8 Binary files /dev/null and b/evidence/results/76b7bdaee975a7500d5b430aa695db4765ffc346b545b0bd74b3b52cad4ba2db.arrow differ diff --git a/evidence/results/76b7bdaee975a7500d5b430aa695db4765ffc346b545b0bd74b3b52cad4ba2db.json b/evidence/results/76b7bdaee975a7500d5b430aa695db4765ffc346b545b0bd74b3b52cad4ba2db.json new file mode 100644 index 000000000..a00c8a0e3 --- /dev/null +++ b/evidence/results/76b7bdaee975a7500d5b430aa695db4765ffc346b545b0bd74b3b52cad4ba2db.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "4ae33509162de3efdf29e33afa349b750e84228ba762e71b88b501e6153da508", + "case_hash": "76b7bdaee975a7500d5b430aa695db4765ffc346b545b0bd74b3b52cad4ba2db", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": 38, + "scale": 10, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "5331dd85b4922133ca51a61b57064dd5375e63e34d185e6b6bfe20ed342d930d", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/7d8894d25792c18162d1633addd9bd8c2c4254527891b50003f63937345e1005.arrow b/evidence/results/7d8894d25792c18162d1633addd9bd8c2c4254527891b50003f63937345e1005.arrow new file mode 100644 index 000000000..a5183d9e8 Binary files /dev/null and b/evidence/results/7d8894d25792c18162d1633addd9bd8c2c4254527891b50003f63937345e1005.arrow differ diff --git a/evidence/results/7d8894d25792c18162d1633addd9bd8c2c4254527891b50003f63937345e1005.json b/evidence/results/7d8894d25792c18162d1633addd9bd8c2c4254527891b50003f63937345e1005.json new file mode 100644 index 000000000..9d90fab6d --- /dev/null +++ b/evidence/results/7d8894d25792c18162d1633addd9bd8c2c4254527891b50003f63937345e1005.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "4ae33509162de3efdf29e33afa349b750e84228ba762e71b88b501e6153da508", + "case_hash": "7d8894d25792c18162d1633addd9bd8c2c4254527891b50003f63937345e1005", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": 38, + "scale": 10, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "32e063a26372c22d7a8d7771e809b70955ad17a456af996379ad0c1afb19db7a", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/7e2aed0b33775d9d70c7a4c89813b57a881ddf42e72d2d5e3210bd75e197a616.arrow b/evidence/results/7e2aed0b33775d9d70c7a4c89813b57a881ddf42e72d2d5e3210bd75e197a616.arrow new file mode 100644 index 000000000..580a76ea0 Binary files /dev/null and b/evidence/results/7e2aed0b33775d9d70c7a4c89813b57a881ddf42e72d2d5e3210bd75e197a616.arrow differ diff --git a/evidence/results/7e2aed0b33775d9d70c7a4c89813b57a881ddf42e72d2d5e3210bd75e197a616.json b/evidence/results/7e2aed0b33775d9d70c7a4c89813b57a881ddf42e72d2d5e3210bd75e197a616.json new file mode 100644 index 000000000..06d934df1 --- /dev/null +++ b/evidence/results/7e2aed0b33775d9d70c7a4c89813b57a881ddf42e72d2d5e3210bd75e197a616.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "ab294485001c4f806ee452218e5d770eb25b300ed0907fb8d6038002402a10fa", + "case_hash": "7e2aed0b33775d9d70c7a4c89813b57a881ddf42e72d2d5e3210bd75e197a616", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": 38, + "scale": 10, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "688b49d44a216dc7210bbee4f23c525252b977dac71408ec6051131a78a9017f", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/80a8eab37ed290d6751d1a9ee288716169fb6bcdfc59c72305ebbb14abe32c68.arrow b/evidence/results/80a8eab37ed290d6751d1a9ee288716169fb6bcdfc59c72305ebbb14abe32c68.arrow new file mode 100644 index 000000000..9aa623efb Binary files /dev/null and b/evidence/results/80a8eab37ed290d6751d1a9ee288716169fb6bcdfc59c72305ebbb14abe32c68.arrow differ diff --git a/evidence/results/80a8eab37ed290d6751d1a9ee288716169fb6bcdfc59c72305ebbb14abe32c68.json b/evidence/results/80a8eab37ed290d6751d1a9ee288716169fb6bcdfc59c72305ebbb14abe32c68.json new file mode 100644 index 000000000..6284ae3f6 --- /dev/null +++ b/evidence/results/80a8eab37ed290d6751d1a9ee288716169fb6bcdfc59c72305ebbb14abe32c68.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "8d9f51ccb0c3e5524821a4bebdce7d900f38aa77e42fc176c1c295a8dbb0dbc4", + "case_hash": "80a8eab37ed290d6751d1a9ee288716169fb6bcdfc59c72305ebbb14abe32c68", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "351d7bebf8ee60b1f3c71bc038b131fa06cb0137c7374acc4b4843fd71555e1d", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/8eac6a94a6457905c7fe6feda9d8269e0e7fcb93dcaa980ff84c2cccc11c1001.arrow b/evidence/results/8eac6a94a6457905c7fe6feda9d8269e0e7fcb93dcaa980ff84c2cccc11c1001.arrow new file mode 100644 index 000000000..e6dd16450 Binary files /dev/null and b/evidence/results/8eac6a94a6457905c7fe6feda9d8269e0e7fcb93dcaa980ff84c2cccc11c1001.arrow differ diff --git a/evidence/results/8eac6a94a6457905c7fe6feda9d8269e0e7fcb93dcaa980ff84c2cccc11c1001.json b/evidence/results/8eac6a94a6457905c7fe6feda9d8269e0e7fcb93dcaa980ff84c2cccc11c1001.json new file mode 100644 index 000000000..759076d38 --- /dev/null +++ b/evidence/results/8eac6a94a6457905c7fe6feda9d8269e0e7fcb93dcaa980ff84c2cccc11c1001.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "702fdfb570fee35a0176af672a6fbfeb9a3204f39678d43399363f758d56372c", + "case_hash": "8eac6a94a6457905c7fe6feda9d8269e0e7fcb93dcaa980ff84c2cccc11c1001", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "df617ed1a85da230c9cbfae929a906a6649b3f636653fb5075d97cc583dcd770", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/b75a59630d3ee20acdd54da6671805e2f4de3e6d91402a1268aedca4cc2d62f4.arrow b/evidence/results/b75a59630d3ee20acdd54da6671805e2f4de3e6d91402a1268aedca4cc2d62f4.arrow new file mode 100644 index 000000000..572a9ef58 Binary files /dev/null and b/evidence/results/b75a59630d3ee20acdd54da6671805e2f4de3e6d91402a1268aedca4cc2d62f4.arrow differ diff --git a/evidence/results/b75a59630d3ee20acdd54da6671805e2f4de3e6d91402a1268aedca4cc2d62f4.json b/evidence/results/b75a59630d3ee20acdd54da6671805e2f4de3e6d91402a1268aedca4cc2d62f4.json new file mode 100644 index 000000000..9dca9a315 --- /dev/null +++ b/evidence/results/b75a59630d3ee20acdd54da6671805e2f4de3e6d91402a1268aedca4cc2d62f4.json @@ -0,0 +1,142 @@ +{ + "arrow_sha256": "107dfda79354e1996828f9f8100f62b072fc3ba391e37c42c5ac5e720c9e06af", + "case_hash": "b75a59630d3ee20acdd54da6671805e2f4de3e6d91402a1268aedca4cc2d62f4", + "columns": [ + { + "internal_size": null, + "name": "VA", + "nullable": true, + "precision": 38, + "scale": 8, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "TA", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": null, + "name": "VB", + "nullable": true, + "precision": 38, + "scale": 12, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "TB", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": null, + "name": "VC", + "nullable": true, + "precision": 38, + "scale": 12, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "TC", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": null, + "name": "VD", + "nullable": true, + "precision": 38, + "scale": 12, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "TD", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": null, + "name": "PB", + "nullable": true, + "precision": 38, + "scale": 12, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "TPB", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "625d1464c0114801d7e453966a10fa5229aeefc14d779122ccddd5243b73ae78", + "recorded_at": "2026-11-06T13:53:43.897300+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/b8d3642d16138d583ba8d4870a496d384af66531ac6ccb683589db095bb47b3a.arrow b/evidence/results/b8d3642d16138d583ba8d4870a496d384af66531ac6ccb683589db095bb47b3a.arrow new file mode 100644 index 000000000..bfdd9bb40 Binary files /dev/null and b/evidence/results/b8d3642d16138d583ba8d4870a496d384af66531ac6ccb683589db095bb47b3a.arrow differ diff --git a/evidence/results/b8d3642d16138d583ba8d4870a496d384af66531ac6ccb683589db095bb47b3a.json b/evidence/results/b8d3642d16138d583ba8d4870a496d384af66531ac6ccb683589db095bb47b3a.json new file mode 100644 index 000000000..e0bd49e52 --- /dev/null +++ b/evidence/results/b8d3642d16138d583ba8d4870a496d384af66531ac6ccb683589db095bb47b3a.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "b20a26365c7db223f0fe5d5a385cafcb0d8f27522bf340dcc034c24dd0aa17a5", + "case_hash": "b8d3642d16138d583ba8d4870a496d384af66531ac6ccb683589db095bb47b3a", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "5d627750226a7e35597705ae02662e8f5949f1de1f7a38f79fd92d9a627579f9", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/c2ac733b842269806829394b1810043d777a96fb247ef8576011b3297d7aeba6.arrow b/evidence/results/c2ac733b842269806829394b1810043d777a96fb247ef8576011b3297d7aeba6.arrow new file mode 100644 index 000000000..ead4d8c0e Binary files /dev/null and b/evidence/results/c2ac733b842269806829394b1810043d777a96fb247ef8576011b3297d7aeba6.arrow differ diff --git a/evidence/results/c2ac733b842269806829394b1810043d777a96fb247ef8576011b3297d7aeba6.json b/evidence/results/c2ac733b842269806829394b1810043d777a96fb247ef8576011b3297d7aeba6.json new file mode 100644 index 000000000..d3d9fb078 --- /dev/null +++ b/evidence/results/c2ac733b842269806829394b1810043d777a96fb247ef8576011b3297d7aeba6.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "fbc3be9a1c1cfbca1e5cd8b3a1048205306cf606f257911c19144699031748c7", + "case_hash": "c2ac733b842269806829394b1810043d777a96fb247ef8576011b3297d7aeba6", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "5f5b9db81437af3ef7a62d896f5f3f0da096c6e5082a4ee718b8f9bcd69b0c38", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/d331d8654ea29993a3bcb618a411a0610acc939afde4f242aef1dd55ea0d0ad0.arrow b/evidence/results/d331d8654ea29993a3bcb618a411a0610acc939afde4f242aef1dd55ea0d0ad0.arrow new file mode 100644 index 000000000..21823bec2 Binary files /dev/null and b/evidence/results/d331d8654ea29993a3bcb618a411a0610acc939afde4f242aef1dd55ea0d0ad0.arrow differ diff --git a/evidence/results/d331d8654ea29993a3bcb618a411a0610acc939afde4f242aef1dd55ea0d0ad0.json b/evidence/results/d331d8654ea29993a3bcb618a411a0610acc939afde4f242aef1dd55ea0d0ad0.json new file mode 100644 index 000000000..8f147df3b --- /dev/null +++ b/evidence/results/d331d8654ea29993a3bcb618a411a0610acc939afde4f242aef1dd55ea0d0ad0.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "892ec1e4e758450c3746009c108e9b497e8bef866660d12544c24207257928fa", + "case_hash": "d331d8654ea29993a3bcb618a411a0610acc939afde4f242aef1dd55ea0d0ad0", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": 38, + "scale": 6, + "type_code": 0, + "type_name": "FIXED" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "5145c18ed9302f9806c48ea619333041d38bf77ff31023d68214f4ebfea61bfe", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/e41e10d93e83728568d14ed4c37d4219b55bc9fd95f8b6078aeff47ee7a5b22f.arrow b/evidence/results/e41e10d93e83728568d14ed4c37d4219b55bc9fd95f8b6078aeff47ee7a5b22f.arrow new file mode 100644 index 000000000..b21681196 Binary files /dev/null and b/evidence/results/e41e10d93e83728568d14ed4c37d4219b55bc9fd95f8b6078aeff47ee7a5b22f.arrow differ diff --git a/evidence/results/e41e10d93e83728568d14ed4c37d4219b55bc9fd95f8b6078aeff47ee7a5b22f.json b/evidence/results/e41e10d93e83728568d14ed4c37d4219b55bc9fd95f8b6078aeff47ee7a5b22f.json new file mode 100644 index 000000000..bda1c3707 --- /dev/null +++ b/evidence/results/e41e10d93e83728568d14ed4c37d4219b55bc9fd95f8b6078aeff47ee7a5b22f.json @@ -0,0 +1,79 @@ +{ + "arrow_sha256": "2b407682e24e59c63a688cb7d949de48efdbfa7f7fdf51145c3226af5d236d7a", + "case_hash": "e41e10d93e83728568d14ed4c37d4219b55bc9fd95f8b6078aeff47ee7a5b22f", + "columns": [ + { + "internal_size": null, + "name": "M1", + "nullable": false, + "precision": null, + "scale": null, + "type_code": 3, + "type_name": "DATE" + }, + { + "internal_size": null, + "name": "P1", + "nullable": false, + "precision": null, + "scale": null, + "type_code": 3, + "type_name": "DATE" + }, + { + "internal_size": null, + "name": "M13", + "nullable": false, + "precision": null, + "scale": null, + "type_code": 3, + "type_name": "DATE" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "8402e2b4098ed8e8d4b723f1f081cb8f04a2299e9016ca07f37221c3c523e88f", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 5, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/e7e52854877fb675bb57c7ec96c34d0579413af28bffd402ce595a3012e80990.arrow b/evidence/results/e7e52854877fb675bb57c7ec96c34d0579413af28bffd402ce595a3012e80990.arrow new file mode 100644 index 000000000..ace484fd6 Binary files /dev/null and b/evidence/results/e7e52854877fb675bb57c7ec96c34d0579413af28bffd402ce595a3012e80990.arrow differ diff --git a/evidence/results/e7e52854877fb675bb57c7ec96c34d0579413af28bffd402ce595a3012e80990.json b/evidence/results/e7e52854877fb675bb57c7ec96c34d0579413af28bffd402ce595a3012e80990.json new file mode 100644 index 000000000..bf9e1a088 --- /dev/null +++ b/evidence/results/e7e52854877fb675bb57c7ec96c34d0579413af28bffd402ce595a3012e80990.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "91e6e5db366e69765de8df0fc0a9ace935d70ea84fa2613a4615714bbe924213", + "case_hash": "e7e52854877fb675bb57c7ec96c34d0579413af28bffd402ce595a3012e80990", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "a744992c1ac0f61ce2d29cdbc7207b6fa18739289978054fc93be594d3f87ad8", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/e910211cf32c35936f8ff38258f5e7be5608738abea4b72c0e46321b961f64b2.arrow b/evidence/results/e910211cf32c35936f8ff38258f5e7be5608738abea4b72c0e46321b961f64b2.arrow new file mode 100644 index 000000000..8d11afb8e Binary files /dev/null and b/evidence/results/e910211cf32c35936f8ff38258f5e7be5608738abea4b72c0e46321b961f64b2.arrow differ diff --git a/evidence/results/e910211cf32c35936f8ff38258f5e7be5608738abea4b72c0e46321b961f64b2.json b/evidence/results/e910211cf32c35936f8ff38258f5e7be5608738abea4b72c0e46321b961f64b2.json new file mode 100644 index 000000000..6afda005c --- /dev/null +++ b/evidence/results/e910211cf32c35936f8ff38258f5e7be5608738abea4b72c0e46321b961f64b2.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "694f720c7620559391a91df48bfeee2ae2e2010e89778fda6c53f772a405975d", + "case_hash": "e910211cf32c35936f8ff38258f5e7be5608738abea4b72c0e46321b961f64b2", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + }, + { + "internal_size": 134217728, + "name": "T", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "3eab6c0a2f5b2272a3922d84c2f6a20ed868fbdb328caf7818135151473e356b", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/ef1805677b87c659ef657c0c48f8cd2e46e4bcf57bdd1a65fcc393629940962e.arrow b/evidence/results/ef1805677b87c659ef657c0c48f8cd2e46e4bcf57bdd1a65fcc393629940962e.arrow new file mode 100644 index 000000000..bf5b426f0 Binary files /dev/null and b/evidence/results/ef1805677b87c659ef657c0c48f8cd2e46e4bcf57bdd1a65fcc393629940962e.arrow differ diff --git a/evidence/results/ef1805677b87c659ef657c0c48f8cd2e46e4bcf57bdd1a65fcc393629940962e.json b/evidence/results/ef1805677b87c659ef657c0c48f8cd2e46e4bcf57bdd1a65fcc393629940962e.json new file mode 100644 index 000000000..3d3715ce2 --- /dev/null +++ b/evidence/results/ef1805677b87c659ef657c0c48f8cd2e46e4bcf57bdd1a65fcc393629940962e.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "96a9716431aa8de1821a3b8bd38638d666e61229d2c90c1ef3afa88706fd1c9e", + "case_hash": "ef1805677b87c659ef657c0c48f8cd2e46e4bcf57bdd1a65fcc393629940962e", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": 38, + "scale": 6, + "type_code": 0, + "type_name": "FIXED" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "78b7ead83e03c5673065a0e104ce5f1a97007ea1b83bc45f460733f001757bf6", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/evidence/results/f4c120779a454f18f99d54580a4bb31687cb682aded35fd77e7547ff977cea97.arrow b/evidence/results/f4c120779a454f18f99d54580a4bb31687cb682aded35fd77e7547ff977cea97.arrow new file mode 100644 index 000000000..5b1db6aa8 Binary files /dev/null and b/evidence/results/f4c120779a454f18f99d54580a4bb31687cb682aded35fd77e7547ff977cea97.arrow differ diff --git a/evidence/results/f4c120779a454f18f99d54580a4bb31687cb682aded35fd77e7547ff977cea97.json b/evidence/results/f4c120779a454f18f99d54580a4bb31687cb682aded35fd77e7547ff977cea97.json new file mode 100644 index 000000000..e93c2dab2 --- /dev/null +++ b/evidence/results/f4c120779a454f18f99d54580a4bb31687cb682aded35fd77e7547ff977cea97.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "f2971000f2850ad20a752c62bf528cd8fb055ddebec0a796b7be4797a69360ab", + "case_hash": "f4c120779a454f18f99d54580a4bb31687cb682aded35fd77e7547ff977cea97", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 1, + "type_name": "REAL" + } + ], + "connector": "snowflake-connector-python 4.7.2", + "duckdb_version": "v2.0.0", + "effective_parameters": { + "BINARY_INPUT_FORMAT": "HEX", + "BINARY_OUTPUT_FORMAT": "HEX", + "DATE_INPUT_FORMAT": "AUTO", + "DATE_OUTPUT_FORMAT": "YYYY-MM-DD", + "DEFAULT_NULL_ORDERING": "LAST", + "GEOGRAPHY_OUTPUT_FORMAT": "GeoJSON", + "GEOMETRY_OUTPUT_FORMAT": "GeoJSON", + "JSON_INDENT": "2", + "QUOTED_IDENTIFIERS_IGNORE_CASE": "false", + "STRICT_JSON_OUTPUT": "false", + "TIMESTAMP_DAY_IS_ALWAYS_24H": "false", + "TIMESTAMP_INPUT_FORMAT": "AUTO", + "TIMESTAMP_LTZ_OUTPUT_FORMAT": "", + "TIMESTAMP_NTZ_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3", + "TIMESTAMP_OUTPUT_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3 TZHTZM", + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMESTAMP_TZ_OUTPUT_FORMAT": "", + "TIMEZONE": "UTC", + "TIME_INPUT_FORMAT": "AUTO", + "TIME_OUTPUT_FORMAT": "HH24:MI:SS", + "TWO_DIGIT_CENTURY_START": "1970", + "USE_CACHED_RESULT": "false", + "WEEK_OF_YEAR_POLICY": "0", + "WEEK_START": "0" + }, + "error": null, + "format": 1, + "outcome": "rows", + "parameters_sha256": "d094d15417903748055eca8fde8cf2884751253939f05ad5ad8d9bf14299ac61", + "query_id_sha256": "3c3c1b20b43e58d2d9774c447ac32f4aff2b2bde9ed8a36b1fc48d75c470ecf7", + "recorded_at": "2026-11-06T13:12:10.222971+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 1, + "session_parameters": { + "DEFAULT_NULL_ORDERING": "LAST", + "QUOTED_IDENTIFIERS_IGNORE_CASE": false, + "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_NTZ", + "TIMEZONE": "UTC", + "USE_CACHED_RESULT": false, + "WEEK_OF_YEAR_POLICY": 0, + "WEEK_START": 0 + }, + "warehouse_version": "10.40.102" +} diff --git a/sqlquack.toml b/sqlquack.toml index c8e85799f..8fa1f25dd 100644 --- a/sqlquack.toml +++ b/sqlquack.toml @@ -302,7 +302,7 @@ minimum_bytes = 4194304 # can return another value. [divergences.numeric_range] -constructs = ["fn:SUM", "fn:AVG", "node:add", "node:sub", "node:mul", "node:div", "node:eq", "node:neq", "node:lt", "node:lte", "node:gt", "node:gte", "node:null_safe_eq", "node:null_safe_neq", "node:in", "fn:EQUAL_NULL", "fn:NULLIF", "node:union", "node:except", "node:intersect", "node:case", "fn:COALESCE", "node:coalesce", "fn:DECODE", "fn:GREATEST", "fn:LEAST", "node:nvl", "fn:NVL2", "fn:IFF", "fn:IFNULL", "fn:ZEROIFNULL", "fn:EXP"] +constructs = ["fn:SUM", "fn:AVG", "node:add", "node:sub", "node:mul", "node:div", "node:eq", "node:neq", "node:lt", "node:lte", "node:gt", "node:gte", "node:null_safe_eq", "node:null_safe_neq", "node:in", "fn:EQUAL_NULL", "fn:NULLIF", "node:union", "node:except", "node:intersect", "node:case", "fn:COALESCE", "node:coalesce", "fn:DECODE", "fn:GREATEST", "fn:LEAST", "node:nvl", "fn:NVL2", "fn:IFF", "fn:IFNULL", "fn:ZEROIFNULL", "fn:EXP", "fn:VARIANCE", "fn:VAR_SAMP", "fn:VAR_POP", "fn:VARIANCE_POP", "fn:STDDEV", "fn:STDDEV_SAMP", "fn:STDDEV_POP"] default = "warn" strict = "refuse" failure = "loud" @@ -434,7 +434,7 @@ failure = "loud" reason = "User decision 2026-10-25: a DATE, TIMESTAMP or TIME inside a VARIANT keeps its type in Snowflake, which DuckDB JSON cannot. The converted SQL stores the JSON string Snowflake writes for the value (batch 8 recorded YYYY-MM-DD, YYYY-MM-DD HH:MI:SS.FFF and a ' Z' suffix for TIMESTAMP_LTZ in UTC), raising where that text drops digits or an offset. TYPEOF and IS_DATE-style reads of a string in such a text raise rather than answer VARCHAR or false. TIMESTAMP_TZ (its offset is not kept), TIME and BINARY (its hex text is indistinguishable from plain strings) stay refused." [divergences.timestamp_range] -constructs = ["node:cast", "node:try_cast", "node:add", "node:sub", "fn:DATEADD", "fn:TIMEADD", "fn:TIMESTAMPADD", "fn:CONVERT_TIMEZONE", "fn:TO_TIMESTAMP", "fn:TO_TIMESTAMP_NTZ", "fn:TRY_TO_TIMESTAMP", "fn:TRY_TO_TIMESTAMP_NTZ", "fn:TRY_TO_TIMESTAMP_TZ", "fn:TIMESTAMP_NTZ_FROM_PARTS", "node:eq", "node:neq", "node:lt", "node:lte", "node:gt", "node:gte", "node:in", "fn:TO_TIMESTAMP_TZ", "fn:TO_TIMESTAMP_LTZ", "fn:TRY_TO_TIMESTAMP_LTZ"] +constructs = ["node:cast", "node:try_cast", "node:add", "node:sub", "fn:DATEADD", "fn:TIMEADD", "fn:TIMESTAMPADD", "fn:ADD_MONTHS", "fn:CONVERT_TIMEZONE", "fn:TO_TIMESTAMP", "fn:TO_TIMESTAMP_NTZ", "fn:TRY_TO_TIMESTAMP", "fn:TRY_TO_TIMESTAMP_NTZ", "fn:TRY_TO_TIMESTAMP_TZ", "fn:TIMESTAMP_NTZ_FROM_PARTS", "node:eq", "node:neq", "node:lt", "node:lte", "node:gt", "node:gte", "node:in", "fn:TO_TIMESTAMP_TZ", "fn:TO_TIMESTAMP_LTZ", "fn:TRY_TO_TIMESTAMP_LTZ"] default = "warn" strict = "refuse" failure = "loud" @@ -463,7 +463,7 @@ failure = "loud" reason = "A REGEXP_LIKE pattern from a column cannot be checked before it runs. Snowflake and RE2 were recorded reading literal characters, '.', groups, alternation, plain bracket expressions, single '*', '+' and '?' and anchors at the ends alike; the converted SQL raises for a pattern with any other syntax, such as escapes, counted repetition, POSIX classes or lazy quantifiers. REGEXP_COUNT and REGEXP_INSTR, and REGEXP_REPLACE and REGEXP_SUBSTR of a column pattern, raise for a pattern that matches empty text, whose empty matches no recording shows; column patterns for REGEXP_REPLACE and REGEXP_SUBSTR are checked as REGEXP_LIKE's are. The failure is loud, never a wrong value." [divergences.float_sum_order] -constructs = ["fn:SUM"] +constructs = ["fn:SUM", "fn:VARIANCE", "fn:VAR_SAMP", "fn:VAR_POP", "fn:VARIANCE_POP", "fn:STDDEV", "fn:STDDEV_SAMP", "fn:STDDEV_POP", "fn:COVAR_SAMP", "fn:COVAR_POP"] default = "warn" strict = "refuse" failure = "loud"