JSONB on table scripts also now

This commit is contained in:
Priec
2025-09-18 10:47:01 +02:00
parent 73bc6dc99c
commit 7350b0985c
5 changed files with 89 additions and 6 deletions

View File

@@ -45,6 +45,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
".komp_ac.table_definition.TableDefinitionResponse", ".komp_ac.table_definition.TableDefinitionResponse",
"#[derive(serde::Serialize, serde::Deserialize)]" "#[derive(serde::Serialize, serde::Deserialize)]"
) )
.type_attribute(
".komp_ac.table_script.PostTableScriptRequest",
"#[derive(serde::Serialize, serde::Deserialize)]",
)
.type_attribute(
".komp_ac.table_script.TableScriptResponse",
"#[derive(serde::Serialize, serde::Deserialize)]",
)
.compile_protos( .compile_protos(
&[ &[
"proto/common.proto", "proto/common.proto",

View File

@@ -1,4 +1,5 @@
// This file is @generated by prost-build. // This file is @generated by prost-build.
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct PostTableScriptRequest { pub struct PostTableScriptRequest {
#[prost(int64, tag = "1")] #[prost(int64, tag = "1")]
@@ -10,6 +11,7 @@ pub struct PostTableScriptRequest {
#[prost(string, tag = "4")] #[prost(string, tag = "4")]
pub description: ::prost::alloc::string::String, pub description: ::prost::alloc::string::String,
} }
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct TableScriptResponse { pub struct TableScriptResponse {
#[prost(int64, tag = "1")] #[prost(int64, tag = "1")]

View File

@@ -2,6 +2,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use tonic::Status; use tonic::Status;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value}; use serde_json::{json, Value};
/// Represents the state of a node during dependency graph traversal. /// Represents the state of a node during dependency graph traversal.
@@ -40,18 +41,38 @@ impl DependencyType {
DependencyType::SqlQuery { .. } => "sql_query", DependencyType::SqlQuery { .. } => "sql_query",
} }
} }
}
/// Generates context JSON for database storage. /// Strongly-typed JSON for script_dependencies.context_info
pub fn context_json(&self) -> Value { /// Using untagged so JSON stays minimal (no "type" field), and we can still
/// deserialize it into a proper enum.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ScriptDependencyContext {
ColumnAccess { column: String },
IndexedAccess { column: String, index: i64 },
SqlQuery { query_fragment: String },
}
impl DependencyType {
/// Convert this dependency into its JSON context struct.
pub fn to_context(&self) -> ScriptDependencyContext {
match self { match self {
DependencyType::ColumnAccess { column } => { DependencyType::ColumnAccess { column } => {
json!({ "column": column }) ScriptDependencyContext::ColumnAccess {
column: column.clone(),
}
} }
DependencyType::IndexedAccess { column, index } => { DependencyType::IndexedAccess { column, index } => {
json!({ "column": column, "index": index }) ScriptDependencyContext::IndexedAccess {
column: column.clone(),
index: *index,
}
} }
DependencyType::SqlQuery { query_fragment } => { DependencyType::SqlQuery { query_fragment } => {
json!({ "query_fragment": query_fragment }) ScriptDependencyContext::SqlQuery {
query_fragment: query_fragment.clone(),
}
} }
} }
} }
@@ -554,7 +575,7 @@ impl DependencyAnalyzer {
table_id, table_id,
target_id, target_id,
dep.dependency_type.as_str(), dep.dependency_type.as_str(),
dep.dependency_type.context_json() serde_json::to_value(dep.dependency_type.to_context()).unwrap()
) )
.execute(&mut **tx) .execute(&mut **tx)
.await .await

View File

@@ -1,4 +1,7 @@
// src/table_script/mod.rs // src/table_script/mod.rs
pub mod handlers; pub mod handlers;
pub mod repo;
pub use handlers::*; pub use handlers::*;
pub use repo::*;

View File

@@ -0,0 +1,49 @@
// src/table_script/repo.rs
use anyhow::Result;
use sqlx::PgPool;
use crate::table_script::handlers::dependency_analyzer::ScriptDependencyContext;
#[derive(Debug, Clone)]
pub struct ScriptDependencyRecord {
pub script_id: i64,
pub source_table_id: i64,
pub target_table_id: i64,
pub dependency_type: String,
pub context: Option<ScriptDependencyContext>,
}
pub async fn get_dependencies_for_script(
db: &PgPool,
script_id: i64,
) -> Result<Vec<ScriptDependencyRecord>> {
let rows = sqlx::query!(
r#"
SELECT script_id, source_table_id, target_table_id, dependency_type, context_info
FROM script_dependencies
WHERE script_id = $1
ORDER BY source_table_id, target_table_id
"#,
script_id
)
.fetch_all(db)
.await?;
let mut out = Vec::new();
for r in rows {
let context = match r.context_info {
Some(value) => Some(serde_json::from_value::<ScriptDependencyContext>(value)?),
None => None,
};
out.push(ScriptDependencyRecord {
script_id: r.script_id,
source_table_id: r.source_table_id,
target_table_id: r.target_table_id,
dependency_type: r.dependency_type,
context,
});
}
Ok(out)
}