Use classes for QueryFragment in sql

This commit is contained in:
Fedor Indutny 2024-11-06 11:27:54 -08:00 committed by GitHub
parent e4046d3bd0
commit 1653a2b546
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,5 +1,6 @@
// Copyright 2021 Signal Messenger, LLC // Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
/* eslint-disable max-classes-per-file */
import { isNumber, last } from 'lodash'; import { isNumber, last } from 'lodash';
import type { ReadableDB, WritableDB } from './Interface'; import type { ReadableDB, WritableDB } from './Interface';
@ -44,10 +45,12 @@ export type QueryTemplateParam =
| undefined; | undefined;
export type QueryFragmentValue = QueryFragment | QueryTemplateParam; export type QueryFragmentValue = QueryFragment | QueryTemplateParam;
export type QueryFragment = [ export class QueryFragment {
{ fragment: string }, constructor(
ReadonlyArray<QueryTemplateParam>, public readonly fragment: string,
]; public readonly fragmentParams: ReadonlyArray<QueryTemplateParam>
) {}
}
/** /**
* You can use tagged template literals to build "fragments" of SQL queries * You can use tagged template literals to build "fragments" of SQL queries
@ -79,8 +82,8 @@ export function sqlFragment(
query += string; query += string;
if (index < values.length) { if (index < values.length) {
if (Array.isArray(value)) { if (value instanceof QueryFragment) {
const [{ fragment }, fragmentParams] = value; const { fragment, fragmentParams } = value;
query += fragment; query += fragment;
params.push(...fragmentParams); params.push(...fragmentParams);
} else { } else {
@ -90,7 +93,7 @@ export function sqlFragment(
} }
}); });
return [{ fragment: query }, params]; return new QueryFragment(query, params);
} }
export function sqlConstant(value: QueryTemplateParam): QueryFragment { export function sqlConstant(value: QueryTemplateParam): QueryFragment {
@ -104,7 +107,7 @@ export function sqlConstant(value: QueryTemplateParam): QueryFragment {
} else { } else {
fragment = `'${value}'`; fragment = `'${value}'`;
} }
return [{ fragment }, []]; return new QueryFragment(fragment, []);
} }
/** /**
@ -118,7 +121,7 @@ export function sqlJoin(
const params: Array<QueryTemplateParam> = []; const params: Array<QueryTemplateParam> = [];
items.forEach((item, index) => { items.forEach((item, index) => {
const [{ fragment }, fragmentParams] = sqlFragment`${item}`; const { fragment, fragmentParams } = sqlFragment`${item}`;
query += fragment; query += fragment;
params.push(...fragmentParams); params.push(...fragmentParams);
@ -127,7 +130,7 @@ export function sqlJoin(
} }
}); });
return [{ fragment: query }, params]; return new QueryFragment(query, params);
} }
export type QueryTemplate = [string, ReadonlyArray<QueryTemplateParam>]; export type QueryTemplate = [string, ReadonlyArray<QueryTemplateParam>];
@ -155,8 +158,8 @@ export function sql(
strings: TemplateStringsArray, strings: TemplateStringsArray,
...values: Array<QueryFragment | QueryTemplateParam> ...values: Array<QueryFragment | QueryTemplateParam>
): QueryTemplate { ): QueryTemplate {
const [{ fragment }, params] = sqlFragment(strings, ...values); const { fragment, fragmentParams } = sqlFragment(strings, ...values);
return [fragment, params]; return [fragment, fragmentParams];
} }
type QueryPlanRow = Readonly<{ type QueryPlanRow = Readonly<{