27.2. Añadir nuevas funciones a MySQL

MySQL 5.0

27.2. Añadir nuevas funciones a MySQL

Hay dos formas de añadir nuevas funciones a MySQL:

  • Puede añadir funciones con la interfaz de funciones definidas de usuario (UDF) (N.del T. Acrónimo para User Defined Functions). Las funciones definidas por el usuario se ocmpilan como ficheros objeto y se añaden y borran del servidor dinámicamente usando los comandos y . Consulte Sección 27.2.2, “Sintaxis de .

  • Puede añadir funciones como funciones nativas MySQL. Se compilan en el servidor mysqld y están disponibles permanentemente.

Cada método tiene ventajas y desventajas:

  • Si escribe funciones definidas por el usuario, debe instalar ficheros objeto además del servidor mismo. Si compilar su función en el servidor, no necesita hacerlo.

  • Puede añadir UDFs a distribuciones binarias MySQL . Las funciones nativas requieren modificar una distribución fuente.

  • Si actualiza su distribución MySQL , puede continuar usando las UDFs previamente instaladas, a no ser que actualice a una versión en la que la interfaz UDF cambie. (Un cambio incompatible ocurrió en MySQL 4.1.1 para funciones agregadas. Una función llamada debe definirse en lugar de .) Para funciones nativas, debe repetir sus modificaciones cada vez que actualice.

Use el método que use para añadir nuevas fucnciones, pueden invocarse en comandos SQL como funciones nativas tales como o .

Otra forma de añadir funciones es creando funciones almacenadas. Se escriben con comandos SQL en lugar de compilando código objeto. La sintaxis para escribr funciones almacenadas se describe en .

La siguiente sección describe características de la interfaz UDF, proporciona intrucciones para escribir UDFs, y discute sobre precauciones de seguridad que toma MySQSL para prevenir un mal uso de UDF.

Para código fuente de ejemplo que ilustra cómo escribir UDFs, mire el fichero que se proporciona en las distribuciones fuentes de MySQL.

27.2.1. Características de la interfaz para funciones definidas por el usuario

La interfaz de MySQL para funciones definidas por el usuario proporciona las siguientes funcionalidades y capacidades:

  • Las funciones pueden retornar cadenas de carácteres, enteros o valores reales.

  • Puede definir funciones simples que operen en con un único registro a la vez, o agregar funciones que operen con grupos de registros.

  • Se proporciona información a las funciones que permite chequear el tipo y número de argumentos que se les pasa.

  • Le puede decir a MySQL que coercione argumentos de un tipo dado antes de pasarlos a la función.

  • Puede indicar que una funcion retorne o que ha ocurrido un error.

27.2.2. Sintaxis de CREATE FUNCTION/DROP FUNCTION

CREATE [AGGREGATE] FUNCTION  RETURNS {STRING|INTEGER|REAL}
       SONAME 

DROP FUNCTION 

Una funciones definidas por el usuario (UDF) es un modo de extender MySQL con una nueva función que funciona como una función nativa de MySQL tal como o .

es el nombre que debe usarse en comandos SQL para invocar la función. La cláusula indica el tipo del valor de retorno de la función. es el nombre base de la fichero del objeto compartido que contiene el código que implementa la función. El fichero debe localizarse en un directorio en el que busque el lincador dinámico del sistema.

Para crear una función , debe tener el privilegio para la base de datos . Para borrar una función, debe tener el privilegio para la base de datos . Esto es así porque añade un registro a la tabla de sistema que registra los nombres de función, tipo, y nombre de la biblioteca compartida, y borra el registro de la función de dicha tabla. Si no tiene esta tabla, debe ejecutar el script mysql_fix_privilege_tables para crearla. Consulte Sección 2.10.2, “Aumentar la versión de las tablas de privilegios”.

Una función activa es una que se ha cargado con y no se ha eliminado con . Todas las funciones activas se recargan cada vez que el servidor arranca, a no ser que arranque mysqld con la opción . En este caso, la inicialización de UDF no se hace y no están disponibles.

Para instrucciones sobre escribir funciones definidas por el usuario consulte Sección 27.2.3, “Añadir una nueva función definida por el usuario”. Para que funcione el mecanismo de UDF, las funciones deben escribirse en C o C++, su sistema operativo debe soportar carga dinámica y debe haber compilado mysqld dinámicamente (no estáticamente).

es una nueva opción para MySQL 3.23. Una función funciona exactamente como una función agregada (resumen) de MySQL tal como o . Para que funcione , su tabla debe contener una columna . Si su tabla no tiene esta columna, debe ejecutar el script mysql_fix_privilege_tables para crearla.

27.2.3. Añadir una nueva función definida por el usuario

Para que funciones el mecanismo UDF, las funciones deben escribirse en C o C++ y su sistema operativo debe soportar carga dinámica. La distribución fuente de MySQL incluye un fichero que define 5 nuevas funciones. Consulte este fichero para ver cómo funcionan las convenciones de llamadas de UDF.

Para poder usar UDFs, necesita lincar mysqld dinámicamente. No configure MySQL usando . Si quiere usar una UDF que necesite acceder a símbolos desde mysqld (por ejemplo la función en que usa ), debe lincar el programa con (consulte ). Si planea usar UDFs, la rula es configurar MySQL con a no ser que tenga una muy buena razón para no hacerlo.

Si usa una distribución precompilada de MySQL, use MySQL-Max, que contiene un servidor lincado dinámicamente que soporta carga dinámica.

Para cada función que quiera usar en comandos SQL, debe definir las funciones correspondientes en C (o C++). En la siguiente discusión, el nombre “xxx” se usa como nombre de función de ejemplo. Para distinguir entre el uso de SQL y C/C++ , (mayúsculas) indicata una llamada de función SQL, (minúsculas) indica una llamada de función C/C++ .

Las funciones C/C++ que escribe para implementar la interficie para son:

  • (requerido)

    La función principal. Es donde el resultado de la función se computa. La correspondencia entre los tipos de datos de la función SQL y el tipo de retorno de la función C/C++ se muestra aquí:

    SQL Type C/C++ Type
  • (opcional)

    La función de inicialización para . Puede usarse para:

    • Chequea el número de argumentos para .

    • Chequea que los argumentos son de un tipo requerido o, alternativamente, le dice a MySQL que coercione argumentos a los tipos que quiera cuando se llama a la función principal.

    • Reserva cualquier memoria requerida por la función principal.

    • Especifica la longitud máxima del resultado.

    • Especifica (para funciones ) el máximo número de decimales.

    • Especifica si el resultado puede ser .

  • (opcional)

    La función de deinicialización para . Debe liberar cualquier memoria reservada por la función de inicialización.

Cuando un comando SQL invoca , MySQL llama a la función de inicialización para que realice cualquier inicialización necesaria, tales como chequeo de argumentos o reserva de memoria. Si retorna un error, el comando SQL se aborta con un mensaje de error y no se llama ni a la función principal ni a la de deinicialización. En caso contrario, se llama a la función principal una vez para cada registro. Tras procesar todos los registros, se llama a la función de deinicialización para que pueda realizar cualquier limpieza requerida.

Para funciones agregadas que funcionan como , debe proporcionar las siguientes funciones:

  • (necesaria antes de 4.1.1)

    Resetea el valor agregado actual e inserta el argumento como valor agregado inicial para un nuevo grupo.

  • (requerido a partir de 4.1.1)

    Resetea el valor agregado actual pero no inserta el argumento como valor agregado inicial para un nuevo grupo.

  • (requerido)

    Añade el argumento al valor agregado actual.

MySQL trata UDFs agregados como sigue:

  1. Llama a para permitir a la función agregada reservar la memoria necesaria para ordenar resultados.

  2. Ordena la table según la expresión .

  3. Llama a para el primer registro en cada grupo.

  4. Llama a para cada nuevo registro que permita al mismo grupo.

  5. Llama a para obtener el resultado del agregado cuando el grupo cambia o cuando el último registro se ha procesado.

  6. Repite 3-5 hasta que se procesan todos los registros

  7. Llama a para permitir al UDF liberar la memoria reservada.

Todas las funciones deben ser flujos seguros. Esto incluye no sólo la función principal,también las funciones de inicialización o deinicialización, y las funciones adicionales requeridas por las funciones agregadas. Una consecuencia de esta restricción es que no se le permite reservar ninguna variable global o estática que cambien! Si necesita memoria, debe reservarla en y liberarla en .

27.2.3.1. Secuencias de llamada UDF para funciones simples

Esta sección describe las distintas funciones que necesita definir cuando crea un UDF simple. Sección 27.2.3, “Añadir una nueva función definida por el usuario” describe el orden en que MySQL llama a estas funciones.

La función principal debe declararse como se muestra en esta sección. Tenga en cuenta que el tipo de retorno y los parámetros difieren, dependiendo de si declara la función SQL para retornar , , o en el comando :

Para funciones :

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

Para funciones :

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

Para funciones :

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

Las funciones de inicialización y deinicialización se declaran así:

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

void xxx_deinit(UDF_INIT *initid);

El parámetro se pasa a las tres funciones. Apunta a la estructura que se usa para comunicar información entre funciones. Los mienbros de la estructura se muestran a continuación. La función de inicialización debe rellenar cualquier miembro que quiera cambiar. (Para usar el valor por defecto de un miembro no lo cambie.)

  • debe asignar a si puede retornar . El valor por defecto es si alguno de los argumentos se declaran .

  • El número de decimales. El valor por defecto es el número máximo de decimales en los argumentos pasados a la función principal. (Por ejemplo, si a la función se pasa , , y , el valor por defecto es 3, ya que tiene 3 decimales.

  • Longitud máxima del resultado. El valor por defecto difiere en función del tipo de resultado de la función. Para funciones de cadenas de carácteres, el valor por defecto es el argumento más largo. Para funciones enteras, el valor por defecto es de 21 dígitos. Para funciones reales, el valor por defecto es 13 mas el número de decimales indicados por . (Para funciones numéricas, la longitud incluye cualquier signo o carácter de punto decimal.)

    Si quiere retornar un valor blob, puede asignar a de 65KB a 16MB. Esta memoria no se reserva, pero el valor se usa para decidir qué tipo de columna usar si hay una necesidad de almacenar los datos temporalmente.

  • Puntero que la función puede usar para su propio propósito. Por ejemplo, las funciones pueden usar para comunicar memoria reservada entre ellos. debe reservar la memoria y asignarla al puntero:

    initid->ptr = allocated_memory;
    

    En y , refiérase a para usar o liberar la memoria.

27.2.3.2. Secuencias de llamada UDF para funciones agregadas

Esta sección describe las distintas funciones que necesita definir cuando crea un UDF agregado. Sección 27.2.3, “Añadir una nueva función definida por el usuario” describe el orden en que MySQL llama a estas funciones.

  • Esta función se llama cuando MySQL encuentra el primer registro en un nuevo grupo. Debe resetear cualquier variable resumen interna y usar el argumento dado como primer valor en su resumen interno del grupo. Declare como se muestra:

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

    se necesita sólo antes de MySQL 4.1.1. NO se necesita usar desde MySQL 4.1.1, cuando la interfaz UDF cambió para usar en su lugar. Sin embargo, puede definir y si quiere que su UDF funcione antes y después del cambio de interfaz. (Si no incluye ambas funciones, la función en muchos casos puede implementarse internamente llamando para resetear todas las variables, y luego llamar para añadir el argumento como primer valor del grupo.)

  • Esta función se llama cuando MySQL necesita resetear los resultados resumen. Se llama al principio para cada nuevo grupo pero sólo puede llamarse para resetear los valores para una consulta donde no hubieran registros que coincidan con la búsqueda. Declare como sigue:

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

    se asigna para que apunte a antes de llamar a .

    Si algo falla, puede almacenar un valor en la variable a la que apunta el argumento . apunta a una variable de un byte, no a un búfer de cadenas de carácteres.

    se requiere sólo a partir de MySQL 4.1.1. Antes de MySQL 4.1.1, use en su lugar.

  • Esta función se llama para todos los registros que pertenezcan al mismo grupo, excepto para el primer registor. Debe ussarlo para añadir el valor en el argumento a su variable de resumen interna.

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

La función para un UDF agregado debe declararse de la misma forma que UDF no agregados. Consulte Sección 27.2.3.1, “Secuencias de llamada UDF para funciones simples”.

Para un UDF agregado, MySQL llama a la función una vez que todos los registros en el grupo han sido procesados. Normalmente no debe acceder el argumento aquí sino devolver un valor basado en sus variables de resumen internas.

El tratamiento de valores retornados en debe hacerse del mismo modo que para UDF no agregados. Consulte Sección 27.2.3.4, “Valores de retorno y tratamiento de errores”.

Las funciones y tratan sus argumentos del mismo modo que las funciones para UDFs no agregados. Consulte Sección 27.2.3.3, “Proceso de argumentos”.

Los argumentos punteros de y son los mismos para todas las llamadas a , , y . Puede usar esto para recordar que obtuvo un error o si la función debería retornar . No debe almacenar una cadena de carácteres en ! apunta a una variable de un byte, no a un búfer de cadenas de carácteres.

se resetea para cada grupo (antes de llamar ). nunca se resetea.

Si o se asignan cuando retorna, MySQL retorna como resultado para la función de grupo.

27.2.3.3. Proceso de argumentos

El parámetro apunta a una estructura que tiene los miembros listados a continuación:

  • Número de argumentos. Chequee este valor en la función de inicialización si necesita que su función sea llamada con un número particular de argumentos. Por ejemplo:

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

  • Puntero a una matriz conteniendo los tipos para cada argumento. Los tipos posibles son , , y .

    Par asegurar que los argumentos sean de un tipo dado y retorne un error si no lo son, chequee la matriz en la función de inicialización. Por ejemplo:

    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 alternativa a requerir que los argumentos de la función sean de un tipo particular, puede usar la función de inicialización para asignar los elementos con los tipos que quiera. Esto hace que MySQL fuerce a los argumentos a los tipos para cada llamada de . Por ejemplo, para especificar que los primeros dos argumentos se fuercen a una cadena de carácteres de enteros, respectivamente, haga lo siguiente en :

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

  • comunica información a la función de inicialización acerca de la naturaleza general de los argumentos pasados a la función. Para un argumento constante , apunta al valor del argumento. (Consulte a continuación instrucciones sobre cómo acceder al valor apropiadamente.) Para argumentos no constantes, es . Un argumento constante es una expresión que usa sólo constantes, como o o . Un argumento no constante es una expresión que se refiere a valores que pueden cambiar de registro a registro, tales como nombres de columna o funciones que se llaman con argumentos no constantes.

    Para cada invocación de la función principal, contiene los argumentos que se pasan para el registro que está procesando.

    Las funciones pueden referirse a un argumento como se muestra:

    • Un argumento de tipo se da como puntero a una cadena de carácteres más una longitud, para permitir tratar datos binarios o datos arbitráriamente largos. Los contenidos de la cadena de carácteres están disponibles como y la longitud de la cadena es . No debe asumir que las cadenas de carácteres están terminadas por null.

    • Para un argumento de tipo , debe convertir a un valor :

      long long int_val;
      int_val = *((long long*) args->args[i]);
      
    • Para un argumento de tipo , debe convertir a un valor :

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

  • Para la función de inicialización, la matriz indica la longitud máxima de cadena de carácteres para cada argumento. No debe cambiar este valor. Para cada invocación de la función principal contiene las longitudes reales de cualquier argumento de cadenas de carácteres que se pasa al registro en proceso. Para argumentos de tipos o , contiene la longitud máxima del argumento (como para la función de inicialización).

27.2.3.4. Valores de retorno y tratamiento de errores

La función de inicialización debe retornar si no hay errores y en cualquier otro caso. Si ocurre un error, debe almacenar un mensaje de error terminado en null en el parámetro . El mensaje se retorna al cliente. El búffer de mensajes es de longitud , pero debe tratar que el mensaje ea inferior a 80 carácteres para que coincida con la anchura de una pantalla de terminal estándar.

El valor retornado por una función principal es el valor de la función, para funciones y . Una función de cadenas de carácteres debe retornar un puntero al resultado y asignar y con los contenidos y longitud del valor de retorno. Por ejemplo:

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

El búffer que se pasa a la función tiene longitud de 255 bytes. Si su resultado coincide con esto, no tiene que preocuparse acerca de reservar memoria para los resultados.

Si su función de cadenas de carácteres necesita retornar una cadena de carácteres mayor a 255 bytes, debe reservar el espacio para ello con en su función o su función y liberarla en su función . Puede almacenar la memoria reservada en la entrada en la estructura para reusar para llamadas futuras . Consulte Sección 27.2.3.1, “Secuencias de llamada UDF para funciones simples”.

Para indicar un valor de retorno de en la función principal, asigne a :

*is_null = 1;

Para indicar un retorno de error en la función principal, inicialice con :

*error = 1;

Si asigna a para cualquier registro, el valor de la función es para el registro actual y para cualquier subsecuente registro procesado por el comando en que se invoca . ( no se llama ni por registros subsecuentes.) Nota: Antes de MySQL 3.22.10, debe asignar tanto como :

*error = 1;
*is_null = 1;

27.2.3.5. Compilar e instalar funciones definidas por el usuario

Los ficheros implementando UDFs deben compilarse e instalarse en el equipo donde corre el servidor. Este proceso se describe a continuación para el fichero UDF de ejemplo que se incluye en la distribución fuente de MySQL.

Las instrucciones siguientes son para Unix. Las instructiones para Windows se dan posteriormente en esta sección.

El fichero contiene las siguientes funciones:

  • retorna una cadena de carácteres metaphon del argumento de cadena de carácteres. Esto es algo como una cadena de carácteres soundex, pero más ajustado al inglés.

  • retorna la suma de los valores ASCII de los carácteres en los argumentos, divididos por la suma de la longitud de los argumentos.

  • retorna la suma de la longitud de los argumentos.

  • retorna una secuencia empezando por el número dado o 1 si no se da ningún número.

  • retorna la IP para un nombre de equipo.

  • retorna el nombre de equipo para una IP. La función puede llamarse con un único argumento de cadena de carácteres de la forma o con cuatro números.

Un fichero cargable dinámicamente debe compilarse como fichero objeto compartible, usando un comando como:

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

Si usa gcc, debe ser capaz de crear con un comando más simple:

shell> make udf_example.so

Puede determinar fácilmente las opciones de compilación adecuadas para su sistema ejecutando este comando en el directorio del árbol fuente de MySQL:

shell> make udf_example.o

Debe ejecutar un comando de compilación similar al que muestra make , excepto que debe quitar la opción cerca del final de la línea y añadir al final de la línea. (En algunos sistemas, puede necesitar dejar en el comando.)

Tras compilar un objeto compartido conteniendo UDFs, debe instalarlo y comunicarlo a MySQL. Compilar un objeto compartido de produce un fichero llamado algo como (el nombre exacto puede variar de plataforma a plataforma). Copie este fichero en un directorio como en el que busque el lincador dinámico del sistema (en tiempo de ejecución), o añada el directorio en el que está el objeto compartido en el fichero de configuración del lincador (por ejemplo, ).

El nombre del lincador depende del sistema (por ejemplo, ld-elf.so.1 en FreeBSD, ld.so en Linux, o dyld en Mac OS X). Consulte su documentación del sistema para información acerca del nombre del lincador y cómo configurarlo.

En muchos sistemas, puede cambiar las variables de entorno o para que apunten al directorio donde tiene los ficheros de su UDF. La página de manual explica qué variables debe usar en su sistema. Debe inicializarla en los scripts de arranque mysql.server o mysqld_safe y reiniciar mysqld.

En algunos sistemas, el programa ldconfig que configura el lincador dinámico no reconoce un objeto compartido a no ser que su nombre comience con . En ese caso debe renombar el fichero como a .

En Windows, puede compilar funciones definidas por el usuario usando el siguiente procedimiento:

  1. Necesita obtener el repositorio fuente BitKeeper para MySQL 4.0 o superior. Consulte Sección 2.8.3, “Instalar desde el árbol de código fuente de desarrollo”.

  2. En el repositorio fuente, busque el directorio . Hay ficheros llamados , , y .

  3. En el repositorio fuente, busque en el directorio . Copie de este directorio al directorio y renombre el fichero a .

  4. Abra el fichero con Visual Studio VC++ y úselo para compilar los UDFs como un proyecto normal.

Cuando el objeto compartido se ha instalado, notifique a mysqld con las nuevas funciones con estos 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';

Las funciones pueden borrarse con :

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;

Los comandos y actualizan la tabla de sistema en la base de datos . El nombre de función, tipo y nombre de biblioteca compartida se salvan en la tabla. Debe tener los privilegios y para la base de datos para crear y borrar funciones.

No debe usar para añadir una función que se ha creado préviamente. Si necesita reinstalar una función, debe borrarla con y reinstalarla con . Puede necesitar hacer esto, por ejemplo si recompila una nueva versión de su función, de forma que mysqld tenga la nueva versión. De otro modo, el servidor continua usando la versión antigua.

Una función activa es una que se ha cargado con y no se ha borrado con . Todas las funciones activas se recargan cada vez que el servidor arranca, a no ser que arranque mysqld con la opción . En ese caso, la inicialización de UDFs no se hace y no están disponibles.

27.2.3.6. Precauciones de seguridad en funciones definidas por usuarios

MySQL toma las siguientes medidas para evitar uso inadecuado de funciones definidas por el usuario.

Debe tener el privilegio para poder usar y el privilegio para poder usar . Esto es necesario ya que estos comandos añaden y borran registros de la tabla .

UDFs debe tener como mínimo un símbolo definido además del símbolo que corresponde a la función principal . Estos símbolos auxiliares se corresponden con las funciones , , , , y . Desde MySQL 4.0.24, 4.1.10a, y 5.0.3, mysqld soporta una opción que controla si UDFs que tienen un solo símbolo pueden cargarse. Por defecto, la opción está desactivada, para evitar intentos de cargar funciones de ficheros de objetos compartidos otros aparte de los que contienen UDFs legítimos. Si tiene UDFs antiguos que contienen sólo el símbolo y no pueden recompilarse para incluir un símbolo auxiliar, puede ser necesario especificar la opción . De otro modo, debe evitar activar esta capacidad.

Los ficheros objeto UDF no pueden guardarse en un directorio arbitrario. Deben estar localizado en un directorio de sistema en el que busque el lincador dinámico. Para forzar esta restricción y evitar intentos de especificar rutas fuera de los directorios buscados por el lincador dinámico, MySQL chequea el fichero de objeto compartido especificado en comandos para delimitadores de rutas. Desde MySQL 4.0.24, 4.1.10a, y 5.0.3, MySQL también chequea los delimitadores de rutas en nombres de ficheros almacenados en la tabla cuando carga funciones. Esto evita intentos de especificar rutas ilegítimas manipuladas en la tabla . Para información acerca de UDFs y lincador en tiempo de ejecución, consulte Sección 27.2.3.5, “Compilar e instalar funciones definidas por el usuario”.

27.2.4. Añadir una nueva función nativa

El procedimiento para añadir una nueva función nativa se describe aquí. Tenga en cuenta que no puede añadir funciones nativas a una distribución binaria ya que el procedimiento implica modificar código fuente MySQL. Debe compilar MySQL de una distribución fuente. También tenga en cuenta que si migra a otra versión de MySQL (por ejemplo, cuando una nueva versión aparece), necesita repetir el procedimiento con la nueva versión.

Para añadir una nueva función MySQL nativa, siga estos pasos:

  1. Añada una línea en que defina el nombre de función en la matriz .

  2. Si el prototipo de función es simple (sólo tiene cero, uno, dos o tres argumentos), debe especificar en ) (donde es el número de argumentos) como el segundo argumento en la matriz y añadir una nueva función que cree un objeto función en . Consulte y para un ejemplo.

    Si la función prototipo es complicada (por ejemplo, tiene un número variable de argumentos), debe añadir dos líneas en . Una indica el símbolo de preprocesador que yacc debe definir (debe añadirse al principio del fichero). Luego defina los parámetros de función y añada un “item” con estos parámetros a la regla de parseo . Para un ejemplo, consulte todas las ocurrencias de en para ver cómo se hace.

  3. En , declare una clase heredando de o , en función de si su función retorna un número o una cadena de carácteres.

  4. En , añada una de las siguientes declaraciones, dependiendo de si está definiendo una función numérica o de cadena de carácteres:

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

    Si hereda su objeto de cualquiera de los objetos estándar (como ), probablemente sólo tiene que definier una de estas funciones y dejar que el objeto padre se ocupe de las otras funciones. Por ejemplo, la clase define una función que ejecuta en el valor retornado por .

  5. Debería probablemente definir la siguiente función objeto:

    void Item_func_newname::fix_length_and_dec()
    

    Esta función debe calcular al menos basándose en los argumentos dados. es el máximo número de carácteres que la función puede retornar. Esta función debería también asignar si la función principal no puede retornar un valor . La función puede chequear si algunos de los argumentos de la función puede retornar chequeando la variable de los argumentos. Puede consultar para un ejemplo típico de cómo hacer esto.

Todas las funciones deben ser flujos seguros. En otras palabras, no usar ninguna variable global o estática en las funciones sin protegerlas con semáforos

Si quiere retornar , desde , or debe asignar a 1 y retornar 0.

Para funciones objeto , hay algunas consideraciones adicionales a tener en cuenta:

  • El argumento proporciona un búffer de cadenas de carácteres que puede usarse para guardar el resultado. (Para más información acerca del tipo , consulte el fichero .)

  • La función debe retornar la cadena de carácteres que tiene el resultado o si el resultado es .

  • Todas las funciones de cadenas de carácteres tratan de evitar cualquier reserva de memoria a no ser que sea absolutamente necesario!