49 lines
2.1 KiB
TypeScript
49 lines
2.1 KiB
TypeScript
export type MysqlEventSchedule = { mode: "at"; executeAt: string } | { mode: "every"; intervalValue: string; intervalUnit: string };
|
|
|
|
export type MysqlEventDraft = {
|
|
name: string;
|
|
schema?: string;
|
|
schedule: MysqlEventSchedule;
|
|
starts?: string;
|
|
ends?: string;
|
|
preserve?: boolean;
|
|
enabled?: boolean;
|
|
comment?: string;
|
|
body: string;
|
|
};
|
|
|
|
function ident(value: string): string {
|
|
const trimmed = value.trim();
|
|
if (!trimmed) throw new Error("Event name is required");
|
|
return `\`${trimmed.replaceAll("`", "``")}\``;
|
|
}
|
|
function literal(value: string): string {
|
|
return `'${value.replaceAll("\\", "\\\\").replaceAll("'", "\\'")}'`;
|
|
}
|
|
const units = new Set(["SECOND", "MINUTE", "HOUR", "DAY", "WEEK", "MONTH", "QUARTER", "YEAR"]);
|
|
|
|
export function buildMysqlEventSql(draft: MysqlEventDraft, operation: "CREATE" | "ALTER" = "ALTER"): string {
|
|
const name = ident(draft.name);
|
|
if (!draft.body.trim()) throw new Error("Event body is required");
|
|
let schedule: string;
|
|
if (draft.schedule.mode === "at") {
|
|
if (!draft.schedule.executeAt.trim()) throw new Error("AT schedule requires an execution time");
|
|
schedule = `AT ${literal(draft.schedule.executeAt)}`;
|
|
} else {
|
|
const unit = draft.schedule.intervalUnit.trim().toUpperCase();
|
|
const intervalValue = draft.schedule.intervalValue.trim();
|
|
if (!/^\d+$/.test(intervalValue) || /^0+$/.test(intervalValue)) {
|
|
throw new Error("EVERY schedule requires a positive integer interval value");
|
|
}
|
|
if (!units.has(unit)) throw new Error(`Invalid interval unit: ${draft.schedule.intervalUnit}`);
|
|
schedule = `EVERY ${intervalValue} ${unit}`;
|
|
}
|
|
let sql = `${operation} EVENT ${name} ON SCHEDULE ${schedule}`;
|
|
if (draft.starts?.trim()) sql += ` STARTS ${literal(draft.starts)}`;
|
|
if (draft.ends?.trim()) sql += ` ENDS ${literal(draft.ends)}`;
|
|
if (draft.preserve !== undefined) sql += draft.preserve ? " ON COMPLETION PRESERVE" : " ON COMPLETION NOT PRESERVE";
|
|
if (draft.enabled !== undefined) sql += draft.enabled ? " ENABLE" : " DISABLE";
|
|
if (draft.comment !== undefined) sql += ` COMMENT ${literal(draft.comment)}`;
|
|
return `${sql} DO ${draft.body.trim()}`;
|
|
}
|