diff --git a/ordinis-migrations/src/main/resources/db/changelog/changes/0016-record-dependents-index.xml b/ordinis-migrations/src/main/resources/db/changelog/changes/0016-record-dependents-index.xml index 383c0ff..4459b59 100644 --- a/ordinis-migrations/src/main/resources/db/changelog/changes/0016-record-dependents-index.xml +++ b/ordinis-migrations/src/main/resources/db/changelog/changes/0016-record-dependents-index.xml @@ -29,7 +29,6 @@ pure JSONB indexing (jsonb_each + ?-marker) — не ожидаем больше. --> - MV record_dependents_index: precomputed reverse FK @@ -37,6 +36,7 @@ + MV record_dependents_index: precomputed reverse FK 'properties') AS prop(key, value) ON true - WHERE prop.value ? 'x-references' - AND prop.value->>'x-references' ~ '^[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*$' - AND r.data ? prop.key + -- Note: избегаем JSONB ?-operator — Liquibase прогоняет SQL через + -- PreparedStatement, который любой ? интерпретирует как $N + -- placeholder → "syntax error at $1". Заменяем на эквиваленты: + -- prop.value ? 'x-references' → prop.value -> 'x-references' IS NOT NULL + -- r.data ? prop.key → r.data -> prop.key IS NOT NULL + -- Регекс с $ anchor по той же причине заменён на LIKE — split_part'ы + -- ниже сами справятся с malformed (вернут empty strings, никогда не + -- match-ятся с real records). + WHERE prop.value -> 'x-references' IS NOT NULL + AND prop.value->>'x-references' LIKE '%.%' + AND r.data -> prop.key IS NOT NULL AND jsonb_typeof(r.data -> prop.key) = 'string' WITH NO DATA; ]]> diff --git a/ordinis-rest-api/src/main/java/cloud/nstart/terravault/ordinis/restapi/service/reference/LineageIndexService.java b/ordinis-rest-api/src/main/java/cloud/nstart/terravault/ordinis/restapi/service/reference/LineageIndexService.java index fb66efc..97564c4 100644 --- a/ordinis-rest-api/src/main/java/cloud/nstart/terravault/ordinis/restapi/service/reference/LineageIndexService.java +++ b/ordinis-rest-api/src/main/java/cloud/nstart/terravault/ordinis/restapi/service/reference/LineageIndexService.java @@ -209,8 +209,11 @@ public class LineageIndexService { int page, int size) { if (page < 0) throw new IllegalArgumentException("page must be >= 0"); - if (size < 1 || size > 200) { - throw new IllegalArgumentException("size must be 1..200, got " + size); + // Service-level cap = 500 (CascadeCloseService запрашивает up to + // CASCADE_MAX_PER_REQUEST). Controller separately enforces 200 cap для + // public endpoint — UI не нуждается в больше. + if (size < 1 || size > 500) { + throw new IllegalArgumentException("size must be 1..500, got " + size); } Optional targetOpt = definitionRepository.findByName(targetDictName); diff --git a/ordinis-rest-api/src/test/java/cloud/nstart/terravault/ordinis/restapi/service/reference/LineageIndexServiceTest.java b/ordinis-rest-api/src/test/java/cloud/nstart/terravault/ordinis/restapi/service/reference/LineageIndexServiceTest.java index 03b403d..37b9c02 100644 --- a/ordinis-rest-api/src/test/java/cloud/nstart/terravault/ordinis/restapi/service/reference/LineageIndexServiceTest.java +++ b/ordinis-rest-api/src/test/java/cloud/nstart/terravault/ordinis/restapi/service/reference/LineageIndexServiceTest.java @@ -206,7 +206,7 @@ class LineageIndexServiceTest { .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("size"); assertThatThrownBy(() -> service.findRecordDependents( - "d", "k", Set.of(DataScope.PUBLIC), 0, 201)) + "d", "k", Set.of(DataScope.PUBLIC), 0, 501)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("size"); }