# 함수 설계서: `addLocalSqlTrace` (#567)

> **부모 설계서**: ./README.md · **상태**: Approved
> **작성**: [AI] Architect · **구현**: `src/main/java/com/cloudhandson/vpdbackoffice/service/OrdsProbeService.java:addLocalSqlTrace` · **테스트**: `ProbeResultTest`, `mvn test`

## 1. 시그니처

```java
private ProbeResult addLocalSqlTrace(ProbeResult result, String bearerToken, ProtectedObject object)
```

## 2. 책임 (단일 책임, 1줄)

ORDS 응답에 trace가 없을 때 DB predicate와 보호 객체 컬럼으로 확인용 effective SQL을 만든다.

## 3. 입력

| 파라미터 | 타입 | 제약/검증 | 설명 |
|----------|------|-----------|------|
| `result` | `ProbeResult` | non-null | 이미 파싱된 성공/0행 결과 |
| `bearerToken` | `String` | 원문은 메모리에서만 사용 | DB context setter에 전달할 토큰 |
| `object` | `ProtectedObject` | 활성·식별자 검증 완료 | SQL FROM 대상 |

## 4. 출력

- **반환**: predicate와 effective SQL이 부착된 새 `ProbeResult`; 조회할 수 없으면 원 결과.
- **부수효과**: predicate 조회는 `findVpdPredicate`를 통한 DB I/O다. 결과 rows/status/evidence는 변경하지 않는다.

## 5. 동작 / 알고리즘

1. bearer/object로 `findVpdPredicate`를 호출한다.
2. predicate가 없으면 원 결과를 반환한다.
3. 보호 객체의 등록 컬럼을 `o.COLUMN` 목록으로 만든다.
4. `SELECT columns FROM owner.object o WHERE (predicate) AND ROWNUM <= ...` 문자열을 만든다.
5. `ProbeResult.withSqlTrace`로 불변 결과를 반환한다.

## 6. 에러 & 실패 모드

| 조건 | 처리 | 반환/예외 |
|------|------|-----------|
| context/predicate DB 오류 | `findVpdPredicate`가 null 반환 | 원 결과 |
| 컬럼 catalog 오류 | runtime exception을 경계에서 흡수 | 원 결과 |
| 컬럼 목록 empty | trace 생성 생략 | 원 결과 |
| vector object | 호출부에서 이 함수 실행을 생략 | 전용 Handler trace만 사용 |

## 7. 엣지케이스

- 0행 결과도 호출 가능해야 한다.
- predicate의 `SYS_CONTEXT` 표현은 실제 값으로 치환하지 않는다.
- 컬럼명은 보호 객체 catalog에서 가져오며 임의 입력을 SQL에 추가하지 않는다.
- token은 반환 문자열·로그에 포함하지 않는다.

## 8. 복잡도 / 성능

- DB predicate 조회 1회와 컬럼 cache 조회 1회. 컬럼 수를 `n`이라 하면 SQL 문자열 조합은 `O(n)`이다.
- ORDS trace가 없는 경우에만 추가 DB 연결 작업을 수행한다.

## 9. 의존성

- `findVpdPredicate`, `ProtectedObjectService.findColumns`, `ProbeResult.withSqlTrace`.
- `ADMIN.CB_AGENT_DOC_VPD_FILTER`와 보호 객체 catalog.

## 10. 테스트 케이스

- [x] trace 부착 후 rows/status/rowCount 보존.
- [ ] predicate 조회 실패 시 원 결과 유지.
- [ ] empty columns 시 trace 생략.
- [ ] vector object는 호출부에서 생략.

## 11. 추적성

- 인수조건: #567의 “유효 토큰 조회 결과에 predicate/effective SQL 표시”.
- 관련 ADR: 없음.
