mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 07:24:10 +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
104
src/ast/mod.rs
104
src/ast/mod.rs
|
@ -1467,6 +1467,9 @@ pub enum Statement {
|
||||||
temporary: bool,
|
temporary: bool,
|
||||||
if_not_exists: bool,
|
if_not_exists: bool,
|
||||||
name: ObjectName,
|
name: ObjectName,
|
||||||
|
data_type: Option<DataType>,
|
||||||
|
sequence_options: Vec<SequenceOptions>,
|
||||||
|
owned_by: Option<ObjectName>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2488,17 +2491,114 @@ impl fmt::Display for Statement {
|
||||||
temporary,
|
temporary,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
name,
|
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!(
|
write!(
|
||||||
f,
|
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 { "" },
|
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
|
||||||
temporary = if *temporary { "TEMPORARY " } 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)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -277,6 +277,7 @@ define_keywords!(
|
||||||
IGNORE,
|
IGNORE,
|
||||||
ILIKE,
|
ILIKE,
|
||||||
IN,
|
IN,
|
||||||
|
INCREMENT,
|
||||||
INDEX,
|
INDEX,
|
||||||
INDICATOR,
|
INDICATOR,
|
||||||
INHERIT,
|
INHERIT,
|
||||||
|
@ -328,6 +329,7 @@ define_keywords!(
|
||||||
MATCHED,
|
MATCHED,
|
||||||
MATERIALIZED,
|
MATERIALIZED,
|
||||||
MAX,
|
MAX,
|
||||||
|
MAXVALUE,
|
||||||
MEDIUMINT,
|
MEDIUMINT,
|
||||||
MEMBER,
|
MEMBER,
|
||||||
MERGE,
|
MERGE,
|
||||||
|
@ -341,6 +343,7 @@ define_keywords!(
|
||||||
MILLISECONDS,
|
MILLISECONDS,
|
||||||
MIN,
|
MIN,
|
||||||
MINUTE,
|
MINUTE,
|
||||||
|
MINVALUE,
|
||||||
MOD,
|
MOD,
|
||||||
MODIFIES,
|
MODIFIES,
|
||||||
MODULE,
|
MODULE,
|
||||||
|
@ -397,6 +400,7 @@ define_keywords!(
|
||||||
OVERLAPS,
|
OVERLAPS,
|
||||||
OVERLAY,
|
OVERLAY,
|
||||||
OVERWRITE,
|
OVERWRITE,
|
||||||
|
OWNED,
|
||||||
PARAMETER,
|
PARAMETER,
|
||||||
PARQUET,
|
PARQUET,
|
||||||
PARTITION,
|
PARTITION,
|
||||||
|
|
|
@ -5510,12 +5510,98 @@ impl<'a> Parser<'a> {
|
||||||
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||||
//name
|
//name
|
||||||
let name = self.parse_object_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 {
|
Ok(Statement::CreateSequence {
|
||||||
temporary,
|
temporary,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
name,
|
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 {
|
impl Word {
|
||||||
|
|
|
@ -37,6 +37,49 @@ fn parse_create_sequence() {
|
||||||
|
|
||||||
let sql4 = "CREATE TEMPORARY SEQUENCE name0";
|
let sql4 = "CREATE TEMPORARY SEQUENCE name0";
|
||||||
pg().one_statement_parses_to(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]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue