Skip to content

Commit 7bbceb2

Browse files
committed
자동 포멧팅 기능 개선
1 parent 14e7e49 commit 7bbceb2

79 files changed

Lines changed: 12811 additions & 209 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

change.md

Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4089,3 +4089,338 @@ registry helper를 사용하도록 바꾸고 production completion 재현 테스
40894089
| `cargo test` | 전체 6,745 통과 · 235 ignored · 실패 0 · doc-test 실패 0 |
40904090
| `cargo clippy --locked --all-targets -- -D warnings -W clippy::perf -W clippy::complexity` | 통과, 경고 0 |
40914091
| `cargo fmt --all -- --check` / `git diff --check` | 통과 |
4092+
4093+
# 30차: 공식 매뉴얼 문법 final 3종 전수 인증 (2026-07-17)
4094+
4095+
## 30-1. 신규 final 스크립트와 실제 실행
4096+
4097+
기존 fixture를 재사용하지 않고 Oracle, MySQL, MariaDB 공식 매뉴얼의 문법군을 기준으로
4098+
각 DB용 `final.sql`을 새로 작성했다. 세 스크립트는 Space Query의 production 실행 경로로
4099+
각 대상 DB에 실행해 모두 정상 완료를 확인했다.
4100+
4101+
- Oracle: `test/final.sql`
4102+
- MySQL: `test_mysql/final.sql`
4103+
- MariaDB: `test_mariadb/final.sql`
4104+
4105+
## 30-2. 하이라이팅과 인텔리센스 전수 검증
4106+
4107+
하이라이팅 sweep은 66개 파일, 83,402단어를 검사했다. catalog 단어 45,625개 중
4108+
45,081개는 직접 하이라이트되고 544개는 문맥상 식별자로 판정됐으며, object 4,480개는
4109+
전부 하이라이트됐다. unexpected highlight 0, failure 0으로 production 수정이 필요한
4110+
잔여 오류는 없었다.
4111+
4112+
인텔리센스 final 리포트는 Oracle 4,819개, MySQL 1,117개, MariaDB 418개 추천 위치를
4113+
검사해 모두 missing 0이었다. 전체 fixture sweep에서 발견한 MySQL `DELIMITER` 문맥
4114+
차이는 재현 테스트를 먼저 추가하고 테스트가 production completion과 같은 흐름을
4115+
사용하도록 맞췄다. 수정 후 해당 sweep은 707개 후보 missing 0이었다.
4116+
4117+
100만 줄 이상 문서의 production/snapshot/shadow completion 성능 회귀 5건은 8.87초에
4118+
모두 통과했다. completion은 전체 문서를 다시 순회하지 않고 상한이 있는 token window와
4119+
국소 symbol snapshot만 사용한다.
4120+
4121+
## 30-3. 포맷 sweep 66개·53,361줄 전수 육안 검토
4122+
4123+
`formatting_sweep_all_files_generate_out_report`로 생성한 `target/format-sweep` 아래
4124+
66개 `.format.out`, 최종 53,361줄을 처음부터 끝까지 검토했다. 자동 PASS를 그대로
4125+
신뢰하지 않고 원문과 결과를 대조했으며, `docs/auto_format_rule.md`의 frame 단일 깊이
4126+
원천, 문법적 부모, first-child-inline, structural body frame, closing owner depth,
4127+
canonical/idempotent 원칙으로 판단했다.
4128+
4129+
자동 검사만으로는 잡히지 않은 네 문법군을 육안 검토에서 발견했다. 각 오류는 먼저
4130+
독립 재현 테스트를 추가해 실패를 확인한 뒤 production formatter의 문법 owner를
4131+
수정했다.
4132+
4133+
### Oracle PROPERTY GRAPH의 TABLES/KEY/PROPERTIES 소유 관계
4134+
4135+
AS-IS:
4136+
4137+
```sql
4138+
CREATE PROPERTY GRAPH graph_cert
4139+
VERTEX TABLES (graph_node KEY (node_id) LABEL node PROPERTIES (node_id, node_name))
4140+
EDGE TABLES (graph_edge KEY (edge_id) SOURCE KEY (source_node_id) REFERENCES graph_node (node_id) DESTINATION KEY (target_node_id) REFERENCES graph_node (node_id) LABEL owns PROPERTIES (edge_label, edge_weight));
4141+
```
4142+
4143+
TO-BE:
4144+
4145+
```sql
4146+
CREATE PROPERTY GRAPH graph_cert
4147+
VERTEX TABLES (graph_node
4148+
KEY (node_id)
4149+
LABEL node
4150+
PROPERTIES (node_id,
4151+
node_name)
4152+
)
4153+
EDGE TABLES (graph_edge
4154+
KEY (edge_id)
4155+
SOURCE KEY (source_node_id) REFERENCES graph_node (node_id)
4156+
DESTINATION KEY (target_node_id) REFERENCES graph_node (node_id)
4157+
LABEL owns
4158+
PROPERTIES (edge_label,
4159+
edge_weight)
4160+
);
4161+
```
4162+
4163+
`VERTEX TABLES``EDGE TABLES`를 명시적 parenthesized owner로 추가하고,
4164+
`KEY`/`SOURCE KEY`/`DESTINATION KEY`/`LABEL`/`PROPERTIES`를 그 자식으로 분류했다.
4165+
`PROPERTIES` 내부 comma-list도 별도 owner를 사용하므로 100만 줄 문서에서 주변 전체를
4166+
재탐색하지 않는다.
4167+
4168+
### Oracle MATERIALIZED VIEW LOG 절 소유 관계
4169+
4170+
AS-IS:
4171+
4172+
```sql
4173+
CREATE MATERIALIZED VIEW LOG
4174+
ON sq_oracle_manual_log WITH PRIMARY KEY,
4175+
ROWID (category,
4176+
amount) INCLUDING NEW VALUES;
4177+
```
4178+
4179+
TO-BE:
4180+
4181+
```sql
4182+
CREATE MATERIALIZED VIEW LOG ON sq_oracle_manual_log
4183+
WITH PRIMARY KEY,
4184+
ROWID (category,
4185+
amount)
4186+
INCLUDING NEW VALUES;
4187+
```
4188+
4189+
`ON`은 CREATE header에 유지하고, `WITH` option-list와 `INCLUDING`을 각각 동일 statement의
4190+
명시적 clause로 만들었다.
4191+
4192+
### MariaDB/MySQL VIEW의 `ALGORITHM = MERGE`
4193+
4194+
AS-IS:
4195+
4196+
```sql
4197+
CREATE OR REPLACE ALGORITHM =
4198+
MERGE VIEW statement_log_v AS
4199+
SELECT id
4200+
FROM statement_log;
4201+
```
4202+
4203+
TO-BE:
4204+
4205+
```sql
4206+
CREATE OR REPLACE ALGORITHM = MERGE VIEW statement_log_v AS
4207+
SELECT id
4208+
FROM statement_log;
4209+
```
4210+
4211+
`MERGE``ALGORITHM =`의 값일 때는 독립 MERGE DML opener가 아니므로 structural break를
4212+
만들지 않게 했다.
4213+
4214+
### MariaDB/MySQL EVENT의 `DO` 본문
4215+
4216+
AS-IS:
4217+
4218+
```sql
4219+
CREATE EVENT syntax_event
4220+
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
4221+
ON COMPLETION PRESERVE DISABLE COMMENT 'disabled event' DO UPDATE statement_log
4222+
SET amount = amount
4223+
WHERE id = -1;
4224+
```
4225+
4226+
TO-BE:
4227+
4228+
```sql
4229+
CREATE EVENT syntax_event
4230+
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
4231+
ON COMPLETION PRESERVE DISABLE
4232+
COMMENT 'disabled event'
4233+
DO
4234+
UPDATE statement_log
4235+
SET amount = amount
4236+
WHERE id = -1;
4237+
```
4238+
4239+
CREATE EVENT를 명시적 construct로 추적하고 `COMMENT`/`DO`를 event clause로,
4240+
`DO` 뒤 실제 SQL을 structural body frame으로 관리한다.
4241+
4242+
## 30-4. 추가 자동 포맷 회귀 수정
4243+
4244+
final 3종의 1차 sweep에서 발견한 나머지 문법도 모두 재현 테스트를 먼저 추가했다.
4245+
4246+
### prepared `EXECUTE ... USING`, transaction/XA/SHOW
4247+
4248+
AS-IS:
4249+
4250+
```sql
4251+
EXECUTE prepared_select
4252+
USING @prepared_amount, @prepared_category;
4253+
START
4254+
TRANSACTION READ WRITE;
4255+
COMMIT AND
4256+
NO CHAIN;
4257+
XA
4258+
START 'sq-final-xa';
4259+
```
4260+
4261+
TO-BE:
4262+
4263+
```sql
4264+
EXECUTE prepared_select USING @prepared_amount, @prepared_category;
4265+
START TRANSACTION READ WRITE;
4266+
COMMIT AND NO CHAIN;
4267+
XA START 'sq-final-xa';
4268+
```
4269+
4270+
prepared EXECUTE의 USING-list를 production list owner에 연결했다. MySQL/MariaDB의
4271+
`START TRANSACTION`, `SHOW CREATE`, `XA START/END`는 client tool/control opener가 아니라
4272+
server SQL 문법으로 판정하고, `COMMIT AND [NO] CHAIN`은 boolean condition으로 분리하지
4273+
않게 했다.
4274+
4275+
### Oracle `EXEC` bind, `EXPLAIN PLAN`
4276+
4277+
AS-IS:
4278+
4279+
```sql
4280+
EXEC
4281+
:b_inout := 10;
4282+
4283+
EXPLAIN PLAN SET STATEMENT_ID = 'SQ_ORACLE_FINAL'
4284+
FOR
4285+
SELECT category, SUM(amount)
4286+
FROM sq_oracle_manual_log
4287+
GROUP BY category;
4288+
```
4289+
4290+
TO-BE:
4291+
4292+
```sql
4293+
EXEC :b_inout := 10;
4294+
4295+
EXPLAIN PLAN SET STATEMENT_ID = 'SQ_ORACLE_FINAL'
4296+
FOR SELECT category,
4297+
SUM(amount)
4298+
FROM sq_oracle_manual_log
4299+
GROUP BY category;
4300+
```
4301+
4302+
Oracle bind assignment의 `EXEC :name`은 줄 단위 tool command 자동 종결 대상에서 제외했다.
4303+
`EXPLAIN PLAN ... FOR`는 procedural FOR-loop가 아니라 explain statement의 clause로
4304+
판정하고 뒤 SELECT의 query/list owner를 정상 생성한다.
4305+
4306+
## 30-5. 최종 포맷 결과
4307+
4308+
요청된 명령을 그대로 실행한 최종 포맷 sweep은 1 passed, 0 failed였다. 생성된
4309+
66개 `.format.out` 모두 `status: PASS`, issue 0이며, 수정된 파일의 재생성 결과까지
4310+
다시 육안 대조해 최종 검토 수는 66개·53,361줄이다.
4311+
4312+
## 30-6. 전체 테스트에서 발견한 production 경로 정합성 수정
4313+
4314+
전체 `cargo test`는 개별 sweep이 놓칠 수 있는 inventory와 production 조합을 추가로
4315+
검사했다. 실패 건은 기존 테스트 또는 새 재현 테스트로 먼저 고정한 다음 수정했다.
4316+
4317+
### Oracle `SET TRANSACTION`의 선택적 `NAME`
4318+
4319+
AS-IS:
4320+
4321+
```sql
4322+
SET TRANSACTION READ WRITE |;
4323+
-- suggestions: []
4324+
```
4325+
4326+
TO-BE:
4327+
4328+
```sql
4329+
SET TRANSACTION READ WRITE NAME 'batch_tx';
4330+
-- suggestions at |: [NAME]
4331+
```
4332+
4333+
Oracle 공식 문법에 따라 `READ ONLY`, `READ WRITE`, `ISOLATION LEVEL SERIALIZABLE`,
4334+
`ISOLATION LEVEL READ COMMITTED` 뒤에 선택적인 `NAME`을 production grammar table에서
4335+
추천한다. prefix가 비어 있을 때와 입력 중일 때 동일한 경로를 사용한다.
4336+
4337+
### MySQL/MariaDB DATABASE 대상과 qualified-member 차단
4338+
4339+
AS-IS:
4340+
4341+
```sql
4342+
DROP DATABASE IF EXISTS qt_m|;
4343+
-- suggestions: []
4344+
4345+
SHOW CREATE DATABASE app.|;
4346+
-- suggestions: [EMP, EMP_VIEW, EMP_PROC, ...]
4347+
```
4348+
4349+
TO-BE:
4350+
4351+
```sql
4352+
DROP DATABASE IF EXISTS qt_mysql_final_boss;
4353+
-- suggestions at qt_m|: [qt_mysql_final_boss]
4354+
4355+
SHOW CREATE DATABASE app.|;
4356+
-- suggestions: []
4357+
```
4358+
4359+
`ALTER/DROP/SHOW CREATE DATABASE|SCHEMA`의 대상은 전용 `Database` object kind로
4360+
분류한다. 따라서 현재 파일과 database catalog의 이름은 추천하지만, 점 뒤에는
4361+
schema의 테이블·뷰·루틴 멤버를 열지 않는다. 테스트와 production 모두 동일한
4362+
qualified-completion entry를 사용한다.
4363+
4364+
### SQL*Plus slash와 REMARK의 원자적 분할
4365+
4366+
AS-IS:
4367+
4368+
```sql
4369+
END
4370+
/ remark execute block
4371+
SELECT 1 FROM DUAL;
4372+
```
4373+
4374+
```text
4375+
Statement("CREATE PROCEDURE ... END")
4376+
Slash
4377+
Statement("remark execute block")
4378+
Statement("SELECT 1 FROM DUAL")
4379+
```
4380+
4381+
TO-BE:
4382+
4383+
```text
4384+
Statement("CREATE PROCEDURE ... END")
4385+
Slash
4386+
Statement("SELECT 1 FROM DUAL")
4387+
```
4388+
4389+
slash 뒤 `REM`/`REMARK`는 parser engine이 이미 하나의 slash terminator/comment로
4390+
분류한다. concatenated-command 복구가 이를 다시 `/`와 SQL 조각으로 나누지 않도록
4391+
shared slash classifier를 먼저 적용한다.
4392+
4393+
### MySQL session setting의 typed residue
4394+
4395+
AS-IS:
4396+
4397+
```sql
4398+
SET autocommit = 1, sql_notes = 0;
4399+
-- sql_notes를 unknown session state로만 기록
4400+
```
4401+
4402+
TO-BE:
4403+
4404+
```sql
4405+
SET autocommit = 1, sql_notes = 0;
4406+
-- autocommit 상태와 session setting residue를 각각 typed state로 기록
4407+
```
4408+
4409+
일반 세션 설정을 `may_have_session_setting`으로 분리해 물리 세션 보존 판단은 유지하면서
4410+
unknown 상태의 의미를 좁혔다. `SET`의 우변에 등장한 `@var`는 assignment target이
4411+
아니므로 user-variable residue로 잘못 기록하지 않는다.
4412+
4413+
## 30-7. 최종 품질 게이트
4414+
4415+
| 검증 | 결과 |
4416+
| --- | --- |
4417+
| Space Query 실제 실행 | Oracle/MySQL/MariaDB `final.sql` 3개 모두 정상 완료 |
4418+
| `syntax_highlighting_sweep_all_files_generate_out_report` | 66개 파일 · 83,402단어 · unexpected 0 · failure 0 |
4419+
| final 인텔리센스 리포트 | Oracle 4,819개 · MySQL 1,117개 · MariaDB 418개, missing 0 |
4420+
| 전체 fixture 인텔리센스 회귀 | MySQL-family 보강 707개 후보, missing 0 |
4421+
| `million_line_` | production/snapshot/shadow 5건 통과, 8.87초 |
4422+
| `formatting_sweep_all_files_generate_out_report` | 통과, 66개 `.format.out` · issue 0 |
4423+
| 전수 상세 검토 | 66개 · 53,361줄 · 잔여 오류 0 |
4424+
| `cargo test` | library 6,623 통과 · 234 ignored · 통합/가드/doc-test 실패 0 |
4425+
| `cargo clippy --locked --all-targets -- -D warnings -W clippy::perf -W clippy::complexity` | 통과, 경고 0 |
4426+
| `cargo fmt --all -- --check` / `git diff --check` | 통과 |

0 commit comments

Comments
 (0)