From fba2a14d1890a3605e8bba8c3fe6ada1a3e3190b Mon Sep 17 00:00:00 2001 From: Jake Swenson Date: Tue, 20 Jun 2023 19:46:14 +0200 Subject: [PATCH] feat(#757): Add Location/Spans in to the AST/parse layer --- src/ast/dcl.rs | 8 +- src/ast/ddl.rs | 115 +- src/ast/dml.rs | 15 +- src/ast/helpers/stmt_create_table.rs | 22 +- src/ast/helpers/stmt_data_loading.rs | 8 +- src/ast/mod.rs | 354 ++++--- src/ast/query.rs | 62 +- src/ast/trigger.rs | 2 +- src/ast/value.rs | 6 +- src/dialect/postgresql.rs | 18 +- src/dialect/snowflake.rs | 43 +- src/parser/mod.rs | 404 +++---- src/test_utils.rs | 15 +- src/tokenizer.rs | 149 ++- tests/sqlparser_bigquery.rs | 367 ++++--- tests/sqlparser_clickhouse.rs | 217 ++-- tests/sqlparser_common.rs | 1452 +++++++++++++++----------- tests/sqlparser_databricks.rs | 50 +- tests/sqlparser_duckdb.rs | 160 +-- tests/sqlparser_hive.rs | 44 +- tests/sqlparser_mssql.rs | 138 ++- tests/sqlparser_mysql.rs | 488 +++++---- tests/sqlparser_postgres.rs | 802 ++++++++------ tests/sqlparser_redshift.rs | 52 +- tests/sqlparser_snowflake.rs | 316 +++--- tests/sqlparser_sqlite.rs | 30 +- 26 files changed, 3196 insertions(+), 2141 deletions(-) diff --git a/src/ast/dcl.rs b/src/ast/dcl.rs index d47476ffa..88b261d95 100644 --- a/src/ast/dcl.rs +++ b/src/ast/dcl.rs @@ -29,7 +29,7 @@ use serde::{Deserialize, Serialize}; use sqlparser_derive::{Visit, VisitMut}; use super::{Expr, Ident, Password}; -use crate::ast::{display_separated, ObjectName}; +use crate::ast::{display_separated, ObjectName, WithSpan}; /// An option in `ROLE` statement. /// @@ -126,15 +126,15 @@ pub enum ResetConfig { pub enum AlterRoleOperation { /// Generic RenameRole { - role_name: Ident, + role_name: WithSpan, }, /// MS SQL Server /// AddMember { - member_name: Ident, + member_name: WithSpan, }, DropMember { - member_name: Ident, + member_name: WithSpan, }, /// PostgreSQL /// diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 21a716d25..cc24e656f 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -25,6 +25,7 @@ use core::fmt::{self, Write}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use sqlparser::ast::WithSpan; #[cfg(feature = "visitor")] use sqlparser_derive::{Visit, VisitMut}; @@ -60,7 +61,7 @@ pub enum AlterTableOperation { /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#add-projection) AddProjection { if_not_exists: bool, - name: Ident, + name: WithSpan, select: ProjectionSelect, }, @@ -68,7 +69,10 @@ pub enum AlterTableOperation { /// /// Note: this is a ClickHouse-specific operation. /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#drop-projection) - DropProjection { if_exists: bool, name: Ident }, + DropProjection { + if_exists: bool, + name: WithSpan, + }, /// `MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name]` /// @@ -76,8 +80,8 @@ pub enum AlterTableOperation { /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#materialize-projection) MaterializeProjection { if_exists: bool, - name: Ident, - partition: Option, + name: WithSpan, + partition: Option>, }, /// `CLEAR PROJECTION [IF EXISTS] name [IN PARTITION partition_name]` @@ -86,8 +90,8 @@ pub enum AlterTableOperation { /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#clear-projection) ClearProjection { if_exists: bool, - name: Ident, - partition: Option, + name: WithSpan, + partition: Option>, }, /// `DISABLE ROW LEVEL SECURITY` @@ -97,20 +101,20 @@ pub enum AlterTableOperation { /// `DISABLE RULE rewrite_rule_name` /// /// Note: this is a PostgreSQL-specific operation. - DisableRule { name: Ident }, + DisableRule { name: WithSpan }, /// `DISABLE TRIGGER [ trigger_name | ALL | USER ]` /// /// Note: this is a PostgreSQL-specific operation. - DisableTrigger { name: Ident }, + DisableTrigger { name: WithSpan }, /// `DROP CONSTRAINT [ IF EXISTS ] ` DropConstraint { if_exists: bool, - name: Ident, + name: WithSpan, cascade: bool, }, /// `DROP [ COLUMN ] [ IF EXISTS ] [ CASCADE ]` DropColumn { - column_name: Ident, + column_name: WithSpan, if_exists: bool, cascade: bool, }, @@ -134,14 +138,14 @@ pub enum AlterTableOperation { /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#freeze-partition) FreezePartition { partition: Partition, - with_name: Option, + with_name: Option>, }, /// `UNFREEZE PARTITION ` /// Note: this is a ClickHouse-specific operation, please refer to /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#unfreeze-partition) UnfreezePartition { partition: Partition, - with_name: Option, + with_name: Option>, }, /// `DROP PRIMARY KEY` /// @@ -150,19 +154,19 @@ pub enum AlterTableOperation { /// `ENABLE ALWAYS RULE rewrite_rule_name` /// /// Note: this is a PostgreSQL-specific operation. - EnableAlwaysRule { name: Ident }, + EnableAlwaysRule { name: WithSpan }, /// `ENABLE ALWAYS TRIGGER trigger_name` /// /// Note: this is a PostgreSQL-specific operation. - EnableAlwaysTrigger { name: Ident }, + EnableAlwaysTrigger { name: WithSpan }, /// `ENABLE REPLICA RULE rewrite_rule_name` /// /// Note: this is a PostgreSQL-specific operation. - EnableReplicaRule { name: Ident }, + EnableReplicaRule { name: WithSpan }, /// `ENABLE REPLICA TRIGGER trigger_name` /// /// Note: this is a PostgreSQL-specific operation. - EnableReplicaTrigger { name: Ident }, + EnableReplicaTrigger { name: WithSpan }, /// `ENABLE ROW LEVEL SECURITY` /// /// Note: this is a PostgreSQL-specific operation. @@ -170,11 +174,11 @@ pub enum AlterTableOperation { /// `ENABLE RULE rewrite_rule_name` /// /// Note: this is a PostgreSQL-specific operation. - EnableRule { name: Ident }, + EnableRule { name: WithSpan }, /// `ENABLE TRIGGER [ trigger_name | ALL | USER ]` /// /// Note: this is a PostgreSQL-specific operation. - EnableTrigger { name: Ident }, + EnableTrigger { name: WithSpan }, /// `RENAME TO PARTITION (partition=val)` RenamePartitions { old_partitions: Vec, @@ -191,15 +195,15 @@ pub enum AlterTableOperation { }, /// `RENAME [ COLUMN ] TO ` RenameColumn { - old_column_name: Ident, - new_column_name: Ident, + old_column_name: WithSpan, + new_column_name: WithSpan, }, /// `RENAME TO ` RenameTable { table_name: ObjectName }, // CHANGE [ COLUMN ] [ ] ChangeColumn { - old_name: Ident, - new_name: Ident, + old_name: WithSpan, + new_name: WithSpan, data_type: DataType, options: Vec, /// MySQL `ALTER TABLE` only [FIRST | AFTER column_name] @@ -207,7 +211,7 @@ pub enum AlterTableOperation { }, // CHANGE [ COLUMN ] [ ] ModifyColumn { - col_name: Ident, + col_name: WithSpan, data_type: DataType, options: Vec, /// MySQL `ALTER TABLE` only [FIRST | AFTER column_name] @@ -216,10 +220,13 @@ pub enum AlterTableOperation { /// `RENAME CONSTRAINT TO ` /// /// Note: this is a PostgreSQL-specific operation. - RenameConstraint { old_name: Ident, new_name: Ident }, + RenameConstraint { + old_name: WithSpan, + new_name: WithSpan, + }, /// `ALTER [ COLUMN ]` AlterColumn { - column_name: Ident, + column_name: WithSpan, op: AlterColumnOperation, }, /// 'SWAP WITH ' @@ -243,7 +250,7 @@ pub enum AlterTableOperation { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum AlterPolicyOperation { Rename { - new_name: Ident, + new_name: WithSpan, }, Apply { to: Option>, @@ -282,7 +289,7 @@ impl fmt::Display for AlterPolicyOperation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum Owner { - Ident(Ident), + Ident(WithSpan), CurrentRole, CurrentUser, SessionUser, @@ -654,9 +661,9 @@ pub enum TableConstraint { /// Constraint name. /// /// Can be not the same as `index_name` - name: Option, + name: Option>, /// Index name - index_name: Option, + index_name: Option>, /// Whether the type is followed by the keyword `KEY`, `INDEX`, or no keyword at all. index_type_display: KeyOrIndexDisplay, /// Optional `USING` of [index type][1] statement before columns. @@ -664,7 +671,7 @@ pub enum TableConstraint { /// [1]: IndexType index_type: Option, /// Identifiers of the columns that are unique. - columns: Vec, + columns: Vec>, index_options: Vec, characteristics: Option, }, @@ -690,15 +697,15 @@ pub enum TableConstraint { /// Constraint name. /// /// Can be not the same as `index_name` - name: Option, + name: Option>, /// Index name - index_name: Option, + index_name: Option>, /// Optional `USING` of [index type][1] statement before columns. /// /// [1]: IndexType index_type: Option, /// Identifiers of the columns that form the primary key. - columns: Vec, + columns: Vec>, index_options: Vec, characteristics: Option, }, @@ -708,17 +715,17 @@ pub enum TableConstraint { /// [ON UPDATE ] [ON DELETE ] /// }`). ForeignKey { - name: Option, - columns: Vec, + name: Option>, + columns: Vec>, foreign_table: ObjectName, - referred_columns: Vec, + referred_columns: Vec>, on_delete: Option, on_update: Option, characteristics: Option, }, /// `[ CONSTRAINT ] CHECK ()` Check { - name: Option, + name: Option>, expr: Box, }, /// MySQLs [index definition][1] for index creation. Not present on ANSI so, for now, the usage @@ -731,13 +738,13 @@ pub enum TableConstraint { /// Whether this index starts with KEY (true) or INDEX (false), to maintain the same syntax. display_as_key: bool, /// Index name. - name: Option, + name: Option>, /// Optional [index type][1]. /// /// [1]: IndexType index_type: Option, /// Referred column identifier list. - columns: Vec, + columns: Vec>, }, /// MySQLs [fulltext][1] definition. Since the [`SPATIAL`][2] definition is exactly the same, /// and MySQL displays both the same way, it is part of this definition as well. @@ -758,9 +765,9 @@ pub enum TableConstraint { /// Whether the type is followed by the keyword `KEY`, `INDEX`, or no keyword at all. index_type_display: KeyOrIndexDisplay, /// Optional index name. - opt_index_name: Option, + opt_index_name: Option>, /// Referred column identifier list. - columns: Vec, + columns: Vec>, }, } @@ -990,7 +997,7 @@ impl fmt::Display for IndexOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ProcedureParam { - pub name: Ident, + pub name: WithSpan, pub data_type: DataType, } @@ -1005,7 +1012,7 @@ impl fmt::Display for ProcedureParam { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ColumnDef { - pub name: Ident, + pub name: WithSpan, pub data_type: DataType, pub collation: Option, pub options: Vec, @@ -1048,7 +1055,7 @@ impl fmt::Display for ColumnDef { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ViewColumnDef { - pub name: Ident, + pub name: WithSpan, pub data_type: Option, pub options: Option>, } @@ -1086,7 +1093,7 @@ impl fmt::Display for ViewColumnDef { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ColumnOptionDef { - pub name: Option, + pub name: Option>, pub option: ColumnOption, } @@ -1280,8 +1287,8 @@ pub struct ColumnPolicyProperty { /// ``` /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table pub with: bool, - pub policy_name: Ident, - pub using_columns: Option>, + pub policy_name: WithSpan, + pub using_columns: Option>>, } /// Tags option of column @@ -1352,7 +1359,7 @@ pub enum ColumnOption { /// `). ForeignKey { foreign_table: ObjectName, - referred_columns: Vec, + referred_columns: Vec>, on_delete: Option, on_update: Option, characteristics: Option, @@ -1550,8 +1557,8 @@ pub enum GeneratedExpressionMode { } #[must_use] -fn display_constraint_name(name: &'_ Option) -> impl fmt::Display + '_ { - struct ConstraintName<'a>(&'a Option); +fn display_constraint_name(name: &'_ Option>) -> impl fmt::Display + '_ { + struct ConstraintName<'a>(&'a Option>); impl<'a> fmt::Display for ConstraintName<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(name) = self.0 { @@ -1707,7 +1714,7 @@ pub enum UserDefinedTypeRepresentation { attributes: Vec, }, /// Note: this is PostgreSQL-specific. See - Enum { labels: Vec }, + Enum { labels: Vec> }, } impl fmt::Display for UserDefinedTypeRepresentation { @@ -1728,7 +1735,7 @@ impl fmt::Display for UserDefinedTypeRepresentation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct UserDefinedTypeCompositeAttributeDef { - pub name: Ident, + pub name: WithSpan, pub data_type: DataType, pub collation: Option, } @@ -1750,7 +1757,7 @@ impl fmt::Display for UserDefinedTypeCompositeAttributeDef { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum Partition { - Identifier(Ident), + Identifier(WithSpan), Expr(Expr), /// ClickHouse supports PART expr which represents physical partition in disk. /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#attach-partitionpart) @@ -1798,7 +1805,7 @@ impl fmt::Display for Deduplicate { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ClusteredBy { - pub columns: Vec, + pub columns: Vec>, pub sorted_by: Option>, pub num_buckets: Value, } diff --git a/src/ast/dml.rs b/src/ast/dml.rs index 2932fafb5..c7228b230 100644 --- a/src/ast/dml.rs +++ b/src/ast/dml.rs @@ -23,6 +23,7 @@ use alloc::{ vec::Vec, }; +use crate::ast::WithSpan; use core::fmt::{self, Display}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -48,12 +49,12 @@ pub struct CreateIndex { pub name: Option, #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] pub table_name: ObjectName, - pub using: Option, + pub using: Option>, pub columns: Vec, pub unique: bool, pub concurrently: bool, pub if_not_exists: bool, - pub include: Vec, + pub include: Vec>, pub nulls_distinct: Option, /// WITH clause: pub with: Vec, @@ -141,7 +142,7 @@ pub struct CreateTable { pub on_commit: Option, /// ClickHouse "ON CLUSTER" clause: /// - pub on_cluster: Option, + pub on_cluster: Option>, /// ClickHouse "PRIMARY KEY " clause. /// pub primary_key: Option>, @@ -154,7 +155,7 @@ pub struct CreateTable { pub partition_by: Option>, /// BigQuery: Table clustering column list. /// - pub cluster_by: Option>>, + pub cluster_by: Option>>>, /// Hive: Table clustering column list. /// pub clustered_by: Option, @@ -473,9 +474,9 @@ pub struct Insert { #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] pub table_name: ObjectName, /// table_name as foo (for PostgreSQL) - pub table_alias: Option, + pub table_alias: Option>, /// COLUMNS - pub columns: Vec, + pub columns: Vec>, /// Overwrite (Hive) pub overwrite: bool, /// A SQL query that specifies what to insert @@ -483,7 +484,7 @@ pub struct Insert { /// partitioned insert (Hive) pub partitioned: Option>, /// Columns defined after PARTITION - pub after_columns: Vec, + pub after_columns: Vec>, /// whether the insert has the table keyword (Hive) pub table: bool, pub on: Option, diff --git a/src/ast/helpers/stmt_create_table.rs b/src/ast/helpers/stmt_create_table.rs index 364969c40..3d78e0a4b 100644 --- a/src/ast/helpers/stmt_create_table.rs +++ b/src/ast/helpers/stmt_create_table.rs @@ -28,7 +28,7 @@ use super::super::dml::CreateTable; use crate::ast::{ ClusteredBy, ColumnDef, CommentDef, Expr, FileFormat, HiveDistributionStyle, HiveFormat, Ident, ObjectName, OnCommit, OneOrManyWithParens, Query, RowAccessPolicy, SqlOption, Statement, - TableConstraint, TableEngine, Tag, WrappedCollection, + TableConstraint, TableEngine, Tag, WithSpan, WrappedCollection, }; use crate::parser::ParserError; @@ -42,7 +42,7 @@ use crate::parser::ParserError; /// ```rust /// use sqlparser::ast::helpers::stmt_create_table::CreateTableBuilder; /// use sqlparser::ast::{ColumnDef, DataType, Ident, ObjectName}; -/// let builder = CreateTableBuilder::new(ObjectName(vec![Ident::new("table_name")])) +/// let builder = CreateTableBuilder::new(ObjectName(vec![Ident::new("table_name").empty_span()])) /// .if_not_exists(true) /// .columns(vec![ColumnDef { /// name: Ident::new("c1"), @@ -90,11 +90,11 @@ pub struct CreateTableBuilder { pub default_charset: Option, pub collation: Option, pub on_commit: Option, - pub on_cluster: Option, + pub on_cluster: Option>, pub primary_key: Option>, pub order_by: Option>, pub partition_by: Option>, - pub cluster_by: Option>>, + pub cluster_by: Option>>>, pub clustered_by: Option, pub options: Option>, pub strict: bool, @@ -280,7 +280,7 @@ impl CreateTableBuilder { self } - pub fn on_cluster(mut self, on_cluster: Option) -> Self { + pub fn on_cluster(mut self, on_cluster: Option>) -> Self { self.on_cluster = on_cluster; self } @@ -300,7 +300,10 @@ impl CreateTableBuilder { self } - pub fn cluster_by(mut self, cluster_by: Option>>) -> Self { + pub fn cluster_by( + mut self, + cluster_by: Option>>>, + ) -> Self { self.cluster_by = cluster_by; self } @@ -527,19 +530,20 @@ impl TryFrom for CreateTableBuilder { #[derive(Default)] pub(crate) struct CreateTableConfiguration { pub partition_by: Option>, - pub cluster_by: Option>>, + pub cluster_by: Option>>>, pub options: Option>, } #[cfg(test)] mod tests { use crate::ast::helpers::stmt_create_table::CreateTableBuilder; - use crate::ast::{Ident, ObjectName, Statement}; + use crate::ast::{Ident, ObjectName, SpanWrapped, Statement}; use crate::parser::ParserError; #[test] pub fn test_from_valid_statement() { - let builder = CreateTableBuilder::new(ObjectName(vec![Ident::new("table_name")])); + let builder = + CreateTableBuilder::new(ObjectName(vec![Ident::new("table_name").empty_span()])); let stmt = builder.clone().build(); diff --git a/src/ast/helpers/stmt_data_loading.rs b/src/ast/helpers/stmt_data_loading.rs index cda6c6ea4..2bb79b552 100644 --- a/src/ast/helpers/stmt_data_loading.rs +++ b/src/ast/helpers/stmt_data_loading.rs @@ -29,7 +29,7 @@ use core::fmt::Formatter; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::ast::Ident; +use crate::ast::{Ident, WithSpan}; #[cfg(feature = "visitor")] use sqlparser_derive::{Visit, VisitMut}; @@ -73,10 +73,10 @@ pub struct DataLoadingOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct StageLoadSelectItem { - pub alias: Option, + pub alias: Option>, pub file_col_num: i32, - pub element: Option, - pub item_as: Option, + pub element: Option>, + pub item_as: Option>, } impl fmt::Display for StageParamsObject { diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 0573240a2..d021d22da 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -24,6 +24,7 @@ use alloc::{ vec::Vec, }; +use core::borrow::Borrow; use core::fmt::{self, Display}; use core::ops::Deref; @@ -76,6 +77,7 @@ pub use self::value::{ use crate::ast::helpers::stmt_data_loading::{ DataLoadingOptions, StageLoadSelectItem, StageParamsObject, }; +use crate::tokenizer::Span; #[cfg(feature = "visitor")] pub use visitor::*; @@ -194,7 +196,7 @@ impl fmt::Display for Ident { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] -pub struct ObjectName(pub Vec); +pub struct ObjectName(pub Vec>); impl fmt::Display for ObjectName { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -297,7 +299,7 @@ impl fmt::Display for Interval { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct StructField { - pub field_name: Option, + pub field_name: Option>, pub field_type: DataType, } @@ -318,7 +320,7 @@ impl fmt::Display for StructField { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct UnionField { - pub field_name: Ident, + pub field_name: WithSpan, pub field_type: DataType, } @@ -335,7 +337,7 @@ impl fmt::Display for UnionField { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct DictionaryField { - pub key: Ident, + pub key: WithSpan, pub value: Box, } @@ -527,6 +529,78 @@ pub enum CeilFloorKind { Scale(Value), } +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub struct WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + inner: T, + span: Span, +} + +impl WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + pub fn new(inner: T, span: Span) -> Self { + Self { inner, span } + } + + pub fn unwrap(self) -> T { + self.inner + } +} + +pub trait SpanWrapped: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq { + fn spanning>(self, span: U) -> WithSpan { + WithSpan::new(self, span.into()) + } + + fn empty_span(self) -> WithSpan { + self.spanning(Span::default()) + } +} + +impl SpanWrapped for T +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + fn spanning>(self, span: U) -> WithSpan { + WithSpan::new(self, span.into()) + } +} + +impl Deref for WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl Borrow for WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + fn borrow(&self) -> &T { + &self.inner + } +} + +impl fmt::Display for WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.inner) + } +} + /// An SQL expression of any type. /// /// The parser does not distinguish between expressions of different types @@ -541,9 +615,9 @@ pub enum CeilFloorKind { )] pub enum Expr { /// Identifier e.g. table name or column name - Identifier(Ident), + Identifier(WithSpan), /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col` - CompoundIdentifier(Vec), + CompoundIdentifier(Vec>), /// Access data nested in a value containing semi-structured data, such as /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`. /// @@ -558,7 +632,7 @@ pub enum Expr { /// CompositeAccess (postgres) eg: SELECT (information_schema._pg_expandarray(array['i','i'])).n CompositeAccess { expr: Box, - key: Ident, + key: WithSpan, }, /// `IS FALSE` operator IsFalse(Box), @@ -856,7 +930,7 @@ pub enum Expr { /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type Named { expr: Box, - name: Ident, + name: WithSpan, }, /// `DuckDB` specific `Struct` literal expression [1] /// @@ -895,7 +969,7 @@ pub enum Expr { /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match MatchAgainst { /// `(, , ...)`. - columns: Vec, + columns: Vec>, /// ``. match_value: Value, /// `` @@ -1001,7 +1075,7 @@ impl fmt::Display for Subscript { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct LambdaFunction { /// The parameters to the lambda function. - pub params: OneOrManyWithParens, + pub params: OneOrManyWithParens>, /// The body of the lambda function. pub body: Box, } @@ -1667,7 +1741,7 @@ impl fmt::Display for Expr { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum WindowType { WindowSpec(WindowSpec), - NamedWindow(Ident), + NamedWindow(WithSpan), } impl Display for WindowType { @@ -1691,7 +1765,7 @@ pub struct WindowSpec { /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS - pub window_name: Option, + pub window_name: Option>, /// `OVER (PARTITION BY ...)` pub partition_by: Vec, /// `OVER (ORDER BY ...)` @@ -2031,7 +2105,7 @@ impl fmt::Display for DeclareType { pub struct Declare { /// The name(s) being declared. /// Example: `DECLARE a, b, c DEFAULT 42; - pub names: Vec, + pub names: Vec>, /// Data-type assigned to the declared variable. /// Example: `DECLARE x INT64 DEFAULT 42; pub data_type: Option, @@ -2237,7 +2311,7 @@ pub enum Statement { table_name: ObjectName, partitions: Option>, for_columns: bool, - columns: Vec, + columns: Vec>, cache_metadata: bool, noscan: bool, compute_statistics: bool, @@ -2264,7 +2338,7 @@ pub enum Statement { /// [ ON CLUSTER cluster_name ] /// /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/truncate/) - on_cluster: Option, + on_cluster: Option>, }, /// ```sql /// MSCK @@ -2289,14 +2363,14 @@ pub enum Statement { /// ``` Install { /// Only for DuckDB - extension_name: Ident, + extension_name: WithSpan, }, /// ```sql /// LOAD /// ``` Load { /// Only for DuckDB - extension_name: Ident, + extension_name: WithSpan, }, // TODO: Support ROW FORMAT Directory { @@ -2338,7 +2412,7 @@ pub enum Statement { CopyIntoSnowflake { into: ObjectName, from_stage: ObjectName, - from_stage_alias: Option, + from_stage_alias: Option>, stage_params: StageParamsObject, from_transformations: Option>, files: Option>, @@ -2385,7 +2459,7 @@ pub enum Statement { columns: Vec, query: Box, options: CreateTableOptions, - cluster_by: Vec, + cluster_by: Vec>, /// Snowflake: Views can have comments in Snowflake. /// comment: Option, @@ -2411,8 +2485,8 @@ pub enum Statement { #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] name: ObjectName, if_not_exists: bool, - module_name: Ident, - module_args: Vec, + module_name: WithSpan, + module_args: Vec>, }, /// ```sql /// `CREATE INDEX` @@ -2436,11 +2510,11 @@ pub enum Statement { replication: Option, connection_limit: Option, valid_until: Option, - in_role: Vec, - in_group: Vec, - role: Vec, - user: Vec, - admin: Vec, + in_role: Vec>, + in_group: Vec>, + role: Vec>, + user: Vec>, + admin: Vec>, // MSSQL authorization_owner: Option, }, @@ -2452,9 +2526,9 @@ pub enum Statement { or_replace: bool, temporary: Option, if_not_exists: bool, - name: Option, - storage_specifier: Option, - secret_type: Ident, + name: Option>, + storage_specifier: Option>, + secret_type: WithSpan, options: Vec, }, /// ```sql @@ -2462,7 +2536,7 @@ pub enum Statement { /// ``` /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html) CreatePolicy { - name: Ident, + name: WithSpan, #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, policy_type: Option, @@ -2485,7 +2559,7 @@ pub enum Statement { /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32` /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update) - on_cluster: Option, + on_cluster: Option>, }, /// ```sql /// ALTER INDEX @@ -2501,7 +2575,7 @@ pub enum Statement { /// View name #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] name: ObjectName, - columns: Vec, + columns: Vec>, query: Box, with_options: Vec, }, @@ -2509,7 +2583,7 @@ pub enum Statement { /// ALTER ROLE /// ``` AlterRole { - name: Ident, + name: WithSpan, operation: AlterRoleOperation, }, /// ```sql @@ -2517,7 +2591,7 @@ pub enum Statement { /// ``` /// (Postgresql-specific) AlterPolicy { - name: Ident, + name: WithSpan, #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, operation: AlterPolicyOperation, @@ -2528,7 +2602,7 @@ pub enum Statement { /// (SQLite-specific) AttachDatabase { /// The name to bind to the newly attached database - schema_name: Ident, + schema_name: WithSpan, /// An expression that indicates the path to the database file database_file_name: Expr, /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH' @@ -2544,8 +2618,8 @@ pub enum Statement { /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH' database: bool, /// An expression that indicates the path to the database file - database_path: Ident, - database_alias: Option, + database_path: WithSpan, + database_alias: Option>, attach_options: Vec, }, /// (DuckDB-specific) @@ -2557,7 +2631,7 @@ pub enum Statement { if_exists: bool, /// true if the syntax is 'DETACH DATABASE', false if it's just 'DETACH' database: bool, - database_alias: Ident, + database_alias: WithSpan, }, /// ```sql /// DROP [TABLE, VIEW, ...] @@ -2607,8 +2681,8 @@ pub enum Statement { DropSecret { if_exists: bool, temporary: Option, - name: Ident, - storage_specifier: Option, + name: WithSpan, + storage_specifier: Option>, }, ///```sql /// DROP POLICY @@ -2616,7 +2690,7 @@ pub enum Statement { /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html) DropPolicy { if_exists: bool, - name: Ident, + name: WithSpan, table_name: ObjectName, option: Option, }, @@ -2637,11 +2711,11 @@ pub enum Statement { /// /// Note: this is a PostgreSQL-specific statement, CreateExtension { - name: Ident, + name: WithSpan, if_not_exists: bool, cascade: bool, - schema: Option, - version: Option, + schema: Option>, + version: Option>, }, /// ```sql /// FETCH @@ -2652,7 +2726,7 @@ pub enum Statement { /// but may also compatible with other SQL. Fetch { /// Cursor name - name: Ident, + name: WithSpan, direction: FetchDirection, /// Optional, It's possible to fetch rows form cursor to the table into: Option, @@ -2692,7 +2766,7 @@ pub enum Statement { /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`). context_modifier: ContextModifier, /// Role name. If NONE is specified, then the current role name is removed. - role_name: Option, + role_name: Option>, }, /// ```sql /// SET = expression; @@ -2739,7 +2813,7 @@ pub enum Statement { /// ``` /// /// Note: this is a PostgreSQL-specific statement. - ShowVariable { variable: Vec }, + ShowVariable { variable: Vec> }, /// ```sql /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr] /// ``` @@ -2788,7 +2862,7 @@ pub enum Statement { ShowTables { extended: bool, full: bool, - db_name: Option, + db_name: Option>, filter: Option, }, /// ```sql @@ -2846,7 +2920,7 @@ pub enum Statement { /// ``` Rollback { chain: bool, - savepoint: Option, + savepoint: Option>, }, /// ```sql /// CREATE SCHEMA @@ -2911,7 +2985,7 @@ pub enum Statement { /// CREATE FUNCTION foo() LANGUAGE js AS "console.log();" /// ``` /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_javascript_udf) - language: Option, + language: Option>, /// Determinism keyword used for non-sql UDF definitions. /// /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11) @@ -3071,9 +3145,9 @@ pub enum Statement { Grant { privileges: Privileges, objects: GrantObjects, - grantees: Vec, + grantees: Vec>, with_grant_option: bool, - granted_by: Option, + granted_by: Option>, }, /// ```sql /// REVOKE privileges ON objects FROM grantees @@ -3081,8 +3155,8 @@ pub enum Statement { Revoke { privileges: Privileges, objects: GrantObjects, - grantees: Vec, - granted_by: Option, + grantees: Vec>, + granted_by: Option>, cascade: bool, }, /// ```sql @@ -3090,14 +3164,17 @@ pub enum Statement { /// ``` /// /// Note: this is a PostgreSQL-specific statement. - Deallocate { name: Ident, prepare: bool }, + Deallocate { + name: WithSpan, + prepare: bool, + }, /// ```sql /// EXECUTE name [ ( parameter [, ...] ) ] [USING ] /// ``` /// /// Note: this is a PostgreSQL-specific statement. Execute { - name: Ident, + name: WithSpan, parameters: Vec, using: Vec, }, @@ -3107,7 +3184,7 @@ pub enum Statement { /// /// Note: this is a PostgreSQL-specific statement. Prepare { - name: Ident, + name: WithSpan, data_types: Vec, statement: Box, }, @@ -3166,11 +3243,11 @@ pub enum Statement { /// SAVEPOINT /// ``` /// Define a new savepoint within the current transaction - Savepoint { name: Ident }, + Savepoint { name: WithSpan }, /// ```sql /// RELEASE [ SAVEPOINT ] savepoint_name /// ``` - ReleaseSavepoint { name: Ident }, + ReleaseSavepoint { name: WithSpan }, /// A `MERGE` statement. /// /// ```sql @@ -3263,7 +3340,7 @@ pub enum Statement { // Athena Unload { query: Box, - to: Ident, + to: WithSpan, with: Vec, }, /// ```sql @@ -3273,7 +3350,7 @@ pub enum Statement { /// See ClickHouse OptimizeTable { name: ObjectName, - on_cluster: Option, + on_cluster: Option>, partition: Option, include_final: bool, deduplicate: Option, @@ -4248,7 +4325,10 @@ impl fmt::Display for Statement { context_modifier, role_name, } => { - let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE")); + let role_name: Ident = role_name + .clone() + .map(|r| r.inner) + .unwrap_or_else(|| Ident::new("NONE")); write!(f, "SET{context_modifier} ROLE {role_name}") } Statement::SetVariable { @@ -4913,7 +4993,7 @@ pub enum OnInsert { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct InsertAliases { pub row_alias: ObjectName, - pub col_aliases: Option>, + pub col_aliases: Option>>, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] @@ -4927,7 +5007,7 @@ pub struct OnConflict { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ConflictTarget { - Columns(Vec), + Columns(Vec>), OnConstraint(ObjectName), } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] @@ -5109,13 +5189,21 @@ pub enum Action { Create, Delete, Execute, - Insert { columns: Option> }, - References { columns: Option> }, - Select { columns: Option> }, + Insert { + columns: Option>>, + }, + References { + columns: Option>>, + }, + Select { + columns: Option>>, + }, Temporary, Trigger, Truncate, - Update { columns: Option> }, + Update { + columns: Option>>, + }, Usage, } @@ -5293,7 +5381,7 @@ impl fmt::Display for FunctionArgOperator { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FunctionArg { Named { - name: Ident, + name: WithSpan, arg: FunctionArgExpr, operator: FunctionArgOperator, }, @@ -5318,7 +5406,7 @@ impl fmt::Display for FunctionArg { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum CloseCursor { All, - Specific { name: Ident }, + Specific { name: WithSpan }, } impl fmt::Display for CloseCursor { @@ -5719,7 +5807,7 @@ pub enum HiveRowFormat { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct HiveRowDelimiter { pub delimiter: HiveDelimiter, - pub char: Ident, + pub char: WithSpan, } impl fmt::Display for HiveRowDelimiter { @@ -5821,7 +5909,7 @@ pub struct HiveFormat { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ClusteredIndex { - pub name: Ident, + pub name: WithSpan, pub asc: Option, } @@ -5841,7 +5929,7 @@ impl fmt::Display for ClusteredIndex { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum TableOptionsClustered { ColumnstoreIndex, - ColumnstoreIndexOrder(Vec), + ColumnstoreIndexOrder(Vec>), Index(Vec), } @@ -5885,11 +5973,11 @@ pub enum SqlOption { /// Single identifier options, e.g. `HEAP` for MSSQL. /// /// - Ident(Ident), + Ident(WithSpan), /// Any option that consists of a key value pair where the value is an expression. e.g. /// /// WITH(DISTRIBUTION = ROUND_ROBIN) - KeyValue { key: Ident, value: Expr }, + KeyValue { key: WithSpan, value: Expr }, /// One or more table partitions and represents which partition the boundary values belong to, /// e.g. /// @@ -5897,7 +5985,7 @@ pub enum SqlOption { /// /// Partition { - column_name: Ident, + column_name: WithSpan, range_direction: Option, for_values: Vec, }, @@ -5940,8 +6028,8 @@ impl fmt::Display for SqlOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct SecretOption { - pub key: Ident, - pub value: Ident, + pub key: WithSpan, + pub value: WithSpan, } impl fmt::Display for SecretOption { @@ -5955,7 +6043,7 @@ impl fmt::Display for SecretOption { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum AttachDuckDBDatabaseOption { ReadOnly(Option), - Type(Ident), + Type(WithSpan), } impl fmt::Display for AttachDuckDBDatabaseOption { @@ -6132,7 +6220,7 @@ pub enum CopySource { table_name: ObjectName, /// A list of column names to copy. Empty list means that all columns /// are copied. - columns: Vec, + columns: Vec>, }, Query(Box), } @@ -6186,7 +6274,7 @@ pub enum OnCommit { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum CopyOption { /// FORMAT format_name - Format(Ident), + Format(WithSpan), /// FREEZE \[ boolean \] Freeze(bool), /// DELIMITER 'delimiter_character' @@ -6200,11 +6288,11 @@ pub enum CopyOption { /// ESCAPE 'escape_character' Escape(char), /// FORCE_QUOTE { ( column_name [, ...] ) | * } - ForceQuote(Vec), + ForceQuote(Vec>), /// FORCE_NOT_NULL ( column_name [, ...] ) - ForceNotNull(Vec), + ForceNotNull(Vec>), /// FORCE_NULL ( column_name [, ...] ) - ForceNull(Vec), + ForceNull(Vec>), /// ENCODING 'encoding_name' Encoding(String), } @@ -6275,9 +6363,9 @@ pub enum CopyLegacyCsvOption { /// ESCAPE \[ AS \] 'escape_character' Escape(char), /// FORCE QUOTE { column_name [, ...] | * } - ForceQuote(Vec), + ForceQuote(Vec>), /// FORCE NOT NULL column_name [, ...] - ForceNotNull(Vec), + ForceNotNull(Vec>), } impl fmt::Display for CopyLegacyCsvOption { @@ -6391,7 +6479,7 @@ pub struct MergeInsertExpr { /// INSERT (product, quantity) VALUES(product, quantity) /// INSERT (product, quantity) ROW /// ``` - pub columns: Vec, + pub columns: Vec>, /// The insert type used by the statement. pub kind: MergeInsertKind, } @@ -6633,7 +6721,7 @@ impl fmt::Display for FunctionDesc { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct OperateFunctionArg { pub mode: Option, - pub name: Option, + pub name: Option>, pub data_type: DataType, pub default_expr: Option, } @@ -6653,7 +6741,7 @@ impl OperateFunctionArg { pub fn with_name(name: &str, data_type: DataType) -> Self { Self { mode: None, - name: Some(name.into()), + name: Some(Ident::new(name).empty_span()), data_type, default_expr: None, } @@ -6854,7 +6942,7 @@ impl fmt::Display for CreateFunctionUsing { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct MacroArg { - pub name: Ident, + pub name: WithSpan, pub default_expr: Option, } @@ -6862,7 +6950,7 @@ impl MacroArg { /// Returns an argument with name. pub fn new(name: &str) -> Self { Self { - name: name.into(), + name: Ident::new(name).empty_span(), default_expr: None, } } @@ -6906,9 +6994,9 @@ pub enum SchemaName { /// Only schema name specified: ``. Simple(ObjectName), /// Only authorization identifier specified: `AUTHORIZATION `. - UnnamedAuthorization(Ident), + UnnamedAuthorization(WithSpan), /// Both schema name and authorization identifier specified: ` AUTHORIZATION `. - NamedAuthorization(ObjectName, Ident), + NamedAuthorization(ObjectName, WithSpan), } impl fmt::Display for SchemaName { @@ -6969,8 +7057,8 @@ impl fmt::Display for SearchModifier { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct LockTable { - pub table: Ident, - pub alias: Option, + pub table: WithSpan, + pub alias: Option>, pub lock_type: LockTableType, } @@ -7025,7 +7113,7 @@ impl fmt::Display for LockTableType { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct HiveSetLocation { pub has_set: bool, - pub location: Ident, + pub location: WithSpan, } impl fmt::Display for HiveSetLocation { @@ -7044,7 +7132,7 @@ impl fmt::Display for HiveSetLocation { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum MySQLColumnPosition { First, - After(Ident), + After(WithSpan), } impl Display for MySQLColumnPosition { @@ -7067,7 +7155,7 @@ impl Display for MySQLColumnPosition { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct TableEngine { pub name: String, - pub parameters: Option>, + pub parameters: Option>>, } impl Display for TableEngine { @@ -7091,11 +7179,11 @@ impl Display for TableEngine { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct RowAccessPolicy { pub policy: ObjectName, - pub on: Vec, + pub on: Vec>, } impl RowAccessPolicy { - pub fn new(policy: ObjectName, on: Vec) -> Self { + pub fn new(policy: ObjectName, on: Vec>) -> Self { Self { policy, on } } } @@ -7118,12 +7206,12 @@ impl Display for RowAccessPolicy { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Tag { - pub key: Ident, + pub key: WithSpan, pub value: String, } impl Tag { - pub fn new(key: Ident, value: String) -> Self { + pub fn new(key: WithSpan, value: String) -> Self { Self { key, value } } } @@ -7226,7 +7314,7 @@ where #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct UtilityOption { - pub name: Ident, + pub name: WithSpan, pub arg: Option, } @@ -7244,6 +7332,10 @@ impl Display for UtilityOption { mod tests { use super::*; + fn ident>(value: T) -> WithSpan { + SpanWrapped::empty_span(Ident::new(value)) + } + #[test] fn test_window_frame_default() { let window_frame = WindowFrame::default(); @@ -7254,84 +7346,72 @@ mod tests { fn test_grouping_sets_display() { // a and b in different group let grouping_sets = Expr::GroupingSets(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![Expr::Identifier(Ident::new("b"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b"))], ]); assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}")); // a and b in the same group let grouping_sets = Expr::GroupingSets(vec![vec![ - Expr::Identifier(Ident::new("a")), - Expr::Identifier(Ident::new("b")), + Expr::Identifier(ident("a")), + Expr::Identifier(ident("b")), ]]); assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}")); // (a, b) and (c, d) in different group let grouping_sets = Expr::GroupingSets(vec![ - vec![ - Expr::Identifier(Ident::new("a")), - Expr::Identifier(Ident::new("b")), - ], - vec![ - Expr::Identifier(Ident::new("c")), - Expr::Identifier(Ident::new("d")), - ], + vec![Expr::Identifier(ident("a")), Expr::Identifier(ident("b"))], + vec![Expr::Identifier(ident("c")), Expr::Identifier(ident("d"))], ]); assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}")); } #[test] fn test_rollup_display() { - let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]); + let rollup = Expr::Rollup(vec![vec![Expr::Identifier(ident("a"))]]); assert_eq!("ROLLUP (a)", format!("{rollup}")); let rollup = Expr::Rollup(vec![vec![ - Expr::Identifier(Ident::new("a")), - Expr::Identifier(Ident::new("b")), + Expr::Identifier(ident("a")), + Expr::Identifier(ident("b")), ]]); assert_eq!("ROLLUP ((a, b))", format!("{rollup}")); let rollup = Expr::Rollup(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![Expr::Identifier(Ident::new("b"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b"))], ]); assert_eq!("ROLLUP (a, b)", format!("{rollup}")); let rollup = Expr::Rollup(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![ - Expr::Identifier(Ident::new("b")), - Expr::Identifier(Ident::new("c")), - ], - vec![Expr::Identifier(Ident::new("d"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b")), Expr::Identifier(ident("c"))], + vec![Expr::Identifier(ident("d"))], ]); assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}")); } #[test] fn test_cube_display() { - let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]); + let cube = Expr::Cube(vec![vec![Expr::Identifier(ident("a"))]]); assert_eq!("CUBE (a)", format!("{cube}")); let cube = Expr::Cube(vec![vec![ - Expr::Identifier(Ident::new("a")), - Expr::Identifier(Ident::new("b")), + Expr::Identifier(ident("a")), + Expr::Identifier(ident("b")), ]]); assert_eq!("CUBE ((a, b))", format!("{cube}")); let cube = Expr::Cube(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![Expr::Identifier(Ident::new("b"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b"))], ]); assert_eq!("CUBE (a, b)", format!("{cube}")); let cube = Expr::Cube(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![ - Expr::Identifier(Ident::new("b")), - Expr::Identifier(Ident::new("c")), - ], - vec![Expr::Identifier(Ident::new("d"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b")), Expr::Identifier(ident("c"))], + vec![Expr::Identifier(ident("d"))], ]); assert_eq!("CUBE (a, (b, c), d)", format!("{cube}")); } diff --git a/src/ast/query.rs b/src/ast/query.rs index dc5966e5e..ce91ced4e 100644 --- a/src/ast/query.rs +++ b/src/ast/query.rs @@ -413,7 +413,7 @@ pub struct LateralView { /// LATERAL VIEW table name pub lateral_view_name: ObjectName, /// LATERAL VIEW optional column aliases - pub lateral_col_alias: Vec, + pub lateral_col_alias: Vec>, /// LATERAL VIEW OUTER pub outer: bool, } @@ -456,7 +456,7 @@ pub enum NamedWindowExpr { /// ``` /// /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls#ref_named_window - NamedWindow(Ident), + NamedWindow(WithSpan), /// A window expression. /// /// Example: @@ -483,7 +483,7 @@ impl fmt::Display for NamedWindowExpr { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] -pub struct NamedWindowDefinition(pub Ident, pub NamedWindowExpr); +pub struct NamedWindowDefinition(pub WithSpan, pub NamedWindowExpr); impl fmt::Display for NamedWindowDefinition { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -544,7 +544,7 @@ impl fmt::Display for CteAsMaterialized { pub struct Cte { pub alias: TableAlias, pub query: Box, - pub from: Option, + pub from: Option>, pub materialized: Option, } @@ -569,7 +569,7 @@ pub enum SelectItem { /// Any expression, not followed by `[ AS ] alias` UnnamedExpr(Expr), /// An expression, followed by `[ AS ] alias` - ExprWithAlias { expr: Expr, alias: Ident }, + ExprWithAlias { expr: Expr, alias: WithSpan }, /// `alias.*` or even `schema.table.*` QualifiedWildcard(ObjectName, WildcardAdditionalOptions), /// An unqualified `*` @@ -586,8 +586,8 @@ pub enum SelectItem { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct IdentWithAlias { - pub ident: Ident, - pub alias: Ident, + pub ident: WithSpan, + pub alias: WithSpan, } impl fmt::Display for IdentWithAlias { @@ -679,13 +679,13 @@ pub enum ExcludeSelectItem { /// ```plaintext /// /// ``` - Single(Ident), + Single(WithSpan), /// Multiple column names inside parenthesis. /// # Syntax /// ```plaintext /// (, , ...) /// ``` - Multiple(Vec), + Multiple(Vec>), } impl fmt::Display for ExcludeSelectItem { @@ -755,9 +755,9 @@ impl fmt::Display for RenameSelectItem { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ExceptSelectItem { /// First guaranteed column. - pub first_element: Ident, + pub first_element: WithSpan, /// Additional columns. This list can be empty. - pub additional_elements: Vec, + pub additional_elements: Vec>, } impl fmt::Display for ExceptSelectItem { @@ -808,7 +808,7 @@ impl fmt::Display for ReplaceSelectItem { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ReplaceSelectElement { pub expr: Expr, - pub column_name: Ident, + pub column_name: WithSpan, pub as_keyword: bool, } @@ -887,7 +887,7 @@ impl fmt::Display for ConnectBy { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Setting { - pub key: Ident, + pub key: WithSpan, pub value: Value, } @@ -908,7 +908,7 @@ impl fmt::Display for Setting { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ExprWithAlias { pub expr: Expr, - pub alias: Option, + pub alias: Option>, } impl fmt::Display for ExprWithAlias { @@ -963,7 +963,7 @@ pub enum TableFactor { /// [WITH ORDINALITY](https://www.postgresql.org/docs/current/functions-srf.html), supported by Postgres. with_ordinality: bool, /// [Partition selection](https://dev.mysql.com/doc/refman/8.0/en/partitioning-selection.html), supported by MySQL. - partitions: Vec, + partitions: Vec>, }, Derived { lateral: bool, @@ -996,7 +996,7 @@ pub enum TableFactor { alias: Option, array_exprs: Vec, with_offset: bool, - with_offset_alias: Option, + with_offset_alias: Option>, with_ordinality: bool, }, /// The `JSON_TABLE` table-valued function. @@ -1044,7 +1044,7 @@ pub enum TableFactor { Pivot { table: Box, aggregate_functions: Vec, // Function expression - value_column: Vec, + value_column: Vec>, value_source: PivotValueSource, default_on_null: Option, alias: Option, @@ -1059,9 +1059,9 @@ pub enum TableFactor { /// See . Unpivot { table: Box, - value: Ident, - name: Ident, - columns: Vec, + value: WithSpan, + name: WithSpan, + columns: Vec>, alias: Option, }, /// A `MATCH_RECOGNIZE` operation on a table. @@ -1130,7 +1130,7 @@ impl fmt::Display for PivotValueSource { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Measure { pub expr: Expr, - pub alias: Ident, + pub alias: WithSpan, } impl fmt::Display for Measure { @@ -1179,9 +1179,9 @@ pub enum AfterMatchSkip { /// `TO NEXT ROW` ToNextRow, /// `TO FIRST ` - ToFirst(Ident), + ToFirst(WithSpan), /// `TO LAST ` - ToLast(Ident), + ToLast(WithSpan), } impl fmt::Display for AfterMatchSkip { @@ -1225,7 +1225,7 @@ impl fmt::Display for EmptyMatchesMode { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct SymbolDefinition { - pub symbol: Ident, + pub symbol: WithSpan, pub definition: Expr, } @@ -1241,7 +1241,7 @@ impl fmt::Display for SymbolDefinition { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum MatchRecognizeSymbol { /// A named symbol, e.g. `S1`. - Named(Ident), + Named(WithSpan), /// A virtual symbol representing the start of the of partition (`^`). Start, /// A virtual symbol representing the end of the partition (`$`). @@ -1546,8 +1546,8 @@ impl fmt::Display for TableFactor { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct TableAlias { - pub name: Ident, - pub columns: Vec, + pub name: WithSpan, + pub columns: Vec>, } impl fmt::Display for TableAlias { @@ -1723,7 +1723,7 @@ pub enum JoinOperator { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum JoinConstraint { On(Expr), - Using(Vec), + Using(Vec>), Natural, None, } @@ -1828,7 +1828,7 @@ impl fmt::Display for WithFill { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct InterpolateExpr { - pub column: Ident, + pub column: WithSpan, pub expr: Option, } @@ -2140,7 +2140,7 @@ impl fmt::Display for GroupByExpr { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FormatClause { - Identifier(Ident), + Identifier(WithSpan), Null, } @@ -2290,7 +2290,7 @@ impl fmt::Display for ForJson { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct JsonTableColumn { /// The name of the column to be extracted. - pub name: Ident, + pub name: WithSpan, /// The type of the column to be extracted. pub r#type: DataType, /// The path to the column to be extracted. Must be a literal string. diff --git a/src/ast/trigger.rs b/src/ast/trigger.rs index cf1c8c466..4a218644e 100644 --- a/src/ast/trigger.rs +++ b/src/ast/trigger.rs @@ -82,7 +82,7 @@ impl fmt::Display for TriggerReferencing { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum TriggerEvent { Insert, - Update(Vec), + Update(Vec>), Delete, Truncate, } diff --git a/src/ast/value.rs b/src/ast/value.rs index 30d956a07..d5124cacd 100644 --- a/src/ast/value.rs +++ b/src/ast/value.rs @@ -26,7 +26,7 @@ use bigdecimal::BigDecimal; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::ast::Ident; +use crate::ast::{Ident, WithSpan}; #[cfg(feature = "visitor")] use sqlparser_derive::{Visit, VisitMut}; @@ -163,7 +163,7 @@ pub enum DateTimeField { /// ``` /// /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/date_functions#extract) - Week(Option), + Week(Option>), Day, DayOfWeek, DayOfYear, @@ -203,7 +203,7 @@ pub enum DateTimeField { /// EXTRACT(q FROM CURRENT_TIMESTAMP) /// ``` /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions-date-time#supported-date-and-time-parts) - Custom(Ident), + Custom(WithSpan), } impl fmt::Display for DateTimeField { diff --git a/src/dialect/postgresql.rs b/src/dialect/postgresql.rs index 51dc49849..72b5c8459 100644 --- a/src/dialect/postgresql.rs +++ b/src/dialect/postgresql.rs @@ -230,14 +230,16 @@ pub fn parse_comment(parser: &mut Parser) -> Result { } pub fn parse_create(parser: &mut Parser) -> Option> { - let name = parser.maybe_parse(|parser| -> Result { - parser.expect_keyword(Keyword::CREATE)?; - parser.expect_keyword(Keyword::TYPE)?; - let name = parser.parse_object_name(false)?; - parser.expect_keyword(Keyword::AS)?; - parser.expect_keyword(Keyword::ENUM)?; - Ok(name) - }); + let name = parser + .maybe_parse(|parser| -> Result { + parser.expect_keyword(Keyword::CREATE)?; + parser.expect_keyword(Keyword::TYPE)?; + let name = parser.parse_object_name(false)?; + parser.expect_keyword(Keyword::AS)?; + parser.expect_keyword(Keyword::ENUM)?; + Ok(name) + }) + .unwrap(); name.map(|name| parse_create_type_as_enum(parser, name)) } diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs index d9331d952..af534efff 100644 --- a/src/dialect/snowflake.rs +++ b/src/dialect/snowflake.rs @@ -25,7 +25,7 @@ use crate::ast::helpers::stmt_data_loading::{ use crate::ast::{ ColumnOption, ColumnPolicy, ColumnPolicyProperty, Ident, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, ObjectName, - RowAccessPolicy, Statement, TagsColumnOption, WrappedCollection, + RowAccessPolicy, SpanWrapped, Statement, TagsColumnOption, WithSpan, WrappedCollection, }; use crate::dialect::{Dialect, Precedence}; use crate::keywords::Keyword; @@ -445,7 +445,7 @@ pub fn parse_create_stage( }) } -pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result { +pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result, ParserError> { let mut ident = String::new(); while let Some(next_token) = parser.next_token_no_skip() { match &next_token.token { @@ -466,7 +466,7 @@ pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result return parser.expected("stage name identifier", parser.peek_token()), } } - Ok(Ident::new(ident)) + Ok(Ident::new(ident).empty_span()) } pub fn parse_snowflake_stage_name(parser: &mut Parser) -> Result { @@ -493,7 +493,7 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result { let into: ObjectName = parse_snowflake_stage_name(parser)?; let mut files: Vec = vec![]; let mut from_transformations: Option> = None; - let from_stage_alias; + let from_stage_alias: Option>; let from_stage: ObjectName; let stage_params: StageParamsObject; @@ -511,8 +511,9 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result { // as from_stage_alias = if parser.parse_keyword(Keyword::AS) { - Some(match parser.next_token().token { - Token::Word(w) => Ok(Ident::new(w.value)), + let next = parser.next_token(); + Some(match next.token { + Token::Word(w) => Ok(Ident::new(w.value).spanning(next.span)), _ => parser.expected("stage alias", parser.peek_token()), }?) } else { @@ -527,8 +528,9 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result { // as from_stage_alias = if parser.parse_keyword(Keyword::AS) { - Some(match parser.next_token().token { - Token::Word(w) => Ok(Ident::new(w.value)), + let next = parser.next_token(); + Some(match next.token { + Token::Word(w) => Ok(Ident::new(w.value).spanning(next.span)), _ => parser.expected("stage alias", parser.peek_token()), }?) } else { @@ -614,10 +616,10 @@ fn parse_select_items_for_data_load( // [.]$[.] [ , [.]$[.] ... ] let mut select_items: Vec = vec![]; loop { - let mut alias: Option = None; + let mut alias: Option> = None; let mut file_col_num: i32 = 0; - let mut element: Option = None; - let mut item_as: Option = None; + let mut element: Option> = None; + let mut item_as: Option> = None; let next_token = parser.next_token(); match next_token.token { @@ -628,7 +630,7 @@ fn parse_select_items_for_data_load( Ok(()) } Token::Word(w) => { - alias = Some(Ident::new(w.value)); + alias = Some(Ident::new(w.value).spanning(next_token.span)); Ok(()) } _ => parser.expected("alias or file_col_num", next_token), @@ -653,10 +655,14 @@ fn parse_select_items_for_data_load( match parser.next_token().token { Token::Colon => { // parse element - element = Some(Ident::new(match parser.next_token().token { - Token::Word(w) => Ok(w.value), - _ => parser.expected("file_col_num", parser.peek_token()), - }?)); + let next_token = parser.next_token(); + element = Some( + Ident::new(match next_token.token { + Token::Word(w) => Ok(w.value), + _ => parser.expected("file_col_num", parser.peek_token()), + }?) + .spanning(next_token.span), + ); } _ => { // element not present move back @@ -666,8 +672,9 @@ fn parse_select_items_for_data_load( // as if parser.parse_keyword(Keyword::AS) { - item_as = Some(match parser.next_token().token { - Token::Word(w) => Ok(Ident::new(w.value)), + let next_token = parser.next_token(); + item_as = Some(match next_token.token { + Token::Word(w) => Ok(Ident::new(w.value).spanning(next_token.span)), _ => parser.expected("column item alias", parser.peek_token()), }?); } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index a9a5b1df4..aac38f776 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -48,12 +48,12 @@ pub enum ParserError { } // avoid clippy type_complexity warnings -type ParsedAction = (Keyword, Option>); +type ParsedAction = (Keyword, Option>>); // Use `Parser::expected` instead, if possible macro_rules! parser_err { ($MSG:expr, $loc:expr) => { - Err(ParserError::ParserError(format!("{}{}", $MSG, $loc))) + Err(ParserError::ParserError(format!("{}{}", $MSG, $loc.start))) }; } @@ -371,7 +371,7 @@ impl<'a> Parser<'a> { .into_iter() .map(|token| TokenWithLocation { token, - location: Location { line: 0, column: 0 }, + span: Span::default(), }) .collect(); self.with_tokens_with_locations(tokens_with_locations) @@ -391,6 +391,20 @@ impl<'a> Parser<'a> { Ok(self.with_tokens_with_locations(tokens)) } + /// Tokenize the sql string and sets this [`Parser`]'s state to + /// parse the resulting tokens + /// + /// Returns an error if there was an error tokenizing the SQL string. + /// + /// See example on [`Parser::new()`] for an example + pub fn try_with_sql_no_locations(self, sql: &str) -> Result { + debug!("Parsing sql '{}'...", sql); + let tokens = Tokenizer::new(self.dialect, sql) + .with_unescape(self.options.unescape) + .tokenize()?; + Ok(self.with_tokens(tokens)) + } + /// Parse potentially multiple statements /// /// Example @@ -564,7 +578,7 @@ impl<'a> Parser<'a> { let mut export = false; if !dialect_of!(self is MySqlDialect | GenericDialect) { - return parser_err!("Unsupported statement FLUSH", self.peek_token().location); + return parser_err!("Unsupported statement FLUSH", self.peek_token().span); } let location = if self.parse_keyword(Keyword::NO_WRITE_TO_BINLOG) { @@ -864,19 +878,21 @@ impl<'a> Parser<'a> { match next_token.token { t @ (Token::Word(_) | Token::SingleQuotedString(_)) => { if self.peek_token().token == Token::Period { - let mut id_parts: Vec = vec![match t { - Token::Word(w) => w.to_ident(), - Token::SingleQuotedString(s) => Ident::with_quote('\'', s), + let mut id_parts: Vec> = vec![match t { + Token::Word(w) => w.to_ident().spanning(next_token.span), + Token::SingleQuotedString(s) => { + Ident::with_quote('\'', s).spanning(next_token.span) + } _ => unreachable!(), // We matched above }]; while self.consume_token(&Token::Period) { let next_token = self.next_token(); match next_token.token { - Token::Word(w) => id_parts.push(w.to_ident()), + Token::Word(w) => id_parts.push(w.to_ident().spanning(next_token.span)), Token::SingleQuotedString(s) => { // SQLite has single-quoted identifiers - id_parts.push(Ident::with_quote('\'', s)) + id_parts.push(Ident::with_quote('\'', s).spanning(next_token.span)) } Token::Mul => { return Ok(Expr::QualifiedWildcard(ObjectName(id_parts))); @@ -969,7 +985,7 @@ impl<'a> Parser<'a> { // Note also that naively `SELECT date` looks like a syntax error because the `date` type // name is not followed by a string literal, but in fact in PostgreSQL it is a valid // expression that should parse as the column name "date". - let loc = self.peek_token().location; + let loc = self.peek_token().span; let opt_expr = self.maybe_parse(|parser| { match parser.parse_data_type()? { DataType::Interval => parser.parse_interval(), @@ -1006,7 +1022,7 @@ impl<'a> Parser<'a> { if dialect_of!(self is PostgreSqlDialect | GenericDialect) => { Ok(Expr::Function(Function { - name: ObjectName(vec![w.to_ident()]), + name: ObjectName(vec![w.to_ident().spanning(next_token.span)]), parameters: FunctionArguments::None, args: FunctionArguments::None, null_treatment: None, @@ -1020,7 +1036,7 @@ impl<'a> Parser<'a> { | Keyword::CURRENT_DATE | Keyword::LOCALTIME | Keyword::LOCALTIMESTAMP => { - self.parse_time_functions(ObjectName(vec![w.to_ident()])) + self.parse_time_functions(ObjectName(vec![w.to_ident().spanning(next_token.span)])) } Keyword::CASE => self.parse_case_expr(), Keyword::CONVERT => self.parse_convert_expr(false), @@ -1045,7 +1061,7 @@ impl<'a> Parser<'a> { Keyword::CEIL => self.parse_ceil_floor_expr(true), Keyword::FLOOR => self.parse_ceil_floor_expr(false), Keyword::POSITION if self.peek_token().token == Token::LParen => { - self.parse_position_expr(w.to_ident()) + self.parse_position_expr(w.to_ident().spanning(next_token.span)) } Keyword::SUBSTRING => self.parse_substring_expr(), Keyword::OVERLAY => self.parse_overlay_expr(), @@ -1064,7 +1080,7 @@ impl<'a> Parser<'a> { let query = self.parse_query()?; self.expect_token(&Token::RParen)?; Ok(Expr::Function(Function { - name: ObjectName(vec![w.to_ident()]), + name: ObjectName(vec![w.to_ident().spanning(next_token.span)]), parameters: FunctionArguments::None, args: FunctionArguments::Subquery(query), filter: None, @@ -1090,74 +1106,77 @@ impl<'a> Parser<'a> { } // Here `w` is a word, check if it's a part of a multipart // identifier, a function call, or a simple identifier: - _ => match self.peek_token().token { - Token::LParen | Token::Period => { - let mut id_parts: Vec = vec![w.to_ident()]; - let mut ends_with_wildcard = false; - while self.consume_token(&Token::Period) { - let next_token = self.next_token(); - match next_token.token { - Token::Word(w) => id_parts.push(w.to_ident()), - Token::Mul => { - // Postgres explicitly allows funcnm(tablenm.*) and the - // function array_agg traverses this control flow - if dialect_of!(self is PostgreSqlDialect) { - ends_with_wildcard = true; - break; - } else { + _ => { + let peek = self.peek_token(); + match peek.token { + Token::LParen | Token::Period => { + let mut id_parts: Vec> = vec![w.to_ident().spanning(peek.span)]; + let mut ends_with_wildcard = false; + while self.consume_token(&Token::Period) { + let next_token = self.next_token(); + match next_token.token { + Token::Word(w) => id_parts.push(w.to_ident().spanning(next_token.span)), + Token::Mul => { + // Postgres explicitly allows funcnm(tablenm.*) and the + // function array_agg traverses this control flow + if dialect_of!(self is PostgreSqlDialect) { + ends_with_wildcard = true; + break; + } else { + return self + .expected("an identifier after '.'", next_token); + } + } + Token::SingleQuotedString(s) => { + id_parts.push(Ident::with_quote('\'', s).spanning(next_token.span)); + } + _ => { return self - .expected("an identifier after '.'", next_token); + .expected("an identifier or a '*' after '.'", next_token); } } - Token::SingleQuotedString(s) => { - id_parts.push(Ident::with_quote('\'', s)) - } - _ => { - return self - .expected("an identifier or a '*' after '.'", next_token); - } } - } - if ends_with_wildcard { - Ok(Expr::QualifiedWildcard(ObjectName(id_parts))) - } else if self.consume_token(&Token::LParen) { - if dialect_of!(self is SnowflakeDialect | MsSqlDialect) - && self.consume_tokens(&[Token::Plus, Token::RParen]) - { - Ok(Expr::OuterJoin(Box::new( - match <[Ident; 1]>::try_from(id_parts) { - Ok([ident]) => Expr::Identifier(ident), - Err(parts) => Expr::CompoundIdentifier(parts), - }, - ))) + if ends_with_wildcard { + Ok(Expr::QualifiedWildcard(ObjectName(id_parts))) + } else if self.consume_token(&Token::LParen) { + if dialect_of!(self is SnowflakeDialect | MsSqlDialect) + && self.consume_tokens(&[Token::Plus, Token::RParen]) + { + Ok(Expr::OuterJoin(Box::new( + match <[WithSpan; 1]>::try_from(id_parts) { + Ok([ident]) => Expr::Identifier(ident), + Err(parts) => Expr::CompoundIdentifier(parts), + }, + ))) + } else { + self.prev_token(); + self.parse_function(ObjectName(id_parts)) + } } else { - self.prev_token(); - self.parse_function(ObjectName(id_parts)) + Ok(Expr::CompoundIdentifier(id_parts)) } - } else { - Ok(Expr::CompoundIdentifier(id_parts)) } - } - // string introducer https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html - Token::SingleQuotedString(_) - | Token::DoubleQuotedString(_) - | Token::HexStringLiteral(_) + // string introducer https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html + Token::SingleQuotedString(_) + | Token::DoubleQuotedString(_) + | Token::HexStringLiteral(_) if w.value.starts_with('_') => - { - Ok(Expr::IntroducedString { - introducer: w.value, - value: self.parse_introduced_string_value()?, - }) - } - Token::Arrow if self.dialect.supports_lambda_functions() => { - self.expect_token(&Token::Arrow)?; - return Ok(Expr::Lambda(LambdaFunction { - params: OneOrManyWithParens::One(w.to_ident()), - body: Box::new(self.parse_expr()?), - })); + { + Ok(Expr::IntroducedString { + introducer: w.value, + value: self.parse_introduced_string_value()?, + }) + } + Token::Arrow if self.dialect.supports_lambda_functions() => { + self.expect_token(&Token::Arrow)?; + return Ok(Expr::Lambda(LambdaFunction { + params: OneOrManyWithParens::One(w.to_ident().spanning(next_token.span)), + body: Box::new(self.parse_expr()?), + })); + } + _ => Ok(Expr::Identifier(w.to_ident().spanning(next_token.span))), } - _ => Ok(Expr::Identifier(w.to_ident())), }, }, // End of Token::Word // array `[1, 2, 3]` @@ -1244,11 +1263,11 @@ impl<'a> Parser<'a> { } else { let tok = self.next_token(); let key = match tok.token { - Token::Word(word) => word.to_ident(), + Token::Word(word) => word.to_ident().spanning(tok.span), _ => { return parser_err!( format!("Expected identifier, found: {tok}"), - tok.location + tok.span ) } }; @@ -1762,7 +1781,7 @@ impl<'a> Parser<'a> { } } - pub fn parse_position_expr(&mut self, ident: Ident) -> Result { + pub fn parse_position_expr(&mut self, ident: WithSpan) -> Result { let between_prec = self.dialect.prec_value(Precedence::Between); let position_expr = self.maybe_parse(|p| { // PARSE SELECT POSITION('@' in field) @@ -2120,7 +2139,7 @@ impl<'a> Parser<'a> { } else if self.dialect.require_interval_qualifier() { return parser_err!( "INTERVAL requires a unit after the literal value", - self.peek_token().location + self.peek_token().span ); } else { None @@ -2211,7 +2230,7 @@ impl<'a> Parser<'a> { let (fields, trailing_bracket) = self.parse_struct_type_def(Self::parse_struct_field_def)?; if trailing_bracket.0 { - return parser_err!("unmatched > in STRUCT literal", self.peek_token().location); + return parser_err!("unmatched > in STRUCT literal", self.peek_token().span); } self.expect_token(&Token::LParen)?; @@ -2241,7 +2260,7 @@ impl<'a> Parser<'a> { if typed_syntax { return parser_err!("Typed syntax does not allow AS", { self.prev_token(); - self.peek_token().location + self.peek_token().span }); } let field_name = self.parse_identifier(false)?; @@ -2294,7 +2313,7 @@ impl<'a> Parser<'a> { // we've matched all field types for the current struct. // e.g. this is invalid syntax `STRUCT>>, INT>(NULL)` if trailing_bracket.0 { - return parser_err!("unmatched > in STRUCT definition", start_token.location); + return parser_err!("unmatched > in STRUCT definition", start_token.span); } }; @@ -2663,7 +2682,7 @@ impl<'a> Parser<'a> { format!( "Expected one of [=, >, <, =>, =<, !=] as comparison operator, found: {op}" ), - tok.location + tok.span ); }; @@ -2789,7 +2808,7 @@ impl<'a> Parser<'a> { // Can only happen if `get_next_precedence` got out of sync with this function _ => parser_err!( format!("No infix parser for token {:?}", tok.token), - tok.location + tok.span ), } } else if Token::DoubleColon == tok { @@ -2821,7 +2840,7 @@ impl<'a> Parser<'a> { // Can only happen if `get_next_precedence` got out of sync with this function parser_err!( format!("No infix parser for token {:?}", tok.token), - tok.location + tok.span ) } } @@ -3124,14 +3143,14 @@ impl<'a> Parser<'a> { index += 1; if let Some(TokenWithLocation { token: Token::Whitespace(_), - location: _, + span: _, }) = token { continue; } break token.cloned().unwrap_or(TokenWithLocation { token: Token::EOF, - location: Location { line: 0, column: 0 }, + span: Span::default(), }); }) } @@ -3144,13 +3163,13 @@ impl<'a> Parser<'a> { match self.tokens.get(index - 1) { Some(TokenWithLocation { token: Token::Whitespace(_), - location: _, + span: _, }) => continue, non_whitespace => { if n == 0 { return non_whitespace.cloned().unwrap_or(TokenWithLocation { token: Token::EOF, - location: Location { line: 0, column: 0 }, + span: Span::default(), }); } n -= 1; @@ -3172,7 +3191,7 @@ impl<'a> Parser<'a> { .cloned() .unwrap_or(TokenWithLocation { token: Token::EOF, - location: Location { line: 0, column: 0 }, + span: Span::default(), }) } @@ -3185,7 +3204,7 @@ impl<'a> Parser<'a> { match self.tokens.get(self.index - 1) { Some(TokenWithLocation { token: Token::Whitespace(_), - location: _, + span: _, }) => continue, token => { return token @@ -3211,7 +3230,7 @@ impl<'a> Parser<'a> { self.index -= 1; if let Some(TokenWithLocation { token: Token::Whitespace(_), - location: _, + span: _, }) = self.tokens.get(self.index) { continue; @@ -3222,10 +3241,7 @@ impl<'a> Parser<'a> { /// Report `found` was encountered instead of `expected` pub fn expected(&self, expected: &str, found: TokenWithLocation) -> Result { - parser_err!( - format!("Expected: {expected}, found: {found}"), - found.location - ) + parser_err!(format!("Expected: {expected}, found: {found}"), found.span) } /// If the current token is the `expected` keyword, consume it and returns @@ -3370,14 +3386,15 @@ impl<'a> Parser<'a> { } } - fn parse(s: String, loc: Location) -> Result + fn parse(s: String, span: Span) -> Result where ::Err: Display, { s.parse::().map_err(|e| { ParserError::ParserError(format!( - "Could not parse '{s}' as {}: {e}{loc}", - core::any::type_name::() + "Could not parse '{s}' as {}: {e}{}", + core::any::type_name::(), + span.start )) }) } @@ -3532,7 +3549,7 @@ impl<'a> Parser<'a> { /// Parse either `ALL`, `DISTINCT` or `DISTINCT ON (...)`. Returns [`None`] if `ALL` is parsed /// and results in a [`ParserError`] if both `ALL` and `DISTINCT` are found. pub fn parse_all_or_distinct(&mut self) -> Result, ParserError> { - let loc = self.peek_token().location; + let loc = self.peek_token().span; let all = self.parse_keyword(Keyword::ALL); let distinct = self.parse_keyword(Keyword::DISTINCT); if !distinct { @@ -3925,7 +3942,7 @@ impl<'a> Parser<'a> { #[derive(Default)] struct Body { - language: Option, + language: Option>, behavior: Option, function_body: Option, called_on_null: Option, @@ -4608,14 +4625,14 @@ impl<'a> Parser<'a> { let mut admin = vec![]; while let Some(keyword) = self.parse_one_of_keywords(&optional_keywords) { - let loc = self + let span = self .tokens .get(self.index - 1) - .map_or(Location { line: 0, column: 0 }, |t| t.location); + .map_or(Span::default(), |t| t.span); match keyword { Keyword::AUTHORIZATION => { if authorization_owner.is_some() { - parser_err!("Found multiple AUTHORIZATION", loc) + parser_err!("Found multiple AUTHORIZATION", span) } else { authorization_owner = Some(self.parse_object_name(false)?); Ok(()) @@ -4623,7 +4640,7 @@ impl<'a> Parser<'a> { } Keyword::LOGIN | Keyword::NOLOGIN => { if login.is_some() { - parser_err!("Found multiple LOGIN or NOLOGIN", loc) + parser_err!("Found multiple LOGIN or NOLOGIN", span) } else { login = Some(keyword == Keyword::LOGIN); Ok(()) @@ -4631,7 +4648,7 @@ impl<'a> Parser<'a> { } Keyword::INHERIT | Keyword::NOINHERIT => { if inherit.is_some() { - parser_err!("Found multiple INHERIT or NOINHERIT", loc) + parser_err!("Found multiple INHERIT or NOINHERIT", span) } else { inherit = Some(keyword == Keyword::INHERIT); Ok(()) @@ -4639,7 +4656,7 @@ impl<'a> Parser<'a> { } Keyword::BYPASSRLS | Keyword::NOBYPASSRLS => { if bypassrls.is_some() { - parser_err!("Found multiple BYPASSRLS or NOBYPASSRLS", loc) + parser_err!("Found multiple BYPASSRLS or NOBYPASSRLS", span) } else { bypassrls = Some(keyword == Keyword::BYPASSRLS); Ok(()) @@ -4647,7 +4664,7 @@ impl<'a> Parser<'a> { } Keyword::CREATEDB | Keyword::NOCREATEDB => { if create_db.is_some() { - parser_err!("Found multiple CREATEDB or NOCREATEDB", loc) + parser_err!("Found multiple CREATEDB or NOCREATEDB", span) } else { create_db = Some(keyword == Keyword::CREATEDB); Ok(()) @@ -4655,7 +4672,7 @@ impl<'a> Parser<'a> { } Keyword::CREATEROLE | Keyword::NOCREATEROLE => { if create_role.is_some() { - parser_err!("Found multiple CREATEROLE or NOCREATEROLE", loc) + parser_err!("Found multiple CREATEROLE or NOCREATEROLE", span) } else { create_role = Some(keyword == Keyword::CREATEROLE); Ok(()) @@ -4663,7 +4680,7 @@ impl<'a> Parser<'a> { } Keyword::SUPERUSER | Keyword::NOSUPERUSER => { if superuser.is_some() { - parser_err!("Found multiple SUPERUSER or NOSUPERUSER", loc) + parser_err!("Found multiple SUPERUSER or NOSUPERUSER", span) } else { superuser = Some(keyword == Keyword::SUPERUSER); Ok(()) @@ -4671,7 +4688,7 @@ impl<'a> Parser<'a> { } Keyword::REPLICATION | Keyword::NOREPLICATION => { if replication.is_some() { - parser_err!("Found multiple REPLICATION or NOREPLICATION", loc) + parser_err!("Found multiple REPLICATION or NOREPLICATION", span) } else { replication = Some(keyword == Keyword::REPLICATION); Ok(()) @@ -4679,7 +4696,7 @@ impl<'a> Parser<'a> { } Keyword::PASSWORD => { if password.is_some() { - parser_err!("Found multiple PASSWORD", loc) + parser_err!("Found multiple PASSWORD", span) } else { password = if self.parse_keyword(Keyword::NULL) { Some(Password::NullPassword) @@ -4692,7 +4709,7 @@ impl<'a> Parser<'a> { Keyword::CONNECTION => { self.expect_keyword(Keyword::LIMIT)?; if connection_limit.is_some() { - parser_err!("Found multiple CONNECTION LIMIT", loc) + parser_err!("Found multiple CONNECTION LIMIT", span) } else { connection_limit = Some(Expr::Value(self.parse_number_value()?)); Ok(()) @@ -4701,7 +4718,7 @@ impl<'a> Parser<'a> { Keyword::VALID => { self.expect_keyword(Keyword::UNTIL)?; if valid_until.is_some() { - parser_err!("Found multiple VALID UNTIL", loc) + parser_err!("Found multiple VALID UNTIL", span) } else { valid_until = Some(Expr::Value(self.parse_value()?)); Ok(()) @@ -4710,14 +4727,14 @@ impl<'a> Parser<'a> { Keyword::IN => { if self.parse_keyword(Keyword::ROLE) { if !in_role.is_empty() { - parser_err!("Found multiple IN ROLE", loc) + parser_err!("Found multiple IN ROLE", span) } else { in_role = self.parse_comma_separated(|p| p.parse_identifier(false))?; Ok(()) } } else if self.parse_keyword(Keyword::GROUP) { if !in_group.is_empty() { - parser_err!("Found multiple IN GROUP", loc) + parser_err!("Found multiple IN GROUP", span) } else { in_group = self.parse_comma_separated(|p| p.parse_identifier(false))?; Ok(()) @@ -4728,7 +4745,7 @@ impl<'a> Parser<'a> { } Keyword::ROLE => { if !role.is_empty() { - parser_err!("Found multiple ROLE", loc) + parser_err!("Found multiple ROLE", span) } else { role = self.parse_comma_separated(|p| p.parse_identifier(false))?; Ok(()) @@ -4736,7 +4753,7 @@ impl<'a> Parser<'a> { } Keyword::USER => { if !user.is_empty() { - parser_err!("Found multiple USER", loc) + parser_err!("Found multiple USER", span) } else { user = self.parse_comma_separated(|p| p.parse_identifier(false))?; Ok(()) @@ -4744,7 +4761,7 @@ impl<'a> Parser<'a> { } Keyword::ADMIN => { if !admin.is_empty() { - parser_err!("Found multiple ADMIN", loc) + parser_err!("Found multiple ADMIN", span) } else { admin = self.parse_comma_separated(|p| p.parse_identifier(false))?; Ok(()) @@ -4921,7 +4938,7 @@ impl<'a> Parser<'a> { let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); let names = self.parse_comma_separated(|p| p.parse_object_name(false))?; - let loc = self.peek_token().location; + let loc = self.peek_token().span; let cascade = self.parse_keyword(Keyword::CASCADE); let restrict = self.parse_keyword(Keyword::RESTRICT); let purge = self.parse_keyword(Keyword::PURGE); @@ -5725,7 +5742,7 @@ impl<'a> Parser<'a> { } } - fn parse_optional_on_cluster(&mut self) -> Result, ParserError> { + fn parse_optional_on_cluster(&mut self) -> Result>, ParserError> { if self.parse_keywords(&[Keyword::ON, Keyword::CLUSTER]) { Ok(Some(self.parse_identifier(false)?)) } else { @@ -5806,7 +5823,7 @@ impl<'a> Parser<'a> { let _ = self.consume_token(&Token::Eq); let next_token = self.next_token(); match next_token.token { - Token::Number(s, _) => Some(Self::parse::(s, next_token.location)?), + Token::Number(s, _) => Some(Self::parse::(s, next_token.span)?), _ => self.expected("literal int", next_token)?, } } else { @@ -6590,7 +6607,7 @@ impl<'a> Parser<'a> { "FULLTEXT or SPATIAL option without constraint name", TokenWithLocation { token: Token::make_keyword(&name.to_string()), - location: next_token.location, + span: next_token.span, }, ); } @@ -6681,7 +6698,7 @@ impl<'a> Parser<'a> { /// Parse `[ident]`, mostly `ident` is name, like: /// `window_name`, `index_name`, ... - pub fn parse_optional_indent(&mut self) -> Result, ParserError> { + pub fn parse_optional_indent(&mut self) -> Result>, ParserError> { self.maybe_parse(|parser| parser.parse_identifier(false)) } @@ -7299,7 +7316,7 @@ impl<'a> Parser<'a> { Expr::Function(f) => Ok(Statement::Call(f)), other => parser_err!( format!("Expected a simple procedure call but found: {other}"), - self.peek_token().location + self.peek_token().span ), } } else { @@ -7503,7 +7520,7 @@ impl<'a> Parser<'a> { let loc = self .tokens .get(self.index - 1) - .map_or(Location { line: 0, column: 0 }, |t| t.location); + .map_or(Span::default(), |t| t.span); return parser_err!(format!("Expect a char, found {s:?}"), loc); } Ok(s.chars().next().unwrap()) @@ -7549,7 +7566,7 @@ impl<'a> Parser<'a> { /// Parse a literal value (numbers, strings, date/time, booleans) pub fn parse_value(&mut self) -> Result { let next_token = self.next_token(); - let location = next_token.location; + let span = next_token.span; match next_token.token { Token::Word(w) => match w.keyword { Keyword::TRUE => Ok(Value::Boolean(true)), @@ -7562,7 +7579,7 @@ impl<'a> Parser<'a> { "A value?", TokenWithLocation { token: Token::Word(w), - location, + span, }, )?, }, @@ -7570,14 +7587,14 @@ impl<'a> Parser<'a> { "a concrete value", TokenWithLocation { token: Token::Word(w), - location, + span, }, ), }, // The call to n.parse() returns a bigdecimal when the // bigdecimal feature is enabled, and is otherwise a no-op // (i.e., it returns the input string). - Token::Number(n, l) => Ok(Value::Number(Self::parse(n, location)?, l)), + Token::Number(n, l) => Ok(Value::Number(Self::parse(n, span)?, l)), Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())), Token::DoubleQuotedString(ref s) => Ok(Value::DoubleQuotedString(s.to_string())), Token::TripleSingleQuotedString(ref s) => { @@ -7632,7 +7649,7 @@ impl<'a> Parser<'a> { "a value", TokenWithLocation { token: unexpected, - location, + span, }, ), } @@ -7672,7 +7689,7 @@ impl<'a> Parser<'a> { fn parse_introduced_string_value(&mut self) -> Result { let next_token = self.next_token(); - let location = next_token.location; + let span = next_token.span; match next_token.token { Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())), Token::DoubleQuotedString(ref s) => Ok(Value::DoubleQuotedString(s.to_string())), @@ -7681,7 +7698,7 @@ impl<'a> Parser<'a> { "a string value", TokenWithLocation { token: unexpected, - location, + span, }, ), } @@ -7691,7 +7708,7 @@ impl<'a> Parser<'a> { pub fn parse_literal_uint(&mut self) -> Result { let next_token = self.next_token(); match next_token.token { - Token::Number(s, _) => Self::parse::(s, next_token.location), + Token::Number(s, _) => Self::parse::(s, next_token.span), _ => self.expected("literal int", next_token), } } @@ -7737,7 +7754,7 @@ impl<'a> Parser<'a> { if trailing_bracket.0 { return parser_err!( format!("unmatched > after parsing data type {ty}"), - self.peek_token() + self.peek_token().span ); } @@ -8080,7 +8097,7 @@ impl<'a> Parser<'a> { pub fn parse_optional_alias( &mut self, reserved_kwds: &[Keyword], - ) -> Result, ParserError> { + ) -> Result>, ParserError> { let after_as = self.parse_keyword(Keyword::AS); let next_token = self.next_token(); match next_token.token { @@ -8090,7 +8107,7 @@ impl<'a> Parser<'a> { // (For example, in `FROM t1 JOIN` the `JOIN` will always be parsed as a keyword, // not an alias.) Token::Word(w) if after_as || !reserved_kwds.contains(&w.keyword) => { - Ok(Some(w.to_ident())) + Ok(Some(w.to_ident().spanning(next_token.span))) } // MSSQL supports single-quoted strings as aliases for columns // We accept them as table aliases too, although MSSQL does not. @@ -8104,9 +8121,13 @@ impl<'a> Parser<'a> { // character. When it sees such a , your DBMS will // ignore the and treat the multiple strings as // a single ." - Token::SingleQuotedString(s) => Ok(Some(Ident::with_quote('\'', s))), + Token::SingleQuotedString(s) => { + Ok(Some(Ident::with_quote('\'', s).spanning(next_token.span))) + } // Support for MySql dialect double-quoted string, `AS "HOUR"` for example - Token::DoubleQuotedString(s) => Ok(Some(Ident::with_quote('\"', s))), + Token::DoubleQuotedString(s) => { + Ok(Some(Ident::with_quote('\"', s).spanning(next_token.span))) + } _ => { if after_as { return self.expected("an identifier after AS", next_token); @@ -8160,7 +8181,7 @@ impl<'a> Parser<'a> { _ => { return parser_err!( "BUG: expected to match GroupBy modifier keyword", - self.peek_token().location + self.peek_token().span ) } }); @@ -8220,9 +8241,12 @@ impl<'a> Parser<'a> { ident .value .split('.') - .map(|value| Ident { - value: value.into(), - quote_style: ident.quote_style, + .map(|value| { + Ident { + value: value.into(), + quote_style: ident.quote_style, + } + .empty_span() }) .collect::>() }) @@ -8233,12 +8257,13 @@ impl<'a> Parser<'a> { } /// Parse identifiers - pub fn parse_identifiers(&mut self) -> Result, ParserError> { + pub fn parse_identifiers(&mut self) -> Result>, ParserError> { let mut idents = vec![]; loop { - match self.peek_token().token { + let peek = self.peek_token(); + match peek.token { Token::Word(w) => { - idents.push(w.to_ident()); + idents.push(w.to_ident().spanning(peek.span)); } Token::EOF | Token::Eq => break, _ => {} @@ -8339,7 +8364,10 @@ impl<'a> Parser<'a> { /// The `in_table_clause` parameter indicates whether the identifier is a table in a FROM, JOIN, or /// similar table clause. Currently, this is used only to support unquoted hyphenated identifiers in // this context on BigQuery. - pub fn parse_identifier(&mut self, in_table_clause: bool) -> Result { + pub fn parse_identifier( + &mut self, + in_table_clause: bool, + ) -> Result, ParserError> { let next_token = self.next_token(); match next_token.token { Token::Word(w) => { @@ -8392,10 +8420,14 @@ impl<'a> Parser<'a> { } } } - Ok(ident) + Ok(ident.spanning(next_token.span)) + } + Token::SingleQuotedString(s) => { + Ok(Ident::with_quote('\'', s).spanning(next_token.span)) + } + Token::DoubleQuotedString(s) => { + Ok(Ident::with_quote('\"', s).spanning(next_token.span)) } - Token::SingleQuotedString(s) => Ok(Ident::with_quote('\'', s)), - Token::DoubleQuotedString(s) => Ok(Ident::with_quote('\"', s)), _ => self.expected("identifier", next_token), } } @@ -8447,7 +8479,7 @@ impl<'a> Parser<'a> { &mut self, optional: IsOptional, allow_empty: bool, - ) -> Result, ParserError> { + ) -> Result>, ParserError> { if self.consume_token(&Token::LParen) { if allow_empty && self.peek_token().token == Token::RParen { self.next_token(); @@ -9456,7 +9488,7 @@ impl<'a> Parser<'a> { } let variables = if self.parse_keywords(&[Keyword::TIME, Keyword::ZONE]) { - OneOrManyWithParens::One(ObjectName(vec!["TIMEZONE".into()])) + OneOrManyWithParens::One(ObjectName(vec![Ident::new("TIMEZONE").empty_span()])) } else if self.dialect.supports_parenthesized_set_variables() && self.consume_token(&Token::LParen) { @@ -10094,7 +10126,7 @@ impl<'a> Parser<'a> { } else { let name = self.parse_object_name(true)?; - let partitions: Vec = if dialect_of!(self is MySqlDialect | GenericDialect) + let partitions: Vec> = if dialect_of!(self is MySqlDialect | GenericDialect) && self.parse_keyword(Keyword::PARTITION) { self.parse_parenthesized_identifiers()? @@ -10320,7 +10352,7 @@ impl<'a> Parser<'a> { return self.expected("literal number", next_token); }; self.expect_token(&Token::RBrace)?; - RepetitionQuantifier::AtMost(Self::parse(n, token.location)?) + RepetitionQuantifier::AtMost(Self::parse(n, token.span)?) } Token::Number(n, _) if self.consume_token(&Token::Comma) => { let next_token = self.next_token(); @@ -10328,12 +10360,12 @@ impl<'a> Parser<'a> { Token::Number(m, _) => { self.expect_token(&Token::RBrace)?; RepetitionQuantifier::Range( - Self::parse(n, token.location)?, - Self::parse(m, token.location)?, + Self::parse(n, token.span)?, + Self::parse(m, token.span)?, ) } Token::RBrace => { - RepetitionQuantifier::AtLeast(Self::parse(n, token.location)?) + RepetitionQuantifier::AtLeast(Self::parse(n, token.span)?) } _ => { return self.expected("} or upper bound", next_token); @@ -10342,7 +10374,7 @@ impl<'a> Parser<'a> { } Token::Number(n, _) => { self.expect_token(&Token::RBrace)?; - RepetitionQuantifier::Exactly(Self::parse(n, token.location)?) + RepetitionQuantifier::Exactly(Self::parse(n, token.span)?) } _ => return self.expected("quantifier range", token), } @@ -10460,11 +10492,14 @@ impl<'a> Parser<'a> { } fn parse_aliased_function_call(&mut self) -> Result { - let function_name = match self.next_token().token { + let next_token = self.next_token(); + let function_name = match next_token.token { Token::Word(w) => Ok(w.value), _ => self.expected("a function identifier", self.peek_token()), }?; - let expr = self.parse_function(ObjectName(vec![Ident::new(function_name)]))?; + let expr = self.parse_function(ObjectName(vec![ + Ident::new(function_name).spanning(next_token.span) + ]))?; let alias = if self.parse_keyword(Keyword::AS) { Some(self.parse_identifier(false)?) } else { @@ -10733,7 +10768,7 @@ impl<'a> Parser<'a> { .parse_keywords(&[Keyword::GRANTED, Keyword::BY]) .then(|| self.parse_identifier(false).unwrap()); - let loc = self.peek_token().location; + let loc = self.peek_token().span; let cascade = self.parse_keyword(Keyword::CASCADE); let restrict = self.parse_keyword(Keyword::RESTRICT); if cascade && restrict { @@ -10752,7 +10787,7 @@ impl<'a> Parser<'a> { /// Parse an REPLACE statement pub fn parse_replace(&mut self) -> Result { if !dialect_of!(self is MySqlDialect | GenericDialect) { - return parser_err!("Unsupported statement REPLACE", self.peek_token().location); + return parser_err!("Unsupported statement REPLACE", self.peek_token().span); } let mut insert = self.parse_insert()?; @@ -11161,7 +11196,7 @@ impl<'a> Parser<'a> { } fn parse_duplicate_treatment(&mut self) -> Result, ParserError> { - let loc = self.peek_token().location; + let loc = self.peek_token().span; match ( self.parse_keyword(Keyword::ALL), self.parse_keyword(Keyword::DISTINCT), @@ -11186,7 +11221,7 @@ impl<'a> Parser<'a> { Expr::Identifier(v) if v.value.to_lowercase() == "from" && v.quote_style.is_none() => { parser_err!( format!("Expected an expression, found: {}", v), - self.peek_token().location + self.peek_token().span ) } Expr::BinaryOp { @@ -11199,7 +11234,7 @@ impl<'a> Parser<'a> { let Expr::Identifier(alias) = *left else { return parser_err!( "BUG: expected identifier expression as alias", - self.peek_token().location + self.peek_token().span ); }; Ok(SelectItem::ExprWithAlias { @@ -11499,7 +11534,7 @@ impl<'a> Parser<'a> { } else { let next_token = self.next_token(); let quantity = match next_token.token { - Token::Number(s, _) => Self::parse::(s, next_token.location)?, + Token::Number(s, _) => Self::parse::(s, next_token.span)?, _ => self.expected("literal int", next_token)?, }; Some(TopQuantity::Constant(quantity)) @@ -11708,7 +11743,7 @@ impl<'a> Parser<'a> { } } - pub fn parse_rollback_savepoint(&mut self) -> Result, ParserError> { + pub fn parse_rollback_savepoint(&mut self) -> Result>, ParserError> { if self.parse_keyword(Keyword::TO) { let _ = self.parse_keyword(Keyword::SAVEPOINT); let savepoint = self.parse_identifier(false)?; @@ -12014,8 +12049,9 @@ impl<'a> Parser<'a> { let sequence_options = self.parse_create_sequence_options()?; // [ OWNED BY { table_name.column_name | NONE } ] let owned_by = if self.parse_keywords(&[Keyword::OWNED, Keyword::BY]) { + let peek = self.peek_token(); if self.parse_keywords(&[Keyword::NONE]) { - Some(ObjectName(vec![Ident::new("NONE")])) + Some(ObjectName(vec![Ident::new("NONE").spanning(peek.span)])) } else { Some(self.parse_object_name(false)?) } @@ -12186,7 +12222,7 @@ impl<'a> Parser<'a> { }) } - fn parse_parenthesized_identifiers(&mut self) -> Result, ParserError> { + fn parse_parenthesized_identifiers(&mut self) -> Result>, ParserError> { self.expect_token(&Token::LParen)?; let partitions = self.parse_comma_separated(|p| p.parse_identifier(false))?; self.expect_token(&Token::RParen)?; @@ -12310,7 +12346,8 @@ mod tests { #[cfg(test)] mod test_parse_data_type { use crate::ast::{ - CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, ObjectName, TimezoneInfo, + CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, Ident, ObjectName, + SpanWrapped, TimezoneInfo, }; use crate::dialect::{AnsiDialect, GenericDialect}; use crate::test_utils::TestedDialects; @@ -12493,14 +12530,17 @@ mod tests { test_parse_data_type!( dialect, "GEOMETRY", - DataType::Custom(ObjectName(vec!["GEOMETRY".into()]), vec![]) + DataType::Custom( + ObjectName(vec![Ident::new("GEOMETRY").empty_span()]), + vec![] + ) ); test_parse_data_type!( dialect, "GEOMETRY(POINT)", DataType::Custom( - ObjectName(vec!["GEOMETRY".into()]), + ObjectName(vec![Ident::new("GEOMETRY").empty_span()]), vec!["POINT".to_string()] ) ); @@ -12509,7 +12549,7 @@ mod tests { dialect, "GEOMETRY(POINT, 4326)", DataType::Custom( - ObjectName(vec!["GEOMETRY".into()]), + ObjectName(vec![Ident::new("GEOMETRY").empty_span()]), vec!["POINT".to_string(), "4326".to_string()] ) ); @@ -12645,8 +12685,8 @@ mod tests { }}; } - let dummy_name = ObjectName(vec![Ident::new("dummy_name")]); - let dummy_authorization = Ident::new("dummy_authorization"); + let dummy_name = ObjectName(vec![Ident::new("dummy_name").empty_span()]); + let dummy_authorization = Ident::new("dummy_authorization").empty_span(); test_parse_schema_name!( format!("{dummy_name}"), @@ -12687,7 +12727,7 @@ mod tests { display_as_key: false, name: None, index_type: None, - columns: vec![Ident::new("c1")], + columns: vec![Ident::new("c1").empty_span()], } ); @@ -12698,7 +12738,7 @@ mod tests { display_as_key: true, name: None, index_type: None, - columns: vec![Ident::new("c1")], + columns: vec![Ident::new("c1").empty_span()], } ); @@ -12707,9 +12747,9 @@ mod tests { "INDEX 'index' (c1, c2)", TableConstraint::Index { display_as_key: false, - name: Some(Ident::with_quote('\'', "index")), + name: Some(Ident::with_quote('\'', "index").empty_span()), index_type: None, - columns: vec![Ident::new("c1"), Ident::new("c2")], + columns: vec![Ident::new("c1").empty_span(), Ident::new("c2").empty_span()], } ); @@ -12720,7 +12760,7 @@ mod tests { display_as_key: false, name: None, index_type: Some(IndexType::BTree), - columns: vec![Ident::new("c1")], + columns: vec![Ident::new("c1").empty_span()], } ); @@ -12731,7 +12771,7 @@ mod tests { display_as_key: false, name: None, index_type: Some(IndexType::Hash), - columns: vec![Ident::new("c1")], + columns: vec![Ident::new("c1").empty_span()], } ); @@ -12740,9 +12780,9 @@ mod tests { "INDEX idx_name USING BTREE (c1)", TableConstraint::Index { display_as_key: false, - name: Some(Ident::new("idx_name")), + name: Some(Ident::new("idx_name").empty_span()), index_type: Some(IndexType::BTree), - columns: vec![Ident::new("c1")], + columns: vec![Ident::new("c1").empty_span()], } ); @@ -12751,9 +12791,9 @@ mod tests { "INDEX idx_name USING HASH (c1)", TableConstraint::Index { display_as_key: false, - name: Some(Ident::new("idx_name")), + name: Some(Ident::new("idx_name").empty_span()), index_type: Some(IndexType::Hash), - columns: vec![Ident::new("c1")], + columns: vec![Ident::new("c1").empty_span()], } ); } diff --git a/src/test_utils.rs b/src/test_utils.rs index b35fc45c2..6f0052490 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -113,7 +113,10 @@ impl TestedDialects { F: Fn(&mut Parser) -> T, { self.one_of_identical_results(|dialect| { - let mut parser = self.new_parser(dialect).try_with_sql(sql).unwrap(); + let mut parser = self + .new_parser(dialect) + .try_with_sql_no_locations(sql) + .unwrap(); f(&mut parser) }) } @@ -331,14 +334,14 @@ pub fn number(n: &str) -> Value { pub fn table_alias(name: impl Into) -> Option { Some(TableAlias { - name: Ident::new(name), + name: Ident::new(name).empty_span(), columns: vec![], }) } pub fn table(name: impl Into) -> TableFactor { TableFactor::Table { - name: ObjectName(vec![Ident::new(name.into())]), + name: ObjectName(vec![Ident::new(name.into()).empty_span()]), alias: None, args: None, with_hints: vec![], @@ -350,9 +353,9 @@ pub fn table(name: impl Into) -> TableFactor { pub fn table_with_alias(name: impl Into, alias: impl Into) -> TableFactor { TableFactor::Table { - name: ObjectName(vec![Ident::new(name)]), + name: ObjectName(vec![Ident::new(name).empty_span()]), alias: Some(TableAlias { - name: Ident::new(alias), + name: Ident::new(alias).empty_span(), columns: vec![], }), args: None, @@ -373,7 +376,7 @@ pub fn join(relation: TableFactor) -> Join { pub fn call(function: &str, args: impl IntoIterator) -> Expr { Expr::Function(Function { - name: ObjectName(vec![Ident::new(function)]), + name: ObjectName(vec![Ident::new(function).empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 4186ec824..42cb1264d 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -33,6 +33,8 @@ use core::fmt; use core::iter::Peekable; use core::num::NonZeroU8; use core::str::Chars; +use std::cmp::{max, min}; +use std::ops::Range; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -421,13 +423,32 @@ impl fmt::Display for Whitespace { } } +pub type LineNumber = u64; +pub type ColumnPosition = u64; +pub type LineColumn = (LineNumber, ColumnPosition); + /// Location in input string -#[derive(Debug, Eq, PartialEq, Clone, Copy)] +#[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Location { /// Line number, starting from 1 - pub line: u64, + pub line: LineNumber, /// Line column, starting from 1 - pub column: u64, + pub column: ColumnPosition, +} + +impl Location { + fn is_valid(&self) -> bool { + self.line > 0 && self.column > 0 + } + pub fn of(line: LineNumber, column: ColumnPosition) -> Self { + Self { line, column } + } + + pub fn span_to(self, end: Self) -> Span { + Span { start: self, end } + } } impl fmt::Display for Location { @@ -444,23 +465,114 @@ impl fmt::Display for Location { } } +impl Default for Location { + fn default() -> Self { + Self { line: 0, column: 0 } + } +} + +impl From for Location { + fn from(value: LineColumn) -> Self { + Location { + line: value.0, + column: value.1, + } + } +} + +impl From for Location { + fn from(value: u64) -> Self { + Location { + line: 1, + column: value, + } + } +} + +impl From for Location { + fn from(value: usize) -> Self { + Location { + line: 1, + column: value as u64, + } + } +} + +impl From for Location { + fn from(value: i32) -> Self { + Location { + line: 1, + column: value as u64, + } + } +} + +/// Location in input string +#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, Ord, PartialOrd, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub struct Span { + /// The span start location, inclusive. + pub start: Location, + /// The span end location, exclusive. + pub end: Location, +} + +impl Span { + pub fn new, U: Into>(start: T, end: U) -> Self { + Self { + start: start.into(), + end: end.into(), + } + } + + pub fn zero_width(start: Location) -> Self { + Self { start, end: start } + } + + pub fn union(self, other: Self) -> Self { + Self { + start: min(self.start, other.start), + end: max(self.end, other.end), + } + } + + pub fn start(self) -> Location { + self.start + } + + pub fn end(self) -> Location { + self.end + } +} + +impl> From> for Span { + fn from(value: Range) -> Self { + Span::new(value.start.into(), value.end.into()) + } +} + /// A [Token] with [Location] attached to it #[derive(Debug, Eq, PartialEq, Clone)] pub struct TokenWithLocation { pub token: Token, - pub location: Location, + pub span: Span, } impl TokenWithLocation { - pub fn new(token: Token, line: u64, column: u64) -> TokenWithLocation { + pub fn new(token: Token, span: Span) -> TokenWithLocation { + TokenWithLocation { token, span } + } + + pub fn at(token: Token, start: LineColumn, end: LineColumn) -> TokenWithLocation { TokenWithLocation { token, - location: Location { line, column }, + span: Location::from(start).span_to(end.into()), } } pub fn wrap(token: Token) -> TokenWithLocation { - TokenWithLocation::new(token, 0, 0) + TokenWithLocation::new(token, Span::default()) } } @@ -656,7 +768,8 @@ impl<'a> Tokenizer<'a> { let mut location = state.location(); while let Some(token) = self.next_token(&mut state)? { - buf.push(TokenWithLocation { token, location }); + let span = location.span_to(state.location()); + buf.push(TokenWithLocation { token, span }); location = state.location(); } @@ -2668,17 +2781,23 @@ mod tests { .tokenize_with_location() .unwrap(); let expected = vec![ - TokenWithLocation::new(Token::make_keyword("SELECT"), 1, 1), - TokenWithLocation::new(Token::Whitespace(Whitespace::Space), 1, 7), - TokenWithLocation::new(Token::make_word("a", None), 1, 8), - TokenWithLocation::new(Token::Comma, 1, 9), - TokenWithLocation::new(Token::Whitespace(Whitespace::Newline), 1, 10), - TokenWithLocation::new(Token::Whitespace(Whitespace::Space), 2, 1), - TokenWithLocation::new(Token::make_word("b", None), 2, 2), + TokenWithLocation::at(Token::make_keyword("SELECT"), (1, 1), (1, 7)), + TokenWithLocation::at(Token::Whitespace(Whitespace::Space), (1, 7), (1, 8)), + TokenWithLocation::at(Token::make_word("a", None), (1, 8), (1, 9)), + TokenWithLocation::at(Token::Comma, (1, 9), (1, 10)), + TokenWithLocation::at(Token::Whitespace(Whitespace::Newline), (1, 10), (2, 1)), + TokenWithLocation::at(Token::Whitespace(Whitespace::Space), (2, 1), (2, 2)), + TokenWithLocation::at(Token::make_word("b", None), (2, 2), (2, 3)), ]; compare(expected, tokens); } + #[test] + fn default_location_is_invalid() { + let d = Location::default(); + assert!(!d.is_valid()) + } + fn compare(expected: Vec, actual: Vec) { //println!("------------------------------"); //println!("tokens = {:?}", actual); diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs index 2bf470f71..d5fbc8994 100644 --- a/tests/sqlparser_bigquery.rs +++ b/tests/sqlparser_bigquery.rs @@ -222,7 +222,7 @@ fn parse_delete_statement() { }) => { assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::with_quote('"', "table")]), + name: ObjectName(vec![Ident::with_quote('"', "table").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -257,23 +257,23 @@ fn parse_create_view_with_options() { assert_eq!( name, ObjectName(vec![ - "myproject".into(), - "mydataset".into(), - "newview".into() + Ident::new("myproject").empty_span(), + Ident::new("mydataset").empty_span(), + Ident::new("newview").empty_span() ]) ); assert_eq!( vec![ ViewColumnDef { - name: Ident::new("name"), + name: Ident::new("name").empty_span(), data_type: None, options: None, }, ViewColumnDef { - name: Ident::new("age"), + name: Ident::new("age").empty_span(), data_type: None, options: Some(vec![ColumnOption::Options(vec![SqlOption::KeyValue { - key: Ident::new("description"), + key: Ident::new("description").empty_span(), value: Expr::Value(Value::DoubleQuotedString("field age".to_string())), }])]), }, @@ -293,7 +293,7 @@ fn parse_create_view_with_options() { }; assert_eq!( &SqlOption::KeyValue { - key: Ident::new("description"), + key: Ident::new("description").empty_span(), value: Expr::Value(Value::DoubleQuotedString( "a view that expires in 2 days".to_string() )), @@ -364,14 +364,14 @@ fn parse_create_table_with_unquoted_hyphen() { assert_eq!( name, ObjectName(vec![ - "my-pro-ject".into(), - "mydataset".into(), - "mytable".into() + Ident::new("my-pro-ject").empty_span(), + Ident::new("mydataset").empty_span(), + Ident::new("mytable").empty_span() ]) ); assert_eq!( vec![ColumnDef { - name: Ident::new("x"), + name: Ident::new("x").empty_span(), data_type: DataType::Int64, collation: None, options: vec![] @@ -404,12 +404,15 @@ fn parse_create_table_with_options() { }) => { assert_eq!( name, - ObjectName(vec!["mydataset".into(), "newtable".into()]) + ObjectName(vec![ + Ident::new("mydataset").empty_span(), + Ident::new("newtable").empty_span() + ]) ); assert_eq!( vec![ ColumnDef { - name: Ident::new("x"), + name: Ident::new("x").empty_span(), data_type: DataType::Int64, collation: None, options: vec![ @@ -420,7 +423,7 @@ fn parse_create_table_with_options() { ColumnOptionDef { name: None, option: ColumnOption::Options(vec![SqlOption::KeyValue { - key: Ident::new("description"), + key: Ident::new("description").empty_span(), value: Expr::Value(Value::DoubleQuotedString( "field x".to_string() )), @@ -429,13 +432,13 @@ fn parse_create_table_with_options() { ] }, ColumnDef { - name: Ident::new("y"), + name: Ident::new("y").empty_span(), data_type: DataType::Bool, collation: None, options: vec![ColumnOptionDef { name: None, option: ColumnOption::Options(vec![SqlOption::KeyValue { - key: Ident::new("description"), + key: Ident::new("description").empty_span(), value: Expr::Value(Value::DoubleQuotedString( "field y".to_string() )), @@ -447,18 +450,20 @@ fn parse_create_table_with_options() { ); assert_eq!( ( - Some(Box::new(Expr::Identifier(Ident::new("_PARTITIONDATE")))), + Some(Box::new(Expr::Identifier( + Ident::new("_PARTITIONDATE").empty_span() + ))), Some(WrappedCollection::NoWrapping(vec![ - Ident::new("userid"), - Ident::new("age"), + Ident::new("userid").empty_span(), + Ident::new("age").empty_span(), ])), Some(vec![ SqlOption::KeyValue { - key: Ident::new("partition_expiration_days"), + key: Ident::new("partition_expiration_days").empty_span(), value: Expr::Value(number("1")), }, SqlOption::KeyValue { - key: Ident::new("description"), + key: Ident::new("description").empty_span(), value: Expr::Value(Value::DoubleQuotedString( "table option description".to_string() )), @@ -487,22 +492,22 @@ fn parse_nested_data_types() { let sql = "CREATE TABLE table (x STRUCT, b BYTES(42)>, y ARRAY>)"; match bigquery_and_generic().one_statement_parses_to(sql, sql) { Statement::CreateTable(CreateTable { name, columns, .. }) => { - assert_eq!(name, ObjectName(vec!["table".into()])); + assert_eq!(name, ObjectName(vec![Ident::new("table").empty_span()])); assert_eq!( columns, vec![ ColumnDef { - name: Ident::new("x"), + name: Ident::new("x").empty_span(), data_type: DataType::Struct( vec![ StructField { - field_name: Some("a".into()), + field_name: Some(Ident::new("a").empty_span()), field_type: DataType::Array(ArrayElemTypeDef::AngleBracket( Box::new(DataType::Int64,) )) }, StructField { - field_name: Some("b".into()), + field_name: Some(Ident::new("b").empty_span()), field_type: DataType::Bytes(Some(42)) }, ], @@ -512,7 +517,7 @@ fn parse_nested_data_types() { options: vec![], }, ColumnDef { - name: Ident::new("y"), + name: Ident::new("y").empty_span(), data_type: DataType::Array(ArrayElemTypeDef::AngleBracket(Box::new( DataType::Struct( vec![StructField { @@ -617,7 +622,10 @@ fn parse_typeless_struct_syntax() { &Expr::Struct { values: vec![ Expr::Value(number("1")), - Expr::CompoundIdentifier(vec![Ident::from("t"), Ident::from("str_col")]), + Expr::CompoundIdentifier(vec![ + Ident::from("t").empty_span(), + Ident::from("str_col").empty_span() + ]), ], fields: Default::default() }, @@ -628,11 +636,11 @@ fn parse_typeless_struct_syntax() { values: vec![ Expr::Named { expr: Expr::Value(number("1")).into(), - name: Ident::from("a") + name: Ident::from("a").empty_span(), }, Expr::Named { expr: Expr::Value(Value::SingleQuotedString("abc".to_string())).into(), - name: Ident::from("b") + name: Ident::from("b").empty_span(), }, ], fields: Default::default() @@ -642,8 +650,8 @@ fn parse_typeless_struct_syntax() { assert_eq!( &Expr::Struct { values: vec![Expr::Named { - expr: Expr::Identifier(Ident::from("str_col")).into(), - name: Ident::from("abc") + expr: Expr::Identifier(Ident::from("str_col").empty_span()).into(), + name: Ident::from("abc").empty_span(), }], fields: Default::default() }, @@ -677,26 +685,34 @@ fn parse_typed_struct_syntax_bigquery() { Ident { value: "t".into(), quote_style: None, - }, + } + .empty_span(), Ident { value: "str_col".into(), quote_style: None, - }, + } + .empty_span(), ]), ], fields: vec![ StructField { - field_name: Some(Ident { - value: "x".into(), - quote_style: None, - }), + field_name: Some( + Ident { + value: "x".into(), + quote_style: None, + } + .empty_span() + ), field_type: DataType::Int64 }, StructField { - field_name: Some(Ident { - value: "y".into(), - quote_style: None, - }), + field_name: Some( + Ident { + value: "y".into(), + quote_style: None, + } + .empty_span() + ), field_type: DataType::String(None) }, ] @@ -705,19 +721,22 @@ fn parse_typed_struct_syntax_bigquery() { ); assert_eq!( &Expr::Struct { - values: vec![Expr::Identifier(Ident { - value: "nested_col".into(), - quote_style: None, - }),], + values: vec![Expr::Identifier( + Ident { + value: "nested_col".into(), + quote_style: None, + } + .empty_span() + ),], fields: vec![ StructField { - field_name: Some("arr".into()), + field_name: Some(Ident::new("arr").empty_span()), field_type: DataType::Array(ArrayElemTypeDef::AngleBracket(Box::new( DataType::Float64 ))) }, StructField { - field_name: Some("str".into()), + field_name: Some(Ident::new("str").empty_span()), field_type: DataType::Struct( vec![StructField { field_name: None, @@ -736,20 +755,23 @@ fn parse_typed_struct_syntax_bigquery() { assert_eq!(1, select.projection.len()); assert_eq!( &Expr::Struct { - values: vec![Expr::Identifier(Ident { - value: "nested_col".into(), - quote_style: None, - }),], + values: vec![Expr::Identifier( + Ident { + value: "nested_col".into(), + quote_style: None, + } + .empty_span() + ),], fields: vec![ StructField { - field_name: Some("x".into()), + field_name: Some(Ident::new("x").empty_span()), field_type: DataType::Struct( Default::default(), StructBracketKind::AngleBrackets ) }, StructField { - field_name: Some("y".into()), + field_name: Some(Ident::new("y").empty_span()), field_type: DataType::Array(ArrayElemTypeDef::AngleBracket(Box::new( DataType::Struct(Default::default(), StructBracketKind::AngleBrackets) ))) @@ -947,11 +969,11 @@ fn parse_typed_struct_syntax_bigquery() { values: vec![Expr::Value(number("1")), Expr::Value(number("2")),], fields: vec![ StructField { - field_name: Some("key".into()), + field_name: Some(Ident::new("key").empty_span()), field_type: DataType::Int64, }, StructField { - field_name: Some("value".into()), + field_name: Some(Ident::new("value").empty_span()), field_type: DataType::Int64, }, ] @@ -986,26 +1008,34 @@ fn parse_typed_struct_syntax_bigquery_and_generic() { Ident { value: "t".into(), quote_style: None, - }, + } + .empty_span(), Ident { value: "str_col".into(), quote_style: None, - }, + } + .empty_span(), ]), ], fields: vec![ StructField { - field_name: Some(Ident { - value: "x".into(), - quote_style: None, - }), + field_name: Some( + Ident { + value: "x".into(), + quote_style: None, + } + .empty_span() + ), field_type: DataType::Int64 }, StructField { - field_name: Some(Ident { - value: "y".into(), - quote_style: None, - }), + field_name: Some( + Ident { + value: "y".into(), + quote_style: None, + } + .empty_span() + ), field_type: DataType::String(None) }, ] @@ -1014,19 +1044,22 @@ fn parse_typed_struct_syntax_bigquery_and_generic() { ); assert_eq!( &Expr::Struct { - values: vec![Expr::Identifier(Ident { - value: "nested_col".into(), - quote_style: None, - }),], + values: vec![Expr::Identifier( + Ident { + value: "nested_col".into(), + quote_style: None, + } + .empty_span() + ),], fields: vec![ StructField { - field_name: Some("arr".into()), + field_name: Some(Ident::new("arr").empty_span()), field_type: DataType::Array(ArrayElemTypeDef::AngleBracket(Box::new( DataType::Float64 ))) }, StructField { - field_name: Some("str".into()), + field_name: Some(Ident::new("str").empty_span()), field_type: DataType::Struct( vec![StructField { field_name: None, @@ -1045,20 +1078,23 @@ fn parse_typed_struct_syntax_bigquery_and_generic() { assert_eq!(1, select.projection.len()); assert_eq!( &Expr::Struct { - values: vec![Expr::Identifier(Ident { - value: "nested_col".into(), - quote_style: None, - }),], + values: vec![Expr::Identifier( + Ident { + value: "nested_col".into(), + quote_style: None, + } + .empty_span() + ),], fields: vec![ StructField { - field_name: Some("x".into()), + field_name: Some(Ident::new("x").empty_span()), field_type: DataType::Struct( Default::default(), StructBracketKind::AngleBrackets ) }, StructField { - field_name: Some("y".into()), + field_name: Some(Ident::new("y").empty_span()), field_type: DataType::Array(ArrayElemTypeDef::AngleBracket(Box::new( DataType::Struct(Default::default(), StructBracketKind::AngleBrackets) ))) @@ -1257,7 +1293,7 @@ fn parse_typed_struct_with_field_name_bigquery() { &Expr::Struct { values: vec![Expr::Value(number("5")),], fields: vec![StructField { - field_name: Some(Ident::from("x")), + field_name: Some(Ident::from("x").empty_span()), field_type: DataType::Int64 }] }, @@ -1267,7 +1303,7 @@ fn parse_typed_struct_with_field_name_bigquery() { &Expr::Struct { values: vec![Expr::Value(Value::DoubleQuotedString("foo".to_string())),], fields: vec![StructField { - field_name: Some(Ident::from("y")), + field_name: Some(Ident::from("y").empty_span()), field_type: DataType::String(None) }] }, @@ -1282,11 +1318,11 @@ fn parse_typed_struct_with_field_name_bigquery() { values: vec![Expr::Value(number("5")), Expr::Value(number("5")),], fields: vec![ StructField { - field_name: Some(Ident::from("x")), + field_name: Some(Ident::from("x").empty_span()), field_type: DataType::Int64 }, StructField { - field_name: Some(Ident::from("y")), + field_name: Some(Ident::from("y").empty_span()), field_type: DataType::Int64 } ] @@ -1304,7 +1340,7 @@ fn parse_typed_struct_with_field_name_bigquery_and_generic() { &Expr::Struct { values: vec![Expr::Value(number("5")),], fields: vec![StructField { - field_name: Some(Ident::from("x")), + field_name: Some(Ident::from("x").empty_span()), field_type: DataType::Int64 }] }, @@ -1314,7 +1350,7 @@ fn parse_typed_struct_with_field_name_bigquery_and_generic() { &Expr::Struct { values: vec![Expr::Value(Value::SingleQuotedString("foo".to_string())),], fields: vec![StructField { - field_name: Some(Ident::from("y")), + field_name: Some(Ident::from("y").empty_span()), field_type: DataType::String(None) }] }, @@ -1329,11 +1365,11 @@ fn parse_typed_struct_with_field_name_bigquery_and_generic() { values: vec![Expr::Value(number("5")), Expr::Value(number("5")),], fields: vec![ StructField { - field_name: Some(Ident::from("x")), + field_name: Some(Ident::from("x").empty_span()), field_type: DataType::Int64 }, StructField { - field_name: Some(Ident::from("y")), + field_name: Some(Ident::from("y").empty_span()), field_type: DataType::Int64 } ] @@ -1352,7 +1388,7 @@ fn parse_table_identifiers() { /// instead as the canonical representation of the identifier for comparison. /// For example, re-serializing the result of ident `foo.bar` produces /// the equivalent canonical representation `foo`.`bar` - fn test_table_ident(ident: &str, canonical: Option<&str>, expected: Vec) { + fn test_table_ident(ident: &str, canonical: Option<&str>, expected: Vec>) { let sql = format!("SELECT 1 FROM {ident}"); let canonical = canonical.map(|ident| format!("SELECT 1 FROM {ident}")); @@ -1384,23 +1420,33 @@ fn parse_table_identifiers() { assert!(bigquery().parse_sql_statements(&sql).is_err()); } - test_table_ident("`spa ce`", None, vec![Ident::with_quote('`', "spa ce")]); + test_table_ident( + "`spa ce`", + None, + vec![Ident::with_quote('`', "spa ce").empty_span()], + ); test_table_ident( "`!@#$%^&*()-=_+`", None, - vec![Ident::with_quote('`', "!@#$%^&*()-=_+")], + vec![Ident::with_quote('`', "!@#$%^&*()-=_+").empty_span()], ); test_table_ident( "_5abc.dataField", None, - vec![Ident::new("_5abc"), Ident::new("dataField")], + vec![ + Ident::new("_5abc").empty_span(), + Ident::new("dataField").empty_span(), + ], ); test_table_ident( "`5abc`.dataField", None, - vec![Ident::with_quote('`', "5abc"), Ident::new("dataField")], + vec![ + Ident::with_quote('`', "5abc").empty_span(), + Ident::new("dataField").empty_span(), + ], ); test_table_ident_err("5abc.dataField"); @@ -1408,7 +1454,10 @@ fn parse_table_identifiers() { test_table_ident( "abc5.dataField", None, - vec![Ident::new("abc5"), Ident::new("dataField")], + vec![ + Ident::new("abc5").empty_span(), + Ident::new("dataField").empty_span(), + ], ); test_table_ident_err("abc5!.dataField"); @@ -1416,7 +1465,10 @@ fn parse_table_identifiers() { test_table_ident( "`GROUP`.dataField", None, - vec![Ident::with_quote('`', "GROUP"), Ident::new("dataField")], + vec![ + Ident::with_quote('`', "GROUP").empty_span(), + Ident::new("dataField").empty_span(), + ], ); // TODO: this should be error @@ -1425,16 +1477,19 @@ fn parse_table_identifiers() { test_table_ident( "abc5.GROUP", None, - vec![Ident::new("abc5"), Ident::new("GROUP")], + vec![ + Ident::new("abc5").empty_span(), + Ident::new("GROUP").empty_span(), + ], ); test_table_ident( "`foo.bar.baz`", Some("`foo`.`bar`.`baz`"), vec![ - Ident::with_quote('`', "foo"), - Ident::with_quote('`', "bar"), - Ident::with_quote('`', "baz"), + Ident::with_quote('`', "foo").empty_span(), + Ident::with_quote('`', "bar").empty_span(), + Ident::with_quote('`', "baz").empty_span(), ], ); @@ -1442,9 +1497,9 @@ fn parse_table_identifiers() { "`foo.bar`.`baz`", Some("`foo`.`bar`.`baz`"), vec![ - Ident::with_quote('`', "foo"), - Ident::with_quote('`', "bar"), - Ident::with_quote('`', "baz"), + Ident::with_quote('`', "foo").empty_span(), + Ident::with_quote('`', "bar").empty_span(), + Ident::with_quote('`', "baz").empty_span(), ], ); @@ -1452,9 +1507,9 @@ fn parse_table_identifiers() { "`foo`.`bar.baz`", Some("`foo`.`bar`.`baz`"), vec![ - Ident::with_quote('`', "foo"), - Ident::with_quote('`', "bar"), - Ident::with_quote('`', "baz"), + Ident::with_quote('`', "foo").empty_span(), + Ident::with_quote('`', "bar").empty_span(), + Ident::with_quote('`', "baz").empty_span(), ], ); @@ -1462,9 +1517,9 @@ fn parse_table_identifiers() { "`foo`.`bar`.`baz`", Some("`foo`.`bar`.`baz`"), vec![ - Ident::with_quote('`', "foo"), - Ident::with_quote('`', "bar"), - Ident::with_quote('`', "baz"), + Ident::with_quote('`', "foo").empty_span(), + Ident::with_quote('`', "bar").empty_span(), + Ident::with_quote('`', "baz").empty_span(), ], ); @@ -1472,8 +1527,8 @@ fn parse_table_identifiers() { "`5abc.dataField`", Some("`5abc`.`dataField`"), vec![ - Ident::with_quote('`', "5abc"), - Ident::with_quote('`', "dataField"), + Ident::with_quote('`', "5abc").empty_span(), + Ident::with_quote('`', "dataField").empty_span(), ], ); @@ -1481,15 +1536,18 @@ fn parse_table_identifiers() { "`_5abc.da-sh-es`", Some("`_5abc`.`da-sh-es`"), vec![ - Ident::with_quote('`', "_5abc"), - Ident::with_quote('`', "da-sh-es"), + Ident::with_quote('`', "_5abc").empty_span(), + Ident::with_quote('`', "da-sh-es").empty_span(), ], ); test_table_ident( "foo-bar.baz-123", Some("foo-bar.baz-123"), - vec![Ident::new("foo-bar"), Ident::new("baz-123")], + vec![ + Ident::new("foo-bar").empty_span(), + Ident::new("baz-123").empty_span(), + ], ); test_table_ident_err("foo-`bar`"); @@ -1515,11 +1573,11 @@ fn parse_hyphenated_table_identifiers() { ) .projection[0], SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("foo"))), + left: Box::new(Expr::Identifier(Ident::new("foo").empty_span())), op: BinaryOperator::Minus, right: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("bar"), - Ident::new("x") + Ident::new("bar").empty_span(), + Ident::new("x").empty_span(), ])) }) ); @@ -1537,7 +1595,7 @@ fn parse_table_time_travel() { select.from, vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("t1")]), + name: ObjectName(vec![Ident::new("t1").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -1568,8 +1626,8 @@ fn parse_join_constraint_unnest_alias() { relation: TableFactor::UNNEST { alias: table_alias("f"), array_exprs: vec![Expr::CompoundIdentifier(vec![ - Ident::new("t1"), - Ident::new("a") + Ident::new("t1").empty_span(), + Ident::new("a").empty_span(), ])], with_offset: false, with_offset_alias: None, @@ -1577,9 +1635,9 @@ fn parse_join_constraint_unnest_alias() { }, global: false, join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp { - left: Box::new(Expr::Identifier("c1".into())), + left: Box::new(Expr::Identifier(Ident::new("c1").empty_span())), op: BinaryOperator::Eq, - right: Box::new(Expr::Identifier("c2".into())), + right: Box::new(Expr::Identifier(Ident::new("c2").empty_span())), })), }] ); @@ -1605,7 +1663,10 @@ fn parse_merge() { "WHEN NOT MATCHED THEN INSERT VALUES (1, DEFAULT)", ); let insert_action = MergeAction::Insert(MergeInsertExpr { - columns: vec![Ident::new("product"), Ident::new("quantity")], + columns: vec![ + Ident::new("product").empty_span(), + Ident::new("quantity").empty_span(), + ], kind: MergeInsertKind::Values(Values { explicit_row: false, rows: vec![vec![Expr::Value(number("1")), Expr::Value(number("2"))]], @@ -1614,11 +1675,15 @@ fn parse_merge() { let update_action = MergeAction::Update { assignments: vec![ Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new("a")])), + target: AssignmentTarget::ColumnName(ObjectName( + vec![Ident::new("a").empty_span()], + )), value: Expr::Value(number("1")), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new("b")])), + target: AssignmentTarget::ColumnName(ObjectName( + vec![Ident::new("b").empty_span()], + )), value: Expr::Value(number("2")), }, ], @@ -1634,9 +1699,9 @@ fn parse_merge() { assert!(!into); assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("inventory")]), + name: ObjectName(vec![Ident::new("inventory").empty_span()]), alias: Some(TableAlias { - name: Ident::new("T"), + name: Ident::new("T").empty_span(), columns: vec![], }), args: Default::default(), @@ -1649,9 +1714,9 @@ fn parse_merge() { ); assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("newArrivals")]), + name: ObjectName(vec![Ident::new("newArrivals").empty_span()]), alias: Some(TableAlias { - name: Ident::new("S"), + name: Ident::new("S").empty_span(), columns: vec![], }), args: Default::default(), @@ -1699,7 +1764,10 @@ fn parse_merge() { clause_kind: MergeClauseKind::NotMatched, predicate: Some(Expr::Value(number("1"))), action: MergeAction::Insert(MergeInsertExpr { - columns: vec![Ident::new("product"), Ident::new("quantity"),], + columns: vec![ + Ident::new("product").empty_span(), + Ident::new("quantity").empty_span(), + ], kind: MergeInsertKind::Row, }) }, @@ -1707,7 +1775,10 @@ fn parse_merge() { clause_kind: MergeClauseKind::NotMatched, predicate: None, action: MergeAction::Insert(MergeInsertExpr { - columns: vec![Ident::new("product"), Ident::new("quantity"),], + columns: vec![ + Ident::new("product").empty_span(), + Ident::new("quantity").empty_span(), + ], kind: MergeInsertKind::Row, }) }, @@ -1741,12 +1812,15 @@ fn parse_merge() { clause_kind: MergeClauseKind::NotMatched, predicate: None, action: MergeAction::Insert(MergeInsertExpr { - columns: vec![Ident::new("a"), Ident::new("b"),], + columns: vec![ + Ident::new("a").empty_span(), + Ident::new("b").empty_span(), + ], kind: MergeInsertKind::Values(Values { explicit_row: false, rows: vec![vec![ Expr::Value(number("1")), - Expr::Identifier(Ident::new("DEFAULT")), + Expr::Identifier(Ident::new("DEFAULT").empty_span()), ]] }) }) @@ -1760,7 +1834,7 @@ fn parse_merge() { explicit_row: false, rows: vec![vec![ Expr::Value(number("1")), - Expr::Identifier(Ident::new("DEFAULT")), + Expr::Identifier(Ident::new("DEFAULT").empty_span()), ]] }) }) @@ -1876,13 +1950,13 @@ fn parse_big_query_declare() { for (sql, expected_names, expected_data_type, expected_assigned_expr) in [ ( "DECLARE x INT64", - vec![Ident::new("x")], + vec![Ident::new("x").empty_span()], Some(DataType::Int64), None, ), ( "DECLARE x INT64 DEFAULT 42", - vec![Ident::new("x")], + vec![Ident::new("x").empty_span()], Some(DataType::Int64), Some(DeclareAssignment::Default(Box::new(Expr::Value(number( "42", @@ -1890,7 +1964,11 @@ fn parse_big_query_declare() { ), ( "DECLARE x, y, z INT64 DEFAULT 42", - vec![Ident::new("x"), Ident::new("y"), Ident::new("z")], + vec![ + Ident::new("x").empty_span(), + Ident::new("y").empty_span(), + Ident::new("z").empty_span(), + ], Some(DataType::Int64), Some(DeclareAssignment::Default(Box::new(Expr::Value(number( "42", @@ -1898,7 +1976,7 @@ fn parse_big_query_declare() { ), ( "DECLARE x DEFAULT 42", - vec![Ident::new("x")], + vec![Ident::new("x").empty_span()], None, Some(DeclareAssignment::Default(Box::new(Expr::Value(number( "42", @@ -1955,7 +2033,7 @@ fn parse_map_access_expr() { MapAccessKey { key, syntax } } let expected = Expr::MapAccess { - column: Expr::Identifier(Ident::new("users")).into(), + column: Expr::Identifier(Ident::new("users").empty_span()).into(), keys: vec![ map_access_key( Expr::UnaryOp { @@ -1969,7 +2047,10 @@ fn parse_map_access_expr() { MapAccessSyntax::Bracket, ), map_access_key( - Expr::CompoundIdentifier(vec![Ident::new("a"), Ident::new("b")]), + Expr::CompoundIdentifier(vec![ + Ident::new("a").empty_span(), + Ident::new("b").empty_span(), + ]), MapAccessSyntax::Period, ), ], @@ -1998,9 +2079,9 @@ fn test_bigquery_create_function() { temporary: true, if_not_exists: false, name: ObjectName(vec![ - Ident::new("project1"), - Ident::new("mydataset"), - Ident::new("myfunction"), + Ident::new("project1").empty_span(), + Ident::new("mydataset").empty_span(), + Ident::new("myfunction").empty_span(), ]), args: Some(vec![OperateFunctionArg::with_name("x", DataType::Float64),]), return_type: Some(DataType::Float64), @@ -2008,7 +2089,7 @@ fn test_bigquery_create_function() { "42" )))), options: Some(vec![SqlOption::KeyValue { - key: Ident::new("x"), + key: Ident::new("x").empty_span(), value: Expr::Value(Value::SingleQuotedString("y".into())), }]), behavior: None, @@ -2150,9 +2231,9 @@ fn parse_extract_weekday() { let select = bigquery_and_generic().verified_only_select(sql); assert_eq!( &Expr::Extract { - field: DateTimeField::Week(Some(Ident::new("MONDAY"))), + field: DateTimeField::Week(Some(Ident::new("MONDAY").empty_span())), syntax: ExtractSyntax::From, - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), }, expr_from_projection(only(&select.projection)), ); diff --git a/tests/sqlparser_clickhouse.rs b/tests/sqlparser_clickhouse.rs index f8c349a37..bcd253846 100644 --- a/tests/sqlparser_clickhouse.rs +++ b/tests/sqlparser_clickhouse.rs @@ -41,15 +41,18 @@ fn parse_map_access_expr() { distinct: None, top: None, projection: vec![UnnamedExpr(MapAccess { - column: Box::new(Identifier(Ident { - value: "string_values".to_string(), - quote_style: None, - })), + column: Box::new(Identifier( + Ident { + value: "string_values".to_string(), + quote_style: None, + } + .empty_span() + )), keys: vec![MapAccessKey { key: call( "indexOf", [ - Expr::Identifier(Ident::new("string_names")), + Expr::Identifier(Ident::new("string_names").empty_span()), Expr::Value(Value::SingleQuotedString("endpoint".to_string())) ] ), @@ -59,7 +62,7 @@ fn parse_map_access_expr() { into: None, from: vec![TableWithJoins { relation: Table { - name: ObjectName(vec![Ident::new("foos")]), + name: ObjectName(vec![Ident::new("foos").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -73,19 +76,19 @@ fn parse_map_access_expr() { prewhere: None, selection: Some(BinaryOp { left: Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("id"))), + left: Box::new(Identifier(Ident::new("id").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::SingleQuotedString("test".to_string()))), }), op: BinaryOperator::And, right: Box::new(BinaryOp { left: Box::new(MapAccess { - column: Box::new(Identifier(Ident::new("string_value"))), + column: Box::new(Identifier(Ident::new("string_value").empty_span())), keys: vec![MapAccessKey { key: call( "indexOf", [ - Expr::Identifier(Ident::new("string_name")), + Expr::Identifier(Ident::new("string_name").empty_span()), Expr::Value(Value::SingleQuotedString("app".to_string())) ] ), @@ -135,8 +138,8 @@ fn parse_array_fn() { &call( "array", [ - Expr::Identifier(Ident::new("x1")), - Expr::Identifier(Ident::new("x2")) + Expr::Identifier(Ident::new("x1").empty_span()), + Expr::Identifier(Ident::new("x2").empty_span()) ] ), expr_from_projection(only(&select.projection)) @@ -172,8 +175,11 @@ fn parse_delimited_identifiers() { with_ordinality: _, partitions: _, } => { - assert_eq!(vec![Ident::with_quote('"', "a table")], name.0); - assert_eq!(Ident::with_quote('"', "alias"), alias.unwrap().name); + assert_eq!(vec![Ident::with_quote('"', "a table").empty_span()], name.0); + assert_eq!( + Ident::with_quote('"', "alias").empty_span(), + alias.unwrap().name + ); assert!(args.is_none()); assert!(with_hints.is_empty()); assert!(version.is_none()); @@ -184,14 +190,14 @@ fn parse_delimited_identifiers() { assert_eq!(3, select.projection.len()); assert_eq!( &Expr::CompoundIdentifier(vec![ - Ident::with_quote('"', "alias"), - Ident::with_quote('"', "bar baz"), + Ident::with_quote('"', "alias").empty_span(), + Ident::with_quote('"', "bar baz").empty_span(), ]), expr_from_projection(&select.projection[0]), ); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::with_quote('"', "myfun")]), + name: ObjectName(vec![Ident::with_quote('"', "myfun").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -207,8 +213,11 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); - assert_eq!(&Ident::with_quote('"', "column alias"), alias); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); + assert_eq!(&Ident::with_quote('"', "column alias").empty_span(), alias); } _ => panic!("Expected ExprWithAlias"), } @@ -241,11 +250,11 @@ fn parse_alter_table_attach_and_detach_partition() { operations[0], if operation == &"ATTACH" { AlterTableOperation::AttachPartition { - partition: Partition::Expr(Identifier(Ident::new("part"))), + partition: Partition::Expr(Identifier(Ident::new("part").empty_span())), } } else { AlterTableOperation::DetachPartition { - partition: Partition::Expr(Identifier(Ident::new("part"))), + partition: Partition::Expr(Identifier(Ident::new("part").empty_span())), } } ); @@ -264,11 +273,11 @@ fn parse_alter_table_attach_and_detach_partition() { operations[0], if operation == &"ATTACH" { AlterTableOperation::AttachPartition { - partition: Partition::Part(Identifier(Ident::new("part"))), + partition: Partition::Part(Identifier(Ident::new("part").empty_span())), } } else { AlterTableOperation::DetachPartition { - partition: Partition::Part(Identifier(Ident::new("part"))), + partition: Partition::Part(Identifier(Ident::new("part").empty_span())), } } ); @@ -301,25 +310,25 @@ fn parse_alter_table_add_projection() { Statement::AlterTable { name, operations, .. } => { - assert_eq!(name, ObjectName(vec!["t0".into()])); + assert_eq!(name, ObjectName(vec![Ident::new("t0").empty_span()])); assert_eq!(1, operations.len()); assert_eq!( operations[0], AlterTableOperation::AddProjection { if_not_exists: true, - name: "my_name".into(), + name: Ident::new("my_name").empty_span(), select: ProjectionSelect { projection: vec![ - UnnamedExpr(Identifier(Ident::new("a"))), - UnnamedExpr(Identifier(Ident::new("b"))), + UnnamedExpr(Identifier(Ident::new("a").empty_span())), + UnnamedExpr(Identifier(Ident::new("b").empty_span())), ], group_by: Some(GroupByExpr::Expressions( - vec![Identifier(Ident::new("a"))], + vec![Identifier(Ident::new("a").empty_span())], vec![] )), order_by: Some(OrderBy { exprs: vec![OrderByExpr { - expr: Identifier(Ident::new("b")), + expr: Identifier(Ident::new("b").empty_span()), asc: None, nulls_first: None, with_fill: None, @@ -371,13 +380,13 @@ fn parse_alter_table_drop_projection() { Statement::AlterTable { name, operations, .. } => { - assert_eq!(name, ObjectName(vec!["t0".into()])); + assert_eq!(name, ObjectName(vec![Ident::new("t0").empty_span()])); assert_eq!(1, operations.len()); assert_eq!( operations[0], AlterTableOperation::DropProjection { if_exists: true, - name: "my_name".into(), + name: Ident::new("my_name").empty_span(), } ) } @@ -404,21 +413,21 @@ fn parse_alter_table_clear_and_materialize_projection() { Statement::AlterTable { name, operations, .. } => { - assert_eq!(name, ObjectName(vec!["t0".into()])); + assert_eq!(name, ObjectName(vec![Ident::new("t0").empty_span()])); assert_eq!(1, operations.len()); assert_eq!( operations[0], if keyword == "CLEAR" { AlterTableOperation::ClearProjection { if_exists: true, - name: "my_name".into(), - partition: Some(Ident::new("p0")), + name: Ident::new("my_name").empty_span(), + partition: Some(Ident::new("p0").empty_span()), } } else { AlterTableOperation::MaterializeProjection { if_exists: true, - name: "my_name".into(), - partition: Some(Ident::new("p0")), + name: Ident::new("my_name").empty_span(), + partition: Some(Ident::new("p0").empty_span()), } } ) @@ -484,15 +493,19 @@ fn parse_optimize_table() { .. } => { assert_eq!(name.to_string(), "t0"); - assert_eq!(on_cluster, Some(Ident::new("cluster"))); + assert_eq!(on_cluster, Some(Ident::new("cluster").empty_span())); assert_eq!( partition, - Some(Partition::Identifier(Ident::with_quote('\'', "2024-07"))) + Some(Partition::Identifier( + Ident::with_quote('\'', "2024-07").empty_span() + )) ); assert!(include_final); assert_eq!( deduplicate, - Some(Deduplicate::ByExpression(Identifier(Ident::new("id")))) + Some(Deduplicate::ByExpression(Identifier( + Ident::new("id").empty_span() + ))) ); } _ => unreachable!(), @@ -521,7 +534,7 @@ fn parse_optimize_table() { fn column_def(name: Ident, data_type: DataType) -> ColumnDef { ColumnDef { - name, + name: name.empty_span(), data_type, collation: None, options: vec![], @@ -548,7 +561,7 @@ fn parse_clickhouse_data_types() { match clickhouse_and_generic().one_statement_parses_to(sql, &canonical_sql) { Statement::CreateTable(CreateTable { name, columns, .. }) => { - assert_eq!(name, ObjectName(vec!["table".into()])); + assert_eq!(name, ObjectName(vec![Ident::new("table").empty_span()])); assert_eq!( columns, vec![ @@ -589,7 +602,7 @@ fn parse_create_table_with_nullable() { match clickhouse_and_generic().one_statement_parses_to(sql, &canonical_sql) { Statement::CreateTable(CreateTable { name, columns, .. }) => { - assert_eq!(name, ObjectName(vec!["table".into()])); + assert_eq!(name, ObjectName(vec![Ident::new("table").empty_span()])); assert_eq!( columns, vec![ @@ -610,7 +623,7 @@ fn parse_create_table_with_nullable() { DataType::Nullable(Box::new(DataType::Datetime64(9, None))) ), ColumnDef { - name: "d".into(), + name: Ident::new("d").empty_span(), data_type: DataType::Date32, collation: None, options: vec![ColumnOptionDef { @@ -638,12 +651,12 @@ fn parse_create_table_with_nested_data_types() { match clickhouse().one_statement_parses_to(sql, "") { Statement::CreateTable(CreateTable { name, columns, .. }) => { - assert_eq!(name, ObjectName(vec!["table".into()])); + assert_eq!(name, ObjectName(vec![Ident::new("table").empty_span()])); assert_eq!( columns, vec![ ColumnDef { - name: Ident::new("i"), + name: Ident::new("i").empty_span(), data_type: DataType::Nested(vec![ column_def( "a".into(), @@ -660,7 +673,7 @@ fn parse_create_table_with_nested_data_types() { options: vec![], }, ColumnDef { - name: Ident::new("k"), + name: Ident::new("k").empty_span(), data_type: DataType::Array(ArrayElemTypeDef::Parenthesis(Box::new( DataType::Tuple(vec![ StructField { @@ -677,14 +690,14 @@ fn parse_create_table_with_nested_data_types() { options: vec![], }, ColumnDef { - name: Ident::new("l"), + name: Ident::new("l").empty_span(), data_type: DataType::Tuple(vec![ StructField { - field_name: Some("a".into()), + field_name: Some(Ident::new("a").empty_span()), field_type: DataType::Datetime64(9, None), }, StructField { - field_name: Some("b".into()), + field_name: Some(Ident::new("b").empty_span()), field_type: DataType::Array(ArrayElemTypeDef::Parenthesis( Box::new(DataType::Uuid) )) @@ -694,7 +707,7 @@ fn parse_create_table_with_nested_data_types() { options: vec![], }, ColumnDef { - name: Ident::new("m"), + name: Ident::new("m").empty_span(), data_type: DataType::Map( Box::new(DataType::String(None)), Box::new(DataType::UInt16) @@ -729,13 +742,13 @@ fn parse_create_table_with_primary_key() { assert_eq!( vec![ ColumnDef { - name: Ident::with_quote('`', "i"), + name: Ident::with_quote('`', "i").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![], }, ColumnDef { - name: Ident::with_quote('`', "k"), + name: Ident::with_quote('`', "k").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![], @@ -748,18 +761,18 @@ fn parse_create_table_with_primary_key() { Some(TableEngine { name: "SharedMergeTree".to_string(), parameters: Some(vec![ - Ident::with_quote('\'', "/clickhouse/tables/{uuid}/{shard}"), - Ident::with_quote('\'', "{replica}"), + Ident::with_quote('\'', "/clickhouse/tables/{uuid}/{shard}").empty_span(), + Ident::with_quote('\'', "{replica}").empty_span(), ]), }) ); fn assert_function(actual: &Function, name: &str, arg: &str) -> bool { - assert_eq!(actual.name, ObjectName(vec![Ident::new(name)])); + assert_eq!(actual.name, ObjectName(vec![Ident::new(name).empty_span()])); assert_eq!( actual.args, FunctionArguments::List(FunctionArgumentList { args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Identifier( - Ident::new(arg) + Ident::new(arg).empty_span() )),)], duplicate_treatment: None, clauses: vec![], @@ -807,13 +820,13 @@ fn parse_create_table_with_variant_default_expressions() { columns, vec![ ColumnDef { - name: Ident::new("a"), + name: Ident::new("a").empty_span(), data_type: DataType::Datetime(None), collation: None, options: vec![ColumnOptionDef { name: None, option: ColumnOption::Materialized(Expr::Function(Function { - name: ObjectName(vec![Ident::new("now")]), + name: ObjectName(vec![Ident::new("now").empty_span()]), args: FunctionArguments::List(FunctionArgumentList { args: vec![], duplicate_treatment: None, @@ -828,13 +841,13 @@ fn parse_create_table_with_variant_default_expressions() { }], }, ColumnDef { - name: Ident::new("b"), + name: Ident::new("b").empty_span(), data_type: DataType::Datetime(None), collation: None, options: vec![ColumnOptionDef { name: None, option: ColumnOption::Ephemeral(Some(Expr::Function(Function { - name: ObjectName(vec![Ident::new("now")]), + name: ObjectName(vec![Ident::new("now").empty_span()]), args: FunctionArguments::List(FunctionArgumentList { args: vec![], duplicate_treatment: None, @@ -849,7 +862,7 @@ fn parse_create_table_with_variant_default_expressions() { }], }, ColumnDef { - name: Ident::new("c"), + name: Ident::new("c").empty_span(), data_type: DataType::Datetime(None), collation: None, options: vec![ColumnOptionDef { @@ -858,16 +871,16 @@ fn parse_create_table_with_variant_default_expressions() { }], }, ColumnDef { - name: Ident::new("d"), + name: Ident::new("d").empty_span(), data_type: DataType::String(None), collation: None, options: vec![ColumnOptionDef { name: None, option: ColumnOption::Alias(Expr::Function(Function { - name: ObjectName(vec![Ident::new("toString")]), + name: ObjectName(vec![Ident::new("toString").empty_span()]), args: FunctionArguments::List(FunctionArgumentList { args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Identifier(Ident::new("c")) + Identifier(Ident::new("c").empty_span()) ))], duplicate_treatment: None, clauses: vec![], @@ -891,28 +904,30 @@ fn parse_create_table_with_variant_default_expressions() { fn parse_create_view_with_fields_data_types() { match clickhouse().verified_stmt(r#"CREATE VIEW v (i "int", f "String") AS SELECT * FROM t"#) { Statement::CreateView { name, columns, .. } => { - assert_eq!(name, ObjectName(vec!["v".into()])); + assert_eq!(name, ObjectName(vec![Ident::new("v").empty_span()])); assert_eq!( columns, vec![ ViewColumnDef { - name: "i".into(), + name: Ident::new("i").empty_span(), data_type: Some(DataType::Custom( ObjectName(vec![Ident { value: "int".into(), quote_style: Some('"') - }]), + } + .empty_span()]), vec![] )), options: None }, ViewColumnDef { - name: "f".into(), + name: Ident::new("f").empty_span(), data_type: Some(DataType::Custom( ObjectName(vec![Ident { value: "String".into(), quote_style: Some('"') - }]), + } + .empty_span()]), vec![] )), options: None @@ -956,11 +971,11 @@ fn parse_settings_in_query() { query.settings, Some(vec![ Setting { - key: Ident::new("max_threads"), + key: Ident::new("max_threads").empty_span(), value: Number("1".parse().unwrap(), false) }, Setting { - key: Ident::new("max_block_size"), + key: Ident::new("max_block_size").empty_span(), value: Number("10000".parse().unwrap(), false) }, ]) @@ -1002,11 +1017,15 @@ fn parse_select_parametric_function() { assert_eq!(args.args.len(), 2); assert_eq!( args.args[0], - FunctionArg::Unnamed(FunctionArgExpr::Expr(Identifier(Ident::from("x")))) + FunctionArg::Unnamed(FunctionArgExpr::Expr(Identifier( + Ident::from("x").empty_span() + ))) ); assert_eq!( args.args[1], - FunctionArg::Unnamed(FunctionArgExpr::Expr(Identifier(Ident::from("y")))) + FunctionArg::Unnamed(FunctionArgExpr::Expr(Identifier( + Ident::from("y").empty_span() + ))) ); let parameters = match f.parameters { @@ -1088,7 +1107,7 @@ fn parse_group_by_with_modifier() { &GroupByExpr::Expressions( clause .split(", ") - .map(|c| Identifier(Ident::new(c))) + .map(|c| Identifier(Ident::new(c).empty_span())) .collect(), expected_modifier.to_vec() ) @@ -1127,7 +1146,7 @@ fn parse_select_order_by_with_fill_interpolate() { OrderBy { exprs: vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("fname")), + expr: Expr::Identifier(Ident::new("fname").empty_span()), asc: Some(true), nulls_first: Some(true), with_fill: Some(WithFill { @@ -1137,7 +1156,7 @@ fn parse_select_order_by_with_fill_interpolate() { }), }, OrderByExpr { - expr: Expr::Identifier(Ident::new("lname")), + expr: Expr::Identifier(Ident::new("lname").empty_span()), asc: Some(false), nulls_first: Some(false), with_fill: Some(WithFill { @@ -1149,9 +1168,9 @@ fn parse_select_order_by_with_fill_interpolate() { ], interpolate: Some(Interpolate { exprs: Some(vec![InterpolateExpr { - column: Ident::new("col1"), + column: Ident::new("col1").empty_span(), expr: Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("col1"))), + left: Box::new(Expr::Identifier(Ident::new("col1").empty_span())), op: BinaryOperator::Plus, right: Box::new(Expr::Value(number("1"))), }), @@ -1236,21 +1255,21 @@ fn parse_interpolate_body_with_columns() { Some(Interpolate { exprs: Some(vec![ InterpolateExpr { - column: Ident::new("col1"), + column: Ident::new("col1").empty_span(), expr: Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("col1"))), + left: Box::new(Expr::Identifier(Ident::new("col1").empty_span())), op: BinaryOperator::Plus, right: Box::new(Expr::Value(number("1"))), }), }, InterpolateExpr { - column: Ident::new("col2"), - expr: Some(Expr::Identifier(Ident::new("col3"))), + column: Ident::new("col2").empty_span(), + expr: Some(Expr::Identifier(Ident::new("col3").empty_span())), }, InterpolateExpr { - column: Ident::new("col4"), + column: Ident::new("col4").empty_span(), expr: Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("col4"))), + left: Box::new(Expr::Identifier(Ident::new("col4").empty_span())), op: BinaryOperator::Plus, right: Box::new(Expr::Value(number("4"))), }), @@ -1291,7 +1310,7 @@ fn test_prewhere() { assert_eq!( prewhere, Some(&BinaryOp { - left: Box::new(Identifier(Ident::new("x"))), + left: Box::new(Identifier(Ident::new("x").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Number("1".parse().unwrap(), false))), }) @@ -1300,7 +1319,7 @@ fn test_prewhere() { assert_eq!( selection, Some(&BinaryOp { - left: Box::new(Identifier(Ident::new("y"))), + left: Box::new(Identifier(Ident::new("y").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Number("2".parse().unwrap(), false))), }) @@ -1316,13 +1335,13 @@ fn test_prewhere() { prewhere, Some(&BinaryOp { left: Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("x"))), + left: Box::new(Identifier(Ident::new("x").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Number("1".parse().unwrap(), false))), }), op: BinaryOperator::And, right: Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("y"))), + left: Box::new(Identifier(Ident::new("y").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Number("2".parse().unwrap(), false))), }), @@ -1351,7 +1370,8 @@ fn parse_use() { clickhouse().verified_stmt(&format!("USE {}", object_name)), Statement::Use(Use::Object(ObjectName(vec![Ident::new( object_name.to_string() - )]))) + ) + .empty_span()]))) ); for "e in "e_styles { // Test single identifier with different type of quotes @@ -1360,7 +1380,8 @@ fn parse_use() { Statement::Use(Use::Object(ObjectName(vec![Ident::with_quote( quote, object_name.to_string(), - )]))) + ) + .empty_span()]))) ); } } @@ -1378,7 +1399,7 @@ fn test_query_with_format_clause() { } else { assert_eq!( query.format_clause, - Some(FormatClause::Identifier(Ident::new(*format))) + Some(FormatClause::Identifier(Ident::new(*format).empty_span())) ); } } @@ -1464,12 +1485,12 @@ fn parse_freeze_and_unfreeze_partition() { let expected_operation = if operation_name == &"FREEZE" { AlterTableOperation::FreezePartition { partition: expected_partition, - with_name: Some(Ident::with_quote('\'', "hello")), + with_name: Some(Ident::with_quote('\'', "hello").empty_span()), } } else { AlterTableOperation::UnfreezePartition { partition: expected_partition, - with_name: Some(Ident::with_quote('\'', "hello")), + with_name: Some(Ident::with_quote('\'', "hello").empty_span()), } }; assert_eq!(operations[0], expected_operation); @@ -1528,16 +1549,16 @@ fn parse_select_table_function_settings() { "SELECT * FROM table_function(arg, SETTINGS s0 = 3, s1 = 's')", &TableFunctionArgs { args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier("arg".into()), + Expr::Identifier(Ident::new("arg").empty_span()), ))], settings: Some(vec![ Setting { - key: "s0".into(), + key: Ident::new("s0").empty_span(), value: Value::Number("3".parse().unwrap(), false), }, Setting { - key: "s1".into(), + key: Ident::new("s1").empty_span(), value: Value::SingleQuotedString("s".into()), }, ]), @@ -1547,7 +1568,7 @@ fn parse_select_table_function_settings() { r#"SELECT * FROM table_function(arg)"#, &TableFunctionArgs { args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier("arg".into()), + Expr::Identifier(Ident::new("arg").empty_span()), ))], settings: None, }, @@ -1558,11 +1579,11 @@ fn parse_select_table_function_settings() { args: vec![], settings: Some(vec![ Setting { - key: "s0".into(), + key: Ident::new("s0").empty_span(), value: Value::Number("3".parse().unwrap(), false), }, Setting { - key: "s1".into(), + key: Ident::new("s1").empty_span(), value: Value::SingleQuotedString("s".into()), }, ]), diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index a2eb5070d..236171637 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -49,6 +49,7 @@ mod test_utils; use pretty_assertions::assert_eq; use sqlparser::ast::ColumnOption::Comment; use sqlparser::ast::Expr::{Identifier, UnaryOp}; +use sqlparser::ast::SpanWrapped; use sqlparser::test_utils::all_dialects_except; #[test] @@ -100,7 +101,10 @@ fn parse_insert_values() { assert_eq!(table_name.to_string(), expected_table_name); assert_eq!(columns.len(), expected_columns.len()); for (index, column) in columns.iter().enumerate() { - assert_eq!(column, &Ident::new(expected_columns[index].clone())); + assert_eq!( + column, + &Ident::new(expected_columns[index].clone()).empty_span() + ); } match *source.body { SetExpr::Values(Values { rows, .. }) => { @@ -148,7 +152,10 @@ fn parse_insert_default_values() { assert_eq!(partitioned, None); assert_eq!(returning, None); assert_eq!(source, None); - assert_eq!(table_name, ObjectName(vec!["test_table".into()])); + assert_eq!( + table_name, + ObjectName(vec![Ident::new("test_table").empty_span()]) + ); } _ => unreachable!(), } @@ -173,7 +180,10 @@ fn parse_insert_default_values() { assert_eq!(partitioned, None); assert!(returning.is_some()); assert_eq!(source, None); - assert_eq!(table_name, ObjectName(vec!["test_table".into()])); + assert_eq!( + table_name, + ObjectName(vec![Ident::new("test_table").empty_span()]) + ); } _ => unreachable!(), } @@ -198,7 +208,10 @@ fn parse_insert_default_values() { assert_eq!(partitioned, None); assert_eq!(returning, None); assert_eq!(source, None); - assert_eq!(table_name, ObjectName(vec!["test_table".into()])); + assert_eq!( + table_name, + ObjectName(vec![Ident::new("test_table").empty_span()]) + ); } _ => unreachable!(), } @@ -303,20 +316,29 @@ fn parse_update() { assignments, vec![ Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec!["a".into()])), + target: AssignmentTarget::ColumnName(ObjectName(vec![ + Ident::new("a").empty_span() + ])), value: Expr::Value(number("1")), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec!["b".into()])), + target: AssignmentTarget::ColumnName(ObjectName(vec![ + Ident::new("b").empty_span() + ])), value: Expr::Value(number("2")), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec!["c".into()])), + target: AssignmentTarget::ColumnName(ObjectName(vec![ + Ident::new("c").empty_span() + ])), value: Expr::Value(number("3")), }, ] ); - assert_eq!(selection.unwrap(), Expr::Identifier("d".into())); + assert_eq!( + selection.unwrap(), + Expr::Identifier(Ident::new("d").empty_span()) + ); } _ => unreachable!(), } @@ -357,7 +379,7 @@ fn parse_update_set_from() { Statement::Update { table: TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("t1")]), + name: ObjectName(vec![Ident::new("t1").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -368,8 +390,13 @@ fn parse_update_set_from() { joins: vec![], }, assignments: vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new("name")])), - value: Expr::CompoundIdentifier(vec![Ident::new("t2"), Ident::new("name")]) + target: AssignmentTarget::ColumnName(ObjectName(vec![ + Ident::new("name").empty_span() + ])), + value: Expr::CompoundIdentifier(vec![ + Ident::new("t2").empty_span(), + Ident::new("name").empty_span() + ]) }], from: Some(TableWithJoins { relation: TableFactor::Derived { @@ -380,13 +407,17 @@ fn parse_update_set_from() { distinct: None, top: None, projection: vec![ - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name"))), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("id"))), + SelectItem::UnnamedExpr(Expr::Identifier( + Ident::new("name").empty_span() + )), + SelectItem::UnnamedExpr(Expr::Identifier( + Ident::new("id").empty_span() + )), ], into: None, from: vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("t1")]), + name: ObjectName(vec![Ident::new("t1").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -400,7 +431,7 @@ fn parse_update_set_from() { prewhere: None, selection: None, group_by: GroupByExpr::Expressions( - vec![Expr::Identifier(Ident::new("id"))], + vec![Expr::Identifier(Ident::new("id").empty_span())], vec![] ), cluster_by: vec![], @@ -424,7 +455,7 @@ fn parse_update_set_from() { format_clause: None, }), alias: Some(TableAlias { - name: Ident::new("t2"), + name: Ident::new("t2").empty_span(), columns: vec![], }) }, @@ -432,13 +463,13 @@ fn parse_update_set_from() { }), selection: Some(Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("t1"), - Ident::new("id") + Ident::new("t1").empty_span(), + Ident::new("id").empty_span(), ])), op: BinaryOperator::Eq, right: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("t2"), - Ident::new("id") + Ident::new("t2").empty_span(), + Ident::new("id").empty_span(), ])), }), returning: None, @@ -460,9 +491,9 @@ fn parse_update_with_table_alias() { assert_eq!( TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("users")]), + name: ObjectName(vec![Ident::new("users").empty_span()]), alias: Some(TableAlias { - name: Ident::new("u"), + name: Ident::new("u").empty_span(), columns: vec![], }), args: None, @@ -478,8 +509,8 @@ fn parse_update_with_table_alias() { assert_eq!( vec![Assignment { target: AssignmentTarget::ColumnName(ObjectName(vec![ - Ident::new("u"), - Ident::new("username") + Ident::new("u").empty_span(), + Ident::new("username").empty_span(), ])), value: Expr::Value(Value::SingleQuotedString("new_user".to_string())), }], @@ -488,8 +519,8 @@ fn parse_update_with_table_alias() { assert_eq!( Some(Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("u"), - Ident::new("username"), + Ident::new("u").empty_span(), + Ident::new("username").empty_span(), ])), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::SingleQuotedString( @@ -519,19 +550,23 @@ fn parse_select_with_table_alias() { assert_eq!( select.projection, vec![ - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("a")),), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("b")),), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("c")),), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("a").empty_span()),), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("b").empty_span()),), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("c").empty_span()),), ] ); assert_eq!( select.from, vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("lineitem")]), + name: ObjectName(vec![Ident::new("lineitem").empty_span()]), alias: Some(TableAlias { - name: Ident::new("l"), - columns: vec![Ident::new("A"), Ident::new("B"), Ident::new("C"),], + name: Ident::new("l").empty_span(), + columns: vec![ + Ident::new("A").empty_span(), + Ident::new("B").empty_span(), + Ident::new("C").empty_span(), + ], }), args: None, with_hints: vec![], @@ -568,7 +603,7 @@ fn parse_delete_statement() { }) => { assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::with_quote('"', "table")]), + name: ObjectName(vec![Ident::with_quote('"', "table").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -606,16 +641,25 @@ fn parse_delete_statement_for_multi_tables() { .. }) => { assert_eq!( - ObjectName(vec![Ident::new("schema1"), Ident::new("table1")]), + ObjectName(vec![ + Ident::new("schema1").empty_span(), + Ident::new("table1").empty_span() + ]), tables[0] ); assert_eq!( - ObjectName(vec![Ident::new("schema2"), Ident::new("table2")]), + ObjectName(vec![ + Ident::new("schema2").empty_span(), + Ident::new("table2").empty_span() + ]), tables[1] ); assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("schema1"), Ident::new("table1")]), + name: ObjectName(vec![ + Ident::new("schema1").empty_span(), + Ident::new("table1").empty_span() + ]), alias: None, args: None, with_hints: vec![], @@ -627,7 +671,10 @@ fn parse_delete_statement_for_multi_tables() { ); assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("schema2"), Ident::new("table2")]), + name: ObjectName(vec![ + Ident::new("schema2").empty_span(), + Ident::new("table2").empty_span() + ]), alias: None, args: None, with_hints: vec![], @@ -653,7 +700,10 @@ fn parse_delete_statement_for_multi_tables_with_using() { }) => { assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("schema1"), Ident::new("table1")]), + name: ObjectName(vec![ + Ident::new("schema1").empty_span(), + Ident::new("table1").empty_span() + ]), alias: None, args: None, with_hints: vec![], @@ -665,7 +715,10 @@ fn parse_delete_statement_for_multi_tables_with_using() { ); assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("schema2"), Ident::new("table2")]), + name: ObjectName(vec![ + Ident::new("schema2").empty_span(), + Ident::new("table2").empty_span() + ]), alias: None, args: None, with_hints: vec![], @@ -677,7 +730,10 @@ fn parse_delete_statement_for_multi_tables_with_using() { ); assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("schema1"), Ident::new("table1")]), + name: ObjectName(vec![ + Ident::new("schema1").empty_span(), + Ident::new("table1").empty_span() + ]), alias: None, args: None, with_hints: vec![], @@ -689,7 +745,10 @@ fn parse_delete_statement_for_multi_tables_with_using() { ); assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("schema2"), Ident::new("table2")]), + name: ObjectName(vec![ + Ident::new("schema2").empty_span(), + Ident::new("table2").empty_span() + ]), alias: None, args: None, with_hints: vec![], @@ -720,7 +779,7 @@ fn parse_where_delete_statement() { }) => { assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("foo")]), + name: ObjectName(vec![Ident::new("foo").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -734,7 +793,7 @@ fn parse_where_delete_statement() { assert_eq!(None, using); assert_eq!( Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("name"))), + left: Box::new(Expr::Identifier(Ident::new("name").empty_span())), op: Eq, right: Box::new(Expr::Value(number("5"))), }, @@ -762,9 +821,9 @@ fn parse_where_delete_with_alias_statement() { }) => { assert_eq!( TableFactor::Table { - name: ObjectName(vec![Ident::new("basket")]), + name: ObjectName(vec![Ident::new("basket").empty_span()]), alias: Some(TableAlias { - name: Ident::new("a"), + name: Ident::new("a").empty_span(), columns: vec![], }), args: None, @@ -778,9 +837,9 @@ fn parse_where_delete_with_alias_statement() { assert_eq!( Some(vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("basket")]), + name: ObjectName(vec![Ident::new("basket").empty_span()]), alias: Some(TableAlias { - name: Ident::new("b"), + name: Ident::new("b").empty_span(), columns: vec![], }), args: None, @@ -796,13 +855,13 @@ fn parse_where_delete_with_alias_statement() { assert_eq!( Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("a"), - Ident::new("id"), + Ident::new("a").empty_span(), + Ident::new("id").empty_span(), ])), op: Lt, right: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("b"), - Ident::new("id"), + Ident::new("b").empty_span(), + Ident::new("id").empty_span(), ])), }, selection.unwrap(), @@ -853,7 +912,7 @@ fn parse_select_distinct() { let select = verified_only_select(sql); assert!(select.distinct.is_some()); assert_eq!( - &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name"))), + &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name").empty_span())), only(&select.projection) ); } @@ -864,11 +923,11 @@ fn parse_select_distinct_two_fields() { let select = verified_only_select(sql); assert!(select.distinct.is_some()); assert_eq!( - &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name"))), + &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name").empty_span())), &select.projection[0] ); assert_eq!( - &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("id"))), + &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("id").empty_span())), &select.projection[1] ); } @@ -879,8 +938,8 @@ fn parse_select_distinct_tuple() { let select = verified_only_select(sql); assert_eq!( &vec![SelectItem::UnnamedExpr(Expr::Tuple(vec![ - Expr::Identifier(Ident::new("name")), - Expr::Identifier(Ident::new("id")), + Expr::Identifier(Ident::new("name").empty_span()), + Expr::Identifier(Ident::new("id").empty_span()), ]))], &select.projection ); @@ -891,7 +950,9 @@ fn parse_select_distinct_on() { let sql = "SELECT DISTINCT ON (album_id) name FROM track ORDER BY album_id, milliseconds"; let select = verified_only_select(sql); assert_eq!( - &Some(Distinct::On(vec![Expr::Identifier(Ident::new("album_id"))])), + &Some(Distinct::On(vec![Expr::Identifier( + Ident::new("album_id").empty_span() + )])), &select.distinct ); @@ -903,8 +964,8 @@ fn parse_select_distinct_on() { let select = verified_only_select(sql); assert_eq!( &Some(Distinct::On(vec![ - Expr::Identifier(Ident::new("album_id")), - Expr::Identifier(Ident::new("milliseconds")), + Expr::Identifier(Ident::new("album_id").empty_span()), + Expr::Identifier(Ident::new("milliseconds").empty_span()), ])), &select.distinct ); @@ -943,7 +1004,7 @@ fn parse_select_into() { temporary: false, unlogged: false, table: false, - name: ObjectName(vec![Ident::new("table0")]), + name: ObjectName(vec![Ident::new("table0").empty_span()]), }, only(&select.into) ); @@ -976,7 +1037,7 @@ fn parse_select_wildcard() { let select = verified_only_select(sql); assert_eq!( &SelectItem::QualifiedWildcard( - ObjectName(vec![Ident::new("foo")]), + ObjectName(vec![Ident::new("foo").empty_span()]), WildcardAdditionalOptions::default() ), only(&select.projection) @@ -986,7 +1047,10 @@ fn parse_select_wildcard() { let select = verified_only_select(sql); assert_eq!( &SelectItem::QualifiedWildcard( - ObjectName(vec![Ident::new("myschema"), Ident::new("mytable"),]), + ObjectName(vec![ + Ident::new("myschema").empty_span(), + Ident::new("mytable").empty_span(), + ]), WildcardAdditionalOptions::default(), ), only(&select.projection) @@ -1022,7 +1086,7 @@ fn parse_column_aliases() { { assert_eq!(&BinaryOperator::Plus, op); assert_eq!(&Expr::Value(number("1")), right.as_ref()); - assert_eq!(&Ident::new("newname"), alias); + assert_eq!(&Ident::new("newname").empty_span(), alias); } else { panic!("Expected: ExprWithAlias") } @@ -1063,7 +1127,7 @@ fn parse_select_count_wildcard() { let select = verified_only_select(sql); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("COUNT")]), + name: ObjectName(vec![Ident::new("COUNT").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -1085,13 +1149,13 @@ fn parse_select_count_distinct() { let select = verified_only_select(sql); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("COUNT")]), + name: ObjectName(vec![Ident::new("COUNT").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: Some(DuplicateTreatment::Distinct), args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::UnaryOp { op: UnaryOperator::Plus, - expr: Box::new(Expr::Identifier(Ident::new("x"))), + expr: Box::new(Expr::Identifier(Ident::new("x").empty_span())), }))], clauses: vec![], }), @@ -1209,11 +1273,11 @@ fn parse_exponent_in_select() -> Result<(), ParserError> { SelectItem::UnnamedExpr(Expr::Value(number("1e+3"))), SelectItem::ExprWithAlias { expr: Expr::Value(number("1e3")), - alias: Ident::new("a") + alias: Ident::new("a").empty_span(), }, SelectItem::ExprWithAlias { expr: Expr::Value(number("1")), - alias: Ident::new("e") + alias: Ident::new("e").empty_span(), }, SelectItem::UnnamedExpr(Expr::Value(number("0.5e2"))), ], @@ -1228,10 +1292,13 @@ fn parse_select_with_date_column_name() { let sql = "SELECT date"; let select = verified_only_select(sql); assert_eq!( - &Expr::Identifier(Ident { - value: "date".into(), - quote_style: None, - }), + &Expr::Identifier( + Ident { + value: "date".into(), + quote_style: None, + } + .empty_span() + ), expr_from_projection(only(&select.projection)), ); } @@ -1246,7 +1313,7 @@ fn parse_escaped_single_quote_string_predicate_with_escape() { assert_eq!( Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("salary"))), + left: Box::new(Expr::Identifier(Ident::new("salary").empty_span())), op: NotEq, right: Box::new(Expr::Value(Value::SingleQuotedString( "Jim's salary".to_string() @@ -1272,7 +1339,7 @@ fn parse_escaped_single_quote_string_predicate_with_no_escape() { assert_eq!( Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("salary"))), + left: Box::new(Expr::Identifier(Ident::new("salary").empty_span())), op: NotEq, right: Box::new(Expr::Value(Value::SingleQuotedString( "Jim''s salary".to_string() @@ -1303,12 +1370,12 @@ fn parse_compound_expr_1() { let sql = "a + b * c"; assert_eq!( BinaryOp { - left: Box::new(Identifier(Ident::new("a"))), + left: Box::new(Identifier(Ident::new("a").empty_span())), op: Plus, right: Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("b"))), + left: Box::new(Identifier(Ident::new("b").empty_span())), op: Multiply, - right: Box::new(Identifier(Ident::new("c"))), + right: Box::new(Identifier(Ident::new("c").empty_span())), }), }, verified_expr(sql) @@ -1323,12 +1390,12 @@ fn parse_compound_expr_2() { assert_eq!( BinaryOp { left: Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("a"))), + left: Box::new(Identifier(Ident::new("a").empty_span())), op: Multiply, - right: Box::new(Identifier(Ident::new("b"))), + right: Box::new(Identifier(Ident::new("b").empty_span())), }), op: Plus, - right: Box::new(Identifier(Ident::new("c"))), + right: Box::new(Identifier(Ident::new("c").empty_span())), }, verified_expr(sql) ); @@ -1342,12 +1409,12 @@ fn parse_unary_math_with_plus() { BinaryOp { left: Box::new(UnaryOp { op: UnaryOperator::Minus, - expr: Box::new(Identifier(Ident::new("a"))), + expr: Box::new(Identifier(Ident::new("a").empty_span())), }), op: BinaryOperator::Plus, right: Box::new(UnaryOp { op: UnaryOperator::Minus, - expr: Box::new(Identifier(Ident::new("b"))), + expr: Box::new(Identifier(Ident::new("b").empty_span())), }), }, verified_expr(sql) @@ -1362,12 +1429,12 @@ fn parse_unary_math_with_multiply() { BinaryOp { left: Box::new(UnaryOp { op: UnaryOperator::Minus, - expr: Box::new(Identifier(Ident::new("a"))), + expr: Box::new(Identifier(Ident::new("a").empty_span())), }), op: BinaryOperator::Multiply, right: Box::new(UnaryOp { op: UnaryOperator::Minus, - expr: Box::new(Identifier(Ident::new("b"))), + expr: Box::new(Identifier(Ident::new("b").empty_span())), }), }, verified_expr(sql) @@ -1380,9 +1447,9 @@ fn parse_mod() { let sql = "a % b"; assert_eq!( BinaryOp { - left: Box::new(Identifier(Ident::new("a"))), + left: Box::new(Identifier(Ident::new("a").empty_span())), op: BinaryOperator::Modulo, - right: Box::new(Identifier(Ident::new("b"))), + right: Box::new(Identifier(Ident::new("b").empty_span())), }, verified_expr(sql) ); @@ -1418,9 +1485,9 @@ fn parse_json_ops_without_colon() { let select = dialects.verified_only_select(&format!("SELECT a {} b", &str_op)); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), op, - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }), select.projection[0] ); @@ -1436,9 +1503,9 @@ fn parse_mod_no_spaces() { println!("Parsing {sql}"); assert_eq!( BinaryOp { - left: Box::new(Identifier(Ident::new("a1"))), + left: Box::new(Identifier(Ident::new("a1").empty_span())), op: BinaryOperator::Modulo, - right: Box::new(Identifier(Ident::new("b1"))), + right: Box::new(Identifier(Ident::new("b1").empty_span())), }, pg_and_generic().expr_parses_to(sql, canonical) ); @@ -1450,7 +1517,7 @@ fn parse_is_null() { use self::Expr::*; let sql = "a IS NULL"; assert_eq!( - IsNull(Box::new(Identifier(Ident::new("a")))), + IsNull(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); } @@ -1460,7 +1527,7 @@ fn parse_is_not_null() { use self::Expr::*; let sql = "a IS NOT NULL"; assert_eq!( - IsNotNull(Box::new(Identifier(Ident::new("a")))), + IsNotNull(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); } @@ -1471,8 +1538,8 @@ fn parse_is_distinct_from() { let sql = "a IS DISTINCT FROM b"; assert_eq!( IsDistinctFrom( - Box::new(Identifier(Ident::new("a"))), - Box::new(Identifier(Ident::new("b"))), + Box::new(Identifier(Ident::new("a").empty_span())), + Box::new(Identifier(Ident::new("b").empty_span())), ), verified_expr(sql) ); @@ -1484,8 +1551,8 @@ fn parse_is_not_distinct_from() { let sql = "a IS NOT DISTINCT FROM b"; assert_eq!( IsNotDistinctFrom( - Box::new(Identifier(Ident::new("a"))), - Box::new(Identifier(Ident::new("b"))), + Box::new(Identifier(Ident::new("a").empty_span())), + Box::new(Identifier(Ident::new("b").empty_span())), ), verified_expr(sql) ); @@ -1551,7 +1618,7 @@ fn parse_not_precedence() { Expr::UnaryOp { op: UnaryOperator::Not, expr: Box::new(Expr::InList { - expr: Box::new(Expr::Identifier("a".into())), + expr: Box::new(Expr::Identifier(Ident::new("a").empty_span())), list: vec![Expr::Value(Value::SingleQuotedString("a".into()))], negated: true, }), @@ -1569,7 +1636,7 @@ fn parse_null_like() { assert_eq!( SelectItem::ExprWithAlias { expr: Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("column1"))), + expr: Box::new(Expr::Identifier(Ident::new("column1").empty_span())), any: false, negated: false, pattern: Box::new(Expr::Value(Value::Null)), @@ -1578,7 +1645,8 @@ fn parse_null_like() { alias: Ident { value: "col_null".to_owned(), quote_style: None, - }, + } + .empty_span(), }, select.projection[0] ); @@ -1588,13 +1656,14 @@ fn parse_null_like() { expr: Box::new(Expr::Value(Value::Null)), any: false, negated: false, - pattern: Box::new(Expr::Identifier(Ident::new("column1"))), + pattern: Box::new(Expr::Identifier(Ident::new("column1").empty_span())), escape_char: None, }, alias: Ident { value: "null_col".to_owned(), quote_style: None, - }, + } + .empty_span(), }, select.projection[1] ); @@ -1610,7 +1679,7 @@ fn parse_ilike() { let select = verified_only_select(sql); assert_eq!( Expr::ILike { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -1627,7 +1696,7 @@ fn parse_ilike() { let select = verified_only_select(sql); assert_eq!( Expr::ILike { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('^'.to_string()), @@ -1645,7 +1714,7 @@ fn parse_ilike() { let select = verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::ILike { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -1668,7 +1737,7 @@ fn parse_like() { let select = verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -1685,7 +1754,7 @@ fn parse_like() { let select = verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('^'.to_string()), @@ -1703,7 +1772,7 @@ fn parse_like() { let select = verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -1726,7 +1795,7 @@ fn parse_similar_to() { let select = verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -1742,7 +1811,7 @@ fn parse_similar_to() { let select = verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('^'.to_string()), @@ -1758,7 +1827,7 @@ fn parse_similar_to() { let select = verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('^'.to_string()), @@ -1780,7 +1849,7 @@ fn parse_in_list() { let select = verified_only_select(sql); assert_eq!( Expr::InList { - expr: Box::new(Expr::Identifier(Ident::new("segment"))), + expr: Box::new(Expr::Identifier(Ident::new("segment").empty_span())), list: vec![ Expr::Value(Value::SingleQuotedString("HIGH".to_string())), Expr::Value(Value::SingleQuotedString("MED".to_string())), @@ -1800,7 +1869,7 @@ fn parse_in_subquery() { let select = verified_only_select(sql); assert_eq!( Expr::InSubquery { - expr: Box::new(Expr::Identifier(Ident::new("segment"))), + expr: Box::new(Expr::Identifier(Ident::new("segment").empty_span())), subquery: Box::new(verified_query("SELECT segm FROM bar")), negated: false, }, @@ -1818,7 +1887,7 @@ fn parse_in_unnest() { let select = verified_only_select(sql); assert_eq!( Expr::InUnnest { - expr: Box::new(Expr::Identifier(Ident::new("segment"))), + expr: Box::new(Expr::Identifier(Ident::new("segment").empty_span())), array_expr: Box::new(verified_expr("expr")), negated, }, @@ -1847,9 +1916,9 @@ fn parse_string_agg() { let select = verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), op: BinaryOperator::StringConcat, - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }), select.projection[0] ); @@ -1878,9 +1947,9 @@ fn parse_bitwise_ops() { let select = dialects.verified_only_select(&format!("SELECT a {} b", &str_op)); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), op: op.clone(), - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }), select.projection[0] ); @@ -1892,9 +1961,9 @@ fn parse_binary_any() { let select = verified_only_select("SELECT a = ANY(b)"); assert_eq!( SelectItem::UnnamedExpr(Expr::AnyOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), compare_op: BinaryOperator::Eq, - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), is_some: false, }), select.projection[0] @@ -1906,9 +1975,9 @@ fn parse_binary_all() { let select = verified_only_select("SELECT a = ALL(b)"); assert_eq!( SelectItem::UnnamedExpr(Expr::AllOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), compare_op: BinaryOperator::Eq, - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }), select.projection[0] ); @@ -1962,7 +2031,7 @@ fn parse_between() { let select = verified_only_select(sql); assert_eq!( Expr::Between { - expr: Box::new(Expr::Identifier(Ident::new("age"))), + expr: Box::new(Expr::Identifier(Ident::new("age").empty_span())), low: Box::new(Expr::Value(number("25"))), high: Box::new(Expr::Value(number("32"))), negated, @@ -2011,7 +2080,7 @@ fn parse_between_with_expr() { expr: Box::new(Expr::BinaryOp { left: Box::new(Expr::Value(number("1"))), op: BinaryOperator::Plus, - right: Box::new(Expr::Identifier(Ident::new("x"))), + right: Box::new(Expr::Identifier(Ident::new("x").empty_span())), }), low: Box::new(Expr::Value(number("1"))), high: Box::new(Expr::Value(number("2"))), @@ -2036,7 +2105,7 @@ fn parse_tuples() { SelectItem::UnnamedExpr(Expr::Tuple(vec![ Expr::Value(Value::SingleQuotedString("foo".into())), Expr::Value(number("3")), - Expr::Identifier(Ident::new("baz")), + Expr::Identifier(Ident::new("baz").empty_span()), ])), ], select.projection @@ -2067,19 +2136,19 @@ fn parse_select_order_by() { assert_eq!( vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("lname")), + expr: Expr::Identifier(Ident::new("lname").empty_span()), asc: Some(true), nulls_first: None, with_fill: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("fname")), + expr: Expr::Identifier(Ident::new("fname").empty_span()), asc: Some(false), nulls_first: None, with_fill: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("id")), + expr: Expr::Identifier(Ident::new("id").empty_span()), asc: None, nulls_first: None, with_fill: None, @@ -2102,13 +2171,13 @@ fn parse_select_order_by_limit() { assert_eq!( vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("lname")), + expr: Expr::Identifier(Ident::new("lname").empty_span()), asc: Some(true), nulls_first: None, with_fill: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("fname")), + expr: Expr::Identifier(Ident::new("fname").empty_span()), asc: Some(false), nulls_first: None, with_fill: None, @@ -2127,13 +2196,13 @@ fn parse_select_order_by_nulls_order() { assert_eq!( vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("lname")), + expr: Expr::Identifier(Ident::new("lname").empty_span()), asc: Some(true), nulls_first: Some(true), with_fill: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("fname")), + expr: Expr::Identifier(Ident::new("fname").empty_span()), asc: Some(false), nulls_first: Some(false), with_fill: None, @@ -2151,8 +2220,8 @@ fn parse_select_group_by() { assert_eq!( GroupByExpr::Expressions( vec![ - Expr::Identifier(Ident::new("lname")), - Expr::Identifier(Ident::new("fname")), + Expr::Identifier(Ident::new("lname").empty_span()), + Expr::Identifier(Ident::new("fname").empty_span()), ], vec![] ), @@ -2185,7 +2254,7 @@ fn parse_select_having() { assert_eq!( Some(Expr::BinaryOp { left: Box::new(Expr::Function(Function { - name: ObjectName(vec![Ident::new("COUNT")]), + name: ObjectName(vec![Ident::new("COUNT").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -2215,7 +2284,7 @@ fn parse_select_qualify() { assert_eq!( Some(Expr::BinaryOp { left: Box::new(Expr::Function(Function { - name: ObjectName(vec![Ident::new("ROW_NUMBER")]), + name: ObjectName(vec![Ident::new("ROW_NUMBER").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -2226,9 +2295,9 @@ fn parse_select_qualify() { filter: None, over: Some(WindowType::WindowSpec(WindowSpec { window_name: None, - partition_by: vec![Expr::Identifier(Ident::new("p"))], + partition_by: vec![Expr::Identifier(Ident::new("p").empty_span())], order_by: vec![OrderByExpr { - expr: Expr::Identifier(Ident::new("o")), + expr: Expr::Identifier(Ident::new("o").empty_span()), asc: None, nulls_first: None, with_fill: None, @@ -2247,7 +2316,7 @@ fn parse_select_qualify() { let select = verified_only_select(sql); assert_eq!( Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("row_num"))), + left: Box::new(Expr::Identifier(Ident::new("row_num").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(number("1"))), }), @@ -2270,7 +2339,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::BigInt(None), format: None, }, @@ -2282,7 +2351,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::TinyInt(None), format: None, }, @@ -2310,7 +2379,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Nvarchar(Some(CharacterLength::IntegerLength { length: 50, unit: None, @@ -2325,7 +2394,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Clob(None), format: None, }, @@ -2337,7 +2406,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Clob(Some(50)), format: None, }, @@ -2349,7 +2418,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Binary(Some(50)), format: None, }, @@ -2361,7 +2430,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Varbinary(Some(50)), format: None, }, @@ -2373,7 +2442,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Blob(None), format: None, }, @@ -2385,7 +2454,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Blob(Some(50)), format: None, }, @@ -2397,7 +2466,7 @@ fn parse_cast() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("details"))), + expr: Box::new(Expr::Identifier(Ident::new("details").empty_span())), data_type: DataType::JSONB, format: None, }, @@ -2412,7 +2481,7 @@ fn parse_try_cast() { assert_eq!( &Expr::Cast { kind: CastKind::TryCast, - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::BigInt(None), format: None, }, @@ -2435,7 +2504,7 @@ fn parse_extract() { &Expr::Extract { field: DateTimeField::Year, syntax: ExtractSyntax::From, - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), }, expr_from_projection(only(&select.projection)), ); @@ -2518,7 +2587,7 @@ fn parse_ceil_scale() { #[cfg(feature = "bigdecimal")] assert_eq!( &Expr::Ceil { - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), field: CeilFloorKind::Scale(Value::Number(bigdecimal::BigDecimal::from(2), false)), }, expr_from_projection(only(&select.projection)), @@ -2527,7 +2596,7 @@ fn parse_ceil_scale() { #[cfg(not(feature = "bigdecimal"))] assert_eq!( &Expr::Ceil { - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), field: CeilFloorKind::Scale(Value::Number(2.to_string(), false)), }, expr_from_projection(only(&select.projection)), @@ -2542,7 +2611,7 @@ fn parse_floor_scale() { #[cfg(feature = "bigdecimal")] assert_eq!( &Expr::Floor { - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), field: CeilFloorKind::Scale(Value::Number(bigdecimal::BigDecimal::from(2), false)), }, expr_from_projection(only(&select.projection)), @@ -2551,7 +2620,7 @@ fn parse_floor_scale() { #[cfg(not(feature = "bigdecimal"))] assert_eq!( &Expr::Floor { - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), field: CeilFloorKind::Scale(Value::Number(2.to_string(), false)), }, expr_from_projection(only(&select.projection)), @@ -2564,7 +2633,7 @@ fn parse_ceil_datetime() { let select = verified_only_select(sql); assert_eq!( &Expr::Ceil { - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), field: CeilFloorKind::DateTimeField(DateTimeField::Day), }, expr_from_projection(only(&select.projection)), @@ -2591,7 +2660,7 @@ fn parse_floor_datetime() { let select = verified_only_select(sql); assert_eq!( &Expr::Floor { - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), field: CeilFloorKind::DateTimeField(DateTimeField::Day), }, expr_from_projection(only(&select.projection)), @@ -2621,14 +2690,14 @@ fn parse_listagg() { assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("LISTAGG")]), + name: ObjectName(vec![Ident::new("LISTAGG").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: Some(DuplicateTreatment::Distinct), args: vec![ - FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new( - "dateid" - )))), + FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier( + Ident::new("dateid").empty_span() + ))), FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value( Value::SingleQuotedString(", ".to_owned()) ))) @@ -2647,19 +2716,25 @@ fn parse_listagg() { over: None, within_group: vec![ OrderByExpr { - expr: Expr::Identifier(Ident { - value: "id".to_string(), - quote_style: None, - }), + expr: Expr::Identifier( + Ident { + value: "id".to_string(), + quote_style: None, + } + .empty_span() + ), asc: None, nulls_first: None, with_fill: None, }, OrderByExpr { - expr: Expr::Identifier(Ident { - value: "username".to_string(), - quote_style: None, - }), + expr: Expr::Identifier( + Ident { + value: "username".to_string(), + quote_style: None, + } + .empty_span() + ), asc: None, nulls_first: None, with_fill: None, @@ -2773,7 +2848,10 @@ fn parse_window_function_null_treatment_arg() { let SelectItem::UnnamedExpr(Expr::Function(actual)) = &projection[i] else { unreachable!() }; - assert_eq!(ObjectName(vec![Ident::new("FIRST_VALUE")]), actual.name); + assert_eq!( + ObjectName(vec![Ident::new("FIRST_VALUE").empty_span()]), + actual.name + ); let FunctionArguments::List(arg_list) = &actual.args else { panic!("expected argument list") }; @@ -2789,7 +2867,7 @@ fn parse_window_function_null_treatment_arg() { else { unreachable!() }; - assert_eq!(&Ident::new(expected_expr), actual_expr); + assert_eq!(&Ident::new(expected_expr).empty_span(), actual_expr); assert_eq!( Some(expected_null_treatment), arg_list.clauses.iter().find_map(|clause| match clause { @@ -2871,7 +2949,7 @@ fn parse_create_table() { columns, vec![ ColumnDef { - name: "name".into(), + name: Ident::new("name").empty_span(), data_type: DataType::Varchar(Some(CharacterLength::IntegerLength { length: 100, unit: None, @@ -2883,7 +2961,7 @@ fn parse_create_table() { }], }, ColumnDef { - name: "lat".into(), + name: Ident::new("lat").empty_span(), data_type: DataType::Double, collation: None, options: vec![ColumnOptionDef { @@ -2892,13 +2970,13 @@ fn parse_create_table() { }], }, ColumnDef { - name: "lng".into(), + name: Ident::new("lng").empty_span(), data_type: DataType::Double, collation: None, options: vec![], }, ColumnDef { - name: "constrained".into(), + name: Ident::new("constrained").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ @@ -2907,7 +2985,7 @@ fn parse_create_table() { option: ColumnOption::Null, }, ColumnOptionDef { - name: Some("pkey".into()), + name: Some(Ident::new("pkey").empty_span()), option: ColumnOption::Unique { is_primary: true, characteristics: None @@ -2931,14 +3009,19 @@ fn parse_create_table() { ], }, ColumnDef { - name: "ref".into(), + name: Ident::new("ref").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { name: None, option: ColumnOption::ForeignKey { - foreign_table: ObjectName(vec!["othertable".into()]), - referred_columns: vec!["a".into(), "b".into()], + foreign_table: ObjectName(vec![ + Ident::new("othertable").empty_span() + ]), + referred_columns: vec![ + Ident::new("a").empty_span(), + Ident::new("b").empty_span() + ], on_delete: None, on_update: None, characteristics: None, @@ -2946,13 +3029,15 @@ fn parse_create_table() { }], }, ColumnDef { - name: "ref2".into(), + name: Ident::new("ref2").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { name: None, option: ColumnOption::ForeignKey { - foreign_table: ObjectName(vec!["othertable2".into()]), + foreign_table: ObjectName(vec![ + Ident::new("othertable2").empty_span() + ]), referred_columns: vec![], on_delete: Some(ReferentialAction::Cascade), on_update: Some(ReferentialAction::NoAction), @@ -2966,37 +3051,37 @@ fn parse_create_table() { constraints, vec![ TableConstraint::ForeignKey { - name: Some("fkey".into()), - columns: vec!["lat".into()], - foreign_table: ObjectName(vec!["othertable3".into()]), - referred_columns: vec!["lat".into()], + name: Some(Ident::new("fkey").empty_span()), + columns: vec![Ident::new("lat").empty_span()], + foreign_table: ObjectName(vec![Ident::new("othertable3").empty_span()]), + referred_columns: vec![Ident::new("lat").empty_span()], on_delete: Some(ReferentialAction::Restrict), on_update: None, characteristics: None, }, TableConstraint::ForeignKey { - name: Some("fkey2".into()), - columns: vec!["lat".into()], - foreign_table: ObjectName(vec!["othertable4".into()]), - referred_columns: vec!["lat".into()], + name: Some(Ident::new("fkey2").empty_span()), + columns: vec![Ident::new("lat").empty_span()], + foreign_table: ObjectName(vec![Ident::new("othertable4").empty_span()]), + referred_columns: vec![Ident::new("lat").empty_span()], on_delete: Some(ReferentialAction::NoAction), on_update: Some(ReferentialAction::Restrict), characteristics: None, }, TableConstraint::ForeignKey { name: None, - columns: vec!["lat".into()], - foreign_table: ObjectName(vec!["othertable4".into()]), - referred_columns: vec!["lat".into()], + columns: vec![Ident::new("lat").empty_span()], + foreign_table: ObjectName(vec![Ident::new("othertable4").empty_span()]), + referred_columns: vec![Ident::new("lat").empty_span()], on_delete: Some(ReferentialAction::Cascade), on_update: Some(ReferentialAction::SetDefault), characteristics: None, }, TableConstraint::ForeignKey { name: None, - columns: vec!["lng".into()], - foreign_table: ObjectName(vec!["othertable4".into()]), - referred_columns: vec!["longitude".into()], + columns: vec![Ident::new("lng").empty_span()], + foreign_table: ObjectName(vec![Ident::new("othertable4").empty_span()]), + referred_columns: vec![Ident::new("longitude").empty_span()], on_delete: None, on_update: Some(ReferentialAction::SetNull), characteristics: None, @@ -3060,7 +3145,7 @@ fn parse_create_table_with_constraint_characteristics() { columns, vec![ ColumnDef { - name: "name".into(), + name: Ident::new("name").empty_span(), data_type: DataType::Varchar(Some(CharacterLength::IntegerLength { length: 100, unit: None, @@ -3072,7 +3157,7 @@ fn parse_create_table_with_constraint_characteristics() { }], }, ColumnDef { - name: "lat".into(), + name: Ident::new("lat").empty_span(), data_type: DataType::Double, collation: None, options: vec![ColumnOptionDef { @@ -3081,7 +3166,7 @@ fn parse_create_table_with_constraint_characteristics() { }], }, ColumnDef { - name: "lng".into(), + name: Ident::new("lng").empty_span(), data_type: DataType::Double, collation: None, options: vec![], @@ -3092,10 +3177,10 @@ fn parse_create_table_with_constraint_characteristics() { constraints, vec![ TableConstraint::ForeignKey { - name: Some("fkey".into()), - columns: vec!["lat".into()], - foreign_table: ObjectName(vec!["othertable3".into()]), - referred_columns: vec!["lat".into()], + name: Some(Ident::new("fkey").empty_span()), + columns: vec![Ident::new("lat").empty_span()], + foreign_table: ObjectName(vec![Ident::new("othertable3").empty_span()]), + referred_columns: vec![Ident::new("lat").empty_span()], on_delete: Some(ReferentialAction::Restrict), on_update: None, characteristics: Some(ConstraintCharacteristics { @@ -3105,10 +3190,10 @@ fn parse_create_table_with_constraint_characteristics() { }), }, TableConstraint::ForeignKey { - name: Some("fkey2".into()), - columns: vec!["lat".into()], - foreign_table: ObjectName(vec!["othertable4".into()]), - referred_columns: vec!["lat".into()], + name: Some(Ident::new("fkey2").empty_span()), + columns: vec![Ident::new("lat").empty_span()], + foreign_table: ObjectName(vec![Ident::new("othertable4").empty_span()]), + referred_columns: vec![Ident::new("lat").empty_span()], on_delete: Some(ReferentialAction::NoAction), on_update: Some(ReferentialAction::Restrict), characteristics: Some(ConstraintCharacteristics { @@ -3119,9 +3204,9 @@ fn parse_create_table_with_constraint_characteristics() { }, TableConstraint::ForeignKey { name: None, - columns: vec!["lat".into()], - foreign_table: ObjectName(vec!["othertable4".into()]), - referred_columns: vec!["lat".into()], + columns: vec![Ident::new("lat").empty_span()], + foreign_table: ObjectName(vec![Ident::new("othertable4").empty_span()]), + referred_columns: vec![Ident::new("lat").empty_span()], on_delete: Some(ReferentialAction::Cascade), on_update: Some(ReferentialAction::SetDefault), characteristics: Some(ConstraintCharacteristics { @@ -3132,9 +3217,9 @@ fn parse_create_table_with_constraint_characteristics() { }, TableConstraint::ForeignKey { name: None, - columns: vec!["lng".into()], - foreign_table: ObjectName(vec!["othertable4".into()]), - referred_columns: vec!["longitude".into()], + columns: vec![Ident::new("lng").empty_span()], + foreign_table: ObjectName(vec![Ident::new("othertable4").empty_span()]), + referred_columns: vec![Ident::new("longitude").empty_span()], on_delete: None, on_update: Some(ReferentialAction::SetNull), characteristics: Some(ConstraintCharacteristics { @@ -3216,7 +3301,7 @@ fn parse_create_table_column_constraint_characteristics() { assert_eq!( columns, vec![ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -3326,18 +3411,18 @@ fn parse_create_table_hive_array() { .. }) => { assert!(if_not_exists); - assert_eq!(name, ObjectName(vec!["something".into()])); + assert_eq!(name, ObjectName(vec![Ident::new("something").empty_span()])); assert_eq!( columns, vec![ ColumnDef { - name: Ident::new("name"), + name: Ident::new("name").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("val"), + name: Ident::new("val").empty_span(), data_type: DataType::Array(expected), collation: None, options: vec![], @@ -3523,7 +3608,7 @@ fn parse_create_table_as_table() { match verified_stmt(sql1) { Statement::CreateTable(CreateTable { query, name, .. }) => { - assert_eq!(name, ObjectName(vec![Ident::new("new_table")])); + assert_eq!(name, ObjectName(vec![Ident::new("new_table").empty_span()])); assert_eq!(query.unwrap(), expected_query1); } _ => unreachable!(), @@ -3550,7 +3635,7 @@ fn parse_create_table_as_table() { match verified_stmt(sql2) { Statement::CreateTable(CreateTable { query, name, .. }) => { - assert_eq!(name, ObjectName(vec![Ident::new("new_table")])); + assert_eq!(name, ObjectName(vec![Ident::new("new_table").empty_span()])); assert_eq!(query.unwrap(), expected_query2); } _ => unreachable!(), @@ -3633,11 +3718,11 @@ fn parse_create_table_with_options() { assert_eq!( vec![ SqlOption::KeyValue { - key: "foo".into(), + key: Ident::new("foo").empty_span(), value: Expr::Value(Value::SingleQuotedString("bar".into())), }, SqlOption::KeyValue { - key: "a".into(), + key: Ident::new("a").empty_span(), value: Expr::Value(number("123")), }, ], @@ -3653,8 +3738,11 @@ fn parse_create_table_clone() { let sql = "CREATE OR REPLACE TABLE a CLONE a_tmp"; match verified_stmt(sql) { Statement::CreateTable(CreateTable { name, clone, .. }) => { - assert_eq!(ObjectName(vec![Ident::new("a")]), name); - assert_eq!(Some(ObjectName(vec![(Ident::new("a_tmp"))])), clone) + assert_eq!(ObjectName(vec![Ident::new("a").empty_span()]), name); + assert_eq!( + Some(ObjectName(vec![(Ident::new("a_tmp").empty_span())])), + clone + ) } _ => unreachable!(), } @@ -3700,7 +3788,7 @@ fn parse_create_external_table() { columns, vec![ ColumnDef { - name: "name".into(), + name: Ident::new("name").empty_span(), data_type: DataType::Varchar(Some(CharacterLength::IntegerLength { length: 100, unit: None, @@ -3712,7 +3800,7 @@ fn parse_create_external_table() { }], }, ColumnDef { - name: "lat".into(), + name: Ident::new("lat").empty_span(), data_type: DataType::Double, collation: None, options: vec![ColumnOptionDef { @@ -3721,7 +3809,7 @@ fn parse_create_external_table() { }], }, ColumnDef { - name: "lng".into(), + name: Ident::new("lng").empty_span(), data_type: DataType::Double, collation: None, options: vec![], @@ -3771,7 +3859,7 @@ fn parse_create_or_replace_external_table() { assert_eq!( columns, vec![ColumnDef { - name: "name".into(), + name: Ident::new("name").empty_span(), data_type: DataType::Varchar(Some(CharacterLength::IntegerLength { length: 100, unit: None, @@ -3866,7 +3954,8 @@ fn parse_alter_table() { key: Ident { value: "classification".to_string(), quote_style: Some('\'') - }, + } + .empty_span(), value: Expr::Value(Value::SingleQuotedString("parquet".to_string())), }], ); @@ -3884,7 +3973,10 @@ fn test_alter_table_with_on_cluster() { name, on_cluster, .. } => { std::assert_eq!(name.to_string(), "t"); - std::assert_eq!(on_cluster, Some(Ident::with_quote('\'', "cluster"))); + std::assert_eq!( + on_cluster, + Some(Ident::with_quote('\'', "cluster").empty_span()) + ); } _ => unreachable!(), } @@ -3896,7 +3988,7 @@ fn test_alter_table_with_on_cluster() { name, on_cluster, .. } => { std::assert_eq!(name.to_string(), "t"); - std::assert_eq!(on_cluster, Some(Ident::new("cluster_name"))); + std::assert_eq!(on_cluster, Some(Ident::new("cluster_name").empty_span())); } _ => unreachable!(), } @@ -3935,7 +4027,7 @@ fn parse_alter_view() { with_options, } => { assert_eq!("myschema.myview", name.to_string()); - assert_eq!(Vec::::new(), columns); + assert_eq!(columns, vec![]); assert_eq!("SELECT foo FROM bar", query.to_string()); assert_eq!(with_options, vec![]); } @@ -3951,11 +4043,11 @@ fn parse_alter_view_with_options() { assert_eq!( vec![ SqlOption::KeyValue { - key: "foo".into(), + key: Ident::new("foo").empty_span(), value: Expr::Value(Value::SingleQuotedString("bar".into())), }, SqlOption::KeyValue { - key: "a".into(), + key: Ident::new("a").empty_span(), value: Expr::Value(number("123")), }, ], @@ -3977,7 +4069,13 @@ fn parse_alter_view_with_columns() { with_options, } => { assert_eq!("v", name.to_string()); - assert_eq!(columns, vec![Ident::new("has"), Ident::new("cols")]); + assert_eq!( + columns, + vec![ + Ident::new("has").empty_span(), + Ident::new("cols").empty_span() + ] + ); assert_eq!("SELECT 1, 2", query.to_string()); assert_eq!(with_options, vec![]); } @@ -4235,7 +4333,10 @@ fn parse_scalar_function_in_projection() { let sql = format!("SELECT {function_name}(id) FROM foo"); let select = verified_only_select(&sql); assert_eq!( - &call(function_name, [Expr::Identifier(Ident::new("id"))]), + &call( + function_name, + [Expr::Identifier(Ident::new("id").empty_span())] + ), expr_from_projection(only(&select.projection)) ); } @@ -4415,20 +4516,20 @@ fn parse_named_argument_function() { assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("FUN")]), + name: ObjectName(vec![Ident::new("FUN").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, args: vec![ FunctionArg::Named { - name: Ident::new("a"), + name: Ident::new("a").empty_span(), arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( "1".to_owned() ))), operator: FunctionArgOperator::RightArrow }, FunctionArg::Named { - name: Ident::new("b"), + name: Ident::new("b").empty_span(), arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( "2".to_owned() ))), @@ -4454,20 +4555,20 @@ fn parse_named_argument_function_with_eq_operator() { .verified_only_select(sql); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("FUN")]), + name: ObjectName(vec![Ident::new("FUN").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, args: vec![ FunctionArg::Named { - name: Ident::new("a"), + name: Ident::new("a").empty_span(), arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( "1".to_owned() ))), operator: FunctionArgOperator::Equals }, FunctionArg::Named { - name: Ident::new("b"), + name: Ident::new("b").empty_span(), arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( "2".to_owned() ))), @@ -4492,7 +4593,7 @@ fn parse_named_argument_function_with_eq_operator() { call( "foo", [Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("bar"))), + left: Box::new(Expr::Identifier(Ident::new("bar").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(number("42"))), }] @@ -4528,7 +4629,7 @@ fn parse_window_functions() { assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("row_number")]), + name: ObjectName(vec![Ident::new("row_number").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -4541,7 +4642,7 @@ fn parse_window_functions() { window_name: None, partition_by: vec![], order_by: vec![OrderByExpr { - expr: Expr::Identifier(Ident::new("dt")), + expr: Expr::Identifier(Ident::new("dt").empty_span()), asc: Some(false), nulls_first: None, with_fill: None, @@ -4594,11 +4695,11 @@ fn parse_named_window_functions() { expr_from_projection(&select.projection[i]), Expr::Function(Function { over: Some(WindowType::WindowSpec(WindowSpec { - window_name: Some(Ident { value, .. }), + window_name: Some(wnd), .. })), .. - }) if value == win_name + }) if wnd.value == *win_name )); } @@ -4655,60 +4756,76 @@ fn test_parse_named_window() { name: ObjectName(vec![Ident { value: "MIN".to_string(), quote_style: None, - }]), + } + .empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident { - value: "c12".to_string(), - quote_style: None, - }), + Expr::Identifier( + Ident { + value: "c12".to_string(), + quote_style: None, + } + .empty_span(), + ), ))], clauses: vec![], }), null_treatment: None, filter: None, - over: Some(WindowType::NamedWindow(Ident { - value: "window1".to_string(), - quote_style: None, - })), + over: Some(WindowType::NamedWindow( + Ident { + value: "window1".to_string(), + quote_style: None, + } + .empty_span(), + )), within_group: vec![], }), alias: Ident { value: "min1".to_string(), quote_style: None, - }, + } + .empty_span(), }, SelectItem::ExprWithAlias { expr: Expr::Function(Function { name: ObjectName(vec![Ident { value: "MAX".to_string(), quote_style: None, - }]), + } + .empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident { - value: "c12".to_string(), - quote_style: None, - }), + Expr::Identifier( + Ident { + value: "c12".to_string(), + quote_style: None, + } + .empty_span(), + ), ))], clauses: vec![], }), null_treatment: None, filter: None, - over: Some(WindowType::NamedWindow(Ident { - value: "window2".to_string(), - quote_style: None, - })), + over: Some(WindowType::NamedWindow( + Ident { + value: "window2".to_string(), + quote_style: None, + } + .empty_span(), + )), within_group: vec![], }), alias: Ident { value: "max1".to_string(), quote_style: None, - }, + } + .empty_span(), }, ], into: None, @@ -4717,7 +4834,8 @@ fn test_parse_named_window() { name: ObjectName(vec![Ident { value: "aggregate_test_100".to_string(), quote_style: None, - }]), + } + .empty_span()]), alias: None, args: None, with_hints: vec![], @@ -4740,15 +4858,19 @@ fn test_parse_named_window() { Ident { value: "window1".to_string(), quote_style: None, - }, + } + .empty_span(), NamedWindowExpr::WindowSpec(WindowSpec { window_name: None, partition_by: vec![], order_by: vec![OrderByExpr { - expr: Expr::Identifier(Ident { - value: "C12".to_string(), - quote_style: None, - }), + expr: Expr::Identifier( + Ident { + value: "C12".to_string(), + quote_style: None, + } + .empty_span(), + ), asc: None, nulls_first: None, with_fill: None, @@ -4760,13 +4882,17 @@ fn test_parse_named_window() { Ident { value: "window2".to_string(), quote_style: None, - }, + } + .empty_span(), NamedWindowExpr::WindowSpec(WindowSpec { window_name: None, - partition_by: vec![Expr::Identifier(Ident { - value: "C11".to_string(), - quote_style: None, - })], + partition_by: vec![Expr::Identifier( + Ident { + value: "C11".to_string(), + quote_style: None, + } + .empty_span(), + )], order_by: vec![], window_frame: None, }), @@ -4809,8 +4935,8 @@ fn parse_window_clause_named_window() { .verified_only_select(sql); assert_eq!( vec![NamedWindowDefinition( - Ident::new("window1"), - NamedWindowExpr::NamedWindow(Ident::new("window2")) + Ident::new("window1").empty_span(), + NamedWindowExpr::NamedWindow(Ident::new("window2").empty_span()) )], named_window ); @@ -5244,10 +5370,13 @@ fn interval_disallow_interval_expr_gt() { fractional_seconds_precision: None, },)), op: BinaryOperator::Gt, - right: Box::new(Expr::Identifier(Ident { - value: "x".to_string(), - quote_style: None, - })), + right: Box::new(Expr::Identifier( + Ident { + value: "x".to_string(), + quote_style: None, + } + .empty_span() + )), } ) } @@ -5289,17 +5418,21 @@ fn parse_interval_and_or_xor() { body: Box::new(SetExpr::Select(Box::new(Select { distinct: None, top: None, - projection: vec![UnnamedExpr(Expr::Identifier(Ident { - value: "col".to_string(), - quote_style: None, - }))], + projection: vec![UnnamedExpr(Expr::Identifier( + Ident { + value: "col".to_string(), + quote_style: None, + } + .empty_span(), + ))], into: None, from: vec![TableWithJoins { relation: TableFactor::Table { name: ObjectName(vec![Ident { value: "test".to_string(), quote_style: None, - }]), + } + .empty_span()]), alias: None, args: None, with_hints: vec![], @@ -5313,16 +5446,22 @@ fn parse_interval_and_or_xor() { prewhere: None, selection: Some(Expr::BinaryOp { left: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "d3_date".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "d3_date".to_string(), + quote_style: None, + } + .empty_span(), + )), op: BinaryOperator::Gt, right: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "d1_date".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "d1_date".to_string(), + quote_style: None, + } + .empty_span(), + )), op: BinaryOperator::Plus, right: Box::new(Expr::Interval(Interval { value: Box::new(Expr::Value(Value::SingleQuotedString( @@ -5337,16 +5476,22 @@ fn parse_interval_and_or_xor() { }), op: BinaryOperator::And, right: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "d2_date".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "d2_date".to_string(), + quote_style: None, + } + .empty_span(), + )), op: BinaryOperator::Gt, right: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "d1_date".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "d1_date".to_string(), + quote_style: None, + } + .empty_span(), + )), op: BinaryOperator::Plus, right: Box::new(Expr::Interval(Interval { value: Box::new(Expr::Value(Value::SingleQuotedString( @@ -5437,7 +5582,8 @@ fn parse_at_timezone() { alias: Ident { value: "hour".to_string(), quote_style: Some('"'), - }, + } + .empty_span(), }, only(&select.projection), ); @@ -5653,10 +5799,10 @@ fn parse_unnest_in_from_clause() { vec![TableWithJoins { relation: TableFactor::UNNEST { alias: Some(TableAlias { - name: Ident::new("numbers"), + name: Ident::new("numbers").empty_span(), columns: vec![], }), - array_exprs: vec![Expr::Identifier(Ident::new("expr"))], + array_exprs: vec![Expr::Identifier(Ident::new("expr").empty_span())], with_offset: true, with_offset_alias: None, with_ordinality: false, @@ -5674,7 +5820,7 @@ fn parse_unnest_in_from_clause() { vec![TableWithJoins { relation: TableFactor::UNNEST { alias: None, - array_exprs: vec![Expr::Identifier(Ident::new("expr"))], + array_exprs: vec![Expr::Identifier(Ident::new("expr").empty_span())], with_offset: false, with_offset_alias: None, with_ordinality: false, @@ -5692,7 +5838,7 @@ fn parse_unnest_in_from_clause() { vec![TableWithJoins { relation: TableFactor::UNNEST { alias: None, - array_exprs: vec![Expr::Identifier(Ident::new("expr"))], + array_exprs: vec![Expr::Identifier(Ident::new("expr").empty_span())], with_offset: true, with_offset_alias: None, with_ordinality: false, @@ -5710,10 +5856,10 @@ fn parse_unnest_in_from_clause() { vec![TableWithJoins { relation: TableFactor::UNNEST { alias: Some(TableAlias { - name: Ident::new("numbers"), + name: Ident::new("numbers").empty_span(), columns: vec![], }), - array_exprs: vec![Expr::Identifier(Ident::new("expr"))], + array_exprs: vec![Expr::Identifier(Ident::new("expr").empty_span())], with_offset: false, with_offset_alias: None, with_ordinality: false, @@ -5787,15 +5933,15 @@ fn parse_parens() { assert_eq!( BinaryOp { left: Box::new(Nested(Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("a"))), + left: Box::new(Identifier(Ident::new("a").empty_span())), op: Plus, - right: Box::new(Identifier(Ident::new("b"))), + right: Box::new(Identifier(Ident::new("b").empty_span())), }))), op: Minus, right: Box::new(Nested(Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("c"))), + left: Box::new(Identifier(Ident::new("c").empty_span())), op: Plus, - right: Box::new(Identifier(Ident::new("d"))), + right: Box::new(Identifier(Ident::new("d").empty_span())), }))), }, verified_expr(sql) @@ -5812,14 +5958,14 @@ fn parse_searched_case_expr() { &Case { operand: None, conditions: vec![ - IsNull(Box::new(Identifier(Ident::new("bar")))), + IsNull(Box::new(Identifier(Ident::new("bar").empty_span()))), BinaryOp { - left: Box::new(Identifier(Ident::new("bar"))), + left: Box::new(Identifier(Ident::new("bar").empty_span())), op: Eq, right: Box::new(Expr::Value(number("0"))), }, BinaryOp { - left: Box::new(Identifier(Ident::new("bar"))), + left: Box::new(Identifier(Ident::new("bar").empty_span())), op: GtEq, right: Box::new(Expr::Value(number("0"))), }, @@ -5845,7 +5991,7 @@ fn parse_simple_case_expr() { use self::Expr::{Case, Identifier}; assert_eq!( &Case { - operand: Some(Box::new(Identifier(Ident::new("foo")))), + operand: Some(Box::new(Identifier(Ident::new("foo").empty_span()))), conditions: vec![Expr::Value(number("1"))], results: vec![Expr::Value(Value::SingleQuotedString("Y".to_string()))], else_result: Some(Box::new(Expr::Value(Value::SingleQuotedString( @@ -5876,7 +6022,7 @@ fn parse_implicit_join() { vec![ TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec!["t1".into()]), + name: ObjectName(vec![Ident::new("t1").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -5888,7 +6034,7 @@ fn parse_implicit_join() { }, TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec!["t2".into()]), + name: ObjectName(vec![Ident::new("t2").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -5908,7 +6054,7 @@ fn parse_implicit_join() { vec![ TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec!["t1a".into()]), + name: ObjectName(vec![Ident::new("t1a").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -5918,7 +6064,7 @@ fn parse_implicit_join() { }, joins: vec![Join { relation: TableFactor::Table { - name: ObjectName(vec!["t1b".into()]), + name: ObjectName(vec![Ident::new("t1b").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -5932,7 +6078,7 @@ fn parse_implicit_join() { }, TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec!["t2a".into()]), + name: ObjectName(vec![Ident::new("t2a").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -5942,7 +6088,7 @@ fn parse_implicit_join() { }, joins: vec![Join { relation: TableFactor::Table { - name: ObjectName(vec!["t2b".into()]), + name: ObjectName(vec![Ident::new("t2b").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -5966,7 +6112,7 @@ fn parse_cross_join() { assert_eq!( Join { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("t2")]), + name: ObjectName(vec![Ident::new("t2").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -5991,7 +6137,7 @@ fn parse_joins_on() { ) -> Join { Join { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new(relation.into())]), + name: ObjectName(vec![Ident::new(relation.into()).empty_span()]), alias, args: None, with_hints: vec![], @@ -6001,9 +6147,9 @@ fn parse_joins_on() { }, global, join_operator: f(JoinConstraint::On(Expr::BinaryOp { - left: Box::new(Expr::Identifier("c1".into())), + left: Box::new(Expr::Identifier(Ident::new("c1").empty_span())), op: BinaryOperator::Eq, - right: Box::new(Expr::Identifier("c2".into())), + right: Box::new(Expr::Identifier(Ident::new("c2").empty_span())), })), } } @@ -6110,7 +6256,7 @@ fn parse_joins_using() { ) -> Join { Join { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new(relation.into())]), + name: ObjectName(vec![Ident::new(relation.into()).empty_span()]), alias, args: None, with_hints: vec![], @@ -6119,7 +6265,7 @@ fn parse_joins_using() { with_ordinality: false, }, global: false, - join_operator: f(JoinConstraint::Using(vec!["c1".into()])), + join_operator: f(JoinConstraint::Using(vec![Ident::new("c1").empty_span()])), } } // Test parsing of aliases @@ -6175,7 +6321,7 @@ fn parse_natural_join() { fn natural_join(f: impl Fn(JoinConstraint) -> JoinOperator, alias: Option) -> Join { Join { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("t2")]), + name: ObjectName(vec![Ident::new("t2").empty_span()]), alias, args: None, with_hints: vec![], @@ -6319,9 +6465,9 @@ fn parse_ctes() { assert_eq!(*exp, query.to_string()); assert_eq!( if i == 0 { - Ident::new("a") + Ident::new("a").empty_span() } else { - Ident::new("b") + Ident::new("b").empty_span() }, alias.name ); @@ -6366,7 +6512,10 @@ fn parse_cte_renamed_columns() { let sql = "WITH cte (col1, col2) AS (SELECT foo, bar FROM baz) SELECT * FROM cte"; let query = all_dialects().verified_query(sql); assert_eq!( - vec![Ident::new("col1"), Ident::new("col2")], + vec![ + Ident::new("col1").empty_span(), + Ident::new("col2").empty_span() + ], query .with .unwrap() @@ -6394,11 +6543,13 @@ fn parse_recursive_cte() { name: Ident { value: "nums".to_string(), quote_style: None, - }, + } + .empty_span(), columns: vec![Ident { value: "val".to_string(), quote_style: None, - }], + } + .empty_span()], }, query: Box::new(cte_query), from: None, @@ -6438,13 +6589,13 @@ fn parse_derived_tables() { lateral: false, subquery: Box::new(verified_query("(SELECT 1) UNION (SELECT 2)")), alias: Some(TableAlias { - name: "t1".into(), + name: Ident::new("t1").empty_span(), columns: vec![], }), }, joins: vec![Join { relation: TableFactor::Table { - name: ObjectName(vec!["t2".into()]), + name: ObjectName(vec![Ident::new("t2").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -6580,10 +6731,10 @@ fn parse_overlay() { assert_eq!( &Expr::Overlay { expr: Box::new(Expr::Value(Value::SingleQuotedString("abcdef".to_string()))), - overlay_what: Box::new(Expr::Identifier(Ident::new("name"))), + overlay_what: Box::new(Expr::Identifier(Ident::new("name").empty_span())), overlay_from: Box::new(Expr::Value(number("3"))), overlay_for: Some(Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("id"))), + left: Box::new(Expr::Identifier(Ident::new("id").empty_span())), op: BinaryOperator::Plus, right: Box::new(Expr::Value(number("1"))), })), @@ -6810,11 +6961,11 @@ fn parse_create_view_with_options() { assert_eq!( CreateTableOptions::With(vec![ SqlOption::KeyValue { - key: "foo".into(), + key: Ident::new("foo").empty_span(), value: Expr::Value(Value::SingleQuotedString("bar".into())), }, SqlOption::KeyValue { - key: "a".into(), + key: Ident::new("a").empty_span(), value: Expr::Value(number("123")), }, ]), @@ -6848,14 +6999,17 @@ fn parse_create_view_with_columns() { assert_eq!("v", name.to_string()); assert_eq!( columns, - vec![Ident::new("has"), Ident::new("cols"),] - .into_iter() - .map(|name| ViewColumnDef { - name, - data_type: None, - options: None - }) - .collect::>() + vec![ + Ident::new("has").empty_span(), + Ident::new("cols").empty_span(), + ] + .into_iter() + .map(|name| ViewColumnDef { + name, + data_type: None, + options: None + }) + .collect::>() ); assert_eq!(options, CreateTableOptions::None); assert_eq!("SELECT 1, 2", query.to_string()); @@ -7040,7 +7194,7 @@ fn parse_create_materialized_view_with_cluster_by() { assert!(materialized); assert_eq!(options, CreateTableOptions::None); assert!(!or_replace); - assert_eq!(cluster_by, vec![Ident::new("foo")]); + assert_eq!(cluster_by, vec![Ident::new("foo").empty_span()]); assert!(comment.is_none()); assert!(!late_binding); assert!(!if_not_exists); @@ -7331,7 +7485,7 @@ fn lateral_derived() { } = join.relation { assert_eq!(lateral_in, lateral); - assert_eq!(Ident::new("order"), alias.name); + assert_eq!(Ident::new("order").empty_span(), alias.name); assert_eq!( subquery.to_string(), "SELECT * FROM order WHERE order.customer = customer.id LIMIT 3" @@ -7380,7 +7534,8 @@ fn lateral_function() { name: ObjectName(vec![Ident { value: "customer".to_string(), quote_style: None, - }]), + } + .empty_span()]), alias: None, args: None, with_hints: vec![], @@ -7391,11 +7546,14 @@ fn lateral_function() { joins: vec![Join { relation: TableFactor::Function { lateral: true, - name: ObjectName(vec!["generate_series".into()]), + name: ObjectName(vec![Ident::new("generate_series").empty_span()]), args: vec![ FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("1")))), FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::CompoundIdentifier( - vec![Ident::new("customer"), Ident::new("id")], + vec![ + Ident::new("customer").empty_span(), + Ident::new("id").empty_span(), + ], ))), ], alias: None, @@ -7531,7 +7689,7 @@ fn parse_set_variable() { assert!(!hivevar); assert_eq!( variables, - OneOrManyWithParens::One(ObjectName(vec!["SOMETHING".into()])) + OneOrManyWithParens::One(ObjectName(vec![Ident::new("SOMETHING").empty_span()])) ); assert_eq!( value, @@ -7555,9 +7713,9 @@ fn parse_set_variable() { assert_eq!( variables, OneOrManyWithParens::Many(vec![ - ObjectName(vec!["a".into()]), - ObjectName(vec!["b".into()]), - ObjectName(vec!["c".into()]), + ObjectName(vec![Ident::new("a").empty_span()]), + ObjectName(vec![Ident::new("b").empty_span()]), + ObjectName(vec![Ident::new("c").empty_span()]), ]) ); assert_eq!( @@ -7631,7 +7789,7 @@ fn parse_set_role_as_variable() { assert!(!hivevar); assert_eq!( variables, - OneOrManyWithParens::One(ObjectName(vec!["role".into()])) + OneOrManyWithParens::One(ObjectName(vec![Ident::new("role").empty_span()])) ); assert_eq!( value, @@ -7678,7 +7836,7 @@ fn parse_set_time_zone() { assert!(!hivevar); assert_eq!( variable, - OneOrManyWithParens::One(ObjectName(vec!["TIMEZONE".into()])) + OneOrManyWithParens::One(ObjectName(vec![Ident::new("TIMEZONE").empty_span()])) ); assert_eq!( value, @@ -7757,7 +7915,7 @@ fn parse_rollback() { chain: false, savepoint, } => { - assert_eq!(savepoint, Some(Ident::new("test1"))); + assert_eq!(savepoint, Some(Ident::new("test1").empty_span())); } _ => unreachable!(), } @@ -7767,7 +7925,7 @@ fn parse_rollback() { chain: true, savepoint, } => { - assert_eq!(savepoint, Some(Ident::new("test1"))); + assert_eq!(savepoint, Some(Ident::new("test1").empty_span())); } _ => unreachable!(), } @@ -7800,13 +7958,13 @@ fn parse_create_index() { let sql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_name ON test(name,age DESC)"; let indexed_columns = vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("name")), + expr: Expr::Identifier(Ident::new("name").empty_span()), asc: None, nulls_first: None, with_fill: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("age")), + expr: Expr::Identifier(Ident::new("age").empty_span()), asc: Some(false), nulls_first: None, with_fill: None, @@ -7836,13 +7994,13 @@ fn test_create_index_with_using_function() { let sql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_name ON test USING btree (name,age DESC)"; let indexed_columns = vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("name")), + expr: Expr::Identifier(Ident::new("name").empty_span()), asc: None, nulls_first: None, with_fill: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("age")), + expr: Expr::Identifier(Ident::new("age").empty_span()), asc: Some(false), nulls_first: None, with_fill: None, @@ -7880,18 +8038,18 @@ fn test_create_index_with_using_function() { fn test_create_index_with_with_clause() { let sql = "CREATE UNIQUE INDEX title_idx ON films(title) WITH (fillfactor = 70, single_param)"; let indexed_columns = vec![OrderByExpr { - expr: Expr::Identifier(Ident::new("title")), + expr: Expr::Identifier(Ident::new("title").empty_span()), asc: None, nulls_first: None, with_fill: None, }]; let with_parameters = vec![ Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("fillfactor"))), + left: Box::new(Expr::Identifier(Ident::new("fillfactor").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(number("70"))), }, - Expr::Identifier(Ident::new("single_param")), + Expr::Identifier(Ident::new("single_param").empty_span()), ]; let dialects = all_dialects_where(|d| d.supports_create_index_with_clause()); match dialects.verified_stmt(sql) { @@ -8017,11 +8175,13 @@ fn parse_grant() { Ident { value: "shape".into(), quote_style: None, - }, + } + .empty_span(), Ident { value: "size".into(), quote_style: None, - }, + } + .empty_span(), ]) }, Action::Usage, @@ -8192,9 +8352,12 @@ fn parse_merge() { assert_eq!( table, TableFactor::Table { - name: ObjectName(vec![Ident::new("s"), Ident::new("bar")]), + name: ObjectName(vec![ + Ident::new("s").empty_span(), + Ident::new("bar").empty_span() + ]), alias: Some(TableAlias { - name: Ident::new("dest"), + name: Ident::new("dest").empty_span(), columns: vec![], }), args: None, @@ -8221,7 +8384,10 @@ fn parse_merge() { into: None, from: vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("s"), Ident::new("foo")]), + name: ObjectName(vec![ + Ident::new("s").empty_span(), + Ident::new("foo").empty_span() + ]), alias: None, args: None, with_hints: vec![], @@ -8259,7 +8425,8 @@ fn parse_merge() { name: Ident { value: "stg".to_string(), quote_style: None, - }, + } + .empty_span(), columns: vec![], }), } @@ -8271,25 +8438,25 @@ fn parse_merge() { Box::new(Expr::BinaryOp { left: Box::new(Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("dest"), - Ident::new("D"), + Ident::new("dest").empty_span(), + Ident::new("D").empty_span(), ])), op: BinaryOperator::Eq, right: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("stg"), - Ident::new("D"), + Ident::new("stg").empty_span(), + Ident::new("D").empty_span(), ])), }), op: BinaryOperator::And, right: Box::new(Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("dest"), - Ident::new("E"), + Ident::new("dest").empty_span(), + Ident::new("E").empty_span(), ])), op: BinaryOperator::Eq, right: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("stg"), - Ident::new("E"), + Ident::new("stg").empty_span(), + Ident::new("E").empty_span(), ])), }), }) @@ -8303,21 +8470,25 @@ fn parse_merge() { clause_kind: MergeClauseKind::NotMatched, predicate: None, action: MergeAction::Insert(MergeInsertExpr { - columns: vec![Ident::new("A"), Ident::new("B"), Ident::new("C")], + columns: vec![ + Ident::new("A").empty_span(), + Ident::new("B").empty_span(), + Ident::new("C").empty_span() + ], kind: MergeInsertKind::Values(Values { explicit_row: false, rows: vec![vec![ Expr::CompoundIdentifier(vec![ - Ident::new("stg"), - Ident::new("A") + Ident::new("stg").empty_span(), + Ident::new("A").empty_span(), ]), Expr::CompoundIdentifier(vec![ - Ident::new("stg"), - Ident::new("B") + Ident::new("stg").empty_span(), + Ident::new("B").empty_span(), ]), Expr::CompoundIdentifier(vec![ - Ident::new("stg"), - Ident::new("C") + Ident::new("stg").empty_span(), + Ident::new("C").empty_span(), ]), ]] }), @@ -8327,8 +8498,8 @@ fn parse_merge() { clause_kind: MergeClauseKind::Matched, predicate: Some(Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("dest"), - Ident::new("A"), + Ident::new("dest").empty_span(), + Ident::new("A").empty_span(), ])), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::SingleQuotedString( @@ -8339,22 +8510,22 @@ fn parse_merge() { assignments: vec![ Assignment { target: AssignmentTarget::ColumnName(ObjectName(vec![ - Ident::new("dest"), - Ident::new("F") + Ident::new("dest").empty_span(), + Ident::new("F").empty_span(), ])), value: Expr::CompoundIdentifier(vec![ - Ident::new("stg"), - Ident::new("F"), + Ident::new("stg").empty_span(), + Ident::new("F").empty_span(), ]), }, Assignment { target: AssignmentTarget::ColumnName(ObjectName(vec![ - Ident::new("dest"), - Ident::new("G") + Ident::new("dest").empty_span(), + Ident::new("G").empty_span(), ])), value: Expr::CompoundIdentifier(vec![ - Ident::new("stg"), - Ident::new("G"), + Ident::new("stg").empty_span(), + Ident::new("G").empty_span(), ]), }, ], @@ -8459,7 +8630,8 @@ fn test_lock_table() { vec![Ident { value: "school".to_string(), quote_style: None - }] + } + .empty_span()] ); assert!(lock.nonblock.is_none()); @@ -8473,7 +8645,8 @@ fn test_lock_table() { vec![Ident { value: "school".to_string(), quote_style: None - }] + } + .empty_span()] ); assert!(lock.nonblock.is_none()); @@ -8487,7 +8660,8 @@ fn test_lock_table() { vec![Ident { value: "school".to_string(), quote_style: None - }] + } + .empty_span()] ); assert!(lock.nonblock.is_none()); let lock = ast.locks.remove(0); @@ -8497,7 +8671,8 @@ fn test_lock_table() { vec![Ident { value: "student".to_string(), quote_style: None - }] + } + .empty_span()] ); assert!(lock.nonblock.is_none()); } @@ -8514,7 +8689,8 @@ fn test_lock_nonblock() { vec![Ident { value: "school".to_string(), quote_style: None - }] + } + .empty_span()] ); assert_eq!(lock.nonblock.unwrap(), NonBlock::SkipLocked); @@ -8528,7 +8704,8 @@ fn test_lock_nonblock() { vec![Ident { value: "school".to_string(), quote_style: None - }] + } + .empty_span()] ); assert_eq!(lock.nonblock.unwrap(), NonBlock::Nowait); } @@ -8551,7 +8728,7 @@ fn test_placeholder() { assert_eq!( ast.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("id"))), + left: Box::new(Expr::Identifier(Ident::new("id").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Placeholder("$Id1".into()))), }) @@ -8588,7 +8765,7 @@ fn test_placeholder() { assert_eq!( ast.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("id"))), + left: Box::new(Expr::Identifier(Ident::new("id").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Placeholder("?".into()))), }) @@ -8710,7 +8887,7 @@ fn parse_time_functions() { let sql = format!("SELECT {}()", func_name); let select = verified_only_select(&sql); let select_localtime_func_call_ast = Function { - name: ObjectName(vec![Ident::new(func_name)]), + name: ObjectName(vec![Ident::new(func_name).empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -8749,7 +8926,7 @@ fn parse_position() { assert_eq!( Expr::Position { expr: Box::new(Expr::Value(Value::SingleQuotedString("@".to_string()))), - r#in: Box::new(Expr::Identifier(Ident::new("field"))), + r#in: Box::new(Expr::Identifier(Ident::new("field").empty_span())), }, verified_expr("POSITION('@' IN field)"), ); @@ -8784,37 +8961,37 @@ fn parse_is_boolean() { let sql = "a IS TRUE"; assert_eq!( - IsTrue(Box::new(Identifier(Ident::new("a")))), + IsTrue(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS NOT TRUE"; assert_eq!( - IsNotTrue(Box::new(Identifier(Ident::new("a")))), + IsNotTrue(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS FALSE"; assert_eq!( - IsFalse(Box::new(Identifier(Ident::new("a")))), + IsFalse(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS NOT FALSE"; assert_eq!( - IsNotFalse(Box::new(Identifier(Ident::new("a")))), + IsNotFalse(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS UNKNOWN"; assert_eq!( - IsUnknown(Box::new(Identifier(Ident::new("a")))), + IsUnknown(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS NOT UNKNOWN"; assert_eq!( - IsNotUnknown(Box::new(Identifier(Ident::new("a")))), + IsNotUnknown(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); @@ -8872,7 +9049,7 @@ fn parse_cursor() { Statement::Close { cursor } => assert_eq!( cursor, CloseCursor::Specific { - name: Ident::new("my_cursor"), + name: Ident::new("my_cursor").empty_span(), } ), _ => unreachable!(), @@ -8906,7 +9083,7 @@ fn parse_cache_table() { verified_stmt(format!("CACHE TABLE '{cache_table_name}'").as_str()), Statement::Cache { table_flag: None, - table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name)]), + table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name).empty_span()]), has_as: false, options: vec![], query: None, @@ -8916,8 +9093,8 @@ fn parse_cache_table() { assert_eq!( verified_stmt(format!("CACHE {table_flag} TABLE '{cache_table_name}'").as_str()), Statement::Cache { - table_flag: Some(ObjectName(vec![Ident::new(table_flag)])), - table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name)]), + table_flag: Some(ObjectName(vec![Ident::new(table_flag).empty_span()])), + table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name).empty_span()]), has_as: false, options: vec![], query: None, @@ -8932,16 +9109,16 @@ fn parse_cache_table() { .as_str() ), Statement::Cache { - table_flag: Some(ObjectName(vec![Ident::new(table_flag)])), - table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name)]), + table_flag: Some(ObjectName(vec![Ident::new(table_flag).empty_span()])), + table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name).empty_span()]), has_as: false, options: vec![ SqlOption::KeyValue { - key: Ident::with_quote('\'', "K1"), + key: Ident::with_quote('\'', "K1").empty_span(), value: Expr::Value(Value::SingleQuotedString("V1".into())), }, SqlOption::KeyValue { - key: Ident::with_quote('\'', "K2"), + key: Ident::with_quote('\'', "K2").empty_span(), value: Expr::Value(number("0.88")), }, ], @@ -8957,16 +9134,16 @@ fn parse_cache_table() { .as_str() ), Statement::Cache { - table_flag: Some(ObjectName(vec![Ident::new(table_flag)])), - table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name)]), + table_flag: Some(ObjectName(vec![Ident::new(table_flag).empty_span()])), + table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name).empty_span()]), has_as: false, options: vec![ SqlOption::KeyValue { - key: Ident::with_quote('\'', "K1"), + key: Ident::with_quote('\'', "K1").empty_span(), value: Expr::Value(Value::SingleQuotedString("V1".into())), }, SqlOption::KeyValue { - key: Ident::with_quote('\'', "K2"), + key: Ident::with_quote('\'', "K2").empty_span(), value: Expr::Value(number("0.88")), }, ], @@ -8982,16 +9159,16 @@ fn parse_cache_table() { .as_str() ), Statement::Cache { - table_flag: Some(ObjectName(vec![Ident::new(table_flag)])), - table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name)]), + table_flag: Some(ObjectName(vec![Ident::new(table_flag).empty_span()])), + table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name).empty_span()]), has_as: true, options: vec![ SqlOption::KeyValue { - key: Ident::with_quote('\'', "K1"), + key: Ident::with_quote('\'', "K1").empty_span(), value: Expr::Value(Value::SingleQuotedString("V1".into())), }, SqlOption::KeyValue { - key: Ident::with_quote('\'', "K2"), + key: Ident::with_quote('\'', "K2").empty_span(), value: Expr::Value(number("0.88")), }, ], @@ -9002,8 +9179,8 @@ fn parse_cache_table() { assert_eq!( verified_stmt(format!("CACHE {table_flag} TABLE '{cache_table_name}' {sql}").as_str()), Statement::Cache { - table_flag: Some(ObjectName(vec![Ident::new(table_flag)])), - table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name)]), + table_flag: Some(ObjectName(vec![Ident::new(table_flag).empty_span()])), + table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name).empty_span()]), has_as: false, options: vec![], query: Some(query.clone().into()), @@ -9013,8 +9190,8 @@ fn parse_cache_table() { assert_eq!( verified_stmt(format!("CACHE {table_flag} TABLE '{cache_table_name}' AS {sql}").as_str()), Statement::Cache { - table_flag: Some(ObjectName(vec![Ident::new(table_flag)])), - table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name)]), + table_flag: Some(ObjectName(vec![Ident::new(table_flag).empty_span()])), + table_name: ObjectName(vec![Ident::with_quote('\'', cache_table_name).empty_span()]), has_as: true, options: vec![], query: Some(query.into()), @@ -9077,7 +9254,7 @@ fn parse_uncache_table() { assert_eq!( verified_stmt("UNCACHE TABLE 'table_name'"), Statement::UNCache { - table_name: ObjectName(vec![Ident::with_quote('\'', "table_name")]), + table_name: ObjectName(vec![Ident::with_quote('\'', "table_name").empty_span()]), if_exists: false, } ); @@ -9085,7 +9262,7 @@ fn parse_uncache_table() { assert_eq!( verified_stmt("UNCACHE TABLE IF EXISTS 'table_name'"), Statement::UNCache { - table_name: ObjectName(vec![Ident::with_quote('\'', "table_name")]), + table_name: ObjectName(vec![Ident::with_quote('\'', "table_name").empty_span()]), if_exists: true, } ); @@ -9280,11 +9457,11 @@ fn parse_pivot_table() { expr: call( "SUM", [Expr::CompoundIdentifier(vec![ - Ident::new(table), - Ident::new("amount"), + Ident::new(table).empty_span(), + Ident::new("amount").empty_span(), ])], ), - alias: alias.map(Ident::new), + alias: alias.map(Ident::new).map(SpanWrapped::empty_span), } } @@ -9292,9 +9469,9 @@ fn parse_pivot_table() { verified_only_select(sql).from[0].relation, Pivot { table: Box::new(TableFactor::Table { - name: ObjectName(vec![Ident::new("monthly_sales")]), + name: ObjectName(vec![Ident::new("monthly_sales").empty_span()]), alias: Some(TableAlias { - name: Ident::new("a"), + name: Ident::new("a").empty_span(), columns: vec![] }), args: None, @@ -9308,19 +9485,22 @@ fn parse_pivot_table() { expected_function("b", Some("t")), expected_function("c", Some("u")), ], - value_column: vec![Ident::new("a"), Ident::new("MONTH")], + value_column: vec![ + Ident::new("a").empty_span(), + Ident::new("MONTH").empty_span() + ], value_source: PivotValueSource::List(vec![ ExprWithAlias { expr: Expr::Value(number("1")), - alias: Some(Ident::new("x")) + alias: Some(Ident::new("x").empty_span()) }, ExprWithAlias { expr: Expr::Value(Value::SingleQuotedString("two".to_string())), alias: None }, ExprWithAlias { - expr: Expr::Identifier(Ident::new("three")), - alias: Some(Ident::new("y")) + expr: Expr::Identifier(Ident::new("three").empty_span()), + alias: Some(Ident::new("y").empty_span()) }, ]), default_on_null: None, @@ -9328,8 +9508,9 @@ fn parse_pivot_table() { name: Ident { value: "p".to_string(), quote_style: None - }, - columns: vec![Ident::new("c"), Ident::new("d")], + } + .empty_span(), + columns: vec![Ident::new("c").empty_span(), Ident::new("d").empty_span()], }), } ); @@ -9362,9 +9543,9 @@ fn parse_unpivot_table() { verified_only_select(sql).from[0].relation, Unpivot { table: Box::new(TableFactor::Table { - name: ObjectName(vec![Ident::new("sales")]), + name: ObjectName(vec![Ident::new("sales").empty_span()]), alias: Some(TableAlias { - name: Ident::new("s"), + name: Ident::new("s").empty_span(), columns: vec![] }), args: None, @@ -9376,21 +9557,25 @@ fn parse_unpivot_table() { value: Ident { value: "quantity".to_string(), quote_style: None - }, + } + .empty_span(), name: Ident { value: "quarter".to_string(), quote_style: None - }, + } + .empty_span(), columns: ["Q1", "Q2", "Q3", "Q4"] .into_iter() .map(Ident::new) + .map(SpanWrapped::empty_span) .collect(), alias: Some(TableAlias { - name: Ident::new("u"), + name: Ident::new("u").empty_span(), columns: ["product", "quarter", "quantity"] .into_iter() .map(Ident::new) + .map(SpanWrapped::empty_span) .collect() }), } @@ -9429,9 +9614,9 @@ fn parse_pivot_unpivot_table() { Pivot { table: Box::new(Unpivot { table: Box::new(TableFactor::Table { - name: ObjectName(vec![Ident::new("census")]), + name: ObjectName(vec![Ident::new("census").empty_span()]), alias: Some(TableAlias { - name: Ident::new("c"), + name: Ident::new("c").empty_span(), columns: vec![] }), args: None, @@ -9443,26 +9628,31 @@ fn parse_pivot_unpivot_table() { value: Ident { value: "population".to_string(), quote_style: None - }, + } + .empty_span(), name: Ident { value: "year".to_string(), quote_style: None - }, + } + .empty_span(), columns: ["population_2000", "population_2010"] .into_iter() - .map(Ident::new) + .map(|s| Ident::new(s).empty_span()) .collect(), alias: Some(TableAlias { - name: Ident::new("u"), + name: Ident::new("u").empty_span(), columns: vec![] }), }), aggregate_functions: vec![ExprWithAlias { - expr: call("sum", [Expr::Identifier(Ident::new("population"))]), + expr: call( + "sum", + [Expr::Identifier(Ident::new("population").empty_span())] + ), alias: None }], - value_column: vec![Ident::new("year")], + value_column: vec![Ident::new("year").empty_span()], value_source: PivotValueSource::List(vec![ ExprWithAlias { expr: Expr::Value(Value::SingleQuotedString("population_2000".to_string())), @@ -9475,7 +9665,7 @@ fn parse_pivot_unpivot_table() { ]), default_on_null: None, alias: Some(TableAlias { - name: Ident::new("p"), + name: Ident::new("p").empty_span(), columns: vec![] }), } @@ -9630,18 +9820,23 @@ fn parse_create_type() { verified_stmt("CREATE TYPE db.type_name AS (foo INT, bar TEXT COLLATE \"de_DE\")"); assert_eq!( Statement::CreateType { - name: ObjectName(vec![Ident::new("db"), Ident::new("type_name")]), + name: ObjectName(vec![ + Ident::new("db").empty_span(), + Ident::new("type_name").empty_span() + ]), representation: UserDefinedTypeRepresentation::Composite { attributes: vec![ UserDefinedTypeCompositeAttributeDef { - name: Ident::new("foo"), + name: Ident::new("foo").empty_span(), data_type: DataType::Int(None), collation: None, }, UserDefinedTypeCompositeAttributeDef { - name: Ident::new("bar"), + name: Ident::new("bar").empty_span(), data_type: DataType::Text, - collation: Some(ObjectName(vec![Ident::with_quote('\"', "de_DE")])), + collation: Some(ObjectName(vec![ + Ident::with_quote('\"', "de_DE").empty_span() + ])), } ] } @@ -9721,7 +9916,7 @@ fn parse_call() { )))], clauses: vec![], }), - name: ObjectName(vec![Ident::new("my_procedure")]), + name: ObjectName(vec![Ident::new("my_procedure").empty_span()]), filter: None, null_treatment: None, over: None, @@ -9803,11 +9998,13 @@ fn parse_unload() { body: Box::new(SetExpr::Select(Box::new(Select { distinct: None, top: None, - projection: vec![UnnamedExpr(Expr::Identifier(Ident::new("cola"))),], + projection: vec![UnnamedExpr(Expr::Identifier( + Ident::new("cola").empty_span() + )),], into: None, from: vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("tab")]), + name: ObjectName(vec![Ident::new("tab").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -9845,12 +10042,14 @@ fn parse_unload() { to: Ident { value: "s3://...".to_string(), quote_style: Some('\'') - }, + } + .empty_span(), with: vec![SqlOption::KeyValue { key: Ident { value: "format".to_string(), quote_style: None - }, + } + .empty_span(), value: Expr::Value(Value::SingleQuotedString("AVRO".to_string())) }] } @@ -9861,7 +10060,7 @@ fn parse_unload() { fn test_savepoint() { match verified_stmt("SAVEPOINT test1") { Statement::Savepoint { name } => { - assert_eq!(Ident::new("test1"), name); + assert_eq!(Ident::new("test1").empty_span(), name); } _ => unreachable!(), } @@ -9871,7 +10070,7 @@ fn test_savepoint() { fn test_release_savepoint() { match verified_stmt("RELEASE SAVEPOINT test1") { Statement::ReleaseSavepoint { name } => { - assert_eq!(Ident::new("test1"), name); + assert_eq!(Ident::new("test1").empty_span(), name); } _ => unreachable!(), } @@ -9911,7 +10110,7 @@ fn test_parse_inline_comment() { assert_eq!( columns, vec![ColumnDef { - name: Ident::new("id".to_string()), + name: Ident::new("id".to_string()).empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -9951,7 +10150,7 @@ fn parse_map_access_expr() { ]); let expr = dialects.verified_expr(sql); let expected = Expr::MapAccess { - column: Expr::Identifier(Ident::new("users")).into(), + column: Expr::Identifier(Ident::new("users").empty_span()).into(), keys: vec![ MapAccessKey { key: Expr::UnaryOp { @@ -9979,13 +10178,13 @@ fn parse_connect_by() { distinct: None, top: None, projection: vec![ - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("employee_id"))), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("manager_id"))), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("title"))), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("employee_id").empty_span())), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("manager_id").empty_span())), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("title").empty_span())), ], from: vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("employees")]), + name: ObjectName(vec![Ident::new("employees").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -10010,18 +10209,18 @@ fn parse_connect_by() { value_table_mode: None, connect_by: Some(ConnectBy { condition: Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("title"))), + left: Box::new(Expr::Identifier(Ident::new("title").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::SingleQuotedString( "president".to_owned(), ))), }, relationships: vec![Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("manager_id"))), + left: Box::new(Expr::Identifier(Ident::new("manager_id").empty_span())), op: BinaryOperator::Eq, - right: Box::new(Expr::Prior(Box::new(Expr::Identifier(Ident::new( - "employee_id", - ))))), + right: Box::new(Expr::Prior(Box::new(Expr::Identifier( + Ident::new("employee_id").empty_span(), + )))), }], }), }; @@ -10065,13 +10264,13 @@ fn parse_connect_by() { distinct: None, top: None, projection: vec![ - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("employee_id"))), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("manager_id"))), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("title"))), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("employee_id").empty_span())), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("manager_id").empty_span())), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("title").empty_span())), ], from: vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("employees")]), + name: ObjectName(vec![Ident::new("employees").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -10085,7 +10284,7 @@ fn parse_connect_by() { lateral_views: vec![], prewhere: None, selection: Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("employee_id"))), + left: Box::new(Expr::Identifier(Ident::new("employee_id").empty_span())), op: BinaryOperator::NotEq, right: Box::new(Expr::Value(number("42"))), }), @@ -10100,18 +10299,18 @@ fn parse_connect_by() { value_table_mode: None, connect_by: Some(ConnectBy { condition: Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("title"))), + left: Box::new(Expr::Identifier(Ident::new("title").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::SingleQuotedString( "president".to_owned(), ))), }, relationships: vec![Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("manager_id"))), + left: Box::new(Expr::Identifier(Ident::new("manager_id").empty_span())), op: BinaryOperator::Eq, - right: Box::new(Expr::Prior(Box::new(Expr::Identifier(Ident::new( - "employee_id", - ))))), + right: Box::new(Expr::Prior(Box::new(Expr::Identifier( + Ident::new("employee_id",).empty_span() + )))), }], }), } @@ -10134,9 +10333,9 @@ fn parse_connect_by() { all_dialects() .verified_only_select("SELECT prior FROM some_table") .projection, - vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident::new( - "prior" - )))] + vec![SelectItem::UnnamedExpr(Expr::Identifier( + Ident::new("prior").empty_span() + ))] ); } @@ -10154,17 +10353,17 @@ fn test_selective_aggregation() { .projection, vec![ SelectItem::UnnamedExpr(Expr::Function(Function { - name: ObjectName(vec![Ident::new("ARRAY_AGG")]), + name: ObjectName(vec![Ident::new("ARRAY_AGG").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("name")) + Expr::Identifier(Ident::new("name").empty_span()) ))], clauses: vec![], }), filter: Some(Box::new(Expr::IsNotNull(Box::new(Expr::Identifier( - Ident::new("name") + Ident::new("name").empty_span() ))))), over: None, within_group: vec![], @@ -10172,18 +10371,18 @@ fn test_selective_aggregation() { })), SelectItem::ExprWithAlias { expr: Expr::Function(Function { - name: ObjectName(vec![Ident::new("ARRAY_AGG")]), + name: ObjectName(vec![Ident::new("ARRAY_AGG").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("name")) + Expr::Identifier(Ident::new("name").empty_span()) ))], clauses: vec![], }), filter: Some(Box::new(Expr::Like { negated: false, - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), pattern: Box::new(Expr::Value(Value::SingleQuotedString("a%".to_owned()))), escape_char: None, any: false, @@ -10192,7 +10391,7 @@ fn test_selective_aggregation() { over: None, within_group: vec![] }), - alias: Ident::new("agg2") + alias: Ident::new("agg2").empty_span(), }, ] ) @@ -10213,11 +10412,11 @@ fn test_group_by_grouping_sets() { GroupByExpr::Expressions( vec![Expr::GroupingSets(vec![ vec![ - Expr::Identifier(Ident::new("city")), - Expr::Identifier(Ident::new("car_model")) + Expr::Identifier(Ident::new("city").empty_span()), + Expr::Identifier(Ident::new("car_model").empty_span()) ], - vec![Expr::Identifier(Ident::new("city")),], - vec![Expr::Identifier(Ident::new("car_model"))], + vec![Expr::Identifier(Ident::new("city").empty_span()),], + vec![Expr::Identifier(Ident::new("car_model").empty_span())], vec![] ])], vec![] @@ -10232,7 +10431,7 @@ fn test_match_recognize() { use RepetitionQuantifier::*; let table = TableFactor::Table { - name: ObjectName(vec![Ident::new("my_table")]), + name: ObjectName(vec![Ident::new("my_table").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -10265,9 +10464,9 @@ fn test_match_recognize() { ), TableFactor::MatchRecognize { table: Box::new(table), - partition_by: vec![Expr::Identifier(Ident::new("company"))], + partition_by: vec![Expr::Identifier(Ident::new("company").empty_span())], order_by: vec![OrderByExpr { - expr: Expr::Identifier(Ident::new("price_date")), + expr: Expr::Identifier(Ident::new("price_date").empty_span()), asc: None, nulls_first: None, with_fill: None, @@ -10275,47 +10474,63 @@ fn test_match_recognize() { measures: vec![ Measure { expr: call("MATCH_NUMBER", []), - alias: Ident::new("match_number"), + alias: Ident::new("match_number").empty_span(), }, Measure { - expr: call("FIRST", [Expr::Identifier(Ident::new("price_date"))]), - alias: Ident::new("start_date"), + expr: call( + "FIRST", + [Expr::Identifier(Ident::new("price_date").empty_span())], + ), + alias: Ident::new("start_date").empty_span(), }, Measure { - expr: call("LAST", [Expr::Identifier(Ident::new("price_date"))]), - alias: Ident::new("end_date"), + expr: call( + "LAST", + [Expr::Identifier(Ident::new("price_date").empty_span())], + ), + alias: Ident::new("end_date").empty_span(), }, ], rows_per_match: Some(RowsPerMatch::OneRow), - after_match_skip: Some(AfterMatchSkip::ToLast(Ident::new( - "row_with_price_increase", - ))), + after_match_skip: Some(AfterMatchSkip::ToLast( + Ident::new("row_with_price_increase").empty_span(), + )), pattern: Concat(vec![ - Symbol(Named(Ident::new("row_before_decrease"))), + Symbol(Named(Ident::new("row_before_decrease").empty_span())), Repetition( - Box::new(Symbol(Named(Ident::new("row_with_price_decrease")))), + Box::new(Symbol(Named( + Ident::new("row_with_price_decrease").empty_span(), + ))), OneOrMore, ), Repetition( - Box::new(Symbol(Named(Ident::new("row_with_price_increase")))), + Box::new(Symbol(Named( + Ident::new("row_with_price_increase").empty_span(), + ))), OneOrMore, ), ]), symbols: vec![ SymbolDefinition { - symbol: Ident::new("row_with_price_decrease"), + symbol: Ident::new("row_with_price_decrease").empty_span(), definition: Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("price"))), + left: Box::new(Expr::Identifier(Ident::new("price").empty_span())), op: BinaryOperator::Lt, - right: Box::new(call("LAG", [Expr::Identifier(Ident::new("price"))])), + right: Box::new(call( + "LAG", + [Expr::Identifier(Ident::new("price").empty_span())], + )), }, }, SymbolDefinition { - symbol: Ident::new("row_with_price_increase"), + symbol: Ident::new("row_with_price_increase").empty_span(), definition: Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("price"))), + left: Box::new(Expr::Identifier(Ident::new("price").empty_span())), op: BinaryOperator::Gt, - right: Box::new(call("LAG", [Expr::Identifier(Ident::new("price"))])), + right: Box::new(call( + "LAG", + [Expr::Identifier(Ident::new("price").empty_span())], + )), }, }, ], @@ -10396,27 +10611,27 @@ fn test_match_recognize_patterns() { } // just a symbol - check("FOO", Symbol(Named(Ident::new("FOO")))); + check("FOO", Symbol(Named(Ident::new("FOO").empty_span()))); // just a symbol check( "^ FOO $", Concat(vec![ Symbol(Start), - Symbol(Named(Ident::new("FOO"))), + Symbol(Named(Ident::new("FOO").empty_span())), Symbol(End), ]), ); // exclusion - check("{- FOO -}", Exclude(Named(Ident::new("FOO")))); + check("{- FOO -}", Exclude(Named(Ident::new("FOO").empty_span()))); check( "PERMUTE(A, B, C)", Permute(vec![ - Named(Ident::new("A")), - Named(Ident::new("B")), - Named(Ident::new("C")), + Named(Ident::new("A").empty_span()), + Named(Ident::new("B").empty_span()), + Named(Ident::new("C").empty_span()), ]), ); @@ -10424,9 +10639,9 @@ fn test_match_recognize_patterns() { check( "FOO | \"BAR\" | baz42", Alternation(vec![ - Symbol(Named(Ident::new("FOO"))), - Symbol(Named(Ident::with_quote('"', "BAR"))), - Symbol(Named(Ident::new("baz42"))), + Symbol(Named(Ident::new("FOO").empty_span())), + Symbol(Named(Ident::with_quote('"', "BAR").empty_span())), + Symbol(Named(Ident::new("baz42").empty_span())), ]), ); @@ -10434,9 +10649,18 @@ fn test_match_recognize_patterns() { check( "S1* S2+ S3?", Concat(vec![ - Repetition(Box::new(Symbol(Named(Ident::new("S1")))), ZeroOrMore), - Repetition(Box::new(Symbol(Named(Ident::new("S2")))), OneOrMore), - Repetition(Box::new(Symbol(Named(Ident::new("S3")))), AtMostOne), + Repetition( + Box::new(Symbol(Named(Ident::new("S1").empty_span()))), + ZeroOrMore, + ), + Repetition( + Box::new(Symbol(Named(Ident::new("S2").empty_span()))), + OneOrMore, + ), + Repetition( + Box::new(Symbol(Named(Ident::new("S3").empty_span()))), + AtMostOne, + ), ]), ); @@ -10445,7 +10669,7 @@ fn test_match_recognize_patterns() { "S2*?", Repetition( Box::new(Repetition( - Box::new(Symbol(Named(Ident::new("S2")))), + Box::new(Symbol(Named(Ident::new("S2").empty_span()))), ZeroOrMore, )), AtMostOne, @@ -10456,10 +10680,22 @@ fn test_match_recognize_patterns() { check( "S1{1} | S2{2,3} | S3{4,} | S4{,5}", Alternation(vec![ - Repetition(Box::new(Symbol(Named(Ident::new("S1")))), Exactly(1)), - Repetition(Box::new(Symbol(Named(Ident::new("S2")))), Range(2, 3)), - Repetition(Box::new(Symbol(Named(Ident::new("S3")))), AtLeast(4)), - Repetition(Box::new(Symbol(Named(Ident::new("S4")))), AtMost(5)), + Repetition( + Box::new(Symbol(Named(Ident::new("S1").empty_span()))), + Exactly(1), + ), + Repetition( + Box::new(Symbol(Named(Ident::new("S2").empty_span()))), + Range(2, 3), + ), + Repetition( + Box::new(Symbol(Named(Ident::new("S3").empty_span()))), + AtLeast(4), + ), + Repetition( + Box::new(Symbol(Named(Ident::new("S4").empty_span()))), + AtMost(5), + ), ]), ); @@ -10467,8 +10703,8 @@ fn test_match_recognize_patterns() { check( "S1 ( S2 )", Concat(vec![ - Symbol(Named(Ident::new("S1"))), - Group(Box::new(Symbol(Named(Ident::new("S2"))))), + Symbol(Named(Ident::new("S1").empty_span())), + Group(Box::new(Symbol(Named(Ident::new("S2").empty_span())))), ]), ); @@ -10477,8 +10713,8 @@ fn test_match_recognize_patterns() { "( {- S3 -} S4 )+", Repetition( Box::new(Group(Box::new(Concat(vec![ - Exclude(Named(Ident::new("S3"))), - Symbol(Named(Ident::new("S4"))), + Exclude(Named(Ident::new("S3").empty_span())), + Symbol(Named(Ident::new("S4").empty_span())), ])))), OneOrMore, ), @@ -10490,18 +10726,18 @@ fn test_match_recognize_patterns() { Alternation(vec![ Concat(vec![ Symbol(Start), - Symbol(Named(Ident::new("S1"))), + Symbol(Named(Ident::new("S1").empty_span())), Repetition( Box::new(Repetition( - Box::new(Symbol(Named(Ident::new("S2")))), + Box::new(Symbol(Named(Ident::new("S2").empty_span()))), ZeroOrMore, )), AtMostOne, ), Repetition( Box::new(Group(Box::new(Concat(vec![ - Exclude(Named(Ident::new("S3"))), - Symbol(Named(Ident::new("S4"))), + Exclude(Named(Ident::new("S3").empty_span())), + Symbol(Named(Ident::new("S4").empty_span())), ])))), OneOrMore, ), @@ -10509,8 +10745,8 @@ fn test_match_recognize_patterns() { Concat(vec![ Repetition( Box::new(Permute(vec![ - Named(Ident::new("S1")), - Named(Ident::new("S2")), + Named(Ident::new("S1").empty_span()), + Named(Ident::new("S2").empty_span()), ])), Range(1, 2), ), @@ -10534,8 +10770,8 @@ fn test_select_wildcard_with_replace() { let expected = SelectItem::Wildcard(WildcardAdditionalOptions { opt_replace: Some(ReplaceSelectItem { items: vec![Box::new(ReplaceSelectElement { - expr: call("lower", [Expr::Identifier(Ident::new("city"))]), - column_name: Ident::new("city"), + expr: call("lower", [Expr::Identifier(Ident::new("city").empty_span())]), + column_name: Ident::new("city").empty_span(), as_keyword: true, })], }), @@ -10549,7 +10785,7 @@ fn test_select_wildcard_with_replace() { opt_replace: Some(ReplaceSelectItem { items: vec![Box::new(ReplaceSelectElement { expr: Expr::Value(Value::SingleQuotedString("widget".to_owned())), - column_name: Ident::new("item_name"), + column_name: Ident::new("item_name").empty_span(), as_keyword: true, })], }), @@ -10565,16 +10801,16 @@ fn test_select_wildcard_with_replace() { items: vec![ Box::new(ReplaceSelectElement { expr: Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("quantity"))), + left: Box::new(Expr::Identifier(Ident::new("quantity").empty_span())), op: BinaryOperator::Divide, right: Box::new(Expr::Value(number("2"))), }, - column_name: Ident::new("quantity"), + column_name: Ident::new("quantity").empty_span(), as_keyword: true, }), Box::new(ReplaceSelectElement { expr: Expr::Value(number("3")), - column_name: Ident::new("order_id"), + column_name: Ident::new("order_id").empty_span(), as_keyword: true, }), ], @@ -10622,13 +10858,13 @@ fn test_dictionary_syntax() { "{'Alberta': 'Edmonton', 'Manitoba': 'Winnipeg'}", Expr::Dictionary(vec![ DictionaryField { - key: Ident::with_quote('\'', "Alberta"), + key: Ident::with_quote('\'', "Alberta").empty_span(), value: Box::new(Expr::Value(Value::SingleQuotedString( "Edmonton".to_owned(), ))), }, DictionaryField { - key: Ident::with_quote('\'', "Manitoba"), + key: Ident::with_quote('\'', "Manitoba").empty_span(), value: Box::new(Expr::Value(Value::SingleQuotedString( "Winnipeg".to_owned(), ))), @@ -10640,7 +10876,7 @@ fn test_dictionary_syntax() { "{'start': CAST('2023-04-01' AS TIMESTAMP), 'end': CAST('2023-04-05' AS TIMESTAMP)}", Expr::Dictionary(vec![ DictionaryField { - key: Ident::with_quote('\'', "start"), + key: Ident::with_quote('\'', "start").empty_span(), value: Box::new(Expr::Cast { kind: CastKind::Cast, expr: Box::new(Expr::Value(Value::SingleQuotedString( @@ -10651,7 +10887,7 @@ fn test_dictionary_syntax() { }), }, DictionaryField { - key: Ident::with_quote('\'', "end"), + key: Ident::with_quote('\'', "end").empty_span(), value: Box::new(Expr::Cast { kind: CastKind::Cast, expr: Box::new(Expr::Value(Value::SingleQuotedString( @@ -10822,7 +11058,7 @@ fn parse_select_wildcard_with_except() { let select = dialects.verified_only_select("SELECT * EXCEPT (col_a) FROM data"); let expected = SelectItem::Wildcard(WildcardAdditionalOptions { opt_except: Some(ExceptSelectItem { - first_element: Ident::new("col_a"), + first_element: Ident::new("col_a").empty_span(), additional_elements: vec![], }), ..Default::default() @@ -10833,8 +11069,8 @@ fn parse_select_wildcard_with_except() { .verified_only_select("SELECT * EXCEPT (department_id, employee_id) FROM employee_table"); let expected = SelectItem::Wildcard(WildcardAdditionalOptions { opt_except: Some(ExceptSelectItem { - first_element: Ident::new("department_id"), - additional_elements: vec![Ident::new("employee_id")], + first_element: Ident::new("department_id").empty_span(), + additional_elements: vec![Ident::new("employee_id").empty_span()], }), ..Default::default() }); @@ -10881,7 +11117,7 @@ fn test_group_by_nothing() { std::assert_eq!( GroupByExpr::Expressions( vec![ - Identifier(Ident::new("name".to_string())), + Identifier(Ident::new("name".to_string()).empty_span()), Expr::Tuple(vec![]) ], vec![] @@ -10899,10 +11135,13 @@ fn test_extract_seconds_ok() { assert_eq!( stmt, Expr::Extract { - field: DateTimeField::Custom(Ident { - value: "seconds".to_string(), - quote_style: None, - }), + field: DateTimeField::Custom( + Ident { + value: "seconds".to_string(), + quote_style: None, + } + .empty_span() + ), syntax: ExtractSyntax::From, expr: Box::new(Expr::Cast { kind: CastKind::DoubleColon, @@ -10924,10 +11163,13 @@ fn test_extract_seconds_single_quote_ok() { assert_eq!( stmt, Expr::Extract { - field: DateTimeField::Custom(Ident { - value: "seconds".to_string(), - quote_style: Some('\''), - }), + field: DateTimeField::Custom( + Ident { + value: "seconds".to_string(), + quote_style: Some('\''), + } + .empty_span() + ), syntax: ExtractSyntax::From, expr: Box::new(Expr::Cast { kind: CastKind::DoubleColon, @@ -10968,7 +11210,7 @@ fn test_truncate_table_with_on_cluster() { let sql = "TRUNCATE TABLE t ON CLUSTER cluster_name"; match all_dialects().verified_stmt(sql) { Statement::Truncate { on_cluster, .. } => { - assert_eq!(on_cluster, Some(Ident::new("cluster_name"))); + assert_eq!(on_cluster, Some(Ident::new("cluster_name").empty_span())); } _ => panic!("Expected: TRUNCATE TABLE statement"), } @@ -10994,11 +11236,11 @@ fn parse_explain_with_option_list() { None, Some(vec![ UtilityOption { - name: Ident::new("ANALYZE"), + name: Ident::new("ANALYZE").empty_span(), arg: Some(Expr::Value(Value::Boolean(false))), }, UtilityOption { - name: Ident::new("VERBOSE"), + name: Ident::new("VERBOSE").empty_span(), arg: Some(Expr::Value(Value::Boolean(true))), }, ]), @@ -11012,12 +11254,12 @@ fn parse_explain_with_option_list() { None, Some(vec![ UtilityOption { - name: Ident::new("ANALYZE"), - arg: Some(Expr::Identifier(Ident::new("ON"))), + name: Ident::new("ANALYZE").empty_span(), + arg: Some(Expr::Identifier(Ident::new("ON").empty_span())), }, UtilityOption { - name: Ident::new("VERBOSE"), - arg: Some(Expr::Identifier(Ident::new("OFF"))), + name: Ident::new("VERBOSE").empty_span(), + arg: Some(Expr::Identifier(Ident::new("OFF").empty_span())), }, ]), ); @@ -11030,20 +11272,20 @@ fn parse_explain_with_option_list() { None, Some(vec![ UtilityOption { - name: Ident::new("FORMAT1"), - arg: Some(Expr::Identifier(Ident::new("TEXT"))), + name: Ident::new("FORMAT1").empty_span(), + arg: Some(Expr::Identifier(Ident::new("TEXT").empty_span())), }, UtilityOption { - name: Ident::new("FORMAT2"), + name: Ident::new("FORMAT2").empty_span(), arg: Some(Expr::Value(Value::SingleQuotedString("JSON".to_string()))), }, UtilityOption { - name: Ident::new("FORMAT3"), - arg: Some(Expr::Identifier(Ident::with_quote('"', "XML"))), + name: Ident::new("FORMAT3").empty_span(), + arg: Some(Expr::Identifier(Ident::with_quote('"', "XML").empty_span())), }, UtilityOption { - name: Ident::new("FORMAT4"), - arg: Some(Expr::Identifier(Ident::new("YAML"))), + name: Ident::new("FORMAT4").empty_span(), + arg: Some(Expr::Identifier(Ident::new("YAML").empty_span())), }, ]), ); @@ -11056,18 +11298,18 @@ fn parse_explain_with_option_list() { None, Some(vec![ UtilityOption { - name: Ident::new("NUM1"), + name: Ident::new("NUM1").empty_span(), arg: Some(Expr::Value(Value::Number("10".parse().unwrap(), false))), }, UtilityOption { - name: Ident::new("NUM2"), + name: Ident::new("NUM2").empty_span(), arg: Some(Expr::UnaryOp { op: UnaryOperator::Plus, expr: Box::new(Expr::Value(Value::Number("10.1".parse().unwrap(), false))), }), }, UtilityOption { - name: Ident::new("NUM3"), + name: Ident::new("NUM3").empty_span(), arg: Some(Expr::UnaryOp { op: UnaryOperator::Minus, expr: Box::new(Expr::Value(Value::Number("10.2".parse().unwrap(), false))), @@ -11078,23 +11320,23 @@ fn parse_explain_with_option_list() { let utility_options = vec![ UtilityOption { - name: Ident::new("ANALYZE"), + name: Ident::new("ANALYZE").empty_span(), arg: None, }, UtilityOption { - name: Ident::new("VERBOSE"), + name: Ident::new("VERBOSE").empty_span(), arg: Some(Expr::Value(Value::Boolean(true))), }, UtilityOption { - name: Ident::new("WAL"), - arg: Some(Expr::Identifier(Ident::new("OFF"))), + name: Ident::new("WAL").empty_span(), + arg: Some(Expr::Identifier(Ident::new("OFF").empty_span())), }, UtilityOption { - name: Ident::new("FORMAT"), - arg: Some(Expr::Identifier(Ident::new("YAML"))), + name: Ident::new("FORMAT").empty_span(), + arg: Some(Expr::Identifier(Ident::new("YAML").empty_span())), }, UtilityOption { - name: Ident::new("USER_DEF_NUM"), + name: Ident::new("USER_DEF_NUM").empty_span(), arg: Some(Expr::UnaryOp { op: UnaryOperator::Minus, expr: Box::new(Expr::Value(Value::Number("100.1".parse().unwrap(), false))), @@ -11135,14 +11377,14 @@ fn test_create_policy() { assert_eq!( to, Some(vec![ - Owner::Ident(Ident::new("my_role")), + Owner::Ident(Ident::new("my_role").empty_span()), Owner::CurrentUser ]) ); assert_eq!( using, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("c0"))), + left: Box::new(Expr::Identifier(Ident::new("c0").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Number("1".parse().unwrap(), false))), }) @@ -11268,7 +11510,7 @@ fn test_alter_policy() { assert_eq!( operation, AlterPolicyOperation::Rename { - new_name: Ident::new("new_policy") + new_name: Ident::new("new_policy").empty_span() } ); } diff --git a/tests/sqlparser_databricks.rs b/tests/sqlparser_databricks.rs index 7b917bd06..94e7cabc3 100644 --- a/tests/sqlparser_databricks.rs +++ b/tests/sqlparser_databricks.rs @@ -39,7 +39,7 @@ fn test_databricks_identifiers() { // databricks uses backtick for delimited identifiers assert_eq!( databricks().verified_only_select("SELECT `Ä`").projection[0], - SelectItem::UnnamedExpr(Expr::Identifier(Ident::with_quote('`', "Ä"))) + SelectItem::UnnamedExpr(Expr::Identifier(Ident::with_quote('`', "Ä").empty_span())) ); // double quotes produce string literals, not delimited identifiers @@ -68,8 +68,10 @@ fn test_databricks_exists() { ] ), Expr::Lambda(LambdaFunction { - params: OneOrManyWithParens::One(Ident::new("x")), - body: Box::new(Expr::IsNull(Box::new(Expr::Identifier(Ident::new("x"))))) + params: OneOrManyWithParens::One(Ident::new("x").empty_span()), + body: Box::new(Expr::IsNull(Box::new(Expr::Identifier( + Ident::new("x").empty_span() + )))) }) ] ), @@ -104,24 +106,27 @@ fn test_databricks_lambdas() { ] ), Expr::Lambda(LambdaFunction { - params: OneOrManyWithParens::Many(vec![Ident::new("p1"), Ident::new("p2")]), + params: OneOrManyWithParens::Many(vec![ + Ident::new("p1").empty_span(), + Ident::new("p2").empty_span() + ]), body: Box::new(Expr::Case { operand: None, conditions: vec![ Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("p1"))), + left: Box::new(Expr::Identifier(Ident::new("p1").empty_span())), op: BinaryOperator::Eq, - right: Box::new(Expr::Identifier(Ident::new("p2"))) + right: Box::new(Expr::Identifier(Ident::new("p2").empty_span())) }, Expr::BinaryOp { left: Box::new(call( "reverse", - [Expr::Identifier(Ident::new("p1"))] + [Expr::Identifier(Ident::new("p1").empty_span())] )), op: BinaryOperator::Lt, right: Box::new(call( "reverse", - [Expr::Identifier(Ident::new("p2"))] + [Expr::Identifier(Ident::new("p2").empty_span())] )) } ], @@ -186,7 +191,7 @@ fn test_values_clause() { )); assert_eq!( Some(&TableFactor::Table { - name: ObjectName(vec![Ident::new("values")]), + name: ObjectName(vec![Ident::new("values").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -215,7 +220,8 @@ fn parse_use() { databricks().verified_stmt(&format!("USE {}", object_name)), Statement::Use(Use::Object(ObjectName(vec![Ident::new( object_name.to_string() - )]))) + ) + .empty_span()]))) ); for "e in "e_styles { // Test single identifier with different type of quotes @@ -224,7 +230,8 @@ fn parse_use() { Statement::Use(Use::Object(ObjectName(vec![Ident::with_quote( quote, object_name.to_string(), - )]))) + ) + .empty_span()]))) ); } } @@ -236,36 +243,45 @@ fn parse_use() { Statement::Use(Use::Catalog(ObjectName(vec![Ident::with_quote( quote, "my_catalog".to_string(), - )]))) + ) + .empty_span()]))) ); assert_eq!( databricks().verified_stmt(&format!("USE DATABASE {0}my_database{0}", quote)), Statement::Use(Use::Database(ObjectName(vec![Ident::with_quote( quote, "my_database".to_string(), - )]))) + ) + .empty_span()]))) ); assert_eq!( databricks().verified_stmt(&format!("USE SCHEMA {0}my_schema{0}", quote)), Statement::Use(Use::Schema(ObjectName(vec![Ident::with_quote( quote, "my_schema".to_string(), - )]))) + ) + .empty_span()]))) ); } // Test single identifier with keyword and no quotes assert_eq!( databricks().verified_stmt("USE CATALOG my_catalog"), - Statement::Use(Use::Catalog(ObjectName(vec![Ident::new("my_catalog")]))) + Statement::Use(Use::Catalog(ObjectName(vec![ + Ident::new("my_catalog").empty_span() + ]))) ); assert_eq!( databricks().verified_stmt("USE DATABASE my_schema"), - Statement::Use(Use::Database(ObjectName(vec![Ident::new("my_schema")]))) + Statement::Use(Use::Database(ObjectName(vec![ + Ident::new("my_schema").empty_span() + ]))) ); assert_eq!( databricks().verified_stmt("USE SCHEMA my_schema"), - Statement::Use(Use::Schema(ObjectName(vec![Ident::new("my_schema")]))) + Statement::Use(Use::Schema(ObjectName(vec![ + Ident::new("my_schema").empty_span() + ]))) ); // Test invalid syntax - missing identifier diff --git a/tests/sqlparser_duckdb.rs b/tests/sqlparser_duckdb.rs index a4109b0a3..c4c386bd7 100644 --- a/tests/sqlparser_duckdb.rs +++ b/tests/sqlparser_duckdb.rs @@ -40,11 +40,11 @@ fn test_struct() { let struct_type1 = DataType::Struct( vec![ StructField { - field_name: Some(Ident::new("v")), + field_name: Some(Ident::new("v").empty_span()), field_type: DataType::Varchar(None), }, StructField { - field_name: Some(Ident::new("i")), + field_name: Some(Ident::new("i").empty_span()), field_type: DataType::Integer(None), }, ], @@ -56,7 +56,7 @@ fn test_struct() { assert_eq!( column_defs(statement), vec![ColumnDef { - name: "s".into(), + name: Ident::new("s").empty_span(), data_type: struct_type1.clone(), collation: None, options: vec![], @@ -68,7 +68,7 @@ fn test_struct() { assert_eq!( column_defs(statement), vec![ColumnDef { - name: "s".into(), + name: Ident::new("s").empty_span(), data_type: DataType::Array(ArrayElemTypeDef::SquareBracket( Box::new(struct_type1), None @@ -82,19 +82,19 @@ fn test_struct() { let struct_type2 = DataType::Struct( vec![ StructField { - field_name: Some(Ident::new("v")), + field_name: Some(Ident::new("v").empty_span()), field_type: DataType::Varchar(None), }, StructField { - field_name: Some(Ident::new("s")), + field_name: Some(Ident::new("s").empty_span()), field_type: DataType::Struct( vec![ StructField { - field_name: Some(Ident::new("a1")), + field_name: Some(Ident::new("a1").empty_span()), field_type: DataType::Integer(None), }, StructField { - field_name: Some(Ident::new("a2")), + field_name: Some(Ident::new("a2").empty_span()), field_type: DataType::Varchar(None), }, ], @@ -113,7 +113,7 @@ fn test_struct() { assert_eq!( column_defs(statement), vec![ColumnDef { - name: "s".into(), + name: Ident::new("s").empty_span(), data_type: DataType::Array(ArrayElemTypeDef::SquareBracket( Box::new(struct_type2), None @@ -150,7 +150,9 @@ fn column_defs(statement: Statement) -> Vec { fn test_select_wildcard_with_exclude() { let select = duckdb().verified_only_select("SELECT * EXCLUDE (col_a) FROM data"); let expected = SelectItem::Wildcard(WildcardAdditionalOptions { - opt_exclude: Some(ExcludeSelectItem::Multiple(vec![Ident::new("col_a")])), + opt_exclude: Some(ExcludeSelectItem::Multiple(vec![ + Ident::new("col_a").empty_span() + ])), ..Default::default() }); assert_eq!(expected, select.projection[0]); @@ -158,9 +160,11 @@ fn test_select_wildcard_with_exclude() { let select = duckdb().verified_only_select("SELECT name.* EXCLUDE department_id FROM employee_table"); let expected = SelectItem::QualifiedWildcard( - ObjectName(vec![Ident::new("name")]), + ObjectName(vec![Ident::new("name").empty_span()]), WildcardAdditionalOptions { - opt_exclude: Some(ExcludeSelectItem::Single(Ident::new("department_id"))), + opt_exclude: Some(ExcludeSelectItem::Single( + Ident::new("department_id").empty_span(), + )), ..Default::default() }, ); @@ -170,8 +174,8 @@ fn test_select_wildcard_with_exclude() { .verified_only_select("SELECT * EXCLUDE (department_id, employee_id) FROM employee_table"); let expected = SelectItem::Wildcard(WildcardAdditionalOptions { opt_exclude: Some(ExcludeSelectItem::Multiple(vec![ - Ident::new("department_id"), - Ident::new("employee_id"), + Ident::new("department_id").empty_span(), + Ident::new("employee_id").empty_span(), ])), ..Default::default() }); @@ -189,12 +193,15 @@ fn test_create_macro() { let expected = Statement::CreateMacro { or_replace: false, temporary: false, - name: ObjectName(vec![Ident::new("schema"), Ident::new("add")]), + name: ObjectName(vec![ + Ident::new("schema").empty_span(), + Ident::new("add").empty_span(), + ]), args: Some(vec![MacroArg::new("a"), MacroArg::new("b")]), definition: MacroDefinition::Expr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), op: BinaryOperator::Plus, - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }), }; assert_eq!(expected, macro_); @@ -206,18 +213,18 @@ fn test_create_macro_default_args() { let expected = Statement::CreateMacro { or_replace: false, temporary: false, - name: ObjectName(vec![Ident::new("add_default")]), + name: ObjectName(vec![Ident::new("add_default").empty_span()]), args: Some(vec![ MacroArg::new("a"), MacroArg { - name: Ident::new("b"), + name: Ident::new("b").empty_span(), default_expr: Some(Expr::Value(number("5"))), }, ]), definition: MacroDefinition::Expr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), op: BinaryOperator::Plus, - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }), }; assert_eq!(expected, macro_); @@ -234,7 +241,7 @@ fn test_create_table_macro() { let expected = Statement::CreateMacro { or_replace: true, temporary: true, - name: ObjectName(vec![Ident::new("dynamic_table")]), + name: ObjectName(vec![Ident::new("dynamic_table").empty_span()]), args: Some(vec![ MacroArg::new("col1_value"), MacroArg::new("col2_value"), @@ -274,7 +281,8 @@ fn test_select_union_by_name() { name: ObjectName(vec![Ident { value: "capitals".to_string(), quote_style: None, - }]), + } + .empty_span()]), alias: None, args: None, with_hints: vec![], @@ -314,7 +322,8 @@ fn test_select_union_by_name() { name: ObjectName(vec![Ident { value: "weather".to_string(), quote_style: None, - }]), + } + .empty_span()]), alias: None, args: None, with_hints: vec![], @@ -353,6 +362,7 @@ fn test_duckdb_install() { value: "tpch".to_string(), quote_style: None } + .empty_span() } ); } @@ -366,6 +376,7 @@ fn test_duckdb_load_extension() { value: "my_extension".to_string(), quote_style: None } + .empty_span() }, stmt ); @@ -381,15 +392,15 @@ fn test_duckdb_struct_literal() { assert_eq!( &Expr::Dictionary(vec![ DictionaryField { - key: Ident::with_quote('\'', "a"), + key: Ident::with_quote('\'', "a").empty_span(), value: Box::new(Expr::Value(number("1"))), }, DictionaryField { - key: Ident::with_quote('\'', "b"), + key: Ident::with_quote('\'', "b").empty_span(), value: Box::new(Expr::Value(number("2"))), }, DictionaryField { - key: Ident::with_quote('\'', "c"), + key: Ident::with_quote('\'', "c").empty_span(), value: Box::new(Expr::Value(number("3"))), }, ],), @@ -399,7 +410,7 @@ fn test_duckdb_struct_literal() { assert_eq!( &Expr::Array(Array { elem: vec![Expr::Dictionary(vec![DictionaryField { - key: Ident::with_quote('\'', "a"), + key: Ident::with_quote('\'', "a").empty_span(), value: Box::new(Expr::Value(Value::SingleQuotedString("abc".to_string()))), },],)], named: false @@ -409,15 +420,15 @@ fn test_duckdb_struct_literal() { assert_eq!( &Expr::Dictionary(vec![ DictionaryField { - key: Ident::with_quote('\'', "a"), + key: Ident::with_quote('\'', "a").empty_span(), value: Box::new(Expr::Value(number("1"))), }, DictionaryField { - key: Ident::with_quote('\'', "b"), + key: Ident::with_quote('\'', "b").empty_span(), value: Box::new(Expr::Array(Array { elem: vec![Expr::CompoundIdentifier(vec![ - Ident::from("t"), - Ident::from("str_col") + Ident::from("t").empty_span(), + Ident::from("str_col").empty_span(), ])], named: false })), @@ -428,11 +439,11 @@ fn test_duckdb_struct_literal() { assert_eq!( &Expr::Dictionary(vec![ DictionaryField { - key: Ident::with_quote('\'', "a"), + key: Ident::with_quote('\'', "a").empty_span(), value: Expr::Value(number("1")).into(), }, DictionaryField { - key: Ident::with_quote('\'', "b"), + key: Ident::with_quote('\'', "b").empty_span(), value: Expr::Value(Value::SingleQuotedString("abc".to_string())).into(), }, ],), @@ -440,16 +451,16 @@ fn test_duckdb_struct_literal() { ); assert_eq!( &Expr::Dictionary(vec![DictionaryField { - key: Ident::with_quote('\'', "abc"), - value: Expr::Identifier(Ident::from("str_col")).into(), + key: Ident::with_quote('\'', "abc").empty_span(), + value: Expr::Identifier(Ident::from("str_col").empty_span()).into(), }],), expr_from_projection(&select.projection[4]) ); assert_eq!( &Expr::Dictionary(vec![DictionaryField { - key: Ident::with_quote('\'', "a"), + key: Ident::with_quote('\'', "a").empty_span(), value: Expr::Dictionary(vec![DictionaryField { - key: Ident::with_quote('\'', "aa"), + key: Ident::with_quote('\'', "aa").empty_span(), value: Expr::Value(number("1")).into(), }],) .into(), @@ -467,17 +478,17 @@ fn test_create_secret() { or_replace: true, temporary: Some(false), if_not_exists: true, - name: Some(Ident::new("name")), - storage_specifier: Some(Ident::new("storage")), - secret_type: Ident::new("type"), + name: Some(Ident::new("name").empty_span()), + storage_specifier: Some(Ident::new("storage").empty_span()), + secret_type: Ident::new("type").empty_span(), options: vec![ SecretOption { - key: Ident::new("key1"), - value: Ident::new("value1"), + key: Ident::new("key1").empty_span(), + value: Ident::new("value1").empty_span(), }, SecretOption { - key: Ident::new("key2"), - value: Ident::new("value2"), + key: Ident::new("key2").empty_span(), + value: Ident::new("value2").empty_span(), } ] }, @@ -496,7 +507,7 @@ fn test_create_secret_simple() { if_not_exists: false, name: None, storage_specifier: None, - secret_type: Ident::new("type"), + secret_type: Ident::new("type").empty_span(), options: vec![] }, stmt @@ -511,8 +522,8 @@ fn test_drop_secret() { Statement::DropSecret { if_exists: true, temporary: Some(false), - name: Ident::new("secret"), - storage_specifier: Some(Ident::new("storage")) + name: Ident::new("secret").empty_span(), + storage_specifier: Some(Ident::new("storage").empty_span()) }, stmt ); @@ -526,7 +537,7 @@ fn test_drop_secret_simple() { Statement::DropSecret { if_exists: false, temporary: None, - name: Ident::new("secret"), + name: Ident::new("secret").empty_span(), storage_specifier: None }, stmt @@ -541,11 +552,11 @@ fn test_attach_database() { Statement::AttachDuckDBDatabase { if_not_exists: true, database: true, - database_path: Ident::with_quote('\'', "sqlite_file.db"), - database_alias: Some(Ident::new("sqlite_db")), + database_path: Ident::with_quote('\'', "sqlite_file.db").empty_span(), + database_alias: Some(Ident::new("sqlite_db").empty_span()), attach_options: vec![ AttachDuckDBDatabaseOption::ReadOnly(Some(false)), - AttachDuckDBDatabaseOption::Type(Ident::new("SQLITE")), + AttachDuckDBDatabaseOption::Type(Ident::new("SQLITE").empty_span()), ] }, stmt @@ -563,7 +574,8 @@ fn test_attach_database_simple() { database_path: Ident::with_quote( '\'', "postgres://user.name:pass-word@some.url.com:5432/postgres" - ), + ) + .empty_span(), database_alias: None, attach_options: vec![] }, @@ -579,7 +591,7 @@ fn test_detach_database() { Statement::DetachDuckDBDatabase { if_exists: true, database: true, - database_alias: Ident::new("db_name"), + database_alias: Ident::new("db_name").empty_span(), }, stmt ); @@ -593,7 +605,7 @@ fn test_detach_database_simple() { Statement::DetachDuckDBDatabase { if_exists: false, database: false, - database_alias: Ident::new("db_name"), + database_alias: Ident::new("db_name").empty_span(), }, stmt ); @@ -605,20 +617,20 @@ fn test_duckdb_named_argument_function_with_assignment_operator() { let select = duckdb_and_generic().verified_only_select(sql); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("FUN")]), + name: ObjectName(vec![Ident::new("FUN").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, args: vec![ FunctionArg::Named { - name: Ident::new("a"), + name: Ident::new("a").empty_span(), arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( "1".to_owned() ))), operator: FunctionArgOperator::Assignment }, FunctionArg::Named { - name: Ident::new("b"), + name: Ident::new("b").empty_span(), arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( "2".to_owned() ))), @@ -677,26 +689,26 @@ fn test_duckdb_union_datatype() { if_not_exists: Default::default(), transient: Default::default(), volatile: Default::default(), - name: ObjectName(vec!["tbl1".into()]), + name: ObjectName(vec![Ident::new("tbl1").empty_span()]), columns: vec![ ColumnDef { - name: "one".into(), + name: Ident::new("one").empty_span(), data_type: DataType::Union(vec![UnionField { - field_name: "a".into(), + field_name: Ident::new("a").empty_span(), field_type: DataType::Int(None) }]), collation: Default::default(), options: Default::default() }, ColumnDef { - name: "two".into(), + name: Ident::new("two").empty_span(), data_type: DataType::Union(vec![ UnionField { - field_name: "a".into(), + field_name: Ident::new("a").empty_span(), field_type: DataType::Int(None) }, UnionField { - field_name: "b".into(), + field_name: Ident::new("b").empty_span(), field_type: DataType::Int(None) } ]), @@ -704,11 +716,11 @@ fn test_duckdb_union_datatype() { options: Default::default() }, ColumnDef { - name: "nested".into(), + name: Ident::new("nested").empty_span(), data_type: DataType::Union(vec![UnionField { - field_name: "a".into(), + field_name: Ident::new("a").empty_span(), field_type: DataType::Union(vec![UnionField { - field_name: "b".into(), + field_name: Ident::new("b").empty_span(), field_type: DataType::Int(None) }]) }]), @@ -778,7 +790,8 @@ fn parse_use() { duckdb().verified_stmt(&format!("USE {}", object_name)), Statement::Use(Use::Object(ObjectName(vec![Ident::new( object_name.to_string() - )]))) + ) + .empty_span()]))) ); for "e in "e_styles { // Test single identifier with different type of quotes @@ -787,7 +800,8 @@ fn parse_use() { Statement::Use(Use::Object(ObjectName(vec![Ident::with_quote( quote, object_name.to_string(), - )]))) + ) + .empty_span()]))) ); } } @@ -797,8 +811,8 @@ fn parse_use() { assert_eq!( duckdb().verified_stmt(&format!("USE {0}CATALOG{0}.{0}my_schema{0}", quote)), Statement::Use(Use::Object(ObjectName(vec![ - Ident::with_quote(quote, "CATALOG"), - Ident::with_quote(quote, "my_schema") + Ident::with_quote(quote, "CATALOG").empty_span(), + Ident::with_quote(quote, "my_schema").empty_span() ]))) ); } @@ -806,8 +820,8 @@ fn parse_use() { assert_eq!( duckdb().verified_stmt("USE mydb.my_schema"), Statement::Use(Use::Object(ObjectName(vec![ - Ident::new("mydb"), - Ident::new("my_schema") + Ident::new("mydb").empty_span(), + Ident::new("my_schema").empty_span(), ]))) ); } diff --git a/tests/sqlparser_hive.rs b/tests/sqlparser_hive.rs index 10bd374c0..d2e9615ee 100644 --- a/tests/sqlparser_hive.rs +++ b/tests/sqlparser_hive.rs @@ -23,7 +23,7 @@ use sqlparser::ast::{ ClusteredBy, CommentDef, CreateFunctionBody, CreateFunctionUsing, CreateTable, Expr, Function, FunctionArgumentList, FunctionArguments, Ident, ObjectName, OneOrManyWithParens, OrderByExpr, - SelectItem, Statement, TableFactor, UnaryOperator, Use, Value, + SelectItem, SpanWrapped, Statement, TableFactor, UnaryOperator, Use, Value, }; use sqlparser::dialect::{GenericDialect, HiveDialect, MsSqlDialect}; use sqlparser::parser::ParserError; @@ -166,16 +166,16 @@ fn create_table_with_clustered_by() { assert_eq!( clustered_by.unwrap(), ClusteredBy { - columns: vec![Ident::new("a"), Ident::new("b")], + columns: vec![Ident::new("a").empty_span(), Ident::new("b").empty_span()], sorted_by: Some(vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("a")), + expr: Expr::Identifier(Ident::new("a").empty_span()), asc: Some(true), nulls_first: None, with_fill: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("b")), + expr: Expr::Identifier(Ident::new("b").empty_span()), asc: Some(false), nulls_first: None, with_fill: None, @@ -368,14 +368,14 @@ fn set_statement_with_minus() { local: false, hivevar: false, variables: OneOrManyWithParens::One(ObjectName(vec![ - Ident::new("hive"), - Ident::new("tez"), - Ident::new("java"), - Ident::new("opts") + Ident::new("hive").empty_span(), + Ident::new("tez").empty_span(), + Ident::new("java").empty_span(), + Ident::new("opts").empty_span(), ])), value: vec![Expr::UnaryOp { op: UnaryOperator::Minus, - expr: Box::new(Expr::Identifier(Ident::new("Xmx4g"))) + expr: Box::new(Expr::Identifier(Ident::new("Xmx4g").empty_span())) }], } ); @@ -458,8 +458,11 @@ fn parse_delimited_identifiers() { with_ordinality: _, partitions: _, } => { - assert_eq!(vec![Ident::with_quote('"', "a table")], name.0); - assert_eq!(Ident::with_quote('"', "alias"), alias.unwrap().name); + assert_eq!(vec![Ident::with_quote('"', "a table").empty_span()], name.0); + assert_eq!( + Ident::with_quote('"', "alias").empty_span(), + alias.unwrap().name + ); assert!(args.is_none()); assert!(with_hints.is_empty()); assert!(version.is_none()); @@ -470,14 +473,14 @@ fn parse_delimited_identifiers() { assert_eq!(3, select.projection.len()); assert_eq!( &Expr::CompoundIdentifier(vec![ - Ident::with_quote('"', "alias"), - Ident::with_quote('"', "bar baz"), + Ident::with_quote('"', "alias").empty_span(), + Ident::with_quote('"', "bar baz").empty_span(), ]), expr_from_projection(&select.projection[0]), ); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::with_quote('"', "myfun")]), + name: ObjectName(vec![Ident::with_quote('"', "myfun").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -493,8 +496,11 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); - assert_eq!(&Ident::with_quote('"', "column alias"), alias); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); + assert_eq!(&Ident::with_quote('"', "column alias").empty_span(), alias); } _ => panic!("Expected: ExprWithAlias"), } @@ -514,7 +520,8 @@ fn parse_use() { hive().verified_stmt(&format!("USE {}", object_name)), Statement::Use(Use::Object(ObjectName(vec![Ident::new( object_name.to_string() - )]))) + ) + .empty_span()]))) ); for "e in "e_styles { // Test single identifier with different type of quotes @@ -523,7 +530,8 @@ fn parse_use() { Statement::Use(Use::Object(ObjectName(vec![Ident::with_quote( quote, object_name.to_string(), - )]))) + ) + .empty_span()]))) ); } } diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs index 0223e2915..2da14ee2d 100644 --- a/tests/sqlparser_mssql.rs +++ b/tests/sqlparser_mssql.rs @@ -36,11 +36,11 @@ fn parse_mssql_identifiers() { let sql = "SELECT @@version, _foo$123 FROM ##temp"; let select = ms_and_generic().verified_only_select(sql); assert_eq!( - &Expr::Identifier(Ident::new("@@version")), + &Expr::Identifier(Ident::new("@@version").empty_span()), expr_from_projection(&select.projection[0]), ); assert_eq!( - &Expr::Identifier(Ident::new("_foo$123")), + &Expr::Identifier(Ident::new("_foo$123").empty_span()), expr_from_projection(&select.projection[1]), ); assert_eq!(2, select.projection.len()); @@ -61,7 +61,7 @@ fn parse_table_time_travel() { select.from, vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("t1")]), + name: ObjectName(vec![Ident::new("t1").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -137,14 +137,16 @@ fn parse_create_procedure() { name: Ident { value: "@foo".into(), quote_style: None - }, + } + .empty_span(), data_type: DataType::Int(None) }, ProcedureParam { name: Ident { value: "@bar".into(), quote_style: None - }, + } + .empty_span(), data_type: DataType::Varchar(Some(CharacterLength::IntegerLength { length: 256, unit: None @@ -154,7 +156,8 @@ fn parse_create_procedure() { name: ObjectName(vec![Ident { value: "test".into(), quote_style: None - }]) + } + .empty_span()]) } ) } @@ -266,7 +269,8 @@ fn parse_mssql_create_role() { Some(ObjectName(vec![Ident { value: "helena".into(), quote_style: None - }])) + } + .empty_span()])) ); } _ => unreachable!(), @@ -282,12 +286,14 @@ fn parse_alter_role() { name: Ident { value: "old_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::RenameRole { role_name: Ident { value: "new_name".into(), quote_style: None } + .empty_span(), }, }] ); @@ -299,12 +305,14 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::AddMember { member_name: Ident { value: "new_member".into(), quote_style: None } + .empty_span(), }, } ); @@ -316,12 +324,14 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::DropMember { member_name: Ident { value: "old_member".into(), quote_style: None } + .empty_span() }, } ); @@ -344,8 +354,11 @@ fn parse_delimited_identifiers() { with_ordinality: _, partitions: _, } => { - assert_eq!(vec![Ident::with_quote('"', "a table")], name.0); - assert_eq!(Ident::with_quote('"', "alias"), alias.unwrap().name); + assert_eq!(vec![Ident::with_quote('"', "a table").empty_span()], name.0); + assert_eq!( + Ident::with_quote('"', "alias").empty_span(), + alias.unwrap().name + ); assert!(args.is_none()); assert!(with_hints.is_empty()); assert!(version.is_none()); @@ -356,14 +369,14 @@ fn parse_delimited_identifiers() { assert_eq!(3, select.projection.len()); assert_eq!( &Expr::CompoundIdentifier(vec![ - Ident::with_quote('"', "alias"), - Ident::with_quote('"', "bar baz"), + Ident::with_quote('"', "alias").empty_span(), + Ident::with_quote('"', "bar baz").empty_span(), ]), expr_from_projection(&select.projection[0]), ); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::with_quote('"', "myfun")]), + name: ObjectName(vec![Ident::with_quote('"', "myfun").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -379,8 +392,11 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); - assert_eq!(&Ident::with_quote('"', "column alias"), alias); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); + assert_eq!(&Ident::with_quote('"', "column alias").empty_span(), alias); } _ => panic!("Expected ExprWithAlias"), } @@ -396,8 +412,8 @@ fn parse_table_name_in_square_brackets() { if let TableFactor::Table { name, .. } = only(select.from).relation { assert_eq!( vec![ - Ident::with_quote('[', "a schema"), - Ident::with_quote('[', "a table") + Ident::with_quote('[', "a schema").empty_span(), + Ident::with_quote('[', "a table").empty_span(), ], name.0 ); @@ -405,7 +421,7 @@ fn parse_table_name_in_square_brackets() { panic!("Expecting TableFactor::Table"); } assert_eq!( - &Expr::Identifier(Ident::with_quote('[', "a column")), + &Expr::Identifier(Ident::with_quote('[', "a column").empty_span()), expr_from_projection(&select.projection[0]), ); } @@ -515,10 +531,13 @@ fn parse_substring_in_select() { distinct: Some(Distinct::Distinct), top: None, projection: vec![SelectItem::UnnamedExpr(Expr::Substring { - expr: Box::new(Expr::Identifier(Ident { - value: "description".to_string(), - quote_style: None - })), + expr: Box::new(Expr::Identifier( + Ident { + value: "description".to_string(), + quote_style: None + } + .empty_span() + )), substring_from: Some(Box::new(Expr::Value(number("0")))), substring_for: Some(Box::new(Expr::Value(number("1")))), special: true, @@ -529,7 +548,8 @@ fn parse_substring_in_select() { name: ObjectName(vec![Ident { value: "test".to_string(), quote_style: None - }]), + } + .empty_span()]), alias: None, args: None, with_hints: vec![], @@ -573,8 +593,11 @@ fn parse_substring_in_select() { #[test] fn parse_mssql_declare() { let sql = "DECLARE @foo CURSOR, @bar INT, @baz AS TEXT = 'foobar';"; - let ast = Parser::parse_sql(&MsSqlDialect {}, sql).unwrap(); - + let ast = Parser::new(&MsSqlDialect {}) + .try_with_sql_no_locations(sql) + .unwrap() + .parse_statements() + .unwrap(); assert_eq!( vec![Statement::Declare { stmts: vec![ @@ -582,7 +605,8 @@ fn parse_mssql_declare() { names: vec![Ident { value: "@foo".to_string(), quote_style: None - }], + } + .empty_span()], data_type: None, assignment: None, declare_type: Some(DeclareType::Cursor), @@ -596,7 +620,8 @@ fn parse_mssql_declare() { names: vec![Ident { value: "@bar".to_string(), quote_style: None - }], + } + .empty_span()], data_type: Some(Int(None)), assignment: None, declare_type: None, @@ -610,7 +635,8 @@ fn parse_mssql_declare() { names: vec![Ident { value: "@baz".to_string(), quote_style: None - }], + } + .empty_span()], data_type: Some(Text), assignment: Some(MsSqlAssignment(Box::new(Expr::Value(SingleQuotedString( "foobar".to_string() @@ -645,7 +671,8 @@ fn parse_use() { ms().verified_stmt(&format!("USE {}", object_name)), Statement::Use(Use::Object(ObjectName(vec![Ident::new( object_name.to_string() - )]))) + ) + .empty_span()]))) ); for "e in "e_styles { // Test single identifier with different type of quotes @@ -654,7 +681,8 @@ fn parse_use() { Statement::Use(Use::Object(ObjectName(vec![Ident::with_quote( quote, object_name.to_string(), - )]))) + ) + .empty_span()]))) ); } } @@ -670,14 +698,14 @@ fn parse_create_table_with_valid_options() { key: Ident { value: "DISTRIBUTION".to_string(), quote_style: None, - }, + }.empty_span(), value: Expr::Identifier(Ident { value: "ROUND_ROBIN".to_string(), quote_style: None, - }) + }.empty_span()) }, SqlOption::Partition { - column_name: "column_a".into(), + column_name: Ident::new("column_a").empty_span(), range_direction: None, for_values: vec![Expr::Value(test_utils::number("10")), Expr::Value(test_utils::number("11"))] , }, @@ -687,7 +715,7 @@ fn parse_create_table_with_valid_options() { "CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (PARTITION (column_a RANGE LEFT FOR VALUES (10, 11)))", vec![ SqlOption::Partition { - column_name: "column_a".into(), + column_name: Ident::new("column_a").empty_span(), range_direction: Some(PartitionRangeDirection::Left), for_values: vec![ Expr::Value(test_utils::number("10")), @@ -704,8 +732,8 @@ fn parse_create_table_with_valid_options() { "CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (CLUSTERED COLUMNSTORE INDEX ORDER (column_a, column_b))", vec![ SqlOption::Clustered(TableOptionsClustered::ColumnstoreIndexOrder(vec![ - "column_a".into(), - "column_b".into(), + Ident::new("column_a").empty_span(), + Ident::new("column_b").empty_span(), ])) ], ), @@ -717,21 +745,21 @@ fn parse_create_table_with_valid_options() { name: Ident { value: "column_a".to_string(), quote_style: None, - }, + }.empty_span(), asc: Some(true), }, ClusteredIndex { name: Ident { value: "column_b".to_string(), quote_style: None, - }, + }.empty_span(), asc: Some(false), }, ClusteredIndex { name: Ident { value: "column_c".to_string(), quote_style: None, - }, + }.empty_span(), asc: None, }, ])) @@ -744,7 +772,7 @@ fn parse_create_table_with_valid_options() { key: Ident { value: "DISTRIBUTION".to_string(), quote_style: None, - }, + }.empty_span(), value: Expr::Function( Function { name: ObjectName( @@ -752,7 +780,7 @@ fn parse_create_table_with_valid_options() { Ident { value: "HASH".to_string(), quote_style: None, - }, + }.empty_span(), ], ), parameters: FunctionArguments::None, @@ -766,7 +794,7 @@ fn parse_create_table_with_valid_options() { Ident { value: "column_a".to_string(), quote_style: None, - }, + }.empty_span(), ), ), ), @@ -776,7 +804,7 @@ fn parse_create_table_with_valid_options() { Ident { value: "column_b".to_string(), quote_style: None, - }, + }.empty_span(), ), ), ), @@ -791,7 +819,7 @@ fn parse_create_table_with_valid_options() { }, ), }, - SqlOption::Ident("HEAP".into()), + SqlOption::Ident(Ident::new("HEAP").empty_span()), ], ), ]; @@ -810,13 +838,15 @@ fn parse_create_table_with_valid_options() { name: ObjectName(vec![Ident { value: "mytable".to_string(), quote_style: None, - },],), + } + .empty_span(),],), columns: vec![ ColumnDef { name: Ident { value: "column_a".to_string(), quote_style: None, - }, + } + .empty_span(), data_type: Int(None,), collation: None, options: vec![], @@ -825,7 +855,8 @@ fn parse_create_table_with_valid_options() { name: Ident { value: "column_b".to_string(), quote_style: None, - }, + } + .empty_span(), data_type: Int(None,), collation: None, options: vec![], @@ -834,7 +865,8 @@ fn parse_create_table_with_valid_options() { name: Ident { value: "column_c".to_string(), quote_style: None, - }, + } + .empty_span(), data_type: Int(None,), collation: None, options: vec![], @@ -975,12 +1007,14 @@ fn parse_create_table_with_identity_column() { name: ObjectName(vec![Ident { value: "mytable".to_string(), quote_style: None, - },],), + } + .empty_span(),],), columns: vec![ColumnDef { name: Ident { value: "columnA".to_string(), quote_style: None, - }, + } + .empty_span(), data_type: Int(None,), collation: None, options: column_options, diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index db5b9ec8d..a61609d82 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -143,16 +143,19 @@ fn parse_flush() { Ident { value: "mek".to_string(), quote_style: Some('`') - }, + } + .empty_span(), Ident { value: "table1".to_string(), quote_style: Some('`') } + .empty_span(), ]), ObjectName(vec![Ident { value: "table2".to_string(), quote_style: None - }]) + } + .empty_span()]) ] } ); @@ -180,16 +183,19 @@ fn parse_flush() { Ident { value: "mek".to_string(), quote_style: Some('`') - }, + } + .empty_span(), Ident { value: "table1".to_string(), quote_style: Some('`') } + .empty_span(), ]), ObjectName(vec![Ident { value: "table2".to_string(), quote_style: None - }]) + } + .empty_span()]) ] } ); @@ -206,16 +212,19 @@ fn parse_flush() { Ident { value: "mek".to_string(), quote_style: Some('`') - }, + } + .empty_span(), Ident { value: "table1".to_string(), quote_style: Some('`') } + .empty_span(), ]), ObjectName(vec![Ident { value: "table2".to_string(), quote_style: None - }]) + } + .empty_span()]) ] } ); @@ -223,7 +232,7 @@ fn parse_flush() { #[test] fn parse_show_columns() { - let table_name = ObjectName(vec![Ident::new("mytable")]); + let table_name = ObjectName(vec![Ident::new("mytable").empty_span()]); assert_eq!( mysql_and_generic().verified_stmt("SHOW COLUMNS FROM mytable"), Statement::ShowColumns { @@ -238,7 +247,10 @@ fn parse_show_columns() { Statement::ShowColumns { extended: false, full: false, - table_name: ObjectName(vec![Ident::new("mydb"), Ident::new("mytable")]), + table_name: ObjectName(vec![ + Ident::new("mydb").empty_span(), + Ident::new("mytable").empty_span() + ]), filter: None, } ); @@ -338,7 +350,7 @@ fn parse_show_tables() { Statement::ShowTables { extended: false, full: false, - db_name: Some(Ident::new("mydb")), + db_name: Some(Ident::new("mydb").empty_span()), filter: None, } ); @@ -405,7 +417,7 @@ fn parse_show_extended_full() { #[test] fn parse_show_create() { - let obj_name = ObjectName(vec![Ident::new("myident")]); + let obj_name = ObjectName(vec![Ident::new("myident").empty_span()]); for obj_type in &[ ShowCreateObject::Table, @@ -464,7 +476,8 @@ fn parse_use() { mysql_and_generic().verified_stmt(&format!("USE {}", object_name)), Statement::Use(Use::Object(ObjectName(vec![Ident::new( object_name.to_string() - )]))) + ) + .empty_span()]))) ); for "e in "e_styles { // Test single identifier with different type of quotes @@ -474,7 +487,8 @@ fn parse_use() { Statement::Use(Use::Object(ObjectName(vec![Ident::with_quote( quote, object_name.to_string(), - )]))) + ) + .empty_span()]))) ); } } @@ -488,7 +502,9 @@ fn parse_set_variables() { Statement::SetVariable { local: true, hivevar: false, - variables: OneOrManyWithParens::One(ObjectName(vec!["autocommit".into()])), + variables: OneOrManyWithParens::One(ObjectName(vec![ + Ident::new("autocommit").empty_span() + ])), value: vec![Expr::Value(number("1"))], } ); @@ -502,7 +518,7 @@ fn parse_create_table_auto_increment() { assert_eq!(name.to_string(), "foo"); assert_eq!( vec![ColumnDef { - name: Ident::new("bar"), + name: Ident::new("bar").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ @@ -531,10 +547,10 @@ fn parse_create_table_auto_increment() { /// if `unique_index_type_display` is `Some` create `TableConstraint::Unique` /// otherwise create `TableConstraint::Primary` fn table_constraint_unique_primary_ctor( - name: Option, - index_name: Option, + name: Option>, + index_name: Option>, index_type: Option, - columns: Vec, + columns: Vec>, index_options: Vec, characteristics: Option, unique_index_type_display: Option, @@ -578,10 +594,10 @@ fn parse_create_table_primary_and_unique_key() { assert_eq!(name.to_string(), "foo"); let expected_constraint = table_constraint_unique_primary_ctor( - Some(Ident::new("bar_key")), + Some(Ident::new("bar_key").empty_span()), None, None, - vec![Ident::new("bar")], + vec![Ident::new("bar").empty_span()], vec![], None, index_type_display, @@ -591,7 +607,7 @@ fn parse_create_table_primary_and_unique_key() { assert_eq!( vec![ ColumnDef { - name: Ident::new("id"), + name: Ident::new("id").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ @@ -611,7 +627,7 @@ fn parse_create_table_primary_and_unique_key() { ], }, ColumnDef { - name: Ident::new("bar"), + name: Ident::new("bar").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -643,10 +659,13 @@ fn parse_create_table_primary_and_unique_key_with_index_options() { assert_eq!(name.to_string(), "foo"); let expected_constraint = table_constraint_unique_primary_ctor( - Some(Ident::new("constr")), - Some(Ident::new("index_name")), + Some(Ident::new("constr").empty_span()), + Some(Ident::new("index_name").empty_span()), None, - vec![Ident::new("bar"), Ident::new("var")], + vec![ + Ident::new("bar").empty_span(), + Ident::new("var").empty_span(), + ], vec![ IndexOption::Using(IndexType::Hash), IndexOption::Comment("yes, ".into()), @@ -682,9 +701,9 @@ fn parse_create_table_primary_and_unique_key_with_index_type() { let expected_constraint = table_constraint_unique_primary_ctor( None, - Some(Ident::new("index_name")), + Some(Ident::new("index_name").empty_span()), Some(IndexType::BTree), - vec![Ident::new("bar")], + vec![Ident::new("bar").empty_span()], vec![IndexOption::Using(IndexType::Hash)], None, index_type_display, @@ -761,13 +780,13 @@ fn parse_create_table_set_enum() { assert_eq!( vec![ ColumnDef { - name: Ident::new("bar"), + name: Ident::new("bar").empty_span(), data_type: DataType::Set(vec!["a".to_string(), "b".to_string()]), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("baz"), + name: Ident::new("baz").empty_span(), data_type: DataType::Enum(vec!["a".to_string(), "b".to_string()]), collation: None, options: vec![], @@ -794,7 +813,7 @@ fn parse_create_table_engine_default_charset() { assert_eq!(name.to_string(), "foo"); assert_eq!( vec![ColumnDef { - name: Ident::new("id"), + name: Ident::new("id").empty_span(), data_type: DataType::Int(Some(11)), collation: None, options: vec![], @@ -827,7 +846,7 @@ fn parse_create_table_collate() { assert_eq!(name.to_string(), "foo"); assert_eq!( vec![ColumnDef { - name: Ident::new("id"), + name: Ident::new("id").empty_span(), data_type: DataType::Int(Some(11)), collation: None, options: vec![], @@ -875,7 +894,7 @@ fn parse_create_table_comment_character_set() { assert_eq!(name.to_string(), "foo"); assert_eq!( vec![ColumnDef { - name: Ident::new("s"), + name: Ident::new("s").empty_span(), data_type: DataType::Text, collation: None, options: vec![ @@ -883,7 +902,8 @@ fn parse_create_table_comment_character_set() { name: None, option: ColumnOption::CharacterSet(ObjectName(vec![Ident::new( "utf8mb4" - )])) + ) + .empty_span()])) }, ColumnOptionDef { name: None, @@ -922,7 +942,7 @@ fn parse_quote_identifiers() { assert_eq!(name.to_string(), "`PRIMARY`"); assert_eq!( vec![ColumnDef { - name: Ident::with_quote('`', "BEGIN"), + name: Ident::with_quote('`', "BEGIN").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -950,10 +970,13 @@ fn parse_escaped_quote_identifiers_with_escape() { body: Box::new(SetExpr::Select(Box::new(Select { distinct: None, top: None, - projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "quoted ` identifier".into(), - quote_style: Some('`'), - }))], + projection: vec![SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "quoted ` identifier".into(), + quote_style: Some('`'), + } + .empty_span() + ))], into: None, from: vec![], lateral_views: vec![], @@ -1000,10 +1023,13 @@ fn parse_escaped_quote_identifiers_with_no_escape() { body: Box::new(SetExpr::Select(Box::new(Select { distinct: None, top: None, - projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "quoted `` identifier".into(), - quote_style: Some('`'), - }))], + projection: vec![SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "quoted `` identifier".into(), + quote_style: Some('`'), + } + .empty_span() + ))], into: None, from: vec![], lateral_views: vec![], @@ -1043,10 +1069,13 @@ fn parse_escaped_backticks_with_escape() { body: Box::new(SetExpr::Select(Box::new(Select { distinct: None, top: None, - projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "`quoted identifier`".into(), - quote_style: Some('`'), - }))], + projection: vec![SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "`quoted identifier`".into(), + quote_style: Some('`'), + } + .empty_span() + ))], into: None, from: vec![], lateral_views: vec![], @@ -1090,10 +1119,13 @@ fn parse_escaped_backticks_with_no_escape() { body: Box::new(SetExpr::Select(Box::new(Select { distinct: None, top: None, - projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "``quoted identifier``".into(), - quote_style: Some('`'), - }))], + projection: vec![SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "``quoted identifier``".into(), + quote_style: Some('`'), + } + .empty_span() + ))], into: None, from: vec![], lateral_views: vec![], @@ -1167,31 +1199,31 @@ fn parse_create_table_with_minimum_display_width() { assert_eq!( vec![ ColumnDef { - name: Ident::new("bar_tinyint"), + name: Ident::new("bar_tinyint").empty_span(), data_type: DataType::TinyInt(Some(3)), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("bar_smallint"), + name: Ident::new("bar_smallint").empty_span(), data_type: DataType::SmallInt(Some(5)), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("bar_mediumint"), + name: Ident::new("bar_mediumint").empty_span(), data_type: DataType::MediumInt(Some(6)), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("bar_int"), + name: Ident::new("bar_int").empty_span(), data_type: DataType::Int(Some(11)), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("bar_bigint"), + name: Ident::new("bar_bigint").empty_span(), data_type: DataType::BigInt(Some(20)), collation: None, options: vec![], @@ -1213,31 +1245,31 @@ fn parse_create_table_unsigned() { assert_eq!( vec![ ColumnDef { - name: Ident::new("bar_tinyint"), + name: Ident::new("bar_tinyint").empty_span(), data_type: DataType::UnsignedTinyInt(Some(3)), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("bar_smallint"), + name: Ident::new("bar_smallint").empty_span(), data_type: DataType::UnsignedSmallInt(Some(5)), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("bar_mediumint"), + name: Ident::new("bar_mediumint").empty_span(), data_type: DataType::UnsignedMediumInt(Some(13)), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("bar_int"), + name: Ident::new("bar_int").empty_span(), data_type: DataType::UnsignedInt(Some(11)), collation: None, options: vec![], }, ColumnDef { - name: Ident::new("bar_bigint"), + name: Ident::new("bar_bigint").empty_span(), data_type: DataType::UnsignedBigInt(Some(20)), collation: None, options: vec![], @@ -1262,8 +1294,17 @@ fn parse_simple_insert() { on, .. }) => { - assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); - assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); + assert_eq!( + ObjectName(vec![Ident::new("tasks").empty_span()]), + table_name + ); + assert_eq!( + vec![ + Ident::new("title").empty_span(), + Ident::new("priority").empty_span() + ], + columns + ); assert!(on.is_none()); assert_eq!( Some(Box::new(Query { @@ -1317,8 +1358,17 @@ fn parse_ignore_insert() { ignore, .. }) => { - assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); - assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); + assert_eq!( + ObjectName(vec![Ident::new("tasks").empty_span()]), + table_name + ); + assert_eq!( + vec![ + Ident::new("title").empty_span(), + Ident::new("priority").empty_span() + ], + columns + ); assert!(on.is_none()); assert!(ignore); assert_eq!( @@ -1361,8 +1411,17 @@ fn parse_priority_insert() { priority, .. }) => { - assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); - assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); + assert_eq!( + ObjectName(vec![Ident::new("tasks").empty_span()]), + table_name + ); + assert_eq!( + vec![ + Ident::new("title").empty_span(), + Ident::new("priority").empty_span() + ], + columns + ); assert!(on.is_none()); assert_eq!(priority, Some(HighPriority)); assert_eq!( @@ -1402,8 +1461,17 @@ fn parse_priority_insert() { priority, .. }) => { - assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); - assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); + assert_eq!( + ObjectName(vec![Ident::new("tasks").empty_span()]), + table_name + ); + assert_eq!( + vec![ + Ident::new("title").empty_span(), + Ident::new("priority").empty_span() + ], + columns + ); assert!(on.is_none()); assert_eq!(priority, Some(LowPriority)); assert_eq!( @@ -1445,14 +1513,14 @@ fn parse_insert_as() { .. }) => { assert_eq!( - ObjectName(vec![Ident::with_quote('`', "table")]), + ObjectName(vec![Ident::with_quote('`', "table").empty_span()]), table_name ); - assert_eq!(vec![Ident::with_quote('`', "date")], columns); + assert_eq!(vec![Ident::with_quote('`', "date").empty_span()], columns); let insert_alias = insert_alias.unwrap(); assert_eq!( - ObjectName(vec![Ident::with_quote('`', "alias")]), + ObjectName(vec![Ident::with_quote('`', "alias").empty_span()]), insert_alias.row_alias ); assert_eq!(Some(vec![]), insert_alias.col_aliases); @@ -1497,22 +1565,25 @@ fn parse_insert_as() { .. }) => { assert_eq!( - ObjectName(vec![Ident::with_quote('`', "table")]), + ObjectName(vec![Ident::with_quote('`', "table").empty_span()]), table_name ); assert_eq!( - vec![Ident::with_quote('`', "id"), Ident::with_quote('`', "date")], + vec![ + Ident::with_quote('`', "id").empty_span(), + Ident::with_quote('`', "date").empty_span() + ], columns ); let insert_alias = insert_alias.unwrap(); assert_eq!( - ObjectName(vec![Ident::with_quote('`', "alias")]), + ObjectName(vec![Ident::with_quote('`', "alias").empty_span()]), insert_alias.row_alias ); assert_eq!( Some(vec![ - Ident::with_quote('`', "mek_id"), - Ident::with_quote('`', "mek_date") + Ident::with_quote('`', "mek_id").empty_span(), + Ident::with_quote('`', "mek_date").empty_span(), ]), insert_alias.col_aliases ); @@ -1556,8 +1627,17 @@ fn parse_replace_insert() { priority, .. }) => { - assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); - assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); + assert_eq!( + ObjectName(vec![Ident::new("tasks").empty_span()]), + table_name + ); + assert_eq!( + vec![ + Ident::new("title").empty_span(), + Ident::new("priority").empty_span() + ], + columns + ); assert!(on.is_none()); assert!(replace_into); assert_eq!(priority, Some(Delayed)); @@ -1600,7 +1680,7 @@ fn parse_empty_row_insert() { on, .. }) => { - assert_eq!(ObjectName(vec![Ident::new("tb")]), table_name); + assert_eq!(ObjectName(vec![Ident::new("tb").empty_span()]), table_name); assert!(columns.is_empty()); assert!(on.is_none()); assert_eq!( @@ -1640,17 +1720,17 @@ fn parse_insert_with_on_duplicate_update() { .. }) => { assert_eq!( - ObjectName(vec![Ident::new("permission_groups")]), + ObjectName(vec![Ident::new("permission_groups").empty_span()]), table_name ); assert_eq!( vec![ - Ident::new("name"), - Ident::new("description"), - Ident::new("perm_create"), - Ident::new("perm_read"), - Ident::new("perm_update"), - Ident::new("perm_delete") + Ident::new("name").empty_span(), + Ident::new("description").empty_span(), + Ident::new("perm_create").empty_span(), + Ident::new("perm_read").empty_span(), + Ident::new("perm_update").empty_span(), + Ident::new("perm_delete").empty_span(), ], columns ); @@ -1689,32 +1769,52 @@ fn parse_insert_with_on_duplicate_update() { Assignment { target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new( "description".to_string() - )])), - value: call("VALUES", [Expr::Identifier(Ident::new("description"))]), + ) + .empty_span()])), + value: call( + "VALUES", + [Expr::Identifier(Ident::new("description").empty_span())] + ), }, Assignment { target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new( "perm_create".to_string() - )])), - value: call("VALUES", [Expr::Identifier(Ident::new("perm_create"))]), + ) + .empty_span()])), + value: call( + "VALUES", + [Expr::Identifier(Ident::new("perm_create").empty_span())] + ), }, Assignment { target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new( "perm_read".to_string() - )])), - value: call("VALUES", [Expr::Identifier(Ident::new("perm_read"))]), + ) + .empty_span()])), + value: call( + "VALUES", + [Expr::Identifier(Ident::new("perm_read").empty_span())] + ), }, Assignment { target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new( "perm_update".to_string() - )])), - value: call("VALUES", [Expr::Identifier(Ident::new("perm_update"))]), + ) + .empty_span()])), + value: call( + "VALUES", + [Expr::Identifier(Ident::new("perm_update").empty_span())] + ), }, Assignment { target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new( "perm_delete".to_string() - )])), - value: call("VALUES", [Expr::Identifier(Ident::new("perm_delete"))]), + ) + .empty_span()])), + value: call( + "VALUES", + [Expr::Identifier(Ident::new("perm_delete").empty_span())] + ), }, ])), on @@ -1734,13 +1834,13 @@ fn parse_select_with_numeric_prefix_column_name() { Box::new(SetExpr::Select(Box::new(Select { distinct: None, top: None, - projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident::new( - "123col_$@123abc" - )))], + projection: vec![SelectItem::UnnamedExpr(Expr::Identifier( + Ident::new("123col_$@123abc").empty_span() + ))], into: None, from: vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::with_quote('"', "table")]), + name: ObjectName(vec![Ident::with_quote('"', "table").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -1790,12 +1890,14 @@ fn parse_select_with_concatenation_of_exp_number_and_numeric_prefix_column() { top: None, projection: vec![ SelectItem::UnnamedExpr(Expr::Value(number("123e4"))), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("123col_$@123abc"))) + SelectItem::UnnamedExpr(Expr::Identifier( + Ident::new("123col_$@123abc").empty_span() + )) ], into: None, from: vec![TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::with_quote('"', "table")]), + name: ObjectName(vec![Ident::with_quote('"', "table").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -1835,10 +1937,13 @@ fn parse_insert_with_numeric_prefix_column_name() { .. }) => { assert_eq!( - ObjectName(vec![Ident::new("s1"), Ident::new("t1")]), + ObjectName(vec![ + Ident::new("s1").empty_span(), + Ident::new("t1").empty_span() + ]), table_name ); - assert_eq!(vec![Ident::new("123col_$@length123")], columns); + assert_eq!(vec![Ident::new("123col_$@length123").empty_span()], columns); } _ => unreachable!(), } @@ -1858,9 +1963,9 @@ fn parse_update_with_joins() { assert_eq!( TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("orders")]), + name: ObjectName(vec![Ident::new("orders").empty_span()]), alias: Some(TableAlias { - name: Ident::new("o"), + name: Ident::new("o").empty_span(), columns: vec![] }), args: None, @@ -1871,9 +1976,9 @@ fn parse_update_with_joins() { }, joins: vec![Join { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("customers")]), + name: ObjectName(vec![Ident::new("customers").empty_span()]), alias: Some(TableAlias { - name: Ident::new("c"), + name: Ident::new("c").empty_span(), columns: vec![] }), args: None, @@ -1885,13 +1990,13 @@ fn parse_update_with_joins() { global: false, join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("o"), - Ident::new("customer_id") + Ident::new("o").empty_span(), + Ident::new("customer_id").empty_span() ])), op: BinaryOperator::Eq, right: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("c"), - Ident::new("id") + Ident::new("c").empty_span(), + Ident::new("id").empty_span(), ])) })), }] @@ -1901,8 +2006,8 @@ fn parse_update_with_joins() { assert_eq!( vec![Assignment { target: AssignmentTarget::ColumnName(ObjectName(vec![ - Ident::new("o"), - Ident::new("completed") + Ident::new("o").empty_span(), + Ident::new("completed").empty_span(), ])), value: Expr::Value(Value::Boolean(true)) }], @@ -1911,8 +2016,8 @@ fn parse_update_with_joins() { assert_eq!( Some(Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("c"), - Ident::new("firstname") + Ident::new("c").empty_span(), + Ident::new("firstname").empty_span(), ])), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::SingleQuotedString("Peter".to_string()))) @@ -1932,10 +2037,13 @@ fn parse_delete_with_order_by() { Statement::Delete(Delete { order_by, .. }) => { assert_eq!( vec![OrderByExpr { - expr: Expr::Identifier(Ident { - value: "id".to_owned(), - quote_style: None - }), + expr: Expr::Identifier( + Ident { + value: "id".to_owned(), + quote_style: None + } + .empty_span() + ), asc: Some(false), nulls_first: None, with_fill: None, @@ -1978,7 +2086,7 @@ fn parse_alter_table_add_column() { column_keyword: true, if_not_exists: false, column_def: ColumnDef { - name: "b".into(), + name: Ident::new("b").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![], @@ -2008,15 +2116,18 @@ fn parse_alter_table_add_column() { column_keyword: true, if_not_exists: false, column_def: ColumnDef { - name: "b".into(), + name: Ident::new("b").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![], }, - column_position: Some(MySQLColumnPosition::After(Ident { - value: String::from("foo"), - quote_style: None - })), + column_position: Some(MySQLColumnPosition::After( + Ident { + value: String::from("foo"), + quote_style: None + } + .empty_span() + )), },] ); } @@ -2047,7 +2158,7 @@ fn parse_alter_table_add_columns() { column_keyword: true, if_not_exists: false, column_def: ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Text, collation: None, options: vec![], @@ -2058,15 +2169,18 @@ fn parse_alter_table_add_columns() { column_keyword: true, if_not_exists: false, column_def: ColumnDef { - name: "b".into(), + name: Ident::new("b").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![], }, - column_position: Some(MySQLColumnPosition::After(Ident { - value: String::from("foo"), - quote_style: None, - })), + column_position: Some(MySQLColumnPosition::After( + Ident { + value: String::from("foo"), + quote_style: None, + } + .empty_span() + )), }, ] ); @@ -2085,10 +2199,10 @@ fn parse_alter_table_drop_primary_key() { #[test] fn parse_alter_table_change_column() { - let expected_name = ObjectName(vec![Ident::new("orders")]); + let expected_name = ObjectName(vec![Ident::new("orders").empty_span()]); let expected_operation = AlterTableOperation::ChangeColumn { - old_name: Ident::new("description"), - new_name: Ident::new("desc"), + old_name: Ident::new("description").empty_span(), + new_name: Ident::new("desc").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], column_position: None, @@ -2107,8 +2221,8 @@ fn parse_alter_table_change_column() { assert_eq!(expected_operation, operation); let expected_operation = AlterTableOperation::ChangeColumn { - old_name: Ident::new("description"), - new_name: Ident::new("desc"), + old_name: Ident::new("description").empty_span(), + new_name: Ident::new("desc").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], column_position: Some(MySQLColumnPosition::First), @@ -2119,14 +2233,17 @@ fn parse_alter_table_change_column() { assert_eq!(expected_operation, operation); let expected_operation = AlterTableOperation::ChangeColumn { - old_name: Ident::new("description"), - new_name: Ident::new("desc"), + old_name: Ident::new("description").empty_span(), + new_name: Ident::new("desc").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], - column_position: Some(MySQLColumnPosition::After(Ident { - value: String::from("foo"), - quote_style: None, - })), + column_position: Some(MySQLColumnPosition::After( + Ident { + value: String::from("foo"), + quote_style: None, + } + .empty_span(), + )), }; let sql4 = "ALTER TABLE orders CHANGE COLUMN description desc TEXT NOT NULL AFTER foo"; let operation = @@ -2136,10 +2253,10 @@ fn parse_alter_table_change_column() { #[test] fn parse_alter_table_change_column_with_column_position() { - let expected_name = ObjectName(vec![Ident::new("orders")]); + let expected_name = ObjectName(vec![Ident::new("orders").empty_span()]); let expected_operation_first = AlterTableOperation::ChangeColumn { - old_name: Ident::new("description"), - new_name: Ident::new("desc"), + old_name: Ident::new("description").empty_span(), + new_name: Ident::new("desc").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], column_position: Some(MySQLColumnPosition::First), @@ -2158,14 +2275,17 @@ fn parse_alter_table_change_column_with_column_position() { assert_eq!(expected_operation_first, operation); let expected_operation_after = AlterTableOperation::ChangeColumn { - old_name: Ident::new("description"), - new_name: Ident::new("desc"), + old_name: Ident::new("description").empty_span(), + new_name: Ident::new("desc").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], - column_position: Some(MySQLColumnPosition::After(Ident { - value: String::from("total_count"), - quote_style: None, - })), + column_position: Some(MySQLColumnPosition::After( + Ident { + value: String::from("total_count"), + quote_style: None, + } + .empty_span(), + )), }; let sql1 = "ALTER TABLE orders CHANGE COLUMN description desc TEXT NOT NULL AFTER total_count"; @@ -2183,9 +2303,9 @@ fn parse_alter_table_change_column_with_column_position() { #[test] fn parse_alter_table_modify_column() { - let expected_name = ObjectName(vec![Ident::new("orders")]); + let expected_name = ObjectName(vec![Ident::new("orders").empty_span()]); let expected_operation = AlterTableOperation::ModifyColumn { - col_name: Ident::new("description"), + col_name: Ident::new("description").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], column_position: None, @@ -2204,7 +2324,7 @@ fn parse_alter_table_modify_column() { assert_eq!(expected_operation, operation); let expected_operation = AlterTableOperation::ModifyColumn { - col_name: Ident::new("description"), + col_name: Ident::new("description").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], column_position: Some(MySQLColumnPosition::First), @@ -2215,13 +2335,16 @@ fn parse_alter_table_modify_column() { assert_eq!(expected_operation, operation); let expected_operation = AlterTableOperation::ModifyColumn { - col_name: Ident::new("description"), + col_name: Ident::new("description").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], - column_position: Some(MySQLColumnPosition::After(Ident { - value: String::from("foo"), - quote_style: None, - })), + column_position: Some(MySQLColumnPosition::After( + Ident { + value: String::from("foo"), + quote_style: None, + } + .empty_span(), + )), }; let sql4 = "ALTER TABLE orders MODIFY COLUMN description TEXT NOT NULL AFTER foo"; let operation = @@ -2231,9 +2354,9 @@ fn parse_alter_table_modify_column() { #[test] fn parse_alter_table_modify_column_with_column_position() { - let expected_name = ObjectName(vec![Ident::new("orders")]); + let expected_name = ObjectName(vec![Ident::new("orders").empty_span()]); let expected_operation_first = AlterTableOperation::ModifyColumn { - col_name: Ident::new("description"), + col_name: Ident::new("description").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], column_position: Some(MySQLColumnPosition::First), @@ -2252,13 +2375,16 @@ fn parse_alter_table_modify_column_with_column_position() { assert_eq!(expected_operation_first, operation); let expected_operation_after = AlterTableOperation::ModifyColumn { - col_name: Ident::new("description"), + col_name: Ident::new("description").empty_span(), data_type: DataType::Text, options: vec![ColumnOption::NotNull], - column_position: Some(MySQLColumnPosition::After(Ident { - value: String::from("total_count"), - quote_style: None, - })), + column_position: Some(MySQLColumnPosition::After( + Ident { + value: String::from("total_count"), + quote_style: None, + } + .empty_span(), + )), }; let sql1 = "ALTER TABLE orders MODIFY COLUMN description TEXT NOT NULL AFTER total_count"; @@ -2289,10 +2415,13 @@ fn parse_substring_in_select() { distinct: Some(Distinct::Distinct), top: None, projection: vec![SelectItem::UnnamedExpr(Expr::Substring { - expr: Box::new(Expr::Identifier(Ident { - value: "description".to_string(), - quote_style: None - })), + expr: Box::new(Expr::Identifier( + Ident { + value: "description".to_string(), + quote_style: None + } + .empty_span() + )), substring_from: Some(Box::new(Expr::Value(number("0")))), substring_for: Some(Box::new(Expr::Value(number("1")))), special: true, @@ -2303,7 +2432,8 @@ fn parse_substring_in_select() { name: ObjectName(vec![Ident { value: "test".to_string(), quote_style: None - }]), + } + .empty_span()]), alias: None, args: None, with_hints: vec![], @@ -2407,7 +2537,7 @@ fn parse_table_colum_option_on_update() { assert_eq!(name.to_string(), "foo"); assert_eq!( vec![ColumnDef { - name: Ident::with_quote('`', "modification_time"), + name: Ident::with_quote('`', "modification_time").empty_span(), data_type: DataType::Datetime(None), collation: None, options: vec![ColumnOptionDef { @@ -2705,12 +2835,16 @@ fn parse_create_table_with_column_collate() { assert_eq!(name.to_string(), "tb"); assert_eq!( vec![ColumnDef { - name: Ident::new("id"), + name: Ident::new("id").empty_span(), data_type: DataType::Text, - collation: Some(ObjectName(vec![Ident::new("utf8mb4_0900_ai_ci")])), + collation: Some(ObjectName(vec![ + Ident::new("utf8mb4_0900_ai_ci").empty_span() + ])), options: vec![ColumnOptionDef { name: None, - option: ColumnOption::CharacterSet(ObjectName(vec![Ident::new("utf8mb4")])) + option: ColumnOption::CharacterSet(ObjectName(vec![ + Ident::new("utf8mb4").empty_span() + ])) }], },], columns @@ -2770,7 +2904,7 @@ fn parse_json_table() { json_path: Value::SingleQuotedString("$[*]".to_string()), columns: vec![ JsonTableColumn { - name: Ident::new("x"), + name: Ident::new("x").empty_span(), r#type: DataType::Int(None), path: Value::SingleQuotedString("$".to_string()), exists: false, @@ -2779,7 +2913,7 @@ fn parse_json_table() { }, ], alias: Some(TableAlias { - name: Ident::new("t"), + name: Ident::new("t").empty_span(), columns: vec![], }), } diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index b9b3811ba..0f599df79 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -359,7 +359,7 @@ fn parse_create_table_with_defaults() { columns, vec![ ColumnDef { - name: "customer_id".into(), + name: Ident::new("customer_id").empty_span(), data_type: DataType::Integer(None), collation: None, options: vec![ColumnOptionDef { @@ -370,7 +370,7 @@ fn parse_create_table_with_defaults() { }], }, ColumnDef { - name: "store_id".into(), + name: Ident::new("store_id").empty_span(), data_type: DataType::SmallInt(None), collation: None, options: vec![ColumnOptionDef { @@ -379,7 +379,7 @@ fn parse_create_table_with_defaults() { }], }, ColumnDef { - name: "first_name".into(), + name: Ident::new("first_name").empty_span(), data_type: DataType::CharacterVarying(Some( CharacterLength::IntegerLength { length: 45, @@ -393,21 +393,23 @@ fn parse_create_table_with_defaults() { }], }, ColumnDef { - name: "last_name".into(), + name: Ident::new("last_name").empty_span(), data_type: DataType::CharacterVarying(Some( CharacterLength::IntegerLength { length: 45, unit: None } )), - collation: Some(ObjectName(vec![Ident::with_quote('"', "es_ES")])), + collation: Some(ObjectName(vec![ + Ident::with_quote('"', "es_ES").empty_span() + ])), options: vec![ColumnOptionDef { name: None, option: ColumnOption::NotNull, }], }, ColumnDef { - name: "email".into(), + name: Ident::new("email").empty_span(), data_type: DataType::CharacterVarying(Some( CharacterLength::IntegerLength { length: 50, @@ -418,7 +420,7 @@ fn parse_create_table_with_defaults() { options: vec![], }, ColumnDef { - name: "address_id".into(), + name: Ident::new("address_id").empty_span(), data_type: DataType::SmallInt(None), collation: None, options: vec![ColumnOptionDef { @@ -427,7 +429,7 @@ fn parse_create_table_with_defaults() { }], }, ColumnDef { - name: "activebool".into(), + name: Ident::new("activebool").empty_span(), data_type: DataType::Boolean, collation: None, options: vec![ @@ -442,7 +444,7 @@ fn parse_create_table_with_defaults() { ], }, ColumnDef { - name: "create_date".into(), + name: Ident::new("create_date").empty_span(), data_type: DataType::Date, collation: None, options: vec![ @@ -457,7 +459,7 @@ fn parse_create_table_with_defaults() { ], }, ColumnDef { - name: "last_update".into(), + name: Ident::new("last_update").empty_span(), data_type: DataType::Timestamp(None, TimezoneInfo::WithoutTimeZone), collation: None, options: vec![ @@ -472,7 +474,7 @@ fn parse_create_table_with_defaults() { ], }, ColumnDef { - name: "active".into(), + name: Ident::new("active").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -487,15 +489,15 @@ fn parse_create_table_with_defaults() { with_options, vec![ SqlOption::KeyValue { - key: "fillfactor".into(), + key: Ident::new("fillfactor").empty_span(), value: Expr::Value(number("20")) }, SqlOption::KeyValue { - key: "user_catalog_table".into(), + key: Ident::new("user_catalog_table").empty_span(), value: Expr::Value(Value::Boolean(true)) }, SqlOption::KeyValue { - key: "autovacuum_vacuum_threshold".into(), + key: Ident::new("autovacuum_vacuum_threshold").empty_span(), value: Expr::Value(number("100")) }, ] @@ -725,7 +727,7 @@ fn parse_alter_table_add_columns() { column_keyword: true, if_not_exists: false, column_def: ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Text, collation: None, options: vec![], @@ -736,7 +738,7 @@ fn parse_alter_table_add_columns() { column_keyword: true, if_not_exists: false, column_def: ColumnDef { - name: "b".into(), + name: Ident::new("b").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![], @@ -760,19 +762,21 @@ fn parse_alter_table_owner_to() { let test_cases = vec![ TestCase { sql: "ALTER TABLE tab OWNER TO new_owner", - expected_owner: Owner::Ident(Ident::new("new_owner".to_string())), + expected_owner: Owner::Ident(Ident::new("new_owner".to_string()).empty_span()), }, TestCase { sql: "ALTER TABLE tab OWNER TO postgres", - expected_owner: Owner::Ident(Ident::new("postgres".to_string())), + expected_owner: Owner::Ident(Ident::new("postgres".to_string()).empty_span()), }, TestCase { sql: "ALTER TABLE tab OWNER TO CREATE", // treats CREATE as an identifier - expected_owner: Owner::Ident(Ident::new("CREATE".to_string())), + expected_owner: Owner::Ident(Ident::new("CREATE".to_string()).empty_span()), }, TestCase { sql: "ALTER TABLE tab OWNER TO \"new_owner\"", - expected_owner: Owner::Ident(Ident::with_quote('\"', "new_owner".to_string())), + expected_owner: Owner::Ident( + Ident::with_quote('\"', "new_owner".to_string()).empty_span(), + ), }, TestCase { sql: "ALTER TABLE tab OWNER TO CURRENT_USER", @@ -925,7 +929,7 @@ fn test_copy_from() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: false, @@ -943,7 +947,7 @@ fn test_copy_from() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: false, @@ -961,7 +965,7 @@ fn test_copy_from() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: false, @@ -985,7 +989,7 @@ fn test_copy_to() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: true, @@ -1003,7 +1007,7 @@ fn test_copy_to() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: true, @@ -1021,7 +1025,7 @@ fn test_copy_to() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: true, @@ -1062,15 +1066,15 @@ fn parse_copy_from() { pg_and_generic().one_statement_parses_to(sql, ""), Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["table".into()]), - columns: vec!["a".into(), "b".into()], + table_name: ObjectName(vec![Ident::new("table").empty_span()]), + columns: vec![Ident::new("a").empty_span(), Ident::new("b").empty_span()], }, to: false, target: CopyTarget::File { filename: "file.csv".into() }, options: vec![ - CopyOption::Format("CSV".into()), + CopyOption::Format(Ident::new("CSV").empty_span()), CopyOption::Freeze(true), CopyOption::Freeze(true), CopyOption::Freeze(false), @@ -1081,9 +1085,12 @@ fn parse_copy_from() { CopyOption::Header(false), CopyOption::Quote('"'), CopyOption::Escape('\\'), - CopyOption::ForceQuote(vec!["a".into(), "b".into()]), - CopyOption::ForceNotNull(vec!["a".into()]), - CopyOption::ForceNull(vec!["b".into()]), + CopyOption::ForceQuote(vec![ + Ident::new("a").empty_span(), + Ident::new("b").empty_span() + ]), + CopyOption::ForceNotNull(vec![Ident::new("a").empty_span()]), + CopyOption::ForceNull(vec![Ident::new("b").empty_span()]), CopyOption::Encoding("utf8".into()), ], legacy_options: vec![], @@ -1108,7 +1115,7 @@ fn parse_copy_to() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: true, @@ -1126,7 +1133,7 @@ fn parse_copy_to() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["country".into()]), + table_name: ObjectName(vec![Ident::new("country").empty_span()]), columns: vec![], }, to: true, @@ -1143,7 +1150,7 @@ fn parse_copy_to() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["country".into()]), + table_name: ObjectName(vec![Ident::new("country").empty_span()]), columns: vec![], }, to: true, @@ -1171,14 +1178,16 @@ fn parse_copy_to() { alias: Ident { value: "a".into(), quote_style: None, - }, + } + .empty_span(), }, SelectItem::ExprWithAlias { expr: Expr::Value(Value::SingleQuotedString("hello".into())), alias: Ident { value: "b".into(), quote_style: None, - }, + } + .empty_span(), } ], into: None, @@ -1225,7 +1234,7 @@ fn parse_copy_from_before_v9_0() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: false, @@ -1241,7 +1250,7 @@ fn parse_copy_from_before_v9_0() { CopyLegacyCsvOption::Header, CopyLegacyCsvOption::Quote('\"'), CopyLegacyCsvOption::Escape('\\'), - CopyLegacyCsvOption::ForceNotNull(vec!["column".into()]), + CopyLegacyCsvOption::ForceNotNull(vec![Ident::new("column").empty_span()]), ]), ], values: vec![], @@ -1254,7 +1263,7 @@ fn parse_copy_from_before_v9_0() { pg_and_generic().one_statement_parses_to(sql, ""), Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: false, @@ -1282,7 +1291,7 @@ fn parse_copy_to_before_v9_0() { stmt, Statement::Copy { source: CopySource::Table { - table_name: ObjectName(vec!["users".into()]), + table_name: ObjectName(vec![Ident::new("users").empty_span()]), columns: vec![], }, to: true, @@ -1298,7 +1307,7 @@ fn parse_copy_to_before_v9_0() { CopyLegacyCsvOption::Header, CopyLegacyCsvOption::Quote('\"'), CopyLegacyCsvOption::Escape('\\'), - CopyLegacyCsvOption::ForceQuote(vec!["column".into()]), + CopyLegacyCsvOption::ForceQuote(vec![Ident::new("column").empty_span()]), ]), ], values: vec![], @@ -1314,11 +1323,14 @@ fn parse_set() { Statement::SetVariable { local: false, hivevar: false, - variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a")])), - value: vec![Expr::Identifier(Ident { - value: "b".into(), - quote_style: None - })], + variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a").empty_span()])), + value: vec![Expr::Identifier( + Ident { + value: "b".into(), + quote_style: None + } + .empty_span() + )], } ); @@ -1328,7 +1340,7 @@ fn parse_set() { Statement::SetVariable { local: false, hivevar: false, - variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a")])), + variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a").empty_span()])), value: vec![Expr::Value(Value::SingleQuotedString("b".into()))], } ); @@ -1339,7 +1351,7 @@ fn parse_set() { Statement::SetVariable { local: false, hivevar: false, - variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a")])), + variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a").empty_span()])), value: vec![Expr::Value(number("0"))], } ); @@ -1350,11 +1362,14 @@ fn parse_set() { Statement::SetVariable { local: false, hivevar: false, - variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a")])), - value: vec![Expr::Identifier(Ident { - value: "DEFAULT".into(), - quote_style: None - })], + variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a").empty_span()])), + value: vec![Expr::Identifier( + Ident { + value: "DEFAULT".into(), + quote_style: None + } + .empty_span() + )], } ); @@ -1364,8 +1379,8 @@ fn parse_set() { Statement::SetVariable { local: true, hivevar: false, - variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a")])), - value: vec![Expr::Identifier("b".into())], + variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a").empty_span()])), + value: vec![Expr::Identifier(Ident::new("b").empty_span())], } ); @@ -1376,14 +1391,17 @@ fn parse_set() { local: false, hivevar: false, variables: OneOrManyWithParens::One(ObjectName(vec![ - Ident::new("a"), - Ident::new("b"), - Ident::new("c") + Ident::new("a").empty_span(), + Ident::new("b").empty_span(), + Ident::new("c").empty_span(), ])), - value: vec![Expr::Identifier(Ident { - value: "b".into(), - quote_style: None - })], + value: vec![Expr::Identifier( + Ident { + value: "b".into(), + quote_style: None + } + .empty_span() + )], } ); @@ -1397,11 +1415,11 @@ fn parse_set() { local: false, hivevar: false, variables: OneOrManyWithParens::One(ObjectName(vec![ - Ident::new("hive"), - Ident::new("tez"), - Ident::new("auto"), - Ident::new("reducer"), - Ident::new("parallelism") + Ident::new("hive").empty_span(), + Ident::new("tez").empty_span(), + Ident::new("auto").empty_span(), + Ident::new("reducer").empty_span(), + Ident::new("parallelism").empty_span(), ])), value: vec![Expr::Value(Value::Boolean(false))], } @@ -1451,10 +1469,13 @@ fn parse_set_role() { stmt, Statement::SetRole { context_modifier: ContextModifier::Local, - role_name: Some(Ident { - value: "rolename".to_string(), - quote_style: Some('\"'), - }), + role_name: Some( + Ident { + value: "rolename".to_string(), + quote_style: Some('\"'), + } + .empty_span() + ), } ); assert_eq!(query, stmt.to_string()); @@ -1465,10 +1486,13 @@ fn parse_set_role() { stmt, Statement::SetRole { context_modifier: ContextModifier::None, - role_name: Some(Ident { - value: "rolename".to_string(), - quote_style: Some('\''), - }), + role_name: Some( + Ident { + value: "rolename".to_string(), + quote_style: Some('\''), + } + .empty_span() + ), } ); assert_eq!(query, stmt.to_string()); @@ -1480,7 +1504,7 @@ fn parse_show() { assert_eq!( stmt, Statement::ShowVariable { - variable: vec!["a".into(), "a".into()] + variable: vec![Ident::new("a").empty_span(), Ident::new("a").empty_span()] } ); @@ -1488,7 +1512,10 @@ fn parse_show() { assert_eq!( stmt, Statement::ShowVariable { - variable: vec!["ALL".into(), "ALL".into()] + variable: vec![ + Ident::new("ALL").empty_span(), + Ident::new("ALL").empty_span() + ] } ) } @@ -1499,7 +1526,7 @@ fn parse_deallocate() { assert_eq!( stmt, Statement::Deallocate { - name: "a".into(), + name: Ident::new("a").empty_span(), prepare: false, } ); @@ -1508,7 +1535,7 @@ fn parse_deallocate() { assert_eq!( stmt, Statement::Deallocate { - name: "ALL".into(), + name: Ident::new("ALL").empty_span(), prepare: false, } ); @@ -1517,7 +1544,7 @@ fn parse_deallocate() { assert_eq!( stmt, Statement::Deallocate { - name: "a".into(), + name: Ident::new("a").empty_span(), prepare: true, } ); @@ -1526,7 +1553,7 @@ fn parse_deallocate() { assert_eq!( stmt, Statement::Deallocate { - name: "ALL".into(), + name: Ident::new("ALL").empty_span(), prepare: true, } ); @@ -1538,7 +1565,7 @@ fn parse_execute() { assert_eq!( stmt, Statement::Execute { - name: "a".into(), + name: Ident::new("a").empty_span(), parameters: vec![], using: vec![] } @@ -1548,7 +1575,7 @@ fn parse_execute() { assert_eq!( stmt, Statement::Execute { - name: "a".into(), + name: Ident::new("a").empty_span(), parameters: vec![ Expr::Value(number("1")), Expr::Value(Value::SingleQuotedString("t".to_string())) @@ -1562,7 +1589,7 @@ fn parse_execute() { assert_eq!( stmt, Statement::Execute { - name: "a".into(), + name: Ident::new("a").empty_span(), parameters: vec![], using: vec![ Expr::Cast { @@ -1593,7 +1620,7 @@ fn parse_prepare() { statement, .. } => { - assert_eq!(name, "a".into()); + assert_eq!(name, Ident::new("a").empty_span()); assert!(data_types.is_empty()); statement @@ -1611,9 +1638,9 @@ fn parse_prepare() { assert!(columns.is_empty()); let expected_values = [vec![ - Expr::Identifier("a1".into()), - Expr::Identifier("a2".into()), - Expr::Identifier("a3".into()), + Expr::Identifier(Ident::new("a1").empty_span()), + Expr::Identifier(Ident::new("a2").empty_span()), + Expr::Identifier(Ident::new("a3").empty_span()), ]]; match &*source.body { SetExpr::Values(Values { rows, .. }) => { @@ -1634,7 +1661,7 @@ fn parse_prepare() { statement, .. } => { - assert_eq!(name, "a".into()); + assert_eq!(name, Ident::new("a").empty_span()); assert_eq!(data_types, vec![DataType::Int(None), DataType::Text]); statement @@ -1666,12 +1693,17 @@ fn parse_pg_on_conflict() { })), .. }) => { - assert_eq!(vec![Ident::from("did")], cols); + assert_eq!(vec![Ident::from("did").empty_span()], cols); assert_eq!( OnConflictAction::DoUpdate(DoUpdate { assignments: vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec!["dname".into()])), - value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "dname".into()]) + target: AssignmentTarget::ColumnName(ObjectName(vec![ + Ident::new("dname").empty_span() + ])), + value: Expr::CompoundIdentifier(vec![ + Ident::new("EXCLUDED").empty_span(), + Ident::new("dname").empty_span() + ]) },], selection: None }), @@ -1696,20 +1728,35 @@ fn parse_pg_on_conflict() { })), .. }) => { - assert_eq!(vec![Ident::from("did"), Ident::from("area"),], cols); + assert_eq!( + vec![ + Ident::from("did").empty_span(), + Ident::from("area").empty_span(), + ], + cols + ); assert_eq!( OnConflictAction::DoUpdate(DoUpdate { assignments: vec![ Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec!["dname".into()])), + target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new( + "dname" + ) + .empty_span()])), value: Expr::CompoundIdentifier(vec![ - "EXCLUDED".into(), - "dname".into() + Ident::new("EXCLUDED").empty_span(), + Ident::new("dname").empty_span() ]) }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec!["area".into()])), - value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "area".into()]) + target: AssignmentTarget::ColumnName(ObjectName(vec![Ident::new( + "area" + ) + .empty_span()])), + value: Expr::CompoundIdentifier(vec![ + Ident::new("EXCLUDED").empty_span(), + Ident::new("area").empty_span() + ]) }, ], selection: None @@ -1754,18 +1801,23 @@ fn parse_pg_on_conflict() { })), .. }) => { - assert_eq!(vec![Ident::from("did")], cols); + assert_eq!(vec![Ident::from("did").empty_span()], cols); assert_eq!( OnConflictAction::DoUpdate(DoUpdate { assignments: vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec!["dname".into()])), + target: AssignmentTarget::ColumnName(ObjectName(vec![ + Ident::new("dname").empty_span() + ])), value: Expr::Value(Value::Placeholder("$1".to_string())) },], selection: Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "dsize".to_string(), - quote_style: None - })), + left: Box::new(Expr::Identifier( + Ident { + value: "dsize".to_string(), + quote_style: None + } + .empty_span() + )), op: BinaryOperator::Gt, right: Box::new(Expr::Value(Value::Placeholder("$2".to_string()))) }) @@ -1791,18 +1843,26 @@ fn parse_pg_on_conflict() { })), .. }) => { - assert_eq!(vec![Ident::from("distributors_did_pkey")], cname.0); + assert_eq!( + vec![Ident::from("distributors_did_pkey").empty_span()], + cname.0 + ); assert_eq!( OnConflictAction::DoUpdate(DoUpdate { assignments: vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec!["dname".into()])), + target: AssignmentTarget::ColumnName(ObjectName(vec![ + Ident::new("dname").empty_span() + ])), value: Expr::Value(Value::Placeholder("$1".to_string())) },], selection: Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "dsize".to_string(), - quote_style: None - })), + left: Box::new(Expr::Identifier( + Ident { + value: "dsize".to_string(), + quote_style: None + } + .empty_span() + )), op: BinaryOperator::Gt, right: Box::new(Expr::Value(Value::Placeholder("$2".to_string()))) }) @@ -1823,7 +1883,7 @@ fn parse_pg_returning() { Statement::Insert(Insert { returning, .. }) => { assert_eq!( Some(vec![SelectItem::UnnamedExpr(Expr::Identifier( - "did".into() + Ident::new("did").empty_span() )),]), returning ); @@ -1841,14 +1901,14 @@ fn parse_pg_returning() { assert_eq!( Some(vec![ SelectItem::ExprWithAlias { - expr: Expr::Identifier("temp_lo".into()), - alias: "lo".into() + expr: Expr::Identifier(Ident::new("temp_lo").empty_span()), + alias: Ident::new("lo").empty_span() }, SelectItem::ExprWithAlias { - expr: Expr::Identifier("temp_hi".into()), - alias: "hi".into() + expr: Expr::Identifier(Ident::new("temp_hi").empty_span()), + alias: Ident::new("hi").empty_span() }, - SelectItem::UnnamedExpr(Expr::Identifier("prcp".into())), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("prcp").empty_span())), ]), returning ); @@ -1881,9 +1941,9 @@ fn test_operator(operator: &str, dialect: &TestedDialects, expected: BinaryOpera "binary op should be 3 tokens, not {operator_tokens:?}" ); let expected_expr = Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), op: expected, - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }; let str_expr_canonical = format!("a {operator} b"); assert_eq!(expected_expr, dialect.verified_expr(&str_expr_canonical)); @@ -1988,7 +2048,7 @@ fn parse_pg_unary_ops() { assert_eq!( SelectItem::UnnamedExpr(Expr::UnaryOp { op: *op, - expr: Box::new(Expr::Identifier(Ident::new("a"))), + expr: Box::new(Expr::Identifier(Ident::new("a").empty_span())), }), select.projection[0] ); @@ -2004,7 +2064,7 @@ fn parse_pg_postfix_factorial() { assert_eq!( SelectItem::UnnamedExpr(Expr::UnaryOp { op: *op, - expr: Box::new(Expr::Identifier(Ident::new("a"))), + expr: Box::new(Expr::Identifier(Ident::new("a").empty_span())), }), select.projection[0] ); @@ -2065,7 +2125,7 @@ fn parse_array_index_expr() { let select = pg_and_generic().verified_only_select(sql); assert_eq!( &Expr::Subscript { - expr: Box::new(Expr::Identifier(Ident::new("foo"))), + expr: Box::new(Expr::Identifier(Ident::new("foo").empty_span())), subscript: Box::new(Subscript::Index { index: num[0].clone() }), @@ -2078,7 +2138,7 @@ fn parse_array_index_expr() { assert_eq!( &Expr::Subscript { expr: Box::new(Expr::Subscript { - expr: Box::new(Expr::Identifier(Ident::new("foo"))), + expr: Box::new(Expr::Identifier(Ident::new("foo").empty_span())), subscript: Box::new(Subscript::Index { index: num[0].clone() }), @@ -2096,23 +2156,29 @@ fn parse_array_index_expr() { &Expr::Subscript { expr: Box::new(Expr::Subscript { expr: Box::new(Expr::Subscript { - expr: Box::new(Expr::Identifier(Ident::new("bar"))), + expr: Box::new(Expr::Identifier(Ident::new("bar").empty_span())), subscript: Box::new(Subscript::Index { index: num[0].clone() }) }), subscript: Box::new(Subscript::Index { - index: Expr::Identifier(Ident { - value: "baz".to_string(), - quote_style: Some('"') - }) + index: Expr::Identifier( + Ident { + value: "baz".to_string(), + quote_style: Some('"') + } + .empty_span() + ) }) }), subscript: Box::new(Subscript::Index { - index: Expr::Identifier(Ident { - value: "fooz".to_string(), - quote_style: Some('"') - }) + index: Expr::Identifier( + Ident { + value: "fooz".to_string(), + quote_style: Some('"') + } + .empty_span() + ) }) }, expr_from_projection(only(&select.projection)), @@ -2175,7 +2241,7 @@ fn parse_array_subscript() { ( "(ARRAY[1, 2, 3, 4, 5, 6])[foo]", Subscript::Index { - index: Expr::Identifier(Ident::new("foo")), + index: Expr::Identifier(Ident::new("foo").empty_span()), }, ), ( @@ -2198,12 +2264,18 @@ fn parse_array_subscript() { "arr[array_length(arr) - 3:array_length(arr) - 1]", Subscript::Slice { lower_bound: Some(Expr::BinaryOp { - left: Box::new(call("array_length", [Expr::Identifier(Ident::new("arr"))])), + left: Box::new(call( + "array_length", + [Expr::Identifier(Ident::new("arr").empty_span())], + )), op: BinaryOperator::Minus, right: Box::new(Expr::Value(number("3"))), }), upper_bound: Some(Expr::BinaryOp { - left: Box::new(call("array_length", [Expr::Identifier(Ident::new("arr"))])), + left: Box::new(call( + "array_length", + [Expr::Identifier(Ident::new("arr").empty_span())], + )), op: BinaryOperator::Minus, right: Box::new(Expr::Value(number("1"))), }), @@ -2495,7 +2567,7 @@ fn parse_array_subquery_expr() { let select = pg().verified_only_select(sql); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("ARRAY")]), + name: ObjectName(vec![Ident::new("ARRAY").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::Subquery(Box::new(Query { with: None, @@ -2594,7 +2666,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("params"))), + left: Box::new(Expr::Identifier(Ident::new("params").empty_span())), op: BinaryOperator::LongArrow, right: Box::new(Expr::Value(Value::SingleQuotedString("name".to_string()))), }), @@ -2605,7 +2677,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("params"))), + left: Box::new(Expr::Identifier(Ident::new("params").empty_span())), op: BinaryOperator::Arrow, right: Box::new(Expr::Value(Value::SingleQuotedString("name".to_string()))), }), @@ -2617,7 +2689,7 @@ fn test_json() { assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { left: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), op: BinaryOperator::Arrow, right: Box::new(Expr::Value(Value::SingleQuotedString("items".to_string()))) }), @@ -2634,7 +2706,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("obj"))), + left: Box::new(Expr::Identifier(Ident::new("obj").empty_span())), op: BinaryOperator::Arrow, right: Box::new(Expr::Value(number("42"))), }), @@ -2646,9 +2718,9 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("obj"))), + left: Box::new(Expr::Identifier(Ident::new("obj").empty_span())), op: BinaryOperator::Arrow, - right: Box::new(Expr::Identifier(Ident::new("key"))), + right: Box::new(Expr::Identifier(Ident::new("key").empty_span())), }), select.projection[0] ); @@ -2658,7 +2730,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("obj"))), + left: Box::new(Expr::Identifier(Ident::new("obj").empty_span())), op: BinaryOperator::Arrow, right: Box::new(Expr::BinaryOp { left: Box::new(Expr::Value(number("3"))), @@ -2673,7 +2745,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), op: BinaryOperator::HashArrow, right: Box::new(Expr::Value(Value::SingleQuotedString( "{a,b,c}".to_string() @@ -2686,7 +2758,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), op: BinaryOperator::HashLongArrow, right: Box::new(Expr::Value(Value::SingleQuotedString( "{a,b,c}".to_string() @@ -2699,7 +2771,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), op: BinaryOperator::AtArrow, right: Box::new(Expr::Value(Value::SingleQuotedString( "{\"a\": 1}".to_string() @@ -2716,7 +2788,7 @@ fn test_json() { "{\"a\": 1}".to_string() ))), op: BinaryOperator::ArrowAt, - right: Box::new(Expr::Identifier(Ident::new("info"))), + right: Box::new(Expr::Identifier(Ident::new("info").empty_span())), }, select.selection.unwrap(), ); @@ -2725,7 +2797,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::from("info"))), + left: Box::new(Expr::Identifier(Ident::from("info").empty_span())), op: BinaryOperator::HashMinus, right: Box::new(Expr::Array(Array { elem: vec![ @@ -2742,7 +2814,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::from("info"))), + left: Box::new(Expr::Identifier(Ident::from("info").empty_span())), op: BinaryOperator::AtQuestion, right: Box::new(Expr::Value(Value::SingleQuotedString("$.a".to_string())),), }, @@ -2753,7 +2825,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::from("info"))), + left: Box::new(Expr::Identifier(Ident::from("info").empty_span())), op: BinaryOperator::AtAt, right: Box::new(Expr::Value(Value::SingleQuotedString("$.a".to_string())),), }, @@ -2764,7 +2836,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), op: BinaryOperator::Question, right: Box::new(Expr::Value(Value::SingleQuotedString("b".to_string()))), }, @@ -2775,7 +2847,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), op: BinaryOperator::QuestionAnd, right: Box::new(Expr::Array(Array { elem: vec![ @@ -2792,7 +2864,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), op: BinaryOperator::QuestionPipe, right: Box::new(Expr::Array(Array { elem: vec![ @@ -2827,10 +2899,10 @@ fn test_composite_value() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::CompositeAccess { - key: Ident::new("name"), + key: Ident::new("name").empty_span(), expr: Box::new(Expr::Nested(Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("on_hand"), - Ident::new("item") + Ident::new("on_hand").empty_span(), + Ident::new("item").empty_span(), ])))) }), select.projection[0] @@ -2840,10 +2912,10 @@ fn test_composite_value() { select.selection, Some(Expr::BinaryOp { left: Box::new(Expr::CompositeAccess { - key: Ident::new("price"), + key: Ident::new("price").empty_span(), expr: Box::new(Expr::Nested(Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("on_hand"), - Ident::new("item") + Ident::new("on_hand").empty_span(), + Ident::new("item").empty_span(), ])))) }), op: BinaryOperator::Gt, @@ -2855,11 +2927,11 @@ fn test_composite_value() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::CompositeAccess { - key: Ident::new("n"), + key: Ident::new("n").empty_span(), expr: Box::new(Expr::Nested(Box::new(Expr::Function(Function { name: ObjectName(vec![ - Ident::new("information_schema"), - Ident::new("_pg_expandarray") + Ident::new("information_schema").empty_span(), + Ident::new("_pg_expandarray").empty_span(), ]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { @@ -3099,7 +3171,7 @@ fn parse_current_functions() { let select = pg_and_generic().verified_only_select(sql); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("CURRENT_CATALOG")]), + name: ObjectName(vec![Ident::new("CURRENT_CATALOG").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::None, null_treatment: None, @@ -3111,7 +3183,7 @@ fn parse_current_functions() { ); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("CURRENT_USER")]), + name: ObjectName(vec![Ident::new("CURRENT_USER").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::None, null_treatment: None, @@ -3123,7 +3195,7 @@ fn parse_current_functions() { ); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("SESSION_USER")]), + name: ObjectName(vec![Ident::new("SESSION_USER").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::None, null_treatment: None, @@ -3135,7 +3207,7 @@ fn parse_current_functions() { ); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::new("USER")]), + name: ObjectName(vec![Ident::new("USER").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::None, null_treatment: None, @@ -3179,10 +3251,13 @@ fn parse_custom_operator() { assert_eq!( select.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "relname".into(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "relname".into(), + quote_style: None, + } + .empty_span() + )), op: BinaryOperator::PGCustomBinaryOperator(vec![ "database".into(), "pg_catalog".into(), @@ -3198,10 +3273,13 @@ fn parse_custom_operator() { assert_eq!( select.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "relname".into(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "relname".into(), + quote_style: None, + } + .empty_span() + )), op: BinaryOperator::PGCustomBinaryOperator(vec!["pg_catalog".into(), "~".into()]), right: Box::new(Expr::Value(Value::SingleQuotedString("^(table)$".into()))) }) @@ -3213,10 +3291,13 @@ fn parse_custom_operator() { assert_eq!( select.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "relname".into(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "relname".into(), + quote_style: None, + } + .empty_span() + )), op: BinaryOperator::PGCustomBinaryOperator(vec!["~".into()]), right: Box::new(Expr::Value(Value::SingleQuotedString("^(table)$".into()))) }) @@ -3367,12 +3448,14 @@ fn parse_alter_role() { name: Ident { value: "old_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::RenameRole { role_name: Ident { value: "new_name".into(), quote_style: None } + .empty_span() }, } ); @@ -3384,7 +3467,8 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::WithOptions { options: vec![ RoleOption::SuperUser(true), @@ -3413,7 +3497,8 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::WithOptions { options: vec![ RoleOption::SuperUser(false), @@ -3436,12 +3521,14 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::Set { config_name: ObjectName(vec![Ident { value: "maintenance_work_mem".into(), quote_style: None - }]), + } + .empty_span()]), config_value: SetConfigValue::FromCurrent, in_database: None }, @@ -3455,17 +3542,20 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::Set { config_name: ObjectName(vec![Ident { value: "maintenance_work_mem".into(), quote_style: None - }]), + } + .empty_span()]), config_value: SetConfigValue::Value(Expr::Value(number("100000"))), in_database: Some(ObjectName(vec![Ident { value: "database_name".into(), quote_style: None - }])) + } + .empty_span()])) }, }] ); @@ -3477,17 +3567,20 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::Set { config_name: ObjectName(vec![Ident { value: "maintenance_work_mem".into(), quote_style: None - }]), + } + .empty_span()]), config_value: SetConfigValue::Value(Expr::Value(number("100000"))), in_database: Some(ObjectName(vec![Ident { value: "database_name".into(), quote_style: None - }])) + } + .empty_span()])) }, } ); @@ -3499,17 +3592,20 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::Set { config_name: ObjectName(vec![Ident { value: "maintenance_work_mem".into(), quote_style: None - }]), + } + .empty_span()]), config_value: SetConfigValue::Default, in_database: Some(ObjectName(vec![Ident { value: "database_name".into(), quote_style: None - }])) + } + .empty_span()])) }, } ); @@ -3521,7 +3617,8 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::Reset { config_name: ResetConfig::ALL, in_database: None @@ -3536,16 +3633,19 @@ fn parse_alter_role() { name: Ident { value: "role_name".into(), quote_style: None - }, + } + .empty_span(), operation: AlterRoleOperation::Reset { config_name: ResetConfig::ConfigName(ObjectName(vec![Ident { value: "maintenance_work_mem".into(), quote_style: None - }])), + } + .empty_span()])), in_database: Some(ObjectName(vec![Ident { value: "database_name".into(), quote_style: None - }])) + } + .empty_span()])) }, } ); @@ -3568,8 +3668,11 @@ fn parse_delimited_identifiers() { with_ordinality: _, partitions: _, } => { - assert_eq!(vec![Ident::with_quote('"', "a table")], name.0); - assert_eq!(Ident::with_quote('"', "alias"), alias.unwrap().name); + assert_eq!(vec![Ident::with_quote('"', "a table").empty_span()], name.0); + assert_eq!( + Ident::with_quote('"', "alias").empty_span(), + alias.unwrap().name + ); assert!(args.is_none()); assert!(with_hints.is_empty()); assert!(version.is_none()); @@ -3580,14 +3683,14 @@ fn parse_delimited_identifiers() { assert_eq!(3, select.projection.len()); assert_eq!( &Expr::CompoundIdentifier(vec![ - Ident::with_quote('"', "alias"), - Ident::with_quote('"', "bar baz"), + Ident::with_quote('"', "alias").empty_span(), + Ident::with_quote('"', "bar baz").empty_span(), ]), expr_from_projection(&select.projection[0]), ); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::with_quote('"', "myfun")]), + name: ObjectName(vec![Ident::with_quote('"', "myfun").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -3603,8 +3706,11 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); - assert_eq!(&Ident::with_quote('"', "column alias"), alias); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); + assert_eq!(&Ident::with_quote('"', "column alias").empty_span(), alias); } _ => panic!("Expected: ExprWithAlias"), } @@ -3642,13 +3748,13 @@ fn parse_create_function() { Statement::CreateFunction { or_replace: false, temporary: false, - name: ObjectName(vec![Ident::new("add")]), + name: ObjectName(vec![Ident::new("add").empty_span()]), args: Some(vec![ OperateFunctionArg::unnamed(DataType::Integer(None)), OperateFunctionArg::unnamed(DataType::Integer(None)), ]), return_type: Some(DataType::Integer(None)), - language: Some("SQL".into()), + language: Some(Ident::new("SQL").empty_span()), behavior: Some(FunctionBehavior::Immutable), called_on_null: Some(FunctionCalledOnNull::Strict), parallel: Some(FunctionParallel::Safe), @@ -3689,7 +3795,8 @@ fn parse_drop_function() { name: ObjectName(vec![Ident { value: "test_func".to_string(), quote_style: None - }]), + } + .empty_span()]), args: None }], option: None @@ -3705,12 +3812,13 @@ fn parse_drop_function() { name: ObjectName(vec![Ident { value: "test_func".to_string(), quote_style: None - }]), + } + .empty_span()]), args: Some(vec![ OperateFunctionArg::with_name("a", DataType::Integer(None)), OperateFunctionArg { mode: Some(ArgMode::In), - name: Some("b".into()), + name: Some(Ident::new("b").empty_span()), data_type: DataType::Integer(None), default_expr: Some(Expr::Value(Value::Number("1".parse().unwrap(), false))), } @@ -3730,12 +3838,13 @@ fn parse_drop_function() { name: ObjectName(vec![Ident { value: "test_func1".to_string(), quote_style: None - }]), + } + .empty_span()]), args: Some(vec![ OperateFunctionArg::with_name("a", DataType::Integer(None)), OperateFunctionArg { mode: Some(ArgMode::In), - name: Some("b".into()), + name: Some(Ident::new("b").empty_span()), data_type: DataType::Integer(None), default_expr: Some(Expr::Value(Value::Number( "1".parse().unwrap(), @@ -3748,12 +3857,13 @@ fn parse_drop_function() { name: ObjectName(vec![Ident { value: "test_func2".to_string(), quote_style: None - }]), + } + .empty_span()]), args: Some(vec![ OperateFunctionArg::with_name("a", DataType::Varchar(None)), OperateFunctionArg { mode: Some(ArgMode::In), - name: Some("b".into()), + name: Some(Ident::new("b").empty_span()), data_type: DataType::Integer(None), default_expr: Some(Expr::Value(Value::Number( "1".parse().unwrap(), @@ -3779,7 +3889,8 @@ fn parse_drop_procedure() { name: ObjectName(vec![Ident { value: "test_proc".to_string(), quote_style: None - }]), + } + .empty_span()]), args: None }], option: None @@ -3795,12 +3906,13 @@ fn parse_drop_procedure() { name: ObjectName(vec![Ident { value: "test_proc".to_string(), quote_style: None - }]), + } + .empty_span()]), args: Some(vec![ OperateFunctionArg::with_name("a", DataType::Integer(None)), OperateFunctionArg { mode: Some(ArgMode::In), - name: Some("b".into()), + name: Some(Ident::new("b").empty_span()), data_type: DataType::Integer(None), default_expr: Some(Expr::Value(Value::Number("1".parse().unwrap(), false))), } @@ -3820,12 +3932,13 @@ fn parse_drop_procedure() { name: ObjectName(vec![Ident { value: "test_proc1".to_string(), quote_style: None - }]), + } + .empty_span()]), args: Some(vec![ OperateFunctionArg::with_name("a", DataType::Integer(None)), OperateFunctionArg { mode: Some(ArgMode::In), - name: Some("b".into()), + name: Some(Ident::new("b").empty_span()), data_type: DataType::Integer(None), default_expr: Some(Expr::Value(Value::Number( "1".parse().unwrap(), @@ -3838,12 +3951,13 @@ fn parse_drop_procedure() { name: ObjectName(vec![Ident { value: "test_proc2".to_string(), quote_style: None - }]), + } + .empty_span()]), args: Some(vec![ OperateFunctionArg::with_name("a", DataType::Varchar(None)), OperateFunctionArg { mode: Some(ArgMode::In), - name: Some("b".into()), + name: Some(Ident::new("b").empty_span()), data_type: DataType::Integer(None), default_expr: Some(Expr::Value(Value::Number( "1".parse().unwrap(), @@ -3918,7 +4032,8 @@ fn parse_dollar_quoted_string() { alias: Ident { value: "col_name".into(), quote_style: None, - }, + } + .empty_span(), } ); @@ -3959,10 +4074,10 @@ fn parse_select_group_by_grouping_sets() { assert_eq!( GroupByExpr::Expressions( vec![ - Expr::Identifier(Ident::new("size")), + Expr::Identifier(Ident::new("size").empty_span()), Expr::GroupingSets(vec![ - vec![Expr::Identifier(Ident::new("brand"))], - vec![Expr::Identifier(Ident::new("size"))], + vec![Expr::Identifier(Ident::new("brand").empty_span())], + vec![Expr::Identifier(Ident::new("size").empty_span())], vec![], ]), ], @@ -3980,10 +4095,10 @@ fn parse_select_group_by_rollup() { assert_eq!( GroupByExpr::Expressions( vec![ - Expr::Identifier(Ident::new("size")), + Expr::Identifier(Ident::new("size").empty_span()), Expr::Rollup(vec![ - vec![Expr::Identifier(Ident::new("brand"))], - vec![Expr::Identifier(Ident::new("size"))], + vec![Expr::Identifier(Ident::new("brand").empty_span())], + vec![Expr::Identifier(Ident::new("size").empty_span())], ]), ], vec![] @@ -4000,10 +4115,10 @@ fn parse_select_group_by_cube() { assert_eq!( GroupByExpr::Expressions( vec![ - Expr::Identifier(Ident::new("size")), + Expr::Identifier(Ident::new("size").empty_span()), Expr::Cube(vec![ - vec![Expr::Identifier(Ident::new("brand"))], - vec![Expr::Identifier(Ident::new("size"))], + vec![Expr::Identifier(Ident::new("brand").empty_span())], + vec![Expr::Identifier(Ident::new("size").empty_span())], ]), ], vec![] @@ -4015,7 +4130,10 @@ fn parse_select_group_by_cube() { #[test] fn parse_truncate() { let truncate = pg_and_generic().verified_stmt("TRUNCATE db.table_name"); - let table_name = ObjectName(vec![Ident::new("db"), Ident::new("table_name")]); + let table_name = ObjectName(vec![ + Ident::new("db").empty_span(), + Ident::new("table_name").empty_span(), + ]); let table_names = vec![TruncateTableTarget { name: table_name.clone(), }]; @@ -4038,7 +4156,10 @@ fn parse_truncate_with_options() { let truncate = pg_and_generic() .verified_stmt("TRUNCATE TABLE ONLY db.table_name RESTART IDENTITY CASCADE"); - let table_name = ObjectName(vec![Ident::new("db"), Ident::new("table_name")]); + let table_name = ObjectName(vec![ + Ident::new("db").empty_span(), + Ident::new("table_name").empty_span(), + ]); let table_names = vec![TruncateTableTarget { name: table_name.clone(), }]; @@ -4063,8 +4184,14 @@ fn parse_truncate_with_table_list() { "TRUNCATE TABLE db.table_name, db.other_table_name RESTART IDENTITY CASCADE", ); - let table_name_a = ObjectName(vec![Ident::new("db"), Ident::new("table_name")]); - let table_name_b = ObjectName(vec![Ident::new("db"), Ident::new("other_table_name")]); + let table_name_a = ObjectName(vec![ + Ident::new("db").empty_span(), + Ident::new("table_name").empty_span(), + ]); + let table_name_b = ObjectName(vec![ + Ident::new("db").empty_span(), + Ident::new("other_table_name").empty_span(), + ]); let table_names = vec![ TruncateTableTarget { @@ -4124,37 +4251,37 @@ fn parse_create_table_with_alias() { columns, vec![ ColumnDef { - name: "int8_col".into(), + name: Ident::new("int8_col").empty_span(), data_type: DataType::Int8(None), collation: None, options: vec![] }, ColumnDef { - name: "int4_col".into(), + name: Ident::new("int4_col").empty_span(), data_type: DataType::Int4(None), collation: None, options: vec![] }, ColumnDef { - name: "int2_col".into(), + name: Ident::new("int2_col").empty_span(), data_type: DataType::Int2(None), collation: None, options: vec![] }, ColumnDef { - name: "float8_col".into(), + name: Ident::new("float8_col").empty_span(), data_type: DataType::Float8, collation: None, options: vec![] }, ColumnDef { - name: "float4_col".into(), + name: Ident::new("float4_col").empty_span(), data_type: DataType::Float4, collation: None, options: vec![] }, ColumnDef { - name: "bool_col".into(), + name: Ident::new("bool_col").empty_span(), data_type: DataType::Bool, collation: None, options: vec![] @@ -4176,13 +4303,13 @@ fn parse_create_table_with_partition_by() { assert_eq!( vec![ ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![] }, ColumnDef { - name: "b".into(), + name: Ident::new("b").empty_span(), data_type: DataType::Text, collation: None, options: vec![] @@ -4198,7 +4325,7 @@ fn parse_create_table_with_partition_by() { duplicate_treatment: None, clauses: vec![], args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("a")) + Expr::Identifier(Ident::new("a").empty_span()) ))], }), f.args @@ -4223,8 +4350,8 @@ fn parse_join_constraint_unnest_alias() { relation: TableFactor::UNNEST { alias: table_alias("f"), array_exprs: vec![Expr::CompoundIdentifier(vec![ - Ident::new("t1"), - Ident::new("a") + Ident::new("t1").empty_span(), + Ident::new("a").empty_span(), ])], with_offset: false, with_offset_alias: None, @@ -4232,9 +4359,9 @@ fn parse_join_constraint_unnest_alias() { }, global: false, join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp { - left: Box::new(Expr::Identifier("c1".into())), + left: Box::new(Expr::Identifier(Ident::new("c1").empty_span())), op: BinaryOperator::Eq, - right: Box::new(Expr::Identifier("c2".into())), + right: Box::new(Expr::Identifier(Ident::new("c2").empty_span())), })), }] ); @@ -4263,20 +4390,26 @@ fn test_simple_postgres_insert_with_alias() { table_name: ObjectName(vec![Ident { value: "test_tables".to_string(), quote_style: None - }]), - table_alias: Some(Ident { - value: "test_table".to_string(), - quote_style: None - }), + } + .empty_span()]), + table_alias: Some( + Ident { + value: "test_table".to_string(), + quote_style: None + } + .empty_span() + ), columns: vec![ Ident { value: "id".to_string(), quote_style: None - }, + } + .empty_span(), Ident { value: "a".to_string(), quote_style: None } + .empty_span(), ], overwrite: false, source: Some(Box::new(Query { @@ -4284,10 +4417,13 @@ fn test_simple_postgres_insert_with_alias() { body: Box::new(SetExpr::Values(Values { explicit_row: false, rows: vec![vec![ - Expr::Identifier(Ident { - value: "DEFAULT".to_string(), - quote_style: None - }), + Expr::Identifier( + Ident { + value: "DEFAULT".to_string(), + quote_style: None + } + .empty_span() + ), Expr::Value(Value::Number("123".to_string(), false)) ]] })), @@ -4329,20 +4465,26 @@ fn test_simple_postgres_insert_with_alias() { table_name: ObjectName(vec![Ident { value: "test_tables".to_string(), quote_style: None - }]), - table_alias: Some(Ident { - value: "test_table".to_string(), - quote_style: None - }), + } + .empty_span()]), + table_alias: Some( + Ident { + value: "test_table".to_string(), + quote_style: None + } + .empty_span() + ), columns: vec![ Ident { value: "id".to_string(), quote_style: None - }, + } + .empty_span(), Ident { value: "a".to_string(), quote_style: None } + .empty_span(), ], overwrite: false, source: Some(Box::new(Query { @@ -4350,10 +4492,13 @@ fn test_simple_postgres_insert_with_alias() { body: Box::new(SetExpr::Values(Values { explicit_row: false, rows: vec![vec![ - Expr::Identifier(Ident { - value: "DEFAULT".to_string(), - quote_style: None - }), + Expr::Identifier( + Ident { + value: "DEFAULT".to_string(), + quote_style: None + } + .empty_span() + ), Expr::Value(Value::Number( bigdecimal::BigDecimal::new(123.into(), 0), false @@ -4397,20 +4542,26 @@ fn test_simple_insert_with_quoted_alias() { table_name: ObjectName(vec![Ident { value: "test_tables".to_string(), quote_style: None - }]), - table_alias: Some(Ident { - value: "Test_Table".to_string(), - quote_style: Some('"') - }), + } + .empty_span()]), + table_alias: Some( + Ident { + value: "Test_Table".to_string(), + quote_style: Some('"') + } + .empty_span() + ), columns: vec![ Ident { value: "id".to_string(), quote_style: None - }, + } + .empty_span(), Ident { value: "a".to_string(), quote_style: None } + .empty_span(), ], overwrite: false, source: Some(Box::new(Query { @@ -4418,10 +4569,13 @@ fn test_simple_insert_with_quoted_alias() { body: Box::new(SetExpr::Values(Values { explicit_row: false, rows: vec![vec![ - Expr::Identifier(Ident { - value: "DEFAULT".to_string(), - quote_style: None - }), + Expr::Identifier( + Ident { + value: "DEFAULT".to_string(), + quote_style: None + } + .empty_span() + ), Expr::Value(Value::SingleQuotedString("0123".to_string())) ]] })), @@ -4523,11 +4677,11 @@ fn parse_create_table_with_options() { assert_eq!( vec![ SqlOption::KeyValue { - key: "foo".into(), + key: Ident::new("foo").empty_span(), value: Expr::Value(Value::SingleQuotedString("bar".into())), }, SqlOption::KeyValue { - key: "a".into(), + key: Ident::new("a").empty_span(), value: Expr::Value(number("123")), }, ], @@ -4587,10 +4741,10 @@ fn parse_create_simple_before_insert_trigger() { let expected = Statement::CreateTrigger { or_replace: false, is_constraint: false, - name: ObjectName(vec![Ident::new("check_insert")]), + name: ObjectName(vec![Ident::new("check_insert").empty_span()]), period: TriggerPeriod::Before, events: vec![TriggerEvent::Insert], - table_name: ObjectName(vec![Ident::new("accounts")]), + table_name: ObjectName(vec![Ident::new("accounts").empty_span()]), referenced_table_name: None, referencing: vec![], trigger_object: TriggerObject::Row, @@ -4599,7 +4753,7 @@ fn parse_create_simple_before_insert_trigger() { exec_body: TriggerExecBody { exec_type: TriggerExecBodyType::Function, func_desc: FunctionDesc { - name: ObjectName(vec![Ident::new("check_account_insert")]), + name: ObjectName(vec![Ident::new("check_account_insert").empty_span()]), args: None, }, }, @@ -4615,18 +4769,18 @@ fn parse_create_after_update_trigger_with_condition() { let expected = Statement::CreateTrigger { or_replace: false, is_constraint: false, - name: ObjectName(vec![Ident::new("check_update")]), + name: ObjectName(vec![Ident::new("check_update").empty_span()]), period: TriggerPeriod::After, events: vec![TriggerEvent::Update(vec![])], - table_name: ObjectName(vec![Ident::new("accounts")]), + table_name: ObjectName(vec![Ident::new("accounts").empty_span()]), referenced_table_name: None, referencing: vec![], trigger_object: TriggerObject::Row, include_each: true, condition: Some(Expr::Nested(Box::new(Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("NEW"), - Ident::new("balance"), + Ident::new("NEW").empty_span(), + Ident::new("balance").empty_span(), ])), op: BinaryOperator::Gt, right: Box::new(Expr::Value(number("10000"))), @@ -4634,7 +4788,7 @@ fn parse_create_after_update_trigger_with_condition() { exec_body: TriggerExecBody { exec_type: TriggerExecBodyType::Function, func_desc: FunctionDesc { - name: ObjectName(vec![Ident::new("check_account_update")]), + name: ObjectName(vec![Ident::new("check_account_update").empty_span()]), args: None, }, }, @@ -4650,10 +4804,10 @@ fn parse_create_instead_of_delete_trigger() { let expected = Statement::CreateTrigger { or_replace: false, is_constraint: false, - name: ObjectName(vec![Ident::new("check_delete")]), + name: ObjectName(vec![Ident::new("check_delete").empty_span()]), period: TriggerPeriod::InsteadOf, events: vec![TriggerEvent::Delete], - table_name: ObjectName(vec![Ident::new("accounts")]), + table_name: ObjectName(vec![Ident::new("accounts").empty_span()]), referenced_table_name: None, referencing: vec![], trigger_object: TriggerObject::Row, @@ -4662,7 +4816,7 @@ fn parse_create_instead_of_delete_trigger() { exec_body: TriggerExecBody { exec_type: TriggerExecBodyType::Function, func_desc: FunctionDesc { - name: ObjectName(vec![Ident::new("check_account_deletes")]), + name: ObjectName(vec![Ident::new("check_account_deletes").empty_span()]), args: None, }, }, @@ -4678,14 +4832,14 @@ fn parse_create_trigger_with_multiple_events_and_deferrable() { let expected = Statement::CreateTrigger { or_replace: false, is_constraint: true, - name: ObjectName(vec![Ident::new("check_multiple_events")]), + name: ObjectName(vec![Ident::new("check_multiple_events").empty_span()]), period: TriggerPeriod::Before, events: vec![ TriggerEvent::Insert, TriggerEvent::Update(vec![]), TriggerEvent::Delete, ], - table_name: ObjectName(vec![Ident::new("accounts")]), + table_name: ObjectName(vec![Ident::new("accounts").empty_span()]), referenced_table_name: None, referencing: vec![], trigger_object: TriggerObject::Row, @@ -4694,7 +4848,7 @@ fn parse_create_trigger_with_multiple_events_and_deferrable() { exec_body: TriggerExecBody { exec_type: TriggerExecBodyType::Function, func_desc: FunctionDesc { - name: ObjectName(vec![Ident::new("check_account_changes")]), + name: ObjectName(vec![Ident::new("check_account_changes").empty_span()]), args: None, }, }, @@ -4714,21 +4868,21 @@ fn parse_create_trigger_with_referencing() { let expected = Statement::CreateTrigger { or_replace: false, is_constraint: false, - name: ObjectName(vec![Ident::new("check_referencing")]), + name: ObjectName(vec![Ident::new("check_referencing").empty_span()]), period: TriggerPeriod::Before, events: vec![TriggerEvent::Insert], - table_name: ObjectName(vec![Ident::new("accounts")]), + table_name: ObjectName(vec![Ident::new("accounts").empty_span()]), referenced_table_name: None, referencing: vec![ TriggerReferencing { refer_type: TriggerReferencingType::NewTable, is_as: true, - transition_relation_name: ObjectName(vec![Ident::new("new_accounts")]), + transition_relation_name: ObjectName(vec![Ident::new("new_accounts").empty_span()]), }, TriggerReferencing { refer_type: TriggerReferencingType::OldTable, is_as: true, - transition_relation_name: ObjectName(vec![Ident::new("old_accounts")]), + transition_relation_name: ObjectName(vec![Ident::new("old_accounts").empty_span()]), }, ], trigger_object: TriggerObject::Row, @@ -4737,7 +4891,7 @@ fn parse_create_trigger_with_referencing() { exec_body: TriggerExecBody { exec_type: TriggerExecBodyType::Function, func_desc: FunctionDesc { - name: ObjectName(vec![Ident::new("check_account_referencing")]), + name: ObjectName(vec![Ident::new("check_account_referencing").empty_span()]), args: None, }, }, @@ -4796,8 +4950,8 @@ fn parse_drop_trigger() { pg().verified_stmt(sql), Statement::DropTrigger { if_exists, - trigger_name: ObjectName(vec![Ident::new("check_update")]), - table_name: ObjectName(vec![Ident::new("table_name")]), + trigger_name: ObjectName(vec![Ident::new("check_update").empty_span()]), + table_name: ObjectName(vec![Ident::new("table_name").empty_span()]), option } ); @@ -4910,28 +5064,28 @@ fn parse_trigger_related_functions() { if_not_exists: false, transient: false, volatile: false, - name: ObjectName(vec![Ident::new("emp")]), + name: ObjectName(vec![Ident::new("emp").empty_span()]), columns: vec![ ColumnDef { - name: "empname".into(), + name: Ident::new("empname").empty_span(), data_type: DataType::Text, collation: None, options: vec![], }, ColumnDef { - name: "salary".into(), + name: Ident::new("salary").empty_span(), data_type: DataType::Integer(None), collation: None, options: vec![], }, ColumnDef { - name: "last_date".into(), + name: Ident::new("last_date").empty_span(), data_type: DataType::Timestamp(None, TimezoneInfo::None), collation: None, options: vec![], }, ColumnDef { - name: "last_user".into(), + name: Ident::new("last_user").empty_span(), data_type: DataType::Text, collation: None, options: vec![], @@ -4987,7 +5141,7 @@ fn parse_trigger_related_functions() { or_replace: false, temporary: false, if_not_exists: false, - name: ObjectName(vec![Ident::new("emp_stamp")]), + name: ObjectName(vec![Ident::new("emp_stamp").empty_span()]), args: None, return_type: Some(DataType::Trigger), function_body: Some( @@ -5008,7 +5162,7 @@ fn parse_trigger_related_functions() { called_on_null: None, parallel: None, using: None, - language: Some(Ident::new("plpgsql")), + language: Some(Ident::new("plpgsql").empty_span()), determinism_specifier: None, options: None, remote_connection: None @@ -5022,10 +5176,10 @@ fn parse_trigger_related_functions() { Statement::CreateTrigger { or_replace: false, is_constraint: false, - name: ObjectName(vec![Ident::new("emp_stamp")]), + name: ObjectName(vec![Ident::new("emp_stamp").empty_span()]), period: TriggerPeriod::Before, events: vec![TriggerEvent::Insert, TriggerEvent::Update(vec![])], - table_name: ObjectName(vec![Ident::new("emp")]), + table_name: ObjectName(vec![Ident::new("emp").empty_span()]), referenced_table_name: None, referencing: vec![], trigger_object: TriggerObject::Row, @@ -5034,7 +5188,7 @@ fn parse_trigger_related_functions() { exec_body: TriggerExecBody { exec_type: TriggerExecBodyType::Function, func_desc: FunctionDesc { - name: ObjectName(vec![Ident::new("emp_stamp")]), + name: ObjectName(vec![Ident::new("emp_stamp").empty_span()]), args: None, } }, @@ -5047,8 +5201,8 @@ fn parse_trigger_related_functions() { drop_trigger, Statement::DropTrigger { if_exists: false, - trigger_name: ObjectName(vec![Ident::new("emp_stamp")]), - table_name: ObjectName(vec![Ident::new("emp")]), + trigger_name: ObjectName(vec![Ident::new("emp_stamp").empty_span()]), + table_name: ObjectName(vec![Ident::new("emp").empty_span()]), option: None } ); @@ -5081,10 +5235,13 @@ fn check_arrow_precedence(sql: &str, arrow_operator: BinaryOperator) { pg().verified_expr(sql), Expr::BinaryOp { left: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "foo".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "foo".to_string(), + quote_style: None, + } + .empty_span() + )), op: arrow_operator, right: Box::new(Expr::Value(Value::SingleQuotedString("bar".to_string()))), }), @@ -5111,10 +5268,13 @@ fn arrow_cast_precedence() { assert_eq!( stmt, Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "foo".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "foo".to_string(), + quote_style: None, + } + .empty_span() + )), op: BinaryOperator::Arrow, right: Box::new(Expr::Cast { kind: CastKind::DoubleColon, @@ -5146,8 +5306,8 @@ fn parse_create_type_as_enum() { assert_eq!( vec!["label1", "label2", "label3", "label4"] .into_iter() - .map(|l| Ident::with_quote('\'', l)) - .collect::>(), + .map(|l| Ident::with_quote('\'', l).empty_span()) + .collect::>>(), labels ); } diff --git a/tests/sqlparser_redshift.rs b/tests/sqlparser_redshift.rs index a25d50605..86991d555 100644 --- a/tests/sqlparser_redshift.rs +++ b/tests/sqlparser_redshift.rs @@ -29,10 +29,13 @@ fn test_square_brackets_over_db_schema_table_name() { let select = redshift().verified_only_select("SELECT [col1] FROM [test_schema].[test_table]"); assert_eq!( select.projection[0], - SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "col1".to_string(), - quote_style: Some('[') - })), + SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "col1".to_string(), + quote_style: Some('[') + } + .empty_span() + )), ); assert_eq!( select.from[0], @@ -42,11 +45,13 @@ fn test_square_brackets_over_db_schema_table_name() { Ident { value: "test_schema".to_string(), quote_style: Some('[') - }, + } + .empty_span(), Ident { value: "test_table".to_string(), quote_style: Some('[') } + .empty_span() ]), alias: None, args: None, @@ -76,10 +81,13 @@ fn test_double_quotes_over_db_schema_table_name() { redshift().verified_only_select("SELECT \"col1\" FROM \"test_schema\".\"test_table\""); assert_eq!( select.projection[0], - SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "col1".to_string(), - quote_style: Some('"') - })), + SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "col1".to_string(), + quote_style: Some('"') + } + .empty_span() + )), ); assert_eq!( select.from[0], @@ -89,11 +97,13 @@ fn test_double_quotes_over_db_schema_table_name() { Ident { value: "test_schema".to_string(), quote_style: Some('"') - }, + } + .empty_span(), Ident { value: "test_table".to_string(), quote_style: Some('"') } + .empty_span() ]), alias: None, args: None, @@ -124,8 +134,11 @@ fn parse_delimited_identifiers() { with_ordinality: _, partitions: _, } => { - assert_eq!(vec![Ident::with_quote('"', "a table")], name.0); - assert_eq!(Ident::with_quote('"', "alias"), alias.unwrap().name); + assert_eq!(vec![Ident::with_quote('"', "a table").empty_span()], name.0); + assert_eq!( + Ident::with_quote('"', "alias").empty_span(), + alias.unwrap().name + ); assert!(args.is_none()); assert!(with_hints.is_empty()); assert!(version.is_none()); @@ -136,14 +149,14 @@ fn parse_delimited_identifiers() { assert_eq!(3, select.projection.len()); assert_eq!( &Expr::CompoundIdentifier(vec![ - Ident::with_quote('"', "alias"), - Ident::with_quote('"', "bar baz"), + Ident::with_quote('"', "alias").empty_span(), + Ident::with_quote('"', "bar baz").empty_span(), ]), expr_from_projection(&select.projection[0]), ); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::with_quote('"', "myfun")]), + name: ObjectName(vec![Ident::with_quote('"', "myfun").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -159,8 +172,11 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); - assert_eq!(&Ident::with_quote('"', "column alias"), alias); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); + assert_eq!(&Ident::with_quote('"', "column alias").empty_span(), alias); } _ => panic!("Expected ExprWithAlias"), } @@ -186,7 +202,7 @@ fn test_sharp() { let sql = "SELECT #_of_values"; let select = redshift().verified_only_select(sql); assert_eq!( - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("#_of_values"))), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("#_of_values").empty_span())), select.projection[0] ); } diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index c17c7b958..c0d0647ad 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -271,8 +271,8 @@ fn test_snowflake_create_table_with_tag() { assert_eq!("my_table", name.to_string()); assert_eq!( Some(vec![ - Tag::new("A".into(), "TAG A".to_string()), - Tag::new("B".into(), "TAG B".to_string()) + Tag::new(Ident::new("A").empty_span(), "TAG A".to_string()), + Tag::new(Ident::new("B").empty_span(), "TAG B".to_string()) ]), with_tags ); @@ -292,8 +292,8 @@ fn test_snowflake_create_table_with_tag() { assert_eq!("my_table", name.to_string()); assert_eq!( Some(vec![ - Tag::new("A".into(), "TAG A".to_string()), - Tag::new("B".into(), "TAG B".to_string()) + Tag::new(Ident::new("A").empty_span(), "TAG A".to_string()), + Tag::new(Ident::new("B").empty_span(), "TAG B".to_string()) ]), with_tags ); @@ -340,7 +340,7 @@ fn test_snowflake_create_table_column_comment() { assert_eq!("my_table", name.to_string()); assert_eq!( vec![ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::String(None), options: vec![ColumnOptionDef { name: None, @@ -450,8 +450,8 @@ fn test_snowflake_create_table_cluster_by() { assert_eq!("my_table", name.to_string()); assert_eq!( Some(WrappedCollection::Parentheses(vec![ - Ident::new("a"), - Ident::new("b"), + Ident::new("a").empty_span(), + Ident::new("b").empty_span(), ])), cluster_by ) @@ -542,7 +542,7 @@ fn test_snowflake_create_table_with_autoincrement_columns() { columns, vec![ ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -556,7 +556,7 @@ fn test_snowflake_create_table_with_autoincrement_columns() { }] }, ColumnDef { - name: "b".into(), + name: Ident::new("b").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -575,7 +575,7 @@ fn test_snowflake_create_table_with_autoincrement_columns() { }] }, ColumnDef { - name: "c".into(), + name: Ident::new("c").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -589,7 +589,7 @@ fn test_snowflake_create_table_with_autoincrement_columns() { }] }, ColumnDef { - name: "d".into(), + name: Ident::new("d").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -623,9 +623,11 @@ fn test_snowflake_create_table_with_collated_column() { assert_eq!( columns, vec![ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Text, - collation: Some(ObjectName(vec![Ident::with_quote('\'', "de_DE")])), + collation: Some(ObjectName(vec![ + Ident::with_quote('\'', "de_DE").empty_span() + ])), options: vec![] },] ); @@ -650,12 +652,18 @@ fn test_snowflake_create_table_with_columns_masking_policy() { ( "CREATE TABLE my_table (a INT WITH MASKING POLICY p USING (a, b))", true, - Some(vec!["a".into(), "b".into()]), + Some(vec![ + Ident::new("a").empty_span(), + Ident::new("b").empty_span(), + ]), ), ( "CREATE TABLE my_table (a INT MASKING POLICY p USING (a, b))", false, - Some(vec!["a".into(), "b".into()]), + Some(vec![ + Ident::new("a").empty_span(), + Ident::new("b").empty_span(), + ]), ), ] { match snowflake().verified_stmt(sql) { @@ -663,7 +671,7 @@ fn test_snowflake_create_table_with_columns_masking_policy() { assert_eq!( columns, vec![ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -671,7 +679,7 @@ fn test_snowflake_create_table_with_columns_masking_policy() { option: ColumnOption::Policy(ColumnPolicy::MaskingPolicy( ColumnPolicyProperty { with, - policy_name: "p".into(), + policy_name: Ident::new("p").empty_span(), using_columns, } )) @@ -698,7 +706,7 @@ fn test_snowflake_create_table_with_columns_projection_policy() { assert_eq!( columns, vec![ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -706,7 +714,7 @@ fn test_snowflake_create_table_with_columns_projection_policy() { option: ColumnOption::Policy(ColumnPolicy::ProjectionPolicy( ColumnPolicyProperty { with, - policy_name: "p".into(), + policy_name: Ident::new("p").empty_span(), using_columns: None, } )) @@ -736,7 +744,7 @@ fn test_snowflake_create_table_with_columns_tags() { assert_eq!( columns, vec![ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ColumnOptionDef { @@ -744,8 +752,8 @@ fn test_snowflake_create_table_with_columns_tags() { option: ColumnOption::Tags(TagsColumnOption { with, tags: vec![ - Tag::new("A".into(), "TAG A".into()), - Tag::new("B".into(), "TAG B".into()), + Tag::new(Ident::new("A").empty_span(), "TAG A".into()), + Tag::new(Ident::new("B").empty_span(), "TAG B".into()), ] }), }], @@ -771,7 +779,7 @@ fn test_snowflake_create_table_with_several_column_options() { columns, vec![ ColumnDef { - name: "a".into(), + name: Ident::new("a").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ @@ -789,8 +797,11 @@ fn test_snowflake_create_table_with_several_column_options() { option: ColumnOption::Policy(ColumnPolicy::MaskingPolicy( ColumnPolicyProperty { with: true, - policy_name: "p1".into(), - using_columns: Some(vec!["a".into(), "b".into()]), + policy_name: Ident::new("p1").empty_span(), + using_columns: Some(vec![ + Ident::new("a").empty_span(), + Ident::new("b").empty_span() + ]), } )), }, @@ -799,24 +810,26 @@ fn test_snowflake_create_table_with_several_column_options() { option: ColumnOption::Tags(TagsColumnOption { with: true, tags: vec![ - Tag::new("A".into(), "TAG A".into()), - Tag::new("B".into(), "TAG B".into()), + Tag::new(Ident::new("A").empty_span(), "TAG A".into()), + Tag::new(Ident::new("B").empty_span(), "TAG B".into()), ] }), } ], }, ColumnDef { - name: "b".into(), + name: Ident::new("b").empty_span(), data_type: DataType::Text, - collation: Some(ObjectName(vec![Ident::with_quote('\'', "de_DE")])), + collation: Some(ObjectName(vec![ + Ident::with_quote('\'', "de_DE").empty_span() + ])), options: vec![ ColumnOptionDef { name: None, option: ColumnOption::Policy(ColumnPolicy::ProjectionPolicy( ColumnPolicyProperty { with: false, - policy_name: "p2".into(), + policy_name: Ident::new("p2").empty_span(), using_columns: None, } )), @@ -826,8 +839,8 @@ fn test_snowflake_create_table_with_several_column_options() { option: ColumnOption::Tags(TagsColumnOption { with: false, tags: vec![ - Tag::new("C".into(), "TAG C".into()), - Tag::new("D".into(), "TAG D".into()), + Tag::new(Ident::new("C").empty_span(), "TAG C".into()), + Tag::new(Ident::new("D").empty_span(), "TAG D".into()), ] }), } @@ -967,7 +980,7 @@ fn parse_array() { assert_eq!( &Expr::Cast { kind: CastKind::Cast, - expr: Box::new(Expr::Identifier(Ident::new("a"))), + expr: Box::new(Expr::Identifier(Ident::new("a").empty_span())), data_type: DataType::Array(ArrayElemTypeDef::None), format: None, }, @@ -989,7 +1002,7 @@ fn parse_semi_structured_data_traversal() { let select = snowflake().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("a"))), + value: Box::new(Expr::Identifier(Ident::new("a").empty_span())), path: JsonPath { path: vec![JsonPathElem::Dot { key: "b".to_owned(), @@ -1005,7 +1018,7 @@ fn parse_semi_structured_data_traversal() { let select = snowflake().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("a"))), + value: Box::new(Expr::Identifier(Ident::new("a").empty_span())), path: JsonPath { path: vec![JsonPathElem::Dot { key: "my long object key name".to_owned(), @@ -1021,7 +1034,7 @@ fn parse_semi_structured_data_traversal() { let select = snowflake().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("a"))), + value: Box::new(Expr::Identifier(Ident::new("a").empty_span())), path: JsonPath { path: vec![JsonPathElem::Bracket { key: Expr::BinaryOp { @@ -1043,7 +1056,7 @@ fn parse_semi_structured_data_traversal() { assert_eq!( vec![ SelectItem::UnnamedExpr(Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("a"))), + value: Box::new(Expr::Identifier(Ident::new("a").empty_span())), path: JsonPath { path: vec![JsonPathElem::Dot { key: "select".to_owned(), @@ -1052,7 +1065,7 @@ fn parse_semi_structured_data_traversal() { }, }), SelectItem::UnnamedExpr(Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("a"))), + value: Box::new(Expr::Identifier(Ident::new("a").empty_span())), path: JsonPath { path: vec![JsonPathElem::Dot { key: "from".to_owned(), @@ -1070,7 +1083,7 @@ fn parse_semi_structured_data_traversal() { let select = snowflake().verified_only_select(sql); assert_eq!( vec![SelectItem::UnnamedExpr(Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("a"))), + value: Box::new(Expr::Identifier(Ident::new("a").empty_span())), path: JsonPath { path: vec![ JsonPathElem::Dot { @@ -1097,7 +1110,7 @@ fn parse_semi_structured_data_traversal() { let select = snowflake().verified_only_select(sql); assert_eq!( vec![SelectItem::UnnamedExpr(Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("a"))), + value: Box::new(Expr::Identifier(Ident::new("a").empty_span())), path: JsonPath { path: vec![ JsonPathElem::Dot { @@ -1123,7 +1136,7 @@ fn parse_semi_structured_data_traversal() { let select = snowflake().verified_only_select(sql); assert_eq!( vec![SelectItem::UnnamedExpr(Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("a"))), + value: Box::new(Expr::Identifier(Ident::new("a").empty_span())), path: JsonPath { path: vec![ JsonPathElem::Bracket { @@ -1147,11 +1160,11 @@ fn parse_semi_structured_data_traversal() { assert_eq!( snowflake().verified_expr("a[b:c]"), Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("a"))), + value: Box::new(Expr::Identifier(Ident::new("a").empty_span())), path: JsonPath { path: vec![JsonPathElem::Bracket { key: Expr::JsonAccess { - value: Box::new(Expr::Identifier(Ident::new("b"))), + value: Box::new(Expr::Identifier(Ident::new("b").empty_span())), path: JsonPath { path: vec![JsonPathElem::Dot { key: "c".to_owned(), @@ -1191,8 +1204,11 @@ fn parse_delimited_identifiers() { with_ordinality: _, partitions: _, } => { - assert_eq!(vec![Ident::with_quote('"', "a table")], name.0); - assert_eq!(Ident::with_quote('"', "alias"), alias.unwrap().name); + assert_eq!(vec![Ident::with_quote('"', "a table").empty_span()], name.0); + assert_eq!( + Ident::with_quote('"', "alias").empty_span(), + alias.unwrap().name + ); assert!(args.is_none()); assert!(with_hints.is_empty()); assert!(version.is_none()); @@ -1203,14 +1219,14 @@ fn parse_delimited_identifiers() { assert_eq!(3, select.projection.len()); assert_eq!( &Expr::CompoundIdentifier(vec![ - Ident::with_quote('"', "alias"), - Ident::with_quote('"', "bar baz"), + Ident::with_quote('"', "alias").empty_span(), + Ident::with_quote('"', "bar baz").empty_span(), ]), expr_from_projection(&select.projection[0]), ); assert_eq!( &Expr::Function(Function { - name: ObjectName(vec![Ident::with_quote('"', "myfun")]), + name: ObjectName(vec![Ident::with_quote('"', "myfun").empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, @@ -1226,8 +1242,11 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); - assert_eq!(&Ident::with_quote('"', "column alias"), alias); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); + assert_eq!(&Ident::with_quote('"', "column alias").empty_span(), alias); } _ => panic!("Expected: ExprWithAlias"), } @@ -1273,7 +1292,9 @@ fn snowflake_and_generic() -> TestedDialects { fn test_select_wildcard_with_exclude() { let select = snowflake_and_generic().verified_only_select("SELECT * EXCLUDE (col_a) FROM data"); let expected = SelectItem::Wildcard(WildcardAdditionalOptions { - opt_exclude: Some(ExcludeSelectItem::Multiple(vec![Ident::new("col_a")])), + opt_exclude: Some(ExcludeSelectItem::Multiple(vec![ + Ident::new("col_a").empty_span() + ])), ..Default::default() }); assert_eq!(expected, select.projection[0]); @@ -1281,9 +1302,11 @@ fn test_select_wildcard_with_exclude() { let select = snowflake_and_generic() .verified_only_select("SELECT name.* EXCLUDE department_id FROM employee_table"); let expected = SelectItem::QualifiedWildcard( - ObjectName(vec![Ident::new("name")]), + ObjectName(vec![Ident::new("name").empty_span()]), WildcardAdditionalOptions { - opt_exclude: Some(ExcludeSelectItem::Single(Ident::new("department_id"))), + opt_exclude: Some(ExcludeSelectItem::Single( + Ident::new("department_id").empty_span(), + )), ..Default::default() }, ); @@ -1293,8 +1316,8 @@ fn test_select_wildcard_with_exclude() { .verified_only_select("SELECT * EXCLUDE (department_id, employee_id) FROM employee_table"); let expected = SelectItem::Wildcard(WildcardAdditionalOptions { opt_exclude: Some(ExcludeSelectItem::Multiple(vec![ - Ident::new("department_id"), - Ident::new("employee_id"), + Ident::new("department_id").empty_span(), + Ident::new("employee_id").empty_span(), ])), ..Default::default() }); @@ -1307,8 +1330,8 @@ fn test_select_wildcard_with_rename() { snowflake_and_generic().verified_only_select("SELECT * RENAME col_a AS col_b FROM data"); let expected = SelectItem::Wildcard(WildcardAdditionalOptions { opt_rename: Some(RenameSelectItem::Single(IdentWithAlias { - ident: Ident::new("col_a"), - alias: Ident::new("col_b"), + ident: Ident::new("col_a").empty_span(), + alias: Ident::new("col_b").empty_span(), })), ..Default::default() }); @@ -1318,16 +1341,16 @@ fn test_select_wildcard_with_rename() { "SELECT name.* RENAME (department_id AS new_dep, employee_id AS new_emp) FROM employee_table", ); let expected = SelectItem::QualifiedWildcard( - ObjectName(vec![Ident::new("name")]), + ObjectName(vec![Ident::new("name").empty_span()]), WildcardAdditionalOptions { opt_rename: Some(RenameSelectItem::Multiple(vec![ IdentWithAlias { - ident: Ident::new("department_id"), - alias: Ident::new("new_dep"), + ident: Ident::new("department_id").empty_span(), + alias: Ident::new("new_dep").empty_span(), }, IdentWithAlias { - ident: Ident::new("employee_id"), - alias: Ident::new("new_emp"), + ident: Ident::new("employee_id").empty_span(), + alias: Ident::new("new_emp").empty_span(), }, ])), ..Default::default() @@ -1345,17 +1368,17 @@ fn test_select_wildcard_with_replace_and_rename() { opt_replace: Some(ReplaceSelectItem { items: vec![Box::new(ReplaceSelectElement { expr: Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("col_z"))), + left: Box::new(Expr::Identifier(Ident::new("col_z").empty_span())), op: BinaryOperator::StringConcat, - right: Box::new(Expr::Identifier(Ident::new("col_z"))), + right: Box::new(Expr::Identifier(Ident::new("col_z").empty_span())), }, - column_name: Ident::new("col_z"), + column_name: Ident::new("col_z").empty_span(), as_keyword: true, })], }), opt_rename: Some(RenameSelectItem::Multiple(vec![IdentWithAlias { - ident: Ident::new("col_z"), - alias: Ident::new("col_zz"), + ident: Ident::new("col_z").empty_span(), + alias: Ident::new("col_zz").empty_span(), }])), ..Default::default() }); @@ -1379,10 +1402,10 @@ fn test_select_wildcard_with_exclude_and_rename() { let select = snowflake_and_generic() .verified_only_select("SELECT * EXCLUDE col_z RENAME col_a AS col_b FROM data"); let expected = SelectItem::Wildcard(WildcardAdditionalOptions { - opt_exclude: Some(ExcludeSelectItem::Single(Ident::new("col_z"))), + opt_exclude: Some(ExcludeSelectItem::Single(Ident::new("col_z").empty_span())), opt_rename: Some(RenameSelectItem::Single(IdentWithAlias { - ident: Ident::new("col_a"), - alias: Ident::new("col_b"), + ident: Ident::new("col_a").empty_span(), + alias: Ident::new("col_b").empty_span(), })), ..Default::default() }); @@ -1450,7 +1473,7 @@ fn parse_snowflake_declare_cursor() { "DECLARE c1 CURSOR FOR res", "c1", Some(DeclareAssignment::For( - Expr::Identifier(Ident::new("res")).into(), + Expr::Identifier(Ident::new("res").empty_span()).into(), )), None, ), @@ -1466,7 +1489,7 @@ fn parse_snowflake_declare_cursor() { for_query, .. } = stmts.swap_remove(0); - assert_eq!(vec![Ident::new(expected_name)], names); + assert_eq!(vec![Ident::new(expected_name).empty_span()], names); assert!(data_type.is_none()); assert_eq!(Some(DeclareType::Cursor), declare_type); assert_eq!(expected_assigned_expr, assigned_expr); @@ -1534,7 +1557,7 @@ fn parse_snowflake_declare_result_set() { for_query, .. } = stmts.swap_remove(0); - assert_eq!(vec![Ident::new(expected_name)], names); + assert_eq!(vec![Ident::new(expected_name).empty_span()], names); assert!(data_type.is_none()); assert!(for_query.is_none()); assert_eq!(Some(DeclareType::ResultSet), declare_type); @@ -1587,7 +1610,7 @@ fn parse_snowflake_declare_exception() { for_query, .. } = stmts.swap_remove(0); - assert_eq!(vec![Ident::new(expected_name)], names); + assert_eq!(vec![Ident::new(expected_name).empty_span()], names); assert!(data_type.is_none()); assert!(for_query.is_none()); assert_eq!(Some(DeclareType::Exception), declare_type); @@ -1627,7 +1650,7 @@ fn parse_snowflake_declare_variable() { for_query, .. } = stmts.swap_remove(0); - assert_eq!(vec![Ident::new(expected_name)], names); + assert_eq!(vec![Ident::new(expected_name).empty_span()], names); assert!(for_query.is_none()); assert_eq!(expected_data_type, data_type); assert_eq!(None, declare_type); @@ -1913,11 +1936,16 @@ fn test_copy_into() { } => { assert_eq!( into, - ObjectName(vec![Ident::new("my_company"), Ident::new("emp_basic")]) + ObjectName(vec![ + Ident::new("my_company").empty_span(), + Ident::new("emp_basic").empty_span() + ]) ); assert_eq!( from_stage, - ObjectName(vec![Ident::with_quote('\'', "gcs://mybucket/./../a.csv")]) + ObjectName(vec![ + Ident::with_quote('\'', "gcs://mybucket/./../a.csv").empty_span() + ]) ); assert!(files.is_none()); assert!(pattern.is_none()); @@ -1948,7 +1976,9 @@ fn test_copy_into_with_stage_params() { //assert_eq!("s3://load/files/", stage_params.url.unwrap()); assert_eq!( from_stage, - ObjectName(vec![Ident::with_quote('\'', "s3://load/files/")]) + ObjectName(vec![ + Ident::with_quote('\'', "s3://load/files/").empty_span() + ]) ); assert_eq!("myint", stage_params.storage_integration.unwrap()); assert_eq!( @@ -2007,7 +2037,9 @@ fn test_copy_into_with_stage_params() { } => { assert_eq!( from_stage, - ObjectName(vec![Ident::with_quote('\'', "s3://load/files/")]) + ObjectName(vec![ + Ident::with_quote('\'', "s3://load/files/").empty_span() + ]) ); assert_eq!("myint", stage_params.storage_integration.unwrap()); } @@ -2036,7 +2068,10 @@ fn test_copy_into_with_files_and_pattern_and_verification() { assert_eq!(files.unwrap(), vec!["file1.json", "file2.json"]); assert_eq!(pattern.unwrap(), ".*employees0[1-5].csv.gz"); assert_eq!(validation_mode.unwrap(), "RETURN_7_ROWS"); - assert_eq!(from_stage_alias.unwrap(), Ident::new("some_alias")); + assert_eq!( + from_stage_alias.unwrap(), + Ident::new("some_alias").empty_span() + ); } _ => unreachable!(), } @@ -2061,15 +2096,18 @@ fn test_copy_into_with_transformations() { } => { assert_eq!( from_stage, - ObjectName(vec![Ident::new("@schema"), Ident::new("general_finished")]) + ObjectName(vec![ + Ident::new("@schema").empty_span(), + Ident::new("general_finished").empty_span() + ]) ); assert_eq!( from_transformations.as_ref().unwrap()[0], StageLoadSelectItem { - alias: Some(Ident::new("t1")), + alias: Some(Ident::new("t1").empty_span()), file_col_num: 1, - element: Some(Ident::new("st")), - item_as: Some(Ident::new("st")) + element: Some(Ident::new("st").empty_span()), + item_as: Some(Ident::new("st").empty_span()) } ); assert_eq!( @@ -2077,14 +2115,14 @@ fn test_copy_into_with_transformations() { StageLoadSelectItem { alias: None, file_col_num: 1, - element: Some(Ident::new("index")), + element: Some(Ident::new("index").empty_span()), item_as: None } ); assert_eq!( from_transformations.as_ref().unwrap()[2], StageLoadSelectItem { - alias: Some(Ident::new("t2")), + alias: Some(Ident::new("t2").empty_span()), file_col_num: 1, element: None, item_as: None @@ -2170,17 +2208,23 @@ fn test_snowflake_stage_object_names() { "@~/path", ]; let mut allowed_object_names = [ - ObjectName(vec![Ident::new("my_company"), Ident::new("emp_basic")]), - ObjectName(vec![Ident::new("@namespace"), Ident::new("%table_name")]), ObjectName(vec![ - Ident::new("@namespace"), - Ident::new("%table_name/path"), + Ident::new("my_company").empty_span(), + Ident::new("emp_basic").empty_span(), + ]), + ObjectName(vec![ + Ident::new("@namespace").empty_span(), + Ident::new("%table_name").empty_span(), + ]), + ObjectName(vec![ + Ident::new("@namespace").empty_span(), + Ident::new("%table_name/path").empty_span(), ]), ObjectName(vec![ - Ident::new("@namespace"), - Ident::new("stage_name/path"), + Ident::new("@namespace").empty_span(), + Ident::new("stage_name/path").empty_span(), ]), - ObjectName(vec![Ident::new("@~/path")]), + ObjectName(vec![Ident::new("@~/path").empty_span()]), ]; for it in allowed_formatted_names @@ -2209,10 +2253,19 @@ fn test_snowflake_copy_into() { Statement::CopyIntoSnowflake { into, from_stage, .. } => { - assert_eq!(into, ObjectName(vec![Ident::new("a"), Ident::new("b")])); + assert_eq!( + into, + ObjectName(vec![ + Ident::new("a").empty_span(), + Ident::new("b").empty_span() + ]) + ); assert_eq!( from_stage, - ObjectName(vec![Ident::new("@namespace"), Ident::new("stage_name")]) + ObjectName(vec![ + Ident::new("@namespace").empty_span(), + Ident::new("stage_name").empty_span() + ]) ) } _ => unreachable!(), @@ -2230,13 +2283,16 @@ fn test_snowflake_copy_into_stage_name_ends_with_parens() { assert_eq!( into, ObjectName(vec![ - Ident::new("SCHEMA"), - Ident::new("SOME_MONITORING_SYSTEM") + Ident::new("SCHEMA").empty_span(), + Ident::new("SOME_MONITORING_SYSTEM").empty_span() ]) ); assert_eq!( from_stage, - ObjectName(vec![Ident::new("@schema"), Ident::new("general_finished")]) + ObjectName(vec![ + Ident::new("@schema").empty_span(), + Ident::new("general_finished").empty_span() + ]) ) } _ => unreachable!(), @@ -2337,9 +2393,9 @@ fn parse_extract_custom_part() { let select = snowflake_and_generic().verified_only_select(sql); assert_eq!( &Expr::Extract { - field: DateTimeField::Custom(Ident::new("eod")), + field: DateTimeField::Custom(Ident::new("eod").empty_span()), syntax: ExtractSyntax::From, - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), }, expr_from_projection(only(&select.projection)), ); @@ -2353,7 +2409,7 @@ fn parse_extract_comma() { &Expr::Extract { field: DateTimeField::Hour, syntax: ExtractSyntax::Comma, - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), }, expr_from_projection(only(&select.projection)), ); @@ -2365,9 +2421,9 @@ fn parse_extract_comma_quoted() { let select = snowflake_and_generic().verified_only_select(sql); assert_eq!( &Expr::Extract { - field: DateTimeField::Custom(Ident::with_quote('\'', "hour")), + field: DateTimeField::Custom(Ident::with_quote('\'', "hour").empty_span()), syntax: ExtractSyntax::Comma, - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), }, expr_from_projection(only(&select.projection)), ); @@ -2382,13 +2438,13 @@ fn parse_comma_outer_join() { case1.selection, Some(Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("t1"), - Ident::new("c1") + Ident::new("t1").empty_span(), + Ident::new("c1").empty_span() ])), op: BinaryOperator::Eq, right: Box::new(Expr::OuterJoin(Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("t2"), - Ident::new("c2") + Ident::new("t2").empty_span(), + Ident::new("c2").empty_span() ])))) }) ); @@ -2399,11 +2455,11 @@ fn parse_comma_outer_join() { assert_eq!( case2.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("c1"))), + left: Box::new(Expr::Identifier(Ident::new("c1").empty_span())), op: BinaryOperator::Eq, - right: Box::new(Expr::OuterJoin(Box::new(Expr::Identifier(Ident::new( - "c2" - ))))) + right: Box::new(Expr::OuterJoin(Box::new(Expr::Identifier( + Ident::new("c2").empty_span() + )))) }) ); @@ -2413,7 +2469,7 @@ fn parse_comma_outer_join() { assert_eq!( case3.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("c1"))), + left: Box::new(Expr::Identifier(Ident::new("c1").empty_span())), op: BinaryOperator::Eq, right: Box::new(call( "myudf", @@ -2558,13 +2614,13 @@ fn asof_joins() { join_operator: JoinOperator::AsOf { match_condition: Expr::BinaryOp { left: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("tu"), - Ident::new("trade_time"), + Ident::new("tu").empty_span(), + Ident::new("trade_time").empty_span(), ])), op: BinaryOperator::GtEq, right: Box::new(Expr::CompoundIdentifier(vec![ - Ident::new("qu"), - Ident::new("quote_time"), + Ident::new("qu").empty_span(), + Ident::new("quote_time").empty_span(), ])), }, constraint: JoinConstraint::None, @@ -2652,7 +2708,8 @@ fn parse_use() { snowflake().verified_stmt(&format!("USE {}", object_name)), Statement::Use(Use::Object(ObjectName(vec![Ident::new( object_name.to_string() - )]))) + ) + .empty_span()]))) ); for "e in "e_styles { // Test single identifier with different type of quotes @@ -2661,7 +2718,8 @@ fn parse_use() { Statement::Use(Use::Object(ObjectName(vec![Ident::with_quote( quote, object_name.to_string(), - )]))) + ) + .empty_span()]))) ); } } @@ -2671,8 +2729,8 @@ fn parse_use() { std::assert_eq!( snowflake().verified_stmt(&format!("USE {0}CATALOG{0}.{0}my_schema{0}", quote)), Statement::Use(Use::Object(ObjectName(vec![ - Ident::with_quote(quote, "CATALOG"), - Ident::with_quote(quote, "my_schema") + Ident::with_quote(quote, "CATALOG").empty_span(), + Ident::with_quote(quote, "my_schema").empty_span(), ]))) ); } @@ -2680,8 +2738,8 @@ fn parse_use() { std::assert_eq!( snowflake().verified_stmt("USE mydb.my_schema"), Statement::Use(Use::Object(ObjectName(vec![ - Ident::new("mydb"), - Ident::new("my_schema") + Ident::new("mydb").empty_span(), + Ident::new("my_schema").empty_span(), ]))) ); @@ -2692,20 +2750,22 @@ fn parse_use() { Statement::Use(Use::Database(ObjectName(vec![Ident::with_quote( quote, "my_database".to_string(), - )]))) + ) + .empty_span()]))) ); std::assert_eq!( snowflake().verified_stmt(&format!("USE SCHEMA {0}my_schema{0}", quote)), Statement::Use(Use::Schema(ObjectName(vec![Ident::with_quote( quote, "my_schema".to_string(), - )]))) + ) + .empty_span()]))) ); std::assert_eq!( snowflake().verified_stmt(&format!("USE SCHEMA {0}CATALOG{0}.{0}my_schema{0}", quote)), Statement::Use(Use::Schema(ObjectName(vec![ - Ident::with_quote(quote, "CATALOG"), - Ident::with_quote(quote, "my_schema") + Ident::with_quote(quote, "CATALOG").empty_span(), + Ident::with_quote(quote, "my_schema").empty_span(), ]))) ); } @@ -2743,12 +2803,12 @@ fn parse_view_column_descriptions() { columns, vec![ ViewColumnDef { - name: Ident::new("a"), + name: Ident::new("a").empty_span(), data_type: None, options: Some(vec![ColumnOption::Comment("Comment".to_string())]), }, ViewColumnDef { - name: Ident::new("b"), + name: Ident::new("b").empty_span(), data_type: None, options: None, } diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs index 6f8bbb2d8..5417b6f69 100644 --- a/tests/sqlparser_sqlite.rs +++ b/tests/sqlparser_sqlite.rs @@ -150,7 +150,10 @@ fn parse_create_virtual_table() { module_name, module_args, } => { - let args = vec![Ident::new("arg1"), Ident::new("arg2")]; + let args = vec![ + Ident::new("arg1").empty_span(), + Ident::new("arg2").empty_span(), + ]; assert_eq!("t", name.to_string()); assert_eq!("module_name", module_name.to_string()); assert_eq!(args, module_args); @@ -212,7 +215,7 @@ fn parse_create_table_auto_increment() { assert_eq!(name.to_string(), "foo"); assert_eq!( vec![ColumnDef { - name: "bar".into(), + name: Ident::new("bar").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ @@ -241,7 +244,7 @@ fn parse_create_table_auto_increment() { #[test] fn parse_create_table_primary_key_asc_desc() { let expected_column_def = |kind| ColumnDef { - name: "bar".into(), + name: Ident::new("bar").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![ @@ -284,13 +287,13 @@ fn parse_create_sqlite_quote() { assert_eq!( vec![ ColumnDef { - name: Ident::with_quote('"', "KEY"), + name: Ident::with_quote('"', "KEY").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![], }, ColumnDef { - name: Ident::with_quote('[', "INDEX"), + name: Ident::with_quote('[', "INDEX").empty_span(), data_type: DataType::Int(None), collation: None, options: vec![], @@ -418,12 +421,12 @@ fn parse_window_function_with_filter() { assert_eq!( select.projection, vec![SelectItem::UnnamedExpr(Expr::Function(Function { - name: ObjectName(vec![Ident::new(func_name)]), + name: ObjectName(vec![Ident::new(func_name).empty_span()]), parameters: FunctionArguments::None, args: FunctionArguments::List(FunctionArgumentList { duplicate_treatment: None, args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("x")) + Expr::Identifier(Ident::new("x").empty_span()) ))], clauses: vec![], }), @@ -434,7 +437,7 @@ fn parse_window_function_with_filter() { order_by: vec![], window_frame: None, })), - filter: Some(Box::new(Expr::Identifier(Ident::new("y")))), + filter: Some(Box::new(Expr::Identifier(Ident::new("y").empty_span()))), within_group: vec![], }))] ); @@ -467,8 +470,8 @@ fn parse_update_tuple_row_values() { Statement::Update { assignments: vec![Assignment { target: AssignmentTarget::Tuple(vec![ - ObjectName(vec![Ident::new("a"),]), - ObjectName(vec![Ident::new("b"),]), + ObjectName(vec![Ident::new("a").empty_span()]), + ObjectName(vec![Ident::new("b").empty_span()]), ]), value: Expr::Tuple(vec![ Expr::Value(Value::Number("1".parse().unwrap(), false)), @@ -478,7 +481,7 @@ fn parse_update_tuple_row_values() { selection: None, table: TableWithJoins { relation: TableFactor::Table { - name: ObjectName(vec![Ident::new("x")]), + name: ObjectName(vec![Ident::new("x").empty_span()]), alias: None, args: None, with_hints: vec![], @@ -562,7 +565,10 @@ fn test_dollar_identifier_as_placeholder() { match sqlite().verified_expr("id = $id") { Expr::BinaryOp { op, left, right } => { assert_eq!(op, BinaryOperator::Eq); - assert_eq!(left, Box::new(Expr::Identifier(Ident::new("id")))); + assert_eq!( + left, + Box::new(Expr::Identifier(Ident::new("id").empty_span())) + ); assert_eq!(right, Box::new(Expr::Value(Placeholder("$id".to_string())))); } _ => unreachable!(),