@opengis/fastify-table
Version:
core-plugins
103 lines (80 loc) • 4.28 kB
JavaScript
import config from '../../../../config.js';
import pgClient from '../pgClients.js';
// subfunc
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 = {};
// main func
async function autoIndex({
table, columns: filter1, pg = pgClient.client, gin,
}) {
const filter = filter1.filter(el => el);
if (!filter?.length || !table || process.env.NODE_ENV === 'unit test') 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 = getTable({ table });
const existsCache = loadedIndex[redisKey];
if (existsCache && !config.disableCache) { return 'ok'; }
const tbs = tableList[0];
const [ns, tbl] = tableList[0].split('.');
const { rows: index } = await pg.query(`select * from pg_indexes where tablename = '${tbl}' and schemaname = '${ns}'`);
if (existsCache && !config.disableCache && index?.length > 0) { return null; }
// console.log('autoindex', table, filter?.map((el) => el.name || el));
const { rows: cols } = await pg.query(`SELECT attrelid::regclass AS tbl, attname AS aname, atttypid::regtype AS datatype, atttypid
FROM pg_attribute WHERE attrelid = '${tbs}'::regclass and attname = any('{ ${attrs} }')`);
const qIndex = [];
const indexAr = {};
// console.log(cols);
for (let i = 0; i < cols.length; i += 1) {
const el = cols[i];
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, // exists1,
};
// 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;
// throw qIndex;
if (!qIndex.length) return null;
if (config.local) {
// console.log(qIndex.filter((v, i, a) => a.indexOf(v) === i));
}
// logger.file('index', { table, filter, sql: qIndex.filter((v, i, a) => a.indexOf(v) === i) });
qIndex.filter((v, i, a) => a.indexOf(v) === i).map((el) => pg.one(el).catch((err) => console.log(err.toString())));
return 'ok';
}
export default autoIndex;