Exemplo n.º 1
0
    def __init__(
        self,
        root_project: RuntimeConfig,
        all_projects: Mapping[str, Project],
        macro_hook: Optional[Callable[[Manifest], Any]] = None,
    ) -> None:
        self.root_project: RuntimeConfig = root_project
        self.all_projects: Mapping[str, Project] = all_projects
        self.manifest: Manifest = Manifest({}, {}, {}, {}, {}, {}, [], {})
        self.manifest.metadata = root_project.get_metadata()
        # This is a MacroQueryStringSetter callable, which is called
        # later after we set the MacroManifest in the adapter. It sets
        # up the query headers.
        self.macro_hook: Callable[[Manifest], Any]
        if macro_hook is None:
            self.macro_hook = lambda m: None
        else:
            self.macro_hook = macro_hook

        self._perf_info = ManifestLoaderInfo(
            is_partial_parse_enabled=self._partial_parse_enabled()
        )
        # State check determines whether the old_manifest and the current
        # manifest match well enough to do partial parsing
        self.manifest.state_check = self.build_manifest_state_check()
        # This is a saved manifest from a previous run that's used for partial parsing
        self.old_manifest: Optional[Manifest] = self.read_saved_manifest()
Exemplo n.º 2
0
def manifest(seed, source, ephemeral_model, view_model, table_model,
             ext_source, ext_model, union_model, ext_source_2,
             ext_source_other, ext_source_other_2, table_id_unique,
             table_id_not_null, view_id_unique, ext_source_id_unique,
             view_test_nothing, namespaced_seed, namespace_model,
             namespaced_union_model):
    nodes = [
        seed, ephemeral_model, view_model, table_model, union_model, ext_model,
        table_id_unique, table_id_not_null, view_id_unique,
        ext_source_id_unique, view_test_nothing, namespaced_seed,
        namespace_model, namespaced_union_model
    ]
    sources = [
        source, ext_source, ext_source_2, ext_source_other, ext_source_other_2
    ]
    manifest = Manifest(
        nodes={n.unique_id: n
               for n in nodes},
        sources={s.unique_id: s
                 for s in sources},
        macros={},
        docs={},
        files={},
        exposures={},
        disabled=[],
        selectors={},
    )
    return manifest
Exemplo n.º 3
0
    def load_all(cls, project_config, all_projects):
        root_project = project_config
        macros = MacroLoader.load_all(root_project, all_projects)
        macros.update(OperationLoader.load_all(root_project, all_projects))
        nodes = {}
        for loader in cls._LOADERS:
            nodes.update(loader.load_all(root_project, all_projects, macros))
        docs = DocumentationLoader.load_all(root_project, all_projects)

        tests, patches = SchemaTestLoader.load_all(root_project, all_projects)

        manifest = Manifest(nodes=nodes, macros=macros, docs=docs,
                            generated_at=timestring(), config=project_config)
        manifest.add_nodes(tests)
        manifest.patch_nodes(patches)

        patches = DocumentationLoader.get_model_doc_patches(nodes, docs)
        manifest.patch_nodes(patches)

        manifest = dbt.parser.ParserUtils.process_refs(
            manifest,
            root_project.project_name
        )
        manifest = dbt.parser.ParserUtils.process_docs(manifest, root_project)
        return manifest
Exemplo n.º 4
0
    def test_no_nodes_with_metadata(self, mock_user):
        mock_user.id = 'cfc9500f-dc7f-4c83-9ea7-2c581c1b38cf'
        mock_user.do_not_track = True
        metadata = ManifestMetadata(
            project_id='098f6bcd4621d373cade4e832627b4f6')
        manifest = Manifest(nodes={},
                            macros={},
                            docs={},
                            generated_at=datetime.utcnow(),
                            disabled=[],
                            metadata=metadata,
                            files={})

        self.assertEqual(
            manifest.writable_manifest().to_dict(), {
                'nodes': {},
                'macros': {},
                'parent_map': {},
                'child_map': {},
                'generated_at': '2018-02-14T09:15:13Z',
                'docs': {},
                'metadata': {
                    'project_id': '098f6bcd4621d373cade4e832627b4f6',
                    'user_id': 'cfc9500f-dc7f-4c83-9ea7-2c581c1b38cf',
                    'send_anonymous_usage_stats': False,
                },
                'disabled': [],
                'files': {},
            })
Exemplo n.º 5
0
    def create_manifest(self) -> Manifest:
        # before we do anything else, patch the sources. This mutates
        # results.disabled, so it needs to come before the final 'disabled'
        # list is created
        sources = patch_sources(self.results, self.root_project)
        disabled = []
        for value in self.results.disabled.values():
            disabled.extend(value)

        nodes: MutableMapping[str, ManifestNode] = {
            k: v for k, v in self.results.nodes.items()
        }

        manifest = Manifest(
            nodes=nodes,
            sources=sources,
            macros=self.results.macros,
            docs=self.results.docs,
            exposures=self.results.exposures,
            generated_at=datetime.utcnow(),
            metadata=self.root_project.get_metadata(),
            disabled=disabled,
            files=self.results.files,
        )
        manifest.patch_nodes(self.results.patches)
        manifest.patch_macros(self.results.macro_patches)
        self.process_manifest(manifest)
        return manifest
Exemplo n.º 6
0
 def setUp(self):
     x_depends_on = mock.MagicMock()
     y_depends_on = mock.MagicMock()
     x_uid = 'model.project.x'
     y_uid = 'model.otherproject.y'
     src_uid = 'source.thirdproject.src.tbl'
     remote_docref = mock.MagicMock(documentation_package='otherproject', documentation_name='my_doc', column_name=None)
     docref = mock.MagicMock(documentation_package='', documentation_name='my_doc', column_name=None)
     self.x_node = mock.MagicMock(
         refs=[], sources=[['src', 'tbl']], docrefs=[remote_docref], unique_id=x_uid,
         resource_type=NodeType.Model, depends_on=x_depends_on,
         description='other_project: {{ doc("otherproject", "my_doc") }}',
     )
     self.y_node = mock.MagicMock(
         refs=[['x']], sources=[], docrefs=[docref], unique_id=y_uid,
         resource_type=NodeType.Model, depends_on=y_depends_on,
         description='{{ doc("my_doc") }}',
     )
     self.src_node = mock.MagicMock(
         resource_type=NodeType.Source, unique_id=src_uid,
     )
     nodes = {
         x_uid: self.x_node,
         y_uid: self.y_node,
         src_uid: self.src_node,
     }
     docs = {
         'otherproject.my_doc': mock.MagicMock(block_contents='some docs')
     }
     self.manifest = Manifest(
         nodes=nodes, macros={}, docs=docs, disabled=[], files={}, generated_at=mock.MagicMock()
     )
Exemplo n.º 7
0
 def test_get_resource_fqns_empty(self):
     manifest = Manifest(nodes={},
                         macros={},
                         docs={},
                         generated_at=timestring(),
                         disabled=[])
     self.assertEqual(manifest.get_resource_fqns(), {})
Exemplo n.º 8
0
 def test_no_nodes_with_metadata(self, mock_user):
     mock_user.id = 'cfc9500f-dc7f-4c83-9ea7-2c581c1b38cf'
     mock_user.do_not_track = True
     config = mock.MagicMock()
     # md5 of 'test'
     config.hashed_name.return_value = '098f6bcd4621d373cade4e832627b4f6'
     manifest = Manifest(nodes={},
                         macros={},
                         docs={},
                         generated_at=timestring(),
                         disabled=[],
                         config=config)
     metadata = {
         'project_id': '098f6bcd4621d373cade4e832627b4f6',
         'user_id': 'cfc9500f-dc7f-4c83-9ea7-2c581c1b38cf',
         'send_anonymous_usage_stats': False,
     }
     self.assertEqual(
         manifest.serialize(), {
             'nodes': {},
             'macros': {},
             'parent_map': {},
             'child_map': {},
             'generated_at': '2018-02-14T09:15:13Z',
             'docs': {},
             'metadata': {
                 'project_id': '098f6bcd4621d373cade4e832627b4f6',
                 'user_id': 'cfc9500f-dc7f-4c83-9ea7-2c581c1b38cf',
                 'send_anonymous_usage_stats': False,
             },
             'disabled': [],
         })
Exemplo n.º 9
0
 def create_manifest(self) -> Manifest:
     nodes: Dict[str, CompileResultNode] = {}
     nodes.update(self.results.nodes)
     nodes.update(self.results.sources)
     disabled = []
     for value in self.results.disabled.values():
         disabled.extend(value)
     manifest = Manifest(
         nodes=nodes,
         macros=self.results.macros,
         docs=self.results.docs,
         generated_at=datetime.utcnow(),
         metadata=self.root_project.get_metadata(),
         disabled=disabled,
         files=self.results.files,
     )
     manifest.patch_nodes(self.results.patches)
     manifest = ParserUtils.process_sources(
         manifest, self.root_project.project_name
     )
     manifest = ParserUtils.process_refs(
         manifest, self.root_project.project_name
     )
     manifest = ParserUtils.process_docs(
         manifest, self.root_project.project_name
     )
     return manifest
Exemplo n.º 10
0
 def test_get_resource_fqns_empty(self):
     manifest = Manifest(nodes={},
                         macros={},
                         docs={},
                         generated_at=datetime.utcnow(),
                         disabled=[],
                         files={})
     self.assertEqual(manifest.get_resource_fqns(), {})
Exemplo n.º 11
0
 def load(self, internal_manifest=None):
     self._load_macros(internal_manifest=internal_manifest)
     # make a manifest with just the macros to get the context
     self.macro_manifest = Manifest(macros=self.macros,
                                    nodes={},
                                    docs={},
                                    generated_at=timestring(),
                                    disabled=[])
     self._load_nodes()
     self._load_docs()
     self._load_schema_tests()
Exemplo n.º 12
0
 def setUp(self):
     super().setUp()
     x_depends_on = mock.MagicMock()
     y_depends_on = mock.MagicMock()
     self.x_node = MockNode(
         package='project',
         name='x',
         config=mock.MagicMock(enabled=True),
         refs=[],
         sources=[['src', 'tbl']],
         depends_on=x_depends_on,
         description='other_project: {{ doc("otherproject", "my_doc") }}',
     )
     self.y_node = MockNode(
         package='otherproject',
         name='y',
         config=mock.MagicMock(enabled=True),
         refs=[['x']],
         sources=[],
         depends_on=y_depends_on,
         description='{{ doc("my_doc") }}',
     )
     self.src_node = MockSource(
         package='thirdproject',
         source_name='src',
         name='tbl',
         config=mock.MagicMock(enabled=True),
     )
     self.doc = MockDocumentation(
         package='otherproject',
         name='my_doc',
         block_contents='some docs',
     )
     nodes = {
         self.x_node.unique_id: self.x_node,
         self.y_node.unique_id: self.y_node,
     }
     sources = {
         self.src_node.unique_id: self.src_node,
     }
     docs = {
         self.doc.unique_id: self.doc,
     }
     self.manifest = Manifest(
         nodes=nodes,
         sources=sources,
         macros={},
         docs=docs,
         disabled=[],
         files={},
         exposures={},
         selectors={},
     )
Exemplo n.º 13
0
 def test__to_flat_graph(self):
     nodes = copy.copy(self.nested_nodes)
     manifest = Manifest(nodes=nodes, macros={}, docs={},
                         generated_at=timestring(), disabled=[])
     flat_graph = manifest.to_flat_graph()
     flat_nodes = flat_graph['nodes']
     self.assertEqual(set(flat_graph), set(['nodes', 'macros']))
     self.assertEqual(flat_graph['macros'], {})
     self.assertEqual(set(flat_nodes), set(self.nested_nodes))
     expected_keys = set(ParsedNode.SCHEMA['required']) | {'agate_table'}
     for node in flat_nodes.values():
         self.assertEqual(set(node), expected_keys)
Exemplo n.º 14
0
 def create_manifest(self):
     manifest = Manifest(nodes=self.nodes,
                         macros=self.macros,
                         docs=self.docs,
                         generated_at=timestring(),
                         config=self.root_project,
                         disabled=self.disabled)
     manifest.add_nodes(self.tests)
     manifest.patch_nodes(self.patches)
     manifest = ParserUtils.process_sources(manifest, self.root_project)
     manifest = ParserUtils.process_refs(manifest,
                                         self.root_project.project_name)
     manifest = ParserUtils.process_docs(manifest, self.root_project)
     return manifest
Exemplo n.º 15
0
 def test__build_flat_graph(self):
     nodes = copy.copy(self.nested_nodes)
     manifest = Manifest(nodes=nodes,
                         macros={},
                         docs={},
                         generated_at=datetime.utcnow(),
                         disabled=[],
                         files={})
     manifest.build_flat_graph()
     flat_graph = manifest.flat_graph
     flat_nodes = flat_graph['nodes']
     self.assertEqual(set(flat_graph), set(['nodes']))
     self.assertEqual(set(flat_nodes), set(self.nested_nodes))
     for node in flat_nodes.values():
         self.assertEqual(frozenset(node), REQUIRED_PARSED_NODE_KEYS)
Exemplo n.º 16
0
    def test__nested_nodes(self):
        nodes = copy.copy(self.nested_nodes)
        manifest = Manifest(nodes=nodes,
                            macros={},
                            docs={},
                            generated_at=datetime.utcnow(),
                            disabled=[],
                            files={})
        serialized = manifest.writable_manifest().to_dict()
        self.assertEqual(serialized['generated_at'], '2018-02-14T09:15:13Z')
        self.assertEqual(serialized['docs'], {})
        self.assertEqual(serialized['disabled'], [])
        self.assertEqual(serialized['files'], {})
        parent_map = serialized['parent_map']
        child_map = serialized['child_map']
        # make sure there aren't any extra/missing keys.
        self.assertEqual(set(parent_map), set(nodes))
        self.assertEqual(set(child_map), set(nodes))
        self.assertEqual(parent_map['model.root.sibling'],
                         ['model.root.events'])
        self.assertEqual(parent_map['model.root.nested'], ['model.root.dep'])
        self.assertEqual(parent_map['model.root.dep'], ['model.root.events'])
        # order doesn't matter.
        self.assertEqual(set(parent_map['model.root.multi']),
                         set(['model.root.nested', 'model.root.sibling']))
        self.assertEqual(
            parent_map['model.root.events'],
            [],
        )
        self.assertEqual(
            parent_map['model.snowplow.events'],
            [],
        )

        self.assertEqual(
            child_map['model.root.sibling'],
            ['model.root.multi'],
        )
        self.assertEqual(
            child_map['model.root.nested'],
            ['model.root.multi'],
        )
        self.assertEqual(child_map['model.root.dep'], ['model.root.nested'])
        self.assertEqual(child_map['model.root.multi'], [])
        self.assertEqual(set(child_map['model.root.events']),
                         set(['model.root.dep', 'model.root.sibling']))
        self.assertEqual(child_map['model.snowplow.events'], [])
Exemplo n.º 17
0
    def _load_macro_nodes(self, resource_type):
        parser = MacroParser(self.root_project, self.all_projects)
        for project_name, project in self.all_projects.items():
            self.macros.update(
                parser.load_and_parse(
                    package_name=project_name,
                    root_dir=project.project_root,
                    relative_dirs=project.macro_paths,
                    resource_type=resource_type,
                ))

        # make a manifest with just the macros to get the context
        self.macro_manifest = Manifest(macros=self.macros,
                                       nodes={},
                                       docs={},
                                       generated_at=timestring(),
                                       disabled=[])
Exemplo n.º 18
0
 def test__no_nodes(self):
     manifest = Manifest(nodes={},
                         macros={},
                         docs={},
                         generated_at=datetime.utcnow(),
                         disabled=[],
                         files={})
     self.assertEqual(
         manifest.writable_manifest().to_dict(), {
             'nodes': {},
             'macros': {},
             'parent_map': {},
             'child_map': {},
             'generated_at': '2018-02-14T09:15:13Z',
             'docs': {},
             'metadata': {},
             'disabled': [],
             'files': {},
         })
Exemplo n.º 19
0
 def test_get_resource_fqns(self):
     nodes = copy.copy(self.nested_nodes)
     nodes['seed.root.seed'] = ParsedNode(name='seed',
                                          database='dbt',
                                          schema='analytics',
                                          alias='seed',
                                          resource_type='seed',
                                          unique_id='seed.root.seed',
                                          fqn=['root', 'seed'],
                                          empty=False,
                                          package_name='root',
                                          refs=[['events']],
                                          sources=[],
                                          depends_on={
                                              'nodes': [],
                                              'macros': []
                                          },
                                          config=self.model_config,
                                          tags=[],
                                          path='seed.csv',
                                          original_file_path='seed.csv',
                                          root_path='',
                                          raw_sql='-- csv --')
     manifest = Manifest(nodes=nodes,
                         macros={},
                         docs={},
                         generated_at=timestring(),
                         disabled=[])
     expect = {
         'models':
         frozenset([
             ('snowplow', 'events'),
             ('root', 'events'),
             ('root', 'dep'),
             ('root', 'nested'),
             ('root', 'sibling'),
             ('root', 'multi'),
         ]),
         'seeds':
         frozenset([('root', 'seed')]),
     }
     resource_fqns = manifest.get_resource_fqns()
     self.assertEqual(resource_fqns, expect)
Exemplo n.º 20
0
 def test__to_flat_graph(self):
     nodes = copy.copy(self.nested_nodes)
     manifest = Manifest(nodes=nodes, macros={}, docs={},
                         generated_at=timestring(), disabled=[])
     flat_graph = manifest.to_flat_graph()
     flat_nodes = flat_graph['nodes']
     self.assertEqual(set(flat_graph), set(['nodes', 'macros']))
     self.assertEqual(flat_graph['macros'], {})
     self.assertEqual(set(flat_nodes), set(self.nested_nodes))
     parsed_keys = set(ParsedNode.SCHEMA['required']) | {'agate_table'}
     compiled_keys = set(CompiledNode.SCHEMA['required']) | {'agate_table'}
     compiled_count = 0
     for node in flat_nodes.values():
         if node.get('compiled'):
             self.assertEqual(set(node), compiled_keys)
             compiled_count += 1
         else:
             self.assertEqual(set(node), parsed_keys)
     self.assertEqual(compiled_count, 2)
Exemplo n.º 21
0
 def test__no_nodes(self):
     manifest = Manifest(nodes={},
                         macros={},
                         docs={},
                         generated_at=timestring())
     self.assertEqual(
         manifest.serialize(), {
             'nodes': {},
             'macros': {},
             'parent_map': {},
             'child_map': {},
             'generated_at': '2018-02-14T09:15:13Z',
             'docs': {},
             'metadata': {
                 'project_id': None,
                 'user_id': None,
                 'send_anonymous_usage_stats': None,
             },
         })
Exemplo n.º 22
0
    def create_manifest(self) -> Manifest:
        # before we do anything else, patch the sources. This mutates
        # results.disabled, so it needs to come before the final 'disabled'
        # list is created
        start_patch = time.perf_counter()
        sources = patch_sources(self.results, self.root_project)
        self._perf_info.patch_sources_elapsed = (time.perf_counter() -
                                                 start_patch)
        disabled = []
        for value in self.results.disabled.values():
            disabled.extend(value)

        nodes: MutableMapping[str, ManifestNode] = {
            k: v
            for k, v in self.results.nodes.items()
        }

        manifest = Manifest(
            nodes=nodes,
            sources=sources,
            macros=self.results.macros,
            docs=self.results.docs,
            exposures=self.results.exposures,
            metadata=self.root_project.get_metadata(),
            disabled=disabled,
            files=self.results.files,
            selectors=self.root_project.manifest_selectors,
        )
        manifest.patch_nodes(self.results.patches)
        manifest.patch_macros(self.results.macro_patches)
        start_process = time.perf_counter()
        self.process_manifest(manifest)

        self._perf_info.process_manifest_elapsed = (time.perf_counter() -
                                                    start_process)

        return manifest
Exemplo n.º 23
0
    def test__prepend_ctes__already_has_cte(self):
        ephemeral_config = self.model_config.copy()
        ephemeral_config['materialized'] = 'ephemeral'

        input_graph = Manifest(
            macros={},
            nodes={
                'model.root.view':
                CompiledNode(
                    name='view',
                    schema='analytics',
                    alias='view',
                    resource_type='model',
                    unique_id='model.root.view',
                    fqn=['root_project', 'view'],
                    empty=False,
                    package_name='root',
                    root_path='/usr/src/app',
                    refs=[],
                    depends_on={
                        'nodes': ['model.root.ephemeral'],
                        'macros': []
                    },
                    config=self.model_config,
                    tags=[],
                    path='view.sql',
                    original_file_path='view.sql',
                    raw_sql='select * from {{ref("ephemeral")}}',
                    compiled=True,
                    extra_ctes_injected=False,
                    extra_ctes=[{
                        'id': 'model.root.ephemeral',
                        'sql': None
                    }],
                    injected_sql='',
                    compiled_sql=('with cte as (select * from something_else) '
                                  'select * from __dbt__CTE__ephemeral')),
                'model.root.ephemeral':
                CompiledNode(name='ephemeral',
                             schema='analytics',
                             alias='view',
                             resource_type='model',
                             unique_id='model.root.ephemeral',
                             fqn=['root_project', 'ephemeral'],
                             empty=False,
                             package_name='root',
                             root_path='/usr/src/app',
                             refs=[],
                             depends_on={
                                 'nodes': [],
                                 'macros': []
                             },
                             config=ephemeral_config,
                             tags=[],
                             path='ephemeral.sql',
                             original_file_path='ephemeral.sql',
                             raw_sql='select * from source_table',
                             compiled=True,
                             compiled_sql='select * from source_table',
                             extra_ctes_injected=False,
                             extra_ctes=[],
                             injected_sql=''),
            },
            docs={},
            generated_at='2018-02-14T09:15:13Z')

        result, output_graph = dbt.compilation.prepend_ctes(
            input_graph.nodes['model.root.view'], input_graph)

        self.assertEqual(result, output_graph.nodes['model.root.view'])
        self.assertEqual(result.get('extra_ctes_injected'), True)
        self.assertEqualIgnoreWhitespace(
            result.get('injected_sql'),
            ('with __dbt__CTE__ephemeral as ('
             'select * from source_table'
             '), cte as (select * from something_else) '
             'select * from __dbt__CTE__ephemeral'))

        self.assertEqual((input_graph.nodes.get(
            'model.root.ephemeral', {}).get('extra_ctes_injected')), True)
Exemplo n.º 24
0
    def test__prepend_ctes__no_ctes(self):
        input_graph = Manifest(
            macros={},
            nodes={
                'model.root.view':
                CompiledNode(
                    name='view',
                    schema='analytics',
                    alias='view',
                    resource_type='model',
                    unique_id='model.root.view',
                    fqn=['root_project', 'view'],
                    empty=False,
                    package_name='root',
                    root_path='/usr/src/app',
                    refs=[],
                    depends_on={
                        'nodes': [],
                        'macros': []
                    },
                    config=self.model_config,
                    tags=[],
                    path='view.sql',
                    original_file_path='view.sql',
                    raw_sql=('with cte as (select * from something_else) '
                             'select * from source_table'),
                    compiled=True,
                    extra_ctes_injected=False,
                    extra_ctes=[],
                    injected_sql='',
                    compiled_sql=('with cte as (select * from something_else) '
                                  'select * from source_table')),
                'model.root.view_no_cte':
                CompiledNode(name='view_no_cte',
                             schema='analytics',
                             alias='view_no_cte',
                             resource_type='model',
                             unique_id='model.root.view_no_cte',
                             fqn=['root_project', 'view_no_cte'],
                             empty=False,
                             package_name='root',
                             root_path='/usr/src/app',
                             refs=[],
                             depends_on={
                                 'nodes': [],
                                 'macros': []
                             },
                             config=self.model_config,
                             tags=[],
                             path='view.sql',
                             original_file_path='view.sql',
                             raw_sql='select * from source_table',
                             compiled=True,
                             extra_ctes_injected=False,
                             extra_ctes=[],
                             injected_sql='',
                             compiled_sql=('select * from source_table')),
            },
            docs={},
            generated_at='2018-02-14T09:15:13Z')

        result, output_graph = dbt.compilation.prepend_ctes(
            input_graph.nodes.get('model.root.view'), input_graph)

        self.assertEqual(result, output_graph.nodes.get('model.root.view'))
        self.assertEqual(result.get('extra_ctes_injected'), True)
        self.assertEqualIgnoreWhitespace(
            result.get('injected_sql'),
            (output_graph.nodes.get('model.root.view').get('compiled_sql')))

        result, output_graph = dbt.compilation.prepend_ctes(
            input_graph.nodes.get('model.root.view_no_cte'), input_graph)

        self.assertEqual(result,
                         output_graph.nodes.get('model.root.view_no_cte'))
        self.assertEqual(result.get('extra_ctes_injected'), True)
        self.assertEqualIgnoreWhitespace(
            result.get('injected_sql'), (output_graph.nodes.get(
                'model.root.view_no_cte').get('compiled_sql')))
Exemplo n.º 25
0
    def test__prepend_ctes__already_has_cte(self):
        ephemeral_config = self.model_config.replace(materialized='ephemeral')

        manifest = Manifest(
            macros={},
            nodes={
                'model.root.view': CompiledModelNode(
                    name='view',
                    database='dbt',
                    schema='analytics',
                    alias='view',
                    resource_type=NodeType.Model,
                    unique_id='model.root.view',
                    fqn=['root', 'view'],
                    package_name='root',
                    root_path='/usr/src/app',
                    refs=[],
                    sources=[],
                    depends_on=DependsOn(nodes=['model.root.ephemeral']),
                    config=self.model_config,
                    tags=[],
                    path='view.sql',
                    original_file_path='view.sql',
                    raw_sql='select * from {{ref("ephemeral")}}',
                    compiled=True,
                    extra_ctes_injected=False,
                    extra_ctes=[InjectedCTE(id='model.root.ephemeral', sql='select * from source_table')],
                    compiled_sql=(
                        'with cte as (select * from something_else) '
                        'select * from __dbt__cte__ephemeral'),
                    checksum=FileHash.from_contents(''),
                ),
                'model.root.ephemeral': CompiledModelNode(
                    name='ephemeral',
                    database='dbt',
                    schema='analytics',
                    alias='view',
                    resource_type=NodeType.Model,
                    unique_id='model.root.ephemeral',
                    fqn=['root', 'ephemeral'],
                    package_name='root',
                    root_path='/usr/src/app',
                    refs=[],
                    sources=[],
                    depends_on=DependsOn(),
                    config=ephemeral_config,
                    tags=[],
                    path='ephemeral.sql',
                    original_file_path='ephemeral.sql',
                    raw_sql='select * from source_table',
                    compiled=True,
                    compiled_sql='select * from source_table',
                    extra_ctes_injected=False,
                    extra_ctes=[],
                    checksum=FileHash.from_contents(''),
                ),
            },
            sources={},
            docs={},
            disabled=[],
            files={},
            exposures={},
            selectors={},
        )

        compiler = dbt.compilation.Compiler(self.config)
        result, _ = compiler._recursively_prepend_ctes(
            manifest.nodes['model.root.view'],
            manifest,
            {}
        )

        self.assertEqual(result, manifest.nodes['model.root.view'])
        self.assertEqual(result.extra_ctes_injected, True)
        self.assertEqualIgnoreWhitespace(
            result.compiled_sql,
            ('with __dbt__cte__ephemeral as ('
             'select * from source_table'
             '), cte as (select * from something_else) '
             'select * from __dbt__cte__ephemeral'))

        self.assertEqual(
            manifest.nodes['model.root.ephemeral'].extra_ctes_injected,
            False)
Exemplo n.º 26
0
    def test__prepend_ctes__no_ctes(self):
        manifest = Manifest(
            macros={},
            nodes={
                'model.root.view': CompiledModelNode(
                    name='view',
                    database='dbt',
                    schema='analytics',
                    alias='view',
                    resource_type=NodeType.Model,
                    unique_id='model.root.view',
                    fqn=['root', 'view'],
                    package_name='root',
                    root_path='/usr/src/app',
                    refs=[],
                    sources=[],
                    depends_on=DependsOn(),
                    config=self.model_config,
                    tags=[],
                    path='view.sql',
                    original_file_path='view.sql',
                    raw_sql=('with cte as (select * from something_else) '
                             'select * from source_table'),
                    compiled=True,
                    extra_ctes_injected=False,
                    extra_ctes=[],
                    compiled_sql=('with cte as (select * from something_else) '
                                  'select * from source_table'),
                    checksum=FileHash.from_contents(''),
                ),
                'model.root.view_no_cte': CompiledModelNode(
                    name='view_no_cte',
                    database='dbt',
                    schema='analytics',
                    alias='view_no_cte',
                    resource_type=NodeType.Model,
                    unique_id='model.root.view_no_cte',
                    fqn=['root', 'view_no_cte'],
                    package_name='root',
                    root_path='/usr/src/app',
                    refs=[],
                    sources=[],
                    depends_on=DependsOn(),
                    config=self.model_config,
                    tags=[],
                    path='view.sql',
                    original_file_path='view.sql',
                    raw_sql='select * from source_table',
                    compiled=True,
                    extra_ctes_injected=False,
                    extra_ctes=[],
                    compiled_sql=('select * from source_table'),
                    checksum=FileHash.from_contents(''),
                ),
            },
            sources={},
            docs={},
            disabled=[],
            files={},
            exposures={},
            selectors={},
        )

        compiler = dbt.compilation.Compiler(self.config)
        result, _ = compiler._recursively_prepend_ctes(
            manifest.nodes['model.root.view'],
            manifest,
            {}
        )

        self.assertEqual(
            result,
            manifest.nodes.get('model.root.view'))
        self.assertTrue(result.extra_ctes_injected)
        self.assertEqualIgnoreWhitespace(
            result.compiled_sql,
            manifest.nodes.get('model.root.view').compiled_sql)

        compiler = dbt.compilation.Compiler(self.config)
        result, _ = compiler._recursively_prepend_ctes(
            manifest.nodes.get('model.root.view_no_cte'),
            manifest,
            {})

        self.assertEqual(
            result,
            manifest.nodes.get('model.root.view_no_cte'))
        self.assertTrue(result.extra_ctes_injected)
        self.assertEqualIgnoreWhitespace(
            result.compiled_sql,
            manifest.nodes.get('model.root.view_no_cte').compiled_sql)
Exemplo n.º 27
0
 def setUp(self):
     super().setUp()
     self.parser = MacroParser(project=self.snowplow_project_config,
                               manifest=Manifest({}, {}, {}, {}, {}, {}, {},
                                                 {}))
Exemplo n.º 28
0
    def test__prepend_ctes__already_has_cte(self):
        ephemeral_config = self.model_config.replace(materialized='ephemeral')

        input_graph = Manifest(
            macros={},
            nodes={
                'model.root.view':
                CompiledModelNode(
                    name='view',
                    database='dbt',
                    schema='analytics',
                    alias='view',
                    resource_type=NodeType.Model,
                    unique_id='model.root.view',
                    fqn=['root_project', 'view'],
                    package_name='root',
                    root_path='/usr/src/app',
                    refs=[],
                    sources=[],
                    depends_on=DependsOn(nodes=['model.root.ephemeral']),
                    config=self.model_config,
                    tags=[],
                    path='view.sql',
                    original_file_path='view.sql',
                    raw_sql='select * from {{ref("ephemeral")}}',
                    compiled=True,
                    extra_ctes_injected=False,
                    extra_ctes=[
                        InjectedCTE(id='model.root.ephemeral',
                                    sql='select * from source_table')
                    ],
                    injected_sql='',
                    compiled_sql=('with cte as (select * from something_else) '
                                  'select * from __dbt__CTE__ephemeral')),
                'model.root.ephemeral':
                CompiledModelNode(name='ephemeral',
                                  database='dbt',
                                  schema='analytics',
                                  alias='view',
                                  resource_type=NodeType.Model,
                                  unique_id='model.root.ephemeral',
                                  fqn=['root_project', 'ephemeral'],
                                  package_name='root',
                                  root_path='/usr/src/app',
                                  refs=[],
                                  sources=[],
                                  depends_on=DependsOn(),
                                  config=ephemeral_config,
                                  tags=[],
                                  path='ephemeral.sql',
                                  original_file_path='ephemeral.sql',
                                  raw_sql='select * from source_table',
                                  compiled=True,
                                  compiled_sql='select * from source_table',
                                  extra_ctes_injected=False,
                                  extra_ctes=[],
                                  injected_sql=''),
            },
            docs={},
            # '2018-02-14T09:15:13Z'
            generated_at=datetime(2018, 2, 14, 9, 15, 13),
            disabled=[],
            files={},
        )

        result, output_graph = dbt.compilation.prepend_ctes(
            input_graph.nodes['model.root.view'], input_graph)

        self.assertEqual(result, output_graph.nodes['model.root.view'])
        self.assertEqual(result.extra_ctes_injected, True)
        self.assertEqualIgnoreWhitespace(
            result.injected_sql, ('with __dbt__CTE__ephemeral as ('
                                  'select * from source_table'
                                  '), cte as (select * from something_else) '
                                  'select * from __dbt__CTE__ephemeral'))

        self.assertEqual(
            input_graph.nodes['model.root.ephemeral'].extra_ctes_injected,
            True)
Exemplo n.º 29
0
 def _new_manifest(self):
     state_check = ManifestStateCheck(MatchingHash(), MatchingHash, [])
     manifest = Manifest({}, {}, {}, {}, {}, {}, [], {})
     manifest.state_check = state_check
     return manifest
Exemplo n.º 30
0
    def parse_node(cls,
                   node,
                   node_path,
                   root_project_config,
                   package_project_config,
                   all_projects,
                   tags=None,
                   fqn_extra=None,
                   fqn=None,
                   macros=None,
                   agate_table=None,
                   archive_config=None,
                   column_name=None):
        """Parse a node, given an UnparsedNode and any other required information.

        agate_table should be set if the node came from a seed file.
        archive_config should be set if the node is an Archive node.
        column_name should be set if the node is a Test node associated with a
        particular column.
        """
        logger.debug("Parsing {}".format(node_path))

        node = node.serialize()

        if agate_table is not None:
            node['agate_table'] = agate_table
        tags = coalesce(tags, [])
        fqn_extra = coalesce(fqn_extra, [])
        macros = coalesce(macros, {})

        node.update({
            'refs': [],
            'depends_on': {
                'nodes': [],
                'macros': [],
            }
        })

        if fqn is None:
            fqn = cls.get_fqn(node.get('path'), package_project_config,
                              fqn_extra)

        config = dbt.model.SourceConfig(root_project_config,
                                        package_project_config, fqn,
                                        node['resource_type'])

        node['unique_id'] = node_path
        node['empty'] = ('raw_sql' in node
                         and len(node['raw_sql'].strip()) == 0)
        node['fqn'] = fqn
        node['tags'] = tags

        # Set this temporarily. Not the full config yet (as config() hasn't
        # been called from jinja yet). But the Var() call below needs info
        # about project level configs b/c they might contain refs.
        # TODO: Restructure this?
        config_dict = coalesce(archive_config, {})
        config_dict.update(config.config)
        node['config'] = config_dict

        # Set this temporarily so get_rendered() has access to a schema & alias
        profile = dbt.utils.get_profile_from_project(root_project_config)
        default_schema = profile.get('schema', 'public')
        node['schema'] = default_schema
        default_alias = node.get('name')
        node['alias'] = default_alias

        # if there's a column, it should end up part of the ParsedNode
        if column_name is not None:
            node['column_name'] = column_name

        # make a manifest with just the macros to get the context
        manifest = Manifest(macros=macros,
                            nodes={},
                            docs={},
                            generated_at=dbt.utils.timestring())

        parsed_node = ParsedNode(**node)
        context = dbt.context.parser.generate(parsed_node, root_project_config,
                                              manifest, config)

        dbt.clients.jinja.get_rendered(parsed_node.raw_sql,
                                       context,
                                       parsed_node.to_shallow_dict(),
                                       capture_macros=True)

        # Clean up any open conns opened by adapter functions that hit the db
        db_wrapper = context['adapter']
        adapter = db_wrapper.adapter
        profile = db_wrapper.profile
        adapter.release_connection(profile, parsed_node.name)

        # Special macro defined in the global project
        schema_override = config.config.get('schema')
        get_schema = context.get('generate_schema_name',
                                 lambda x: default_schema)
        parsed_node.schema = get_schema(schema_override)
        parsed_node.alias = config.config.get('alias', default_alias)

        # Overwrite node config
        config_dict = parsed_node.get('config', {})
        config_dict.update(config.config)
        parsed_node.config = config_dict

        for hook_type in dbt.hooks.ModelHookType.Both:
            parsed_node.config[hook_type] = dbt.hooks.get_hooks(
                node, hook_type)

        parsed_node.validate()

        return parsed_node