viyv-db-postgres 0.1.0
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/LICENSE +21 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +15 -0
- package/dist/config.js.map +1 -0
- package/dist/db.d.ts +9 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +13 -0
- package/dist/db.js.map +1 -0
- package/dist/error-mapper.d.ts +2 -0
- package/dist/error-mapper.d.ts.map +1 -0
- package/dist/error-mapper.js +24 -0
- package/dist/error-mapper.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/logical/cte-builder.d.ts +57 -0
- package/dist/logical/cte-builder.d.ts.map +1 -0
- package/dist/logical/cte-builder.js +167 -0
- package/dist/logical/cte-builder.js.map +1 -0
- package/dist/logical/data-ops.d.ts +19 -0
- package/dist/logical/data-ops.d.ts.map +1 -0
- package/dist/logical/data-ops.js +124 -0
- package/dist/logical/data-ops.js.map +1 -0
- package/dist/logical/embedding-ops.d.ts +24 -0
- package/dist/logical/embedding-ops.d.ts.map +1 -0
- package/dist/logical/embedding-ops.js +94 -0
- package/dist/logical/embedding-ops.js.map +1 -0
- package/dist/logical/migration-ops.d.ts +10 -0
- package/dist/logical/migration-ops.d.ts.map +1 -0
- package/dist/logical/migration-ops.js +201 -0
- package/dist/logical/migration-ops.js.map +1 -0
- package/dist/logical/query-ops.d.ts +18 -0
- package/dist/logical/query-ops.d.ts.map +1 -0
- package/dist/logical/query-ops.js +193 -0
- package/dist/logical/query-ops.js.map +1 -0
- package/dist/logical/registry.d.ts +27 -0
- package/dist/logical/registry.d.ts.map +1 -0
- package/dist/logical/registry.js +79 -0
- package/dist/logical/registry.js.map +1 -0
- package/dist/logical/schema-ops.d.ts +7 -0
- package/dist/logical/schema-ops.d.ts.map +1 -0
- package/dist/logical/schema-ops.js +311 -0
- package/dist/logical/schema-ops.js.map +1 -0
- package/dist/logical/sql-parser.d.ts +11 -0
- package/dist/logical/sql-parser.d.ts.map +1 -0
- package/dist/logical/sql-parser.js +37 -0
- package/dist/logical/sql-parser.js.map +1 -0
- package/dist/logical/sql-table-refs.d.ts +18 -0
- package/dist/logical/sql-table-refs.d.ts.map +1 -0
- package/dist/logical/sql-table-refs.js +203 -0
- package/dist/logical/sql-table-refs.js.map +1 -0
- package/dist/logical/sql-tokenizer.d.ts +20 -0
- package/dist/logical/sql-tokenizer.d.ts.map +1 -0
- package/dist/logical/sql-tokenizer.js +249 -0
- package/dist/logical/sql-tokenizer.js.map +1 -0
- package/dist/logical/type-utils.d.ts +11 -0
- package/dist/logical/type-utils.d.ts.map +1 -0
- package/dist/logical/type-utils.js +42 -0
- package/dist/logical/type-utils.js.map +1 -0
- package/dist/logical/where-builder.d.ts +6 -0
- package/dist/logical/where-builder.d.ts.map +1 -0
- package/dist/logical/where-builder.js +20 -0
- package/dist/logical/where-builder.js.map +1 -0
- package/dist/schema.d.ts +926 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +78 -0
- package/dist/schema.js.map +1 -0
- package/dist/services/postgres-service.d.ts +40 -0
- package/dist/services/postgres-service.d.ts.map +1 -0
- package/dist/services/postgres-service.js +479 -0
- package/dist/services/postgres-service.js.map +1 -0
- package/dist/services/semantic-search-service.d.ts +16 -0
- package/dist/services/semantic-search-service.d.ts.map +1 -0
- package/dist/services/semantic-search-service.js +94 -0
- package/dist/services/semantic-search-service.js.map +1 -0
- package/dist/system-migrations/001_composite_pk.d.ts +4 -0
- package/dist/system-migrations/001_composite_pk.d.ts.map +1 -0
- package/dist/system-migrations/001_composite_pk.js +23 -0
- package/dist/system-migrations/001_composite_pk.js.map +1 -0
- package/dist/system-migrations/002_schema_log_index.d.ts +4 -0
- package/dist/system-migrations/002_schema_log_index.d.ts.map +1 -0
- package/dist/system-migrations/002_schema_log_index.js +13 -0
- package/dist/system-migrations/002_schema_log_index.js.map +1 -0
- package/dist/system-migrations/index.d.ts +9 -0
- package/dist/system-migrations/index.d.ts.map +1 -0
- package/dist/system-migrations/index.js +9 -0
- package/dist/system-migrations/index.js.map +1 -0
- package/dist/system-migrations/types.d.ts +18 -0
- package/dist/system-migrations/types.d.ts.map +1 -0
- package/dist/system-migrations/types.js +28 -0
- package/dist/system-migrations/types.js.map +1 -0
- package/dist/system-migrations.d.ts +25 -0
- package/dist/system-migrations.d.ts.map +1 -0
- package/dist/system-migrations.js +66 -0
- package/dist/system-migrations.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQL 内の全テーブル参照を抽出する。
|
|
3
|
+
* クォート認識: 文字列リテラル・コメント内の FROM/JOIN は無視。
|
|
4
|
+
*/
|
|
5
|
+
import { tokenizeSql } from './sql-tokenizer.js';
|
|
6
|
+
// FROM/JOIN 句を終了するキーワード(エイリアスと区別するため)
|
|
7
|
+
const CLAUSE_KEYWORDS = new Set([
|
|
8
|
+
'SELECT',
|
|
9
|
+
'WHERE',
|
|
10
|
+
'JOIN',
|
|
11
|
+
'LEFT',
|
|
12
|
+
'RIGHT',
|
|
13
|
+
'INNER',
|
|
14
|
+
'OUTER',
|
|
15
|
+
'CROSS',
|
|
16
|
+
'FULL',
|
|
17
|
+
'NATURAL',
|
|
18
|
+
'ON',
|
|
19
|
+
'ORDER',
|
|
20
|
+
'GROUP',
|
|
21
|
+
'HAVING',
|
|
22
|
+
'LIMIT',
|
|
23
|
+
'OFFSET',
|
|
24
|
+
'UNION',
|
|
25
|
+
'INTERSECT',
|
|
26
|
+
'EXCEPT',
|
|
27
|
+
'RETURNING',
|
|
28
|
+
'FOR',
|
|
29
|
+
'WINDOW',
|
|
30
|
+
'FETCH',
|
|
31
|
+
'LATERAL',
|
|
32
|
+
]);
|
|
33
|
+
/** 意味トークンのみ(whitespace/comment を除く)のインデックスを返す */
|
|
34
|
+
function semanticTokens(tokens) {
|
|
35
|
+
const indices = [];
|
|
36
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
37
|
+
if (tokens[i].type !== 'whitespace' && tokens[i].type !== 'comment') {
|
|
38
|
+
indices.push(i);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return indices;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* テーブル名の後のオプショナルなエイリアスを読み飛ばす。
|
|
45
|
+
* パターン: [AS] <alias> — AS はオプション、alias は clause keyword でない word/quoted_ident
|
|
46
|
+
*/
|
|
47
|
+
function skipAlias(tokens, semIdx, pos) {
|
|
48
|
+
if (pos >= semIdx.length)
|
|
49
|
+
return pos;
|
|
50
|
+
const t = tokens[semIdx[pos]];
|
|
51
|
+
// AS keyword → skip AS + alias
|
|
52
|
+
if (t.type === 'word' && t.value.toUpperCase() === 'AS') {
|
|
53
|
+
const afterAs = pos + 1;
|
|
54
|
+
return afterAs < semIdx.length ? afterAs + 1 : afterAs;
|
|
55
|
+
}
|
|
56
|
+
// Implicit alias: word that's not a clause keyword
|
|
57
|
+
if ((t.type === 'word' && !CLAUSE_KEYWORDS.has(t.value.toUpperCase())) ||
|
|
58
|
+
t.type === 'quoted_ident') {
|
|
59
|
+
return pos + 1;
|
|
60
|
+
}
|
|
61
|
+
return pos;
|
|
62
|
+
}
|
|
63
|
+
/** トークンから識別子名を取得(quoted_ident ならクォートを外す) */
|
|
64
|
+
function identName(token) {
|
|
65
|
+
if (token.type === 'quoted_ident') {
|
|
66
|
+
// Remove surrounding quotes and unescape ""
|
|
67
|
+
return token.value.slice(1, -1).replace(/""/g, '"');
|
|
68
|
+
}
|
|
69
|
+
return token.value;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* SQL 内の全テーブル参照を抽出する。
|
|
73
|
+
*
|
|
74
|
+
* 検出パターン:
|
|
75
|
+
* FROM <table> [, <table>, ...]
|
|
76
|
+
* [LEFT|RIGHT|INNER|OUTER|CROSS|FULL|NATURAL] JOIN <table>
|
|
77
|
+
* WITH <name> AS ( → context='with'
|
|
78
|
+
*/
|
|
79
|
+
export function extractTableRefs(sql) {
|
|
80
|
+
const tokens = tokenizeSql(sql);
|
|
81
|
+
const semIdx = semanticTokens(tokens);
|
|
82
|
+
const refs = [];
|
|
83
|
+
for (let si = 0; si < semIdx.length; si++) {
|
|
84
|
+
const token = tokens[semIdx[si]];
|
|
85
|
+
const upper = token.type === 'word' ? token.value.toUpperCase() : '';
|
|
86
|
+
// WITH <name> AS
|
|
87
|
+
if (upper === 'WITH') {
|
|
88
|
+
// Skip RECURSIVE if present
|
|
89
|
+
let nextSi = si + 1;
|
|
90
|
+
if (nextSi < semIdx.length &&
|
|
91
|
+
tokens[semIdx[nextSi]].type === 'word' &&
|
|
92
|
+
tokens[semIdx[nextSi]].value.toUpperCase() === 'RECURSIVE') {
|
|
93
|
+
nextSi++;
|
|
94
|
+
}
|
|
95
|
+
// Parse CTE definitions: name AS (...), name AS (...), ...
|
|
96
|
+
while (nextSi < semIdx.length) {
|
|
97
|
+
const nameToken = tokens[semIdx[nextSi]];
|
|
98
|
+
if (nameToken.type !== 'word' && nameToken.type !== 'quoted_ident')
|
|
99
|
+
break;
|
|
100
|
+
const afterName = nextSi + 1 < semIdx.length ? tokens[semIdx[nextSi + 1]] : null;
|
|
101
|
+
if (!afterName || afterName.type !== 'word' || afterName.value.toUpperCase() !== 'AS') {
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
refs.push({ name: identName(nameToken), context: 'with' });
|
|
105
|
+
// Skip past AS and the parenthesized body
|
|
106
|
+
const bodyStart = nextSi + 2;
|
|
107
|
+
if (bodyStart < semIdx.length &&
|
|
108
|
+
tokens[semIdx[bodyStart]].type === 'punctuation' &&
|
|
109
|
+
tokens[semIdx[bodyStart]].value === '(') {
|
|
110
|
+
// Track paren depth
|
|
111
|
+
let depth = 1;
|
|
112
|
+
let k = bodyStart + 1;
|
|
113
|
+
while (k < semIdx.length && depth > 0) {
|
|
114
|
+
const t = tokens[semIdx[k]];
|
|
115
|
+
if (t.type === 'punctuation' && t.value === '(')
|
|
116
|
+
depth++;
|
|
117
|
+
if (t.type === 'punctuation' && t.value === ')')
|
|
118
|
+
depth--;
|
|
119
|
+
k++;
|
|
120
|
+
}
|
|
121
|
+
nextSi = k;
|
|
122
|
+
// Check for comma → next CTE
|
|
123
|
+
if (nextSi < semIdx.length &&
|
|
124
|
+
tokens[semIdx[nextSi]].type === 'punctuation' &&
|
|
125
|
+
tokens[semIdx[nextSi]].value === ',') {
|
|
126
|
+
nextSi++;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
// FROM <table> [, <table>, ...]
|
|
138
|
+
if (upper === 'FROM') {
|
|
139
|
+
let nextSi = si + 1;
|
|
140
|
+
if (nextSi >= semIdx.length)
|
|
141
|
+
continue;
|
|
142
|
+
const firstToken = tokens[semIdx[nextSi]];
|
|
143
|
+
// Skip subquery: FROM (SELECT ...)
|
|
144
|
+
if (firstToken.type === 'punctuation' && firstToken.value === '(')
|
|
145
|
+
continue;
|
|
146
|
+
if (firstToken.type === 'word' || firstToken.type === 'quoted_ident') {
|
|
147
|
+
// Check if function call: FROM generate_series(...)
|
|
148
|
+
const afterFirst = nextSi + 1 < semIdx.length ? tokens[semIdx[nextSi + 1]] : null;
|
|
149
|
+
if (afterFirst && afterFirst.type === 'punctuation' && afterFirst.value === '(') {
|
|
150
|
+
// Function call — skip
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
refs.push({ name: identName(firstToken), context: 'from' });
|
|
154
|
+
}
|
|
155
|
+
nextSi++;
|
|
156
|
+
// Skip optional alias: AS alias, or just alias (word not a clause keyword)
|
|
157
|
+
nextSi = skipAlias(tokens, semIdx, nextSi);
|
|
158
|
+
// Check for comma-separated tables
|
|
159
|
+
while (nextSi < semIdx.length) {
|
|
160
|
+
const commaCheck = tokens[semIdx[nextSi]];
|
|
161
|
+
if (commaCheck.type !== 'punctuation' || commaCheck.value !== ',')
|
|
162
|
+
break;
|
|
163
|
+
nextSi++; // skip comma
|
|
164
|
+
if (nextSi >= semIdx.length)
|
|
165
|
+
break;
|
|
166
|
+
const nextTable = tokens[semIdx[nextSi]];
|
|
167
|
+
if (nextTable.type === 'word' || nextTable.type === 'quoted_ident') {
|
|
168
|
+
// Check for function call
|
|
169
|
+
const afterNext = nextSi + 1 < semIdx.length ? tokens[semIdx[nextSi + 1]] : null;
|
|
170
|
+
if (afterNext && afterNext.type === 'punctuation' && afterNext.value === '(') {
|
|
171
|
+
// Function call — skip
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
refs.push({ name: identName(nextTable), context: 'from' });
|
|
175
|
+
}
|
|
176
|
+
nextSi++;
|
|
177
|
+
// Skip optional alias after comma-separated table
|
|
178
|
+
nextSi = skipAlias(tokens, semIdx, nextSi);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
nextSi++;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
// JOIN <table> (possibly preceded by LEFT/RIGHT/INNER/OUTER/CROSS/FULL/NATURAL)
|
|
188
|
+
if (upper === 'JOIN') {
|
|
189
|
+
const nextSi = si + 1;
|
|
190
|
+
if (nextSi >= semIdx.length)
|
|
191
|
+
continue;
|
|
192
|
+
const joinTarget = tokens[semIdx[nextSi]];
|
|
193
|
+
// Skip subquery: JOIN (SELECT ...)
|
|
194
|
+
if (joinTarget.type === 'punctuation' && joinTarget.value === '(')
|
|
195
|
+
continue;
|
|
196
|
+
if (joinTarget.type === 'word' || joinTarget.type === 'quoted_ident') {
|
|
197
|
+
refs.push({ name: identName(joinTarget), context: 'join' });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return refs;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=sql-table-refs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-table-refs.js","sourceRoot":"","sources":["../../src/logical/sql-table-refs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* クォート認識 SQL トークナイザー。
|
|
3
|
+
* 文字列リテラル・コメント内のキーワードやプレースホルダを安全に無視する基盤層。
|
|
4
|
+
*/
|
|
5
|
+
export type SqlTokenType = 'word' | 'quoted_ident' | 'string' | 'number' | 'placeholder' | 'operator' | 'punctuation' | 'whitespace' | 'comment' | 'other';
|
|
6
|
+
export interface SqlToken {
|
|
7
|
+
type: SqlTokenType;
|
|
8
|
+
value: string;
|
|
9
|
+
offset: number;
|
|
10
|
+
}
|
|
11
|
+
/** クォート認識 SQL トークナイザー(状態機械、O(n) 単一パス) */
|
|
12
|
+
export declare function tokenizeSql(sql: string): SqlToken[];
|
|
13
|
+
/** $N placeholder のみ変換(文字列リテラル・コメント内は無視) */
|
|
14
|
+
export declare function offsetSqlParamsSafe(sql: string, offset: number): string;
|
|
15
|
+
/** クォート認識でプレースホルダ位置を分割(buildParameterizedSql の安全版) */
|
|
16
|
+
export declare function splitByPlaceholders(sql: string): {
|
|
17
|
+
parts: string[];
|
|
18
|
+
placeholderCount: number;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=sql-tokenizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-tokenizer.d.ts","sourceRoot":"","sources":["../../src/logical/sql-tokenizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,YAAY,GACrB,MAAM,GACN,cAAc,GACd,QAAQ,GACR,QAAQ,GACR,aAAa,GACb,UAAU,GACV,aAAa,GACb,YAAY,GACZ,SAAS,GACT,OAAO,CAAC;AAEX,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AA4BD,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAsLnD;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAavE;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG;IACjD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;CACzB,CAkBA"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* クォート認識 SQL トークナイザー。
|
|
3
|
+
* 文字列リテラル・コメント内のキーワードやプレースホルダを安全に無視する基盤層。
|
|
4
|
+
*/
|
|
5
|
+
// Character classification helpers (avoid regex in hot loop)
|
|
6
|
+
function isWhitespace(c) {
|
|
7
|
+
return c === ' ' || c === '\t' || c === '\n' || c === '\r' || c === '\f';
|
|
8
|
+
}
|
|
9
|
+
function isWordStart(c) {
|
|
10
|
+
const code = c.charCodeAt(0);
|
|
11
|
+
return ((code >= 65 && code <= 90) || // A-Z
|
|
12
|
+
(code >= 97 && code <= 122) || // a-z
|
|
13
|
+
code === 95 // _
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
function isWordChar(c) {
|
|
17
|
+
const code = c.charCodeAt(0);
|
|
18
|
+
return ((code >= 65 && code <= 90) || // A-Z
|
|
19
|
+
(code >= 97 && code <= 122) || // a-z
|
|
20
|
+
(code >= 48 && code <= 57) || // 0-9
|
|
21
|
+
code === 95 // _
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
function isDigit(c) {
|
|
25
|
+
const code = c.charCodeAt(0);
|
|
26
|
+
return code >= 48 && code <= 57;
|
|
27
|
+
}
|
|
28
|
+
/** クォート認識 SQL トークナイザー(状態機械、O(n) 単一パス) */
|
|
29
|
+
export function tokenizeSql(sql) {
|
|
30
|
+
const tokens = [];
|
|
31
|
+
const len = sql.length;
|
|
32
|
+
let i = 0;
|
|
33
|
+
while (i < len) {
|
|
34
|
+
const ch = sql[i];
|
|
35
|
+
// Single-quoted string: 'text', '' escape
|
|
36
|
+
if (ch === "'") {
|
|
37
|
+
const start = i;
|
|
38
|
+
i++; // skip opening '
|
|
39
|
+
while (i < len) {
|
|
40
|
+
if (sql[i] === "'") {
|
|
41
|
+
if (i + 1 < len && sql[i + 1] === "'") {
|
|
42
|
+
i += 2; // '' escape
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
i++; // closing '
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
i++;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
tokens.push({ type: 'string', value: sql.slice(start, i), offset: start });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
// Double-quoted identifier: "ident", "" escape
|
|
57
|
+
if (ch === '"') {
|
|
58
|
+
const start = i;
|
|
59
|
+
i++; // skip opening "
|
|
60
|
+
while (i < len) {
|
|
61
|
+
if (sql[i] === '"') {
|
|
62
|
+
if (i + 1 < len && sql[i + 1] === '"') {
|
|
63
|
+
i += 2; // "" escape
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
i++; // closing "
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
i++;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
tokens.push({ type: 'quoted_ident', value: sql.slice(start, i), offset: start });
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// $ — dollar-quote or placeholder
|
|
78
|
+
if (ch === '$') {
|
|
79
|
+
// $N placeholder: $ followed by digit(s)
|
|
80
|
+
if (i + 1 < len && isDigit(sql[i + 1])) {
|
|
81
|
+
const start = i;
|
|
82
|
+
i++; // skip $
|
|
83
|
+
while (i < len && isDigit(sql[i]))
|
|
84
|
+
i++;
|
|
85
|
+
tokens.push({ type: 'placeholder', value: sql.slice(start, i), offset: start });
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
// Dollar-quoted string: $$...$$ or $tag$...$tag$
|
|
89
|
+
const tagStart = i;
|
|
90
|
+
i++; // skip first $
|
|
91
|
+
// Read tag (may be empty for $$)
|
|
92
|
+
let tag = '';
|
|
93
|
+
if (i < len && sql[i] === '$') {
|
|
94
|
+
// empty tag: $$
|
|
95
|
+
i++; // skip second $
|
|
96
|
+
}
|
|
97
|
+
else if (i < len && isWordStart(sql[i])) {
|
|
98
|
+
const tagNameStart = i;
|
|
99
|
+
while (i < len && isWordChar(sql[i]))
|
|
100
|
+
i++;
|
|
101
|
+
if (i < len && sql[i] === '$') {
|
|
102
|
+
tag = sql.slice(tagNameStart, i);
|
|
103
|
+
i++; // skip closing $ of tag
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
// Not a valid dollar quote — emit as 'other'
|
|
107
|
+
tokens.push({ type: 'other', value: sql.slice(tagStart, i), offset: tagStart });
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Just a lone $ — emit as 'other'
|
|
113
|
+
tokens.push({ type: 'other', value: '$', offset: tagStart });
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
// Now consume until closing $tag$
|
|
117
|
+
const closer = `$${tag}$`;
|
|
118
|
+
const closerIdx = sql.indexOf(closer, i);
|
|
119
|
+
if (closerIdx === -1) {
|
|
120
|
+
// Unclosed — consume rest
|
|
121
|
+
tokens.push({ type: 'string', value: sql.slice(tagStart), offset: tagStart });
|
|
122
|
+
i = len;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
i = closerIdx + closer.length;
|
|
126
|
+
tokens.push({ type: 'string', value: sql.slice(tagStart, i), offset: tagStart });
|
|
127
|
+
}
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
// Line comment: --
|
|
131
|
+
if (ch === '-' && i + 1 < len && sql[i + 1] === '-') {
|
|
132
|
+
const start = i;
|
|
133
|
+
i += 2;
|
|
134
|
+
while (i < len && sql[i] !== '\n')
|
|
135
|
+
i++;
|
|
136
|
+
if (i < len)
|
|
137
|
+
i++; // include \n
|
|
138
|
+
tokens.push({ type: 'comment', value: sql.slice(start, i), offset: start });
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// Block comment: /* ... */
|
|
142
|
+
if (ch === '/' && i + 1 < len && sql[i + 1] === '*') {
|
|
143
|
+
const start = i;
|
|
144
|
+
i += 2;
|
|
145
|
+
while (i < len) {
|
|
146
|
+
if (sql[i] === '*' && i + 1 < len && sql[i + 1] === '/') {
|
|
147
|
+
i += 2;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
i++;
|
|
151
|
+
}
|
|
152
|
+
tokens.push({ type: 'comment', value: sql.slice(start, i), offset: start });
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
// ? placeholder
|
|
156
|
+
if (ch === '?') {
|
|
157
|
+
tokens.push({ type: 'placeholder', value: '?', offset: i });
|
|
158
|
+
i++;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
// Whitespace
|
|
162
|
+
if (isWhitespace(ch)) {
|
|
163
|
+
const start = i;
|
|
164
|
+
while (i < len && isWhitespace(sql[i]))
|
|
165
|
+
i++;
|
|
166
|
+
tokens.push({ type: 'whitespace', value: sql.slice(start, i), offset: start });
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
// Word: keyword or identifier
|
|
170
|
+
if (isWordStart(ch)) {
|
|
171
|
+
const start = i;
|
|
172
|
+
while (i < len && isWordChar(sql[i]))
|
|
173
|
+
i++;
|
|
174
|
+
tokens.push({ type: 'word', value: sql.slice(start, i), offset: start });
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
// Number
|
|
178
|
+
if (isDigit(ch)) {
|
|
179
|
+
const start = i;
|
|
180
|
+
while (i < len && (isDigit(sql[i]) || sql[i] === '.'))
|
|
181
|
+
i++;
|
|
182
|
+
tokens.push({ type: 'number', value: sql.slice(start, i), offset: start });
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
// Punctuation
|
|
186
|
+
if (ch === '(' || ch === ')' || ch === ',' || ch === ';' || ch === '*') {
|
|
187
|
+
tokens.push({ type: 'punctuation', value: ch, offset: i });
|
|
188
|
+
i++;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
// Multi-char operators
|
|
192
|
+
if ('<>=!|&+-/%^~'.includes(ch)) {
|
|
193
|
+
const start = i;
|
|
194
|
+
i++;
|
|
195
|
+
// Consume second char for two-char operators like <=, >=, <>, !=, ||, ::
|
|
196
|
+
if (i < len && '<>=!|:'.includes(sql[i]))
|
|
197
|
+
i++;
|
|
198
|
+
tokens.push({ type: 'operator', value: sql.slice(start, i), offset: start });
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
// :: cast operator
|
|
202
|
+
if (ch === ':' && i + 1 < len && sql[i + 1] === ':') {
|
|
203
|
+
tokens.push({ type: 'operator', value: '::', offset: i });
|
|
204
|
+
i += 2;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
// Other single char (includes ., :, etc.)
|
|
208
|
+
tokens.push({ type: 'other', value: ch, offset: i });
|
|
209
|
+
i++;
|
|
210
|
+
}
|
|
211
|
+
return tokens;
|
|
212
|
+
}
|
|
213
|
+
/** $N placeholder のみ変換(文字列リテラル・コメント内は無視) */
|
|
214
|
+
export function offsetSqlParamsSafe(sql, offset) {
|
|
215
|
+
if (offset === 0)
|
|
216
|
+
return sql;
|
|
217
|
+
const tokens = tokenizeSql(sql);
|
|
218
|
+
const parts = [];
|
|
219
|
+
for (const token of tokens) {
|
|
220
|
+
if (token.type === 'placeholder' && token.value.startsWith('$')) {
|
|
221
|
+
const num = Number.parseInt(token.value.slice(1), 10);
|
|
222
|
+
parts.push(`$${num + offset}`);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
parts.push(token.value);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return parts.join('');
|
|
229
|
+
}
|
|
230
|
+
/** クォート認識でプレースホルダ位置を分割(buildParameterizedSql の安全版) */
|
|
231
|
+
export function splitByPlaceholders(sql) {
|
|
232
|
+
const tokens = tokenizeSql(sql);
|
|
233
|
+
const parts = [];
|
|
234
|
+
let current = '';
|
|
235
|
+
let placeholderCount = 0;
|
|
236
|
+
for (const token of tokens) {
|
|
237
|
+
if (token.type === 'placeholder') {
|
|
238
|
+
parts.push(current);
|
|
239
|
+
current = '';
|
|
240
|
+
placeholderCount++;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
current += token.value;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
parts.push(current);
|
|
247
|
+
return { parts, placeholderCount };
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=sql-tokenizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-tokenizer.js","sourceRoot":"","sources":["../../src/logical/sql-tokenizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** JSONB 型判定・値変換ユーティリティ(純粋関数) */
|
|
2
|
+
export declare function isNumericType(type: string): boolean;
|
|
3
|
+
export declare function isBooleanType(type: string): boolean;
|
|
4
|
+
/** 論理カラム型に対応する PostgreSQL キャスト式を返す。TEXT 系はキャスト不要。 */
|
|
5
|
+
export declare function pgCastForType(type: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* 文字列値を JSONB @> 比較に適した型に変換する。
|
|
8
|
+
* 変換失敗時は元の値をそのまま返す(安全側倒し)。
|
|
9
|
+
*/
|
|
10
|
+
export declare function coerceValueForJsonb(value: unknown, columnType: string): unknown;
|
|
11
|
+
//# sourceMappingURL=type-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-utils.d.ts","sourceRoot":"","sources":["../../src/logical/type-utils.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKnD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAiB/E"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** JSONB 型判定・値変換ユーティリティ(純粋関数) */
|
|
2
|
+
export function isNumericType(type) {
|
|
3
|
+
const upper = type.toUpperCase();
|
|
4
|
+
return ['INTEGER', 'INT', 'BIGINT', 'REAL', 'FLOAT', 'NUMERIC', 'DECIMAL', 'DOUBLE'].some((t) => upper.includes(t));
|
|
5
|
+
}
|
|
6
|
+
export function isBooleanType(type) {
|
|
7
|
+
const upper = type.toUpperCase();
|
|
8
|
+
return upper === 'BOOLEAN' || upper === 'BOOL';
|
|
9
|
+
}
|
|
10
|
+
/** 論理カラム型に対応する PostgreSQL キャスト式を返す。TEXT 系はキャスト不要。 */
|
|
11
|
+
export function pgCastForType(type) {
|
|
12
|
+
if (isNumericType(type))
|
|
13
|
+
return '::numeric';
|
|
14
|
+
if (isBooleanType(type))
|
|
15
|
+
return '::boolean';
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 文字列値を JSONB @> 比較に適した型に変換する。
|
|
20
|
+
* 変換失敗時は元の値をそのまま返す(安全側倒し)。
|
|
21
|
+
*/
|
|
22
|
+
export function coerceValueForJsonb(value, columnType) {
|
|
23
|
+
if (value === null || value === undefined)
|
|
24
|
+
return value;
|
|
25
|
+
if (typeof value !== 'string')
|
|
26
|
+
return value;
|
|
27
|
+
if (isNumericType(columnType)) {
|
|
28
|
+
if (value.trim() === '')
|
|
29
|
+
return value;
|
|
30
|
+
const n = Number(value);
|
|
31
|
+
return Number.isNaN(n) || !Number.isFinite(n) ? value : n;
|
|
32
|
+
}
|
|
33
|
+
if (isBooleanType(columnType)) {
|
|
34
|
+
if (value === 'true')
|
|
35
|
+
return true;
|
|
36
|
+
if (value === 'false')
|
|
37
|
+
return false;
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=type-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-utils.js","sourceRoot":"","sources":["../../src/logical/type-utils.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,MAAM,UAAU,aAAa,CAAC,IAAY;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/F,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM,CAAC;AAChD,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,aAAa,CAAC,IAAY;IACzC,IAAI,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,WAAW,CAAC;IAC5C,IAAI,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,WAAW,CAAC;IAC5C,OAAO,EAAE,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAc,EAAE,UAAkB;IACrE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5C,IAAI,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC;QACtC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,IAAI,KAAK,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QAClC,IAAI,KAAK,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QACpC,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** WHERE {key: value} → JSONB 条件配列(NULL-safe、型変換付き) */
|
|
2
|
+
export declare function buildWhereConditions(where: Record<string, unknown>, columns?: Array<{
|
|
3
|
+
name: string;
|
|
4
|
+
type: string;
|
|
5
|
+
}>): import("drizzle-orm").SQL<unknown>[];
|
|
6
|
+
//# sourceMappingURL=where-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"where-builder.d.ts","sourceRoot":"","sources":["../../src/logical/where-builder.ts"],"names":[],"mappings":"AAKA,uDAAuD;AACvD,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,wCAe/C"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { sql } from 'drizzle-orm';
|
|
2
|
+
import { isValidIdentifier } from 'viyv-db-core';
|
|
3
|
+
import { logicalRows } from '../schema.js';
|
|
4
|
+
import { coerceValueForJsonb } from './type-utils.js';
|
|
5
|
+
/** WHERE {key: value} → JSONB 条件配列(NULL-safe、型変換付き) */
|
|
6
|
+
export function buildWhereConditions(where, columns) {
|
|
7
|
+
const typeMap = columns ? new Map(columns.map((c) => [c.name, c.type])) : null;
|
|
8
|
+
return Object.entries(where).map(([key, value]) => {
|
|
9
|
+
if (!isValidIdentifier(key)) {
|
|
10
|
+
throw new Error(`Invalid column name in WHERE: "${key}"`);
|
|
11
|
+
}
|
|
12
|
+
if (value === null) {
|
|
13
|
+
return sql.raw(`(${logicalRows.data.name}->>'${key}') IS NULL`);
|
|
14
|
+
}
|
|
15
|
+
const colType = typeMap?.get(key);
|
|
16
|
+
const coerced = colType ? coerceValueForJsonb(value, colType) : value;
|
|
17
|
+
return sql `${logicalRows.data} @> ${JSON.stringify({ [key]: coerced })}::jsonb`;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=where-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"where-builder.js","sourceRoot":"","sources":["../../src/logical/where-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,uDAAuD;AACvD,MAAM,UAAU,oBAAoB,CACnC,KAA8B,EAC9B,OAA+C;IAE/C,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE/E,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QACjD,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,GAAG,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,OAAO,GAAG,YAAY,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACtE,OAAO,GAAG,CAAA,GAAG,WAAW,CAAC,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,SAAS,CAAC;IACjF,CAAC,CAAC,CAAC;AACJ,CAAC"}
|