2
* $Id: PgDiffTables.java 80 2007-09-01 20:25:45Z fordfrog $
4
package cz.startnet.utils.pgdiff;
6
import cz.startnet.utils.pgdiff.schema.PgColumn;
7
import cz.startnet.utils.pgdiff.schema.PgColumnUtils;
8
import cz.startnet.utils.pgdiff.schema.PgSchema;
9
import cz.startnet.utils.pgdiff.schema.PgTable;
11
import java.io.PrintWriter;
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.List;
23
* @version $Id: PgDiffTables.java 80 2007-09-01 20:25:45Z fordfrog $
25
public class PgDiffTables {
27
* Creates a new instance of PgDiffTables.
29
private PgDiffTables() {
34
* Generates and outputs CLUSTER specific DDL if appropriate.
36
* @param writer writer the output should be written to
37
* @param arguments object containing arguments settings
38
* @param oldSchema original schema
39
* @param newSchema new schema
41
public static void diffClusters(
42
final PrintWriter writer,
43
final PgDiffArguments arguments,
44
final PgSchema oldSchema,
45
final PgSchema newSchema) {
46
for (PgTable newTable : newSchema.getTables()) {
47
final PgTable oldTable;
49
if (oldSchema == null) {
52
oldTable = oldSchema.getTable(newTable.getName());
55
final String oldCluster;
57
if (oldTable == null) {
60
oldCluster = oldTable.getClusterIndexName();
63
final String newCluster = newTable.getClusterIndexName();
66
((oldCluster == null) && (newCluster != null))
67
|| ((oldCluster != null) && (newCluster != null)
68
&& (newCluster.compareTo(oldCluster) != 0))) {
70
writer.print("ALTER TABLE ");
72
PgDiffUtils.getQuotedName(
74
arguments.isQuoteNames()));
75
writer.print(" CLUSTER ON ");
77
PgDiffUtils.getQuotedName(
79
arguments.isQuoteNames()));
83
&& (newCluster == null)
84
&& newTable.containsIndex(oldCluster)) {
86
writer.print("ALTER TABLE ");
88
PgDiffUtils.getQuotedName(
90
arguments.isQuoteNames()));
91
writer.println(" SET WITHOUT CLUSTER;");
97
* Creates diff of tables.
99
* @param writer writer the output should be written to
100
* @param arguments object containing arguments settings
101
* @param oldSchema original schema
102
* @param newSchema new schema
104
public static void diffTables(
105
final PrintWriter writer,
106
final PgDiffArguments arguments,
107
final PgSchema oldSchema,
108
final PgSchema newSchema) {
109
dropTables(writer, arguments, oldSchema, newSchema);
110
createTables(writer, arguments, oldSchema, newSchema);
112
for (PgTable newTable : newSchema.getTables()) {
115
|| !oldSchema.containsTable(newTable.getName())) {
119
final PgTable oldTable = oldSchema.getTable(newTable.getName());
120
updateTableColumns(writer, arguments, oldTable, newTable);
121
checkWithOIDS(writer, arguments, oldTable, newTable);
122
checkInherits(writer, arguments, oldTable, newTable);
123
addAlterStatistics(writer, arguments, oldTable, newTable);
128
* Generate the needed alter table xxx set statistics when needed.
130
* @param writer writer the output should be written to
131
* @param arguments object containing arguments settings
132
* @param oldTable original table
133
* @param newTable new table
135
private static void addAlterStatistics(
136
final PrintWriter writer,
137
final PgDiffArguments arguments,
138
final PgTable oldTable,
139
final PgTable newTable) {
140
final Map<String, Integer> stats = new HashMap<String, Integer>();
142
for (PgColumn newColumn : newTable.getColumns()) {
143
final PgColumn oldColumn = oldTable.getColumn(newColumn.getName());
145
if (oldColumn != null) {
146
final Integer oldStat = oldColumn.getStatistics();
147
final Integer newStat = newColumn.getStatistics();
148
Integer newStatValue = null;
152
&& ((oldStat == null) || !newStat.equals(oldStat))) {
153
newStatValue = newStat;
154
} else if ((oldStat != null) && (newStat == null)) {
155
newStatValue = Integer.valueOf(-1);
158
if (newStatValue != null) {
159
stats.put(newColumn.getName(), newStatValue);
164
for (Map.Entry<String, Integer> entry : stats.entrySet()) {
166
writer.print("ALTER TABLE ONLY ");
168
PgDiffUtils.getQuotedName(
170
arguments.isQuoteNames()));
171
writer.print(" ALTER COLUMN ");
173
PgDiffUtils.getQuotedName(
175
arguments.isQuoteNames()));
176
writer.print(" SET STATISTICS ");
177
writer.print(entry.getValue());
183
* Adds commands for creation of new columns to the list of
186
* @param commands list of commands
187
* @param arguments object containing arguments settings
188
* @param oldTable original table
189
* @param newTable new table
190
* @param dropDefaultsColumns list for storing columns for which default
191
* value should be dropped
193
private static void addCreateTableColumns(
194
final List<String> commands,
195
final PgDiffArguments arguments,
196
final PgTable oldTable,
197
final PgTable newTable,
198
final List<PgColumn> dropDefaultsColumns) {
199
for (PgColumn column : newTable.getColumns()) {
200
if (!oldTable.containsColumn(column.getName())) {
203
+ column.getFullDefinition(
204
arguments.isQuoteNames(),
205
arguments.isAddDefaults()));
207
if (arguments.isAddDefaults() && !column.getNullValue()) {
208
dropDefaultsColumns.add(column);
215
* Adds commands for removal of columns to the list of commands.
217
* @param commands list of commands
218
* @param arguments object containing arguments settings
219
* @param oldTable original table
220
* @param newTable new table
222
private static void addDropTableColumns(
223
final List<String> commands,
224
final PgDiffArguments arguments,
225
final PgTable oldTable,
226
final PgTable newTable) {
227
for (PgColumn column : oldTable.getColumns()) {
228
if (!newTable.containsColumn(column.getName())) {
231
+ PgDiffUtils.getQuotedName(
233
arguments.isQuoteNames()));
239
* Adds commands for modification of columns to the list of
242
* @param commands list of commands
243
* @param arguments object containing arguments settings
244
* @param oldTable original table
245
* @param newTable new table
246
* @param dropDefaultsColumns list for storing columns for which default
247
* value should be dropped
249
private static void addModifyTableColumns(
250
final List<String> commands,
251
final PgDiffArguments arguments,
252
final PgTable oldTable,
253
final PgTable newTable,
254
final List<PgColumn> dropDefaultsColumns) {
255
for (PgColumn newColumn : newTable.getColumns()) {
256
if (!oldTable.containsColumn(newColumn.getName())) {
260
final PgColumn oldColumn = oldTable.getColumn(newColumn.getName());
261
final String newColumnName =
262
PgDiffUtils.getQuotedName(
264
arguments.isQuoteNames());
266
if (!oldColumn.getType().equals(newColumn.getType())) {
268
"\tALTER COLUMN " + newColumnName + " TYPE "
269
+ newColumn.getType());
272
final String oldDefault =
273
(oldColumn.getDefaultValue() == null) ? ""
276
final String newDefault =
277
(newColumn.getDefaultValue() == null) ? ""
281
if (!oldDefault.equals(newDefault)) {
282
if (newDefault.length() == 0) {
284
"\tALTER COLUMN " + newColumnName + " DROP DEFAULT");
287
"\tALTER COLUMN " + newColumnName + " SET DEFAULT "
292
if (oldColumn.getNullValue() != newColumn.getNullValue()) {
293
if (newColumn.getNullValue()) {
295
"\tALTER COLUMN " + newColumnName
298
if (arguments.isAddDefaults()) {
299
final String defaultValue =
300
PgColumnUtils.getDefaultValue(newColumn.getType());
302
if (defaultValue != null) {
304
"\tALTER COLUMN " + newColumnName
305
+ " SET DEFAULT " + defaultValue);
306
dropDefaultsColumns.add(newColumn);
311
"\tALTER COLUMN " + newColumnName + " SET NOT NULL");
318
* Checks whether there is a discrepancy in INHERITS for original
321
* @param writer writer the output should be written to
322
* @param arguments object containing arguments settings
323
* @param oldTable original table
324
* @param newTable new table
326
private static void checkInherits(
327
final PrintWriter writer,
328
final PgDiffArguments arguments,
329
final PgTable oldTable,
330
final PgTable newTable) {
331
final String oldInherits = oldTable.getInherits();
332
final String newInherits = newTable.getInherits();
334
if ((oldInherits == null) && (newInherits != null)) {
337
"Modified INHERITS on TABLE "
338
+ PgDiffUtils.getQuotedName(
340
arguments.isQuoteNames())
341
+ ": original table doesn't use INHERITS but new table "
342
+ "uses INHERITS " + newTable.getInherits());
343
} else if ((oldInherits != null) && (newInherits == null)) {
346
"Modified INHERITS on TABLE "
347
+ PgDiffUtils.getQuotedName(
349
arguments.isQuoteNames())
350
+ ": original table uses INHERITS "
351
+ oldTable.getInherits()
352
+ " but new table doesn't use INHERITS");
354
(oldInherits != null)
355
&& (newInherits != null)
356
&& !oldInherits.equals(newInherits)) {
359
"Modified INHERITS on TABLE "
360
+ PgDiffUtils.getQuotedName(
362
arguments.isQuoteNames())
363
+ ": original table uses INHERITS "
364
+ oldTable.getInherits() + " but new table uses INHERITS "
365
+ newTable.getInherits());
370
* Checks whether OIDS are dropped from the new table. There is no
371
* way to add OIDS to existing table so we do not create SQL command for
372
* addition of OIDS but we issue warning.
374
* @param writer writer the output should be written to
375
* @param arguments object containing arguments settings
376
* @param oldTable original table
377
* @param newTable new table
379
private static void checkWithOIDS(
380
final PrintWriter writer,
381
final PgDiffArguments arguments,
382
final PgTable oldTable,
383
final PgTable newTable) {
384
if (oldTable.isWithOIDS() && !newTable.isWithOIDS()) {
388
+ PgDiffUtils.getQuotedName(
390
arguments.isQuoteNames()));
391
writer.println("\tSET WITHOUT OIDS;");
392
} else if (!oldTable.isWithOIDS() && newTable.isWithOIDS()) {
396
+ PgDiffUtils.getQuotedName(
398
arguments.isQuoteNames())
399
+ " adds WITH OIDS but there is no equivalent command "
400
+ "for adding of OIDS in PostgreSQL");
405
* Outputs commands for creation of new tables.
407
* @param writer writer the output should be written to
408
* @param arguments object containing arguments settings
409
* @param oldSchema original schema
410
* @param newSchema new schema
412
private static void createTables(
413
final PrintWriter writer,
414
final PgDiffArguments arguments,
415
final PgSchema oldSchema,
416
final PgSchema newSchema) {
417
for (PgTable table : newSchema.getTables()) {
420
|| !oldSchema.containsTable(table.getName())) {
422
writer.println(table.getCreationSQL(arguments.isQuoteNames()));
428
* Outputs commands for dropping tables.
430
* @param writer writer the output should be written to
431
* @param arguments object containing arguments settings
432
* @param oldSchema original schema
433
* @param newSchema new schema
435
private static void dropTables(
436
final PrintWriter writer,
437
final PgDiffArguments arguments,
438
final PgSchema oldSchema,
439
final PgSchema newSchema) {
440
if (oldSchema != null) {
441
for (PgTable table : oldSchema.getTables()) {
442
if (!newSchema.containsTable(table.getName())) {
444
writer.println(table.getDropSQL(arguments.isQuoteNames()));
451
* Outputs commands for addition, removal and modifications of
454
* @param writer writer the output should be written to
455
* @param arguments object containing arguments settings
456
* @param oldTable original table
457
* @param newTable new table
459
private static void updateTableColumns(
460
final PrintWriter writer,
461
final PgDiffArguments arguments,
462
final PgTable oldTable,
463
final PgTable newTable) {
464
final List<String> commands = new ArrayList<String>();
465
final List<PgColumn> dropDefaultsColumns = new ArrayList<PgColumn>();
466
addDropTableColumns(commands, arguments, oldTable, newTable);
467
addCreateTableColumns(
472
dropDefaultsColumns);
473
addModifyTableColumns(
478
dropDefaultsColumns);
480
if (commands.size() > 0) {
481
final String quotedTableName =
482
PgDiffUtils.getQuotedName(
484
arguments.isQuoteNames());
486
writer.println("ALTER TABLE " + quotedTableName);
488
for (int i = 0; i < commands.size(); i++) {
489
writer.print(commands.get(i));
490
writer.println(((i + 1) < commands.size()) ? "," : ";");
493
if (!dropDefaultsColumns.isEmpty()) {
495
writer.println("ALTER TABLE " + quotedTableName);
497
for (int i = 0; i < dropDefaultsColumns.size(); i++) {
498
writer.print("\tALTER COLUMN ");
500
PgDiffUtils.getQuotedName(
501
dropDefaultsColumns.get(i).getName(),
502
arguments.isQuoteNames()));
503
writer.print(" DROP DEFAULT");
505
((i + 1) < dropDefaultsColumns.size()) ? "," : ";");