@opengis/fastify-table
Version:
core-plugins
100 lines (99 loc) • 4.4 kB
JavaScript
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";
}