뷰 기본 키 추가(Add Primary Key) (V2)
아직 기본 키가 없는 뷰에 기본 키를 추가합니다. 이미 기본 키가 있으면 ViewPrimaryKeyCannotBeModified가 발생합니다. 기본 키는 데이터 생성자가 보장하는 계약이며 쓰기 작업이 해당 불변 조건을 유지해야 합니다.
경로의 viewDatasetRid는 필수 문자열이며 쿼리 매개변수는 없습니다. 필수 본문은 AddPrimaryKeyRequest입니다.
| 필드 | 자료형 | 필수 여부 | 의미 |
|---|---|---|---|
branch | string | 선택 | 뷰 브랜치 |
primaryKey | object | 필수 | 기본 키 열과 중복 해결 방식 |
primaryKey.columns는 선택적인 목록 필드이지만 기본 키 설정에서는 비어 있으면 안 됩니다. 열 이름 정규화 이후 중복이 없어야 하고 모든 열이 스키마에 존재해야 합니다. 유형은 BYTE, SHORT, DECIMAL, INTEGER, LONG, STRING, BOOLEAN, TIMESTAMP, DATE 중 하나여야 합니다.
필수 resolution에서 unique는 키의 고유성을 보장합니다. duplicate는 중복을 허용하며 필수 resolutionStrategy를 지정합니다. 지원하는 latestWins는 선택적인 columns 목록을 차례로 비교하여 가장 높은 행을 선택합니다. 선택적인 deletionColumn은 실제 존재하는 boolean 열이어야 하며, 최종 선택 행의 값이 true이면 결과에서 제외합니다.
기반 데이터셋이 없는 뷰에는 기본 키를 추가할 수 없습니다. unique 보장을 위반하는 등 계약을 어기면 읽기 동작이 정의되어 있지 않습니다. 전체 중첩 구조는 View 자료형을 따릅니다.
HTTP 요청
POST /api/v2/datasets/views/{viewDatasetRid}/addPrimaryKey
작업 식별자는 v2.addPrimaryKey입니다. Authorization: Bearer <접근 토큰> 헤더로 인증합니다. OAuth 클라이언트에는 api:datasets-write 권한 범위가 필요합니다.
JSON 요청 예시
가상 뷰와 기반 데이터셋을 사용하는 요청 본문 예시입니다.
{
"branch": "master",
"primaryKey": {
"columns": [
"colA"
],
"resolution": {
"type": "duplicate",
"deletionColumn": "deletionCol",
"resolutionStrategy": {
"type": "latestWins",
"columns": [
"colB",
"colC"
]
}
}
}
}
응답 구조
응답 형식은 View입니다.
| 필드 | 자료형 | 필수 여부 | 의미 |
|---|---|---|---|
viewName | string | 필수 | 표시 이름 |
datasetRid | string | 필수 | 뷰 자체의 RID |
parentFolderRid | string | 필수 | 상위 폴더 RID |
branch | string | 선택 | 뷰 브랜치 |
backingDatasets | list<ViewBackingDataset> | 선택 | 기반 데이터셋과 브랜치 및 보안 표지 상속 중단 설정 |
primaryKey | object | 선택 | 기본 키 열, 필수 resolution과 유형별 중복 해결 설정 |
ViewBackingDataset과 primaryKey의 모든 필드 및 보안과 중복 처리 조건은 View 자료형을 따릅니다.
가상 뷰의 메타데이터 응답 예시입니다.
{
"datasetRid": "ri.foundry.main.dataset.11111111-1111-4111-8111-111111111111",
"parentFolderRid": "ri.compass.main.folder.c410f510-2937-420e-8ea3-8c9bcb3c1791",
"viewName": "My Dataset",
"backingDatasets": [
{
"datasetRid": "ri.foundry.main.dataset.c26f11c8-cdb3-4f44-9f5d-9816ea1c82da",
"stopPropagatingMarkingIds": [
"18212f9a-0e63-4b79-96a0-aae04df23336"
],
"branch": "master"
}
],
"branch": "master",
"primaryKey": {
"columns": [
"colA"
],
"resolution": {
"type": "duplicate",
"deletionColumn": "deletionCol",
"resolutionStrategy": {
"type": "latestWins",
"columns": [
"colB",
"colC"
]
}
}
}
}
개별 오류
| 오류 이름 | 오류 코드 | HTTP | 의미와 조건 | 추가 매개변수 |
|---|---|---|---|---|
ViewPrimaryKeyCannotBeModified | CONFLICT | 409 | 뷰에 기본 키가 이미 존재합니다. | 없음 |
ViewNotFound | NOT_FOUND | 404 | 뷰가 없거나 브랜치가 유효하지 않거나 토큰이 접근할 수 없습니다. | viewDatasetRid, branch |
ViewPrimaryKeyMustContainAtLeastOneColumn | INVALID_ARGUMENT | 400 | 기본 키에 열을 하나 이상 지정해야 합니다. | 없음 |
ViewPrimaryKeyRequiresBackingDatasets | INVALID_ARGUMENT | 400 | 기반 데이터셋이 없는 뷰에는 기본 키를 추가할 수 없습니다. | 없음 |
InvalidViewPrimaryKeyColumnType | INVALID_ARGUMENT | 400 | 기본 키 열 유형은 BYTE, SHORT, DECIMAL, INTEGER, LONG, STRING, BOOLEAN, TIMESTAMP, DATE 중 하나여야 합니다. | primaryKeyColumns, invalidColumns |
NotAllColumnsInPrimaryKeyArePresent | INVALID_ARGUMENT | 400 | 기본 키에 지정한 열 중 일부가 기반 데이터셋에 없습니다. | primaryKeyColumns, missingColumns |
ViewPrimaryKeyDeletionColumnNotInDatasetSchema | INVALID_ARGUMENT | 400 | 삭제 표시 열이 데이터셋 스키마에 없습니다. | deletionColumn |
InvalidViewPrimaryKeyDeletionColumn | INVALID_ARGUMENT | 400 | 삭제 표시 열의 유형은 boolean이어야 합니다. | deletionColumn, deletionColumnType |
AddPrimaryKeyPermissionDenied | PERMISSION_DENIED | 403 | 뷰의 기본 키 추가 권한이 거부되었습니다. | viewDatasetRid |
요청 예제
FOUNDRY_HOST에는 https://를 제외한 Foundry 호스트를, FOUNDRY_TOKEN에는 유효한 토큰을 환경 변수로 제공합니다. 아래 RID, 이름과 파일 경로는 예시이며 실제 작업 대상으로 바꾸어야 합니다.
cURL
curl -X POST \
-H "Content-type: application/json" \
-H "Authorization: Bearer ${FOUNDRY_TOKEN}" \
"https://${FOUNDRY_HOST}/api/v2/datasets/views/ri.foundry.main.dataset.11111111-1111-4111-8111-111111111111/addPrimaryKey" \
-d '{"branch":"master","primaryKey":{"columns":["colA"],"resolution":{"type":"duplicate","deletionColumn":"deletionCol","resolutionStrategy":{"type":"latestWins","columns":["colB","colC"]}}}}'
Python
Requests 라이브러리가 설치된 Python 환경에서 사용합니다.
import os
import requests
HOSTNAME = os.environ["FOUNDRY_HOST"]
TOKEN = os.environ["FOUNDRY_TOKEN"]
headers = {
"content-type": "application/json",
"authorization": "Bearer {}".format(TOKEN)
}
request_body = {
"branch": "master",
"primaryKey": {
"columns": [
"colA"
],
"resolution": {
"type": "duplicate",
"deletionColumn": "deletionCol",
"resolutionStrategy": {
"type": "latestWins",
"columns": [
"colB",
"colC"
]
}
}
}
}
response = requests.post('https://{}/api/v2/datasets/views/ri.foundry.main.dataset.11111111-1111-4111-8111-111111111111/addPrimaryKey'.format(HOSTNAME), headers=headers, json=request_body)
print(response)
Java
Apache HttpClient 4.5 API와 try-with-resources를 사용하는 예제입니다. 클래스 이름에 맞는 AddPrimaryKeyExample.java 파일에서 사용합니다.
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
public class AddPrimaryKeyExample {
public static void main(String[] args) throws Exception {
String HOSTNAME = System.getenv("FOUNDRY_HOST");
String TOKEN = System.getenv("FOUNDRY_TOKEN");
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
HttpPost request = new HttpPost("https://" + HOSTNAME + "/api/v2/datasets/views/ri.foundry.main.dataset.11111111-1111-4111-8111-111111111111/addPrimaryKey");
request.addHeader("content-type", "application/json");
request.addHeader("authorization", String.format("Bearer %s", TOKEN));
request.setEntity(new StringEntity("{\"branch\":\"master\",\"primaryKey\":{\"columns\":[\"colA\"],\"resolution\":{\"type\":\"duplicate\",\"deletionColumn\":\"deletionCol\",\"resolutionStrategy\":{\"type\":\"latestWins\",\"columns\":[\"colB\",\"colC\"]}}}}", ContentType.APPLICATION_JSON));
try (CloseableHttpResponse response = httpClient.execute(request)) {
System.out.println(response);
}
}
}
}
JavaScript
fetch를 제공하는 Node.js 환경에서 사용합니다. 서비스 사용자 토큰을 브라우저로 전달하지 않습니다.
const HOSTNAME = process.env.FOUNDRY_HOST;
const TOKEN = process.env.FOUNDRY_TOKEN;
fetch(`https://${HOSTNAME}/api/v2/datasets/views/ri.foundry.main.dataset.11111111-1111-4111-8111-111111111111/addPrimaryKey`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${TOKEN}`,
},
body: '{"branch":"master","primaryKey":{"columns":["colA"],"resolution":{"type":"duplicate","deletionColumn":"deletionCol","resolutionStrategy":{"type":"latestWins","columns":["colB","colC"]}}}}'
}).then((response) => {
console.log(response)
});
PowerShell
$TOKEN = $env:FOUNDRY_TOKEN
$HOSTNAME = $env:FOUNDRY_HOST
$headers = @{
"authorization" = "Bearer $TOKEN"
}
$response = Invoke-WebRequest -Uri "https://$HOSTNAME/api/v2/datasets/views/ri.foundry.main.dataset.11111111-1111-4111-8111-111111111111/addPrimaryKey" `
-Method Post `
-Headers $headers `
-ContentType application/json `
-Body "{`"branch`":`"master`",`"primaryKey`":{`"columns`":[`"colA`"],`"resolution`":{`"type`":`"duplicate`",`"deletionColumn`":`"deletionCol`",`"resolutionStrategy`":{`"type`":`"latestWins`",`"columns`":[`"colB`",`"colC`"]}}}}"
$response.content