UNPKG

rhombic

Version:

SQL parsing, lineage extraction and manipulation

144 lines 6.26 kB
"use strict"; 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