132 self.argument = argument |
136 self.argument = argument |
133 self.name = argument |
137 self.name = argument |
134 |
138 |
135 |
139 |
136 class DiffFunction(DiffBase): |
140 class DiffFunction(DiffBase): |
137 def __init__(self, change, schema, function): |
141 def __init__(self, change, schema, function, show_body_diff=False): |
138 DiffBase.__init__(self) |
142 DiffBase.__init__(self) |
139 self.level = 1 |
143 self.level = 1 |
140 self.type = 'function' |
144 self.type = 'function' |
141 self.change = change |
145 self.change = change |
142 self.schema = schema |
146 self.schema = schema |
143 self.function = function |
147 self.function = function |
144 self.name = function |
148 self.name = function |
|
149 self.show_body_diff = show_body_diff |
145 |
150 |
146 def _formatchanges(self): |
151 def _formatchanges(self): |
147 res = [] |
152 res = [] |
148 for x in self.changes: |
153 for x in self.changes: |
149 type, a, b = x |
154 type, a, b = x |
150 if type == 'source': |
155 if type == 'source': |
151 s = 'Changed source.' |
156 if self.show_body_diff: |
152 else: |
157 lines = ['Source differs:\n'] |
153 s = ''.join(['Changed ', type, ' from ', |
158 for line in difflib.unified_diff(a, b, lineterm=''): |
|
159 if line[:3] in ('---', '+++'): |
|
160 continue |
|
161 lines.append(line + '\n') |
|
162 diff = ''.join(lines) |
|
163 diff = colordiff(diff) |
|
164 res.append(diff) |
|
165 else: |
|
166 res.append('Source differs.') |
|
167 else: |
|
168 res.append(''.join(['Changed ', type, ' from ', |
154 highlight(1,15), a, highlight(0), ' to ', |
169 highlight(1,15), a, highlight(0), ' to ', |
155 highlight(1,15), b, highlight(0), '.']) |
170 highlight(1,15), b, highlight(0), '.'])) |
156 res.append(s) |
|
157 return ' '.join(res) |
171 return ' '.join(res) |
158 |
172 |
159 |
173 |
160 class DiffColumn(DiffBase): |
174 class DiffColumn(DiffBase): |
161 ALTER_COMMANDS = { |
175 ALTER_COMMANDS = { |
247 self.dst = dstbrowser |
261 self.dst = dstbrowser |
248 self.include_schemas = set() # if not empty, consider only these schemas for diff |
262 self.include_schemas = set() # if not empty, consider only these schemas for diff |
249 self.exclude_schemas = set() # exclude these schemas from diff |
263 self.exclude_schemas = set() # exclude these schemas from diff |
250 self.include_tables = set() |
264 self.include_tables = set() |
251 self.exclude_tables = set() |
265 self.exclude_tables = set() |
|
266 self.function_regex = re.compile(r"") |
|
267 self.function_body_diff = False |
252 |
268 |
253 def _test_schema(self, schema): |
269 def _test_schema(self, schema): |
254 if self.include_schemas and schema not in self.include_schemas: |
270 if self.include_schemas and schema not in self.include_schemas: |
255 return False |
271 return False |
256 if schema in self.exclude_schemas: |
272 if schema in self.exclude_schemas: |
261 if self.include_tables and table not in self.include_tables: |
277 if self.include_tables and table not in self.include_tables: |
262 return False |
278 return False |
263 if table in self.exclude_tables: |
279 if table in self.exclude_tables: |
264 return False |
280 return False |
265 return True |
281 return True |
|
282 |
|
283 def _test_function(self, function): |
|
284 return bool(self.function_regex.match(function)) |
266 |
285 |
267 def _diff_names(self, src, dst): |
286 def _diff_names(self, src, dst): |
268 for x in src: |
287 for x in src: |
269 if x in dst: |
288 if x in dst: |
270 yield ('*', x) |
289 yield ('*', x) |
294 |
313 |
295 def _compare_functions(self, a, b): |
314 def _compare_functions(self, a, b): |
296 diff = [] |
315 diff = [] |
297 if a.result != b.result: |
316 if a.result != b.result: |
298 diff.append(('result', a.result, b.result)) |
317 diff.append(('result', a.result, b.result)) |
299 if a.source != b.source: |
318 # function source may differ in newlines (\n vs \r\n) |
300 diff.append(('source', a.source, b.source)) |
319 # split lines before comparison, so that these differencies are ignored |
|
320 a_source = a.source.splitlines() |
|
321 b_source = b.source.splitlines() |
|
322 if a_source != b_source: |
|
323 diff.append(('source', a_source, b_source)) |
301 return diff |
324 return diff |
302 |
325 |
303 def _compare_arguments(self, a, b): |
326 def _compare_arguments(self, a, b): |
304 diff = [] |
327 diff = [] |
305 if a.type != b.type: |
328 if a.type != b.type: |
385 else: |
408 else: |
386 yield ado |
409 yield ado |
387 |
410 |
388 def _diff_functions(self, schema, src_functions, dst_functions): |
411 def _diff_functions(self, schema, src_functions, dst_functions): |
389 for nd in self._diff_names(src_functions, dst_functions): |
412 for nd in self._diff_names(src_functions, dst_functions): |
390 fdo = DiffFunction(change=nd[0], schema=schema, function=nd[1]) |
413 if not self._test_function(nd[1]): |
|
414 continue |
|
415 fdo = DiffFunction(change=nd[0], schema=schema, function=nd[1], show_body_diff=self.function_body_diff) |
391 if nd[0] == '*': |
416 if nd[0] == '*': |
392 # compare function body and result |
417 # compare function body and result |
393 a = src_functions[nd[1]] |
418 a = src_functions[nd[1]] |
394 b = dst_functions[nd[1]] |
419 b = dst_functions[nd[1]] |
395 fdo.changes = self._compare_functions(a, b) |
420 fdo.changes = self._compare_functions(a, b) |
490 self.include_schemas.clear() |
515 self.include_schemas.clear() |
491 self.include_schemas.update(include) |
516 self.include_schemas.update(include) |
492 self.exclude_schemas.clear() |
517 self.exclude_schemas.clear() |
493 self.exclude_schemas.update(exclude) |
518 self.exclude_schemas.update(exclude) |
494 |
519 |
495 |
|
496 def filter_tables(self, include=[], exclude=[]): |
520 def filter_tables(self, include=[], exclude=[]): |
497 self.include_tables.clear() |
521 self.include_tables.clear() |
498 self.include_tables.update(include) |
522 self.include_tables.update(include) |
499 self.exclude_tables.clear() |
523 self.exclude_tables.clear() |
500 self.exclude_tables.update(exclude) |
524 self.exclude_tables.update(exclude) |
501 |
525 |
|
526 def filter_functions(self, regex=''): |
|
527 self.function_regex = re.compile(regex) |
502 |
528 |
503 def _check_schema_exist(self, schema): |
529 def _check_schema_exist(self, schema): |
504 if not schema in self.src.schemas: |
530 if not schema in self.src.schemas: |
505 raise PgDiffError('Schema "%s" not found in source database.' % schema) |
531 raise PgDiffError('Schema "%s" not found in source database.' % schema) |
506 |
532 |