Adicionando Novas Funções Definidas Por Usuário
Para o mecanismo UDF funcionar, as funções devem estar em C ou C++ e o seu sistema operacional deve suporta carregamento dinâmico. A distribuição fonte do MariaDB inclui um arquivo sql/udf_example.cc
que definem 5 novas funções. Consulte este arquivo para ver como a convenção de chamadas UDF funciona.
Para o mysqld
estar apto a usar funções UDF, você deve configurar o MariaDB com --with-mysqld-ldflags=-rdynamic
. A razão é que para muitas plataformas (incluindo Linux) você pode carregar uma biblioteca (com dlopen()
) de um programa ligado estaticamente, que você teria se estivesse usando --with-mysqld-ldflags=-all-static
. Se você quiser usar uma UDF que precisa acessar símbolos do mysqld
(como o exemplo metaphone
em sql/udf_example.cc
que usa default_charset_info
), você deve ligar o programa com -rdynamic
(veja man dlopen
).
Se você estiver usando uma versão precompilada do servidor, use o MySQL-Max, que suporta carregamento dinâmico.
Para cada função que você deseja usar nas instruções SQL, você deve definir funções C (ou C++) correspondente. Na discussão abaixo, o nome xxx
é usado um nome de função exemplo. Para distinguir entre o uso de SQL e C/C++, XXX()
(maiúscula) indica a chamada da função SQL e xxx()
(minúscula) indica da chamada da função C/C++.
Aa funções C/C++ que você escreve para implemmentar a interface para XXX()
são:
xxx()
(exigido)A função principal. É onde o resultado da função é computado. A correspondência entre o tipo SQL e o tipo retornado da sua função C/C++ é mostrada aqui:
Tipo SQL Tipo C/C++ STRING
char *
INTEGER
long long
REAL
double
xxx_init()
(opcional)A função de inicialização para
xxx()
. Ela pode ser usada para:- Verifica o número de argumentos para
XXX()
. - Verifica se os argumentos são de um tipo exigido ou, alternativamente, diga ao MariaDB para converter os argumentos para o tipo desejado quando a função principal é chamada.
- Aloca a memória exigida pela função principal.
- Especifica o tamanho máximo do resultado.
- Especifica (para funções
REAL
) o número máximo de decimais. - Especifica se o resultado pode ser
NULL
.
- Verifica o número de argumentos para
xxx_deinit()
(opicional)A função de finalização para
xxx()
. Ela deve liberar qualquer memória alocada pela função de inicialização.
Quando uma instrução SQL invoka XXX()
, o MariaDB chama a função de inicialização xxx_init()
para realizar qualquer configuração necessária, tais como verificação de argumentos e alocação de memória. Se xxx_init()
retorna um erro, a instrução SQL é abortada com uma mensagem e as funções principais e de finalização não são chamadas. Senão, a função principal xxx()
é chamada uma vez para cada linha. Depois de todas as linhas tiverem sido processadas, a função de finalização xxx_deinit()
é chamada, podendo assim realizar qualquer 'limpeza'.
Para funções agregadas (como SUM()
), você também deve fornecer as seguintes funções:
xxx_reset()
(exigida)Zera a soma e insere um argumento como o valor inicial para um novo grupo.
xxx_add()
(exigida)Adiciona o argumento a soma antiga.
Quando se usa UDF's agregadas o MariaDB funciona da seguinte maneira:
- Chama
xxx_init()
para deixar funções agregadas alocarem a memória necessária para armazenar os resultados. - Ordena a tabela de acordo com a expressão
GROUP BY
. - Para a primeira linha em um novo grupo, chama a função
xxx_reset()
. - Para cada nova linha que pertence ao mesmo grupo, chame a função
xxx_add()
. - Quando o grupo muda ou depois da última linha ter sido processada, chame
xxx()
para obter o resultado para o conjunto. - Repita 3-5 até que todas as linhas tenham sido processada.
- Chame
xxx_deinit()
para deixar a UDF liberar a memória alocada.
Todas as funções devem ser seguras com thread (não apenas a função principal, mas também as funções de inicialização e finalização). Isto significa que você não tem permissão para alocar qualquer variável global ou estática que alterou! Se você precisa de memória, você deve alocá-la em xxx_init()
e liberá-la em xxx_deinit()
.