rhombic
Version:
SQL parsing, lineage extraction and manipulation
144 lines • 6.26 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConnectedElementsHelper = exports.LineageHelper = void 0;
const edgeFinder = (edges) => (edgeId) => edges.find(element => element.source.tableId === edgeId.source.tableId &&
element.source.columnId === edgeId.source.columnId &&
element.target.tableId === edgeId.target.tableId &&
element.target.columnId === edgeId.target.columnId &&
element.edgeType === edgeId.edgeType);
const tableFinder = (tables) => (tableId) => tables.find(element => element.id === tableId.id);
const columnFinder = (tables) => (columnId) => {
const table = tableFinder(tables)({ type: "table", id: columnId.tableId });
if (!table)
return;
const column = table.columns.find(column => column.id === columnId.column.id);
if (!column)
return;
return {
type: "column",
tableId: table.id,
column
};
};
const edgesBySourceFinder = (edges) => (elementId) => edges.filter(edge => (elementId.type === "table" && edge.source.tableId === elementId.id && edge.source.columnId === undefined) ||
(elementId.type === "column" &&
edge.source.tableId === elementId.tableId &&
edge.source.columnId === elementId.column.id));
const edgesByTargetFinder = (edges) => (elementId) => edges.filter(edge => (elementId.type === "table" && edge.target.tableId === elementId.id && edge.target.columnId === undefined) ||
(elementId.type === "column" &&
edge.target.tableId === elementId.tableId &&
edge.target.columnId === elementId.column.id));
/**
* Lineage Helper provides useful functions to work with an extracted lineage graph
*/
const LineageHelper = (lineage) => {
const findEdge = edgeFinder(lineage.edges);
const findTable = tableFinder(lineage.nodes);
const findColumn = columnFinder(lineage.nodes);
const findEdgesFromSource = edgesBySourceFinder(lineage.edges);
const findEdgesToTarget = edgesByTargetFinder(lineage.edges);
const findElement = (elementId) => {
switch (elementId.type) {
case "table":
return findTable(elementId);
case "column":
return findColumn(elementId);
case "edge":
return findEdge(elementId);
}
};
const walkUp = (elementId) => {
if (elementId.type === "table" || elementId.type === "column") {
return findEdgesToTarget(elementId);
}
// it's and edge
const tableOrColumn = elementId.source.columnId !== undefined
? findElement({ type: "column", tableId: elementId.source.tableId, column: { id: elementId.source.columnId } })
: findElement({ type: "table", id: elementId.source.tableId });
return tableOrColumn === undefined ? [] : [tableOrColumn];
};
const walkDown = (elementId) => {
if (elementId.type === "table" || elementId.type === "column") {
return findEdgesFromSource(elementId);
}
// it's and edge
const tableOrColumn = elementId.target.columnId !== undefined
? findElement({ type: "column", tableId: elementId.target.tableId, column: { id: elementId.target.columnId } })
: findElement({ type: "table", id: elementId.target.tableId });
return tableOrColumn === undefined ? [] : [tableOrColumn];
};
// Texas Ranger
const walker = (elementId, direction, eachElement) => {
(direction === "up" ? walkUp : walkDown)(elementId).forEach(element => {
eachElement(element);
walker(element, direction, eachElement);
});
};
const findConnectedElements = (elementId) => {
// Check that the given element exists
const referenceElement = findElement(elementId);
if (!referenceElement)
throw Error(`Element not found in lineage - ${JSON.stringify(elementId)}`);
// Collect connected elements
const elements = { tables: [], columns: [], edges: [] };
const collect = (element) => {
switch (element.type) {
case "table":
elements.tables.push(element);
break;
case "column":
elements.columns.push(element);
break;
case "edge":
elements.edges.push(element);
break;
}
};
// Include the given element in the connected elements
collect(referenceElement);
// Walk the graph
walker(elementId, "up", collect);
walker(elementId, "down", collect);
return exports.ConnectedElementsHelper(elements);
};
return {
/**
* Finds an element (table, column, edge) in the lineage graph
*/
findElement,
/**
* Finds all edges originating at a specific source table or column
*/
findEdgesFromSource,
/**
* Finds all edges targeting a specific source table or column
*/
findEdgesToTarget,
/**
* Finds all elements connected via the graph to a focused element
*/
findConnectedElements
};
};
exports.LineageHelper = LineageHelper;
const ConnectedElementsHelper = (elements) => {
return {
elements,
findElement: (elementId) => {
switch (elementId.type) {
case "table":
return elements.tables.find(t => t.id === elementId.id);
case "column":
return elements.columns.find(c => c.tableId === elementId.tableId && c.column.id === elementId.column.id);
case "edge":
return elements.edges.find(e => e.edgeType === elementId.edgeType &&
e.source.tableId === elementId.source.tableId &&
e.source.columnId === elementId.source.columnId &&
e.target.tableId === elementId.target.tableId &&
e.target.columnId === elementId.target.columnId);
}
}
};
};
exports.ConnectedElementsHelper = ConnectedElementsHelper;
//# sourceMappingURL=LineageHelper.js.map