sql >> Base de Datos >  >> RDS >> Mysql

Scripts SQL:¿existe el equivalente de #define?

El Preprocesador C (cpp) está históricamente asociado con C (de ahí el nombre), pero en realidad es un procesador de texto genérico que se puede usar (o abusar) para otra cosa.

Considere este archivo, llamado location.src (más sobre eso más adelante).

// C++ style comments works here
/* C style works also */
-- plain old SQL comments also work,
-- but you should avoid using '#' style of comments,
-- this will confuse the C pre-processor ...

#define LOCATION_LEN 25

/* Debug helper macro */
#include "debug.src"

DROP TABLE IF EXISTS test.locations;
CREATE TABLE test.locations
(
   `location` VARCHAR(LOCATION_LEN) NOT NULL
);

DROP PROCEDURE IF EXISTS test.AddLocation;
delimiter $$
CREATE PROCEDURE test.AddLocation (IN location VARCHAR(LOCATION_LEN))
BEGIN
  -- example of macro
  ASSERT(length(location) > 0, "lost or something ?");

  -- do something
  select "Hi there.";
END
$$

delimiter ;

y el archivo debug.src, que se incluye:

#ifdef HAVE_DEBUG
#define ASSERT(C, T)                                          \
  begin                                                       \
    if (not (C)) then                                         \
      begin                                                   \
        declare my_msg varchar(1000);                         \
        set my_msg = concat("Assert failed, file:", __FILE__, \
                            ", line: ", __LINE__,             \
                            ", condition ", #C,               \
                            ", text: ", T);                   \
        signal sqlstate "HY000" set message_text = my_msg;    \
     end;                                                     \
    end if;                                                   \
  end
#else
#define ASSERT(C, T) begin end
#endif

Cuando se compila con:

cpp -E location.src -o location.sql

obtienes el código que buscas, con cpp expandiendo #define valores.

Cuando se compila con:

cpp -E -DHAVE_DEBUG location.src -o location.sql

obtienes lo mismo, más la macro ASSERT (publicada como bonificación, para mostrar lo que podría hacerse).

Suponiendo una compilación con HAVE_DEBUG implementada en un entorno de prueba (en 5.5 o posterior, ya que se usa SIGNAL), el resultado se ve así:

mysql> call AddLocation("Here");
+-----------+
| Hi there. |
+-----------+
| Hi there. |
+-----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> call AddLocation("");
ERROR 1644 (HY000): Assert failed, file:location.src, line: 24, condition length(location) > 0, text: lost or something ?

Observe cómo el nombre del archivo, el número de línea y la condición apuntan directamente al lugar del código fuente en location.src donde se genera la aserción, gracias de nuevo al preprocesador C.

Ahora, sobre la extensión de archivo ".src":

  • puedes usar cualquier cosa.
  • Tener una extensión de archivo diferente ayuda con los archivos MAKE, etc., y evita confusiones.

EDITAR:Publicado originalmente como .xql, renombrado a .src para mayor claridad. Aquí no hay nada relacionado con consultas xml.

Al igual que con cualquier herramienta, el uso de cpp puede dar lugar a cosas buenas, y el caso de uso para mantener LOCATION_LEN de forma portátil parece muy razonable. También puede dar lugar a cosas malas, con demasiados #include, #ifdef anidados, macros, etc. que al final ofuscan el código, por lo que su kilometraje puede variar.

Con esta respuesta, obtienes todo (#define , #include , #ifdef , __FILE__ , __LINE__ , #C , opciones de línea de comando para compilar), así que espero que lo cubra todo.