feat: InfluxQL planner learns how to project multiple measurements (#7063)

* feat: Planner learns how to project multiple measurements

Closes #6896

* chore: Update test

* chore: PR feedback
pull/24376/head
Stuart Carnie 2023-02-27 11:50:06 +11:00 committed by GitHub
parent accf59ad61
commit 2ed5758ddb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 640 additions and 533 deletions

View File

@ -50,12 +50,12 @@ async fn influxql_select_returns_results() {
Step::InfluxQLQuery {
query: format!("select tag1, val from {table_name}"),
expected: vec![
"+--------------------------------+------+-----+",
"| time | tag1 | val |",
"+--------------------------------+------+-----+",
"| 1970-01-01T00:00:00.000123456Z | A | 42 |",
"| 1970-01-01T00:00:00.000123457Z | A | 43 |",
"+--------------------------------+------+-----+",
"+------------------+--------------------------------+------+-----+",
"| iox::measurement | time | tag1 | val |",
"+------------------+--------------------------------+------+-----+",
"| the_table | 1970-01-01T00:00:00.000123456Z | A | 42 |",
"| the_table | 1970-01-01T00:00:00.000123457Z | A | 43 |",
"+------------------+--------------------------------+------+-----+",
],
},
],

View File

@ -10,6 +10,9 @@
-- IOX_COMPARE: sorted
SELECT * FROM m0;
-- No matching measurement
SELECT * FROM non_existent;
-- Projection wildcard, only tags
-- IOX_COMPARE: sorted
SELECT *::tag, f64 FROM m0;
@ -250,3 +253,9 @@ SELECT tag0, i64, i64 * 0.5, i64 + f64::integer, i64 & 1 FROM m0 WHERE f64 > 19;
-- non-existing column
SELECT f64, non_existing, f64 + non_existing FROM m0 WHERE f64 > 19;
--
-- Multiple measurements in the FROM clause
--
SELECT usage_idle, bytes_used FROM cpu, disk;

View File

@ -1,367 +1,370 @@
-- Test Setup: InfluxQLSelectSupport
-- InfluxQL: SELECT * FROM m0;
-- Results After Sorting
+----------------------+------+-----+-----+-------+-------+
| time | f64 | i64 | str | tag0 | tag1 |
+----------------------+------+-----+-----+-------+-------+
| 2022-10-31T02:00:00Z | 10.1 | 101 | hi | val00 | |
| 2022-10-31T02:00:00Z | 10.4 | 101 | lo | val02 | |
| 2022-10-31T02:00:00Z | 11.3 | 211 | lo | val01 | |
| 2022-10-31T02:00:10Z | 18.9 | 211 | lo | val00 | val10 |
| 2022-10-31T02:00:10Z | 21.2 | 211 | hi | val00 | |
| 2022-10-31T02:00:20Z | 11.2 | 191 | lo | val00 | |
| 2022-10-31T02:00:30Z | 19.2 | 392 | lo | val00 | |
+----------------------+------+-----+-----+-------+-------+
+------------------+----------------------+------+-----+-----+-------+-------+
| iox::measurement | time | f64 | i64 | str | tag0 | tag1 |
+------------------+----------------------+------+-----+-----+-------+-------+
| m0 | 2022-10-31T02:00:00Z | 10.1 | 101 | hi | val00 | |
| m0 | 2022-10-31T02:00:00Z | 10.4 | 101 | lo | val02 | |
| m0 | 2022-10-31T02:00:00Z | 11.3 | 211 | lo | val01 | |
| m0 | 2022-10-31T02:00:10Z | 18.9 | 211 | lo | val00 | val10 |
| m0 | 2022-10-31T02:00:10Z | 21.2 | 211 | hi | val00 | |
| m0 | 2022-10-31T02:00:20Z | 11.2 | 191 | lo | val00 | |
| m0 | 2022-10-31T02:00:30Z | 19.2 | 392 | lo | val00 | |
+------------------+----------------------+------+-----+-----+-------+-------+
-- InfluxQL: SELECT * FROM non_existent;
++
++
-- InfluxQL: SELECT *::tag, f64 FROM m0;
-- Results After Sorting
+----------------------+-------+-------+------+
| time | tag0 | tag1 | f64 |
+----------------------+-------+-------+------+
| 2022-10-31T02:00:00Z | val00 | | 10.1 |
| 2022-10-31T02:00:00Z | val01 | | 11.3 |
| 2022-10-31T02:00:00Z | val02 | | 10.4 |
| 2022-10-31T02:00:10Z | val00 | val10 | 18.9 |
| 2022-10-31T02:00:10Z | val00 | | 21.2 |
| 2022-10-31T02:00:20Z | val00 | | 11.2 |
| 2022-10-31T02:00:30Z | val00 | | 19.2 |
+----------------------+-------+-------+------+
+------------------+----------------------+-------+-------+------+
| iox::measurement | time | tag0 | tag1 | f64 |
+------------------+----------------------+-------+-------+------+
| m0 | 2022-10-31T02:00:00Z | val00 | | 10.1 |
| m0 | 2022-10-31T02:00:00Z | val01 | | 11.3 |
| m0 | 2022-10-31T02:00:00Z | val02 | | 10.4 |
| m0 | 2022-10-31T02:00:10Z | val00 | val10 | 18.9 |
| m0 | 2022-10-31T02:00:10Z | val00 | | 21.2 |
| m0 | 2022-10-31T02:00:20Z | val00 | | 11.2 |
| m0 | 2022-10-31T02:00:30Z | val00 | | 19.2 |
+------------------+----------------------+-------+-------+------+
-- InfluxQL: SELECT *::field FROM m0;
-- Results After Sorting
+----------------------+------+-----+-----+
| time | f64 | i64 | str |
+----------------------+------+-----+-----+
| 2022-10-31T02:00:00Z | 10.1 | 101 | hi |
| 2022-10-31T02:00:00Z | 10.4 | 101 | lo |
| 2022-10-31T02:00:00Z | 11.3 | 211 | lo |
| 2022-10-31T02:00:10Z | 18.9 | 211 | lo |
| 2022-10-31T02:00:10Z | 21.2 | 211 | hi |
| 2022-10-31T02:00:20Z | 11.2 | 191 | lo |
| 2022-10-31T02:00:30Z | 19.2 | 392 | lo |
+----------------------+------+-----+-----+
+------------------+----------------------+------+-----+-----+
| iox::measurement | time | f64 | i64 | str |
+------------------+----------------------+------+-----+-----+
| m0 | 2022-10-31T02:00:00Z | 10.1 | 101 | hi |
| m0 | 2022-10-31T02:00:00Z | 10.4 | 101 | lo |
| m0 | 2022-10-31T02:00:00Z | 11.3 | 211 | lo |
| m0 | 2022-10-31T02:00:10Z | 18.9 | 211 | lo |
| m0 | 2022-10-31T02:00:10Z | 21.2 | 211 | hi |
| m0 | 2022-10-31T02:00:20Z | 11.2 | 191 | lo |
| m0 | 2022-10-31T02:00:30Z | 19.2 | 392 | lo |
+------------------+----------------------+------+-----+-----+
-- InfluxQL: SELECT /64|tag0/ FROM m0;
-- Results After Sorting
+----------------------+------+-----+-------+
| time | f64 | i64 | tag0 |
+----------------------+------+-----+-------+
| 2022-10-31T02:00:00Z | 10.1 | 101 | val00 |
| 2022-10-31T02:00:00Z | 10.4 | 101 | val02 |
| 2022-10-31T02:00:00Z | 11.3 | 211 | val01 |
| 2022-10-31T02:00:10Z | 18.9 | 211 | val00 |
| 2022-10-31T02:00:10Z | 21.2 | 211 | val00 |
| 2022-10-31T02:00:20Z | 11.2 | 191 | val00 |
| 2022-10-31T02:00:30Z | 19.2 | 392 | val00 |
+----------------------+------+-----+-------+
+------------------+----------------------+------+-----+-------+
| iox::measurement | time | f64 | i64 | tag0 |
+------------------+----------------------+------+-----+-------+
| m0 | 2022-10-31T02:00:00Z | 10.1 | 101 | val00 |
| m0 | 2022-10-31T02:00:00Z | 10.4 | 101 | val02 |
| m0 | 2022-10-31T02:00:00Z | 11.3 | 211 | val01 |
| m0 | 2022-10-31T02:00:10Z | 18.9 | 211 | val00 |
| m0 | 2022-10-31T02:00:10Z | 21.2 | 211 | val00 |
| m0 | 2022-10-31T02:00:20Z | 11.2 | 191 | val00 |
| m0 | 2022-10-31T02:00:30Z | 19.2 | 392 | val00 |
+------------------+----------------------+------+-----+-------+
-- InfluxQL: SELECT f64, tag0 FROM m0;
-- Results After Sorting
+----------------------+------+-------+
| time | f64 | tag0 |
+----------------------+------+-------+
| 2022-10-31T02:00:00Z | 10.1 | val00 |
| 2022-10-31T02:00:00Z | 10.4 | val02 |
| 2022-10-31T02:00:00Z | 11.3 | val01 |
| 2022-10-31T02:00:10Z | 18.9 | val00 |
| 2022-10-31T02:00:10Z | 21.2 | val00 |
| 2022-10-31T02:00:20Z | 11.2 | val00 |
| 2022-10-31T02:00:30Z | 19.2 | val00 |
+----------------------+------+-------+
+------------------+----------------------+------+-------+
| iox::measurement | time | f64 | tag0 |
+------------------+----------------------+------+-------+
| m0 | 2022-10-31T02:00:00Z | 10.1 | val00 |
| m0 | 2022-10-31T02:00:00Z | 10.4 | val02 |
| m0 | 2022-10-31T02:00:00Z | 11.3 | val01 |
| m0 | 2022-10-31T02:00:10Z | 18.9 | val00 |
| m0 | 2022-10-31T02:00:10Z | 21.2 | val00 |
| m0 | 2022-10-31T02:00:20Z | 11.2 | val00 |
| m0 | 2022-10-31T02:00:30Z | 19.2 | val00 |
+------------------+----------------------+------+-------+
-- InfluxQL: SELECT f64, tag0, time FROM m0;
-- Results After Sorting
+------+-------+----------------------+
| f64 | tag0 | time |
+------+-------+----------------------+
| 10.1 | val00 | 2022-10-31T02:00:00Z |
| 10.4 | val02 | 2022-10-31T02:00:00Z |
| 11.2 | val00 | 2022-10-31T02:00:20Z |
| 11.3 | val01 | 2022-10-31T02:00:00Z |
| 18.9 | val00 | 2022-10-31T02:00:10Z |
| 19.2 | val00 | 2022-10-31T02:00:30Z |
| 21.2 | val00 | 2022-10-31T02:00:10Z |
+------+-------+----------------------+
+------------------+------+-------+----------------------+
| iox::measurement | f64 | tag0 | time |
+------------------+------+-------+----------------------+
| m0 | 10.1 | val00 | 2022-10-31T02:00:00Z |
| m0 | 10.4 | val02 | 2022-10-31T02:00:00Z |
| m0 | 11.2 | val00 | 2022-10-31T02:00:20Z |
| m0 | 11.3 | val01 | 2022-10-31T02:00:00Z |
| m0 | 18.9 | val00 | 2022-10-31T02:00:10Z |
| m0 | 19.2 | val00 | 2022-10-31T02:00:30Z |
| m0 | 21.2 | val00 | 2022-10-31T02:00:10Z |
+------------------+------+-------+----------------------+
-- InfluxQL: SELECT f64, f64 * 2, i64, i64 + i64 FROM m0;
-- Results After Sorting
+----------------------+------+-------+-----+---------+
| time | f64 | f64_1 | i64 | i64_i64 |
+----------------------+------+-------+-----+---------+
| 2022-10-31T02:00:00Z | 10.1 | 20.2 | 101 | 202 |
| 2022-10-31T02:00:00Z | 10.4 | 20.8 | 101 | 202 |
| 2022-10-31T02:00:00Z | 11.3 | 22.6 | 211 | 422 |
| 2022-10-31T02:00:10Z | 18.9 | 37.8 | 211 | 422 |
| 2022-10-31T02:00:10Z | 21.2 | 42.4 | 211 | 422 |
| 2022-10-31T02:00:20Z | 11.2 | 22.4 | 191 | 382 |
| 2022-10-31T02:00:30Z | 19.2 | 38.4 | 392 | 784 |
+----------------------+------+-------+-----+---------+
+------------------+----------------------+------+-------+-----+---------+
| iox::measurement | time | f64 | f64_1 | i64 | i64_i64 |
+------------------+----------------------+------+-------+-----+---------+
| m0 | 2022-10-31T02:00:00Z | 10.1 | 20.2 | 101 | 202 |
| m0 | 2022-10-31T02:00:00Z | 10.4 | 20.8 | 101 | 202 |
| m0 | 2022-10-31T02:00:00Z | 11.3 | 22.6 | 211 | 422 |
| m0 | 2022-10-31T02:00:10Z | 18.9 | 37.8 | 211 | 422 |
| m0 | 2022-10-31T02:00:10Z | 21.2 | 42.4 | 211 | 422 |
| m0 | 2022-10-31T02:00:20Z | 11.2 | 22.4 | 191 | 382 |
| m0 | 2022-10-31T02:00:30Z | 19.2 | 38.4 | 392 | 784 |
+------------------+----------------------+------+-------+-----+---------+
-- InfluxQL: SELECT i64, i64 & 1 FROM m0;
-- Results After Sorting
+----------------------+-----+-------+
| time | i64 | i64_1 |
+----------------------+-----+-------+
| 2022-10-31T02:00:00Z | 101 | 1 |
| 2022-10-31T02:00:00Z | 101 | 1 |
| 2022-10-31T02:00:00Z | 211 | 1 |
| 2022-10-31T02:00:10Z | 211 | 1 |
| 2022-10-31T02:00:10Z | 211 | 1 |
| 2022-10-31T02:00:20Z | 191 | 1 |
| 2022-10-31T02:00:30Z | 392 | 0 |
+----------------------+-----+-------+
+------------------+----------------------+-----+-------+
| iox::measurement | time | i64 | i64_1 |
+------------------+----------------------+-----+-------+
| m0 | 2022-10-31T02:00:00Z | 101 | 1 |
| m0 | 2022-10-31T02:00:00Z | 101 | 1 |
| m0 | 2022-10-31T02:00:00Z | 211 | 1 |
| m0 | 2022-10-31T02:00:10Z | 211 | 1 |
| m0 | 2022-10-31T02:00:10Z | 211 | 1 |
| m0 | 2022-10-31T02:00:20Z | 191 | 1 |
| m0 | 2022-10-31T02:00:30Z | 392 | 0 |
+------------------+----------------------+-----+-------+
-- InfluxQL: SELECT f64 + i64 FROM m0;
-- Results After Sorting
+----------------------+---------+
| time | f64_i64 |
+----------------------+---------+
| 2022-10-31T02:00:00Z | 111.1 |
| 2022-10-31T02:00:00Z | 111.4 |
| 2022-10-31T02:00:00Z | 222.3 |
| 2022-10-31T02:00:10Z | 229.9 |
| 2022-10-31T02:00:10Z | 232.2 |
| 2022-10-31T02:00:20Z | 202.2 |
| 2022-10-31T02:00:30Z | 411.2 |
+----------------------+---------+
+------------------+----------------------+---------+
| iox::measurement | time | f64_i64 |
+------------------+----------------------+---------+
| m0 | 2022-10-31T02:00:00Z | 111.1 |
| m0 | 2022-10-31T02:00:00Z | 111.4 |
| m0 | 2022-10-31T02:00:00Z | 222.3 |
| m0 | 2022-10-31T02:00:10Z | 229.9 |
| m0 | 2022-10-31T02:00:10Z | 232.2 |
| m0 | 2022-10-31T02:00:20Z | 202.2 |
| m0 | 2022-10-31T02:00:30Z | 411.2 |
+------------------+----------------------+---------+
-- InfluxQL: SELECT f64, f64::integer FROM m0;
+----------------------+------+-------+
| time | f64 | f64_1 |
+----------------------+------+-------+
| 2022-10-31T02:00:00Z | 10.1 | 10 |
| 2022-10-31T02:00:00Z | 11.3 | 11 |
| 2022-10-31T02:00:00Z | 10.4 | 10 |
| 2022-10-31T02:00:10Z | 21.2 | 21 |
| 2022-10-31T02:00:10Z | 18.9 | 18 |
| 2022-10-31T02:00:20Z | 11.2 | 11 |
| 2022-10-31T02:00:30Z | 19.2 | 19 |
+----------------------+------+-------+
+------------------+----------------------+------+-------+
| iox::measurement | time | f64 | f64_1 |
+------------------+----------------------+------+-------+
| m0 | 2022-10-31T02:00:00Z | 10.1 | 10 |
| m0 | 2022-10-31T02:00:00Z | 11.3 | 11 |
| m0 | 2022-10-31T02:00:00Z | 10.4 | 10 |
| m0 | 2022-10-31T02:00:10Z | 21.2 | 21 |
| m0 | 2022-10-31T02:00:10Z | 18.9 | 18 |
| m0 | 2022-10-31T02:00:20Z | 11.2 | 11 |
| m0 | 2022-10-31T02:00:30Z | 19.2 | 19 |
+------------------+----------------------+------+-------+
-- InfluxQL: SELECT f64 AS f64_2, f64, f64, f64 FROM m0 LIMIT 1;
-- Results After Sorting
+----------------------+-------+------+-------+-------+
| time | f64_2 | f64 | f64_1 | f64_3 |
+----------------------+-------+------+-------+-------+
| 2022-10-31T02:00:00Z | 10.1 | 10.1 | 10.1 | 10.1 |
+----------------------+-------+------+-------+-------+
+------------------+----------------------+-------+------+-------+-------+
| iox::measurement | time | f64_2 | f64 | f64_1 | f64_3 |
+------------------+----------------------+-------+------+-------+-------+
| m0 | 2022-10-31T02:00:00Z | 10.1 | 10.1 | 10.1 | 10.1 |
+------------------+----------------------+-------+------+-------+-------+
-- InfluxQL: SELECT tag0, f64 FROM m0 WHERE tag0 = 'val00';
-- Results After Sorting
+----------------------+-------+------+
| time | tag0 | f64 |
+----------------------+-------+------+
| 2022-10-31T02:00:00Z | val00 | 10.1 |
| 2022-10-31T02:00:10Z | val00 | 18.9 |
| 2022-10-31T02:00:10Z | val00 | 21.2 |
| 2022-10-31T02:00:20Z | val00 | 11.2 |
| 2022-10-31T02:00:30Z | val00 | 19.2 |
+----------------------+-------+------+
+------------------+----------------------+-------+------+
| iox::measurement | time | tag0 | f64 |
+------------------+----------------------+-------+------+
| m0 | 2022-10-31T02:00:00Z | val00 | 10.1 |
| m0 | 2022-10-31T02:00:10Z | val00 | 18.9 |
| m0 | 2022-10-31T02:00:10Z | val00 | 21.2 |
| m0 | 2022-10-31T02:00:20Z | val00 | 11.2 |
| m0 | 2022-10-31T02:00:30Z | val00 | 19.2 |
+------------------+----------------------+-------+------+
-- InfluxQL: SELECT tag0, f64 FROM m0 WHERE tag0 =~ /^val0(1|2)/;
-- Results After Sorting
+----------------------+-------+------+
| time | tag0 | f64 |
+----------------------+-------+------+
| 2022-10-31T02:00:00Z | val01 | 11.3 |
| 2022-10-31T02:00:00Z | val02 | 10.4 |
+----------------------+-------+------+
+------------------+----------------------+-------+------+
| iox::measurement | time | tag0 | f64 |
+------------------+----------------------+-------+------+
| m0 | 2022-10-31T02:00:00Z | val01 | 11.3 |
| m0 | 2022-10-31T02:00:00Z | val02 | 10.4 |
+------------------+----------------------+-------+------+
-- InfluxQL: SELECT /tag(0|1)/, f64 FROM m0 WHERE tag0 = 'val00' AND tag1 = 'val10';
-- Results After Sorting
+----------------------+-------+-------+------+
| time | tag0 | tag1 | f64 |
+----------------------+-------+-------+------+
| 2022-10-31T02:00:10Z | val00 | val10 | 18.9 |
+----------------------+-------+-------+------+
+------------------+----------------------+-------+-------+------+
| iox::measurement | time | tag0 | tag1 | f64 |
+------------------+----------------------+-------+-------+------+
| m0 | 2022-10-31T02:00:10Z | val00 | val10 | 18.9 |
+------------------+----------------------+-------+-------+------+
-- InfluxQL: SELECT /tag(0|1)/, f64 FROM m0 WHERE tag0 = 'val00' OR tag1 = 'val10';
-- Results After Sorting
+----------------------+-------+-------+------+
| time | tag0 | tag1 | f64 |
+----------------------+-------+-------+------+
| 2022-10-31T02:00:00Z | val00 | | 10.1 |
| 2022-10-31T02:00:10Z | val00 | val10 | 18.9 |
| 2022-10-31T02:00:10Z | val00 | | 21.2 |
| 2022-10-31T02:00:20Z | val00 | | 11.2 |
| 2022-10-31T02:00:30Z | val00 | | 19.2 |
+----------------------+-------+-------+------+
+------------------+----------------------+-------+-------+------+
| iox::measurement | time | tag0 | tag1 | f64 |
+------------------+----------------------+-------+-------+------+
| m0 | 2022-10-31T02:00:00Z | val00 | | 10.1 |
| m0 | 2022-10-31T02:00:10Z | val00 | val10 | 18.9 |
| m0 | 2022-10-31T02:00:10Z | val00 | | 21.2 |
| m0 | 2022-10-31T02:00:20Z | val00 | | 11.2 |
| m0 | 2022-10-31T02:00:30Z | val00 | | 19.2 |
+------------------+----------------------+-------+-------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 > 10 + 10;
-- Results After Sorting
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:10Z | 21.2 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:10Z | 21.2 |
+------------------+----------------------+------+
-- InfluxQL: SELECT i64 FROM m0 WHERE i64 & 1 = 0;
-- Results After Sorting
+----------------------+-----+
| time | i64 |
+----------------------+-----+
| 2022-10-31T02:00:30Z | 392 |
+----------------------+-----+
+------------------+----------------------+-----+
| iox::measurement | time | i64 |
+------------------+----------------------+-----+
| m0 | 2022-10-31T02:00:30Z | 392 |
+------------------+----------------------+-----+
-- InfluxQL: SELECT i64 FROM m0 WHERE time > '2022-10-31';
-- Results After Sorting
+----------------------+-----+
| time | i64 |
+----------------------+-----+
| 2022-10-31T02:00:00Z | 101 |
| 2022-10-31T02:00:00Z | 101 |
| 2022-10-31T02:00:00Z | 211 |
| 2022-10-31T02:00:10Z | 211 |
| 2022-10-31T02:00:10Z | 211 |
| 2022-10-31T02:00:20Z | 191 |
| 2022-10-31T02:00:30Z | 392 |
+----------------------+-----+
+------------------+----------------------+-----+
| iox::measurement | time | i64 |
+------------------+----------------------+-----+
| m0 | 2022-10-31T02:00:00Z | 101 |
| m0 | 2022-10-31T02:00:00Z | 101 |
| m0 | 2022-10-31T02:00:00Z | 211 |
| m0 | 2022-10-31T02:00:10Z | 211 |
| m0 | 2022-10-31T02:00:10Z | 211 |
| m0 | 2022-10-31T02:00:20Z | 191 |
| m0 | 2022-10-31T02:00:30Z | 392 |
+------------------+----------------------+-----+
-- InfluxQL: SELECT i64 FROM m0 WHERE time > '2022-10-31 02:00:10';
-- Results After Sorting
+----------------------+-----+
| time | i64 |
+----------------------+-----+
| 2022-10-31T02:00:20Z | 191 |
| 2022-10-31T02:00:30Z | 392 |
+----------------------+-----+
+------------------+----------------------+-----+
| iox::measurement | time | i64 |
+------------------+----------------------+-----+
| m0 | 2022-10-31T02:00:20Z | 191 |
| m0 | 2022-10-31T02:00:30Z | 392 |
+------------------+----------------------+-----+
-- InfluxQL: SELECT i64 FROM m0 WHERE time > now() - 100000d;
-- Results After Sorting
+----------------------+-----+
| time | i64 |
+----------------------+-----+
| 2022-10-31T02:00:00Z | 101 |
| 2022-10-31T02:00:00Z | 101 |
| 2022-10-31T02:00:00Z | 211 |
| 2022-10-31T02:00:10Z | 211 |
| 2022-10-31T02:00:10Z | 211 |
| 2022-10-31T02:00:20Z | 191 |
| 2022-10-31T02:00:30Z | 392 |
+----------------------+-----+
+------------------+----------------------+-----+
| iox::measurement | time | i64 |
+------------------+----------------------+-----+
| m0 | 2022-10-31T02:00:00Z | 101 |
| m0 | 2022-10-31T02:00:00Z | 101 |
| m0 | 2022-10-31T02:00:00Z | 211 |
| m0 | 2022-10-31T02:00:10Z | 211 |
| m0 | 2022-10-31T02:00:10Z | 211 |
| m0 | 2022-10-31T02:00:20Z | 191 |
| m0 | 2022-10-31T02:00:30Z | 392 |
+------------------+----------------------+-----+
-- InfluxQL: SELECT tag1, f64 FROM m0 WHERE tag1 != '';
-- Results After Sorting
+----------------------+-------+------+
| time | tag1 | f64 |
+----------------------+-------+------+
| 2022-10-31T02:00:10Z | val10 | 18.9 |
+----------------------+-------+------+
+------------------+----------------------+-------+------+
| iox::measurement | time | tag1 | f64 |
+------------------+----------------------+-------+------+
| m0 | 2022-10-31T02:00:10Z | val10 | 18.9 |
+------------------+----------------------+-------+------+
-- InfluxQL: SELECT tag0, f64 FROM m0 LIMIT 1;
+----------------------+-------+------+
| time | tag0 | f64 |
+----------------------+-------+------+
| 2022-10-31T02:00:00Z | val00 | 10.1 |
+----------------------+-------+------+
+------------------+----------------------+-------+------+
| iox::measurement | time | tag0 | f64 |
+------------------+----------------------+-------+------+
| m0 | 2022-10-31T02:00:00Z | val00 | 10.1 |
+------------------+----------------------+-------+------+
-- InfluxQL: SELECT tag0, f64 FROM m0 WHERE tag0 = 'val00' LIMIT 2 OFFSET 1;
+----------------------+-------+------+
| time | tag0 | f64 |
+----------------------+-------+------+
| 2022-10-31T02:00:10Z | val00 | 21.2 |
| 2022-10-31T02:00:10Z | val00 | 18.9 |
+----------------------+-------+------+
+------------------+----------------------+-------+------+
| iox::measurement | time | tag0 | f64 |
+------------------+----------------------+-------+------+
| m0 | 2022-10-31T02:00:10Z | val00 | 21.2 |
| m0 | 2022-10-31T02:00:10Z | val00 | 18.9 |
+------------------+----------------------+-------+------+
-- InfluxQL: SELECT tag0, f64 FROM m0 LIMIT 1 OFFSET 1;
+----------------------+-------+------+
| time | tag0 | f64 |
+----------------------+-------+------+
| 2022-10-31T02:00:00Z | val01 | 11.3 |
+----------------------+-------+------+
+------------------+----------------------+-------+------+
| iox::measurement | time | tag0 | f64 |
+------------------+----------------------+-------+------+
| m0 | 2022-10-31T02:00:00Z | val01 | 11.3 |
+------------------+----------------------+-------+------+
-- InfluxQL: SELECT * FROM m0;
+----------------------+------+-----+-----+-------+-------+
| time | f64 | i64 | str | tag0 | tag1 |
+----------------------+------+-----+-----+-------+-------+
| 2022-10-31T02:00:00Z | 10.1 | 101 | hi | val00 | |
| 2022-10-31T02:00:00Z | 11.3 | 211 | lo | val01 | |
| 2022-10-31T02:00:00Z | 10.4 | 101 | lo | val02 | |
| 2022-10-31T02:00:10Z | 21.2 | 211 | hi | val00 | |
| 2022-10-31T02:00:10Z | 18.9 | 211 | lo | val00 | val10 |
| 2022-10-31T02:00:20Z | 11.2 | 191 | lo | val00 | |
| 2022-10-31T02:00:30Z | 19.2 | 392 | lo | val00 | |
+----------------------+------+-----+-----+-------+-------+
+------------------+----------------------+------+-----+-----+-------+-------+
| iox::measurement | time | f64 | i64 | str | tag0 | tag1 |
+------------------+----------------------+------+-----+-----+-------+-------+
| m0 | 2022-10-31T02:00:00Z | 10.1 | 101 | hi | val00 | |
| m0 | 2022-10-31T02:00:00Z | 11.3 | 211 | lo | val01 | |
| m0 | 2022-10-31T02:00:00Z | 10.4 | 101 | lo | val02 | |
| m0 | 2022-10-31T02:00:10Z | 18.9 | 211 | lo | val00 | val10 |
| m0 | 2022-10-31T02:00:10Z | 21.2 | 211 | hi | val00 | |
| m0 | 2022-10-31T02:00:20Z | 11.2 | 191 | lo | val00 | |
| m0 | 2022-10-31T02:00:30Z | 19.2 | 392 | lo | val00 | |
+------------------+----------------------+------+-----+-----+-------+-------+
-- InfluxQL: SELECT * FROM m0 ORDER BY time DESC;
+----------------------+------+-----+-----+-------+-------+
| time | f64 | i64 | str | tag0 | tag1 |
+----------------------+------+-----+-----+-------+-------+
| 2022-10-31T02:00:30Z | 19.2 | 392 | lo | val00 | |
| 2022-10-31T02:00:20Z | 11.2 | 191 | lo | val00 | |
| 2022-10-31T02:00:10Z | 21.2 | 211 | hi | val00 | |
| 2022-10-31T02:00:10Z | 18.9 | 211 | lo | val00 | val10 |
| 2022-10-31T02:00:00Z | 10.1 | 101 | hi | val00 | |
| 2022-10-31T02:00:00Z | 11.3 | 211 | lo | val01 | |
| 2022-10-31T02:00:00Z | 10.4 | 101 | lo | val02 | |
+----------------------+------+-----+-----+-------+-------+
+------------------+----------------------+------+-----+-----+-------+-------+
| iox::measurement | time | f64 | i64 | str | tag0 | tag1 |
+------------------+----------------------+------+-----+-----+-------+-------+
| m0 | 2022-10-31T02:00:30Z | 19.2 | 392 | lo | val00 | |
| m0 | 2022-10-31T02:00:20Z | 11.2 | 191 | lo | val00 | |
| m0 | 2022-10-31T02:00:10Z | 18.9 | 211 | lo | val00 | val10 |
| m0 | 2022-10-31T02:00:10Z | 21.2 | 211 | hi | val00 | |
| m0 | 2022-10-31T02:00:00Z | 10.1 | 101 | hi | val00 | |
| m0 | 2022-10-31T02:00:00Z | 11.3 | 211 | lo | val01 | |
| m0 | 2022-10-31T02:00:00Z | 10.4 | 101 | lo | val02 | |
+------------------+----------------------+------+-----+-----+-------+-------+
-- InfluxQL: SELECT f64, abs(f64 * -1), sin(f64), cos(f64), tan(f64), asin(1/f64), acos(1/f64), atan(f64), atan2(f64, 2), exp(f64), ln(f64), log2(f64), log10(f64), sqrt(f64), pow(f64, 2), floor(f64), ceil(f64), round(f64) FROM m0 LIMIT 1;
+----------------------+------+------+---------------------+---------------------+--------------------+--------------------+-------------------+------------------+--------------------+-------------------+-------------------+--------------------+--------------------+--------------------+--------------------+-------+------+-------+
| time | f64 | abs | sin | cos | tan | asin | acos | atan | atan2 | exp | ln | log2 | log10 | sqrt | pow | floor | ceil | round |
+----------------------+------+------+---------------------+---------------------+--------------------+--------------------+-------------------+------------------+--------------------+-------------------+-------------------+--------------------+--------------------+--------------------+--------------------+-------+------+-------+
| 2022-10-31T02:00:00Z | 10.1 | 10.1 | -0.6250706488928821 | -0.7805681801691837 | 0.8007893029375109 | 0.0991723838059207 | 1.471623942988976 | 1.47210806614649 | 1.3753055265462157 | 24343.00942440838 | 2.312535423847214 | 3.3362833878644325 | 1.0043213737826426 | 3.1780497164141406 | 102.00999999999999 | 10.0 | 11.0 | 10.0 |
+----------------------+------+------+---------------------+---------------------+--------------------+--------------------+-------------------+------------------+--------------------+-------------------+-------------------+--------------------+--------------------+--------------------+--------------------+-------+------+-------+
+------------------+----------------------+------+------+---------------------+---------------------+--------------------+--------------------+-------------------+------------------+--------------------+-------------------+-------------------+--------------------+--------------------+--------------------+--------------------+-------+------+-------+
| iox::measurement | time | f64 | abs | sin | cos | tan | asin | acos | atan | atan2 | exp | ln | log2 | log10 | sqrt | pow | floor | ceil | round |
+------------------+----------------------+------+------+---------------------+---------------------+--------------------+--------------------+-------------------+------------------+--------------------+-------------------+-------------------+--------------------+--------------------+--------------------+--------------------+-------+------+-------+
| m0 | 2022-10-31T02:00:00Z | 10.1 | 10.1 | -0.6250706488928821 | -0.7805681801691837 | 0.8007893029375109 | 0.0991723838059207 | 1.471623942988976 | 1.47210806614649 | 1.3753055265462157 | 24343.00942440838 | 2.312535423847214 | 3.3362833878644325 | 1.0043213737826426 | 3.1780497164141406 | 102.00999999999999 | 10.0 | 11.0 | 10.0 |
+------------------+----------------------+------+------+---------------------+---------------------+--------------------+--------------------+-------------------+------------------+--------------------+-------------------+-------------------+--------------------+--------------------+--------------------+--------------------+-------+------+-------+
-- InfluxQL: SELECT i64, abs(i64 * -1), sin(i64), cos(i64), tan(i64), acos(1/i64), atan(i64), atan2(i64, 2), exp(i64), ln(i64), log2(i64), log10(i64), sqrt(i64), pow(i64, 2), floor(i64), ceil(i64), round(i64) FROM m0 LIMIT 1;
+----------------------+-----+-------+---------------------+--------------------+--------------------+--------------------+-------------------+-----------+----------------------+------------------+-------------------+--------------------+-------------------+-------+-------+-------+-------+
| time | i64 | abs | sin | cos | tan | acos | atan | atan2 | exp | ln | log2 | log10 | sqrt | pow | floor | ceil | round |
+----------------------+-----+-------+---------------------+--------------------+--------------------+--------------------+-------------------+-----------+----------------------+------------------+-------------------+--------------------+-------------------+-------+-------+-------+-------+
| 2022-10-31T02:00:00Z | 101 | 101.0 | 0.45202578717835057 | 0.8920048697881602 | 0.5067526002248183 | 1.5707963267948966 | 1.560895660206908 | 1.5509969 | 7.307059979368067e43 | 4.61512051684126 | 6.658211482751795 | 2.0043213737826426 | 10.04987562112089 | 10201 | 101.0 | 101.0 | 101.0 |
+----------------------+-----+-------+---------------------+--------------------+--------------------+--------------------+-------------------+-----------+----------------------+------------------+-------------------+--------------------+-------------------+-------+-------+-------+-------+
+------------------+----------------------+-----+-------+---------------------+--------------------+--------------------+--------------------+-------------------+-----------+----------------------+------------------+-------------------+--------------------+-------------------+-------+-------+-------+-------+
| iox::measurement | time | i64 | abs | sin | cos | tan | acos | atan | atan2 | exp | ln | log2 | log10 | sqrt | pow | floor | ceil | round |
+------------------+----------------------+-----+-------+---------------------+--------------------+--------------------+--------------------+-------------------+-----------+----------------------+------------------+-------------------+--------------------+-------------------+-------+-------+-------+-------+
| m0 | 2022-10-31T02:00:00Z | 101 | 101.0 | 0.45202578717835057 | 0.8920048697881602 | 0.5067526002248183 | 1.5707963267948966 | 1.560895660206908 | 1.5509969 | 7.307059979368067e43 | 4.61512051684126 | 6.658211482751795 | 2.0043213737826426 | 10.04987562112089 | 10201 | 101.0 | 101.0 | 101.0 |
+------------------+----------------------+-----+-------+---------------------+--------------------+--------------------+--------------------+-------------------+-----------+----------------------+------------------+-------------------+--------------------+-------------------+-------+-------+-------+-------+
-- InfluxQL: SELECT f64, asin(f64), acos(f64) FROM m0 LIMIT 1;
+----------------------+------+------+------+
| time | f64 | asin | acos |
+----------------------+------+------+------+
| 2022-10-31T02:00:00Z | 10.1 | NaN | NaN |
+----------------------+------+------+------+
+------------------+----------------------+------+------+------+
| iox::measurement | time | f64 | asin | acos |
+------------------+----------------------+------+------+------+
| m0 | 2022-10-31T02:00:00Z | 10.1 | NaN | NaN |
+------------------+----------------------+------+------+------+
-- InfluxQL: SELECT f64, pow(f64, pow(2, 10)) FROM m0 LIMIT 1;
+----------------------+------+-----+
| time | f64 | pow |
+----------------------+------+-----+
| 2022-10-31T02:00:00Z | 10.1 | inf |
+----------------------+------+-----+
+------------------+----------------------+------+-----+
| iox::measurement | time | f64 | pow |
+------------------+----------------------+------+-----+
| m0 | 2022-10-31T02:00:00Z | 10.1 | inf |
+------------------+----------------------+------+-----+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 >= 19 + 0.5;
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:10Z | 21.2 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:10Z | 21.2 |
+------------------+----------------------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 - 0.5 >= 19;
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:10Z | 21.2 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:10Z | 21.2 |
+------------------+----------------------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE str = 'h' + 'i';
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:00Z | 10.1 |
| 2022-10-31T02:00:10Z | 21.2 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:00Z | 10.1 |
| m0 | 2022-10-31T02:00:10Z | 21.2 |
+------------------+----------------------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64::integer & 1 = 1;
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:00Z | 11.3 |
| 2022-10-31T02:00:10Z | 21.2 |
| 2022-10-31T02:00:20Z | 11.2 |
| 2022-10-31T02:00:30Z | 19.2 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:00Z | 11.3 |
| m0 | 2022-10-31T02:00:10Z | 21.2 |
| m0 | 2022-10-31T02:00:20Z | 11.2 |
| m0 | 2022-10-31T02:00:30Z | 19.2 |
+------------------+----------------------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64::integer & 1 = 0;
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:00Z | 10.1 |
| 2022-10-31T02:00:00Z | 10.4 |
| 2022-10-31T02:00:10Z | 18.9 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:00Z | 10.1 |
| m0 | 2022-10-31T02:00:00Z | 10.4 |
| m0 | 2022-10-31T02:00:10Z | 18.9 |
+------------------+----------------------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 & 1 = 1;
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:00Z | 11.3 |
| 2022-10-31T02:00:10Z | 21.2 |
| 2022-10-31T02:00:20Z | 11.2 |
| 2022-10-31T02:00:30Z | 19.2 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:00Z | 11.3 |
| m0 | 2022-10-31T02:00:10Z | 21.2 |
| m0 | 2022-10-31T02:00:20Z | 11.2 |
| m0 | 2022-10-31T02:00:30Z | 19.2 |
+------------------+----------------------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 & 1 = 0;
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:00Z | 10.1 |
| 2022-10-31T02:00:00Z | 10.4 |
| 2022-10-31T02:00:10Z | 18.9 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:00Z | 10.1 |
| m0 | 2022-10-31T02:00:00Z | 10.4 |
| m0 | 2022-10-31T02:00:10Z | 18.9 |
+------------------+----------------------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 >= 19 + 0.5 OR str = 1;
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:10Z | 21.2 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:10Z | 21.2 |
+------------------+----------------------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 >= 19.5 AND str = 1;
++
++
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 >= 19 + 0.5 OR non_existent = 1;
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:10Z | 21.2 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:10Z | 21.2 |
+------------------+----------------------+------+
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 >= 19.5 AND non_existent = 1;
++
++
@ -369,36 +372,45 @@
++
++
-- InfluxQL: SELECT f64 FROM m0 WHERE f64 >= 19.5 OR f64 =~ /foo/;
+----------------------+------+
| time | f64 |
+----------------------+------+
| 2022-10-31T02:00:10Z | 21.2 |
+----------------------+------+
+------------------+----------------------+------+
| iox::measurement | time | f64 |
+------------------+----------------------+------+
| m0 | 2022-10-31T02:00:10Z | 21.2 |
+------------------+----------------------+------+
-- InfluxQL: SELECT tag0, f64, f64 * 0.5, f64 + str FROM m0 WHERE f64 > 19;
+----------------------+-------+------+-------+---------+
| time | tag0 | f64 | f64_1 | f64_str |
+----------------------+-------+------+-------+---------+
| 2022-10-31T02:00:10Z | val00 | 21.2 | 10.6 | |
| 2022-10-31T02:00:30Z | val00 | 19.2 | 9.6 | |
+----------------------+-------+------+-------+---------+
+------------------+----------------------+-------+------+-------+---------+
| iox::measurement | time | tag0 | f64 | f64_1 | f64_str |
+------------------+----------------------+-------+------+-------+---------+
| m0 | 2022-10-31T02:00:10Z | val00 | 21.2 | 10.6 | |
| m0 | 2022-10-31T02:00:30Z | val00 | 19.2 | 9.6 | |
+------------------+----------------------+-------+------+-------+---------+
-- InfluxQL: SELECT tag0, str, str + 'foo', str * 5 FROM m0 WHERE f64 > 19;
+----------------------+-------+-----+-------+-------+
| time | tag0 | str | str_1 | str_2 |
+----------------------+-------+-----+-------+-------+
| 2022-10-31T02:00:10Z | val00 | hi | hifoo | |
| 2022-10-31T02:00:30Z | val00 | lo | lofoo | |
+----------------------+-------+-----+-------+-------+
+------------------+----------------------+-------+-----+-------+-------+
| iox::measurement | time | tag0 | str | str_1 | str_2 |
+------------------+----------------------+-------+-----+-------+-------+
| m0 | 2022-10-31T02:00:10Z | val00 | hi | hifoo | |
| m0 | 2022-10-31T02:00:30Z | val00 | lo | lofoo | |
+------------------+----------------------+-------+-----+-------+-------+
-- InfluxQL: SELECT tag0, i64, i64 * 0.5, i64 + f64::integer, i64 & 1 FROM m0 WHERE f64 > 19;
+----------------------+-------+-----+-------+---------+-------+
| time | tag0 | i64 | i64_1 | i64_f64 | i64_2 |
+----------------------+-------+-----+-------+---------+-------+
| 2022-10-31T02:00:10Z | val00 | 211 | 105.5 | 232 | 1 |
| 2022-10-31T02:00:30Z | val00 | 392 | 196.0 | 411 | 0 |
+----------------------+-------+-----+-------+---------+-------+
+------------------+----------------------+-------+-----+-------+---------+-------+
| iox::measurement | time | tag0 | i64 | i64_1 | i64_f64 | i64_2 |
+------------------+----------------------+-------+-----+-------+---------+-------+
| m0 | 2022-10-31T02:00:10Z | val00 | 211 | 105.5 | 232 | 1 |
| m0 | 2022-10-31T02:00:30Z | val00 | 392 | 196.0 | 411 | 0 |
+------------------+----------------------+-------+-----+-------+---------+-------+
-- InfluxQL: SELECT f64, non_existing, f64 + non_existing FROM m0 WHERE f64 > 19;
+----------------------+------+--------------+------------------+
| time | f64 | non_existing | f64_non_existing |
+----------------------+------+--------------+------------------+
| 2022-10-31T02:00:10Z | 21.2 | | |
| 2022-10-31T02:00:30Z | 19.2 | | |
+----------------------+------+--------------+------------------+
+------------------+----------------------+------+--------------+------------------+
| iox::measurement | time | f64 | non_existing | f64_non_existing |
+------------------+----------------------+------+--------------+------------------+
| m0 | 2022-10-31T02:00:10Z | 21.2 | | |
| m0 | 2022-10-31T02:00:30Z | 19.2 | | |
+------------------+----------------------+------+--------------+------------------+
-- InfluxQL: SELECT usage_idle, bytes_used FROM cpu, disk;
+------------------+----------------------+------------+------------+
| iox::measurement | time | usage_idle | bytes_used |
+------------------+----------------------+------------+------------+
| cpu | 2022-10-31T02:00:00Z | 0.98 | |
| cpu | 2022-10-31T02:00:10Z | 0.99 | |
| disk | 2022-10-31T02:00:00Z | | 219838.0 |
| disk | 2022-10-31T02:00:10Z | | 219833.0 |
+------------------+----------------------+------------+------------+

View File

@ -1233,6 +1233,10 @@ pub static SETUPS: Lazy<HashMap<SetupName, SetupSteps>> = Lazy::new(|| {
m1,tag0=val00 f64=100.5,i64=1001i,str="hi" 1667181600000000000
m1,tag0=val00 f64=200.6,i64=2001i,str="lo" 1667181610000000000
m1,tag0=val01 f64=101.7,i64=1011i,str="lo" 1667181600000000000
cpu,host=host1,cpu=cpu0 usage_idle=0.98,usage_system=0.2 1667181600000000000
cpu,host=host1,cpu=cpu0 usage_idle=0.99,usage_system=0.1 1667181610000000000
disk,host=host1,device=disk1s1 bytes_free=1234,bytes_used=219838 1667181600000000000
disk,host=host1,device=disk1s1 bytes_free=1239,bytes_used=219833 1667181610000000000
"#
.to_string(),
),

View File

@ -70,7 +70,7 @@ mod test {
);
assert_eq!(
tag_set,
TagSet::from(["host".to_string(), "region".to_string()])
TagSet::from(["cpu".to_string(), "host".to_string(), "region".to_string()])
);
// Measurement does not exist

View File

@ -8,16 +8,14 @@ use crate::plan::influxql::var_ref::{
use crate::DataFusionError;
use arrow::datatypes::DataType;
use datafusion::common::{Result, ScalarValue, ToDFSchema};
use datafusion::logical_expr::expr::Sort;
use datafusion::logical_expr::expr_rewriter::{normalize_col, ExprRewritable, ExprRewriter};
use datafusion::logical_expr::logical_plan::builder::project;
use datafusion::logical_expr::logical_plan::Analyze;
use datafusion::logical_expr::{
lit, BinaryExpr, BuiltinScalarFunction, Explain, Expr, ExprSchemable, LogicalPlan,
LogicalPlanBuilder, Operator, PlanType, TableSource, ToStringifiedPlan,
binary_expr, lit, BinaryExpr, BuiltinScalarFunction, Explain, Expr, ExprSchemable, LogicalPlan,
LogicalPlanBuilder, Operator, PlanType, Projection, TableSource, ToStringifiedPlan,
};
use datafusion::prelude::{binary_expr, Column};
use datafusion_util::AsExpr;
use datafusion_util::{lit_dict, AsExpr};
use influxdb_influxql_parser::common::OrderByClause;
use influxdb_influxql_parser::explain::{ExplainOption, ExplainStatement};
use influxdb_influxql_parser::expression::{
@ -32,10 +30,11 @@ use influxdb_influxql_parser::{
select::{Field, FieldList, FromMeasurementClause, MeasurementSelection, SelectStatement},
statement::Statement,
};
use itertools::Itertools;
use once_cell::sync::Lazy;
use query_functions::clean_non_meta_escapes;
use schema::{InfluxColumnType, InfluxFieldType, Schema};
use std::collections::HashSet;
use std::collections::{HashSet, VecDeque};
use std::fmt::Debug;
use std::iter;
use std::ops::Deref;
@ -96,7 +95,9 @@ impl<'a> InfluxQLToLogicalPlan<'a> {
Err(DataFusionError::NotImplemented("DROP MEASUREMENT".into()))
}
Statement::Explain(explain) => self.explain_statement_to_plan(*explain),
Statement::Select(select) => self.select_statement_to_plan(*select),
Statement::Select(select) => {
self.select_statement_to_plan(&self.rewrite_select_statement(*select)?)
}
Statement::ShowDatabases(_) => {
Err(DataFusionError::NotImplemented("SHOW DATABASES".into()))
}
@ -119,7 +120,8 @@ impl<'a> InfluxQLToLogicalPlan<'a> {
}
fn explain_statement_to_plan(&self, explain: ExplainStatement) -> Result<LogicalPlan> {
let plan = self.select_statement_to_plan(*explain.select)?;
let plan =
self.select_statement_to_plan(&self.rewrite_select_statement(*explain.select)?)?;
let plan = Arc::new(plan);
let schema = LogicalPlan::explain_schema();
let schema = schema.to_dfschema_ref()?;
@ -149,56 +151,74 @@ impl<'a> InfluxQLToLogicalPlan<'a> {
}
}
fn rewrite_select_statement(&self, select: SelectStatement) -> Result<SelectStatement> {
rewrite_statement(self.s, &select)
}
/// Create a [`LogicalPlan`] from the specified InfluxQL `SELECT` statement.
fn select_statement_to_plan(&self, select: SelectStatement) -> Result<LogicalPlan> {
let select = rewrite_statement(self.s, &select)?;
fn select_statement_to_plan(&self, select: &SelectStatement) -> Result<LogicalPlan> {
let mut plans = self.plan_from_tables(&select.from)?;
// Process FROM clause
let plans = self.plan_from_tables(select.from)?;
let Some(plan) = plans.pop_front() else { return LogicalPlanBuilder::empty(false).build(); };
let plan = self.project_select(plan, select)?;
// Only support a single measurement to begin with
let plan = match plans.len() {
0 => Err(DataFusionError::NotImplemented(
"unsupported FROM: schema must exist".into(),
)),
1 => Ok(plans[0].clone()),
_ => Err(DataFusionError::NotImplemented(
"unsupported FROM: must target a single measurement".into(),
)),
}?;
// If there are multiple measurements, we need to sort by the measurement column
// NOTE: Ideally DataFusion would maintain the order of the UNION ALL, which would eliminate
// the need to sort by measurement.
// See: https://github.com/influxdata/influxdb_iox/issues/7062
let mut series_sort = if !plans.is_empty() {
vec![Expr::sort("iox::measurement".as_expr(), true, false)]
} else {
vec![]
};
let schemas = Schemas::new(plan.schema())?;
let tz = select.timezone.map(|tz| *tz);
let plan = self.plan_where_clause(select.condition, plan, &schemas, tz)?;
// UNION the remaining plans
let plan = plans.into_iter().try_fold(plan, |prev, next| {
let next = self.project_select(next, select)?;
LogicalPlanBuilder::from(prev).union(next)?.build()
})?;
let plan = if select.group_by.is_none() {
LogicalPlanBuilder::from(plan)
.sort(iter::once(Expr::Sort(Sort {
expr: Box::new(Expr::Column(Column {
relation: None,
name: "time".to_string(),
})),
asc: match select.order_by {
// Default behaviour is to sort by time in ascending order if there is no ORDER BY
None | Some(OrderByClause::Ascending) => true,
Some(OrderByClause::Descending) => false,
},
nulls_first: false,
})))?
.build()
// Generate the following sort:
// iox::measurement, time, [projected tags, sorted lexicographically]
series_sort.push(Expr::sort(
"time".as_expr(),
match select.order_by {
// Default behaviour is to sort by time in ascending order if there is no ORDER BY
None | Some(OrderByClause::Ascending) => true,
Some(OrderByClause::Descending) => false,
},
false,
));
series_sort.extend(
select
.fields
.iter()
.filter_map(|f| {
if let IQLExpr::VarRef {
name,
data_type: Some(VarRefDataType::Tag),
} = &f.expr
{
Some(name.deref())
} else {
None
}
})
// the tags must be sorted lexicographically in ascending order to match
// the ordering in InfluxQL
.sorted()
.map(|n| Expr::sort(n.as_expr(), true, false)),
);
LogicalPlanBuilder::from(plan).sort(series_sort)?.build()
} else {
Err(DataFusionError::NotImplemented(
"GROUP BY not supported".into(),
))
}?;
// Process and validate the field expressions in the SELECT projection list
let select_exprs = self.field_list_to_exprs(&plan, select.fields, &schemas)?;
// Wrap the plan in a `LogicalPlan::Projection` from the select expressions
let plan = project(plan, select_exprs)?;
let plan = self.limit(plan, select.offset, select.limit)?;
let plan = self.slimit(plan, select.series_offset, select.series_limit)?;
@ -206,6 +226,27 @@ impl<'a> InfluxQLToLogicalPlan<'a> {
Ok(plan)
}
fn project_select(&self, plan: LogicalPlan, select: &SelectStatement) -> Result<LogicalPlan> {
let (proj, plan) = match plan {
LogicalPlan::Projection(Projection { expr, input, .. }) => {
(expr, input.deref().clone())
}
// TODO: Review when we support subqueries, as this shouldn't be the case
_ => (vec![], plan),
};
let schemas = Schemas::new(plan.schema())?;
let tz = select.timezone.as_deref().cloned();
let plan = self.plan_where_clause(&select.condition, plan, &schemas, tz)?;
// Process and validate the field expressions in the SELECT projection list
let select_exprs = self.field_list_to_exprs(&plan, &select.fields, &schemas)?;
// Wrap the plan in a `LogicalPlan::Projection` from the select expressions
project(plan, proj.into_iter().chain(select_exprs.into_iter()))
}
/// Optionally wrap the input logical plan in a [`LogicalPlan::Limit`] node using the specified
/// `offset` and `limit`.
fn limit(
@ -249,11 +290,11 @@ impl<'a> InfluxQLToLogicalPlan<'a> {
fn field_list_to_exprs(
&self,
plan: &LogicalPlan,
fields: FieldList,
fields: &FieldList,
schemas: &Schemas,
) -> Result<Vec<Expr>> {
// InfluxQL requires the time column is present in the projection list.
let extra = if !has_time_column(&fields) {
let extra = if !has_time_column(fields) {
vec![Field {
expr: IQLExpr::VarRef {
name: "time".into(),
@ -283,12 +324,14 @@ impl<'a> InfluxQLToLogicalPlan<'a> {
) -> Result<Expr> {
let expr = self.expr_to_df_expr(ExprScope::Projection, &field.expr, schemas)?;
let expr = rewrite_field_expr(expr, schemas)?;
if let Some(alias) = &field.alias {
let expr = Expr::Alias(Box::new(expr), alias.deref().into());
normalize_col(expr, plan)
} else {
normalize_col(expr, plan)
}
normalize_col(
if let Some(alias) = &field.alias {
expr.alias(alias.deref())
} else {
expr
},
plan,
)
}
/// Map an InfluxQL [`ConditionalExpression`] to a DataFusion [`Expr`].
@ -504,14 +547,14 @@ impl<'a> InfluxQLToLogicalPlan<'a> {
/// optional InfluxQL conditional expression.
fn plan_where_clause(
&self,
condition: Option<WhereClause>,
condition: &Option<WhereClause>,
plan: LogicalPlan,
schemas: &Schemas,
tz: Option<chrono_tz::Tz>,
) -> Result<LogicalPlan> {
match condition {
Some(where_clause) => {
let filter_expr = self.conditional_to_df_expr(&where_clause, schemas, tz)?;
let filter_expr = self.conditional_to_df_expr(where_clause, schemas, tz)?;
let filter_expr = rewrite_conditional_expr(filter_expr, schemas)?;
let plan = LogicalPlanBuilder::from(plan)
.filter(filter_expr)?
@ -524,10 +567,10 @@ impl<'a> InfluxQLToLogicalPlan<'a> {
/// Generate a list of logical plans for each of the tables references in the `FROM`
/// clause.
fn plan_from_tables(&self, from: FromMeasurementClause) -> Result<Vec<LogicalPlan>> {
let mut plans = vec![];
fn plan_from_tables(&self, from: &FromMeasurementClause) -> Result<VecDeque<LogicalPlan>> {
let mut plans = VecDeque::new();
for ms in from.iter() {
let plan = match ms {
let Some(plan) = match ms {
MeasurementSelection::Name(qn) => match qn.name {
MeasurementName::Name(ref ident) => {
self.create_table_ref(normalize_identifier(ident))
@ -540,20 +583,25 @@ impl<'a> InfluxQLToLogicalPlan<'a> {
MeasurementSelection::Subquery(_) => Err(DataFusionError::NotImplemented(
"subquery in FROM clause".into(),
)),
}?;
plans.push(plan);
}? else { continue };
plans.push_back(plan);
}
Ok(plans)
}
/// Create a [LogicalPlan] that refers to the specified `table_name` or
/// an [LogicalPlan::EmptyRelation] if the table does not exist.
fn create_table_ref(&self, table_name: String) -> Result<LogicalPlan> {
if let Ok(source) = self.s.get_table_provider(&table_name) {
LogicalPlanBuilder::scan(&table_name, source, None)?.build()
/// Create a [LogicalPlan] that refers to the specified `table_name`.
///
/// Normally, this functions will not return a `None`, as tables have been matched]
/// by the [`rewrite_statement`] function.
fn create_table_ref(&self, table_name: String) -> Result<Option<LogicalPlan>> {
Ok(if let Ok(source) = self.s.get_table_provider(&table_name) {
Some(project(
LogicalPlanBuilder::scan(&table_name, source, None)?.build()?,
iter::once(lit_dict(&table_name).alias("iox::measurement")),
)?)
} else {
LogicalPlanBuilder::empty(false).build()
}
None
})
}
}
@ -792,20 +840,51 @@ mod test {
mod select {
use super::*;
/// Verify the behaviour of the `FROM` clause when selecting from zero to many measurements.
#[test]
fn test_from_zero_to_many() {
assert_snapshot!(plan("SELECT host, cpu, device, usage_idle, bytes_used FROM cpu, disk"), @r###"
Sort: iox::measurement ASC NULLS LAST, time ASC NULLS LAST, cpu ASC NULLS LAST, device ASC NULLS LAST, host ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, cpu:Utf8;N, device:Utf8;N, usage_idle:Float64;N, bytes_used:Int64;N]
Union [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, cpu:Utf8;N, device:Utf8;N, usage_idle:Float64;N, bytes_used:Int64;N]
Projection: Dictionary(Int32, Utf8("cpu")) AS iox::measurement, cpu.time, cpu.host AS host, CAST(cpu.cpu AS Utf8) AS cpu, CAST(NULL AS Utf8) AS device, cpu.usage_idle AS usage_idle, CAST(NULL AS Int64) AS bytes_used [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, cpu:Utf8;N, device:Utf8;N, usage_idle:Float64;N, bytes_used:Int64;N]
TableScan: cpu [cpu:Dictionary(Int32, Utf8);N, host:Dictionary(Int32, Utf8);N, region:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), usage_idle:Float64;N, usage_system:Float64;N, usage_user:Float64;N]
Projection: Dictionary(Int32, Utf8("disk")) AS iox::measurement, disk.time, disk.host AS host, CAST(NULL AS Utf8) AS cpu, CAST(disk.device AS Utf8) AS device, CAST(NULL AS Float64) AS usage_idle, disk.bytes_used AS bytes_used [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, cpu:Utf8;N, device:Utf8;N, usage_idle:Float64;N, bytes_used:Int64;N]
TableScan: disk [bytes_free:Int64;N, bytes_used:Int64;N, device:Dictionary(Int32, Utf8);N, host:Dictionary(Int32, Utf8);N, region:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None)]
"###);
// nonexistent
assert_snapshot!(plan("SELECT host, usage_idle FROM non_existent"), @"EmptyRelation []");
assert_snapshot!(plan("SELECT host, usage_idle FROM cpu, non_existent"), @r###"
Sort: cpu.time ASC NULLS LAST, host ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, usage_idle:Float64;N]
Projection: Dictionary(Int32, Utf8("cpu")) AS iox::measurement, cpu.time, cpu.host AS host, cpu.usage_idle AS usage_idle [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, usage_idle:Float64;N]
TableScan: cpu [cpu:Dictionary(Int32, Utf8);N, host:Dictionary(Int32, Utf8);N, region:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), usage_idle:Float64;N, usage_system:Float64;N, usage_user:Float64;N]
"###);
// multiple of same measurement
assert_snapshot!(plan("SELECT host, usage_idle FROM cpu, cpu"), @r###"
Sort: iox::measurement ASC NULLS LAST, time ASC NULLS LAST, host ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, usage_idle:Float64;N]
Union [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, usage_idle:Float64;N]
Projection: Dictionary(Int32, Utf8("cpu")) AS iox::measurement, cpu.time, cpu.host AS host, cpu.usage_idle AS usage_idle [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, usage_idle:Float64;N]
TableScan: cpu [cpu:Dictionary(Int32, Utf8);N, host:Dictionary(Int32, Utf8);N, region:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), usage_idle:Float64;N, usage_system:Float64;N, usage_user:Float64;N]
Projection: Dictionary(Int32, Utf8("cpu")) AS iox::measurement, cpu.time, cpu.host AS host, cpu.usage_idle AS usage_idle [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), host:Dictionary(Int32, Utf8);N, usage_idle:Float64;N]
TableScan: cpu [cpu:Dictionary(Int32, Utf8);N, host:Dictionary(Int32, Utf8);N, region:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), usage_idle:Float64;N, usage_system:Float64;N, usage_user:Float64;N]
"###);
}
#[test]
fn test_time_range_in_where() {
assert_snapshot!(
plan("SELECT foo, f64_field FROM data where time > now() - 10s"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Filter: data.time > now() - IntervalMonthDayNano("10000000000") [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###
);
assert_snapshot!(
plan("SELECT foo, f64_field FROM data where time > '2004-04-09T02:33:45Z'"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Filter: data.time > TimestampNanosecond(1081478025000000000, None) [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###
@ -817,8 +896,8 @@ mod test {
// time on the right-hand side
assert_snapshot!(
plan("SELECT foo, f64_field FROM data where now() - 10s < time"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Filter: now() - IntervalMonthDayNano("10000000000") < data.time [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###
@ -827,16 +906,16 @@ mod test {
// Regular expression equality tests
assert_snapshot!(plan("SELECT foo, f64_field FROM data where foo =~ /f/"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Filter: CAST(data.foo AS Utf8) ~ Utf8("f") [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
// regular expression for a numeric field is rewritten to `false`
assert_snapshot!(plan("SELECT foo, f64_field FROM data where f64_field =~ /f/"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Filter: Boolean(false) [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
@ -844,8 +923,8 @@ mod test {
// regular expression for a non-existent field is rewritten to `false`
assert_snapshot!(
plan("SELECT foo, f64_field FROM data where non_existent =~ /f/"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Filter: Boolean(false) [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###
@ -854,16 +933,16 @@ mod test {
// Regular expression inequality tests
assert_snapshot!(plan("SELECT foo, f64_field FROM data where foo !~ /f/"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Filter: CAST(data.foo AS Utf8) !~ Utf8("f") [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
// regular expression for a numeric field is rewritten to `false`
assert_snapshot!(plan("SELECT foo, f64_field FROM data where f64_field !~ /f/"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Filter: Boolean(false) [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
@ -871,8 +950,8 @@ mod test {
// regular expression for a non-existent field is rewritten to `false`
assert_snapshot!(
plan("SELECT foo, f64_field FROM data where non_existent !~ /f/"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Filter: Boolean(false) [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###
@ -883,49 +962,49 @@ mod test {
fn test_column_matching_rules() {
// Cast between numeric types
assert_snapshot!(plan("SELECT f64_field::integer FROM data"), @r###"
Projection: data.time, CAST(data.f64_field AS Int64) AS f64_field [time:Timestamp(Nanosecond, None), f64_field:Int64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Int64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, CAST(data.f64_field AS Int64) AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Int64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT i64_field::float FROM data"), @r###"
Projection: data.time, CAST(data.i64_field AS Float64) AS i64_field [time:Timestamp(Nanosecond, None), i64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, CAST(data.i64_field AS Float64) AS i64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
// use field selector
assert_snapshot!(plan("SELECT bool_field::field FROM data"), @r###"
Projection: data.time, data.bool_field AS bool_field [time:Timestamp(Nanosecond, None), bool_field:Boolean;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Boolean;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.bool_field AS bool_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Boolean;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
// invalid column reverence
assert_snapshot!(plan("SELECT not_exists::tag FROM data"), @r###"
Projection: data.time, NULL AS not_exists [time:Timestamp(Nanosecond, None), not_exists:Null;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), not_exists:Null;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, NULL AS not_exists [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), not_exists:Null;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT not_exists::field FROM data"), @r###"
Projection: data.time, NULL AS not_exists [time:Timestamp(Nanosecond, None), not_exists:Null;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), not_exists:Null;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, NULL AS not_exists [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), not_exists:Null;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
// Returns NULL for invalid casts
assert_snapshot!(plan("SELECT f64_field::string FROM data"), @r###"
Projection: data.time, NULL AS f64_field [time:Timestamp(Nanosecond, None), f64_field:Null;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Null;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, NULL AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Null;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT f64_field::boolean FROM data"), @r###"
Projection: data.time, NULL AS f64_field [time:Timestamp(Nanosecond, None), f64_field:Null;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Null;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, NULL AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Null;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT str_field::boolean FROM data"), @r###"
Projection: data.time, NULL AS str_field [time:Timestamp(Nanosecond, None), str_field:Null;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, NULL AS str_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
}
@ -934,26 +1013,26 @@ mod test {
fn test_explain() {
assert_snapshot!(plan("EXPLAIN SELECT foo, f64_field FROM data"), @r###"
Explain [plan_type:Utf8, plan:Utf8]
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("EXPLAIN VERBOSE SELECT foo, f64_field FROM data"), @r###"
Explain [plan_type:Utf8, plan:Utf8]
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("EXPLAIN ANALYZE SELECT foo, f64_field FROM data"), @r###"
Analyze [plan_type:Utf8, plan:Utf8]
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("EXPLAIN ANALYZE VERBOSE SELECT foo, f64_field FROM data"), @r###"
Analyze [plan_type:Utf8, plan:Utf8]
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
}
@ -962,150 +1041,150 @@ mod test {
fn test_select_cast_postfix_operator() {
// Float casting
assert_snapshot!(plan("SELECT f64_field::float FROM all_types"), @r###"
Projection: all_types.time, all_types.f64_field AS f64_field [time:Timestamp(Nanosecond, None), f64_field:Float64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, all_types.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Float64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT f64_field::unsigned FROM all_types"), @r###"
Projection: all_types.time, CAST(all_types.f64_field AS UInt64) AS f64_field [time:Timestamp(Nanosecond, None), f64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:UInt64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, CAST(all_types.f64_field AS UInt64) AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:UInt64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT f64_field::integer FROM all_types"), @r###"
Projection: all_types.time, CAST(all_types.f64_field AS Int64) AS f64_field [time:Timestamp(Nanosecond, None), f64_field:Int64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Int64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, CAST(all_types.f64_field AS Int64) AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Int64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT f64_field::string FROM all_types"), @r###"
Projection: all_types.time, NULL AS f64_field [time:Timestamp(Nanosecond, None), f64_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT f64_field::boolean FROM all_types"), @r###"
Projection: all_types.time, NULL AS f64_field [time:Timestamp(Nanosecond, None), f64_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
// Integer casting
assert_snapshot!(plan("SELECT i64_field::float FROM all_types"), @r###"
Projection: all_types.time, CAST(all_types.i64_field AS Float64) AS i64_field [time:Timestamp(Nanosecond, None), i64_field:Float64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, CAST(all_types.i64_field AS Float64) AS i64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Float64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT i64_field::unsigned FROM all_types"), @r###"
Projection: all_types.time, CAST(all_types.i64_field AS UInt64) AS i64_field [time:Timestamp(Nanosecond, None), i64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:UInt64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, CAST(all_types.i64_field AS UInt64) AS i64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:UInt64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT i64_field::integer FROM all_types"), @r###"
Projection: all_types.time, all_types.i64_field AS i64_field [time:Timestamp(Nanosecond, None), i64_field:Int64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Int64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, all_types.i64_field AS i64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Int64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT i64_field::string FROM all_types"), @r###"
Projection: all_types.time, NULL AS i64_field [time:Timestamp(Nanosecond, None), i64_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS i64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT i64_field::boolean FROM all_types"), @r###"
Projection: all_types.time, NULL AS i64_field [time:Timestamp(Nanosecond, None), i64_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS i64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), i64_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
// Unsigned casting
assert_snapshot!(plan("SELECT u64_field::float FROM all_types"), @r###"
Projection: all_types.time, CAST(all_types.u64_field AS Float64) AS u64_field [time:Timestamp(Nanosecond, None), u64_field:Float64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, CAST(all_types.u64_field AS Float64) AS u64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:Float64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT u64_field::unsigned FROM all_types"), @r###"
Projection: all_types.time, all_types.u64_field AS u64_field [time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, all_types.u64_field AS u64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT u64_field::integer FROM all_types"), @r###"
Projection: all_types.time, CAST(all_types.u64_field AS Int64) AS u64_field [time:Timestamp(Nanosecond, None), u64_field:Int64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:Int64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, CAST(all_types.u64_field AS Int64) AS u64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:Int64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT u64_field::string FROM all_types"), @r###"
Projection: all_types.time, NULL AS u64_field [time:Timestamp(Nanosecond, None), u64_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS u64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT u64_field::boolean FROM all_types"), @r###"
Projection: all_types.time, NULL AS u64_field [time:Timestamp(Nanosecond, None), u64_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS u64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), u64_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
// String casting
assert_snapshot!(plan("SELECT str_field::float FROM all_types"), @r###"
Projection: all_types.time, NULL AS str_field [time:Timestamp(Nanosecond, None), str_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS str_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT str_field::unsigned FROM all_types"), @r###"
Projection: all_types.time, NULL AS str_field [time:Timestamp(Nanosecond, None), str_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS str_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT str_field::integer FROM all_types"), @r###"
Projection: all_types.time, NULL AS str_field [time:Timestamp(Nanosecond, None), str_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS str_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT str_field::string FROM all_types"), @r###"
Projection: all_types.time, all_types.str_field AS str_field [time:Timestamp(Nanosecond, None), str_field:Utf8;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Utf8;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, all_types.str_field AS str_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Utf8;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT str_field::boolean FROM all_types"), @r###"
Projection: all_types.time, NULL AS str_field [time:Timestamp(Nanosecond, None), str_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS str_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), str_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
// Boolean casting
assert_snapshot!(plan("SELECT bool_field::float FROM all_types"), @r###"
Projection: all_types.time, NULL AS bool_field [time:Timestamp(Nanosecond, None), bool_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS bool_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT bool_field::unsigned FROM all_types"), @r###"
Projection: all_types.time, NULL AS bool_field [time:Timestamp(Nanosecond, None), bool_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS bool_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT bool_field::integer FROM all_types"), @r###"
Projection: all_types.time, NULL AS bool_field [time:Timestamp(Nanosecond, None), bool_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS bool_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT bool_field::string FROM all_types"), @r###"
Projection: all_types.time, NULL AS bool_field [time:Timestamp(Nanosecond, None), bool_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS bool_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT bool_field::boolean FROM all_types"), @r###"
Projection: all_types.time, all_types.bool_field AS bool_field [time:Timestamp(Nanosecond, None), bool_field:Boolean;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Boolean;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, all_types.bool_field AS bool_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), bool_field:Boolean;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
// Validate various projection expressions with casts
assert_snapshot!(plan("SELECT f64_field::integer + i64_field + u64_field::integer FROM all_types"), @r###"
Projection: all_types.time, CAST(all_types.f64_field AS Int64) + all_types.i64_field + CAST(all_types.u64_field AS Int64) AS f64_field_i64_field_u64_field [time:Timestamp(Nanosecond, None), f64_field_i64_field_u64_field:Int64;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field_i64_field_u64_field:Int64;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, CAST(all_types.f64_field AS Int64) + all_types.i64_field + CAST(all_types.u64_field AS Int64) AS f64_field_i64_field_u64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field_i64_field_u64_field:Int64;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
assert_snapshot!(plan("SELECT f64_field::integer + i64_field + str_field::integer FROM all_types"), @r###"
Projection: all_types.time, NULL AS f64_field_i64_field_str_field [time:Timestamp(Nanosecond, None), f64_field_i64_field_str_field:Null;N]
Sort: all_types.time ASC NULLS LAST [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
Sort: all_types.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field_i64_field_str_field:Null;N]
Projection: Dictionary(Int32, Utf8("all_types")) AS iox::measurement, all_types.time, NULL AS f64_field_i64_field_str_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field_i64_field_str_field:Null;N]
TableScan: all_types [bool_field:Boolean;N, f64_field:Float64;N, i64_field:Int64;N, str_field:Utf8;N, tag0:Dictionary(Int32, Utf8);N, tag1:Dictionary(Int32, Utf8);N, time:Timestamp(Nanosecond, None), u64_field:UInt64;N]
"###);
}
@ -1120,43 +1199,44 @@ mod test {
#[test]
fn test_single_measurement() {
assert_snapshot!(plan("SELECT f64_field FROM data"), @r###"
Projection: data.time, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT time, f64_field FROM data"), @r###"
Projection: data.time AS time, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time AS time, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT time as timestamp, f64_field FROM data"), @r###"
Projection: data.time AS timestamp, data.f64_field AS f64_field [timestamp:Timestamp(Nanosecond, None), f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Projection: iox::measurement, timestamp, f64_field [iox::measurement:Dictionary(Int32, Utf8), timestamp:Timestamp(Nanosecond, None), f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), timestamp:Timestamp(Nanosecond, None), f64_field:Float64;N, time:Timestamp(Nanosecond, None)]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time AS timestamp, data.f64_field AS f64_field, data.time [iox::measurement:Dictionary(Int32, Utf8), timestamp:Timestamp(Nanosecond, None), f64_field:Float64;N, time:Timestamp(Nanosecond, None)]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT foo, f64_field FROM data"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT foo, f64_field, i64_field FROM data"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field AS f64_field, data.i64_field AS i64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N, i64_field:Int64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N, i64_field:Int64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field AS f64_field, data.i64_field AS i64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N, i64_field:Int64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT /^f/ FROM data"), @r###"
Projection: data.time, data.f64_field AS f64_field, data.foo AS foo [time:Timestamp(Nanosecond, None), f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.f64_field AS f64_field, data.foo AS foo [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT * FROM data"), @r###"
Projection: data.time, data.TIME AS TIME, data.bar AS bar, data.bool_field AS bool_field, data.f64_field AS f64_field, data.foo AS foo, data.i64_field AS i64_field, data.mixedCase AS mixedCase, data.str_field AS str_field, data.with space AS with space [time:Timestamp(Nanosecond, None), TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, with space:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, bar ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, with space:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.TIME AS TIME, data.bar AS bar, data.bool_field AS bool_field, data.f64_field AS f64_field, data.foo AS foo, data.i64_field AS i64_field, data.mixedCase AS mixedCase, data.str_field AS str_field, data.with space AS with space [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, with space:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT TIME FROM data"), @r###"
Projection: data.time, data.TIME AS TIME [time:Timestamp(Nanosecond, None), TIME:Boolean;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), TIME:Boolean;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.TIME AS TIME [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), TIME:Boolean;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###); // TIME is a field
}
@ -1165,23 +1245,23 @@ mod test {
#[test]
fn test_simple_arithmetic_in_projection() {
assert_snapshot!(plan("SELECT foo, f64_field + f64_field FROM data"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field + data.f64_field AS f64_field_f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field_f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field_f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field + data.f64_field AS f64_field_f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field_f64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT foo, sin(f64_field) FROM data"), @r###"
Projection: data.time, data.foo AS foo, sin(data.f64_field) AS sin [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, sin:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, sin:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, sin(data.f64_field) AS sin [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, sin:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT foo, atan2(f64_field, 2) FROM data"), @r###"
Projection: data.time, data.foo AS foo, atan2(data.f64_field, Int64(2)) AS atan2 [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, atan2:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, atan2:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, atan2(data.f64_field, Int64(2)) AS atan2 [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, atan2:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
assert_snapshot!(plan("SELECT foo, f64_field + 0.5 FROM data"), @r###"
Projection: data.time, data.foo AS foo, data.f64_field + Float64(0.5) AS f64_field [time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Sort: data.time ASC NULLS LAST [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
Sort: data.time ASC NULLS LAST, foo ASC NULLS LAST [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
Projection: Dictionary(Int32, Utf8("data")) AS iox::measurement, data.time, data.foo AS foo, data.f64_field + Float64(0.5) AS f64_field [iox::measurement:Dictionary(Int32, Utf8), time:Timestamp(Nanosecond, None), foo:Dictionary(Int32, Utf8);N, f64_field:Float64;N]
TableScan: data [TIME:Boolean;N, bar:Dictionary(Int32, Utf8);N, bool_field:Boolean;N, f64_field:Float64;N, foo:Dictionary(Int32, Utf8);N, i64_field:Int64;N, mixedCase:Float64;N, str_field:Utf8;N, time:Timestamp(Nanosecond, None), with space:Float64;N]
"###);
}

View File

@ -554,14 +554,14 @@ mod test {
let stmt = rewrite_statement(&namespace, &stmt).unwrap();
assert_eq!(
stmt.to_string(),
"SELECT host::tag AS host, region::tag AS region, usage_idle::float AS usage_idle, usage_system::float AS usage_system, usage_user::float AS usage_user FROM cpu"
"SELECT cpu::tag AS cpu, host::tag AS host, region::tag AS region, usage_idle::float AS usage_idle, usage_system::float AS usage_system, usage_user::float AS usage_user FROM cpu"
);
let stmt = parse_select("SELECT * FROM cpu, disk");
let stmt = rewrite_statement(&namespace, &stmt).unwrap();
assert_eq!(
stmt.to_string(),
"SELECT bytes_free::integer AS bytes_free, bytes_used::integer AS bytes_used, host::tag AS host, region::tag AS region, usage_idle::float AS usage_idle, usage_system::float AS usage_system, usage_user::float AS usage_user FROM cpu, disk"
"SELECT bytes_free::integer AS bytes_free, bytes_used::integer AS bytes_used, cpu::tag AS cpu, device::tag AS device, host::tag AS host, region::tag AS region, usage_idle::float AS usage_idle, usage_system::float AS usage_system, usage_user::float AS usage_user FROM cpu, disk"
);
// Regular expression selects fields from multiple measurements
@ -577,7 +577,7 @@ mod test {
let stmt = rewrite_statement(&namespace, &stmt).unwrap();
assert_eq!(
stmt.to_string(),
"SELECT host::tag AS host, region::tag AS region FROM cpu"
"SELECT cpu::tag AS cpu, host::tag AS host, region::tag AS region FROM cpu"
);
// Selective wildcard for fields
@ -593,7 +593,7 @@ mod test {
let stmt = rewrite_statement(&namespace, &stmt).unwrap();
assert_eq!(
stmt.to_string(),
"SELECT usage_idle::float AS usage_idle, host::tag AS host, region::tag AS region FROM cpu"
"SELECT usage_idle::float AS usage_idle, cpu::tag AS cpu, host::tag AS host, region::tag AS region FROM cpu"
);
// GROUP BY expansion
@ -609,7 +609,7 @@ mod test {
let stmt = rewrite_statement(&namespace, &stmt).unwrap();
assert_eq!(
stmt.to_string(),
"SELECT usage_idle::float AS usage_idle FROM cpu GROUP BY host, region"
"SELECT usage_idle::float AS usage_idle FROM cpu GROUP BY cpu, host, region"
);
// Does not include tags in projection when expanded in GROUP BY
@ -617,7 +617,7 @@ mod test {
let stmt = rewrite_statement(&namespace, &stmt).unwrap();
assert_eq!(
stmt.to_string(),
"SELECT usage_idle::float AS usage_idle, usage_system::float AS usage_system, usage_user::float AS usage_user FROM cpu GROUP BY host, region"
"SELECT usage_idle::float AS usage_idle, usage_system::float AS usage_system, usage_user::float AS usage_user FROM cpu GROUP BY cpu, host, region"
);
// Does include explicitly listed tags in projection
@ -625,7 +625,7 @@ mod test {
let stmt = rewrite_statement(&namespace, &stmt).unwrap();
assert_eq!(
stmt.to_string(),
"SELECT host::tag AS host, usage_idle::float AS usage_idle, usage_system::float AS usage_system, usage_user::float AS usage_user FROM cpu GROUP BY host, region"
"SELECT host::tag AS host, usage_idle::float AS usage_idle, usage_system::float AS usage_system, usage_user::float AS usage_user FROM cpu GROUP BY cpu, host, region"
);
// Fallible

View File

@ -55,6 +55,7 @@ pub(crate) mod database {
.with_time_column()
.with_tag_column("host")
.with_tag_column("region")
.with_tag_column("cpu")
.with_f64_field_column("usage_user")
.with_f64_field_column("usage_system")
.with_f64_field_column("usage_idle")
@ -67,6 +68,7 @@ pub(crate) mod database {
.with_time_column()
.with_tag_column("host")
.with_tag_column("region")
.with_tag_column("device")
.with_i64_field_column("bytes_used")
.with_i64_field_column("bytes_free")
.with_one_row_of_data(),