diff --git a/lib/PostgreSQL/store.js b/lib/PostgreSQL/store.js index 42bef83..6e2ef7f 100644 --- a/lib/PostgreSQL/store.js +++ b/lib/PostgreSQL/store.js @@ -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; } } } diff --git a/src/PostgreSQL/store.ts b/src/PostgreSQL/store.ts index b14580d..17ce927 100644 --- a/src/PostgreSQL/store.ts +++ b/src/PostgreSQL/store.ts @@ -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; } } }