Scala로 스칼라 UDF 작성하기

Scala로 스칼라 UDF(사용자 정의 함수)를 작성할 수 있습니다. Scala 처리기 코드는 UDF 호출 시 실행됩니다. 이 항목에서는 Scala로 처리기를 작성하고 UDF를 만드는 방법을 설명합니다.

UDF는 스칼라 결과(즉, 여러 행이 아닌 단일 값)를 반환하는 사용자 정의 함수입니다. UDF에 대한 보다 일반적인 내용은 사용자 정의 함수 개요 섹션을 참조하십시오.

UDF를 만들 때 다음을 수행합니다.

  1. UDF가 호출될 때 Snowflake가 호출할 메서드로 Scala 오브젝트 또는 클래스를 작성합니다.

    자세한 내용은 이 항목의 핸들러 구현하기 섹션을 참조하십시오.

  2. CREATE FUNCTION 명령으로 SQL로 작성된 UDF를 만들어 오브젝트 또는 클래스와 메서드를 처리기로 지정합니다. UDF를 만들 때 다음을 지정합니다.

    • UDF 입력 매개 변수의 데이터 타입.

    • UDF 반환 값의 데이터 타입.

    • UDF 호출 시 핸들러로 실행하는 코드.

    • 처리기가 작성되는 언어.

    CREATE FUNCTION 구문에 대한 자세한 내용은 CREATE FUNCTION 으로 UDF 만들기 섹션을 참조하십시오.

UDF 호출하기 에 설명된 대로 UDF를 호출할 수 있습니다.

핸들러 구현하기

처리기 메서드로 오브젝트 또는 클래스를 구현하여 UDF 인자 값을 UDF의 반환 값으로 처리합니다.

처리기를 작성할 때 다음을 수행합니다.

  • 처리기로 지정할 공용 메서드가 있는 공용 클래스를 작성합니다.

    이것은 SQL에서 UDF가 호출될 때 Snowflake가 호출하는 메서드가 됩니다.

    동일한 오브젝트 또는 클래스에서 다른 메서드를 여러 개 정의한 다음 각각을 다른 UDF에 대한 처리기로 사용할 수 있습니다. 예를 들어 컴파일된 처리기 코드를 스테이지에 유지하고 여러 함수에서 이 코드를 참조하려는 경우 이렇게 할 수 있습니다.

    스테이징된 처리기에 대한 자세한 내용은 처리기 코드를 인라인 또는 스테이지에 유지하기 섹션을 참조하십시오.

  • 선택적으로, Snowflake에서 처리기를 초기화하기 위해 호출할 인자 없는 생성자를 작성합니다.

참고

각 처리기 메서드와 처리기가 호출하는 메서드에서 Snowflake가 부과하는 제약 조건에 맞춰 처리기를 작성해야 합니다. 이러한 제약 조건에 대한 자세한 내용은 Snowflake에서 적용한 제약 조건 내에서 유지되는 처리기 설계하기 섹션을 참조하십시오.

처리기의 예

다음 예제의 코드에는 문자열을 수신하고 반환하는 MyHandler.echoVarchar 처리기 메서드가 포함되어 있습니다. Snowflake는 UDF에서 수신한 값(VARCHAR)을 처리기 메서드의 매개 변수 유형인 문자열에 매핑합니다.

CREATE OR REPLACE FUNCTION echo_varchar(x VARCHAR)
RETURNS VARCHAR
LANGUAGE SCALA
RUNTIME_VERSION = 2.12
HANDLER='MyHandler.echoVarchar'
AS
$$
class MyHandler {
  def echoVarchar(x : String): String = {
    return x
  }
}
$$;
Copy

UDF 호출하기

SELECT echo_varchar('Hello');
Copy

처리기 초기화하기

인자 없는 생성자를 추가하여 처리기를 선택적으로 초기화할 수 있습니다.

생성자에서 오류가 발생하는 경우, 이 오류는 예외 메시지와 함께 사용자 오류로서 발생합니다.

def this() = {
    // Initialize here.
}
Copy

함수 인자 처리하기

UDF에 인자로 전달된 데이터를 처리하려면 SQL 코드에서 UDF가 호출될 때 Snowflake가 호출할 공용 메서드를 구현하십시오. CREATE FUNCTION 명령으로 UDF를 만들 때 HANDLER 절을 사용하여 메서드를 처리기로 지정합니다.

처리기 메서드를 선언할 때 다음을 수행합니다.

  • 처리기 메서드를 공용으로 선언합니다.

    처리기를 초기화하기 위해 인자 없는 생성자를 선택적으로 포함할 수 있습니다. 자세한 내용은 이 항목의 처리기 초기화하기 섹션을 참조하십시오.

    클래스를 스테이징된 처리기로 JAR에 패키징하려는 경우 여러 개의 처리기 메서드를 선언한 이후에 각각을 CREATE FUNCTION 문의 HANDLER 절을 사용하여 처리기로 지정할 수 있습니다. 스테이징된 처리기에 대한 자세한 내용은 처리기 코드를 인라인 또는 스테이지에 유지하기 섹션을 참조하십시오.

  • UDF 선언에서 지정한 SQL 유형에 매핑되는 처리기 메서드 매개 변수 및 반환 유형을 지정합니다.

    자세한 내용은 SQL-Scala 데이터 타입 매핑 섹션을 참조하십시오.

  • 선택적으로 처리기 메서드에서 호출할 메서드와 같이 처리기 메서드의 처리를 지원하는 메서드를 추가로 선언합니다.

    다음 예제의 코드에는 인자로 받은 배열을 처리하는 데 도움이 되는 비 처리기 메서드 concatenate 를 호출하는 handleStrings 처리기 메서드가 있습니다.

    CREATE OR REPLACE FUNCTION generate_greeting(greeting_words ARRAY)
    RETURNS VARCHAR
    LANGUAGE SCALA
    RUNTIME_VERSION = 2.12
    HANDLER='StringHandler.handleStrings'
    AS
    $$
    class StringHandler {
      def handleStrings(strings: Array[String]): String = {
        return concatenate(strings)
      }
      private def concatenate(strings: Array[String]): String = {
        var concatenated : String = ""
        for (newString <- strings)  {
            concatenated = concatenated + " " + newString
        }
        return concatenated
      }
    }
    $$;
    
    Copy

    다음은 generate_greeting 함수를 호출합니다.

    SELECT generate_greeting(['Hello', 'world']);
    
    Copy

    다음은 위의 값으로 generate_greeting 을 호출한 출력을 보여줍니다.

    Hello world
    

처리기 메서드 오버로드하기

매개 변수 수가 다른 한 동일한 클래스 또는 오브젝트에서 처리기 메서드를 오버로드할 수 있습니다.

Scala UDF의 경우 Snowflake는 유형 이 아닌 메서드 인자의 개수 만으로 처리기 메서드를 구분합니다. 데이터 타입을 기반으로 확인하는 것은 비실용적입니다. 일부 SQL 데이터 타입은 둘 이상의 Scala 또는 Java 데이터 타입에 맵핑될 수 있고 따라서 잠재적으로 둘 이상의 처리기 메서드 서명에 맵핑될 수 있기 때문입니다.

예를 들어 두 Scala 메서드가 동일 이름과 동일 수의 인자를 갖지만 데이터 타입이 다른 경우, 이러한 메서드 중 하나를 처리기로 사용하여 UDF를 호출하면 다음과 유사한 오류가 생성됩니다.

Cannot determine which implementation of handler "handler name" to invoke since there are multiple
definitions with <number of args> arguments in function <user defined function name> with
handler <class name>.<handler name>
Copy

웨어하우스를 사용할 수 있는 경우, UDF가 만들어질 때 오류가 감지됩니다. 그렇지 않은 경우, UDF가 호출될 때 오류가 발생합니다.