Skip to content

Commit 8c82fc0

Browse files
Moved constraint variant outside of TableConstraint enum (#2054)
Co-authored-by: Ifeanyi Ubah <[email protected]>
1 parent ade4082 commit 8c82fc0

File tree

9 files changed

+688
-484
lines changed

9 files changed

+688
-484
lines changed

src/ast/ddl.rs

Lines changed: 12 additions & 297 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ 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, table_constraints::TableConstraint, ArgMode,
34+
CommentDef, ConditionalStatements, CreateFunctionBody, CreateFunctionUsing,
35+
CreateTableLikeKind, CreateTableOptions, DataType, Expr, FileFormat, FunctionBehavior,
36+
FunctionCalledOnNull, FunctionDeterminismSpecifier, FunctionParallel, HiveDistributionStyle,
37+
HiveFormat, HiveIOFormat, HiveRowFormat, Ident, InitializeKind, MySQLColumnPosition,
38+
ObjectName, OnCommit, OneOrManyWithParens, OperateFunctionArg, OrderByExpr, ProjectionSelect,
39+
Query, RefreshModeKind, RowAccessPolicy, SequenceOptions, Spanned, SqlOption,
40+
StorageSerializationPolicy, TableVersion, Tag, TriggerEvent, TriggerExecBody, TriggerObject,
41+
TriggerPeriod, TriggerReferencing, Value, ValueWithSpan, WrappedCollection,
4242
};
4343
use crate::display_utils::{DisplayCommaSeparated, Indent, NewLine, SpaceOrNewline};
4444
use crate::keywords::Keyword;
@@ -1029,291 +1029,6 @@ impl fmt::Display for AlterColumnOperation {
10291029
}
10301030
}
10311031

1032-
/// A table-level constraint, specified in a `CREATE TABLE` or an
1033-
/// `ALTER TABLE ADD <constraint>` statement.
1034-
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1035-
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1036-
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1037-
pub enum TableConstraint {
1038-
/// MySQL [definition][1] for `UNIQUE` constraints statements:\
1039-
/// * `[CONSTRAINT [<name>]] UNIQUE <index_type_display> [<index_name>] [index_type] (<columns>) <index_options>`
1040-
///
1041-
/// where:
1042-
/// * [index_type][2] is `USING {BTREE | HASH}`
1043-
/// * [index_options][3] is `{index_type | COMMENT 'string' | ... %currently unsupported stmts% } ...`
1044-
/// * [index_type_display][4] is `[INDEX | KEY]`
1045-
///
1046-
/// [1]: https://dev.mysql.com/doc/refman/8.3/en/create-table.html
1047-
/// [2]: IndexType
1048-
/// [3]: IndexOption
1049-
/// [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-
},
1070-
/// MySQL [definition][1] for `PRIMARY KEY` constraints statements:\
1071-
/// * `[CONSTRAINT [<name>]] PRIMARY KEY [index_name] [index_type] (<columns>) <index_options>`
1072-
///
1073-
/// Actually the specification have no `[index_name]` but the next query will complete successfully:
1074-
/// ```sql
1075-
/// CREATE TABLE unspec_table (
1076-
/// xid INT NOT NULL,
1077-
/// CONSTRAINT p_name PRIMARY KEY index_name USING BTREE (xid)
1078-
/// );
1079-
/// ```
1080-
///
1081-
/// where:
1082-
/// * [index_type][2] is `USING {BTREE | HASH}`
1083-
/// * [index_options][3] is `{index_type | COMMENT 'string' | ... %currently unsupported stmts% } ...`
1084-
///
1085-
/// [1]: https://dev.mysql.com/doc/refman/8.3/en/create-table.html
1086-
/// [2]: IndexType
1087-
/// [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-
},
1104-
/// A referential integrity constraint (`[ CONSTRAINT <name> ] FOREIGN KEY (<columns>)
1105-
/// REFERENCES <foreign_table> (<referred_columns>)
1106-
/// { [ON DELETE <referential_action>] [ON UPDATE <referential_action>] |
1107-
/// [ON UPDATE <referential_action>] [ON DELETE <referential_action>]
1108-
/// }`).
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-
},
1121-
/// `[ 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-
},
1129-
/// MySQLs [index definition][1] for index creation. Not present on ANSI so, for now, the usage
1130-
/// is restricted to MySQL, as no other dialects that support this syntax were found.
1131-
///
1132-
/// `{INDEX | KEY} [index_name] [index_type] (key_part,...) [index_option]...`
1133-
///
1134-
/// [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-
},
1149-
/// MySQLs [fulltext][1] definition. Since the [`SPATIAL`][2] definition is exactly the same,
1150-
/// and MySQL displays both the same way, it is part of this definition as well.
1151-
///
1152-
/// Supported syntax:
1153-
///
1154-
/// ```markdown
1155-
/// {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name] (key_part,...)
1156-
///
1157-
/// key_part: col_name
1158-
/// ```
1159-
///
1160-
/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-natural-language.html
1161-
/// [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-
},
1172-
}
1173-
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-
)?;
1219-
1220-
if !index_options.is_empty() {
1221-
write!(f, " {}", display_separated(index_options, " "))?;
1222-
}
1223-
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-
}
1302-
1303-
write!(f, "{index_type_display:>}")?;
1304-
1305-
if let Some(name) = opt_index_name {
1306-
write!(f, " {name}")?;
1307-
}
1308-
1309-
write!(f, " ({})", display_comma_separated(columns))?;
1310-
1311-
Ok(())
1312-
}
1313-
}
1314-
}
1315-
}
1316-
13171032
/// Representation whether a definition can can contains the KEY or INDEX keywords with the same
13181033
/// meaning.
13191034
///
@@ -2065,7 +1780,7 @@ pub enum GeneratedExpressionMode {
20651780
}
20661781

20671782
#[must_use]
2068-
fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
1783+
pub(crate) fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
20691784
struct ConstraintName<'a>(&'a Option<Ident>);
20701785
impl fmt::Display for ConstraintName<'_> {
20711786
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -2082,7 +1797,7 @@ fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
20821797
/// * `Some(inner)` => create display struct for `"{prefix}{inner}{postfix}"`
20831798
/// * `_` => do nothing
20841799
#[must_use]
2085-
fn display_option<'a, T: fmt::Display>(
1800+
pub(crate) fn display_option<'a, T: fmt::Display>(
20861801
prefix: &'a str,
20871802
postfix: &'a str,
20881803
option: &'a Option<T>,
@@ -2104,7 +1819,7 @@ fn display_option<'a, T: fmt::Display>(
21041819
/// * `Some(inner)` => create display struct for `" {inner}"`
21051820
/// * `_` => do nothing
21061821
#[must_use]
2107-
fn display_option_spaced<T: fmt::Display>(option: &Option<T>) -> impl fmt::Display + '_ {
1822+
pub(crate) fn display_option_spaced<T: fmt::Display>(option: &Option<T>) -> impl fmt::Display + '_ {
21081823
display_option(" ", "", option)
21091824
}
21101825

src/ast/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@ pub use self::ddl::{
6868
DropBehavior, DropTrigger, GeneratedAs, GeneratedExpressionMode, IdentityParameters,
6969
IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
7070
IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
71-
ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TableConstraint,
72-
TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
73-
ViewColumnDef,
71+
ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TagsColumnOption,
72+
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef,
7473
};
7574
pub use self::dml::{Delete, Insert};
7675
pub use self::operator::{BinaryOperator, UnaryOperator};
@@ -118,6 +117,11 @@ mod dcl;
118117
mod ddl;
119118
mod dml;
120119
pub mod helpers;
120+
pub mod table_constraints;
121+
pub use table_constraints::{
122+
CheckConstraint, ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint,
123+
PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
124+
};
121125
mod operator;
122126
mod query;
123127
mod spans;
@@ -152,14 +156,14 @@ where
152156
}
153157
}
154158

155-
pub fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
159+
pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
156160
where
157161
T: fmt::Display,
158162
{
159163
DisplaySeparated { slice, sep }
160164
}
161165

162-
pub fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
166+
pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
163167
where
164168
T: fmt::Display,
165169
{

0 commit comments

Comments
 (0)