Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

07.01.2025

Міграції в SQLite

#SQLite

🗑️ Стикнувся сьогодні з класичним багом в Ping: видалення тегу звалювалося через порушення FOREIGN KEY. Бо ключ я додати згадав, а ON DELETE CASCADE забув. Почав було виправляти на рівні застосунку (тобто видаляти всі відмітки, а потім сам тег), та й думаю… хіба це не робота для бази даних?

🪨 Але ось що виявилося: в SQLite команда ALTER TABLE здатна тільки на найпростіші зміни схеми: додати / видалити / перейменувати стовпчик, або перейменувати саму таблицю, і все. Що мене, звиклого до PostgreSQL, ввело в ступор: невже я застряг з поганою таблицею?

✂️ Знайшов відповідь на StackOverflow з цікавою порадою: оскільки схема таблиць в SQLite зберігається в спеціальній табличці, то достатньо зняти спеціальний запобігач PRAGMA writable_schema та можна просто замінити схему та додати до неї ON DELETE CASCADE. Ясно, що це виглядає максимально сумнівно.

💣 Сумнівно чи ні, але спробував; виявилося, що на iOS цей метод взагалі не працює, бо там підключення відбувається в особливому defensive mode, де абсолютно заборонені такі “сумнівні дії”. (Якщо в схемі змінити таким чином щось суттєве — типи чи порядок стовпчиків, наприклад — то база гепнеться.)

📖 Тоді почитав трохи документацію, та виявилося, що рекомендований підхід дуже простий: створити другу, “правильну” таблицю, наповнити її даними, а потім підмінити стару таблицю новою. Мінуси цього рішення: не відчуєш себе містером роботом. Плюси: все пройшло успішно, без втрати даних та цілісності.

❓ До речі, причина цього (яка теж є на тій же ж сторінці документації), прагматична. SQLite не зберігає схему в структурній формі, а тільки в текстовій (власне, зберігається команда CREATE TABLE.) Тому будь-які зміни в схемі повинні були б перекладатися назад в текст CREATE TABLE - ще й гарантовано без втрат змісту. Творці SQLite вирішили не ускладнювати цим проєкт та залишили зміни схеми в такому ручному, явному режимі.