fix(progress): перенести профильную миграцию на V13 после аттестаций
This commit is contained in:
@@ -3,10 +3,12 @@
|
|||||||
**Перед любыми миграциями обязателен backup:** `./deploy/backup.sh backup`
|
**Перед любыми миграциями обязателен backup:** `./deploy/backup.sh backup`
|
||||||
(см. [`../BACKUP.md`](../BACKUP.md)). Preflight не заменяет backup.
|
(см. [`../BACKUP.md`](../BACKUP.md)). Preflight не заменяет backup.
|
||||||
|
|
||||||
Два скрипта только читают данные:
|
Скрипты только читают данные:
|
||||||
|
|
||||||
- `groups-courses.sql` — до миграций: проблемы, которые могут помешать;
|
- `groups-courses.sql` — до миграций: проблемы, которые могут помешать;
|
||||||
- `groups-courses-post.sql` — после миграций и bootstrap курса C: проверка результата.
|
- `groups-courses-post.sql` — после миграций и bootstrap курса C: проверка результата;
|
||||||
|
- `progress-v10-v13.sql` — проверка истории Flyway и колонок/индекса при переходе
|
||||||
|
старой feature-миграции V10 на V13.
|
||||||
|
|
||||||
## До миграций
|
## До миграций
|
||||||
|
|
||||||
@@ -40,6 +42,34 @@ psql -h localhost -U lms -d lms -f deploy/preflight/groups-courses-post.sql
|
|||||||
- статусы аккаунтов;
|
- статусы аккаунтов;
|
||||||
- группы без полного разбора.
|
- группы без полного разбора.
|
||||||
|
|
||||||
|
## Переход V10 → V13
|
||||||
|
|
||||||
|
Нужен для любой БД, которая когда-либо применяла старую feature-миграцию
|
||||||
|
`V10__profile_authors.sql`: dev/feature-БД и staging, ненадолго запускавший
|
||||||
|
master-коммит `bfdae41` (out-of-order + V10). На production/master записи V10
|
||||||
|
нет — раздел можно пропустить.
|
||||||
|
|
||||||
|
Порядок:
|
||||||
|
|
||||||
|
1. Backup: `./deploy/backup.sh backup`.
|
||||||
|
2. Проверить состояние:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
psql -h localhost -U lms -d lms -f deploy/preflight/progress-v10-v13.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
Колонки должны быть `uuid`/nullable, индекс `lab_grades_lab_idx` — существовать
|
||||||
|
и быть валидным; `columns_ok` и `index_ok` должны быть `true`.
|
||||||
|
3. Если V10 есть в истории с `success=true`, удалить только эту запись истории
|
||||||
|
(`flyway repair` или точечный `DELETE` из примера в конце скрипта). При
|
||||||
|
`success=false` сначала проверить откат объектов; V13 идемпотентна и создаст
|
||||||
|
недостающее.
|
||||||
|
4. Deploy: обычный запуск применит V13.
|
||||||
|
5. Postflight: `psql -h localhost -U lms -d lms -f deploy/preflight/groups-courses-post.sql`.
|
||||||
|
|
||||||
|
После V13 переход forward-only: откат на сборку без V13 не пройдёт валидацию
|
||||||
|
Flyway. Не оставляйте `out-of-order` включённым.
|
||||||
|
|
||||||
## Что делать с результатами
|
## Что делать с результатами
|
||||||
|
|
||||||
1. Группы с нестандартными именами — разобрать вручную и заполнить поля до
|
1. Группы с нестандартными именами — разобрать вручную и заполнить поля до
|
||||||
|
|||||||
96
deploy/preflight/progress-v10-v13.sql
Normal file
96
deploy/preflight/progress-v10-v13.sql
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
-- Preflight (только чтение): переход progress-миграции профиля V10 -> V13.
|
||||||
|
-- Проверяет историю Flyway, тип/nullable колонок и валидность индекса.
|
||||||
|
-- Ничего не изменяет: DELETE в конце приведён только как закомментированный пример.
|
||||||
|
-- Пример:
|
||||||
|
-- psql -h localhost -U lms -d lms -f deploy/preflight/progress-v10-v13.sql
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP on
|
||||||
|
\pset pager off
|
||||||
|
|
||||||
|
\echo '=== 0. Наличие progress.flyway_schema_history ==='
|
||||||
|
SELECT to_regclass('progress.flyway_schema_history') IS NOT NULL
|
||||||
|
AS progress_flyway_schema_history_exists \gset
|
||||||
|
|
||||||
|
\if :progress_flyway_schema_history_exists
|
||||||
|
\echo '=== 1. progress.flyway_schema_history: версии 10-13 ==='
|
||||||
|
SELECT installed_rank, version, description, type, script, success, installed_on
|
||||||
|
FROM progress.flyway_schema_history
|
||||||
|
WHERE version IN ('10', '11', '12', '13')
|
||||||
|
ORDER BY installed_rank;
|
||||||
|
\else
|
||||||
|
\echo 'progress.flyway_schema_history не найдена: сервис ещё не применял миграции progress.'
|
||||||
|
\echo 'Проверьте LMS_DB_URL / схему progress и повторите preflight.'
|
||||||
|
\endif
|
||||||
|
|
||||||
|
\echo '=== 2. Колонки профиля: тип uuid и nullable (ok = true) ==='
|
||||||
|
SELECT expected.table_name,
|
||||||
|
expected.column_name,
|
||||||
|
c.data_type,
|
||||||
|
c.is_nullable,
|
||||||
|
(c.data_type = 'uuid' AND c.is_nullable = 'YES') AS ok
|
||||||
|
FROM (VALUES
|
||||||
|
('grade_comments', 'author_account_id'),
|
||||||
|
('lab_grades', 'updated_by_account_id')
|
||||||
|
) AS expected(table_name, column_name)
|
||||||
|
LEFT JOIN information_schema.columns c
|
||||||
|
ON c.table_schema = 'progress'
|
||||||
|
AND c.table_name = expected.table_name
|
||||||
|
AND c.column_name = expected.column_name
|
||||||
|
ORDER BY expected.table_name, expected.column_name;
|
||||||
|
|
||||||
|
\echo '=== 3. Индекс lab_grades_lab_idx: существует, валиден, определение ==='
|
||||||
|
SELECT i.indexrelid::regclass AS index_name,
|
||||||
|
i.indisvalid,
|
||||||
|
i.indisready,
|
||||||
|
pg_get_indexdef(i.indexrelid) AS definition
|
||||||
|
FROM pg_index i
|
||||||
|
JOIN pg_class idx ON idx.oid = i.indexrelid
|
||||||
|
JOIN pg_namespace n ON n.oid = idx.relnamespace
|
||||||
|
WHERE n.nspname = 'progress'
|
||||||
|
AND idx.relname = 'lab_grades_lab_idx';
|
||||||
|
|
||||||
|
\echo '=== 4. Сводка: колонки и индекс готовы к V13 ==='
|
||||||
|
SELECT
|
||||||
|
(
|
||||||
|
SELECT count(*) = 2
|
||||||
|
AND bool_and(c.data_type = 'uuid' AND c.is_nullable = 'YES')
|
||||||
|
FROM information_schema.columns c
|
||||||
|
WHERE c.table_schema = 'progress'
|
||||||
|
AND (c.table_name, c.column_name) IN (
|
||||||
|
('grade_comments', 'author_account_id'),
|
||||||
|
('lab_grades', 'updated_by_account_id')
|
||||||
|
)
|
||||||
|
) AS columns_ok,
|
||||||
|
(
|
||||||
|
SELECT count(*) = 1
|
||||||
|
AND bool_and(i.indisvalid)
|
||||||
|
FROM pg_index i
|
||||||
|
JOIN pg_class idx ON idx.oid = i.indexrelid
|
||||||
|
JOIN pg_namespace n ON n.oid = idx.relnamespace
|
||||||
|
WHERE n.nspname = 'progress'
|
||||||
|
AND idx.relname = 'lab_grades_lab_idx'
|
||||||
|
) AS index_ok;
|
||||||
|
|
||||||
|
-- Очистка истории (НЕ выполняется этим скриптом).
|
||||||
|
--
|
||||||
|
-- Если старая feature-миграция V10 применена со success=true, удалите ТОЛЬКО
|
||||||
|
-- её запись истории: объекты схемы уже созданы, а V13 идемпотентна и создаст
|
||||||
|
-- недостающие колонки/индекс. Гард по RETURNING: ожидается ровно одна строка;
|
||||||
|
-- если строк больше или меньше — ROLLBACK.
|
||||||
|
--
|
||||||
|
-- BEGIN;
|
||||||
|
-- DELETE FROM progress.flyway_schema_history
|
||||||
|
-- WHERE version = '10'
|
||||||
|
-- AND script = 'V10__profile_authors.sql'
|
||||||
|
-- AND success
|
||||||
|
-- RETURNING installed_rank, version, script, success;
|
||||||
|
-- -- expect exactly one row; otherwise ROLLBACK
|
||||||
|
-- COMMIT;
|
||||||
|
--
|
||||||
|
-- Если V10 осталась со success=false, сначала убедитесь, что её частичные
|
||||||
|
-- изменения откатились на уровне объектов, затем выполните `flyway repair`
|
||||||
|
-- или удалите только неуспешную строку. V13 идемпотентна и досоздаст
|
||||||
|
-- недостающие объекты. Перед удалением строки запустите этот preflight:
|
||||||
|
-- все проверки должны быть true.
|
||||||
|
--
|
||||||
|
-- Не переставляйте V11/V12 и не включайте out-of-order.
|
||||||
@@ -95,9 +95,11 @@
|
|||||||
### progress
|
### progress
|
||||||
Данные привязаны к `lab_id` и студенту (сдачи, оценки, комментарии, защиты, назначения вариантов,
|
Данные привязаны к `lab_id` и студенту (сдачи, оценки, комментарии, защиты, назначения вариантов,
|
||||||
публикации). Схема **в основном не меняется**: доступ регулируется по цепочке
|
публикации). Схема **в основном не меняется**: доступ регулируется по цепочке
|
||||||
`lab → course → (преподаватель | группа)`. Для профиля студента курса добавляется
|
`lab → course → (преподаватель | группа)`. Для профиля студента курса добавляются
|
||||||
`grade_comments.author_account_id` (nullable) и индекс `(student_id, lab_id)`;
|
`grade_comments.author_account_id` (nullable) и `lab_grades.updated_by_account_id`
|
||||||
остальное — рантайм-проверки.
|
(nullable); существующий индекс `(student_id, lab_id)` (`grade_comments_grade_idx`)
|
||||||
|
переиспользуется, дополнительно добавляется индекс `lab_grades(lab_id)`.
|
||||||
|
Остальное — рантайм-проверки.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -270,7 +272,7 @@ CREATE UNIQUE INDEX chapters_slug_course_uidx ON chapters (course_id, slug) WHER
|
|||||||
Признак видимости актив наследует от статьи→раздела→главы (course/audience). Требуется проверка доступа в
|
Признак видимости актив наследует от статьи→раздела→главы (course/audience). Требуется проверка доступа в
|
||||||
маршруте выдачи активов (см. §6). Отдельных колонок достаточно опционально; минимум — корректная авторизация.
|
маршруте выдачи активов (см. §6). Отдельных колонок достаточно опционально; минимум — корректная авторизация.
|
||||||
|
|
||||||
**V10 — курс C: завершение привязки лаб (post-bootstrap шаг)**
|
**Post-bootstrap шаг academic (условный «V10», не файл `db/migration` и вне обычной цепочки Flyway) — курс C: завершение привязки лаб**
|
||||||
```sql
|
```sql
|
||||||
-- Выполняется после bootstrap-сервиса, когда все лабы получили course_id.
|
-- Выполняется после bootstrap-сервиса, когда все лабы получили course_id.
|
||||||
-- Это отдельный шаг/миграция: обычный Flyway-старт применяет миграции раньше
|
-- Это отдельный шаг/миграция: обычный Flyway-старт применяет миграции раньше
|
||||||
@@ -281,12 +283,14 @@ ALTER TABLE labs ALTER COLUMN course_id SET NOT NULL;
|
|||||||
### progress
|
### progress
|
||||||
Схема **в основном не меняется**. Проверки доступа — рантайм (по `lab_id → course`).
|
Схема **в основном не меняется**. Проверки доступа — рантайм (по `lab_id → course`).
|
||||||
|
|
||||||
**V10 — профиль студента курса: автор комментария**
|
**V13 — профиль студента курса: автор комментария**
|
||||||
```sql
|
```sql
|
||||||
ALTER TABLE grade_comments ADD COLUMN author_account_id uuid;
|
ALTER TABLE grade_comments ADD COLUMN IF NOT EXISTS author_account_id uuid;
|
||||||
ALTER TABLE lab_grades ADD COLUMN updated_by_account_id uuid;
|
ALTER TABLE lab_grades ADD COLUMN IF NOT EXISTS updated_by_account_id uuid;
|
||||||
CREATE INDEX lab_grades_lab_idx ON lab_grades (lab_id);
|
CREATE INDEX IF NOT EXISTS lab_grades_lab_idx ON lab_grades (lab_id);
|
||||||
```
|
```
|
||||||
|
V13 идемпотентна: если старая feature-миграция V10 уже применялась в dev-БД,
|
||||||
|
достаточно убрать её запись из истории Flyway (см. план реализации).
|
||||||
Индекс `grade_comments (student_id, lab_id)` уже существует (`grade_comments_grade_idx`).
|
Индекс `grade_comments (student_id, lab_id)` уже существует (`grade_comments_grade_idx`).
|
||||||
Старые комментарии остаются без автора и отображаются как «автор не указан».
|
Старые комментарии остаются без автора и отображаются как «автор не указан».
|
||||||
|
|
||||||
|
|||||||
@@ -200,14 +200,38 @@
|
|||||||
|
|
||||||
## 4. Ориентировочные миграции
|
## 4. Ориентировочные миграции
|
||||||
|
|
||||||
Номера уточняются при реализации, чтобы не конфликтовать с текущими максимумами
|
Номера уточняются при реализации, чтобы не конфликтовать с максимумами master
|
||||||
(identity V3, academic V5, progress V9).
|
**до этой ветки** (identity V3, academic V5, progress V12); максимумы этой ветки
|
||||||
|
больше.
|
||||||
|
|
||||||
| Сервис | Миграции | Содержание |
|
| Сервис | Миграции | Содержание |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| identity | V4–V9 | роли, поля групп, статусы студентов, `membership_history`, `promotion_runs/items`, `accounts.status` |
|
| identity | V4–V9 | роли, поля групп, статусы студентов, `membership_history`, `promotion_runs/items`, `accounts.status` |
|
||||||
| academic | V6–V9 + post-bootstrap V10 | курсы, преподаватели, группы курса, `labs.course_id` (nullable), материалы курса/аудитории, частичные индексы, активы; `SET NOT NULL` — отдельный шаг после bootstrap |
|
| academic | V6–V9 + post-bootstrap V10 | курсы, преподаватели, группы курса, `labs.course_id` (nullable), материалы курса/аудитории, частичные индексы, активы; `SET NOT NULL` — отдельный шаг после bootstrap |
|
||||||
| progress | V10 (+ V11 при необходимости аудита) | `grade_comments.author_account_id`, `lab_grades.updated_by_account_id`, индекс `lab_grades(lab_id)`; аудит скачиваний — этап 6 |
|
| progress | V13 (+ V14 при необходимости аудита) | `grade_comments.author_account_id`, `lab_grades.updated_by_account_id`, индекс `lab_grades(lab_id)`; аудит скачиваний — этап 6 |
|
||||||
|
|
||||||
|
### Переход со старой feature-миграции V10 на V13
|
||||||
|
|
||||||
|
Старая `progress V10__profile_authors.sql` — временная feature-миграция, её нет
|
||||||
|
в master.
|
||||||
|
|
||||||
|
- **Production / master:** есть только V11 и V12, записи V10 нет — V13 применяется
|
||||||
|
обычным порядком, ничего делать не нужно.
|
||||||
|
- **Dev/feature-БД, где `V10__profile_authors.sql` уже применена и имеет
|
||||||
|
`success=true`:** удалить только эту запись истории, ничего не удаляя из схемы;
|
||||||
|
V13 идемпотентна и сама создаст недостающие колонки и индекс. Используйте
|
||||||
|
`flyway repair` или точечно:
|
||||||
|
`DELETE FROM progress.flyway_schema_history WHERE version = '10' AND script = 'V10__profile_authors.sql' AND success;`.
|
||||||
|
- **Staging-БД**, которые ненадолго запускали master-коммит `bfdae41` (out-of-order
|
||||||
|
+ V10), тоже содержат запись V10 — для них действует тот же порядок.
|
||||||
|
- **Если V10 осталась с `success=false`:** сначала убедитесь, что её частичные
|
||||||
|
изменения откатились на уровне объектов, затем `flyway repair` или удаление
|
||||||
|
неуспешной строки; V13 досоздаст недостающее.
|
||||||
|
- Перед очисткой и деплоем проверьте состояние через
|
||||||
|
`deploy/preflight/progress-v10-v13.sql`.
|
||||||
|
- Переход **forward-only**: после V13 откат на сборку без V13 не пройдёт валидацию
|
||||||
|
Flyway. Не оставляйте `out-of-order` включённым.
|
||||||
|
- **Нельзя** переставлять V11/V12.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,12 @@
|
|||||||
история членства, статусы аккаунтов;
|
история членства, статусы аккаунтов;
|
||||||
- academic `V6–V9`: курсы, преподаватели, группы курса, `labs.course_id`,
|
- academic `V6–V9`: курсы, преподаватели, группы курса, `labs.course_id`,
|
||||||
материалы курса/аудитории, индексы активов;
|
материалы курса/аудитории, индексы активов;
|
||||||
- progress `V10`: автор комментария и последнего изменения оценки.
|
- progress `V13`: автор комментария и последнего изменения оценки.
|
||||||
- Preflight-скрипты:
|
- Preflight-скрипты:
|
||||||
- `deploy/preflight/groups-courses.sql` — до миграций;
|
- `deploy/preflight/groups-courses.sql` — до миграций;
|
||||||
- `deploy/preflight/groups-courses-post.sql` — после миграций/bootstrap.
|
- `deploy/preflight/groups-courses-post.sql` — после миграций/bootstrap;
|
||||||
|
- `deploy/preflight/progress-v10-v13.sql` — переход старой feature-миграции
|
||||||
|
progress V10 на V13.
|
||||||
- UI: статус защиты в ведомости различает «готова» и «кончилось время».
|
- UI: статус защиты в ведомости различает «готова» и «кончилось время».
|
||||||
- Резервное копирование:
|
- Резервное копирование:
|
||||||
- `deploy/backup.sh` — БД + решения + материалы, checksums, retention,
|
- `deploy/backup.sh` — БД + решения + материалы, checksums, retention,
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
-- Автор комментария и последнего изменения оценки — для профиля студента курса.
|
|
||||||
-- Старые записи остаются без автора и отображаются как «автор не указан».
|
|
||||||
ALTER TABLE grade_comments ADD COLUMN author_account_id uuid;
|
|
||||||
ALTER TABLE lab_grades ADD COLUMN updated_by_account_id uuid;
|
|
||||||
|
|
||||||
-- Комментарии уже индексированы grade_comments_grade_idx (student_id, lab_id).
|
|
||||||
CREATE INDEX lab_grades_lab_idx ON lab_grades (lab_id);
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
-- V13: миграция профиля студента курса.
|
||||||
|
-- Номер V13, потому что V11 (attestations) и V12 (attestation_semester_and_publication)
|
||||||
|
-- уже существуют в master и применены в production; их порядок нельзя нарушать,
|
||||||
|
-- а V10 не может быть вставлена перед ними.
|
||||||
|
-- Автор комментария и последнего изменения оценки — для профиля студента курса.
|
||||||
|
-- Старые записи остаются без автора и отображаются как «автор не указан».
|
||||||
|
-- IF NOT EXISTS: безопасно, если старая feature-миграция V10 уже была применена вручную/dev.
|
||||||
|
ALTER TABLE grade_comments ADD COLUMN IF NOT EXISTS author_account_id uuid;
|
||||||
|
ALTER TABLE lab_grades ADD COLUMN IF NOT EXISTS updated_by_account_id uuid;
|
||||||
|
|
||||||
|
-- Комментарии уже индексированы grade_comments_grade_idx (student_id, lab_id).
|
||||||
|
CREATE INDEX IF NOT EXISTS lab_grades_lab_idx ON lab_grades (lab_id);
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
package ru.ysu.lms.progress.migration
|
||||||
|
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest
|
||||||
|
import org.springframework.boot.testcontainers.service.connection.ServiceConnection
|
||||||
|
import org.springframework.core.io.ClassPathResource
|
||||||
|
import org.springframework.core.io.Resource
|
||||||
|
import org.springframework.jdbc.datasource.init.ScriptUtils
|
||||||
|
import org.testcontainers.junit.jupiter.Container
|
||||||
|
import org.testcontainers.junit.jupiter.Testcontainers
|
||||||
|
import org.testcontainers.postgresql.PostgreSQLContainer
|
||||||
|
import java.sql.PreparedStatement
|
||||||
|
import java.sql.Statement
|
||||||
|
import javax.sql.DataSource
|
||||||
|
|
||||||
|
/**
|
||||||
|
* V13 идемпотентна: повторный запуск не должен падать, а колонки и индекс
|
||||||
|
* остаются в ожидаемом состоянии. Реальная PostgreSQL 18 (Testcontainers).
|
||||||
|
*/
|
||||||
|
@Testcontainers
|
||||||
|
@SpringBootTest
|
||||||
|
class ProfileAuthorsMigrationTest {
|
||||||
|
companion object {
|
||||||
|
@Container
|
||||||
|
@ServiceConnection
|
||||||
|
@JvmStatic
|
||||||
|
val postgres = PostgreSQLContainer("postgres:18")
|
||||||
|
|
||||||
|
private const val COLUMN_QUERY = """
|
||||||
|
SELECT data_type, is_nullable
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_schema = 'progress'
|
||||||
|
AND table_name = ?
|
||||||
|
AND column_name = ?
|
||||||
|
"""
|
||||||
|
|
||||||
|
private const val INDEX_QUERY = """
|
||||||
|
SELECT i.indisvalid, pg_get_indexdef(i.indexrelid) AS definition
|
||||||
|
FROM pg_index i
|
||||||
|
JOIN pg_class c ON c.oid = i.indexrelid
|
||||||
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||||
|
WHERE n.nspname = 'progress'
|
||||||
|
AND c.relname = 'lab_grades_lab_idx'
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private lateinit var dataSource: DataSource
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `V13 profile authors migration is idempotent`() {
|
||||||
|
val migration = ClassPathResource("db/migration/V13__profile_authors.sql")
|
||||||
|
|
||||||
|
repeat(2) { applyMigration(migration) }
|
||||||
|
|
||||||
|
assertThat(column("grade_comments", "author_account_id"))
|
||||||
|
.isEqualTo("uuid" to "YES")
|
||||||
|
assertThat(column("lab_grades", "updated_by_account_id"))
|
||||||
|
.isEqualTo("uuid" to "YES")
|
||||||
|
|
||||||
|
val index = labIndex()
|
||||||
|
assertThat(index).isNotNull
|
||||||
|
assertThat(index!!.first).isTrue()
|
||||||
|
assertThat(index.second).contains("lab_grades").contains("lab_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun applyMigration(migration: Resource) {
|
||||||
|
dataSource.connection.use { connection ->
|
||||||
|
// Flyway работает в схеме progress; сырой JDBC-коннект её не видит.
|
||||||
|
connection.createStatement().use { statement ->
|
||||||
|
statement.execute("SET search_path TO progress, public")
|
||||||
|
}
|
||||||
|
ScriptUtils.executeSqlScript(connection, migration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun column(
|
||||||
|
table: String,
|
||||||
|
column: String,
|
||||||
|
): Pair<String, String>? =
|
||||||
|
dataSource.connection.use { connection ->
|
||||||
|
connection.prepareStatement(COLUMN_QUERY.trimIndent()).use { statement ->
|
||||||
|
statement.setString(1, table)
|
||||||
|
statement.setString(2, column)
|
||||||
|
readColumn(statement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readColumn(statement: PreparedStatement): Pair<String, String>? =
|
||||||
|
statement.executeQuery().use { rows ->
|
||||||
|
if (rows.next()) {
|
||||||
|
rows.getString("data_type") to rows.getString("is_nullable")
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun labIndex(): Pair<Boolean, String>? =
|
||||||
|
dataSource.connection.use { connection ->
|
||||||
|
connection.createStatement().use { statement ->
|
||||||
|
readIndex(statement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readIndex(statement: Statement): Pair<Boolean, String>? =
|
||||||
|
statement.executeQuery(INDEX_QUERY.trimIndent()).use { rows ->
|
||||||
|
if (rows.next()) {
|
||||||
|
rows.getBoolean("indisvalid") to rows.getString("definition")
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user