Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b2f0c4d
refactor: call native command helpers directly from the plan, query, …
kvlonge Oct 17, 2026
d91b632
refactor: build native records through classes captured at module init
kvlonge Oct 17, 2026
0e32e47
refactor: construct native records directly in planner and plan outpu…
kvlonge Oct 17, 2026
11671f9
refactor: construct native records directly in record_behaviours … ru…
kvlonge Oct 17, 2026
e6dd716
refactor: construct native records directly in macro_bridge … workspa…
kvlonge Oct 17, 2026
d2f5c97
refactor: call native helpers directly from refactor, render, rules a…
kvlonge Oct 17, 2026
c951886
refactor: call schema validation, query reanalysis and rules request …
kvlonge Oct 17, 2026
a9629bb
refactor: report compile diagnostics and macro store tokens through d…
kvlonge Oct 17, 2026
5f1e12f
refactor: construct declaration contexts and binding positions directly
kvlonge Oct 17, 2026
820d050
refactor: read own records natively and rebuild them without dataclas…
kvlonge Oct 17, 2026
26014ef
refactor: build planner records and the default scope index natively
kvlonge Oct 17, 2026
afa34da
refactor: resolve native record field defaults through the captured c…
kvlonge Oct 17, 2026
10245f8
refactor: construct native records directly in attachments … command_…
kvlonge Oct 17, 2026
35ab909
refactor: construct native records directly in compile_attachment … c…
kvlonge Oct 17, 2026
e56b480
refactor: construct native records directly in contract_command … cur…
kvlonge Oct 17, 2026
bee315b
refactor: construct native records directly in dag_artifact … discove…
kvlonge Oct 17, 2026
c892388
refactor: construct native records directly in event_exporting … load…
kvlonge Oct 17, 2026
7d97f99
refactor: expose native entry points to direct Rust callers
kvlonge Oct 17, 2026
ecc0ad8
refactor: call native entry points directly in audit_command to comma…
kvlonge Oct 17, 2026
44f66df
refactor: call native entry points directly in compile_command to cos…
kvlonge Oct 17, 2026
3df4e87
refactor: call native entry points directly in dbt_command to debug_c…
kvlonge Oct 17, 2026
7bf3bbb
refactor: call native entry points directly in format_command to load…
kvlonge Oct 17, 2026
4aba02b
refactor: call test-replaced native entry points directly
kvlonge Oct 17, 2026
f4b012a
refactor: call native classes, entry points and context variables dir…
kvlonge Oct 17, 2026
8c27605
refactor: read own records through native fields and rebuild them nat…
kvlonge Oct 17, 2026
2490ad8
refactor: keep rich column lineage on the extension module
kvlonge Oct 17, 2026
2e754ef
refactor: read remaining multi-line record chains through native fiel…
kvlonge Oct 17, 2026
3127f54
refactor: remove registry lookups left unused by the direct-call sweep
kvlonge Oct 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use sqlbuild_analysis::semantic_validation::types::{BindingRequest, DiagnosticRo

use crate::bindings::_helpers::analysis::conversions;
use crate::bindings::_helpers::boundary::panics::compiler_error;
use crate::bindings::_helpers::records::construct::new_record;
use crate::bindings::_helpers::records::fields::field as native_field;
use crate::bindings::_helpers::records::ids::RecordId;
use crate::bindings::_helpers::records::registry;
use crate::bindings::models::{CatalogInput, ProjectCatalog};
use crate::bindings::types::CompilerDetach;

Expand Down Expand Up @@ -323,9 +323,7 @@ pub(crate) fn schema_validations<'py>(
None => groups.push((catalog, own, vec![index])),
}
}
let result_type: Bound<'py, PyAny> = registry::class(py, RecordId::SqlBindingResult)?;
let diagnostic_type: Bound<'py, PyAny> = registry::class(py, RecordId::SqlBindingDiagnostic)?;
let empty: Bound<'py, PyAny> = result_type.call0()?;
let empty: Bound<'py, PyAny> = new_record(py, RecordId::SqlBindingResult, (), None)?;
let mut results: Vec<Bound<'py, PyAny>> = vec![empty; requests.len()];
for (catalog, any_explicit, members) in groups {
let catalog = catalog.borrow(py);
Expand All @@ -351,11 +349,11 @@ pub(crate) fn schema_validations<'py>(
for (index, diagnostics) in members.into_iter().zip(rows) {
let built: Vec<Bound<'py, PyAny>> = diagnostics
.into_iter()
.map(|row| diagnostic_type.call1(row))
.map(|row| new_record(py, RecordId::SqlBindingDiagnostic, row, None))
.collect::<PyResult<_>>()?;
let keywords: Bound<'py, PyDict> = PyDict::new(py);
keywords.set_item("diagnostics", PyTuple::new(py, built)?)?;
results[index] = result_type.call((), Some(&keywords))?;
results[index] = new_record(py, RecordId::SqlBindingResult, (), Some(&keywords))?;
}
}
PyTuple::new(py, results)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type LocatedRow = (

/// Each reported diagnostic of `rows` through `(authored, query, cleaned)` and the expansion.
#[pyfunction]
fn locate_model_binding_diagnostics(
pub(crate) fn locate_model_binding_diagnostics(
rows: Vec<DiagnosticRow>,
texts: (String, String, String),
expansion: Option<(String, Vec<Vec<Expansion>>)>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ use sqlbuild_pysource::literal_sql::models::FunctionSource;
use crate::bindings::_helpers::analysis::reference_facts::{ProjectFacts, project_facts};
use crate::bindings::_helpers::boundary::panics::compiler_error;
use crate::bindings::_helpers::compile_driver::python_calls::imported;
use crate::bindings::_helpers::graph::execution_gates::model_python_hook_names;
use crate::bindings::_helpers::native_host::host;
use crate::bindings::_helpers::native_host::user_code::UserCodeHost;
use crate::bindings::_helpers::records::construct::{enum_from_value, new_record, record_class};
use crate::bindings::_helpers::records::fields::field as native_field;
use crate::bindings::_helpers::records::ids::{ErrorId, NativeAttr, RecordId};
use crate::bindings::_helpers::records::ids::{ErrorId, RecordId};
use crate::bindings::_helpers::records::registry;
use crate::bindings::types::CompilerDetach;

Expand Down Expand Up @@ -157,7 +159,7 @@ fn python_sql_owners<'py>(
let py: Python<'py> = project.py();
let mut owners: Vec<PythonSqlOwner<'py>> = Vec::new();
for (label, attribute) in NODE_OWNERS {
for node in discovered_inputs.getattr(attribute)?.try_iter()? {
for node in native_field(discovered_inputs, attribute)?.try_iter()? {
let node: Bound<'py, PyAny> = node?;
let name: String = native_field(&node, "name")?.extract()?;
owners.push(PythonSqlOwner::new(
Expand All @@ -168,14 +170,11 @@ fn python_sql_owners<'py>(
}
}
owners.extend(loader_owners(project, discovered_inputs)?);
let hook_names = registry::native(py, NativeAttr::ModelPythonHookNames)?;
let mut attached: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
for model in native_field(project, "models")?.try_iter()? {
let model: Bound<'py, PyAny> = model?;
let keywords: Bound<'py, PyDict> = PyDict::new(py);
keywords.set_item("model", &model)?;
let model_name: String = native_field(&model, "name")?.extract()?;
for hook_name in hook_names.call((), Some(&keywords))?.try_iter()? {
for hook_name in model_python_hook_names(py, &model)?.try_iter()? {
attached
.entry(hook_name?.extract()?)
.or_default()
Expand Down Expand Up @@ -309,11 +308,8 @@ fn python_report<'py>(
report: &ReferenceReport,
owners: &[PythonSqlOwner<'py>],
) -> PyResult<Bound<'py, PyAny>> {
let owner_kind: Bound<'py, PyAny> = registry::class(py, RecordId::HardCodedRelationOwnerKind)?;
let reference_models = py.import(REFERENCE_MODELS_MODULE)?;
let source_location: Bound<'py, PyAny> = registry::class(py, RecordId::SourceLocation)?;
let path_class: Bound<'py, PyAny> = py.import("pathlib")?.getattr("Path")?;
let compiler_diagnostic: Bound<'py, PyAny> = registry::class(py, RecordId::CompilerDiagnostic)?;
let mut diagnostics: Vec<Bound<'py, PyAny>> = Vec::with_capacity(report.diagnostics.len());
for row in &report.diagnostics {
let fields: Bound<'py, PyDict> = PyDict::new(py);
Expand All @@ -333,15 +329,23 @@ fn python_report<'py>(
location.set_item("path", &owners[owner].relative_path)?;
location.set_item("line", row.line)?;
location.set_item("column", 1)?;
fields.set_item("location", source_location.call((), Some(&location))?)?;
fields.set_item(
"location",
new_record(py, RecordId::SourceLocation, (), Some(&location))?,
)?;
}
None => fields.set_item("location", py.None())?,
}
fields.set_item("help", &row.help)?;
diagnostics.push(compiler_diagnostic.call((), Some(&fields))?);
diagnostics.push(new_record(
py,
RecordId::CompilerDiagnostic,
(),
Some(&fields),
)?);
}
let literal_relation: Bound<'py, PyAny> =
registry::class(reference_models.py(), RecordId::LiteralSqlRelation)?;
record_class(reference_models.py(), RecordId::LiteralSqlRelation)?;
let relation_name: Bound<'py, PyAny> = native_field(&reference_models, "RelationName")?;
let mut unmatched: Vec<Bound<'py, PyAny>> = Vec::with_capacity(report.unmatched.len());
for row in &report.unmatched {
Expand All @@ -352,7 +356,10 @@ fn python_report<'py>(
relation.set_item("database", &row.relation.database)?;
let fields: Bound<'py, PyDict> = PyDict::new(py);
fields.set_item("owner_label", &owner.label)?;
fields.set_item("owner_kind", owner_kind.call1((owner.kind,))?)?;
fields.set_item(
"owner_kind",
enum_from_value(py, RecordId::HardCodedRelationOwnerKind, owner.kind)?,
)?;
fields.set_item("relative_path", &owner.relative_path)?;
fields.set_item("line", row.line)?;
fields.set_item("method", &row.method)?;
Expand All @@ -362,7 +369,7 @@ fn python_report<'py>(
let fields: Bound<'py, PyDict> = PyDict::new(py);
fields.set_item("diagnostics", PyTuple::new(py, diagnostics)?)?;
fields.set_item("unmatched", PyTuple::new(py, unmatched)?)?;
registry::class(py, RecordId::PythonSqlReferenceReport)?.call((), Some(&fields))
new_record(py, RecordId::PythonSqlReferenceReport, (), Some(&fields))
}

/// `(method, sql, line)` for each literal SQL call to the context in a dedented function source.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::bindings::_helpers::boundary::panics::value_error;
use crate::bindings::types::CompilerDetach;

#[pyfunction]
fn normalize_analysis_sql(
pub(crate) fn normalize_analysis_sql(
py: Python<'_>,
request: crate::bindings::models::NormalizationInput,
) -> PyResult<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use sqlbuild_analysis::semantic_validation::models as validation;
#[pymethods]
impl BindingPositions {
#[new]
fn new(request: PositionInput) -> PyResult<Self> {
pub(crate) fn new(request: PositionInput) -> PyResult<Self> {
compiler_guard(|| {
validation::BindingPositions::new(request.into())
.map(|inner| Self { inner })
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! The explicit-reference facts of a compiled project, read from its Python views.

use crate::bindings::_helpers::records::construct::record_class;
use crate::bindings::_helpers::records::fields::field as native_field;
use crate::bindings::_helpers::records::ids::RecordId;
use crate::bindings::_helpers::records::registry;
use pyo3::prelude::{Bound, PyAny, PyAnyMethods, PyResult, Python};
use pyo3::types::{PyBool, PyList, PyTuple};
use sqlbuild_analysis::explicit_references::models::{
Expand Down Expand Up @@ -108,8 +108,8 @@ struct HookEntries<'py> {
impl<'py> HookEntries<'py> {
fn imported(py: Python<'py>) -> PyResult<Self> {
Ok(Self {
python: registry::class(py, RecordId::PythonHookEntry)?,
sql: registry::class(py, RecordId::SqlHookEntry)?,
python: record_class(py, RecordId::PythonHookEntry)?,
sql: record_class(py, RecordId::SqlHookEntry)?,
})
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ use sqlbuild_analysis::required_columns::main::resolve_required_columns::resolve
use sqlbuild_analysis::required_columns::models::{ColumnRead, ReferenceInput};

use crate::bindings::_helpers::boundary::panics::value_error;
use crate::bindings::_helpers::compile_driver::python_calls::call_with;
use crate::bindings::_helpers::records::construct::new_record_with;
use crate::bindings::_helpers::records::fields::field as native_field;
use crate::bindings::_helpers::records::ids::RecordId;
use crate::bindings::_helpers::records::registry;
use crate::bindings::types::CompilerDetach;

/// CTE-aware column reads of `query_sql`, resolved to the external resources it references.
Expand Down Expand Up @@ -41,11 +40,11 @@ fn analyze_resolved_column_reads<'py>(
}
RequiredColumnsError::Normalization(message) => value_error(message),
})?;
let fact: Bound<'py, PyAny> = registry::class(py, RecordId::CompiledLineageSourceFact)?;
let mut facts: Vec<Bound<'py, PyAny>> = Vec::with_capacity(reads.len());
for read in reads {
facts.push(call_with(
&fact,
facts.push(new_record_with(
py,
RecordId::CompiledLineageSourceFact,
&[
(
"resource_type",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use sqlbuild_analysis::semantic_validation::main::normalize::normalize_analysis_
use sqlbuild_analysis::semantic_validation::models::NormalizationInput;

use crate::bindings::_helpers::boundary::panics::value_error;
use crate::bindings::_helpers::records::construct::new_record;
use crate::bindings::_helpers::records::ids::RecordId;
use crate::bindings::_helpers::records::registry;
use crate::bindings::types::CompilerDetach;

const GENERIC_DIALECT: &str = "generic";
Expand Down Expand Up @@ -61,5 +61,10 @@ pub(crate) fn schema_validation_request<'py>(
parts.quoted_identifiers_ignore_case,
)?;
arguments.set_item("catalog", parts.catalog)?;
registry::class(py, RecordId::SqlSchemaValidationRequest)?.call((), Some(&arguments))
new_record(
py,
RecordId::SqlSchemaValidationRequest,
(),
Some(&arguments),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,47 @@

use std::collections::HashMap;

use pyo3::prelude::{Bound, PyAny, PyAnyMethods, PyModule, PyModuleMethods, PyResult, Python};
use pyo3::prelude::{Bound, Py, PyAny, PyAnyMethods, PyModule, PyModuleMethods, PyResult, Python};
use pyo3::sync::PyOnceLock;
use pyo3::types::{PyDict, PyDictMethods, PyFrozenSet, PyTuple};
use pyo3::{pyfunction, wrap_pyfunction};
use sqlbuild_analysis::assembly::analysis_session::main::projection_facts::projection_facts;
use sqlbuild_analysis::assembly::analysis_session::models::ProjectionFacts;
use sqlbuild_core::panics::main::native_failure::native_failure;
use sqlbuild_core::text::main::python_casefold::python_casefold;

use crate::bindings::_helpers::analysis_session::models::FixtureInferenceCount;
use crate::bindings::_helpers::analysis_session::query_columns::ColumnsRow;
use crate::bindings::_helpers::analysis_session::stage_functions::query_column_rows;
use crate::bindings::_helpers::boundary::keyword_request::Request;
use crate::bindings::_helpers::boundary::panics::compiler_error;
use crate::bindings::_helpers::records::construct::{enum_from_value, new_record};
use crate::bindings::_helpers::records::fields::field as native_field;
use crate::bindings::_helpers::records::ids::RecordId;
use crate::bindings::_helpers::records::registry;
use crate::bindings::types::CompilerDetach;

const PROJECTION_FACTS_CONTEXT: &str = "native fixture projection facts";
const LEGACY_MODE: &str = "legacy";

/// Fixture column inferences computed in this process.
static INFERENCES: PyOnceLock<Py<FixtureInferenceCount>> = PyOnceLock::new();

/// `infer_fixture_column_facts(*, query_sql, inference_profile)`: a `FixtureColumnInference`.
#[pyfunction]
#[pyo3(signature = (**request))]
fn infer_fixture_column_facts<'py>(
pub(crate) fn infer_fixture_column_facts<'py>(
request: Option<&Bound<'py, PyDict>>,
) -> PyResult<Bound<'py, PyAny>> {
let request = Request::new("infer_fixture_column_facts", request)?;
let py: Python<'py> = request.py();
inference_count(py)?.borrow_mut().computed += 1;
let query_sql: String = request.get("query_sql")?.extract()?;
let profile: Bound<'py, PyAny> = request.get("inference_profile")?;
let query: Bound<'py, PyDict> = PyDict::new(py);
query.set_item("sql", &query_sql)?;
query.set_item("mode", LEGACY_MODE)?;
query.set_item("recover_cte_facts", false)?;
let query: Bound<'py, PyAny> =
registry::class(py, RecordId::NativeColumnQuery)?.call((), Some(&query))?;
let query: Bound<'py, PyAny> = new_record(py, RecordId::NativeColumnQuery, (), Some(&query))?;
let empty: Bound<'py, PyAny> = PyDict::new(py).into_any();
let rows: Vec<ColumnsRow> = query_column_rows(
PyTuple::new(py, [query])?.as_any(),
Expand All @@ -52,8 +57,6 @@ fn infer_fixture_column_facts<'py>(
.compiler_detach(|| projection_facts(&query_sql, dialect.as_deref()))
.map_err(|reason| compiler_error(native_failure(PROJECTION_FACTS_CONTEXT, &reason)))?;
let simple_types: HashMap<String, String> = facts.types.into_iter().collect();
let column_class: Bound<'py, PyAny> = registry::class(py, RecordId::InferredColumn)?;
let nullability_class: Bound<'py, PyAny> = registry::class(py, RecordId::InferredNullability)?;
let mut built: Vec<Bound<'py, PyAny>> = Vec::with_capacity(columns.len());
for (name, data_type, nullability) in columns {
let data_type: Option<String> = data_type
Expand All @@ -62,8 +65,16 @@ fn infer_fixture_column_facts<'py>(
let arguments: Bound<'py, PyDict> = PyDict::new(py);
arguments.set_item("name", name)?;
arguments.set_item("type", data_type)?;
arguments.set_item("nullability", nullability_class.call1((nullability,))?)?;
built.push(column_class.call((), Some(&arguments))?);
arguments.set_item(
"nullability",
enum_from_value(py, RecordId::InferredNullability, nullability)?,
)?;
built.push(new_record(
py,
RecordId::InferredColumn,
(),
Some(&arguments),
)?);
}
let arguments: Bound<'py, PyDict> = PyDict::new(py);
arguments.set_item("columns", PyTuple::new(py, built)?)?;
Expand All @@ -72,9 +83,30 @@ fn infer_fixture_column_facts<'py>(
PyFrozenSet::new(py, facts.null_literal_names)?,
)?;
arguments.set_item("quoted_names", PyFrozenSet::new(py, facts.quoted_names)?)?;
registry::class(py, RecordId::FixtureColumnInference)?.call((), Some(&arguments))
new_record(py, RecordId::FixtureColumnInference, (), Some(&arguments))
}

/// Fixture column inferences computed in this process, optionally clearing the count first.
#[pyfunction]
#[pyo3(signature = (*, reset = false))]
fn fixture_inference_count(py: Python<'_>, reset: bool) -> PyResult<u64> {
let count = inference_count(py)?;
let mut count = count.borrow_mut();
if reset {
count.computed = 0;
}
Ok(count.computed)
}

/// The extension-wide fixture inference counter.
fn inference_count(py: Python<'_>) -> PyResult<Bound<'_, FixtureInferenceCount>> {
Ok(INFERENCES
.get_or_try_init(py, || Py::new(py, FixtureInferenceCount::default()))?
.bind(py)
.clone())
}

pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
module.add_function(wrap_pyfunction!(infer_fixture_column_facts, module)?)
module.add_function(wrap_pyfunction!(infer_fixture_column_facts, module)?)?;
module.add_function(wrap_pyfunction!(fixture_inference_count, module)?)
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//! Fixture column inference computed once per fixture body and inference profile.

use crate::bindings::_helpers::compile_driver::python_calls::call_with;
use crate::bindings::_helpers::analysis_session::fixture_columns::infer_fixture_column_facts;
use crate::bindings::_helpers::compile_driver::python_calls::keywords;
use crate::bindings::_helpers::records::fields::field as native_field;
use crate::bindings::_helpers::records::ids::NativeAttr;
use crate::bindings::_helpers::records::registry;
use pyo3::prelude::{Bound, Py, PyAny, PyAnyMethods, PyResult, Python};
use pyo3::types::{PyDict, PyDictMethods};
use pyo3::{pyclass, pymethods};
Expand Down Expand Up @@ -33,13 +32,13 @@ impl FixtureColumnInferences {
) -> PyResult<Bound<'py, PyAny>> {
let py = query_sql.py();
let compute = || {
call_with(
&registry::native(py, NativeAttr::InferFixtureColumnFacts)?,
infer_fixture_column_facts(Some(&keywords(
py,
&[
("query_sql", query_sql.clone()),
("inference_profile", inference_profile.clone()),
],
)
)?))
};
if !native_field(inference_profile, "binding_catalog")?.is_none() {
return compute();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub(crate) mod fixture_columns;
pub(crate) mod fixture_inferences;
pub(crate) mod model_analyses;
pub(crate) mod models;
pub(crate) mod nullability_rules;
pub(crate) mod oracle;
pub(crate) mod outcome_objects;
Expand Down
Loading
Loading