From cab8403d8327e753feb7524b6df610810e915849 Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Fri, 31 May 2024 14:32:38 +0800 Subject: [PATCH] refactor(parser): eliminate the gap between parser v1 and v2 (#17019) Signed-off-by: Runji Wang Signed-off-by: TennyZhuang Co-authored-by: TennyZhuang --- .typos.toml | 3 +- e2e_test/error_ui/extended/main.slt | 4 +- e2e_test/error_ui/simple/main.slt | 4 +- e2e_test/source/basic/ddl.slt | 2 +- .../src/expr/function_impl/cast_regclass.rs | 22 +- src/sqlparser/src/ast/legacy_source.rs | 33 +- src/sqlparser/src/ast/mod.rs | 17 +- src/sqlparser/src/ast/statement.rs | 126 +- src/sqlparser/src/bin/sqlparser.rs | 27 +- src/sqlparser/src/parser.rs | 1356 +++++++---------- src/sqlparser/src/parser_v2/data_type.rs | 2 +- src/sqlparser/src/parser_v2/impl_.rs | 72 +- src/sqlparser/src/parser_v2/mod.rs | 89 +- src/sqlparser/src/parser_v2/number.rs | 32 +- src/sqlparser/src/test_utils.rs | 4 +- src/sqlparser/src/tokenizer.rs | 85 +- src/sqlparser/tests/sqlparser_postgres.rs | 8 +- src/sqlparser/tests/testdata/array.yaml | 32 +- src/sqlparser/tests/testdata/create.yaml | 38 +- src/sqlparser/tests/testdata/insert.yaml | 4 +- src/sqlparser/tests/testdata/select.yaml | 43 +- src/sqlparser/tests/testdata/set.yaml | 6 +- src/sqlparser/tests/testdata/struct.yaml | 2 +- src/sqlparser/tests/testdata/subquery.yaml | 8 +- 24 files changed, 885 insertions(+), 1134 deletions(-) diff --git a/.typos.toml b/.typos.toml index 7dcf4af6257d4..567904f5c319b 100644 --- a/.typos.toml +++ b/.typos.toml @@ -9,7 +9,7 @@ steam = "stream" # You played with Steam games too much. ser = "ser" # Serialization # Some weird short variable names ot = "ot" -bui = "bui" # BackwardUserIterator +bui = "bui" # BackwardUserIterator mosquitto = "mosquitto" # This is a MQTT broker. abd = "abd" iy = "iy" @@ -22,6 +22,7 @@ extend-exclude = [ "e2e_test", "**/*.svg", "scripts", + "src/sqlparser/tests/testdata/", "src/frontend/planner_test/tests/testdata", "src/tests/sqlsmith/tests/freeze", "Cargo.lock", diff --git a/e2e_test/error_ui/extended/main.slt b/e2e_test/error_ui/extended/main.slt index eb6669ce89d71..99de2de06908d 100644 --- a/e2e_test/error_ui/extended/main.slt +++ b/e2e_test/error_ui/extended/main.slt @@ -4,9 +4,9 @@ selet 1; db error: ERROR: Failed to prepare the statement Caused by: - sql parser error: expected an SQL statement, found: selet at line 1, column 1 + sql parser error: expected statement, found: selet LINE 1: selet 1; - ^ + ^ query error diff --git a/e2e_test/error_ui/simple/main.slt b/e2e_test/error_ui/simple/main.slt index c569560af631a..4445bedee968b 100644 --- a/e2e_test/error_ui/simple/main.slt +++ b/e2e_test/error_ui/simple/main.slt @@ -4,9 +4,9 @@ selet 1; db error: ERROR: Failed to run the query Caused by: - sql parser error: expected an SQL statement, found: selet at line 1, column 1 + sql parser error: expected statement, found: selet LINE 1: selet 1; - ^ + ^ statement error diff --git a/e2e_test/source/basic/ddl.slt b/e2e_test/source/basic/ddl.slt index 33b79dfda9b67..465e0f19344e9 100644 --- a/e2e_test/source/basic/ddl.slt +++ b/e2e_test/source/basic/ddl.slt @@ -4,7 +4,7 @@ create source s; db error: ERROR: Failed to run the query Caused by: - sql parser error: expected description of the format, found: ; at line 1, column 16 + sql parser error: expected description of the format, found: ; LINE 1: create source s; ^ diff --git a/src/frontend/src/expr/function_impl/cast_regclass.rs b/src/frontend/src/expr/function_impl/cast_regclass.rs index b1ec47a2d3508..c350d3984ab97 100644 --- a/src/frontend/src/expr/function_impl/cast_regclass.rs +++ b/src/frontend/src/expr/function_impl/cast_regclass.rs @@ -15,7 +15,6 @@ use risingwave_common::session_config::SearchPath; use risingwave_expr::{capture_context, function, ExprError}; use risingwave_sqlparser::parser::{Parser, ParserError}; -use risingwave_sqlparser::tokenizer::{Token, Tokenizer}; use thiserror::Error; use thiserror_ext::AsReport; @@ -63,7 +62,11 @@ fn resolve_regclass_inner( db_name: &str, class_name: &str, ) -> Result { - let obj = parse_object_name(class_name)?; + // We use the full parser here because this function needs to accept every legal way + // of identifying an object in PG SQL as a valid value for the varchar + // literal. For example: 'foo', 'public.foo', '"my table"', and + // '"my schema".foo' must all work as values passed pg_table_size. + let obj = Parser::parse_object_name_str(class_name)?; if obj.0.len() == 1 { let class_name = obj.0[0].real_value(); @@ -81,21 +84,6 @@ fn resolve_regclass_inner( } } -fn parse_object_name(name: &str) -> Result { - // We use the full parser here because this function needs to accept every legal way - // of identifying an object in PG SQL as a valid value for the varchar - // literal. For example: 'foo', 'public.foo', '"my table"', and - // '"my schema".foo' must all work as values passed pg_table_size. - let mut tokenizer = Tokenizer::new(name); - let tokens = tokenizer - .tokenize_with_location() - .map_err(ParserError::from)?; - let mut parser = Parser::new(tokens); - let object = parser.parse_object_name()?; - parser.expect_token(&Token::EOF)?; - Ok(object) -} - #[function("cast_regclass(varchar) -> int4")] fn cast_regclass(class_name: &str) -> Result { let oid = resolve_regclass_impl_captured(class_name)?; diff --git a/src/sqlparser/src/ast/legacy_source.rs b/src/sqlparser/src/ast/legacy_source.rs index e5f957231f5ad..6a079688c2d4e 100644 --- a/src/sqlparser/src/ast/legacy_source.rs +++ b/src/sqlparser/src/ast/legacy_source.rs @@ -20,14 +20,15 @@ use std::fmt; use itertools::Itertools as _; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use winnow::PResult; use crate::ast::{ AstString, AstVec, ConnectorSchema, Encode, Format, Ident, ObjectName, ParseTo, SqlOption, Value, }; use crate::keywords::Keyword; -use crate::parser::{Parser, ParserError}; -use crate::{impl_fmt_display, impl_parse_to}; +use crate::parser::{Parser, StrError}; +use crate::{impl_fmt_display, impl_parse_to, parser_err}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -64,12 +65,10 @@ impl From for CompatibleSourceSchema { } } -pub fn parse_source_schema(p: &mut Parser) -> Result { +pub fn parse_source_schema(p: &mut Parser<'_>) -> PResult { if let Some(schema_v2) = p.parse_schema()? { if schema_v2.key_encode.is_some() { - return Err(ParserError::ParserError( - "key encode clause is not supported in source schema".to_string(), - )); + parser_err!("key encode clause is not supported in source schema"); } Ok(CompatibleSourceSchema::V2(schema_v2)) } else if p.peek_nth_any_of_keywords(0, &[Keyword::ROW]) @@ -109,16 +108,15 @@ pub fn parse_source_schema(p: &mut Parser) -> Result SourceSchema::Bytes, _ => { - return Err(ParserError::ParserError( + parser_err!( "expected JSON | UPSERT_JSON | PROTOBUF | DEBEZIUM_JSON | DEBEZIUM_AVRO \ | AVRO | UPSERT_AVRO | MAXWELL | CANAL_JSON | BYTES | NATIVE after ROW FORMAT" - .to_string(), - )); + ); } }; Ok(CompatibleSourceSchema::RowFormat(schema)) } else { - p.expected("description of the format", p.peek_token()) + p.expected("description of the format") } } @@ -286,7 +284,7 @@ pub struct ProtobufSchema { } impl ParseTo for ProtobufSchema { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!([Keyword::MESSAGE], p); impl_parse_to!(message_name: AstString, p); impl_parse_to!([Keyword::ROW, Keyword::SCHEMA, Keyword::LOCATION], p); @@ -324,7 +322,7 @@ pub struct AvroSchema { } impl ParseTo for AvroSchema { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!([Keyword::ROW, Keyword::SCHEMA, Keyword::LOCATION], p); impl_parse_to!(use_schema_registry => [Keyword::CONFLUENT, Keyword::SCHEMA, Keyword::REGISTRY], p); impl_parse_to!(row_schema_location: AstString, p); @@ -371,7 +369,7 @@ impl fmt::Display for DebeziumAvroSchema { } impl ParseTo for DebeziumAvroSchema { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!( [ Keyword::ROW, @@ -397,19 +395,18 @@ pub struct CsvInfo { pub has_header: bool, } -pub fn get_delimiter(chars: &str) -> Result { +pub fn get_delimiter(chars: &str) -> Result { match chars { "," => Ok(b','), // comma "\t" => Ok(b'\t'), // tab - other => Err(ParserError::ParserError(format!( - "The delimiter should be one of ',', E'\\t', but got {:?}", - other + other => Err(StrError(format!( + "The delimiter should be one of ',', E'\\t', but got {other:?}", ))), } } impl ParseTo for CsvInfo { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!(without_header => [Keyword::WITHOUT, Keyword::HEADER], p); impl_parse_to!([Keyword::DELIMITED, Keyword::BY], p); impl_parse_to!(delimiter: AstString, p); diff --git a/src/sqlparser/src/ast/mod.rs b/src/sqlparser/src/ast/mod.rs index 4b96565a0d683..0ce72be34bf82 100644 --- a/src/sqlparser/src/ast/mod.rs +++ b/src/sqlparser/src/ast/mod.rs @@ -33,6 +33,7 @@ use std::sync::Arc; use itertools::Itertools; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use winnow::PResult; pub use self::data_type::{DataType, StructField}; pub use self::ddl::{ @@ -59,7 +60,7 @@ pub use crate::ast::ddl::{ AlterViewOperation, }; use crate::keywords::Keyword; -use crate::parser::{IncludeOption, IncludeOptionItem, Parser, ParserError}; +use crate::parser::{IncludeOption, IncludeOptionItem, Parser, ParserError, StrError}; pub type RedactSqlOptionKeywordsRef = Arc>; @@ -191,7 +192,7 @@ impl From<&str> for Ident { } impl ParseTo for Ident { - fn parse_to(parser: &mut Parser) -> Result { + fn parse_to(parser: &mut Parser<'_>) -> PResult { parser.parse_identifier() } } @@ -235,7 +236,7 @@ impl fmt::Display for ObjectName { } impl ParseTo for ObjectName { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { p.parse_object_name() } } @@ -2560,7 +2561,7 @@ impl fmt::Display for ObjectType { } impl ParseTo for ObjectType { - fn parse_to(parser: &mut Parser) -> Result { + fn parse_to(parser: &mut Parser<'_>) -> PResult { let object_type = if parser.parse_keyword(Keyword::TABLE) { ObjectType::Table } else if parser.parse_keyword(Keyword::VIEW) { @@ -2588,7 +2589,6 @@ impl ParseTo for ObjectType { } else { return parser.expected( "TABLE, VIEW, INDEX, MATERIALIZED VIEW, SOURCE, SINK, SUBSCRIPTION, SCHEMA, DATABASE, USER, SECRET or CONNECTION after DROP", - parser.peek_token(), ); }; Ok(object_type) @@ -3007,7 +3007,7 @@ impl CreateFunctionWithOptions { /// TODO(kwannoel): Generate from the struct definition instead. impl TryFrom> for CreateFunctionWithOptions { - type Error = ParserError; + type Error = StrError; fn try_from(with_options: Vec) -> Result { let mut always_retry_on_network_error = None; @@ -3015,10 +3015,7 @@ impl TryFrom> for CreateFunctionWithOptions { if option.name.to_string().to_lowercase() == "always_retry_on_network_error" { always_retry_on_network_error = Some(option.value == Value::Boolean(true)); } else { - return Err(ParserError::ParserError(format!( - "Unsupported option: {}", - option.name - ))); + return Err(StrError(format!("Unsupported option: {}", option.name))); } } Ok(Self { diff --git a/src/sqlparser/src/ast/statement.rs b/src/sqlparser/src/ast/statement.rs index 2e5b281d1938f..0c92209471450 100644 --- a/src/sqlparser/src/ast/statement.rs +++ b/src/sqlparser/src/ast/statement.rs @@ -19,6 +19,7 @@ use std::fmt::Write; use itertools::Itertools; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use winnow::PResult; use super::ddl::SourceWatermark; use super::legacy_source::{parse_source_schema, CompatibleSourceSchema}; @@ -27,12 +28,14 @@ use crate::ast::{ display_comma_separated, display_separated, ColumnDef, ObjectName, SqlOption, TableConstraint, }; use crate::keywords::Keyword; -use crate::parser::{IncludeOption, IsOptional, Parser, ParserError, UPSTREAM_SOURCE_KEY}; +use crate::parser::{IncludeOption, IsOptional, Parser, UPSTREAM_SOURCE_KEY}; +use crate::parser_err; +use crate::parser_v2::literal_u32; use crate::tokenizer::Token; /// Consumes token from the parser into an AST node. pub trait ParseTo: Sized { - fn parse_to(parser: &mut Parser) -> Result; + fn parse_to(parser: &mut Parser<'_>) -> PResult; } #[macro_export] @@ -132,7 +135,7 @@ impl fmt::Display for Format { } impl Format { - pub fn from_keyword(s: &str) -> Result { + pub fn from_keyword(s: &str) -> PResult { Ok(match s { "DEBEZIUM" => Format::Debezium, "DEBEZIUM_MONGO" => Format::DebeziumMongo, @@ -142,12 +145,9 @@ impl Format { "UPSERT" => Format::Upsert, "NATIVE" => Format::Native, // used internally for schema change "NONE" => Format::None, // used by iceberg - _ => { - return Err(ParserError::ParserError( - "expected CANAL | PROTOBUF | DEBEZIUM | MAXWELL | PLAIN | NATIVE | NONE after FORMAT" - .to_string(), - )); - } + _ => parser_err!( + "expected CANAL | PROTOBUF | DEBEZIUM | MAXWELL | PLAIN | NATIVE | NONE after FORMAT" + ), }) } } @@ -188,7 +188,7 @@ impl fmt::Display for Encode { } impl Encode { - pub fn from_keyword(s: &str) -> Result { + pub fn from_keyword(s: &str) -> PResult { Ok(match s { "AVRO" => Encode::Avro, "TEXT" => Encode::Text, @@ -199,10 +199,9 @@ impl Encode { "TEMPLATE" => Encode::Template, "NATIVE" => Encode::Native, // used internally for schema change "NONE" => Encode::None, // used by iceberg - _ => return Err(ParserError::ParserError( + _ => parser_err!( "expected AVRO | BYTES | CSV | PROTOBUF | JSON | NATIVE | TEMPLATE | NONE after Encode" - .to_string(), - )), + ), }) } } @@ -217,7 +216,7 @@ pub struct ConnectorSchema { pub key_encode: Option, } -impl Parser { +impl Parser<'_> { /// Peek the next tokens to see if it is `FORMAT` or `ROW FORMAT` (for compatibility). fn peek_source_schema_format(&mut self) -> bool { (self.peek_nth_any_of_keywords(0, &[Keyword::ROW]) @@ -230,7 +229,7 @@ impl Parser { &mut self, connector: &str, cdc_source_job: bool, - ) -> Result { + ) -> PResult { // row format for cdc source must be debezium json // row format for nexmark source must be native // default row format for datagen source is native @@ -247,10 +246,10 @@ impl Parser { if self.peek_source_schema_format() { let schema = parse_source_schema(self)?.into_v2(); if schema != expected { - return Err(ParserError::ParserError(format!( + parser_err!( "Row format for CDC connectors should be \ either omitted or set to `{expected}`", - ))); + ); } } Ok(expected.into()) @@ -259,10 +258,10 @@ impl Parser { if self.peek_source_schema_format() { let schema = parse_source_schema(self)?.into_v2(); if schema != expected { - return Err(ParserError::ParserError(format!( + parser_err!( "Row format for nexmark connectors should be \ either omitted or set to `{expected}`", - ))); + ); } } Ok(expected.into()) @@ -277,10 +276,10 @@ impl Parser { if self.peek_source_schema_format() { let schema = parse_source_schema(self)?.into_v2(); if schema != expected { - return Err(ParserError::ParserError(format!( + parser_err!( "Row format for iceberg connectors should be \ either omitted or set to `{expected}`", - ))); + ); } } Ok(expected.into()) @@ -290,7 +289,7 @@ impl Parser { } /// Parse `FORMAT ... ENCODE ... (...)`. - pub fn parse_schema(&mut self) -> Result, ParserError> { + pub fn parse_schema(&mut self) -> PResult> { if !self.parse_keyword(Keyword::FORMAT) { return Ok(None); } @@ -389,7 +388,7 @@ impl fmt::Display for ConnectorSchema { } impl ParseTo for CreateSourceStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!(if_not_exists => [Keyword::IF, Keyword::NOT, Keyword::EXISTS], p); impl_parse_to!(source_name: ObjectName, p); @@ -405,9 +404,7 @@ impl ParseTo for CreateSourceStatement { let connector: String = option.map(|opt| opt.value.to_string()).unwrap_or_default(); let cdc_source_job = connector.contains("-cdc"); if cdc_source_job && (!columns.is_empty() || !constraints.is_empty()) { - return Err(ParserError::ParserError( - "CDC source cannot define columns and constraints".to_string(), - )); + parser_err!("CDC source cannot define columns and constraints"); } // row format for nexmark source must be native @@ -524,7 +521,7 @@ pub struct CreateSinkStatement { } impl ParseTo for CreateSinkStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!(if_not_exists => [Keyword::IF, Keyword::NOT, Keyword::EXISTS], p); impl_parse_to!(sink_name: ObjectName, p); @@ -544,7 +541,7 @@ impl ParseTo for CreateSinkStatement { let query = Box::new(p.parse_query()?); CreateSink::AsQuery(query) } else { - p.expected("FROM or AS after CREATE SINK sink_name", p.peek_token())? + p.expected("FROM or AS after CREATE SINK sink_name")? }; let emit_mode: Option = p.parse_emit_mode()?; @@ -552,14 +549,12 @@ impl ParseTo for CreateSinkStatement { // This check cannot be put into the `WithProperties::parse_to`, since other // statements may not need the with properties. if !p.peek_nth_any_of_keywords(0, &[Keyword::WITH]) && into_table_name.is_none() { - p.expected("WITH", p.peek_token())? + p.expected("WITH")? } impl_parse_to!(with_properties: WithProperties, p); if with_properties.0.is_empty() && into_table_name.is_none() { - return Err(ParserError::ParserError( - "sink properties not provided".to_string(), - )); + parser_err!("sink properties not provided"); } let sink_schema = p.parse_schema()?; @@ -616,7 +611,7 @@ pub struct CreateSubscriptionStatement { } impl ParseTo for CreateSubscriptionStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!(if_not_exists => [Keyword::IF, Keyword::NOT, Keyword::EXISTS], p); impl_parse_to!(subscription_name: ObjectName, p); @@ -624,10 +619,7 @@ impl ParseTo for CreateSubscriptionStatement { impl_parse_to!(from_name: ObjectName, p); from_name } else { - p.expected( - "FROM after CREATE SUBSCRIPTION subscription_name", - p.peek_token(), - )? + p.expected("FROM after CREATE SUBSCRIPTION subscription_name")? }; // let emit_mode = p.parse_emit_mode()?; @@ -635,14 +627,12 @@ impl ParseTo for CreateSubscriptionStatement { // This check cannot be put into the `WithProperties::parse_to`, since other // statements may not need the with properties. if !p.peek_nth_any_of_keywords(0, &[Keyword::WITH]) { - p.expected("WITH", p.peek_token())? + p.expected("WITH")? } impl_parse_to!(with_properties: WithProperties, p); if with_properties.0.is_empty() { - return Err(ParserError::ParserError( - "subscription properties not provided".to_string(), - )); + parser_err!("subscription properties not provided"); } Ok(Self { @@ -703,7 +693,7 @@ pub struct DeclareCursorStatement { } impl ParseTo for DeclareCursorStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!(cursor_name: ObjectName, p); let declare_cursor = if !p.parse_keyword(Keyword::SUBSCRIPTION) { @@ -746,14 +736,11 @@ pub struct FetchCursorStatement { } impl ParseTo for FetchCursorStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { let count = if p.parse_keyword(Keyword::NEXT) { 1 } else { - let count_str = p.parse_number_value()?; - count_str.parse::().map_err(|e| { - ParserError::ParserError(format!("Could not parse '{}' as i32: {}", count_str, e)) - })? + literal_u32(p)? }; p.expect_keyword(Keyword::FROM)?; impl_parse_to!(cursor_name: ObjectName, p); @@ -786,7 +773,7 @@ pub struct CloseCursorStatement { } impl ParseTo for CloseCursorStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { let cursor_name = if p.parse_keyword(Keyword::ALL) { None } else { @@ -823,14 +810,12 @@ pub struct CreateConnectionStatement { } impl ParseTo for CreateConnectionStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!(if_not_exists => [Keyword::IF, Keyword::NOT, Keyword::EXISTS], p); impl_parse_to!(connection_name: ObjectName, p); impl_parse_to!(with_properties: WithProperties, p); if with_properties.0.is_empty() { - return Err(ParserError::ParserError( - "connection properties not provided".to_string(), - )); + parser_err!("connection properties not provided"); } Ok(Self { @@ -861,7 +846,7 @@ pub struct CreateSecretStatement { } impl ParseTo for CreateSecretStatement { - fn parse_to(parser: &mut Parser) -> Result { + fn parse_to(parser: &mut Parser<'_>) -> PResult { impl_parse_to!(if_not_exists => [Keyword::IF, Keyword::NOT, Keyword::EXISTS], parser); impl_parse_to!(secret_name: ObjectName, parser); impl_parse_to!(with_properties: WithProperties, parser); @@ -907,7 +892,7 @@ impl fmt::Display for AstVec { pub struct WithProperties(pub Vec); impl ParseTo for WithProperties { - fn parse_to(parser: &mut Parser) -> Result { + fn parse_to(parser: &mut Parser<'_>) -> PResult { Ok(Self( parser.parse_options_with_preceding_keyword(Keyword::WITH)?, )) @@ -950,7 +935,7 @@ pub struct RowSchemaLocation { } impl ParseTo for RowSchemaLocation { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!([Keyword::ROW, Keyword::SCHEMA, Keyword::LOCATION], p); impl_parse_to!(value: AstString, p); Ok(Self { value }) @@ -973,7 +958,7 @@ impl fmt::Display for RowSchemaLocation { pub struct AstString(pub String); impl ParseTo for AstString { - fn parse_to(parser: &mut Parser) -> Result { + fn parse_to(parser: &mut Parser<'_>) -> PResult { Ok(Self(parser.parse_literal_string()?)) } } @@ -996,7 +981,7 @@ pub enum AstOption { } impl ParseTo for AstOption { - fn parse_to(parser: &mut Parser) -> Result { + fn parse_to(parser: &mut Parser<'_>) -> PResult { match T::parse_to(parser) { Ok(t) => Ok(AstOption::Some(t)), Err(_) => Ok(AstOption::None), @@ -1116,17 +1101,14 @@ impl UserOptionsBuilder { } impl ParseTo for UserOptions { - fn parse_to(parser: &mut Parser) -> Result { + fn parse_to(parser: &mut Parser<'_>) -> PResult { let mut builder = UserOptionsBuilder::default(); let add_option = |item: &mut Option, user_option| { let old_value = item.replace(user_option); if old_value.is_some() { - Err(ParserError::ParserError( - "conflicting or redundant options".to_string(), - )) - } else { - Ok(()) + parser_err!("conflicting or redundant options"); } + Ok(()) }; let _ = parser.parse_keyword(Keyword::WITH); loop { @@ -1136,6 +1118,7 @@ impl ParseTo for UserOptions { } if let Token::Word(ref w) = token.token { + let checkpoint = *parser; parser.next_token(); let (item_mut_ref, user_option) = match w.keyword { Keyword::SUPERUSER => (&mut builder.super_user, UserOption::SuperUser), @@ -1168,10 +1151,10 @@ impl ParseTo for UserOptions { (&mut builder.password, UserOption::OAuth(options)) } _ => { - parser.expected( + parser.expected_at( + checkpoint, "SUPERUSER | NOSUPERUSER | CREATEDB | NOCREATEDB | LOGIN \ | NOLOGIN | CREATEUSER | NOCREATEUSER | [ENCRYPTED] PASSWORD | NULL | OAUTH", - token, )?; unreachable!() } @@ -1181,7 +1164,6 @@ impl ParseTo for UserOptions { parser.expected( "SUPERUSER | NOSUPERUSER | CREATEDB | NOCREATEDB | LOGIN | NOLOGIN \ | CREATEUSER | NOCREATEUSER | [ENCRYPTED] PASSWORD | NULL | OAUTH", - token, )? } } @@ -1200,7 +1182,7 @@ impl fmt::Display for UserOptions { } impl ParseTo for CreateUserStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!(user_name: ObjectName, p); impl_parse_to!(with_options: UserOptions, p); @@ -1243,7 +1225,7 @@ impl fmt::Display for AlterUserStatement { } impl ParseTo for AlterUserStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!(user_name: ObjectName, p); impl_parse_to!(mode: AlterUserMode, p); @@ -1252,7 +1234,7 @@ impl ParseTo for AlterUserStatement { } impl ParseTo for AlterUserMode { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { if p.parse_keyword(Keyword::RENAME) { p.expect_keyword(Keyword::TO)?; impl_parse_to!(new_name: ObjectName, p); @@ -1285,7 +1267,7 @@ pub struct DropStatement { // drop_mode: AstOption, // }); impl ParseTo for DropStatement { - fn parse_to(p: &mut Parser) -> Result { + fn parse_to(p: &mut Parser<'_>) -> PResult { impl_parse_to!(object_type: ObjectType, p); impl_parse_to!(if_exists => [Keyword::IF, Keyword::EXISTS], p); let object_name = p.parse_object_name()?; @@ -1318,13 +1300,13 @@ pub enum DropMode { } impl ParseTo for DropMode { - fn parse_to(parser: &mut Parser) -> Result { + fn parse_to(parser: &mut Parser<'_>) -> PResult { let drop_mode = if parser.parse_keyword(Keyword::CASCADE) { DropMode::Cascade } else if parser.parse_keyword(Keyword::RESTRICT) { DropMode::Restrict } else { - return parser.expected("CASCADE | RESTRICT", parser.peek_token()); + return parser.expected("CASCADE | RESTRICT"); }; Ok(drop_mode) } diff --git a/src/sqlparser/src/bin/sqlparser.rs b/src/sqlparser/src/bin/sqlparser.rs index be2ec51bc78fc..57a984a8c1cd1 100644 --- a/src/sqlparser/src/bin/sqlparser.rs +++ b/src/sqlparser/src/bin/sqlparser.rs @@ -1,3 +1,19 @@ +// 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. + +#![feature(register_tool)] +#![register_tool(rw)] +#![allow(rw::format_error)] // test code + use std::io; use risingwave_sqlparser::parser::Parser; @@ -12,5 +28,14 @@ fn main() { let mut buffer = String::new(); io::stdin().read_line(&mut buffer).unwrap(); let result = Parser::parse_sql(&buffer); - println!("{:#?}", result); + match result { + Ok(statements) => { + for statement in statements { + println!("{:#?}", statement); + } + } + Err(e) => { + eprintln!("{}", e); + } + } } diff --git a/src/sqlparser/src/parser.rs b/src/sqlparser/src/parser.rs index 71a2099e0e6fd..b1a8e2ba22b90 100644 --- a/src/sqlparser/src/parser.rs +++ b/src/sqlparser/src/parser.rs @@ -24,10 +24,13 @@ use core::fmt; use itertools::Itertools; use tracing::{debug, instrument}; +use winnow::combinator::{alt, cut_err, dispatch, fail, opt, peek, preceded, repeat, separated}; +use winnow::{PResult, Parser as _}; use crate::ast::*; use crate::keywords::{self, Keyword}; use crate::parser_v2; +use crate::parser_v2::{keyword, literal_i64, literal_uint, ParserExt as _}; use crate::tokenizer::*; pub(crate) const UPSTREAM_SOURCE_KEY: &str = "connector"; @@ -45,14 +48,33 @@ impl ParserError { } } } + +#[derive(Debug, thiserror::Error)] +#[error("{0}")] +pub struct StrError(pub String); + // Use `Parser::expected` instead, if possible #[macro_export] macro_rules! parser_err { - ($MSG:expr) => { - Err(ParserError::ParserError($MSG.to_string())) + ($($arg:tt)*) => { + return Err(winnow::error::ErrMode::Backtrack(>::from_external_error( + &Parser::default(), + winnow::error::ErrorKind::Fail, + $crate::parser::StrError(format!($($arg)*)), + ))) }; } +impl From for winnow::error::ErrMode { + fn from(e: StrError) -> Self { + winnow::error::ErrMode::Backtrack(>::from_external_error( + &Parser::default(), + winnow::error::ErrorKind::Fail, + e, + )) + } +} + // Returns a successful result if the optional expression is some macro_rules! return_ok_if_some { ($e:expr) => {{ @@ -169,70 +191,20 @@ pub enum Precedence { DoubleColon, // 50 in upstream } -pub struct Parser { - tokens: Vec, - /// The index of the first unprocessed token in `self.tokens` - index: usize, -} - -impl Parser { - /// Parse the specified tokens - pub fn new(tokens: Vec) -> Self { - Parser { tokens, index: 0 } - } - - /// Adaptor for [`parser_v2`]. - /// - /// You can call a v2 parser from original parser by using this method. - pub(crate) fn parse_v2<'a, O>( - &'a mut self, - mut parse_next: impl winnow::Parser< - winnow::Located>, - O, - winnow::error::ContextError, - >, - ) -> Result { - use winnow::stream::Location; - - let mut token_stream = winnow::Located::new(parser_v2::TokenStreamWrapper { - tokens: &self.tokens[self.index..], - }); - let output = parse_next.parse_next(&mut token_stream).map_err(|e| { - let msg = if let Some(e) = e.into_inner() - && let Some(cause) = e.cause() - { - format!(": {}", cause) - } else { - "".to_string() - }; - ParserError::ParserError(format!( - "Unexpected {}{}", - if self.index + token_stream.location() >= self.tokens.len() { - &"EOF" as &dyn std::fmt::Display - } else { - &self.tokens[self.index + token_stream.location()] as &dyn std::fmt::Display - }, - msg - )) - }); - let offset = token_stream.location(); - self.index += offset; - output - } +#[derive(Clone, Copy, Default)] +pub struct Parser<'a>(pub(crate) &'a [TokenWithLocation]); +impl Parser<'_> { /// Parse a SQL statement and produce an Abstract Syntax Tree (AST) #[instrument(level = "debug")] pub fn parse_sql(sql: &str) -> Result, ParserError> { let mut tokenizer = Tokenizer::new(sql); let tokens = tokenizer.tokenize_with_location()?; - let mut parser = Parser::new(tokens); - let ast = parser.parse_statements().map_err(|e| { + let parser = Parser(&tokens); + let stmts = Parser::parse_statements.parse(parser).map_err(|e| { // append SQL context to the error message, e.g.: // LINE 1: SELECT 1::int(2); - // ^ - // XXX: the cursor location is not accurate - // it may be offset one token forward because the error token has been consumed - let loc = match parser.tokens.get(parser.index) { + let loc = match tokens.get(e.offset()) { Some(token) => token.location.clone(), None => { // get location of EOF @@ -247,17 +219,27 @@ impl Parser { let cursor = " ".repeat(prefix.len() + loc.column as usize - 1); ParserError::ParserError(format!( "{}\n{}{}\n{}^", - e.inner_msg(), + e.inner().to_string().replace('\n', ": "), prefix, sql_line, cursor )) })?; - Ok(ast) + Ok(stmts) + } + + /// Parse object name from a string. + pub fn parse_object_name_str(s: &str) -> Result { + let mut tokenizer = Tokenizer::new(s); + let tokens = tokenizer.tokenize_with_location()?; + let parser = Parser(&tokens); + Parser::parse_object_name + .parse(parser) + .map_err(|e| ParserError::ParserError(e.inner().to_string())) } - /// Parse a list of semicolon-separated SQL statements. - pub fn parse_statements(&mut self) -> Result, ParserError> { + /// Parse a list of semicolon-separated statements. + fn parse_statements(&mut self) -> PResult> { let mut stmts = Vec::new(); let mut expecting_statement_delimiter = false; loop { @@ -270,7 +252,7 @@ impl Parser { break; } if expecting_statement_delimiter { - return self.expected("end of statement", self.peek_token()); + return self.expected("end of statement"); } let statement = self.parse_statement()?; @@ -283,14 +265,15 @@ impl Parser { /// Parse a single top-level statement (such as SELECT, INSERT, CREATE, etc.), /// stopping before the statement separator, if any. - pub fn parse_statement(&mut self) -> Result { + pub fn parse_statement(&mut self) -> PResult { + let checkpoint = *self; let token = self.next_token(); match token.token { Token::Word(w) => match w.keyword { Keyword::EXPLAIN => Ok(self.parse_explain()?), Keyword::ANALYZE => Ok(self.parse_analyze()?), Keyword::SELECT | Keyword::WITH | Keyword::VALUES => { - self.prev_token(); + *self = checkpoint; Ok(Statement::Query(Box::new(self.parse_query()?))) } Keyword::DECLARE => Ok(self.parse_declare()?), @@ -337,28 +320,23 @@ impl Parser { Keyword::FLUSH => Ok(Statement::Flush), Keyword::WAIT => Ok(Statement::Wait), Keyword::RECOVER => Ok(Statement::Recover), - _ => self.expected( - "an SQL statement", - Token::Word(w).with_location(token.location), - ), + _ => self.expected_at(checkpoint, "statement"), }, Token::LParen => { - self.prev_token(); + *self = checkpoint; Ok(Statement::Query(Box::new(self.parse_query()?))) } - unexpected => { - self.expected("an SQL statement", unexpected.with_location(token.location)) - } + _ => self.expected_at(checkpoint, "statement"), } } - pub fn parse_truncate(&mut self) -> Result { + pub fn parse_truncate(&mut self) -> PResult { let _ = self.parse_keyword(Keyword::TABLE); let table_name = self.parse_object_name()?; Ok(Statement::Truncate { table_name }) } - pub fn parse_analyze(&mut self) -> Result { + pub fn parse_analyze(&mut self) -> PResult { let table_name = self.parse_object_name()?; Ok(Statement::Analyze { table_name }) @@ -372,14 +350,14 @@ impl Parser { /// contain parentheses. /// - Selecting all columns from a table. In this case, it is a /// [`WildcardOrExpr::QualifiedWildcard`] or a [`WildcardOrExpr::Wildcard`]. - pub fn parse_wildcard_or_expr(&mut self) -> Result { - let index = self.index; + pub fn parse_wildcard_or_expr(&mut self) -> PResult { + let checkpoint = *self; match self.next_token().token { Token::Word(w) if self.peek_token() == Token::Period => { // Since there's no parenthesis, `w` must be a column or a table // So what follows must be dot-delimited identifiers, e.g. `a.b.c.*` - let wildcard_expr = self.parse_simple_wildcard_expr(index)?; + let wildcard_expr = self.parse_simple_wildcard_expr(checkpoint)?; return self.word_concat_wildcard_expr(w.to_ident()?, wildcard_expr); } Token::Mul => { @@ -396,14 +374,14 @@ impl Parser { } // Now that we have an expr, what follows must be // dot-delimited identifiers, e.g. `b.c.*` in `(a).b.c.*` - let wildcard_expr = self.parse_simple_wildcard_expr(index)?; + let wildcard_expr = self.parse_simple_wildcard_expr(checkpoint)?; return self.expr_concat_wildcard_expr(expr, wildcard_expr); } } _ => (), }; - self.index = index; + *self = checkpoint; self.parse_expr().map(WildcardOrExpr::Expr) } @@ -412,7 +390,7 @@ impl Parser { &mut self, ident: Ident, simple_wildcard_expr: WildcardOrExpr, - ) -> Result { + ) -> PResult { let mut idents = vec![ident]; let mut except_cols = vec![]; match simple_wildcard_expr { @@ -445,7 +423,7 @@ impl Parser { &mut self, expr: Expr, simple_wildcard_expr: WildcardOrExpr, - ) -> Result { + ) -> PResult { if let WildcardOrExpr::Expr(e) = simple_wildcard_expr { return Ok(WildcardOrExpr::Expr(e)); } @@ -475,19 +453,13 @@ impl Parser { match simple_wildcard_expr { WildcardOrExpr::QualifiedWildcard(ids, except) => { if except.is_some() { - return self.expected( - "Expr quantified wildcard does not support except", - self.peek_token(), - ); + return self.expected("Expr quantified wildcard does not support except"); } idents.extend(ids.0); } WildcardOrExpr::Wildcard(except) => { if except.is_some() { - return self.expected( - "Expr quantified wildcard does not support except", - self.peek_token(), - ); + return self.expected("Expr quantified wildcard does not support except"); } } WildcardOrExpr::ExprQualifiedWildcard(_, _) => unreachable!(), @@ -499,12 +471,10 @@ impl Parser { /// Tries to parses a wildcard expression without any parentheses. /// /// If wildcard is not found, go back to `index` and parse an expression. - pub fn parse_simple_wildcard_expr( - &mut self, - index: usize, - ) -> Result { + pub fn parse_simple_wildcard_expr(&mut self, checkpoint: Self) -> PResult { let mut id_parts = vec![]; while self.consume_token(&Token::Period) { + let ckpt = *self; let token = self.next_token(); match token.token { Token::Word(w) => id_parts.push(w.to_ident()?), @@ -518,43 +488,38 @@ impl Parser { )) }; } - unexpected => { - return self.expected( - "an identifier or a '*' after '.'", - unexpected.with_location(token.location), - ); + _ => { + *self = ckpt; + return self.expected("an identifier or a '*' after '.'"); } } } - self.index = index; + *self = checkpoint; self.parse_expr().map(WildcardOrExpr::Expr) } - pub fn parse_except(&mut self) -> Result>, ParserError> { + pub fn parse_except(&mut self) -> PResult>> { if !self.parse_keyword(Keyword::EXCEPT) { return Ok(None); } if !self.consume_token(&Token::LParen) { - return self.expected("EXCEPT should be followed by (", self.peek_token()); + return self.expected("EXCEPT should be followed by ("); } let exprs = self.parse_comma_separated(Parser::parse_expr)?; if self.consume_token(&Token::RParen) { Ok(Some(exprs)) } else { - self.expected( - "( should be followed by ) after column names", - self.peek_token(), - ) + self.expected("( should be followed by ) after column names") } } /// Parse a new expression - pub fn parse_expr(&mut self) -> Result { + pub fn parse_expr(&mut self) -> PResult { self.parse_subexpr(Precedence::Zero) } /// Parse tokens until the precedence changes - pub fn parse_subexpr(&mut self, precedence: Precedence) -> Result { + pub fn parse_subexpr(&mut self, precedence: Precedence) -> PResult { debug!("parsing expr, current token: {:?}", self.peek_token().token); let mut expr = self.parse_prefix()?; debug!("prefix: {:?}", expr); @@ -572,7 +537,7 @@ impl Parser { } /// Parse an expression prefix - pub fn parse_prefix(&mut self) -> Result { + pub fn parse_prefix(&mut self) -> PResult { // PostgreSQL allows any string literal to be preceded by a type name, indicating that the // string literal represents a literal of that type. Some examples: // @@ -607,11 +572,12 @@ impl Parser { } })); + let checkpoint = *self; let token = self.next_token(); let expr = match token.token.clone() { Token::Word(w) => match w.keyword { Keyword::TRUE | Keyword::FALSE | Keyword::NULL => { - self.prev_token(); + *self = checkpoint; Ok(Expr::Value(self.parse_value()?)) } Keyword::CASE => self.parse_case_expr(), @@ -657,7 +623,7 @@ impl Parser { // TODO: support `all/any/some(subquery)`. if let Expr::Subquery(_) = &sub { - parser_err!("ANY/SOME/ALL(Subquery) is not implemented")?; + parser_err!("ANY/SOME/ALL(Subquery) is not implemented"); } Ok(match keyword { @@ -668,7 +634,7 @@ impl Parser { }) } k if keywords::RESERVED_FOR_COLUMN_OR_TABLE_NAME.contains(&k) => { - parser_err!(format!("syntax error at or near {token}")) + parser_err!("syntax error at or near {token}") } // Here `w` is a word, check if it's a part of a multi-part // identifier, a function call, or a simple identifier: @@ -676,20 +642,18 @@ impl Parser { Token::LParen | Token::Period => { let mut id_parts: Vec = vec![w.to_ident()?]; while self.consume_token(&Token::Period) { + let ckpt = *self; let token = self.next_token(); match token.token { Token::Word(w) => id_parts.push(w.to_ident()?), - unexpected => { - return self.expected( - "an identifier or a '*' after '.'", - unexpected.with_location(token.location), - ); + _ => { + *self = ckpt; + return self.expected("an identifier or a '*' after '.'"); } } } - if self.consume_token(&Token::LParen) { - self.prev_token(); + if self.peek_token().token == Token::LParen { self.parse_function(ObjectName(id_parts)) } else { Ok(Expr::CompoundIdentifier(id_parts)) @@ -743,7 +707,7 @@ impl Parser { | Token::NationalStringLiteral(_) | Token::HexStringLiteral(_) | Token::CstyleEscapesString(_) => { - self.prev_token(); + *self = checkpoint; Ok(Expr::Value(self.parse_value()?)) } Token::Parameter(number) => self.parse_param(number), @@ -757,18 +721,17 @@ impl Parser { }) } Token::LParen => { - let expr = - if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH) { - self.prev_token(); - Expr::Subquery(Box::new(self.parse_query()?)) + let expr = if matches!(self.peek_token().token, Token::Word(w) if w.keyword == Keyword::SELECT || w.keyword == Keyword::WITH) + { + Expr::Subquery(Box::new(self.parse_query()?)) + } else { + let mut exprs = self.parse_comma_separated(Parser::parse_expr)?; + if exprs.len() == 1 { + Expr::Nested(Box::new(exprs.pop().unwrap())) } else { - let mut exprs = self.parse_comma_separated(Parser::parse_expr)?; - if exprs.len() == 1 { - Expr::Nested(Box::new(exprs.pop().unwrap())) - } else { - Expr::Row(exprs) - } - }; + Expr::Row(exprs) + } + }; self.expect_token(&Token::RParen)?; if self.peek_token() == Token::Period && matches!(expr, Expr::Nested(_)) { self.parse_struct_selection(expr) @@ -776,7 +739,7 @@ impl Parser { Ok(expr) } } - unexpected => self.expected("an expression:", unexpected.with_location(token.location)), + _ => self.expected_at(checkpoint, "an expression"), }?; if self.parse_keyword(Keyword::COLLATE) { @@ -789,16 +752,15 @@ impl Parser { } } - fn parse_param(&mut self, param: String) -> Result { - Ok(Expr::Parameter { - index: param.parse().map_err(|_| { - ParserError::ParserError(format!("Parameter symbol has a invalid index {}.", param)) - })?, - }) + fn parse_param(&mut self, param: String) -> PResult { + let Ok(index) = param.parse() else { + parser_err!("Parameter symbol has a invalid index {}.", param); + }; + Ok(Expr::Parameter { index }) } /// Parses a field selection expression. See also [`Expr::FieldIdentifier`]. - pub fn parse_struct_selection(&mut self, expr: Expr) -> Result { + pub fn parse_struct_selection(&mut self, expr: Expr) -> PResult { let mut nested_expr = expr; // Unwrap parentheses while let Expr::Nested(inner) = nested_expr { @@ -809,35 +771,21 @@ impl Parser { } /// Parses consecutive field identifiers after a period. i.e., `.foo.bar.baz` - pub fn parse_fields(&mut self) -> Result, ParserError> { - let mut idents = vec![]; - while self.consume_token(&Token::Period) { - let token = self.next_token(); - match token.token { - Token::Word(w) => { - idents.push(w.to_ident()?); - } - unexpected => { - return self.expected( - "an identifier after '.'", - unexpected.with_location(token.location), - ); - } - } - } - Ok(idents) + pub fn parse_fields(&mut self) -> PResult> { + repeat(.., preceded(Token::Period, cut_err(Self::parse_identifier))).parse_next(self) } - pub fn parse_qualified_operator(&mut self) -> Result { + pub fn parse_qualified_operator(&mut self) -> PResult { self.expect_token(&Token::LParen)?; + let checkpoint = *self; let schema = match self.parse_identifier_non_reserved() { Ok(ident) => { self.expect_token(&Token::Period)?; Some(ident) } Err(_) => { - self.prev_token(); + *self = checkpoint; None } }; @@ -853,11 +801,12 @@ impl Parser { // // To support custom operators and be fully compatible with PostgreSQL later, the // tokenizer should also be updated. + let checkpoint = *self; let token = self.next_token(); let name = token.token.to_string(); if !name.trim_matches(OP_CHARS).is_empty() { - self.prev_token(); - return self.expected(&format!("one of {}", OP_CHARS.iter().join(" ")), token); + return self + .expected_at(checkpoint, &format!("one of {}", OP_CHARS.iter().join(" "))); } name }; @@ -866,7 +815,7 @@ impl Parser { Ok(QualifiedOperator { schema, name }) } - pub fn parse_function(&mut self, name: ObjectName) -> Result { + pub fn parse_function(&mut self, name: ObjectName) -> PResult { self.expect_token(&Token::LParen)?; let distinct = self.parse_all_or_distinct()?; let (args, order_by, variadic) = self.parse_optional_args()?; @@ -914,10 +863,7 @@ impl Parser { let within_group = if self.parse_keywords(&[Keyword::WITHIN, Keyword::GROUP]) { self.expect_token(&Token::LParen)?; self.expect_keywords(&[Keyword::ORDER, Keyword::BY])?; - let order_by_parsed = self.parse_comma_separated(Parser::parse_order_by_expr)?; - let order_by = order_by_parsed.iter().exactly_one().map_err(|_| { - ParserError::ParserError("only one arg in order by is expected here".to_string()) - })?; + let order_by = self.parse_order_by_expr()?; self.expect_token(&Token::RParen)?; Some(Box::new(order_by.clone())) } else { @@ -936,26 +882,18 @@ impl Parser { })) } - pub fn parse_window_frame_units(&mut self) -> Result { - let token = self.next_token(); - match token.token { - Token::Word(w) => match w.keyword { - Keyword::ROWS => Ok(WindowFrameUnits::Rows), - Keyword::RANGE => Ok(WindowFrameUnits::Range), - Keyword::GROUPS => Ok(WindowFrameUnits::Groups), - _ => self.expected( - "ROWS, RANGE, GROUPS", - Token::Word(w).with_location(token.location), - )?, - }, - unexpected => self.expected( - "ROWS, RANGE, GROUPS", - unexpected.with_location(token.location), - ), + pub fn parse_window_frame_units(&mut self) -> PResult { + dispatch! { peek(keyword); + Keyword::ROWS => keyword.value(WindowFrameUnits::Rows), + Keyword::RANGE => keyword.value(WindowFrameUnits::Range), + Keyword::GROUPS => keyword.value(WindowFrameUnits::Groups), + _ => fail, } + .expect("ROWS, RANGE, or GROUPS") + .parse_next(self) } - pub fn parse_window_frame(&mut self) -> Result { + pub fn parse_window_frame(&mut self) -> PResult { let units = self.parse_window_frame_units()?; let (start_bound, end_bound) = if self.parse_keyword(Keyword::BETWEEN) { let start_bound = self.parse_window_frame_bound()?; @@ -979,7 +917,7 @@ impl Parser { } /// Parse `CURRENT ROW` or `{ | UNBOUNDED } { PRECEDING | FOLLOWING }` - pub fn parse_window_frame_bound(&mut self) -> Result { + pub fn parse_window_frame_bound(&mut self) -> PResult { if self.parse_keywords(&[Keyword::CURRENT, Keyword::ROW]) { Ok(WindowFrameBound::CurrentRow) } else { @@ -993,12 +931,12 @@ impl Parser { } else if self.parse_keyword(Keyword::FOLLOWING) { Ok(WindowFrameBound::Following(rows)) } else { - self.expected("PRECEDING or FOLLOWING", self.peek_token()) + self.expected("PRECEDING or FOLLOWING") } } } - pub fn parse_window_frame_exclusion(&mut self) -> Result { + pub fn parse_window_frame_exclusion(&mut self) -> PResult { if self.parse_keywords(&[Keyword::CURRENT, Keyword::ROW]) { Ok(WindowFrameExclusion::CurrentRow) } else if self.parse_keyword(Keyword::GROUP) { @@ -1008,13 +946,13 @@ impl Parser { } else if self.parse_keywords(&[Keyword::NO, Keyword::OTHERS]) { Ok(WindowFrameExclusion::NoOthers) } else { - self.expected("CURRENT ROW, GROUP, TIES, or NO OTHERS", self.peek_token()) + self.expected("CURRENT ROW, GROUP, TIES, or NO OTHERS") } } /// parse a group by expr. a group by expr can be one of group sets, roll up, cube, or simple /// expr. - fn parse_group_by_expr(&mut self) -> Result { + fn parse_group_by_expr(&mut self) -> PResult { if self.parse_keywords(&[Keyword::GROUPING, Keyword::SETS]) { self.expect_token(&Token::LParen)?; let result = self.parse_comma_separated(|p| p.parse_tuple(true, true))?; @@ -1038,11 +976,7 @@ impl Parser { /// parse a tuple with `(` and `)`. /// If `lift_singleton` is true, then a singleton tuple is lifted to a tuple of length 1, /// otherwise it will fail. If `allow_empty` is true, then an empty tuple is allowed. - fn parse_tuple( - &mut self, - lift_singleton: bool, - allow_empty: bool, - ) -> Result, ParserError> { + fn parse_tuple(&mut self, lift_singleton: bool, allow_empty: bool) -> PResult> { if lift_singleton { if self.consume_token(&Token::LParen) { let result = if allow_empty && self.consume_token(&Token::RParen) { @@ -1069,7 +1003,7 @@ impl Parser { } } - pub fn parse_case_expr(&mut self) -> Result { + pub fn parse_case_expr(&mut self) -> PResult { let mut operand = None; if !self.parse_keyword(Keyword::WHEN) { operand = Some(Box::new(self.parse_expr()?)); @@ -1100,7 +1034,7 @@ impl Parser { } /// Parse a SQL CAST function e.g. `CAST(expr AS FLOAT)` - pub fn parse_cast_expr(&mut self) -> Result { + pub fn parse_cast_expr(&mut self) -> PResult { self.expect_token(&Token::LParen)?; let expr = self.parse_expr()?; self.expect_keyword(Keyword::AS)?; @@ -1113,7 +1047,7 @@ impl Parser { } /// Parse a SQL TRY_CAST function e.g. `TRY_CAST(expr AS FLOAT)` - pub fn parse_try_cast_expr(&mut self) -> Result { + pub fn parse_try_cast_expr(&mut self) -> PResult { self.expect_token(&Token::LParen)?; let expr = self.parse_expr()?; self.expect_keyword(Keyword::AS)?; @@ -1126,14 +1060,14 @@ impl Parser { } /// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`. - pub fn parse_exists_expr(&mut self) -> Result { + pub fn parse_exists_expr(&mut self) -> PResult { self.expect_token(&Token::LParen)?; let exists_node = Expr::Exists(Box::new(self.parse_query()?)); self.expect_token(&Token::RParen)?; Ok(exists_node) } - pub fn parse_extract_expr(&mut self) -> Result { + pub fn parse_extract_expr(&mut self) -> PResult { self.expect_token(&Token::LParen)?; let field = self.parse_date_time_field_in_extract()?; self.expect_keyword(Keyword::FROM)?; @@ -1145,7 +1079,7 @@ impl Parser { }) } - pub fn parse_substring_expr(&mut self) -> Result { + pub fn parse_substring_expr(&mut self) -> PResult { // PARSE SUBSTRING (EXPR [FROM 1] [FOR 3]) self.expect_token(&Token::LParen)?; let expr = self.parse_expr()?; @@ -1168,7 +1102,7 @@ impl Parser { } /// `POSITION( IN )` - pub fn parse_position_expr(&mut self) -> Result { + pub fn parse_position_expr(&mut self) -> PResult { self.expect_token(&Token::LParen)?; // Logically `parse_expr`, but limited to those with precedence higher than `BETWEEN`/`IN`, @@ -1187,7 +1121,7 @@ impl Parser { } /// `OVERLAY( PLACING FROM [ FOR ])` - pub fn parse_overlay_expr(&mut self) -> Result { + pub fn parse_overlay_expr(&mut self) -> PResult { self.expect_token(&Token::LParen)?; let expr = self.parse_expr()?; @@ -1215,7 +1149,7 @@ impl Parser { /// `TRIM ([WHERE] ['text'] FROM 'text')`\ /// `TRIM ([WHERE] [FROM] 'text' [, 'text'])` - pub fn parse_trim_expr(&mut self) -> Result { + pub fn parse_trim_expr(&mut self) -> PResult { self.expect_token(&Token::LParen)?; let mut trim_where = None; if let Token::Word(word) = self.peek_token().token { @@ -1251,26 +1185,19 @@ impl Parser { }) } - pub fn parse_trim_where(&mut self) -> Result { - let token = self.next_token(); - match token.token { - Token::Word(w) => match w.keyword { - Keyword::BOTH => Ok(TrimWhereField::Both), - Keyword::LEADING => Ok(TrimWhereField::Leading), - Keyword::TRAILING => Ok(TrimWhereField::Trailing), - _ => self.expected( - "trim_where field", - Token::Word(w).with_location(token.location), - )?, - }, - unexpected => { - self.expected("trim_where field", unexpected.with_location(token.location)) - } + pub fn parse_trim_where(&mut self) -> PResult { + dispatch! { peek(keyword); + Keyword::BOTH => keyword.value(TrimWhereField::Both), + Keyword::LEADING => keyword.value(TrimWhereField::Leading), + Keyword::TRAILING => keyword.value(TrimWhereField::Trailing), + _ => fail } + .expect("BOTH, LEADING, or TRAILING") + .parse_next(self) } /// Parses an array expression `[ex1, ex2, ..]` - pub fn parse_array_expr(&mut self) -> Result { + pub fn parse_array_expr(&mut self) -> PResult { let mut expected_depth = None; let exprs = self.parse_array_inner(0, &mut expected_depth)?; Ok(Expr::Array(Array { @@ -1284,12 +1211,12 @@ impl Parser { &mut self, depth: usize, expected_depth: &mut Option, - ) -> Result, ParserError> { + ) -> PResult> { self.expect_token(&Token::LBracket)?; if let Some(expected_depth) = *expected_depth && depth > expected_depth { - return self.expected("]", self.peek_token()); + return self.expected("]"); } let exprs = if self.peek_token() == Token::LBracket { self.parse_comma_separated(|parser| { @@ -1302,7 +1229,7 @@ impl Parser { } else { if let Some(expected_depth) = *expected_depth { if depth < expected_depth { - return self.expected("[", self.peek_token()); + return self.expected("["); } } else { *expected_depth = Some(depth); @@ -1317,25 +1244,18 @@ impl Parser { } // This function parses date/time fields for interval qualifiers. - pub fn parse_date_time_field(&mut self) -> Result { - let token = self.next_token(); - match token.token { - Token::Word(w) => match w.keyword { - Keyword::YEAR => Ok(DateTimeField::Year), - Keyword::MONTH => Ok(DateTimeField::Month), - Keyword::DAY => Ok(DateTimeField::Day), - Keyword::HOUR => Ok(DateTimeField::Hour), - Keyword::MINUTE => Ok(DateTimeField::Minute), - Keyword::SECOND => Ok(DateTimeField::Second), - _ => self.expected( - "date/time field", - Token::Word(w).with_location(token.location), - )?, - }, - unexpected => { - self.expected("date/time field", unexpected.with_location(token.location)) - } + pub fn parse_date_time_field(&mut self) -> PResult { + dispatch! { peek(keyword); + Keyword::YEAR => keyword.value(DateTimeField::Year), + Keyword::MONTH => keyword.value(DateTimeField::Month), + Keyword::DAY => keyword.value(DateTimeField::Day), + Keyword::HOUR => keyword.value(DateTimeField::Hour), + Keyword::MINUTE => keyword.value(DateTimeField::Minute), + Keyword::SECOND => keyword.value(DateTimeField::Second), + _ => fail, } + .expect("date/time field") + .parse_next(self) } // This function parses date/time fields for the EXTRACT function-like operator. PostgreSQL @@ -1347,13 +1267,15 @@ impl Parser { // select extract("invaLId" from null::date); // select extract('invaLId' from null::date); // ``` - pub fn parse_date_time_field_in_extract(&mut self) -> Result { + pub fn parse_date_time_field_in_extract(&mut self) -> PResult { + let checkpoint = *self; let token = self.next_token(); match token.token { Token::Word(w) => Ok(w.value.to_uppercase()), Token::SingleQuotedString(s) => Ok(s.to_uppercase()), - unexpected => { - self.expected("date/time field", unexpected.with_location(token.location)) + _ => { + *self = checkpoint; + self.expected("date/time field") } } } @@ -1370,7 +1292,7 @@ impl Parser { /// 6. `INTERVAL '1:1' HOUR (5) TO MINUTE (5)` /// /// Note that we do not currently attempt to parse the quoted value. - pub fn parse_literal_interval(&mut self) -> Result { + pub fn parse_literal_interval(&mut self) -> PResult { // The SQL standard allows an optional sign before the value string, but // it is not clear if any implementations support that syntax, so we // don't currently try to parse it. (The sign can instead be included @@ -1438,7 +1360,8 @@ impl Parser { } /// Parse an operator following an expression - pub fn parse_infix(&mut self, expr: Expr, precedence: Precedence) -> Result { + pub fn parse_infix(&mut self, expr: Expr, precedence: Precedence) -> PResult { + let checkpoint = *self; let tok = self.next_token(); debug!("parsing infix {:?}", tok.token); let regular_binary_operator = match &tok.token { @@ -1508,7 +1431,7 @@ impl Parser { // // TODO: support `all/any/some(subquery)`. // if let Expr::Subquery(_) = &right { - // parser_err!("ANY/SOME/ALL(Subquery) is not implemented")?; + // parser_err!("ANY/SOME/ALL(Subquery) is not implemented"); // } // let right = match keyword { @@ -1564,27 +1487,20 @@ impl Parser { } else { self.expected( "[NOT] { TRUE | FALSE | UNKNOWN | NULL | DISTINCT FROM | JSON } after IS", - self.peek_token(), ) } } } Keyword::AT => { - if self.parse_keywords(&[Keyword::TIME, Keyword::ZONE]) { - let token = self.next_token(); - match token.token { - Token::SingleQuotedString(time_zone) => Ok(Expr::AtTimeZone { - timestamp: Box::new(expr), - time_zone, - }), - unexpected => self.expected( - "Expected Token::SingleQuotedString after AT TIME ZONE", - unexpected.with_location(token.location), - ), - } - } else { - self.expected("Expected Token::Word after AT", tok) - } + let time_zone = preceded( + (Keyword::TIME, Keyword::ZONE), + cut_err(Self::parse_literal_string), + ) + .parse_next(self)?; + Ok(Expr::AtTimeZone { + timestamp: Box::new(expr), + time_zone, + }) } keyword @ (Keyword::ALL | Keyword::ANY | Keyword::SOME) => { self.expect_token(&Token::LParen)?; @@ -1595,7 +1511,7 @@ impl Parser { // TODO: support `all/any/some(subquery)`. if let Expr::Subquery(_) = &sub { - parser_err!("ANY/SOME/ALL(Subquery) is not implemented")?; + parser_err!("ANY/SOME/ALL(Subquery) is not implemented"); } Ok(match keyword { @@ -1611,7 +1527,7 @@ impl Parser { | Keyword::LIKE | Keyword::ILIKE | Keyword::SIMILAR => { - self.prev_token(); + *self = checkpoint; let negated = self.parse_keyword(Keyword::NOT); if self.parse_keyword(Keyword::IN) { self.parse_in(expr, negated) @@ -1639,11 +1555,11 @@ impl Parser { escape_char: self.parse_escape()?, }) } else { - self.expected("IN, BETWEEN or SIMILAR TO after NOT", self.peek_token()) + self.expected("IN, BETWEEN or SIMILAR TO after NOT") } } // Can only happen if `get_next_precedence` got out of sync with this function - _ => parser_err!(format!("No infix parser for token {:?}", tok)), + _ => parser_err!("No infix parser for token {:?}", tok), } } else if Token::DoubleColon == tok { self.parse_pg_cast(expr) @@ -1657,20 +1573,18 @@ impl Parser { self.parse_array_index(expr) } else { // Can only happen if `get_next_precedence` got out of sync with this function - parser_err!(format!("No infix parser for token {:?}", tok)) + parser_err!("No infix parser for token {:?}", tok) } } /// parse the ESCAPE CHAR portion of LIKE, ILIKE, and SIMILAR TO - pub fn parse_escape(&mut self) -> Result, ParserError> { + pub fn parse_escape(&mut self) -> PResult> { if self.parse_keyword(Keyword::ESCAPE) { let s = self.parse_literal_string()?; let mut chs = s.chars(); if let Some(ch) = chs.next() { if chs.next().is_some() { - parser_err!(format!( - "Escape string must be empty or one character, found {s:?}" - )) + parser_err!("Escape string must be empty or one character, found {s:?}") } else { Ok(Some(EscapeChar::escape(ch))) } @@ -1684,7 +1598,7 @@ impl Parser { /// We parse both `array[1,9][1]`, `array[1,9][1:2]`, `array[1,9][:2]`, `array[1,9][1:]` and /// `array[1,9][:]` in this function. - pub fn parse_array_index(&mut self, expr: Expr) -> Result { + pub fn parse_array_index(&mut self, expr: Expr) -> PResult { let new_expr = match self.peek_token().token { Token::Colon => { // [:] or [:N] @@ -1749,7 +1663,7 @@ impl Parser { } /// Parses the optional constraints following the `IS [NOT] JSON` predicate - pub fn parse_is_json(&mut self, expr: Expr, negated: bool) -> Result { + pub fn parse_is_json(&mut self, expr: Expr, negated: bool) -> PResult { let item_type = match self.peek_token().token { Token::Word(w) => match w.keyword { Keyword::VALUE => Some(JsonPredicateType::Value), @@ -1781,10 +1695,10 @@ impl Parser { } /// Parses the parens following the `[ NOT ] IN` operator - pub fn parse_in(&mut self, expr: Expr, negated: bool) -> Result { + pub fn parse_in(&mut self, expr: Expr, negated: bool) -> PResult { self.expect_token(&Token::LParen)?; - let in_op = if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH) { - self.prev_token(); + let in_op = if matches!(self.peek_token().token, Token::Word(w) if w.keyword == Keyword::SELECT || w.keyword == Keyword::WITH) + { Expr::InSubquery { expr: Box::new(expr), subquery: Box::new(self.parse_query()?), @@ -1802,7 +1716,7 @@ impl Parser { } /// Parses `BETWEEN AND `, assuming the `BETWEEN` keyword was already consumed - pub fn parse_between(&mut self, expr: Expr, negated: bool) -> Result { + pub fn parse_between(&mut self, expr: Expr, negated: bool) -> PResult { // Stop parsing subexpressions for and on tokens with // precedence lower than that of `BETWEEN`, such as `AND`, `IS`, etc. let low = self.parse_subexpr(Precedence::Between)?; @@ -1817,7 +1731,7 @@ impl Parser { } /// Parse a postgresql casting style which is in the form of `expr::datatype` - pub fn parse_pg_cast(&mut self, expr: Expr) -> Result { + pub fn parse_pg_cast(&mut self, expr: Expr) -> PResult { Ok(Expr::Cast { expr: Box::new(expr), data_type: self.parse_data_type()?, @@ -1825,7 +1739,7 @@ impl Parser { } /// Get the precedence of the next token - pub fn get_next_precedence(&self) -> Result { + pub fn get_next_precedence(&self) -> PResult { use Precedence as P; let token = self.peek_token(); @@ -1930,17 +1844,15 @@ impl Parser { /// Return nth non-whitespace token that has not yet been processed pub fn peek_nth_token(&self, mut n: usize) -> TokenWithLocation { - let mut index = self.index; + let mut index = 0; loop { + let token = self.0.get(index); index += 1; - let token = self.tokens.get(index - 1); match token.map(|x| &x.token) { Some(Token::Whitespace(_)) => continue, _ => { if n == 0 { - return token - .cloned() - .unwrap_or(TokenWithLocation::wrap(Token::EOF)); + return token.cloned().unwrap_or(TokenWithLocation::eof()); } n -= 1; } @@ -1953,44 +1865,37 @@ impl Parser { /// repeatedly after reaching EOF. pub fn next_token(&mut self) -> TokenWithLocation { loop { - self.index += 1; - let token = self.tokens.get(self.index - 1); - match token.map(|x| &x.token) { - Some(Token::Whitespace(_)) => continue, - _ => { - return token - .cloned() - .unwrap_or(TokenWithLocation::wrap(Token::EOF)); - } + let Some(token) = self.0.first() else { + return TokenWithLocation::eof(); + }; + self.0 = &self.0[1..]; + match token.token { + Token::Whitespace(_) => continue, + _ => return token.clone(), } } } /// Return the first unprocessed token, possibly whitespace. pub fn next_token_no_skip(&mut self) -> Option<&TokenWithLocation> { - self.index += 1; - self.tokens.get(self.index - 1) + if self.0.is_empty() { + None + } else { + let (first, rest) = self.0.split_at(1); + self.0 = rest; + Some(&first[0]) + } } - /// Push back the last one non-whitespace token. Must be called after - /// `next_token()`, otherwise might panic. OK to call after - /// `next_token()` indicates an EOF. - pub fn prev_token(&mut self) { - loop { - assert!(self.index > 0); - self.index -= 1; - if let Some(token) = self.tokens.get(self.index) - && let Token::Whitespace(_) = token.token - { - continue; - } - return; - } + /// Report an expected error at the current position. + pub fn expected(&self, expected: &str) -> PResult { + parser_err!("expected {}, found: {}", expected, self.peek_token().token) } - /// Report unexpected token - pub fn expected(&self, expected: &str, found: TokenWithLocation) -> Result { - parser_err!(format!("expected {}, found: {}", expected, found)) + /// Revert the parser to a previous position and report an expected error. + pub fn expected_at(&mut self, checkpoint: Self, expected: &str) -> PResult { + *self = checkpoint; + self.expected(expected) } /// Look for an expected keyword and consume it if it exists @@ -2008,12 +1913,12 @@ impl Parser { /// Look for an expected sequence of keywords and consume them if they exist #[must_use] pub fn parse_keywords(&mut self, keywords: &[Keyword]) -> bool { - let index = self.index; + let checkpoint = *self; for &keyword in keywords { if !self.parse_keyword(keyword) { // println!("parse_keywords aborting .. did not find {:?}", keyword); // reset index and return immediately - self.index = index; + *self = checkpoint; return false; } } @@ -2045,30 +1950,27 @@ impl Parser { } /// Bail out if the current token is not one of the expected keywords, or consume it if it is - pub fn expect_one_of_keywords(&mut self, keywords: &[Keyword]) -> Result { + pub fn expect_one_of_keywords(&mut self, keywords: &[Keyword]) -> PResult { if let Some(keyword) = self.parse_one_of_keywords(keywords) { Ok(keyword) } else { let keywords: Vec = keywords.iter().map(|x| format!("{:?}", x)).collect(); - self.expected( - &format!("one of {}", keywords.join(" or ")), - self.peek_token(), - ) + self.expected(&format!("one of {}", keywords.join(" or "))) } } /// Bail out if the current token is not an expected keyword, or consume it if it is - pub fn expect_keyword(&mut self, expected: Keyword) -> Result<(), ParserError> { + pub fn expect_keyword(&mut self, expected: Keyword) -> PResult<()> { if self.parse_keyword(expected) { Ok(()) } else { - self.expected(format!("{:?}", &expected).as_str(), self.peek_token()) + self.expected(format!("{:?}", &expected).as_str()) } } /// Bail out if the following tokens are not the expected sequence of /// keywords, or consume them if they are. - pub fn expect_keywords(&mut self, expected: &[Keyword]) -> Result<(), ParserError> { + pub fn expect_keywords(&mut self, expected: &[Keyword]) -> PResult<()> { for &kw in expected { self.expect_keyword(kw)?; } @@ -2087,18 +1989,18 @@ impl Parser { } /// Bail out if the current token is not an expected keyword, or consume it if it is - pub fn expect_token(&mut self, expected: &Token) -> Result<(), ParserError> { + pub fn expect_token(&mut self, expected: &Token) -> PResult<()> { if self.consume_token(expected) { Ok(()) } else { - self.expected(&expected.to_string(), self.peek_token()) + self.expected(&expected.to_string()) } } /// Parse a comma-separated list of 1+ items accepted by `F` - pub fn parse_comma_separated(&mut self, mut f: F) -> Result, ParserError> + pub fn parse_comma_separated(&mut self, mut f: F) -> PResult> where - F: FnMut(&mut Parser) -> Result, + F: FnMut(&mut Self) -> PResult, { let mut values = vec![]; loop { @@ -2115,31 +2017,31 @@ impl Parser { #[must_use] fn maybe_parse(&mut self, mut f: F) -> Option where - F: FnMut(&mut Parser) -> Result, + F: FnMut(&mut Self) -> PResult, { - let index = self.index; + let checkpoint = *self; if let Ok(t) = f(self) { Some(t) } else { - self.index = index; + *self = checkpoint; None } } /// Parse either `ALL` or `DISTINCT`. Returns `true` if `DISTINCT` is parsed and results in a /// `ParserError` if both `ALL` and `DISTINCT` are fround. - pub fn parse_all_or_distinct(&mut self) -> Result { + pub fn parse_all_or_distinct(&mut self) -> PResult { let all = self.parse_keyword(Keyword::ALL); let distinct = self.parse_keyword(Keyword::DISTINCT); if all && distinct { - parser_err!("Cannot specify both ALL and DISTINCT".to_string()) + parser_err!("Cannot specify both ALL and DISTINCT") } else { Ok(distinct) } } /// Parse either `ALL` or `DISTINCT` or `DISTINCT ON ()`. - pub fn parse_all_or_distinct_on(&mut self) -> Result { + pub fn parse_all_or_distinct_on(&mut self) -> PResult { if self.parse_keywords(&[Keyword::DISTINCT, Keyword::ON]) { self.expect_token(&Token::LParen)?; let exprs = self.parse_comma_separated(Parser::parse_expr)?; @@ -2153,7 +2055,7 @@ impl Parser { } /// Parse a SQL CREATE statement - pub fn parse_create(&mut self) -> Result { + pub fn parse_create(&mut self) -> PResult { let or_replace = self.parse_keywords(&[Keyword::OR, Keyword::REPLACE]); let temporary = self .parse_one_of_keywords(&[Keyword::TEMP, Keyword::TEMPORARY]) @@ -2181,7 +2083,6 @@ impl Parser { } else if or_replace { self.expected( "[EXTERNAL] TABLE or [MATERIALIZED] VIEW or [MATERIALIZED] SOURCE or SINK or FUNCTION after CREATE OR REPLACE", - self.peek_token(), ) } else if self.parse_keyword(Keyword::INDEX) { self.parse_create_index(false) @@ -2196,11 +2097,11 @@ impl Parser { } else if self.parse_keyword(Keyword::SECRET) { self.parse_create_secret() } else { - self.expected("an object type after CREATE", self.peek_token()) + self.expected("an object type after CREATE") } } - pub fn parse_create_schema(&mut self) -> Result { + pub fn parse_create_schema(&mut self) -> PResult { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); let (schema_name, user_specified) = if self.parse_keyword(Keyword::AUTHORIZATION) { let user_specified = self.parse_object_name()?; @@ -2221,7 +2122,7 @@ impl Parser { }) } - pub fn parse_create_database(&mut self) -> Result { + pub fn parse_create_database(&mut self) -> PResult { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); let db_name = self.parse_object_name()?; Ok(Statement::CreateDatabase { @@ -2234,7 +2135,7 @@ impl Parser { &mut self, materialized: bool, or_replace: bool, - ) -> Result { + ) -> PResult { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); // Many dialects support `OR ALTER` right after `CREATE`, but we don't (yet). // ANSI SQL and Postgres support RECURSIVE here, but we don't support it either. @@ -2269,7 +2170,7 @@ impl Parser { // [WITH (properties)]? // ROW FORMAT // [ROW SCHEMA LOCATION ]? - pub fn parse_create_source(&mut self, _or_replace: bool) -> Result { + pub fn parse_create_source(&mut self, _or_replace: bool) -> PResult { Ok(Statement::CreateSource { stmt: CreateSourceStatement::parse_to(self)?, }) @@ -2282,7 +2183,7 @@ impl Parser { // FROM // // [WITH (properties)]? - pub fn parse_create_sink(&mut self, _or_replace: bool) -> Result { + pub fn parse_create_sink(&mut self, _or_replace: bool) -> PResult { Ok(Statement::CreateSink { stmt: CreateSinkStatement::parse_to(self)?, }) @@ -2295,10 +2196,7 @@ impl Parser { // FROM // // [WITH (properties)]? - pub fn parse_create_subscription( - &mut self, - _or_replace: bool, - ) -> Result { + pub fn parse_create_subscription(&mut self, _or_replace: bool) -> PResult { Ok(Statement::CreateSubscription { stmt: CreateSubscriptionStatement::parse_to(self)?, }) @@ -2309,7 +2207,7 @@ impl Parser { // [IF NOT EXISTS]? // // [WITH (properties)]? - pub fn parse_create_connection(&mut self) -> Result { + pub fn parse_create_connection(&mut self) -> PResult { Ok(Statement::CreateConnection { stmt: CreateConnectionStatement::parse_to(self)?, }) @@ -2319,11 +2217,10 @@ impl Parser { &mut self, or_replace: bool, temporary: bool, - ) -> Result { + ) -> PResult { let name = self.parse_object_name()?; self.expect_token(&Token::LParen)?; - let args = if self.consume_token(&Token::RParen) { - self.prev_token(); + let args = if self.peek_token().token == Token::RParen { None } else { Some(self.parse_comma_separated(Parser::parse_function_arg)?) @@ -2342,7 +2239,7 @@ impl Parser { // allow a trailing comma, even though it's not in standard break; } else if !comma { - return self.expected("',' or ')'", self.peek_token()); + return self.expected("',' or ')'"); } } Some(CreateFunctionReturns::Table(values)) @@ -2367,7 +2264,7 @@ impl Parser { }) } - fn parse_create_aggregate(&mut self, or_replace: bool) -> Result { + fn parse_create_aggregate(&mut self, or_replace: bool) -> PResult { let name = self.parse_object_name()?; self.expect_token(&Token::LParen)?; let args = self.parse_comma_separated(Parser::parse_function_arg)?; @@ -2389,32 +2286,32 @@ impl Parser { }) } - pub fn parse_declare(&mut self) -> Result { + pub fn parse_declare(&mut self) -> PResult { Ok(Statement::DeclareCursor { stmt: DeclareCursorStatement::parse_to(self)?, }) } - pub fn parse_fetch_cursor(&mut self) -> Result { + pub fn parse_fetch_cursor(&mut self) -> PResult { Ok(Statement::FetchCursor { stmt: FetchCursorStatement::parse_to(self)?, }) } - pub fn parse_close_cursor(&mut self) -> Result { + pub fn parse_close_cursor(&mut self) -> PResult { Ok(Statement::CloseCursor { stmt: CloseCursorStatement::parse_to(self)?, }) } - fn parse_table_column_def(&mut self) -> Result { + fn parse_table_column_def(&mut self) -> PResult { Ok(TableColumnDef { name: self.parse_identifier_non_reserved()?, data_type: self.parse_data_type()?, }) } - fn parse_function_arg(&mut self) -> Result { + fn parse_function_arg(&mut self) -> PResult { let mode = if self.parse_keyword(Keyword::IN) { Some(ArgMode::In) } else if self.parse_keyword(Keyword::OUT) { @@ -2450,14 +2347,12 @@ impl Parser { }) } - fn parse_create_function_body(&mut self) -> Result { + fn parse_create_function_body(&mut self) -> PResult { let mut body = CreateFunctionBody::default(); loop { - fn ensure_not_set(field: &Option, name: &str) -> Result<(), ParserError> { + fn ensure_not_set(field: &Option, name: &str) -> PResult<()> { if field.is_some() { - return Err(ParserError::ParserError(format!( - "{name} specified more than once", - ))); + parser_err!("{name} specified more than once"); } Ok(()) } @@ -2500,7 +2395,7 @@ impl Parser { } } - fn parse_create_function_using(&mut self) -> Result { + fn parse_create_function_using(&mut self) -> PResult { let keyword = self.expect_one_of_keywords(&[Keyword::LINK, Keyword::BASE64])?; match keyword { @@ -2520,7 +2415,7 @@ impl Parser { &mut self, is_async: bool, is_generator: bool, - ) -> Result { + ) -> PResult { let is_generator = if is_generator { true } else { @@ -2542,29 +2437,28 @@ impl Parser { // | CREATEUSER | NOCREATEUSER // | LOGIN | NOLOGIN // | [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL | OAUTH - fn parse_create_user(&mut self) -> Result { + fn parse_create_user(&mut self) -> PResult { Ok(Statement::CreateUser(CreateUserStatement::parse_to(self)?)) } - fn parse_create_secret(&mut self) -> Result { + fn parse_create_secret(&mut self) -> PResult { Ok(Statement::CreateSecret { stmt: CreateSecretStatement::parse_to(self)?, }) } - pub fn parse_with_properties(&mut self) -> Result, ParserError> { + pub fn parse_with_properties(&mut self) -> PResult> { Ok(self .parse_options_with_preceding_keyword(Keyword::WITH)? .to_vec()) } - pub fn parse_discard(&mut self) -> Result { - self.expect_keyword(Keyword::ALL) - .map_err(|_| ParserError::ParserError("only DISCARD ALL is supported".to_string()))?; + pub fn parse_discard(&mut self) -> PResult { + self.expect_keyword(Keyword::ALL)?; Ok(Statement::Discard(DiscardType::All)) } - pub fn parse_drop(&mut self) -> Result { + pub fn parse_drop(&mut self) -> PResult { if self.parse_keyword(Keyword::FUNCTION) { return self.parse_drop_function(); } else if self.parse_keyword(Keyword::AGGREGATE) { @@ -2577,7 +2471,7 @@ impl Parser { /// DROP FUNCTION [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...] /// [ CASCADE | RESTRICT ] /// ``` - fn parse_drop_function(&mut self) -> Result { + fn parse_drop_function(&mut self) -> PResult { let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); let func_desc = self.parse_comma_separated(Parser::parse_function_desc)?; let option = match self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]) { @@ -2596,7 +2490,7 @@ impl Parser { /// DROP AGGREGATE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...] /// [ CASCADE | RESTRICT ] /// ``` - fn parse_drop_aggregate(&mut self) -> Result { + fn parse_drop_aggregate(&mut self) -> PResult { let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); let func_desc = self.parse_comma_separated(Parser::parse_function_desc)?; let option = match self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]) { @@ -2611,7 +2505,7 @@ impl Parser { }) } - fn parse_function_desc(&mut self) -> Result { + fn parse_function_desc(&mut self) -> PResult { let name = self.parse_object_name()?; let args = if self.consume_token(&Token::LParen) { @@ -2629,7 +2523,7 @@ impl Parser { Ok(FunctionDesc { name, args }) } - pub fn parse_create_index(&mut self, unique: bool) -> Result { + pub fn parse_create_index(&mut self, unique: bool) -> PResult { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); let index_name = self.parse_object_name()?; self.expect_keyword(Keyword::ON)?; @@ -2660,7 +2554,7 @@ impl Parser { }) } - pub fn parse_with_version_column(&mut self) -> Result, ParserError> { + pub fn parse_with_version_column(&mut self) -> PResult> { if self.parse_keywords(&[Keyword::WITH, Keyword::VERSION, Keyword::COLUMN]) { self.expect_token(&Token::LParen)?; let name = self.parse_identifier_non_reserved()?; @@ -2671,7 +2565,7 @@ impl Parser { } } - pub fn parse_on_conflict(&mut self) -> Result, ParserError> { + pub fn parse_on_conflict(&mut self) -> PResult> { if self.parse_keywords(&[Keyword::ON, Keyword::CONFLICT]) { self.parse_handle_conflict_behavior() } else { @@ -2679,11 +2573,7 @@ impl Parser { } } - pub fn parse_create_table( - &mut self, - or_replace: bool, - temporary: bool, - ) -> Result { + pub fn parse_create_table(&mut self, or_replace: bool, temporary: bool) -> PResult { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); let table_name = self.parse_object_name()?; // parse optional column list (schema) and watermarks on source. @@ -2718,9 +2608,7 @@ impl Parser { // Parse optional `AS ( query )` let query = if self.parse_keyword(Keyword::AS) { if !source_watermarks.is_empty() { - return Err(ParserError::ParserError( - "Watermarks can't be defined on table created by CREATE TABLE AS".to_string(), - )); + parser_err!("Watermarks can't be defined on table created by CREATE TABLE AS"); } Some(Box::new(self.parse_query()?)) } else { @@ -2759,7 +2647,7 @@ impl Parser { }) } - pub fn parse_include_options(&mut self) -> Result { + pub fn parse_include_options(&mut self) -> PResult { let mut options = vec![]; while self.parse_keyword(Keyword::INCLUDE) { let column_type = self.parse_identifier()?; @@ -2803,7 +2691,7 @@ impl Parser { Ok(options) } - pub fn parse_columns_with_watermark(&mut self) -> Result { + pub fn parse_columns_with_watermark(&mut self) -> PResult { let mut columns = vec![]; let mut constraints = vec![]; let mut watermarks = vec![]; @@ -2817,9 +2705,7 @@ impl Parser { if wildcard_idx.is_none() { wildcard_idx = Some(columns.len()); } else { - return Err(ParserError::ParserError( - "At most 1 wildcard is allowed in source definetion".to_string(), - )); + parser_err!("At most 1 wildcard is allowed in source definetion"); } } else if let Some(constraint) = self.parse_optional_table_constraint()? { constraints.push(constraint); @@ -2827,28 +2713,26 @@ impl Parser { watermarks.push(watermark); if watermarks.len() > 1 { // TODO(yuhao): allow multiple watermark on source. - return Err(ParserError::ParserError( - "Only 1 watermark is allowed to be defined on source.".to_string(), - )); + parser_err!("Only 1 watermark is allowed to be defined on source."); } } else if let Token::Word(_) = self.peek_token().token { columns.push(self.parse_column_def()?); } else { - return self.expected("column name or constraint definition", self.peek_token()); + return self.expected("column name or constraint definition"); } let comma = self.consume_token(&Token::Comma); if self.consume_token(&Token::RParen) { // allow a trailing comma, even though it's not in standard break; } else if !comma { - return self.expected("',' or ')' after column definition", self.peek_token()); + return self.expected("',' or ')' after column definition"); } } Ok((columns, constraints, watermarks, wildcard_idx)) } - fn parse_column_def(&mut self) -> Result { + fn parse_column_def(&mut self) -> PResult { let name = self.parse_identifier_non_reserved()?; let data_type = if let Token::Word(_) = self.peek_token().token { Some(self.parse_data_type()?) @@ -2868,10 +2752,7 @@ impl Parser { if let Some(option) = self.parse_optional_column_option()? { options.push(ColumnOptionDef { name, option }); } else { - return self.expected( - "constraint details after CONSTRAINT ", - self.peek_token(), - ); + return self.expected("constraint details after CONSTRAINT "); } } else if let Some(option) = self.parse_optional_column_option()? { options.push(ColumnOptionDef { name: None, option }); @@ -2887,7 +2768,7 @@ impl Parser { }) } - pub fn parse_optional_column_option(&mut self) -> Result, ParserError> { + pub fn parse_optional_column_option(&mut self) -> PResult> { if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) { Ok(Some(ColumnOption::NotNull)) } else if self.parse_keyword(Keyword::NULL) { @@ -2934,7 +2815,7 @@ impl Parser { } } - pub fn parse_handle_conflict_behavior(&mut self) -> Result, ParserError> { + pub fn parse_handle_conflict_behavior(&mut self) -> PResult> { if self.parse_keyword(Keyword::OVERWRITE) { Ok(Some(OnConflict::OverWrite)) } else if self.parse_keyword(Keyword::IGNORE) { @@ -2952,7 +2833,7 @@ impl Parser { } } - pub fn parse_referential_action(&mut self) -> Result { + pub fn parse_referential_action(&mut self) -> PResult { if self.parse_keyword(Keyword::RESTRICT) { Ok(ReferentialAction::Restrict) } else if self.parse_keyword(Keyword::CASCADE) { @@ -2964,14 +2845,11 @@ impl Parser { } else if self.parse_keywords(&[Keyword::SET, Keyword::DEFAULT]) { Ok(ReferentialAction::SetDefault) } else { - self.expected( - "one of RESTRICT, CASCADE, SET NULL, NO ACTION or SET DEFAULT", - self.peek_token(), - ) + self.expected("one of RESTRICT, CASCADE, SET NULL, NO ACTION or SET DEFAULT") } } - pub fn parse_optional_watermark(&mut self) -> Result, ParserError> { + pub fn parse_optional_watermark(&mut self) -> PResult> { if self.parse_keyword(Keyword::WATERMARK) { self.expect_keyword(Keyword::FOR)?; let column = self.parse_identifier_non_reserved()?; @@ -2983,14 +2861,13 @@ impl Parser { } } - pub fn parse_optional_table_constraint( - &mut self, - ) -> Result, ParserError> { + pub fn parse_optional_table_constraint(&mut self) -> PResult> { let name = if self.parse_keyword(Keyword::CONSTRAINT) { Some(self.parse_identifier_non_reserved()?) } else { None }; + let checkpoint = *self; let token = self.next_token(); match token.token { Token::Word(w) if w.keyword == Keyword::PRIMARY || w.keyword == Keyword::UNIQUE => { @@ -3039,14 +2916,11 @@ impl Parser { self.expect_token(&Token::RParen)?; Ok(Some(TableConstraint::Check { name, expr })) } - unexpected => { + _ => { + *self = checkpoint; if name.is_some() { - self.expected( - "PRIMARY, UNIQUE, FOREIGN, or CHECK", - unexpected.with_location(token.location), - ) + self.expected("PRIMARY, UNIQUE, FOREIGN, or CHECK") } else { - self.prev_token(); Ok(None) } } @@ -3056,7 +2930,7 @@ impl Parser { pub fn parse_options_with_preceding_keyword( &mut self, keyword: Keyword, - ) -> Result, ParserError> { + ) -> PResult> { if self.parse_keyword(keyword) { self.expect_token(&Token::LParen)?; self.parse_options_inner() @@ -3065,7 +2939,7 @@ impl Parser { } } - pub fn parse_options(&mut self) -> Result, ParserError> { + pub fn parse_options(&mut self) -> PResult> { if self.peek_token() == Token::LParen { self.next_token(); self.parse_options_inner() @@ -3075,7 +2949,7 @@ impl Parser { } // has parsed a LParen - pub fn parse_options_inner(&mut self) -> Result, ParserError> { + pub fn parse_options_inner(&mut self) -> PResult> { let mut values = vec![]; loop { values.push(Parser::parse_sql_option(self)?); @@ -3084,21 +2958,22 @@ impl Parser { // allow a trailing comma, even though it's not in standard break; } else if !comma { - return self.expected("',' or ')' after option definition", self.peek_token()); + return self.expected("',' or ')' after option definition"); } } Ok(values) } - pub fn parse_sql_option(&mut self) -> Result { + pub fn parse_sql_option(&mut self) -> PResult { let name = self.parse_object_name()?; self.expect_token(&Token::Eq)?; let value = self.parse_value()?; Ok(SqlOption { name, value }) } - pub fn parse_since(&mut self) -> Result, ParserError> { + pub fn parse_since(&mut self) -> PResult> { if self.parse_keyword(Keyword::SINCE) { + let checkpoint = *self; let token = self.next_token(); match token.token { Token::Word(w) => { @@ -3113,29 +2988,26 @@ impl Parser { self.expect_token(&Token::RParen)?; Ok(Some(Since::Begin)) } else { - parser_err!(format!( + parser_err!( "Expected proctime(), begin() or now(), found: {}", ident.real_value() - )) + ) } } Token::Number(s) => { - let num = s.parse::().map_err(|e| { - ParserError::ParserError(format!("Could not parse '{}' as u64: {}", s, e)) - }); - Ok(Some(Since::TimestampMsNum(num?))) + let num = s + .parse::() + .map_err(|e| StrError(format!("Could not parse '{}' as u64: {}", s, e)))?; + Ok(Some(Since::TimestampMsNum(num))) } - unexpected => self.expected( - "proctime(), begin() , now(), Number", - unexpected.with_location(token.location), - ), + _ => self.expected_at(checkpoint, "proctime(), begin() , now(), Number"), } } else { Ok(None) } } - pub fn parse_emit_mode(&mut self) -> Result, ParserError> { + pub fn parse_emit_mode(&mut self) -> PResult> { if self.parse_keyword(Keyword::EMIT) { match self.parse_one_of_keywords(&[Keyword::IMMEDIATELY, Keyword::ON]) { Some(Keyword::IMMEDIATELY) => Ok(Some(EmitMode::Immediately)), @@ -3144,17 +3016,14 @@ impl Parser { Ok(Some(EmitMode::OnWindowClose)) } Some(_) => unreachable!(), - None => self.expected( - "IMMEDIATELY or ON WINDOW CLOSE after EMIT", - self.peek_token(), - ), + None => self.expected("IMMEDIATELY or ON WINDOW CLOSE after EMIT"), } } else { Ok(None) } } - pub fn parse_alter(&mut self) -> Result { + pub fn parse_alter(&mut self) -> PResult { if self.parse_keyword(Keyword::DATABASE) { self.parse_alter_database() } else if self.parse_keyword(Keyword::SCHEMA) { @@ -3183,13 +3052,12 @@ impl Parser { self.parse_alter_subscription() } else { self.expected( - "DATABASE, SCHEMA, TABLE, INDEX, MATERIALIZED, VIEW, SINK, SUBSCRIPTION, SOURCE, FUNCTION, USER or SYSTEM after ALTER", - self.peek_token(), + "DATABASE, SCHEMA, TABLE, INDEX, MATERIALIZED, VIEW, SINK, SUBSCRIPTION, SOURCE, FUNCTION, USER or SYSTEM after ALTER" ) } } - pub fn parse_alter_database(&mut self) -> Result { + pub fn parse_alter_database(&mut self) -> PResult { let database_name = self.parse_object_name()?; let operation = if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { let owner_name: Ident = self.parse_identifier()?; @@ -3201,10 +3069,10 @@ impl Parser { let database_name = self.parse_object_name()?; AlterDatabaseOperation::RenameDatabase { database_name } } else { - return self.expected("TO after RENAME", self.peek_token()); + return self.expected("TO after RENAME"); } } else { - return self.expected("OWNER TO after ALTER DATABASE", self.peek_token()); + return self.expected("OWNER TO after ALTER DATABASE"); }; Ok(Statement::AlterDatabase { @@ -3213,7 +3081,7 @@ impl Parser { }) } - pub fn parse_alter_schema(&mut self) -> Result { + pub fn parse_alter_schema(&mut self) -> PResult { let schema_name = self.parse_object_name()?; let operation = if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { let owner_name: Ident = self.parse_identifier()?; @@ -3221,14 +3089,11 @@ impl Parser { new_owner_name: owner_name, } } else if self.parse_keyword(Keyword::RENAME) { - if self.parse_keyword(Keyword::TO) { - let schema_name = self.parse_object_name()?; - AlterSchemaOperation::RenameSchema { schema_name } - } else { - return self.expected("TO after RENAME", self.peek_token()); - } + self.expect_keyword(Keyword::TO)?; + let schema_name = self.parse_object_name()?; + AlterSchemaOperation::RenameSchema { schema_name } } else { - return self.expected("RENAME OR OWNER TO after ALTER SCHEMA", self.peek_token()); + return self.expected("RENAME OR OWNER TO after ALTER SCHEMA"); }; Ok(Statement::AlterSchema { @@ -3237,11 +3102,11 @@ impl Parser { }) } - pub fn parse_alter_user(&mut self) -> Result { + pub fn parse_alter_user(&mut self) -> PResult { Ok(Statement::AlterUser(AlterUserStatement::parse_to(self)?)) } - pub fn parse_alter_table(&mut self) -> Result { + pub fn parse_alter_table(&mut self) -> PResult { let _ = self.parse_keyword(Keyword::ONLY); let table_name = self.parse_object_name()?; let operation = if self.parse_keyword(Keyword::ADD) { @@ -3288,10 +3153,7 @@ impl Parser { if self.expect_keyword(Keyword::TO).is_err() && self.expect_token(&Token::Eq).is_err() { - return self.expected( - "TO or = after ALTER TABLE SET PARALLELISM", - self.peek_token(), - ); + return self.expected("TO or = after ALTER TABLE SET PARALLELISM"); } let value = self.parse_set_variable()?; @@ -3305,10 +3167,7 @@ impl Parser { } else if let Some(rate_limit) = self.parse_alter_streaming_rate_limit()? { AlterTableOperation::SetStreamingRateLimit { rate_limit } } else { - return self.expected( - "SCHEMA/PARALLELISM/STREAMING_RATE_LIMIT after SET", - self.peek_token(), - ); + return self.expected("SCHEMA/PARALLELISM/STREAMING_RATE_LIMIT after SET"); } } else if self.parse_keyword(Keyword::DROP) { let _ = self.parse_keyword(Keyword::COLUMN); @@ -3345,19 +3204,14 @@ impl Parser { }; AlterColumnOperation::SetDataType { data_type, using } } else { - return self.expected( - "SET/DROP NOT NULL, SET DEFAULT, SET DATA TYPE after ALTER COLUMN", - self.peek_token(), - ); + return self + .expected("SET/DROP NOT NULL, SET DEFAULT, SET DATA TYPE after ALTER COLUMN"); }; AlterTableOperation::AlterColumn { column_name, op } } else if self.parse_keywords(&[Keyword::REFRESH, Keyword::SCHEMA]) { AlterTableOperation::RefreshSchema } else { - return self.expected( - "ADD or RENAME or OWNER TO or SET or DROP after ALTER TABLE", - self.peek_token(), - ); + return self.expected("ADD or RENAME or OWNER TO or SET or DROP after ALTER TABLE"); }; Ok(Statement::AlterTable { name: table_name, @@ -3367,15 +3221,12 @@ impl Parser { /// STREAMING_RATE_LIMIT = default | NUMBER /// STREAMING_RATE_LIMIT TO default | NUMBER - pub fn parse_alter_streaming_rate_limit(&mut self) -> Result, ParserError> { + pub fn parse_alter_streaming_rate_limit(&mut self) -> PResult> { if !self.parse_keyword(Keyword::STREAMING_RATE_LIMIT) { return Ok(None); } if self.expect_keyword(Keyword::TO).is_err() && self.expect_token(&Token::Eq).is_err() { - return self.expected( - "TO or = after ALTER TABLE SET STREAMING_RATE_LIMIT", - self.peek_token(), - ); + return self.expected("TO or = after ALTER TABLE SET STREAMING_RATE_LIMIT"); } let rate_limit = if self.parse_keyword(Keyword::DEFAULT) { -1 @@ -3384,30 +3235,27 @@ impl Parser { if let Ok(n) = s.parse::() { n } else { - return self.expected("number or DEFAULT", self.peek_token()); + return self.expected("number or DEFAULT"); } }; Ok(Some(rate_limit)) } - pub fn parse_alter_index(&mut self) -> Result { + pub fn parse_alter_index(&mut self) -> PResult { let index_name = self.parse_object_name()?; let operation = if self.parse_keyword(Keyword::RENAME) { if self.parse_keyword(Keyword::TO) { let index_name = self.parse_object_name()?; AlterIndexOperation::RenameIndex { index_name } } else { - return self.expected("TO after RENAME", self.peek_token()); + return self.expected("TO after RENAME"); } } else if self.parse_keyword(Keyword::SET) { if self.parse_keyword(Keyword::PARALLELISM) { if self.expect_keyword(Keyword::TO).is_err() && self.expect_token(&Token::Eq).is_err() { - return self.expected( - "TO or = after ALTER TABLE SET PARALLELISM", - self.peek_token(), - ); + return self.expected("TO or = after ALTER TABLE SET PARALLELISM"); } let value = self.parse_set_variable()?; @@ -3419,10 +3267,10 @@ impl Parser { deferred, } } else { - return self.expected("PARALLELISM after SET", self.peek_token()); + return self.expected("PARALLELISM after SET"); } } else { - return self.expected("RENAME after ALTER INDEX", self.peek_token()); + return self.expected("RENAME after ALTER INDEX"); }; Ok(Statement::AlterIndex { @@ -3431,14 +3279,14 @@ impl Parser { }) } - pub fn parse_alter_view(&mut self, materialized: bool) -> Result { + pub fn parse_alter_view(&mut self, materialized: bool) -> PResult { let view_name = self.parse_object_name()?; let operation = if self.parse_keyword(Keyword::RENAME) { if self.parse_keyword(Keyword::TO) { let view_name = self.parse_object_name()?; AlterViewOperation::RenameView { view_name } } else { - return self.expected("TO after RENAME", self.peek_token()); + return self.expected("TO after RENAME"); } } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { let owner_name: Ident = self.parse_identifier()?; @@ -3455,10 +3303,7 @@ impl Parser { if self.expect_keyword(Keyword::TO).is_err() && self.expect_token(&Token::Eq).is_err() { - return self.expected( - "TO or = after ALTER TABLE SET PARALLELISM", - self.peek_token(), - ); + return self.expected("TO or = after ALTER TABLE SET PARALLELISM"); } let value = self.parse_set_variable()?; @@ -3474,19 +3319,13 @@ impl Parser { { AlterViewOperation::SetStreamingRateLimit { rate_limit } } else { - return self.expected( - "SCHEMA/PARALLELISM/STREAMING_RATE_LIMIT after SET", - self.peek_token(), - ); + return self.expected("SCHEMA/PARALLELISM/STREAMING_RATE_LIMIT after SET"); } } else { - return self.expected( - &format!( - "RENAME or OWNER TO or SET after ALTER {}VIEW", - if materialized { "MATERIALIZED " } else { "" } - ), - self.peek_token(), - ); + return self.expected(&format!( + "RENAME or OWNER TO or SET after ALTER {}VIEW", + if materialized { "MATERIALIZED " } else { "" } + )); }; Ok(Statement::AlterView { @@ -3496,14 +3335,14 @@ impl Parser { }) } - pub fn parse_alter_sink(&mut self) -> Result { + pub fn parse_alter_sink(&mut self) -> PResult { let sink_name = self.parse_object_name()?; let operation = if self.parse_keyword(Keyword::RENAME) { if self.parse_keyword(Keyword::TO) { let sink_name = self.parse_object_name()?; AlterSinkOperation::RenameSink { sink_name } } else { - return self.expected("TO after RENAME", self.peek_token()); + return self.expected("TO after RENAME"); } } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { let owner_name: Ident = self.parse_identifier()?; @@ -3520,10 +3359,7 @@ impl Parser { if self.expect_keyword(Keyword::TO).is_err() && self.expect_token(&Token::Eq).is_err() { - return self.expected( - "TO or = after ALTER TABLE SET PARALLELISM", - self.peek_token(), - ); + return self.expected("TO or = after ALTER TABLE SET PARALLELISM"); } let value = self.parse_set_variable()?; @@ -3534,13 +3370,10 @@ impl Parser { deferred, } } else { - return self.expected("SCHEMA/PARALLELISM after SET", self.peek_token()); + return self.expected("SCHEMA/PARALLELISM after SET"); } } else { - return self.expected( - "RENAME or OWNER TO or SET after ALTER SINK", - self.peek_token(), - ); + return self.expected("RENAME or OWNER TO or SET after ALTER SINK"); }; Ok(Statement::AlterSink { @@ -3549,14 +3382,14 @@ impl Parser { }) } - pub fn parse_alter_subscription(&mut self) -> Result { + pub fn parse_alter_subscription(&mut self) -> PResult { let subscription_name = self.parse_object_name()?; let operation = if self.parse_keyword(Keyword::RENAME) { if self.parse_keyword(Keyword::TO) { let subscription_name = self.parse_object_name()?; AlterSubscriptionOperation::RenameSubscription { subscription_name } } else { - return self.expected("TO after RENAME", self.peek_token()); + return self.expected("TO after RENAME"); } } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { let owner_name: Ident = self.parse_identifier()?; @@ -3570,13 +3403,10 @@ impl Parser { new_schema_name: schema_name, } } else { - return self.expected("SCHEMA after SET", self.peek_token()); + return self.expected("SCHEMA after SET"); } } else { - return self.expected( - "RENAME or OWNER TO or SET after ALTER SUBSCRIPTION", - self.peek_token(), - ); + return self.expected("RENAME or OWNER TO or SET after ALTER SUBSCRIPTION"); }; Ok(Statement::AlterSubscription { @@ -3585,14 +3415,14 @@ impl Parser { }) } - pub fn parse_alter_source(&mut self) -> Result { + pub fn parse_alter_source(&mut self) -> PResult { let source_name = self.parse_object_name()?; let operation = if self.parse_keyword(Keyword::RENAME) { if self.parse_keyword(Keyword::TO) { let source_name = self.parse_object_name()?; AlterSourceOperation::RenameSource { source_name } } else { - return self.expected("TO after RENAME", self.peek_token()); + return self.expected("TO after RENAME"); } } else if self.parse_keyword(Keyword::ADD) { let _ = self.parse_keyword(Keyword::COLUMN); @@ -3613,14 +3443,12 @@ impl Parser { } else if let Some(rate_limit) = self.parse_alter_streaming_rate_limit()? { AlterSourceOperation::SetStreamingRateLimit { rate_limit } } else { - return self.expected("SCHEMA after SET", self.peek_token()); + return self.expected("SCHEMA after SET"); } } else if self.peek_nth_any_of_keywords(0, &[Keyword::FORMAT]) { let connector_schema = self.parse_schema()?.unwrap(); if connector_schema.key_encode.is_some() { - return Err(ParserError::ParserError( - "key encode clause is not supported in source schema".to_string(), - )); + parser_err!("key encode clause is not supported in source schema"); } AlterSourceOperation::FormatEncode { connector_schema } } else if self.parse_keywords(&[Keyword::REFRESH, Keyword::SCHEMA]) { @@ -3628,7 +3456,6 @@ impl Parser { } else { return self.expected( "RENAME, ADD COLUMN, OWNER TO, SET or STREAMING_RATE_LIMIT after ALTER SOURCE", - self.peek_token(), ); }; @@ -3638,7 +3465,7 @@ impl Parser { }) } - pub fn parse_alter_function(&mut self) -> Result { + pub fn parse_alter_function(&mut self) -> PResult { let FunctionDesc { name, args } = self.parse_function_desc()?; let operation = if self.parse_keyword(Keyword::SET) { @@ -3648,10 +3475,10 @@ impl Parser { new_schema_name: schema_name, } } else { - return self.expected("SCHEMA after SET", self.peek_token()); + return self.expected("SCHEMA after SET"); } } else { - return self.expected("SET after ALTER FUNCTION", self.peek_token()); + return self.expected("SET after ALTER FUNCTION"); }; Ok(Statement::AlterFunction { @@ -3661,7 +3488,7 @@ impl Parser { }) } - pub fn parse_alter_connection(&mut self) -> Result { + pub fn parse_alter_connection(&mut self) -> PResult { let connection_name = self.parse_object_name()?; let operation = if self.parse_keyword(Keyword::SET) { if self.parse_keyword(Keyword::SCHEMA) { @@ -3670,10 +3497,10 @@ impl Parser { new_schema_name: schema_name, } } else { - return self.expected("SCHEMA after SET", self.peek_token()); + return self.expected("SCHEMA after SET"); } } else { - return self.expected("SET after ALTER CONNECTION", self.peek_token()); + return self.expected("SET after ALTER CONNECTION"); }; Ok(Statement::AlterConnection { @@ -3682,18 +3509,18 @@ impl Parser { }) } - pub fn parse_alter_system(&mut self) -> Result { + pub fn parse_alter_system(&mut self) -> PResult { self.expect_keyword(Keyword::SET)?; let param = self.parse_identifier()?; if self.expect_keyword(Keyword::TO).is_err() && self.expect_token(&Token::Eq).is_err() { - return self.expected("TO or = after ALTER SYSTEM SET", self.peek_token()); + return self.expected("TO or = after ALTER SYSTEM SET"); } let value = self.parse_set_variable()?; Ok(Statement::AlterSystem { param, value }) } /// Parse a copy statement - pub fn parse_copy(&mut self) -> Result { + pub fn parse_copy(&mut self) -> PResult { let table_name = self.parse_object_name()?; let columns = self.parse_parenthesized_column_list(Optional)?; self.expect_keywords(&[Keyword::FROM, Keyword::STDIN])?; @@ -3744,7 +3571,8 @@ impl Parser { } /// Parse a literal value (numbers, strings, date/time, booleans) - pub fn parse_value(&mut self) -> Result { + pub fn parse_value(&mut self) -> PResult { + let checkpoint = *self; let token = self.next_token(); match token.token { Token::Word(w) => match w.keyword { @@ -3754,12 +3582,9 @@ impl Parser { Keyword::NoKeyword if w.quote_style.is_some() => match w.quote_style { Some('"') => Ok(Value::DoubleQuotedString(w.value)), Some('\'') => Ok(Value::SingleQuotedString(w.value)), - _ => self.expected("A value?", Token::Word(w).with_location(token.location))?, + _ => self.expected_at(checkpoint, "A value")?, }, - _ => self.expected( - "a concrete value", - Token::Word(w).with_location(token.location), - ), + _ => self.expected_at(checkpoint, "a concrete value"), }, Token::Number(ref n) => Ok(Value::Number(n.clone())), Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())), @@ -3767,67 +3592,55 @@ impl Parser { Token::CstyleEscapesString(ref s) => Ok(Value::CstyleEscapedString(s.clone())), Token::NationalStringLiteral(ref s) => Ok(Value::NationalStringLiteral(s.to_string())), Token::HexStringLiteral(ref s) => Ok(Value::HexStringLiteral(s.to_string())), - unexpected => self.expected("a value", unexpected.with_location(token.location)), - } - } - - fn parse_set_variable(&mut self) -> Result { - let mut values = vec![]; - loop { - let token = self.peek_token(); - let value = match (self.parse_value(), token.token) { - (Ok(value), _) => SetVariableValueSingle::Literal(value), - (Err(_), Token::Word(w)) => { - if w.keyword == Keyword::DEFAULT { - if !values.is_empty() { - self.expected( - "parameter list value", - Token::Word(w).with_location(token.location), - )? + _ => self.expected_at(checkpoint, "a value"), + } + } + + fn parse_set_variable(&mut self) -> PResult { + alt(( + Keyword::DEFAULT.value(SetVariableValue::Default), + separated( + 1.., + alt(( + Self::parse_value.map(SetVariableValueSingle::Literal), + |parser: &mut Self| { + let checkpoint = *parser; + let ident = parser.parse_identifier()?; + if ident.value == "default" { + *parser = checkpoint; + return parser.expected("parameter list value").map_err(|e| e.cut()); } - return Ok(SetVariableValue::Default); - } else { - SetVariableValueSingle::Ident(w.to_ident()?) - } - } - (Err(_), unexpected) => { - self.expected("parameter value", unexpected.with_location(token.location))? + Ok(SetVariableValueSingle::Ident(ident)) + }, + fail.expect("parameter value"), + )), + Token::Comma, + ) + .map(|list: Vec| { + if list.len() == 1 { + SetVariableValue::Single(list[0].clone()) + } else { + SetVariableValue::List(list) } - }; - values.push(value); - if !self.consume_token(&Token::Comma) { - break; - } - } - if values.len() == 1 { - Ok(SetVariableValue::Single(values[0].clone())) - } else { - Ok(SetVariableValue::List(values)) - } + }), + )) + .parse_next(self) } - pub fn parse_number_value(&mut self) -> Result { + pub fn parse_number_value(&mut self) -> PResult { + let checkpoint = *self; match self.parse_value()? { Value::Number(v) => Ok(v), - _ => { - self.prev_token(); - self.expected("literal number", self.peek_token()) - } + _ => self.expected_at(checkpoint, "literal number"), } } /// Parse an unsigned literal integer/long - pub fn parse_literal_uint(&mut self) -> Result { - let token = self.next_token(); - match token.token { - Token::Number(s) => s.parse::().map_err(|e| { - ParserError::ParserError(format!("Could not parse '{}' as u64: {}", s, e)) - }), - unexpected => self.expected("literal int", unexpected.with_location(token.location)), - } + pub fn parse_literal_uint(&mut self) -> PResult { + literal_uint(self) } - pub fn parse_function_definition(&mut self) -> Result { + pub fn parse_function_definition(&mut self) -> PResult { let peek_token = self.peek_token(); match peek_token.token { Token::DollarQuotedString(value) => { @@ -3841,7 +3654,8 @@ impl Parser { } /// Parse a literal string - pub fn parse_literal_string(&mut self) -> Result { + pub fn parse_literal_string(&mut self) -> PResult { + let checkpoint = *self; let token = self.next_token(); match token.token { Token::Word(Word { @@ -3850,12 +3664,13 @@ impl Parser { .. }) => Ok(value), Token::SingleQuotedString(s) => Ok(s), - unexpected => self.expected("literal string", unexpected.with_location(token.location)), + _ => self.expected_at(checkpoint, "literal string"), } } /// Parse a map key string - pub fn parse_map_key(&mut self) -> Result { + pub fn parse_map_key(&mut self) -> PResult { + let checkpoint = *self; let token = self.next_token(); match token.token { Token::Word(Word { @@ -3870,27 +3685,22 @@ impl Parser { } Token::SingleQuotedString(s) => Ok(Expr::Value(Value::SingleQuotedString(s))), Token::Number(s) => Ok(Expr::Value(Value::Number(s))), - unexpected => self.expected( - "literal string, number or function", - unexpected.with_location(token.location), - ), + _ => self.expected_at(checkpoint, "literal string, number or function"), } } /// Parse a SQL datatype (in the context of a CREATE TABLE statement for example) and convert /// into an array of that datatype if needed - pub fn parse_data_type(&mut self) -> Result { - self.parse_v2(parser_v2::data_type) + pub fn parse_data_type(&mut self) -> PResult { + parser_v2::data_type(self) } /// Parse `AS identifier` (or simply `identifier` if it's not a reserved keyword) /// Some examples with aliases: `SELECT 1 foo`, `SELECT COUNT(*) AS cnt`, /// `SELECT ... FROM t1 foo, t2 bar`, `SELECT ... FROM (...) AS bar` - pub fn parse_optional_alias( - &mut self, - reserved_kwds: &[Keyword], - ) -> Result, ParserError> { + pub fn parse_optional_alias(&mut self, reserved_kwds: &[Keyword]) -> PResult> { let after_as = self.parse_keyword(Keyword::AS); + let checkpoint = *self; let token = self.next_token(); match token.token { // Accept any identifier after `AS` (though many dialects have restrictions on @@ -3901,14 +3711,11 @@ impl Parser { Token::Word(w) if after_as || (!reserved_kwds.contains(&w.keyword)) => { Ok(Some(w.to_ident()?)) } - not_an_ident => { + _ => { + *self = checkpoint; if after_as { - return self.expected( - "an identifier after AS", - not_an_ident.with_location(token.location), - ); + return self.expected("an identifier after AS"); } - self.prev_token(); Ok(None) // no alias found } } @@ -3921,7 +3728,7 @@ impl Parser { pub fn parse_optional_table_alias( &mut self, reserved_kwds: &[Keyword], - ) -> Result, ParserError> { + ) -> PResult> { match self.parse_optional_alias(reserved_kwds)? { Some(name) => { let columns = self.parse_parenthesized_column_list(Optional)?; @@ -3932,67 +3739,38 @@ impl Parser { } /// syntax `FOR SYSTEM_TIME AS OF PROCTIME()` is used for temporal join. - pub fn parse_as_of(&mut self) -> Result, ParserError> { - let after_for = self.parse_keyword(Keyword::FOR); - if after_for { - if self.peek_nth_any_of_keywords(0, &[Keyword::SYSTEM_TIME]) { - self.expect_keywords(&[Keyword::SYSTEM_TIME, Keyword::AS, Keyword::OF])?; - let token = self.next_token(); - match token.token { - Token::Word(w) => { - let ident = w.to_ident()?; - // Backward compatibility for now. - if ident.real_value() == "proctime" || ident.real_value() == "now" { - self.expect_token(&Token::LParen)?; - self.expect_token(&Token::RParen)?; - Ok(Some(AsOf::ProcessTime)) - } else { - parser_err!(format!("Expected proctime, found: {}", ident.real_value())) - } - } - Token::Number(s) => { - let num = s.parse::().map_err(|e| { - ParserError::ParserError(format!( - "Could not parse '{}' as i64: {}", - s, e - )) - }); - Ok(Some(AsOf::TimestampNum(num?))) - } - Token::SingleQuotedString(s) => Ok(Some(AsOf::TimestampString(s))), - unexpected => self.expected( - "Proctime(), Number or SingleQuotedString", - unexpected.with_location(token.location), - ), - } - } else { - self.expect_keywords(&[Keyword::SYSTEM_VERSION, Keyword::AS, Keyword::OF])?; - let token = self.next_token(); - match token.token { - Token::Number(s) => { - let num = s.parse::().map_err(|e| { - ParserError::ParserError(format!( - "Could not parse '{}' as i64: {}", - s, e - )) - }); - Ok(Some(AsOf::VersionNum(num?))) - } - Token::SingleQuotedString(s) => Ok(Some(AsOf::VersionString(s))), - unexpected => self.expected( - "Number or SingleQuotedString", - unexpected.with_location(token.location), - ), - } - } - } else { - Ok(None) - } + pub fn parse_as_of(&mut self) -> PResult { + Keyword::FOR.parse_next(self)?; + alt(( + preceded( + (Keyword::SYSTEM_TIME, Keyword::AS, Keyword::OF), + alt(( + ( + Self::parse_identifier.verify(|ident| { + ident.real_value() == "proctime" || ident.real_value() == "now" + }), + Token::LParen, + Token::RParen, + ) + .value(AsOf::ProcessTime), + literal_i64.map(AsOf::VersionNum), + Self::parse_literal_string.map(AsOf::TimestampString), + )), + ), + preceded( + (Keyword::SYSTEM_VERSION, Keyword::AS, Keyword::OF), + alt(( + literal_i64.map(AsOf::VersionNum), + Self::parse_literal_string.map(AsOf::VersionString), + )), + ), + )) + .parse_next(self) } /// Parse a possibly qualified, possibly quoted identifier, e.g. /// `foo` or `myschema."table" - pub fn parse_object_name(&mut self) -> Result { + pub fn parse_object_name(&mut self) -> PResult { let mut idents = vec![]; loop { idents.push(self.parse_identifier()?); @@ -4004,7 +3782,7 @@ impl Parser { } /// Parse identifiers strictly i.e. don't parse keywords - pub fn parse_identifiers_non_keywords(&mut self) -> Result, ParserError> { + pub fn parse_identifiers_non_keywords(&mut self) -> PResult> { let mut idents = vec![]; loop { match self.peek_token().token { @@ -4026,7 +3804,7 @@ impl Parser { } /// Parse identifiers - pub fn parse_identifiers(&mut self) -> Result, ParserError> { + pub fn parse_identifiers(&mut self) -> PResult> { let mut idents = vec![]; loop { let token = self.next_token(); @@ -4043,33 +3821,32 @@ impl Parser { } /// Parse a simple one-word identifier (possibly quoted, possibly a keyword) - pub fn parse_identifier(&mut self) -> Result { + pub fn parse_identifier(&mut self) -> PResult { + let checkpoint = *self; let token = self.next_token(); match token.token { Token::Word(w) => Ok(w.to_ident()?), - unexpected => self.expected("identifier", unexpected.with_location(token.location)), + _ => self.expected_at(checkpoint, "identifier"), } } /// Parse a simple one-word identifier (possibly quoted, possibly a non-reserved keyword) - pub fn parse_identifier_non_reserved(&mut self) -> Result { + pub fn parse_identifier_non_reserved(&mut self) -> PResult { + let checkpoint = *self; let token = self.next_token(); - match token.token.clone() { + match token.token { Token::Word(w) => { match keywords::RESERVED_FOR_COLUMN_OR_TABLE_NAME.contains(&w.keyword) { - true => parser_err!(format!("syntax error at or near {token}")), + true => parser_err!("syntax error at or near {w}"), false => Ok(w.to_ident()?), } } - unexpected => self.expected("identifier", unexpected.with_location(token.location)), + _ => self.expected_at(checkpoint, "identifier"), } } /// Parse a parenthesized comma-separated list of unqualified, possibly quoted identifiers - pub fn parse_parenthesized_column_list( - &mut self, - optional: IsOptional, - ) -> Result, ParserError> { + pub fn parse_parenthesized_column_list(&mut self, optional: IsOptional) -> PResult> { if self.consume_token(&Token::LParen) { let cols = self.parse_comma_separated(Parser::parse_identifier_non_reserved)?; self.expect_token(&Token::RParen)?; @@ -4077,25 +3854,22 @@ impl Parser { } else if optional == Optional { Ok(vec![]) } else { - self.expected("a list of columns in parentheses", self.peek_token()) + self.expected("a list of columns in parentheses") } } - pub fn parse_returning( - &mut self, - optional: IsOptional, - ) -> Result, ParserError> { + pub fn parse_returning(&mut self, optional: IsOptional) -> PResult> { if self.parse_keyword(Keyword::RETURNING) { let cols = self.parse_comma_separated(Parser::parse_select_item)?; Ok(cols) } else if optional == Optional { Ok(vec![]) } else { - self.expected("a list of columns or * after returning", self.peek_token()) + self.expected("a list of columns or * after returning") } } - pub fn parse_row_expr(&mut self) -> Result { + pub fn parse_row_expr(&mut self) -> PResult { Ok(Expr::Row(self.parse_token_wrapped_exprs( &Token::LParen, &Token::RParen, @@ -4103,11 +3877,7 @@ impl Parser { } /// Parse a comma-separated list (maybe empty) from a wrapped expression - pub fn parse_token_wrapped_exprs( - &mut self, - left: &Token, - right: &Token, - ) -> Result, ParserError> { + pub fn parse_token_wrapped_exprs(&mut self, left: &Token, right: &Token) -> PResult> { if self.consume_token(left) { let exprs = if self.consume_token(right) { vec![] @@ -4118,11 +3888,11 @@ impl Parser { }; Ok(exprs) } else { - self.expected(left.to_string().as_str(), self.peek_token()) + self.expected(left.to_string().as_str()) } } - pub fn parse_optional_precision(&mut self) -> Result, ParserError> { + pub fn parse_optional_precision(&mut self) -> PResult> { if self.consume_token(&Token::LParen) { let n = self.parse_literal_uint()?; self.expect_token(&Token::RParen)?; @@ -4132,9 +3902,7 @@ impl Parser { } } - pub fn parse_optional_precision_scale( - &mut self, - ) -> Result<(Option, Option), ParserError> { + pub fn parse_optional_precision_scale(&mut self) -> PResult<(Option, Option)> { if self.consume_token(&Token::LParen) { let n = self.parse_literal_uint()?; let scale = if self.consume_token(&Token::Comma) { @@ -4149,7 +3917,7 @@ impl Parser { } } - pub fn parse_delete(&mut self) -> Result { + pub fn parse_delete(&mut self) -> PResult { self.expect_keyword(Keyword::FROM)?; let table_name = self.parse_object_name()?; let selection = if self.parse_keyword(Keyword::WHERE) { @@ -4178,7 +3946,7 @@ impl Parser { } } - pub fn parse_explain(&mut self) -> Result { + pub fn parse_explain(&mut self) -> PResult { let mut options = ExplainOptions::default(); let explain_key_words = [ @@ -4190,7 +3958,7 @@ impl Parser { Keyword::DISTSQL, ]; - let parse_explain_option = |parser: &mut Parser| -> Result<(), ParserError> { + let parse_explain_option = |parser: &mut Parser<'_>| -> PResult<()> { let keyword = parser.expect_one_of_keywords(&explain_key_words)?; match keyword { Keyword::VERBOSE => options.verbose = parser.parse_optional_boolean(true), @@ -4239,7 +4007,7 @@ impl Parser { /// preceded with some `WITH` CTE declarations and optionally followed /// by `ORDER BY`. Unlike some other parse_... methods, this one doesn't /// expect the initial keyword to be already consumed - pub fn parse_query(&mut self) -> Result { + pub fn parse_query(&mut self) -> PResult { let with = if self.parse_keyword(Keyword::WITH) { Some(With { recursive: self.parse_keyword(Keyword::RECURSIVE), @@ -4271,13 +4039,11 @@ impl Parser { let fetch = if self.parse_keyword(Keyword::FETCH) { if limit.is_some() { - return parser_err!("Cannot specify both LIMIT and FETCH".to_string()); + parser_err!("Cannot specify both LIMIT and FETCH"); } let fetch = self.parse_fetch()?; if fetch.with_ties && order_by.is_empty() { - return parser_err!( - "WITH TIES cannot be specified without ORDER BY clause".to_string() - ); + parser_err!("WITH TIES cannot be specified without ORDER BY clause"); } Some(fetch) } else { @@ -4295,7 +4061,7 @@ impl Parser { } /// Parse a CTE (`alias [( col1, col2, ... )] AS (subquery)`) - fn parse_cte(&mut self) -> Result { + fn parse_cte(&mut self) -> PResult { let name = self.parse_identifier_non_reserved()?; let mut cte = if self.parse_keyword(Keyword::AS) { @@ -4338,7 +4104,7 @@ impl Parser { /// subquery ::= query_body [ order_by_limit ] /// set_operation ::= query_body { 'UNION' | 'EXCEPT' | 'INTERSECT' } [ 'ALL' ] query_body /// ``` - fn parse_query_body(&mut self, precedence: u8) -> Result { + fn parse_query_body(&mut self, precedence: u8) -> PResult { // We parse the expression using a Pratt parser, as in `parse_expr()`. // Start by parsing a restricted SELECT or a `(subquery)`: let mut expr = if self.parse_keyword(Keyword::SELECT) { @@ -4351,10 +4117,7 @@ impl Parser { } else if self.parse_keyword(Keyword::VALUES) { SetExpr::Values(self.parse_values()?) } else { - return self.expected( - "SELECT, VALUES, or a subquery in the query body", - self.peek_token(), - ); + return self.expected("SELECT, VALUES, or a subquery in the query body"); }; loop { @@ -4394,7 +4157,7 @@ impl Parser { /// Parse a restricted `SELECT` statement (no CTEs / `UNION` / `ORDER BY`), /// assuming the initial `SELECT` was already consumed - pub fn parse_select(&mut self) -> Result { + pub fn parse_select(&mut self) -> PResult