Diretrizes de codificação do manipulador de UDF de Scala¶
Este tópico descreve as diretrizes gerais para escrever código de manipulador em Scala. Para obter mais informações específicas sobre manipuladores de funções escalares, consulte Como escrever uma UDF escalar em Scala.
Para obter sugestões sobre como estruturar seu projeto, empacotar seu código e gerenciar dependências, consulte Projeto e empacotamento do manipulador da UDF de Scala.
Práticas recomendadas¶
Escreva código independente de plataforma.
Evite códigos que suponham uma arquitetura de CPU específica (por exemplo, x86).
Evite códigos que suponham um sistema operacional específico.
Se você precisar executar o código de inicialização e não quiser incluí-lo no método que você chama, você pode colocar o código de inicialização em um objeto complementar de sua classe de manipulador.
Sempre que possível ao usar um manipulador em linha, especifique um valor para o parâmetro CREATE FUNCTION ou CREATE PROCEDURE TARGET_PATH. Isso solicitará que o Snowflake reutilize a saída do código do manipulador gerado anteriormente, em vez de recompilar para cada chamada. Para obter mais informações, consulte Uso de um manipulador inline.
Como escrever um manipulador¶
Você pode escrever uma UDF escalar com um manipulador escrito em Scala.
O manipulador é chamado uma vez para cada linha passada para a UDF de Scala. Uma nova instância da classe não é criada para cada linha; o Snowflake pode chamar o mesmo método do manipulador da instância mais de uma vez.
Para otimizar a execução do seu código, os limites de tempo limite do Snowflake diferem entre o tempo necessário para inicializar a classe ou o objeto do manipulador e o tempo necessário para executar o método do manipulador. O Snowflake permite mais tempo para inicializar a classe ou o objeto do manipulador, supondo que a inicialização possa demorar mais. Isso inclui o tempo para carregar sua UDF e o tempo para chamar o construtor da classe que contém o método do manipulador, se houver um construtor definido.
Tratamento de erros¶
Você pode tratar exceções com técnicas comuns de tratamento de exceções para capturar erros no método do manipulador.
Se uma exceção ocorre dentro do método e não é capturada pelo método, o Snowflake gera um erro que inclui o traço da pilha para a exceção.
Você pode gerar uma exceção explicitamente sem capturá-la para encerrar a consulta e produzir um erro de SQL. Por exemplo:
if (x < 0) throw new IllegalArgumentException("x must be non-negative.")
Ao depurar, você pode incluir valores no texto da mensagem de erro do SQL. Para isso:
Coloque todo o corpo de um método Scala em um bloco try-catch;
Anexe os valores do argumento à mensagem do erro detectado; e
Lance uma exceção com a mensagem estendida.
Para evitar revelar dados sensíveis, remova valores de argumento antes de enviar arquivos JAR para um ambiente de produção.
Como escolher tipos de dados¶
Ao escrever seu manipulador, você precisará declarar os tipos de dados de parâmetro e retorno (da linguagem do manipulador) que fazem bem os mapeamentos nos tipos de dados de parâmetro e retorno da UDF (do SQL).
Quando a UDF é chamada, o Snowflake converte os argumentos da UDF dos tipos de parâmetro SQL para os tipos de parâmetro do manipulador. Ao retornar um valor, o Snowflake converte o valor de retorno do tipo de retorno do manipulador para o tipo de retorno da UDF.
O Snowflake converte valores entre tipos de acordo com os mapeamentos suportados entre os tipos SQL e os tipos Scala. Para saber mais sobre esses mapeamentos, consulte Mapeamentos de tipos de dados SQL-Scala.
Ao escolher os tipos de dados das variáveis de Scala, leve em conta os valores máximos e mínimos possíveis dos dados que poderiam ser enviados do Snowflake (e devolvidos a ele).
Como criar a UDF com CREATE FUNCTION
¶
Você cria uma UDF em SQL usando o comando CREATE FUNCTION, especificando o código que você escreveu como manipulador. Para obter a referência do comando, consulte CREATE FUNCTION.
CREATE OR REPLACE FUNCTION <name> ( [ <arguments> ] )
RETURNS <type>
LANGUAGE SCALA
[ IMPORTS = ( '<imports>' ) ]
RUNTIME_VERSION = 2.12
[ PACKAGES = ( '<package_name>' [, '<package_name>' . . .] ) ]
[ TARGET_PATH = '<stage_path_and_file_name_to_write>' ]
HANDLER = '<handler_class>.<handler_method>'
[ AS '<scala_code>' ]
Para associar o código do manipulador que você escreveu com a UDF, faça o seguinte ao executar CREATE FUNCTION:
Defina LANGUAGE como SCALA.
Defina o valor da cláusula IMPORTS como o caminho e nome da classe do manipulador se a classe estiver em um local externo, como um estágio.
Defina RUNTIME_VERSION como a versão do Scala runtime que seu código requer.
Defina o valor da cláusula PACKAGES como o nome de um ou mais pacotes, se houver, exigidos pela classe do manipulador.
Defina o valor da cláusula HANDLER como o nome do método e objeto do manipulador.
A cláusula
AS '<scala_code>'
é necessária se o código do manipulador for especificado inline com CREATE FUNCTION.