~ubuntu-branches/ubuntu/raring/apgdiff/raring

« back to all changes in this revision

Viewing changes to src/main/java/cz/startnet/utils/pgdiff/parsers/AlterTableParser.java

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Berg
  • Date: 2008-09-09 15:42:54 UTC
  • Revision ID: james.westby@ubuntu.com-20080909154254-458sv7ew1rczdal1
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: AlterTableParser.java 80 2007-09-01 20:25:45Z fordfrog $
 
3
 */
 
4
package cz.startnet.utils.pgdiff.parsers;
 
5
 
 
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;
 
10
 
 
11
import java.util.regex.Matcher;
 
12
import java.util.regex.Pattern;
 
13
 
 
14
 
 
15
/**
 
16
 * Parses ALTER TABLE commands.
 
17
 *
 
18
 * @author fordfrog
 
19
 * @version $Id: AlterTableParser.java 80 2007-09-01 20:25:45Z fordfrog $
 
20
 */
 
21
public class AlterTableParser {
 
22
    /**
 
23
     * Pattern for matching ALTER TABLE ... OWNER TO ...;.
 
24
     */
 
25
    private static final Pattern PATTERN_OWNER =
 
26
        Pattern.compile(
 
27
                "^ALTER[\\s]+TABLE[\\s]+.*[\\s]+OWNER[\\s]+TO[\\s]+.*;$",
 
28
                Pattern.CASE_INSENSITIVE);
 
29
 
 
30
    /**
 
31
     * Pattern for matching table name and optional definition.
 
32
     */
 
33
    private static final Pattern PATTERN_START =
 
34
        Pattern.compile(
 
35
                "ALTER[\\s]+TABLE[\\s]+(?:ONLY[\\s]+)?\"?([^\\s\"]+)\"?"
 
36
                + "(?:[\\s]+)?(.+)?",
 
37
                Pattern.CASE_INSENSITIVE);
 
38
 
 
39
    /**
 
40
     * Pattern for matching of trailing definition of ALTER TABLE
 
41
     * command.
 
42
     */
 
43
    private static final Pattern PATTERN_TRAILING_DEF =
 
44
        Pattern.compile(
 
45
                "(CLUSTER[\\s]+ON|ALTER[\\s]+COLUMN)[\\s]+\"?([^\\s;\"]+)\"?"
 
46
                + "(?:[\\s]+SET[\\s]+STATISTICS[\\s]+)?(\\d+)?;?",
 
47
                Pattern.CASE_INSENSITIVE);
 
48
 
 
49
    /**
 
50
     * Pattern for matching ADD CONSTRAINT row.
 
51
     */
 
52
    private static final Pattern PATTERN_ADD_CONSTRAINT =
 
53
        Pattern.compile(
 
54
                "^ADD[\\s]+CONSTRAINT[\\s]+\"?([^\\s\"]+)\"?[\\s]+(.*)$",
 
55
                Pattern.CASE_INSENSITIVE);
 
56
 
 
57
    /**
 
58
     * Pattern for matching ADD FOREIGN KEY row.
 
59
     */
 
60
    private static final Pattern PATTERN_ADD_FOREIGN_KEY =
 
61
        Pattern.compile(
 
62
                "^ADD[\\s]+(FOREIGN[\\s]+KEY[\\s]+\\(([^\\s]+)\\)[\\s]+.*)$",
 
63
                Pattern.CASE_INSENSITIVE);
 
64
 
 
65
    /**
 
66
     * Pattern for matching ALTER COLUMN ... SET DEFAULT ...
 
67
     */
 
68
    private static final Pattern PATTERN_SET_DEFAULT =
 
69
        Pattern.compile(
 
70
                "^ALTER[\\s]+COLUMN[\\s]+\"?([^\\s\"]+)\"?[\\s]+SET[\\s]+"
 
71
                + "DEFAULT[\\s]+(.*)$",
 
72
                Pattern.CASE_INSENSITIVE);
 
73
 
 
74
    /**
 
75
     * Pattern for checking whether string is ALTER COLUMN.
 
76
     */
 
77
    private static final Pattern PATTERN_ALTER_COLUMN =
 
78
        Pattern.compile("ALTER[\\s]+COLUMN", Pattern.CASE_INSENSITIVE);
 
79
 
 
80
    /**
 
81
     * Creates a new instance of AlterTableParser.
 
82
     */
 
83
    private AlterTableParser() {
 
84
        super();
 
85
    }
 
86
 
 
87
    /**
 
88
     * Parses ALTER TABLE command.
 
89
     *
 
90
     * @param database database
 
91
     * @param command ALTER TABLE command
 
92
     *
 
93
     * @throws ParserException Thrown if problem occured while parsing DDL.
 
94
     */
 
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;
 
100
 
 
101
            if (matcher.find()) {
 
102
                tableName = matcher.group(1).trim();
 
103
            } else {
 
104
                throw new ParserException(
 
105
                        ParserException.CANNOT_PARSE_COMMAND + line);
 
106
            }
 
107
 
 
108
            final PgTable table =
 
109
                database.getSchema(
 
110
                        ParserUtils.getSchemaName(tableName, database)).getTable(
 
111
                        ParserUtils.getObjectName(tableName));
 
112
            line = ParserUtils.removeLastSemicolon(matcher.group(2));
 
113
 
 
114
            if (PATTERN_TRAILING_DEF.matcher(line).matches()) {
 
115
                parseTraillingDef(table, line.trim());
 
116
            } else {
 
117
                parseRows(table, line);
 
118
            }
 
119
        }
 
120
    }
 
121
 
 
122
    /**
 
123
     * Parses all rows in ALTER TABLE command.
 
124
     *
 
125
     * @param table table being parsed
 
126
     * @param commands commands
 
127
     *
 
128
     * @throws ParserException Thrown if problem occured while parsing DDL.
 
129
     */
 
130
    private static void parseRows(final PgTable table, final String commands) {
 
131
        String line = commands;
 
132
        String subCommand = null;
 
133
 
 
134
        while (line.length() > 0) {
 
135
            try {
 
136
                final int commandEnd = ParserUtils.getCommandEnd(line, 0);
 
137
                subCommand = line.substring(0, commandEnd).trim();
 
138
                line =
 
139
                    (commandEnd >= line.length()) ? ""
 
140
                                                  : line.substring(
 
141
                            commandEnd + 1);
 
142
 
 
143
                Matcher matcher = PATTERN_ADD_CONSTRAINT.matcher(subCommand);
 
144
 
 
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());
 
152
                    subCommand = "";
 
153
                }
 
154
 
 
155
                if (subCommand.length() > 0) {
 
156
                    matcher = PATTERN_ADD_FOREIGN_KEY.matcher(subCommand);
 
157
 
 
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());
 
167
                        subCommand = "";
 
168
                    }
 
169
                }
 
170
 
 
171
                if (subCommand.length() > 0) {
 
172
                    matcher = PATTERN_SET_DEFAULT.matcher(subCommand);
 
173
 
 
174
                    if (matcher.matches()) {
 
175
                        final String columnName = matcher.group(1).trim();
 
176
                        final String defaultValue = matcher.group(2).trim();
 
177
 
 
178
                        if (table.containsColumn(columnName)) {
 
179
                            final PgColumn column = table.getColumn(columnName);
 
180
                            column.setDefaultValue(defaultValue);
 
181
                        } else {
 
182
                            throw new ParserException(
 
183
                                    "Cannot find column '" + columnName
 
184
                                    + " 'in table '" + table.getName() + "'");
 
185
                        }
 
186
 
 
187
                        subCommand = "";
 
188
                    }
 
189
                }
 
190
            } catch (RuntimeException ex) {
 
191
                throw new ParserException(
 
192
                        "Cannot parse ALTER TABLE '" + table.getName()
 
193
                        + "', line '" + subCommand + "'",
 
194
                        ex);
 
195
            }
 
196
 
 
197
            if (subCommand.length() > 0) {
 
198
                throw new ParserException(
 
199
                        "Don't know how to parse: " + subCommand);
 
200
            }
 
201
        }
 
202
    }
 
203
 
 
204
    /**
 
205
     * Parses trailling definition.
 
206
     *
 
207
     * @param table table being parsed
 
208
     * @param traillingDef trailling definition
 
209
     */
 
210
    private static void parseTraillingDef(
 
211
        final PgTable table,
 
212
        final String traillingDef) {
 
213
        final Matcher matcher = PATTERN_TRAILING_DEF.matcher(traillingDef);
 
214
 
 
215
        if (matcher.matches()) {
 
216
            if (PATTERN_ALTER_COLUMN.matcher(matcher.group(1).trim()).matches()) {
 
217
                //Stats
 
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);
 
222
            } else {
 
223
                //Cluster
 
224
                final String indexName = matcher.group(2).trim();
 
225
                table.setClusterIndexName(indexName);
 
226
            }
 
227
        }
 
228
    }
 
229
}