diff --git a/influxdb_iox/tests/end_to_end_cases/influxql.rs b/influxdb_iox/tests/end_to_end_cases/influxql.rs index 2345ec8ff1..f9f8da43ab 100644 --- a/influxdb_iox/tests/end_to_end_cases/influxql.rs +++ b/influxdb_iox/tests/end_to_end_cases/influxql.rs @@ -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 |", + "+------------------+--------------------------------+------+-----+", ], }, ], diff --git a/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql b/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql index 408b63661f..30a42f17de 100644 --- a/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql +++ b/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql @@ -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; \ No newline at end of file diff --git a/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql.expected b/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql.expected index 9818274054..b4198d805e 100644 --- a/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql.expected +++ b/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql.expected @@ -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 | | | -+----------------------+------+--------------+------------------+ \ No newline at end of file ++------------------+----------------------+------+--------------+------------------+ +| 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 | ++------------------+----------------------+------------+------------+ \ No newline at end of file diff --git a/influxdb_iox/tests/query_tests2/setups.rs b/influxdb_iox/tests/query_tests2/setups.rs index 05c8a073b5..14bf2ba253 100644 --- a/influxdb_iox/tests/query_tests2/setups.rs +++ b/influxdb_iox/tests/query_tests2/setups.rs @@ -1233,6 +1233,10 @@ pub static SETUPS: Lazy> = 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(), ), diff --git a/iox_query/src/plan/influxql/field_mapper.rs b/iox_query/src/plan/influxql/field_mapper.rs index 5fdcb64b8a..d50e387df2 100644 --- a/iox_query/src/plan/influxql/field_mapper.rs +++ b/iox_query/src/plan/influxql/field_mapper.rs @@ -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 diff --git a/iox_query/src/plan/influxql/planner.rs b/iox_query/src/plan/influxql/planner.rs index f77b61ca34..928efc337f 100644 --- a/iox_query/src/plan/influxql/planner.rs +++ b/iox_query/src/plan/influxql/planner.rs @@ -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 { - 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 { + rewrite_statement(self.s, &select) + } + /// Create a [`LogicalPlan`] from the specified InfluxQL `SELECT` statement. - fn select_statement_to_plan(&self, select: SelectStatement) -> Result { - let select = rewrite_statement(self.s, &select)?; + fn select_statement_to_plan(&self, select: &SelectStatement) -> Result { + 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 { + 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> { // 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 { 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, + condition: &Option, plan: LogicalPlan, schemas: &Schemas, tz: Option, ) -> Result { 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> { - let mut plans = vec![]; + fn plan_from_tables(&self, from: &FromMeasurementClause) -> Result> { + 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 { - 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> { + 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] "###); } diff --git a/iox_query/src/plan/influxql/rewriter.rs b/iox_query/src/plan/influxql/rewriter.rs index f1072c1e0c..f595a5cb13 100644 --- a/iox_query/src/plan/influxql/rewriter.rs +++ b/iox_query/src/plan/influxql/rewriter.rs @@ -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 diff --git a/iox_query/src/plan/influxql/test_utils.rs b/iox_query/src/plan/influxql/test_utils.rs index f322dc799c..9971ddb44d 100644 --- a/iox_query/src/plan/influxql/test_utils.rs +++ b/iox_query/src/plan/influxql/test_utils.rs @@ -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(),