Oracle SQL скрипти, створені агентами великих мовних моделей (LLM), можуть виглядати бездоганно на папері, але все одно призводити до критичних збоїв у продакшні. У застарілій кодовій базі обсягом 2,3 мільйона рядків AI-агент постійно допускав помилки в ідентифікаторах, яких не існувало — наприклад, використовував POLICY_STATUS замість реальної колонки STATUS_CD або посилався на неіснуючу таблицю CUSTOMERS замість CUSTOMER.

Запуск скрипта для виявлення друкарської помилки не є варіантом для операторів UPDATE або DELETE. Виконання їх на наборі даних, подібному до продакшну, призводить до отримання блокувань, витрачає номери послідовностей і може викликати каскадні побічні ефекти. Розробникам потрібен спосіб перевірити назви та синтаксис, не торкаючись самих даних. Відповідь, напрочуд проста, — команда Oracle EXPLAIN PLAN, яку можна використати як етап лінтингу.

Як EXPLAIN PLAN працює як швидкий валідатор

Коли Oracle отримує оператор, він спочатку виконує його парсинг. Парсинг перевіряє наявність кожної згаданої таблиці, колонки та прав доступу, після чого будує план виконання і записує цей план у системну таблицю. Команда ніколи не виконує сам оператор: рядки не змінюються, тригери не спрацьовують, блокування не створюються. Якщо парсер стикається з невідомим об'єктом, він видає помилку за лічені мілісекунди.

Така поведінка робить EXPLAIN PLAN ідеальним інструментом попередньої перевірки для SQL, згенерованого ШІ. Про відсутність таблиці або колонки повідомляється миттєво, що дозволяє циклу генерації виправити помилку ще до того, як скрипт побачить людина.

Робочий процес, який я впровадив у свій CI-пайплайн

  1. Розділіть вхідний скрипт на окремі оператори.
  2. Запустіть EXPLAIN PLAN FOR <statement> проти схеми розробки.
  3. Зберіть усі помилки парсингу, які поверне Oracle.
  4. Передайте помилки назад у LLM для повторної спроби.

На практиці одна повторна спроба усуває більшість помилок у назвах. ШІ вивчає правильну схему і автоматично коригує свій результат. Я також обмежую агента режимом «тільки для читання»: він може виконувати SELECT та виклики EXPLAIN PLAN, але операції DDL, DML та COMMIT заблоковані. Така «пісочниця» гарантує, що база даних залишиться недоторканою, поки ШІ досліджує її структуру.

Окрім перевірки назв, згенерований план виявляє очевидні ознаки проблем із продуктивністю. Якщо оператор призведе до повного сканування величезної таблиці (full-table scan), план покаже це ще до того, як будуть зачеплені будь-які рядки, даючи розробникам можливість запропонувати індекси або переписати предикат.

Обмеження підходу

  • Логічна коректність не перевіряється. Оператор, який посилається на правильні колонки, але застосовує неправильний фільтр, все одно пройде лінтинг.
  • Блоки PL/SQL не входять до сфери застосування. Парсер обробляє лише окремі SQL-оператори; процедурний код потребує окремого шляху валідації.
  • Відсутня валідація на рівні даних. Лінтер не може сказати, чи відповідає літеральне значення домену колонки або чи дійсно існує посилання на зовнішній ключ.
  • Тільки схема розробки. Помилки, які з'являються лише в продакшні — наприклад, таблиця, яка існує в dev, але була перейменована в prod — залишаються непоміченими до пізнішого часу.

Ці прогалини не зменшують корисності методу; вони просто визначають його межі. Для більшості DML-скриптів, згенерованих LLM, найпоширенішим видом помилки є друкарська помилка або неправильна назва об'єкта, і саме це ловить EXPLAIN PLAN.

Портативність на інші механізми баз даних

Цей же принцип застосовується і поза межами Oracle. Оператор PREPARE або EXPLAIN у PostgreSQL може розібрати запит без його виконання. SQL Server пропонує SET PARSEONLY ON, що змушує рушій перевіряти синтаксис і назви об'єктів, пропускаючи фактичну обробку. Будь-яка РСУБД, яка відокремлює парсинг від виконання, може стати легким шлюзом для лінтингу.

Висновок

Запуск EXPLAIN PLAN (або його еквівалента) для кожного SQL-оператора, згенерованого ШІ, перетворює парсер бази даних на недорогий і безризиковий етап лінтингу. Він виявляє найпоширеніші помилки в назвах і синтаксисі до того, як будуть змінені будь-які дані, підтримуючи стабільність застарілих систем і дозволяючи розробникам отримувати переваги продуктивності кодування за допомогою LLM.