UNPKG

@opengis/fastify-table

Version:

core-plugins

100 lines (99 loc) 4.4 kB
import config from "../../../../config.js"; import pgClient from "../pgClients.js"; const getTable = (table) => table ?.toLowerCase?.() ?.replace?.(/[\n\r]+/g, " ") ?.split?.(" from ") ?.filter((el) => /^[a-z0-9_]+\.[a-z0-9_"]+/.test(el)) ?.map((el) => el?.split?.(/[ )]/)?.[0]); const loadedIndex = {}; export default async function autoIndex({ table, columns: filter1, pg = pgClient.client, gin, }) { const filter = filter1.filter((el) => el); if (!filter?.length || !table) return null; const attrs = filter .map((el) => (el.name || el).replace(/'/g, "")) .filter((el) => el?.indexOf("(") === -1) .sort(); const types = filter .filter((el) => (el?.name || el)?.indexOf?.("(") === -1) .map((el) => (el.name ? el : { name: el })) .reduce((p, el) => ({ ...p, [el.name]: el.type || "-", }), {}); const redisKey = `autoindex1:${table}:${attrs.join(";")}`; const tableList = pg.pk[table.replace(/"/g, "")] ? [table] : getTable(table); if (!tableList.length) { return "empty table list"; } const existsCache = loadedIndex[redisKey]; if (existsCache && !config.disableCache) { return "ok"; } const tbs = tableList[0]; const [ns, tbl] = tableList[0]?.split?.(".") || []; const index = tbl ? await pg .query("select * from pg_indexes where tablename = $1 and schemaname = $2", [tbl, ns]) .then((el) => el.rows || []) : []; if (existsCache && !config.disableCache && index?.length > 0) { return null; } const cols = tbs ? await pg .query(`SELECT attrelid::regclass AS tbl, attname AS aname, atttypid::regtype AS datatype, atttypid FROM pg_attribute WHERE attrelid::regclass::text = $1 and attname = any($2::text[])`, [tbs, attrs]) .then((el) => el.rows || []) : []; const qIndex = []; const indexAr = {}; cols.forEach((el) => { el.relname = tbl; el.nspname = ns; const isGin = types[el.aname] === "Text" || gin; const indexUsing = (el.datatype === "geometry" ? "gist" : null) || (isGin ? "gin" : null) || "btree"; const name = `${el.nspname}_${el.relname}_${el.aname}_${indexUsing}_idx`; const exists = index.filter((ind) => ind.tablename === el.relname && ind.schemaname === el.nspname && ind.indexdef.includes(isGin ? `gin (${el.aname} gin_trgm_ops)` : `btree (${el.aname})`)); indexAr[el.aname] = { name, type: el.datatype, exists, }; // drop /* if (exists?.length > 1) { exists.filter((ind, i1) => i1).forEach((ind) => qIndex.push(`DROP INDEX if exists ${ind.schemaname}.${ind.indexname} `)); } */ // add if (exists?.length <= (isGin ? 2 : 1)) { // console.log(`${name} - ${el.datatype}`); const suffix = isGin ? "gin_trgm_ops" : ""; qIndex.push(`CREATE INDEX if not exists ${name} ON ${el.nspname}.${el.relname} USING ${indexUsing} (${el.aname} ${suffix})`); if (isGin) { qIndex.push(`CREATE INDEX if not exists ${name}_lower ON ${el.nspname}.${el.relname} USING ${indexUsing} (lower(${el.aname}) ${suffix})`); } if (indexUsing === "gist") { qIndex.push(`CREATE INDEX if not exists ${name.replace("gist", "gist1")} ON ${el.nspname}.${el.relname} USING gist (${el.aname})`); qIndex.push(`CREATE INDEX if not exists ${name.replace("gist", "area")} ON ${el.nspname}.${el.relname} USING btree (st_area(st_transform(${el.aname},3857)))`); qIndex.push(`CREATE INDEX if not exists ${name.replace("gist", "area_true")} ON ${el.nspname}.${el.relname} USING btree (st_area(${el.aname}, true))`); qIndex.push(`CREATE INDEX if not exists ${name.replace("gist", "4326")} ON ${el.nspname}.${el.relname} USING gist (st_transform(${el.aname},4326))`); } } }); loadedIndex[redisKey] = 1; if (!qIndex.length) return null; qIndex .filter((el, idx, arr) => arr.indexOf(el) === idx) .map((el) => pg.query(el).catch((err) => console.log(err.toString()))); return "ok"; }