feat: Add support for data-driven InfluxQL tests (#6830)
* feat: Add support for data-driven InfluxQL tests
* chore: Added more tests
* chore: Check if GIT_HASH has changed, to avoid rebuilds
This speeds up the edit-test cycle, when changing data files, as
cargo won't rebuild the test binary 🥳
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Andrew Lamb <alamb@influxdata.com>
pull/24376/head
parent
b521c68eef
commit
7ae453fa75
|
@ -5,6 +5,7 @@
|
|||
use std::process::Command;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = '';
|
|
@ -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 |
|
||||
+----------------------+-------+------+
|
|
@ -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
|
||||
|
|
|
@ -1197,6 +1197,32 @@ pub static SETUPS: Lazy<HashMap<SetupName, SetupSteps>> = 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,
|
||||
},
|
||||
],
|
||||
),
|
||||
])
|
||||
});
|
||||
|
||||
|
|
|
@ -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<T, E = Error> = std::result::Result<T, E>;
|
||||
|
||||
#[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<PathBuf, OutputPathError> {
|
||||
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<PathBuf, OutputPathError> {
|
|||
|
||||
// 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<Vec<String>> {
|
||||
let sql = query.sql();
|
||||
async fn run_query(
|
||||
cluster: &MiniCluster,
|
||||
query: &Query,
|
||||
language: Language,
|
||||
) -> Result<Vec<String>> {
|
||||
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: <REDACTED>`
|
||||
normalized_filters: bool,
|
||||
|
||||
/// The SQL string
|
||||
sql: String,
|
||||
/// The query string
|
||||
text: String,
|
||||
}
|
||||
|
||||
impl Query {
|
||||
#[cfg(test)]
|
||||
fn new(sql: impl Into<String>) -> Self {
|
||||
let sql = sql.into();
|
||||
fn new(text: impl Into<String>) -> 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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue