Line data Source code
1 : /// A value of a placeholder in a SQL template
2 : export type SqlTemplateValue = string | number;
3 :
4 : /// A placeholder `:name`, but not the second colon of a cast `::type`
5 1 : const PLACEHOLDER = /(?<![:\w]):([A-Za-z_]\w*)/g;
6 :
7 : /// A value as a SQL literal
8 1 : export function sqlLiteral(value: SqlTemplateValue | null): string {
9 1 : if (value == null) return 'null';
10 1 : if (typeof value === 'number') {
11 1 : if (!Number.isFinite(value)) return 'null';
12 1 : return String(value);
13 1 : }
14 1 : return `'${value.replace(/'/g, "''")}'`;
15 1 : }
16 :
17 : /// Replace the placeholders `:name` of a SQL template with the literals of their values.
18 : /// The templates are the SQL files of the demos, their string literals and comments contain no placeholders.
19 1 : export function bindSqlTemplate(template: string, values: Readonly<Record<string, SqlTemplateValue>>): string {
20 1 : return template.replace(PLACEHOLDER, (_match, name: string) => {
21 1 : if (!(name in values)) throw new Error(`missing value of the SQL placeholder :${name}`);
22 1 : return sqlLiteral(values[name]);
23 1 : });
24 1 : }
|