mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-21 12:56:00 +00:00
duckdb index columns
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
* @property {string[]} items
|
* @property {string[]} items
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const extractIndexColumns = require('./extractIndexColumns');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {object} DuckDbColumnRow
|
* @typedef {object} DuckDbColumnRow
|
||||||
* @property {number | null} numeric_scale
|
* @property {number | null} numeric_scale
|
||||||
@@ -353,7 +355,7 @@ function mapIndexRowToIndexInfo(duckDbIndexRow) {
|
|||||||
pureName: duckDbIndexRow.table_name,
|
pureName: duckDbIndexRow.table_name,
|
||||||
schemaName: duckDbIndexRow.schema_name,
|
schemaName: duckDbIndexRow.schema_name,
|
||||||
constraintType: 'index',
|
constraintType: 'index',
|
||||||
columns: [],
|
columns: extractIndexColumns(duckDbIndexRow.sql).map((columnName) => ({ columnName })),
|
||||||
isUnique: duckDbIndexRow.is_unique,
|
isUnique: duckDbIndexRow.is_unique,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// 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;
|
||||||
Reference in New Issue
Block a user