mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-08 01:15:00 +00:00
Support create sequence with options INCREMENT, MINVALUE, MAXVALUE, START etc. (#681)
* Creat sequence options model [ INCREMENT [ BY ] increment ] [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ] [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ] [ OWNED BY { table_name.column_name | NONE } ] * Fix for format! not avalable in --target thumbv6m-none-eabi * Fix for format! not avalable in --target thumbv6m-none-eabi * Fix for format! not avalable in --target thumbv6m-none-eabi * Fix for format! not avalable in --target thumbv6m-none-eabi * Updated parser for sequence options * Updated parser for sequence options * Update src/ast/mod.rs Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org> Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
93a050e5f0
commit
bbf32a9e81
4 changed files with 236 additions and 3 deletions
106
src/ast/mod.rs
106
src/ast/mod.rs
|
@ -1467,6 +1467,9 @@ pub enum Statement {
|
|||
temporary: bool,
|
||||
if_not_exists: bool,
|
||||
name: ObjectName,
|
||||
data_type: Option<DataType>,
|
||||
sequence_options: Vec<SequenceOptions>,
|
||||
owned_by: Option<ObjectName>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -2488,19 +2491,116 @@ impl fmt::Display for Statement {
|
|||
temporary,
|
||||
if_not_exists,
|
||||
name,
|
||||
data_type,
|
||||
sequence_options,
|
||||
owned_by,
|
||||
} => {
|
||||
let as_type: String = if let Some(dt) = data_type.as_ref() {
|
||||
//Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
|
||||
// " AS ".to_owned() + &dt.to_string()
|
||||
[" AS ", &dt.to_string()].concat()
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
write!(
|
||||
f,
|
||||
"CREATE {temporary}SEQUENCE {if_not_exists}{name}",
|
||||
"CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
|
||||
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
|
||||
temporary = if *temporary { "TEMPORARY " } else { "" },
|
||||
name = name
|
||||
)
|
||||
name = name,
|
||||
as_type = as_type
|
||||
)?;
|
||||
for sequence_option in sequence_options {
|
||||
write!(f, "{}", sequence_option)?;
|
||||
}
|
||||
if let Some(ob) = owned_by.as_ref() {
|
||||
write!(f, " OWNED BY {}", ob)?;
|
||||
}
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
/// Can use to describe options in create sequence or table column type identity
|
||||
/// [ INCREMENT [ BY ] increment ]
|
||||
/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
|
||||
/// [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
|
||||
pub enum SequenceOptions {
|
||||
IncrementBy(Expr, bool),
|
||||
MinValue(MinMaxValue),
|
||||
MaxValue(MinMaxValue),
|
||||
StartWith(Expr, bool),
|
||||
Cache(Expr),
|
||||
Cycle(bool),
|
||||
}
|
||||
|
||||
impl fmt::Display for SequenceOptions {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
SequenceOptions::IncrementBy(increment, by) => {
|
||||
write!(
|
||||
f,
|
||||
" INCREMENT{by} {increment}",
|
||||
by = if *by { " BY" } else { "" },
|
||||
increment = increment
|
||||
)
|
||||
}
|
||||
SequenceOptions::MinValue(value) => match value {
|
||||
MinMaxValue::Empty => {
|
||||
write!(f, "")
|
||||
}
|
||||
MinMaxValue::None => {
|
||||
write!(f, " NO MINVALUE")
|
||||
}
|
||||
MinMaxValue::Some(minvalue) => {
|
||||
write!(f, " MINVALUE {minvalue}", minvalue = minvalue)
|
||||
}
|
||||
},
|
||||
SequenceOptions::MaxValue(value) => match value {
|
||||
MinMaxValue::Empty => {
|
||||
write!(f, "")
|
||||
}
|
||||
MinMaxValue::None => {
|
||||
write!(f, " NO MAXVALUE")
|
||||
}
|
||||
MinMaxValue::Some(maxvalue) => {
|
||||
write!(f, " MAXVALUE {maxvalue}", maxvalue = maxvalue)
|
||||
}
|
||||
},
|
||||
SequenceOptions::StartWith(start, with) => {
|
||||
write!(
|
||||
f,
|
||||
" START{with} {start}",
|
||||
with = if *with { " WITH" } else { "" },
|
||||
start = start
|
||||
)
|
||||
}
|
||||
SequenceOptions::Cache(cache) => {
|
||||
write!(f, " CACHE {}", *cache)
|
||||
}
|
||||
SequenceOptions::Cycle(no) => {
|
||||
write!(f, " {}CYCLE", if *no { "NO " } else { "" })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
/// Can use to describe options in create sequence or table column type identity
|
||||
/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
|
||||
pub enum MinMaxValue {
|
||||
// clause is not specified
|
||||
Empty,
|
||||
// NO MINVALUE/NO MAXVALUE
|
||||
None,
|
||||
// MINVALUE <expr> / MAXVALUE <expr>
|
||||
Some(Expr),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[non_exhaustive]
|
||||
|
|
|
@ -277,6 +277,7 @@ define_keywords!(
|
|||
IGNORE,
|
||||
ILIKE,
|
||||
IN,
|
||||
INCREMENT,
|
||||
INDEX,
|
||||
INDICATOR,
|
||||
INHERIT,
|
||||
|
@ -328,6 +329,7 @@ define_keywords!(
|
|||
MATCHED,
|
||||
MATERIALIZED,
|
||||
MAX,
|
||||
MAXVALUE,
|
||||
MEDIUMINT,
|
||||
MEMBER,
|
||||
MERGE,
|
||||
|
@ -341,6 +343,7 @@ define_keywords!(
|
|||
MILLISECONDS,
|
||||
MIN,
|
||||
MINUTE,
|
||||
MINVALUE,
|
||||
MOD,
|
||||
MODIFIES,
|
||||
MODULE,
|
||||
|
@ -397,6 +400,7 @@ define_keywords!(
|
|||
OVERLAPS,
|
||||
OVERLAY,
|
||||
OVERWRITE,
|
||||
OWNED,
|
||||
PARAMETER,
|
||||
PARQUET,
|
||||
PARTITION,
|
||||
|
|
|
@ -5510,12 +5510,98 @@ impl<'a> Parser<'a> {
|
|||
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||
//name
|
||||
let name = self.parse_object_name()?;
|
||||
//[ AS data_type ]
|
||||
let mut data_type: Option<DataType> = None;
|
||||
if self.parse_keywords(&[Keyword::AS]) {
|
||||
data_type = Some(self.parse_data_type()?)
|
||||
}
|
||||
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]) {
|
||||
if self.parse_keywords(&[Keyword::NONE]) {
|
||||
Some(ObjectName(vec![Ident::new("NONE")]))
|
||||
} else {
|
||||
Some(self.parse_object_name()?)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Statement::CreateSequence {
|
||||
temporary,
|
||||
if_not_exists,
|
||||
name,
|
||||
data_type,
|
||||
sequence_options,
|
||||
owned_by,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_create_sequence_options(&mut self) -> Result<Vec<SequenceOptions>, ParserError> {
|
||||
let mut sequence_options = vec![];
|
||||
//[ INCREMENT [ BY ] increment ]
|
||||
if self.parse_keywords(&[Keyword::INCREMENT]) {
|
||||
if self.parse_keywords(&[Keyword::BY]) {
|
||||
sequence_options.push(SequenceOptions::IncrementBy(
|
||||
Expr::Value(self.parse_number_value()?),
|
||||
true,
|
||||
));
|
||||
} else {
|
||||
sequence_options.push(SequenceOptions::IncrementBy(
|
||||
Expr::Value(self.parse_number_value()?),
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
//[ MINVALUE minvalue | NO MINVALUE ]
|
||||
if self.parse_keyword(Keyword::MINVALUE) {
|
||||
sequence_options.push(SequenceOptions::MinValue(MinMaxValue::Some(Expr::Value(
|
||||
self.parse_number_value()?,
|
||||
))));
|
||||
} else if self.parse_keywords(&[Keyword::NO, Keyword::MINVALUE]) {
|
||||
sequence_options.push(SequenceOptions::MinValue(MinMaxValue::None));
|
||||
} else {
|
||||
sequence_options.push(SequenceOptions::MinValue(MinMaxValue::Empty));
|
||||
}
|
||||
//[ MAXVALUE maxvalue | NO MAXVALUE ]
|
||||
if self.parse_keywords(&[Keyword::MAXVALUE]) {
|
||||
sequence_options.push(SequenceOptions::MaxValue(MinMaxValue::Some(Expr::Value(
|
||||
self.parse_number_value()?,
|
||||
))));
|
||||
} else if self.parse_keywords(&[Keyword::NO, Keyword::MAXVALUE]) {
|
||||
sequence_options.push(SequenceOptions::MaxValue(MinMaxValue::None));
|
||||
} else {
|
||||
sequence_options.push(SequenceOptions::MaxValue(MinMaxValue::Empty));
|
||||
}
|
||||
//[ START [ WITH ] start ]
|
||||
if self.parse_keywords(&[Keyword::START]) {
|
||||
if self.parse_keywords(&[Keyword::WITH]) {
|
||||
sequence_options.push(SequenceOptions::StartWith(
|
||||
Expr::Value(self.parse_number_value()?),
|
||||
true,
|
||||
));
|
||||
} else {
|
||||
sequence_options.push(SequenceOptions::StartWith(
|
||||
Expr::Value(self.parse_number_value()?),
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
//[ CACHE cache ]
|
||||
if self.parse_keywords(&[Keyword::CACHE]) {
|
||||
sequence_options.push(SequenceOptions::Cache(Expr::Value(
|
||||
self.parse_number_value()?,
|
||||
)));
|
||||
}
|
||||
// [ [ NO ] CYCLE ]
|
||||
if self.parse_keywords(&[Keyword::NO]) {
|
||||
if self.parse_keywords(&[Keyword::CYCLE]) {
|
||||
sequence_options.push(SequenceOptions::Cycle(true));
|
||||
}
|
||||
} else if self.parse_keywords(&[Keyword::CYCLE]) {
|
||||
sequence_options.push(SequenceOptions::Cycle(false));
|
||||
}
|
||||
Ok(sequence_options)
|
||||
}
|
||||
}
|
||||
|
||||
impl Word {
|
||||
|
|
|
@ -37,6 +37,49 @@ fn parse_create_sequence() {
|
|||
|
||||
let sql4 = "CREATE TEMPORARY SEQUENCE name0";
|
||||
pg().one_statement_parses_to(sql4, "CREATE TEMPORARY SEQUENCE name0");
|
||||
|
||||
let sql2 = "CREATE TEMPORARY SEQUENCE IF NOT EXISTS name1
|
||||
AS BIGINT
|
||||
INCREMENT BY 1
|
||||
MINVALUE 1 MAXVALUE 20
|
||||
START WITH 10";
|
||||
pg().one_statement_parses_to(
|
||||
sql2,
|
||||
"CREATE TEMPORARY SEQUENCE IF NOT EXISTS name1 AS BIGINT INCREMENT BY 1 MINVALUE 1 MAXVALUE 20 START WITH 10", );
|
||||
|
||||
let sql3 = "CREATE SEQUENCE IF NOT EXISTS name2
|
||||
AS BIGINT
|
||||
INCREMENT 1
|
||||
MINVALUE 1 MAXVALUE 20
|
||||
START WITH 10 CACHE 2 NO CYCLE";
|
||||
pg().one_statement_parses_to(
|
||||
sql3,
|
||||
"CREATE SEQUENCE IF NOT EXISTS name2 AS BIGINT INCREMENT 1 MINVALUE 1 MAXVALUE 20 START WITH 10 CACHE 2 NO CYCLE",
|
||||
);
|
||||
|
||||
let sql4 = "CREATE TEMPORARY SEQUENCE IF NOT EXISTS name3
|
||||
INCREMENT 1
|
||||
NO MINVALUE MAXVALUE 20 CACHE 2 CYCLE";
|
||||
pg().one_statement_parses_to(
|
||||
sql4,
|
||||
"CREATE TEMPORARY SEQUENCE IF NOT EXISTS name3 INCREMENT 1 NO MINVALUE MAXVALUE 20 CACHE 2 CYCLE",
|
||||
);
|
||||
|
||||
let sql5 = "CREATE TEMPORARY SEQUENCE IF NOT EXISTS name3
|
||||
INCREMENT 1
|
||||
NO MINVALUE MAXVALUE 20 OWNED BY public.table01";
|
||||
pg().one_statement_parses_to(
|
||||
sql5,
|
||||
"CREATE TEMPORARY SEQUENCE IF NOT EXISTS name3 INCREMENT 1 NO MINVALUE MAXVALUE 20 OWNED BY public.table01",
|
||||
);
|
||||
|
||||
let sql6 = "CREATE TEMPORARY SEQUENCE IF NOT EXISTS name3
|
||||
INCREMENT 1
|
||||
NO MINVALUE MAXVALUE 20 OWNED BY NONE";
|
||||
pg().one_statement_parses_to(
|
||||
sql6,
|
||||
"CREATE TEMPORARY SEQUENCE IF NOT EXISTS name3 INCREMENT 1 NO MINVALUE MAXVALUE 20 OWNED BY NONE",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue