UNPKG

ddl-manager

Version:

store postgres procedures and triggers in files

165 lines (142 loc) 5.39 kB
import { Update, SetItem, Expression, SimpleSelect, Spaces } from "../../../ast"; import { Exists } from "../../../ast/expression/Exists"; import { Comment } from "../../../database/schema/Comment"; import { DatabaseFunction } from "../../../database/schema/DatabaseFunction"; import { DatabaseTrigger } from "../../../database/schema/DatabaseTrigger"; import { AbstractLastRowTriggerBuilder } from "./AbstractLastRowTriggerBuilder"; import { buildOneLastRowByIdBody } from "../body/buildOneLastRowByIdBody"; import { shortName } from "../CacheContext"; export class LastRowByIdTriggerBuilder extends AbstractLastRowTriggerBuilder { createTriggers() { return [{ trigger: this.createDatabaseTriggerOnDIU(), procedure: this.createDatabaseFunction( this.createBody() ) }, ...this.createHelperTriggers()]; } protected createHelperTriggers() { const orderBy = this.context.cache.select.orderBy!.items[0]!; if ( orderBy.type === "asc" ) { return []; } const isLastColumnName = this.getIsLastColumnName(); const helperTriggerName = [ "cache", this.context.cache.name, "for", shortName(this.context.cache.for.table.name), "before", "insert", shortName(this.context.triggerTable.name) ].join("_"); const trigger = new DatabaseTrigger({ name: helperTriggerName, before: true, insert: true, procedure: { schema: "public", name: helperTriggerName, args: [] }, table: this.context.triggerTable, comment: Comment.fromFs({ objectType: "trigger", cacheSignature: this.context.cache.getSignature() }) }); return [{ trigger, procedure: new DatabaseFunction({ schema: "public", name: helperTriggerName, body: ` begin new.${isLastColumnName} = coalesce(( ${this.conditions .hasReferenceWithoutJoins("new")! .toSQL( Spaces.level(2) )} ), false); return new; end; `.trim(), comment: Comment.fromFs({ objectType: "function", cacheSignature: this.context.cache.getSignature() }), args: [], returns: {type: "trigger"} }) }]; } protected createBody() { const isLastColumnName = this.getIsLastColumnName(); const triggerTable = this.triggerTableAlias(); const clearLastColumnOnInsert = new Update({ table: this.fromTable().toString(), set: [new SetItem({ column: isLastColumnName, value: Expression.unknown("false") })], where: this.filterTriggerTable("new", [ `${triggerTable}.id < new.id`, `${triggerTable}.${isLastColumnName} = true` ]) }); const orderBy = this.context.cache.select.orderBy!.items[0]!; const selectMaxPrevId = new SimpleSelect({ columns: [ `${ orderBy.type == "desc" ? "max" : "min" }( ${ triggerTable }.id )` ], from: this.context.cache.select.getFromTable(), where: this.filterTriggerTable("new", [ `${triggerTable}.id <> new.id` ]) }); const existsPrevRow = new Exists({ select: this.context.cache.select.clone({ columns: [], where: this.filterTriggerTable("new", [ `${triggerTable}.id < new.id` ]), orderBy: undefined, limit: undefined }) }); const body = buildOneLastRowByIdBody({ orderVector: orderBy.type, isLastColumn: isLastColumnName, ifNeedUpdateNewOnChangeReference: Expression.or([ `prev_id ${orderBy.type === "desc" ? "<" : ">"} new.id`, "prev_id is null" ]), updateNew: this.updateNew(), updatePrev: this.updatePrev(), exitFromDeltaUpdateIf: this.conditions.exitFromDeltaUpdateIf(), selectMaxPrevId, selectPrevRow: this.selectPrevRowByOrder(), existsPrevRow, updateMaxRowLastColumnFalse: this.updateMaxRowLastColumnFalse("prev_id"), updateThisRowLastColumnTrue: this.updateThisRowLastColumn("true"), clearLastColumnOnInsert, updatePrevRowLastColumnTrue: this.updatePrevRowLastColumnTrue(), hasNewReference: this.conditions .hasReferenceWithoutJoins("new")!, hasOldReference: this.conditions .hasReferenceWithoutJoins("old")!, hasOldReferenceAndIsLast: Expression.and([ this.conditions.hasReferenceWithoutJoins("old")!, `old.${isLastColumnName}` ]), noChanges: this.conditions.noChanges(), noReferenceChanges: this.conditions.noReferenceChanges() }); return body; } }