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:
sam 2022-11-03 18:46:43 +05:30 committed by GitHub
parent 93a050e5f0
commit bbf32a9e81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 236 additions and 3 deletions

View file

@ -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]

View file

@ -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,

View file

@ -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 {

View file

@ -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]