~ubuntu-branches/ubuntu/vivid/apgdiff/vivid

« 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: 2010-10-02 19:35:17 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20101002193517-9wesve8sksxcktkc
Tags: 2.2-1
* New upstream version.
* Update homepage location.
* Finally enable test suite, yay!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Copyright 2006 StartNet s.r.o.
 
3
 *
 
4
 * Distributed under MIT license
 
5
 */
1
6
package cz.startnet.utils.pgdiff.parsers;
2
7
 
3
8
import cz.startnet.utils.pgdiff.schema.PgColumn;
6
11
import cz.startnet.utils.pgdiff.schema.PgSchema;
7
12
import cz.startnet.utils.pgdiff.schema.PgTable;
8
13
 
9
 
import java.util.regex.Matcher;
10
 
import java.util.regex.Pattern;
11
 
 
12
14
/**
13
 
 * Parses CREATE TABLE commands.
 
15
 * Parses CREATE TABLE statements.
14
16
 *
15
17
 * @author fordfrog
16
18
 */
17
19
public class CreateTableParser {
18
20
 
19
21
    /**
20
 
     * Pattern for getting table name from CREATE TABLE.
21
 
     */
22
 
    private static final Pattern PATTERN_TABLE_NAME = Pattern.compile(
23
 
            "CREATE[\\s]+TABLE[\\s]+\"?([^\\s\"]+)\"?[\\s]*\\(",
24
 
            Pattern.CASE_INSENSITIVE);
25
 
    /**
26
 
     * Pattern for getting CONSTRAINT parameters.
27
 
     */
28
 
    private static final Pattern PATTERN_CONSTRAINT = Pattern.compile(
29
 
            "CONSTRAINT[\\s]+\"?([^\\s\"]+)\"?[\\s]+(.*)",
30
 
            Pattern.CASE_INSENSITIVE);
31
 
    /**
32
 
     * Pattern for parsing column definition.
33
 
     */
34
 
    private static final Pattern PATTERN_COLUMN = Pattern.compile(
35
 
            "\"?([^\\s\"]+)\"?[\\s]+(.*)", Pattern.CASE_INSENSITIVE);
36
 
    /**
37
 
     * Pattern for parsing INHERITS.
38
 
     */
39
 
    private static final Pattern PATTERN_INHERITS = Pattern.compile(
40
 
            "INHERITS[\\s]+([^;]+)[;]?", Pattern.CASE_INSENSITIVE);
41
 
    /**
42
 
     * Pattern for checking whether string contains WITH OIDS string.
43
 
     */
44
 
    private static final Pattern PATTERN_WITH_OIDS =
45
 
            Pattern.compile(".*WITH[\\s]+OIDS.*", Pattern.CASE_INSENSITIVE);
46
 
    /**
47
 
     * Pattern for checking whether string contains WITHOUT OIDS
48
 
     * string.
49
 
     */
50
 
    private static final Pattern PATTERN_WITHOUT_OIDS =
51
 
            Pattern.compile(".*WITHOUT[\\s]+OIDS.*", Pattern.CASE_INSENSITIVE);
52
 
 
53
 
    /**
54
22
     * Creates a new instance of CreateTableParser.
55
23
     */
56
24
    private CreateTableParser() {
57
 
        super();
58
25
    }
59
26
 
60
27
    /**
61
 
     * Parses CREATE TABLE command.
 
28
     * Parses CREATE TABLE statement.
62
29
     *
63
30
     * @param database database
64
 
     * @param command CREATE TABLE command
65
 
     *
66
 
     * @throws ParserException Thrown if problem occured while parsing DDL.
67
 
     * @throws RuntimeException DOCUMENT ME!
 
31
     * @param statement CREATE TABLE statement
68
32
     */
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;
73
 
 
74
 
        if (matcher.find()) {
75
 
            tableName = matcher.group(1).trim();
76
 
            line = ParserUtils.removeSubString(
77
 
                    line, matcher.start(), matcher.end());
78
 
        } else {
79
 
            throw new ParserException(
80
 
                    ParserException.CANNOT_PARSE_COMMAND + line);
81
 
        }
82
 
 
 
33
    public static void parse(final PgDatabase database,
 
34
            final String statement) {
 
35
        final Parser parser = new Parser(statement);
 
36
        parser.expect("CREATE", "TABLE");
 
37
 
 
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);
93
49
        }
94
50
 
95
51
        schema.addTable(table);
96
 
        parseRows(table, ParserUtils.removeLastSemicolon(line));
97
 
    }
98
 
 
99
 
    /**
100
 
     * Parses COLUMN and other DDL within '(' and ')' in CREATE TABLE
101
 
     * definition.
102
 
     *
103
 
     * @param table table being parsed
104
 
     * @param line line being processed
105
 
     *
106
 
     * @throws ParserException Thrown if problem occured while parsing DDL.
107
 
     */
108
 
    private static void parseColumnDefs(final PgTable table,
109
 
            final String line) {
110
 
        if (line.length() > 0) {
111
 
            boolean matched = false;
112
 
            Matcher matcher = PATTERN_CONSTRAINT.matcher(line.trim());
113
 
 
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());
120
 
                matched = true;
121
 
            }
122
 
 
123
 
            if (!matched) {
124
 
                matcher = PATTERN_COLUMN.matcher(line);
125
 
 
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());
131
 
                    matched = true;
132
 
                }
133
 
            }
134
 
 
135
 
            if (!matched) {
136
 
                throw new ParserException(
137
 
                        ParserException.CANNOT_PARSE_COMMAND + line);
138
 
            }
139
 
        }
140
 
    }
141
 
 
142
 
    /**
143
 
     * Parses definitions that are present after column definition is
144
 
     * closed with ')'.
145
 
     *
146
 
     * @param table table being parsed
147
 
     * @param commands commands being processed
148
 
     *
149
 
     * @return true if the command was the last command for CREATE TABLE,
150
 
     *         otherwise false
151
 
     */
152
 
    private static String parsePostColumns(final PgTable table,
153
 
            final String commands) {
154
 
        String line = commands;
155
 
        final Matcher matcher = PATTERN_INHERITS.matcher(line);
156
 
 
157
 
        if (matcher.find()) {
158
 
            table.setInherits(matcher.group(1).trim());
159
 
            line = ParserUtils.removeSubString(
160
 
                    line, matcher.start(), matcher.end());
161
 
        }
162
 
 
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");
169
 
        }
170
 
 
171
 
        return line;
172
 
    }
173
 
 
174
 
    /**
175
 
     * Parses all rows in CREATE TABLE command.
176
 
     *
177
 
     * @param table table being parsed
178
 
     * @param command command without 'CREATE SEQUENCE ... (' string
179
 
     *
180
 
     * @throws ParserException Thrown if problem occured with parsing of DDL.
181
 
     */
182
 
    private static void parseRows(final PgTable table, final String command) {
183
 
        String line = command;
184
 
        boolean postColumns = false;
185
 
 
186
 
        try {
187
 
            while (line.length() > 0) {
188
 
                final int commandEnd = ParserUtils.getCommandEnd(line, 0);
189
 
                final String subCommand = line.substring(0, commandEnd).trim();
190
 
 
191
 
                if (postColumns) {
192
 
                    line = parsePostColumns(table, subCommand);
193
 
 
194
 
                    break;
195
 
                } else if (line.charAt(commandEnd) == ')') {
196
 
                    postColumns = true;
197
 
                }
198
 
 
199
 
                parseColumnDefs(table, subCommand);
200
 
                line = (commandEnd >= line.length()) ? ""
201
 
                        : line.substring(commandEnd + 1);
202
 
            }
203
 
        } catch (RuntimeException ex) {
204
 
            throw new ParserException(
205
 
                    ParserException.CANNOT_PARSE_COMMAND + "CREATE TABLE "
206
 
                    + table.getName() + " ( " + command, ex);
207
 
        }
208
 
 
209
 
        line = line.trim();
210
 
 
211
 
        if (line.length() > 0) {
212
 
            throw new ParserException(
213
 
                    "Cannot parse CREATE TABLE '" + table.getName()
214
 
                    + "' - do not know how to parse '" + line + "'");
215
 
        }
 
52
 
 
53
        parser.expect("(");
 
54
 
 
55
        while (!parser.expectOptional(")")) {
 
56
            if (parser.expectOptional("CONSTRAINT")) {
 
57
                parseConstraint(parser, table);
 
58
            } else {
 
59
                parseColumn(parser, table);
 
60
            }
 
61
 
 
62
            if (parser.expectOptional(")")) {
 
63
                break;
 
64
            } else {
 
65
                parser.expect(",");
 
66
            }
 
67
        }
 
68
 
 
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");
 
80
                } else {
 
81
                    table.setWith(parser.getExpression());
 
82
                }
 
83
            } else if (parser.expectOptional("TABLESPACE")) {
 
84
                table.setTablespace(parser.parseString());
 
85
            } else {
 
86
                parser.throwUnsupportedCommand();
 
87
            }
 
88
        }
 
89
    }
 
90
 
 
91
    /**
 
92
     * Parses INHERITS.
 
93
     *
 
94
     * @param parser parser
 
95
     * @param table pg table
 
96
     */
 
97
    private static void parseInherits(final Parser parser,
 
98
            final PgTable table) {
 
99
        parser.expect("(");
 
100
 
 
101
        while (!parser.expectOptional(")")) {
 
102
            table.addInherits(
 
103
                    ParserUtils.getObjectName(parser.parseIdentifier()));
 
104
 
 
105
            if (parser.expectOptional(")")) {
 
106
                break;
 
107
            } else {
 
108
                parser.expect(",");
 
109
            }
 
110
        }
 
111
    }
 
112
 
 
113
    /**
 
114
     * Parses CONSTRAINT definition.
 
115
     *
 
116
     * @param parser parser
 
117
     * @param table pg table
 
118
     */
 
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());
 
126
    }
 
127
 
 
128
    /**
 
129
     * Parses column definition.
 
130
     *
 
131
     * @param parser parser
 
132
     * @param table pg table
 
133
     */
 
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());
216
139
    }
217
140
}