2
* $Id: AlterTableParser.java 80 2007-09-01 20:25:45Z fordfrog $
4
package cz.startnet.utils.pgdiff.parsers;
6
import cz.startnet.utils.pgdiff.schema.PgColumn;
7
import cz.startnet.utils.pgdiff.schema.PgConstraint;
8
import cz.startnet.utils.pgdiff.schema.PgDatabase;
9
import cz.startnet.utils.pgdiff.schema.PgTable;
11
import java.util.regex.Matcher;
12
import java.util.regex.Pattern;
16
* Parses ALTER TABLE commands.
19
* @version $Id: AlterTableParser.java 80 2007-09-01 20:25:45Z fordfrog $
21
public class AlterTableParser {
23
* Pattern for matching ALTER TABLE ... OWNER TO ...;.
25
private static final Pattern PATTERN_OWNER =
27
"^ALTER[\\s]+TABLE[\\s]+.*[\\s]+OWNER[\\s]+TO[\\s]+.*;$",
28
Pattern.CASE_INSENSITIVE);
31
* Pattern for matching table name and optional definition.
33
private static final Pattern PATTERN_START =
35
"ALTER[\\s]+TABLE[\\s]+(?:ONLY[\\s]+)?\"?([^\\s\"]+)\"?"
37
Pattern.CASE_INSENSITIVE);
40
* Pattern for matching of trailing definition of ALTER TABLE
43
private static final Pattern PATTERN_TRAILING_DEF =
45
"(CLUSTER[\\s]+ON|ALTER[\\s]+COLUMN)[\\s]+\"?([^\\s;\"]+)\"?"
46
+ "(?:[\\s]+SET[\\s]+STATISTICS[\\s]+)?(\\d+)?;?",
47
Pattern.CASE_INSENSITIVE);
50
* Pattern for matching ADD CONSTRAINT row.
52
private static final Pattern PATTERN_ADD_CONSTRAINT =
54
"^ADD[\\s]+CONSTRAINT[\\s]+\"?([^\\s\"]+)\"?[\\s]+(.*)$",
55
Pattern.CASE_INSENSITIVE);
58
* Pattern for matching ADD FOREIGN KEY row.
60
private static final Pattern PATTERN_ADD_FOREIGN_KEY =
62
"^ADD[\\s]+(FOREIGN[\\s]+KEY[\\s]+\\(([^\\s]+)\\)[\\s]+.*)$",
63
Pattern.CASE_INSENSITIVE);
66
* Pattern for matching ALTER COLUMN ... SET DEFAULT ...
68
private static final Pattern PATTERN_SET_DEFAULT =
70
"^ALTER[\\s]+COLUMN[\\s]+\"?([^\\s\"]+)\"?[\\s]+SET[\\s]+"
71
+ "DEFAULT[\\s]+(.*)$",
72
Pattern.CASE_INSENSITIVE);
75
* Pattern for checking whether string is ALTER COLUMN.
77
private static final Pattern PATTERN_ALTER_COLUMN =
78
Pattern.compile("ALTER[\\s]+COLUMN", Pattern.CASE_INSENSITIVE);
81
* Creates a new instance of AlterTableParser.
83
private AlterTableParser() {
88
* Parses ALTER TABLE command.
90
* @param database database
91
* @param command ALTER TABLE command
93
* @throws ParserException Thrown if problem occured while parsing DDL.
95
public static void parse(final PgDatabase database, final String command) {
96
if (!PATTERN_OWNER.matcher(command).matches()) {
97
String line = command;
98
final Matcher matcher = PATTERN_START.matcher(line);
99
final String tableName;
101
if (matcher.find()) {
102
tableName = matcher.group(1).trim();
104
throw new ParserException(
105
ParserException.CANNOT_PARSE_COMMAND + line);
108
final PgTable table =
110
ParserUtils.getSchemaName(tableName, database)).getTable(
111
ParserUtils.getObjectName(tableName));
112
line = ParserUtils.removeLastSemicolon(matcher.group(2));
114
if (PATTERN_TRAILING_DEF.matcher(line).matches()) {
115
parseTraillingDef(table, line.trim());
117
parseRows(table, line);
123
* Parses all rows in ALTER TABLE command.
125
* @param table table being parsed
126
* @param commands commands
128
* @throws ParserException Thrown if problem occured while parsing DDL.
130
private static void parseRows(final PgTable table, final String commands) {
131
String line = commands;
132
String subCommand = null;
134
while (line.length() > 0) {
136
final int commandEnd = ParserUtils.getCommandEnd(line, 0);
137
subCommand = line.substring(0, commandEnd).trim();
139
(commandEnd >= line.length()) ? ""
143
Matcher matcher = PATTERN_ADD_CONSTRAINT.matcher(subCommand);
145
if (matcher.matches()) {
146
final String constraintName = matcher.group(1).trim();
147
final PgConstraint constraint =
148
new PgConstraint(constraintName);
149
table.addConstraint(constraint);
150
constraint.setDefinition(matcher.group(2).trim());
151
constraint.setTableName(table.getName());
155
if (subCommand.length() > 0) {
156
matcher = PATTERN_ADD_FOREIGN_KEY.matcher(subCommand);
158
if (matcher.matches()) {
159
final String columnName = matcher.group(2).trim();
160
final String constraintName =
161
table.getName() + "_" + columnName + "_fkey";
162
final PgConstraint constraint =
163
new PgConstraint(constraintName);
164
table.addConstraint(constraint);
165
constraint.setDefinition(matcher.group(1).trim());
166
constraint.setTableName(table.getName());
171
if (subCommand.length() > 0) {
172
matcher = PATTERN_SET_DEFAULT.matcher(subCommand);
174
if (matcher.matches()) {
175
final String columnName = matcher.group(1).trim();
176
final String defaultValue = matcher.group(2).trim();
178
if (table.containsColumn(columnName)) {
179
final PgColumn column = table.getColumn(columnName);
180
column.setDefaultValue(defaultValue);
182
throw new ParserException(
183
"Cannot find column '" + columnName
184
+ " 'in table '" + table.getName() + "'");
190
} catch (RuntimeException ex) {
191
throw new ParserException(
192
"Cannot parse ALTER TABLE '" + table.getName()
193
+ "', line '" + subCommand + "'",
197
if (subCommand.length() > 0) {
198
throw new ParserException(
199
"Don't know how to parse: " + subCommand);
205
* Parses trailling definition.
207
* @param table table being parsed
208
* @param traillingDef trailling definition
210
private static void parseTraillingDef(
212
final String traillingDef) {
213
final Matcher matcher = PATTERN_TRAILING_DEF.matcher(traillingDef);
215
if (matcher.matches()) {
216
if (PATTERN_ALTER_COLUMN.matcher(matcher.group(1).trim()).matches()) {
218
final String columnName = matcher.group(2).trim();
219
final Integer value = Integer.valueOf(matcher.group(3).trim());
220
final PgColumn col = table.getColumn(columnName);
221
col.setStatistics(value);
224
final String indexName = matcher.group(2).trim();
225
table.setClusterIndexName(indexName);