Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 19 additions & 4 deletions cli/api/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ export class Builder {
)
),
this.prunedGraph.operations.map(o => this.buildOperation(o)),
this.prunedGraph.assertions.map(a => this.buildAssertion(a))
this.prunedGraph.assertions.map(a => this.buildAssertion(a)),
this.prunedGraph.propertyGraphs.map(g => this.buildPropertyGraph(g))
);
return dataform.ExecutionGraph.create({
projectConfig: this.prunedGraph.projectConfig,
Expand Down Expand Up @@ -106,17 +107,31 @@ export class Builder {
};
}

private buildPropertyGraph(propertyGraph: dataform.IPropertyGraph) {
return {
...this.toPartialExecutionAction(propertyGraph),
type: "propertyGraph",
tasks: this.executionSql.createPropertyGraphTasks(propertyGraph)
};
}

private toPartialExecutionAction(
action: dataform.ITable | dataform.IOperation | dataform.IAssertion
action:
| dataform.ITable
| dataform.IOperation
| dataform.IAssertion
| dataform.IPropertyGraph
) {
const jitCode = "jitCode" in action ? action.jitCode : undefined;
const actionDescriptor = "actionDescriptor" in action ? action.actionDescriptor : undefined;
const disabled = !!action.disabled;
const executionAction = dataform.ExecutionAction.create({
target: action.target,
fileName: action.fileName,
dependencyTargets: action.dependencyTargets,
actionDescriptor: action.actionDescriptor
actionDescriptor
});
if (jitCode && !action.disabled) {
if (jitCode && !disabled) {
executionAction.jitCode = jitCode;
}
return executionAction;
Expand Down
9 changes: 9 additions & 0 deletions cli/api/dbadapters/execution_sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ from (${query}) as insertions`;
);
}

public createPropertyGraphTasks(
propertyGraph: dataform.IPropertyGraph
): dataform.IExecutionTask[] {
const statement =
`CREATE OR REPLACE PROPERTY GRAPH ${this.resolveTarget(propertyGraph.target)} ` +
`${propertyGraph.graphBody}`;
return [dataform.ExecutionTask.create({ type: "statement", statement })];
}

public createAssertionTasks(assertion: dataform.IAssertion): dataform.IExecutionTask[] {
return assertion.disabled ? [] : this.assertTasks(assertion, this.project).build();
}
Expand Down
48 changes: 48 additions & 0 deletions cli/api/execution_sql_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,51 @@ suite("ExecutionSql with 'onSchemaChange'", () => {
expect(sql).to.equal(expectedSql.trim());
});
});

suite("ExecutionSql for property graphs", () => {
const executionSql = new ExecutionSql(
{
defaultDatabase: "project-id",
defaultSchema: "dataset-id"
},
"2.0.0",
() => "test_uuid"
);

test("emits CREATE OR REPLACE PROPERTY GRAPH for FinGraph", () => {
const graphBody = `NODE TABLES (
\`project-id.dataset-id.account\` AS Account KEY (id) LABEL Account PROPERTIES ARE ALL COLUMNS,
\`project-id.dataset-id.person\` AS Person KEY (id) LABEL Person PROPERTIES ARE ALL COLUMNS
)
EDGE TABLES (
\`project-id.dataset-id.person_own_account\` AS PersonOwnAccount SOURCE KEY (id) REFERENCES Person (id) DESTINATION KEY (account_id) REFERENCES Account (id) LABEL Owns PROPERTIES ARE ALL COLUMNS,
\`project-id.dataset-id.account_transfer_account\` AS AccountTransferAccount SOURCE KEY (id) REFERENCES Account (id) DESTINATION KEY (to_id) REFERENCES Account (id) LABEL Transfers PROPERTIES (amount, create_time)
)`;
const propertyGraph: dataform.IPropertyGraph = {
target: { database: "project-id", schema: "dataset-id", name: "FinGraph" },
graphBody
};
const tasks = executionSql.createPropertyGraphTasks(propertyGraph);
const sql = tasks.map(t => t.statement).join("\n;\n");
const expectedSql = fs.readFileSync("cli/api/goldens/property_graph_fingraph.sql", "utf8");
expect(sql).to.equal(expectedSql.trim());
});

test("emits CREATE OR REPLACE PROPERTY GRAPH for HRGraph", () => {
const graphBody = `NODE TABLES (
\`project-id.dataset-id.employee\` AS Employee KEY (id) LABEL Employee PROPERTIES ARE ALL COLUMNS EXCEPT (ssn, salary),
\`project-id.dataset-id.manager\` AS Manager KEY (id) LABEL Manager PROPERTIES ARE ALL COLUMNS EXCEPT (bonus)
)
EDGE TABLES (
\`project-id.dataset-id.reports\` AS Reports SOURCE KEY (employee_id) REFERENCES Employee (id) DESTINATION KEY (manager_id) REFERENCES Manager (id) LABEL Reports PROPERTIES ARE ALL COLUMNS
)`;
const propertyGraph: dataform.IPropertyGraph = {
target: { database: "project-id", schema: "dataset-id", name: "HRGraph" },
graphBody
};
const tasks = executionSql.createPropertyGraphTasks(propertyGraph);
const sql = tasks.map(t => t.statement).join("\n;\n");
const expectedSql = fs.readFileSync("cli/api/goldens/property_graph_hrgraph.sql", "utf8");
expect(sql).to.equal(expectedSql.trim());
});
});
8 changes: 8 additions & 0 deletions cli/api/goldens/property_graph_fingraph.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE OR REPLACE PROPERTY GRAPH `project-id.dataset-id.FinGraph` NODE TABLES (
`project-id.dataset-id.account` AS Account KEY (id) LABEL Account PROPERTIES ARE ALL COLUMNS,
`project-id.dataset-id.person` AS Person KEY (id) LABEL Person PROPERTIES ARE ALL COLUMNS
)
EDGE TABLES (
`project-id.dataset-id.person_own_account` AS PersonOwnAccount SOURCE KEY (id) REFERENCES Person (id) DESTINATION KEY (account_id) REFERENCES Account (id) LABEL Owns PROPERTIES ARE ALL COLUMNS,
`project-id.dataset-id.account_transfer_account` AS AccountTransferAccount SOURCE KEY (id) REFERENCES Account (id) DESTINATION KEY (to_id) REFERENCES Account (id) LABEL Transfers PROPERTIES (amount, create_time)
)
7 changes: 7 additions & 0 deletions cli/api/goldens/property_graph_hrgraph.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE OR REPLACE PROPERTY GRAPH `project-id.dataset-id.HRGraph` NODE TABLES (
`project-id.dataset-id.employee` AS Employee KEY (id) LABEL Employee PROPERTIES ARE ALL COLUMNS EXCEPT (ssn, salary),
`project-id.dataset-id.manager` AS Manager KEY (id) LABEL Manager PROPERTIES ARE ALL COLUMNS EXCEPT (bonus)
)
EDGE TABLES (
`project-id.dataset-id.reports` AS Reports SOURCE KEY (employee_id) REFERENCES Employee (id) DESTINATION KEY (manager_id) REFERENCES Manager (id) LABEL Reports PROPERTIES ARE ALL COLUMNS
)
Loading