diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26cf5c8..fcc49ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,7 +63,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: install - args: cargo-semver-checks --version ^0.22 --locked + args: cargo-semver-checks --version ^0.27 --locked - name: Check semver run: | cargo semver-checks check-release -p sqllogictest diff --git a/CHANGELOG.md b/CHANGELOG.md index 3343948..907de43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.19.1] - 2024-01-04 + +* parser: `include` now returns error if no file is matched. + ## [0.19.0] - 2023-11-11 * parser: refactor `expect` field in sqllogictest parser to make it easier to work with. diff --git a/Cargo.lock b/Cargo.lock index e2b729d..8e6cbe6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1403,7 +1403,7 @@ dependencies = [ [[package]] name = "sqllogictest" -version = "0.19.0" +version = "0.19.1" dependencies = [ "async-trait", "educe", @@ -1426,7 +1426,7 @@ dependencies = [ [[package]] name = "sqllogictest-bin" -version = "0.19.0" +version = "0.19.1" dependencies = [ "anyhow", "async-trait", @@ -1447,7 +1447,7 @@ dependencies = [ [[package]] name = "sqllogictest-engines" -version = "0.19.0" +version = "0.19.1" dependencies = [ "async-trait", "bytes", diff --git a/Cargo.toml b/Cargo.toml index bc9370a..826e541 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "2" members = ["sqllogictest", "sqllogictest-bin", "sqllogictest-engines", "tests"] [workspace.package] -version = "0.19.0" +version = "0.19.1" edition = "2021" homepage = "https://github.com/risinglightdb/sqllogictest-rs" keywords = ["sql", "database", "parser", "cli"] diff --git a/sqllogictest-bin/src/main.rs b/sqllogictest-bin/src/main.rs index f05502c..710a3e2 100644 --- a/sqllogictest-bin/src/main.rs +++ b/sqllogictest-bin/src/main.rs @@ -465,10 +465,9 @@ async fn run_test_file( filename: impl AsRef, ) -> Result { let filename = filename.as_ref(); - let records = tokio::task::block_in_place(|| { - sqllogictest::parse_file(filename).map_err(|e| anyhow!("{:?}", e)) - }) - .context("failed to parse sqllogictest file")?; + let records = + tokio::task::block_in_place(|| sqllogictest::parse_file(filename).map_err(|e| anyhow!(e))) + .context("failed to parse sqllogictest file")?; let mut begin_times = vec![]; let mut did_pop = false; diff --git a/sqllogictest/src/parser.rs b/sqllogictest/src/parser.rs index ac2f5ab..c0021f2 100644 --- a/sqllogictest/src/parser.rs +++ b/sqllogictest/src/parser.rs @@ -10,7 +10,6 @@ use itertools::Itertools; use regex::Regex; use crate::ColumnType; -use crate::ParseErrorKind::InvalidIncludeFile; const RESULTS_DELIMITER: &str = "----"; @@ -112,6 +111,7 @@ pub enum Record { /// An include copies all records from another files. Include { loc: Location, + /// A glob pattern filename: String, }, /// A statement is an SQL command that is to be evaluated but from which we do not expect to @@ -584,8 +584,10 @@ pub enum ParseErrorKind { InvalidDuration(String), #[error("invalid control: {0:?}")] InvalidControl(String), - #[error("invalid include file pattern: {0:?}")] + #[error("invalid include file pattern: {0}")] InvalidIncludeFile(String), + #[error("no files found for include file pattern: {0:?}")] + EmptyIncludeFile(String), #[error("no such file")] FileNotFound, } @@ -843,10 +845,16 @@ fn parse_file_inner(loc: Location) -> Result>, Pars path_buf.as_os_str().to_string_lossy().to_string() }; - for included_file in glob::glob(&complete_filename) - .map_err(|e| InvalidIncludeFile(format!("{e:?}")).at(loc.clone()))? - .filter_map(Result::ok) - { + let mut iter = glob::glob(&complete_filename) + .map_err(|e| ParseErrorKind::InvalidIncludeFile(e.to_string()).at(loc.clone()))? + .peekable(); + if iter.peek().is_none() { + return Err(ParseErrorKind::EmptyIncludeFile(filename).at(loc.clone())); + } + for included_file in iter { + let included_file = included_file.map_err(|e| { + ParseErrorKind::InvalidIncludeFile(e.to_string()).at(loc.clone()) + })?; let included_file = included_file.as_os_str().to_string_lossy().to_string(); records.push(Record::Injected(Injected::BeginInclude(