Mysql
 sql >> Database >  >> RDS >> Mysql

Script SQL - Esiste l'equivalente di #define?

Il C Pre Processor (cpp) è storicamente associato a C (da cui il nome), ma in realtà è un generico elaboratore di testo che può essere usato (o abusato) per qualcos'altro.

Considera questo file, chiamato location.src (ne parleremo più avanti).

// 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 il file debug.src, che è incluso:

#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 compilato con:

cpp -E location.src -o location.sql

ottieni il codice che stai cercando, con cpp che espande i valori #define.

Quando compilato con:

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

ottieni lo stesso, più la macro ASSERT (pubblicata come bonus, per mostrare cosa potrebbe essere fatto).

Supponendo una build con HAVE_DEBUG distribuita in un ambiente di test (in 5.5 o versioni successive poiché viene utilizzato SIGNAL), il risultato è simile al seguente:

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 ?

Nota come il nome del file, il numero di riga e la condizione puntano proprio nel punto del codice sorgente in location.src in cui l'asserzione viene sollevata, grazie ancora al preprocessore C.

Ora, sull'estensione del file ".src":

  • puoi usare qualsiasi cosa.
  • Avere un'estensione di file diversa aiuta con i makefile, ecc. e previene la confusione.

EDIT:originariamente pubblicato come .xql, rinominato in .src per chiarezza. Niente relativo alle query xml qui.

Come con qualsiasi strumento, l'uso di cpp può portare a cose buone e il caso d'uso per mantenere LOCATION_LEN in modo portabile sembra molto ragionevole. Può anche portare a cose cattive, con troppi #include, nidificati #ifdef hell, macro, ecc. che alla fine offuscano il codice, quindi il tuo chilometraggio potrebbe variare.

Con questa risposta, ottieni tutto (#define , #include , #ifdef , __FILE__ , __LINE__ , #C , opzioni della riga di comando da compilare), quindi spero che dovrebbe coprire tutto.