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

« back to all changes in this revision

Viewing changes to src/main/java/cz/startnet/utils/pgdiff/parsers/CreateTableParser.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: CreateTableParser.java 86 2007-10-29 11:29:53Z 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.PgSchema;
 
10
import cz.startnet.utils.pgdiff.schema.PgTable;
 
11
 
 
12
import java.util.regex.Matcher;
 
13
import java.util.regex.Pattern;
 
14
 
 
15
 
 
16
/**
 
17
 * Parses CREATE TABLE commands.
 
18
 *
 
19
 * @author fordfrog
 
20
 * @version $Id: CreateTableParser.java 86 2007-10-29 11:29:53Z fordfrog $
 
21
 */
 
22
public class CreateTableParser {
 
23
    /**
 
24
     * Pattern for getting table name from CREATE TABLE.
 
25
     */
 
26
    private static final Pattern PATTERN_TABLE_NAME =
 
27
        Pattern.compile(
 
28
                "CREATE[\\s]+TABLE[\\s]+\"?([^\\s\"]+)\"?[\\s]*\\(",
 
29
                Pattern.CASE_INSENSITIVE);
 
30
 
 
31
    /**
 
32
     * Pattern for getting CONSTRAINT parameters.
 
33
     */
 
34
    private static final Pattern PATTERN_CONSTRAINT =
 
35
        Pattern.compile(
 
36
                "CONSTRAINT[\\s]+\"?([^\\s\"]+)\"?[\\s]+(.*)",
 
37
                Pattern.CASE_INSENSITIVE);
 
38
 
 
39
    /**
 
40
     * Pattern for parsing column definition.
 
41
     */
 
42
    private static final Pattern PATTERN_COLUMN =
 
43
        Pattern.compile(
 
44
                "\"?([^\\s\"]+)\"?[\\s]+(.*)",
 
45
                Pattern.CASE_INSENSITIVE);
 
46
 
 
47
    /**
 
48
     * Pattern for parsing INHERITS.
 
49
     */
 
50
    private static final Pattern PATTERN_INHERITS =
 
51
        Pattern.compile("INHERITS[\\s]+([^;]+)[;]?", Pattern.CASE_INSENSITIVE);
 
52
 
 
53
    /**
 
54
     * Pattern for checking whether string contains WITH OIDS string.
 
55
     */
 
56
    private static final Pattern PATTERN_WITH_OIDS =
 
57
        Pattern.compile(".*WITH[\\s]+OIDS.*", Pattern.CASE_INSENSITIVE);
 
58
 
 
59
    /**
 
60
     * Pattern for checking whether string contains WITHOUT OIDS
 
61
     * string.
 
62
     */
 
63
    private static final Pattern PATTERN_WITHOUT_OIDS =
 
64
        Pattern.compile(".*WITHOUT[\\s]+OIDS.*", Pattern.CASE_INSENSITIVE);
 
65
 
 
66
    /**
 
67
     * Creates a new instance of CreateTableParser.
 
68
     */
 
69
    private CreateTableParser() {
 
70
        super();
 
71
    }
 
72
 
 
73
    /**
 
74
     * Parses CREATE TABLE command.
 
75
     *
 
76
     * @param database database
 
77
     * @param command CREATE TABLE command
 
78
     *
 
79
     * @throws ParserException Thrown if problem occured while parsing DDL.
 
80
     * @throws RuntimeException DOCUMENT ME!
 
81
     */
 
82
    public static void parse(final PgDatabase database, final String command) {
 
83
        String line = command;
 
84
        final Matcher matcher = PATTERN_TABLE_NAME.matcher(line);
 
85
        final String tableName;
 
86
 
 
87
        if (matcher.find()) {
 
88
            tableName = matcher.group(1).trim();
 
89
            line =
 
90
                ParserUtils.removeSubString(
 
91
                        line,
 
92
                        matcher.start(),
 
93
                        matcher.end());
 
94
        } else {
 
95
            throw new ParserException(
 
96
                    ParserException.CANNOT_PARSE_COMMAND + line);
 
97
        }
 
98
 
 
99
        final PgTable table = new PgTable(ParserUtils.getObjectName(tableName));
 
100
        final String schemaName =
 
101
            ParserUtils.getSchemaName(tableName, database);
 
102
        final PgSchema schema = database.getSchema(schemaName);
 
103
 
 
104
        if (schema == null) {
 
105
            throw new RuntimeException(
 
106
                    "Cannot get schema '" + schemaName
 
107
                    + "'. Need to issue 'CREATE SCHEMA " + schemaName
 
108
                    + ";' before 'CREATE TABLE " + tableName + "...;'?");
 
109
        }
 
110
 
 
111
        schema.addTable(table);
 
112
        parseRows(table, ParserUtils.removeLastSemicolon(line));
 
113
    }
 
114
 
 
115
    /**
 
116
     * Parses COLUMN and other DDL within '(' and ')' in CREATE TABLE
 
117
     * definition.
 
118
     *
 
119
     * @param table table being parsed
 
120
     * @param line line being processed
 
121
     *
 
122
     * @throws ParserException Thrown if problem occured while parsing DDL.
 
123
     */
 
124
    private static void parseColumnDefs(final PgTable table, final String line) {
 
125
        if (line.length() > 0) {
 
126
            boolean matched = false;
 
127
            Matcher matcher = PATTERN_CONSTRAINT.matcher(line.trim());
 
128
 
 
129
            if (matcher.matches()) {
 
130
                final PgConstraint constraint =
 
131
                    new PgConstraint(matcher.group(1).trim());
 
132
                table.addConstraint(constraint);
 
133
                constraint.setDefinition(matcher.group(2).trim());
 
134
                constraint.setTableName(table.getName());
 
135
                matched = true;
 
136
            }
 
137
 
 
138
            if (!matched) {
 
139
                matcher = PATTERN_COLUMN.matcher(line);
 
140
 
 
141
                if (matcher.matches()) {
 
142
                    final PgColumn column =
 
143
                        new PgColumn(matcher.group(1).trim());
 
144
                    table.addColumn(column);
 
145
                    column.parseDefinition(matcher.group(2).trim());
 
146
                    matched = true;
 
147
                }
 
148
            }
 
149
 
 
150
            if (!matched) {
 
151
                throw new ParserException(
 
152
                        ParserException.CANNOT_PARSE_COMMAND + line);
 
153
            }
 
154
        }
 
155
    }
 
156
 
 
157
    /**
 
158
     * Parses definitions that are present after column definition is
 
159
     * closed with ')'.
 
160
     *
 
161
     * @param table table being parsed
 
162
     * @param commands commands being processed
 
163
     *
 
164
     * @return true if the command was the last command for CREATE TABLE,
 
165
     *         otherwise false
 
166
     */
 
167
    private static String parsePostColumns(
 
168
        final PgTable table,
 
169
        final String commands) {
 
170
        String line = commands;
 
171
        final Matcher matcher = PATTERN_INHERITS.matcher(line);
 
172
 
 
173
        if (matcher.find()) {
 
174
            table.setInherits(matcher.group(1).trim());
 
175
            line =
 
176
                ParserUtils.removeSubString(
 
177
                        line,
 
178
                        matcher.start(),
 
179
                        matcher.end());
 
180
        }
 
181
 
 
182
        if (PATTERN_WITH_OIDS.matcher(line).matches()) {
 
183
            table.setWithOIDS(true);
 
184
            line = ParserUtils.removeSubString(line, "WITH OIDS");
 
185
        } else if (PATTERN_WITHOUT_OIDS.matcher(line).matches()) {
 
186
            table.setWithOIDS(false);
 
187
            line = ParserUtils.removeSubString(line, "WITHOUT OIDS");
 
188
        }
 
189
 
 
190
        return line;
 
191
    }
 
192
 
 
193
    /**
 
194
     * Parses all rows in CREATE TABLE command.
 
195
     *
 
196
     * @param table table being parsed
 
197
     * @param command command without 'CREATE SEQUENCE ... (' string
 
198
     *
 
199
     * @throws ParserException Thrown if problem occured with parsing of DDL.
 
200
     */
 
201
    private static void parseRows(final PgTable table, final String command) {
 
202
        String line = command;
 
203
        boolean postColumns = false;
 
204
 
 
205
        try {
 
206
            while (line.length() > 0) {
 
207
                final int commandEnd = ParserUtils.getCommandEnd(line, 0);
 
208
                final String subCommand = line.substring(0, commandEnd).trim();
 
209
 
 
210
                if (postColumns) {
 
211
                    line = parsePostColumns(table, subCommand);
 
212
 
 
213
                    break;
 
214
                } else if (line.charAt(commandEnd) == ')') {
 
215
                    postColumns = true;
 
216
                }
 
217
 
 
218
                parseColumnDefs(table, subCommand);
 
219
                line =
 
220
                    (commandEnd >= line.length()) ? ""
 
221
                                                  : line.substring(
 
222
                            commandEnd + 1);
 
223
            }
 
224
        } catch (RuntimeException ex) {
 
225
            throw new ParserException(
 
226
                    ParserException.CANNOT_PARSE_COMMAND + "CREATE TABLE "
 
227
                    + table.getName() + " ( " + command,
 
228
                    ex);
 
229
        }
 
230
 
 
231
        line = line.trim();
 
232
 
 
233
        if (line.length() > 0) {
 
234
            throw new ParserException(
 
235
                    "Cannot parse CREATE TABLE '" + table.getName()
 
236
                    + "' - do not know how to parse '" + line + "'");
 
237
        }
 
238
    }
 
239
}