Skip to content

Commit 85fb6a9

Browse files
committed
feat(query): extract query lineage
1 parent 96d89cf commit 85fb6a9

17 files changed

Lines changed: 2885 additions & 22 deletions

File tree

src/meta/app/src/schema/catalog.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::schema::catalog_id_ident;
2626
use crate::storage::StorageParams;
2727
use crate::tenant::Tenant;
2828

29-
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
29+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
3030
pub enum CatalogType {
3131
Default = 1,
3232
Hive = 2,

src/query/catalog/src/table.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,15 @@ pub trait Table: Sync + Send {
109109

110110
fn get_table_info(&self) -> &TableInfo;
111111

112+
/// Returns the source table whose data columns a stream exposes.
113+
///
114+
/// Lineage intentionally passes through a stream to its source table.
115+
/// Views are lineage boundaries and must not use this relation-level hook;
116+
/// their output columns are annotated separately by the planner.
117+
fn stream_source_table_info(&self) -> Option<&TableInfo> {
118+
None
119+
}
120+
112121
fn get_data_source_info(&self) -> DataSourceInfo {
113122
DataSourceInfo::TableSource(self.get_table_info().clone())
114123
}

src/query/service/src/interpreters/interpreter_table_create.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,12 @@ impl CreateTableInterpreter {
251251
overwrite: false,
252252
source: InsertInputSource::SelectPlan(select_plan),
253253
table_info: Some(table_info),
254+
lineage_target_table_id: None,
255+
lineage_target_catalog_type: if self.plan.engine == Engine::Iceberg {
256+
databend_common_meta_app::schema::CatalogType::Iceberg
257+
} else {
258+
databend_common_meta_app::schema::CatalogType::Default
259+
},
254260
};
255261

256262
let mut pipeline = InsertInterpreter::try_create(self.ctx.clone(), insert_plan)?

src/query/sql/src/planner/binder/bind_table_reference/bind_table.rs

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@ use databend_common_catalog::table_with_options::get_with_opt_consume;
2727
use databend_common_catalog::table_with_options::get_with_opt_max_batch_size;
2828
use databend_common_exception::ErrorCode;
2929
use databend_common_exception::Result;
30+
use databend_common_expression::ColumnId;
3031
use databend_common_storages_basic::view_table::QUERY;
3132
use databend_storages_common_table_meta::table::get_change_type;
3233

3334
use crate::BindContext;
35+
use crate::LineageSourceRelation;
36+
use crate::ViewLineageSourceColumn;
3437
use crate::binder::Binder;
3538
use crate::binder::ViewIdent;
3639
use crate::binder::util::TableIdentifier;
@@ -189,17 +192,25 @@ impl Binder {
189192
{
190193
let change_type = get_change_type(&table_name_alias);
191194
if change_type.is_some() {
192-
let table_index = self.metadata.write().add_table(
193-
catalog,
194-
database.clone(),
195-
table_meta.clone(),
196-
branch_name,
197-
table_name_alias,
198-
!bind_context.binding_views.is_empty(),
199-
bind_context.planning_agg_index,
200-
false,
201-
cte_suffix_name,
202-
);
195+
let stream_lineage_source = stream_lineage_source_relation(&table_meta);
196+
let table_index = {
197+
let mut metadata = self.metadata.write();
198+
let table_index = metadata.add_table(
199+
catalog,
200+
database.clone(),
201+
table_meta.clone(),
202+
branch_name,
203+
table_name_alias,
204+
!bind_context.binding_views.is_empty(),
205+
bind_context.planning_agg_index,
206+
false,
207+
cte_suffix_name,
208+
);
209+
if let Some(stream_lineage_source) = stream_lineage_source {
210+
metadata.set_stream_lineage_source(table_index, stream_lineage_source);
211+
}
212+
table_index
213+
};
203214
let (s_expr, mut bind_context) = self.bind_base_table(
204215
bind_context,
205216
database.as_str(),
@@ -280,11 +291,11 @@ impl Binder {
280291
new_bind_context.binding_views.insert(view_ident);
281292
if let Statement::Query(query) = &stmt {
282293
self.metadata.write().add_table(
283-
catalog,
294+
catalog.clone(),
284295
database.clone(),
285-
table_meta,
286-
branch_name,
287-
table_name_alias,
296+
table_meta.clone(),
297+
branch_name.clone(),
298+
table_name_alias.clone(),
288299
false,
289300
false,
290301
false,
@@ -302,6 +313,13 @@ impl Binder {
302313
column.table_name = Some(self.normalize_identifier(table).name);
303314
}
304315
}
316+
self.add_view_lineage_source_columns(
317+
&new_bind_context,
318+
catalog.as_str(),
319+
database.as_str(),
320+
table_name.as_str(),
321+
&table_meta,
322+
);
305323
// Restore binding_views to the outer scope's value so the
306324
// current view does not leak into sibling/parent contexts.
307325
new_bind_context.binding_views = bind_context.binding_views.clone();
@@ -343,4 +361,44 @@ impl Binder {
343361
}
344362
}
345363
}
364+
365+
fn add_view_lineage_source_columns(
366+
&mut self,
367+
bind_context: &BindContext,
368+
catalog: &str,
369+
database: &str,
370+
view_name: &str,
371+
view: &std::sync::Arc<dyn databend_common_catalog::table::Table>,
372+
) {
373+
let relation = LineageSourceRelation {
374+
catalog: catalog.to_string(),
375+
database: database.to_string(),
376+
name: view_name.to_string(),
377+
id: view.get_table_info().ident.table_id,
378+
};
379+
let mut metadata = self.metadata.write();
380+
for (idx, column) in bind_context.columns.iter().enumerate() {
381+
metadata.add_view_lineage_source_column(column.index, ViewLineageSourceColumn {
382+
relation: relation.clone(),
383+
// View TableMeta has no persisted schema. The bound view query (including an
384+
// explicit view column list) is the source of truth for output column names.
385+
name: column.column_name.clone(),
386+
id: idx as ColumnId,
387+
});
388+
}
389+
}
390+
}
391+
392+
fn stream_lineage_source_relation(
393+
table: &std::sync::Arc<dyn databend_common_catalog::table::Table>,
394+
) -> Option<LineageSourceRelation> {
395+
table.stream_source_table_info().and_then(|table_info| {
396+
let database = table_info.database_name().ok()?.to_string();
397+
Some(LineageSourceRelation {
398+
catalog: table_info.catalog().to_string(),
399+
database,
400+
name: table_info.name.clone(),
401+
id: table_info.ident.table_id,
402+
})
403+
})
346404
}

src/query/sql/src/planner/binder/ddl/view.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ impl Binder {
7474
view_name,
7575
column_names,
7676
subquery,
77+
query_plan: None,
7778
};
7879
Ok(Plan::CreateView(plan.into()))
7980
}

src/query/sql/src/planner/binder/insert.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,10 @@ impl Binder {
311311
overwrite: *overwrite,
312312
source: input_source?,
313313
table_info: None,
314+
lineage_target_table_id: (table.get_table_info().catalog_info.catalog_type()
315+
== databend_common_meta_app::schema::CatalogType::Default)
316+
.then_some(table.get_table_info().ident.table_id),
317+
lineage_target_catalog_type: table.get_table_info().catalog_info.catalog_type(),
314318
};
315319

316320
Ok(Plan::Insert(Box::new(plan)))

0 commit comments

Comments
 (0)