Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class CreateTable implements Statement {
private DuplicateHandling duplicateHandling;
private Table likeTable;
private Table cloneTable;
private List<Table> inherits;
private ColDataType ofType;
private boolean selectParenthesis;
private boolean useAsKeyword = true;
Expand Down Expand Up @@ -347,6 +348,27 @@ public void setPartitionBound(PartitionBound partitionBound) {
this.partitionBound = partitionBound;
}

/** PostgreSQL parent tables, in declaration order; null if INHERITS is absent. */
public List<Table> getInherits() {
return inherits;
}

public void setInherits(List<Table> inherits) {
this.inherits = inherits;
}

public CreateTable withInherits(List<Table> inherits) {
setInherits(inherits);
return this;
}

/** Shared rendering of the structured parent references. */
public void appendInheritanceTo(StringBuilder builder) {
if (inherits != null) {
builder.append(" INHERITS ").append(PlainSelect.getStringList(inherits, true, true));
}
}

public boolean isSelectParenthesis() {
return selectParenthesis;
}
Expand All @@ -369,6 +391,7 @@ public String toString() {
StringBuilder b = new StringBuilder();
appendCreateClause(b);
appendColumnDefinitions(b);
appendInheritanceTo(b);
if (partitionBound != null) {
b.append(" ").append(partitionBound);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ public static void visit(CreateTable table, Consumer<Expression> expressions,
}
});
}
if (table.getInherits() != null) {
table.getInherits().forEach(parent -> accept(parent, tables));
}
accept(table.getTrailingLikeTable(), tables);
accept(table.getPartitionOf(), tables);
visit(table.getPartitioning(), expressions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public void deParse(CreateTable createTable) {
builder.append(")");
}

createTable.appendInheritanceTo(builder);
if (createTable.getPartitionBound() != null) {
builder.append(' ');
createTable.getPartitionBound().appendTo(builder,
Expand Down
8 changes: 8 additions & 0 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -14984,6 +14984,8 @@ CreateTable CreateTable(boolean isUsingOrReplace):
Table partitionOfTable = null;
PartitionBound partitionBound = null;
ColDataType ofType = null;
Table parent;
List<Table> parents = new ArrayList<Table>();
boolean withData;
}
{
Expand All @@ -15008,6 +15010,8 @@ CreateTable CreateTable(boolean isUsingOrReplace):
[ LOOKAHEAD(2) <K_PARTITION> <K_OF> partitionOfTable=Table()
{ createTable.setPartitionOf(partitionOfTable); } ]
[ LOOKAHEAD(2) (
LOOKAHEAD("(" ")") "(" ")" { createTable.setTableElements(tableElements); }
|
LOOKAHEAD(3) (
"(" tableColumn=RelObjectName() { columns.add(tableColumn); } ("," tableColumn=RelObjectName() { columns.add(tableColumn); } )* ")"
)
Expand All @@ -15024,6 +15028,10 @@ CreateTable CreateTable(boolean isUsingOrReplace):
)
)
]
[ LOOKAHEAD({ isKeywordAhead("INHERITS") }) ContextualKeyword("INHERITS")
"(" parent=Table() { parents.add(parent); }
( "," parent=Table() { parents.add(parent); } )* ")"
{ createTable.setInherits(parents); } ]
[ LOOKAHEAD({ partitionOfTable != null })
partitionBound=PostgreSqlPartitionBound()
{ createTable.setPartitionBound(partitionBound); } ]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2019 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.statement.create;

import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.List;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.util.TableDefinitionTraversal;
import net.sf.jsqlparser.util.TablesNamesFinder;
import net.sf.jsqlparser.util.deparser.StatementDeParser;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class PostgreSqlTableInheritanceTest {
@ParameterizedTest
@ValueSource(strings = {"parent", "public.parent", "public.parent, other.parent2",
"\"Odd.Schema\".\"Parent.Name\""})
void modelsAndVisitsParentTables(String parents) throws JSQLParserException {
for (String definition : new String[] {"()", "(extra INT)", "(LIKE source, extra INT)"}) {
CreateTable table = (CreateTable) CCJSqlParserUtil.parse(
"CREATE TABLE child " + definition + " INHERITS (" + parents
+ ") WITH (fillfactor = 80)");
List<Table> inherited = table.getInherits();
assertEquals(parents.split(", ").length, inherited.size());
assertEquals(parents.split(", ")[0], inherited.get(0).getFullyQualifiedName());
List<Table> visited = new ArrayList<>();
TableDefinitionTraversal.visit(table, e -> {
}, visited::add);
for (Table parent : inherited) {
assertTrue(visited.stream().anyMatch(t -> t == parent));
assertTrue(new TablesNamesFinder().getTables(table)
.contains(parent.getFullyQualifiedName()));
}
roundTrip(table);
inherited.set(0, new Table("replacement"));
assertTrue(table.toString().contains("INHERITS (replacement"));
roundTrip(table);
}
}

@Test
void preservesEmptyDefinitionsAndCanRemoveInheritance() throws JSQLParserException {
CreateTable table =
(CreateTable) CCJSqlParserUtil.parse("CREATE TABLE child () INHERITS (parent)");
assertNotNull(table.getTableElements());
assertTrue(table.getTableElements().isEmpty());
table.setInherits(null);
assertEquals("CREATE TABLE child ()", table.toString());
roundTrip(table);
assertEquals(2, CCJSqlParserUtil.parseStatements(table + "; SELECT 1").size());
}

@ParameterizedTest
@ValueSource(strings = {"()", "(parent,)", "(parent AS p)", "(parent + 1)"})
void rejectsMalformedParentLists(String parents) {
assertThrows(JSQLParserException.class,
() -> CCJSqlParserUtil.parse("CREATE TABLE child () INHERITS " + parents));
}

private static void roundTrip(CreateTable table) throws JSQLParserException {
StringBuilder out = new StringBuilder();
table.accept(new StatementDeParser(out));
assertEquals(table.toString(), out.toString());
assertEquals(out.toString(), CCJSqlParserUtil.parse(out.toString()).toString());
}
}
Loading