UNPKG

ddl-manager

Version:

store postgres procedures and triggers in files

167 lines 7.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CacheColumnGraph = void 0; const CacheColumn_1 = require("./CacheColumn"); const TableReference_1 = require("../../database/schema/TableReference"); const TableID_1 = require("../../database/schema/TableID"); const lodash_1 = require("lodash"); const CacheUpdate_1 = require("./CacheUpdate"); const utils_1 = require("./utils"); const Column_1 = require("../../database/schema/Column"); const ast_1 = require("../../ast"); const buildReferenceMeta_1 = require("../../cache/processor/buildReferenceMeta"); class CacheColumnGraph { constructor(allColumns) { this.allColumns = allColumns .map(columnParams => new CacheColumn_1.CacheColumn(columnParams)); this.tables = utils_1.groupByTables(this.allColumns); this.rootColumns = []; this.assignAllDependencies(); this.dependencyMatrix = utils_1.buildDependencyMatrix(this.rootColumns.slice()); } static build(aggregators, allCache) { const cacheColumns = []; for (const cache of allCache) { const selectForUpdate = cache.createSelectForUpdate(aggregators); for (const updateColumn of selectForUpdate.columns) { cacheColumns.push({ for: cache.for, name: updateColumn.name, cache: { name: cache.name, signature: cache.getSignature() }, select: selectForUpdate.clone({ columns: [ updateColumn ] }) }); } const needLastRowColumn = (cache.select.from.length === 1 && cache.select.orderBy && cache.select.limit === 1); if (needLastRowColumn) { const fromRef = cache.select.getFromTable(); const prevRef = new TableReference_1.TableReference(fromRef.table, `prev_${fromRef.table.name}`); const orderBy = cache.select.orderBy.items[0]; const columnName = cache.getIsLastColumnName(); const referenceMeta = buildReferenceMeta_1.buildReferenceMeta(cache, fromRef.table); cacheColumns.push({ for: fromRef, name: columnName, cache: { name: cache.name, signature: cache.getSignature() }, select: ast_1.Select.notExists(prevRef, ast_1.Expression.and([ ...referenceMeta.columns.map(column => new ast_1.Expression([ new ast_1.ColumnReference(prevRef, column), new ast_1.Operator("="), new ast_1.ColumnReference(fromRef, column), ])), ...referenceMeta.filters.map(filter => filter.replaceTable(fromRef, prevRef)), new ast_1.Expression([ new ast_1.ColumnReference(prevRef, "id"), new ast_1.Operator(orderBy.type === "desc" ? ">" : "<"), new ast_1.ColumnReference(fromRef, "id"), ]) ]), columnName) }); } } const graph = new CacheColumnGraph(cacheColumns); return graph; } getAllColumns() { return this.allColumns; } getAllColumnsFromRootToDeps() { return lodash_1.flatMap(this.dependencyMatrix); } generateUpdatesFor(changedColumns) { const changesMap = buildChangesMap(changedColumns); const matrix = this.dependencyMatrix.map(columns => columns.filter(column => column.getId() in changesMap)); const updatesMatrix = matrix.map(columns => CacheUpdate_1.CacheUpdate.fromManyTables(columns)); const allUpdates = lodash_1.flatMap(updatesMatrix); return allUpdates; } generateAllUpdates() { const updatesMatrix = this.dependencyMatrix .map(columns => CacheUpdate_1.CacheUpdate.fromManyTables(columns)); const allUpdates = lodash_1.flatMap(updatesMatrix); return allUpdates; } getColumn(tableRef, columnName) { return this.getColumns(tableRef).find(cacheColumn => Column_1.equalColumnName(cacheColumn.name, columnName)); } getColumns(tableRef) { if (typeof tableRef === "string") { tableRef = TableID_1.TableID.fromString(tableRef); } const tableId = (tableRef instanceof TableReference_1.TableReference ? tableRef.table : tableRef); return this.tables[tableId.toString()] || []; } getDependencyLevel(column) { return this.dependencyMatrix.findIndex(level => level.some(levelColumn => levelColumn.name === column.name && levelColumn.for.table.equal(column.for.table))); } findCacheColumnsForTablesOrColumns(targetTablesOrColumns) { if (!targetTablesOrColumns) { return this.getAllColumns(); } const concreteColumns = []; for (const tableOrColumn of String(targetTablesOrColumns).split(/\s*,\s*/)) { const path = tableOrColumn.trim().toLowerCase().split("."); const tableId = path.slice(0, 2).join("."); const tableColumns = this.getColumns(tableId); if (path.length === 3) { const columnName = path.slice(-1)[0]; const column = tableColumns.find(cacheColumn => cacheColumn.name === columnName); if (column) { concreteColumns.push(column); } } else { concreteColumns.push(...tableColumns); } } return concreteColumns; } findCacheColumnsDependentOn(table) { const dependencyColumns = []; for (const column of this.getAllColumns()) { const isDependency = column.select.getAllColumnReferences().some(depRef => depRef.isFromTable(table)); if (isDependency || column.for.table.equal(table)) { dependencyColumns.push(column); } } return dependencyColumns; } assignAllDependencies() { const allColumns = lodash_1.flatMap(Object.values(this.tables)); for (const column of allColumns) { const dependencyColumns = this.findDependencies(column); column.assignDependencies(dependencyColumns); if (column.isRoot()) { this.rootColumns.push(column); } } this.rootColumns = lodash_1.uniqBy(this.rootColumns, (column) => column.getId()); } findDependencies(column) { const dependencyColumns = column.getColumnRefs().map((depColumnRef) => this.getColumn(depColumnRef.tableReference, depColumnRef.name)).filter(column => !!column); return lodash_1.uniqBy(dependencyColumns, (column) => column.getId()); } } exports.CacheColumnGraph = CacheColumnGraph; function buildChangesMap(columns, map = {}) { for (const column of columns) { map[column.getId()] = true; buildChangesMap(column.findNotCircularUses(), map); } return map; } //# sourceMappingURL=CacheColumnGraph.js.map