41
49
"^SET[\\s]+search_path[\\s]*=[\\s]*([^,\\s]+)(?:,[\\s]+.*)?;$",
42
50
Pattern.CASE_INSENSITIVE);
44
* Pattern for testing whether command is CREATE TABLE command.
52
* Pattern for testing whether it is CREATE TABLE statement.
46
54
private static final Pattern PATTERN_CREATE_TABLE = Pattern.compile(
47
55
"^CREATE[\\s]+TABLE[\\s]+.*$", Pattern.CASE_INSENSITIVE);
49
* Pattern for testing whether command is CREATE VIEW command.
57
* Pattern for testing whether it is CREATE VIEW statement.
51
59
private static final Pattern PATTERN_CREATE_VIEW = Pattern.compile(
52
60
"^CREATE[\\s]+(?:OR[\\s]+REPLACE[\\s]+)?VIEW[\\s]+.*$",
53
61
Pattern.CASE_INSENSITIVE);
55
* Pattern for testing whether command is ALTER TABLE command.
63
* Pattern for testing whether it is ALTER TABLE statement.
57
65
private static final Pattern PATTERN_ALTER_TABLE =
58
Pattern.compile("^ALTER[\\s]+TABLE[\\s]+.*$", Pattern.CASE_INSENSITIVE);
66
Pattern.compile("^ALTER[\\s]+TABLE[\\s]+.*$",
67
Pattern.CASE_INSENSITIVE);
60
* Pattern for testing whether command is CREATE SEQUENCE command.
69
* Pattern for testing whether it is CREATE SEQUENCE statement.
62
71
private static final Pattern PATTERN_CREATE_SEQUENCE = Pattern.compile(
63
72
"^CREATE[\\s]+SEQUENCE[\\s]+.*$", Pattern.CASE_INSENSITIVE);
65
* Pattern for testing whether command is CREATE INDEX command.
74
* Pattern for testing whether it is CREATE INDEX statement.
67
76
private static final Pattern PATTERN_CREATE_INDEX = Pattern.compile(
68
77
"^CREATE[\\s]+(?:UNIQUE[\\s]+)?INDEX[\\s]+.*$",
69
78
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.
80
* Pattern for testing whether it is SELECT statement.
83
82
private static final Pattern PATTERN_SELECT =
84
83
Pattern.compile("^SELECT[\\s]+.*$", Pattern.CASE_INSENSITIVE);
86
* Pattern for testing whether command is INSERT INTO command.
85
* Pattern for testing whether it is INSERT INTO statement.
88
87
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.
88
Pattern.compile("^INSERT[\\s]+INTO[\\s]+.*$",
89
Pattern.CASE_INSENSITIVE);
91
* Pattern for testing whether it is UPDATE statement.
93
private static final Pattern PATTERN_UPDATE =
94
Pattern.compile("^UPDATE[\\s].*$", Pattern.CASE_INSENSITIVE);
96
* Pattern for testing whether it is DELETE FROM statement.
98
private static final Pattern PATTERN_DELETE_FROM =
99
Pattern.compile("^DELETE[\\s]+FROM[\\s]+.*$",
100
Pattern.CASE_INSENSITIVE);
102
* Pattern for testing whether it is CREATE TRIGGER statement.
103
104
private static final Pattern PATTERN_CREATE_TRIGGER = Pattern.compile(
104
105
"^CREATE[\\s]+TRIGGER[\\s]+.*$", Pattern.CASE_INSENSITIVE);
106
* Pattern for testing whether command is CREATE FUNCTION or CREATE
107
* OR REPLACE FUNCTION command.
107
* Pattern for testing whether it is CREATE FUNCTION or CREATE OR REPLACE
108
* FUNCTION statement.
109
110
private static final Pattern PATTERN_CREATE_FUNCTION = Pattern.compile(
110
111
"^CREATE[\\s]+(?:OR[\\s]+REPLACE[\\s]+)?FUNCTION[\\s]+.*$",
111
112
Pattern.CASE_INSENSITIVE);
113
* Pattern for getting the string that is used to end the function
114
* or the function definition itself.
114
* Pattern for testing whether it is ALTER VIEW statement.
116
private static final Pattern PATTERN_END_OF_FUNCTION = Pattern.compile(
117
"^(?:.*[\\s]+)?AS[\\s]+(['$][^\\s]*).*$", Pattern.CASE_INSENSITIVE);
116
private static final Pattern PATTERN_ALTER_VIEW = Pattern.compile(
117
"^ALTER[\\s]+VIEW[\\s]+.*$", Pattern.CASE_INSENSITIVE);
120
120
* Creates a new instance of PgDumpLoader.
122
122
private PgDumpLoader() {
171
168
database.setDefaultSchema(matcher.group(1));
172
169
} else if (PATTERN_CREATE_TABLE.matcher(line).matches()) {
173
170
CreateTableParser.parse(
174
database, getWholeCommand(reader, line));
171
database, getWholeStatement(reader, line));
175
172
} else if (PATTERN_ALTER_TABLE.matcher(line).matches()) {
176
AlterTableParser.parse(
177
database, getWholeCommand(reader, line));
173
AlterTableParser.parse(database,
174
getWholeStatement(reader, line),
175
outputIgnoredStatements);
178
176
} else if (PATTERN_CREATE_SEQUENCE.matcher(line).matches()) {
179
177
CreateSequenceParser.parse(
180
database, getWholeCommand(reader, line));
178
database, getWholeStatement(reader, line));
181
179
} else if (PATTERN_CREATE_INDEX.matcher(line).matches()) {
182
180
CreateIndexParser.parse(
183
database, getWholeCommand(reader, line));
181
database, getWholeStatement(reader, line));
184
182
} else if (PATTERN_CREATE_VIEW.matcher(line).matches()) {
185
183
CreateViewParser.parse(
186
database, getWholeCommand(reader, line));
184
database, getWholeStatement(reader, line));
185
} else if (PATTERN_ALTER_VIEW.matcher(line).matches()) {
186
AlterViewParser.parse(database,
187
getWholeStatement(reader, line),
188
outputIgnoredStatements);
187
189
} else if (PATTERN_CREATE_TRIGGER.matcher(line).matches()) {
188
190
CreateTriggerParser.parse(
189
database, getWholeCommand(reader, line));
191
database, getWholeStatement(reader, line));
190
192
} else if (PATTERN_CREATE_FUNCTION.matcher(line).matches()) {
191
193
CreateFunctionParser.parse(
192
194
database, getWholeFunction(reader, line));
193
} else if (PATTERN_SET.matcher(line).matches()
194
|| PATTERN_COMMENT.matcher(line).matches()
195
|| PATTERN_SELECT.matcher(line).matches()
195
} else if (PATTERN_SELECT.matcher(line).matches()
196
196
|| PATTERN_INSERT_INTO.matcher(line).matches()
197
|| PATTERN_REVOKE.matcher(line).matches()
198
|| PATTERN_GRANT.matcher(line).matches()) {
199
getWholeCommand(reader, line);
197
|| PATTERN_UPDATE.matcher(line).matches()
198
|| PATTERN_DELETE_FROM.matcher(line).matches()) {
199
getWholeStatement(reader, line);
200
} else if (outputIgnoredStatements) {
201
database.addIgnoredStatement(
202
getWholeStatement(reader, line));
204
getWholeStatement(reader, line);
202
207
line = reader.readLine();
204
209
} catch (final IOException ex) {
205
throw new FileException(FileException.CANNOT_READ_FILE, ex);
210
throw new FileException(Resources.getString("CannotReadFile"), ex);
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
throw new FileException("File '" + file + "' not found", ex);
232
throw new FileException(MessageFormat.format(
233
Resources.getString("FileNotFound"), file), ex);
231
* Reads whole command from the reader into single-line string.
238
* Reads whole statement from the reader into single-line string.
233
240
* @param reader reader to be read
234
241
* @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>.
243
* @return whole statement from the reader into single-line string
241
private static String getWholeCommand(final BufferedReader reader,
245
private static String getWholeStatement(final BufferedReader reader,
242
246
final String line) {
243
247
String newLine = line.trim();
244
final StringBuilder sbCommand = new StringBuilder(newLine);
248
final StringBuilder sbStatement = new StringBuilder(newLine);
246
250
while (!newLine.trim().endsWith(";")) {
248
252
newLine = stripComment(reader.readLine()).trim();
249
253
} catch (IOException ex) {
250
throw new FileException(FileException.CANNOT_READ_FILE, ex);
254
throw new FileException(
255
Resources.getString("CannotReadFile"), ex);
253
258
if (newLine.length() > 0) {
254
sbCommand.append(' ');
255
sbCommand.append(newLine);
259
sbStatement.append(' ');
260
sbStatement.append(newLine);
259
return sbCommand.toString();
264
return sbStatement.toString();
267
272
* @param line first line read
269
274
* @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
276
private static String getWholeFunction(final BufferedReader reader,
276
277
final String line) {
277
278
final String firstLine = line;
278
final StringBuilder sbCommand = new StringBuilder();
279
final StringBuilder sbStatement = new StringBuilder(1000);
279
280
String newLine = line;
280
Pattern endOfFunctionPattern = null;
281
String endOfFunction = null;
282
boolean ignoreFirstOccurence = true;
281
283
boolean searchForSemicolon = false;
284
boolean nextIsSeparator = false;
283
286
while (newLine != null) {
284
if (!searchForSemicolon && (endOfFunctionPattern == null)) {
285
final Matcher matcher =
286
PATTERN_END_OF_FUNCTION.matcher(newLine);
288
if (matcher.matches()) {
289
String endOfFunction = matcher.group(1);
291
if (endOfFunction.charAt(0) == '\'') {
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();
287
if (endOfFunction == null) {
288
boolean previousWasWhitespace = true;
290
for (int i = 0; i < newLine.length(); i++) {
291
final char chr = newLine.charAt(i);
293
if (Character.isWhitespace(chr)) {
294
previousWasWhitespace = true;
296
} else if (nextIsSeparator) {
300
endOfFunction = newLine.substring(
301
i, newLine.indexOf('$', i + 1) + 1);
305
} else if (previousWasWhitespace
306
&& Character.toUpperCase(chr) == 'A'
307
&& Character.toUpperCase(newLine.charAt(i + 1)) == 'S'
308
&& (i + 2 == newLine.length()
309
|| Character.isWhitespace(newLine.charAt(i + 2)))) {
311
nextIsSeparator = true;
313
previousWasWhitespace = false;
314
sbCommand.append(newLine);
315
sbCommand.append('\n');
317
if (searchForSemicolon && newLine.trim().endsWith(";")) {
318
sbStatement.append(newLine);
319
sbStatement.append('\n');
321
if (endOfFunction != null) {
323
if (!searchForSemicolon) {
324
int count = ignoreFirstOccurence ? -1 : 0;
325
int pos = newLine.indexOf(endOfFunction);
326
ignoreFirstOccurence = false;
330
pos = newLine.indexOf(
331
endOfFunction, pos + endOfFunction.length());
334
if (count % 2 == 1) {
335
searchForSemicolon = true;
339
if (searchForSemicolon && newLine.trim().endsWith(";")) {
322
345
newLine = reader.readLine();
323
346
} catch (final IOException ex) {
324
throw new FileException(FileException.CANNOT_READ_FILE, ex);
347
throw new FileException(
348
Resources.getString("CannotReadFile"), ex);
327
351
if (newLine == null) {
328
352
throw new RuntimeException(
329
"Cannot find end of function: " + firstLine);
332
if (!searchForSemicolon && (endOfFunctionPattern != null)
333
&& endOfFunctionPattern.matcher(newLine).matches()) {
334
searchForSemicolon = true;
353
Resources.getString("CannotFindEndOfFunction") + ": "
338
return sbCommand.toString();
358
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
362
* Strips comment from statement line.
364
* @param statement statement
366
* @return if comment was found then statement without the comment,
367
* otherwise the original statement
349
private static String stripComment(final String command) {
350
String result = command;
369
private static String stripComment(final String statement) {
370
String result = statement;
351
371
int pos = result.indexOf("--");
353
373
while (pos >= 0) {