fix #495: add schema preflight and DDL details

This commit is contained in:
devmrko
2026-06-26 16:32:38 +09:00
parent cacf7b2bc4
commit 5d864379bd
8 changed files with 922 additions and 182 deletions

View File

@@ -10,10 +10,15 @@
</div>
<div class="alert alert-success" th:if="${message}" th:text="${message}"></div>
<div class="alert alert-danger" th:if="${error}" th:text="${error}"></div>
<div class="alert alert-warning" th:if="${runtimeErrorMessage}">
<strong th:text="${runtimeErrorTitle}">DB 준비 필요</strong>
<div th:text="${runtimeErrorMessage}">지원 테이블을 생성하세요.</div>
</div>
<div class="alert alert-warning" th:if="${schemaPreflightErrorMessage}">
<strong th:text="${schemaPreflightErrorTitle}">DB 준비 상태 확인 불가</strong>
<div th:text="${schemaPreflightErrorMessage}">DB 연결을 확인하세요.</div>
</div>
<section class="content-band">
<h2>ORDS</h2>
@@ -27,10 +32,97 @@
</form>
</section>
<section class="content-band mt-3" th:if="${schemaPreflight}">
<div class="section-heading">
<div>
<h2>DB 준비 상태</h2>
<p>현재 연결 사용자 기준으로 백오피스 메타데이터, VPD runtime, ORDS runtime, grant 상태를 점검합니다.</p>
</div>
</div>
<div class="schema-summary">
<div>
<span>현재 연결 사용자</span>
<strong th:text="${schemaPreflight.currentUser()}">ADMIN</strong>
</div>
<div>
<span>권장 ORDS parsing schema</span>
<strong th:text="${schemaPreflight.recommendedOrdsSchema()}">CB_ORDS</strong>
</div>
<div>
<span>OK</span>
<strong th:text="${schemaPreflight.okCount()}">0</strong>
</div>
<div>
<span>WARN</span>
<strong th:text="${schemaPreflight.warnCount()}">0</strong>
</div>
<div>
<span>MISSING</span>
<strong th:text="${schemaPreflight.missingCount()}">0</strong>
</div>
<div>
<span>ERROR</span>
<strong th:text="${schemaPreflight.errorCount()}">0</strong>
</div>
</div>
<div class="alert alert-info mt-3 mb-3" th:if="${schemaPreflight.hasActionNeeded()}">
앱에서 실행 가능한 항목은 아래 `지원 테이블 생성/확인` 버튼으로 보강하고, `sqlcl 필요` 항목은 preview 순서대로 DB 권한을 가진 세션에서 실행하세요.
</div>
<div class="table-responsive">
<table class="table table-sm align-middle schema-preflight-table">
<thead>
<tr>
<th>Layer</th>
<th>Item</th>
<th>Type</th>
<th>Status</th>
<th>Detail</th>
<th>Next Action</th>
</tr>
</thead>
<tbody>
<tr th:each="check : ${schemaPreflight.checks()}">
<td th:text="${check.layer()}">Backoffice Metadata</td>
<td><code th:text="${check.itemName()}">CB_APP_USER</code></td>
<td th:text="${check.objectType()}">TABLE</td>
<td>
<span class="badge"
th:classappend="${check.ok()} ? ' text-bg-success' : (${check.warning()} ? ' text-bg-warning' : (${check.missing()} ? ' text-bg-secondary' : ' text-bg-danger'))"
th:text="${check.status()}">OK</span>
</td>
<td th:text="${check.detail()}">존재합니다.</td>
<td>
<span class="badge" th:classappend="${check.sqlclRequired()} ? ' text-bg-warning' : ' text-bg-info'"
th:text="${check.sqlclRequired()} ? 'sqlcl 필요' : '앱 실행 가능'">앱 실행 가능</span>
<div class="mt-1" th:text="${check.nextAction()}">조치 없음</div>
</td>
</tr>
</tbody>
</table>
</div>
</section>
<section class="content-band mt-3" th:if="${schemaPreflight}">
<h2>SQL Preview</h2>
<p class="text-muted mb-3">
앱 버튼이 실행할 SQL과 sqlcl로 실행할 runtime 준비 순서를 구분해서 확인합니다.
</p>
<div class="schema-preview-grid">
<details open>
<summary>앱에서 실행하는 지원 DDL</summary>
<pre class="schema-sql-preview" th:text="${schemaPreflight.appDdlPreview()}">CREATE TABLE ...</pre>
</details>
<details>
<summary>sqlcl로 실행할 VPD/ORDS runtime 순서</summary>
<pre class="schema-sql-preview" th:text="${schemaPreflight.sqlclScript()}">@sql/adb/...</pre>
</details>
</div>
</section>
<section class="content-band mt-3">
<h2>DB 스키마 초기화</h2>
<p class="text-muted mb-3">
현재 연결된 DB에 백오피스가 사용하는 지원 테이블 시퀀스 생성하거나 보강합니다.
현재 연결된 DB 사용자에 백오피스 지원 테이블, 시퀀스, 컬럼을 생성하거나 보강합니다. VPD context, ORDS enablement, grant는 sqlcl preview 순서를 사용하세요.
</p>
<form method="post" action="/settings/schema/initialize" class="inline-form">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
@@ -44,6 +136,7 @@
<th>Action</th>
<th>Status</th>
<th>Message</th>
<th>SQL</th>
</tr>
</thead>
<tbody>
@@ -52,10 +145,17 @@
<td th:text="${result.action()}">TABLE</td>
<td>
<span class="badge"
th:classappend="${result.status() == 'CREATED' || result.status() == 'MERGED'} ? ' text-bg-success' : (${result.status() == 'EXISTS'} ? ' text-bg-secondary' : ' text-bg-danger')"
th:classappend="${result.status() == 'CREATED' || result.status() == 'MERGED' || result.status() == 'UPDATED'} ? ' text-bg-success' : (${result.status() == 'EXISTS'} ? ' text-bg-secondary' : ' text-bg-danger')"
th:text="${result.status()}">CREATED</span>
</td>
<td th:text="${result.message()}">생성했습니다.</td>
<td>
<details th:if="${result.sqlText()}">
<summary>보기</summary>
<pre class="table-pre" th:text="${result.sqlText()}">CREATE TABLE ...</pre>
</details>
<span class="text-muted" th:unless="${result.sqlText()}">-</span>
</td>
</tr>
</tbody>
</table>