Skip to content

Commit 468f188

Browse files
authored
Add profile-derived dispatch adapter identity (#66)
1 parent 8eaf78e commit 468f188

17 files changed

Lines changed: 629 additions & 37 deletions

.agent/research/dbt-upstream-reference-map.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Every compatibility slice should record:
4747
| YAML properties and resource patches | `core/dbt/parser/schemas.py::SchemaParser`, `SourceParser`, `PatchParser`, `ModelPatchParser`, `MacroPatchParser`; `core/dbt/parser/schema_yaml_readers.py::ExposureParser`, `MetricParser`, `SemanticModelParser`, `SavedQueryParser` | `crates/dbt-parser/src/resolver.rs::resolve_package_waves` resource order: sources, seeds, snapshots, groups, models, analyses, functions, exposures, semantic models, metrics, saved queries, data tests, unit tests | Current `src/project.zig` YAML routines and `src/project/parse.zig` helpers; future `src/project/parse.zig` plus narrower modules if needed |
4848
| Exposure, source, ref, metric dependency resolution | `core/dbt/parser/manifest.py::_process_refs`, `_process_sources_for_node`, `_process_sources_for_exposure`, `_process_metrics_for_node` | `crates/dbt-jinja-utils/src/node_resolver.rs::resolve_dependencies`; `crates/dbt-parser/src/resolver.rs` access validation, relation uniqueness, primary-key inference | `src/project/resolve.zig`; current higher-level orchestration still in `src/project.zig` |
4949
| Parse vs runtime Jinja context | `core/dbt/context/providers.py::ParseProvider`, `RuntimeProvider`, `ProviderContext.ref`, `source`, `execute`, `var`, `graph`, `env_var`, `selected_resources`, `generate_parser_model_context`, `generate_runtime_model_context`, `generate_parse_exposure`, `generate_parse_semantic_models` | `crates/dbt-parser/src/renderer.rs::render_sql_file_inner`, `augment_sql_resources_with_static_sources`; `crates/dbt-parser/src/dbt_namespace.rs::DbtNamespace` parse-mode interception of `get_relation` and `get_columns_in_relation` | Current lexical `src/project/jinja.zig`; future parse context and compile/runtime context modules before M2 |
50+
| Profile and adapter identity | `core/dbt/config/profile.py::Profile.pick_profile_name`, `render_profile`, `from_raw_profile_info`, `_get_profile_data`, `_credentials_from_profile`, `to_target_dict`; `core/dbt/config/runtime.py::load_profile`, `RuntimeConfig.get_metadata`; `core/dbt/context/target.py::TargetContext.target` | `crates/dbt-loader/src/load_profiles.rs::load_profiles`; `crates/dbt-profile/src/resolve.rs`; `crates/dbt-schemas/src/schemas/profiles.rs::DbConfig::adapter_type`; `crates/dbt-adapter-core/src/lib.rs::AdapterType` | `src/project/profile.zig` owns the current scalar `profiles.yml` adapter-type parser; `src/project/config.zig` owns `dbt_project.yml` `profile:`; future profile/context modules own Jinja rendering, credentials, target context, and relation identity |
5051
| Manifest data model and maps | `core/dbt/contracts/graph/manifest.py::Manifest` maps for nodes, sources, macros, docs, exposures, metrics, groups, selectors, files, disabled, semantic_models, unit_tests, saved_queries, fixtures; `build_flat_graph`, `build_parent_and_child_maps`, lookup rebuilders, resource adders | `crates/dbt-schemas/src/schemas/manifest/manifest.rs::build_manifest`, `build_disabled_map`, `build_parent_and_child_maps`, path normalization, `nodes_from_dbt_manifest` | `src/project/types.zig`, `src/project/manifest.zig`, `src/project/resolve.zig` |
5152
| Selector grammar and methods | `core/dbt/graph/selector_spec.py`, `selector.py`, `selector_methods.py`, `cli.py`, `graph.py`, `queue.py`; methods include FQN, tag, group, access, source, exposure, metric, semantic_model, saved_query, unit_test, path, file, package, config, resource_type, test_name, test_type, state, result, source_status, version, selector | `crates/dbt-parser/src/resolver.rs` selector YAML loading; command flags in `crates/dbt-clap-core/src/commands.rs` | `src/project/selector.zig` and CLI validation in `src/root.zig`; future state/result/source-status work in `src/project/state.zig` |
5253
| Artifact schemas | `schemas/dbt/manifest/v12.json`, `schemas/dbt/run-results/v6.json`, `schemas/dbt/sources/v3.json`, `schemas/dbt/catalog/v1.json` | v2 still emits JSON for compatibility and adds Parquet artifacts per README; manifest builder in `crates/dbt-schemas/src/schemas/manifest/manifest.rs` | `src/project/manifest.zig`, future run/catalog/source writers and schema validators under tests/scripts |
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# M2 Profile-Derived Adapter Dispatch Identity Slice
2+
3+
This slice replaces dxt's temporary static adapter dispatch prefix list with a
4+
profile-derived adapter type for parse-time `adapter.dispatch(...)` dependency
5+
recording. It still records `depends_on.macros` only. It does not validate
6+
credentials, render secrets, open adapter connections, execute macros, implement
7+
project `dispatch:` config, compile `target.*`, or run materializations.
8+
9+
## Upstream References
10+
11+
dbt Core v1, branch `1.latest`, commit `566b75d`:
12+
13+
- `core/dbt/config/runtime.py::load_profile` selects the project profile and
14+
passes CLI profile, target, and threads overrides into profile loading.
15+
- `core/dbt/config/profile.py::Profile.pick_profile_name`,
16+
`render_profile`, `from_raw_profile_info`, `_get_profile_data`, and
17+
`_credentials_from_profile` define profile-name selection, target selection,
18+
selected-output lookup, required `type`, and adapter plugin identity.
19+
- `core/dbt/config/profile.py::Profile.to_target_dict` and
20+
`core/dbt/context/target.py::TargetContext.target` define the common target
21+
context fields, including `type`, `name`, `target_name`, `profile_name`, and
22+
`threads`.
23+
- `core/dbt/config/runtime.py::RuntimeConfig.get_metadata` emits manifest
24+
metadata `adapter_type` from credentials.
25+
- `core/dbt/context/providers.py::BaseDatabaseWrapper._get_adapter_macro_prefixes`
26+
defines dispatch prefixes as adapter type hierarchy plus `default`.
27+
- `core/dbt/context/providers.py::BaseDatabaseWrapper.dispatch` rejects dotted
28+
macro names and deprecated `packages`, then searches
29+
`{adapter_prefix}__{macro_name}` candidates.
30+
- `core/dbt/clients/jinja_static.py::statically_parse_adapter_dispatch` uses the
31+
adapter wrapper to statically resolve literal dispatch calls into macro
32+
dependencies.
33+
34+
dbt Core v2 / Fusion foundation, branch `main`, commit `0529e06`:
35+
36+
- `crates/dbt-loader/src/load_profiles.rs::load_profiles` locates
37+
`profiles.yml`, selects profile and target, resolves profile data, and stores
38+
the adapter type in `DbtProfile`.
39+
- `crates/dbt-profile/src/resolve.rs` resolves profile name, target override,
40+
selected output, and adapter type as data.
41+
- `crates/dbt-schemas/src/schemas/profiles.rs::DbConfig::adapter_type` maps
42+
typed profile configuration into `AdapterType`.
43+
- `crates/dbt-adapter-core/src/lib.rs::AdapterType` defines adapter identity and
44+
accepts the Postgres naming forms.
45+
- `crates/dbt-jinja/minijinja/src/dispatch_object.rs::get_adapter_prefixes`
46+
defines Fusion's current parent-prefix fallback: `redshift -> postgres`,
47+
`databricks -> spark`, then `default`.
48+
- `crates/dbt-jinja/minijinja/src/dispatch_object.rs::DispatchObject::call`
49+
applies adapter prefixes during dispatch resolution.
50+
51+
## dxt Ownership
52+
53+
- `src/project/profile.zig` owns the narrow scalar profile/target adapter-type
54+
parser.
55+
- `src/project/config.zig` owns `dbt_project.yml` `profile:` discovery.
56+
- `src/project/loader.zig` resolves profile identity before loading macros and
57+
resources, so parse-time Jinja scanning sees the selected adapter type.
58+
- `src/project/jinja.zig` derives static dispatch prefixes from
59+
`Graph.adapter_type`.
60+
- `src/project/manifest.zig` emits manifest `metadata.adapter_type`.
61+
62+
## Supported Surface
63+
64+
- Select profile from CLI `--profile`, falling back to `dbt_project.yml`
65+
`profile:`.
66+
- Select target from CLI `--target`, falling back to profile `target:`, then
67+
`default`.
68+
- Read selected output scalar `type` from `profiles.yml`.
69+
- Normalize `postgresql` to dispatch adapter type `postgres`.
70+
- Use dispatch prefix order:
71+
- `redshift`, `postgres`, `default`
72+
- `databricks`, `spark`, `default`
73+
- selected adapter, `default`
74+
- Preserve the current `duckdb` default only when no profile file is found and
75+
no profile-related CLI flag requested profile loading.
76+
77+
## Validation
78+
79+
- Native Zig tests cover profile/target selection, missing profile/target/type
80+
errors, Postgres alias normalization, profile-derived dispatch prefix choice,
81+
and parent prefix fallback.
82+
- Pytest fixture `profile_adapter_dispatch` validates parse-time manifest
83+
`depends_on.macros` and `metadata.adapter_type` for default Postgres, explicit
84+
DuckDB, and Redshift parent fallback targets through the Zig binary.
85+
- Existing no-profile fixtures remain covered by the default DuckDB identity.
86+
87+
## Stop Conditions
88+
89+
- Do not render Jinja in `profiles.yml` in this slice.
90+
- Do not read host-global profile locations beyond the project or explicit
91+
`--profiles-dir` path.
92+
- Do not validate or emit credentials.
93+
- Do not implement project `dispatch:` config.
94+
- Do not execute dispatched macros, materializations, tests, or adapter SQL.
95+
- Do not add relation identity, quoting, `target.*`, `this`, catalog
96+
introspection, or `run_results.json`.

PLAN.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,19 @@ Current static adapter dispatch dependency source note:
304304
`.agent/research/m2-static-adapter-dispatch-deps.md` maps upstream dbt Core v1
305305
`BaseDatabaseWrapper.dispatch` and Fusion `DispatchObject` behavior to dxt's
306306
static `depends_on.macros` extraction for literal `adapter.dispatch(...)` calls.
307-
This slice records dispatch macro dependencies only, using a temporary
308-
`duckdb`, `default` prefix list until profile-derived adapter identity exists.
309-
It does not execute dispatched macros, implement project `dispatch:` config,
310-
parse profiles, or run adapters.
307+
This slice records dispatch macro dependencies only. It does not execute
308+
dispatched macros, implement project `dispatch:` config, or run adapters.
309+
310+
Current profile-derived adapter identity source note:
311+
`.agent/research/m2-profile-adapter-dispatch-identity.md` maps upstream dbt Core
312+
v1 profile/target selection, manifest `adapter_type`, and dispatch prefix
313+
behavior plus Fusion `AdapterType` and `get_adapter_prefixes` behavior to dxt's
314+
narrow scalar `profiles.yml` parser. This slice lets parse-time static
315+
`adapter.dispatch(...)` dependency extraction use the selected profile output
316+
`type`, including `redshift -> postgres -> default` and
317+
`databricks -> spark -> default` parent fallbacks. It does not render Jinja in
318+
profiles, validate credentials, read host-global profile locations, implement
319+
project `dispatch:` config, execute macros, or open adapter connections.
311320

312321
The next source-grounded M1/M2 slices after macro block variant support are:
313322

@@ -341,9 +350,9 @@ The next source-grounded M1/M2 slices after macro block variant support are:
341350
5. Grow artifact schema coverage only alongside emitted fields, using v1 JSON
342351
schemas and v2 manifest builder behavior while keeping dxt-specific metadata
343352
out of dbt schemas.
344-
6. Add adapter relation identity and profile-derived target values after the
345-
render-only compile boundary is stable, using v1 compile runner/compiler
346-
behavior plus v2 adapter core/SQL identity references.
353+
6. Add adapter relation identity and target context values after the render-only
354+
compile boundary is stable, using v1 compile runner/compiler behavior plus
355+
v2 adapter core/SQL identity references.
347356

348357
## Fixture Ladder
349358

@@ -675,4 +684,4 @@ Exit criteria:
675684
- Selector wildcard behavior is currently pinned to observed dbt Core 1.10 behavior. dbt Fusion preview currently differs for resource-type-prefixed wildcard selectors such as `model.<package>.*` and filename-suffix path selectors such as `path:*orders.sql`; a future Fusion-compatibility slice must decide whether to support a selector dialect switch or a compatible superset.
676685
- Compatibility planning now uses a source-grounded reference map under `.agent/research/dbt-upstream-reference-map.md`; future feature slices should name upstream dbt v1/v2 source references, dxt Zig owners, affected artifact fields, validation gates, and stop conditions before implementation.
677686
- The committed dbt Core M1 oracle harness lives in `scripts/check_dbt_core_m1_oracle.py`. It is optional developer-side Python tooling that requires `dbt-core` and `dbt-duckdb`, invokes dbt Core through its Python runner, runs `dxt parse` through the Zig binary, and compares stable manifest slices for the supported synthetic M1 fixture ladder. It ignores dbt internal package docs/macros that are outside the current dxt artifact scope, records a known allowed gap for installed-package exposure refs that dbt Core resolves to a root same-name model while dxt currently resolves package-local, and leaves full source-map parity, full artifact schemas, and execution parity for later slices.
678-
- Before broadening M2 product implementation, close or explicitly re-scope the remaining M1 macro-compatibility behavior gaps. Macro `docs`/`meta` patch fields are covered for the current scalar artifact subset. Macro argument extraction under dbt Core v1 `flags.validate_macro_args` semantics and YAML patch argument validation/replacement are implemented for the manifest artifact surface. Static macro dependency lookup now uses the supported dbt order of current package, root project, other-package fallback for macro bodies, graph-present internal `dbt` macros, and literal `adapter.dispatch(...)` dependency extraction with a temporary `duckdb`, `default` prefix list. Macro execution, bundled dbt internal macros, project `dispatch:` config, profile-derived adapter identity, and materialization runtime lookup remain planned. `{% data_test %}` has native source-grounded parser coverage, but the local dbt Core 1.10 oracle rejects that tag before writing artifacts, so dbt-oracle coverage currently pins `{% test %}` and `{% materialization %}` block parity.
687+
- Before broadening M2 product implementation, close or explicitly re-scope the remaining M1 macro-compatibility behavior gaps. Macro `docs`/`meta` patch fields are covered for the current scalar artifact subset. Macro argument extraction under dbt Core v1 `flags.validate_macro_args` semantics and YAML patch argument validation/replacement are implemented for the manifest artifact surface. Static macro dependency lookup now uses the supported dbt order of current package, root project, other-package fallback for macro bodies, graph-present internal `dbt` macros, and literal `adapter.dispatch(...)` dependency extraction. Parse-time dispatch prefixes now come from a narrow source-grounded `profiles.yml` adapter identity parser and emit manifest `metadata.adapter_type`, with default DuckDB behavior preserved when no profile file is loaded. Macro execution, bundled dbt internal macros, project `dispatch:` config, full target context, credential validation, and materialization runtime lookup remain planned. `{% data_test %}` has native source-grounded parser coverage, but the local dbt Core 1.10 oracle rejects that tag before writing artifacts, so dbt-oracle coverage currently pins `{% test %}` and `{% materialization %}` block parity.

0 commit comments

Comments
 (0)