Как рекурсивно внедрить предложения WHERE в глубокие подзапросы и вложенные выражения?JAVA

Программисты JAVA общаются здесь
Anonymous
Как рекурсивно внедрить предложения WHERE в глубокие подзапросы и вложенные выражения?

Сообщение Anonymous »

Я создаю перехватчик SQL на Java для реализации мультитенантной изоляции. Моя цель — проанализировать входящие операторы SQL с помощью JSqlParser и внедрить обязательный предикат tenant_id = '123' при каждом доступе к таблице. Предположим, что каждая таблица имеет столбец tenant_id.
У меня есть рабочий прототип, который обрабатывает простые операторы SELECT, UPDATE и DELETE. Однако мой текущий подход предполагает ручную проверку определенных типов выражений, таких как InExpression, ExistsExpression, SubSelect и других.
Текущий подход (ручной)
В настоящее время я разворачиваю выражения вручную. Это работает для запросов верхнего уровня, но быстро становится запутанным:

Код: Выделить всё

public void modifyPlainSelect(PlainSelect plainSelect, String simId) {
// 1. Add to main table
if (plainSelect.getFromItem() instanceof Table) {
addWhereCondition(plainSelect, simId);
}

// 2. Manually check WHERE clause for subqueries
Expression where = plainSelect.getWhere();
if (where instanceof InExpression inExpr) {
// Manually handle the right side
if (inExpr.getRightItemsList() instanceof SubSelect) {
modifySelect(((SubSelect) inExpr.getRightItemsList()).getSelectBody());
}
}
// I have to add manual checks for Exists, Between, BinaryExpression, etc...
}
Проблема
Это не позволяет автоматически охватить сложные сценарии. Например:
Ввод:

Код: Выделить всё

SELECT * FROM orders o
WHERE o.customer_id IN (
SELECT c.id FROM customers c
WHERE c.status = (SELECT s.code FROM status s WHERE s.active = 1)
)
Желаемый результат:

Код: Выделить всё

SELECT * FROM orders o
WHERE o.simulation_id = '123' -- Injected
AND o.customer_id IN (
SELECT c.id FROM customers c
WHERE c.simulation_id = '123' -- Injected (Recursion Level 1)
AND c.status = (
SELECT s.code FROM status s
WHERE s.simulation_id = '123' -- Injected (Recursion Level 2)
AND s.active = 1
)
)
Мой вопрос
Существует ли в JSqlParser стандартный шаблон, такой как StatementVisitor, TablesNamesFinder или ExpressionDeParser, который позволяет мне делать следующее:
  • Посещать каждый узел в AST автоматически, с помощью рекурсии обрабатывается библиотекой.
  • Определяйте всякий раз, когда осуществляется доступ к таблице, будь то FROM, JOIN, UPDATE или DELETE.
  • Внедрите предложение WHERE в родительский объект SELECT или UPDATE.
Я хочу избежать написания логики ручного обхода для каждого возможного типа выражения, чтобы не было слепых зон.

Подробнее здесь: https://stackoverflow.com/questions/798 ... d-expressi

Вернуться в «JAVA»