Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Scripts SQL - Existe o equivalente a um #define?


O C Pre Processor (cpp) é historicamente associado ao C (daí o nome), mas na verdade é um processador de texto genérico que pode ser usado (ou abusado) para outra coisa.

Considere este arquivo, chamado location.src (mais sobre isso posteriormente).
// 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 ;

e arquivo debug.src, que está incluído:
#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

Quando compilado com:
cpp -E location.src -o location.sql

você obtém o código que está procurando, com o cpp expandindo os valores #define.

Quando compilado com:
cpp -E -DHAVE_DEBUG location.src -o location.sql

você recebe o mesmo, mais a macro ASSERT (postada como bônus, para mostrar o que poderia ser feito).

Assumindo uma compilação com HAVE_DEBUG implantado em um ambiente de teste (no 5.5 ou posterior desde que o SIGNAL é usado), o resultado é assim:
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 como o nome do arquivo, o número da linha e a condição apontam para o local no código-fonte em location.src onde a declaração é levantada, graças novamente ao pré-processador C.

Agora, sobre a extensão de arquivo ".src":
  • você pode usar qualquer coisa.
  • Ter uma extensão de arquivo diferente ajuda com makefiles, etc., e evita confusão.

EDIT:Originalmente postado como .xql, renomeado para .src para maior clareza. Nada relacionado a consultas xml aqui.

Como acontece com qualquer ferramenta, usar cpp pode levar a coisas boas, e o caso de uso para manter LOCATION_LEN de maneira portátil parece muito razoável. Também pode levar a coisas ruins, com muitos #include, #ifdef aninhados, macros, etc. que no final ofusque o código, então sua milhagem pode variar.

Com esta resposta, você obtém tudo (#define , #include , #ifdef , __FILE__ , __LINE__ , #C , opções de linha de comando para construir), então espero que cubra tudo.