Skip to content

Commit 896c088

Browse files
Add support for INHERITS option in CREATE TABLE statement (#1806)
1 parent bbc80d7 commit 896c088

File tree

8 files changed

+71
-2
lines changed

8 files changed

+71
-2
lines changed

src/ast/dml.rs

+8
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ pub struct CreateTable {
182182
/// BigQuery: Table options list.
183183
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
184184
pub options: Option<Vec<SqlOption>>,
185+
/// Postgres `INHERITs` clause, which contains the list of tables from which
186+
/// the new table inherits.
187+
/// <https://www.postgresql.org/docs/current/ddl-inherit.html>
188+
/// <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-INHERITS>
189+
pub inherits: Option<Vec<ObjectName>>,
185190
/// SQLite "STRICT" clause.
186191
/// if the "STRICT" table-option keyword is added to the end, after the closing ")",
187192
/// then strict typing rules apply to that table.
@@ -405,6 +410,9 @@ impl Display for CreateTable {
405410
if let Some(order_by) = &self.order_by {
406411
write!(f, " ORDER BY {}", order_by)?;
407412
}
413+
if let Some(inherits) = &self.inherits {
414+
write!(f, " INHERITS ({})", display_comma_separated(inherits))?;
415+
}
408416
if let Some(partition_by) = self.partition_by.as_ref() {
409417
write!(f, " PARTITION BY {partition_by}")?;
410418
}

src/ast/helpers/stmt_create_table.rs

+11
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pub struct CreateTableBuilder {
9797
pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
9898
pub clustered_by: Option<ClusteredBy>,
9999
pub options: Option<Vec<SqlOption>>,
100+
pub inherits: Option<Vec<ObjectName>>,
100101
pub strict: bool,
101102
pub copy_grants: bool,
102103
pub enable_schema_evolution: Option<bool>,
@@ -151,6 +152,7 @@ impl CreateTableBuilder {
151152
cluster_by: None,
152153
clustered_by: None,
153154
options: None,
155+
inherits: None,
154156
strict: false,
155157
copy_grants: false,
156158
enable_schema_evolution: None,
@@ -331,6 +333,11 @@ impl CreateTableBuilder {
331333
self
332334
}
333335

336+
pub fn inherits(mut self, inherits: Option<Vec<ObjectName>>) -> Self {
337+
self.inherits = inherits;
338+
self
339+
}
340+
334341
pub fn strict(mut self, strict: bool) -> Self {
335342
self.strict = strict;
336343
self
@@ -451,6 +458,7 @@ impl CreateTableBuilder {
451458
cluster_by: self.cluster_by,
452459
clustered_by: self.clustered_by,
453460
options: self.options,
461+
inherits: self.inherits,
454462
strict: self.strict,
455463
copy_grants: self.copy_grants,
456464
enable_schema_evolution: self.enable_schema_evolution,
@@ -512,6 +520,7 @@ impl TryFrom<Statement> for CreateTableBuilder {
512520
cluster_by,
513521
clustered_by,
514522
options,
523+
inherits,
515524
strict,
516525
copy_grants,
517526
enable_schema_evolution,
@@ -560,6 +569,7 @@ impl TryFrom<Statement> for CreateTableBuilder {
560569
cluster_by,
561570
clustered_by,
562571
options,
572+
inherits,
563573
strict,
564574
iceberg,
565575
copy_grants,
@@ -591,6 +601,7 @@ pub(crate) struct CreateTableConfiguration {
591601
pub partition_by: Option<Box<Expr>>,
592602
pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
593603
pub options: Option<Vec<SqlOption>>,
604+
pub inherits: Option<Vec<ObjectName>>,
594605
}
595606

596607
#[cfg(test)]

src/ast/spans.rs

+1
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ impl Spanned for CreateTable {
581581
cluster_by: _, // todo, BigQuery specific
582582
clustered_by: _, // todo, Hive specific
583583
options: _, // todo, BigQuery specific
584+
inherits: _, // todo, PostgreSQL specific
584585
strict: _, // bool
585586
copy_grants: _, // bool
586587
enable_schema_evolution: _, // bool

src/keywords.rs

+1
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ define_keywords!(
430430
INDEX,
431431
INDICATOR,
432432
INHERIT,
433+
INHERITS,
433434
INITIALLY,
434435
INNER,
435436
INOUT,

src/parser/mod.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -7050,6 +7050,7 @@ impl<'a> Parser<'a> {
70507050
.partition_by(create_table_config.partition_by)
70517051
.cluster_by(create_table_config.cluster_by)
70527052
.options(create_table_config.options)
7053+
.inherits(create_table_config.inherits)
70537054
.primary_key(primary_key)
70547055
.strict(strict)
70557056
.build())
@@ -7070,13 +7071,20 @@ impl<'a> Parser<'a> {
70707071
}
70717072
}
70727073

7073-
/// Parse configuration like partitioning, clustering information during the table creation.
7074+
/// Parse configuration like inheritance, partitioning, clustering information during the table creation.
70747075
///
70757076
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_2)
7076-
/// [PostgreSQL](https://www.postgresql.org/docs/current/ddl-partitioning.html)
7077+
/// [PostgreSQL Partitioning](https://www.postgresql.org/docs/current/ddl-partitioning.html)
7078+
/// [PostgreSQL Inheritance](https://www.postgresql.org/docs/current/ddl-inherit.html)
70777079
fn parse_optional_create_table_config(
70787080
&mut self,
70797081
) -> Result<CreateTableConfiguration, ParserError> {
7082+
let inherits = if self.parse_keyword(Keyword::INHERITS) {
7083+
Some(self.parse_parenthesized_qualified_column_list(IsOptional::Mandatory, false)?)
7084+
} else {
7085+
None
7086+
};
7087+
70807088
let partition_by = if dialect_of!(self is BigQueryDialect | PostgreSqlDialect | GenericDialect)
70817089
&& self.parse_keywords(&[Keyword::PARTITION, Keyword::BY])
70827090
{
@@ -7105,6 +7113,7 @@ impl<'a> Parser<'a> {
71057113
partition_by,
71067114
cluster_by,
71077115
options,
7116+
inherits,
71087117
})
71097118
}
71107119

tests/sqlparser_duckdb.rs

+1
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,7 @@ fn test_duckdb_union_datatype() {
756756
cluster_by: Default::default(),
757757
clustered_by: Default::default(),
758758
options: Default::default(),
759+
inherits: Default::default(),
759760
strict: Default::default(),
760761
copy_grants: Default::default(),
761762
enable_schema_evolution: Default::default(),

tests/sqlparser_mssql.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,7 @@ fn parse_create_table_with_valid_options() {
15941594
cluster_by: None,
15951595
clustered_by: None,
15961596
options: None,
1597+
inherits: None,
15971598
strict: false,
15981599
iceberg: false,
15991600
copy_grants: false,
@@ -1764,6 +1765,7 @@ fn parse_create_table_with_identity_column() {
17641765
cluster_by: None,
17651766
clustered_by: None,
17661767
options: None,
1768+
inherits: None,
17671769
strict: false,
17681770
copy_grants: false,
17691771
enable_schema_evolution: None,

tests/sqlparser_postgres.rs

+36
Original file line numberDiff line numberDiff line change
@@ -2733,6 +2733,41 @@ fn parse_create_brin() {
27332733
}
27342734
}
27352735

2736+
#[test]
2737+
fn parse_create_table_with_inherits() {
2738+
let single_inheritance_sql =
2739+
"CREATE TABLE child_table (child_column INT) INHERITS (public.parent_table)";
2740+
match pg().verified_stmt(single_inheritance_sql) {
2741+
Statement::CreateTable(CreateTable {
2742+
inherits: Some(inherits),
2743+
..
2744+
}) => {
2745+
assert_eq_vec(&["public", "parent_table"], &inherits[0].0);
2746+
}
2747+
_ => unreachable!(),
2748+
}
2749+
2750+
let double_inheritance_sql = "CREATE TABLE child_table (child_column INT) INHERITS (public.parent_table, pg_catalog.pg_settings)";
2751+
match pg().verified_stmt(double_inheritance_sql) {
2752+
Statement::CreateTable(CreateTable {
2753+
inherits: Some(inherits),
2754+
..
2755+
}) => {
2756+
assert_eq_vec(&["public", "parent_table"], &inherits[0].0);
2757+
assert_eq_vec(&["pg_catalog", "pg_settings"], &inherits[1].0);
2758+
}
2759+
_ => unreachable!(),
2760+
}
2761+
}
2762+
2763+
#[test]
2764+
fn parse_create_table_with_empty_inherits_fails() {
2765+
assert!(matches!(
2766+
pg().parse_sql_statements("CREATE TABLE child_table (child_column INT) INHERITS ()"),
2767+
Err(ParserError::ParserError(_))
2768+
));
2769+
}
2770+
27362771
#[test]
27372772
fn parse_create_index_concurrently() {
27382773
let sql = "CREATE INDEX CONCURRENTLY IF NOT EXISTS my_index ON my_table(col1,col2)";
@@ -5426,6 +5461,7 @@ fn parse_trigger_related_functions() {
54265461
cluster_by: None,
54275462
clustered_by: None,
54285463
options: None,
5464+
inherits: None,
54295465
strict: false,
54305466
copy_grants: false,
54315467
enable_schema_evolution: None,

0 commit comments

Comments
 (0)