diff --git a/influxdb_iox/build.rs b/influxdb_iox/build.rs index f5ec762286..55dbb86234 100644 --- a/influxdb_iox/build.rs +++ b/influxdb_iox/build.rs @@ -5,6 +5,7 @@ use std::process::Command; fn main() -> Result<(), Box> { + println!("cargo:rerun-if-env-changed=GIT_HASH"); // Populate env!(GIT_HASH) with the current git commit println!("cargo:rustc-env=GIT_HASH={}", get_git_hash()); diff --git a/influxdb_iox/tests/query_tests2/cases.rs b/influxdb_iox/tests/query_tests2/cases.rs index 9f013839fc..b02bb08276 100644 --- a/influxdb_iox/tests/query_tests2/cases.rs +++ b/influxdb_iox/tests/query_tests2/cases.rs @@ -13,9 +13,9 @@ //! ``` //! Possibly helpful commands: //! # See diff -//! diff -du "cases/in/pushdown.expected" "cases/out/pushdown.out" +//! diff -du "cases/in/pushdown.sql.expected" "cases/out/pushdown.sql.out" //! # Update expected -//! cp -f "cases/in/pushdown.out" "cases/out/pushdown.expected" +//! cp -f "cases/in/pushdown.sql.out" "cases/out/pushdown.sql.expected" //! ``` //! //! # Cookbook: Adding a new test scenario @@ -300,3 +300,19 @@ async fn different_tag_sets() { .run() .await; } + +mod influxql { + use super::*; + + #[tokio::test] + async fn issue_6112() { + test_helpers::maybe_start_logging(); + + TestCase { + input: "cases/in/issue_6112.influxql", + chunk_stage: ChunkStage::All, + } + .run() + .await; + } +} diff --git a/influxdb_iox/tests/query_tests2/cases/in/aggregates.expected b/influxdb_iox/tests/query_tests2/cases/in/aggregates.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/aggregates.expected rename to influxdb_iox/tests/query_tests2/cases/in/aggregates.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/aggregates_with_nulls.expected b/influxdb_iox/tests/query_tests2/cases/in/aggregates_with_nulls.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/aggregates_with_nulls.expected rename to influxdb_iox/tests/query_tests2/cases/in/aggregates_with_nulls.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/basic.expected b/influxdb_iox/tests/query_tests2/cases/in/basic.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/basic.expected rename to influxdb_iox/tests/query_tests2/cases/in/basic.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/dedup_and_predicates_parquet.expected b/influxdb_iox/tests/query_tests2/cases/in/dedup_and_predicates_parquet.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/dedup_and_predicates_parquet.expected rename to influxdb_iox/tests/query_tests2/cases/in/dedup_and_predicates_parquet.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/dedup_and_predicates_parquet_ingester.expected b/influxdb_iox/tests/query_tests2/cases/in/dedup_and_predicates_parquet_ingester.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/dedup_and_predicates_parquet_ingester.expected rename to influxdb_iox/tests/query_tests2/cases/in/dedup_and_predicates_parquet_ingester.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/different_tag_sets.expected b/influxdb_iox/tests/query_tests2/cases/in/different_tag_sets.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/different_tag_sets.expected rename to influxdb_iox/tests/query_tests2/cases/in/different_tag_sets.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/duplicates_ingester.expected b/influxdb_iox/tests/query_tests2/cases/in/duplicates_ingester.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/duplicates_ingester.expected rename to influxdb_iox/tests/query_tests2/cases/in/duplicates_ingester.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/duplicates_parquet.expected b/influxdb_iox/tests/query_tests2/cases/in/duplicates_parquet.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/duplicates_parquet.expected rename to influxdb_iox/tests/query_tests2/cases/in/duplicates_parquet.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/duplicates_parquet_many.expected b/influxdb_iox/tests/query_tests2/cases/in/duplicates_parquet_many.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/duplicates_parquet_many.expected rename to influxdb_iox/tests/query_tests2/cases/in/duplicates_parquet_many.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql b/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql new file mode 100644 index 0000000000..e7690b956f --- /dev/null +++ b/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql @@ -0,0 +1,123 @@ +-- Query tests derived from https://github.com/influxdata/influxdb_iox/issues/6112 +-- IOX_SETUP: InfluxQLSelectSupport + +-- +-- Single measurement queries +-- + +-- Projection wildcard, all tags and fields +-- IOX_COMPARE: sorted +SELECT * FROM m0; + +-- Projection wildcard, only tags +-- IOX_COMPARE: sorted +SELECT *::tag, f64 FROM m0; + +-- Projection wildcard, only fields +-- IOX_COMPARE: sorted +SELECT *::field FROM m0; + +-- Projection regex, mixture of tags and fields +-- IOX_COMPARE: sorted +SELECT /64|tag0/ FROM m0; + +-- Projection specific tags and fields +-- IOX_COMPARE: sorted +SELECT f64, tag0 FROM m0; + +-- Explicitly select time column +-- IOX_COMPARE: sorted +SELECT f64, tag0, time FROM m0; + +-- Validate some math functions +-- IOX_COMPARE: sorted +SELECT f64, floor(f64), ceil(f64) FROM m0; + +-- Validate all scalar functions +-- -- IOX_COMPARE: sorted +-- TODO(sgc): log expects two arguments +-- TODO(sgc): asin and acos should cast NaN to NULL +-- SELECT f64, abs(f64), sin(f64), cos(f64), tan(f64), +-- asin(f64), acos(f64), atan(f64), atan2(f64, 1), +-- exp(f64), log(f64), ln(f64), log2(f64), +-- log10(f64), sqrt(f64), pow(f64, 2), floor(f64), +-- ceil(f64), round(f64) +-- FROM m0 LIMIT 1; + +-- arithmetic operators +-- IOX_COMPARE: sorted +SELECT f64, f64 * 2, i64, i64 + i64 FROM m0; + +-- bitwise operators +-- IOX_COMPARE: sorted +SELECT i64, i64 & 1 FROM m0; + +-- Automatic type coercion integer → float +-- IOX_COMPARE: sorted +SELECT f64 + i64 FROM m0; + + +-- Type cast postfix operator +-- -- IOX_COMPARE: sorted +-- TODO(sgc): cast operator not implemented +-- SELECT f64, f64::integer FROM m0; + +-- Column alias behaviour +-- IOX_COMPARE: sorted +SELECT f64 AS f64_2, f64, f64, f64 FROM m0 LIMIT 1; + +-- +-- WHERE clause +-- + +-- Single tag +-- IOX_COMPARE: sorted +SELECT tag0, f64 FROM m0 WHERE tag0 = 'val00'; + +-- IOX_COMPARE: sorted +SELECT tag0, f64 FROM m0 WHERE tag0 =~ /^val0(1|2)/; + +-- Conjunction (AND) +-- IOX_COMPARE: sorted +SELECT /tag(0|1)/, f64 FROM m0 WHERE tag0 = 'val00' AND tag1 = 'val10'; + +-- Disjunction (OR) +-- IOX_COMPARE: sorted +SELECT /tag(0|1)/, f64 FROM m0 WHERE tag0 = 'val00' OR tag1 = 'val10'; + +-- arithmetic +-- IOX_COMPARE: sorted +SELECT f64 FROM m0 WHERE f64 > 10 + 10; + +-- bitwise +-- IOX_COMPARE: sorted +SELECT i64 FROM m0 WHERE i64 & 1 = 0; + +-- time bounds + +-- timestamp format %Y-%M-%D +-- IOX_COMPARE: sorted +SELECT i64 FROM m0 WHERE time > '2022-10-31'; + +-- timestamp format %Y-%M-%D %h:%m:%s +-- IOX_COMPARE: sorted +SELECT i64 FROM m0 WHERE time > '2022-10-31 02:00:10'; + +-- now() and duration +-- NOTE: 100000d is > 270 years, so this test should be ok for a while. +-- However, if this test is still in use in 270 years and it starts failing, +-- try increasing the number of days 😂 +-- IOX_COMPARE: sorted +SELECT i64 FROM m0 WHERE time > now() - 100000d; + +-- NOT NULL test +-- WHERE tag1 != '' is the equivalent to tag1 IS NOT NULL +-- TODO(sgc): This is working, but likely by accident +-- IOX_COMPARE: sorted +SELECT tag1, f64 FROM m0 WHERE tag1 != ''; + +-- NULL test +-- WHERE tag1 = '' is the equivalent to tag1 IS NULL +-- TODO(sgc): Not working, as expected +-- -- IOX_COMPARE: sorted +-- SELECT tag1, f64 FROM m0 WHERE tag1 = ''; 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 new file mode 100644 index 0000000000..8496502694 --- /dev/null +++ b/influxdb_iox/tests/query_tests2/cases/in/issue_6112.influxql.expected @@ -0,0 +1,230 @@ +-- 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 | | ++----------------------+------+-----+-----+-------+-------+ +-- 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 | ++----------------------+-------+-------+------+ +-- 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 | ++----------------------+------+-----+-----+ +-- 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 | ++----------------------+------+-----+-------+ +-- 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 | ++----------------------+------+-------+ +-- 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 | ++------+-------+----------------------+ +-- InfluxQL: SELECT f64, floor(f64), ceil(f64) FROM m0; +-- Results After Sorting ++----------------------+------+-------+------+ +| time | f64 | floor | ceil | ++----------------------+------+-------+------+ +| 2022-10-31T02:00:00Z | 10.1 | 10 | 11 | +| 2022-10-31T02:00:00Z | 10.4 | 10 | 11 | +| 2022-10-31T02:00:00Z | 11.3 | 11 | 12 | +| 2022-10-31T02:00:10Z | 18.9 | 18 | 19 | +| 2022-10-31T02:00:10Z | 21.2 | 21 | 22 | +| 2022-10-31T02:00:20Z | 11.2 | 11 | 12 | +| 2022-10-31T02:00:30Z | 19.2 | 19 | 20 | ++----------------------+------+-------+------+ +-- 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 | ++----------------------+------+-------+-----+---------+ +-- 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 | ++----------------------+-----+-------+ +-- 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 | ++----------------------+---------+ +-- 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 | ++----------------------+-------+------+-------+-------+ +-- 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 | ++----------------------+-------+------+ +-- 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 | ++----------------------+-------+------+ +-- 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 | ++----------------------+-------+-------+------+ +-- 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 | ++----------------------+-------+-------+------+ +-- InfluxQL: SELECT f64 FROM m0 WHERE f64 > 10 + 10; +-- Results After Sorting ++----------------------+------+ +| time | f64 | ++----------------------+------+ +| 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 | ++----------------------+-----+ +-- 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 | ++----------------------+-----+ +-- 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 | ++----------------------+-----+ +-- 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 | ++----------------------+-----+ +-- InfluxQL: SELECT tag1, f64 FROM m0 WHERE tag1 != ''; +-- Results After Sorting ++----------------------+-------+------+ +| time | tag1 | f64 | ++----------------------+-------+------+ +| 2022-10-31T02:00:10Z | val10 | 18.9 | ++----------------------+-------+------+ \ No newline at end of file diff --git a/influxdb_iox/tests/query_tests2/cases/in/new_sql_system_tables.expected b/influxdb_iox/tests/query_tests2/cases/in/new_sql_system_tables.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/new_sql_system_tables.expected rename to influxdb_iox/tests/query_tests2/cases/in/new_sql_system_tables.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/periods.expected b/influxdb_iox/tests/query_tests2/cases/in/periods.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/periods.expected rename to influxdb_iox/tests/query_tests2/cases/in/periods.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/pushdown.expected b/influxdb_iox/tests/query_tests2/cases/in/pushdown.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/pushdown.expected rename to influxdb_iox/tests/query_tests2/cases/in/pushdown.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/restaurant.expected b/influxdb_iox/tests/query_tests2/cases/in/restaurant.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/restaurant.expected rename to influxdb_iox/tests/query_tests2/cases/in/restaurant.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/retention.expected b/influxdb_iox/tests/query_tests2/cases/in/retention.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/retention.expected rename to influxdb_iox/tests/query_tests2/cases/in/retention.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/schema_merge.expected b/influxdb_iox/tests/query_tests2/cases/in/schema_merge.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/schema_merge.expected rename to influxdb_iox/tests/query_tests2/cases/in/schema_merge.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/selectors.expected b/influxdb_iox/tests/query_tests2/cases/in/selectors.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/selectors.expected rename to influxdb_iox/tests/query_tests2/cases/in/selectors.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/several_chunks.expected b/influxdb_iox/tests/query_tests2/cases/in/several_chunks.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/several_chunks.expected rename to influxdb_iox/tests/query_tests2/cases/in/several_chunks.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/sql_information_schema.expected b/influxdb_iox/tests/query_tests2/cases/in/sql_information_schema.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/sql_information_schema.expected rename to influxdb_iox/tests/query_tests2/cases/in/sql_information_schema.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/timestamps.expected b/influxdb_iox/tests/query_tests2/cases/in/timestamps.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/timestamps.expected rename to influxdb_iox/tests/query_tests2/cases/in/timestamps.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/two_chunks.expected b/influxdb_iox/tests/query_tests2/cases/in/two_chunks.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/two_chunks.expected rename to influxdb_iox/tests/query_tests2/cases/in/two_chunks.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/two_chunks_missing_columns.expected b/influxdb_iox/tests/query_tests2/cases/in/two_chunks_missing_columns.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/two_chunks_missing_columns.expected rename to influxdb_iox/tests/query_tests2/cases/in/two_chunks_missing_columns.sql.expected diff --git a/influxdb_iox/tests/query_tests2/cases/in/union_all.expected b/influxdb_iox/tests/query_tests2/cases/in/union_all.sql.expected similarity index 100% rename from influxdb_iox/tests/query_tests2/cases/in/union_all.expected rename to influxdb_iox/tests/query_tests2/cases/in/union_all.sql.expected diff --git a/influxdb_iox/tests/query_tests2/framework.rs b/influxdb_iox/tests/query_tests2/framework.rs index 9bcfccc420..e6b298bcb2 100644 --- a/influxdb_iox/tests/query_tests2/framework.rs +++ b/influxdb_iox/tests/query_tests2/framework.rs @@ -89,7 +89,7 @@ impl TestCase { let given_input_path: PathBuf = self.input.into(); let mut input_path = PathBuf::from("tests/query_tests2/"); - input_path.push(given_input_path); + input_path.push(given_input_path.clone()); let contents = fs::read_to_string(&input_path).unwrap_or_else(|_| { panic!("Could not read test case file `{}`", input_path.display()) }); @@ -120,10 +120,21 @@ impl TestCase { (_, other) => vec![other], }); - let test_step = Step::QueryAndCompare { - input_path, - setup_name: setup_name.into(), - contents, + let test_step = match given_input_path.extension() { + Some(ext) if ext == "sql" => Step::QueryAndCompare { + input_path, + setup_name: setup_name.into(), + contents, + }, + Some(ext) if ext == "influxql" => Step::InfluxQLQueryAndCompare { + input_path, + setup_name: setup_name.into(), + contents, + }, + _ => panic!( + "invalid language extension for path {}: expected sql or influxql", + self.input + ), }; // Run the tests diff --git a/influxdb_iox/tests/query_tests2/setups.rs b/influxdb_iox/tests/query_tests2/setups.rs index c27e1a146a..7ea9a963d0 100644 --- a/influxdb_iox/tests/query_tests2/setups.rs +++ b/influxdb_iox/tests/query_tests2/setups.rs @@ -1197,6 +1197,32 @@ pub static SETUPS: Lazy> = Lazy::new(|| { }, ], ), + ( + // This is the dataset defined by https://github.com/influxdata/influxdb_iox/issues/6112 + "InfluxQLSelectSupport", + vec![ + Step::RecordNumParquetFiles, + Step::WriteLineProtocol( + r#" + m0,tag0=val00 f64=10.1,i64=101i,str="hi" 1667181600000000000 + m0,tag0=val00 f64=21.2,i64=211i,str="hi" 1667181610000000000 + m0,tag0=val00 f64=11.2,i64=191i,str="lo" 1667181620000000000 + m0,tag0=val00 f64=19.2,i64=392i,str="lo" 1667181630000000000 + m0,tag0=val01 f64=11.3,i64=211i,str="lo" 1667181600000000000 + m0,tag0=val02 f64=10.4,i64=101i,str="lo" 1667181600000000000 + m0,tag0=val00,tag1=val10 f64=18.9,i64=211i,str="lo" 1667181610000000000 + 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 + "# + .to_string(), + ), + Step::Persist, + Step::WaitForPersisted2 { + expected_increase: 2, + }, + ], + ), ]) }); diff --git a/test_helpers_end_to_end/src/snapshot_comparison.rs b/test_helpers_end_to_end/src/snapshot_comparison.rs index d6b8a9483d..d8e3144381 100644 --- a/test_helpers_end_to_end/src/snapshot_comparison.rs +++ b/test_helpers_end_to_end/src/snapshot_comparison.rs @@ -1,7 +1,8 @@ -use crate::{run_sql, MiniCluster}; +use crate::{run_influxql, run_sql, MiniCluster}; use arrow_util::{display::pretty_format_batches, test_util::sort_record_batch}; use regex::{Captures, Regex}; use snafu::{OptionExt, ResultExt, Snafu}; +use std::fmt::{Display, Formatter}; use std::{ collections::HashMap, fs, @@ -45,15 +46,41 @@ pub enum Error { pub type Result = std::result::Result; +#[derive(Debug, Clone, Copy, Default)] +pub enum Language { + #[default] + Sql, + InfluxQL, +} + +impl Display for Language { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Language::Sql => Display::fmt("SQL", f), + Language::InfluxQL => Display::fmt("InfluxQL", f), + } + } +} + pub async fn run( cluster: &mut MiniCluster, input_path: PathBuf, setup_name: String, contents: String, + language: Language, ) -> Result<()> { // create output and expected output let output_path = make_output_path(&input_path)?; - let expected_path = input_path.with_extension("expected"); + let expected_path = { + let mut p = input_path.clone(); + let ext = p + .extension() + .expect("input path missing extension") + .to_str() + .expect("input path extension is not valid UTF-8"); + p.set_extension(format!("{}.expected", ext)); + p + }; println!("Running case in {:?}", input_path); println!(" writing output to {:?}", output_path); @@ -66,7 +93,7 @@ pub async fn run( output.push(format!("-- Test Setup: {setup_name}")); for q in queries.iter() { - output.push(format!("-- SQL: {}", q.sql())); + output.push(format!("-- {}: {}", language, q.text())); if q.sorted_compare() { output.push("-- Results After Sorting".into()) } @@ -80,7 +107,7 @@ pub async fn run( output.push("-- Results After Normalizing Filters".into()) } - let results = run_query(cluster, q).await?; + let results = run_query(cluster, q, language).await?; output.extend(results); } @@ -146,15 +173,21 @@ pub enum OutputPathError { #[snafu(display("Input path has no file stem: '{:?}'", path))] NoFileStem { path: PathBuf }, + #[snafu(display("Input path missing file extension: '{:?}'", path))] + MissingFileExt { path: PathBuf }, + #[snafu(display("Input path has no parent?!: '{:?}'", path))] NoParent { path: PathBuf }, } /// Return output path for input path. /// -/// This converts `some/prefix/in/foo.sql` (or other file extensions) to `some/prefix/out/foo.out`. +/// This converts `some/prefix/in/foo.sql` (or other file extensions) to `some/prefix/out/foo.sql.out`. fn make_output_path(input: &Path) -> Result { let stem = input.file_stem().context(NoFileStemSnafu { path: input })?; + let ext = input + .extension() + .context(MissingFileExtSnafu { path: input })?; // go two levels up (from file to dir, from dir to parent dir) let parent = input.parent().context(NoParentSnafu { path: input })?; @@ -174,7 +207,10 @@ fn make_output_path(input: &Path) -> Result { // set file name and ext out.push(stem); - out.set_extension("out"); + out.set_extension(format!( + "{}.out", + ext.to_str().expect("extension is not valid UTF-8") + )); Ok(out) } @@ -186,15 +222,31 @@ fn make_absolute(path: &Path) -> PathBuf { absolute } -async fn run_query(cluster: &MiniCluster, query: &Query) -> Result> { - let sql = query.sql(); +async fn run_query( + cluster: &MiniCluster, + query: &Query, + language: Language, +) -> Result> { + let query_text = query.text(); - let mut results = run_sql( - sql, - cluster.namespace(), - cluster.querier().querier_grpc_connection(), - ) - .await; + let mut results = match language { + Language::Sql => { + run_sql( + query_text, + cluster.namespace(), + cluster.querier().querier_grpc_connection(), + ) + .await + } + Language::InfluxQL => { + run_influxql( + query_text, + cluster.namespace(), + cluster.querier().querier_grpc_connection(), + ) + .await + } + }; // compare against sorted results, if requested if query.sorted_compare() && !results.is_empty() { @@ -334,20 +386,20 @@ pub struct Query { /// `FilterExec: ` normalized_filters: bool, - /// The SQL string - sql: String, + /// The query string + text: String, } impl Query { #[cfg(test)] - fn new(sql: impl Into) -> Self { - let sql = sql.into(); + fn new(text: impl Into) -> Self { + let text = text.into(); Self { sorted_compare: false, normalized_uuids: false, normalized_metrics: false, normalized_filters: false, - sql, + text, } } @@ -357,9 +409,9 @@ impl Query { self } - /// Get a reference to the query's sql. - pub fn sql(&self) -> &str { - self.sql.as_ref() + /// Get a reference to the query text. + pub fn text(&self) -> &str { + self.text.as_ref() } /// Get the query's sorted compare. @@ -394,11 +446,11 @@ impl QueryBuilder { } fn push_str(&mut self, s: &str) { - self.query.sql.push_str(s) + self.query.text.push_str(s) } fn push(&mut self, c: char) { - self.query.sql.push(c) + self.query.text.push(c) } fn sorted_compare(&mut self) { @@ -418,7 +470,7 @@ impl QueryBuilder { } fn is_empty(&self) -> bool { - self.query.sql.is_empty() + self.query.text.is_empty() } /// Creates a Query and resets this builder to default diff --git a/test_helpers_end_to_end/src/steps.rs b/test_helpers_end_to_end/src/steps.rs index fb6821decb..4893b39630 100644 --- a/test_helpers_end_to_end/src/steps.rs +++ b/test_helpers_end_to_end/src/steps.rs @@ -1,3 +1,4 @@ +use crate::snapshot_comparison::Language; use crate::{ check_flight_error, get_write_token, run_influxql, run_sql, snapshot_comparison, token_is_persisted, try_run_influxql, try_run_sql, wait_for_persisted, wait_for_readable, @@ -225,6 +226,14 @@ pub enum Step { expected: Vec<&'static str>, }, + /// Read the InfluxQL queries in the specified file and verify that the results match the expected + /// results in the corresponding expected file + InfluxQLQueryAndCompare { + input_path: PathBuf, + setup_name: String, + contents: String, + }, + /// Run an InfluxQL query that's expected to fail using the FlightSQL interface and verify that the /// request returns the expected error code and message InfluxQLExpectingError { @@ -391,16 +400,20 @@ where setup_name, contents, } => { - info!("====Begin running queries in file {}", input_path.display()); + info!( + "====Begin running SQL queries in file {}", + input_path.display() + ); snapshot_comparison::run( state.cluster, input_path.into(), setup_name.into(), contents.into(), + Language::Sql, ) .await .unwrap(); - info!("====Done running queries"); + info!("====Done running SQL queries"); } Step::QueryExpectingError { sql, @@ -445,6 +458,26 @@ where assert_batches_sorted_eq!(expected, &batches); info!("====Done running"); } + Step::InfluxQLQueryAndCompare { + input_path, + setup_name, + contents, + } => { + info!( + "====Begin running InfluxQL queries in file {}", + input_path.display() + ); + snapshot_comparison::run( + state.cluster, + input_path.into(), + setup_name.into(), + contents.into(), + Language::InfluxQL, + ) + .await + .unwrap(); + info!("====Done running InfluxQL queries"); + } Step::InfluxQLExpectingError { query, expected_error_code,