{#call-yield-call--yield} # CALL … YIELD {bdg-primary-line}`GQL 절` {bdg-secondary-line}`2.18에 추가` 이름 있는 함수를 호출해 그 함수가 내놓는 컬럼을 작업 행에 더하며, 그 행들을 파이프라인에 조인합니다. {#call-yield-synopsis} ## 개요
[ OPTIONAL ] CALL function( [ argument [, argument ] ... ] ) YIELD * [ OPTIONAL ] CALL function( [ argument [, argument ] ... ] ) YIELD column [ AS alias ] [, column ] ...

굵게 키워드 · 기울임 직접 채우는 자리 · [ ] 생략 가능 · ... 반복 가능. 구문 표기 규약을 참고하십시오.

{#call-yield-description} ## 설명 이 절은 앞선 절의 행에 조인된 함수 스캔이 되어 lateral `SELECT * FROM function(arguments)`처럼 동작하고, `YIELD` 목록은 그 결과에서 고릅니다. 내놓을 항목은 함수의 결과에서만 찾고 다른 곳에서는 찾지 않으므로, 함수가 반환하지 않는 이름은 쿼리에 같은 이름의 변수가 바인딩돼 있어도 오류입니다. - `YIELD`는 **필수**입니다. `YIELD` 없는 `CALL f(x)`는 구문 오류입니다. - 이 절은 쿼리를 시작할 수도, 끝낼 수도 없습니다. 문장 맨 앞의 `CALL`은 PostgreSQL의 SQL `CALL`로 읽히므로, 맨 앞에 온 `CALL f() YIELD …`는 구문 오류입니다. - 인자가 앞서 바인딩된 변수를 가리키면 그 호출은 **상관 호출**이 되어 입력 행마다 한 번 실행됩니다. 인자가 상수면 함수가 한 번 실행되고 그 행들이 파이프라인에 교차 조인됩니다. - 내놓인 컬럼은 그 뒤로 평범한 바인딩입니다. 걸러 내고, 집계하고, 그것으로 정렬하고, 뒤따르는 `MATCH`에 넘길 수 있습니다. - 함수가 행을 내놓지 못한 입력 행은 내부 조인이 버리는 것과 똑같이 **버려집니다.** 그 행을 남기려면 [`OPTIONAL CALL`](optional-call.md)을 쓰십시오. {#call-yield-parameters} ## 매개변수 function : 호출할 함수의 이름이며, `search_path`가 닿지 않으면 스키마로 수식합니다. 인자가 없어도 괄호는 필요합니다. 프로시저는 `() is a procedure`로 거부됩니다. argument : 입력 행마다 평가되는 값 표현식입니다. 속성 접근은 `jsonb`를 내놓으므로, 매개변수가 다른 타입인 함수에는 명시적 형 변환이 필요합니다. column : 그 함수의 출력 컬럼입니다. 스칼라 함수나 단일 컬럼 집합 반환 함수에는 하나가 있고 함수 자신의 이름을 땁니다. 복합 타입이나 `RETURNS TABLE` 함수에는 출력 필드마다 하나가 있고 필드 이름을 그대로 씁니다. `YIELD *`는 그 전부를 취합니다. 함수 자신의 이름은 그 이름의 컬럼이 없을 때 행 전체를 가리키며, `RETURNS SETOF vertex`나 `RETURNS SETOF edge`로 선언된 함수는 이렇게 정점이나 간선 그대로 내놓입니다. 그 밖의 이름은 `function f has no output column "x"`로 거부됩니다. alias : 내놓인 컬럼의 새 이름입니다. 그 컬럼의 이름이 쿼리에 이미 바인딩돼 있다면 필수입니다. {#call-yield-examples} ## 예제 모든 예제는 [예제 데이터셋](../../get_started/example-dataset.md)에서 실행됩니다. 영화 한 편의 속성을 행으로 펼칩니다. `jsonb_each_text`는 컬럼 두 개를 반환하고, `YIELD`가 둘 다 이름으로 부릅니다: ```cypher MATCH (m:movie {title: 'The Matrix'}) CALL jsonb_each_text(jsonb_build_object('title', m.title, 'year', m.year, 'genre', m.genre)) YIELD key, value RETURN key AS property, value ORDER BY property; ``` ``` property | value ----------+-------------- "genre" | "Action" "title" | "The Matrix" "year" | "1999" (3 rows) ``` {#call-yield-rename-a-yielded-column} ### 내놓인 컬럼 이름 바꾸기 `AS`는 뒤따르는 모든 절에 대해 그 이름을 바꿉니다: ```cypher MATCH (m:movie {title: 'The Matrix'}) CALL jsonb_each_text(properties(m)) YIELD key AS property RETURN property ORDER BY property; ``` ``` property ------------- "embedding" "genre" "plot" "title" "year" (5 rows) ``` 일부만 내놓는 것도 됩니다. 여기서 `value`는 바인딩되지 않습니다. {#call-yield-take-every-column-with-yield-} ### YIELD * 로 모든 컬럼 취하기 단일 컬럼 집합 반환 함수는 자기 컬럼에 자신의 이름을 붙입니다: ```cypher MATCH (m:movie) WHERE m.genre = 'Adventure' CALL generate_series(1, 2) YIELD * RETURN m.title AS film, generate_series AS n ORDER BY n; ``` ``` film | n -----------------+--- "Jurassic Park" | 1 "Jurassic Park" | 2 (2 rows) ``` 인자가 상수이므로 `generate_series`가 한 번 실행되고 그 두 행이 그 영화에 교차 조인됩니다. {#call-yield-correlate-the-call-with-the-matched-row} ### 호출을 일치한 행과 상관시키기 행에서 값을 넘기면 함수가 행마다 실행됩니다. `m.year`는 `jsonb`이므로 형 변환이 필요합니다: ```cypher MATCH (m:movie {title: 'The Matrix'}) CALL generate_series(1, (m.year)::int) YIELD generate_series AS n RETURN count(n) AS years; ``` ``` years ------- 1999 (1 row) ``` 형 변환이 없으면 그 함수를 찾지 못합니다: ```cypher MATCH (m:movie {title: 'The Matrix'}) CALL generate_series(1, m.year) YIELD generate_series AS n RETURN count(n); ``` ``` ERROR: function generate_series(integer, jsonb) does not exist LINE 2: CALL generate_series(1, m.year) YIELD generate_series AS n ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. ``` {#call-yield-chain-two-calls} ### 호출 두 개 잇기 둘째 호출은 첫 호출이 내놓은 컬럼과 상관될 수 있습니다: ```cypher MATCH (m:movie {title: 'The Matrix'}) CALL generate_series(1, 2) YIELD generate_series AS n CALL generate_series(1, n) YIELD generate_series AS k RETURN n, k ORDER BY n, k; ``` ``` n | k ---+--- 1 | 1 2 | 1 2 | 2 (3 rows) ``` ### 행 전체를 내놓기 함수 자신의 이름을 가진 출력 컬럼이 없으면 그 이름은 행 전체를 가리킵니다. `jsonb_each_text`는 `(key, value)` 행을 반환합니다: ```cypher MATCH (m:movie {title: 'The Matrix'}) CALL jsonb_each_text(jsonb_build_object('title', m.title, 'year', m.year)) YIELD jsonb_each_text AS pair RETURN pair ORDER BY pair; ``` ``` pair ----------------------------------------- {"key": "title", "value": "The Matrix"} {"key": "year", "value": "1999"} (2 rows) ``` `RETURNS SETOF vertex`로 선언된 함수도 같은 방식으로, 자신의 이름 아래 정점을 내놓습니다. {#call-yield-notes} ## 참고 실행 계획은 두 실행 모양 중 어느 것을 받았는지 보여 줍니다. 상관 호출은 내부 쪽이 함수 스캔인 `Nested Loop`입니다. 상관되지 않은 호출은 함수 스캔을 외부 쪽에 두고 그래프 스캔을 구체화합니다: ```cypher EXPLAIN (COSTS OFF) MATCH (m:movie) CALL generate_series(1, (m.year)::int) YIELD generate_series AS n RETURN m.title, n; ``` ``` QUERY PLAN ---------------------------------------- Nested Loop -> Seq Scan on movie m -> Function Scan on generate_series (3 rows) ``` 내놓인 이름이 이미 유효 범위에 있는 바인딩과 충돌하면, 그것을 덮어 가리는 것이 아니라 거부됩니다. 오류는 `variable "m" yielded by CALL is already bound in the outer query`입니다. `AS`로 이름을 바꾸십시오. 그 반대도 거부됩니다. 함수의 출력 컬럼이 아닌 이름은 앞서 같은 이름의 변수가 바인딩돼 있어도 거부됩니다. 앞선 바인딩은 `YIELD`가 가리키는 대상이 아닙니다. ```cypher MATCH (m:movie {title: 'The Matrix'}) CALL generate_series(1, 2) YIELD m AS n RETURN n; ``` ``` ERROR: function generate_series has no output column "m" LINE 2: CALL generate_series(1, 2) YIELD m AS n ^ ``` ```{note} 가상 타입 `record`를 반환하는 함수는 호출할 수 없습니다. PostgreSQL이 요구하는 컬럼 정의 목록을 둘 자리가 이 절에 없으므로, `CALL jsonb_to_recordset(…) YIELD *`는 `a column definition list is required for functions returning "record"`를 냅니다. 그런 호출은 대신 SQL 서브쿼리로 감싸십시오. ``` {#call-yield-compatibility} ## 호환성 ```{admonition} GQL 적합성 :class: gql-conformance §15.1의 *call procedure statement* 아래에서, §16.14의 *yield clause*와 함께 GQL의 *named procedure call*(ISO/IEC 39075:2024 §15.3)을 구현합니다. - **지원** — 인자 목록, 상관 인자, `YIELD *`와 `YIELD column [AS alias]` 형태, 내놓을 항목이 프로시저 결과의 컬럼을 가리켜야 한다는 §16.14 구문 규칙 7, 구문 규칙 6의 중복 별칭 거부, 그리고 `OPTIONAL` 접두. - **미지원** — GQL 프로시저 호출. §15.3은 *procedure reference*를 §17.5가 기술하는 카탈로그에서 찾는데 AgensGraph에는 그것이 없습니다. 이름은 대신 PostgreSQL 함수로 해석됩니다. - **이탈** — §15.3은 `YIELD` 절을 선택으로 둡니다. AgensGraph는 그 절이 작업 테이블에 컬럼을 보태야 하므로 필수로 요구합니다. 진행 상황은 [GQL 적합성 표](../../appendix/gql-conformance.md)에서 확인하십시오. ``` {#call-yield-opencypher} ### openCypher openCypher도 같은 절을 쓰지만 그 이름을 프로시저 레지스트리(`db.labels()`, `dbms.components()`)에서 찾고, `YIELD` 없는 `CALL proc()`을 독립 문장으로 허용합니다. 여기에는 그 레지스트리도, 독립 형태도 없습니다. 이름은 PostgreSQL 함수로 해석되고 `YIELD`가 필수입니다. {#call-yield-see-also} ## 관련 항목 - [`CALL`](call.md) {bdg-secondary-line}`GQL` — 두 호출 형태, 그리고 여기서 루틴이란 무엇인가 - [`CALL { subquery }`](call-subquery.md) {bdg-secondary-line}`GQL` — 인라인 형태 - [`OPTIONAL CALL`](optional-call.md) {bdg-secondary-line}`GQL` — 함수가 아무것도 내놓지 않은 행 남기기 - [GQL 적합성 표](../../appendix/gql-conformance.md)