KI-AGENT: Serialisiere JSON-Felder beim Mandantenimport
This commit is contained in:
@@ -6,6 +6,10 @@ import { s3 } from "./s3"
|
||||
import { secrets } from "./secrets"
|
||||
|
||||
type TableRows = Record<string, Record<string, any>[]>
|
||||
type TableMetadata = {
|
||||
columns: string[]
|
||||
jsonColumns: Set<string>
|
||||
}
|
||||
|
||||
export type TenantFullExport = {
|
||||
format: "fedeo.tenant-full-export"
|
||||
@@ -33,17 +37,25 @@ const quoteIdent = (value: string) => `"${value.replace(/"/g, '""')}"`
|
||||
|
||||
const tableColumns = async (client: any) => {
|
||||
const result = await client.query(`
|
||||
select table_name, column_name
|
||||
select table_name, column_name, data_type
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
order by table_name, ordinal_position
|
||||
`)
|
||||
|
||||
const columnsByTable = new Map<string, string[]>()
|
||||
const columnsByTable = new Map<string, TableMetadata>()
|
||||
for (const row of result.rows) {
|
||||
const columns = columnsByTable.get(row.table_name) || []
|
||||
columns.push(row.column_name)
|
||||
columnsByTable.set(row.table_name, columns)
|
||||
const metadata = columnsByTable.get(row.table_name) || {
|
||||
columns: [],
|
||||
jsonColumns: new Set<string>(),
|
||||
}
|
||||
|
||||
metadata.columns.push(row.column_name)
|
||||
if (row.data_type === "json" || row.data_type === "jsonb") {
|
||||
metadata.jsonColumns.add(row.column_name)
|
||||
}
|
||||
|
||||
columnsByTable.set(row.table_name, metadata)
|
||||
}
|
||||
|
||||
return columnsByTable
|
||||
@@ -103,8 +115,9 @@ export const buildTenantFullExport = async (server: FastifyInstance, tenantId: n
|
||||
|
||||
addRows(tables, "tenants", tenantRows)
|
||||
|
||||
for (const [table, columns] of columnsByTable.entries()) {
|
||||
for (const [table, metadata] of columnsByTable.entries()) {
|
||||
if (table === "tenants") continue
|
||||
const { columns } = metadata
|
||||
|
||||
const tenantColumn = columns.includes("tenant")
|
||||
? "tenant"
|
||||
@@ -196,18 +209,25 @@ const restoreFiles = async (exportData: TenantFullExport) => {
|
||||
return { restored, skipped }
|
||||
}
|
||||
|
||||
const insertRows = async (client: any, table: string, rows: Record<string, any>[], columns: string[]) => {
|
||||
const prepareColumnValue = (value: any, isJsonColumn: boolean) => {
|
||||
if (!isJsonColumn || value === null || typeof value === "undefined") return value
|
||||
if (typeof value === "string") return value
|
||||
|
||||
return JSON.stringify(value)
|
||||
}
|
||||
|
||||
const insertRows = async (client: any, table: string, rows: Record<string, any>[], metadata: TableMetadata) => {
|
||||
if (!rows.length) return 0
|
||||
|
||||
let inserted = 0
|
||||
const availableColumns = new Set(columns)
|
||||
const availableColumns = new Set(metadata.columns)
|
||||
|
||||
for (const row of rows) {
|
||||
const rowColumns = Object.keys(row).filter((column) => availableColumns.has(column))
|
||||
if (!rowColumns.length) continue
|
||||
|
||||
const placeholders = rowColumns.map((_, index) => `$${index + 1}`).join(", ")
|
||||
const values = rowColumns.map((column) => row[column])
|
||||
const values = rowColumns.map((column) => prepareColumnValue(row[column], metadata.jsonColumns.has(column)))
|
||||
|
||||
await client.query(
|
||||
`insert into ${quoteIdent(table)} (${rowColumns.map(quoteIdent).join(", ")}) values (${placeholders}) on conflict do nothing`,
|
||||
@@ -219,8 +239,9 @@ const insertRows = async (client: any, table: string, rows: Record<string, any>[
|
||||
return inserted
|
||||
}
|
||||
|
||||
const refreshSequences = async (client: any, columnsByTable: Map<string, string[]>) => {
|
||||
for (const [table, columns] of columnsByTable.entries()) {
|
||||
const refreshSequences = async (client: any, columnsByTable: Map<string, TableMetadata>) => {
|
||||
for (const [table, metadata] of columnsByTable.entries()) {
|
||||
const { columns } = metadata
|
||||
if (!columns.includes("id")) continue
|
||||
|
||||
const sequenceResult = await client.query("select pg_get_serial_sequence($1, $2) as sequence_name", [`public.${table}`, "id"])
|
||||
@@ -269,10 +290,10 @@ export const importTenantFullExport = async (server: FastifyInstance, exportData
|
||||
const importedTables: { table: string; rows: number }[] = []
|
||||
for (const table of tableNames) {
|
||||
const rows = exportData.tables[table] || []
|
||||
const columns = columnsByTable.get(table)
|
||||
if (!columns) continue
|
||||
const metadata = columnsByTable.get(table)
|
||||
if (!metadata) continue
|
||||
|
||||
const count = await insertRows(client, table, rows, columns)
|
||||
const count = await insertRows(client, table, rows, metadata)
|
||||
importedTables.push({ table, rows: count })
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user