Skip to content

Commit b5ac814

Browse files
Merge table-constraint-struct into future-main
2 parents 7fb5af6 + 7e72e20 commit b5ac814

File tree

9 files changed

+690
-483
lines changed

9 files changed

+690
-483
lines changed

src/ast/ddl.rs

Lines changed: 15 additions & 298 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,20 @@ use serde::{Deserialize, Serialize};
2828
#[cfg(feature = "visitor")]
2929
use sqlparser_derive::{Visit, VisitMut};
3030

31+
use crate::ast::helpers::attached_token::AttachedToken;
32+
use crate::ast::table_constraints::TableConstraint;
3133
use crate::ast::value::escape_single_quote_string;
3234
use crate::ast::{
33-
display_comma_separated, display_separated, ArgMode, AttachedToken, CommentDef,
34-
ConditionalStatements, CreateFunctionBody, CreateFunctionUsing, CreateTableLikeKind,
35-
CreateTableOptions, CreateViewParams, DataType, Expr, FileFormat, FunctionBehavior,
36-
FunctionCalledOnNull, FunctionDesc, FunctionDeterminismSpecifier, FunctionParallel,
37-
HiveDistributionStyle, HiveFormat, HiveIOFormat, HiveRowFormat, HiveSetLocation, Ident,
38-
InitializeKind, MySQLColumnPosition, ObjectName, OnCommit, OneOrManyWithParens,
39-
OperateFunctionArg, OrderByExpr, ProjectionSelect, Query, RefreshModeKind, RowAccessPolicy,
40-
SequenceOptions, Spanned, SqlOption, StorageSerializationPolicy, TableVersion, Tag,
41-
TriggerEvent, TriggerExecBody, TriggerObject, TriggerPeriod, TriggerReferencing, Value,
42-
ValueWithSpan, WrappedCollection,
35+
display_comma_separated, display_separated, ArgMode, CommentDef, ConditionalStatements,
36+
CreateFunctionBody, CreateFunctionUsing, CreateTableLikeKind, CreateTableOptions,
37+
CreateViewParams, DataType, Expr, FileFormat, FunctionBehavior, FunctionCalledOnNull,
38+
FunctionDesc, FunctionDeterminismSpecifier, FunctionParallel, HiveDistributionStyle,
39+
HiveFormat, HiveIOFormat, HiveRowFormat, HiveSetLocation, Ident, InitializeKind,
40+
MySQLColumnPosition, ObjectName, OnCommit, OneOrManyWithParens, OperateFunctionArg,
41+
OrderByExpr, ProjectionSelect, Query, RefreshModeKind, RowAccessPolicy, SequenceOptions,
42+
Spanned, SqlOption, StorageSerializationPolicy, TableVersion, Tag, TriggerEvent,
43+
TriggerExecBody, TriggerObject, TriggerPeriod, TriggerReferencing, Value, ValueWithSpan,
44+
WrappedCollection,
4345
};
4446
use crate::display_utils::{DisplayCommaSeparated, Indent, NewLine, SpaceOrNewline};
4547
use crate::keywords::Keyword;
@@ -1030,291 +1032,6 @@ impl fmt::Display for AlterColumnOperation {
10301032
}
10311033
}
10321034

1033-
/// A table-level constraint, specified in a `CREATE TABLE` or an
1034-
/// `ALTER TABLE ADD <constraint>` statement.
1035-
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1036-
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1037-
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1038-
pub enum TableConstraint {
1039-
/// MySQL [definition][1] for `UNIQUE` constraints statements:\
1040-
/// * `[CONSTRAINT [<name>]] UNIQUE <index_type_display> [<index_name>] [index_type] (<columns>) <index_options>`
1041-
///
1042-
/// where:
1043-
/// * [index_type][2] is `USING {BTREE | HASH}`
1044-
/// * [index_options][3] is `{index_type | COMMENT 'string' | ... %currently unsupported stmts% } ...`
1045-
/// * [index_type_display][4] is `[INDEX | KEY]`
1046-
///
1047-
/// [1]: https://dev.mysql.com/doc/refman/8.3/en/create-table.html
1048-
/// [2]: IndexType
1049-
/// [3]: IndexOption
1050-
/// [4]: KeyOrIndexDisplay
1051-
Unique {
1052-
/// Constraint name.
1053-
///
1054-
/// Can be not the same as `index_name`
1055-
name: Option<Ident>,
1056-
/// Index name
1057-
index_name: Option<Ident>,
1058-
/// Whether the type is followed by the keyword `KEY`, `INDEX`, or no keyword at all.
1059-
index_type_display: KeyOrIndexDisplay,
1060-
/// Optional `USING` of [index type][1] statement before columns.
1061-
///
1062-
/// [1]: IndexType
1063-
index_type: Option<IndexType>,
1064-
/// Identifiers of the columns that are unique.
1065-
columns: Vec<IndexColumn>,
1066-
index_options: Vec<IndexOption>,
1067-
characteristics: Option<ConstraintCharacteristics>,
1068-
/// Optional Postgres nulls handling: `[ NULLS [ NOT ] DISTINCT ]`
1069-
nulls_distinct: NullsDistinctOption,
1070-
},
1071-
/// MySQL [definition][1] for `PRIMARY KEY` constraints statements:\
1072-
/// * `[CONSTRAINT [<name>]] PRIMARY KEY [index_name] [index_type] (<columns>) <index_options>`
1073-
///
1074-
/// Actually the specification have no `[index_name]` but the next query will complete successfully:
1075-
/// ```sql
1076-
/// CREATE TABLE unspec_table (
1077-
/// xid INT NOT NULL,
1078-
/// CONSTRAINT p_name PRIMARY KEY index_name USING BTREE (xid)
1079-
/// );
1080-
/// ```
1081-
///
1082-
/// where:
1083-
/// * [index_type][2] is `USING {BTREE | HASH}`
1084-
/// * [index_options][3] is `{index_type | COMMENT 'string' | ... %currently unsupported stmts% } ...`
1085-
///
1086-
/// [1]: https://dev.mysql.com/doc/refman/8.3/en/create-table.html
1087-
/// [2]: IndexType
1088-
/// [3]: IndexOption
1089-
PrimaryKey {
1090-
/// Constraint name.
1091-
///
1092-
/// Can be not the same as `index_name`
1093-
name: Option<Ident>,
1094-
/// Index name
1095-
index_name: Option<Ident>,
1096-
/// Optional `USING` of [index type][1] statement before columns.
1097-
///
1098-
/// [1]: IndexType
1099-
index_type: Option<IndexType>,
1100-
/// Identifiers of the columns that form the primary key.
1101-
columns: Vec<IndexColumn>,
1102-
index_options: Vec<IndexOption>,
1103-
characteristics: Option<ConstraintCharacteristics>,
1104-
},
1105-
/// A referential integrity constraint (`[ CONSTRAINT <name> ] FOREIGN KEY (<columns>)
1106-
/// REFERENCES <foreign_table> (<referred_columns>)
1107-
/// { [ON DELETE <referential_action>] [ON UPDATE <referential_action>] |
1108-
/// [ON UPDATE <referential_action>] [ON DELETE <referential_action>]
1109-
/// }`).
1110-
ForeignKey {
1111-
name: Option<Ident>,
1112-
/// MySQL-specific field
1113-
/// <https://dev.mysql.com/doc/refman/8.4/en/create-table-foreign-keys.html>
1114-
index_name: Option<Ident>,
1115-
columns: Vec<Ident>,
1116-
foreign_table: ObjectName,
1117-
referred_columns: Vec<Ident>,
1118-
on_delete: Option<ReferentialAction>,
1119-
on_update: Option<ReferentialAction>,
1120-
characteristics: Option<ConstraintCharacteristics>,
1121-
},
1122-
/// `[ CONSTRAINT <name> ] CHECK (<expr>) [[NOT] ENFORCED]`
1123-
Check {
1124-
name: Option<Ident>,
1125-
expr: Box<Expr>,
1126-
/// MySQL-specific syntax
1127-
/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
1128-
enforced: Option<bool>,
1129-
},
1130-
/// MySQLs [index definition][1] for index creation. Not present on ANSI so, for now, the usage
1131-
/// is restricted to MySQL, as no other dialects that support this syntax were found.
1132-
///
1133-
/// `{INDEX | KEY} [index_name] [index_type] (key_part,...) [index_option]...`
1134-
///
1135-
/// [1]: https://dev.mysql.com/doc/refman/8.0/en/create-table.html
1136-
Index {
1137-
/// Whether this index starts with KEY (true) or INDEX (false), to maintain the same syntax.
1138-
display_as_key: bool,
1139-
/// Index name.
1140-
name: Option<Ident>,
1141-
/// Optional [index type][1].
1142-
///
1143-
/// [1]: IndexType
1144-
index_type: Option<IndexType>,
1145-
/// Referred column identifier list.
1146-
columns: Vec<IndexColumn>,
1147-
/// Optional index options such as `USING`; see [`IndexOption`].
1148-
index_options: Vec<IndexOption>,
1149-
},
1150-
/// MySQLs [fulltext][1] definition. Since the [`SPATIAL`][2] definition is exactly the same,
1151-
/// and MySQL displays both the same way, it is part of this definition as well.
1152-
///
1153-
/// Supported syntax:
1154-
///
1155-
/// ```markdown
1156-
/// {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name] (key_part,...)
1157-
///
1158-
/// key_part: col_name
1159-
/// ```
1160-
///
1161-
/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-natural-language.html
1162-
/// [2]: https://dev.mysql.com/doc/refman/8.0/en/spatial-types.html
1163-
FulltextOrSpatial {
1164-
/// Whether this is a `FULLTEXT` (true) or `SPATIAL` (false) definition.
1165-
fulltext: bool,
1166-
/// Whether the type is followed by the keyword `KEY`, `INDEX`, or no keyword at all.
1167-
index_type_display: KeyOrIndexDisplay,
1168-
/// Optional index name.
1169-
opt_index_name: Option<Ident>,
1170-
/// Referred column identifier list.
1171-
columns: Vec<IndexColumn>,
1172-
},
1173-
}
1174-
1175-
impl fmt::Display for TableConstraint {
1176-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1177-
match self {
1178-
TableConstraint::Unique {
1179-
name,
1180-
index_name,
1181-
index_type_display,
1182-
index_type,
1183-
columns,
1184-
index_options,
1185-
characteristics,
1186-
nulls_distinct,
1187-
} => {
1188-
write!(
1189-
f,
1190-
"{}UNIQUE{nulls_distinct}{index_type_display:>}{}{} ({})",
1191-
display_constraint_name(name),
1192-
display_option_spaced(index_name),
1193-
display_option(" USING ", "", index_type),
1194-
display_comma_separated(columns),
1195-
)?;
1196-
1197-
if !index_options.is_empty() {
1198-
write!(f, " {}", display_separated(index_options, " "))?;
1199-
}
1200-
1201-
write!(f, "{}", display_option_spaced(characteristics))?;
1202-
Ok(())
1203-
}
1204-
TableConstraint::PrimaryKey {
1205-
name,
1206-
index_name,
1207-
index_type,
1208-
columns,
1209-
index_options,
1210-
characteristics,
1211-
} => {
1212-
write!(
1213-
f,
1214-
"{}PRIMARY KEY{}{} ({})",
1215-
display_constraint_name(name),
1216-
display_option_spaced(index_name),
1217-
display_option(" USING ", "", index_type),
1218-
display_comma_separated(columns),
1219-
)?;
1220-
1221-
if !index_options.is_empty() {
1222-
write!(f, " {}", display_separated(index_options, " "))?;
1223-
}
1224-
1225-
write!(f, "{}", display_option_spaced(characteristics))?;
1226-
Ok(())
1227-
}
1228-
TableConstraint::ForeignKey {
1229-
name,
1230-
index_name,
1231-
columns,
1232-
foreign_table,
1233-
referred_columns,
1234-
on_delete,
1235-
on_update,
1236-
characteristics,
1237-
} => {
1238-
write!(
1239-
f,
1240-
"{}FOREIGN KEY{} ({}) REFERENCES {}",
1241-
display_constraint_name(name),
1242-
display_option_spaced(index_name),
1243-
display_comma_separated(columns),
1244-
foreign_table,
1245-
)?;
1246-
if !referred_columns.is_empty() {
1247-
write!(f, "({})", display_comma_separated(referred_columns))?;
1248-
}
1249-
if let Some(action) = on_delete {
1250-
write!(f, " ON DELETE {action}")?;
1251-
}
1252-
if let Some(action) = on_update {
1253-
write!(f, " ON UPDATE {action}")?;
1254-
}
1255-
if let Some(characteristics) = characteristics {
1256-
write!(f, " {characteristics}")?;
1257-
}
1258-
Ok(())
1259-
}
1260-
TableConstraint::Check {
1261-
name,
1262-
expr,
1263-
enforced,
1264-
} => {
1265-
write!(f, "{}CHECK ({})", display_constraint_name(name), expr)?;
1266-
if let Some(b) = enforced {
1267-
write!(f, " {}", if *b { "ENFORCED" } else { "NOT ENFORCED" })
1268-
} else {
1269-
Ok(())
1270-
}
1271-
}
1272-
TableConstraint::Index {
1273-
display_as_key,
1274-
name,
1275-
index_type,
1276-
columns,
1277-
index_options,
1278-
} => {
1279-
write!(f, "{}", if *display_as_key { "KEY" } else { "INDEX" })?;
1280-
if let Some(name) = name {
1281-
write!(f, " {name}")?;
1282-
}
1283-
if let Some(index_type) = index_type {
1284-
write!(f, " USING {index_type}")?;
1285-
}
1286-
write!(f, " ({})", display_comma_separated(columns))?;
1287-
if !index_options.is_empty() {
1288-
write!(f, " {}", display_comma_separated(index_options))?;
1289-
}
1290-
Ok(())
1291-
}
1292-
Self::FulltextOrSpatial {
1293-
fulltext,
1294-
index_type_display,
1295-
opt_index_name,
1296-
columns,
1297-
} => {
1298-
if *fulltext {
1299-
write!(f, "FULLTEXT")?;
1300-
} else {
1301-
write!(f, "SPATIAL")?;
1302-
}
1303-
1304-
write!(f, "{index_type_display:>}")?;
1305-
1306-
if let Some(name) = opt_index_name {
1307-
write!(f, " {name}")?;
1308-
}
1309-
1310-
write!(f, " ({})", display_comma_separated(columns))?;
1311-
1312-
Ok(())
1313-
}
1314-
}
1315-
}
1316-
}
1317-
13181035
/// Representation whether a definition can can contains the KEY or INDEX keywords with the same
13191036
/// meaning.
13201037
///
@@ -2066,7 +1783,7 @@ pub enum GeneratedExpressionMode {
20661783
}
20671784

20681785
#[must_use]
2069-
fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
1786+
pub(crate) fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
20701787
struct ConstraintName<'a>(&'a Option<Ident>);
20711788
impl fmt::Display for ConstraintName<'_> {
20721789
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -2083,7 +1800,7 @@ fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
20831800
/// * `Some(inner)` => create display struct for `"{prefix}{inner}{postfix}"`
20841801
/// * `_` => do nothing
20851802
#[must_use]
2086-
fn display_option<'a, T: fmt::Display>(
1803+
pub(crate) fn display_option<'a, T: fmt::Display>(
20871804
prefix: &'a str,
20881805
postfix: &'a str,
20891806
option: &'a Option<T>,
@@ -2105,7 +1822,7 @@ fn display_option<'a, T: fmt::Display>(
21051822
/// * `Some(inner)` => create display struct for `" {inner}"`
21061823
/// * `_` => do nothing
21071824
#[must_use]
2108-
fn display_option_spaced<T: fmt::Display>(option: &Option<T>) -> impl fmt::Display + '_ {
1825+
pub(crate) fn display_option_spaced<T: fmt::Display>(option: &Option<T>) -> impl fmt::Display + '_ {
21091826
display_option(" ", "", option)
21101827
}
21111828

src/ast/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub use self::ddl::{
7070
IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind,
7171
IdentityPropertyOrder, IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, Msck,
7272
NullsDistinctOption, Owner, Partition, ProcedureParam, ReferentialAction, RenameTableNameKind,
73-
ReplicaIdentity, TableConstraint, TagsColumnOption, Truncate,
73+
ReplicaIdentity, TagsColumnOption, TriggerObjectKind, Truncate,
7474
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef,
7575
};
7676
pub use self::dml::{Delete, Insert, Update};
@@ -119,6 +119,11 @@ mod dcl;
119119
mod ddl;
120120
mod dml;
121121
pub mod helpers;
122+
pub mod table_constraints;
123+
pub use table_constraints::{
124+
CheckConstraint, ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint,
125+
PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
126+
};
122127
mod operator;
123128
mod query;
124129
mod spans;
@@ -153,14 +158,14 @@ where
153158
}
154159
}
155160

156-
pub fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
161+
pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
157162
where
158163
T: fmt::Display,
159164
{
160165
DisplaySeparated { slice, sep }
161166
}
162167

163-
pub fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
168+
pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
164169
where
165170
T: fmt::Display,
166171
{

0 commit comments

Comments
 (0)