@@ -28,18 +28,20 @@ use serde::{Deserialize, Serialize};
2828#[ cfg( feature = "visitor" ) ]
2929use sqlparser_derive:: { Visit , VisitMut } ;
3030
31+ use crate :: ast:: helpers:: attached_token:: AttachedToken ;
32+ use crate :: ast:: table_constraints:: TableConstraint ;
3133use crate :: ast:: value:: escape_single_quote_string;
3234use 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} ;
4446use crate :: display_utils:: { DisplayCommaSeparated , Indent , NewLine , SpaceOrNewline } ;
4547use 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
0 commit comments