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,94 @@
|
|
|
1
|
+
import { sql } from 'drizzle-orm';
|
|
2
|
+
export async function initializeEmbeddingTable(db, dimensions) {
|
|
3
|
+
await db.execute(sql `CREATE EXTENSION IF NOT EXISTS vector`);
|
|
4
|
+
// vector(N) must be a literal in DDL — dimensions comes from config, not user input
|
|
5
|
+
await db.execute(sql.raw(`
|
|
6
|
+
CREATE TABLE IF NOT EXISTS _viyv_embeddings (
|
|
7
|
+
row_id UUID NOT NULL,
|
|
8
|
+
tenant_id TEXT NOT NULL,
|
|
9
|
+
table_id UUID NOT NULL REFERENCES _viyv_logical_tables(id) ON DELETE CASCADE,
|
|
10
|
+
embedding vector(${Number(dimensions)}) NOT NULL,
|
|
11
|
+
embedding_text TEXT NOT NULL DEFAULT '',
|
|
12
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
13
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
14
|
+
PRIMARY KEY (row_id, tenant_id)
|
|
15
|
+
)
|
|
16
|
+
`));
|
|
17
|
+
await db.execute(sql `
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_viyv_embeddings_hnsw
|
|
19
|
+
ON _viyv_embeddings USING hnsw (embedding vector_cosine_ops)
|
|
20
|
+
`);
|
|
21
|
+
await db.execute(sql `
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_viyv_embeddings_tenant
|
|
23
|
+
ON _viyv_embeddings (tenant_id, table_id)
|
|
24
|
+
`);
|
|
25
|
+
}
|
|
26
|
+
export async function storeEmbeddings(db, tenantId, entries) {
|
|
27
|
+
if (entries.length === 0)
|
|
28
|
+
return;
|
|
29
|
+
const batchSize = 500;
|
|
30
|
+
for (let i = 0; i < entries.length; i += batchSize) {
|
|
31
|
+
const batch = entries.slice(i, i + batchSize);
|
|
32
|
+
const values = batch.map((e) => sql `(${e.rowId}::uuid, ${tenantId}, ${e.tableId}::uuid,
|
|
33
|
+
${`[${e.embedding.join(',')}]`}::vector, ${e.embeddingText}, now())`);
|
|
34
|
+
await db.execute(sql `
|
|
35
|
+
INSERT INTO _viyv_embeddings
|
|
36
|
+
(row_id, tenant_id, table_id, embedding, embedding_text, updated_at)
|
|
37
|
+
VALUES ${sql.join(values, sql `, `)}
|
|
38
|
+
ON CONFLICT (row_id, tenant_id) DO UPDATE SET
|
|
39
|
+
embedding = EXCLUDED.embedding,
|
|
40
|
+
embedding_text = EXCLUDED.embedding_text,
|
|
41
|
+
table_id = EXCLUDED.table_id,
|
|
42
|
+
updated_at = now()
|
|
43
|
+
`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function searchSimilar(db, tenantId, queryVector, options) {
|
|
47
|
+
const vectorStr = `[${queryVector.join(',')}]`;
|
|
48
|
+
// Build query with parameterized values
|
|
49
|
+
// PostgreSQL array literal: '{uuid1,uuid2}' — drizzle doesn't auto-convert JS arrays
|
|
50
|
+
const tableIdsLiteral = options.tableIds?.length ? `{${options.tableIds.join(',')}}` : null;
|
|
51
|
+
const baseQuery = tableIdsLiteral
|
|
52
|
+
? sql `SELECT
|
|
53
|
+
e.row_id, e.table_id,
|
|
54
|
+
t.name AS table_name, t.purpose AS table_purpose,
|
|
55
|
+
r.data,
|
|
56
|
+
1 - (e.embedding <=> ${vectorStr}::vector) AS similarity
|
|
57
|
+
FROM _viyv_embeddings e
|
|
58
|
+
JOIN _viyv_logical_tables t ON e.table_id = t.id
|
|
59
|
+
JOIN _viyv_logical_rows r ON e.row_id = r.id AND e.tenant_id = r.tenant_id
|
|
60
|
+
WHERE e.tenant_id = ${tenantId}
|
|
61
|
+
AND e.table_id = ANY(${tableIdsLiteral}::uuid[])
|
|
62
|
+
AND 1 - (e.embedding <=> ${vectorStr}::vector) >= ${options.threshold}
|
|
63
|
+
ORDER BY e.embedding <=> ${vectorStr}::vector
|
|
64
|
+
LIMIT ${options.limit}`
|
|
65
|
+
: sql `SELECT
|
|
66
|
+
e.row_id, e.table_id,
|
|
67
|
+
t.name AS table_name, t.purpose AS table_purpose,
|
|
68
|
+
r.data,
|
|
69
|
+
1 - (e.embedding <=> ${vectorStr}::vector) AS similarity
|
|
70
|
+
FROM _viyv_embeddings e
|
|
71
|
+
JOIN _viyv_logical_tables t ON e.table_id = t.id
|
|
72
|
+
JOIN _viyv_logical_rows r ON e.row_id = r.id AND e.tenant_id = r.tenant_id
|
|
73
|
+
WHERE e.tenant_id = ${tenantId}
|
|
74
|
+
AND 1 - (e.embedding <=> ${vectorStr}::vector) >= ${options.threshold}
|
|
75
|
+
ORDER BY e.embedding <=> ${vectorStr}::vector
|
|
76
|
+
LIMIT ${options.limit}`;
|
|
77
|
+
const result = await db.execute(baseQuery);
|
|
78
|
+
const rows = (result.rows ?? result);
|
|
79
|
+
return rows.map((row) => ({
|
|
80
|
+
rowId: String(row.row_id),
|
|
81
|
+
tableId: String(row.table_id),
|
|
82
|
+
tableName: String(row.table_name),
|
|
83
|
+
tablePurpose: row.table_purpose != null ? String(row.table_purpose) : null,
|
|
84
|
+
data: (typeof row.data === 'string' ? JSON.parse(row.data) : row.data),
|
|
85
|
+
similarity: Number(row.similarity),
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
export async function deleteEmbeddingsByRowIds(db, tenantId, rowIds) {
|
|
89
|
+
if (rowIds.length === 0)
|
|
90
|
+
return;
|
|
91
|
+
const idsLiteral = `{${rowIds.join(',')}}`;
|
|
92
|
+
await db.execute(sql `DELETE FROM _viyv_embeddings WHERE tenant_id = ${tenantId} AND row_id = ANY(${idsLiteral}::uuid[])`);
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=embedding-ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-ops.js","sourceRoot":"","sources":["../../src/logical/embedding-ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Migration } from 'viyv-db-core';
|
|
2
|
+
import type { DrizzleDb } from '../db.js';
|
|
3
|
+
import type { LogicalTableRegistry } from './registry.js';
|
|
4
|
+
export declare function getMigrationInfo(db: DrizzleDb): Promise<Migration[]>;
|
|
5
|
+
/**
|
|
6
|
+
* Rollback migrations after the target version.
|
|
7
|
+
* Parses structured downSql JSON and reverses logical table operations.
|
|
8
|
+
*/
|
|
9
|
+
export declare function rollbackMigration(db: DrizzleDb, registry: LogicalTableRegistry, tenantId: string, targetVersion: string): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=migration-ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-ops.d.ts","sourceRoot":"","sources":["../../src/logical/migration-ops.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAQ1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAY1E;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACtC,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { and, desc, eq, sql } from 'drizzle-orm';
|
|
2
|
+
import { MigrationError } from 'viyv-db-core';
|
|
3
|
+
import { logicalColumns, logicalForeignKeys, logicalIndexes, logicalTables, migrations, } from '../schema.js';
|
|
4
|
+
export async function getMigrationInfo(db) {
|
|
5
|
+
const rows = await db.select().from(migrations).orderBy(migrations.appliedAt);
|
|
6
|
+
return rows.map((row) => ({
|
|
7
|
+
version: row.version,
|
|
8
|
+
description: row.description,
|
|
9
|
+
upSql: row.upSql,
|
|
10
|
+
downSql: row.downSql,
|
|
11
|
+
appliedAt: row.appliedAt.toISOString(),
|
|
12
|
+
appliedBy: row.appliedBy,
|
|
13
|
+
reason: row.reason,
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Rollback migrations after the target version.
|
|
18
|
+
* Parses structured downSql JSON and reverses logical table operations.
|
|
19
|
+
*/
|
|
20
|
+
export async function rollbackMigration(db, registry, tenantId, targetVersion) {
|
|
21
|
+
// Verify target exists
|
|
22
|
+
const [target] = await db.select().from(migrations).where(eq(migrations.version, targetVersion));
|
|
23
|
+
if (!target) {
|
|
24
|
+
throw new MigrationError(`Target version "${targetVersion}" not found`);
|
|
25
|
+
}
|
|
26
|
+
// Compare timestamps entirely within PostgreSQL to avoid JS Date microsecond truncation
|
|
27
|
+
const laterMigrations = await db
|
|
28
|
+
.select()
|
|
29
|
+
.from(migrations)
|
|
30
|
+
.where(sql `${migrations.appliedAt} > (SELECT applied_at FROM _viyv_migrations WHERE version = ${targetVersion})`)
|
|
31
|
+
.orderBy(desc(migrations.appliedAt));
|
|
32
|
+
if (laterMigrations.length === 0) {
|
|
33
|
+
throw new MigrationError(`No migrations found after version "${targetVersion}"`);
|
|
34
|
+
}
|
|
35
|
+
await db.transaction(async (tx) => {
|
|
36
|
+
// Execute reverse operations in reverse chronological order
|
|
37
|
+
for (const migration of laterMigrations) {
|
|
38
|
+
await executeRollbackOp(tx, tenantId, migration.downSql);
|
|
39
|
+
await tx.delete(migrations).where(eq(migrations.version, migration.version));
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
registry.invalidate();
|
|
43
|
+
}
|
|
44
|
+
async function executeRollbackOp(tx, tenantId, downSql) {
|
|
45
|
+
// Skip legacy comment-style downSql (non-JSON)
|
|
46
|
+
if (!downSql.startsWith('{'))
|
|
47
|
+
return;
|
|
48
|
+
const op = JSON.parse(downSql);
|
|
49
|
+
switch (op.op) {
|
|
50
|
+
case 'drop_table': {
|
|
51
|
+
// Reverse of CREATE TABLE: delete the logical table (CASCADE)
|
|
52
|
+
const [table] = await tx
|
|
53
|
+
.select({ id: logicalTables.id })
|
|
54
|
+
.from(logicalTables)
|
|
55
|
+
.where(and(eq(logicalTables.tenantId, tenantId), eq(logicalTables.name, op.tableName)));
|
|
56
|
+
if (table) {
|
|
57
|
+
await tx.delete(logicalTables).where(eq(logicalTables.id, table.id));
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case 'create_table': {
|
|
62
|
+
// Reverse of DROP TABLE: recreate table with columns, indexes, foreign keys
|
|
63
|
+
const [newTable] = await tx
|
|
64
|
+
.insert(logicalTables)
|
|
65
|
+
.values({
|
|
66
|
+
tenantId: op.tenantId ?? tenantId,
|
|
67
|
+
name: op.tableName,
|
|
68
|
+
purpose: op.purpose ?? null,
|
|
69
|
+
createdBy: op.createdBy ?? null,
|
|
70
|
+
})
|
|
71
|
+
.returning();
|
|
72
|
+
if (op.columns && op.columns.length > 0) {
|
|
73
|
+
await tx.insert(logicalColumns).values(op.columns.map((c) => ({
|
|
74
|
+
tableId: newTable.id,
|
|
75
|
+
name: c.name,
|
|
76
|
+
type: c.type ?? 'TEXT',
|
|
77
|
+
nullable: c.nullable ?? true,
|
|
78
|
+
defaultValue: c.defaultValue ?? null,
|
|
79
|
+
primaryKey: c.primaryKey ?? false,
|
|
80
|
+
uniqueCol: c.uniqueCol ?? false,
|
|
81
|
+
description: c.description ?? null,
|
|
82
|
+
position: c.position ?? 0,
|
|
83
|
+
})));
|
|
84
|
+
}
|
|
85
|
+
if (op.indexes && op.indexes.length > 0) {
|
|
86
|
+
await tx.insert(logicalIndexes).values(op.indexes.map((i) => ({
|
|
87
|
+
tableId: newTable.id,
|
|
88
|
+
name: i.name,
|
|
89
|
+
columns: i.columns,
|
|
90
|
+
uniqueIdx: i.uniqueIdx ?? false,
|
|
91
|
+
})));
|
|
92
|
+
}
|
|
93
|
+
if (op.foreignKeys && op.foreignKeys.length > 0) {
|
|
94
|
+
await tx.insert(logicalForeignKeys).values(op.foreignKeys.map((f) => ({
|
|
95
|
+
tableId: newTable.id,
|
|
96
|
+
columnName: f.columnName,
|
|
97
|
+
refTableName: f.refTableName,
|
|
98
|
+
refColumnName: f.refColumnName,
|
|
99
|
+
})));
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case 'drop_columns': {
|
|
104
|
+
// Reverse of ADD COLUMNS: remove specific columns
|
|
105
|
+
const [table] = await tx
|
|
106
|
+
.select({ id: logicalTables.id })
|
|
107
|
+
.from(logicalTables)
|
|
108
|
+
.where(and(eq(logicalTables.tenantId, tenantId), eq(logicalTables.name, op.tableName)));
|
|
109
|
+
if (table) {
|
|
110
|
+
for (const colName of op.columnNames) {
|
|
111
|
+
await tx
|
|
112
|
+
.delete(logicalColumns)
|
|
113
|
+
.where(and(eq(logicalColumns.tableId, table.id), eq(logicalColumns.name, colName)));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case 'add_columns': {
|
|
119
|
+
// Reverse of DROP COLUMNS: re-add columns with their original definitions
|
|
120
|
+
const [table] = await tx
|
|
121
|
+
.select({ id: logicalTables.id })
|
|
122
|
+
.from(logicalTables)
|
|
123
|
+
.where(and(eq(logicalTables.tenantId, tenantId), eq(logicalTables.name, op.tableName)));
|
|
124
|
+
if (table && op.columns && op.columns.length > 0) {
|
|
125
|
+
await tx.insert(logicalColumns).values(op.columns.map((c) => ({
|
|
126
|
+
tableId: table.id,
|
|
127
|
+
name: c.name,
|
|
128
|
+
type: c.type ?? 'TEXT',
|
|
129
|
+
nullable: c.nullable ?? true,
|
|
130
|
+
defaultValue: c.defaultValue ?? null,
|
|
131
|
+
primaryKey: c.primaryKey ?? false,
|
|
132
|
+
uniqueCol: c.uniqueCol ?? false,
|
|
133
|
+
description: c.description ?? null,
|
|
134
|
+
position: c.position ?? 0,
|
|
135
|
+
})));
|
|
136
|
+
}
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
case 'modify_columns': {
|
|
140
|
+
// Reverse of MODIFY COLUMNS: restore original column values
|
|
141
|
+
const [table] = await tx
|
|
142
|
+
.select({ id: logicalTables.id })
|
|
143
|
+
.from(logicalTables)
|
|
144
|
+
.where(and(eq(logicalTables.tenantId, tenantId), eq(logicalTables.name, op.tableName)));
|
|
145
|
+
if (table && op.original) {
|
|
146
|
+
for (const col of op.original) {
|
|
147
|
+
const updates = {};
|
|
148
|
+
if (col.name !== undefined)
|
|
149
|
+
updates.name = col.name;
|
|
150
|
+
if (col.type !== undefined)
|
|
151
|
+
updates.type = col.type;
|
|
152
|
+
if (col.nullable !== undefined)
|
|
153
|
+
updates.nullable = col.nullable;
|
|
154
|
+
if (col.defaultValue !== undefined)
|
|
155
|
+
updates.defaultValue = col.defaultValue;
|
|
156
|
+
await tx
|
|
157
|
+
.update(logicalColumns)
|
|
158
|
+
.set(updates)
|
|
159
|
+
.where(and(eq(logicalColumns.tableId, table.id), eq(logicalColumns.name, col.name)));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
case 'drop_index': {
|
|
165
|
+
// Reverse of ADD INDEX: remove the index
|
|
166
|
+
const [table] = await tx
|
|
167
|
+
.select({ id: logicalTables.id })
|
|
168
|
+
.from(logicalTables)
|
|
169
|
+
.where(and(eq(logicalTables.tenantId, tenantId), eq(logicalTables.name, op.tableName)));
|
|
170
|
+
if (table) {
|
|
171
|
+
await tx
|
|
172
|
+
.delete(logicalIndexes)
|
|
173
|
+
.where(and(eq(logicalIndexes.tableId, table.id), eq(logicalIndexes.name, op.indexName)));
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
case 'update_purpose': {
|
|
178
|
+
// Reverse: restore old purpose
|
|
179
|
+
await tx
|
|
180
|
+
.update(logicalTables)
|
|
181
|
+
.set({ purpose: op.oldPurpose ?? null, updatedAt: new Date() })
|
|
182
|
+
.where(and(eq(logicalTables.tenantId, tenantId), eq(logicalTables.name, op.tableName)));
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
case 'update_description': {
|
|
186
|
+
// Reverse: restore old description
|
|
187
|
+
const [table] = await tx
|
|
188
|
+
.select({ id: logicalTables.id })
|
|
189
|
+
.from(logicalTables)
|
|
190
|
+
.where(and(eq(logicalTables.tenantId, tenantId), eq(logicalTables.name, op.tableName)));
|
|
191
|
+
if (table) {
|
|
192
|
+
await tx
|
|
193
|
+
.update(logicalColumns)
|
|
194
|
+
.set({ description: op.oldDescription ?? null })
|
|
195
|
+
.where(and(eq(logicalColumns.tableId, table.id), eq(logicalColumns.name, op.columnName)));
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=migration-ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-ops.js","sourceRoot":"","sources":["../../src/logical/migration-ops.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EACN,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,UAAU,GACV,MAAM,cAAc,CAAC;AAGtB,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EAAa;IACnD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAE9E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACzB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE;QACtC,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;KAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACtC,EAAa,EACb,QAA8B,EAC9B,QAAgB,EAChB,aAAqB;IAErB,uBAAuB;IACvB,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;IAEjG,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,IAAI,cAAc,CAAC,mBAAmB,aAAa,aAAa,CAAC,CAAC;IACzE,CAAC;IAED,wFAAwF;IACxF,MAAM,eAAe,GAAG,MAAM,EAAE;SAC9B,MAAM,EAAE;SACR,IAAI,CAAC,UAAU,CAAC;SAChB,KAAK,CACL,GAAG,CAAA,GAAG,UAAU,CAAC,SAAS,+DAA+D,aAAa,GAAG,CACzG;SACA,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAEtC,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,cAAc,CAAC,sCAAsC,aAAa,GAAG,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACjC,4DAA4D;QAC5D,KAAK,MAAM,SAAS,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,iBAAiB,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;YACzD,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9E,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,UAAU,EAAE,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC/B,EAA0D,EAC1D,QAAgB,EAChB,OAAe;IAEf,+CAA+C;IAC/C,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO;IAErC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE/B,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QACf,KAAK,YAAY,CAAC,CAAC,CAAC;YACnB,8DAA8D;YAC9D,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,EAAE;iBACtB,MAAM,CAAC,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC;iBAChC,IAAI,CAAC,aAAa,CAAC;iBACnB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACzF,IAAI,KAAK,EAAE,CAAC;gBACX,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YACtE,CAAC;YACD,MAAM;QACP,CAAC;QAED,KAAK,cAAc,CAAC,CAAC,CAAC;YACrB,4EAA4E;YAC5E,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;iBACzB,MAAM,CAAC,aAAa,CAAC;iBACrB,MAAM,CAAC;gBACP,QAAQ,EAAE,EAAE,CAAC,QAAQ,IAAI,QAAQ;gBACjC,IAAI,EAAE,EAAE,CAAC,SAAS;gBAClB,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,IAAI;gBAC3B,SAAS,EAAE,EAAE,CAAC,SAAS,IAAI,IAAI;aAC/B,CAAC;iBACD,SAAS,EAAE,CAAC;YAEd,IAAI,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzC,MAAM,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CACrC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,CAAC;oBAC/C,OAAO,EAAE,QAAQ,CAAC,EAAE;oBACpB,IAAI,EAAE,CAAC,CAAC,IAAc;oBACtB,IAAI,EAAG,CAAC,CAAC,IAAe,IAAI,MAAM;oBAClC,QAAQ,EAAG,CAAC,CAAC,QAAoB,IAAI,IAAI;oBACzC,YAAY,EAAG,CAAC,CAAC,YAAuB,IAAI,IAAI;oBAChD,UAAU,EAAG,CAAC,CAAC,UAAsB,IAAI,KAAK;oBAC9C,SAAS,EAAG,CAAC,CAAC,SAAqB,IAAI,KAAK;oBAC5C,WAAW,EAAG,CAAC,CAAC,WAAsB,IAAI,IAAI;oBAC9C,QAAQ,EAAG,CAAC,CAAC,QAAmB,IAAI,CAAC;iBACrC,CAAC,CAAC,CACH,CAAC;YACH,CAAC;YAED,IAAI,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzC,MAAM,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CACrC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,CAAC;oBAC/C,OAAO,EAAE,QAAQ,CAAC,EAAE;oBACpB,IAAI,EAAE,CAAC,CAAC,IAAc;oBACtB,OAAO,EAAE,CAAC,CAAC,OAAmB;oBAC9B,SAAS,EAAG,CAAC,CAAC,SAAqB,IAAI,KAAK;iBAC5C,CAAC,CAAC,CACH,CAAC;YACH,CAAC;YAED,IAAI,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjD,MAAM,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,MAAM,CACzC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,CAAC;oBACnD,OAAO,EAAE,QAAQ,CAAC,EAAE;oBACpB,UAAU,EAAE,CAAC,CAAC,UAAoB;oBAClC,YAAY,EAAE,CAAC,CAAC,YAAsB;oBACtC,aAAa,EAAE,CAAC,CAAC,aAAuB;iBACxC,CAAC,CAAC,CACH,CAAC;YACH,CAAC;YACD,MAAM;QACP,CAAC;QAED,KAAK,cAAc,CAAC,CAAC,CAAC;YACrB,kDAAkD;YAClD,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,EAAE;iBACtB,MAAM,CAAC,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC;iBAChC,IAAI,CAAC,aAAa,CAAC;iBACnB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACzF,IAAI,KAAK,EAAE,CAAC;gBACX,KAAK,MAAM,OAAO,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;oBACtC,MAAM,EAAE;yBACN,MAAM,CAAC,cAAc,CAAC;yBACtB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;gBACtF,CAAC;YACF,CAAC;YACD,MAAM;QACP,CAAC;QAED,KAAK,aAAa,CAAC,CAAC,CAAC;YACpB,0EAA0E;YAC1E,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,EAAE;iBACtB,MAAM,CAAC,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC;iBAChC,IAAI,CAAC,aAAa,CAAC;iBACnB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACzF,IAAI,KAAK,IAAI,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClD,MAAM,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CACrC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,CAAC;oBAC/C,OAAO,EAAE,KAAK,CAAC,EAAE;oBACjB,IAAI,EAAE,CAAC,CAAC,IAAc;oBACtB,IAAI,EAAG,CAAC,CAAC,IAAe,IAAI,MAAM;oBAClC,QAAQ,EAAG,CAAC,CAAC,QAAoB,IAAI,IAAI;oBACzC,YAAY,EAAG,CAAC,CAAC,YAAuB,IAAI,IAAI;oBAChD,UAAU,EAAG,CAAC,CAAC,UAAsB,IAAI,KAAK;oBAC9C,SAAS,EAAG,CAAC,CAAC,SAAqB,IAAI,KAAK;oBAC5C,WAAW,EAAG,CAAC,CAAC,WAAsB,IAAI,IAAI;oBAC9C,QAAQ,EAAG,CAAC,CAAC,QAAmB,IAAI,CAAC;iBACrC,CAAC,CAAC,CACH,CAAC;YACH,CAAC;YACD,MAAM;QACP,CAAC;QAED,KAAK,gBAAgB,CAAC,CAAC,CAAC;YACvB,4DAA4D;YAC5D,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,EAAE;iBACtB,MAAM,CAAC,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC;iBAChC,IAAI,CAAC,aAAa,CAAC;iBACnB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACzF,IAAI,KAAK,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;gBAC1B,KAAK,MAAM,GAAG,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;oBAC/B,MAAM,OAAO,GAA4B,EAAE,CAAC;oBAC5C,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS;wBAAE,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;oBACpD,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS;wBAAE,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;oBACpD,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS;wBAAE,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;oBAChE,IAAI,GAAG,CAAC,YAAY,KAAK,SAAS;wBAAE,OAAO,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;oBAC5E,MAAM,EAAE;yBACN,MAAM,CAAC,cAAc,CAAC;yBACtB,GAAG,CAAC,OAAO,CAAC;yBACZ,KAAK,CACL,GAAG,CACF,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,EACpC,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,IAAc,CAAC,CAC3C,CACD,CAAC;gBACJ,CAAC;YACF,CAAC;YACD,MAAM;QACP,CAAC;QAED,KAAK,YAAY,CAAC,CAAC,CAAC;YACnB,yCAAyC;YACzC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,EAAE;iBACtB,MAAM,CAAC,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC;iBAChC,IAAI,CAAC,aAAa,CAAC;iBACnB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACzF,IAAI,KAAK,EAAE,CAAC;gBACX,MAAM,EAAE;qBACN,MAAM,CAAC,cAAc,CAAC;qBACtB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC3F,CAAC;YACD,MAAM;QACP,CAAC;QAED,KAAK,gBAAgB,CAAC,CAAC,CAAC;YACvB,+BAA+B;YAC/B,MAAM,EAAE;iBACN,MAAM,CAAC,aAAa,CAAC;iBACrB,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,UAAU,IAAI,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;iBAC9D,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACzF,MAAM;QACP,CAAC;QAED,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC3B,mCAAmC;YACnC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,EAAE;iBACtB,MAAM,CAAC,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC;iBAChC,IAAI,CAAC,aAAa,CAAC;iBACnB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACzF,IAAI,KAAK,EAAE,CAAC;gBACX,MAAM,EAAE;qBACN,MAAM,CAAC,cAAc,CAAC;qBACtB,GAAG,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;qBAC/C,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC5F,CAAC;YACD,MAAM;QACP,CAAC;IACF,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { QueryResult, QueryTableOptions } from 'viyv-db-core';
|
|
2
|
+
import type { PostgresConfig } from '../config.js';
|
|
3
|
+
import type { DrizzleDb } from '../db.js';
|
|
4
|
+
import type { LogicalTableRegistry } from './registry.js';
|
|
5
|
+
/**
|
|
6
|
+
* Execute a SELECT query with row limit enforcement.
|
|
7
|
+
* If the query references logical tables, rewrites them as CTEs.
|
|
8
|
+
*/
|
|
9
|
+
export declare function query(db: DrizzleDb, registry: LogicalTableRegistry, tenantId: string, config: PostgresConfig, sqlStr: string, params?: unknown[]): Promise<QueryResult>;
|
|
10
|
+
/**
|
|
11
|
+
* Structured query: SQL 不要で論理テーブルを検索
|
|
12
|
+
*/
|
|
13
|
+
export declare function queryTableStructured(db: DrizzleDb, registry: LogicalTableRegistry, tenantId: string, config: PostgresConfig, tableName: string, options?: QueryTableOptions): Promise<QueryResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Execute raw SQL with access level checking.
|
|
16
|
+
*/
|
|
17
|
+
export declare function executeSql(db: DrizzleDb, registry: LogicalTableRegistry, tenantId: string, config: PostgresConfig, sqlStr: string, params?: unknown[], accessLevel?: string): Promise<QueryResult>;
|
|
18
|
+
//# sourceMappingURL=query-ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-ops.d.ts","sourceRoot":"","sources":["../../src/logical/query-ops.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AASnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAuE1D;;;GAGG;AACH,wBAAsB,KAAK,CAC1B,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,OAAO,EAAE,GAChB,OAAO,CAAC,WAAW,CAAC,CA+BtB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACzC,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,iBAAsB,GAC7B,OAAO,CAAC,WAAW,CAAC,CAwEtB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC/B,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,OAAO,EAAE,EAClB,WAAW,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,CAAC,CAyCtB"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { and, eq, sql } from 'drizzle-orm';
|
|
2
|
+
import { AccessDeniedError, SqlValidationError, TableNotFoundError, classifySql, hasAccess, isValidIdentifier, } from 'viyv-db-core';
|
|
3
|
+
import { logicalRows } from '../schema.js';
|
|
4
|
+
import { composeCteQuery } from './cte-builder.js';
|
|
5
|
+
import { extractTableRefs } from './sql-table-refs.js';
|
|
6
|
+
import { splitByPlaceholders } from './sql-tokenizer.js';
|
|
7
|
+
import { isNumericType } from './type-utils.js';
|
|
8
|
+
import { buildWhereConditions } from './where-builder.js';
|
|
9
|
+
// Detect any reference to system tables in SQL
|
|
10
|
+
const SYSTEM_TABLE_RE = /\b_viyv_\w+/i;
|
|
11
|
+
/**
|
|
12
|
+
* Build a parameterized SQL template from a raw SQL string and positional params.
|
|
13
|
+
* Uses quote-aware splitting to avoid replacing $N inside string literals.
|
|
14
|
+
*/
|
|
15
|
+
function buildParameterizedSqlSafe(sqlStr, params) {
|
|
16
|
+
if (!params || params.length === 0) {
|
|
17
|
+
return sql.raw(sqlStr);
|
|
18
|
+
}
|
|
19
|
+
const { parts, placeholderCount } = splitByPlaceholders(sqlStr);
|
|
20
|
+
if (placeholderCount !== params.length) {
|
|
21
|
+
return sql.raw(sqlStr);
|
|
22
|
+
}
|
|
23
|
+
let result = sql.raw(parts[0]);
|
|
24
|
+
for (let i = 0; i < params.length; i++) {
|
|
25
|
+
result = sql `${result}${params[i]}${sql.raw(parts[i + 1])}`;
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
/** 生 SQL 実行結果 → QueryResult 変換(truncation 判定付き) */
|
|
30
|
+
function buildRawQueryResult(result, limit) {
|
|
31
|
+
const rows = (result.rows ?? []);
|
|
32
|
+
const truncated = rows.length > limit;
|
|
33
|
+
const finalRows = truncated ? rows.slice(0, limit) : rows;
|
|
34
|
+
const columns = finalRows.length > 0
|
|
35
|
+
? Object.keys(finalRows[0])
|
|
36
|
+
: (result.fields ?? []).map((f) => f.name);
|
|
37
|
+
return { columns, rows: finalRows, rowCount: finalRows.length, truncated };
|
|
38
|
+
}
|
|
39
|
+
/** SQL 内の論理テーブル参照を解決し、バインディング配列を返す */
|
|
40
|
+
async function resolveLogicalBindings(db, registry, tenantId, sqlStr) {
|
|
41
|
+
const refs = extractTableRefs(sqlStr);
|
|
42
|
+
const bindings = [];
|
|
43
|
+
const seen = new Set();
|
|
44
|
+
// ユーザー CTE 定義名を先に収集 — 同名の論理テーブルより CTE を優先する
|
|
45
|
+
const userCteNames = new Set();
|
|
46
|
+
for (const ref of refs) {
|
|
47
|
+
if (ref.context === 'with')
|
|
48
|
+
userCteNames.add(ref.name);
|
|
49
|
+
}
|
|
50
|
+
for (const ref of refs) {
|
|
51
|
+
if (ref.context === 'with' || seen.has(ref.name) || userCteNames.has(ref.name))
|
|
52
|
+
continue;
|
|
53
|
+
seen.add(ref.name);
|
|
54
|
+
const isLogical = registry.has(ref.name) || (await registry.refreshIfMissing(db, tenantId, ref.name));
|
|
55
|
+
if (isLogical) {
|
|
56
|
+
const entry = registry.getTable(ref.name);
|
|
57
|
+
if (entry)
|
|
58
|
+
bindings.push({ tableName: ref.name, entry });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return bindings;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Execute a SELECT query with row limit enforcement.
|
|
65
|
+
* If the query references logical tables, rewrites them as CTEs.
|
|
66
|
+
*/
|
|
67
|
+
export async function query(db, registry, tenantId, config, sqlStr, params) {
|
|
68
|
+
const sqlType = classifySql(sqlStr);
|
|
69
|
+
if (sqlType !== 'select') {
|
|
70
|
+
throw new SqlValidationError('query() only accepts SELECT statements. Use executeSql() for other operations.');
|
|
71
|
+
}
|
|
72
|
+
// Block access to system tables
|
|
73
|
+
if (SYSTEM_TABLE_RE.test(sqlStr)) {
|
|
74
|
+
throw new SqlValidationError('Cannot access system tables (_viyv_*)');
|
|
75
|
+
}
|
|
76
|
+
// Resolve logical table bindings
|
|
77
|
+
const bindings = await resolveLogicalBindings(db, registry, tenantId, sqlStr);
|
|
78
|
+
if (bindings.length > 0) {
|
|
79
|
+
const composition = composeCteQuery(bindings, tenantId, sqlStr, params, config.rowLimit);
|
|
80
|
+
const q = buildParameterizedSqlSafe(composition.sql, composition.params);
|
|
81
|
+
const result = await db.execute(q);
|
|
82
|
+
return buildRawQueryResult(result, config.rowLimit);
|
|
83
|
+
}
|
|
84
|
+
// Fallback: raw SQL(論理テーブルなし)
|
|
85
|
+
const limit = config.rowLimit;
|
|
86
|
+
const cleanSql = sqlStr.replace(/;\s*$/, '');
|
|
87
|
+
const wrappedSql = `SELECT * FROM (${cleanSql}) AS _q LIMIT ${limit + 1}`;
|
|
88
|
+
const q = buildParameterizedSqlSafe(wrappedSql, params);
|
|
89
|
+
const result = await db.execute(q);
|
|
90
|
+
return buildRawQueryResult(result, limit);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Structured query: SQL 不要で論理テーブルを検索
|
|
94
|
+
*/
|
|
95
|
+
export async function queryTableStructured(db, registry, tenantId, config, tableName, options = {}) {
|
|
96
|
+
const entry = registry.getTable(tableName);
|
|
97
|
+
if (!entry)
|
|
98
|
+
throw new TableNotFoundError(tableName);
|
|
99
|
+
const limit = options.limit ?? config.rowLimit;
|
|
100
|
+
// 1. Build WHERE: tenant_id + table_id scope + user conditions
|
|
101
|
+
const whereConditions = options.where && Object.keys(options.where).length > 0
|
|
102
|
+
? buildWhereConditions(options.where, entry.columns)
|
|
103
|
+
: [];
|
|
104
|
+
// 2. Build query
|
|
105
|
+
let q = db
|
|
106
|
+
.select({ data: logicalRows.data, createdAt: logicalRows.createdAt })
|
|
107
|
+
.from(logicalRows)
|
|
108
|
+
.where(and(eq(logicalRows.tenantId, tenantId), eq(logicalRows.tableId, entry.id), ...whereConditions))
|
|
109
|
+
.$dynamic();
|
|
110
|
+
// 3. ORDER BY
|
|
111
|
+
if (options.orderBy && options.orderBy.length > 0) {
|
|
112
|
+
const orderExprs = [];
|
|
113
|
+
for (const ob of options.orderBy) {
|
|
114
|
+
if (!isValidIdentifier(ob.column))
|
|
115
|
+
continue;
|
|
116
|
+
const col = entry.columns.find((c) => c.name === ob.column);
|
|
117
|
+
const cast = col && isNumericType(col.type) ? '::numeric' : '';
|
|
118
|
+
const dir = ob.direction === 'desc' ? 'DESC' : 'ASC';
|
|
119
|
+
orderExprs.push(sql.raw(`(data->>'${ob.column}')${cast} ${dir}`));
|
|
120
|
+
}
|
|
121
|
+
if (orderExprs.length > 0) {
|
|
122
|
+
q = q.orderBy(...orderExprs);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
q = q.orderBy(logicalRows.createdAt);
|
|
127
|
+
}
|
|
128
|
+
// 4. LIMIT / OFFSET
|
|
129
|
+
q = q.limit(limit + 1);
|
|
130
|
+
if (options.offset !== undefined) {
|
|
131
|
+
q = q.offset(options.offset);
|
|
132
|
+
}
|
|
133
|
+
const rows = await q;
|
|
134
|
+
// 5. Result mapping
|
|
135
|
+
const truncated = rows.length > limit;
|
|
136
|
+
const finalRows = truncated ? rows.slice(0, limit) : rows;
|
|
137
|
+
const allColumns = [...entry.columns].sort((a, b) => a.position - b.position).map((c) => c.name);
|
|
138
|
+
const selectedColumns = options.columns ?? allColumns;
|
|
139
|
+
const resultRows = finalRows.map((row) => {
|
|
140
|
+
const data = row.data;
|
|
141
|
+
const result = {};
|
|
142
|
+
for (const col of selectedColumns) {
|
|
143
|
+
result[col] = data[col] ?? null;
|
|
144
|
+
}
|
|
145
|
+
return result;
|
|
146
|
+
});
|
|
147
|
+
return {
|
|
148
|
+
columns: selectedColumns,
|
|
149
|
+
rows: resultRows,
|
|
150
|
+
rowCount: resultRows.length,
|
|
151
|
+
truncated,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Execute raw SQL with access level checking.
|
|
156
|
+
*/
|
|
157
|
+
export async function executeSql(db, registry, tenantId, config, sqlStr, params, accessLevel) {
|
|
158
|
+
const currentAccess = accessLevel ?? config.accessLevel;
|
|
159
|
+
const sqlType = classifySql(sqlStr);
|
|
160
|
+
// Block access to system tables
|
|
161
|
+
if (SYSTEM_TABLE_RE.test(sqlStr)) {
|
|
162
|
+
throw new SqlValidationError('Cannot access system tables (_viyv_*)');
|
|
163
|
+
}
|
|
164
|
+
if (sqlType === 'dml' && !hasAccess(currentAccess, 'data')) {
|
|
165
|
+
throw new AccessDeniedError(sqlType, 'data', currentAccess);
|
|
166
|
+
}
|
|
167
|
+
if (sqlType === 'ddl' && !hasAccess(currentAccess, 'schema')) {
|
|
168
|
+
throw new AccessDeniedError(sqlType, 'schema', currentAccess);
|
|
169
|
+
}
|
|
170
|
+
// If it's a SELECT referencing logical tables, use CTE rewrite
|
|
171
|
+
if (sqlType === 'select') {
|
|
172
|
+
const bindings = await resolveLogicalBindings(db, registry, tenantId, sqlStr);
|
|
173
|
+
if (bindings.length > 0) {
|
|
174
|
+
const composition = composeCteQuery(bindings, tenantId, sqlStr, params, config.rowLimit);
|
|
175
|
+
const q = buildParameterizedSqlSafe(composition.sql, composition.params);
|
|
176
|
+
const result = await db.execute(q);
|
|
177
|
+
return buildRawQueryResult(result, config.rowLimit);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const q = buildParameterizedSqlSafe(sqlStr, params);
|
|
181
|
+
const result = await db.execute(q);
|
|
182
|
+
const rows = (result.rows ?? []);
|
|
183
|
+
const columns = rows.length > 0
|
|
184
|
+
? Object.keys(rows[0])
|
|
185
|
+
: (result.fields ?? []).map((f) => f.name);
|
|
186
|
+
return {
|
|
187
|
+
columns,
|
|
188
|
+
rows,
|
|
189
|
+
rowCount: rows.length,
|
|
190
|
+
truncated: false,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=query-ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-ops.js","sourceRoot":"","sources":["../../src/logical/query-ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { DrizzleDb } from '../db.js';
|
|
2
|
+
export interface TableCacheEntry {
|
|
3
|
+
id: string;
|
|
4
|
+
columns: Array<{
|
|
5
|
+
name: string;
|
|
6
|
+
type: string;
|
|
7
|
+
nullable: boolean;
|
|
8
|
+
primaryKey: boolean;
|
|
9
|
+
uniqueCol: boolean;
|
|
10
|
+
defaultValue: string | null;
|
|
11
|
+
description: string | null;
|
|
12
|
+
position: number;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
export declare class LogicalTableRegistry {
|
|
16
|
+
private cache;
|
|
17
|
+
private lastRefreshedAt;
|
|
18
|
+
private static readonly REFRESH_COOLDOWN_MS;
|
|
19
|
+
refreshIfMissing(db: DrizzleDb, tenantId: string, name: string): Promise<boolean>;
|
|
20
|
+
ensureLoaded(db: DrizzleDb, tenantId: string): Promise<void>;
|
|
21
|
+
getTableId(name: string): string | null;
|
|
22
|
+
getTable(name: string): TableCacheEntry | null;
|
|
23
|
+
has(name: string): boolean;
|
|
24
|
+
listTables(): Map<string, TableCacheEntry>;
|
|
25
|
+
invalidate(): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/logical/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,OAAO,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC;QACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,QAAQ,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACH;AAED,qBAAa,oBAAoB;IAChC,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAE9C,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjF,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmDlE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIvC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAI9C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;IAI1C,UAAU,IAAI,IAAI;CAGlB"}
|