diff --git a/Cargo.lock b/Cargo.lock index 828ca3ba6504b..b14c92fe74785 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6497,8 +6497,12 @@ name = "risingwave_sqlparser_test_runner" version = "0.1.0" dependencies = [ "anyhow", + "console", + "futures", + "madsim-tokio", "risingwave_sqlparser", "serde", + "serde_with 2.2.0", "serde_yaml", "walkdir", "workspace-hack", diff --git a/Makefile.toml b/Makefile.toml index 86c63c7683d11..46b0300c90ded 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -9,6 +9,7 @@ extend = [ { path = "src/risedevtool/redis.toml" }, { path = "src/risedevtool/connector.toml" }, { path = "src/risedevtool/risedev-components.toml" }, + { path = "src/sqlparser/test_runner/sqlparser_test.toml"}, { path = "src/frontend/planner_test/planner_test.toml" }, { path = "src/tests/compaction_test/Makefile.toml" }, { path = "src/storage/backup/integration_tests/Makefile.toml" }, diff --git a/src/cmd_all/Cargo.toml b/src/cmd_all/Cargo.toml index 218c2e48956b1..a8b02c9c99c70 100644 --- a/src/cmd_all/Cargo.toml +++ b/src/cmd_all/Cargo.toml @@ -20,7 +20,7 @@ ignored = ["workspace-hack", "workspace-config", "task_stats_alloc"] [dependencies] anyhow = "1" clap = { version = "4", features = ["derive"] } -console = "0.15.2" +console = "0.15" risingwave_common = { path = "../common" } risingwave_compactor = { path = "../storage/compactor" } risingwave_compute = { path = "../compute" } diff --git a/src/sqlparser/test_runner/Cargo.toml b/src/sqlparser/test_runner/Cargo.toml index f33c8cf1b218f..d1cd39edf1a93 100644 --- a/src/sqlparser/test_runner/Cargo.toml +++ b/src/sqlparser/test_runner/Cargo.toml @@ -11,11 +11,27 @@ normal = ["workspace-hack"] [dependencies] anyhow = "1" +console = "0.15" +futures = { version = "0.3", default-features = false, features = ["alloc"] } risingwave_sqlparser = { path = "../" } serde = { version = "1", features = ["derive"] } +serde_with = "2" serde_yaml = "0.9" +tokio = { version = "0.2", package = "madsim-tokio", features = [ + "rt", + "rt-multi-thread", + "sync", + "macros", + "time", + "signal", + "fs", +] } walkdir = "2" +[[bin]] +name = "parser-test-apply" +path = "src/bin/apply.rs" + [target.'cfg(not(madsim))'.dependencies] workspace-hack = { path = "../../workspace-hack" } diff --git a/src/sqlparser/test_runner/sqlparser_test.toml b/src/sqlparser/test_runner/sqlparser_test.toml new file mode 100644 index 0000000000000..32990be7df6df --- /dev/null +++ b/src/sqlparser/test_runner/sqlparser_test.toml @@ -0,0 +1,55 @@ +[tasks.update-parser-test] +description = "Update parser test data" +private = true +script = ''' +#!/usr/bin/env bash +set -e +cargo run --bin parser-test-apply +''' + +[tasks.apply-parser-test] +description = "Generate parser test data" +dependencies = [ + "update-parser-test" +] +script = ''' +#!/usr/bin/env bash +set -e +cd src/sqlparser/tests/testdata/ + +for f in *.apply.yaml +do + diff "$f" "$(basename "$f" .apply.yaml).yaml" || true +done + +echo "If you want to apply the parser test data, run: $(tput setaf 2)./risedev do-apply-parser-test$(tput sgr 0)" +''' +category = "RiseDev - Test" + +[tasks.do-apply-parser-test] +description = "Apply parser test data" +dependencies = [ + "update-parser-test" +] +script = ''' +#!/usr/bin/env bash +set -e +cd src/sqlparser/tests/testdata/ + +for f in *.apply.yaml +do + SOURCE="$(basename $f .apply.yaml).yaml" + if [ -f "$SOURCE" ]; then + cat < temp.apply.yaml +# This file is automatically generated. See \`src/sqlparser/test_runner/src/bin/apply.rs\` for more information. +EOF + cat "$f" >> temp.apply.yaml + mv temp.apply.yaml "$SOURCE" + fi +done + +rm *.apply.yaml + +echo "$(tput setaf 2)Diff applied!$(tput sgr 0)" +''' +category = "RiseDev - Test" diff --git a/src/sqlparser/test_runner/src/bin/apply.rs b/src/sqlparser/test_runner/src/bin/apply.rs new file mode 100644 index 0000000000000..1c1318b8c809a --- /dev/null +++ b/src/sqlparser/test_runner/src/bin/apply.rs @@ -0,0 +1,121 @@ +// Copyright 2023 RisingWave Labs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::path::Path; +use std::sync::{Arc, Mutex}; + +use anyhow::Result; +use console::style; +use futures::future::try_join_all; +use risingwave_sqlparser::ast::Statement; +use risingwave_sqlparser::parser::Parser; +use risingwave_sqlparser_test_runner::TestCase; +use walkdir::WalkDir; + +#[tokio::main] +async fn main() -> Result<()> { + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let dir = Path::new(manifest_dir) + .parent() + .unwrap() + .join("tests") + .join("testdata"); + println!("Using test cases from {:?}", dir); + + let mut futs = vec![]; + + let log_lock = Arc::new(Mutex::new(())); + + for entry in WalkDir::new(dir) { + let entry = entry.unwrap(); + let path = entry.path(); + + if !path.is_file() { + continue; + } + + if path.is_file() + && path.extension().map_or(false, |p| { + p.eq_ignore_ascii_case("yml") || p.eq_ignore_ascii_case("yaml") + }) + && !path + .file_name() + .unwrap() + .to_string_lossy() + .ends_with(".apply.yaml") + { + let target = path.with_extension("apply.yaml"); + + let path = path.to_path_buf(); + let log_lock = Arc::clone(&log_lock); + futs.push(async move { + let file_content = tokio::fs::read_to_string(&path).await?; + + let cases: Vec = serde_yaml::from_str(&file_content)?; + + let mut new_cases = Vec::with_capacity(cases.len()); + + for case in cases { + let input = &case.input; + let ast = Parser::parse_sql(input); + let actual_case = match ast { + Ok(ast) => { + let [ast]: [Statement; 1] = ast + .try_into() + .expect("Only one statement is supported now."); + + let actual_formatted_sql = + case.formatted_sql.as_ref().map(|_| format!("{}", ast)); + let actual_formatted_ast = + case.formatted_ast.as_ref().map(|_| format!("{:?}", ast)); + + TestCase { + input: input.clone(), + formatted_sql: actual_formatted_sql, + formatted_ast: actual_formatted_ast, + error_msg: None, + } + } + Err(err) => { + let actual_error_msg = format!("{}", err); + TestCase { + input: input.clone(), + formatted_sql: None, + formatted_ast: None, + error_msg: Some(actual_error_msg), + } + } + }; + + if actual_case != case { + let _guard = log_lock.lock(); + println!("{}\n{}\n", style(&case).red(), style(&actual_case).green()) + } + + new_cases.push(actual_case); + } + + let output_content = serde_yaml::to_string(&new_cases)?; + + tokio::fs::write(target, output_content).await?; + + Ok::<_, anyhow::Error>(()) + }); + } + } + + let _res = try_join_all(futs).await?; + + Ok(()) +} diff --git a/src/sqlparser/test_runner/src/lib.rs b/src/sqlparser/test_runner/src/lib.rs index 4ffc2381c95cc..2f9b395026a87 100644 --- a/src/sqlparser/test_runner/src/lib.rs +++ b/src/sqlparser/test_runner/src/lib.rs @@ -14,17 +14,27 @@ // Data-driven tests. +use std::fmt::Display; + use anyhow::{anyhow, Result}; use risingwave_sqlparser::parser::Parser; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; /// `TestCase` will be deserialized from yaml. -#[derive(PartialEq, Eq, Debug, Deserialize)] -struct TestCase { - input: String, - formatted_sql: Option, - error_msg: Option, - formatted_ast: Option, +#[serde_with::skip_serializing_none] +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct TestCase { + pub input: String, + pub formatted_sql: Option, + pub error_msg: Option, + pub formatted_ast: Option, +} + +impl Display for TestCase { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&serde_yaml::to_string(self).unwrap()) + } } fn run_test_case(c: TestCase) -> Result<()> { @@ -97,7 +107,14 @@ pub fn run_all_test_files() { use walkdir::WalkDir; for entry in WalkDir::new("../tests/testdata/") { let entry = entry.unwrap(); - if !entry.path().is_file() { + if !(entry.path().is_file()) { + continue; + } + if !(entry + .path() + .extension() + .map_or(false, |p| p.eq_ignore_ascii_case("yaml"))) + { continue; } let file_content = std::fs::read_to_string(entry.path()).unwrap(); diff --git a/src/sqlparser/tests/testdata/.gitignore b/src/sqlparser/tests/testdata/.gitignore new file mode 100644 index 0000000000000..059da14bb42b3 --- /dev/null +++ b/src/sqlparser/tests/testdata/.gitignore @@ -0,0 +1 @@ +*.apply.yaml diff --git a/src/sqlparser/tests/testdata/alter.yaml b/src/sqlparser/tests/testdata/alter.yaml index 0672068780a5c..4dd0a20684923 100644 --- a/src/sqlparser/tests/testdata/alter.yaml +++ b/src/sqlparser/tests/testdata/alter.yaml @@ -1,11 +1,9 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: ALTER USER user WITH SUPERUSER CREATEDB PASSWORD 'password' formatted_sql: ALTER USER user WITH SUPERUSER CREATEDB PASSWORD 'password' - - input: ALTER USER user RENAME TO another formatted_sql: ALTER USER user RENAME TO another - - input: ALTER SYSTEM SET a = 'abc' formatted_sql: ALTER SYSTEM SET a = 'abc' - - input: ALTER SYSTEM SET a = DEFAULT formatted_sql: ALTER SYSTEM SET a = DEFAULT diff --git a/src/sqlparser/tests/testdata/array.yaml b/src/sqlparser/tests/testdata/array.yaml index b51356ae42f63..f166818c21548 100644 --- a/src/sqlparser/tests/testdata/array.yaml +++ b/src/sqlparser/tests/testdata/array.yaml @@ -1,32 +1,21 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: CREATE TABLE t(a int[]); formatted_sql: CREATE TABLE t (a INT[]) - - input: CREATE TABLE t(a int[][]); formatted_sql: CREATE TABLE t (a INT[][]) - - input: CREATE TABLE t(a int[][][]); formatted_sql: CREATE TABLE t (a INT[][][]) - - input: CREATE TABLE t(a int[); - error_msg: | - sql parser error: Expected ], found: ) - + error_msg: 'sql parser error: Expected ], found: )' - input: CREATE TABLE t(a int[[]); - error_msg: | - sql parser error: Expected ], found: [ - + error_msg: 'sql parser error: Expected ], found: [' - input: CREATE TABLE t(a int]); - error_msg: | - sql parser error: Expected ',' or ')' after column definition, found: ] - + error_msg: 'sql parser error: Expected '','' or '')'' after column definition, found: ]' - input: SELECT foo[0] FROM foos formatted_sql: SELECT foo[0] FROM foos - - input: SELECT foo[0][0] FROM foos formatted_sql: SELECT foo[0][0] FROM foos - - input: SELECT (CAST(ARRAY[ARRAY[2, 3]] AS INT[][]))[1][2] formatted_sql: SELECT (CAST(ARRAY[ARRAY[2, 3]] AS INT[][]))[1][2] - - input: SELECT ARRAY[] formatted_sql: SELECT ARRAY[] diff --git a/src/sqlparser/tests/testdata/create.yaml b/src/sqlparser/tests/testdata/create.yaml index d3ce3dc38c46d..9c8983a2293da 100644 --- a/src/sqlparser/tests/testdata/create.yaml +++ b/src/sqlparser/tests/testdata/create.yaml @@ -1,96 +1,58 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: CREATE DATABASE t formatted_sql: CREATE DATABASE t - formatted_ast: | - CreateDatabase { db_name: ObjectName([Ident { value: "t", quote_style: None }]), if_not_exists: false } - + formatted_ast: 'CreateDatabase { db_name: ObjectName([Ident { value: "t", quote_style: None }]), if_not_exists: false }' - input: CREATE DATABASE IF NOT EXISTS t formatted_sql: CREATE DATABASE IF NOT EXISTS t - formatted_ast: | - CreateDatabase { db_name: ObjectName([Ident { value: "t", quote_style: None }]), if_not_exists: true } - + formatted_ast: 'CreateDatabase { db_name: ObjectName([Ident { value: "t", quote_style: None }]), if_not_exists: true }' - input: CREATE SCHEMA t formatted_sql: CREATE SCHEMA t - formatted_ast: | - CreateSchema { schema_name: ObjectName([Ident { value: "t", quote_style: None }]), if_not_exists: false } - + formatted_ast: 'CreateSchema { schema_name: ObjectName([Ident { value: "t", quote_style: None }]), if_not_exists: false }' - input: CREATE SCHEMA IF NOT EXISTS t formatted_sql: CREATE SCHEMA IF NOT EXISTS t - formatted_ast: | - CreateSchema { schema_name: ObjectName([Ident { value: "t", quote_style: None }]), if_not_exists: true } - + formatted_ast: 'CreateSchema { schema_name: ObjectName([Ident { value: "t", quote_style: None }]), if_not_exists: true }' - input: CREATE OR REPLACE TABLE t (a INT) formatted_sql: CREATE OR REPLACE TABLE t (a INT) - - input: CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a formatted_sql: CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a - - input: CREATE SOURCE src - error_msg: | - sql parser error: Expected ROW, found: EOF - + error_msg: 'sql parser error: Expected ROW, found: EOF' - input: CREATE SOURCE src ROW FORMAT JSON formatted_sql: CREATE SOURCE src ROW FORMAT JSON - - input: CREATE SOURCE IF NOT EXISTS src WITH (kafka.topic = 'abc', kafka.servers = 'localhost:1001') ROW FORMAT PROTOBUF MESSAGE 'Foo' ROW SCHEMA LOCATION 'file://' formatted_sql: CREATE SOURCE IF NOT EXISTS src WITH (kafka.topic = 'abc', kafka.servers = 'localhost:1001') ROW FORMAT PROTOBUF MESSAGE 'Foo' ROW SCHEMA LOCATION 'file://' - formatted_ast: | - CreateSource { stmt: CreateSourceStatement { if_not_exists: true, columns: [], constraints: [], source_name: ObjectName([Ident { value: "src", quote_style: None }]), with_properties: WithProperties([SqlOption { name: ObjectName([Ident { value: "kafka", quote_style: None }, Ident { value: "topic", quote_style: None }]), value: SingleQuotedString("abc") }, SqlOption { name: ObjectName([Ident { value: "kafka", quote_style: None }, Ident { value: "servers", quote_style: None }]), value: SingleQuotedString("localhost:1001") }]), source_schema: Protobuf(ProtobufSchema { message_name: AstString("Foo"), row_schema_location: AstString("file://"), use_schema_registry: false }), source_watermarks: [] } } - + formatted_ast: 'CreateSource { stmt: CreateSourceStatement { if_not_exists: true, columns: [], constraints: [], source_name: ObjectName([Ident { value: "src", quote_style: None }]), with_properties: WithProperties([SqlOption { name: ObjectName([Ident { value: "kafka", quote_style: None }, Ident { value: "topic", quote_style: None }]), value: SingleQuotedString("abc") }, SqlOption { name: ObjectName([Ident { value: "kafka", quote_style: None }, Ident { value: "servers", quote_style: None }]), value: SingleQuotedString("localhost:1001") }]), source_schema: Protobuf(ProtobufSchema { message_name: AstString("Foo"), row_schema_location: AstString("file://"), use_schema_registry: false }), source_watermarks: [] } }' - input: CREATE SOURCE IF NOT EXISTS src WITH (kafka.topic = 'abc', kafka.servers = 'localhost:1001') ROW FORMAT PROTOBUF MESSAGE 'Foo' ROW SCHEMA LOCATION CONFLUENT SCHEMA REGISTRY 'http://' formatted_sql: CREATE SOURCE IF NOT EXISTS src WITH (kafka.topic = 'abc', kafka.servers = 'localhost:1001') ROW FORMAT PROTOBUF MESSAGE 'Foo' ROW SCHEMA LOCATION CONFLUENT SCHEMA REGISTRY 'http://' - formatted_ast: | - CreateSource { stmt: CreateSourceStatement { if_not_exists: true, columns: [], constraints: [], source_name: ObjectName([Ident { value: "src", quote_style: None }]), with_properties: WithProperties([SqlOption { name: ObjectName([Ident { value: "kafka", quote_style: None }, Ident { value: "topic", quote_style: None }]), value: SingleQuotedString("abc") }, SqlOption { name: ObjectName([Ident { value: "kafka", quote_style: None }, Ident { value: "servers", quote_style: None }]), value: SingleQuotedString("localhost:1001") }]), source_schema: Protobuf(ProtobufSchema { message_name: AstString("Foo"), row_schema_location: AstString("http://"), use_schema_registry: true }), source_watermarks: [] } } - + formatted_ast: 'CreateSource { stmt: CreateSourceStatement { if_not_exists: true, columns: [], constraints: [], source_name: ObjectName([Ident { value: "src", quote_style: None }]), with_properties: WithProperties([SqlOption { name: ObjectName([Ident { value: "kafka", quote_style: None }, Ident { value: "topic", quote_style: None }]), value: SingleQuotedString("abc") }, SqlOption { name: ObjectName([Ident { value: "kafka", quote_style: None }, Ident { value: "servers", quote_style: None }]), value: SingleQuotedString("localhost:1001") }]), source_schema: Protobuf(ProtobufSchema { message_name: AstString("Foo"), row_schema_location: AstString("http://"), use_schema_registry: true }), source_watermarks: [] } }' - input: CREATE SOURCE bid (auction INTEGER, bidder INTEGER, price INTEGER, WATERMARK FOR auction AS auction - 1, "date_time" TIMESTAMP) with (connector = 'nexmark', nexmark.table.type = 'Bid', nexmark.split.num = '12', nexmark.min.event.gap.in.ns = '0') formatted_sql: CREATE SOURCE bid (auction INT, bidder INT, price INT, "date_time" TIMESTAMP, WATERMARK FOR auction AS auction - 1) WITH (connector = 'nexmark', nexmark.table.type = 'Bid', nexmark.split.num = '12', nexmark.min.event.gap.in.ns = '0') ROW FORMAT NATIVE - formatted_ast: | - CreateSource { stmt: CreateSourceStatement { if_not_exists: false, columns: [ColumnDef { name: Ident { value: "auction", quote_style: None }, data_type: Some(Int), collation: None, options: [] }, ColumnDef { name: Ident { value: "bidder", quote_style: None }, data_type: Some(Int), collation: None, options: [] }, ColumnDef { name: Ident { value: "price", quote_style: None }, data_type: Some(Int), collation: None, options: [] }, ColumnDef { name: Ident { value: "date_time", quote_style: Some('"') }, data_type: Some(Timestamp(false)), collation: None, options: [] }], constraints: [], source_name: ObjectName([Ident { value: "bid", quote_style: None }]), with_properties: WithProperties([SqlOption { name: ObjectName([Ident { value: "connector", quote_style: None }]), value: SingleQuotedString("nexmark") }, SqlOption { name: ObjectName([Ident { value: "nexmark", quote_style: None }, Ident { value: "table", quote_style: None }, Ident { value: "type", quote_style: None }]), value: SingleQuotedString("Bid") }, SqlOption { name: ObjectName([Ident { value: "nexmark", quote_style: None }, Ident { value: "split", quote_style: None }, Ident { value: "num", quote_style: None }]), value: SingleQuotedString("12") }, SqlOption { name: ObjectName([Ident { value: "nexmark", quote_style: None }, Ident { value: "min", quote_style: None }, Ident { value: "event", quote_style: None }, Ident { value: "gap", quote_style: None }, Ident { value: "in", quote_style: None }, Ident { value: "ns", quote_style: None }]), value: SingleQuotedString("0") }]), source_schema: Native, source_watermarks: [SourceWatermark { column: Ident { value: "auction", quote_style: None }, expr: BinaryOp { left: Identifier(Ident { value: "auction", quote_style: None }), op: Minus, right: Value(Number("1")) } }] } } - + formatted_ast: 'CreateSource { stmt: CreateSourceStatement { if_not_exists: false, columns: [ColumnDef { name: Ident { value: "auction", quote_style: None }, data_type: Some(Int), collation: None, options: [] }, ColumnDef { name: Ident { value: "bidder", quote_style: None }, data_type: Some(Int), collation: None, options: [] }, ColumnDef { name: Ident { value: "price", quote_style: None }, data_type: Some(Int), collation: None, options: [] }, ColumnDef { name: Ident { value: "date_time", quote_style: Some(''"'') }, data_type: Some(Timestamp(false)), collation: None, options: [] }], constraints: [], source_name: ObjectName([Ident { value: "bid", quote_style: None }]), with_properties: WithProperties([SqlOption { name: ObjectName([Ident { value: "connector", quote_style: None }]), value: SingleQuotedString("nexmark") }, SqlOption { name: ObjectName([Ident { value: "nexmark", quote_style: None }, Ident { value: "table", quote_style: None }, Ident { value: "type", quote_style: None }]), value: SingleQuotedString("Bid") }, SqlOption { name: ObjectName([Ident { value: "nexmark", quote_style: None }, Ident { value: "split", quote_style: None }, Ident { value: "num", quote_style: None }]), value: SingleQuotedString("12") }, SqlOption { name: ObjectName([Ident { value: "nexmark", quote_style: None }, Ident { value: "min", quote_style: None }, Ident { value: "event", quote_style: None }, Ident { value: "gap", quote_style: None }, Ident { value: "in", quote_style: None }, Ident { value: "ns", quote_style: None }]), value: SingleQuotedString("0") }]), source_schema: Native, source_watermarks: [SourceWatermark { column: Ident { value: "auction", quote_style: None }, expr: BinaryOp { left: Identifier(Ident { value: "auction", quote_style: None }), op: Minus, right: Value(Number("1")) } }] } }' - input: CREATE TABLE T (v1 INT, v2 STRUCT) formatted_sql: CREATE TABLE T (v1 INT, v2 STRUCT) - - input: CREATE TABLE T (v1 INT, v2 STRUCT>) formatted_sql: CREATE TABLE T (v1 INT, v2 STRUCT>) - - input: CREATE TABLE T (a STRUCT) formatted_sql: CREATE TABLE T (a STRUCT) - - input: CREATE TABLE T (FULL INT) - error_msg: | - sql parser error: syntax error at or near "FULL" - + error_msg: 'sql parser error: syntax error at or near "FULL"' - input: CREATE TABLE T ("FULL" INT) formatted_sql: CREATE TABLE T ("FULL" INT) - - input: CREATE USER user WITH SUPERUSER CREATEDB PASSWORD 'password' formatted_sql: CREATE USER user WITH SUPERUSER CREATEDB PASSWORD 'password' - - input: CREATE SINK snk - error_msg: | - sql parser error: Expected FROM or AS after CREATE SINK sink_name, found: EOF - + error_msg: 'sql parser error: Expected FROM or AS after CREATE SINK sink_name, found: EOF' - input: CREATE SINK IF NOT EXISTS snk FROM mv WITH (connector = 'mysql', mysql.endpoint = '127.0.0.1:3306', mysql.table = '', mysql.database = '', mysql.user = '', mysql.password = '') formatted_sql: CREATE SINK IF NOT EXISTS snk FROM mv WITH (connector = 'mysql', mysql.endpoint = '127.0.0.1:3306', mysql.table = '', mysql.database = '', mysql.user = '', mysql.password = '') - - input: CREATE SINK IF NOT EXISTS snk AS SELECT count(*) AS cnt FROM mv WITH (connector = 'mysql', mysql.endpoint = '127.0.0.1:3306', mysql.table = '', mysql.database = '', mysql.user = '', mysql.password = '') formatted_sql: CREATE SINK IF NOT EXISTS snk AS SELECT count(*) AS cnt FROM mv WITH (connector = 'mysql', mysql.endpoint = '127.0.0.1:3306', mysql.table = '', mysql.database = '', mysql.user = '', mysql.password = '') - - input: create user tmp createdb nocreatedb - error_msg: | - sql parser error: conflicting or redundant options - + error_msg: 'sql parser error: conflicting or redundant options' - input: create user tmp createdb createdb - error_msg: | - sql parser error: conflicting or redundant options - + error_msg: 'sql parser error: conflicting or redundant options' - input: create user tmp with password '123' password null - error_msg: | - sql parser error: conflicting or redundant options - + error_msg: 'sql parser error: conflicting or redundant options' - input: create user tmp with encrypted password '' password null - error_msg: | - sql parser error: conflicting or redundant options - + error_msg: 'sql parser error: conflicting or redundant options' - input: create user tmp with encrypted password null - error_msg: | - sql parser error: Expected literal string, found: null + error_msg: 'sql parser error: Expected literal string, found: null' diff --git a/src/sqlparser/tests/testdata/drop.yaml b/src/sqlparser/tests/testdata/drop.yaml index f6b1673d48375..0fc49060328fb 100644 --- a/src/sqlparser/tests/testdata/drop.yaml +++ b/src/sqlparser/tests/testdata/drop.yaml @@ -1,25 +1,18 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: DROP SOURCE src formatted_sql: DROP SOURCE src - formatted_ast: | - Drop(DropStatement { object_type: Source, if_exists: false, object_name: ObjectName([Ident { value: "src", quote_style: None }]), drop_mode: None }) - + formatted_ast: 'Drop(DropStatement { object_type: Source, if_exists: false, object_name: ObjectName([Ident { value: "src", quote_style: None }]), drop_mode: None })' - input: DROP MATERIALIZED VIEW t formatted_sql: DROP MATERIALIZED VIEW t - - input: DROP DATABASE t formatted_sql: DROP DATABASE t - - input: DROP SCHEMA t formatted_sql: DROP SCHEMA t - - input: DROP DATABASE IF EXISTS t formatted_sql: DROP DATABASE IF EXISTS t - - input: DROP SCHEMA IF EXISTS t formatted_sql: DROP SCHEMA IF EXISTS t - - input: DROP USER user formatted_sql: DROP USER user - - input: DROP USER IF EXISTS user formatted_sql: DROP USER IF EXISTS user diff --git a/src/sqlparser/tests/testdata/drop_index.yaml b/src/sqlparser/tests/testdata/drop_index.yaml index a0cb6d42eb9f0..130a6b36673dd 100644 --- a/src/sqlparser/tests/testdata/drop_index.yaml +++ b/src/sqlparser/tests/testdata/drop_index.yaml @@ -1,4 +1,4 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: DROP INDEX idx_a formatted_sql: DROP INDEX idx_a - formatted_ast: | - Drop(DropStatement { object_type: Index, if_exists: false, object_name: ObjectName([Ident { value: "idx_a", quote_style: None }]), drop_mode: None }) + formatted_ast: 'Drop(DropStatement { object_type: Index, if_exists: false, object_name: ObjectName([Ident { value: "idx_a", quote_style: None }]), drop_mode: None })' diff --git a/src/sqlparser/tests/testdata/insert.yaml b/src/sqlparser/tests/testdata/insert.yaml index 5a8d5a872c874..cb2f32526b81b 100644 --- a/src/sqlparser/tests/testdata/insert.yaml +++ b/src/sqlparser/tests/testdata/insert.yaml @@ -1,6 +1,5 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: INSERT public.customer (id, name, active) VALUES (1, 2, 3) - error_msg: | - sql parser error: Expected INTO, found: public - + error_msg: 'sql parser error: Expected INTO, found: public' - input: INSERT INTO t VALUES(1,3), (2,4) RETURNING *, a, a as aaa formatted_sql: INSERT INTO t VALUES (1, 3), (2, 4) RETURNING (*, a, a AS aaa) diff --git a/src/sqlparser/tests/testdata/precedence.yaml b/src/sqlparser/tests/testdata/precedence.yaml index 5f0304f963f97..72673d1e93299 100644 --- a/src/sqlparser/tests/testdata/precedence.yaml +++ b/src/sqlparser/tests/testdata/precedence.yaml @@ -1,24 +1,16 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: select 2 + 2 ^ 2 formatted_sql: SELECT 2 + 2 ^ 2 - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(BinaryOp { left: Value(Number("2")), op: Plus, right: BinaryOp { left: Value(Number("2")), op: BitwiseXor, right: Value(Number("2")) } })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(BinaryOp { left: Value(Number("2")), op: Plus, right: BinaryOp { left: Value(Number("2")), op: BitwiseXor, right: Value(Number("2")) } })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: select 2 | 3 & 4 formatted_sql: SELECT 2 | 3 & 4 - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(BinaryOp { left: BinaryOp { left: Value(Number("2")), op: BitwiseOr, right: Value(Number("3")) }, op: BitwiseAnd, right: Value(Number("4")) })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(BinaryOp { left: BinaryOp { left: Value(Number("2")), op: BitwiseOr, right: Value(Number("3")) }, op: BitwiseAnd, right: Value(Number("4")) })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: select - 3 ^ 2 formatted_sql: SELECT -3 ^ 2 - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(BinaryOp { left: Value(Number("-3")), op: BitwiseXor, right: Value(Number("2")) })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(BinaryOp { left: Value(Number("-3")), op: BitwiseXor, right: Value(Number("2")) })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: select - 3 * 2 formatted_sql: SELECT -3 * 2 - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(BinaryOp { left: Value(Number("-3")), op: Multiply, right: Value(Number("2")) })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(BinaryOp { left: Value(Number("-3")), op: Multiply, right: Value(Number("2")) })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: select |/ 4 + 12 formatted_sql: SELECT |/ 4 + 12 - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(UnaryOp { op: PGSquareRoot, expr: BinaryOp { left: Value(Number("4")), op: Plus, right: Value(Number("12")) } })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(UnaryOp { op: PGSquareRoot, expr: BinaryOp { left: Value(Number("4")), op: Plus, right: Value(Number("12")) } })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' diff --git a/src/sqlparser/tests/testdata/privilege.yaml b/src/sqlparser/tests/testdata/privilege.yaml index 6cd980d3c5494..44d1b40d0bcc3 100644 --- a/src/sqlparser/tests/testdata/privilege.yaml +++ b/src/sqlparser/tests/testdata/privilege.yaml @@ -1,39 +1,25 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: GRANT ALL ON DATABASE database TO user1 WITH GRANT OPTION GRANTED BY user formatted_sql: GRANT ALL ON DATABASE database TO user1 WITH GRANT OPTION GRANTED BY user - formatted_ast: | - Grant { privileges: All { with_privileges_keyword: false }, objects: Databases([ObjectName([Ident { value: "database", quote_style: None }])]), grantees: [Ident { value: "user1", quote_style: None }], with_grant_option: true, granted_by: Some(Ident { value: "user", quote_style: None }) } - + formatted_ast: 'Grant { privileges: All { with_privileges_keyword: false }, objects: Databases([ObjectName([Ident { value: "database", quote_style: None }])]), grantees: [Ident { value: "user1", quote_style: None }], with_grant_option: true, granted_by: Some(Ident { value: "user", quote_style: None }) }' - input: GRANT ALL ON SCHEMA schema1, schema2 TO user1 WITH GRANT OPTION GRANTED BY user formatted_sql: GRANT ALL ON SCHEMA schema1, schema2 TO user1 WITH GRANT OPTION GRANTED BY user - formatted_ast: | - Grant { privileges: All { with_privileges_keyword: false }, objects: Schemas([ObjectName([Ident { value: "schema1", quote_style: None }]), ObjectName([Ident { value: "schema2", quote_style: None }])]), grantees: [Ident { value: "user1", quote_style: None }], with_grant_option: true, granted_by: Some(Ident { value: "user", quote_style: None }) } - + formatted_ast: 'Grant { privileges: All { with_privileges_keyword: false }, objects: Schemas([ObjectName([Ident { value: "schema1", quote_style: None }]), ObjectName([Ident { value: "schema2", quote_style: None }])]), grantees: [Ident { value: "user1", quote_style: None }], with_grant_option: true, granted_by: Some(Ident { value: "user", quote_style: None }) }' - input: GRANT ALL PRIVILEGES ON ALL SOURCES IN SCHEMA schema TO user1 GRANTED BY user formatted_sql: GRANT ALL PRIVILEGES ON ALL SOURCES IN SCHEMA schema TO user1 GRANTED BY user - formatted_ast: | - Grant { privileges: All { with_privileges_keyword: true }, objects: AllSourcesInSchema { schemas: [ObjectName([Ident { value: "schema", quote_style: None }])] }, grantees: [Ident { value: "user1", quote_style: None }], with_grant_option: false, granted_by: Some(Ident { value: "user", quote_style: None }) } - + formatted_ast: 'Grant { privileges: All { with_privileges_keyword: true }, objects: AllSourcesInSchema { schemas: [ObjectName([Ident { value: "schema", quote_style: None }])] }, grantees: [Ident { value: "user1", quote_style: None }], with_grant_option: false, granted_by: Some(Ident { value: "user", quote_style: None }) }' - input: GRANT ALL PRIVILEGES ON ALL MATERIALIZED VIEWS IN SCHEMA schema TO user1 GRANTED BY user formatted_sql: GRANT ALL PRIVILEGES ON ALL MATERIALIZED VIEWS IN SCHEMA schema TO user1 GRANTED BY user - formatted_ast: | - Grant { privileges: All { with_privileges_keyword: true }, objects: AllMviewsInSchema { schemas: [ObjectName([Ident { value: "schema", quote_style: None }])] }, grantees: [Ident { value: "user1", quote_style: None }], with_grant_option: false, granted_by: Some(Ident { value: "user", quote_style: None }) } - + formatted_ast: 'Grant { privileges: All { with_privileges_keyword: true }, objects: AllMviewsInSchema { schemas: [ObjectName([Ident { value: "schema", quote_style: None }])] }, grantees: [Ident { value: "user1", quote_style: None }], with_grant_option: false, granted_by: Some(Ident { value: "user", quote_style: None }) }' - input: REVOKE GRANT OPTION FOR ALL ON DATABASE database FROM user1 GRANTED BY user formatted_sql: REVOKE GRANT OPTION FOR ALL ON DATABASE database FROM user1 GRANTED BY user RESTRICT - formatted_ast: | - Revoke { privileges: All { with_privileges_keyword: false }, objects: Databases([ObjectName([Ident { value: "database", quote_style: None }])]), grantees: [Ident { value: "user1", quote_style: None }], granted_by: Some(Ident { value: "user", quote_style: None }), revoke_grant_option: true, cascade: false } - + formatted_ast: 'Revoke { privileges: All { with_privileges_keyword: false }, objects: Databases([ObjectName([Ident { value: "database", quote_style: None }])]), grantees: [Ident { value: "user1", quote_style: None }], granted_by: Some(Ident { value: "user", quote_style: None }), revoke_grant_option: true, cascade: false }' - input: REVOKE ALL PRIVILEGES ON DATABASE database FROM user1 GRANTED BY user formatted_sql: REVOKE ALL PRIVILEGES ON DATABASE database FROM user1 GRANTED BY user RESTRICT - formatted_ast: | - Revoke { privileges: All { with_privileges_keyword: true }, objects: Databases([ObjectName([Ident { value: "database", quote_style: None }])]), grantees: [Ident { value: "user1", quote_style: None }], granted_by: Some(Ident { value: "user", quote_style: None }), revoke_grant_option: false, cascade: false } - + formatted_ast: 'Revoke { privileges: All { with_privileges_keyword: true }, objects: Databases([ObjectName([Ident { value: "database", quote_style: None }])]), grantees: [Ident { value: "user1", quote_style: None }], granted_by: Some(Ident { value: "user", quote_style: None }), revoke_grant_option: false, cascade: false }' - input: REVOKE ALL PRIVILEGES ON ALL MATERIALIZED VIEWS IN SCHEMA schema FROM user1 formatted_sql: REVOKE ALL PRIVILEGES ON ALL MATERIALIZED VIEWS IN SCHEMA schema FROM user1 RESTRICT - formatted_ast: | - Revoke { privileges: All { with_privileges_keyword: true }, objects: AllMviewsInSchema { schemas: [ObjectName([Ident { value: "schema", quote_style: None }])] }, grantees: [Ident { value: "user1", quote_style: None }], granted_by: None, revoke_grant_option: false, cascade: false } - + formatted_ast: 'Revoke { privileges: All { with_privileges_keyword: true }, objects: AllMviewsInSchema { schemas: [ObjectName([Ident { value: "schema", quote_style: None }])] }, grantees: [Ident { value: "user1", quote_style: None }], granted_by: None, revoke_grant_option: false, cascade: false }' - input: REVOKE ALL PRIVILEGES ON ALL SOURCES IN SCHEMA schema FROM user1 formatted_sql: REVOKE ALL PRIVILEGES ON ALL SOURCES IN SCHEMA schema FROM user1 RESTRICT - formatted_ast: | - Revoke { privileges: All { with_privileges_keyword: true }, objects: AllSourcesInSchema { schemas: [ObjectName([Ident { value: "schema", quote_style: None }])] }, grantees: [Ident { value: "user1", quote_style: None }], granted_by: None, revoke_grant_option: false, cascade: false } + formatted_ast: 'Revoke { privileges: All { with_privileges_keyword: true }, objects: AllSourcesInSchema { schemas: [ObjectName([Ident { value: "schema", quote_style: None }])] }, grantees: [Ident { value: "user1", quote_style: None }], granted_by: None, revoke_grant_option: false, cascade: false }' diff --git a/src/sqlparser/tests/testdata/select.yaml b/src/sqlparser/tests/testdata/select.yaml index 741790a18120d..589b6baef5a2c 100644 --- a/src/sqlparser/tests/testdata/select.yaml +++ b/src/sqlparser/tests/testdata/select.yaml @@ -1,112 +1,72 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: SELECT sqrt(id) FROM foo formatted_sql: SELECT sqrt(id) FROM foo - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Function(Function { name: ObjectName([Ident { value: "sqrt", quote_style: None }]), args: [Unnamed(Expr(Identifier(Ident { value: "id", quote_style: None })))], over: None, distinct: false, order_by: [], filter: None }))], from: [TableWithJoins { relation: Table { name: ObjectName([Ident { value: "foo", quote_style: None }]), alias: None }, joins: [] }], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - -# Typed string literal + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Function(Function { name: ObjectName([Ident { value: "sqrt", quote_style: None }]), args: [Unnamed(Expr(Identifier(Ident { value: "id", quote_style: None })))], over: None, distinct: false, order_by: [], filter: None }))], from: [TableWithJoins { relation: Table { name: ObjectName([Ident { value: "foo", quote_style: None }]), alias: None }, joins: [] }], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: SELECT INT '1' formatted_sql: SELECT INT '1' - - input: SELECT (foo).v1.v2 FROM foo formatted_sql: SELECT (foo).v1.v2 FROM foo - - input: SELECT ((((foo).v1)).v2) FROM foo formatted_sql: SELECT (((foo).v1).v2) FROM foo - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Nested(FieldIdentifier(FieldIdentifier(Identifier(Ident { value: "foo", quote_style: None }), [Ident { value: "v1", quote_style: None }]), [Ident { value: "v2", quote_style: None }])))], from: [TableWithJoins { relation: Table { name: ObjectName([Ident { value: "foo", quote_style: None }]), alias: None }, joins: [] }], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Nested(FieldIdentifier(FieldIdentifier(Identifier(Ident { value: "foo", quote_style: None }), [Ident { value: "v1", quote_style: None }]), [Ident { value: "v2", quote_style: None }])))], from: [TableWithJoins { relation: Table { name: ObjectName([Ident { value: "foo", quote_style: None }]), alias: None }, joins: [] }], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: SELECT (foo.v1).v2 FROM foo formatted_sql: SELECT (foo.v1).v2 FROM foo - - input: SELECT (v1).v2 FROM foo formatted_sql: SELECT (v1).v2 FROM foo - - input: SELECT ((1,2,3)::foo).v1 formatted_sql: SELECT (CAST(ROW(1, 2, 3) AS foo)).v1 - - input: SELECT ((1,2,3)::foo).v1.v2 formatted_sql: SELECT (CAST(ROW(1, 2, 3) AS foo)).v1.v2 - - input: SELECT (((1,2,3)::foo).v1).v2 formatted_sql: SELECT ((CAST(ROW(1, 2, 3) AS foo)).v1).v2 - - input: SELECT (foo).* FROM foo formatted_sql: SELECT (foo).* FROM foo - - input: SELECT ((foo.v1).v2).* FROM foo formatted_sql: SELECT (foo.v1).v2.* FROM foo - - input: SELECT ((1,2,3)::foo).v1.* formatted_sql: SELECT (CAST(ROW(1, 2, 3) AS foo)).v1.* - - input: SELECT (((((1,2,3)::foo).v1))).* formatted_sql: SELECT (CAST(ROW(1, 2, 3) AS foo)).v1.* - - input: SELECT * FROM generate_series('2'::INT,'10'::INT,'2'::INT) formatted_sql: SELECT * FROM generate_series(CAST('2' AS INT), CAST('10' AS INT), CAST('2' AS INT)) - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [Wildcard], from: [TableWithJoins { relation: TableFunction { name: ObjectName([Ident { value: "generate_series", quote_style: None }]), alias: None, args: [Unnamed(Expr(Cast { expr: Value(SingleQuotedString("2")), data_type: Int })), Unnamed(Expr(Cast { expr: Value(SingleQuotedString("10")), data_type: Int })), Unnamed(Expr(Cast { expr: Value(SingleQuotedString("2")), data_type: Int }))] }, joins: [] }], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [Wildcard], from: [TableWithJoins { relation: TableFunction { name: ObjectName([Ident { value: "generate_series", quote_style: None }]), alias: None, args: [Unnamed(Expr(Cast { expr: Value(SingleQuotedString("2")), data_type: Int })), Unnamed(Expr(Cast { expr: Value(SingleQuotedString("10")), data_type: Int })), Unnamed(Expr(Cast { expr: Value(SingleQuotedString("2")), data_type: Int }))] }, joins: [] }], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: SELECT * FROM unnest(Array[1,2,3]); formatted_sql: SELECT * FROM unnest(ARRAY[1, 2, 3]) - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [Wildcard], from: [TableWithJoins { relation: TableFunction { name: ObjectName([Ident { value: "unnest", quote_style: None }]), alias: None, args: [Unnamed(Expr(Array(Array { elem: [Value(Number("1")), Value(Number("2")), Value(Number("3"))], named: true })))] }, joins: [] }], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [Wildcard], from: [TableWithJoins { relation: TableFunction { name: ObjectName([Ident { value: "unnest", quote_style: None }]), alias: None, args: [Unnamed(Expr(Array(Array { elem: [Value(Number("1")), Value(Number("2")), Value(Number("3"))], named: true })))] }, joins: [] }], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: SELECT id, fname, lname FROM customer WHERE salary <> 'Not Provided' AND salary <> '' formatted_sql: SELECT id, fname, lname FROM customer WHERE salary <> 'Not Provided' AND salary <> '' - - input: SELECT id FROM customer WHERE NOT salary = '' formatted_sql: SELECT id FROM customer WHERE NOT salary = '' - - input: SELECT * FROM t LIMIT 1 FETCH FIRST ROWS ONLY - error_msg: "sql parser error: Cannot specify both LIMIT and FETCH" - + error_msg: 'sql parser error: Cannot specify both LIMIT and FETCH' - input: SELECT * FROM t FETCH FIRST ROWS WITH TIES - error_msg: "sql parser error: WITH TIES cannot be specified without ORDER BY clause" - + error_msg: 'sql parser error: WITH TIES cannot be specified without ORDER BY clause' - input: select * from (select 1 from 1); - error_msg: "sql parser error: Expected identifier, found: 1" - + error_msg: 'sql parser error: Expected identifier, found: 1' - input: select * from (select * from tumble(t, x, interval '10' minutes)) - error_msg: "sql parser error: Expected ), found: minutes" - + error_msg: 'sql parser error: Expected ), found: minutes' - input: SELECT 1, FROM t error_msg: 'sql parser error: syntax error at or near "FROM"' - - input: SELECT 1, WHERE true error_msg: 'sql parser error: syntax error at or near "WHERE"' - - input: SELECT timestamp with time zone '2022-10-01 12:00:00Z' AT TIME ZONE 'US/Pacific' formatted_sql: SELECT TIMESTAMP WITH TIME ZONE '2022-10-01 12:00:00Z' AT TIME ZONE 'US/Pacific' - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(AtTimeZone { timestamp: TypedString { data_type: Timestamp(true), value: "2022-10-01 12:00:00Z" }, time_zone: "US/Pacific" })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(AtTimeZone { timestamp: TypedString { data_type: Timestamp(true), value: "2022-10-01 12:00:00Z" }, time_zone: "US/Pacific" })], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: SELECT 1e6 formatted_sql: SELECT 1e6 - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Value(Number("1e6")))], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Value(Number("1e6")))], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: SELECT 1.25E6 formatted_sql: SELECT 1.25e6 - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Value(Number("1.25e6")))], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Value(Number("1.25e6")))], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: SELECT 1e-6 formatted_sql: SELECT 1e-6 - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Value(Number("1e-6")))], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Value(Number("1e-6")))], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: SELECT -1e6 formatted_sql: SELECT -1e6 - formatted_ast: | - Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Value(Number("-1e6")))], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None }) - + formatted_ast: 'Query(Query { with: None, body: Select(Select { distinct: All, projection: [UnnamedExpr(Value(Number("-1e6")))], from: [], lateral_views: [], selection: None, group_by: [], having: None }), order_by: [], limit: None, offset: None, fetch: None })' - input: SELECT 1::float(0) - error_msg: | - sql parser error: precision for type float must be at least 1 bit + error_msg: 'sql parser error: precision for type float must be at least 1 bit' - input: SELECT 1::float(54) - error_msg: | - sql parser error: precision for type float must be less than 54 bits + error_msg: 'sql parser error: precision for type float must be less than 54 bits' - input: SELECT 1::int(2) - error_msg: | - sql parser error: Expected end of statement, found: ( + error_msg: 'sql parser error: Expected end of statement, found: (' diff --git a/src/sqlparser/tests/testdata/show.yaml b/src/sqlparser/tests/testdata/show.yaml index e2ca4c6eacb1a..079021c135b4b 100644 --- a/src/sqlparser/tests/testdata/show.yaml +++ b/src/sqlparser/tests/testdata/show.yaml @@ -1,74 +1,46 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: SHOW DATABASES formatted_sql: SHOW DATABASES - formatted_ast: | - ShowObjects(Database) - + formatted_ast: ShowObjects(Database) - input: SHOW SCHEMAS formatted_sql: SHOW SCHEMAS - formatted_ast: | - ShowObjects(Schema) - + formatted_ast: ShowObjects(Schema) - input: SHOW TABLES formatted_sql: SHOW TABLES - formatted_ast: | - ShowObjects(Table { schema: None }) - + formatted_ast: 'ShowObjects(Table { schema: None })' - input: SHOW TABLES FROM t formatted_sql: SHOW TABLES FROM t - formatted_ast: | - ShowObjects(Table { schema: Some(Ident { value: "t", quote_style: None }) }) - + formatted_ast: 'ShowObjects(Table { schema: Some(Ident { value: "t", quote_style: None }) })' - input: SHOW VIEWS formatted_sql: SHOW VIEWS - formatted_ast: | - ShowObjects(View { schema: None }) - + formatted_ast: 'ShowObjects(View { schema: None })' - input: SHOW VIEWS FROM t formatted_sql: SHOW VIEWS FROM t - formatted_ast: | - ShowObjects(View { schema: Some(Ident { value: "t", quote_style: None }) }) - + formatted_ast: 'ShowObjects(View { schema: Some(Ident { value: "t", quote_style: None }) })' - input: SHOW MATERIALIZED VIEWS formatted_sql: SHOW MATERIALIZED VIEWS - formatted_ast: | - ShowObjects(MaterializedView { schema: None }) - + formatted_ast: 'ShowObjects(MaterializedView { schema: None })' - input: SHOW INTERNAL TABLES formatted_sql: SHOW INTERNAL TABLES - formatted_ast: | - ShowObjects(InternalTable { schema: None }) - + formatted_ast: 'ShowObjects(InternalTable { schema: None })' - input: SHOW INTERNAL TABLES FROM t formatted_sql: SHOW INTERNAL TABLES FROM t - formatted_ast: | - ShowObjects(InternalTable { schema: Some(Ident { value: "t", quote_style: None }) }) - + formatted_ast: 'ShowObjects(InternalTable { schema: Some(Ident { value: "t", quote_style: None }) })' - input: SHOW MATERIALIZED VIEWS FROM t formatted_sql: SHOW MATERIALIZED VIEWS FROM t - formatted_ast: | - ShowObjects(MaterializedView { schema: Some(Ident { value: "t", quote_style: None }) }) - + formatted_ast: 'ShowObjects(MaterializedView { schema: Some(Ident { value: "t", quote_style: None }) })' - input: SHOW SOURCES FROM t formatted_sql: SHOW SOURCES FROM t - formatted_ast: | - ShowObjects(Source { schema: Some(Ident { value: "t", quote_style: None }) }) - + formatted_ast: 'ShowObjects(Source { schema: Some(Ident { value: "t", quote_style: None }) })' - input: DESCRIBE schema.t formatted_sql: DESCRIBE schema.t - formatted_ast: | - Describe { name: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "t", quote_style: None }]) } - + formatted_ast: 'Describe { name: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "t", quote_style: None }]) }' - input: SHOW COLUMNS FROM schema.t formatted_sql: SHOW COLUMNS FROM schema.t - formatted_ast: | - ShowObjects(Columns { table: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "t", quote_style: None }]) }) - + formatted_ast: 'ShowObjects(Columns { table: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "t", quote_style: None }]) })' - input: SHOW CREATE MATERIALIZED VIEW schema.mv formatted_sql: SHOW CREATE MATERIALIZED VIEW schema.mv - formatted_ast: | - ShowCreateObject { create_type: MaterializedView, name: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "mv", quote_style: None }]) } - + formatted_ast: 'ShowCreateObject { create_type: MaterializedView, name: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "mv", quote_style: None }]) }' - input: SHOW CREATE VIEW schema.v formatted_sql: SHOW CREATE VIEW schema.v - formatted_ast: | - ShowCreateObject { create_type: View, name: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "v", quote_style: None }]) } + formatted_ast: 'ShowCreateObject { create_type: View, name: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "v", quote_style: None }]) }' diff --git a/src/sqlparser/tests/testdata/struct.yaml b/src/sqlparser/tests/testdata/struct.yaml index 5a3815b3f99c7..4898714fc5858 100644 --- a/src/sqlparser/tests/testdata/struct.yaml +++ b/src/sqlparser/tests/testdata/struct.yaml @@ -1,5 +1,5 @@ +# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: SELECT (1 * 2, 1.0)::foo; formatted_sql: SELECT CAST(ROW(1 * 2, 1.0) AS foo) - - input: SELECT ROW(1 * 2, 1.0)::foo; formatted_sql: SELECT CAST(ROW(1 * 2, 1.0) AS foo)