~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: 2010-10-11 09:08:18 UTC
  • mfrom: (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20101011090818-sdw8yfemrnxo328k
Tags: 2.2.2-1
* New upstream version.
* Using changelog included in zipfile, thanks Miroslav for providing this.
* Update manpage.

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
 
 
8
import cz.startnet.utils.pgdiff.Resources;
3
9
import cz.startnet.utils.pgdiff.schema.PgColumn;
4
10
import cz.startnet.utils.pgdiff.schema.PgConstraint;
5
11
import cz.startnet.utils.pgdiff.schema.PgDatabase;
6
12
import cz.startnet.utils.pgdiff.schema.PgSchema;
7
13
import cz.startnet.utils.pgdiff.schema.PgTable;
8
 
 
9
 
import java.util.regex.Matcher;
10
 
import java.util.regex.Pattern;
 
14
import java.text.MessageFormat;
11
15
 
12
16
/**
13
 
 * Parses CREATE TABLE commands.
 
17
 * Parses CREATE TABLE statements.
14
18
 *
15
19
 * @author fordfrog
16
20
 */
17
21
public class CreateTableParser {
18
22
 
19
23
    /**
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
24
     * Creates a new instance of CreateTableParser.
55
25
     */
56
26
    private CreateTableParser() {
57
 
        super();
58
27
    }
59
28
 
60
29
    /**
61
 
     * Parses CREATE TABLE command.
 
30
     * Parses CREATE TABLE statement.
62
31
     *
63
32
     * @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!
 
33
     * @param statement CREATE TABLE statement
68
34
     */
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
 
 
 
35
    public static void parse(final PgDatabase database,
 
36
            final String statement) {
 
37
        final Parser parser = new Parser(statement);
 
38
        parser.expect("CREATE", "TABLE");
 
39
 
 
40
        final String tableName = parser.parseIdentifier();
83
41
        final PgTable table = new PgTable(ParserUtils.getObjectName(tableName));
84
42
        final String schemaName =
85
43
                ParserUtils.getSchemaName(tableName, database);
86
44
        final PgSchema schema = database.getSchema(schemaName);
87
45
 
88
46
        if (schema == null) {
89
 
            throw new RuntimeException(
90
 
                    "Cannot get schema '" + schemaName
91
 
                    + "'. Need to issue 'CREATE SCHEMA " + schemaName
92
 
                    + ";' before 'CREATE TABLE " + tableName + "...;'?");
 
47
            throw new RuntimeException(MessageFormat.format(
 
48
                    Resources.getString("CannotFindSchemaCreateTable"),
 
49
                    schemaName, tableName));
93
50
        }
94
51
 
95
52
        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
 
        }
 
53
 
 
54
        parser.expect("(");
 
55
 
 
56
        while (!parser.expectOptional(")")) {
 
57
            if (parser.expectOptional("CONSTRAINT")) {
 
58
                parseConstraint(parser, table);
 
59
            } else {
 
60
                parseColumn(parser, table);
 
61
            }
 
62
 
 
63
            if (parser.expectOptional(")")) {
 
64
                break;
 
65
            } else {
 
66
                parser.expect(",");
 
67
            }
 
68
        }
 
69
 
 
70
        while (!parser.expectOptional(";")) {
 
71
            if (parser.expectOptional("INHERITS")) {
 
72
                parseInherits(parser, table);
 
73
            } else if (parser.expectOptional("WITHOUT")) {
 
74
                table.setWith("OIDS=false");
 
75
            } else if (parser.expectOptional("WITH")) {
 
76
                if (parser.expectOptional("OIDS")
 
77
                        || parser.expectOptional("OIDS=true")) {
 
78
                    table.setWith("OIDS=true");
 
79
                } else if (parser.expectOptional("OIDS=false")) {
 
80
                    table.setWith("OIDS=false");
 
81
                } else {
 
82
                    table.setWith(parser.getExpression());
 
83
                }
 
84
            } else if (parser.expectOptional("TABLESPACE")) {
 
85
                table.setTablespace(parser.parseString());
 
86
            } else {
 
87
                parser.throwUnsupportedCommand();
 
88
            }
 
89
        }
 
90
    }
 
91
 
 
92
    /**
 
93
     * Parses INHERITS.
 
94
     *
 
95
     * @param parser parser
 
96
     * @param table pg table
 
97
     */
 
98
    private static void parseInherits(final Parser parser,
 
99
            final PgTable table) {
 
100
        parser.expect("(");
 
101
 
 
102
        while (!parser.expectOptional(")")) {
 
103
            table.addInherits(
 
104
                    ParserUtils.getObjectName(parser.parseIdentifier()));
 
105
 
 
106
            if (parser.expectOptional(")")) {
 
107
                break;
 
108
            } else {
 
109
                parser.expect(",");
 
110
            }
 
111
        }
 
112
    }
 
113
 
 
114
    /**
 
115
     * Parses CONSTRAINT definition.
 
116
     *
 
117
     * @param parser parser
 
118
     * @param table pg table
 
119
     */
 
120
    private static void parseConstraint(final Parser parser,
 
121
            final PgTable table) {
 
122
        final PgConstraint constraint = new PgConstraint(
 
123
                ParserUtils.getObjectName(parser.parseIdentifier()));
 
124
        table.addConstraint(constraint);
 
125
        constraint.setDefinition(parser.getExpression());
 
126
        constraint.setTableName(table.getName());
 
127
    }
 
128
 
 
129
    /**
 
130
     * Parses column definition.
 
131
     *
 
132
     * @param parser parser
 
133
     * @param table pg table
 
134
     */
 
135
    private static void parseColumn(final Parser parser, final PgTable table) {
 
136
        final PgColumn column = new PgColumn(
 
137
                ParserUtils.getObjectName(parser.parseIdentifier()));
 
138
        table.addColumn(column);
 
139
        column.parseDefinition(parser.getExpression());
216
140
    }
217
141
}