diff --git a/cases/translation/functions/flatten.path.toml b/cases/translation/functions/flatten.path.toml new file mode 100644 index 000000000..535025a17 --- /dev/null +++ b/cases/translation/functions/flatten.path.toml @@ -0,0 +1,39 @@ +category = "translation" +construct = "sf.functions.flatten" +session_profile = "utc-v1" + +[[case]] +id = "t001_object_under_path" +description = "PATH reaching an object: one row per key, with KEY, VALUE and a PATH prefixed with the given path, for a plain key and one with a space. Catches: the prefix joined without a dot, or a quoted key written as a plain one" +columns = [{ name = "a", type = "VARCHAR" }] +rows = [ + ["'{\"x\":{\"y\":{\"b\":1,\"a c\":2}}}'"], +] +query = "SELECT i.ordinal, f.key, f.index, f.value, f.path FROM input i, LATERAL FLATTEN(INPUT => PARSE_JSON(i.a), PATH => 'x.y') f ORDER BY i.ordinal, f.key" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t002_path_key_case" +description = "PATH keys match case-sensitively: 'Items' finds nothing where the key is items, and one-step 'items' reaches the array. Catches: keys matched ignoring case" +columns = [{ name = "a", type = "VARCHAR" }] +rows = [ + ["'{\"items\":[10,20]}'"], +] +query = "SELECT 'lower' AS k, f.index, f.value, f.path FROM input i, LATERAL FLATTEN(INPUT => PARSE_JSON(i.a), PATH => 'items') f UNION ALL SELECT 'upper', f.index, f.value, f.path FROM input i, LATERAL FLATTEN(INPUT => PARSE_JSON(i.a), PATH => 'Items') f ORDER BY 1, 2" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t003_scalar_and_null_at_path" +description = "PATH reaching a scalar, a JSON null and an empty array gives no rows. Catches: a scalar flattened into one row, or a JSON null giving a row" +columns = [{ name = "a", type = "VARCHAR" }] +rows = [ + ["'{\"x\":5}'"], + ["'{\"x\":null}'"], + ["'{\"x\":[]}'"], + ["'{\"x\":[7]}'"], +] +query = "SELECT i.ordinal, f.index, f.value, f.path FROM input i, LATERAL FLATTEN(INPUT => PARSE_JSON(i.a), PATH => 'x') f ORDER BY i.ordinal, f.index" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/pow.power-of-two.toml b/cases/translation/functions/pow.power-of-two.toml new file mode 100644 index 000000000..048e07077 --- /dev/null +++ b/cases/translation/functions/pow.power-of-two.toml @@ -0,0 +1,57 @@ +category = "translation" +construct = "sf.functions.pow.power" +session_profile = "utc-v1" + +[[case]] +id = "t001_whole_exponents" +description = "POWER(2, n) for whole exponents from -52 to 64, as dbt_utils.date_spine writes it for each bit. Catches: an inexact power of two, an integer result, or a lost low bit past 2^53" +columns = [{ name = "n", type = "NUMBER(38,0)" }] +rows = [ + ["0"], ["1"], ["2"], ["3"], ["4"], ["5"], ["6"], ["7"], ["8"], ["9"], ["10"], ["11"], + ["31"], ["32"], ["52"], ["53"], ["62"], ["63"], ["64"], + ["-1"], ["-2"], ["-52"], +] +query = "SELECT POWER(2, n) AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t002_literal_exponents_in_a_sum" +description = "The dbt_utils.date_spine shape: a NUMBER times POWER(2, k) for literal k, summed, plus 1. Catches: the result typed NUMBER instead of FLOAT, or a power other than 2^k" +columns = [{ name = "a", type = "NUMBER(38,0)" }, { name = "b", type = "NUMBER(38,0)" }] +rows = [ + ["0", "0"], + ["1", "0"], + ["1", "1"], + ["NULL", "1"], +] +query = "SELECT a * POWER(2, 0) + b * POWER(2, 1) + 1 AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t003_range_edges" +description = "The largest and smallest finite powers of two in a double, 2^1023 and 2^-1074, and 2^-1075 below the smallest. Catches: 2^1023 overflowing, or the subnormal 2^-1074 flushed to 0" +columns = [{ name = "n", type = "NUMBER(38,0)" }] +rows = [["1023"], ["-1074"], ["-1075"]] +query = "SELECT POWER(2, n) AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t004_overflow" +description = "2^1024, past the largest double. Catches: a finite value or an error where Snowflake gives its overflow result" +columns = [{ name = "n", type = "NUMBER(38,0)" }] +rows = [["1024"]] +query = "SELECT POWER(2, n) AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t005_null_exponent" +description = "POWER(2, NULL). Catches: 1 or 2 returned instead of NULL" +columns = [{ name = "n", type = "NUMBER(38,0)" }] +rows = [["NULL"], ["3"]] +query = "SELECT POWER(2, n) AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["null"] diff --git a/cases/translation/functions/regexp-substr.empty-match-position.toml b/cases/translation/functions/regexp-substr.empty-match-position.toml new file mode 100644 index 000000000..0603193bd --- /dev/null +++ b/cases/translation/functions/regexp-substr.empty-match-position.toml @@ -0,0 +1,16 @@ +category = "translation" +construct = "sf.functions.regexp-substr" +session_profile = "utc-v1" + +[[case]] +id = "t001_empty_match_at_and_past_the_end" +description = "REGEXP_SUBSTR(a, 'x*', n) on 'abc' with n at the last character, one past it and two past it, where 'x*' matches the empty string. Catches: '' where Snowflake gives NULL, or an error past the end where Snowflake answers" +columns = [{ name = "a", type = "VARCHAR" }, { name = "n", type = "NUMBER(38,0)" }] +rows = [ + ["'abc'", "3"], + ["'abc'", "4"], + ["'abc'", "5"], +] +query = "SELECT n, REGEXP_SUBSTR(a, 'x*', n) AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] diff --git a/cases/translation/functions/to-char.month-names.toml b/cases/translation/functions/to-char.month-names.toml new file mode 100644 index 000000000..d9c52e7be --- /dev/null +++ b/cases/translation/functions/to-char.month-names.toml @@ -0,0 +1,56 @@ +category = "translation" +construct = "sf.functions.to-char.to-char" +session_profile = "utc-v1" + +[[case]] +id = "t001_mon_every_month" +description = "TO_CHAR(date, 'MON') for a date in every month, as dbt_date.get_date_dimension writes month_name_short. Catches: the month number written, the wrong letter case, or a locale's abbreviation" +columns = [{ name = "d", type = "DATE" }] +rows = [ + ["'2024-01-15'"], ["'2024-02-29'"], ["'2024-03-15'"], ["'2024-04-15'"], ["'2024-05-15'"], ["'2024-06-15'"], + ["'2024-07-15'"], ["'2024-08-15'"], ["'2024-09-15'"], ["'2024-10-15'"], ["'2024-11-15'"], ["'2024-12-31'"], +] +query = "SELECT TO_CHAR(d, 'MON') AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t002_mmmm_every_month" +description = "TO_CHAR(date, 'MMMM') for a date in every month, as dbt_date.get_date_dimension writes month_name. Catches: MMMM read as MM twice ('0101'), the wrong letter case, or an abbreviation" +columns = [{ name = "d", type = "DATE" }] +rows = [ + ["'2024-01-15'"], ["'2024-02-29'"], ["'2024-03-15'"], ["'2024-04-15'"], ["'2024-05-15'"], ["'2024-06-15'"], + ["'2024-07-15'"], ["'2024-08-15'"], ["'2024-09-15'"], ["'2024-10-15'"], ["'2024-11-15'"], ["'2024-12-31'"], +] +query = "SELECT TO_CHAR(d, 'MMMM') AS r FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t003_month_names_in_a_format" +description = "MON and MMMM beside other fields and on a timestamp. Catches: a field next to the name misread, or the timestamp's time leaking into the name" +columns = [{ name = "d", type = "DATE" }, { name = "t", type = "TIMESTAMP_NTZ(9)" }] +rows = [ + ["'2024-09-05'", "'2024-05-01 23:59:59'"], +] +query = "SELECT TO_CHAR(d, 'DD MON YYYY') AS a, TO_CHAR(d, 'MMMM DD, YYYY') AS b, TO_CHAR(t, 'MON') AS c, TO_CHAR(t, 'MMMM') AS e FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] + +[[case]] +id = "t004_null" +description = "A NULL date. Catches: a month name for NULL" +columns = [{ name = "d", type = "DATE" }] +rows = [["NULL"], ["'2024-03-01'"]] +query = "SELECT TO_CHAR(d, 'MON') AS a, TO_CHAR(d, 'MMMM') AS b FROM input ORDER BY ordinal" +order = "ordered" +tags = ["null"] + +[[case]] +id = "t007_names_beside_month_and_day" +description = "MONMM and MMMMDD, a name directly before another field. Catches: the name's letters read as part of the next field" +columns = [{ name = "d", type = "DATE" }] +rows = [["'2024-09-05'"]] +query = "SELECT TO_CHAR(d, 'MONMM') AS a, TO_CHAR(d, 'MMMMDD') AS b FROM input ORDER BY ordinal" +order = "ordered" +tags = ["type-combination"] diff --git a/coverage/translation/results-baseline.json b/coverage/translation/results-baseline.json index c891a50dd..9101a26fd 100644 --- a/coverage/translation/results-baseline.json +++ b/coverage/translation/results-baseline.json @@ -6919,7 +6919,7 @@ "semi-structured/flatten_outer.toml#flatten_top_level_outer_plain": "matching", "semi-structured/flatten_outer.toml#flatten_top_level_outer_recursive": "refused", "semi-structured/flatten_outer.toml#lateral_subquery_without_rows": "matching", - "semi-structured/flatten_recursive.toml#flatten_path_option": "refused", + "semi-structured/flatten_recursive.toml#flatten_path_option": "matching", "semi-structured/flatten_recursive.toml#flatten_recursive": "matching", "semi-structured/flatten_recursive.toml#flatten_recursive_deep": "matching", "semi-structured/flatten_recursive.toml#flatten_recursive_filtered": "matching", @@ -9388,8 +9388,11 @@ "translation/functions/first-value.toml#t002_ignore_nulls": "matching", "translation/functions/first-value.toml#t003_frame": "matching", "translation/functions/first-value.toml#t004_null_expr": "matching", + "translation/functions/flatten.path.toml#t001_object_under_path": "matching", + "translation/functions/flatten.path.toml#t002_path_key_case": "matching", + "translation/functions/flatten.path.toml#t003_scalar_and_null_at_path": "matching", "translation/functions/flatten.toml#t001_default": "matching", - "translation/functions/flatten.toml#t002_path": "refused", + "translation/functions/flatten.toml#t002_path": "matching", "translation/functions/flatten.toml#t003_outer": "matching", "translation/functions/flatten.toml#t004_recursive": "matching", "translation/functions/flatten.toml#t005_mode": "matching", @@ -10228,6 +10231,11 @@ "translation/functions/pow.pow.toml#t007_overflow_inf": "refused", "translation/functions/pow.pow.toml#t008_neg_base": "refused", "translation/functions/pow.pow.toml#t009_neg_frac": "refused", + "translation/functions/pow.power-of-two.toml#t001_whole_exponents": "matching", + "translation/functions/pow.power-of-two.toml#t002_literal_exponents_in_a_sum": "matching", + "translation/functions/pow.power-of-two.toml#t003_range_edges": "matching", + "translation/functions/pow.power-of-two.toml#t004_overflow": "matching", + "translation/functions/pow.power-of-two.toml#t005_null_exponent": "matching", "translation/functions/pow.power.toml#t001_int": "refused", "translation/functions/pow.power.toml#t002_dec": "refused", "translation/functions/pow.power.toml#t003_float": "refused", @@ -10320,6 +10328,7 @@ "translation/functions/regexp-substr-all.toml#t009_null_regex_parameters": "refused", "translation/functions/regexp-substr-all.toml#t010_null_group_num": "refused", "translation/functions/regexp-substr-all.toml#t011_empty": "matching", + "translation/functions/regexp-substr.empty-match-position.toml#t001_empty_match_at_and_past_the_end": "refused", "translation/functions/regexp-substr.toml#t001_varchar": "matching", "translation/functions/regexp-substr.toml#t002_position_occurrence": "refused", "translation/functions/regexp-substr.toml#t003_group": "refused", @@ -11155,13 +11164,18 @@ "translation/functions/to-boolean.toml#t003_invalid_string": "matching_error", "translation/functions/to-boolean.toml#t004_nan": "refused", "translation/functions/to-boolean.toml#t005_null_string_or_numeric_expr": "matching", + "translation/functions/to-char.month-names.toml#t001_mon_every_month": "matching", + "translation/functions/to-char.month-names.toml#t002_mmmm_every_month": "matching", + "translation/functions/to-char.month-names.toml#t003_month_names_in_a_format": "refused", + "translation/functions/to-char.month-names.toml#t004_null": "matching", + "translation/functions/to-char.month-names.toml#t007_names_beside_month_and_day": "refused", "translation/functions/to-char.to-char.toml#t001_number_format": "refused", - "translation/functions/to-char.to-char.toml#t002_date_format": "refused", + "translation/functions/to-char.to-char.toml#t002_date_format": "matching", "translation/functions/to-char.to-char.toml#t003_binary_format": "refused", "translation/functions/to-char.to-char.toml#t004_variant": "refused", "translation/functions/to-char.to-char.toml#t005_null_expr": "matching", "translation/functions/to-char.to-varchar.toml#t001_number_format": "refused", - "translation/functions/to-char.to-varchar.toml#t002_date_format": "refused", + "translation/functions/to-char.to-varchar.toml#t002_date_format": "matching", "translation/functions/to-char.to-varchar.toml#t003_binary_format": "refused", "translation/functions/to-char.to-varchar.toml#t004_variant": "matching", "translation/functions/to-char.to-varchar.toml#t005_null_expr": "matching", diff --git a/crates/sqlquack-rules/src/catalogue/constants.rs b/crates/sqlquack-rules/src/catalogue/constants.rs index 956582135..2ea64640b 100644 --- a/crates/sqlquack-rules/src/catalogue/constants.rs +++ b/crates/sqlquack-rules/src/catalogue/constants.rs @@ -904,7 +904,7 @@ pub const RULES: &[RuleSpec] = &[ RuleSpec { id: POWER_RULE, constructs: &["fn:POWER"], - conditions: "POWER of the constant 10 to a whole NUMBER exponent, as the FLOAT nearest the power, ties to even, as recorded from 10^-3 to 10^38 (10^23 is the tie DuckDB's pow rounds the other way); far out of range inf or 0. NULL is NULL. Other bases refuse: DuckDB's pow is not correctly rounded, and no recording shows Snowflake's rounding.", + conditions: "POWER of the constant 10 to a whole NUMBER exponent, as the FLOAT nearest the power, ties to even, as recorded from 10^-3 to 10^38 (10^23 is the tie DuckDB's pow rounds the other way); far out of range inf or 0. NULL is NULL. POWER of the constant 2 to a whole NUMBER exponent is the exact power of two a double holds, from 2^-1074 to 2^1023, as recorded; NULL is NULL. Other bases refuse: DuckDB's pow is not correctly rounded, and no recording shows Snowflake's rounding.", failures: &[], }, RuleSpec { @@ -993,7 +993,7 @@ pub const RULES: &[RuleSpec] = &[ RuleSpec { id: FLATTEN_RULE, constructs: &["node:lateral", "fn:FLATTEN"], - conditions: "LATERAL FLATTEN of a VARIANT input after another FROM source or after JOIN ... ON clauses, as a comma or CROSS JOIN source, with OUTER => a boolean literal at most: INDEX and PATH [i] for array elements, KEY and PATH for object keys (raising for keys that are not plain names), VALUE and THIS; scalars, JSON null and NULL give no rows. Under OUTER => TRUE an input with no rows gives one row: PATH '' and THIS the input for an empty container MODE takes, every column NULL otherwise (JSON null, NULL, a missing path, a scalar, a kind MODE skips), as recorded. MODE => 'ARRAY' or 'OBJECT' without RECURSIVE takes only that kind. RECURSIVE => TRUE walks every depth with keys in byte order, writing a key of letters, digits, `_`, spaces and dots that is not a plain name as ['key'] and raising for any other, MODE => 'BOTH', 'OBJECT' or 'ARRAY' choosing what it descends into, a scalar input giving one row of itself under BOTH and raising under OBJECT or ARRAY; RECURSIVE with OUTER, SEQ and PATH => are not converted.", + conditions: "LATERAL FLATTEN of a VARIANT input after another FROM source or after JOIN ... ON clauses, as a comma or CROSS JOIN source, with OUTER => a boolean literal at most: INDEX and PATH [i] for array elements, KEY and PATH for object keys (raising for keys that are not plain names), VALUE and THIS; scalars, JSON null and NULL give no rows. Under OUTER => TRUE an input with no rows gives one row: PATH '' and THIS the input for an empty container MODE takes, every column NULL otherwise (JSON null, NULL, a missing path, a scalar, a kind MODE skips), as recorded. MODE => 'ARRAY' or 'OBJECT' without RECURSIVE takes only that kind. RECURSIVE => TRUE walks every depth with keys in byte order, writing a key of letters, digits, `_`, spaces and dots that is not a plain name as ['key'] and raising for any other, MODE => 'BOTH', 'OBJECT' or 'ARRAY' choosing what it descends into, a scalar input giving one row of itself under BOTH and raising under OBJECT or ARRAY; PATH => a literal of dot-separated plain keys flattens the value at that path, PATH prefixed with it ('x.y[0]'), a missing path giving no rows, as recorded; other PATHs, PATH with RECURSIVE or OUTER, RECURSIVE with OUTER, and SEQ are not converted.", failures: &[], }, RuleSpec { @@ -1169,7 +1169,7 @@ pub const RULES: &[RuleSpec] = &[ RuleSpec { id: TEMPORAL_TEXT_FORMAT, constructs: &["fn:TO_VARCHAR", "fn:TO_CHAR"], - conditions: "A TIME and a format of only HH24, MI, SS and FF1 to FF6 fields, truncating, as recorded; a DATE or TIMESTAMP_NTZ and a literal format of YYYY, MM and DD and, for timestamps, HH24, MI, SS and FF, FF3, FF6 and FF9 fields (each truncating, as recorded; FF writes as many digits as the TIMESTAMP_NTZ precision, recorded for 0, 3, 6 and 9), in any case, between the separators - _ / : . and space: each field zero-padded, as strftime writes it.", + conditions: "A TIME and a format of only HH24, MI, SS and FF1 to FF6 fields, truncating, as recorded; a DATE or TIMESTAMP_NTZ and a literal format of YYYY, MM and DD and, for timestamps, HH24, MI, SS and FF, FF3, FF6 and FF9 fields (each truncating, as recorded; FF writes as many digits as the TIMESTAMP_NTZ precision, recorded for 0, 3, 6 and 9), in any case, between the separators - _ / : . and space: each field zero-padded, as strftime writes it. MON and MMMM, written in upper case, write the English month's abbreviation (Jan) and full name (January) in title case, as recorded for every month. MMMM directly before DD writes the name then the day (MMMMDD is September05), as recorded. A format where two adjacent fields would spell a longer run of one letter (MMMMMM, DDDD, SSSS), where a field follows MON directly (MONMM writes the full name, as recorded), where a field other than DD follows MMMM directly, or where a month name directly follows another field, is not converted, nor any element other than these.", failures: &[], }, RuleSpec { diff --git a/crates/sqlquack-rules/src/conversion/_helpers/expressions/numeric_functions.rs b/crates/sqlquack-rules/src/conversion/_helpers/expressions/numeric_functions.rs index 41da7c1d1..d2ff42418 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/numeric_functions.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/numeric_functions.rs @@ -21,7 +21,8 @@ use crate::conversion::_helpers::support::site::Site; use crate::conversion::constants::{ BITWISE, HALF_AWAY_FROM_ZERO, HALF_TO_EVEN, LN_NAME, LOGARITHM, NUMERIC_FUNCTION, POWER_BASE, - POWER_RULE, ROUND_FUNCTION, ROUND_WITH_MODE_ARGUMENTS, ROUNDING, SIGN_RULE, SQRT_NAME, + POWER_BASE_TWO, POWER_RULE, ROUND_FUNCTION, ROUND_WITH_MODE_ARGUMENTS, ROUNDING, SIGN_RULE, + SQRT_NAME, }; use sqlquack_policy::policy::constants::NUMERIC_RANGE; @@ -86,7 +87,7 @@ pub(crate) fn logarithm( Ok(Emitted::new(sql, SnowflakeType::Float)) } -/// POWER(10, n) of a whole NUMBER exponent, as the FLOAT nearest the power; other bases refuse. +/// POWER(10, n) or POWER(2, n) of a whole NUMBER exponent, as a FLOAT; other bases refuse. pub(crate) fn power( arguments: &[Value], construct: &Construct, @@ -98,19 +99,27 @@ pub(crate) fn power( return Err(refuse("POWER with these arguments".to_owned())); }; let base = convert_expression(base, site)?; - if base.literal != Some(Literal::Number(POWER_BASE.to_owned())) { + let two = base.literal == Some(Literal::Number(POWER_BASE_TWO.to_owned())); + if base.literal != Some(Literal::Number(POWER_BASE.to_owned())) && !two { return Err(refuse( - "POWER of a base other than the constant 10, whose rounding no recording shows" + "POWER of a base other than the constant 10 or 2, whose rounding no recording shows" .to_owned(), )); } let exponent = convert_expression(exponent, site)?; - match exponent.data_type { - SnowflakeType::Number { scale: 0, .. } | SnowflakeType::Null => Ok(Emitted::new( + match (exponent.data_type, two) { + (SnowflakeType::Number { scale: 0, .. } | SnowflakeType::Null, true) => Ok(Emitted::new( + format!("pow(CAST(2 AS DOUBLE), CAST({} AS DOUBLE))", exponent.sql), + SnowflakeType::Float, + )), + (SnowflakeType::Number { scale: 0, .. } | SnowflakeType::Null, false) => Ok(Emitted::new( power_of_ten(&exponent.sql, site.context.log), SnowflakeType::Float, )), - other => Err(refuse(format!("POWER(10, n) of a {other} exponent"))), + (other, _) => Err(refuse(format!( + "POWER({}, n) of a {other} exponent", + if two { POWER_BASE_TWO } else { POWER_BASE } + ))), } } 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 3cee47429..37b8073a9 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/expressions/temporal_functions.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/expressions/temporal_functions.rs @@ -61,11 +61,12 @@ 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, FRACTIONAL_DATE_AMOUNT, FROM_PARTS, LAST_DAY_RULE, MAX_FRACTION_DIGITS_U8, MICROSECOND_DIGITS, - 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, 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, + 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, + 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 sqlquack_duckdb::raises::main::raised::raised; use sqlquack_policy::policy::constants::{ @@ -1024,15 +1025,23 @@ fn strftime_pattern(format: &str, precision: Option) -> Option { 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 @@ -1040,10 +1049,20 @@ fn strftime_pattern(format: &str, precision: Option) -> Option { .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; @@ -1056,6 +1075,20 @@ fn strftime_pattern(format: &str, precision: Option) -> Option { 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/queries/flatten.rs b/crates/sqlquack-rules/src/conversion/_helpers/queries/flatten.rs index 48fe37a56..817742496 100644 --- a/crates/sqlquack-rules/src/conversion/_helpers/queries/flatten.rs +++ b/crates/sqlquack-rules/src/conversion/_helpers/queries/flatten.rs @@ -75,6 +75,7 @@ pub(crate) fn lateral_flatten( keep_empty, recursive, mode, + path, } = arguments(call, &function)?; let scope = Scope::new(earlier.to_vec(), outer); let site = Site { @@ -97,10 +98,27 @@ pub(crate) fn lateral_flatten( diverge(context, JSON_FIDELITY, &function)?; let log = context.log; let json = read_json(&input, context); + let json = match path.is_empty() { + true => json, + false => format!( + "json_extract({json}, '${}')", + path.iter() + .map(|key| format!(".\"{key}\"")) + .collect::() + ), + }; let rows = match (recursive, mode) { (true, mode) => json_flatten_recursive(&json, mode, log), (false, mode) => json_flatten(&json, (mode, keep_empty), log), }; + let rows = match path.join(".") { + prefix if prefix.is_empty() => rows, + prefix => format!( + "SELECT \"INDEX\", \"KEY\", CASE WHEN starts_with(\"PATH\", '[') \ + THEN '{prefix}' || \"PATH\" ELSE '{prefix}.' || \"PATH\" END AS \"PATH\", \ + \"VALUE\", \"THIS\" FROM ({rows})" + ), + }; let flattened = format!("LATERAL ({rows}) AS {}", quoted_identifier(&alias, log)); let sql = format!(" CROSS JOIN {flattened}"); let columns: Vec = FLATTEN_COLUMNS @@ -126,21 +144,23 @@ pub(crate) fn lateral_flatten( }) } -/// A FLATTEN call's input, OUTER and RECURSIVE flags, and MODE. +/// A FLATTEN call's input, OUTER and RECURSIVE flags, MODE and PATH keys. struct Arguments<'a> { input: &'a Value, keep_empty: bool, recursive: bool, mode: FlattenMode, + path: Vec, } -/// The input, OUTER, RECURSIVE and MODE; PATH and OUTER with RECURSIVE are refused. +/// The input, OUTER, RECURSIVE, MODE and a PATH of dotted keys; OUTER with RECURSIVE or PATH is refused. fn arguments<'a>(call: &'a Payload, construct: &Construct) -> Result, Refusal> { let refuse = |reason: String| outside_conditions(construct.clone(), reason); let mut input: Option<&Value> = None; let mut keep_empty = false; let mut recursive = false; let mut mode: Option = None; + let mut path: Vec = Vec::new(); for (position, argument) in list(call, "args").iter().enumerate() { let Some(named) = argument.get("named_argument") else { if position > 0 { @@ -179,21 +199,50 @@ fn arguments<'a>(call: &'a Payload, construct: &Construct) -> Result return Err(refuse("a MODE other than a literal mode".to_owned())), }); } + "PATH" => { + let written = value + .get("literal") + .and_then(|literal| literal.get("value")) + .and_then(Value::as_str) + .unwrap_or_default(); + path = written.split('.').map(str::to_owned).collect(); + if !path.iter().all(|key| plain_key(key)) { + return Err(refuse( + "a PATH other than literal dot-separated keys, which no recording shows" + .to_owned(), + )); + } + } other => return Err(refuse(format!("FLATTEN with {other}"))), } } if recursive && keep_empty { return Err(refuse("FLATTEN with RECURSIVE and OUTER".to_owned())); } + if !path.is_empty() && (recursive || keep_empty) { + return Err(refuse( + "FLATTEN with PATH and RECURSIVE or OUTER, which no recording shows".to_owned(), + )); + } let input = input.ok_or_else(|| refuse("FLATTEN without an input".to_owned()))?; Ok(Arguments { input, keep_empty, recursive, mode: mode.unwrap_or(FlattenMode::Both), + path, }) } +/// Whether a PATH step is a key needing no quotes: a letter or `_`, then letters, digits or `_`. +fn plain_key(key: &str) -> bool { + let mut characters = key.chars(); + characters + .next() + .is_some_and(|first| first.is_ascii_alphabetic() || first == '_') + && characters.all(|next| next.is_ascii_alphanumeric() || next == '_') +} + /// The value of a boolean literal. fn boolean_literal(value: &Value) -> Option { value diff --git a/crates/sqlquack-rules/src/conversion/constants.rs b/crates/sqlquack-rules/src/conversion/constants.rs index 006eb3e0f..c0a81f28c 100644 --- a/crates/sqlquack-rules/src/conversion/constants.rs +++ b/crates/sqlquack-rules/src/conversion/constants.rs @@ -882,6 +882,8 @@ 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), @@ -891,6 +893,10 @@ pub const TEMPORAL_TEXT_FIELDS: &[(&str, &str, bool)] = &[ ("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. @@ -1272,8 +1278,10 @@ pub const NULL_IF_ZERO_RULE: &str = "rule.null_if_zero"; pub const LOGARITHM: &str = "rule.logarithm"; /// POWER(10, n) of a whole exponent. pub const POWER_RULE: &str = "rule.power"; -/// The one base POWER converts, as its literal is written. +/// The base POWER converts as the FLOAT nearest the power, as its literal is written. pub(crate) const POWER_BASE: &str = "10"; +/// The other POWER base converted: 2, whose whole powers a double holds exactly. +pub(crate) const POWER_BASE_TWO: &str = "2"; /// The natural logarithm's name, beside EXP. pub(crate) const LN_NAME: &str = "LN"; /// ARRAY_SORT of one array. diff --git a/crates/sqlquack/src/analysis/tests/test_coverage_batch.rs b/crates/sqlquack/src/analysis/tests/test_coverage_batch.rs index bf4bad852..750ad4fad 100644 --- a/crates/sqlquack/src/analysis/tests/test_coverage_batch.rs +++ b/crates/sqlquack/src/analysis/tests/test_coverage_batch.rs @@ -820,7 +820,7 @@ fn given_powers_of_ten_when_converting_power_then_the_nearest_double_is_kept() { }, FirstValueTestCase { description: "another base refuses", - sql: "SELECT POWER(2, 3) AS v", + sql: "SELECT POWER(3, 3) AS v", expected_outcome: Err("other than the constant 10"), }, FirstValueTestCase { @@ -1386,3 +1386,266 @@ fn given_urls_when_converting_parse_url_then_parts_and_parameters_are_read_as_re ); } } + +#[test] +fn given_each_documented_format_element_when_writing_text_then_it_converts_as_recorded_or_refuses() +{ + let test_cases = [ + FirstValueTestCase { + description: "the four-digit year", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'YYYY') AS v", + expected_outcome: Ok("2024"), + }, + FirstValueTestCase { + description: "the zero-padded month", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MM') AS v", + expected_outcome: Ok("09"), + }, + FirstValueTestCase { + description: "the zero-padded day", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'DD') AS v", + expected_outcome: Ok("05"), + }, + FirstValueTestCase { + description: "MON, the month's abbreviation in title case", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MON') AS v", + expected_outcome: Ok("Sep"), + }, + FirstValueTestCase { + description: "MMMM, the month's full name, not MM twice", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MMMM') AS v", + expected_outcome: Ok("September"), + }, + FirstValueTestCase { + description: "MON between other fields", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'DD MON YYYY') AS v", + expected_outcome: Ok("05 Sep 2024"), + }, + FirstValueTestCase { + description: "adjacent numeric fields", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'YYYYMMDD') AS v", + expected_outcome: Ok("20240905"), + }, + FirstValueTestCase { + description: "the 24-hour hour", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'HH24') AS v", + expected_outcome: Ok("13"), + }, + FirstValueTestCase { + description: "the minutes", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'MI') AS v", + expected_outcome: Ok("04"), + }, + FirstValueTestCase { + description: "the seconds", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'SS') AS v", + expected_outcome: Ok("05"), + }, + FirstValueTestCase { + description: "milliseconds", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'FF3') AS v", + expected_outcome: Ok("123"), + }, + FirstValueTestCase { + description: "FF at the timestamp's precision", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'FF') AS v", + expected_outcome: Ok("123"), + }, + FirstValueTestCase { + description: "MON of a timestamp", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'MON') AS v", + expected_outcome: Ok("Sep"), + }, + FirstValueTestCase { + description: "MON in lower case, whose letter case no recording shows", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'mon') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "MMMM in mixed case", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'Mmmm') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "YY", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'YY') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "D", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'D') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "DY", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'DY') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "UUUU", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'UUUU') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "HH12", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'HH12') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "HH", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'HH') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "H24", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'H24') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "H12", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'H12') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "H", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'H') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "AM", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'HH12 AM') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "PM", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'HH12 PM') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "A", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'HH12 A') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "P", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'HH12 P') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "FF0", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'FF0') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "FF1", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'FF1') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "FF7", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'FF7') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "TZH:TZM", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'TZH:TZM') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "TZHTZM", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'TZHTZM') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "TZH", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'TZH') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "TZM", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'TZM') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "MMMMMM, which MMMM and MM would spell", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MMMMMM') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "MM then MON, a run of M", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MMMON') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "DDDD, which DD would match twice", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'DDDD') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "YYYYYYYY, which YYYY would match twice", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'YYYYYYYY') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "SSSS, which SS would match twice", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'SSSS') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "MMMM directly before DD, as recorded", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MMMMDD') AS v", + expected_outcome: Ok("September05"), + }, + FirstValueTestCase { + description: "MONMM, which Snowflake writes as the full name, not MON then MM", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MONMM') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "MON directly before DD, unrecorded", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MONDD') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "bare FF directly after MON", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'MONFF') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "MMMM directly before YYYY, unrecorded", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MMMMYYYY') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "bare FF directly after MMMM, unrecorded", + sql: "SELECT TO_CHAR('2024-09-05 13:04:05.123'::TIMESTAMP_NTZ(3), 'MMMMFF') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "MON directly after DD, unrecorded", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'DDMON') AS v", + expected_outcome: Err("which no recording shows"), + }, + FirstValueTestCase { + description: "MON after a separator still converts", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'MON-MM') AS v", + expected_outcome: Ok("Sep-09"), + }, + FirstValueTestCase { + description: "time fields of a DATE", + sql: "SELECT TO_CHAR(DATE '2024-09-05', 'HH24 MI') AS v", + expected_outcome: Err("which no recording shows"), + }, + ]; + 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 + ); + } +} diff --git a/evidence/results/4a4ffeb793d992e24f24607e47b4db725eb0a620227173256d8a3bcbebb9f681.arrow b/evidence/results/4a4ffeb793d992e24f24607e47b4db725eb0a620227173256d8a3bcbebb9f681.arrow new file mode 100644 index 000000000..9ff4f14d9 Binary files /dev/null and b/evidence/results/4a4ffeb793d992e24f24607e47b4db725eb0a620227173256d8a3bcbebb9f681.arrow differ diff --git a/evidence/results/4a4ffeb793d992e24f24607e47b4db725eb0a620227173256d8a3bcbebb9f681.json b/evidence/results/4a4ffeb793d992e24f24607e47b4db725eb0a620227173256d8a3bcbebb9f681.json new file mode 100644 index 000000000..00adaaf40 --- /dev/null +++ b/evidence/results/4a4ffeb793d992e24f24607e47b4db725eb0a620227173256d8a3bcbebb9f681.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "22d7b4c2e340590c789afa703a11590edb2f4e174820cc20f3e557f41d0dc063", + "case_hash": "4a4ffeb793d992e24f24607e47b4db725eb0a620227173256d8a3bcbebb9f681", + "columns": [ + { + "internal_size": 134217728, + "name": "R", + "nullable": false, + "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": "c8793ceda3b4b379c3e382d4e758875b843de63feb6d9166898e6bcef3f32537", + "recorded_at": "2026-11-06T10:22:52.631570+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 12, + "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/4cf76346bdfb14872198308f8d0eeac2f91ecaeb07f4338d82bdb8d957d665c6.arrow b/evidence/results/4cf76346bdfb14872198308f8d0eeac2f91ecaeb07f4338d82bdb8d957d665c6.arrow new file mode 100644 index 000000000..63cb7c5ae Binary files /dev/null and b/evidence/results/4cf76346bdfb14872198308f8d0eeac2f91ecaeb07f4338d82bdb8d957d665c6.arrow differ diff --git a/evidence/results/4cf76346bdfb14872198308f8d0eeac2f91ecaeb07f4338d82bdb8d957d665c6.json b/evidence/results/4cf76346bdfb14872198308f8d0eeac2f91ecaeb07f4338d82bdb8d957d665c6.json new file mode 100644 index 000000000..6783dde3c --- /dev/null +++ b/evidence/results/4cf76346bdfb14872198308f8d0eeac2f91ecaeb07f4338d82bdb8d957d665c6.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "9040c92c0d0031949c7c0e0457be20023502ed6a967bd4e3e77b39434aac59ac", + "case_hash": "4cf76346bdfb14872198308f8d0eeac2f91ecaeb07f4338d82bdb8d957d665c6", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": false, + "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": "0d309420d85a92ed82255fd683a5c1c09dd33f579857074591bc225147f535a7", + "recorded_at": "2026-11-06T10:22:52.631570+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/6b44d9301fbc0b7b7232f8c211164205ecd27e9871d05fd90c74f296e28eecbb.arrow b/evidence/results/6b44d9301fbc0b7b7232f8c211164205ecd27e9871d05fd90c74f296e28eecbb.arrow new file mode 100644 index 000000000..dd82e1a86 Binary files /dev/null and b/evidence/results/6b44d9301fbc0b7b7232f8c211164205ecd27e9871d05fd90c74f296e28eecbb.arrow differ diff --git a/evidence/results/6b44d9301fbc0b7b7232f8c211164205ecd27e9871d05fd90c74f296e28eecbb.json b/evidence/results/6b44d9301fbc0b7b7232f8c211164205ecd27e9871d05fd90c74f296e28eecbb.json new file mode 100644 index 000000000..1e356df45 --- /dev/null +++ b/evidence/results/6b44d9301fbc0b7b7232f8c211164205ecd27e9871d05fd90c74f296e28eecbb.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "b2bba74b6de15b1767cf9c6e1b3a3da64574c911d850547d06b73383030d3ea4", + "case_hash": "6b44d9301fbc0b7b7232f8c211164205ecd27e9871d05fd90c74f296e28eecbb", + "columns": [ + { + "internal_size": null, + "name": "N", + "nullable": false, + "precision": 38, + "scale": 0, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "R", + "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": "e70777b3325687cd2bc1b01b4e3f6d414d8ca268c826a8c71972c647588e2338", + "recorded_at": "2026-11-06T10:22:52.631570+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 3, + "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/75f342293e8afc81b5ef4599d2b0bbcc29ca8c6dca96aaed915c2113ad3e40cb.arrow b/evidence/results/75f342293e8afc81b5ef4599d2b0bbcc29ca8c6dca96aaed915c2113ad3e40cb.arrow new file mode 100644 index 000000000..6cc3e01c0 Binary files /dev/null and b/evidence/results/75f342293e8afc81b5ef4599d2b0bbcc29ca8c6dca96aaed915c2113ad3e40cb.arrow differ diff --git a/evidence/results/75f342293e8afc81b5ef4599d2b0bbcc29ca8c6dca96aaed915c2113ad3e40cb.json b/evidence/results/75f342293e8afc81b5ef4599d2b0bbcc29ca8c6dca96aaed915c2113ad3e40cb.json new file mode 100644 index 000000000..9c2491570 --- /dev/null +++ b/evidence/results/75f342293e8afc81b5ef4599d2b0bbcc29ca8c6dca96aaed915c2113ad3e40cb.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "a8392d2cbb0f52541b29d00c3df5ef7e3769f95674c2164018ba2d7ff089a455", + "case_hash": "75f342293e8afc81b5ef4599d2b0bbcc29ca8c6dca96aaed915c2113ad3e40cb", + "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": "136cb8969daef54beaf8834457cc42437c827f2b701b90d985f3a15c2897218a", + "recorded_at": "2026-11-06T10:22:52.631570+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/7a3cabb7e435bb7053d9288848fc73a14f1e662b2ef390f15181fee3125e489f.arrow b/evidence/results/7a3cabb7e435bb7053d9288848fc73a14f1e662b2ef390f15181fee3125e489f.arrow new file mode 100644 index 000000000..8c8ce95d8 Binary files /dev/null and b/evidence/results/7a3cabb7e435bb7053d9288848fc73a14f1e662b2ef390f15181fee3125e489f.arrow differ diff --git a/evidence/results/7a3cabb7e435bb7053d9288848fc73a14f1e662b2ef390f15181fee3125e489f.json b/evidence/results/7a3cabb7e435bb7053d9288848fc73a14f1e662b2ef390f15181fee3125e489f.json new file mode 100644 index 000000000..ecd526792 --- /dev/null +++ b/evidence/results/7a3cabb7e435bb7053d9288848fc73a14f1e662b2ef390f15181fee3125e489f.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "80cf863d6d9160db65f335f0cf488168401fe0d3f79512a20e36a8f130564535", + "case_hash": "7a3cabb7e435bb7053d9288848fc73a14f1e662b2ef390f15181fee3125e489f", + "columns": [ + { + "internal_size": 134217728, + "name": "A", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": 134217728, + "name": "B", + "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": "62028b264e190cd013031746c2d023719a494f02d91e07328240388414d3e2f3", + "recorded_at": "2026-11-06T10:22:52.631570+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/9e3cd6c4430556325c9cfe03efb782f11fe3aa59aca4a00b83bfadd793aec4de.arrow b/evidence/results/9e3cd6c4430556325c9cfe03efb782f11fe3aa59aca4a00b83bfadd793aec4de.arrow new file mode 100644 index 000000000..a845366e3 Binary files /dev/null and b/evidence/results/9e3cd6c4430556325c9cfe03efb782f11fe3aa59aca4a00b83bfadd793aec4de.arrow differ diff --git a/evidence/results/9e3cd6c4430556325c9cfe03efb782f11fe3aa59aca4a00b83bfadd793aec4de.json b/evidence/results/9e3cd6c4430556325c9cfe03efb782f11fe3aa59aca4a00b83bfadd793aec4de.json new file mode 100644 index 000000000..e9de14e7a --- /dev/null +++ b/evidence/results/9e3cd6c4430556325c9cfe03efb782f11fe3aa59aca4a00b83bfadd793aec4de.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "b80fd64cd3f72687bced5e63ffc2750e2b77755033c53279500926f3cc18f6de", + "case_hash": "9e3cd6c4430556325c9cfe03efb782f11fe3aa59aca4a00b83bfadd793aec4de", + "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": "b99bea907058469b8764caf3efeec676d07d0db73482b3cacd382686aa6693dd", + "recorded_at": "2026-11-06T10:22:52.631570+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/a0b4fb649137078b6c464dd859dbe8f478b725dfbb8c3fe7114338442f3de75f.arrow b/evidence/results/a0b4fb649137078b6c464dd859dbe8f478b725dfbb8c3fe7114338442f3de75f.arrow new file mode 100644 index 000000000..fe9b0802d Binary files /dev/null and b/evidence/results/a0b4fb649137078b6c464dd859dbe8f478b725dfbb8c3fe7114338442f3de75f.arrow differ diff --git a/evidence/results/a0b4fb649137078b6c464dd859dbe8f478b725dfbb8c3fe7114338442f3de75f.json b/evidence/results/a0b4fb649137078b6c464dd859dbe8f478b725dfbb8c3fe7114338442f3de75f.json new file mode 100644 index 000000000..36fad24f5 --- /dev/null +++ b/evidence/results/a0b4fb649137078b6c464dd859dbe8f478b725dfbb8c3fe7114338442f3de75f.json @@ -0,0 +1,97 @@ +{ + "arrow_sha256": "e4a81b8efcf75c725966f5d14b4ab0f67e600ab54a9668c7b4705afc76a94451", + "case_hash": "a0b4fb649137078b6c464dd859dbe8f478b725dfbb8c3fe7114338442f3de75f", + "columns": [ + { + "internal_size": null, + "name": "ORDINAL", + "nullable": false, + "precision": 1, + "scale": 0, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": 134217728, + "name": "KEY", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": null, + "name": "INDEX", + "nullable": true, + "precision": 38, + "scale": 0, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": null, + "name": "VALUE", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 5, + "type_name": "VARIANT" + }, + { + "internal_size": 134217728, + "name": "PATH", + "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": "41ae8fc8fd0bc87b05816d2c1d416563423a60ca681abc8b6923ab242ed36b1b", + "recorded_at": "2026-11-06T10:37:41.742721+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/a25a12c6b772eeced9362e53613d987170b1f3a3241203a9df4f15c5a9790734.arrow b/evidence/results/a25a12c6b772eeced9362e53613d987170b1f3a3241203a9df4f15c5a9790734.arrow new file mode 100644 index 000000000..078ce6f64 Binary files /dev/null and b/evidence/results/a25a12c6b772eeced9362e53613d987170b1f3a3241203a9df4f15c5a9790734.arrow differ diff --git a/evidence/results/a25a12c6b772eeced9362e53613d987170b1f3a3241203a9df4f15c5a9790734.json b/evidence/results/a25a12c6b772eeced9362e53613d987170b1f3a3241203a9df4f15c5a9790734.json new file mode 100644 index 000000000..459f132d5 --- /dev/null +++ b/evidence/results/a25a12c6b772eeced9362e53613d987170b1f3a3241203a9df4f15c5a9790734.json @@ -0,0 +1,88 @@ +{ + "arrow_sha256": "20c42704e723a2616fe63b2770dfe18ccfd8f5d3c3992e96beec75bf0aec4952", + "case_hash": "a25a12c6b772eeced9362e53613d987170b1f3a3241203a9df4f15c5a9790734", + "columns": [ + { + "internal_size": 5, + "name": "K", + "nullable": false, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": null, + "name": "INDEX", + "nullable": true, + "precision": 38, + "scale": 0, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": null, + "name": "VALUE", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 5, + "type_name": "VARIANT" + }, + { + "internal_size": 134217728, + "name": "PATH", + "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": "134071d486165bf60d696709f14d386ad0cfea85a4e3fb5a2a2c5d149d62b6c1", + "recorded_at": "2026-11-06T10:37:41.742721+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/a746e0056cd8546feb423cf4f00cd81732b6ba2195a071939f5ce2f88670b347.arrow b/evidence/results/a746e0056cd8546feb423cf4f00cd81732b6ba2195a071939f5ce2f88670b347.arrow new file mode 100644 index 000000000..46e216e99 Binary files /dev/null and b/evidence/results/a746e0056cd8546feb423cf4f00cd81732b6ba2195a071939f5ce2f88670b347.arrow differ diff --git a/evidence/results/a746e0056cd8546feb423cf4f00cd81732b6ba2195a071939f5ce2f88670b347.json b/evidence/results/a746e0056cd8546feb423cf4f00cd81732b6ba2195a071939f5ce2f88670b347.json new file mode 100644 index 000000000..b0761bd06 --- /dev/null +++ b/evidence/results/a746e0056cd8546feb423cf4f00cd81732b6ba2195a071939f5ce2f88670b347.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "f90cee47a945998de57d6f5dc0a98d8014b71652539778d92f066de0e2bc001d", + "case_hash": "a746e0056cd8546feb423cf4f00cd81732b6ba2195a071939f5ce2f88670b347", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": false, + "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": "9dd1ddc1509a6ff9f38e23d11027090bdfeaffff4abf943f7a9a1323eca8d9ca", + "recorded_at": "2026-11-06T10:22:52.631570+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 22, + "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/b30082406f48e628889819d888598b56ff6faee43e265a388b225d400ecb6963.arrow b/evidence/results/b30082406f48e628889819d888598b56ff6faee43e265a388b225d400ecb6963.arrow new file mode 100644 index 000000000..9babb7c8f Binary files /dev/null and b/evidence/results/b30082406f48e628889819d888598b56ff6faee43e265a388b225d400ecb6963.arrow differ diff --git a/evidence/results/b30082406f48e628889819d888598b56ff6faee43e265a388b225d400ecb6963.json b/evidence/results/b30082406f48e628889819d888598b56ff6faee43e265a388b225d400ecb6963.json new file mode 100644 index 000000000..affe40b5d --- /dev/null +++ b/evidence/results/b30082406f48e628889819d888598b56ff6faee43e265a388b225d400ecb6963.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "6117f06746cc35af28fbf9b9b37cf7bfdc08a0905b5515339fa8bc9f6925517e", + "case_hash": "b30082406f48e628889819d888598b56ff6faee43e265a388b225d400ecb6963", + "columns": [ + { + "internal_size": 134217728, + "name": "R", + "nullable": false, + "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": "f1652927c1434159cb3787ec8fca8472b447a7f5d6ed14e4a40d0f26d38aaa93", + "recorded_at": "2026-11-06T10:22:52.631570+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 12, + "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/defe2a2cd18d2f6fecd30623029412ae893c2597b5b190d6684fd0010b8e5472.arrow b/evidence/results/defe2a2cd18d2f6fecd30623029412ae893c2597b5b190d6684fd0010b8e5472.arrow new file mode 100644 index 000000000..3caf7b132 Binary files /dev/null and b/evidence/results/defe2a2cd18d2f6fecd30623029412ae893c2597b5b190d6684fd0010b8e5472.arrow differ diff --git a/evidence/results/defe2a2cd18d2f6fecd30623029412ae893c2597b5b190d6684fd0010b8e5472.json b/evidence/results/defe2a2cd18d2f6fecd30623029412ae893c2597b5b190d6684fd0010b8e5472.json new file mode 100644 index 000000000..d46aa33a3 --- /dev/null +++ b/evidence/results/defe2a2cd18d2f6fecd30623029412ae893c2597b5b190d6684fd0010b8e5472.json @@ -0,0 +1,61 @@ +{ + "arrow_sha256": "11678990efd7538fd904b40fd2140d60953f802c50a106de96256de872d8ed58", + "case_hash": "defe2a2cd18d2f6fecd30623029412ae893c2597b5b190d6684fd0010b8e5472", + "columns": [ + { + "internal_size": null, + "name": "R", + "nullable": false, + "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": "e62ed8f2bf983f7a14a4d8a72e7ed21f27bf682f4c3db2edb3daf23f1e35744a", + "recorded_at": "2026-11-06T10:22:52.631570+00:00", + "recorder": "sqlquack-record 0.1.0", + "row_count": 3, + "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/f73a4be69ccd2128d8b01b2f33c46bdba317fbc5726b98b2d4bdaa7a64e67d3f.arrow b/evidence/results/f73a4be69ccd2128d8b01b2f33c46bdba317fbc5726b98b2d4bdaa7a64e67d3f.arrow new file mode 100644 index 000000000..45e72b057 Binary files /dev/null and b/evidence/results/f73a4be69ccd2128d8b01b2f33c46bdba317fbc5726b98b2d4bdaa7a64e67d3f.arrow differ diff --git a/evidence/results/f73a4be69ccd2128d8b01b2f33c46bdba317fbc5726b98b2d4bdaa7a64e67d3f.json b/evidence/results/f73a4be69ccd2128d8b01b2f33c46bdba317fbc5726b98b2d4bdaa7a64e67d3f.json new file mode 100644 index 000000000..77862e050 --- /dev/null +++ b/evidence/results/f73a4be69ccd2128d8b01b2f33c46bdba317fbc5726b98b2d4bdaa7a64e67d3f.json @@ -0,0 +1,70 @@ +{ + "arrow_sha256": "9942f729200c43cffd8cffe1ad6376952b291c23e956ae49957459a25871cb63", + "case_hash": "f73a4be69ccd2128d8b01b2f33c46bdba317fbc5726b98b2d4bdaa7a64e67d3f", + "columns": [ + { + "internal_size": 134217728, + "name": "A", + "nullable": false, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": 134217728, + "name": "B", + "nullable": false, + "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": "97f73cbbcd820d3fac481ec7f876821f7e7a1d889c28bc7e79d631aee258361f", + "recorded_at": "2026-11-06T11:28:56.418860+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/f94b375853ed0dad32ea9ca9fe29839cb1e9ee3c16e176b3ef1398e5bc883207.arrow b/evidence/results/f94b375853ed0dad32ea9ca9fe29839cb1e9ee3c16e176b3ef1398e5bc883207.arrow new file mode 100644 index 000000000..bd9fa339f Binary files /dev/null and b/evidence/results/f94b375853ed0dad32ea9ca9fe29839cb1e9ee3c16e176b3ef1398e5bc883207.arrow differ diff --git a/evidence/results/f94b375853ed0dad32ea9ca9fe29839cb1e9ee3c16e176b3ef1398e5bc883207.json b/evidence/results/f94b375853ed0dad32ea9ca9fe29839cb1e9ee3c16e176b3ef1398e5bc883207.json new file mode 100644 index 000000000..ee9d82008 --- /dev/null +++ b/evidence/results/f94b375853ed0dad32ea9ca9fe29839cb1e9ee3c16e176b3ef1398e5bc883207.json @@ -0,0 +1,88 @@ +{ + "arrow_sha256": "eeaa06a26e9a71feba9864cd1f2c446fb821d264a39f0a7aa07e847fc5790eb6", + "case_hash": "f94b375853ed0dad32ea9ca9fe29839cb1e9ee3c16e176b3ef1398e5bc883207", + "columns": [ + { + "internal_size": null, + "name": "ORDINAL", + "nullable": false, + "precision": 1, + "scale": 0, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": null, + "name": "INDEX", + "nullable": true, + "precision": 38, + "scale": 0, + "type_code": 0, + "type_name": "FIXED" + }, + { + "internal_size": null, + "name": "VALUE", + "nullable": true, + "precision": null, + "scale": null, + "type_code": 5, + "type_name": "VARIANT" + }, + { + "internal_size": 134217728, + "name": "PATH", + "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": "8827b5e87274ce164e048ea4fa672bd76c903d6755f53e36c99a4136bb6278e8", + "recorded_at": "2026-11-06T10:37:41.742721+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/ffd83d3f865bb76030682a49bf90a0c565139cfa9c9f12810cd431a7693bbaa9.arrow b/evidence/results/ffd83d3f865bb76030682a49bf90a0c565139cfa9c9f12810cd431a7693bbaa9.arrow new file mode 100644 index 000000000..ea16997a0 Binary files /dev/null and b/evidence/results/ffd83d3f865bb76030682a49bf90a0c565139cfa9c9f12810cd431a7693bbaa9.arrow differ diff --git a/evidence/results/ffd83d3f865bb76030682a49bf90a0c565139cfa9c9f12810cd431a7693bbaa9.json b/evidence/results/ffd83d3f865bb76030682a49bf90a0c565139cfa9c9f12810cd431a7693bbaa9.json new file mode 100644 index 000000000..a59f9c365 --- /dev/null +++ b/evidence/results/ffd83d3f865bb76030682a49bf90a0c565139cfa9c9f12810cd431a7693bbaa9.json @@ -0,0 +1,88 @@ +{ + "arrow_sha256": "8086f8fbfe39b17fd73bda0af5d77f1426ed09fe11d43523d1cdc8a7c38c4f31", + "case_hash": "ffd83d3f865bb76030682a49bf90a0c565139cfa9c9f12810cd431a7693bbaa9", + "columns": [ + { + "internal_size": 134217728, + "name": "A", + "nullable": false, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": 134217728, + "name": "B", + "nullable": false, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": 134217728, + "name": "C", + "nullable": false, + "precision": null, + "scale": null, + "type_code": 2, + "type_name": "TEXT" + }, + { + "internal_size": 134217728, + "name": "E", + "nullable": false, + "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": "350b4b42fbfb5717c4013fed76fec786661ffa6441acb4c82cc9a8ff8e968e45", + "recorded_at": "2026-11-06T10:22:52.631570+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" +}