Compare commits
2 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
c080b15078 | |
|
|
ec085ddfd1 |
|
|
@ -336,19 +336,16 @@ class PostgreSQLStore extends CascadeStore_1.CascadeStore {
|
|||
await this.connector.disconnect();
|
||||
}
|
||||
async initialize(option) {
|
||||
// PG的DDL支持事务,所以这里直接用一个事务包裹所有的初始化操作
|
||||
const txn = await this.connector.startTransaction({
|
||||
isolationLevel: 'serializable',
|
||||
});
|
||||
try {
|
||||
const schema = this.getSchema();
|
||||
// ===== 第一阶段:事务外创建扩展 =====
|
||||
let hasGeoType = false;
|
||||
let hasChineseTsConfig = false;
|
||||
let chineseParser = null;
|
||||
// 扫描 schema
|
||||
for (const entity in schema) {
|
||||
const { attributes, indexes } = schema[entity];
|
||||
for (const attr in attributes) {
|
||||
const { type } = attributes[attr];
|
||||
if (type === 'geometry') {
|
||||
if (attributes[attr].type === 'geometry') {
|
||||
hasGeoType = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -356,12 +353,27 @@ class PostgreSQLStore extends CascadeStore_1.CascadeStore {
|
|||
if (index.config?.tsConfig === 'chinese' || index.config?.tsConfig?.includes('chinese')) {
|
||||
hasChineseTsConfig = true;
|
||||
}
|
||||
if (index.config?.chineseParser) {
|
||||
(0, assert_1.default)(!chineseParser || chineseParser === index.config.chineseParser, '当前定义了多个中文分词器,请保持一致');
|
||||
chineseParser = index.config.chineseParser;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 在事务外创建扩展
|
||||
if (hasGeoType) {
|
||||
console.log('Initializing PostGIS extension for geometry support...');
|
||||
await this.connector.exec('CREATE EXTENSION IF NOT EXISTS postgis;');
|
||||
}
|
||||
if (hasChineseTsConfig) {
|
||||
console.log('Initializing Chinese parser extension...');
|
||||
await this.connector.exec(`CREATE EXTENSION IF NOT EXISTS ${chineseParser || 'zhparser'};`);
|
||||
}
|
||||
// ===== 第二阶段:事务内创建配置和表 =====
|
||||
const txn = await this.connector.startTransaction({
|
||||
isolationLevel: 'serializable',
|
||||
});
|
||||
try {
|
||||
// 创建中文文本搜索配置
|
||||
if (hasChineseTsConfig) {
|
||||
console.log('Initializing Chinese text search configuration...');
|
||||
const checkChineseConfigSql = `
|
||||
|
|
@ -369,17 +381,17 @@ class PostgreSQLStore extends CascadeStore_1.CascadeStore {
|
|||
FROM pg_catalog.pg_ts_config
|
||||
WHERE cfgname = 'chinese';
|
||||
`;
|
||||
const result = await this.connector.exec(checkChineseConfigSql);
|
||||
const result = await this.connector.exec(checkChineseConfigSql, txn);
|
||||
const count = parseInt(result[0][0]?.cnt || '0', 10);
|
||||
if (count === 0) {
|
||||
const createChineseConfigSql = `
|
||||
CREATE EXTENSION IF NOT EXISTS zhparser;
|
||||
CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = zhparser);
|
||||
CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = ${chineseParser || 'zhparser'});
|
||||
ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l WITH simple;
|
||||
`;
|
||||
await this.connector.exec(createChineseConfigSql);
|
||||
await this.connector.exec(createChineseConfigSql, txn);
|
||||
}
|
||||
}
|
||||
// 创建实体表
|
||||
for (const entity in schema) {
|
||||
const sqls = this.translator.translateCreateEntity(entity, option);
|
||||
for (const sql of sqls) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export type Plan = {
|
|||
updatedIndexes: Record<string, Index<any>[]>;
|
||||
};
|
||||
export interface DbStore<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends AsyncRowStore<ED, Cxt> {
|
||||
checkRelationAsync<T extends keyof ED, Cxt extends AsyncContext<ED>>(entity: T, operation: Omit<ED[T]['Operation'] | ED[T]['Selection'], 'id'>, context: Cxt): Promise<void>;
|
||||
connect: () => Promise<void>;
|
||||
disconnect: () => Promise<void>;
|
||||
initialize(options: CreateEntityOption): Promise<void>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "oak-db",
|
||||
"version": "3.3.13",
|
||||
"version": "3.3.14",
|
||||
"description": "oak-db",
|
||||
"main": "lib/index",
|
||||
"author": {
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
"lodash": "^4.17.21",
|
||||
"mysql": "^2.18.1",
|
||||
"mysql2": "^2.3.3",
|
||||
"oak-domain": "^5.1.34",
|
||||
"oak-domain": "file:../oak-domain",
|
||||
"pg": "^8.16.3",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -452,22 +452,18 @@ export class PostgreSQLStore<
|
|||
}
|
||||
|
||||
async initialize(option: CreateEntityOption) {
|
||||
// PG的DDL支持事务,所以这里直接用一个事务包裹所有的初始化操作
|
||||
const txn = await this.connector.startTransaction({
|
||||
isolationLevel: 'serializable',
|
||||
});
|
||||
try {
|
||||
|
||||
const schema = this.getSchema();
|
||||
|
||||
// ===== 第一阶段:事务外创建扩展 =====
|
||||
let hasGeoType = false;
|
||||
let hasChineseTsConfig = false;
|
||||
let chineseParser = null;
|
||||
|
||||
// 扫描 schema
|
||||
for (const entity in schema) {
|
||||
const { attributes, indexes } = schema[entity];
|
||||
for (const attr in attributes) {
|
||||
const { type } = attributes[attr];
|
||||
if (type === 'geometry') {
|
||||
if (attributes[attr].type === 'geometry') {
|
||||
hasGeoType = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -475,14 +471,32 @@ export class PostgreSQLStore<
|
|||
if (index.config?.tsConfig === 'chinese' || index.config?.tsConfig?.includes('chinese')) {
|
||||
hasChineseTsConfig = true;
|
||||
}
|
||||
if (index.config?.chineseParser) {
|
||||
assert(!chineseParser || chineseParser === index.config.chineseParser,
|
||||
'当前定义了多个中文分词器,请保持一致');
|
||||
chineseParser = index.config.chineseParser;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 在事务外创建扩展
|
||||
if (hasGeoType) {
|
||||
console.log('Initializing PostGIS extension for geometry support...');
|
||||
await this.connector.exec('CREATE EXTENSION IF NOT EXISTS postgis;');
|
||||
}
|
||||
|
||||
if (hasChineseTsConfig) {
|
||||
console.log('Initializing Chinese parser extension...');
|
||||
await this.connector.exec(`CREATE EXTENSION IF NOT EXISTS ${chineseParser || 'zhparser'};`);
|
||||
}
|
||||
|
||||
// ===== 第二阶段:事务内创建配置和表 =====
|
||||
const txn = await this.connector.startTransaction({
|
||||
isolationLevel: 'serializable',
|
||||
});
|
||||
|
||||
try {
|
||||
// 创建中文文本搜索配置
|
||||
if (hasChineseTsConfig) {
|
||||
console.log('Initializing Chinese text search configuration...');
|
||||
const checkChineseConfigSql = `
|
||||
|
|
@ -490,30 +504,33 @@ export class PostgreSQLStore<
|
|||
FROM pg_catalog.pg_ts_config
|
||||
WHERE cfgname = 'chinese';
|
||||
`;
|
||||
const result = await this.connector.exec(checkChineseConfigSql);
|
||||
const result = await this.connector.exec(checkChineseConfigSql, txn);
|
||||
const count = parseInt(result[0][0]?.cnt || '0', 10);
|
||||
|
||||
if (count === 0) {
|
||||
const createChineseConfigSql = `
|
||||
CREATE EXTENSION IF NOT EXISTS zhparser;
|
||||
CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = zhparser);
|
||||
CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = ${chineseParser || 'zhparser'});
|
||||
ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l WITH simple;
|
||||
`;
|
||||
await this.connector.exec(createChineseConfigSql);
|
||||
await this.connector.exec(createChineseConfigSql, txn);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建实体表
|
||||
for (const entity in schema) {
|
||||
const sqls = this.translator.translateCreateEntity(entity, option);
|
||||
for (const sql of sqls) {
|
||||
await this.connector.exec(sql, txn);
|
||||
}
|
||||
}
|
||||
|
||||
await this.connector.commitTransaction(txn);
|
||||
} catch (error) {
|
||||
await this.connector.rollbackTransaction(txn);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 从数据库中读取当前schema
|
||||
readSchema() {
|
||||
return this.translator.readSchema((sql) => this.connector.exec(sql));
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export type Plan = {
|
|||
};
|
||||
|
||||
export interface DbStore<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends AsyncRowStore<ED, Cxt> {
|
||||
checkRelationAsync<T extends keyof ED, Cxt extends AsyncContext<ED>>(entity: T, operation: Omit<ED[T]['Operation'] | ED[T]['Selection'], 'id'>, context: Cxt): Promise<void>;
|
||||
connect: () => Promise<void>;
|
||||
disconnect: () => Promise<void>;
|
||||
initialize(options: CreateEntityOption): Promise<void>;
|
||||
|
|
|
|||
Loading…
Reference in New Issue