기초코드 화면에서 사람이 관리하는 표를 스킬에서 읽고 씁니다. 프롬프트에 목록을 실어 주는 {{$테이블.필드}} 가 보는 것과 같은 데이터입니다.
왜 이 진입점이 필요한가. 기초코드는 code_rows 테이블의 data 컬럼에 JSONB 로 들어갑니다. 이 진입점이 없으면 스킬이 그 저장 구조를 알고 Zio.raw() 로 SQL 을 짜야 합니다 — 엔진 내부 구조에 대한 raw 접근이고, 저장 방식이 바뀌면 모든 인스턴스의 스킬이 함께 깨집니다.
엔진은 어떤 표가 있는지 모릅니다. 건설업은 공종, 패션업은 브랜드, 요식업은 점포 를 만듭니다. 표 이름도 칼럼 이름도 전부 인자로만 오갑니다. 특정 표를 전제한 코드를 SDK 나 엔진에 넣지 마십시오.
Method
Description
Zio.code(table_name)
기초코드 표 하나를 지정합니다. 기초코드 화면의 테이블 ID(영문명)를 씁니다. 없는 표를 지정하면 LookupError 가 납니다 — 오타를 조용히 빈 목록으로 넘기지 않습니다.
.where(**kwargs)
행을 걸러냅니다. 비교 접미사를 그대로 씁니다. (예: use_yn="Y", client_name__startswith="GS")
.where_or(**kwargs)
같은 표의 여러 조건을 OR 로 묶습니다(다른 .where() 와는 AND). 키워드 검색처럼 여러 칸 중 하나라도 맞으면 될 때 씁니다 — 예전엔 질의를 여러 번 나눠 파이썬에서 합쳐야 했습니다. 접미사(__contains 등)는 .where() 와 같습니다. 여러 번 부르면 각 호출이 별개의 OR 덩어리가 되어 서로 AND 로 이어집니다. fetch()·count()(읽기)에만 걸립니다 — update()·delete() 에 OR 을 걸면 의도보다 많은 행을 건드릴 수 있어 받지 않습니다. (예: .where_or(client_name__contains=kw, aliases__contains=kw))
Zio.code.list()
어떤 표가 있는지 먼저 봅니다. [{table_name, title, description, field_count}] — 행은 안 옵니다. 이름을 모르는 채 Zio.code("추측") 를 되풀이하지 말고 여기서 고르십시오.
.fetch()
행 목록을 GraphResult 로 가져옵니다. 각 행은 칼럼명이 그대로 키가 된 평평한 dict 입니다. 행 식별자는 _id 로 함께 들어갑니다.
.info()
표 자체의 설명을 dict 로 가져옵니다. {table_name, title, description, fields:[{name, label, type}]}. 제목을 안 붙인 표는 title 이 표 이름 그대로입니다.
.create(props)
행 하나를 넣습니다. 중복은 보지 않습니다 — 무엇이 중복인지는 표마다 다르므로, 넣기 전에 .where(...).fetch() 로 확인하십시오.
.update(props)
조건에 맞는 행을 고칩니다. 준 칼럼만 덮어쓰고 나머지는 그대로 둡니다. 조건이 없으면 ValueError 입니다.
.delete()
조건에 맞는 행을 지웁니다. 지워진 행을 그대로 돌려줍니다 — 무엇이 사라졌는지 남기라는 뜻입니다. 조건이 없으면 ValueError 입니다.
.create_table(columns, title, description)
표를 만듭니다. columns=[{name, label, type}]. 만들어진 표는 사람이 화면에서 이어서 관리합니다 — 스킬이 세웠다고 잠기지 않습니다. 태어날 때는 잠금이 하나도 없습니다(화면에서 만든 표와 같습니다).
.add_column(column)
칸 하나를 뒤에 더합니다. {name, label, type}. 이미 든 행은 그 칸이 빈 채로 보입니다 — 값을 지어 넣지 않습니다.
.drop_column(column_name)
칸 하나를 선언에서 뺍니다. 행에 든 값은 안 지웁니다 — 같은 이름으로 다시 더하면 돌아옵니다. 남은 값은 화면에서는 사라지지만 .fetch() 에는 그대로 실립니다 (읽기까지 거르면 그 값을 볼 자리가 없어지므로). 다시 쓰려 하면 선언에 없는 칼럼이라 ValueError 입니다. 마지막 한 칸은 못 뺍니다.
.rename_column(old_name, new_name)
칸 이름을 바꾸고 행에 든 값도 같이 옮깁니다. 선언만 바꾸면 값이 옛 키에 남아, 지워지지도 않고 보이지도 않는 상태가 됩니다.
.drop_table(force=False)
표와 그 행을 없앱니다. 다른 곳이 이 표를 물고 있으면 거부하고 어디가 물고 있는지 알려줍니다. 알고도 없애려면 force=True 입니다. 돌려주는 것은 {table_name, deleted_rows, dependencies}.
.resolve(value, name, alias=None)
이 표가 아는 표기입니까. 알면 정식명을, 모르면 None 을 돌려줍니다. 100% 일치만 봅니다 — 대소문자·공백·기호는 무시합니다(GS 25 = GS25).
.suggest(value, name, alias=None, limit=3)
닮은 정식명을 골라 줍니다. .resolve() 가 못 찾았을 때 사람에게 되물을 후보입니다. 재료는 별칭까지, 내놓는 것은 정식명뿐입니다.
.name_conflicts(name, alias=None)
같은 별칭이 두 정식명에 걸린 곳을 알려줍니다. [{"alias": "편의점", "claimed_by": ["GS25", "CVSNET"]}]. 빈 목록이면 깨끗한 표입니다.
어느 칸이 정식명이고 어느 칸이 별칭인지는 표를 만든 사람만 압니다. 건설업은 공종명, 패션업은 브랜드명 이고, 별칭 칸을 아예 안 만든 표도 있습니다. SDK 가 aliases 같은 이름을 정해두면 그 순간 한 산업 전용이 되고, 별칭 칸이 없는 표에서는 조용히 빈손이 됩니다.
.resolve() 와 .suggest() 를 한 함수로 합치지 않은 이유가 있습니다. “아는 것” 과 “닮은 것” 이 섞이면, 안 물어도 될 것을 묻거나 물어야 할 것을 그냥 넘깁니다. .resolve() 가 답을 주면 통과, 못 주면 .suggest() 로 후보를 받아 되묻기 — 이 두 줄이 표준 흐름입니다.
사전이 틀렸을 때는 손대지 않는 것이 낫습니다. 같은 별칭이 두 정식명에 걸려 있으면(편의점 이 두 편의점 회사에) 어느 쪽으로 붙을지가 표에 적힌 순서로 정해지고, 나중에 왜 그렇게 붙었는지 아무도 못 찾습니다. .resolve()·.suggest() 는 그런 별칭을 아예 쓰지 않으므로 틀린 곳에 붙지는 않지만, 표가 틀렸다는 것을 알려면 .name_conflicts() 를 한 번 부르십시오. 무엇을 할지는 알려주지 않습니다 — 그 표를 통째로 건너뛸지는 도메인 판단입니다.
조건 없는 update·delete 를 거부합니다. 기준 데이터가 한 번에 날아가면 되돌릴 방법이 없습니다. .where() 를 반드시 거십시오.
선언에 없는 칼럼을 거부합니다. 화면은 선언된 칼럼만 그리므로, 받아주면 아무 데도 안 보이는 값이 저장되고 나중에 아무도 못 찾습니다. 오류 문장에 그 표에서 쓸 수 있는 칼럼이 함께 옵니다.
기초코드의 주인은 도메인 담당자입니다. 사람이 화면에서 세운 표에 스킬이 한 줄 더하는 것이지, 스킬이 자기 저장소로 쓰는 곳이 아닙니다. 스킬이 만들고 지우는 표가 필요하면 Zio.entity() 를 쓰십시오 — 상태가 바뀌고 사라지는 성격의 데이터(작업 큐, 처리 이력)는 그쪽입니다.