Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions datafusion/sqllogictest/test_files/dictionary.slt
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,121 @@ DROP TABLE dict_hash_10;

statement ok
DROP TABLE dict_hash_src;

statement ok
CREATE TABLE dict_large_utf8 AS
SELECT
arrow_cast(column1, 'Dictionary(Int32, LargeUtf8)') AS tag,
arrow_cast(column2, 'Float64') AS val
FROM (VALUES ('alpha', 1.0), ('beta', 2.0), ('alpha', 3.0), ('gamma', 4.0), ('beta', 5.0), (NULL, 6.0));

query TRI rowsort
SELECT tag, SUM(val), COUNT(*) FROM dict_large_utf8 GROUP BY tag;
----
NULL 6 1
alpha 4 2
beta 7 2
gamma 4 1

statement ok
DROP TABLE dict_large_utf8;

# multiple dictionary columns as group keys

statement ok
CREATE TABLE dict_multi_key AS

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice addition. This expands the GROUP BY coverage for multiple dictionary columns well.

One thought for a future follow-up: all of the rows here come from a single VALUES-derived table, so this is mostly exercising one dictionary encoding per column. It could be useful to add a case where the same logical values arrive in different batches or inputs with different dictionary key assignments. That would help catch implementations that accidentally group by dictionary keys instead of decoded values.

Not blocking though. The current tests already cover multiple dictionary key columns, mixed key widths, nulls, and aggregates.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the review @kosiew , I agree I think this would be a nice addition. Id be happy to make a follow up PR to add this.

SELECT
arrow_cast(column1, 'Dictionary(Int32, Utf8)') AS region,
arrow_cast(column2, 'Dictionary(Int16, Utf8)') AS status,
arrow_cast(column3, 'Dictionary(Int8, Utf8)') AS tier,
arrow_cast(column4, 'Float64') AS amount
FROM (
VALUES
('us', 'active', 'gold', 100.0),
('eu', 'active', 'silver', 200.0),
('us', 'active', 'gold', 300.0),
('eu', 'inactive', 'gold', 400.0),
('us', 'inactive', 'silver', 500.0),
('eu', 'inactive', 'gold', 600.0),
('us', 'active', 'silver', 150.0),
('eu', 'active', 'silver', 250.0),
(NULL, 'active', 'gold', 700.0)
);

query TTTRI rowsort
SELECT region, status, tier, SUM(amount), COUNT(*) FROM dict_multi_key GROUP BY region, status, tier;
----
NULL active gold 700 1
eu active silver 450 2
eu inactive gold 1000 2
us active gold 400 2
us active silver 150 1
us inactive silver 500 1

statement ok
DROP TABLE dict_multi_key;

# mixed dict (2) and non-dict (2) group keys with nulls spread across all columns

statement ok
CREATE TABLE dict_mixed_nulls AS
SELECT
arrow_cast(column1, 'Dictionary(Int32, Utf8)') AS region,
arrow_cast(column2, 'Dictionary(Int16, Utf8)') AS status,
arrow_cast(column3, 'Utf8') AS tier,
arrow_cast(column4, 'Int32') AS category,
arrow_cast(column5, 'Float64') AS amount
FROM (
VALUES
('us', 'active', 'gold', 1, 100.0),
('us', 'active', 'gold', 1, 200.0),
('eu', 'active', 'silver', 2, 300.0),
(NULL, 'active', 'gold', 1, 400.0),
('us', NULL, 'gold', 1, 500.0),
('us', 'active', NULL, 1, 600.0),
('us', 'active', 'gold', NULL, 700.0)
);

query TTTIRI rowsort
SELECT region, status, tier, category, SUM(amount), COUNT(*) FROM dict_mixed_nulls GROUP BY region, status, tier, category;
----
NULL active gold 1 400 1
eu active silver 2 300 1
us NULL gold 1 500 1
us active NULL 1 600 1
us active gold 1 300 2
us active gold NULL 700 1

statement ok
DROP TABLE dict_mixed_nulls;

##########
## Aggregation tests: COUNT(DISTINCT) on dictionary columns
##########

statement ok
CREATE TABLE dict_count_distinct AS
SELECT
arrow_cast(column1, 'Dictionary(Int64, Utf8)') AS region,
arrow_cast(column2, 'Dictionary(Int8, Utf8)') AS sensor
FROM (
VALUES
('north', 's1'), ('north', 's2'), ('north', 's1'), ('north', 's3'),
('south', 's3'), ('south', 's3'), ('south', 's4'),
('east', 's1'),
(NULL, 's5'),
('north', NULL)
);

query TI rowsort
SELECT region, COUNT(DISTINCT sensor) FROM dict_count_distinct GROUP BY region;
----
NULL 1
east 1
north 3
south 2

statement ok
DROP TABLE dict_count_distinct;


Loading