예시 Python UDF

예시 Python UDF (Example Python UDFs)

Python 사용자 정의 함수에 대해 배운 뒤, 유효한 Python UDF 예시를 보여주는 문서예요. 인라인과 카탈로그 UDF에서 어떻게 쓰는지 차이를 중심으로 살펴봐요.

출처: 문서

본문

Python 사용자 정의 함수에 대해 배운 뒤, 다음 섹션들은 유효한 Python UDF 예시를 보여줘요.

UDF들은 이름과 예시 호출을 조정하면 인라인 사용자 정의 함수나 카탈로그 사용자 정의 함수로 모두 적합해요.

인라인 및 카탈로그 Python UDF

다음 섹션은 간단한 Python UDF 예시로 인라인과 카탈로그 UDF 사용의 차이를 보여줘요. 같은 패턴이 이후의 모든 섹션에 적용돼요.

입력 없이 정적 int 값 42를 반환하는 아주 간단한 Python UDF:

FUNCTION answer()
LANGUAGE PYTHON
RETURNS int
WITH (handler='theanswer')
AS $$
def theanswer():
    return 42
$$

이 UDF를 인라인 UDF로 쓴 전체 예시와 문자열 연결에서 CAST와 함께 쓰는 예시:

WITH
  FUNCTION answer()
  RETURNS int
  LANGUAGE PYTHON
  WITH (handler='theanswer')
  AS $$
  def theanswer():
      return 42
  $$
SELECT 'The answer is ' || CAST(answer() as varchar);
-- The answer is 42

카탈로그 exampledefault 스키마에서 UDF 저장을 지원한다면 다음을 사용할 수 있어요:

CREATE FUNCTION example.default.answer()
  RETURNS int
  LANGUAGE PYTHON
  WITH (handler='theanswer')
  AS $$
  def theanswer():
      return 42
  $$;

UDF가 카탈로그에 저장되면, 재정의 없이 UDF를 여러 번 실행할 수 있어요:

SELECT example.default.answer() + 1; -- 43
SELECT 'The answer is ' || CAST(example.default.answer() as varchar); -- The answer is 42

또는 Config 속성에서 SQL PATH를 UDF 저장을 지원하는 카탈로그와 스키마로 구성할 수 있어요:

sql.default-function-catalog=example
sql.default-function-schema=default
sql.path=example.default

이제 전체 경로 없이 UDF를 관리할 수 있어요:

CREATE FUNCTION answer()
  RETURNS int
  LANGUAGE PYTHON
  WITH (handler='theanswer')
  AS $$
  def theanswer():
      return 42
  $$;

UDF 호출도 전체 경로 없이 동작해요:

SELECT answer() + 5; -- 47

XOR

다음 예시는 두 boolean 입력 매개변수에 논리적 배타적 OR 연산을 수행하는 xor 함수를 구현하고 두 호출로 테스트해요:

WITH FUNCTION xor(a boolean, b boolean)
RETURNS boolean
LANGUAGE PYTHON
WITH (handler = 'bool_xor')
AS $$
import operator
def bool_xor(a, b):
    return operator.xor(a, b)
$$
SELECT xor(true, false), xor(false, true);

쿼리 결과:

 true  | true

reverse_words

다음 예시는 varchar 타입 입력 문자열 s의 각 단어에서 문자를 뒤집는 더 정교한 Python 스크립트를 사용하고 함수를 테스트해요.

WITH FUNCTION reverse_words(s varchar)
RETURNS varchar
LANGUAGE PYTHON
WITH (handler = 'reverse_words')
AS $$
import re

def reverse(s):
    str = ""
    for i in s:
        str = i + str
    return str

pattern = re.compile(r"\w+[.,'!?\"]\w*")

def process_word(word):
    # Reverse only words without non-letter signs
    return word if pattern.match(word) else reverse(word)

def reverse_words(payload):
    text_words = payload.split(' ')
    return ' '.join([process_word(w) for w in text_words])
$$
SELECT reverse_words('Civic, level, dna racecar era semordnilap');

쿼리 결과:

Civic, level, and racecar are palindromes