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++ STRINGchar *INTEGERlong longREALdoublexxx_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().