ddl-manager
Version:
store postgres procedures and triggers in files
167 lines • 7.48 kB
JavaScript
;
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