forked from paulfitz/daff
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCompareFlags.hx
444 lines (399 loc) · 11.7 KB
/
CompareFlags.hx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
// -*- mode:java; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
#if !TOPLEVEL
package coopy;
#end
/**
*
* Flags that influence how tables are compared and how information
* is presented.
*
*/
@:expose
class CompareFlags {
/**
*
* Is the order of rows and columns meaningful? Defaults to `true`.
*
*/
public var ordered : Bool;
/**
*
* Should we show all rows in diffs? We default to showing
* just rows that have changes (and some context rows around
* them, if row order is meaningful), but you can override
* this here.
*
*/
public var show_unchanged : Bool;
/**
*
* When showing context rows around a changed row, what
* is the minimum number of such rows we should show?
*
*/
public var unchanged_context : Int;
/**
*
* Diffs for tables where row/column order has been permuted may include
* an extra row/column specifying the changes in row numbers.
* If you'd like that extra row/column to always be included,
* turn on this flag, and turn off never_show_order.
*
*/
public var always_show_order : Bool;
/**
*
* Diffs for tables where row/column order has been permuted may include
* an extra row/column specifying the changes in row numbers.
* If you'd like to be sure that that row/column is *never*
* included, turn on this flag, and turn off always_show_order.
*
*/
public var never_show_order : Bool;
/**
*
* Should we show all columns in diffs? We default to showing
* just columns that have changes (and some context columns around
* them, if column order is meaningful), but you can override
* this here. Irrespective of this flag, you can rely
* on index/key columns needed to identify rows to be included
* in the diff.
*
*/
public var show_unchanged_columns : Bool;
/**
*
* When showing context columns around a changed column, what
* is the minimum number of such columns we should show?
*
*/
public var unchanged_column_context : Int;
/**
*
* Should we always give a table header in diffs? This defaults
* to true, and - frankly - you should leave it at true for now.
*
*/
public var always_show_header : Bool;
/**
*
* Optional filters for what kind of changes we want to show.
* Please call `filter()`
* to choose your filters, this variable will be made private soon.
*
*/
public var acts : Map<String, Bool>;
/**
* List of columns that make up a primary key, if known.
* Otherwise heuristics are used to find a decent key
* (or a set of decent keys). Please set via (multiple
* calls of) `addPrimaryKey()`. This variable will be made private
* soon.
*
*/
public var ids : Array<String>;
/**
*
* List of columns to ignore in all calculations. Changes
* related to these columns should be discounted. Please set
* via (multiple calls of) `ignoreColumn`.
*
*/
public var columns_to_ignore : Array<String>;
/**
*
* List of tables to process. Used when reading from a source
* with multiple tables. Defaults to null, meaning all tables.
*
*/
public var tables : Array<String>;
/**
*
* Should cells in diff output contain nested content?
* This is the difference between getting eg the string
* "version1->version2" and a hash {before: "version1", after: "version2"}.
* Defaults to false.
*
*/
public var allow_nested_cells : Bool;
/**
*
* List of warnings generated during a comparison.
*
*/
public var warnings : Array<String>;
/**
*
* Strategy to use when making comparisons. Valid values are "hash" and "sql".
* The latter is only useful for SQL sources. Leave null for a sensible default.
*
*/
public var diff_strategy : String;
/**
*
* Strategy to use when padding columns. Valid values are "smart", "dense",
* and "sparse". Leave null for a sensible default.
*
*/
public var padding_strategy : String;
/**
*
* Show changes in column properties, not just data, if available.
* Defaults to true.
*
*/
public var show_meta : Bool;
/**
*
* Show all column properties, if available, even if unchanged.
* Defaults to false.
*
*/
public var show_unchanged_meta : Bool;
/**
*
* Set a common ancestor for use in comparison. Defaults to null
* (no known common ancestor).
*
*/
public var parent : Table;
/**
*
* Should column numbers, if present, be rendered spreadsheet-style
* as A,B,C,...,AA,BB,CC?
* Defaults to true.
*
*/
public var count_like_a_spreadsheet : Bool;
/**
*
* Should whitespace be omitted from comparisons. Defaults to false.
*
*/
public var ignore_whitespace : Bool;
/**
*
* Should case be omitted from comparisons. Defaults to false.
*
*/
public var ignore_case : Bool;
/**
*
* If set to a positive number, then cells that looks like floating point
* numbers are treated as equal if they are within epsilon of each other.
* This option does NOT affect the alignment of rows, so if a floating point
* number is part of your table's primary key, this option will not help.
* Defaults to a negative number (so it is disabled).
*
*/
public var ignore_epsilon : Float;
/**
*
* Format to use for terminal output. "plain" for plain text,
* "ansi", for ansi color codes, null to autodetect. Defaults to
* autodetect.
*
*/
public var terminal_format : String;
/**
*
* Choose whether we can use utf8 characters for describing diff
* (specifically long arrow). Defaults to true.
*
*/
public var use_glyphs : Bool;
/**
* Choose whether html elements should be neutralized or passed through,
* in html contexts.
*
*/
public var quote_html : Bool;
public function new() {
ordered = true;
show_unchanged = false;
unchanged_context = 1;
always_show_order = false;
never_show_order = true;
show_unchanged_columns = false;
unchanged_column_context = 1;
always_show_header = true;
acts = null;
ids = null;
columns_to_ignore = null;
allow_nested_cells = false;
warnings = null;
diff_strategy = null;
show_meta = true;
show_unchanged_meta = false;
tables = null;
parent = null;
count_like_a_spreadsheet = true;
ignore_whitespace = false;
ignore_case = false;
ignore_epsilon = -1;
terminal_format = null;
use_glyphs = true;
quote_html = true;
}
/**
*
* Filter for particular kinds of changes.
* @param act set this to "update", "insert", "delete", or "column".
* @param allow set this to true to allow this kind, or false to
* deny it.
* @return true if the kind of change was recognized.
*
*/
public function filter(act: String, allow: Bool) : Bool {
if (acts==null) {
acts = new Map<String,Bool>();
acts.set("update",!allow);
acts.set("insert",!allow);
acts.set("delete",!allow);
acts.set("column",!allow);
}
if (!acts.exists(act)) return false;
acts.set(act,allow);
return true;
}
/**
*
* @return true if updates are allowed by the current filters.
*
*/
public function allowUpdate() : Bool {
if (acts==null) return true;
return acts.exists("update") && acts.get("update");
}
/**
*
* @return true if inserts are allowed by the current filters.
*
*/
public function allowInsert() : Bool {
if (acts==null) return true;
return acts.exists("insert") && acts.get("insert");
}
/**
*
* @return true if deletions are allowed by the current filters.
*
*/
public function allowDelete() : Bool {
if (acts==null) return true;
return acts.exists("delete") && acts.get("delete");
}
/**
*
* @return true if column additions/deletions are allowed by the current filters.
*
*/
public function allowColumn() : Bool {
if (acts==null) return true;
return acts.exists("column") && acts.get("column");
}
/**
*
* @return the columns to ignore, as a map. For internal use.
*
*/
public function getIgnoredColumns() : Map<String,Bool> {
if (columns_to_ignore==null) return null;
var ignore = new Map<String,Bool>();
for (i in 0...columns_to_ignore.length) {
ignore.set(columns_to_ignore[i],true);
}
return ignore;
}
/**
*
* Add a column to the primary key. If this is never called,
* then we will muddle along without it. Fine to call multiple
* times to set up a multi-column primary key.
*
* @param column a name of a column to add to the primary key
*
*/
public function addPrimaryKey(column: String) : Void {
if (ids == null) ids = new Array<String>();
ids.push(column);
}
/**
*
* Add a table to compare. Fine to call multiple times,
* although multiple tables won't do anything sensible
* yet at the time of writing.
*
* @param table the name of a table to consider
*
*/
public function ignoreColumn(column: String) : Void {
if (columns_to_ignore==null) columns_to_ignore = new Array<String>();
columns_to_ignore.push(column);
}
public function addTable(table: String) : Void {
if (tables==null) tables = new Array<String>();
tables.push(table);
}
/**
*
* Add a warning. Used by daff to pass non-critical information
* to the developer without disrupting operations.
*
* @param warn the warning text to record
*
*/
public function addWarning(warn: String) : Void {
if (warnings==null) warnings = new Array<String>();
warnings.push(warn);
}
/**
*
* @return any warnings generated during an operation.
*
*/
public function getWarning() : String {
return warnings.join("\n");
}
/**
*
* Primary key and table names may be specified as "local:remote" or "parent:local:remote"
* when they should be different for the local, remote, and parent sources. This
* method returns the appropriate part of a name given a role of local, remote, or parent.
*
*/
public function getNameByRole(name: String, role: String): String {
var parts = name.split(":");
if (parts.length <= 1) { return name; }
if (role == 'parent') {
return parts[0];
}
if (role == 'local') {
return parts[parts.length - 2];
}
return parts[parts.length - 1];
}
/**
*
* If we need a single name for a table/column, we use the local name.
*
*/
public function getCanonicalName(name: String): String {
return getNameByRole(name, 'local');
}
/**
*
* Returns primary key for 'local', 'remote', and 'parent' sources.
*
*/
public function getIdsByRole(role: String): Array<String> {
var result = new Array<String>();
if (ids==null) {
return result;
}
for (name in ids) {
result.push(getNameByRole(name, role));
}
return result;
}
}