1
0
Fork 0
sqlglot/tests/test_diff.py
Daniel Baumann 88f99e1c27
Merging upstream version 11.4.5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-13 15:48:10 +01:00

177 lines
6 KiB
Python

import unittest
from sqlglot import exp, parse_one
from sqlglot.diff import Insert, Keep, Move, Remove, Update, diff
from sqlglot.expressions import Join, to_identifier
class TestDiff(unittest.TestCase):
def test_simple(self):
self._validate_delta_only(
diff(parse_one("SELECT a + b"), parse_one("SELECT a - b")),
[
Remove(parse_one("a + b")), # the Add node
Insert(parse_one("a - b")), # the Sub node
],
)
self._validate_delta_only(
diff(parse_one("SELECT a, b, c"), parse_one("SELECT a, c")),
[
Remove(to_identifier("b", quoted=False)), # the Identifier node
Remove(parse_one("b")), # the Column node
],
)
self._validate_delta_only(
diff(parse_one("SELECT a, b"), parse_one("SELECT a, b, c")),
[
Insert(to_identifier("c", quoted=False)), # the Identifier node
Insert(parse_one("c")), # the Column node
],
)
self._validate_delta_only(
diff(
parse_one("SELECT a FROM table_one"),
parse_one("SELECT a FROM table_two"),
),
[
Update(
to_identifier("table_one", quoted=False),
to_identifier("table_two", quoted=False),
), # the Identifier node
],
)
def test_node_position_changed(self):
self._validate_delta_only(
diff(parse_one("SELECT a, b, c"), parse_one("SELECT c, a, b")),
[
Move(parse_one("c")), # the Column node
],
)
self._validate_delta_only(
diff(parse_one("SELECT a + b"), parse_one("SELECT b + a")),
[
Move(parse_one("a")), # the Column node
],
)
self._validate_delta_only(
diff(parse_one("SELECT aaaa AND bbbb"), parse_one("SELECT bbbb AND aaaa")),
[
Move(parse_one("aaaa")), # the Column node
],
)
self._validate_delta_only(
diff(
parse_one("SELECT aaaa OR bbbb OR cccc"),
parse_one("SELECT cccc OR bbbb OR aaaa"),
),
[
Move(parse_one("aaaa")), # the Column node
Move(parse_one("cccc")), # the Column node
],
)
def test_cte(self):
expr_src = """
WITH
cte1 AS (SELECT a, b, LOWER(c) AS c FROM table_one WHERE d = 'filter'),
cte2 AS (SELECT d, e, f FROM table_two)
SELECT a, b, d, e FROM cte1 JOIN cte2 ON f = c
"""
expr_tgt = """
WITH
cte1 AS (SELECT a, b, c FROM table_one WHERE d = 'different_filter'),
cte2 AS (SELECT d, e, f FROM table_two)
SELECT a, b, d, e FROM cte1 JOIN cte2 ON f = c
"""
self._validate_delta_only(
diff(parse_one(expr_src), parse_one(expr_tgt)),
[
Remove(parse_one("LOWER(c) AS c")), # the Alias node
Remove(to_identifier("c", quoted=False)), # the Identifier node
Remove(parse_one("LOWER(c)")), # the Lower node
Remove(parse_one("'filter'")), # the Literal node
Insert(parse_one("'different_filter'")), # the Literal node
],
)
def test_join(self):
expr_src = "SELECT a, b FROM t1 LEFT JOIN t2 ON t1.key = t2.key"
expr_tgt = "SELECT a, b FROM t1 RIGHT JOIN t2 ON t1.key = t2.key"
changes = diff(parse_one(expr_src), parse_one(expr_tgt))
changes = _delta_only(changes)
self.assertEqual(len(changes), 2)
self.assertTrue(isinstance(changes[0], Remove))
self.assertTrue(isinstance(changes[1], Insert))
self.assertTrue(all(isinstance(c.expression, Join) for c in changes))
def test_window_functions(self):
expr_src = parse_one("SELECT ROW_NUMBER() OVER (PARTITION BY a ORDER BY b)")
expr_tgt = parse_one("SELECT RANK() OVER (PARTITION BY a ORDER BY b)")
self._validate_delta_only(diff(expr_src, expr_src), [])
self._validate_delta_only(
diff(expr_src, expr_tgt),
[
Remove(parse_one("ROW_NUMBER()")), # the Anonymous node
Insert(parse_one("RANK()")), # the Anonymous node
],
)
def test_pre_matchings(self):
expr_src = parse_one("SELECT 1")
expr_tgt = parse_one("SELECT 1, 2, 3, 4")
self._validate_delta_only(
diff(expr_src, expr_tgt),
[
Remove(expr_src),
Insert(expr_tgt),
Insert(exp.Literal.number(2)),
Insert(exp.Literal.number(3)),
Insert(exp.Literal.number(4)),
],
)
self._validate_delta_only(
diff(expr_src, expr_tgt, matchings=[(expr_src, expr_tgt)]),
[
Insert(exp.Literal.number(2)),
Insert(exp.Literal.number(3)),
Insert(exp.Literal.number(4)),
],
)
with self.assertRaises(ValueError):
diff(expr_src, expr_tgt, matchings=[(expr_src, expr_tgt), (expr_src, expr_tgt)])
def test_identifier(self):
expr_src = parse_one("SELECT a FROM tbl")
expr_tgt = parse_one("SELECT a, tbl.b from tbl")
self._validate_delta_only(
diff(expr_src, expr_tgt),
[
Insert(expression=exp.to_identifier("b")),
Insert(expression=exp.to_column("tbl.b")),
Insert(expression=exp.to_identifier("tbl")),
],
)
def _validate_delta_only(self, actual_diff, expected_delta):
actual_delta = _delta_only(actual_diff)
self.assertEqual(set(actual_delta), set(expected_delta))
def _delta_only(changes):
return [d for d in changes if not isinstance(d, Keep)]