iffyio commented on code in PR #2062:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/2062#discussion_r2419535421


##########
src/ast/mod.rs:
##########
@@ -655,6 +655,40 @@ pub enum CastKind {
     DoubleColon,
 }
 
+/// The MATCH option for foreign key constraints.
+///
+/// Specifies how to match composite foreign keys against the referenced table.
+/// A value inserted into the referencing column(s) is matched against the 
values
+/// of the referenced table and referenced columns using the given match type.

Review Comment:
   ```suggestion
   /// `MATCH` type for constraint references
   ```
   We can avoid defining semantics and leave the description generic so that it 
can be reused correctly in other context (like table constraint references)



##########
src/ast/mod.rs:
##########
@@ -655,6 +655,40 @@ pub enum CastKind {
     DoubleColon,
 }
 
+/// The MATCH option for foreign key constraints.
+///
+/// Specifies how to match composite foreign keys against the referenced table.
+/// A value inserted into the referencing column(s) is matched against the 
values
+/// of the referenced table and referenced columns using the given match type.
+///
+/// See: 
<https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum MatchKind {

Review Comment:
   ```suggestion
   pub enum ConstraintReferenceMatchKind {
   ```
   Thinking `MATCH` might be too generic and likely to conflict naming wise in 
other contexts as a result



##########
src/parser/mod.rs:
##########
@@ -7929,22 +7929,22 @@ impl<'a> Parser<'a> {
         loop {
             if self.parse_keyword(Keyword::CONSTRAINT) {
                 let name = Some(self.parse_identifier()?);
-                if let Some(option) = self.parse_optional_column_option()? {
+                if let Some(option) = 
self.parse_optional_column_option(&col_name)? {

Review Comment:
   not sure what this change implies, it looks like we'd be storing the column 
name twice in the AST node which doesn't seem ideal?



##########
tests/sqlparser_postgres.rs:
##########
@@ -6646,3 +6647,144 @@ fn parse_alter_schema() {
         _ => unreachable!(),
     }
 }
+
+#[test]
+/// Test to verify whether `MATCH FULL` syntax for foreign keys is parsed 
correctly.

Review Comment:
   ```suggestion
   ```
   The comment read superfluous since the fact should be clear from the test 
name



##########
src/ast/mod.rs:
##########
@@ -655,6 +655,40 @@ pub enum CastKind {
     DoubleColon,
 }
 
+/// The MATCH option for foreign key constraints.
+///
+/// Specifies how to match composite foreign keys against the referenced table.
+/// A value inserted into the referencing column(s) is matched against the 
values
+/// of the referenced table and referenced columns using the given match type.
+///
+/// See: 
<https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum MatchKind {
+    /// `MATCH FULL` - Will not allow one column of a multicolumn foreign key 
to be null
+    /// unless all foreign key columns are null; if they are all null, the row 
is not
+    /// required to have a match in the referenced table.
+    Full,
+    /// `MATCH PARTIAL` - Not yet implemented by most databases (part of SQL 
standard).
+    /// Would allow partial matches in multicolumn foreign keys.
+    Partial,
+    /// `MATCH SIMPLE` - The default behavior. Allows any of the foreign key 
columns
+    /// to be null; if any of them are null, the row is not required to have a 
match
+    /// in the referenced table.

Review Comment:
   ```suggestion
       /// `MATCH FULL`
       Full,
       /// `MATCH PARTIAL`
       Partial,
       /// `MATCH SIMPLE`
   ```



##########
tests/sqlparser_postgres.rs:
##########
@@ -6646,3 +6647,144 @@ fn parse_alter_schema() {
         _ => unreachable!(),
     }
 }
+
+#[test]
+/// Test to verify whether `MATCH FULL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_full() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH FULL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH FULL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH FULL
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH FULL
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH SIMPLE` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_simple() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH SIMPLE, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH SIMPLE)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH SIMPLE
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH SIMPLE
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH PARTIAL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_partial() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH PARTIAL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH PARTIAL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH PARTIAL
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, 
Some(MatchKind::Partial));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH PARTIAL

Review Comment:
   ```suggestion
   ```



##########
tests/sqlparser_postgres.rs:
##########
@@ -6646,3 +6647,144 @@ fn parse_alter_schema() {
         _ => unreachable!(),
     }
 }
+
+#[test]
+/// Test to verify whether `MATCH FULL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_full() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH FULL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH FULL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH FULL
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH FULL
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH SIMPLE` syntax for foreign keys is parsed 
correctly.

Review Comment:
   ```suggestion
   ```



##########
tests/sqlparser_postgres.rs:
##########
@@ -6646,3 +6647,144 @@ fn parse_alter_schema() {
         _ => unreachable!(),
     }
 }
+
+#[test]
+/// Test to verify whether `MATCH FULL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_full() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH FULL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH FULL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH FULL
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH FULL
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH SIMPLE` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_simple() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH SIMPLE, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH SIMPLE)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH SIMPLE
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH SIMPLE
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH PARTIAL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_partial() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH PARTIAL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH PARTIAL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH PARTIAL

Review Comment:
   ```suggestion
   ```



##########
tests/sqlparser_postgres.rs:
##########
@@ -6646,3 +6647,144 @@ fn parse_alter_schema() {
         _ => unreachable!(),
     }
 }
+
+#[test]
+/// Test to verify whether `MATCH FULL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_full() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH FULL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH FULL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH FULL
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH FULL
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH SIMPLE` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_simple() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH SIMPLE, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH SIMPLE)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH SIMPLE
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH SIMPLE
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH PARTIAL` syntax for foreign keys is parsed 
correctly.

Review Comment:
   ```suggestion
   ```



##########
tests/sqlparser_postgres.rs:
##########
@@ -6646,3 +6647,144 @@ fn parse_alter_schema() {
         _ => unreachable!(),
     }
 }
+
+#[test]
+/// Test to verify whether `MATCH FULL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_full() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH FULL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH FULL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH FULL
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH FULL
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH SIMPLE` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_simple() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH SIMPLE, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH SIMPLE)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH SIMPLE
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH SIMPLE
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH PARTIAL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_partial() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH PARTIAL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH PARTIAL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH PARTIAL
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, 
Some(MatchKind::Partial));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH PARTIAL
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, 
Some(MatchKind::Partial));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify foreign key MATCH syntax combined with ON DELETE/ON UPDATE 
actions

Review Comment:
   ```suggestion
   ```



##########
tests/sqlparser_postgres.rs:
##########
@@ -6646,3 +6647,144 @@ fn parse_alter_schema() {
         _ => unreachable!(),
     }
 }
+
+#[test]
+/// Test to verify whether `MATCH FULL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_full() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH FULL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH FULL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH FULL
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH FULL
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH SIMPLE` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_simple() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH SIMPLE, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH SIMPLE)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH SIMPLE
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH SIMPLE
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify whether `MATCH PARTIAL` syntax for foreign keys is parsed 
correctly.
+fn parse_foreign_key_match_partial() {
+    let sql = "CREATE TABLE orders (order_id INT PRIMARY KEY REFERENCES 
another_table (id) MATCH PARTIAL, customer_id INT, FOREIGN KEY (customer_id) 
REFERENCES customers(customer_id) MATCH PARTIAL)";
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH PARTIAL
+            assert_eq!(columns[0].name.value, "order_id");
+            match &columns[0].options[1].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, 
Some(MatchKind::Partial));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH PARTIAL
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, 
Some(MatchKind::Partial));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }
+}
+
+#[test]
+/// Test to verify foreign key MATCH syntax combined with ON DELETE/ON UPDATE 
actions
+fn parse_foreign_key_match_with_actions() {
+    let sql = "CREATE TABLE orders (order_id INT REFERENCES another_table (id) 
MATCH FULL ON DELETE CASCADE ON UPDATE RESTRICT, customer_id INT, CONSTRAINT 
fk_customer FOREIGN KEY (customer_id) REFERENCES customers(customer_id) MATCH 
SIMPLE ON DELETE SET NULL ON UPDATE CASCADE)";
+
+    let statement = pg_and_generic().verified_stmt(sql);
+    match statement {
+        Statement::CreateTable(CreateTable {
+            columns,
+            constraints,
+            ..
+        }) => {
+            // Check column-level foreign key with MATCH FULL and actions
+            match &columns[0].options[0].option {
+                ColumnOption::ForeignKey(constraint) => {
+                    assert_eq!(constraint.foreign_table.to_string(), 
"another_table");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Full));
+                    assert_eq!(constraint.on_delete, 
Some(ReferentialAction::Cascade));
+                    assert_eq!(constraint.on_update, 
Some(ReferentialAction::Restrict));
+                }
+                _ => panic!("Expected ColumnOption::ForeignKey"),
+            }
+
+            // Check table-level foreign key constraint with MATCH SIMPLE and 
actions
+            match &constraints[0] {
+                TableConstraint::ForeignKey(constraint) => {
+                    assert_eq!(constraint.name.as_ref().unwrap().value, 
"fk_customer");
+                    assert_eq!(constraint.foreign_table.to_string(), 
"customers");
+                    assert_eq!(constraint.match_kind, Some(MatchKind::Simple));
+                    assert_eq!(constraint.on_delete, 
Some(ReferentialAction::SetNull));
+                    assert_eq!(constraint.on_update, 
Some(ReferentialAction::Cascade));
+                }
+                _ => panic!("Expected TableConstraint::ForeignKey"),
+            }
+        }
+        _ => unreachable!("{:?} should parse to Statement::CreateTable", sql),
+    }

Review Comment:
   ```suggestion
       pg_and_generic().verified_stmt(sql);
   ```
   I think in scenarios like these where we want to verify more complicated 
combinations (or different variant of the same component) and each component 
has already been asserted previously we can rely solely on the  verified_stmt 
assertions to keep the tests leaner. Similarly, given that we've asserted the 
returned AST on say `MATCH FULL` test scenario, we can rely on verified_stmt 
only for the othe variants like `MATCH SIMPLE/PARTIAL`. Leads to significantly 
less test code to maintain going forward



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to