Skip to content
This repository was archived by the owner on May 17, 2024. It is now read-only.

Commit b28066f

Browse files
committed
Fixed oracle support (normalize-fields)
1 parent 66248cf commit b28066f

File tree

2 files changed

+39
-22
lines changed

2 files changed

+39
-22
lines changed

data_diff/database.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,8 @@ def normalize_value_by_type(value: str, coltype: ColType) -> str:
156156
157157
- Dates are expected in the format:
158158
"YYYY-MM-DD HH:mm:SS.FFFFFF"
159-
(number of F depends on coltype.precision)
160-
Or if precision=0 then
161-
"YYYY-MM-DD HH:mm:SS" (without the dot)
159+
160+
Rounded up/down according to coltype.rounds
162161
163162
"""
164163
...
@@ -474,6 +473,8 @@ def normalize_value_by_type(self, value: str, coltype: ColType) -> str:
474473

475474

476475
class Oracle(ThreadedDatabase):
476+
ROUNDS_ON_PREC_LOSS = True
477+
477478
def __init__(self, host, port, user, password, *, database, thread_count, **kw):
478479
assert not port
479480
self.kwargs = dict(user=user, password=password, dsn="%s/%s" % (host, database), **kw)
@@ -509,9 +510,7 @@ def select_table_schema(self, path: DbPath) -> str:
509510

510511
def normalize_value_by_type(self, value: str, coltype: ColType) -> str:
511512
if isinstance(coltype, PrecisionType):
512-
if coltype.precision == 0:
513-
return f"to_char(cast({value} as timestamp({coltype.precision})), 'YYYY-MM-DD HH24:MI:SS')"
514-
return f"to_char(cast({value} as timestamp({coltype.precision})), 'YYYY-MM-DD HH24:MI:SS.FF{coltype.precision or ''}')"
513+
return f"to_char(cast({value} as timestamp({coltype.precision})), 'YYYY-MM-DD HH24:MI:SS.FF6')"
515514
return self.to_string(f"{value}")
516515

517516
def _parse_type(self, type_repr: str, datetime_precision: int = None, numeric_precision: int = None) -> ColType:
@@ -524,7 +523,9 @@ def _parse_type(self, type_repr: str, datetime_precision: int = None, numeric_pr
524523
m = re.match(regexp + "$", type_repr)
525524
if m:
526525
datetime_precision = int(m.group(1))
527-
return cls(precision=datetime_precision if datetime_precision is not None else DEFAULT_PRECISION)
526+
return cls(precision=datetime_precision if datetime_precision is not None else DEFAULT_PRECISION,
527+
rounds=self.ROUNDS_ON_PREC_LOSS
528+
)
528529

529530
return UnknownColType(type_repr)
530531

tests/test_database_types.py

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import unittest
2-
import preql
32
import time
43
from data_diff import database as db
5-
from data_diff.diff_tables import TableDiffer, TableSegment, split_space
4+
from data_diff.diff_tables import TableDiffer, TableSegment
65
from parameterized import parameterized, parameterized_class
7-
from .common import CONN_STRINGS, str_to_checksum
6+
from .common import CONN_STRINGS
87
import logging
98

109
logging.getLogger("diff_tables").setLevel(logging.WARN)
@@ -115,9 +114,9 @@
115114
# "int",
116115
],
117116
"datetime_no_timezone": [
118-
# "timestamp",
119-
# "timestamp(6)",
120-
# "timestamp(9)",
117+
"timestamp with local time zone",
118+
"timestamp(6) with local time zone",
119+
"timestamp(9) with local time zone",
121120
],
122121
"float": [
123122
# "float",
@@ -179,11 +178,20 @@ def expand_params(testcase_func, param_num, param):
179178

180179

181180
def _insert_to_table(conn, table, values):
182-
insertion_query = f"INSERT INTO {table} (id, col) VALUES "
183-
for j, sample in values:
184-
insertion_query += f"({j}, '{sample}'),"
185-
186-
conn.query(insertion_query[0:-1], None)
181+
insertion_query = f"INSERT INTO {table} (id, col) "
182+
183+
if isinstance(conn, db.Oracle):
184+
selects = []
185+
for j, sample in values:
186+
selects.append( f"SELECT {j}, timestamp '{sample}' FROM dual" )
187+
insertion_query += ' UNION ALL '.join(selects)
188+
else:
189+
insertion_query += ' VALUES '
190+
for j, sample in values:
191+
insertion_query += f"({j}, '{sample}'),"
192+
insertion_query = insertion_query[0:-1]
193+
194+
conn.query(insertion_query, None)
187195
if not isinstance(conn, db.BigQuery):
188196
conn.query("COMMIT", None)
189197

@@ -204,14 +212,22 @@ def test_types(self, source_db, target_db, source_type, target_type, type_catego
204212
src_table = src_conn.quote(".".join(src_table_path))
205213
dst_table = dst_conn.quote(".".join(dst_table_path))
206214

207-
src_conn.query(f"DROP TABLE IF EXISTS {src_table}", None)
208-
src_conn.query(f"CREATE TABLE {src_table}(id int, col {source_type});", None)
215+
if isinstance(src_conn, db.Oracle):
216+
src_conn.query(f"DROP TABLE {src_table}", None)
217+
else:
218+
src_conn.query(f"DROP TABLE IF EXISTS {src_table}", None)
219+
220+
src_conn.query(f"CREATE TABLE {src_table}(id int, col {source_type})", None)
209221
_insert_to_table(src_conn, src_table, enumerate(sample_values, 1))
210222

211223
values_in_source = src_conn.query(f"SELECT id, col FROM {src_table}", list)
212224

213-
dst_conn.query(f"DROP TABLE IF EXISTS {dst_table}", None)
214-
dst_conn.query(f"CREATE TABLE {dst_table}(id int, col {target_type});", None)
225+
if isinstance(dst_conn, db.Oracle):
226+
dst_conn.query(f"DROP TABLE {dst_table}", None)
227+
else:
228+
dst_conn.query(f"DROP TABLE IF EXISTS {dst_table}", None)
229+
230+
dst_conn.query(f"CREATE TABLE {dst_table}(id int, col {target_type})", None)
215231
_insert_to_table(dst_conn, dst_table, values_in_source)
216232

217233
self.table = TableSegment(self.src_conn, src_table_path, "id", None, ("col",), quote_columns=False)

0 commit comments

Comments
 (0)