Por que utilizar JavaScript em Stored Proceduers?
JavaScript é uma das linguagens de programação mais populares. Além de sua sintaxe simplificada e suporte a recursos modernos, um fator-chave para sua adoção é o vasto ecossistema de módulos reutilizáveis disponíveis para diversas plataformas, como navegadoers e ambientes de servidor.
Invocando JavaScript no Banco de Dados
O código JavaScript pode ser executado dinamicamente ou através de especificações de chamada. As especificações podem referenciar módulos MLE (Multilingual Engine) ou funções JavaScript inline.
Existem duas abordagens principais para rodar JavaScript no lado do servidor:
- Execução dinâmica utilizando o pacote
DBMS_MLE. - Uso de código PL/SQL que invoca funções exportadas de módulos JavaScript (chamadas de invocação via módulo MLE) ou funções definidas diretamente no DDL.
Execução Dinâmica
O exemplo abaixo demonstra como executar código JavaScript de forma dinâmica:
SET SERVEROUTPUT ON;
DECLARE
v_ctx DBMS_MLE.context_handle_t;
v_source CLOB;
BEGIN
v_ctx := DBMS_MLE.create_context;
v_source := q'~
console.log('Mensagem de teste via DBMS_MLE')
~';
DBMS_MLE.eval(
context_handle => v_ctx,
language_id => 'JAVASCRIPT',
source => v_source,
source_name => 'Trecho JS'
);
END;
/
Mensagem de teste via DBMS_MLE
Procedimento PL/SQL concluído com sucesso.
Este trecho ilustra conceitos essenciais:
- Um contexto de execução deve ser criado explicitamente.
- O código JavaScript é fornecido como uma variável
CLOBouVARCHAR2. - O contexto precisa ser avaliado diretamente.
Ao executar JavaScript dinamicamente, há uma integração entre PL/SQL e JavaScript. O snippet não é reutilizável fora desse contexto. A saída de console.log é redirecionada para DBMS_OUTPUT.
Invocação via Módulo MLE
Módulos JavaScript podem ser criados como objetos de schema e persistidos no banco de dados.
Após a definição, o módulo pode ser utilizado em SQL e PL/SQL. Veja a criação de um módulo:
CREATE OR REPLACE MLE MODULE modulo_saudacao
LANGUAGE JAVASCRIPT AS
function saudacao() {
console.log('Olá, este é um módulo JavaScript');
}
export { saudacao }
/
Módulo MLE criado.
Para invocar a função exportada, é necessário uma especificação de chamada PL/SQL:
CREATE OR REPLACE PROCEDURE proc_saudacao
AS MLE MODULE modulo_saudacao
SIGNATURE 'saudacao()';
/
Procedimento criado.
A especificação de chamada expõe a função saudacao(). A partir daí, ela pode ser chamada como qualquer outro procedimento PL/SQL:
SET SERVEROUTPUT ON
BEGIN
proc_saudacao;
END;
/
Olá, este é um módulo JavaScript
Procedimento PL/SQL concluído com sucesso.
Ambiente de Execução Restrita (Execução PURE)
A palavra-chave PURE pode ser usada em ambientes MLE e especificações de chamada inline para criar um contexto JavaScript restrito. Neste modo, o código não pode acessar APIs de banco de dados com estado, como drivers SQL ou interfaces de funções externas (FFI).
Execuções PURE são úteis para isolar código, como bibliotecas JavaScript de terceiros, reduzindo superfícies de ataque. Elas também permitem que desenvolvedores com permissões mínimas criem funções definidas pelo usuário sem acesso adicional a recursos do banco.
Durante a execução PURE, as seguintes APIs não estão disponíveis:
mle-js-oracledbmle-js-plsql-ffimle-js-fetch- Classes globais como
session,sodae funções comorequire.
APIs que não interagem com o estado do banco, como js-encodings, permanecem acessíveis.
Exemplo de definição de um módulo PURE e sua invocação:
CREATE OR REPLACE MLE MODULE modulo_puro
LANGUAGE JAVASCRIPT AS
export function mensagemPura() {
console.log('Execução em ambiente restrito');
}
/
Módulo MLE criado.
CREATE OR REPLACE MLE ENV env_puro
IMPORTS( 'modulo_puro' MODULE modulo_puro) PURE;
Ambiente MLE criado.
CREATE OR REPLACE PROCEDURE proc_puro
AS MLE MODULE modulo_puro ENV env_puro SIGNATURE 'mensagemPura';
/
Procedimento criado.
-- Alternativa inline
CREATE OR REPLACE PROCEDURE proc_puro_inline
AS MLE LANGUAGE JAVASCRIPT PURE
{{
console.log('Chamada inline em ambiente PURE');
}};
/
Procedimento criado.
Para execução dinâmica com PURE, utilize um ambiente criado com a palavra-chave:
SET SERVEROUTPUT ON;
DECLARE
v_ctx dbms_mle.context_handle_t;
v_snippet CLOB;
BEGIN
v_ctx := dbms_mle.create_context(environment => 'ENV_PURO');
v_snippet := q'~
console.log('Execução dinâmica MLE em modo PURE');
~';
dbms_mle.eval(v_ctx, 'JAVASCRIPT', v_snippet);
dbms_mle.drop_context(v_ctx);
EXCEPTION
WHEN OTHERS THEN
dbms_mle.drop_context(v_ctx);
RAISE;
END;
/
Execução dinâmica MLE em modo PURE
Procedimento PL/SQL concluído com sucesso.
Exemplo Prático: Acesso a Dados com Depuração
O código abaixo demonstra como acessar o banco de dados usando mle-js-oracledb em um módulo não restrito. As variáveis e estruturas foram adaptadas para clareza:
CREATE OR REPLACE MLE MODULE modulo_debug
LANGUAGE JAVASCRIPT AS
import conexao from "mle-js-oracledb";
export function contarTabelas() {
const db = conexao.defaultConnection();
console.log("Fase 1: Verificando conectividade");
const teste = db.execute(`SELECT 'OK' as status FROM dual`);
console.log("Resultado do teste: " + JSON.stringify(teste.rows[0]));
console.log("Fase 2: Consultando metadados");
const meta = db.execute(`
SELECT COUNT(*) as contagem
FROM user_tables
WHERE table_name = 'TABELA_EXEMPLO'
`);
console.log("Tabela existe: " + JSON.stringify(meta.rows[0]));
console.log("Fase 3: Contagem final");
const resultado = db.execute(`
SELECT COUNT(*) as total
FROM tabela_exemplo
`);
console.log("Dados finais: " + JSON.stringify(resultado));
return resultado.rows[0][0];
}
/
Módulo MLE criado.
Criando a função PL/SQL correspondente:
CREATE OR REPLACE FUNCTION fn_contar_tabelas
RETURN NUMBER
AS MLE MODULE modulo_debug
SIGNATURE 'contarTabelas';
/
Função criada.
Executanod a função e observando a saída:
SELECT fn_contar_tabelas() FROM DUAL;
FN_CONTAR_TABELAS()
-------------------
Fase 1: Verificando conectividade
Resultado do teste: {"STATUS":"OK"}
Fase 2: Consultando metadados
Tabela existe: {"CONTAGEM":1}
Fase 3: Contagem final
Dados finais: {"metaData":[{"name":"TOTAL"}],"rows":[{"TOTAL":5}]}
5
Parâmetros de Controle em PDB/CDB
O recurso MLE é controlado pelo parâmetro mle_prog_languages. Desativando-o:
ALTER SYSTEM SET mle_prog_languages=off;
Qualquer chamada a funções MLE resultará em erro:
SELECT fn_contar_tabelas() FROM DUAL;
ORA-00439: recurso não habilitado: MLE
Reativando o recurso:
ALTER SYSTEM SET mle_prog_languages=all;
SELECT fn_contar_tabelas() FROM DUAL;
-- Saída normal como anteriormente
Para detalhes adicionais, consulte a documentação oficial do Oracle Database sobre MLE.