Rotinas Armazenadas em JavaScript no MySQL

Como o componente MLE do MySQL 9.0+ permite criar functions e procedures escritas em JavaScript, rodando sobre o GraalVM, para manipular dados e JSON diretamente dentro do banco.

A partir do MySQL 9.0/9.1 (ciclo de "innovation releases"), o servidor ganhou a capacidade de rodar rotinas armazenadas escritas em JavaScript, não só em SQL. Usando LANGUAGE JAVASCRIPT em uma CREATE FUNCTION ou CREATE PROCEDURE, o corpo da rotina é executado dentro do banco por uma engine embutida baseada no GraalVM, sem precisar exportar dados para um servidor de aplicação só para fazer uma transformação mais elaborada.

Instalando o componente MLE

Esse recurso não vem ativado por padrão: ele depende do Multilingual Engine (MLE), um componente do MySQL Enterprise Edition que precisa ser instalado explicitamente antes de criar qualquer rotina em JavaScript:

INSTALL COMPONENT "file://component_mle";

Sem o componente instalado, qualquer tentativa de usar LANGUAGE JAVASCRIPT falha. Vale reforçar: como é um recurso de Enterprise Edition, ele não está disponível na build Community do MySQL nem em todo serviço gerenciado — antes de planejar em cima dele, confirme se a distribuição em uso realmente oferece o MLE.

Criando uma função em JavaScript

A sintaxe é parecida com a de uma rotina SQL normal, trocando o corpo por um bloco delimitado com dollar-quoting ($$) e escrito em JavaScript:

CREATE FUNCTION titulo_capitalizado(texto VARCHAR(255))
RETURNS VARCHAR(255)
LANGUAGE JAVASCRIPT
AS $$
    return texto
        .toLowerCase()
        .split(' ')
        .map(palavra => palavra.charAt(0).toUpperCase() + palavra.slice(1))
        .join(' ');
$$;

SELECT titulo_capitalizado('o rato roeu a roupa do rei');
-- 'O Rato Roeu A Roupa Do Rei'

Os argumentos de entrada e o valor de retorno são convertidos automaticamente entre os tipos SQL e os tipos equivalentes em JavaScript (INT vira number, VARCHAR vira string, e assim por diante), então dentro da função é só JavaScript comum.

Manipulando JSON nativamente

Um dos casos mais úteis é processar colunas JSON, já que dentro da rotina o valor chega como um objeto JavaScript de verdade, sem precisar de funções como JSON_EXTRACT() encadeadas:

CREATE FUNCTION soma_valores_pedido(pedido JSON)
RETURNS DECIMAL(10, 2)
LANGUAGE JAVASCRIPT
AS $$
    return pedido.itens.reduce((total, item) => total + item.preco * item.quantidade, 0);
$$;

SELECT soma_valores_pedido('{
    "itens": [
        {"preco": 19.90, "quantidade": 2},
        {"preco": 45.00, "quantidade": 1}
    ]
}');
-- 84.80

Procedures em JavaScript

O mesmo vale para CREATE PROCEDURE, incluindo o uso de parâmetros OUT:

CREATE PROCEDURE classifica_nota(IN nota DECIMAL(4,2), OUT conceito VARCHAR(20))
LANGUAGE JAVASCRIPT
AS $$
    if (nota >= 9) {
        conceito = 'Excelente';
    } else if (nota >= 7) {
        conceito = 'Bom';
    } else if (nota >= 5) {
        conceito = 'Regular';
    } else {
        conceito = 'Insuficiente';
    }
$$;

CALL classifica_nota(8.5, @resultado);
SELECT @resultado;
-- 'Bom'

Onde faz sentido usar

Cuidados

As palavras mysql, console e graal são reservadas pelo componente MLE e não podem ser usadas como nomes de variável ou argumento. A execução roda em um ambiente isolado (sem acesso a rede ou sistema de arquivos), então não é possível fazer chamadas HTTP ou usar bibliotecas externas de dentro da rotina. E, como qualquer lógica embutida no banco, abusar de rotinas em JavaScript para regras de negócio complexas pode dificultar versionamento e testes comparado a manter essa lógica na camada de aplicação — vale usar com moderação.

Compatibilidade

Rotinas em JavaScript exigem MySQL 9.0 ou superior (innovation release, não faz parte do MySQL 8.4 LTS) com o componente MLE instalado, disponível apenas no MySQL Enterprise Edition e em serviços gerenciados que o disponibilizem, como o Oracle HeatWave MySQL. Confirme o suporte na versão e distribuição em uso antes de depender desse recurso em produção.

documentação oficial

Conclusão

Rotinas armazenadas em JavaScript trazem uma linguagem mais expressiva para dentro do MySQL em casos onde SQL procedural fica verboso demais, especialmente ao lidar com JSON. É um recurso ainda recente, restrito ao Enterprise Edition, mas mostra para onde o MySQL está caminhando: um motor cada vez mais poliglota, e não mais limitado só a SQL.

Tecnologia:
mysql

Deixe seu Comentário!

Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.

Comentário
Nome
Email
lock Seu e-mail não será publicado.