다중 대상 참조와 빌드 변종
되돌렸습니다 — 참조가 내는 이름 §6.
foreign의 대상은 테이블 하나이고, 여러 테이블 중 하나여도 되는 값은 참조가 아니라 검사입니다(refs=A;B). 이 문서가 세운 검사는 그대로 살아 있고, 없어진 것은 승격과 그 위에 선 생성 표면입니다. 아래는 그 결정에 이르기까지의 기록입니다.상태: 단일 대상 접근자까지 구현됨. 다중 대상의 대상별 프로퍼티와 4절의 빌드 변종이 남았습니다
8절이 남겨 둔 대상별 프로퍼티는 대상별 접근자로 분리했습니다 — 실측하니 승격된 다중 대상이 3개가 아니라 31개이고, 레코드 멤버까지 합치면 187개였습니다
어떤 시트는 한 컬럼의 id가 여러 테이블 중 어느 하나에 있으면 된다고 적습니다. 그것을 표현할 자리가 없어서 그 시트의 검증이 막혀 있습니다.
이 개정은 검사까지입니다. 그 선언이 원본에서 무엇을 하는지 확인해 보니 대조뿐이었고, 그래서 먼저 대조를 세웠습니다. 대상을 컬럼 제약에 담은 것은 그 단계의 선택이지 최종 결론이 아닙니다.
다음 단계는 이것을
foreign으로 되돌립니다. 원본이 대조만 하는 것은 그쪽에 코드 생성이 없기 때문이고, 우리에게는 있습니다. 그러면 이 선언은 「한 컬럼에서 여러 테이블의 레코드에 닿는다」는 뜻이 되고, 대상별 가상 프로퍼티를 낼 수 있습니다 — 대조는 그때 부산물입니다. 8절에 그 설계를 적어 두었습니다.
1. 문제 — 검증 이식의 선행 조건
한 레이아웃의 제약 행은 대상을 여럿 적을 수 있습니다. 한 줄에 하나씩, 따옴표로 감싸서 적습니다.
:link "Mail" 단일 — 대상 하나를 적는 행
:links "CharGear"⏎"Item" 다중 — 둘 중 하나
선언이 576개 있고, 이 도구가 그 행을 읽지 않아 그 규칙이 전혀 검사되지 않았습니다.
막고 있는 것이 무엇인지는 실측되어 있습니다. 상점의 itemId를 Item 하나에만 대조하니
4,400건이 걸렸는데, 그 컬럼이 실제로 선언한 것은 Item 하나가 아니었습니다.
「여러 테이블 중 어느 하나」가 그 시트의 실제 규칙이고, 그것이 표현되기 전까지 상점·보상 계열의 규칙은 카탈로그를 손으로 나열합니다. 로드맵이 이 항목에 「검증 이식이 이것을 기다립니다」라고 적어 둔 것이 그 뜻입니다.
카탈로그는 둘입니다. 앞선 조사가
GearSlot·CharGear·Item셋이라고 적었는데, 시트를 읽어 보니Shop.ItemId의 선언은"CharGear"과"Item"둘입니다. 셋으로 적힌 문서들은 이 개정에서 함께 고쳤습니다.
2. 결정 — 검사와 해석의 분리
참조는 두 가지 일을 합니다. 이 둘은 비용이 완전히 다릅니다.
| 무엇 | 다중 대상에서 |
|---|---|
| 검사 — 이 id가 실재하는가 | 셋 중 하나에 있으면 통과. 정의가 분명하고, 와이어도 생성 코드도 관여하지 않습니다 |
| 해석 — 소비하는 쪽에 레코드를 물려 줌 | 어느 타입인가가 정해지지 않습니다. 모든 언어에 합 타입을 내는 일이고, 각 언어의 결과가 다릅니다 |
결정. 이 단계는 검사까지입니다. 그 컬럼은 int 컬럼 그대로이고, 값이 나열된 테이블 중
하나의 행 id인지를 변환 단계에서 검사합니다. 해석은 8절이 담습니다.
레코드 멤버별 옵셔널과 같은 갈래입니다 — 막고 있는 것은 검사이지 표현이 아니었습니다. 4,400건을 0건으로 만드는 것은 검사 쪽이고, 그것은 형식도 생성기도 건드리지 않습니다.
이 단계에서 해석을 담 지 않는 근거
순서입니다. 검사가 있어야 접근자가 맞는 레코드를 물리는지 판정할 수 있습니다. 그리고 검사는 형식도 생성기도 안 건드리므로, 여기서 끊으면 되돌릴 것이 없는 지점에서 한 번 멈추게 됩니다.
합 타입 때문이 아닙니다. 처음에는 그렇게 적었습니다 — 대상이 셋이면 소비하는 쪽이 받는
것이 「StatOperator 또는 WorldPassiveEffect」이고 모든 언어에 각자의 합 타입을 골라 줘야
한다는 것이었습니다. 8절이 그 전제를 치웁니다: 대상별 프로퍼티를 따로 내면 합 타입이
필요 없습니다.
3. 이 단계에서 모델이 받는 것 — 컬럼 제약
컬럼 제약의 항목 하나를 더합니다. 「이 컬럼의 값은 이 테이블들 중 하나의 행 id여야 한다」이고, 그것이 이 선언이 뜻하는 전부입니다.
foreign (참조) | 이 제약 |
|---|---|
| 대상 테이블 하나 | 대상 테이블 하나 이상 |
| 타입이 바뀝니다 — 값이 대상의 행이 됩니다 | 타입은 int 그대로 |
| 생성 코드가 레코드 프로퍼티를 냅니다 | 생성 코드 무관 |
| 와이어가 대상의 인덱스를 싣습니다 | 와이어 무관 — 이미 실리던 int입니다 |
:min·:max·값 화이트리스트와 같은 자리입니다 — 타입으로 나타낼 수 없는 것을 시트에서 읽어
어느 셀인지 함께 검사하고, 그 외에는 아무것도 하지 않습니다. 화이트리스트가 값의 목록이라면
이것은 값의 출처 목록입니다.
foreign은 이 단계에서 손대지 않습니다. 8절이 손댑니다.- 형식·생성기·모든 런타임 무변경. 검사를 더할 뿐입니다.
- 대상이 하나여도 같은 자리에 담습니다. 원본에서 그 선언은 대상이 하나든 셋이든 같은 역할이므로, 개수로 갈라 둘 곳을 나누지 않습니다.
- 적힌 테이블이 이 빌드에 하나라도 없으면 그 컬럼은 검사하지 않습니다. 아래.
빌드에 없는 대상 — 전부이거나 아무것도 아니거나
recipe가 고른 워크북만 읽으므로, 선언이 적은 테이블이 이 빌드에 없을 수 있습니다. 그때 남은 것들로 대조하면 없는 테이블 에 사는 id가 전부 위반이 됩니다 — 1절의 4,400건이 바로 그 형태이고, 카탈로그 하나를 빼고 검사한 결과였습니다.
그러므로 전부 있거나, 그 컬럼은 판정하지 않습니다. 부분 대조는 틀린 결과를 많이 내는 쪽이지 적게 내는 쪽이 아닙니다.
거부가 아니라 경고입니다. 모델은 오타와 「이 빌드가 안 읽는 워크북의 테이블」을 구별할 수
없고, 거부하면 넓은 빌드를 겨냥한 선언 하나가 좁은 빌드를 전부 멈춥니다. 더 엄격하게 읽고
싶은 파이프라인에는 이미 TreatWarningsAsErrors가 있습니다 —
asset이 없는 파일을 다루는 방식과
같은
자리입니다.
검사의 정의
대상 중 하나라도 그 id를 가지면 통과합니다. 어느 것인지는 기록하지 않습니다 — 기록하면 그것이 해석이고, 2절이 담지 않기로 한 것입니다.
| 경우 | 판정 |
|---|---|
| 셋 중 하나에 있음 | 통과 |
| 어디에도 없음 | 거부 — 셀 위치와, 어느 테이블들을 찾아봤는지 함께 적습니다 |
| 둘 이상에 있음 | 통과. 그 시트의 규칙이 「어느 하나」이므로 모호함이 아닙니다 |
| 셀이 비어 있음 | 통과 — 값이 없으면 대조할 것이 없습니다 |
세 번째가 판단이 필요한 자리인데, 거부하지 않는 이유는 id 대역이 테이블마다 갈라져 있는 것이 그 시트의 규칙이 아니기 때문입니다. 겹침을 문제로 보는 프로젝트라면 그것은 별도의 규칙이고, 검증 파이프라인이 이미 그런 규칙을 적는 자리입니다.
원본이 하는 것 — 실제 검사기를 읽고 확인한 것
이 규칙의 출처는 원본의 검사 스크립트이고, 거기서 확인한 것이 셋입니다.
| 무엇 | 원본 |
|---|---|
| 대조하는 키 | 그 컬럼의 값 그 자체. 대상의 산출물이 id를 최상위 키로 하는 map이라 조회가 키 룩업입니다 — 즉 대상의 기본 인덱스입니다 |
| 대상 하나의 표기 | 파일/테이블. /가 없으면 파일 이름이 곧 테이블 이름입니다. 코어가 받는 것은 테이블 이름 쪽입니다 |
| 값이 없을 때 | 통과. 검사에 들어가기 전에 돌아갑니다 |
| 대상이 없는 빌드 | 해당 없음. 원본은 언제나 산출물 전체를 놓고 돌므로 이 경우가 생기지 않습니다 — 3절의 마지막 항목이 그래서 이 도구의 결정입니다 |
단수 행도 있습니다. 대상 하나를 적는 행과 목록을 적는 행이 따로 있고, 역할은 대상의 개수만 다릅니다. 3절이 둘을 하나로 받는 근거입니다 — 개수는 목록의 길이일 뿐입니다.
0을 어떻게 볼지는 실측으로 정합니다. 원본은0을 특별 취급하지 않습니다 — 값이 있는 것으로 보고0이라는 키를 실제로 찾습니다. 저희foreign은0을 「아무것도 가리키지 않음」으로 통과시키는데, 이 제약은 출처가 다르므로 그 규약을 물려받을 이유가 없습니다. 통과시킬 때와 아닐 때 걸리는 행 수를 세면 그 시트가0을 무슨 뜻으로 쓰는지 나오므로, 재고 나서 정합니다.
4. _BC 빌드 변종 — 다른 축
같은 항목에 묶여 있지만 다른 문제입니다.
한 레이아웃은 같은 테이블의 지역별 대체본을 이름의 접미사로 적습니다 — Profile_BCGL,
Crest_BCCN. 산출물 615개 중 95개가 그 짝이고, 고르는 것은 로드 시점의 지역 코드입니다.
TargetSide와 같은 축이 아닙니다. 서버/클라는 한 테이블을 좁히는 것이고, 변종은
여러 테이블 중 하나를 고르는 것입니다.
결정. 이 개정에서는 담지 않습니다. 접미사가 붙은 것을 각각 별개의 테이블로 둡니다 — 지금 동작이 그것이고, 이름이 다르므로 충돌하지 않습니다.
미루는 근거가 둘입니다.
- 고르는 시점이 빌드가 아니라 로드입니다. 이 도구가 고르면 산출물이 지역마다 갈라지고, 그것은 그쪽이 지금 하는 방식이 아닙니다. 한 번 내보내고 클라이언트가 고르는 구조라면 이 도구가 할 일은 둘 다 내보내는 것이고, 그것은 이미 되고 있습니다.
- 표현을 정하려면 소비하는 쪽을 봐야 합니다. 생성 코드가
Profile이라는 이름 하나로 지역에 맞는 것을 돌려주려면 로드 시점의 선택을 모든 런타임이 알아야 합니다. 3절의 검사와 달리 이것은 런타임의 일이고, 요구가 확인되기 전에는 정할 것이 아닙니다.
이 문서가 그것을 여기 적어 두는 이유는 묶여 있던 두 문제를 갈라 두기 위해서입니다. 참조 쪽은 막고 있는 것이 분명하고, 변종 쪽은 그렇지 않습니다.
5. 담지 않는 것
아래는 이 단계가 담지 않는 것입니다. 앞의 둘은 8절이 담습니다.
- 다중 대상의 해석. 2절 · 8절.
foreign을 다중 대상으로 넓히는 것. 3절 · 8절._BC변종의 선택. 4절. 이것만은 다음 단계에도 없습니다.- 대상별 id 대역의 검사.
:min/:max