13
13
from sqeleton .schema import create_schema
14
14
from sqeleton .queries .api import current_timestamp
15
15
16
+ from .dbt import DbtDiffer
16
17
from .utils import eval_name_template , remove_password_from_url , safezip , match_like
17
18
from .diff_tables import Algorithm
18
- from .hashdiff_tables import HashDiffer , DEFAULT_BISECTION_THRESHOLD , DEFAULT_BISECTION_FACTOR
19
+ from .hashdiff_tables import (
20
+ HashDiffer ,
21
+ DEFAULT_BISECTION_THRESHOLD ,
22
+ DEFAULT_BISECTION_FACTOR ,
23
+ )
19
24
from .joindiff_tables import TABLE_WRITE_LIMIT , JoinDiffer
20
25
from .table_segment import TableSegment
21
26
from .databases import connect
@@ -98,9 +103,20 @@ def write_usage(self, prog: str, args: str = "", prefix: Optional[str] = None) -
98
103
@click .argument ("database2" , required = False )
99
104
@click .argument ("table2" , required = False )
100
105
@click .option (
101
- "-k" , "--key-columns" , default = [], multiple = True , help = "Names of primary key columns. Default='id'." , metavar = "NAME"
106
+ "-k" ,
107
+ "--key-columns" ,
108
+ default = [],
109
+ multiple = True ,
110
+ help = "Names of primary key columns. Default='id'." ,
111
+ metavar = "NAME" ,
112
+ )
113
+ @click .option (
114
+ "-t" ,
115
+ "--update-column" ,
116
+ default = None ,
117
+ help = "Name of updated_at/last_updated column" ,
118
+ metavar = "NAME" ,
102
119
)
103
- @click .option ("-t" , "--update-column" , default = None , help = "Name of updated_at/last_updated column" , metavar = "NAME" )
104
120
@click .option (
105
121
"-c" ,
106
122
"--columns" ,
@@ -111,7 +127,13 @@ def write_usage(self, prog: str, args: str = "", prefix: Optional[str] = None) -
111
127
"Accepts a name or a pattern like in SQL. Example: -c col% -c another_col" ,
112
128
metavar = "NAME" ,
113
129
)
114
- @click .option ("-l" , "--limit" , default = None , help = "Maximum number of differences to find" , metavar = "NUM" )
130
+ @click .option (
131
+ "-l" ,
132
+ "--limit" ,
133
+ default = None ,
134
+ help = "Maximum number of differences to find" ,
135
+ metavar = "NUM" ,
136
+ )
115
137
@click .option (
116
138
"--bisection-factor" ,
117
139
default = None ,
@@ -140,15 +162,27 @@ def write_usage(self, prog: str, args: str = "", prefix: Optional[str] = None) -
140
162
metavar = "AGE" ,
141
163
)
142
164
@click .option (
143
- "--max-age" , default = None , help = "Considers only rows younger than specified. See --min-age." , metavar = "AGE"
165
+ "--max-age" ,
166
+ default = None ,
167
+ help = "Considers only rows younger than specified. See --min-age." ,
168
+ metavar = "AGE" ,
144
169
)
145
170
@click .option ("-s" , "--stats" , is_flag = True , help = "Print stats instead of a detailed diff" )
146
171
@click .option ("-d" , "--debug" , is_flag = True , help = "Print debug info" )
147
- @click .option ("--json" , "json_output" , is_flag = True , help = "Print JSONL output for machine readability" )
172
+ @click .option (
173
+ "--json" ,
174
+ "json_output" ,
175
+ is_flag = True ,
176
+ help = "Print JSONL output for machine readability" ,
177
+ )
148
178
@click .option ("-v" , "--verbose" , is_flag = True , help = "Print extra info" )
149
179
@click .option ("--version" , is_flag = True , help = "Print version info and exit" )
150
180
@click .option ("-i" , "--interactive" , is_flag = True , help = "Confirm queries, implies --debug" )
151
- @click .option ("--no-tracking" , is_flag = True , help = "data-diff sends home anonymous usage data. Use this to disable it." )
181
+ @click .option (
182
+ "--no-tracking" ,
183
+ is_flag = True ,
184
+ help = "data-diff sends home anonymous usage data. Use this to disable it." ,
185
+ )
152
186
@click .option (
153
187
"--case-sensitive" ,
154
188
is_flag = True ,
@@ -185,9 +219,18 @@ def write_usage(self, prog: str, args: str = "", prefix: Optional[str] = None) -
185
219
metavar = "COUNT" ,
186
220
)
187
221
@click .option (
188
- "-w" , "--where" , default = None , help = "An additional 'where' expression to restrict the search space. Beware of SQL Injection!" , metavar = "EXPR"
222
+ "-w" ,
223
+ "--where" ,
224
+ default = None ,
225
+ help = "An additional 'where' expression to restrict the search space. Beware of SQL Injection!" ,
226
+ metavar = "EXPR" ,
227
+ )
228
+ @click .option (
229
+ "-a" ,
230
+ "--algorithm" ,
231
+ default = Algorithm .AUTO .value ,
232
+ type = click .Choice ([i .value for i in Algorithm ]),
189
233
)
190
- @click .option ("-a" , "--algorithm" , default = Algorithm .AUTO .value , type = click .Choice ([i .value for i in Algorithm ]))
191
234
@click .option (
192
235
"--conf" ,
193
236
default = None ,
@@ -200,24 +243,74 @@ def write_usage(self, prog: str, args: str = "", prefix: Optional[str] = None) -
200
243
help = "Name of run-configuration to run. If used, CLI arguments for database and table must be omitted." ,
201
244
metavar = "NAME" ,
202
245
)
246
+ @click .option (
247
+ "--dbt" ,
248
+ is_flag = True ,
249
+ help = "Run dbt diff." ,
250
+ )
251
+ @click .option (
252
+ "--dbt-cloud" ,
253
+ is_flag = True ,
254
+ help = "Run dbt diff on Datafold cloud. Expects an api key on env var DATAFOLD_API_KEY." ,
255
+ )
256
+ @click .option (
257
+ "--dbt-profiles-dir" ,
258
+ default = None ,
259
+ metavar = "PATH" ,
260
+ help = "Override the default dbt profile location (~/.dbt)." ,
261
+ )
262
+ @click .option (
263
+ "--dbt-project-dir" ,
264
+ default = None ,
265
+ metavar = "PATH" ,
266
+ help = "Override the dbt project directory. Otherwise assumed to be the current directory." ,
267
+ )
203
268
def main (conf , run , ** kw ):
204
269
if kw ["table2" ] is None and kw ["database2" ]:
205
270
# Use the "database table table" form
206
271
kw ["table2" ] = kw ["database2" ]
207
272
kw ["database2" ] = kw ["database1" ]
208
273
274
+ if kw ["version" ]:
275
+ print (f"v{ __version__ } " )
276
+ return
277
+
209
278
if conf :
210
279
kw = apply_config_from_file (conf , run , kw )
211
280
281
+ if kw ["no_tracking" ]:
282
+ disable_tracking ()
283
+
284
+ if kw .get ("interactive" ):
285
+ kw ["debug" ] = True
286
+
287
+ if kw ["debug" ]:
288
+ logging .basicConfig (level = logging .DEBUG , format = LOG_FORMAT , datefmt = DATE_FORMAT )
289
+ if kw .get ("__conf__" ):
290
+ kw ["__conf__" ] = deepcopy (kw ["__conf__" ])
291
+ _remove_passwords_in_dict (kw ["__conf__" ])
292
+ logging .debug (f"Applied run configuration: { kw ['__conf__' ]} " )
293
+ elif kw .get ("verbose" ):
294
+ logging .basicConfig (level = logging .INFO , format = LOG_FORMAT , datefmt = DATE_FORMAT )
295
+ else :
296
+ logging .basicConfig (level = logging .WARNING , format = LOG_FORMAT , datefmt = DATE_FORMAT )
297
+
212
298
try :
213
- return _main (** kw )
299
+ if kw ["dbt" ] or kw ["dbt_cloud" ]:
300
+ DbtDiffer .diff (
301
+ profiles_dir_override = kw ["dbt_profiles_dir" ],
302
+ project_dir_override = kw ["dbt_project_dir" ],
303
+ is_cloud = kw ["dbt_cloud" ],
304
+ )
305
+ else :
306
+ return _data_diff (** kw )
214
307
except Exception as e :
215
308
logging .error (e )
216
309
if kw ["debug" ]:
217
310
raise
218
311
219
312
220
- def _main (
313
+ def _data_diff (
221
314
database1 ,
222
315
table1 ,
223
316
database2 ,
@@ -246,31 +339,14 @@ def _main(
246
339
materialize_all_rows ,
247
340
table_write_limit ,
248
341
materialize_to_table ,
342
+ dbt ,
343
+ dbt_cloud ,
344
+ dbt_profiles_dir ,
345
+ dbt_project_dir ,
249
346
threads1 = None ,
250
347
threads2 = None ,
251
348
__conf__ = None ,
252
349
):
253
- if version :
254
- print (f"v{ __version__ } " )
255
- return
256
-
257
- if no_tracking :
258
- disable_tracking ()
259
-
260
- if interactive :
261
- debug = True
262
-
263
- if debug :
264
- logging .basicConfig (level = logging .DEBUG , format = LOG_FORMAT , datefmt = DATE_FORMAT )
265
- if __conf__ :
266
- __conf__ = deepcopy (__conf__ )
267
- _remove_passwords_in_dict (__conf__ )
268
- logging .debug (f"Applied run configuration: { __conf__ } " )
269
- elif verbose :
270
- logging .basicConfig (level = logging .INFO , format = LOG_FORMAT , datefmt = DATE_FORMAT )
271
- else :
272
- logging .basicConfig (level = logging .WARNING , format = LOG_FORMAT , datefmt = DATE_FORMAT )
273
-
274
350
if limit and stats :
275
351
logging .error ("Cannot specify a limit when using the -s/--stats switch" )
276
352
return
0 commit comments