Example Python UDFs#

После ознакомления с Python user-defined functions, в следующих разделах приведены примеры корректных Python UDF.

Эти UDF подходят для использования как Inline пользовательские функции или Catalog user-defined functions, после изменения имени и примеров вызова.

Inline and catalog Python UDFs#

В следующем разделе показаны различия в использовании inline и catalog UDF на примере простого Python UDF. Тот же шаблон применяется ко всем последующим разделам.

Очень простой Python UDF, который возвращает статическое значение int 42 без необходимости входных параметров:

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

Полный пример этого UDF как inline UDF и его использование в конкатенации строк с приведением типов:

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

Если каталог example поддерживает хранение UDF в схеме default, вы можете использовать следующее:

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

После сохранения UDF в каталоге, вы можете вызывать его многократно без повторного определения:

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

Альтернативно, вы можете настроить SQL PATH в Config properties на каталог и схему, поддерживающие хранение 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#

Следующий пример реализует функцию xor для логической операции исключающего ИЛИ (Exclusive OR) над двумя булевыми входными параметрами и проверяет её с помощью двух вызовов:

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#

Следующий пример использует более сложный Python-скрипт для разворота символов в каждом слове входной строки s типа varchar и тестирует функцию.

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