ddl-manager
Version:
store postgres procedures and triggers in files
209 lines (177 loc) • 6.11 kB
text/typescript
import { MAX_NAME_LENGTH } from "../postgres/constants";
import { TableID } from "./TableID";
import { Comment } from "./Comment";
export interface IDatabaseTriggerParams {
name: string;
table: TableID;
procedure: {
schema: string;
name: string;
args: string[];
}
before?: boolean;
after?: boolean;
insert?: boolean;
delete?: boolean;
update?: boolean;
updateOf?: string[];
when?: string;
constraint?: boolean;
deferrable?: boolean;
notDeferrable?: boolean;
statement?: boolean;
initially?: "immediate" | "deferred";
comment?: Comment;
}
export class DatabaseTrigger {
readonly name!: string;
readonly procedure!: {
schema: string;
name: string;
args: string[];
};
readonly table!: TableID;
readonly comment!: Comment;
readonly frozen?: boolean;
readonly cacheSignature?: string;
readonly before?: boolean;
readonly after?: boolean;
readonly insert?: boolean;
readonly delete?: boolean;
readonly update?: boolean;
readonly updateOf?: string[];
readonly when?: string;
readonly constraint?: boolean;
readonly deferrable?: boolean;
readonly notDeferrable?: boolean;
readonly statement?: boolean;
readonly initially?: "immediate" | "deferred";
constructor(json: IDatabaseTriggerParams) {
Object.assign(this, json);
this.name = this.name.slice(0, MAX_NAME_LENGTH);
if ( !(this.table instanceof TableID) ) {
const tableJson = this.table as {schema: string, name: string};
this.table = new TableID(
tableJson.schema,
tableJson.name
);
}
this.comment = json.comment || Comment.fromFs({
objectType: "trigger",
});
this.frozen = this.comment.frozen;
this.cacheSignature = this.comment.cacheSignature;
}
equal(otherTrigger: DatabaseTrigger) {
return (
this.name.slice(0, MAX_NAME_LENGTH) === otherTrigger.name.slice(0, MAX_NAME_LENGTH) &&
this.table.schema === otherTrigger.table.schema &&
this.table.name === otherTrigger.table.name &&
this.procedure.schema === otherTrigger.procedure.schema &&
this.procedure.name.slice(0, MAX_NAME_LENGTH) === otherTrigger.procedure.name.slice(0, MAX_NAME_LENGTH) &&
this.procedure.args.join(",") === otherTrigger.procedure.args.join(",") &&
!!this.before === !!otherTrigger.before &&
!!this.after === !!otherTrigger.after &&
!!this.insert === !!otherTrigger.insert &&
!!this.delete === !!otherTrigger.delete &&
!!this.update === !!otherTrigger.update &&
(this.updateOf || []).join(",") === (otherTrigger.updateOf || []).join(",") &&
this.comment.equal(otherTrigger.comment) &&
// null == undefined
// tslint:disable-next-line: triple-equals
this.when == otherTrigger.when &&
!!this.constraint === !!otherTrigger.constraint &&
!!this.deferrable === !!otherTrigger.deferrable &&
!!this.notDeferrable === !!otherTrigger.notDeferrable &&
!!this.statement === !!otherTrigger.statement &&
// null == undefined
// tslint:disable-next-line: triple-equals
this.initially == otherTrigger.initially
);
}
getSignature() {
return `${this.name} on ${ this.table.schema }.${ this.table.name }`;
}
clone(changes: Partial<IDatabaseTriggerParams> = {}) {
return new DatabaseTrigger({
name: this.name,
table: this.table,
procedure: this.procedure,
before: this.before,
after: this.after,
insert: this.insert,
delete: this.delete,
update: this.update,
updateOf: this.updateOf,
when: this.when,
constraint: this.constraint,
deferrable: this.deferrable,
notDeferrable: this.notDeferrable,
statement: this.statement,
initially: this.initially,
comment: this.comment,
... changes
});
}
toSQL() {
let out = "create ";
if ( this.constraint ) {
out += "constraint ";
}
out += `trigger ${this.name}\n`;
// after|before
if ( this.before ) {
out += "before";
}
else if ( this.after ) {
out += "after";
}
out += " ";
// insert or update of x or delete
const events: string[] = [];
if ( this.insert ) {
events.push("insert");
}
if ( this.update ) {
if ( this.updateOf && this.updateOf.length ) {
events.push(`update of ${ this.updateOf.join(", ") }`);
}
else if ( this.update === true ) {
events.push("update");
}
}
if ( this.delete ) {
events.push("delete");
}
out += events.join(" or ");
// table
out += "\non ";
out += `${this.table.schema}.${this.table.name}`;
if ( this.notDeferrable ) {
out += " not deferrable";
}
if ( this.deferrable ) {
out += " deferrable";
}
if ( this.initially ) {
out += " initially ";
out += this.initially;
}
if ( this.statement ) {
out += "\nfor each statement";
} else {
out += "\nfor each row";
}
if ( this.when ) {
out += "\nwhen ( ";
out += this.when;
out += " ) ";
}
out += `\nexecute procedure ${
this.procedure.schema === "public" ?
"" :
this.procedure.schema + "."
}${ this.procedure.name }()`;
return out;
}
}