Files
dbgate/plugins/dbgate-plugin-duckdb/src/backend/extractIndexColumns.js
SPRINX0\prochazka d5e6f99819 duckdb index columns
2025-04-28 10:47:27 +02:00

70 lines
1.8 KiB
JavaScript

// this algoruthm is implemented by ChatGPT o3
function sliceColumnList(ddl) {
// ① jump to the first “(” that follows the ON <table> qualifier
const onMatch = /ON\s+(?:"[^"]+"|\w+)(?:\s*\.\s*(?:"[^"]+"|\w+))*\s*\(/i.exec(ddl);
if (!onMatch) return '';
const start = onMatch.index + onMatch[0].length - 1; // points at the "("
// ② walk forward until depth returns to 0
let depth = 0,
i = start,
end = -1;
while (i < ddl.length) {
const ch = ddl[i++];
if (ch === '(') depth++;
else if (ch === ')') {
depth--;
if (depth === 0) {
end = i - 1;
break;
}
}
}
return end === -1 ? '' : ddl.slice(start + 1, end); // inside the ()
}
function splitTopLevel(list) {
const parts = [];
let depth = 0,
last = 0;
for (let i = 0; i <= list.length; i++) {
const ch = list[i] ?? ','; // virtual comma at the end
if (ch === '(') depth++;
else if (ch === ')') depth--;
if (ch === ',' && depth === 0) {
parts.push(list.slice(last, i).trim());
last = i + 1;
}
}
return parts.filter(Boolean);
}
function clean(segment) {
return (
segment
// drop ASC|DESC, NULLS FIRST|LAST
.replace(/\bASC\b|\bDESC\b|\bNULLS\s+(FIRST|LAST)\b/gi, '')
// un-wrap one-liner functions: LOWER(col) -> col
.replace(/^[A-Za-z_][\w$]*\(\s*([^()]+?)\s*\)$/i, '$1')
// chop any schema- or table- prefix: tbl.col -> col
.replace(/^.*\.(?=[^.)]+$)/, '')
// strip double-quotes
.replace(/"/g, '')
.trim()
);
}
function extractIndexColumns(sql) {
const sqlText = sql // your variable
.replace(/\s+/g, ' ') // collapse whitespace
.replace(/--.*?$/gm, '') // strip line comments
.trim();
const list = sliceColumnList(sqlText);
if (!list) return [];
return splitTopLevel(list).map(clean);
}
module.exports = extractIndexColumns;