6
11
import cz.startnet.utils.pgdiff.schema.PgSchema;
7
12
import cz.startnet.utils.pgdiff.schema.PgTable;
9
import java.util.regex.Matcher;
10
import java.util.regex.Pattern;
13
* Parses CREATE TABLE commands.
15
* Parses CREATE TABLE statements.
17
19
public class CreateTableParser {
20
* Pattern for getting table name from CREATE TABLE.
22
private static final Pattern PATTERN_TABLE_NAME = Pattern.compile(
23
"CREATE[\\s]+TABLE[\\s]+\"?([^\\s\"]+)\"?[\\s]*\\(",
24
Pattern.CASE_INSENSITIVE);
26
* Pattern for getting CONSTRAINT parameters.
28
private static final Pattern PATTERN_CONSTRAINT = Pattern.compile(
29
"CONSTRAINT[\\s]+\"?([^\\s\"]+)\"?[\\s]+(.*)",
30
Pattern.CASE_INSENSITIVE);
32
* Pattern for parsing column definition.
34
private static final Pattern PATTERN_COLUMN = Pattern.compile(
35
"\"?([^\\s\"]+)\"?[\\s]+(.*)", Pattern.CASE_INSENSITIVE);
37
* Pattern for parsing INHERITS.
39
private static final Pattern PATTERN_INHERITS = Pattern.compile(
40
"INHERITS[\\s]+([^;]+)[;]?", Pattern.CASE_INSENSITIVE);
42
* Pattern for checking whether string contains WITH OIDS string.
44
private static final Pattern PATTERN_WITH_OIDS =
45
Pattern.compile(".*WITH[\\s]+OIDS.*", Pattern.CASE_INSENSITIVE);
47
* Pattern for checking whether string contains WITHOUT OIDS
50
private static final Pattern PATTERN_WITHOUT_OIDS =
51
Pattern.compile(".*WITHOUT[\\s]+OIDS.*", Pattern.CASE_INSENSITIVE);
54
22
* Creates a new instance of CreateTableParser.
56
24
private CreateTableParser() {
61
* Parses CREATE TABLE command.
28
* Parses CREATE TABLE statement.
63
30
* @param database database
64
* @param command CREATE TABLE command
66
* @throws ParserException Thrown if problem occured while parsing DDL.
67
* @throws RuntimeException DOCUMENT ME!
31
* @param statement CREATE TABLE statement
69
public static void parse(final PgDatabase database, final String command) {
70
String line = command;
71
final Matcher matcher = PATTERN_TABLE_NAME.matcher(line);
72
final String tableName;
75
tableName = matcher.group(1).trim();
76
line = ParserUtils.removeSubString(
77
line, matcher.start(), matcher.end());
79
throw new ParserException(
80
ParserException.CANNOT_PARSE_COMMAND + line);
33
public static void parse(final PgDatabase database,
34
final String statement) {
35
final Parser parser = new Parser(statement);
36
parser.expect("CREATE", "TABLE");
38
final String tableName = parser.parseIdentifier();
83
39
final PgTable table = new PgTable(ParserUtils.getObjectName(tableName));
84
40
final String schemaName =
85
41
ParserUtils.getSchemaName(tableName, database);
95
51
schema.addTable(table);
96
parseRows(table, ParserUtils.removeLastSemicolon(line));
100
* Parses COLUMN and other DDL within '(' and ')' in CREATE TABLE
103
* @param table table being parsed
104
* @param line line being processed
106
* @throws ParserException Thrown if problem occured while parsing DDL.
108
private static void parseColumnDefs(final PgTable table,
110
if (line.length() > 0) {
111
boolean matched = false;
112
Matcher matcher = PATTERN_CONSTRAINT.matcher(line.trim());
114
if (matcher.matches()) {
115
final PgConstraint constraint =
116
new PgConstraint(matcher.group(1).trim());
117
table.addConstraint(constraint);
118
constraint.setDefinition(matcher.group(2).trim());
119
constraint.setTableName(table.getName());
124
matcher = PATTERN_COLUMN.matcher(line);
126
if (matcher.matches()) {
127
final PgColumn column =
128
new PgColumn(matcher.group(1).trim());
129
table.addColumn(column);
130
column.parseDefinition(matcher.group(2).trim());
136
throw new ParserException(
137
ParserException.CANNOT_PARSE_COMMAND + line);
143
* Parses definitions that are present after column definition is
146
* @param table table being parsed
147
* @param commands commands being processed
149
* @return true if the command was the last command for CREATE TABLE,
152
private static String parsePostColumns(final PgTable table,
153
final String commands) {
154
String line = commands;
155
final Matcher matcher = PATTERN_INHERITS.matcher(line);
157
if (matcher.find()) {
158
table.setInherits(matcher.group(1).trim());
159
line = ParserUtils.removeSubString(
160
line, matcher.start(), matcher.end());
163
if (PATTERN_WITH_OIDS.matcher(line).matches()) {
164
table.setWithOIDS(true);
165
line = ParserUtils.removeSubString(line, "WITH OIDS");
166
} else if (PATTERN_WITHOUT_OIDS.matcher(line).matches()) {
167
table.setWithOIDS(false);
168
line = ParserUtils.removeSubString(line, "WITHOUT OIDS");
175
* Parses all rows in CREATE TABLE command.
177
* @param table table being parsed
178
* @param command command without 'CREATE SEQUENCE ... (' string
180
* @throws ParserException Thrown if problem occured with parsing of DDL.
182
private static void parseRows(final PgTable table, final String command) {
183
String line = command;
184
boolean postColumns = false;
187
while (line.length() > 0) {
188
final int commandEnd = ParserUtils.getCommandEnd(line, 0);
189
final String subCommand = line.substring(0, commandEnd).trim();
192
line = parsePostColumns(table, subCommand);
195
} else if (line.charAt(commandEnd) == ')') {
199
parseColumnDefs(table, subCommand);
200
line = (commandEnd >= line.length()) ? ""
201
: line.substring(commandEnd + 1);
203
} catch (RuntimeException ex) {
204
throw new ParserException(
205
ParserException.CANNOT_PARSE_COMMAND + "CREATE TABLE "
206
+ table.getName() + " ( " + command, ex);
211
if (line.length() > 0) {
212
throw new ParserException(
213
"Cannot parse CREATE TABLE '" + table.getName()
214
+ "' - do not know how to parse '" + line + "'");
55
while (!parser.expectOptional(")")) {
56
if (parser.expectOptional("CONSTRAINT")) {
57
parseConstraint(parser, table);
59
parseColumn(parser, table);
62
if (parser.expectOptional(")")) {
69
while (!parser.expectOptional(";")) {
70
if (parser.expectOptional("INHERITS")) {
71
parseInherits(parser, table);
72
} else if (parser.expectOptional("WITHOUT")) {
73
table.setWith("OIDS=false");
74
} else if (parser.expectOptional("WITH")) {
75
if (parser.expectOptional("OIDS")
76
|| parser.expectOptional("OIDS=true")) {
77
table.setWith("OIDS=true");
78
} else if (parser.expectOptional("OIDS=false")) {
79
table.setWith("OIDS=false");
81
table.setWith(parser.getExpression());
83
} else if (parser.expectOptional("TABLESPACE")) {
84
table.setTablespace(parser.parseString());
86
parser.throwUnsupportedCommand();
94
* @param parser parser
95
* @param table pg table
97
private static void parseInherits(final Parser parser,
98
final PgTable table) {
101
while (!parser.expectOptional(")")) {
103
ParserUtils.getObjectName(parser.parseIdentifier()));
105
if (parser.expectOptional(")")) {
114
* Parses CONSTRAINT definition.
116
* @param parser parser
117
* @param table pg table
119
private static void parseConstraint(final Parser parser,
120
final PgTable table) {
121
final PgConstraint constraint = new PgConstraint(
122
ParserUtils.getObjectName(parser.parseIdentifier()));
123
table.addConstraint(constraint);
124
constraint.setDefinition(parser.getExpression());
125
constraint.setTableName(table.getName());
129
* Parses column definition.
131
* @param parser parser
132
* @param table pg table
134
private static void parseColumn(final Parser parser, final PgTable table) {
135
final PgColumn column = new PgColumn(
136
ParserUtils.getObjectName(parser.parseIdentifier()));
137
table.addColumn(column);
138
column.parseDefinition(parser.getExpression());