Skip to content

Commit a181c34

Browse files
deeasuElias Kassell
authored andcommitted
Update @dataform/core to never return a graph with non-unique action names. (#1366)
* Update @dataform/core to never return a graph with non-unique action names. * Include a compilation error for each removed action. * Rename a shadowed variable * Increment DF_VERSION
1 parent ddc3793 commit a181c34

File tree

3 files changed

+90
-50
lines changed

3 files changed

+90
-50
lines changed

core/session.ts

Lines changed: 60 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -416,19 +416,10 @@ export class Session {
416416
[].concat(compiledGraph.declarations.map(declaration => declaration.target))
417417
);
418418

419-
const standardActions = [].concat(
420-
compiledGraph.tables,
421-
compiledGraph.assertions,
422-
compiledGraph.operations,
423-
compiledGraph.declarations
424-
);
425-
426-
this.checkActionNameUniqueness(standardActions);
419+
this.removeNonUniqueActionsFromCompiledGraph(compiledGraph);
427420

428421
this.checkTestNameUniqueness(compiledGraph.tests);
429422

430-
this.checkCanonicalTargetUniqueness(standardActions);
431-
432423
this.checkTableConfigValidity(compiledGraph.tables);
433424

434425
this.checkCircularity(
@@ -574,41 +565,6 @@ export class Session {
574565
});
575566
}
576567

577-
private checkActionNameUniqueness(actions: IActionProto[]) {
578-
const allNames: string[] = [];
579-
actions.forEach(action => {
580-
const name = targetAsReadableString(action.target);
581-
if (allNames.includes(name)) {
582-
this.compileError(
583-
new Error(
584-
`Duplicate action name detected. Names within a schema must be unique across tables, declarations, assertions, and operations`
585-
),
586-
action.fileName,
587-
action.target
588-
);
589-
}
590-
allNames.push(name);
591-
});
592-
}
593-
594-
private checkCanonicalTargetUniqueness(actions: IActionProto[]) {
595-
const allCanonicalTargets = new StringifiedSet<dataform.ITarget>(targetStringifier);
596-
actions.forEach(action => {
597-
if (allCanonicalTargets.has(action.canonicalTarget)) {
598-
this.compileError(
599-
new Error(
600-
`Duplicate canonical target detected. Canonical targets must be unique across tables, declarations, assertions, and operations:\n"${JSON.stringify(
601-
action.canonicalTarget
602-
)}"`
603-
),
604-
action.fileName,
605-
action.target
606-
);
607-
}
608-
allCanonicalTargets.add(action.canonicalTarget);
609-
});
610-
}
611-
612568
private checkTableConfigValidity(tables: dataform.ITable[]) {
613569
tables.forEach(table => {
614570
// type
@@ -866,6 +822,65 @@ export class Session {
866822
);
867823
});
868824
}
825+
826+
private removeNonUniqueActionsFromCompiledGraph(compiledGraph: dataform.CompiledGraph) {
827+
function getNonUniqueTargets(targets: dataform.ITarget[]): StringifiedSet<dataform.ITarget> {
828+
const allTargets = new StringifiedSet<dataform.ITarget>(targetStringifier);
829+
const nonUniqueTargets = new StringifiedSet<dataform.ITarget>(targetStringifier);
830+
831+
targets.forEach(target => {
832+
if (allTargets.has(target)) {
833+
nonUniqueTargets.add(target);
834+
}
835+
allTargets.add(target);
836+
});
837+
838+
return nonUniqueTargets;
839+
}
840+
841+
const actions = [].concat(
842+
compiledGraph.tables,
843+
compiledGraph.assertions,
844+
compiledGraph.operations,
845+
compiledGraph.declarations
846+
);
847+
848+
const nonUniqueActionsTargets = getNonUniqueTargets(actions.map(action => action.target));
849+
const nonUniqueActionsCanonicalTargets = getNonUniqueTargets(actions.map(action => action.canonicalTarget));
850+
851+
const isUniqueAction = (action: IActionProto) => {
852+
const isNonUniqueTarget = nonUniqueActionsTargets.has(action.target);
853+
const isNonUniqueCanonicalTarget = nonUniqueActionsCanonicalTargets.has(action.canonicalTarget);
854+
855+
if (isNonUniqueTarget) {
856+
this.compileError(
857+
new Error(
858+
`Duplicate action name detected. Names within a schema must be unique across tables, declarations, assertions, and operations`
859+
),
860+
action.fileName,
861+
action.target
862+
);
863+
}
864+
if (isNonUniqueCanonicalTarget) {
865+
this.compileError(
866+
new Error(
867+
`Duplicate canonical target detected. Canonical targets must be unique across tables, declarations, assertions, and operations:\n"${JSON.stringify(
868+
action.canonicalTarget
869+
)}"`
870+
),
871+
action.fileName,
872+
action.target
873+
);
874+
}
875+
876+
return !isNonUniqueTarget && !isNonUniqueCanonicalTarget;
877+
}
878+
879+
compiledGraph.tables = compiledGraph.tables.filter(isUniqueAction);
880+
compiledGraph.operations = compiledGraph.operations.filter(isUniqueAction);
881+
compiledGraph.declarations = compiledGraph.declarations.filter(isUniqueAction);
882+
compiledGraph.assertions = compiledGraph.assertions.filter(isUniqueAction);
883+
}
869884
}
870885

871886
function declaresDataset(type: string, hasOutput?: boolean) {

tests/core/core.spec.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,9 @@ suite("@dataform/core", () => {
310310
schema: "schema"
311311
});
312312
const graph = session.compile();
313-
expect(graph.graphErrors.compilationErrors.map(error => error.message)).deep.equals([
313+
expect(graph.graphErrors.compilationErrors.map(error => error.message)).deep.equals(Array(2).fill(
314314
'Duplicate canonical target detected. Canonical targets must be unique across tables, declarations, assertions, and operations:\n"{"schema":"schema","name":"view","database":"database"}"'
315-
]);
315+
));
316316
});
317317

318318
test("validation_type_incremental", () => {
@@ -967,7 +967,32 @@ suite("@dataform/core", () => {
967967
cGraph.graphErrors.compilationErrors.filter(item =>
968968
item.message.match(/Duplicate action name/)
969969
).length
970-
).greaterThan(0);
970+
).equals(2);
971+
});
972+
973+
test("duplicate actions in compiled graph", () => {
974+
const session = new Session(path.dirname(__filename), TestConfigs.redshift);
975+
session.publish("a")
976+
session.publish("a");
977+
session.publish("b"); // unique action
978+
session.publish("c")
979+
980+
session.operate("a")
981+
session.operate("d") // unique action
982+
session.operate("e") // unique action
983+
984+
session.declare({ name: "a" })
985+
session.declare({ name: "f" }) // unique action
986+
session.declare({ name: "g" })
987+
988+
session.assert("c")
989+
session.assert("g")
990+
991+
const cGraph = session.compile();
992+
993+
expect(
994+
[].concat(cGraph.tables, cGraph.assertions, cGraph.operations, cGraph.declarations).length
995+
).equals(4)
971996
});
972997

973998
test("same action names in different schemas (ambiguity)", () => {
@@ -995,7 +1020,7 @@ suite("@dataform/core", () => {
9951020
cGraph.graphErrors.compilationErrors.filter(item =>
9961021
item.message.match(/Duplicate action name detected. Names within a schema must be unique/)
9971022
).length
998-
).greaterThan(0);
1023+
).equals(2);
9991024
});
10001025

10011026
test("same action names in different schemas", () => {

version.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# NOTE: If you change the format of this line, you must change the bash command
22
# in /scripts/publish to extract the version string correctly.
3-
DF_VERSION = "2.0.0"
3+
DF_VERSION = "2.0.1"

0 commit comments

Comments
 (0)