XOOPS Brasil

 

14.2. Adicionando Novas Funções ao MySQL

Existem dois modos de se adicionar novas funções ao MySQL:

  • Você pode adicionar novas funções através da interface de funções definidas por utilizadores - user-definable function (UDF). Funções definidas por utilizadores são adicionadas e removidas dinamicamente usando as instruções CREATE FUNCTION e DROP FUNCTION. Veja mais informações sobre isto na Seção 14.2.1, “Sintaxe CREATE FUNCTION/DROP FUNCTION.

  • Você pode adicionar as funções como uma função nativa do MySQL. Funções nativas são compiladas no servidor mysqld e ficam disponíveis em uma base permanente.

Cada método tem suas vantagens e desvantagens:

  • Se você escreve uma função definida pelo utilizador, você deve instalar o arquivo objeto no seu servidor. Se você compilou a sua função dentro do servidor você não precisará fazer isto.

  • Você pode adicionar UDFs para um distribuição binária MySQL. Funções nativas exigem que você modifique a sua distribuição fonte.

  • Se você atualizar a sua ditribuição MySQL, você pode continuar a usar a sua UDF previamente instalada. Para funções nativas, você deve repetir as suas modificações a cada vez que você atualizar.

Seja qual for o método que você utilizou para adicionar novas funções, eles podem ser usados como funções nativas tais como ABS() ou SOUNDEX().

14.2.1. Sintaxe CREATE FUNCTION/DROP FUNCTION

CREATE [AGGREGATE] FUNCTION nome_função RETURNS {STRING|REAL|INTEGER}
SONAME nome_bibliot_compartilhada
DROP FUNCTION function_name

Uma função definida pelo utilizador (user-definable function - UDF) é um modo de extender o MySQL com uma nova função que funciona como funções nativas do MySQL tais como ABS() e CONCAT().

AGGREGATE é uma nova opção do MySQL Versão 3.23. Uma função AGGREGATE funciona exatamente como uma função GROUP nativa do MySQL como SUM ou COUNT().

CREATE FUNCTION salva o nome e o tipo da função e o nome da biblioteca compartilhada na tabela do sistema mysql.func. Você deve ter privilégios INSERT e DELETE no banco de dados mysql para criar e deletar funções.

Todas as funções ativas são recarregadas a cada vez que o servidor é reiniciado, a menos que você reinicie o mysqld com a opção --skip-grant-tables. Neste caso, a inicialização de UDF é ignorada e as UDFs estão indisponíveis. (Uma função ativa é aquela que foi carregada com CREATE FUNCTION e não foi removida com DROP FUNCTION.)

Para instruções sobre como escrever funções denidas por utilizadores, veja Seção 14.2, “Adicionando Novas Funções ao MySQL”. Para o mecanisnmo UDF funcionar, as funções dever ser escritas em C ou C++, seu sistema operacional deve suporta carregamento dinâmico e você deve compilar o mysqld dinamicamente (e não estaticamente).

Note que para fazer AGGREGATE funcioanr, você deve ter uma tabela mysql.func que contém a coluna type. Se você não tem esta tabela, você deve executar o script mysql_fix_privilege_tables para criá-la.

14.2.2. Adicionando Novas Funções Definidas Por Utilizador

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 MySQL 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 MySQL 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 SQLTipo C/C++
    STRINGchar *
    INTEGERlong long
    REALdouble
  • 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 MySQL 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.

  • 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 MySQL 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 MySQL funciona da seguinte maneira:

  1. Chama xxx_init() para deixar funções agregadas alocarem a memória necessária para armazenar os resultados.

  2. Ordena a tabela de acordo com a expressão GROUP BY.

  3. Para a primeira linha em um novo grupo, chama a função xxx_reset().

  4. Para cada nova linha que pertence ao mesmo grupo, chame a função xxx_add().

  5. Quando o grupo muda ou depois da última linha ter sido processada, chame xxx() para obter o resultado para o conjunto.

  6. Repita 3-5 até que todas as linhas tenham sido processada.

  7. 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().

14.2.2.1. Sequência de Chamadas UDF para Funções Simples

A função principal deve ser declarada como mostrado aqui. Note que o tipo retornado e os parâmetros diferem, dependendo se você irá declarar a função SQL XXX() para retornar STRING, INTEGER, ou REAL na instrução CREATE FUNCTION:

Para funções STRING:

char *xxx(UDF_INIT *initid, UDF_ARGS *args,
char *result, unsigned long *length,
char *is_null, char *error);

Para funções INTEGER:

long long xxx(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);

Para funções REAL:

double xxx(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);

As funções de inicialização e finalização são declaradas desta forma:

my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
void xxx_deinit(UDF_INIT *initid);

O parâmetro initid é passado para todas as três funções. Ela aponta para uma estrutura UDF_INIT que é usada para passar informações entre as funções. Os membros da estrutura UDF_INIT são listados abaixo. A função de inicialização deve estar em todos os menbros que desejam ser alterados. (Para utilizar o padrão para um membro, deixe-o inalterado.):

  • my_bool maybe_null

    xxx_init() deve definir maybe_null com 1 se xxx() pode retornar NULL. O valor padrão é 1 se qualquer um dos argumentos são declarados como maybe_null.

  • unsigned int decimals

    Número de decimais. O valor padrão é o número máximo de deciamis no argumento passado na função principal. (Por exemplo, se a função é passada function is passed 1.34, 1.345 e 1.3, o padrão seria 3, pois 1.345 tem 3 decimais.

  • unsigned int max_length

    O tamanho máximo de um resultado string. O valor padrão difere dependendo do tipo de resultado da função. Para funções strings, o padrão é o temanho do maior argumento. Para funções do tipo inteiro, o padrão é 21 digitos. Para funções do tipo real, o padrão é 13 mais o número de decimais indicados por initid->decimals. (Para funções numéricas, o tamanho inclui qualquer caracter de sinal ou ponto decimal.)

    Se você quiser retornar um blon, você pode definí-lo com 65K ou 16M; esta memória não é alocada, mas usada para decidir qual tipo de coluna utilizar se houver necessidade dese armazenar dados temporários.

  • char *ptr

    Um ponteiro que a função pode usar para o seus propósitos. Por exemplo, funções pode usar initid->ptr para comunicar memórias alocadas entre funções. Na xxx_init(), aloca a memória e a atribui a este ponteiro:

    initid->ptr = allocated_memory;
    

    Em xxx() e xxx_deinit(), se refira a initid->ptr para usar ou liberar a memória.

14.2.2.2. Sequência de Chamadas UDF para Funções Agregadas

Aqui segue uma descrição das diferentes funções que você precisa definir quando você quer criar uma função UDF agregada.

Note que a seguinte função NÃO é necessária ou usada pelo MySQL 4.1.1. Você ainda pode manter a definição de sua função se você quiser o seu código funcinonando com o MySQL 4.0 e MySQL 4.1.1

char *xxx_reset(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);

Esta função é chamada quando o MySQL encontra a primiera linha em um novo grupo. Na função você deve zerar quaisquer variáveis sumárias internas e então definir o argumento dados como o primeiro argumento no grupo.

Em muitos casos isto é implementado internamente zerando todas as variáveis (por exemplo, chamando xxx_clear() e então chamando xxx_add().

A seguinte função só é exigida pelo MySQL 4.1.1 e acima:

char *xxx_clear(UDF_INIT *initid, char *is_null, char *error);

Esta função é chamada quando o MySQL precisa de zerar o resumo dos resultados. Ele será chamado no começo de cada grupo novo mas também pode ser chamado para zerar os valores para uma consulta que não tiver registros coincidentes. is_null será definido para apontar para CHAR(0) antes de chamar xxx_clear().

Você pode usar o ponteiro error para armazenar um byte se alguma coisa der errado.

char *xxx_add(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);

Esta função é chamada por todas as linhas que pertencem ao mesmo grupo, exceto na primeira linha. Nesta você deve adicionar o valor em UDF_ARGS a sua variavel sumária interna.

A função xxx() deve ser declarada da mesma forma que você define uam função UDF simples. Veja mais informações sobre isto na Seção 14.2.2.1, “Sequência de Chamadas UDF para Funções Simples”.

A função é chamada quando todas as linhas no grupo tem sido processada. Normamente você nunca deve acessar a variável args aqui mas retornar o seu valor baseado em sua variável sumária interna.

Todos os argumentos processados em xxx_reset() e xxx_add() devem ser feito de forma idêntica as UDF's normais. Veja mais informações sobre isto na Seção 14.2.2.3, “Processando Argumentos”.

O tratamento do valor de retorno em xxx() deve ser feito de forma idêntica a uma UDF normal. Veja mais informações sobre isto na Seção 14.2.2.4, “Valor de Retorno e Tartamento de Erros”.

O argumento ponteiro para is_null e error é o mesmo para todas as chamadas xxx_reset(), xxx_clear(), xxx_add() e xxx(). Você pode utilizar isto para lembrar que você obteve um erro ou se a função xxx() deve retornar NULL. Note que você não deve armazenar uma string em *error! Ela é um parâmetro de apenas 1 byte!

is_null é zerado para cada grupo (antes de chamar xxx_clear()). error nunca é zerado.

Se isnull ou error são definidos depois de xxx() então o MySQL retornará NULL como o rsultado para a função do grupo.

14.2.2.3. Processando Argumentos

O parâmetro args aponta para uma estrutura UDF_ARGS que tem os mambros listados abaixo:

  • unsigned int arg_count

    O número de argumentos. Verifique o valor na função de inicialização se você quiser que ssua função seja chamada com um número específico de argumentos. For exemplo:

    if (args->arg_count != 2)
    {
    strcpy(message,"XXX() requires two arguments");
    return 1;
    }
    

  • enum Item_result *arg_type

    Os tipos para cada argumento. Os valores de tipos possíveis são STRING_RESULT, INT_RESULT, e REAL_RESULT.

    Para ter certeza que os argumentos são de um tipo dado e retornar um erro se não forem, verifique o vetor arg_type na função de inicialização. Por exemplo:

    if (args->arg_type[0] != STRING_RESULT ||
    args->arg_type[1] != INT_RESULT)
    {
    strcpy(message,"XXX() requires a string and an integer");
    return 1;
    }
    

    Como uma alternativa para exigir que os argumentos de sua função sejam de um tipo específico, você pode usar a função de inicialização para definir o elemento arg_type com o tipo que você quiser. Isto faz com que o MySQL converta argumentos para aqueles tipo a cada chamada de xxx(). Por exemplo, para fazer conversão dos dois primeiros argumentos para string e integer, faça isto com xxx_init():

    args->arg_type[0] = STRING_RESULT;
    args->arg_type[1] = INT_RESULT;
    

  • char **args

    args->args informa a função de inicialização sobre a natureza geral dos argumentos chamados com sua função. Para um argumento constante i, args->args[i] aponta para o valor do argumento. (Veja abaixo sobre instruções de como acessar o valor de forma apropriada). Para um argumento não constante, args->args[i] é 0. Um argumento constante é uma expressão é uma expressão que utiliza apenas constante, tais como 3 ou 4*7-2 ou SIN(3.14). Um argumento não constante é uma expressão que refere a valores que podem alterar a cada linha, tais como nomes de coluna ou funções que são chamadas com argumentos não contantes.

    Para cada chamada da função principal, args->args contém os argumentos atuais que são passados pela linhas sendo processadas atualmente.

    As funções podem se referir a um argumento i como a seguir:

    • Um argumento do tipo STRING_RESULT é dado como um apontador string mais um tamanho, para permitir o tratamento de dados binários de tamanho arbitrário. Os conteúdo da string estão disponíveis como args->args[i] e o tamanho da string é args->lengths[i]. Você não deve assumir aue as strings são terminadas em null.

    • Para um argumnto do tipo INT_RESULT, você deve converter args->args[i] para um valor long long:

      long long int_val;
      int_val = *((long long*) args->args[i]);
      
    • Para um argumento do tipo REAL_RESULT, você deve converter args->args[i] para um valor double:

      double real_val;
      real_val = *((double*) args->args[i]);
      

  • unsigned long *lengths

    Para a função de inicialização, o vetor lengths indica o tamanho máximo da string para cada argumento. Você não deve alterá-los. Para cada chamada da função principal, lengths contém o tamanho atual de quaisquer argumentos string que são passados para a linha sendo processada atualmente. Para argumentos do tipo INT_RESULT ou REAL_RESULT, lengths ainda contém o tamanho máximo do argumento (como para a função de inicialização).

14.2.2.4. Valor de Retorno e Tartamento de Erros

A função de inicialização deve retornar 0 se nenhum erro ocorrer e 1 em outro caso. Se ocorrer um erro, xxx_init() deve armazenar uma mensagem de erro terminada em null no parâmetro message. A mensagem será retornada ao cliente. O buffer de mensagens tem MYSQL_ERRMSG_SIZE caracteres, mas você deve tentar manter a mensagem com menos que 80 caracteres assim ela cabe na tela de terminal padrão.

O valor de retorno de uma função principal xxx() é o valor da função, para funções long long e double. Uma função string deve retornar um ponteiro ao resultado e armazenar o tamanho da string no argumento length.

Definá-os ao conteúdo e tamanho do valor de retorno. Por exemplo:

memcpy(result, "result string", 13);
*length = 13;

O buffer result que é passado para o cálculo da função é de 255 bytes. Se o seu resultado couber nele, você não terá que se preocupar com alocação de memória para os resultados.

Se a sua função string precisar retornar uma string maior que 255 bytes, você deve alocar o espaço para ela com malloc() em sua função xxx_init() ou sua função xxx() e liberá-la em sua função xxx_deinit(). Você pode armazenar a memória alocada na posição ptr na estrutura UDF_INIT para ser reutilizado por chamadas xxx() futuras. Veja mais informações sobre isto na Seção 14.2.2.1, “Sequência de Chamadas UDF para Funções Simples”.

Para indicar um valor de retorno de NULL na função principal, defina is_null com 1:

*is_null = 1;

Para indicar um erro retornado na função principal, atribua 1 ao parâmetro error:

*error = 1;

Se xxx() definir *error com 1 para qualquer linha, o valor da função é NULL para a linha atual e qualquer linha subsequente processada pela instrução na qual XXX() foi chamado. (xxx() nem mesmo será chamado para linhas subsequentes.) Nota: na versão do MySQL anterior a 3.22.10, você deve configurar *error e *is_null:

*error = 1;
*is_null = 1;

14.2.2.5. Compilando e Instalando Funções Definidas Por Utilizador

Arquivos implementando UDFs devem ser compilados e instalados na máquina onde o servidor está sendo executado. Este processo é descrito abaixo pelo arquivo UDF exemplo udf_example.cc que é incluído na distribuição fonte do MySQL. Este arquivo contém as seguintes funções:

  • metaphon() retorna uma string metafonica do argumento string. Ela é algo como uma string soundex, mas é mais voltada para o inglês.

  • myfunc_double() retorna a soma de valores ASCII de caracteres e seus argumentos, dividido pela soma de tamanho de seus argumentos.

  • myfunc_int() retorna a soma do tamanho de seus argumentos.

  • sequence([const int]) retorna uma sequência iniciando a partir de um número dado ou 1 se nenhum número for fornecido.

  • lookup() retorna o IP de um nome de máquina.

  • reverse_lookup() retorna o nome de mauina para um número IP. A função pode ser chamada com uma string "xxx.xxx.xxx.xxx" ou quatro números.

A arquivo carregável dinamicamente deve ser compilado como um arquivo objeto compartilhável usando um comando como este:

shell> gcc -shared -o udf_example.so myfunc.cc

Você pode encontrar facilmente as opções de compilador corretas para seu sistema executando este comando no diretório sql da sua árvore de fonte MySQL:

shell> make udf_example.o

Você deve executar comando de compilador similar àquele que o make mostra, exceto que você deve remover a opção -c próxima ao fim da linha e adicionar -o udf_example.so. (Em alguns sistemas você pode precisar deixar o comando -c.)

Uma vez que você tenha compilado um objeto compartilhado contendo UDFs, você deve instalá-lo e avisar o MySQL sobre ele. Compilar um objeto compartilhado de udf_example.cc produz um arquivo com nome parecido com udf_example.so (o nome exato pode variar de plataforma para plataforma). Copie este arquivo para algum diretório procurado com o ligador dinâmico ld, tal como /usr/lib ou adicione o diretório no qual você colocou o objeto compartilhado ao arquivo de configuração do ligador (e.g. /etc/ld.so.conf).

Em muitos sistemas você pode as variáveis de ambiente LD_LIBRARY ou LD_LIBRARY_PATH para apontar para o diretório onde se encontra os seus arquivos de funções UDF. A página dlopen do manual diz a você quais variáveis você deve utilizar em seu sistema. Você deve configurar isto nos scripts de inicialização mysql.server ou mysqld_safe e reiniciar o mysqld.

Depois da biblioteca ser instalada, notifique mysqld sobre as novas funções com estes comandos:

mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
mysql> CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION reverse_lookup
-> RETURNS STRING SONAME "udf_example.so";
mysql> CREATE AGGREGATE FUNCTION avgcost
-> RETURNS REAL SONAME "udf_example.so";

Funções podem ser deletadas utilizando-se DROP FUNCTION:

mysql> DROP FUNCTION metaphon;
mysql> DROP FUNCTION myfunc_double;
mysql> DROP FUNCTION myfunc_int;
mysql> DROP FUNCTION lookup;
mysql> DROP FUNCTION reverse_lookup;
mysql> DROP FUNCTION avgcost;

As instruções CREATE FUNCTION e DROP FUNCTION atualizam a tabela de sistema func no banco de dados mysql. O nome da função, tipo e biblioteca compartilhada são salvas na tabela. Você deve ter os privilégios INSERT e DELETE para o banco de dados mysql para criar e deletar funções.

Você não deve usar CREATE FUNCTION para adicionar uma função que já tenha sido criada. Se você precisar reinstalar uma função, você deve removê-la com DROP FUNCTION e então reinstalá-la com CREATE FUNCTION. Você precisaria fazer isto, por exemplo, se você recompilar uma nova versão da sua função, assim o mysqld obtem a nova versão. Por outro lado, o servidor continuará a utilizar a versão antiga.

Funções ativas são recarregadas a cada vez que o servidor inicia, a menos que você inicie mysqld com a opção --skip-grant-tables. Neste caso, a a inicialização de UDF é ignorada e as UDFs ficam indisponíveis. Uma função ativa é aquela que carregada com CREATE FUNCTION e não removida com DROP FUNCTION.)

14.2.3. Adicionando uma Nova Função Nativa

O procedimento para adicionar uma nova função nativa é descrito aqui. Note que você não pode adicionar funções nativas a distribuição binária porque o procedimento envolve modificação no código fonte do MySQL. Você deve compilar o MySQL de uma distribuição fonte. Note também que se você migrar para outra versão do MySQL (por exemplo, quando uma nova versão é liberada), você precisará repetir o procedimento com a nova versão.

Para adicionar uma função MySQL nativa, siga estes passos:

  1. Adicionr uma linha a lex.h que defina o nome da função no vetor sql_functions[].

  2. Na função protótipo é simples (utilize apenas zero, um, dois ou três argumentos), você deve especificar SYM(FUNC_ARG#) em lex.h (onde # é o número de argumentos) como o segundo argumento no vetor sql_functions[] e adicionar uma função que cria um objeto de função em item_create.cc. De uma olhada em "ABS" e create_funcs_abs() para um exemplo disto.

    Se o protótipo da função for complicado (por exemplo, tiver um número variável de argumentos), você deve adicionar duas linhas a sql_yacc.yy. Uma indica o símbolo pre-processador que o yacc deve difinir (isto deve ser adicionado no começo do arquivo). Então defina os parâmetros da função e adicione um ``item'' com estes parâmetros a regra simple_expr do analizador. Por exemplo, verifique todas as acorrências de ATAN em sql_yacc.yy para ver como ele é feito.

  3. Em item_func.h, declare uma classe herdada de Item_num_func ou Item_str_func, dependendo se sua função retorna um número ou uma string.

  4. Em item_func.cc, adicione uma das seguintes declarações, dependendo se você está definindo uma função numérica ou string:

    double Item_func_newname::val()
    longlong Item_func_newname::val_int()
    String *Item_func_newname::Str(String *str)
    

    Se você herdar seu objeto de qualquer um dos itens padrões (como Item_num_func), você provavelmente só deverá definir uma das funções acima e deixar os objetos pais cuidar das outras funções. Por exemplo, a classe Item_str_func define uma função val() que executa atof() no valor retornado por ::str().

  5. Você também deve, provavelmente, definir a seguinte função objeto:

    void Item_func_newname::fix_length_and_dec()
    

    Esta função deve pelo menos calcular max_length baseado nos argumentos dados. max_length é o número máximo de caracteres que a função pode retornar. Esta função também deve definir maybe_null = 0 se a função principal não puder retornar um valor NULL. A função pode verificar se algum dos argumentos da função pode retornar NULL verificando a variável de argumentos maybe_null. Você pode dar uma olhada em Item_func_mod::fix_length_and_dec para um exemplo típico de como fazer isto.

Todas as funções devem ser seguras com thread (em outras palavras, não utilize qualquer variável global ou estática nas funções sem protege-las com mutexes).

Se você retornar NULL, de ::val(), ::val_int() ou ::str() você deve definir null_value com 1 e retornar 0.

Para funções objetos ::str(), existem algumas considerações adicionais das quais você deve estar ciente:

  • O arguemto String *str fornece um buffer string que pode ser utilizado para guardar o resultado. (Para mais informações sobre o tipo String, dê uma olhada no arquivo sql_string.h.)

  • A função ::str() deve retornar a string que guarda o resultado ou (char*) 0 se o resultado é NULL.

  • Todas as funções string atuais tentam evitar a alocação de memória a menos que seja absolutamente necessário!