CREATE FUNCTION

CREATE FUNCTION — 새 함수 정의

요약

CREATE [ OR REPLACE ] FUNCTION
    이름 ( [ [ 인자모드 ] [ 인자이름 ] 인자자료형 [ { DEFAULT | = } 기본값표현식 ] [, ...] ] )
    [ RETURNS 반환자료형
      | RETURNS TABLE ( 칼럼이름 칼럼자료형 [, ...] ) ]
  { LANGUAGE 언어이름
    | TRANSFORM { FOR TYPE 자료형이름 } [, ... ]
    | WINDOW
    | IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF
    | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
    | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
    | PARALLEL { UNSAFE | RESTRICTED | SAFE }
    | COST 실행비용
    | ROWS 반환로우수
    | SUPPORT support_function
    | SET 환경설정_매개변수 { TO  | =  | FROM CURRENT }
    | AS '정의'
    | AS '오브젝트파일', '링크_심벌'
  } ...

설명

CREATE FUNCTION 명령은 새 함수를 만든다. CREATE OR REPLACE FUNCTION 명령은 함수를 새로 만들 거나, 이미 있는 함수 정의를 바꾼다. 함수를 만드려면, 그 함수가 사용하는 언어에 대해서 USAGE 권한이 있어야 한다.

함수 이름에 스키마 이름을 포함하면, 해당 스키마 안에 함수가 만들어진다. 지정하지 않으면 현재 스키마 안에 만든다. 특정 스키마 안에, 함수 이름과 그 함수가 사용하는 입력 인자 자료형이 모두 일치하는 다른 함수는 만들 수 없다. (프로시져도 마찬가지다.) 하지만 이름은 같은데 입력 인자 자료형이 다른 함수는 만들 수 있다. (이것은 함수 오버로드라고 한다.)

이미 만들어진 함수 정의를 바꿀 때는 CREATE OR REPLACE FUNCTION 명령을 사용한다. 이 명령은 함수 이름과 입력 인자 자료형이 일치 하는 경우만 그 함수를 바꾼다. (입력 인자가 바뀌면 오버로드된 새로운 함수가 만들어진다 - 옮긴이) 또한, 함수 이름과 입력 인자 자료형이 같은데, 반환 자료형을 바꿔 실행하면 오류로 처리한다. 반환 자료형을 바꿀 때는 그 함수를 지우고, 새로 만들어야 한다. (OUT 인자를 쓰는 경우도 이것이 반환 자료형이기 때문에 이 정책을 그대로 따른다.)

CREATE OR REPLACE FUNCTION 명령을 이용해서 함수를 바꾸는 경우, 그 함수의 소요주와 접근 권한은 바뀌지 않는다. 그외 모든 함수 속성 변경 작업은 이 명령으로 수행할 수 있다. 함수를 바꾸려면, 해당 함수의 소유주이거나 그 소유주의 소속원이어야 한다.

함수를 지우고 다시 만들면, 새 함수의 oid는 기존 oid와 다르게 된다. 또한 기존 함수를 사용하고 있는 룰, 뷰, 트리거 등 의존 관계에 있는 개체들도 모두 삭제 되어야 그 함수를 지울 수 있다. 단지 함수 속성이나, 함수의 본문 내용을 바꾸고자 한다면, CREATE OR REPLACE FUNCTION 명령을 사용해서 이런 의존 관계 개체들의 삭제 작업 없이 함수를 바꿀 수 있다. 또한, ALTER FUNCTION 명령은 해당 함수의 외부 속성들 바꾸는데 사용 한다.

함수를 만드는 사용자가 그 함수의 소유주가 된다.

함수를 만드려면, 그 함수에서 사용하는 입력 인자 자료형과 반환 자료형에 대해서 USAGE 권한이 있어야 한다.

Refer to 37.3절 for further information on writing functions.

매개 변수

이름

새로 만들고자 하는 함수의 이름(스키마 이름 포함).

인자모드

사용할 수 있는 모드값: IN, OUT, INOUT, 또는 VARIADIC. 생략하면 기본값인 IN으로 간주한다. OUT VARIADIC 형은 한번만 사용할 수 있다. 또한, OUT , INOUT 인자는 RETURNS TABLE 구문과 함께 사용할 수 없다.

인자이름

해당 인자의 이름. SQL, PL/pgSQL 언어를 포함해서 몇 언어를 사용하는 함수에서는 함수 본문에서 여기서 지정한 이름을 변수명으로 사용할 수 있다. 그외 다른 언어에서는 단순히 함수 문서화 작업에 도움을 줄 뿐이다. 물론 함수를 호출 할 때 명령문의 가독성을 높이기 위해서, 입력 인자 이름과 그 값을 함께 지정해서 쓰기도 한다(4.3절 참조). (이렇게 함수 이름을 사용할 수 없는 언어에서는 그 인자값을 사용하기 위해 별도의 변수 선언, 변수 값 할당 같은 부가 작업을 함수 본문에 추가해서 보통 진행한다. - 옮긴이) 한편, 출력 인자 이름은 그 함수 결과의 칼럼 이름으로 사용하기 때문에, 중요한 의미를 지닌다. (출력 인자 이름을 사용하지 않은 경우에는 출력 결과에 사용하는 각 칼럼 이름은 시스템이 자동으로 부여한다.)

인자자료형

함수 인자의 해당 자료형 이름(스키마 이름 포함). 그 자료형으로 기본 자료형, 복합 자료형, 도메인, 한 테이블의 칼럼이 사용하는 자료형을 뜻하는 참조 자료형을 사용할 수 있다.

사용하는 언어에 따라 어떤 경우는 cstring 같은 의사-자료형 pseudo-type도 사용할 수 있다. 의사 자료형은 그 진짜 인자 자료형이 불완전한 지정이거나, (SQL 수준에서 임의로 어떤 자료형으로 바뀔 수 있는), 보통의 SQL 자료형이 아닌 경우를 뜻한다.

인자 자료형으로 테이블이름.칼럼이름%TYPE 구문으로 특정 테이블의 특정 칼럼이 사용하는 참조 자료형을 쓸 수 있다. 이런 자료형 정의는 테이블 정의 변경과 독립적인 함수를 만드는데 유용하게 쓰인다.

기본값표현식

이 표현식으로 지정한 기본값은 함수를 호출 할 때, 해당 인자를 아에 지정하지 않았을 때, 자동으로 사용할 인자값이 된다. 즉, 이 표현식의 계산 결과는 해당 인자 자료형과 같아야 한다. 입력 인자 (INOUT 인자 포함)만 기본값을 사용할 수 있다. 모든 입력 인자는 이 기본값 표현식을 구문을 이용해서 기본값을 지정할 수 있다.

반환자료형

함수 반환값의 자료형 이름(스키마 이름 포함). 이 자료형으로 기본 자료형, 복합 자료형, 도메인, 테이블 칼럼의 참조 자료형을 사용할 수 있다. 사용하는 언어에 따라 cstring 같은 의사-자료형도 사용할 수 있다. 반환값이 없는 함수를 만드려면, 이 반환 자료형을 void로 지정한다.

OUT 또는 INOUT 인자를 지정했다면, RETURNS 절은 생략할 수 있다. 둘 다 있다면, 출력 인자의 자료형과 이 반환 자료형이 같아야 한다. 반환 자료형이 RECORD 형이라면, 각 개별 출력 인자의 자료형은 그 출력 결과의 각 칼럼 자료형과 같아야 한다.

SETOF 옵션을 자료형 이름 앞에 지정할 수 있는데, 이 때는 반환 되는 자료형이 단일 자료가 아니라, 그 자료들의 집합임을 지시한다. (다중 로우 반환을 뜻한다.)

이 자료형으로 테이블이름.칼럼이름%TYPE 형태의 테이블 칼럼 참조 자료형도 사용할 수 있다.

칼럼이름

RETURNS TABLE 구문에서 사용하는 반환 테이블의 칼럼 이름. RETURNS TABLE 반환은 RETURNS SETOF 옵션을 사용하지 않아도, 집합을 반환한다. 또한 OUT 인자에 이름을 함께 사용하는 출력 자료형 지정보다 편하게 다중 칼럼 출력 자료형을 지정할 수 있다.

칼럼자료형

RETURNS TABLE 구문에서 사용하는 반환 테이블의 칼럼 자료형.

언어이름

함수 본문으로 지정하는 코드들을 해석하고 처리하는 내장 언어 이름. sql, c, internal 이렇게 기본 3 종을 제공하면, 일반적으로 SQL 사용자 정의 함수나 프로시져를 만들 때 사용하는 plpgsql 언어를 확장 모듈로 제공한다(이것은 데이터베이스를 만들 때 자동 설치된다.) 언어 이름에 작은 따옴표를 함께 쓰지 않으며, 대소문자를 구분한다.

TRANSFORM { FOR TYPE 자료형이름 } [, ... ] }

해당 함수에서 사용할 transform 목록. transform은 SQL 자료형과 프로시져 언어에서 사용하는 고유 자료형 사이 전환을 담당한다. CREATE TRANSFORM 명령 설명서 참조. 일반적으로 프로시져 언어는 내장 자료형에 대한 하드 코딩된 정보를 구현해서 제공한다. 그래서, 그 언어가 다루지 못하는 자료형이 아니면, 이 구문은 필요가 없다. 프로시져 언어가 SQL 자료형을 자신이 쓸 자료형으로 바꾸지 못하면(여기서 지정한 transform을 사용하든, 아니면, 기본 자료형으로 바꾸든, 이런 변환 작업을 못하면) 오류를 발생한다. 이런 형 변환에 대한 부분은 각 언어를 어떻게 구현했는가에 달렸다.

WINDOW

WINDOW 옵션은 이 함수가 윈도우 함수로 사용함을 지정한다. C 언어로 구현한 함수에서 사용된다. WINDOW 속성은 CREATE OR REPLACE 작업으로는 변경될 수 없다.

IMMUTABLE
STABLE
VOLATILE

쿼리 최적화기가 이 함수를 사용하는 쿼리를 최적화 할 때 참조하는 속성값. 세 가지 중 하나를 선택한다. 지정하지 않으면 VOLATILE 함수로 간주한다.

IMMUTABLE 옵션은 한 입력값에 대해서는 항상 같은 반환값을 반환하는 함수임을 알린다. 즉, 이 옵션을 사용하는 함수는 데이터베이스 자료를 찾는 작업을 하지 않는 함수임을 뜻한다. 또는 this function use information not directly present in its argument list. (번역 불가) 이 옵션을 사용하는 함수에 상수값 인자가 사용되면, 그 반환값을 구해서 그것을 기준으로 최적화기를 실행 계획을 짜는데 반영한다.

STABLE 옵션은 데이터베이스 자료 조작 작업은 하지 않는 함수임을 의미한다. 하나의 테이블 탐색에서 이 함수가 호출되면, 동일 입력 인자 값에 대해서는 동일 반환 값을 갖는다. 하지만, 각각 다른 SQL 명령에서는 입력 인자 값이 같더라도 반환 값이 다를 수 있다고 여긴다. 이 옵션은 해당 함수가 자료 조회용 작업이나, 매개 변수 값(예, timezone) 조회를 하는 등, 이런 작업을 하는 함수에 사용한다. (자료 조작 뒤에 실행 되는 AFTER 트리거용 함수에 이 옵션을 지정하면 위험하다.) current_timestamp 계열 값을 사용하는 경우도 사용할 수 있다. 이 계열 값들은 한 트랜잭션 내에서 그 값이 바뀌지 않기 때문이다.

VOLATILE 옵션은 그 함수의 반환 값이 상황에 따라 얼마든지 바뀔 수 있는 경우에 사용한다. 최적화기에서는 예상값 추정을 못하는 경우로 처리한다. 이런 이유로 기본으로 제공하는 내장 SQL 함수 중에는 이 속성이 있는 함수가 상대적으로 적다. random(), currval(), timeofday() 이런 종류의 함수들이다. 그러나, 그 반환값이 일정할지라도, 예측하지 못하는 부작용이 생길 수 있는 함수들은 이 휘발성 함수로 지정하는 것이 안전하다. 그래야 최적화 계산에서 빠지게 된다. 대표적인 함수가 setval() 함수다.

LEAKPROOF

LEAKPROOF 옵션은 해당 함수 처리에서 의도하지 않은 결과 side effect 가 없다고 지정한다. 이 옵션이 지정된 함수는 입력 인자를 받아 반환 값을 반환 하는 것 외에는 어떠한 정보도 보여주지 않는 함수임을 뜻한다. 예를 들어, 같은 인자에 대해 그 인자값에 따라 어떤 경우는 오류 메시지를 보여주고, 어떤 경우는 정상 처리하는 함수나, 어떤 오류 메시지에서 그 인자값을 포함하는 함수가 NOT LEAKPROOF 함수다. security_barrier 옵션을 지정한 뷰 또는, 로우 단위 보안 정책이 있는 테이블을 사용하는 뷰를 사용하는데 이 옵션은 영향을 준다. 의도되지 않은 자료 누출 사고를 막기 위해, NOT LEAKPROOF 함수를 포함하는 뷰 쿼리의 사용자 지정 조건 보다 먼저, 보안 정책과 자료 보호 뷰(security_barrier 옵션이 있는 뷰)의 조건이 적용된다. 이 LEAKPROOF 옵션을 지정한 함수나, 그 함수를 사용하는 연산자는 보안 정책이나, 자료 보호 뷰의 조건보다 먼저 실행 될 수도 있다. 추가로, 아무런 인자도 사용하지 않는 함수나, 자료 보호 뷰나, 테이블에서 어떤 인자도 전달하지 않는 함수는 보안 조건 전에 실행 될 수 있도록 이 옵션을 사용하지 말아야 한다. CREATE VIEW 명령 설명서와 40.5절 참조. 이 옵션은 슈퍼유저만 지정할 수 있다.

CALLED ON NULL INPUT
RETURNS NULL ON NULL INPUT
STRICT

CALLED ON NULL INPUT (기본값) 옵션은 인자값으로 null 값을 사용해도 해당 함수 본문을 실행하도록 지정한다. 즉, 인자값 유효성 검사는 함수 본문에서 진행되며, 이 부분에 대한 책임은 사용자 몫이다.

RETURNS NULL ON NULL INPUT 또는 STRICT 옵션은 입력 인자 가운데 하나라도 null 값이 있으면, 함수 본문을 실행하지 않고, 무조건 null 값을 반환하도록 지정한다.

[EXTERNAL] SECURITY INVOKER
[EXTERNAL] SECURITY DEFINER

SECURITY INVOKER 옵션은 함수 본문을 실행할 때 그 실행 권한이 그 실행자의 권한을 사용한다. 이것이 기본값이다. 반면 SECURITY DEFINER 옵션은 함수 본문 실행 권한이 해당 함수 소유주의 권한을 사용한다.

EXTERNAL 옵션은 SQL 호환성 때문에 허용한다. 표준과 달리 이 옵션을 사용해도 모든 함수가 그 대상이 된다.

PARALLEL

PARALLEL UNSAFE 옵션은 해당 함수가 병렬 쿼리 작업에서 안전하지 않다고 지정한다. 이것이 기본값이다. PARALLEL RESTRICTED 옵션은 병렬 쿼리 작업에서 사용될 수 있지만, 이 함수는 반드시 병렬 그룹 리더 작업자만 실행해야 하는 함수로 지정한다. PARALLEL SAFE 옵션은 해당 함수가 병렬 쿼리 작업에서 어떤 제한도 없이 안전하다고 지정한다.

데이터베이스 상태를 변경하거나, 서브 트랜잭션 같은 것을 사용해서 트랜잭션에 변경 사항을 만들거나, 시쿼스를 사용하거나, setval 같이 값을 고정하거나 하는 함수는 UNSAFE로 지정해야 한다. 임시 테이블을 사용하거나, 클라이언트 접속 상태를 조회하거나, 커서, 미리 준비된 구문, setseed 같이 하나의 작업에서는 일관성을 유지해야 하는 일을 하는 함수는 RESTRICTED로 지정해야 한다. 일반적으로, RESTRICTED나, UNSAFE 함수를 SAFE 함수로 지정하거나, UNSAFE 함수를 RESTRICTED 함수로 지정하면, 그 함수를 사용하는 쿼리는 병렬 쿼리로 처리된다. 이렇게 되면, 그 쿼리가 오류로 처리되든가, 잘못된 결과를 보여 줄 수 있다. 서버는 임의 C 코드에 대항해서 자신을 지킬 방법이 없어, 이론적으로, 이런 잘못된 속성을 지정한 C 언어로 만든 함수는 충분히 오동작을 할 수 있다. 하지만 그 오동작 결과가 다른 언어로 만든 함수들 보다는 더 나쁘지는 않다. 그 함수가 하는 일을 정확히 몰라 오동작이 우려되면, 기본값인 UNSAFE 옵션을 사용하는 것이 안전하다.

COST 실행비용

해당 함수의 cpu_operator_cost 값. 이 값은 양수여야 하며, 실행계획기가 이 값을 사용한다. 해당 함수가 다중 로우를 반환한다면, 이 비용은 한 로우를 반환하는데 드는 비용이다. 이 옵션을 사용하지 않으면, C 언어 함수와 내장 함수는 1, 그외 함수는 100이 기본값이다. 이 값이 크면, 실행계획기는 최대한 이 함수를 자주 사용하지 않도록 계획을 짠다.

ROWS 반환로우수

함수가 레코드 반환 또는 테이블 반환하는 경우에, 그 예상 자료 수를 지정한다. 이 값은 실행계획기에서 사용한다. 이 옵션은 다중 로우를 반환하는 함수에서만 쓸 수 있다. 기본 값은 1000 개의 로우다.

SUPPORT support_function

The name (optionally schema-qualified) of a planner support function to use for this function. See 37.11절 for details. You must be superuser to use this option.

환경설정_매개변수

SET 옵션은 해당 함수가 실행 될 때 사용할 환경 설정 매개 변수를 설정한다. 기존 환경 설정 매개 변수값은 따로 보관해 두고, 함수가 실행 될 때는 이 설정 값을 사용하고, 함수 실행이 끝나면 설정값을 자동으로 사용한다. SET FROM CURRENT 옵션은 CREATE FUNCTION 명령을 실행할 때 그 세션이 사용하고 있는 해당 환경 설정 매개 변수의 값을 지정한다.

SET 옵션을 추가해서 함수를 만들면, 내부적으로 그 함수 본문이 실행 되기 전에, SET LOCAL 명령이 먼저 실행 되는 것과 같은 기능을 한다: 이것은 함수 실행 전 설정 값은 보관하고, 지정한 매개 변수 값으로 지정한 값을 사용하고, 함수가 끝날 때 이전 값으로 다시 설정 한다. 반면, 함수 본문 내, LOCAL 옵션이 없는 SET 명령을 사용하면 그 설정값은 함수가 실패로 끝나지 않는 한, 해당 세션이 종료되기 전까지 유지된다.

여기서 사용할 수 있는 매개 변수 이름과 값에 대한 설명은 SET 명령 설명서와 See SET에서 보다 자세히 다룬다.

정의

LANGUAGE 옵션에서 지정한 언어와 관계된 해당 함수가 하는 일을 문자열로 지정한다. 여기에 내장 함수 이름, 오브젝트 파일 경로, SQL 명령어, 또는 프로시져 언어 문법으로 작성된 코드들을 지정한다.

함수 정의 문자열을 지정할 때는 일반 작은 따옴표 인용법 보다, 때로는 달러 인용법이 유용하게 쓰인다(4.1.2.4절 참조). 달러 인용법을 사용하지 않으면, 이 함수 정의 안에 작은 따옴표는 모두 두 개로 표기해야 하기 때문이다.

오브젝트파일, 링그_심벌

C 언어 소스 코드 안에 있는 함수 이름이 만들고자 하는 SQL 함수 이름과 다를 때, 이 구문을 이용해서 동적 불러오기 가능한 C 언어 함수를 지정한다. 오브젝트파일은 컴파일된 C 함수를 포함하고 있는 공유 라이브러리 파일 이름이다. 이 함수를 서버로 불러오려면, LOAD 명령을 사용한다. 링크_심벌은 그 라이브러리 파일에 있는 C 함수 이름이다. 링크 심벌이 빠지면, SQL 함수 이름과 같은 함수로 간주한다. SQL 함수 이름은 오버로드되지만, C 함수 이름은 그렇게 사용할 수 없기 때문에, C 함수 이름은 모두 달라야 한다(예, C 함수 이름으로 함수 이름과 인자 자료형 이름을 함께 사용한다).

세션이 해당 함수가 처음 한 번 사용하면, 이 때 해당 공유 라이브러리를 자동으로 서버로 불러온다. 이 상황에서 개발 중에, 다시 만든 같은 공유 라이브러리를 이용해서 CREATE FUNCTION 작업을 하는 경우는 먼저 불러온 공유 라이브러리를 다시 불러오고, 세션을 다시 시작 한 다음 작업해야 한다.

함수 만들기에 대한 자세한 내용은 37.3절에서 다룬다.

오버로드

PostgreSQL에서는 함수 오버로드가 가능하다. 함수 오버로드란 입력 인자 자료형은 다르지만, 함수 이름이 같은 함수를 만들 수 있는 것을 말한다. 이 기능을 사용하든 하지 않든 간에, 이 기능 때문에, 의도하지 않게 생길 수 있는 보안 사고를 예방해야 한다. 다중 사용자 환경에서 의도하지 않게, 같은 이름의 악의적인 코드가 숨겨진 다른 함수를 호출할 가능성이 있기 때문이다. 10.3절 참조.

같은 함수인지를 확인 하는 기준은 함수 이름과 입력 인자 자료형이다. OUT 인자는 무시한다. 즉 다음 두 함수는 이미 해당 함수가 있는지 확인하는 작업에서 같은 함수로 취급한다:

CREATE FUNCTION foo(int) ...
CREATE FUNCTION foo(int, out text) ...

아래의 경우 처럼, 입력 인자가 달라 만들어 질 수는 있지만, 이 두 함수도 같은 함수로 취급될 가능성이 있다:

CREATE FUNCTION foo(int) ...
CREATE FUNCTION foo(int, int default 42) ...

예를 들어 foo(10) 형태로 호출한다면, 어느 함수를 사용해야 할지 몰라 오류로 처리한다.

참고

함수 인자나, 반환 값의 자료형을 지정할 때, 전체 SQL 자료형 문법을 허용한다. 하지만, CREATE FUNCTION 작업에서는 자료형 변환자는 무시한다. (예, numeric 자료형의 정밀도 지정) 예를 들면 CREATE FUNCTION foo (varchar(10)) ... 구문과 CREATE FUNCTION foo (varchar) ... 구문은 동일하게 처리한다.

CREATE OR REPLACE FUNCTION 구문으로 함수 정의를 바꿀 때, 이미 지정한 인자 이름은 바꿀 수 없고, 인자 이름이 없었던 인자에 새 이름을 지정하는 것은 가능하다. 둘 이상의 출력 인자를 쓰는 경우 그 인자 이름을 바꿀 수 없다. 왜냐하면, 이렇게 되면 반환값으로 쓸 내부적으로 자동으로 만들어진 그 반환값용 복합 자료형을 바꿔야하기 때문이다. 이렇게 제한하는 이유는 함수 바꾸기 작업이 진행 되는 동안에도 기존 함수는 정상적으로 작동되도록 하기 위함이다.

STRICT 옵션이 있는데 인자를 VARIADIC 형으로 지정했다면, 그 가변 배열 그 자체가 null이 아닌지 검사한다. 즉, 그 배열 요소 중 하나가 null이어도 그 함수는 호출 될 수 있다.

예제

여기서는 처음 함수를 만들어 보는 사용자를 위해 여러 예제를 소개한다. 다음은 두 정수를 더하는 예제:

CREATE FUNCTION add(integer, integer) RETURNS integer
    AS 'select $1 + $2;'
    LANGUAGE SQL
    IMMUTABLE
    RETURNS NULL ON NULL INPUT;

PL/pgSQL 언어를 사용해서 입력 인자 이름을 사용하는 경우:

CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
        BEGIN
                RETURN i + 1;
        END;
$$ LANGUAGE plpgsql;

다중 출력 인자가 있고 그것을 여러 칼럼으로 처리하는 경우:

CREATE FUNCTION dup(in int, out f1 int, out f2 text)
    AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
    LANGUAGE SQL;

SELECT * FROM dup(42);

위 함수와 같은데, 이번에는 함수 반환 자료형을 복합 자료형으로 처리하는 경우:

CREATE TYPE dup_result AS (f1 int, f2 text);

CREATE FUNCTION dup(int) RETURNS dup_result
    AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
    LANGUAGE SQL;

SELECT * FROM dup(42);

TABLE 반환 자료형 처리:

CREATE FUNCTION dup(int) RETURNS TABLE(f1 int, f2 text)
    AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
    LANGUAGE SQL;

SELECT * FROM dup(42);

TABLE 반환 처리는 위 함수들과 약간 다르다. 이것은 레코드 집합을 반환하는 것이고, 다른 함수들은 그냥 하나의 레코드만 반환한다.

SECURITY DEFINER 함수를 안전하게 만드는 방법

SECURITY DEFINER 함수는 그 함수 본문에 정의한 작업들이 그 함수 만든 사용자의 권한으로 실행되는 함수이기 때문에, 잘못 사용되면, 권한 침해 사고가 발생할 수 있어 조심해야 한다. 보안을 위해, 신뢰할 수 없는 사용자도 쓰기 가능한 스키마들은 search_path 설정값으로 사용하지 말아야 한다. 악의적인 사용자가 개체 만들기(예, 테이블, 함수, 연산자)를 해서, 해당 함수에서 사용해야 하는 개체를 사용하지 못하게 되는 문제를 이런 조치로 막을 수 있다. (원문: This prevents malicious users from creating objects (e.g., tables, functions, and operators) that mask objects intended to be used by the function.) 여기서 특별히 중요한 것은 임시 테이블 스키마다. 이 스키마는 특별히 지정하지 않으면, 가장 먼저 개체 찾기 작업에 사용되며, 보통 모두가 쓰기 가능한 권한으로 지정되어있다. 이 임시 스키마(pg_temp)를 search_path 값 맨 뒤에 강제로 지정해서 보안 취약점을 해결할 수 있다. 다음이 사용 예다:

CREATE FUNCTION check_password(uname TEXT, pass TEXT)
RETURNS BOOLEAN AS $$
DECLARE passed BOOLEAN;
BEGIN
        SELECT  (pwd = $2) INTO passed
        FROM    pwds
        WHERE   username = $1;

        RETURN passed;
END;
$$  LANGUAGE plpgsql
    SECURITY DEFINER
    -- search_path 안전하게 지정: 신뢰하는 스키마들, 다음에 'pg_temp'.
    SET search_path = admin, pg_temp;

이 함수는 admin.pwds 테이블을 사용한다는 가정에서 작성 되었다. 그런데 SET 설정이 없거나, SET 설정에 단지 admin 만 지정했다면, pwds 이름의 임시 테이블을 만들면, 그 함수는 새로 만들어진 임시 테이블을 대상으로 작업하게 된다.

8.3 이전 버전에서는 SET 옵션이 없어서, 이런 설정을 하려면, 함수 본문 안에, 기존 search_path 값 구해서 따로 보관하고, 새 값을 지정하고, 작업이 끝나면, 다시 기존 값으로 바꾸는 번거로운 작업을 해야 했었다. SET 옵션이 생겨 한결 쉬워졌다.

또 하나 기억해야 할 것은, 함수를 새로 만들면, 모두(PUBLIC)가 그 함수를 실행할 수 있게 실행 권한이 부여된다는 점이다.(이게 기본값이다) (5.7절 명령 설명서 참조) 즉, 특정 사용자만 그 함수를 사용하도록 제한하려면, (SECURITY DEFINER 함수는 그럴 필요가 종종 있다 - 옮긴이) 함수를 만든 뒤 반드시 권한 조정 작업을 해야한다. 그 첫번째 작업은 PUBLIC 대상으로 실행권한을 박탈하는 일이다. 이런 보안 위험성을 피하려면, 다음과 같이 함수 만드는 작업과 권한 조정 작업을 하나의 트랜잭션으로 처리하는 것이다:

BEGIN;
CREATE FUNCTION check_password(uname TEXT, pass TEXT) ... SECURITY DEFINER;
REVOKE ALL ON FUNCTION check_password(uname TEXT, pass TEXT) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION check_password(uname TEXT, pass TEXT) TO admins;
COMMIT;

호환성

CREATE FUNCTION 구문은 SQL 표준을 따른다. PostgreSQL의 구문은 표준과 문법이 비슷하지만, 모두 호환되지는 않는다. 함수 속성들과 프로시져 언어 지정하는 부분은 PostgreSQL 확장 기능이다.

각 데이터베이스 시스템 마다 인자모드인자이름 앞이나 뒤에 오는 식으로 문법이 다른데, 인자모드 인자이름 형식이 표준이다.

인자 기본값 지정 구문은 표준에서는 DEFAULT 키워드만 사용할 수 있다. = 기호는 T-SQL이나 Firebird에서 사용한다.

관련 항목

ALTER FUNCTION, DROP FUNCTION, GRANT, LOAD, REVOKE