Merge pull request #105 from benesch/renames

Remove "SQL" from types (and other renames)
This commit is contained in:
Nikhil Benesch 2019-06-25 13:16:13 -04:00 committed by GitHub
commit bafb20746f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 887 additions and 905 deletions

View file

@ -19,7 +19,7 @@ use simple_logger;
use std::fs; use std::fs;
use sqlparser::dialect::*; use sqlparser::dialect::*;
use sqlparser::sqlparser::Parser; use sqlparser::parser::Parser;
fn main() { fn main() {
simple_logger::init().unwrap(); simple_logger::init().unwrap();
@ -30,10 +30,10 @@ fn main() {
); );
let dialect: Box<dyn Dialect> = match std::env::args().nth(2).unwrap_or_default().as_ref() { let dialect: Box<dyn Dialect> = match std::env::args().nth(2).unwrap_or_default().as_ref() {
"--ansi" => Box::new(AnsiSqlDialect {}), "--ansi" => Box::new(AnsiDialect {}),
"--postgres" => Box::new(PostgreSqlDialect {}), "--postgres" => Box::new(PostgreSqlDialect {}),
"--ms" => Box::new(MsSqlDialect {}), "--ms" => Box::new(MsSqlDialect {}),
"--generic" | "" => Box::new(GenericSqlDialect {}), "--generic" | "" => Box::new(GenericDialect {}),
s => panic!("Unexpected parameter: {}", s), s => panic!("Unexpected parameter: {}", s),
}; };

View file

@ -12,8 +12,8 @@
#![warn(clippy::all)] #![warn(clippy::all)]
use sqlparser::dialect::GenericSqlDialect; use sqlparser::dialect::GenericDialect;
use sqlparser::sqlparser::*; use sqlparser::parser::*;
fn main() { fn main() {
let sql = "SELECT a, b, 123, myfunc(b) \ let sql = "SELECT a, b, 123, myfunc(b) \
@ -21,7 +21,7 @@ fn main() {
WHERE a > b AND b < 100 \ WHERE a > b AND b < 100 \
ORDER BY a DESC, b"; ORDER BY a DESC, b";
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let ast = Parser::parse_sql(&dialect, sql.to_string()).unwrap(); let ast = Parser::parse_sql(&dialect, sql.to_string()).unwrap();

View file

@ -10,11 +10,11 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::SQLObjectName; use super::ObjectName;
/// SQL data types /// SQL data types
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLType { pub enum DataType {
/// Fixed-length character type e.g. CHAR(10) /// Fixed-length character type e.g. CHAR(10)
Char(Option<u64>), Char(Option<u64>),
/// Variable-length character type e.g. VARCHAR(10) /// Variable-length character type e.g. VARCHAR(10)
@ -60,44 +60,44 @@ pub enum SQLType {
/// Bytea /// Bytea
Bytea, Bytea,
/// Custom type such as enums /// Custom type such as enums
Custom(SQLObjectName), Custom(ObjectName),
/// Arrays /// Arrays
Array(Box<SQLType>), Array(Box<DataType>),
} }
impl ToString for SQLType { impl ToString for DataType {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
SQLType::Char(size) => format_type_with_optional_length("char", size), DataType::Char(size) => format_type_with_optional_length("char", size),
SQLType::Varchar(size) => format_type_with_optional_length("character varying", size), DataType::Varchar(size) => format_type_with_optional_length("character varying", size),
SQLType::Uuid => "uuid".to_string(), DataType::Uuid => "uuid".to_string(),
SQLType::Clob(size) => format!("clob({})", size), DataType::Clob(size) => format!("clob({})", size),
SQLType::Binary(size) => format!("binary({})", size), DataType::Binary(size) => format!("binary({})", size),
SQLType::Varbinary(size) => format!("varbinary({})", size), DataType::Varbinary(size) => format!("varbinary({})", size),
SQLType::Blob(size) => format!("blob({})", size), DataType::Blob(size) => format!("blob({})", size),
SQLType::Decimal(precision, scale) => { DataType::Decimal(precision, scale) => {
if let Some(scale) = scale { if let Some(scale) = scale {
format!("numeric({},{})", precision.unwrap(), scale) format!("numeric({},{})", precision.unwrap(), scale)
} else { } else {
format_type_with_optional_length("numeric", precision) format_type_with_optional_length("numeric", precision)
} }
} }
SQLType::Float(size) => format_type_with_optional_length("float", size), DataType::Float(size) => format_type_with_optional_length("float", size),
SQLType::SmallInt => "smallint".to_string(), DataType::SmallInt => "smallint".to_string(),
SQLType::Int => "int".to_string(), DataType::Int => "int".to_string(),
SQLType::BigInt => "bigint".to_string(), DataType::BigInt => "bigint".to_string(),
SQLType::Real => "real".to_string(), DataType::Real => "real".to_string(),
SQLType::Double => "double".to_string(), DataType::Double => "double".to_string(),
SQLType::Boolean => "boolean".to_string(), DataType::Boolean => "boolean".to_string(),
SQLType::Date => "date".to_string(), DataType::Date => "date".to_string(),
SQLType::Time => "time".to_string(), DataType::Time => "time".to_string(),
SQLType::Timestamp => "timestamp".to_string(), DataType::Timestamp => "timestamp".to_string(),
SQLType::Interval => "interval".to_string(), DataType::Interval => "interval".to_string(),
SQLType::Regclass => "regclass".to_string(), DataType::Regclass => "regclass".to_string(),
SQLType::Text => "text".to_string(), DataType::Text => "text".to_string(),
SQLType::Bytea => "bytea".to_string(), DataType::Bytea => "bytea".to_string(),
SQLType::Array(ty) => format!("{}[]", ty.to_string()), DataType::Array(ty) => format!("{}[]", ty.to_string()),
SQLType::Custom(ty) => ty.to_string(), DataType::Custom(ty) => ty.to_string(),
} }
} }
} }

View file

@ -1,6 +1,6 @@
//! AST types specific to CREATE/ALTER variants of `SQLStatement` //! AST types specific to CREATE/ALTER variants of `SQLStatement`
//! (commonly referred to as Data Definition Language, or DDL) //! (commonly referred to as Data Definition Language, or DDL)
use super::{Expr, SQLIdent, SQLObjectName, SQLType}; use super::{DataType, Expr, Ident, ObjectName};
/// An `ALTER TABLE` (`SQLStatement::SQLAlterTable`) operation /// An `ALTER TABLE` (`SQLStatement::SQLAlterTable`) operation
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
@ -8,7 +8,7 @@ pub enum AlterTableOperation {
/// `ADD <table_constraint>` /// `ADD <table_constraint>`
AddConstraint(TableConstraint), AddConstraint(TableConstraint),
/// TODO: implement `DROP CONSTRAINT <name>` /// TODO: implement `DROP CONSTRAINT <name>`
DropConstraint { name: SQLIdent }, DropConstraint { name: Ident },
} }
impl ToString for AlterTableOperation { impl ToString for AlterTableOperation {
@ -26,22 +26,22 @@ impl ToString for AlterTableOperation {
pub enum TableConstraint { pub enum TableConstraint {
/// `[ CONSTRAINT <name> ] { PRIMARY KEY | UNIQUE } (<columns>)` /// `[ CONSTRAINT <name> ] { PRIMARY KEY | UNIQUE } (<columns>)`
Unique { Unique {
name: Option<SQLIdent>, name: Option<Ident>,
columns: Vec<SQLIdent>, columns: Vec<Ident>,
/// Whether this is a `PRIMARY KEY` or just a `UNIQUE` constraint /// Whether this is a `PRIMARY KEY` or just a `UNIQUE` constraint
is_primary: bool, is_primary: bool,
}, },
/// A referential integrity constraint (`[ CONSTRAINT <name> ] FOREIGN KEY (<columns>) /// A referential integrity constraint (`[ CONSTRAINT <name> ] FOREIGN KEY (<columns>)
/// REFERENCES <foreign_table> (<referred_columns>)`) /// REFERENCES <foreign_table> (<referred_columns>)`)
ForeignKey { ForeignKey {
name: Option<SQLIdent>, name: Option<Ident>,
columns: Vec<SQLIdent>, columns: Vec<Ident>,
foreign_table: SQLObjectName, foreign_table: ObjectName,
referred_columns: Vec<SQLIdent>, referred_columns: Vec<Ident>,
}, },
/// `[ CONSTRAINT <name> ] CHECK (<expr>)` /// `[ CONSTRAINT <name> ] CHECK (<expr>)`
Check { Check {
name: Option<SQLIdent>, name: Option<Ident>,
expr: Box<Expr>, expr: Box<Expr>,
}, },
} }
@ -82,14 +82,14 @@ impl ToString for TableConstraint {
/// SQL column definition /// SQL column definition
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLColumnDef { pub struct ColumnDef {
pub name: SQLIdent, pub name: Ident,
pub data_type: SQLType, pub data_type: DataType,
pub collation: Option<SQLObjectName>, pub collation: Option<ObjectName>,
pub options: Vec<ColumnOptionDef>, pub options: Vec<ColumnOptionDef>,
} }
impl ToString for SQLColumnDef { impl ToString for ColumnDef {
fn to_string(&self) -> String { fn to_string(&self) -> String {
format!( format!(
"{} {}{}", "{} {}{}",
@ -122,7 +122,7 @@ impl ToString for SQLColumnDef {
/// "column options," and we allow any column option to be named. /// "column options," and we allow any column option to be named.
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct ColumnOptionDef { pub struct ColumnOptionDef {
pub name: Option<SQLIdent>, pub name: Option<Ident>,
pub option: ColumnOption, pub option: ColumnOption,
} }
@ -153,8 +153,8 @@ pub enum ColumnOption {
/// A referential integrity constraint (`[FOREIGN KEY REFERENCES /// A referential integrity constraint (`[FOREIGN KEY REFERENCES
/// <foreign_table> (<referred_columns>)`). /// <foreign_table> (<referred_columns>)`).
ForeignKey { ForeignKey {
foreign_table: SQLObjectName, foreign_table: ObjectName,
referred_columns: Vec<SQLIdent>, referred_columns: Vec<Ident>,
}, },
// `CHECK (<expr>)` // `CHECK (<expr>)`
Check(Expr), Check(Expr),
@ -187,7 +187,7 @@ impl ToString for ColumnOption {
} }
} }
fn format_constraint_name(name: &Option<SQLIdent>) -> String { fn format_constraint_name(name: &Option<Ident>) -> String {
name.as_ref() name.as_ref()
.map(|name| format!("CONSTRAINT {} ", name)) .map(|name| format!("CONSTRAINT {} ", name))
.unwrap_or_default() .unwrap_or_default()

View file

@ -12,23 +12,23 @@
//! SQL Abstract Syntax Tree (AST) types //! SQL Abstract Syntax Tree (AST) types
mod data_type;
mod ddl; mod ddl;
mod operator;
mod query; mod query;
mod sql_operator;
mod sqltype;
mod value; mod value;
use std::ops::Deref; use std::ops::Deref;
pub use self::data_type::DataType;
pub use self::ddl::{ pub use self::ddl::{
AlterTableOperation, ColumnOption, ColumnOptionDef, SQLColumnDef, TableConstraint, AlterTableOperation, ColumnDef, ColumnOption, ColumnOptionDef, TableConstraint,
}; };
pub use self::operator::{BinaryOperator, UnaryOperator};
pub use self::query::{ pub use self::query::{
Cte, Fetch, Join, JoinConstraint, JoinOperator, SQLOrderByExpr, SQLQuery, SQLSelect, Cte, Fetch, Join, JoinConstraint, JoinOperator, OrderByExpr, Query, Select, SelectItem,
SQLSelectItem, SQLSetExpr, SQLSetOperator, SQLValues, TableAlias, TableFactor, TableWithJoins, SetExpr, SetOperator, TableAlias, TableFactor, TableWithJoins, Values,
}; };
pub use self::sql_operator::{SQLBinaryOperator, SQLUnaryOperator};
pub use self::sqltype::SQLType;
pub use self::value::{SQLDateTimeField, Value}; pub use self::value::{SQLDateTimeField, Value};
/// Like `vec.join(", ")`, but for any types implementing ToString. /// Like `vec.join(", ")`, but for any types implementing ToString.
@ -45,7 +45,7 @@ where
} }
/// Identifier name, in the originally quoted form (e.g. `"id"`) /// Identifier name, in the originally quoted form (e.g. `"id"`)
pub type SQLIdent = String; pub type Ident = String;
/// An SQL expression of any type. /// An SQL expression of any type.
/// ///
@ -55,76 +55,76 @@ pub type SQLIdent = String;
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum Expr { pub enum Expr {
/// Identifier e.g. table name or column name /// Identifier e.g. table name or column name
SQLIdentifier(SQLIdent), Identifier(Ident),
/// Unqualified wildcard (`*`). SQL allows this in limited contexts, such as: /// Unqualified wildcard (`*`). SQL allows this in limited contexts, such as:
/// - right after `SELECT` (which is represented as a [SQLSelectItem::Wildcard] instead) /// - right after `SELECT` (which is represented as a [SQLSelectItem::Wildcard] instead)
/// - or as part of an aggregate function, e.g. `COUNT(*)`, /// - or as part of an aggregate function, e.g. `COUNT(*)`,
/// ///
/// ...but we currently also accept it in contexts where it doesn't make /// ...but we currently also accept it in contexts where it doesn't make
/// sense, such as `* + *` /// sense, such as `* + *`
SQLWildcard, Wildcard,
/// Qualified wildcard, e.g. `alias.*` or `schema.table.*`. /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
/// (Same caveats apply to SQLQualifiedWildcard as to SQLWildcard.) /// (Same caveats apply to SQLQualifiedWildcard as to SQLWildcard.)
SQLQualifiedWildcard(Vec<SQLIdent>), QualifiedWildcard(Vec<Ident>),
/// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col` /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
SQLCompoundIdentifier(Vec<SQLIdent>), CompoundIdentifier(Vec<Ident>),
/// `IS NULL` expression /// `IS NULL` expression
SQLIsNull(Box<Expr>), IsNull(Box<Expr>),
/// `IS NOT NULL` expression /// `IS NOT NULL` expression
SQLIsNotNull(Box<Expr>), IsNotNull(Box<Expr>),
/// `[ NOT ] IN (val1, val2, ...)` /// `[ NOT ] IN (val1, val2, ...)`
SQLInList { InList {
expr: Box<Expr>, expr: Box<Expr>,
list: Vec<Expr>, list: Vec<Expr>,
negated: bool, negated: bool,
}, },
/// `[ NOT ] IN (SELECT ...)` /// `[ NOT ] IN (SELECT ...)`
SQLInSubquery { InSubquery {
expr: Box<Expr>, expr: Box<Expr>,
subquery: Box<SQLQuery>, subquery: Box<Query>,
negated: bool, negated: bool,
}, },
/// `<expr> [ NOT ] BETWEEN <low> AND <high>` /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
SQLBetween { Between {
expr: Box<Expr>, expr: Box<Expr>,
negated: bool, negated: bool,
low: Box<Expr>, low: Box<Expr>,
high: Box<Expr>, high: Box<Expr>,
}, },
/// Binary operation e.g. `1 + 1` or `foo > bar` /// Binary operation e.g. `1 + 1` or `foo > bar`
SQLBinaryOp { BinaryOp {
left: Box<Expr>, left: Box<Expr>,
op: SQLBinaryOperator, op: BinaryOperator,
right: Box<Expr>, right: Box<Expr>,
}, },
/// Unary operation e.g. `NOT foo` /// Unary operation e.g. `NOT foo`
SQLUnaryOp { UnaryOp { op: UnaryOperator, expr: Box<Expr> },
op: SQLUnaryOperator,
expr: Box<Expr>,
},
/// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))` /// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
SQLCast { expr: Box<Expr>, data_type: SQLType }, Cast {
SQLExtract { expr: Box<Expr>,
data_type: DataType,
},
Extract {
field: SQLDateTimeField, field: SQLDateTimeField,
expr: Box<Expr>, expr: Box<Expr>,
}, },
/// `expr COLLATE collation` /// `expr COLLATE collation`
SQLCollate { Collate {
expr: Box<Expr>, expr: Box<Expr>,
collation: SQLObjectName, collation: ObjectName,
}, },
/// Nested expression e.g. `(foo > bar)` or `(1)` /// Nested expression e.g. `(foo > bar)` or `(1)`
SQLNested(Box<Expr>), Nested(Box<Expr>),
/// SQLValue /// SQLValue
SQLValue(Value), Value(Value),
/// Scalar function call e.g. `LEFT(foo, 5)` /// Scalar function call e.g. `LEFT(foo, 5)`
SQLFunction(SQLFunction), Function(Function),
/// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END` /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
/// ///
/// Note we only recognize a complete single expression as `<condition>`, /// Note we only recognize a complete single expression as `<condition>`,
/// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
/// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause> /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
SQLCase { Case {
operand: Option<Box<Expr>>, operand: Option<Box<Expr>>,
conditions: Vec<Expr>, conditions: Vec<Expr>,
results: Vec<Expr>, results: Vec<Expr>,
@ -132,22 +132,22 @@ pub enum Expr {
}, },
/// An exists expression `EXISTS(SELECT ...)`, used in expressions like /// An exists expression `EXISTS(SELECT ...)`, used in expressions like
/// `WHERE EXISTS (SELECT ...)`. /// `WHERE EXISTS (SELECT ...)`.
SQLExists(Box<SQLQuery>), Exists(Box<Query>),
/// A parenthesized subquery `(SELECT ...)`, used in expression like /// A parenthesized subquery `(SELECT ...)`, used in expression like
/// `SELECT (subquery) AS x` or `WHERE (subquery) = x` /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
SQLSubquery(Box<SQLQuery>), Subquery(Box<Query>),
} }
impl ToString for Expr { impl ToString for Expr {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
Expr::SQLIdentifier(s) => s.to_string(), Expr::Identifier(s) => s.to_string(),
Expr::SQLWildcard => "*".to_string(), Expr::Wildcard => "*".to_string(),
Expr::SQLQualifiedWildcard(q) => q.join(".") + ".*", Expr::QualifiedWildcard(q) => q.join(".") + ".*",
Expr::SQLCompoundIdentifier(s) => s.join("."), Expr::CompoundIdentifier(s) => s.join("."),
Expr::SQLIsNull(ast) => format!("{} IS NULL", ast.as_ref().to_string()), Expr::IsNull(ast) => format!("{} IS NULL", ast.as_ref().to_string()),
Expr::SQLIsNotNull(ast) => format!("{} IS NOT NULL", ast.as_ref().to_string()), Expr::IsNotNull(ast) => format!("{} IS NOT NULL", ast.as_ref().to_string()),
Expr::SQLInList { Expr::InList {
expr, expr,
list, list,
negated, negated,
@ -157,7 +157,7 @@ impl ToString for Expr {
if *negated { "NOT " } else { "" }, if *negated { "NOT " } else { "" },
comma_separated_string(list) comma_separated_string(list)
), ),
Expr::SQLInSubquery { Expr::InSubquery {
expr, expr,
subquery, subquery,
negated, negated,
@ -167,7 +167,7 @@ impl ToString for Expr {
if *negated { "NOT " } else { "" }, if *negated { "NOT " } else { "" },
subquery.to_string() subquery.to_string()
), ),
Expr::SQLBetween { Expr::Between {
expr, expr,
negated, negated,
low, low,
@ -179,32 +179,32 @@ impl ToString for Expr {
low.to_string(), low.to_string(),
high.to_string() high.to_string()
), ),
Expr::SQLBinaryOp { left, op, right } => format!( Expr::BinaryOp { left, op, right } => format!(
"{} {} {}", "{} {} {}",
left.as_ref().to_string(), left.as_ref().to_string(),
op.to_string(), op.to_string(),
right.as_ref().to_string() right.as_ref().to_string()
), ),
Expr::SQLUnaryOp { op, expr } => { Expr::UnaryOp { op, expr } => {
format!("{} {}", op.to_string(), expr.as_ref().to_string()) format!("{} {}", op.to_string(), expr.as_ref().to_string())
} }
Expr::SQLCast { expr, data_type } => format!( Expr::Cast { expr, data_type } => format!(
"CAST({} AS {})", "CAST({} AS {})",
expr.as_ref().to_string(), expr.as_ref().to_string(),
data_type.to_string() data_type.to_string()
), ),
Expr::SQLExtract { field, expr } => { Expr::Extract { field, expr } => {
format!("EXTRACT({} FROM {})", field.to_string(), expr.to_string()) format!("EXTRACT({} FROM {})", field.to_string(), expr.to_string())
} }
Expr::SQLCollate { expr, collation } => format!( Expr::Collate { expr, collation } => format!(
"{} COLLATE {}", "{} COLLATE {}",
expr.as_ref().to_string(), expr.as_ref().to_string(),
collation.to_string() collation.to_string()
), ),
Expr::SQLNested(ast) => format!("({})", ast.as_ref().to_string()), Expr::Nested(ast) => format!("({})", ast.as_ref().to_string()),
Expr::SQLValue(v) => v.to_string(), Expr::Value(v) => v.to_string(),
Expr::SQLFunction(f) => f.to_string(), Expr::Function(f) => f.to_string(),
Expr::SQLCase { Expr::Case {
operand, operand,
conditions, conditions,
results, results,
@ -225,21 +225,21 @@ impl ToString for Expr {
} }
s + " END" s + " END"
} }
Expr::SQLExists(s) => format!("EXISTS ({})", s.to_string()), Expr::Exists(s) => format!("EXISTS ({})", s.to_string()),
Expr::SQLSubquery(s) => format!("({})", s.to_string()), Expr::Subquery(s) => format!("({})", s.to_string()),
} }
} }
} }
/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`) /// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`)
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLWindowSpec { pub struct WindowSpec {
pub partition_by: Vec<Expr>, pub partition_by: Vec<Expr>,
pub order_by: Vec<SQLOrderByExpr>, pub order_by: Vec<OrderByExpr>,
pub window_frame: Option<SQLWindowFrame>, pub window_frame: Option<WindowFrame>,
} }
impl ToString for SQLWindowSpec { impl ToString for WindowSpec {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let mut clauses = vec![]; let mut clauses = vec![];
if !self.partition_by.is_empty() { if !self.partition_by.is_empty() {
@ -277,39 +277,39 @@ impl ToString for SQLWindowSpec {
/// Specifies the data processed by a window function, e.g. /// Specifies the data processed by a window function, e.g.
/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`. /// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLWindowFrame { pub struct WindowFrame {
pub units: SQLWindowFrameUnits, pub units: WindowFrameUnits,
pub start_bound: SQLWindowFrameBound, pub start_bound: WindowFrameBound,
/// The right bound of the `BETWEEN .. AND` clause. /// The right bound of the `BETWEEN .. AND` clause.
pub end_bound: Option<SQLWindowFrameBound>, pub end_bound: Option<WindowFrameBound>,
// TBD: EXCLUDE // TBD: EXCLUDE
} }
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLWindowFrameUnits { pub enum WindowFrameUnits {
Rows, Rows,
Range, Range,
Groups, Groups,
} }
impl ToString for SQLWindowFrameUnits { impl ToString for WindowFrameUnits {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
SQLWindowFrameUnits::Rows => "ROWS".to_string(), WindowFrameUnits::Rows => "ROWS".to_string(),
SQLWindowFrameUnits::Range => "RANGE".to_string(), WindowFrameUnits::Range => "RANGE".to_string(),
SQLWindowFrameUnits::Groups => "GROUPS".to_string(), WindowFrameUnits::Groups => "GROUPS".to_string(),
} }
} }
} }
impl FromStr for SQLWindowFrameUnits { impl FromStr for WindowFrameUnits {
type Err = ParserError; type Err = ParserError;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s { match s {
"ROWS" => Ok(SQLWindowFrameUnits::Rows), "ROWS" => Ok(WindowFrameUnits::Rows),
"RANGE" => Ok(SQLWindowFrameUnits::Range), "RANGE" => Ok(WindowFrameUnits::Range),
"GROUPS" => Ok(SQLWindowFrameUnits::Groups), "GROUPS" => Ok(WindowFrameUnits::Groups),
_ => Err(ParserError::ParserError(format!( _ => Err(ParserError::ParserError(format!(
"Expected ROWS, RANGE, or GROUPS, found: {}", "Expected ROWS, RANGE, or GROUPS, found: {}",
s s
@ -319,7 +319,7 @@ impl FromStr for SQLWindowFrameUnits {
} }
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLWindowFrameBound { pub enum WindowFrameBound {
/// "CURRENT ROW" /// "CURRENT ROW"
CurrentRow, CurrentRow,
/// "<N> PRECEDING" or "UNBOUNDED PRECEDING" /// "<N> PRECEDING" or "UNBOUNDED PRECEDING"
@ -329,14 +329,14 @@ pub enum SQLWindowFrameBound {
Following(Option<u64>), Following(Option<u64>),
} }
impl ToString for SQLWindowFrameBound { impl ToString for WindowFrameBound {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
SQLWindowFrameBound::CurrentRow => "CURRENT ROW".to_string(), WindowFrameBound::CurrentRow => "CURRENT ROW".to_string(),
SQLWindowFrameBound::Preceding(None) => "UNBOUNDED PRECEDING".to_string(), WindowFrameBound::Preceding(None) => "UNBOUNDED PRECEDING".to_string(),
SQLWindowFrameBound::Following(None) => "UNBOUNDED FOLLOWING".to_string(), WindowFrameBound::Following(None) => "UNBOUNDED FOLLOWING".to_string(),
SQLWindowFrameBound::Preceding(Some(n)) => format!("{} PRECEDING", n), WindowFrameBound::Preceding(Some(n)) => format!("{} PRECEDING", n),
SQLWindowFrameBound::Following(Some(n)) => format!("{} FOLLOWING", n), WindowFrameBound::Following(Some(n)) => format!("{} FOLLOWING", n),
} }
} }
} }
@ -344,91 +344,91 @@ impl ToString for SQLWindowFrameBound {
/// A top-level statement (SELECT, INSERT, CREATE, etc.) /// A top-level statement (SELECT, INSERT, CREATE, etc.)
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLStatement { pub enum Statement {
/// SELECT /// SELECT
SQLQuery(Box<SQLQuery>), Query(Box<Query>),
/// INSERT /// INSERT
SQLInsert { Insert {
/// TABLE /// TABLE
table_name: SQLObjectName, table_name: ObjectName,
/// COLUMNS /// COLUMNS
columns: Vec<SQLIdent>, columns: Vec<Ident>,
/// A SQL query that specifies what to insert /// A SQL query that specifies what to insert
source: Box<SQLQuery>, source: Box<Query>,
}, },
SQLCopy { Copy {
/// TABLE /// TABLE
table_name: SQLObjectName, table_name: ObjectName,
/// COLUMNS /// COLUMNS
columns: Vec<SQLIdent>, columns: Vec<Ident>,
/// VALUES a vector of values to be copied /// VALUES a vector of values to be copied
values: Vec<Option<String>>, values: Vec<Option<String>>,
}, },
/// UPDATE /// UPDATE
SQLUpdate { Update {
/// TABLE /// TABLE
table_name: SQLObjectName, table_name: ObjectName,
/// Column assignments /// Column assignments
assignments: Vec<SQLAssignment>, assignments: Vec<Assignment>,
/// WHERE /// WHERE
selection: Option<Expr>, selection: Option<Expr>,
}, },
/// DELETE /// DELETE
SQLDelete { Delete {
/// FROM /// FROM
table_name: SQLObjectName, table_name: ObjectName,
/// WHERE /// WHERE
selection: Option<Expr>, selection: Option<Expr>,
}, },
/// CREATE VIEW /// CREATE VIEW
SQLCreateView { CreateView {
/// View name /// View name
name: SQLObjectName, name: ObjectName,
columns: Vec<SQLIdent>, columns: Vec<Ident>,
query: Box<SQLQuery>, query: Box<Query>,
materialized: bool, materialized: bool,
with_options: Vec<SQLOption>, with_options: Vec<SqlOption>,
}, },
/// CREATE TABLE /// CREATE TABLE
SQLCreateTable { CreateTable {
/// Table name /// Table name
name: SQLObjectName, name: ObjectName,
/// Optional schema /// Optional schema
columns: Vec<SQLColumnDef>, columns: Vec<ColumnDef>,
constraints: Vec<TableConstraint>, constraints: Vec<TableConstraint>,
with_options: Vec<SQLOption>, with_options: Vec<SqlOption>,
external: bool, external: bool,
file_format: Option<FileFormat>, file_format: Option<FileFormat>,
location: Option<String>, location: Option<String>,
}, },
/// ALTER TABLE /// ALTER TABLE
SQLAlterTable { AlterTable {
/// Table name /// Table name
name: SQLObjectName, name: ObjectName,
operation: AlterTableOperation, operation: AlterTableOperation,
}, },
/// DROP TABLE /// DROP TABLE
SQLDrop { Drop {
object_type: SQLObjectType, object_type: ObjectType,
if_exists: bool, if_exists: bool,
names: Vec<SQLObjectName>, names: Vec<ObjectName>,
cascade: bool, cascade: bool,
}, },
/// `{ BEGIN [ TRANSACTION | WORK ] | START TRANSACTION } ...` /// `{ BEGIN [ TRANSACTION | WORK ] | START TRANSACTION } ...`
SQLStartTransaction { modes: Vec<TransactionMode> }, StartTransaction { modes: Vec<TransactionMode> },
/// `SET TRANSACTION ...` /// `SET TRANSACTION ...`
SQLSetTransaction { modes: Vec<TransactionMode> }, SetTransaction { modes: Vec<TransactionMode> },
/// `COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]` /// `COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
SQLCommit { chain: bool }, Commit { chain: bool },
/// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]` /// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
SQLRollback { chain: bool }, Rollback { chain: bool },
} }
impl ToString for SQLStatement { impl ToString for Statement {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
SQLStatement::SQLQuery(s) => s.to_string(), Statement::Query(s) => s.to_string(),
SQLStatement::SQLInsert { Statement::Insert {
table_name, table_name,
columns, columns,
source, source,
@ -440,7 +440,7 @@ impl ToString for SQLStatement {
s += &source.to_string(); s += &source.to_string();
s s
} }
SQLStatement::SQLCopy { Statement::Copy {
table_name, table_name,
columns, columns,
values, values,
@ -463,7 +463,7 @@ impl ToString for SQLStatement {
s += "\n\\."; s += "\n\\.";
s s
} }
SQLStatement::SQLUpdate { Statement::Update {
table_name, table_name,
assignments, assignments,
selection, selection,
@ -478,7 +478,7 @@ impl ToString for SQLStatement {
} }
s s
} }
SQLStatement::SQLDelete { Statement::Delete {
table_name, table_name,
selection, selection,
} => { } => {
@ -488,7 +488,7 @@ impl ToString for SQLStatement {
} }
s s
} }
SQLStatement::SQLCreateView { Statement::CreateView {
name, name,
columns, columns,
query, query,
@ -515,7 +515,7 @@ impl ToString for SQLStatement {
query.to_string(), query.to_string(),
) )
} }
SQLStatement::SQLCreateTable { Statement::CreateTable {
name, name,
columns, columns,
constraints, constraints,
@ -546,10 +546,10 @@ impl ToString for SQLStatement {
} }
s s
} }
SQLStatement::SQLAlterTable { name, operation } => { Statement::AlterTable { name, operation } => {
format!("ALTER TABLE {} {}", name.to_string(), operation.to_string()) format!("ALTER TABLE {} {}", name.to_string(), operation.to_string())
} }
SQLStatement::SQLDrop { Statement::Drop {
object_type, object_type,
if_exists, if_exists,
names, names,
@ -561,7 +561,7 @@ impl ToString for SQLStatement {
comma_separated_string(names), comma_separated_string(names),
if *cascade { " CASCADE" } else { "" }, if *cascade { " CASCADE" } else { "" },
), ),
SQLStatement::SQLStartTransaction { modes } => format!( Statement::StartTransaction { modes } => format!(
"START TRANSACTION{}", "START TRANSACTION{}",
if modes.is_empty() { if modes.is_empty() {
"".into() "".into()
@ -569,7 +569,7 @@ impl ToString for SQLStatement {
format!(" {}", comma_separated_string(modes)) format!(" {}", comma_separated_string(modes))
} }
), ),
SQLStatement::SQLSetTransaction { modes } => format!( Statement::SetTransaction { modes } => format!(
"SET TRANSACTION{}", "SET TRANSACTION{}",
if modes.is_empty() { if modes.is_empty() {
"".into() "".into()
@ -577,10 +577,10 @@ impl ToString for SQLStatement {
format!(" {}", comma_separated_string(modes)) format!(" {}", comma_separated_string(modes))
} }
), ),
SQLStatement::SQLCommit { chain } => { Statement::Commit { chain } => {
format!("COMMIT{}", if *chain { " AND CHAIN" } else { "" },) format!("COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
} }
SQLStatement::SQLRollback { chain } => { Statement::Rollback { chain } => {
format!("ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },) format!("ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
} }
} }
@ -589,9 +589,9 @@ impl ToString for SQLStatement {
/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj /// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLObjectName(pub Vec<SQLIdent>); pub struct ObjectName(pub Vec<Ident>);
impl ToString for SQLObjectName { impl ToString for ObjectName {
fn to_string(&self) -> String { fn to_string(&self) -> String {
self.0.join(".") self.0.join(".")
} }
@ -599,12 +599,12 @@ impl ToString for SQLObjectName {
/// SQL assignment `foo = expr` as used in SQLUpdate /// SQL assignment `foo = expr` as used in SQLUpdate
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLAssignment { pub struct Assignment {
pub id: SQLIdent, pub id: Ident,
pub value: Expr, pub value: Expr,
} }
impl ToString for SQLAssignment { impl ToString for Assignment {
fn to_string(&self) -> String { fn to_string(&self) -> String {
format!("{} = {}", self.id, self.value.to_string()) format!("{} = {}", self.id, self.value.to_string())
} }
@ -612,15 +612,15 @@ impl ToString for SQLAssignment {
/// SQL function /// SQL function
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLFunction { pub struct Function {
pub name: SQLObjectName, pub name: ObjectName,
pub args: Vec<Expr>, pub args: Vec<Expr>,
pub over: Option<SQLWindowSpec>, pub over: Option<WindowSpec>,
// aggregate functions may specify eg `COUNT(DISTINCT x)` // aggregate functions may specify eg `COUNT(DISTINCT x)`
pub distinct: bool, pub distinct: bool,
} }
impl ToString for SQLFunction { impl ToString for Function {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let mut s = format!( let mut s = format!(
"{}({}{})", "{}({}{})",
@ -662,7 +662,7 @@ impl ToString for FileFormat {
} }
} }
use crate::sqlparser::ParserError; use crate::parser::ParserError;
use std::str::FromStr; use std::str::FromStr;
impl FromStr for FileFormat { impl FromStr for FileFormat {
type Err = ParserError; type Err = ParserError;
@ -686,27 +686,27 @@ impl FromStr for FileFormat {
} }
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLObjectType { pub enum ObjectType {
Table, Table,
View, View,
} }
impl SQLObjectType { impl ObjectType {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
SQLObjectType::Table => "TABLE".into(), ObjectType::Table => "TABLE".into(),
SQLObjectType::View => "VIEW".into(), ObjectType::View => "VIEW".into(),
} }
} }
} }
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLOption { pub struct SqlOption {
pub name: SQLIdent, pub name: Ident,
pub value: Value, pub value: Value,
} }
impl ToString for SQLOption { impl ToString for SqlOption {
fn to_string(&self) -> String { fn to_string(&self) -> String {
format!("{} = {}", self.name.to_string(), self.value.to_string()) format!("{} = {}", self.name.to_string(), self.value.to_string())
} }

71
src/ast/operator.rs Normal file
View file

@ -0,0 +1,71 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Unary operators
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum UnaryOperator {
Plus,
Minus,
Not,
}
impl ToString for UnaryOperator {
fn to_string(&self) -> String {
match self {
UnaryOperator::Plus => "+".to_string(),
UnaryOperator::Minus => "-".to_string(),
UnaryOperator::Not => "NOT".to_string(),
}
}
}
/// Binary operators
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum BinaryOperator {
Plus,
Minus,
Multiply,
Divide,
Modulus,
Gt,
Lt,
GtEq,
LtEq,
Eq,
NotEq,
And,
Or,
Like,
NotLike,
}
impl ToString for BinaryOperator {
fn to_string(&self) -> String {
match self {
BinaryOperator::Plus => "+".to_string(),
BinaryOperator::Minus => "-".to_string(),
BinaryOperator::Multiply => "*".to_string(),
BinaryOperator::Divide => "/".to_string(),
BinaryOperator::Modulus => "%".to_string(),
BinaryOperator::Gt => ">".to_string(),
BinaryOperator::Lt => "<".to_string(),
BinaryOperator::GtEq => ">=".to_string(),
BinaryOperator::LtEq => "<=".to_string(),
BinaryOperator::Eq => "=".to_string(),
BinaryOperator::NotEq => "<>".to_string(),
BinaryOperator::And => "AND".to_string(),
BinaryOperator::Or => "OR".to_string(),
BinaryOperator::Like => "LIKE".to_string(),
BinaryOperator::NotLike => "NOT LIKE".to_string(),
}
}
}

View file

@ -15,13 +15,13 @@ use super::*;
/// The most complete variant of a `SELECT` query expression, optionally /// The most complete variant of a `SELECT` query expression, optionally
/// including `WITH`, `UNION` / other set operations, and `ORDER BY`. /// including `WITH`, `UNION` / other set operations, and `ORDER BY`.
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLQuery { pub struct Query {
/// WITH (common table expressions, or CTEs) /// WITH (common table expressions, or CTEs)
pub ctes: Vec<Cte>, pub ctes: Vec<Cte>,
/// SELECT or UNION / EXCEPT / INTECEPT /// SELECT or UNION / EXCEPT / INTECEPT
pub body: SQLSetExpr, pub body: SetExpr,
/// ORDER BY /// ORDER BY
pub order_by: Vec<SQLOrderByExpr>, pub order_by: Vec<OrderByExpr>,
/// `LIMIT { <N> | ALL }` /// `LIMIT { <N> | ALL }`
pub limit: Option<Expr>, pub limit: Option<Expr>,
/// `OFFSET <N> { ROW | ROWS }` /// `OFFSET <N> { ROW | ROWS }`
@ -30,7 +30,7 @@ pub struct SQLQuery {
pub fetch: Option<Fetch>, pub fetch: Option<Fetch>,
} }
impl ToString for SQLQuery { impl ToString for Query {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let mut s = String::new(); let mut s = String::new();
if !self.ctes.is_empty() { if !self.ctes.is_empty() {
@ -57,30 +57,30 @@ impl ToString for SQLQuery {
/// A node in a tree, representing a "query body" expression, roughly: /// A node in a tree, representing a "query body" expression, roughly:
/// `SELECT ... [ {UNION|EXCEPT|INTERSECT} SELECT ...]` /// `SELECT ... [ {UNION|EXCEPT|INTERSECT} SELECT ...]`
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLSetExpr { pub enum SetExpr {
/// Restricted SELECT .. FROM .. HAVING (no ORDER BY or set operations) /// Restricted SELECT .. FROM .. HAVING (no ORDER BY or set operations)
Select(Box<SQLSelect>), Select(Box<Select>),
/// Parenthesized SELECT subquery, which may include more set operations /// Parenthesized SELECT subquery, which may include more set operations
/// in its body and an optional ORDER BY / LIMIT. /// in its body and an optional ORDER BY / LIMIT.
Query(Box<SQLQuery>), Query(Box<Query>),
/// UNION/EXCEPT/INTERSECT of two queries /// UNION/EXCEPT/INTERSECT of two queries
SetOperation { SetOperation {
op: SQLSetOperator, op: SetOperator,
all: bool, all: bool,
left: Box<SQLSetExpr>, left: Box<SetExpr>,
right: Box<SQLSetExpr>, right: Box<SetExpr>,
}, },
Values(SQLValues), Values(Values),
// TODO: ANSI SQL supports `TABLE` here. // TODO: ANSI SQL supports `TABLE` here.
} }
impl ToString for SQLSetExpr { impl ToString for SetExpr {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
SQLSetExpr::Select(s) => s.to_string(), SetExpr::Select(s) => s.to_string(),
SQLSetExpr::Query(q) => format!("({})", q.to_string()), SetExpr::Query(q) => format!("({})", q.to_string()),
SQLSetExpr::Values(v) => v.to_string(), SetExpr::Values(v) => v.to_string(),
SQLSetExpr::SetOperation { SetExpr::SetOperation {
left, left,
right, right,
op, op,
@ -100,18 +100,18 @@ impl ToString for SQLSetExpr {
} }
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLSetOperator { pub enum SetOperator {
Union, Union,
Except, Except,
Intersect, Intersect,
} }
impl ToString for SQLSetOperator { impl ToString for SetOperator {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
SQLSetOperator::Union => "UNION".to_string(), SetOperator::Union => "UNION".to_string(),
SQLSetOperator::Except => "EXCEPT".to_string(), SetOperator::Except => "EXCEPT".to_string(),
SQLSetOperator::Intersect => "INTERSECT".to_string(), SetOperator::Intersect => "INTERSECT".to_string(),
} }
} }
} }
@ -120,10 +120,10 @@ impl ToString for SQLSetOperator {
/// appear either as the only body item of an `SQLQuery`, or as an operand /// appear either as the only body item of an `SQLQuery`, or as an operand
/// to a set operation like `UNION`. /// to a set operation like `UNION`.
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLSelect { pub struct Select {
pub distinct: bool, pub distinct: bool,
/// projection expressions /// projection expressions
pub projection: Vec<SQLSelectItem>, pub projection: Vec<SelectItem>,
/// FROM /// FROM
pub from: Vec<TableWithJoins>, pub from: Vec<TableWithJoins>,
/// WHERE /// WHERE
@ -134,7 +134,7 @@ pub struct SQLSelect {
pub having: Option<Expr>, pub having: Option<Expr>,
} }
impl ToString for SQLSelect { impl ToString for Select {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let mut s = format!( let mut s = format!(
"SELECT{} {}", "SELECT{} {}",
@ -164,7 +164,7 @@ impl ToString for SQLSelect {
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct Cte { pub struct Cte {
pub alias: TableAlias, pub alias: TableAlias,
pub query: SQLQuery, pub query: Query,
} }
impl ToString for Cte { impl ToString for Cte {
@ -175,26 +175,26 @@ impl ToString for Cte {
/// One item of the comma-separated list following `SELECT` /// One item of the comma-separated list following `SELECT`
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLSelectItem { pub enum SelectItem {
/// Any expression, not followed by `[ AS ] alias` /// Any expression, not followed by `[ AS ] alias`
UnnamedExpr(Expr), UnnamedExpr(Expr),
/// An expression, followed by `[ AS ] alias` /// An expression, followed by `[ AS ] alias`
ExprWithAlias { expr: Expr, alias: SQLIdent }, ExprWithAlias { expr: Expr, alias: Ident },
/// `alias.*` or even `schema.table.*` /// `alias.*` or even `schema.table.*`
QualifiedWildcard(SQLObjectName), QualifiedWildcard(ObjectName),
/// An unqualified `*` /// An unqualified `*`
Wildcard, Wildcard,
} }
impl ToString for SQLSelectItem { impl ToString for SelectItem {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match &self { match &self {
SQLSelectItem::UnnamedExpr(expr) => expr.to_string(), SelectItem::UnnamedExpr(expr) => expr.to_string(),
SQLSelectItem::ExprWithAlias { expr, alias } => { SelectItem::ExprWithAlias { expr, alias } => {
format!("{} AS {}", expr.to_string(), alias) format!("{} AS {}", expr.to_string(), alias)
} }
SQLSelectItem::QualifiedWildcard(prefix) => format!("{}.*", prefix.to_string()), SelectItem::QualifiedWildcard(prefix) => format!("{}.*", prefix.to_string()),
SQLSelectItem::Wildcard => "*".to_string(), SelectItem::Wildcard => "*".to_string(),
} }
} }
} }
@ -219,7 +219,7 @@ impl ToString for TableWithJoins {
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum TableFactor { pub enum TableFactor {
Table { Table {
name: SQLObjectName, name: ObjectName,
alias: Option<TableAlias>, alias: Option<TableAlias>,
/// Arguments of a table-valued function, as supported by Postgres /// Arguments of a table-valued function, as supported by Postgres
/// and MSSQL. Note that deprecated MSSQL `FROM foo (NOLOCK)` syntax /// and MSSQL. Note that deprecated MSSQL `FROM foo (NOLOCK)` syntax
@ -230,7 +230,7 @@ pub enum TableFactor {
}, },
Derived { Derived {
lateral: bool, lateral: bool,
subquery: Box<SQLQuery>, subquery: Box<Query>,
alias: Option<TableAlias>, alias: Option<TableAlias>,
}, },
/// Represents a parenthesized join expression, such as /// Represents a parenthesized join expression, such as
@ -285,8 +285,8 @@ impl ToString for TableFactor {
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct TableAlias { pub struct TableAlias {
pub name: SQLIdent, pub name: Ident,
pub columns: Vec<SQLIdent>, pub columns: Vec<Ident>,
} }
impl ToString for TableAlias { impl ToString for TableAlias {
@ -368,18 +368,18 @@ pub enum JoinOperator {
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub enum JoinConstraint { pub enum JoinConstraint {
On(Expr), On(Expr),
Using(Vec<SQLIdent>), Using(Vec<Ident>),
Natural, Natural,
} }
/// SQL ORDER BY expression /// SQL ORDER BY expression
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLOrderByExpr { pub struct OrderByExpr {
pub expr: Expr, pub expr: Expr,
pub asc: Option<bool>, pub asc: Option<bool>,
} }
impl ToString for SQLOrderByExpr { impl ToString for OrderByExpr {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self.asc { match self.asc {
Some(true) => format!("{} ASC", self.expr.to_string()), Some(true) => format!("{} ASC", self.expr.to_string()),
@ -414,9 +414,9 @@ impl ToString for Fetch {
} }
#[derive(Debug, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct SQLValues(pub Vec<Vec<Expr>>); pub struct Values(pub Vec<Vec<Expr>>);
impl ToString for SQLValues { impl ToString for Values {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let rows = self let rows = self
.0 .0

View file

@ -13,9 +13,9 @@
use crate::dialect::Dialect; use crate::dialect::Dialect;
#[derive(Debug)] #[derive(Debug)]
pub struct AnsiSqlDialect {} pub struct AnsiDialect {}
impl Dialect for AnsiSqlDialect { impl Dialect for AnsiDialect {
fn is_identifier_start(&self, ch: char) -> bool { fn is_identifier_start(&self, ch: char) -> bool {
(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
} }

View file

@ -13,9 +13,9 @@
use crate::dialect::Dialect; use crate::dialect::Dialect;
#[derive(Debug)] #[derive(Debug)]
pub struct GenericSqlDialect {} pub struct GenericDialect {}
impl Dialect for GenericSqlDialect { impl Dialect for GenericDialect {
fn is_identifier_start(&self, ch: char) -> bool { fn is_identifier_start(&self, ch: char) -> bool {
(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' || ch == '#' || ch == '@' (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' || ch == '#' || ch == '@'
} }

View file

@ -10,16 +10,16 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
mod ansi_sql; mod ansi;
mod generic_sql; mod generic;
pub mod keywords; pub mod keywords;
mod mssql; mod mssql;
mod postgresql; mod postgresql;
use std::fmt::Debug; use std::fmt::Debug;
pub use self::ansi_sql::AnsiSqlDialect; pub use self::ansi::AnsiDialect;
pub use self::generic_sql::GenericSqlDialect; pub use self::generic::GenericDialect;
pub use self::mssql::MsSqlDialect; pub use self::mssql::MsSqlDialect;
pub use self::postgresql::PostgreSqlDialect; pub use self::postgresql::PostgreSqlDialect;

View file

@ -18,10 +18,10 @@
//! Syntax Tree (AST). //! Syntax Tree (AST).
//! //!
//! ``` //! ```
//! use sqlparser::dialect::GenericSqlDialect; //! use sqlparser::dialect::GenericDialect;
//! use sqlparser::sqlparser::Parser; //! use sqlparser::parser::Parser;
//! //!
//! let dialect = GenericSqlDialect {}; // or AnsiSqlDialect //! let dialect = GenericDialect {}; // or AnsiSqlDialect
//! //!
//! let sql = "SELECT a, b, 123, myfunc(b) \ //! let sql = "SELECT a, b, 123, myfunc(b) \
//! FROM table_1 \ //! FROM table_1 \
@ -34,10 +34,10 @@
//! ``` //! ```
#![warn(clippy::all)] #![warn(clippy::all)]
pub mod ast;
pub mod dialect; pub mod dialect;
pub mod sqlast; pub mod parser;
pub mod sqlparser; pub mod tokenizer;
pub mod sqltokenizer;
#[doc(hidden)] #[doc(hidden)]
// This is required to make utilities accessible by both the crate-internal // This is required to make utilities accessible by both the crate-internal

File diff suppressed because it is too large Load diff

View file

@ -1,71 +0,0 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Unary operators
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLUnaryOperator {
Plus,
Minus,
Not,
}
impl ToString for SQLUnaryOperator {
fn to_string(&self) -> String {
match self {
SQLUnaryOperator::Plus => "+".to_string(),
SQLUnaryOperator::Minus => "-".to_string(),
SQLUnaryOperator::Not => "NOT".to_string(),
}
}
}
/// Binary operators
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum SQLBinaryOperator {
Plus,
Minus,
Multiply,
Divide,
Modulus,
Gt,
Lt,
GtEq,
LtEq,
Eq,
NotEq,
And,
Or,
Like,
NotLike,
}
impl ToString for SQLBinaryOperator {
fn to_string(&self) -> String {
match self {
SQLBinaryOperator::Plus => "+".to_string(),
SQLBinaryOperator::Minus => "-".to_string(),
SQLBinaryOperator::Multiply => "*".to_string(),
SQLBinaryOperator::Divide => "/".to_string(),
SQLBinaryOperator::Modulus => "%".to_string(),
SQLBinaryOperator::Gt => ">".to_string(),
SQLBinaryOperator::Lt => "<".to_string(),
SQLBinaryOperator::GtEq => ">=".to_string(),
SQLBinaryOperator::LtEq => "<=".to_string(),
SQLBinaryOperator::Eq => "=".to_string(),
SQLBinaryOperator::NotEq => "<>".to_string(),
SQLBinaryOperator::And => "AND".to_string(),
SQLBinaryOperator::Or => "OR".to_string(),
SQLBinaryOperator::Like => "LIKE".to_string(),
SQLBinaryOperator::NotLike => "NOT LIKE".to_string(),
}
}
}

View file

@ -12,10 +12,10 @@
use std::fmt::Debug; use std::fmt::Debug;
use super::ast::*;
use super::dialect::*; use super::dialect::*;
use super::sqlast::*; use super::parser::{Parser, ParserError};
use super::sqlparser::{Parser, ParserError}; use super::tokenizer::Tokenizer;
use super::sqltokenizer::Tokenizer;
/// Tests use the methods on this struct to invoke the parser on one or /// Tests use the methods on this struct to invoke the parser on one or
/// multiple dialects. /// multiple dialects.
@ -57,7 +57,7 @@ impl TestedDialects {
}) })
} }
pub fn parse_sql_statements(&self, sql: &str) -> Result<Vec<SQLStatement>, ParserError> { pub fn parse_sql_statements(&self, sql: &str) -> Result<Vec<Statement>, ParserError> {
self.one_of_identical_results(|dialect| Parser::parse_sql(dialect, sql.to_string())) self.one_of_identical_results(|dialect| Parser::parse_sql(dialect, sql.to_string()))
// To fail the `ensure_multiple_dialects_are_tested` test: // To fail the `ensure_multiple_dialects_are_tested` test:
// Parser::parse_sql(&**self.dialects.first().unwrap(), sql.to_string()) // Parser::parse_sql(&**self.dialects.first().unwrap(), sql.to_string())
@ -66,7 +66,7 @@ impl TestedDialects {
/// Ensures that `sql` parses as a single statement, optionally checking /// Ensures that `sql` parses as a single statement, optionally checking
/// that converting AST back to string equals to `canonical` (unless an /// that converting AST back to string equals to `canonical` (unless an
/// empty canonical string is provided). /// empty canonical string is provided).
pub fn one_statement_parses_to(&self, sql: &str, canonical: &str) -> SQLStatement { pub fn one_statement_parses_to(&self, sql: &str, canonical: &str) -> Statement {
let mut statements = self.parse_sql_statements(&sql).unwrap(); let mut statements = self.parse_sql_statements(&sql).unwrap();
assert_eq!(statements.len(), 1); assert_eq!(statements.len(), 1);
@ -79,24 +79,24 @@ impl TestedDialects {
/// Ensures that `sql` parses as a single SQLStatement, and is not modified /// Ensures that `sql` parses as a single SQLStatement, and is not modified
/// after a serialization round-trip. /// after a serialization round-trip.
pub fn verified_stmt(&self, query: &str) -> SQLStatement { pub fn verified_stmt(&self, query: &str) -> Statement {
self.one_statement_parses_to(query, query) self.one_statement_parses_to(query, query)
} }
/// Ensures that `sql` parses as a single SQLQuery, and is not modified /// Ensures that `sql` parses as a single SQLQuery, and is not modified
/// after a serialization round-trip. /// after a serialization round-trip.
pub fn verified_query(&self, sql: &str) -> SQLQuery { pub fn verified_query(&self, sql: &str) -> Query {
match self.verified_stmt(sql) { match self.verified_stmt(sql) {
SQLStatement::SQLQuery(query) => *query, Statement::Query(query) => *query,
_ => panic!("Expected SQLQuery"), _ => panic!("Expected SQLQuery"),
} }
} }
/// Ensures that `sql` parses as a single SQLSelect, and is not modified /// Ensures that `sql` parses as a single SQLSelect, and is not modified
/// after a serialization round-trip. /// after a serialization round-trip.
pub fn verified_only_select(&self, query: &str) -> SQLSelect { pub fn verified_only_select(&self, query: &str) -> Select {
match self.verified_query(query).body { match self.verified_query(query).body {
SQLSetExpr::Select(s) => *s, SetExpr::Select(s) => *s,
_ => panic!("Expected SQLSetExpr::Select"), _ => panic!("Expected SQLSetExpr::Select"),
} }
} }
@ -113,10 +113,10 @@ impl TestedDialects {
pub fn all_dialects() -> TestedDialects { pub fn all_dialects() -> TestedDialects {
TestedDialects { TestedDialects {
dialects: vec![ dialects: vec![
Box::new(GenericSqlDialect {}), Box::new(GenericDialect {}),
Box::new(PostgreSqlDialect {}), Box::new(PostgreSqlDialect {}),
Box::new(MsSqlDialect {}), Box::new(MsSqlDialect {}),
Box::new(AnsiSqlDialect {}), Box::new(AnsiDialect {}),
], ],
} }
} }
@ -130,9 +130,9 @@ pub fn only<T>(v: impl IntoIterator<Item = T>) -> T {
} }
} }
pub fn expr_from_projection(item: &SQLSelectItem) -> &Expr { pub fn expr_from_projection(item: &SelectItem) -> &Expr {
match item { match item {
SQLSelectItem::UnnamedExpr(expr) => expr, SelectItem::UnnamedExpr(expr) => expr,
_ => panic!("Expected UnnamedExpr"), _ => panic!("Expected UnnamedExpr"),
} }
} }

View file

@ -26,7 +26,7 @@ use super::dialect::Dialect;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Token { pub enum Token {
/// A keyword (like SELECT) or an optionally quoted SQL identifier /// A keyword (like SELECT) or an optionally quoted SQL identifier
SQLWord(SQLWord), Word(Word),
/// An unsigned numeric literal /// An unsigned numeric literal
Number(String), Number(String),
/// A character that could not be tokenized /// A character that could not be tokenized
@ -92,7 +92,7 @@ pub enum Token {
impl ToString for Token { impl ToString for Token {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
Token::SQLWord(ref w) => w.to_string(), Token::Word(ref w) => w.to_string(),
Token::Number(ref n) => n.to_string(), Token::Number(ref n) => n.to_string(),
Token::Char(ref c) => c.to_string(), Token::Char(ref c) => c.to_string(),
Token::SingleQuotedString(ref s) => format!("'{}'", s), Token::SingleQuotedString(ref s) => format!("'{}'", s),
@ -137,7 +137,7 @@ impl Token {
// not fast but I want the simplicity for now while I experiment with pluggable // not fast but I want the simplicity for now while I experiment with pluggable
// dialects // dialects
let is_keyword = quote_style == None && ALL_KEYWORDS.contains(&word_uppercase.as_str()); let is_keyword = quote_style == None && ALL_KEYWORDS.contains(&word_uppercase.as_str());
Token::SQLWord(SQLWord { Token::Word(Word {
value: word.to_string(), value: word.to_string(),
quote_style, quote_style,
keyword: if is_keyword { keyword: if is_keyword {
@ -151,7 +151,7 @@ impl Token {
/// A keyword (like SELECT) or an optionally quoted SQL identifier /// A keyword (like SELECT) or an optionally quoted SQL identifier
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct SQLWord { pub struct Word {
/// The value of the token, without the enclosing quotes, and with the /// The value of the token, without the enclosing quotes, and with the
/// escape sequences (if any) processed (TODO: escapes are not handled) /// escape sequences (if any) processed (TODO: escapes are not handled)
pub value: String, pub value: String,
@ -164,18 +164,18 @@ pub struct SQLWord {
pub keyword: String, pub keyword: String,
} }
impl ToString for SQLWord { impl ToString for Word {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self.quote_style { match self.quote_style {
Some(s) if s == '"' || s == '[' || s == '`' => { Some(s) if s == '"' || s == '[' || s == '`' => {
format!("{}{}{}", s, self.value, SQLWord::matching_end_quote(s)) format!("{}{}{}", s, self.value, Word::matching_end_quote(s))
} }
None => self.value.clone(), None => self.value.clone(),
_ => panic!("Unexpected quote_style!"), _ => panic!("Unexpected quote_style!"),
} }
} }
} }
impl SQLWord { impl Word {
fn matching_end_quote(ch: char) -> char { fn matching_end_quote(ch: char) -> char {
match ch { match ch {
'"' => '"', // ANSI and most dialects '"' => '"', // ANSI and most dialects
@ -244,8 +244,8 @@ impl<'a> Tokenizer<'a> {
} }
Token::Whitespace(Whitespace::Tab) => self.col += 4, Token::Whitespace(Whitespace::Tab) => self.col += 4,
Token::SQLWord(w) if w.quote_style == None => self.col += w.value.len() as u64, Token::Word(w) if w.quote_style == None => self.col += w.value.len() as u64,
Token::SQLWord(w) if w.quote_style != None => self.col += w.value.len() as u64 + 2, Token::Word(w) if w.quote_style != None => self.col += w.value.len() as u64 + 2,
Token::Number(s) => self.col += s.len() as u64, Token::Number(s) => self.col += s.len() as u64,
Token::SingleQuotedString(s) => self.col += s.len() as u64, Token::SingleQuotedString(s) => self.col += s.len() as u64,
_ => self.col += 1, _ => self.col += 1,
@ -318,7 +318,7 @@ impl<'a> Tokenizer<'a> {
// delimited (quoted) identifier // delimited (quoted) identifier
quote_start if self.dialect.is_delimited_identifier_start(quote_start) => { quote_start if self.dialect.is_delimited_identifier_start(quote_start) => {
chars.next(); // consume the opening quote chars.next(); // consume the opening quote
let quote_end = SQLWord::matching_end_quote(quote_start); let quote_end = Word::matching_end_quote(quote_start);
let s = peeking_take_while(chars, |ch| ch != quote_end); let s = peeking_take_while(chars, |ch| ch != quote_end);
if chars.next() == Some(quote_end) { if chars.next() == Some(quote_end) {
Ok(Some(Token::make_word(&s, Some(quote_start)))) Ok(Some(Token::make_word(&s, Some(quote_start))))
@ -520,13 +520,13 @@ fn peeking_take_while(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::super::dialect::GenericSqlDialect; use super::super::dialect::GenericDialect;
use super::*; use super::*;
#[test] #[test]
fn tokenize_select_1() { fn tokenize_select_1() {
let sql = String::from("SELECT 1"); let sql = String::from("SELECT 1");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
@ -542,7 +542,7 @@ mod tests {
#[test] #[test]
fn tokenize_scalar_function() { fn tokenize_scalar_function() {
let sql = String::from("SELECT sqrt(1)"); let sql = String::from("SELECT sqrt(1)");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
@ -561,7 +561,7 @@ mod tests {
#[test] #[test]
fn tokenize_simple_select() { fn tokenize_simple_select() {
let sql = String::from("SELECT * FROM customer WHERE id = 1 LIMIT 5"); let sql = String::from("SELECT * FROM customer WHERE id = 1 LIMIT 5");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
@ -593,7 +593,7 @@ mod tests {
#[test] #[test]
fn tokenize_string_predicate() { fn tokenize_string_predicate() {
let sql = String::from("SELECT * FROM customer WHERE salary != 'Not Provided'"); let sql = String::from("SELECT * FROM customer WHERE salary != 'Not Provided'");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
@ -622,7 +622,7 @@ mod tests {
fn tokenize_invalid_string() { fn tokenize_invalid_string() {
let sql = String::from("\nمصطفىh"); let sql = String::from("\nمصطفىh");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
println!("tokens: {:#?}", tokens); println!("tokens: {:#?}", tokens);
@ -642,7 +642,7 @@ mod tests {
fn tokenize_invalid_string_cols() { fn tokenize_invalid_string_cols() {
let sql = String::from("\n\nSELECT * FROM table\tمصطفىh"); let sql = String::from("\n\nSELECT * FROM table\tمصطفىh");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
println!("tokens: {:#?}", tokens); println!("tokens: {:#?}", tokens);
@ -670,7 +670,7 @@ mod tests {
#[test] #[test]
fn tokenize_is_null() { fn tokenize_is_null() {
let sql = String::from("a IS NULL"); let sql = String::from("a IS NULL");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
@ -689,7 +689,7 @@ mod tests {
fn tokenize_comment() { fn tokenize_comment() {
let sql = String::from("0--this is a comment\n1"); let sql = String::from("0--this is a comment\n1");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
let expected = vec![ let expected = vec![
@ -706,7 +706,7 @@ mod tests {
fn tokenize_comment_at_eof() { fn tokenize_comment_at_eof() {
let sql = String::from("--this is a comment"); let sql = String::from("--this is a comment");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
let expected = vec![Token::Whitespace(Whitespace::SingleLineComment( let expected = vec![Token::Whitespace(Whitespace::SingleLineComment(
@ -719,7 +719,7 @@ mod tests {
fn tokenize_multiline_comment() { fn tokenize_multiline_comment() {
let sql = String::from("0/*multi-line\n* /comment*/1"); let sql = String::from("0/*multi-line\n* /comment*/1");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
let expected = vec![ let expected = vec![
@ -736,7 +736,7 @@ mod tests {
fn tokenize_multiline_comment_with_even_asterisks() { fn tokenize_multiline_comment_with_even_asterisks() {
let sql = String::from("\n/** Comment **/\n"); let sql = String::from("\n/** Comment **/\n");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
let expected = vec![ let expected = vec![
@ -751,7 +751,7 @@ mod tests {
fn tokenize_mismatched_quotes() { fn tokenize_mismatched_quotes() {
let sql = String::from("\"foo"); let sql = String::from("\"foo");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
assert_eq!( assert_eq!(
tokenizer.tokenize(), tokenizer.tokenize(),
@ -765,7 +765,7 @@ mod tests {
fn tokenize_newlines() { fn tokenize_newlines() {
let sql = String::from("line1\nline2\rline3\r\nline4\r"); let sql = String::from("line1\nline2\rline3\r\nline4\r");
let dialect = GenericSqlDialect {}; let dialect = GenericDialect {};
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
let expected = vec![ let expected = vec![

File diff suppressed because it is too large Load diff

View file

@ -14,8 +14,8 @@
//! Test SQL syntax specific to Microsoft's T-SQL. The parser based on the //! Test SQL syntax specific to Microsoft's T-SQL. The parser based on the
//! generic dialect is also tested (on the inputs it can handle). //! generic dialect is also tested (on the inputs it can handle).
use sqlparser::dialect::{GenericSqlDialect, MsSqlDialect}; use sqlparser::ast::*;
use sqlparser::sqlast::*; use sqlparser::dialect::{GenericDialect, MsSqlDialect};
use sqlparser::test_utils::*; use sqlparser::test_utils::*;
#[test] #[test]
@ -23,11 +23,11 @@ fn parse_mssql_identifiers() {
let sql = "SELECT @@version, _foo$123 FROM ##temp"; let sql = "SELECT @@version, _foo$123 FROM ##temp";
let select = ms_and_generic().verified_only_select(sql); let select = ms_and_generic().verified_only_select(sql);
assert_eq!( assert_eq!(
&Expr::SQLIdentifier("@@version".to_string()), &Expr::Identifier("@@version".to_string()),
expr_from_projection(&select.projection[0]), expr_from_projection(&select.projection[0]),
); );
assert_eq!( assert_eq!(
&Expr::SQLIdentifier("_foo$123".to_string()), &Expr::Identifier("_foo$123".to_string()),
expr_from_projection(&select.projection[1]), expr_from_projection(&select.projection[1]),
); );
assert_eq!(2, select.projection.len()); assert_eq!(2, select.projection.len());
@ -75,6 +75,6 @@ fn ms() -> TestedDialects {
} }
fn ms_and_generic() -> TestedDialects { fn ms_and_generic() -> TestedDialects {
TestedDialects { TestedDialects {
dialects: vec![Box::new(MsSqlDialect {}), Box::new(GenericSqlDialect {})], dialects: vec![Box::new(MsSqlDialect {}), Box::new(GenericDialect {})],
} }
} }

View file

@ -14,8 +14,8 @@
//! Test SQL syntax specific to PostgreSQL. The parser based on the //! Test SQL syntax specific to PostgreSQL. The parser based on the
//! generic dialect is also tested (on the inputs it can handle). //! generic dialect is also tested (on the inputs it can handle).
use sqlparser::dialect::{GenericSqlDialect, PostgreSqlDialect}; use sqlparser::ast::*;
use sqlparser::sqlast::*; use sqlparser::dialect::{GenericDialect, PostgreSqlDialect};
use sqlparser::test_utils::*; use sqlparser::test_utils::*;
#[test] #[test]
@ -33,7 +33,7 @@ fn parse_create_table_with_defaults() {
active integer NOT NULL active integer NOT NULL
) WITH (fillfactor = 20, user_catalog_table = true, autovacuum_vacuum_threshold = 100)"; ) WITH (fillfactor = 20, user_catalog_table = true, autovacuum_vacuum_threshold = 100)";
match pg_and_generic().one_statement_parses_to(sql, "") { match pg_and_generic().one_statement_parses_to(sql, "") {
SQLStatement::SQLCreateTable { Statement::CreateTable {
name, name,
columns, columns,
constraints, constraints,
@ -46,9 +46,9 @@ fn parse_create_table_with_defaults() {
assert_eq!( assert_eq!(
columns, columns,
vec![ vec![
SQLColumnDef { ColumnDef {
name: "customer_id".into(), name: "customer_id".into(),
data_type: SQLType::Int, data_type: DataType::Int,
collation: None, collation: None,
options: vec![ColumnOptionDef { options: vec![ColumnOptionDef {
name: None, name: None,
@ -57,56 +57,56 @@ fn parse_create_table_with_defaults() {
) )
}], }],
}, },
SQLColumnDef { ColumnDef {
name: "store_id".into(), name: "store_id".into(),
data_type: SQLType::SmallInt, data_type: DataType::SmallInt,
collation: None, collation: None,
options: vec![ColumnOptionDef { options: vec![ColumnOptionDef {
name: None, name: None,
option: ColumnOption::NotNull, option: ColumnOption::NotNull,
}], }],
}, },
SQLColumnDef { ColumnDef {
name: "first_name".into(), name: "first_name".into(),
data_type: SQLType::Varchar(Some(45)), data_type: DataType::Varchar(Some(45)),
collation: None, collation: None,
options: vec![ColumnOptionDef { options: vec![ColumnOptionDef {
name: None, name: None,
option: ColumnOption::NotNull, option: ColumnOption::NotNull,
}], }],
}, },
SQLColumnDef { ColumnDef {
name: "last_name".into(), name: "last_name".into(),
data_type: SQLType::Varchar(Some(45)), data_type: DataType::Varchar(Some(45)),
collation: Some(SQLObjectName(vec!["\"es_ES\"".into()])), collation: Some(ObjectName(vec!["\"es_ES\"".into()])),
options: vec![ColumnOptionDef { options: vec![ColumnOptionDef {
name: None, name: None,
option: ColumnOption::NotNull, option: ColumnOption::NotNull,
}], }],
}, },
SQLColumnDef { ColumnDef {
name: "email".into(), name: "email".into(),
data_type: SQLType::Varchar(Some(50)), data_type: DataType::Varchar(Some(50)),
collation: None, collation: None,
options: vec![], options: vec![],
}, },
SQLColumnDef { ColumnDef {
name: "address_id".into(), name: "address_id".into(),
data_type: SQLType::SmallInt, data_type: DataType::SmallInt,
collation: None, collation: None,
options: vec![ColumnOptionDef { options: vec![ColumnOptionDef {
name: None, name: None,
option: ColumnOption::NotNull option: ColumnOption::NotNull
}], }],
}, },
SQLColumnDef { ColumnDef {
name: "activebool".into(), name: "activebool".into(),
data_type: SQLType::Boolean, data_type: DataType::Boolean,
collation: None, collation: None,
options: vec![ options: vec![
ColumnOptionDef { ColumnOptionDef {
name: None, name: None,
option: ColumnOption::Default(Expr::SQLValue(Value::Boolean(true))), option: ColumnOption::Default(Expr::Value(Value::Boolean(true))),
}, },
ColumnOptionDef { ColumnOptionDef {
name: None, name: None,
@ -114,9 +114,9 @@ fn parse_create_table_with_defaults() {
} }
], ],
}, },
SQLColumnDef { ColumnDef {
name: "create_date".into(), name: "create_date".into(),
data_type: SQLType::Date, data_type: DataType::Date,
collation: None, collation: None,
options: vec![ options: vec![
ColumnOptionDef { ColumnOptionDef {
@ -131,9 +131,9 @@ fn parse_create_table_with_defaults() {
} }
], ],
}, },
SQLColumnDef { ColumnDef {
name: "last_update".into(), name: "last_update".into(),
data_type: SQLType::Timestamp, data_type: DataType::Timestamp,
collation: None, collation: None,
options: vec![ options: vec![
ColumnOptionDef { ColumnOptionDef {
@ -146,9 +146,9 @@ fn parse_create_table_with_defaults() {
} }
], ],
}, },
SQLColumnDef { ColumnDef {
name: "active".into(), name: "active".into(),
data_type: SQLType::Int, data_type: DataType::Int,
collation: None, collation: None,
options: vec![ColumnOptionDef { options: vec![ColumnOptionDef {
name: None, name: None,
@ -161,15 +161,15 @@ fn parse_create_table_with_defaults() {
assert_eq!( assert_eq!(
with_options, with_options,
vec![ vec![
SQLOption { SqlOption {
name: "fillfactor".into(), name: "fillfactor".into(),
value: Value::Long(20) value: Value::Long(20)
}, },
SQLOption { SqlOption {
name: "user_catalog_table".into(), name: "user_catalog_table".into(),
value: Value::Boolean(true) value: Value::Boolean(true)
}, },
SQLOption { SqlOption {
name: "autovacuum_vacuum_threshold".into(), name: "autovacuum_vacuum_threshold".into(),
value: Value::Long(100) value: Value::Long(100)
}, },
@ -259,9 +259,6 @@ fn pg() -> TestedDialects {
fn pg_and_generic() -> TestedDialects { fn pg_and_generic() -> TestedDialects {
TestedDialects { TestedDialects {
dialects: vec![ dialects: vec![Box::new(PostgreSqlDialect {}), Box::new(GenericDialect {})],
Box::new(PostgreSqlDialect {}),
Box::new(GenericSqlDialect {}),
],
} }
} }