2024-09-02 18:40:48 +00:00
|
|
|
import { BaseFrom, From, Parser, Select, With } from "node-sql-parser"
|
2024-04-30 21:52:52 +00:00
|
|
|
import { generatePrefix } from "./hash"
|
|
|
|
|
|
|
|
|
|
const isGlobal = (table: string, globalTables: string[]) => {
|
|
|
|
|
return globalTables.map(t =>
|
|
|
|
|
t.toLowerCase()
|
|
|
|
|
).includes(table.toLowerCase())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isBaseFrom = (from: From): from is BaseFrom => {
|
2024-09-02 18:40:48 +00:00
|
|
|
return Object.keys(from).includes('table')
|
2024-04-30 21:52:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const prefixedIfNotGlobal = (tableName: string, globalTables: string[], prefix: string) => {
|
|
|
|
|
if (isGlobal(tableName, globalTables)) {
|
|
|
|
|
return tableName
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return generatePrefix(prefix, tableName)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-02 18:40:48 +00:00
|
|
|
const updateSelect = (selectAst: Select, globalTables: string[], prefix: string): { selectAst: Select, tables: string[] } => {
|
|
|
|
|
|
|
|
|
|
let cteGlobals: string[] = []
|
|
|
|
|
let withs = selectAst.with
|
|
|
|
|
let extraTables: string[] = []
|
|
|
|
|
if (selectAst.with) {
|
|
|
|
|
cteGlobals = selectAst.with.map(w => w.name.value)
|
|
|
|
|
const updatedWiths = selectAst.with.map(w => {
|
|
|
|
|
const { selectAst, tables } = updateSelect(w.stmt.ast, [...cteGlobals, ...globalTables], prefix)
|
|
|
|
|
extraTables.push(...tables)
|
|
|
|
|
return {
|
|
|
|
|
...w,
|
|
|
|
|
stmt: {
|
|
|
|
|
...w.stmt,
|
|
|
|
|
ast: selectAst
|
|
|
|
|
}
|
|
|
|
|
} satisfies With
|
|
|
|
|
})
|
|
|
|
|
withs = updatedWiths
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-30 21:52:52 +00:00
|
|
|
if (!selectAst.from) {
|
2024-05-06 12:42:14 +00:00
|
|
|
return { selectAst: selectAst, tables: [] }
|
2024-04-30 21:52:52 +00:00
|
|
|
}
|
2024-05-06 12:42:14 +00:00
|
|
|
|
|
|
|
|
const tables: Array<string> = []
|
|
|
|
|
|
|
|
|
|
const updatedFrom = selectAst.from.map(from => {
|
|
|
|
|
if(isBaseFrom(from)) {
|
2024-09-02 18:40:48 +00:00
|
|
|
const t = prefixedIfNotGlobal(from.table, [...cteGlobals, ...globalTables], prefix)
|
2024-05-06 12:42:14 +00:00
|
|
|
tables.push(t)
|
|
|
|
|
return {
|
|
|
|
|
...from,
|
2024-09-02 18:40:48 +00:00
|
|
|
table: t,
|
2024-04-30 21:52:52 +00:00
|
|
|
}
|
2024-05-06 12:42:14 +00:00
|
|
|
}
|
|
|
|
|
return from
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
selectAst: {
|
|
|
|
|
...selectAst,
|
2024-09-02 18:40:48 +00:00
|
|
|
from: updatedFrom,
|
|
|
|
|
with: withs
|
2024-05-06 12:42:14 +00:00
|
|
|
},
|
2024-09-02 18:40:48 +00:00
|
|
|
tables: [...tables, ...extraTables]
|
2024-04-30 21:52:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const updateTables = (selectStatement: string, globalTables: string[], prefix: string) => {
|
|
|
|
|
const parser = new Parser()
|
|
|
|
|
const { ast } = parser.parse(selectStatement)
|
|
|
|
|
if (!Array.isArray(ast) && ast.type === 'select') {
|
2024-05-06 12:42:14 +00:00
|
|
|
const { selectAst, tables } = updateSelect(ast!, globalTables, prefix)
|
|
|
|
|
return { statement: parser.sqlify(selectAst), tables }
|
2024-04-30 21:52:52 +00:00
|
|
|
} else {
|
|
|
|
|
throw new Error('Invalid Statement. Only single SELECTs are accepted at the moment.')
|
|
|
|
|
}
|
|
|
|
|
}
|