Skip to content

Commit facbdfd

Browse files
Moved constraint variant outside of TableConstraint enum
1 parent 7461d8b commit facbdfd

15 files changed

+789
-406
lines changed

src/ast/ddl.rs

Lines changed: 61 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,19 @@ use sqlparser_derive::{Visit, VisitMut};
3030

3131
use crate::ast::value::escape_single_quote_string;
3232
use crate::ast::{
33-
display_comma_separated, display_separated, ArgMode, CommentDef, ConditionalStatements,
34-
CreateFunctionBody, CreateFunctionUsing, CreateTableLikeKind, CreateTableOptions, DataType,
35-
Expr, FileFormat, FunctionBehavior, FunctionCalledOnNull, FunctionDeterminismSpecifier,
36-
FunctionParallel, HiveDistributionStyle, HiveFormat, HiveIOFormat, HiveRowFormat, Ident,
37-
InitializeKind, MySQLColumnPosition, ObjectName, OnCommit, OneOrManyWithParens,
38-
OperateFunctionArg, OrderByExpr, ProjectionSelect, Query, RefreshModeKind, RowAccessPolicy,
39-
SequenceOptions, Spanned, SqlOption, StorageSerializationPolicy, TableVersion, Tag,
40-
TriggerEvent, TriggerExecBody, TriggerObject, TriggerPeriod, TriggerReferencing, Value,
41-
ValueWithSpan, WrappedCollection,
33+
display_comma_separated, display_separated,
34+
table_constraints::{
35+
CheckConstraint, ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint,
36+
PrimaryKeyConstraint, UniqueConstraint,
37+
},
38+
ArgMode, CommentDef, ConditionalStatements, CreateFunctionBody, CreateFunctionUsing,
39+
CreateTableLikeKind, CreateTableOptions, DataType, Expr, FileFormat, FunctionBehavior,
40+
FunctionCalledOnNull, FunctionDeterminismSpecifier, FunctionParallel, HiveDistributionStyle,
41+
HiveFormat, HiveIOFormat, HiveRowFormat, Ident, InitializeKind, MySQLColumnPosition,
42+
ObjectName, OnCommit, OneOrManyWithParens, OperateFunctionArg, OrderByExpr, ProjectionSelect,
43+
Query, RefreshModeKind, RowAccessPolicy, SequenceOptions, Spanned, SqlOption,
44+
StorageSerializationPolicy, TableVersion, Tag, TriggerEvent, TriggerExecBody, TriggerObject,
45+
TriggerPeriod, TriggerReferencing, Value, ValueWithSpan, WrappedCollection,
4246
};
4347
use crate::display_utils::{DisplayCommaSeparated, Indent, NewLine, SpaceOrNewline};
4448
use crate::keywords::Keyword;
@@ -1047,26 +1051,7 @@ pub enum TableConstraint {
10471051
/// [2]: IndexType
10481052
/// [3]: IndexOption
10491053
/// [4]: KeyOrIndexDisplay
1050-
Unique {
1051-
/// Constraint name.
1052-
///
1053-
/// Can be not the same as `index_name`
1054-
name: Option<Ident>,
1055-
/// Index name
1056-
index_name: Option<Ident>,
1057-
/// Whether the type is followed by the keyword `KEY`, `INDEX`, or no keyword at all.
1058-
index_type_display: KeyOrIndexDisplay,
1059-
/// Optional `USING` of [index type][1] statement before columns.
1060-
///
1061-
/// [1]: IndexType
1062-
index_type: Option<IndexType>,
1063-
/// Identifiers of the columns that are unique.
1064-
columns: Vec<IndexColumn>,
1065-
index_options: Vec<IndexOption>,
1066-
characteristics: Option<ConstraintCharacteristics>,
1067-
/// Optional Postgres nulls handling: `[ NULLS [ NOT ] DISTINCT ]`
1068-
nulls_distinct: NullsDistinctOption,
1069-
},
1054+
Unique(UniqueConstraint),
10701055
/// MySQL [definition][1] for `PRIMARY KEY` constraints statements:\
10711056
/// * `[CONSTRAINT [<name>]] PRIMARY KEY [index_name] [index_type] (<columns>) <index_options>`
10721057
///
@@ -1085,67 +1070,22 @@ pub enum TableConstraint {
10851070
/// [1]: https://dev.mysql.com/doc/refman/8.3/en/create-table.html
10861071
/// [2]: IndexType
10871072
/// [3]: IndexOption
1088-
PrimaryKey {
1089-
/// Constraint name.
1090-
///
1091-
/// Can be not the same as `index_name`
1092-
name: Option<Ident>,
1093-
/// Index name
1094-
index_name: Option<Ident>,
1095-
/// Optional `USING` of [index type][1] statement before columns.
1096-
///
1097-
/// [1]: IndexType
1098-
index_type: Option<IndexType>,
1099-
/// Identifiers of the columns that form the primary key.
1100-
columns: Vec<IndexColumn>,
1101-
index_options: Vec<IndexOption>,
1102-
characteristics: Option<ConstraintCharacteristics>,
1103-
},
1073+
PrimaryKey(PrimaryKeyConstraint),
11041074
/// A referential integrity constraint (`[ CONSTRAINT <name> ] FOREIGN KEY (<columns>)
11051075
/// REFERENCES <foreign_table> (<referred_columns>)
11061076
/// { [ON DELETE <referential_action>] [ON UPDATE <referential_action>] |
11071077
/// [ON UPDATE <referential_action>] [ON DELETE <referential_action>]
11081078
/// }`).
1109-
ForeignKey {
1110-
name: Option<Ident>,
1111-
/// MySQL-specific field
1112-
/// <https://dev.mysql.com/doc/refman/8.4/en/create-table-foreign-keys.html>
1113-
index_name: Option<Ident>,
1114-
columns: Vec<Ident>,
1115-
foreign_table: ObjectName,
1116-
referred_columns: Vec<Ident>,
1117-
on_delete: Option<ReferentialAction>,
1118-
on_update: Option<ReferentialAction>,
1119-
characteristics: Option<ConstraintCharacteristics>,
1120-
},
1079+
ForeignKey(ForeignKeyConstraint),
11211080
/// `[ CONSTRAINT <name> ] CHECK (<expr>) [[NOT] ENFORCED]`
1122-
Check {
1123-
name: Option<Ident>,
1124-
expr: Box<Expr>,
1125-
/// MySQL-specific syntax
1126-
/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
1127-
enforced: Option<bool>,
1128-
},
1081+
Check(CheckConstraint),
11291082
/// MySQLs [index definition][1] for index creation. Not present on ANSI so, for now, the usage
11301083
/// is restricted to MySQL, as no other dialects that support this syntax were found.
11311084
///
11321085
/// `{INDEX | KEY} [index_name] [index_type] (key_part,...) [index_option]...`
11331086
///
11341087
/// [1]: https://dev.mysql.com/doc/refman/8.0/en/create-table.html
1135-
Index {
1136-
/// Whether this index starts with KEY (true) or INDEX (false), to maintain the same syntax.
1137-
display_as_key: bool,
1138-
/// Index name.
1139-
name: Option<Ident>,
1140-
/// Optional [index type][1].
1141-
///
1142-
/// [1]: IndexType
1143-
index_type: Option<IndexType>,
1144-
/// Referred column identifier list.
1145-
columns: Vec<IndexColumn>,
1146-
/// Optional index options such as `USING`; see [`IndexOption`].
1147-
index_options: Vec<IndexOption>,
1148-
},
1088+
Index(IndexConstraint),
11491089
/// MySQLs [fulltext][1] definition. Since the [`SPATIAL`][2] definition is exactly the same,
11501090
/// and MySQL displays both the same way, it is part of this definition as well.
11511091
///
@@ -1159,157 +1099,54 @@ pub enum TableConstraint {
11591099
///
11601100
/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-natural-language.html
11611101
/// [2]: https://dev.mysql.com/doc/refman/8.0/en/spatial-types.html
1162-
FulltextOrSpatial {
1163-
/// Whether this is a `FULLTEXT` (true) or `SPATIAL` (false) definition.
1164-
fulltext: bool,
1165-
/// Whether the type is followed by the keyword `KEY`, `INDEX`, or no keyword at all.
1166-
index_type_display: KeyOrIndexDisplay,
1167-
/// Optional index name.
1168-
opt_index_name: Option<Ident>,
1169-
/// Referred column identifier list.
1170-
columns: Vec<IndexColumn>,
1171-
},
1102+
FulltextOrSpatial(FullTextOrSpatialConstraint),
11721103
}
11731104

1174-
impl fmt::Display for TableConstraint {
1175-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1176-
match self {
1177-
TableConstraint::Unique {
1178-
name,
1179-
index_name,
1180-
index_type_display,
1181-
index_type,
1182-
columns,
1183-
index_options,
1184-
characteristics,
1185-
nulls_distinct,
1186-
} => {
1187-
write!(
1188-
f,
1189-
"{}UNIQUE{nulls_distinct}{index_type_display:>}{}{} ({})",
1190-
display_constraint_name(name),
1191-
display_option_spaced(index_name),
1192-
display_option(" USING ", "", index_type),
1193-
display_comma_separated(columns),
1194-
)?;
1195-
1196-
if !index_options.is_empty() {
1197-
write!(f, " {}", display_separated(index_options, " "))?;
1198-
}
1199-
1200-
write!(f, "{}", display_option_spaced(characteristics))?;
1201-
Ok(())
1202-
}
1203-
TableConstraint::PrimaryKey {
1204-
name,
1205-
index_name,
1206-
index_type,
1207-
columns,
1208-
index_options,
1209-
characteristics,
1210-
} => {
1211-
write!(
1212-
f,
1213-
"{}PRIMARY KEY{}{} ({})",
1214-
display_constraint_name(name),
1215-
display_option_spaced(index_name),
1216-
display_option(" USING ", "", index_type),
1217-
display_comma_separated(columns),
1218-
)?;
1105+
impl From<UniqueConstraint> for TableConstraint {
1106+
fn from(constraint: UniqueConstraint) -> Self {
1107+
TableConstraint::Unique(constraint)
1108+
}
1109+
}
12191110

1220-
if !index_options.is_empty() {
1221-
write!(f, " {}", display_separated(index_options, " "))?;
1222-
}
1111+
impl From<PrimaryKeyConstraint> for TableConstraint {
1112+
fn from(constraint: PrimaryKeyConstraint) -> Self {
1113+
TableConstraint::PrimaryKey(constraint)
1114+
}
1115+
}
12231116

1224-
write!(f, "{}", display_option_spaced(characteristics))?;
1225-
Ok(())
1226-
}
1227-
TableConstraint::ForeignKey {
1228-
name,
1229-
index_name,
1230-
columns,
1231-
foreign_table,
1232-
referred_columns,
1233-
on_delete,
1234-
on_update,
1235-
characteristics,
1236-
} => {
1237-
write!(
1238-
f,
1239-
"{}FOREIGN KEY{} ({}) REFERENCES {}",
1240-
display_constraint_name(name),
1241-
display_option_spaced(index_name),
1242-
display_comma_separated(columns),
1243-
foreign_table,
1244-
)?;
1245-
if !referred_columns.is_empty() {
1246-
write!(f, "({})", display_comma_separated(referred_columns))?;
1247-
}
1248-
if let Some(action) = on_delete {
1249-
write!(f, " ON DELETE {action}")?;
1250-
}
1251-
if let Some(action) = on_update {
1252-
write!(f, " ON UPDATE {action}")?;
1253-
}
1254-
if let Some(characteristics) = characteristics {
1255-
write!(f, " {characteristics}")?;
1256-
}
1257-
Ok(())
1258-
}
1259-
TableConstraint::Check {
1260-
name,
1261-
expr,
1262-
enforced,
1263-
} => {
1264-
write!(f, "{}CHECK ({})", display_constraint_name(name), expr)?;
1265-
if let Some(b) = enforced {
1266-
write!(f, " {}", if *b { "ENFORCED" } else { "NOT ENFORCED" })
1267-
} else {
1268-
Ok(())
1269-
}
1270-
}
1271-
TableConstraint::Index {
1272-
display_as_key,
1273-
name,
1274-
index_type,
1275-
columns,
1276-
index_options,
1277-
} => {
1278-
write!(f, "{}", if *display_as_key { "KEY" } else { "INDEX" })?;
1279-
if let Some(name) = name {
1280-
write!(f, " {name}")?;
1281-
}
1282-
if let Some(index_type) = index_type {
1283-
write!(f, " USING {index_type}")?;
1284-
}
1285-
write!(f, " ({})", display_comma_separated(columns))?;
1286-
if !index_options.is_empty() {
1287-
write!(f, " {}", display_comma_separated(index_options))?;
1288-
}
1289-
Ok(())
1290-
}
1291-
Self::FulltextOrSpatial {
1292-
fulltext,
1293-
index_type_display,
1294-
opt_index_name,
1295-
columns,
1296-
} => {
1297-
if *fulltext {
1298-
write!(f, "FULLTEXT")?;
1299-
} else {
1300-
write!(f, "SPATIAL")?;
1301-
}
1117+
impl From<ForeignKeyConstraint> for TableConstraint {
1118+
fn from(constraint: ForeignKeyConstraint) -> Self {
1119+
TableConstraint::ForeignKey(constraint)
1120+
}
1121+
}
13021122

1303-
write!(f, "{index_type_display:>}")?;
1123+
impl From<CheckConstraint> for TableConstraint {
1124+
fn from(constraint: CheckConstraint) -> Self {
1125+
TableConstraint::Check(constraint)
1126+
}
1127+
}
13041128

1305-
if let Some(name) = opt_index_name {
1306-
write!(f, " {name}")?;
1307-
}
1129+
impl From<IndexConstraint> for TableConstraint {
1130+
fn from(constraint: IndexConstraint) -> Self {
1131+
TableConstraint::Index(constraint)
1132+
}
1133+
}
13081134

1309-
write!(f, " ({})", display_comma_separated(columns))?;
1135+
impl From<FullTextOrSpatialConstraint> for TableConstraint {
1136+
fn from(constraint: FullTextOrSpatialConstraint) -> Self {
1137+
TableConstraint::FulltextOrSpatial(constraint)
1138+
}
1139+
}
13101140

1311-
Ok(())
1312-
}
1141+
impl fmt::Display for TableConstraint {
1142+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1143+
match self {
1144+
TableConstraint::Unique(constraint) => constraint.fmt(f),
1145+
TableConstraint::PrimaryKey(constraint) => constraint.fmt(f),
1146+
TableConstraint::ForeignKey(constraint) => constraint.fmt(f),
1147+
TableConstraint::Check(constraint) => constraint.fmt(f),
1148+
TableConstraint::Index(constraint) => constraint.fmt(f),
1149+
TableConstraint::FulltextOrSpatial(constraint) => constraint.fmt(f),
13131150
}
13141151
}
13151152
}
@@ -2065,7 +1902,7 @@ pub enum GeneratedExpressionMode {
20651902
}
20661903

20671904
#[must_use]
2068-
fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
1905+
pub fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
20691906
struct ConstraintName<'a>(&'a Option<Ident>);
20701907
impl fmt::Display for ConstraintName<'_> {
20711908
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -2082,7 +1919,7 @@ fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
20821919
/// * `Some(inner)` => create display struct for `"{prefix}{inner}{postfix}"`
20831920
/// * `_` => do nothing
20841921
#[must_use]
2085-
fn display_option<'a, T: fmt::Display>(
1922+
pub fn display_option<'a, T: fmt::Display>(
20861923
prefix: &'a str,
20871924
postfix: &'a str,
20881925
option: &'a Option<T>,
@@ -2104,7 +1941,7 @@ fn display_option<'a, T: fmt::Display>(
21041941
/// * `Some(inner)` => create display struct for `" {inner}"`
21051942
/// * `_` => do nothing
21061943
#[must_use]
2107-
fn display_option_spaced<T: fmt::Display>(option: &Option<T>) -> impl fmt::Display + '_ {
1944+
pub fn display_option_spaced<T: fmt::Display>(option: &Option<T>) -> impl fmt::Display + '_ {
21081945
display_option(" ", "", option)
21091946
}
21101947

src/ast/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ mod dcl;
118118
mod ddl;
119119
mod dml;
120120
pub mod helpers;
121+
pub mod table_constraints;
122+
pub use table_constraints::{
123+
CheckConstraint, ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint,
124+
PrimaryKeyConstraint, UniqueConstraint,
125+
};
121126
mod operator;
122127
mod query;
123128
mod spans;

0 commit comments

Comments
 (0)