pgsql-template-tag 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/core.d.ts +75 -0
- package/dist/src/core.d.ts.map +1 -1
- package/dist/src/core.js +114 -42
- package/dist/src/sql.d.ts +40 -1
- package/dist/src/sql.d.ts.map +1 -1
- package/dist/src/sql.js +31 -1
- package/package.json +1 -1
- package/src/core.ts +156 -67
- package/src/sql.ts +45 -1
package/dist/src/core.d.ts
CHANGED
|
@@ -1,18 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQL クエリー内で使用される値の型定義です。
|
|
3
|
+
*/
|
|
1
4
|
export type Value = unknown;
|
|
5
|
+
/**
|
|
6
|
+
* SQL クエリーの構築に使用できる生の値、または別の Sql インスタンスを表す型です。
|
|
7
|
+
*/
|
|
2
8
|
export type RawValue = Value | Sql;
|
|
9
|
+
/**
|
|
10
|
+
* 安全な SQL クエリーを構築するためのクラスです。
|
|
11
|
+
* プレースホルダーを使用したパラメーター化クエリーを生成します。
|
|
12
|
+
*/
|
|
3
13
|
export declare class Sql {
|
|
14
|
+
/**
|
|
15
|
+
* 構築された SQL クエリーテキストを取得します。
|
|
16
|
+
*
|
|
17
|
+
* 初回アクセス時に文字列が結合され、結果はキャッシュされます。
|
|
18
|
+
*
|
|
19
|
+
* @returns SQL クエリーテキストを返します。
|
|
20
|
+
*/
|
|
4
21
|
get text(): string;
|
|
22
|
+
/**
|
|
23
|
+
* クエリーに使用されるパラメーター値の配列です。
|
|
24
|
+
*/
|
|
5
25
|
readonly values: readonly Value[];
|
|
26
|
+
/**
|
|
27
|
+
* 内部状態を保持するためのプロパティーです。
|
|
28
|
+
*/
|
|
6
29
|
private readonly _;
|
|
30
|
+
/**
|
|
31
|
+
* 新しい Sql インスタンスを初期化します。
|
|
32
|
+
*
|
|
33
|
+
* @param rawStrings SQL の断片となる文字列の配列です。
|
|
34
|
+
* @param rawBindings 文字列の間に挿入される値の配列です。
|
|
35
|
+
*/
|
|
7
36
|
constructor(rawStrings: readonly string[], rawBindings: readonly RawValue[]);
|
|
37
|
+
/**
|
|
38
|
+
* オブジェクトを JSON 形式に変換可能な形式で返します。
|
|
39
|
+
*
|
|
40
|
+
* @returns クエリーテキストと値の配列を含むオブジェクトを返します。
|
|
41
|
+
*/
|
|
8
42
|
toJSON(): {
|
|
9
43
|
text: string;
|
|
10
44
|
values: Value[];
|
|
11
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* インスタンスを文字列に変換します。
|
|
48
|
+
*
|
|
49
|
+
* @returns 構築された SQL クエリーテキストを返します。
|
|
50
|
+
*/
|
|
12
51
|
toString(): string;
|
|
13
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* 生の文字列を SQL 断片として扱います。
|
|
55
|
+
* この値はパラメーター化の対象にならず、そのままクエリーに含まれます。
|
|
56
|
+
*
|
|
57
|
+
* @param value SQL に含める生の文字列です。
|
|
58
|
+
* @returns 指定された文字列を持つ Sql インスタンスを返します。
|
|
59
|
+
*/
|
|
14
60
|
export declare function raw(value: string): Sql;
|
|
61
|
+
/**
|
|
62
|
+
* 空の SQL インスタンスを表す定数です。
|
|
63
|
+
*/
|
|
15
64
|
export declare const empty: Sql;
|
|
65
|
+
/**
|
|
66
|
+
* 複数の SQL 断片や値を、指定されたセパレーターで結合します。
|
|
67
|
+
*
|
|
68
|
+
* 配列が空の場合は、{@link empty} を返します。
|
|
69
|
+
*
|
|
70
|
+
* @param values 結合対象となる値の配列です。
|
|
71
|
+
* @param separator 結合時に挿入される文字列です。デフォルトはカンマ(,)です。
|
|
72
|
+
* @returns 結合された新しい Sql インスタンスを返します。
|
|
73
|
+
*/
|
|
16
74
|
export declare function join(values: readonly RawValue[], separator?: string | undefined): Sql;
|
|
75
|
+
/**
|
|
76
|
+
* 文字列を SQL の識別子(テーブル名やカラム名など)として安全にエスケープします。
|
|
77
|
+
*
|
|
78
|
+
* 二重引用符を二重にすることでエスケープを行い、全体を二重引用符で囲みます。
|
|
79
|
+
*
|
|
80
|
+
* @param value エスケープする識別子の文字列です。
|
|
81
|
+
* @returns エスケープ済みの識別子文字列を返します。
|
|
82
|
+
*/
|
|
17
83
|
export declare function ident(value: string): string;
|
|
84
|
+
/**
|
|
85
|
+
* 文字列を SQL のリテラル文字列として安全にエスケープします。
|
|
86
|
+
*
|
|
87
|
+
* 一重引用符を二重にすることでエスケープを行い、全体を一重引用符で囲みます。
|
|
88
|
+
*
|
|
89
|
+
* @param value エスケープする文字列です。
|
|
90
|
+
* @returns エスケープ済みのリテラル文字列を返します。
|
|
91
|
+
*/
|
|
92
|
+
export declare function literal(value: string): string;
|
|
18
93
|
//# sourceMappingURL=core.d.ts.map
|
package/dist/src/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,CAAC;AAE5B;;GAEG;AAEH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,GAAG,CAAC;AAsBnC;;;GAGG;AACH,qBAAa,GAAG;IACd;;;;;;OAMG;IACH,IAAW,IAAI,IAAI,MAAM,CAexB;IAED;;OAEG;IACH,SAAgB,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAEzC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAgB;IAElC;;;;;OAKG;gBACgB,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,WAAW,EAAE,SAAS,QAAQ,EAAE;IAsElF;;;;OAIG;IACI,MAAM,IAAI;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,KAAK,EAAE,CAAC;KACjB;IAOD;;;;OAIG;IACI,QAAQ,IAAI,MAAM;CAG1B;AAED;;;;;;GAMG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAEtC;AAED;;GAEG;AACH,eAAO,MAAM,KAAK,EAAE,GAAa,CAAC;AAElC;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,EAAE,SAAS,GAAE,MAAM,GAAG,SAAe,GAAG,GAAG,CAM1F;AAOD;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3C;AAOD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C"}
|
package/dist/src/core.js
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 安全な SQL クエリーを構築するためのクラスです。
|
|
3
|
+
* プレースホルダーを使用したパラメーター化クエリーを生成します。
|
|
4
|
+
*/
|
|
1
5
|
export class Sql {
|
|
6
|
+
/**
|
|
7
|
+
* 構築された SQL クエリーテキストを取得します。
|
|
8
|
+
*
|
|
9
|
+
* 初回アクセス時に文字列が結合され、結果はキャッシュされます。
|
|
10
|
+
*
|
|
11
|
+
* @returns SQL クエリーテキストを返します。
|
|
12
|
+
*/
|
|
2
13
|
get text() {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
14
|
+
// キャッシュが存在しない場合にのみ、文字列を構築します。
|
|
15
|
+
if (this._.t === undefined) {
|
|
16
|
+
let i = 0, text = this._.s[0];
|
|
17
|
+
// 文字列の断片とプレースホルダー($1, $2...)を交互に結合します。
|
|
18
|
+
for (; i < this._.p.length; i++) {
|
|
19
|
+
text += "$" + this._.p[i] + this._.s[i + 1];
|
|
9
20
|
}
|
|
10
|
-
this._.t =
|
|
11
|
-
c: true,
|
|
12
|
-
v: text,
|
|
13
|
-
};
|
|
21
|
+
this._.t = text;
|
|
14
22
|
}
|
|
15
|
-
return this._.t
|
|
23
|
+
return this._.t;
|
|
16
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* 新しい Sql インスタンスを初期化します。
|
|
27
|
+
*
|
|
28
|
+
* @param rawStrings SQL の断片となる文字列の配列です。
|
|
29
|
+
* @param rawBindings 文字列の間に挿入される値の配列です。
|
|
30
|
+
*/
|
|
17
31
|
constructor(rawStrings, rawBindings) {
|
|
18
32
|
if (rawStrings.length === 0) {
|
|
19
33
|
throw new TypeError("Expected at least 1 string");
|
|
@@ -24,70 +38,128 @@ export class Sql {
|
|
|
24
38
|
const strings = [rawStrings[0]];
|
|
25
39
|
const bindings = [];
|
|
26
40
|
const placeholderIds = [];
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
strings.push(child._.s[j + 1]);
|
|
43
|
-
placeholderIds.push(placeholderId);
|
|
44
|
-
}
|
|
45
|
-
strings[strings.length - 1] += rawString;
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
placeholderId = valueToId.get(child);
|
|
41
|
+
/** 値の重複を排除し、同じ値には同じプレースホルダー ID を割り当てるためのマップです。 */
|
|
42
|
+
const valueToId = new Map();
|
|
43
|
+
// 提供された全てのバインディング値を走査して、SQL 文字列と値を正規化します。
|
|
44
|
+
for (let i = 0; i < rawBindings.length; i++) {
|
|
45
|
+
const child = rawBindings[i];
|
|
46
|
+
const rawString = rawStrings[i + 1];
|
|
47
|
+
// バインディング値が Sql インスタンス(ネストされたクエリー)の場合の処理です。
|
|
48
|
+
if (child instanceof Sql) {
|
|
49
|
+
// 現在の最後の文字列断片に、ネストされた Sql の最初の断片を結合します。
|
|
50
|
+
strings[strings.length - 1] += child._.s[0];
|
|
51
|
+
// ネストされた Sql のプレースホルダーと値を再マッピングします。
|
|
52
|
+
for (let j = 0; j < child._.p.length; j++) {
|
|
53
|
+
const childPlaceholderId = child._.p[j];
|
|
54
|
+
const value = child.values[childPlaceholderId - 1];
|
|
55
|
+
let placeholderId = valueToId.get(value);
|
|
49
56
|
if (placeholderId === undefined) {
|
|
50
|
-
bindings.push(
|
|
57
|
+
bindings.push(value);
|
|
51
58
|
placeholderId = bindings.length;
|
|
52
|
-
valueToId.set(
|
|
59
|
+
valueToId.set(value, placeholderId);
|
|
53
60
|
}
|
|
54
|
-
strings.push(
|
|
61
|
+
strings.push(child._.s[j + 1]);
|
|
55
62
|
placeholderIds.push(placeholderId);
|
|
56
63
|
}
|
|
64
|
+
// ネストされた Sql の展開が終わった後に、後続の生の文字列を結合します。
|
|
65
|
+
strings[strings.length - 1] += rawString;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
let placeholderId = valueToId.get(child);
|
|
69
|
+
if (placeholderId === undefined) {
|
|
70
|
+
bindings.push(child);
|
|
71
|
+
placeholderId = bindings.length;
|
|
72
|
+
valueToId.set(child, placeholderId);
|
|
73
|
+
}
|
|
74
|
+
strings.push(rawString);
|
|
75
|
+
placeholderIds.push(placeholderId);
|
|
57
76
|
}
|
|
58
77
|
}
|
|
59
78
|
this.values = bindings;
|
|
79
|
+
// 内部状態を隠蔽し、不必要なプロパティーの露出を防ぎます。
|
|
60
80
|
Object.defineProperty(this, "_", {
|
|
61
|
-
value:
|
|
62
|
-
t: {
|
|
63
|
-
c: false,
|
|
64
|
-
v: placeholderIds,
|
|
65
|
-
},
|
|
81
|
+
value: {
|
|
66
82
|
s: strings,
|
|
67
|
-
|
|
83
|
+
p: placeholderIds,
|
|
84
|
+
},
|
|
68
85
|
});
|
|
69
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* オブジェクトを JSON 形式に変換可能な形式で返します。
|
|
89
|
+
*
|
|
90
|
+
* @returns クエリーテキストと値の配列を含むオブジェクトを返します。
|
|
91
|
+
*/
|
|
70
92
|
toJSON() {
|
|
71
93
|
return {
|
|
72
94
|
text: this.text,
|
|
73
95
|
values: this.values.slice(),
|
|
74
96
|
};
|
|
75
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* インスタンスを文字列に変換します。
|
|
100
|
+
*
|
|
101
|
+
* @returns 構築された SQL クエリーテキストを返します。
|
|
102
|
+
*/
|
|
76
103
|
toString() {
|
|
77
104
|
return this.text;
|
|
78
105
|
}
|
|
79
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* 生の文字列を SQL 断片として扱います。
|
|
109
|
+
* この値はパラメーター化の対象にならず、そのままクエリーに含まれます。
|
|
110
|
+
*
|
|
111
|
+
* @param value SQL に含める生の文字列です。
|
|
112
|
+
* @returns 指定された文字列を持つ Sql インスタンスを返します。
|
|
113
|
+
*/
|
|
80
114
|
export function raw(value) {
|
|
81
115
|
return new Sql([value], []);
|
|
82
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* 空の SQL インスタンスを表す定数です。
|
|
119
|
+
*/
|
|
83
120
|
export const empty = raw("");
|
|
121
|
+
/**
|
|
122
|
+
* 複数の SQL 断片や値を、指定されたセパレーターで結合します。
|
|
123
|
+
*
|
|
124
|
+
* 配列が空の場合は、{@link empty} を返します。
|
|
125
|
+
*
|
|
126
|
+
* @param values 結合対象となる値の配列です。
|
|
127
|
+
* @param separator 結合時に挿入される文字列です。デフォルトはカンマ(,)です。
|
|
128
|
+
* @returns 結合された新しい Sql インスタンスを返します。
|
|
129
|
+
*/
|
|
84
130
|
export function join(values, separator = ",") {
|
|
85
131
|
if (values.length === 0) {
|
|
86
132
|
return empty;
|
|
87
133
|
}
|
|
88
134
|
return new Sql(["", ...Array(values.length - 1).fill(separator), ""], values);
|
|
89
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* 二重引用符をエスケープするための正規表現です。
|
|
138
|
+
*/
|
|
90
139
|
const DOUBLE_QUOTE_REGEX = /"/g;
|
|
140
|
+
/**
|
|
141
|
+
* 文字列を SQL の識別子(テーブル名やカラム名など)として安全にエスケープします。
|
|
142
|
+
*
|
|
143
|
+
* 二重引用符を二重にすることでエスケープを行い、全体を二重引用符で囲みます。
|
|
144
|
+
*
|
|
145
|
+
* @param value エスケープする識別子の文字列です。
|
|
146
|
+
* @returns エスケープ済みの識別子文字列を返します。
|
|
147
|
+
*/
|
|
91
148
|
export function ident(value) {
|
|
92
149
|
return '"' + value.replace(DOUBLE_QUOTE_REGEX, '""') + '"';
|
|
93
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* 一重引用符をエスケープするための正規表現です。
|
|
153
|
+
*/
|
|
154
|
+
const SINGLE_QUOTE_REGEX = /'/g;
|
|
155
|
+
/**
|
|
156
|
+
* 文字列を SQL のリテラル文字列として安全にエスケープします。
|
|
157
|
+
*
|
|
158
|
+
* 一重引用符を二重にすることでエスケープを行い、全体を一重引用符で囲みます。
|
|
159
|
+
*
|
|
160
|
+
* @param value エスケープする文字列です。
|
|
161
|
+
* @returns エスケープ済みのリテラル文字列を返します。
|
|
162
|
+
*/
|
|
163
|
+
export function literal(value) {
|
|
164
|
+
return "'" + value.replace(SINGLE_QUOTE_REGEX, "''") + "'";
|
|
165
|
+
}
|
package/dist/src/sql.d.ts
CHANGED
|
@@ -1,15 +1,54 @@
|
|
|
1
|
-
import { join, raw, Sql, ident } from "./core.js";
|
|
1
|
+
import { join, raw, Sql, ident, literal } from "./core.js";
|
|
2
2
|
declare namespace sql {
|
|
3
|
+
/**
|
|
4
|
+
* SQL クエリーの構築に使用できる生の値、または別の Sql インスタンスを表す型です。
|
|
5
|
+
*/
|
|
3
6
|
type RawValue = import("./core.js").RawValue;
|
|
7
|
+
/**
|
|
8
|
+
* SQL クエリー内で使用される値の型定義です。
|
|
9
|
+
*/
|
|
4
10
|
type Value = import("./core.js").Value;
|
|
11
|
+
/**
|
|
12
|
+
* 安全な SQL クエリーを構築するためのクラス型です。
|
|
13
|
+
*/
|
|
5
14
|
type Sql = import("./core.js").Sql;
|
|
6
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* テンプレートリテラルを使用して SQL クエリーを安全に構築するためのタグ関数です。
|
|
18
|
+
*
|
|
19
|
+
* @param strings テンプレートリテラルの静的な文字列部分の配列です。
|
|
20
|
+
* @param bindings テンプレートリテラルに埋め込まれた動的な値の配列です。
|
|
21
|
+
* @returns パラメーター化された SQL 情報を保持する Sql インスタンスを返します。
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const query = sql`SELECT * FROM users WHERE id = ${1}`;
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
7
27
|
declare const sql: ((strings: TemplateStringsArray, ...bindings: readonly sql.RawValue[]) => sql.Sql) & {
|
|
28
|
+
/**
|
|
29
|
+
* Sql クラス自体への参照です。
|
|
30
|
+
*/
|
|
8
31
|
readonly Sql: typeof Sql;
|
|
32
|
+
/**
|
|
33
|
+
* 生の文字列を SQL 断片として扱うための関数です。
|
|
34
|
+
*/
|
|
9
35
|
readonly raw: typeof raw;
|
|
36
|
+
/**
|
|
37
|
+
* 複数の SQL 断片を結合するための関数です。
|
|
38
|
+
*/
|
|
10
39
|
readonly join: typeof join;
|
|
40
|
+
/**
|
|
41
|
+
* 空の SQL クエリーを表す定数です。
|
|
42
|
+
*/
|
|
11
43
|
readonly empty: Sql;
|
|
44
|
+
/**
|
|
45
|
+
* 識別子(テーブル名等)を安全にエスケープするための関数です。
|
|
46
|
+
*/
|
|
12
47
|
readonly ident: typeof ident;
|
|
48
|
+
/**
|
|
49
|
+
* 文字列を安全にエスケープするための関数です。
|
|
50
|
+
*/
|
|
51
|
+
readonly literal: typeof literal;
|
|
13
52
|
};
|
|
14
53
|
export { sql };
|
|
15
54
|
//# sourceMappingURL=sql.d.ts.map
|
package/dist/src/sql.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../../src/sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../../src/sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAElE,kBAAU,GAAG,CAAC;IACZ;;OAEG;IACH,KAAY,QAAQ,GAAG,OAAO,WAAW,EAAE,QAAQ,CAAC;IAEpD;;OAEG;IACH,KAAY,KAAK,GAAG,OAAO,WAAW,EAAE,KAAK,CAAC;IAE9C;;OAEG;IACH,KAAY,GAAG,GAAG,OAAO,WAAW,EAAE,GAAG,CAAC;CAC3C;AAED;;;;;;;;;;GAUG;AACH,QAAA,MAAM,GAAG,aACe,oBAAoB,eAAe,SAAS,GAAG,CAAC,QAAQ,EAAE,KAAG,GAAG,CAAC,GAAG;IAIxF;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAGN,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
package/dist/src/sql.js
CHANGED
|
@@ -1,11 +1,41 @@
|
|
|
1
|
-
import { empty, join, raw, Sql, ident } from "./core.js";
|
|
1
|
+
import { empty, join, raw, Sql, ident, literal } from "./core.js";
|
|
2
|
+
/**
|
|
3
|
+
* テンプレートリテラルを使用して SQL クエリーを安全に構築するためのタグ関数です。
|
|
4
|
+
*
|
|
5
|
+
* @param strings テンプレートリテラルの静的な文字列部分の配列です。
|
|
6
|
+
* @param bindings テンプレートリテラルに埋め込まれた動的な値の配列です。
|
|
7
|
+
* @returns パラメーター化された SQL 情報を保持する Sql インスタンスを返します。
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const query = sql`SELECT * FROM users WHERE id = ${1}`;
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
2
13
|
const sql = /*#__PURE__*/ Object.assign(function sql(strings, ...bindings) {
|
|
3
14
|
return new Sql(strings, bindings);
|
|
4
15
|
}, {
|
|
16
|
+
/**
|
|
17
|
+
* Sql クラス自体への参照です。
|
|
18
|
+
*/
|
|
5
19
|
Sql,
|
|
20
|
+
/**
|
|
21
|
+
* 生の文字列を SQL 断片として扱うための関数です。
|
|
22
|
+
*/
|
|
6
23
|
raw,
|
|
24
|
+
/**
|
|
25
|
+
* 複数の SQL 断片を結合するための関数です。
|
|
26
|
+
*/
|
|
7
27
|
join,
|
|
28
|
+
/**
|
|
29
|
+
* 空の SQL クエリーを表す定数です。
|
|
30
|
+
*/
|
|
8
31
|
empty,
|
|
32
|
+
/**
|
|
33
|
+
* 識別子(テーブル名等)を安全にエスケープするための関数です。
|
|
34
|
+
*/
|
|
9
35
|
ident,
|
|
36
|
+
/**
|
|
37
|
+
* 文字列を安全にエスケープするための関数です。
|
|
38
|
+
*/
|
|
39
|
+
literal,
|
|
10
40
|
});
|
|
11
41
|
export { sql };
|
package/package.json
CHANGED
package/src/core.ts
CHANGED
|
@@ -1,43 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQL クエリー内で使用される値の型定義です。
|
|
3
|
+
*/
|
|
1
4
|
export type Value = unknown;
|
|
2
5
|
|
|
6
|
+
/**
|
|
7
|
+
* SQL クエリーの構築に使用できる生の値、または別の Sql インスタンスを表す型です。
|
|
8
|
+
*/
|
|
3
9
|
// oxlint-disable-next-line typescript/no-redundant-type-constituents
|
|
4
10
|
export type RawValue = Value | Sql;
|
|
5
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Sql クラスの内部状態を管理するためのプライベートな型定義です。
|
|
14
|
+
*/
|
|
15
|
+
type PrivateState = {
|
|
16
|
+
/**
|
|
17
|
+
* クエリーを構成する静的な文字列の配列です。
|
|
18
|
+
*/
|
|
19
|
+
readonly s: readonly [string, ...string[]];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* プレースホルダーに対応するインデックス(1 から始まる数値)の配列です。
|
|
23
|
+
*/
|
|
24
|
+
readonly p: readonly number[];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* キャッシュされた最終的なクエリーテキストです。
|
|
28
|
+
*/
|
|
29
|
+
t?: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 安全な SQL クエリーを構築するためのクラスです。
|
|
34
|
+
* プレースホルダーを使用したパラメーター化クエリーを生成します。
|
|
35
|
+
*/
|
|
6
36
|
export class Sql {
|
|
37
|
+
/**
|
|
38
|
+
* 構築された SQL クエリーテキストを取得します。
|
|
39
|
+
*
|
|
40
|
+
* 初回アクセス時に文字列が結合され、結果はキャッシュされます。
|
|
41
|
+
*
|
|
42
|
+
* @returns SQL クエリーテキストを返します。
|
|
43
|
+
*/
|
|
7
44
|
public get text(): string {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
45
|
+
// キャッシュが存在しない場合にのみ、文字列を構築します。
|
|
46
|
+
if (this._.t === undefined) {
|
|
47
|
+
let i = 0,
|
|
48
|
+
text = this._.s[0];
|
|
49
|
+
|
|
50
|
+
// 文字列の断片とプレースホルダー($1, $2...)を交互に結合します。
|
|
51
|
+
for (; i < this._.p.length; i++) {
|
|
52
|
+
text += "$" + this._.p[i] + this._.s[i + 1];
|
|
15
53
|
}
|
|
16
54
|
|
|
17
|
-
this._.t =
|
|
18
|
-
c: true,
|
|
19
|
-
v: text,
|
|
20
|
-
};
|
|
55
|
+
this._.t = text;
|
|
21
56
|
}
|
|
22
57
|
|
|
23
|
-
return this._.t
|
|
58
|
+
return this._.t;
|
|
24
59
|
}
|
|
25
60
|
|
|
61
|
+
/**
|
|
62
|
+
* クエリーに使用されるパラメーター値の配列です。
|
|
63
|
+
*/
|
|
26
64
|
public readonly values: readonly Value[];
|
|
27
65
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
};
|
|
40
|
-
|
|
66
|
+
/**
|
|
67
|
+
* 内部状態を保持するためのプロパティーです。
|
|
68
|
+
*/
|
|
69
|
+
private readonly _!: PrivateState;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 新しい Sql インスタンスを初期化します。
|
|
73
|
+
*
|
|
74
|
+
* @param rawStrings SQL の断片となる文字列の配列です。
|
|
75
|
+
* @param rawBindings 文字列の間に挿入される値の配列です。
|
|
76
|
+
*/
|
|
41
77
|
public constructor(rawStrings: readonly string[], rawBindings: readonly RawValue[]) {
|
|
42
78
|
if (rawStrings.length === 0) {
|
|
43
79
|
throw new TypeError("Expected at least 1 string");
|
|
@@ -53,65 +89,66 @@ export class Sql {
|
|
|
53
89
|
const bindings: Value[] = [];
|
|
54
90
|
const placeholderIds: number[] = [];
|
|
55
91
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
child = rawBindings[i];
|
|
69
|
-
rawString = rawStrings[i + 1]!;
|
|
70
|
-
|
|
71
|
-
if (child instanceof Sql) {
|
|
72
|
-
strings[strings.length - 1] += child._.s[0];
|
|
73
|
-
|
|
74
|
-
for (let j = 0, value: unknown; j < child.values.length; j++) {
|
|
75
|
-
value = child.values[j];
|
|
76
|
-
placeholderId = valueToId.get(value);
|
|
77
|
-
if (placeholderId === undefined) {
|
|
78
|
-
bindings.push(value);
|
|
79
|
-
placeholderId = bindings.length;
|
|
80
|
-
valueToId.set(value, placeholderId);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
strings.push(child._.s[j + 1]!);
|
|
84
|
-
placeholderIds.push(placeholderId);
|
|
85
|
-
}
|
|
92
|
+
/** 値の重複を排除し、同じ値には同じプレースホルダー ID を割り当てるためのマップです。 */
|
|
93
|
+
const valueToId = new Map<Value, number>();
|
|
94
|
+
|
|
95
|
+
// 提供された全てのバインディング値を走査して、SQL 文字列と値を正規化します。
|
|
96
|
+
for (let i = 0; i < rawBindings.length; i++) {
|
|
97
|
+
const child = rawBindings[i];
|
|
98
|
+
const rawString = rawStrings[i + 1]!;
|
|
99
|
+
|
|
100
|
+
// バインディング値が Sql インスタンス(ネストされたクエリー)の場合の処理です。
|
|
101
|
+
if (child instanceof Sql) {
|
|
102
|
+
// 現在の最後の文字列断片に、ネストされた Sql の最初の断片を結合します。
|
|
103
|
+
strings[strings.length - 1] += child._.s[0];
|
|
86
104
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
105
|
+
// ネストされた Sql のプレースホルダーと値を再マッピングします。
|
|
106
|
+
for (let j = 0; j < child._.p.length; j++) {
|
|
107
|
+
const childPlaceholderId = child._.p[j]!;
|
|
108
|
+
const value = child.values[childPlaceholderId - 1]!;
|
|
90
109
|
|
|
110
|
+
let placeholderId = valueToId.get(value);
|
|
91
111
|
if (placeholderId === undefined) {
|
|
92
|
-
bindings.push(
|
|
112
|
+
bindings.push(value);
|
|
93
113
|
placeholderId = bindings.length;
|
|
94
|
-
valueToId.set(
|
|
114
|
+
valueToId.set(value, placeholderId);
|
|
95
115
|
}
|
|
96
116
|
|
|
97
|
-
strings.push(
|
|
117
|
+
strings.push(child._.s[j + 1]!);
|
|
98
118
|
placeholderIds.push(placeholderId);
|
|
99
119
|
}
|
|
120
|
+
|
|
121
|
+
// ネストされた Sql の展開が終わった後に、後続の生の文字列を結合します。
|
|
122
|
+
strings[strings.length - 1] += rawString;
|
|
123
|
+
} else {
|
|
124
|
+
let placeholderId = valueToId.get(child);
|
|
125
|
+
if (placeholderId === undefined) {
|
|
126
|
+
bindings.push(child);
|
|
127
|
+
placeholderId = bindings.length;
|
|
128
|
+
valueToId.set(child, placeholderId);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
strings.push(rawString);
|
|
132
|
+
placeholderIds.push(placeholderId);
|
|
100
133
|
}
|
|
101
134
|
}
|
|
102
135
|
|
|
103
136
|
this.values = bindings;
|
|
137
|
+
|
|
138
|
+
// 内部状態を隠蔽し、不必要なプロパティーの露出を防ぎます。
|
|
104
139
|
Object.defineProperty(this, "_", {
|
|
105
|
-
value:
|
|
106
|
-
t: {
|
|
107
|
-
c: false,
|
|
108
|
-
v: placeholderIds,
|
|
109
|
-
},
|
|
140
|
+
value: {
|
|
110
141
|
s: strings,
|
|
111
|
-
|
|
142
|
+
p: placeholderIds,
|
|
143
|
+
},
|
|
112
144
|
});
|
|
113
145
|
}
|
|
114
146
|
|
|
147
|
+
/**
|
|
148
|
+
* オブジェクトを JSON 形式に変換可能な形式で返します。
|
|
149
|
+
*
|
|
150
|
+
* @returns クエリーテキストと値の配列を含むオブジェクトを返します。
|
|
151
|
+
*/
|
|
115
152
|
public toJSON(): {
|
|
116
153
|
text: string;
|
|
117
154
|
values: Value[];
|
|
@@ -122,17 +159,41 @@ export class Sql {
|
|
|
122
159
|
};
|
|
123
160
|
}
|
|
124
161
|
|
|
162
|
+
/**
|
|
163
|
+
* インスタンスを文字列に変換します。
|
|
164
|
+
*
|
|
165
|
+
* @returns 構築された SQL クエリーテキストを返します。
|
|
166
|
+
*/
|
|
125
167
|
public toString(): string {
|
|
126
168
|
return this.text;
|
|
127
169
|
}
|
|
128
170
|
}
|
|
129
171
|
|
|
172
|
+
/**
|
|
173
|
+
* 生の文字列を SQL 断片として扱います。
|
|
174
|
+
* この値はパラメーター化の対象にならず、そのままクエリーに含まれます。
|
|
175
|
+
*
|
|
176
|
+
* @param value SQL に含める生の文字列です。
|
|
177
|
+
* @returns 指定された文字列を持つ Sql インスタンスを返します。
|
|
178
|
+
*/
|
|
130
179
|
export function raw(value: string): Sql {
|
|
131
180
|
return new Sql([value], []);
|
|
132
181
|
}
|
|
133
182
|
|
|
183
|
+
/**
|
|
184
|
+
* 空の SQL インスタンスを表す定数です。
|
|
185
|
+
*/
|
|
134
186
|
export const empty: Sql = raw("");
|
|
135
187
|
|
|
188
|
+
/**
|
|
189
|
+
* 複数の SQL 断片や値を、指定されたセパレーターで結合します。
|
|
190
|
+
*
|
|
191
|
+
* 配列が空の場合は、{@link empty} を返します。
|
|
192
|
+
*
|
|
193
|
+
* @param values 結合対象となる値の配列です。
|
|
194
|
+
* @param separator 結合時に挿入される文字列です。デフォルトはカンマ(,)です。
|
|
195
|
+
* @returns 結合された新しい Sql インスタンスを返します。
|
|
196
|
+
*/
|
|
136
197
|
export function join(values: readonly RawValue[], separator: string | undefined = ","): Sql {
|
|
137
198
|
if (values.length === 0) {
|
|
138
199
|
return empty;
|
|
@@ -141,8 +202,36 @@ export function join(values: readonly RawValue[], separator: string | undefined
|
|
|
141
202
|
return new Sql(["", ...Array(values.length - 1).fill(separator), ""], values);
|
|
142
203
|
}
|
|
143
204
|
|
|
205
|
+
/**
|
|
206
|
+
* 二重引用符をエスケープするための正規表現です。
|
|
207
|
+
*/
|
|
144
208
|
const DOUBLE_QUOTE_REGEX = /"/g;
|
|
145
209
|
|
|
210
|
+
/**
|
|
211
|
+
* 文字列を SQL の識別子(テーブル名やカラム名など)として安全にエスケープします。
|
|
212
|
+
*
|
|
213
|
+
* 二重引用符を二重にすることでエスケープを行い、全体を二重引用符で囲みます。
|
|
214
|
+
*
|
|
215
|
+
* @param value エスケープする識別子の文字列です。
|
|
216
|
+
* @returns エスケープ済みの識別子文字列を返します。
|
|
217
|
+
*/
|
|
146
218
|
export function ident(value: string): string {
|
|
147
219
|
return '"' + value.replace(DOUBLE_QUOTE_REGEX, '""') + '"';
|
|
148
220
|
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* 一重引用符をエスケープするための正規表現です。
|
|
224
|
+
*/
|
|
225
|
+
const SINGLE_QUOTE_REGEX = /'/g;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* 文字列を SQL のリテラル文字列として安全にエスケープします。
|
|
229
|
+
*
|
|
230
|
+
* 一重引用符を二重にすることでエスケープを行い、全体を一重引用符で囲みます。
|
|
231
|
+
*
|
|
232
|
+
* @param value エスケープする文字列です。
|
|
233
|
+
* @returns エスケープ済みのリテラル文字列を返します。
|
|
234
|
+
*/
|
|
235
|
+
export function literal(value: string): string {
|
|
236
|
+
return "'" + value.replace(SINGLE_QUOTE_REGEX, "''") + "'";
|
|
237
|
+
}
|
package/src/sql.ts
CHANGED
|
@@ -1,23 +1,67 @@
|
|
|
1
|
-
import { empty, join, raw, Sql, ident } from "./core.js";
|
|
1
|
+
import { empty, join, raw, Sql, ident, literal } from "./core.js";
|
|
2
2
|
|
|
3
3
|
namespace sql {
|
|
4
|
+
/**
|
|
5
|
+
* SQL クエリーの構築に使用できる生の値、または別の Sql インスタンスを表す型です。
|
|
6
|
+
*/
|
|
4
7
|
export type RawValue = import("./core.js").RawValue;
|
|
5
8
|
|
|
9
|
+
/**
|
|
10
|
+
* SQL クエリー内で使用される値の型定義です。
|
|
11
|
+
*/
|
|
6
12
|
export type Value = import("./core.js").Value;
|
|
7
13
|
|
|
14
|
+
/**
|
|
15
|
+
* 安全な SQL クエリーを構築するためのクラス型です。
|
|
16
|
+
*/
|
|
8
17
|
export type Sql = import("./core.js").Sql;
|
|
9
18
|
}
|
|
10
19
|
|
|
20
|
+
/**
|
|
21
|
+
* テンプレートリテラルを使用して SQL クエリーを安全に構築するためのタグ関数です。
|
|
22
|
+
*
|
|
23
|
+
* @param strings テンプレートリテラルの静的な文字列部分の配列です。
|
|
24
|
+
* @param bindings テンプレートリテラルに埋め込まれた動的な値の配列です。
|
|
25
|
+
* @returns パラメーター化された SQL 情報を保持する Sql インスタンスを返します。
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const query = sql`SELECT * FROM users WHERE id = ${1}`;
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
11
31
|
const sql = /*#__PURE__*/ Object.assign(
|
|
12
32
|
function sql(strings: TemplateStringsArray, ...bindings: readonly sql.RawValue[]): sql.Sql {
|
|
13
33
|
return new Sql(strings, bindings);
|
|
14
34
|
},
|
|
15
35
|
{
|
|
36
|
+
/**
|
|
37
|
+
* Sql クラス自体への参照です。
|
|
38
|
+
*/
|
|
16
39
|
Sql,
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 生の文字列を SQL 断片として扱うための関数です。
|
|
43
|
+
*/
|
|
17
44
|
raw,
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 複数の SQL 断片を結合するための関数です。
|
|
48
|
+
*/
|
|
18
49
|
join,
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 空の SQL クエリーを表す定数です。
|
|
53
|
+
*/
|
|
19
54
|
empty,
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 識別子(テーブル名等)を安全にエスケープするための関数です。
|
|
58
|
+
*/
|
|
20
59
|
ident,
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 文字列を安全にエスケープするための関数です。
|
|
63
|
+
*/
|
|
64
|
+
literal,
|
|
21
65
|
} as const,
|
|
22
66
|
);
|
|
23
67
|
|