Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fd1ca82
refactor(native): move discovery's header keys and header changes int…
kvlonge Oct 20, 2026
941409e
refactor(native): move plain scope logic from the bindings into sqlbu…
kvlonge Oct 20, 2026
e7d8e51
feat(native): add a typed model config value and layer described mode…
kvlonge Oct 20, 2026
96c6ddc
refactor(native): build model configs as typed values in sqlbuild-mod…
kvlonge Oct 20, 2026
d71a88f
refactor(native): read planner config values as typed nodes
kvlonge Oct 20, 2026
dcaa537
fix(native): keep header-owned config values as the header's objects
kvlonge Oct 20, 2026
64a0669
fix(native): read config value text through Python when only Python p…
kvlonge Oct 20, 2026
0948d46
perf(native): carry header containers the config build never looks in…
kvlonge Oct 20, 2026
45e6afa
perf(native): convert typed config values key by key on first read
kvlonge Oct 20, 2026
7575fa9
refactor(native): read planner resolution config through typed values
kvlonge Oct 20, 2026
6b195a6
refactor(native): read planner strategy config through typed values
kvlonge Oct 20, 2026
d25e9a1
Merge remote-tracking branch 'origin/main' into refactor/split-sqlbui…
kvlonge Oct 20, 2026
0714535
refactor(native): read planner warehouse config through typed values
kvlonge Oct 20, 2026
0a89690
refactor(native): read remaining planner config through typed values
kvlonge Oct 21, 2026
2cfb914
build(native): add the sqlbuild-project crate
kvlonge Oct 21, 2026
9572d2d
refactor(native): move the compiled model's plain rows into sqlbuild-…
kvlonge Oct 21, 2026
43384fc
refactor(native): move the model input record into sqlbuild-project
kvlonge Oct 21, 2026
23a3ad4
refactor(native): move the compiled model and analysis records into s…
kvlonge Oct 21, 2026
6f1aa05
Merge remote-tracking branch 'origin/main' into refactor/split-sqlbui…
kvlonge Oct 21, 2026
0c877bf
refactor(native): move the source, function and audit records into sq…
kvlonge Oct 21, 2026
baac0d6
refactor(native): move the seed record into sqlbuild-project
kvlonge Oct 21, 2026
3db8309
refactor(native): move the compiled project container into sqlbuild-p…
kvlonge Oct 21, 2026
6066e7e
docs(native): describe the records sqlbuild-project holds
kvlonge Oct 21, 2026
3b62a15
Merge remote-tracking branch 'origin/main' into refactor/sqlbuild-pro…
kvlonge Oct 21, 2026
3b4c66d
chore: refresh Cargo.lock after merging main
kvlonge Oct 21, 2026
3ad06ba
Merge branch 'main' into refactor/sqlbuild-project-records
kvlonge Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ members = [
"crates/sqlbuild-analysis",
"crates/sqlbuild-rules",
"crates/sqlbuild-refactor",
"crates/sqlbuild-project",
"crates/sqlbuild-cli",
"crates/sqlbuild-python",
]
Expand Down Expand Up @@ -46,6 +47,7 @@ order = [
"sqlbuild-analysis",
"sqlbuild-rules",
"sqlbuild-refactor",
"sqlbuild-project",
"sqlbuild-cli",
"sqlbuild-python",
]
Expand Down Expand Up @@ -126,6 +128,7 @@ sqlbuild-render = { path = "crates/sqlbuild-render" }
sqlbuild-refactor = { path = "crates/sqlbuild-refactor" }
sqlbuild-rules = { path = "crates/sqlbuild-rules" }
sqlbuild-model-config = { path = "crates/sqlbuild-model-config" }
sqlbuild-project = { path = "crates/sqlbuild-project" }
sqlbuild-pysource = { path = "crates/sqlbuild-pysource" }
sqlbuild-recall = { path = "crates/sqlbuild-recall" }
sqlbuild-scopes = { path = "crates/sqlbuild-scopes" }
Expand Down
3 changes: 2 additions & 1 deletion crates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ that can be tested and benchmarked with `cargo test` alone.
| `sqlbuild-analysis` | SQL analysis over polyglot: query analysis, binding, semantic validation and usage, column references, type normalization, FAST/RICH lineage, SQL-test/scenario extraction and compiler-side assembly, and Snowflake cost statement classification and query-tag parsing. |
| `sqlbuild-rules` | Built-in rules and the rules engine, the custom-rule host, SQL lint, quality checks and formatting, rules configuration and the request models. It also owns the build identity script. |
| `sqlbuild-refactor` | Native rename/move plans, contract-adoption edits, MODEL/SCHEMA/YAML text edits and atomic staging/commit with rollback. Shared scope placement delegates to the native scope implementation; user Python source inspection remains at the Python AST boundary. |
| `sqlbuild-project` | The compiled project as plain Rust: `CompiledProject` with the producers' facts and each resource's records (model inputs and schemas, compiled models and their analysis, sources, functions, audits and seeds), and what those records answer without Python, such as lineage rows, resolved namespaces and dependency keys. Values the host owns, such as user config and discovered files, and the views it builds lazily live in one slot per record, whose types `sqlbuild-python` supplies through the `ProjectHost` trait; reads that need Python stay in the bindings as extension traits. |
| `sqlbuild-cli` | The `sqb` and `sqlbuild` executables: `--version`, unchanged compiles replayed from the shared reuse store with Python's exact streams, exit code and compute log capture, and a handoff of every other invocation to the installed `sqlbuild-python` script. Built as its own wheel (`crates/sqlbuild-cli/pyproject.toml`). |
| `sqlbuild-python` | The only PyO3 crate: the `_native` module, its Python classes and functions, conversions from Python objects, and the process allocator. |

Expand All @@ -32,7 +33,7 @@ Dependencies point one way, from the top of this graph to the bottom:

```text
sqlbuild-python
-> sqlbuild-refactor -> sqlbuild-rules -> sqlbuild-analysis -> sqlbuild-attachments
-> sqlbuild-project -> sqlbuild-refactor -> sqlbuild-rules -> sqlbuild-analysis -> sqlbuild-attachments
-> sqlbuild-model-config -> sqlbuild-scopes -> sqlbuild-render -> sqlbuild-discovery -> sqlbuild-host
-> sqlbuild-config -> sqlbuild-sqltext -> sqlbuild-cache -> sqlbuild-pysource -> sqlbuild-state -> sqlbuild-cursor -> sqlbuild-core
sqlbuild-cli -> sqlbuild-cache, sqlbuild-core, sqlbuild-build-features
Expand Down
16 changes: 16 additions & 0 deletions crates/sqlbuild-project/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "sqlbuild-project"
version.workspace = true
description = "The compiled project as plain Rust: model, source, function, audit and seed records, with the host's values carried as opaque handles."
edition.workspace = true
license.workspace = true
publish.workspace = true
rust-version.workspace = true

[lints]
workspace = true

[dependencies]
sqlbuild-analysis.workspace = true
sqlbuild-core.workspace = true
sqlbuild-sqltext.workspace = true
22 changes: 22 additions & 0 deletions crates/sqlbuild-project/src/_helpers/analysis_records.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! What a model analysis record answers without the host.

use sqlbuild_analysis::assembly::analysis_session::models::{LineageFacts, LineageRow};

use crate::models::AnalysisRecord;
use crate::types::ProjectHost;

impl<H: ProjectHost> AnalysisRecord<H> {
/// The session's lineage rows, or `None` when the model kept no lineage.
#[inline]
pub fn lineage_rows(&self) -> Option<&[LineageRow]> {
self.lineage.as_ref().map(|lineage| match lineage {
LineageFacts::Native(rows) | LineageFacts::NativeFacts(rows) => rows.as_slice(),
})
}

/// The number of upstream sources across the model's lineage rows, or `None` without lineage.
pub fn lineage_edge_count(&self) -> Option<usize> {
let rows: &[LineageRow] = self.lineage_rows()?;
Some(rows.iter().map(|row| row.sources.len()).sum())
}
}
3 changes: 3 additions & 0 deletions crates/sqlbuild-project/src/_helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub(crate) mod analysis_records;
pub(crate) mod project_records;
pub(crate) mod resource_records;
79 changes: 79 additions & 0 deletions crates/sqlbuild-project/src/_helpers/project_records.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//! What the compiled project answers and records without the host.

use sqlbuild_analysis::compiled_project::main::model_facts::model_facts;
use sqlbuild_analysis::compiled_project::main::record_model::record_model;
use sqlbuild_analysis::compiled_project::models::{
CompiledModelFacts, CompiledProjectFacts, ModelSchemaFact,
};

use crate::models::{
AuditRecord, CompiledProject, FunctionRecord, ModelInputRecord, SeedRecord, SourceRecord,
};
use crate::types::ProjectHost;

impl<H: ProjectHost> Default for CompiledProject<H> {
fn default() -> Self {
Self::with_facts(CompiledProjectFacts::default())
}
}

impl<H: ProjectHost> CompiledProject<H> {
/// A project holding only `facts`, which analyses can be recorded into apart from the compile's.
pub fn with_facts(facts: CompiledProjectFacts) -> Self {
Self {
facts,
inputs: Vec::new(),
graph_builds: 0,
seeds: Vec::new(),
sources: Vec::new(),
functions: Vec::new(),
audits: Vec::new(),
}
}

/// Retain facts a producer finished natively.
pub fn retain(&mut self, facts: CompiledModelFacts) {
record_model(&mut self.facts, facts);
}

/// Retain a finished model's input record; return its index for the model's view.
pub fn retain_input(&mut self, record: ModelInputRecord<H>) -> usize {
self.inputs.push(record);
self.inputs.len() - 1
}

/// The schema fact recorded for an input record's model.
pub fn input_schema_fact(&self, record: &ModelInputRecord<H>) -> Option<&ModelSchemaFact> {
model_facts(&self.facts, &record.name).and_then(|facts| facts.schema.as_ref())
}

/// The input record at `index`, or `None` past the last model.
#[inline]
pub fn input(&self, index: usize) -> Option<&ModelInputRecord<H>> {
self.inputs.get(index)
}

/// Every attached audit, in attachment order.
#[inline]
pub fn audits(&self) -> &[AuditRecord<H>] {
&self.audits
}

/// Every attached function, in attachment order.
#[inline]
pub fn functions(&self) -> &[FunctionRecord<H>] {
&self.functions
}

/// Every attached source, in attachment order.
#[inline]
pub fn sources(&self) -> &[SourceRecord<H>] {
&self.sources
}

/// Every attached seed, in attachment order.
#[inline]
pub fn seeds(&self) -> &[SeedRecord<H>] {
&self.seeds
}
}
56 changes: 56 additions & 0 deletions crates/sqlbuild-project/src/_helpers/resource_records.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//! What source, function and audit records answer without the host.

use crate::models::{
AttachedAudit, AttachedFunction, AttachedSource, AuditRecord, FunctionRecord, SourceRecord,
};
use crate::types::{ObjectKeyRow, ProjectHost, SourceNamespace};

const TABLE_FUNCTION_TYPE: &str = "table_fn";
const SCALAR_FUNCTION_TYPE: &str = "udf";

impl<H: ProjectHost> SourceRecord<H> {
/// The attached source.
#[inline]
pub fn attached(&self) -> &AttachedSource<H> {
&self.attached
}

/// Keep the namespace native project assembly resolved for the source.
pub fn set_namespace(&mut self, namespace: SourceNamespace) {
self.namespace = Some(namespace);
}
}

impl<H: ProjectHost> AttachedFunction<H> {
/// `function_node_type`: a table function when it declares return columns.
#[inline]
pub fn node_type(&self) -> &'static str {
if self.return_columns.is_empty() {
SCALAR_FUNCTION_TYPE
} else {
TABLE_FUNCTION_TYPE
}
}
}

impl<H: ProjectHost> FunctionRecord<H> {
/// Keep the dependency keys native project assembly resolved for the function.
pub fn set_deps(&mut self, deps: Vec<ObjectKeyRow>) {
self.deps = Some(deps);
}
}

impl<H: ProjectHost> AttachedAudit<H> {
/// `_resolve_audit_name`: the instance name, else the definition name.
#[inline]
pub fn compiled_name(&self) -> &str {
self.name.as_deref().unwrap_or(&self.definition_name)
}
}

impl<H: ProjectHost> AuditRecord<H> {
/// Keep the scope dependency keys native project assembly resolved for the audit.
pub fn set_scope_deps(&mut self, deps: Vec<ObjectKeyRow>) {
self.scope_deps = Some(deps);
}
}
11 changes: 11 additions & 0 deletions crates/sqlbuild-project/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! The compiled project as plain Rust: each resource's records, with host values held as opaque handles.

#![forbid(unsafe_code)]

mod _helpers;

pub mod models;
pub mod types;

#[cfg(test)]
mod tests;
Loading
Loading