As instruções CREATE FUNCTION e CREATE PROCEDURE definem uma função ou um procedimento que pode ser chamado, geralmente denominado rotina.
As instruções CREATE FUNCTION e CREATE PROCEDURE definem uma função ou um procedimento que pode ser chamado, geralmente denominado rotina.
As rotinas são úteis para a criação de blocos reutilizáveis de código que podem ser executados, várias vezes, independentemente. Elas podem ser implementadas como uma série de instruções ESQL, um método Java ou um procedimento armazenado do banco de dados. Essa flexibilidade significa que algumas das cláusulas no diagrama de sintaxe não são aplicáveis (ou permitidas) para todos os tipos de rotina.
Cada rotina possui um nome, que deve ser exclusivo no esquema ao qual ela pertence. Isso significa que os nomes de rotinas não podem ser sobrecarregados; se o intermediário detectar que uma rotina foi sobrecarregada, ele emitirá uma exceção.
Especifique o nome da rotina utilizando a cláusula RoutineName e os parâmetros da rotina utilizando a cláusula ParameterList. Se a cláusula LANGUAGE especificar ESQL, a rotina deverá ser implementada utilizando uma única instrução ESQL. Essa instrução será mais útil se for uma instrução composta (BEGIN ... END), uma vez que pode conter quantas instruções ESQL forem necessárias para desempenhar sua função.
Alternativamente, em vez de fornecer um corpo ESQL para a rotina, você pode especificar uma cláusula LANGUAGE que não seja ESQL. Isso permite utilizar a cláusula EXTERNAL NAME para fornecer uma referência ao corpo real da rotina, onde quer que esteja localizada externamente, para o intermediário. Para obter detalhes adicionais sobre como utilizar a cláusula EXTERNAL NAME, consulte Chamando Procedimentos Armazenados e Chamando uma Rotina Java.
As rotinas de qualquer tipo de LANGUAGE pode ter parâmetros IN, OUT e INOUT. Isso permite que o responsável pela chamada transmita vários valores para a rotina e receba vários valores atualizados de volta. Isso é um adicionamento a qualquer cláusula RETURNS que a rotina possa ter. A cláusula RETURNS permite que a rotina transmita de volta um valor para o responsável pela chamada.
As rotinas implementadas em diferentes linguagens possuem suas próprias restrições, documentadas a seguir, sobre quais tipos de dados podem ser transmitidos ou retornados. O tipo de dados do valor retornado deve corresponder ao tipo de dados do valor definido para ser retornado da rotina. Além disso, se uma rotina for definida para ter um valor de retorno, o responsável pela chamada da rotina não poderá ignorá-lo. Para obter detalhes adicionais, consulte a Instrução CALL.
Para qualquer tipo de linguagem ou rotina, o método de chamada da rotina deve corresponder ao modo de declaração da rotina. Se a rotina tiver uma cláusula RETURNS, utilize a sintaxe de chamada FUNCTION ou uma instrução CALL com uma cláusula INTO. Por outro lado, se uma rotina não tiver uma cláusula RETURNS, você deverá utilizar uma instrução CALL sem uma cláusula INTO.
Se o tipo de rotina for FUNCTION, o indicador de direção (IN, OUT, INOUT) será opcional para cada parâmetro. No entanto, é uma boa prática de programação especificar um indicador de direção para todas as novas rotinas de qualquer tipo para finalidades de documentação.
As variáveis ESQL que são declaradas como CONSTANT (ou referências a variáveis declaradas como CONSTANT) não têm permissão para ter a direção OUT ou INOUT.
As rotinas ESQL são escritas em ESQL e possuem uma cláusula LANGUAGE de ESQL. O corpo de uma rotina ESQL é geralmente uma instrução composta da forma BEGIN … END, contendo várias instruções para processar os parâmetros transmitidos para a rotina.
CREATE PROCEDURE swapParms ( IN parm1 CHARACTER, OUT parm2 CHARACTER, INOUT parm3 CHARACTER ) BEGIN SET parm2 = parm3; SET parm3 = parm1; END;
Este procedimento de exemplo mostra o uso recursivo de uma rotina ESQL. Ele analisa uma árvore, visitando todos os locais no ponto inicial especificado, e abaixo dele, e relata o que foi localizado:
SET OutputRoot.MQMD = InputRoot.MQMD; DECLARE answer CHARACTER; SET answer = ''; CALL navigate(InputRoot.XML, answer); SET OutputRoot.XML.Data.FieldNames = answer; CREATE PROCEDURE navigate (IN root REFERENCE, INOUT answer CHARACTER) BEGIN SET answer = answer || 'Reached Field... Type:' || CAST(FIELDTYPE(root) AS CHAR)|| ': Name:' || FIELDNAME(root) || ': Value :' || root || ': '; DECLARE cursor REFERENCE TO root; MOVE cursor FIRSTCHILD; IF LASTMOVE(cursor) THEN SET answer = answer || 'Field has children... drilling down '; ELSE SET answer = answer || 'Listing siblings... '; END IF; WHILE LASTMOVE(cursor) DO CALL navigate(cursor, answer); MOVE cursor NEXTSIBLING; END WHILE; SET answer = answer || 'Finished siblings... Popping up '; END;
Ao receber a seguinte mensagem de entrada:
<Person> <Nome>John Smith</Nome> <Salary period='monthly' taxable='yes'>-1200</Salary> </Person>
o procedimento produz a seguinte saída, que foi formatada manualmente:
Reached Field... Type:16777232: Name:XML: Value :: Field has children... drilling down Reached Field... Type:16777216: Name:Person: Value :: Field has children... drilling down Reached Field... Type:16777216: Name:Name: Value :John Smith: Field has children... drilling down Reached Field... Type:33554432: Name:: Value :John Smith: Listing siblings... Finished siblings... Popping up Finished siblings... Popping up Reached Field... Type:16777216: Name:Salary: Value :-1200: Field has children... drilling down Reached Field... Type:50331648: Name:period: Value :monthly: Listing siblings... Finished siblings... Popping up Reached Field... Type:50331648: Name:taxable: Value :yes: Listing siblings... Finished siblings... Popping up Reached Field... Type:33554432: Name:: Value :-1200: Listing siblings... Finished siblings... Popping up Finished siblings... Popping up Finished siblings... Popping up Finished siblings... Popping up
>>--"-- className---.---methodName--"--------------><em que className identifica a classe que contém o método e methodName identifica o método a ser chamado. Se a classe fizer parte de um pacote, a parte do identificador de classe deve incluir o prefixo completo do pacote; por exemplo, "com.ibm.broker.test.MyClass.myMethod".
Para localizar a classe Java, o intermediário procura conforme descrito em Implementando Classes Java.
public static <return-type> <method-name> (< 0 - N parameters>)
em que <return-type> deve estar na lista dos tipos de dados IN Java na tabela no Mapeamento de Tipo de Dados ESQL para Java (excluindo o tipo REFERENCE, que não é permitido como um valor de retorno) ou o tipo de dados Java void. Os tipos de dados do parâmetro também devem estar na tabela Mapeamento de Tipo de Dados ESQL para Java. Além disso, não é permitido que o método Java tenha uma cláusula exception throws em sua assinatura.
Você pode utilizar a API Java UDN (User Defined Node) em seu método Java, desde que observe as restrições documentadas em Restrições em Rotinas Java. Para obter informações adicionais sobre como utilizar a API UDN, consulte Compilando um Nó Java Definido pelo Usuário.
Esta rotina contém três parâmetros de direções diversas e retorna um inteiro, que é mapeado para um tipo de retorno Java de java.lang.Long.
CREATE FUNCTION myProc1( IN P1 INTEGER, OUT P2 INTEGER, INOUT P3 INTEGER ) RETURNS INTEGER LANGUAGE JAVA EXTERNAL NAME "com.ibm.broker.test.MyClass.myMethod1";
É possível utilizar o seguinte ESQL para chamar myProc1:
CALL myProc1( intVar1, intVar2, intVar3) INTO intReturnVar3; -- or SET intReturnVar3 = myProc1( intVar1, intVar2, intVar3);
Esta rotina contém três parâmetros de direções diversas e possui um tipo de retorno Java de void.
CREATE PROCEDURE myProc2( IN P1 INTEGER, OUT P2 INTEGER, INOUT P3 INTEGER ) LANGUAGE JAVA EXTERNAL NAME "com.ibm.broker.test.MyClass.myMethod2";
Você deve utilizar o seguinte ESQL para chamar myProc2:
CALL myProc2(intVar1, intVar2, intVar3);
A classe Java a seguir fornece um método para cada um dos exemplos de Java anteriores:
package com.ibm.broker.test; class MyClass { public static Long myMethod1( Long P1, Long[] P2 Long[] P3) { ... } public static void myMethod2( Long P2, Long[] P2 Long[] P3) { ... } /* Quando qualquer um desses métodos é chamado: P1 pode ou não ser NULL (dependendo do valor de intVar1). P2[0] é sempre NULL (qualquer que seja o valor de intVar2). P3[0] pode ou não ser NULL (dependendo do valor de intVar3). Isso é igual às rotinas ESQL LANGUAGE. Quando esses métodos retornam: intVar1 é inalterado intVar2 pode ainda ser NULL ou pode ter sido alterado intVar3 pode conter o mesmo valor ou pode ter sido alterado. Isso é igual às rotinas ESQL LANGUAGE. Quando myMethod1 retorna: intReturnVar3 é NULL (se o método retornar NULL) ou contém o valor retornado pelo método. */ }
Tipos de Dados ESQL 1 | Tipos de Dados Java IN | Tipos de Dados Java INOUT e OUT |
INTEGER, INT | java.lang.Long | java.lang.Long [] |
FLOAT | java.lang.Double | java.lang.Double[] |
DECIMAL | java.math.BigDecimal | java.math.BigDecimal[] |
CHARACTER, CHAR | java.lang.String | java.lang.String[] |
BLOB | byte[] | byte[][] |
BIT | java.util.BitSet | java.util.BitSet[] |
DATE | com.ibm.broker.plugin.MbDate | com.ibm.broker.plugin.MbDate[] |
TIME 2 | com.ibm.broker.plugin.MbTime | com.ibm.broker.plugin.MbTime[] |
GMTTIME 2 | com.ibm.broker.plugin.MbTime | com.ibm.broker.plugin.MbTime[] |
TIMESTAMP 2 | com.ibm.broker.plugin.MbTimestamp | com.ibm.broker.plugin.MbTimestamp[] |
GMTTIMESTAMP 2 | com.ibm.broker.plugin.MbTimestamp | com.ibm.broker.plugin.MbTimestamp[] |
INTERVAL | Não Suportado | Não Suportado |
BOOLEAN | java.lang.Boolean | java.lang.Boolean[] |
REFERENCE (para uma árvore de mensagens) 3 4 5 6 | com.ibm.broker.plugin.MbElement | com.ibm.broker.plugin.MbElement[] (Suportado para INOUT. Não suportado para OUT) |
ROW | Não Suportado | Não Suportado |
LIST | Não Suportado | Não Suportado |
Por exemplo, se uma referência ESQL para OutputRoot.XML.Test for transmitida para um método Java como um MbElement INOUT, mas um MbElement diferente for transmitido de volta para o ESQL quando a chamada retornar, o elemento diferente também deverá apontar para algum lugar na árvore OutputRoot.
Uma REFERENCE a uma variável escalar pode ser utilizada na CALL de um método Java, desde que o tipo de dados da variável ao qual a referência se refere corresponda ao tipo de dados correspondente na assinatura do programa Java.
Você tem direito a efetuar spawn de encadeamentos em seu método. No entanto, os encadeamentos que sofrerem spawn não deverão utilizar APIs Java de plug-in e você deverá retornar o controle ao intermediário.
Observe que todas as restrições que se aplicam à utilização da API UDN também se aplicam aos métodos Java chamados a partir de ESQL.
Incluir seu arquivo JAR no arquivo BAR é o método mais eficiente e flexível de implementação no intermediário.
Você pode incluir um arquivo JAR no arquivo BAR manualmente ou automaticamente utilizando as ferramentas. Através das ferramentas é a maneira mais simples de incluir um arquivo JAR em um arquivo BAR.
Se as ferramentas localizarem a classe Java correta dentro de um projeto Java referido aberto no espaço de trabalho, elas automaticamente compilarão a classe Java em um arquivo JAR e a incluirão no arquivo BAR. Este é o mesmo procedimento que você segue para implementar um nó Java Compute dentro de um JAR, conforme descrito em Carregamento de Classe do Nó Definido pelo Usuário.
Quando implementar um arquivo JAR a partir das ferramentas, uma reimplementação do arquivo BAR contendo o arquivo JAR faz as classes Java referidas serem recarregadas pelo fluxo que foi reimplementando; assim como parar e reiniciar um fluxo de mensagens que se refere a uma classe Java. Certifique-se de parar e reiniciar (ou reimplementar) todos os fluxos que se referem ao arquivo JAR que você deseja atualizar. Isto evita o problema de alguns fluxos serem executados com a versão antiga do arquivo JAR e outros fluxos executados com a nova versão.
Observe que as ferramentas implementarão apenas um arquivo JAR; elas não implementarão um arquivo de classe Java independente.
Este procedimento deve ser feito manualmente; não é possível utilizar as ferramentas.
Neste método, a reimplementação do fluxo de mensagens não recarrega as classes Java referidas; nem pára e reinicia o fluxo de mensagens. A única maneira de recarregar as classes neste caso é parar e reiniciar o próprio intermediário.
Para ativar o intermediário para localizar uma classe Java, certifique-se de que ela esteja em um dos locais acima. Se o intermediário não puder localizar a classe especificada, ele emitirá uma exceção.
Apesar de você ter as opções mostradas acima ao implementar o arquivo JAR, permitir que as ferramentas implementem o arquivo BAR fornece a maior flexibilidade ao implementar novamente o arquivo JAR.