41
47
"^SET[\\s]+search_path[\\s]*=[\\s]*([^,\\s]+)(?:,[\\s]+.*)?;$",
42
48
Pattern.CASE_INSENSITIVE);
44
* Pattern for testing whether command is CREATE TABLE command.
50
* Pattern for testing whether it is CREATE TABLE statement.
46
52
private static final Pattern PATTERN_CREATE_TABLE = Pattern.compile(
47
53
"^CREATE[\\s]+TABLE[\\s]+.*$", Pattern.CASE_INSENSITIVE);
49
* Pattern for testing whether command is CREATE VIEW command.
55
* Pattern for testing whether it is CREATE VIEW statement.
51
57
private static final Pattern PATTERN_CREATE_VIEW = Pattern.compile(
52
58
"^CREATE[\\s]+(?:OR[\\s]+REPLACE[\\s]+)?VIEW[\\s]+.*$",
53
59
Pattern.CASE_INSENSITIVE);
55
* Pattern for testing whether command is ALTER TABLE command.
61
* Pattern for testing whether it is ALTER TABLE statement.
57
63
private static final Pattern PATTERN_ALTER_TABLE =
58
Pattern.compile("^ALTER[\\s]+TABLE[\\s]+.*$", Pattern.CASE_INSENSITIVE);
64
Pattern.compile("^ALTER[\\s]+TABLE[\\s]+.*$",
65
Pattern.CASE_INSENSITIVE);
60
* Pattern for testing whether command is CREATE SEQUENCE command.
67
* Pattern for testing whether it is CREATE SEQUENCE statement.
62
69
private static final Pattern PATTERN_CREATE_SEQUENCE = Pattern.compile(
63
70
"^CREATE[\\s]+SEQUENCE[\\s]+.*$", Pattern.CASE_INSENSITIVE);
65
* Pattern for testing whether command is CREATE INDEX command.
72
* Pattern for testing whether it is CREATE INDEX statement.
67
74
private static final Pattern PATTERN_CREATE_INDEX = Pattern.compile(
68
75
"^CREATE[\\s]+(?:UNIQUE[\\s]+)?INDEX[\\s]+.*$",
69
76
Pattern.CASE_INSENSITIVE);
71
* Pattern for testing whether command is SET command.
73
private static final Pattern PATTERN_SET =
74
Pattern.compile("^SET[\\s]+.*$", Pattern.CASE_INSENSITIVE);
76
* Pattern for testing whether command is COMMENT command.
78
private static final Pattern PATTERN_COMMENT =
79
Pattern.compile("^COMMENT[\\s]+.*$", Pattern.CASE_INSENSITIVE);
81
* Pattern for testing whether command is SELECT command.
78
* Pattern for testing whether it is SELECT statement.
83
80
private static final Pattern PATTERN_SELECT =
84
81
Pattern.compile("^SELECT[\\s]+.*$", Pattern.CASE_INSENSITIVE);
86
* Pattern for testing whether command is INSERT INTO command.
83
* Pattern for testing whether it is INSERT INTO statement.
88
85
private static final Pattern PATTERN_INSERT_INTO =
89
Pattern.compile("^INSERT[\\s]+INTO[\\s]+.*$", Pattern.CASE_INSENSITIVE);
91
* Pattern for testing whether command is REVOKE command.
93
private static final Pattern PATTERN_REVOKE =
94
Pattern.compile("^REVOKE[\\s]+.*$", Pattern.CASE_INSENSITIVE);
96
* Pattern for testing whether command is GRANT command.
98
private static final Pattern PATTERN_GRANT =
99
Pattern.compile("^GRANT[\\s]+.*$", Pattern.CASE_INSENSITIVE);
101
* Pattern for testing whether command is CREATE TRIGGER command.
86
Pattern.compile("^INSERT[\\s]+INTO[\\s]+.*$",
87
Pattern.CASE_INSENSITIVE);
89
* Pattern for testing whether it is UPDATE statement.
91
private static final Pattern PATTERN_UPDATE =
92
Pattern.compile("^UPDATE[\\s].*$", Pattern.CASE_INSENSITIVE);
94
* Pattern for testing whether it is DELETE FROM statement.
96
private static final Pattern PATTERN_DELETE_FROM =
97
Pattern.compile("^DELETE[\\s]+FROM[\\s]+.*$",
98
Pattern.CASE_INSENSITIVE);
100
* Pattern for testing whether it is CREATE TRIGGER statement.
103
102
private static final Pattern PATTERN_CREATE_TRIGGER = Pattern.compile(
104
103
"^CREATE[\\s]+TRIGGER[\\s]+.*$", Pattern.CASE_INSENSITIVE);
106
* Pattern for testing whether command is CREATE FUNCTION or CREATE
107
* OR REPLACE FUNCTION command.
105
* Pattern for testing whether it is CREATE FUNCTION or CREATE OR REPLACE
106
* FUNCTION statement.
109
108
private static final Pattern PATTERN_CREATE_FUNCTION = Pattern.compile(
110
109
"^CREATE[\\s]+(?:OR[\\s]+REPLACE[\\s]+)?FUNCTION[\\s]+.*$",
111
110
Pattern.CASE_INSENSITIVE);
112
* Pattern for testing whether it is ALTER VIEW statement.
114
private static final Pattern PATTERN_ALTER_VIEW = Pattern.compile(
115
"^ALTER[\\s]+VIEW[\\s]+.*$", Pattern.CASE_INSENSITIVE);
113
117
* Pattern for getting the string that is used to end the function
114
118
* or the function definition itself.
116
120
private static final Pattern PATTERN_END_OF_FUNCTION = Pattern.compile(
117
"^(?:.*[\\s]+)?AS[\\s]+(['$][^\\s]*).*$", Pattern.CASE_INSENSITIVE);
121
"^(?:.*[\\s]+)?AS[\\s]+([\\S]+).*$", Pattern.CASE_INSENSITIVE);
120
124
* Creates a new instance of PgDumpLoader.
122
126
private PgDumpLoader() {
171
171
database.setDefaultSchema(matcher.group(1));
172
172
} else if (PATTERN_CREATE_TABLE.matcher(line).matches()) {
173
173
CreateTableParser.parse(
174
database, getWholeCommand(reader, line));
174
database, getWholeStatement(reader, line));
175
175
} else if (PATTERN_ALTER_TABLE.matcher(line).matches()) {
176
176
AlterTableParser.parse(
177
database, getWholeCommand(reader, line));
177
database, getWholeStatement(reader, line));
178
178
} else if (PATTERN_CREATE_SEQUENCE.matcher(line).matches()) {
179
179
CreateSequenceParser.parse(
180
database, getWholeCommand(reader, line));
180
database, getWholeStatement(reader, line));
181
181
} else if (PATTERN_CREATE_INDEX.matcher(line).matches()) {
182
182
CreateIndexParser.parse(
183
database, getWholeCommand(reader, line));
183
database, getWholeStatement(reader, line));
184
184
} else if (PATTERN_CREATE_VIEW.matcher(line).matches()) {
185
185
CreateViewParser.parse(
186
database, getWholeCommand(reader, line));
186
database, getWholeStatement(reader, line));
187
} else if (PATTERN_ALTER_VIEW.matcher(line).matches()) {
188
AlterViewParser.parse(
189
database, getWholeStatement(reader, line));
187
190
} else if (PATTERN_CREATE_TRIGGER.matcher(line).matches()) {
188
191
CreateTriggerParser.parse(
189
database, getWholeCommand(reader, line));
192
database, getWholeStatement(reader, line));
190
193
} else if (PATTERN_CREATE_FUNCTION.matcher(line).matches()) {
191
194
CreateFunctionParser.parse(
192
195
database, getWholeFunction(reader, line));
193
} else if (PATTERN_SET.matcher(line).matches()
194
|| PATTERN_COMMENT.matcher(line).matches()
195
|| PATTERN_SELECT.matcher(line).matches()
196
} else if (PATTERN_SELECT.matcher(line).matches()
196
197
|| PATTERN_INSERT_INTO.matcher(line).matches()
197
|| PATTERN_REVOKE.matcher(line).matches()
198
|| PATTERN_GRANT.matcher(line).matches()) {
199
getWholeCommand(reader, line);
198
|| PATTERN_UPDATE.matcher(line).matches()
199
|| PATTERN_DELETE_FROM.matcher(line).matches()) {
200
getWholeStatement(reader, line);
201
} else if (outputIgnoredStatements) {
202
database.addIgnoredStatement(getWholeStatement(reader, line));
204
getWholeStatement(reader, line);
202
207
line = reader.readLine();
214
219
* @param file name of file containing the dump
215
220
* @param charsetName charset that should be used to read the file
221
* @param outputIgnoredStatements whether ignored statements should be
222
* included in the output
217
224
* @return database schema from dump file
219
* @throws FileException Thrown if file not found.
221
226
public static PgDatabase loadDatabaseSchema(final String file,
222
final String charsetName) {
227
final String charsetName, final boolean outputIgnoredStatements) {
224
return loadDatabaseSchema(new FileInputStream(file), charsetName);
229
return loadDatabaseSchema(new FileInputStream(file), charsetName,
230
outputIgnoredStatements);
225
231
} catch (final FileNotFoundException ex) {
226
232
throw new FileException("File '" + file + "' not found", ex);
231
* Reads whole command from the reader into single-line string.
237
* Reads whole statement from the reader into single-line string.
233
239
* @param reader reader to be read
234
240
* @param line first line read
236
* @return whole command from the reader into single-line string
238
* @throws FileException Thrown if problem occured while reading string
239
* from <code>reader</code>.
242
* @return whole statement from the reader into single-line string
241
private static String getWholeCommand(final BufferedReader reader,
244
private static String getWholeStatement(final BufferedReader reader,
242
245
final String line) {
243
246
String newLine = line.trim();
244
final StringBuilder sbCommand = new StringBuilder(newLine);
247
final StringBuilder sbStatement = new StringBuilder(newLine);
246
249
while (!newLine.trim().endsWith(";")) {
267
270
* @param line first line read
269
272
* @return whole CREATE FUNCTION DDL from the reader into multi-line string
271
* @throws FileException Thrown if problem occured while reading string
272
* from<code>reader</code>.
273
* @throws RuntimeException Thrown if cannot find end of function.
275
274
private static String getWholeFunction(final BufferedReader reader,
276
275
final String line) {
277
276
final String firstLine = line;
278
final StringBuilder sbCommand = new StringBuilder();
277
final StringBuilder sbStatement = new StringBuilder(1000);
279
278
String newLine = line;
280
Pattern endOfFunctionPattern = null;
279
String endOfFunction = null;
280
boolean ignoreFirstOccurence = true;
281
281
boolean searchForSemicolon = false;
283
283
while (newLine != null) {
284
if (!searchForSemicolon && (endOfFunctionPattern == null)) {
284
if (endOfFunction == null) {
285
285
final Matcher matcher =
286
286
PATTERN_END_OF_FUNCTION.matcher(newLine);
288
288
if (matcher.matches()) {
289
String endOfFunction = matcher.group(1);
289
final String string = matcher.group(1);
291
if (endOfFunction.charAt(0) == '\'') {
291
if (string.charAt(0) == '\'') {
292
292
endOfFunction = "'";
294
endOfFunction = endOfFunction.substring(
295
0, endOfFunction.indexOf('$', 1) + 1);
298
if ("'".equals(endOfFunction)) {
299
endOfFunctionPattern = Pattern.compile(
300
"(?:.*[^\\\\]'.*|^.*[\\s]*'[\\s]*.*$)");
302
endOfFunctionPattern = Pattern.compile(
303
".*\\Q" + endOfFunction + "\\E.*$",
304
Pattern.CASE_INSENSITIVE);
307
final String stripped = newLine.replaceAll(
308
"[\\s]+AS[\\s]+\\Q" + endOfFunction + "\\E", " ");
310
endOfFunctionPattern.matcher(stripped).matches();
295
string.substring(0, string.indexOf('$', 1) + 1);
314
sbCommand.append(newLine);
315
sbCommand.append('\n');
317
if (searchForSemicolon && newLine.trim().endsWith(";")) {
300
sbStatement.append(newLine);
301
sbStatement.append('\n');
303
if (endOfFunction != null) {
305
if (!searchForSemicolon) {
306
int count = ignoreFirstOccurence ? -1 : 0;
307
int pos = newLine.indexOf(endOfFunction);
308
ignoreFirstOccurence = false;
312
pos = newLine.indexOf(
313
endOfFunction, pos + endOfFunction.length());
316
if (count % 2 == 1) {
317
searchForSemicolon = true;
321
if (searchForSemicolon && newLine.trim().endsWith(";")) {
328
333
throw new RuntimeException(
329
334
"Cannot find end of function: " + firstLine);
332
if (!searchForSemicolon && (endOfFunctionPattern != null)
333
&& endOfFunctionPattern.matcher(newLine).matches()) {
334
searchForSemicolon = true;
338
return sbCommand.toString();
338
return sbStatement.toString();
342
* Strips comment from command line.
344
* @param command command
346
* @return if comment was found then command without the comment, otherwise
347
* the original command
342
* Strips comment from statement line.
344
* @param statement statement
346
* @return if comment was found then statement without the comment,
347
* otherwise the original statement
349
private static String stripComment(final String command) {
350
String result = command;
349
private static String stripComment(final String statement) {
350
String result = statement;
351
351
int pos = result.indexOf("--");
353
353
while (pos >= 0) {