Как рекурсивно внедрить предложения 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/ объект.
Я хочу избежать написания логики ручного обхода для каждого возможного типа выражения, чтобы гарантировать отсутствие слепых зон.

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

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

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