7
7
from dbt .source import Source
8
8
from dbt .utils import find_model_by_fqn , find_model_by_name , dependency_projects , split_path , This , Var , compiler_error
9
9
from dbt .linker import Linker
10
+ import dbt .targets
11
+ import dbt .templates
10
12
import time
11
13
import sqlparse
12
14
15
+ CompilableEntities = ["models" , "tests" , "archives" , "analyses" ]
16
+
13
17
class Compiler (object ):
14
18
def __init__ (self , project , create_template_class ):
15
19
self .project = project
16
20
self .create_template = create_template_class ()
21
+ self .macro_generator = None
22
+ self .target = self .get_target ()
17
23
18
24
def initialize (self ):
19
25
if not os .path .exists (self .project ['target-path' ]):
@@ -24,7 +30,7 @@ def initialize(self):
24
30
25
31
def get_target (self ):
26
32
target_cfg = self .project .run_environment ()
27
- return RedshiftTarget (target_cfg )
33
+ return dbt . targets . get_target (target_cfg )
28
34
29
35
def model_sources (self , this_project , own_project = None ):
30
36
if own_project is None :
@@ -35,9 +41,21 @@ def model_sources(self, this_project, own_project=None):
35
41
return Source (this_project , own_project = own_project ).get_models (paths , self .create_template )
36
42
elif self .create_template .label == 'test' :
37
43
return Source (this_project , own_project = own_project ).get_test_models (paths , self .create_template )
44
+ elif self .create_template .label == 'archive' :
45
+ return []
38
46
else :
39
47
raise RuntimeError ("unexpected create template type: '{}'" .format (self .create_template .label ))
40
48
49
+ def get_macros (self , this_project , own_project = None ):
50
+ if own_project is None :
51
+ own_project = this_project
52
+ paths = own_project .get ('macro-paths' , [])
53
+ return Source (this_project , own_project = own_project ).get_macros (paths )
54
+
55
+ def get_archives (self , project ):
56
+ archive_template = dbt .templates .ArchiveInsertTemplate ()
57
+ return Source (project , own_project = project ).get_archives (archive_template )
58
+
41
59
def project_schemas (self ):
42
60
source_paths = self .project .get ('source-paths' , [])
43
61
return Source (self .project ).get_schemas (source_paths )
@@ -147,16 +165,30 @@ def wrapped_do_ref(*args):
147
165
148
166
def get_context (self , linker , model , models ):
149
167
context = self .project .context ()
168
+
169
+ # built-ins
150
170
context ['ref' ] = self .__ref (linker , context , model , models )
151
171
context ['config' ] = self .__model_config (model , linker )
152
172
context ['this' ] = This (context ['env' ]['schema' ], model .immediate_name , model .name )
153
- context ['compiled_at' ] = time .strftime ('%Y-%m-%d %H:%M:%S' )
154
173
context ['var' ] = Var (model , context = context )
174
+
175
+ # these get re-interpolated at runtime!
176
+ context ['run_started_at' ] = '{{ run_started_at }}'
177
+ context ['invocation_id' ] = '{{ invocation_id }}'
178
+
179
+ # add in context from run target
180
+ context .update (self .target .context )
181
+
182
+ # add in macros (can we cache these somehow?)
183
+ for macro_name , macro in self .macro_generator (context ):
184
+ context [macro_name ] = macro
185
+
155
186
return context
156
187
157
188
def compile_model (self , linker , model , models ):
158
189
try :
159
- jinja = jinja2 .Environment (loader = jinja2 .FileSystemLoader (searchpath = model .root_dir ))
190
+ fs_loader = jinja2 .FileSystemLoader (searchpath = model .root_dir )
191
+ jinja = jinja2 .Environment (loader = fs_loader )
160
192
161
193
# this is a dumb jinja2 bug -- on windows, forward slashes are EXPECTED
162
194
posix_filepath = '/' .join (split_path (model .rel_filepath ))
@@ -169,8 +201,8 @@ def compile_model(self, linker, model, models):
169
201
170
202
return rendered
171
203
172
- def write_graph_file (self , linker ):
173
- filename = 'graph-{}.yml' .format (self . create_template . label )
204
+ def write_graph_file (self , linker , label ):
205
+ filename = 'graph-{}.yml' .format (label )
174
206
graph_path = os .path .join (self .project ['target-path' ], filename )
175
207
linker .write_graph (graph_path )
176
208
@@ -297,13 +329,39 @@ def compile_schema_tests(self, linker):
297
329
298
330
return written_tests
299
331
332
+ def generate_macros (self , all_macros ):
333
+ def do_gen (ctx ):
334
+ macros = []
335
+ for macro in all_macros :
336
+ new_macros = macro .get_macros (ctx )
337
+ macros .extend (new_macros )
338
+ return macros
339
+ return do_gen
340
+
341
+ def compile_archives (self ):
342
+ linker = Linker ()
343
+ all_archives = self .get_archives (self .project )
344
+
345
+ for archive in all_archives :
346
+ sql = archive .compile ()
347
+ fqn = tuple (archive .fqn )
348
+ linker .update_node_data (fqn , archive .serialize ())
349
+ self .__write (archive .build_path (), sql )
350
+
351
+ self .write_graph_file (linker , 'archive' )
352
+ return all_archives
353
+
300
354
def compile (self , dry = False ):
301
355
linker = Linker ()
302
356
303
357
all_models = self .model_sources (this_project = self .project )
358
+ all_macros = self .get_macros (this_project = self .project )
304
359
305
360
for project in dependency_projects (self .project ):
306
361
all_models .extend (self .model_sources (this_project = self .project , own_project = project ))
362
+ all_macros .extend (self .get_macros (this_project = self .project , own_project = project ))
363
+
364
+ self .macro_generator = self .generate_macros (all_macros )
307
365
308
366
enabled_models = [model for model in all_models if model .is_enabled ]
309
367
@@ -314,11 +372,19 @@ def compile(self, dry=False):
314
372
315
373
self .validate_models_unique (compiled_models )
316
374
self .validate_models_unique (written_schema_tests )
317
- self .write_graph_file (linker )
375
+ self .write_graph_file (linker , self . create_template . label )
318
376
319
- if self .create_template .label != 'test' :
377
+ if self .create_template .label not in [ 'test' , 'archive' ] :
320
378
written_analyses = self .compile_analyses (linker , compiled_models )
321
379
else :
322
380
written_analyses = []
323
381
324
- return len (written_models ), len (written_schema_tests ), len (written_analyses )
382
+
383
+ compiled_archives = self .compile_archives ()
384
+
385
+ return {
386
+ "models" : len (written_models ),
387
+ "tests" : len (written_schema_tests ),
388
+ "archives" : len (compiled_archives ),
389
+ "analyses" : len (written_analyses )
390
+ }
0 commit comments