Como criar um manipulador de UDF de Java¶
Este tópico descreve como escrever o manipulador de Java para uma função definida pelo usuário (UDF). Quando você escreve uma UDF em Java, você está escrevendo um código Java para o Snowflake executar como lógica UDF. Esse código Java é o manipulador da UDF.
Você implanta a UDF com CREATE FUNCTION, dando um nome à UDF e especificando o método Java como o manipulador a usar quando a UDF é chamada. Para obter mais informações sobre a criação de uma UDF com SQL, consulte Criação de uma UDF.
Para obter mais exemplos de código, consulte Exemplos de manipuladores de UDF em Java.
Neste tópico:
Como escrever o manipulador de UDF em Java¶
Use os seguintes requisitos e diretrizes ao escrever seu manipulador de UDF em Java.
Defina a classe como pública.
Dentro da classe, declare pelo menos um método público a ser usado como manipulador de UDF.
Para uma UDF inline, declare apenas um método do manipulador. Se, em vez disso, você pretende inserir a classe em um JAR como um manipulador em estágio, você pode declarar vários métodos do manipulador, especificando mais tarde cada um como manipulador com a cláusula HANDLER de uma instrução CREATE FUNCTION.
Para saber mais sobre a diferença entre um manipulador em linha e um manipulador em estágio, consulte Como manter o código do manipulador inline ou em um estágio.
Você pode declarar outros métodos, se necessário, a serem chamados pelo método do manipulador.
Use os seguintes requisitos e diretrizes para cada método do manipulador:
Declare o método do manipulador como público, estático ou não estático.
Se o método não for estático, sua classe também deverá declarar um construtor sem argumentos ou nenhum construtor.
O Snowflake não passa nenhum argumento para o construtor quando ele instancia a classe. Se o construtor lança um erro, o erro é lançado como um erro do usuário, juntamente com a mensagem de exceção.
Especifique um tipo de retorno adequado.
O tipo de retorno deve ser um dos tipos de dados especificados na coluna
Java Data Type
da tabela de mapeamento de tipos SQL-Java. O tipo de retorno deve ser compatível com o tipo de dados SQL especificado na cláusula RETURNS da instrução CREATE FUNCTION.Certifique-se de que cada argumento do método do manipulador (se houver) seja um tipo de dados especificado na coluna
Java Data Type
da tabela de mapeamento de tipos SQL-Java.Ao escolher os tipos de dados das variáveis de Java, leve em conta os valores máximos e mínimos possíveis dos dados que poderiam ser enviados do Snowflake (e devolvidos a ele).
Se você sobrecarregar um método em uma determinada classe Java, lembre-se de que o Snowflake usa apenas o número de argumentos do método, não seus tipos, para diferenciar os métodos do manipulador dentro de uma classe. A resolução baseada em tipos de dados não é prática, porque alguns tipos de dados de SQL podem ser mapeados para mais de um tipo de dados de Java e, portanto, potencialmente para mais de uma assinatura do método do manipulador.
Por exemplo, se dois métodos Java em uma classe tiverem o mesmo nome, o mesmo número de argumentos e diferentes tipos de dados, chamar uma UDF que usa um desses métodos como manipulador gera um erro semelhante ao seguinte:
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>
Se um warehouse estiver disponível, o erro será detectado no momento em que a UDF for criada. Caso contrário, o erro ocorre quando a UDF é chamada.
Siga as restrições impostas pelo Snowflake para UDFs de Java em cada método do manipulador e nos métodos chamados por ele. Para saber mais sobre estas restrições, consulte Criação de manipuladores que ficam dentro das restrições impostas pelo Snowflake.
Adição de dependências ao Classpath¶
Se o código de seu manipulador exigir classes empacotadas em arquivos JAR externos, você poderá adicionar essas dependências ao classpath gerenciado pelo Snowflake disponível para seu manipulador. A seção a seguir descreve como adicionar arquivos JAR ao classpath visível a um manipulador de UDF de Java. Para obter mais informações, consulte Disponibilização das dependências para seus códigos.
Organização de seus arquivos¶
Se você planeja compilar o código de Java para criar o arquivo JAR por conta própria, você pode organizar os arquivos da forma mostrada abaixo. Este exemplo assume que você planeja usar o mecanismo de pacote do Java.
developmentDirectory
packageDirectory
class_file1.java
class_file2.java
classDirectory
class_file1.class
class_file2.class
manifest_file.manifest (opcional)
jar_file.jar
put_command.sql
developmentDirectory
Esse diretório contém os arquivos específicos do projeto necessários para criar sua UDF em Java.
packageDirectory
Esse diretório contém os arquivos .java para compilar e incluir no pacote.
class_file#.java
Esses arquivos contêm o código-fonte de Java da UDF.
class_file#.class
Esses são os arquivos .class criados ao compilar os arquivos .java.
manifest_file.manifest
O arquivo do manifesto opcional usado ao combinar os arquivos .class (e, opcionalmente, os arquivos JAR de dependência) com o arquivo JAR.
jar_file.jar
O arquivo JAR que contém o código da UDF.
put_command.sql
Esse arquivo contém o comando SQL PUT para copiar o arquivo JAR em um estágio do Snowflake.
Compilação do código de Java e criação do arquivo JAR¶
Para criar um arquivo JAR contendo o código de Java compilado:
Use o javac para compilar seu arquivo .java em um arquivo .class.
Se você usar um compilador mais novo que a versão 11.x, você poderá usar a opção “–release” para especificar que a versão de destino é a versão 11.
Coloque seu arquivo .class em um arquivo JAR. Você pode empacotar vários arquivos de classe (e outros arquivos JAR) em seu arquivo JAR.
Por exemplo:
jar cf ./my_udf.jar MyClass.class
Um arquivo do manifesto será necessário se sua classe de manipulador estiver em um pacote, e opcional caso contrário. O exemplo a seguir utiliza um arquivo do manifesto:
jar cmf my_udf.manifest ./my_udf.jar example/MyClass.class
Para construir o arquivo jar com todas as dependências incluídas, você pode usar o comando
mvn package
do Maven com o plugin maven-assembly. Para obter mais informações sobre o plugin maven-assembly, veja a página de utilização do Maven.O Snowflake fornece automaticamente as bibliotecas Java padrão (por exemplo,
java.util
). Se seu código chamar essas bibliotecas, você não precisará incluí-las em seu arquivo JAR.Os métodos que você chama nas bibliotecas devem seguir as mesmas restrições impostas pelo Snowflake que seu método Java. Para saber mais sobre estas restrições, consulte Criação de manipuladores que ficam dentro das restrições impostas pelo Snowflake.
Cópia do arquivo JAR em seu estágio¶
Para que o Snowflake possa ler o JAR que contém seu método do manipulador, você precisa copiar o JAR em um dos seguintes tipos de estágio:
Um estágio interno de usuário ou nomeado.
Atualmente, o Snowflake não oferece suporte ao uso de uma tabela de estágio para armazenar um arquivo JAR com manipuladores da UDF. Para saber mais sobre estágios internos, consulte Escolha de um estágio interno para os arquivos locais.
Um estágio externo.
O estágio que hospeda o arquivo JAR deve ser legível pelo proprietário da UDF.
Normalmente, você carrega o JAR em um estágio interno nomeado usando o comando PUT. Observe que você não pode executar o comando PUT
pelo Snowflake GUI; você pode usar o SnowSQL para executar PUT
. Consulte a seção Exemplos de manipuladores de UDF em Java para obter um exemplo de um comando PUT
para copiar um arquivo .jar em um estágio.
Para saber mais sobre a criação de estágios, consulte CREATE STAGE.
Advertências e práticas recomendadas
Se você apagar ou renomear o arquivo JAR, não poderá mais chamar a UDF.
Se você precisar atualizar seu arquivo JAR:
Atualize-o enquanto nenhuma chamada para a UDF pode ser feita.
Se o antigo arquivo .jar ainda estiver no estágio, o comando
PUT
deverá incluir a cláusulaOVERWRITE=TRUE
.
Nota
Um usuário que atue em relação a UDFs deve ter uma função que tenha recebido as permissões necessárias para a ação. Para obter mais informações, consulte Granting Privileges for User-Defined Functions.