Skip to content

merge : commit update #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Oct 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ Given that the parser produces a typed AST, any changes to the AST will technica
## [Unreleased]
Check https://github.com/sqlparser-rs/sqlparser-rs/commits/main for undocumented changes.


## [0.26.0] 2022-10-19

### Added
* Support MySQL table option `{INDEX | KEY}` in CREATE TABLE definiton (#665) - Thanks @AugustoFKL
* Support `CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>` (#678) - Thanks @sam-mmm
* Support `DROP SEQUENCE` statement (#673) - Thanks @sam-mmm
* Support for ANSI types `CHARACTER LARGE OBJECT[(p)]` and `CHAR LARGE OBJECT[(p)]` (#671) - Thanks @AugustoFKL
* Support `[CACHE|UNCACHE] TABLE` (#670) - Thanks @francis-du
* Support `CEIL(expr TO DateTimeField)` and `FLOOR(expr TO DateTimeField)` - Thanks @sarahyurick
* Support all ansii character string types, (#648) - Thanks @AugustoFKL

### Changed
* Support expressions inside window frames (#655) - Thanks @mustafasrepo and @ozankabak
* Support unit on char length units for small character strings (#663) - Thanks @AugustoFKL
* Replace booleans on `SET ROLE` with a single enum. (#664) - Thanks @AugustoFKL
* Replace `Option`s with enum for `DECIMAL` precision (#654) - Thanks @AugustoFKL

## [0.25.0] 2022-10-03

### Added
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "sqlparser"
description = "Extensible SQL Lexer and Parser with support for ANSI SQL:2011"
version = "0.25.0"
version = "0.26.0"
authors = ["Andy Grove <[email protected]>"]
homepage = "https://github.com/sqlparser-rs/sqlparser-rs"
documentation = "https://docs.rs/sqlparser/"
Expand Down
26 changes: 23 additions & 3 deletions src/ast/data_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,15 @@ pub enum DataType {
Nvarchar(Option<u64>),
/// Uuid type
Uuid,
/// Large character object with optional length e.g. CLOB, CLOB(1000), [standard], [Oracle]
/// Large character object with optional length e.g. CHARACTER LARGE OBJECT, CHARACTER LARGE OBJECT(1000), [standard]
///
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type
CharacterLargeObject(Option<u64>),
/// Large character object with optional length e.g. CHAR LARGE OBJECT, CHAR LARGE OBJECT(1000), [standard]
///
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type
CharLargeObject(Option<u64>),
/// Large character object with optional length e.g. CLOB, CLOB(1000), [standard]
///
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type
/// [Oracle]: https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html
Expand Down Expand Up @@ -121,7 +129,7 @@ pub enum DataType {
/// Bytea
Bytea,
/// Custom type such as enums
Custom(ObjectName),
Custom(ObjectName, Vec<String>),
/// Arrays
Array(Box<DataType>),
/// Enums
Expand All @@ -145,6 +153,12 @@ impl fmt::Display for DataType {
format_type_with_optional_length(f, "NVARCHAR", size, false)
}
DataType::Uuid => write!(f, "UUID"),
DataType::CharacterLargeObject(size) => {
format_type_with_optional_length(f, "CHARACTER LARGE OBJECT", size, false)
}
DataType::CharLargeObject(size) => {
format_type_with_optional_length(f, "CHAR LARGE OBJECT", size, false)
}
DataType::Clob(size) => format_type_with_optional_length(f, "CLOB", size, false),
DataType::Binary(size) => format_type_with_optional_length(f, "BINARY", size, false),
DataType::Varbinary(size) => {
Expand Down Expand Up @@ -203,7 +217,13 @@ impl fmt::Display for DataType {
DataType::String => write!(f, "STRING"),
DataType::Bytea => write!(f, "BYTEA"),
DataType::Array(ty) => write!(f, "{}[]", ty),
DataType::Custom(ty) => write!(f, "{}", ty),
DataType::Custom(ty, modifiers) => {
if modifiers.is_empty() {
write!(f, "{}", ty)
} else {
write!(f, "{}({})", ty, modifiers.join(", "))
}
}
DataType::Enum(vals) => {
write!(f, "ENUM(")?;
for (i, v) in vals.iter().enumerate() {
Expand Down
60 changes: 60 additions & 0 deletions src/ast/ddl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,24 @@ pub enum TableConstraint {
name: Option<Ident>,
expr: Box<Expr>,
},
/// MySQLs [index definition][1] for index creation. Not present on ANSI so, for now, the usage
/// is restricted to MySQL, as no other dialects that support this syntax were found.
///
/// `{INDEX | KEY} [index_name] [index_type] (key_part,...) [index_option]...`
///
/// [1]: https://dev.mysql.com/doc/refman/8.0/en/create-table.html
Index {
/// Whether this index starts with KEY (true) or INDEX (false), to maintain the same syntax.
display_as_key: bool,
/// Index name.
name: Option<Ident>,
/// Optional [index type][1].
///
/// [1]: IndexType
index_type: Option<IndexType>,
/// Referred column identifier list.
columns: Vec<Ident>,
},
}

impl fmt::Display for TableConstraint {
Expand Down Expand Up @@ -290,6 +308,48 @@ impl fmt::Display for TableConstraint {
TableConstraint::Check { name, expr } => {
write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
}
TableConstraint::Index {
display_as_key,
name,
index_type,
columns,
} => {
write!(f, "{}", if *display_as_key { "KEY" } else { "INDEX" })?;
if let Some(name) = name {
write!(f, " {}", name)?;
}
if let Some(index_type) = index_type {
write!(f, " USING {}", index_type)?;
}
write!(f, " ({})", display_comma_separated(columns))?;

Ok(())
}
}
}
}

/// Indexing method used by that index.
///
/// This structure isn't present on ANSI, but is found at least in [MySQL CREATE TABLE][1],
/// [MySQL CREATE INDEX][2], and [Postgresql CREATE INDEX][3] statements.
///
/// [1]: https://dev.mysql.com/doc/refman/8.0/en/create-table.html
/// [2]: https://dev.mysql.com/doc/refman/8.0/en/create-index.html
/// [3]: https://www.postgresql.org/docs/14/sql-createindex.html
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum IndexType {
BTree,
Hash,
// TODO add Postgresql's possible indexes
}

impl fmt::Display for IndexType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::BTree => write!(f, "BTREE"),
Self::Hash => write!(f, "HASH"),
}
}
}
Expand Down
101 changes: 97 additions & 4 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub use self::data_type::{
CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, TimezoneInfo,
};
pub use self::ddl::{
AlterColumnOperation, AlterTableOperation, ColumnDef, ColumnOption, ColumnOptionDef,
AlterColumnOperation, AlterTableOperation, ColumnDef, ColumnOption, ColumnOptionDef, IndexType,
ReferentialAction, TableConstraint,
};
pub use self::operator::{BinaryOperator, UnaryOperator};
Expand Down Expand Up @@ -906,9 +906,9 @@ pub enum WindowFrameBound {
/// `CURRENT ROW`
CurrentRow,
/// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
Preceding(Option<u64>),
Preceding(Option<Box<Expr>>),
/// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
Following(Option<u64>),
Following(Option<Box<Expr>>),
}

impl fmt::Display for WindowFrameBound {
Expand Down Expand Up @@ -1184,6 +1184,9 @@ pub enum Statement {
/// Whether `CASCADE` was specified. This will be `false` when
/// `RESTRICT` or no drop behavior at all was specified.
cascade: bool,
/// Whether `RESTRICT` was specified. This will be `false` when
/// `CASCADE` or no drop behavior at all was specified.
restrict: bool,
/// Hive allows you specify whether the table's stored data will be
/// deleted along with the dropped table
purge: bool,
Expand Down Expand Up @@ -1430,6 +1433,32 @@ pub enum Statement {
// Specifies the actions to perform when values match or do not match.
clauses: Vec<MergeClause>,
},
/// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
/// Based on Spark SQL,see <https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html>
Cache {
// Table flag
table_flag: Option<ObjectName>,
// Table name
table_name: ObjectName,
has_as: bool,
// Table confs
options: Vec<SqlOption>,
// Cache table as a Query
query: Option<Query>,
},
/// UNCACHE TABLE [ IF EXISTS ] <table_name>
UNCache {
// Table name
table_name: ObjectName,
if_exists: bool,
},
///CreateSequence -- define a new sequence
/// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
CreateSequence {
temporary: bool,
if_not_exists: bool,
name: ObjectName,
},
}

impl fmt::Display for Statement {
Expand Down Expand Up @@ -2124,14 +2153,16 @@ impl fmt::Display for Statement {
if_exists,
names,
cascade,
restrict,
purge,
} => write!(
f,
"DROP {}{} {}{}{}",
"DROP {}{} {}{}{}{}",
object_type,
if *if_exists { " IF EXISTS" } else { "" },
display_comma_separated(names),
if *cascade { " CASCADE" } else { "" },
if *restrict { " RESTRICT" } else { "" },
if *purge { " PURGE" } else { "" }
),
Statement::Discard { object_type } => {
Expand Down Expand Up @@ -2397,6 +2428,66 @@ impl fmt::Display for Statement {
write!(f, "ON {} ", on)?;
write!(f, "{}", display_separated(clauses, " "))
}
Statement::Cache {
table_name,
table_flag,
has_as,
options,
query,
} => {
if table_flag.is_some() {
write!(
f,
"CACHE {table_flag} TABLE {table_name}",
table_flag = table_flag.clone().unwrap(),
table_name = table_name,
)?;
} else {
write!(f, "CACHE TABLE {table_name}", table_name = table_name,)?;
}

if !options.is_empty() {
write!(f, " OPTIONS({})", display_comma_separated(options))?;
}

let has_query = query.is_some();
if *has_as && has_query {
write!(f, " AS {query}", query = query.clone().unwrap())
} else if !has_as && has_query {
write!(f, " {query}", query = query.clone().unwrap())
} else if *has_as && !has_query {
write!(f, " AS")
} else {
Ok(())
}
}
Statement::UNCache {
table_name,
if_exists,
} => {
if *if_exists {
write!(
f,
"UNCACHE TABLE IF EXISTS {table_name}",
table_name = table_name
)
} else {
write!(f, "UNCACHE TABLE {table_name}", table_name = table_name)
}
}
Statement::CreateSequence {
temporary,
if_not_exists,
name,
} => {
write!(
f,
"CREATE {temporary}SEQUENCE {if_not_exists}{name}",
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
temporary = if *temporary { "TEMPORARY " } else { "" },
name = name
)
}
}
}
}
Expand Down Expand Up @@ -2844,6 +2935,7 @@ pub enum ObjectType {
Index,
Schema,
Role,
Sequence,
}

impl fmt::Display for ObjectType {
Expand All @@ -2854,6 +2946,7 @@ impl fmt::Display for ObjectType {
ObjectType::Index => "INDEX",
ObjectType::Schema => "SCHEMA",
ObjectType::Role => "ROLE",
ObjectType::Sequence => "SEQUENCE",
})
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ define_keywords!(
BLOB,
BOOLEAN,
BOTH,
BTREE,
BY,
BYPASSRLS,
BYTEA,
Expand Down Expand Up @@ -265,6 +266,7 @@ define_keywords!(
GROUP,
GROUPING,
GROUPS,
HASH,
HAVING,
HEADER,
HIVEVAR,
Expand Down Expand Up @@ -383,6 +385,7 @@ define_keywords!(
OPEN,
OPERATOR,
OPTION,
OPTIONS,
OR,
ORC,
ORDER,
Expand Down Expand Up @@ -554,6 +557,7 @@ define_keywords!(
TYPE,
UESCAPE,
UNBOUNDED,
UNCACHE,
UNCOMMITTED,
UNION,
UNIQUE,
Expand Down
Loading