feat: 支持在init时自动创建地理和paser插件,以及将初始化包裹在事务中

This commit is contained in:
Pan Qiancheng 2026-01-20 12:04:57 +08:00
parent b4e0b08ba7
commit 5a5ac5c194
2 changed files with 111 additions and 14 deletions

View File

@ -336,14 +336,61 @@ class PostgreSQLStore extends CascadeStore_1.CascadeStore {
await this.connector.disconnect();
}
async initialize(option) {
const schema = this.getSchema();
// 可选:先创建 PostGIS 扩展
// await this.connector.exec('CREATE EXTENSION IF NOT EXISTS postgis;');
for (const entity in schema) {
const sqls = this.translator.translateCreateEntity(entity, option);
for (const sql of sqls) {
await this.connector.exec(sql);
// PG的DDL支持事务所以这里直接用一个事务包裹所有的初始化操作
const txn = await this.connector.startTransaction({
isolationLevel: 'serializable',
});
try {
const schema = this.getSchema();
let hasGeoType = false;
let hasChineseTsConfig = false;
for (const entity in schema) {
const { attributes, indexes } = schema[entity];
for (const attr in attributes) {
const { type } = attributes[attr];
if (type === 'geometry') {
hasGeoType = true;
}
}
for (const index of indexes || []) {
if (index.config?.tsConfig === 'chinese' || index.config?.tsConfig?.includes('chinese')) {
hasChineseTsConfig = true;
}
}
}
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 text search configuration...');
const checkChineseConfigSql = `
SELECT COUNT(*) as cnt
FROM pg_catalog.pg_ts_config
WHERE cfgname = 'chinese';
`;
const result = await this.connector.exec(checkChineseConfigSql);
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);
ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l WITH simple;
`;
await this.connector.exec(createChineseConfigSql);
}
}
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;
}
}
}

View File

@ -449,16 +449,66 @@ export class PostgreSQLStore<
}
async initialize(option: CreateEntityOption) {
const schema = this.getSchema();
// PG的DDL支持事务所以这里直接用一个事务包裹所有的初始化操作
const txn = await this.connector.startTransaction({
isolationLevel: 'serializable',
});
try {
// 可选:先创建 PostGIS 扩展
// await this.connector.exec('CREATE EXTENSION IF NOT EXISTS postgis;');
const schema = this.getSchema();
for (const entity in schema) {
const sqls = this.translator.translateCreateEntity(entity, option);
for (const sql of sqls) {
await this.connector.exec(sql);
let hasGeoType = false;
let hasChineseTsConfig = false;
for (const entity in schema) {
const { attributes, indexes } = schema[entity];
for (const attr in attributes) {
const { type } = attributes[attr];
if (type === 'geometry') {
hasGeoType = true;
}
}
for (const index of indexes || []) {
if (index.config?.tsConfig === 'chinese' || index.config?.tsConfig?.includes('chinese')) {
hasChineseTsConfig = true;
}
}
}
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 text search configuration...');
const checkChineseConfigSql = `
SELECT COUNT(*) as cnt
FROM pg_catalog.pg_ts_config
WHERE cfgname = 'chinese';
`;
const result = await this.connector.exec(checkChineseConfigSql);
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);
ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l WITH simple;
`;
await this.connector.exec(createChineseConfigSql);
}
}
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;
}
}
}