Skip to content

Support ref() and DAG dependencies in PropertyGraph - #2258

Open
rafal-hawrylak wants to merge 1 commit into
mainfrom
pr/property-graph-ref-deps
Open

Support ref() and DAG dependencies in PropertyGraph#2258
rafal-hawrylak wants to merge 1 commit into
mainfrom
pr/property-graph-ref-deps

Conversation

@rafal-hawrylak

Copy link
Copy Markdown
Collaborator

Extends PropertyGraph to accept ref: [dataset, table] in place of a bare table name for nodeTables and edgeTables. Refs resolve through the same Session.resolve path used by tables and operations so the graph action inherits the standard dependency edges.

The resolved dependencies land on the compiled action's dependencyTargets which makes the executor run source tables before the graph DDL. Ref resolution respects schema suffixes and database overrides so a graph declared with ref: [authors] in a suffixed workspace still targets the suffixed dataset.

Lock-in tests cover the resolved-DDL output for named refs, dataset-scoped refs, mixed literal-and-ref entries, and the error surface when a ref points at a nonexistent action.

@rafal-hawrylak
rafal-hawrylak requested a review from a team as a code owner August 25, 2026 06:19
@rafal-hawrylak
rafal-hawrylak force-pushed the pr/property-graph-ref-deps branch from a5f5c57 to d06d1bd Compare August 25, 2026 06:47
Comment thread core/actions/property_graph.ts Outdated
Comment thread core/actions/property_graph.ts
Comment on lines +111 to +125
const resolved = this.session.indexedActions.find(rawRef);
if (resolved.length !== 1) {
return false;
}
const resolvedAction = resolved[0];
const target = resolvedAction.getTarget();
if (resolvedAction instanceof Declaration) {
entityOrRel.dataSource = target;
} else {
entityOrRel.dataSource = dataform.Target.create({
database: target.database && this.session.finalizeDatabase(target.database),
schema: this.session.finalizeSchema(target.schema),
name: this.session.finalizeName(target.name)
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this logic repeats this a lot

public resolve(ref: Resolvable | string[], ...rest: string[]): string {
? could we use session.resolve method here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolve() returns SQL string, we need target. I could still unify it introducing shared helper. Is this what you'd expect?

}
this.pendingRefs.set(pendingKey, rawRef);
const depKey = `${rawRef.database || ""}.${rawRef.schema || ""}.${rawRef.name}`;
if (!this.dependencyKeys.has(depKey)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this logic should respect https://docs.cloud.google.com/dataform/docs/dependencies#set-assertions-as-dependencies

const dependencyTarget = checkAssertionsForDependency(this, resolvable);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, but note graph.yaml has no surface for these flags today (DataSourceRef proto is just {name, schema, database}), so the plumbing is inert.
Would you like keep it that way for now? Revert it? Or add support through proto?

Comment thread core/main_test.ts Outdated
Comment thread core/session.ts

this.removeNonUniqueActionsFromCompiledGraph(compiledGraph);

this.finalizePropertyGraphs();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need a separate callback for graph actions here? Regular SQLX actions also have to insert resolved ref in generated SQL body and I'm wondering if it's possible to have it using consistent interfaces inside session

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SQLX ref() runs inside the query closure, which the session doesn't evaluate until every action is indexed - so ref() sees a fully-populated index at call time. YAML has no closure, so we get the equivalent deferral by stashing raw refs in construction and draining them in finalize(). Could contextify graphBody as a Contextable to mirror SQLX, but that changes YAML from data into code.

@rafal-hawrylak
rafal-hawrylak force-pushed the pr/property-graph-ref-deps branch from d06d1bd to b7b8fda Compare August 25, 2026 16:50
Extends PropertyGraph to accept `ref: [dataset, table]` in place of a
bare table name for `nodeTables` and `edgeTables`. Refs resolve through
the same `Session.resolve` path used by tables and operations so the
graph action inherits the standard dependency edges.

The resolved dependencies land on the compiled action's `dependencyTargets`
which makes the executor run source tables before the graph DDL. Ref
resolution respects schema suffixes and database overrides so a graph
declared with `ref: [authors]` in a suffixed workspace still targets the
suffixed dataset.

Lock-in tests cover the resolved-DDL output for named refs, dataset-scoped
refs, mixed literal-and-ref entries, and the error surface when a ref
points at a nonexistent action.
@rafal-hawrylak
rafal-hawrylak force-pushed the pr/property-graph-ref-deps branch 2 times, most recently from b7b8fda to 638a793 Compare August 25, 2026 17:05
@rafal-hawrylak
rafal-hawrylak requested a review from kolina August 25, 2026 17:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants