COMMIT.YAC



/* OPERACION COMMIT EN BASES DE DATOS */
/* ---------------------------------------------------*/
/* --  Programa:    commit.yac                    ----*/
/* --  TEcnica:     Dirigida por la sintAxis      ----*/
/* --  Objetivo:    Permitir el lenguaje de SQL   ----*/
/* --  Programador: J. Rafael R. ochoa            ----*/
/*----------------------------------------------------*/

%{
   int begin_transaction=0;
   char enlace_commit[80];
%}

%union
{
   char str[256];
}

%token <str> COMA LEFT RIGHT IGUAL LINEA SALIR GO INSERT INTO
%token <str> VALUES DELETE FROM WHERE SELECT UPDATE CREATE TABLE DROP
%token <str> APOSTROFE NOT_NULL SET AND OR CHAR INT ASTERISCO
%token <str> NUMERO TEXTO COMMIT BEGINX TRANSACTION ROLLBACK
%type  <str> insert delete select update tables datos dato criterio
%type  <str> view list_view estructura not_null tipo cambios crit_list
%type  <str> commit begin rollback

%%
/* producciones de la gramatica */
entrada   : expr
          | expr entrada
          | error LINEA { printf("\n:-) "); } entrada
          ;
expr      : SALIR     LINEA   { return 1; }
          | insert   GO LINEA   { printf("\n:-) "); }
          | delete   GO LINEA   { printf("\n:-) "); }
          | select   GO LINEA   { printf("\n:-) "); }
          | update   GO LINEA   { printf("\n:-) "); }
          | tables   GO LINEA   { printf("\n:-) "); }
          | commit   GO LINEA   { printf("\n:-) "); }
          | rollback GO LINEA   { printf("\n:-) "); }
          | begin    GO LINEA   { printf("\n:-) "); }
          ;
insert    : INSERT INTO TEXTO VALUES LEFT datos RIGHT
            {
               if(begin_transaction)
                  sprintf($$,"insert into %s values ( %s )",$3,$6);
               else
                  sprintf($$,"insert into %s values (%s)",$3,$6);
               if(begin_transaction) guarda_log($$);
               else ejecuta_instr_mslq($$);
            }
          ;
delete    : DELETE FROM TEXTO criterio
            {
               sprintf($$,"delete from %s %s",$3,$4);
               if(begin_transaction) guarda_log($$);
               else ejecuta_instr_mslq($$);
            }
          ;
select    : SELECT view FROM TEXTO criterio
            {
               sprintf($$,"select %s from %s %s",$2,$4,$5);
               if(begin_transaction) guarda_log($$);
               else ejecuta_instr_mslq($$);
            }
          ;
update    : UPDATE TEXTO SET cambios criterio
            {
               sprintf($$,"update %s set %s where %s",
                       $2,$4,$5);
               if(begin_transaction) guarda_log($$);
               else ejecuta_instr_mslq($$);
            }
          ;
tables    : CREATE TABLE TEXTO LEFT estructura RIGHT
            {
               sprintf($$,"create table %s ( %s )",$3,$5);
               if(begin_transaction) guarda_log($$);
               else ejecuta_instr_mslq($$);
            }
          | DROP TABLE TEXTO
            {
               sprintf($$,"drop table %s",$3);
               if(begin_transaction) guarda_log($$);
               else ejecuta_instr_mslq($$);
            }
          ;
datos     : dato
              { sprintf($$,"%s",$1); }
          | dato COMA datos
              { sprintf($$,"%s,%s",$1,$3); }
          ;
dato      : APOSTROFE TEXTO APOSTROFE
              { sprintf($$,"'%s'",$2); }
          | NUMERO
              { strcpy($$,$1); }
          ;
criterio  : { sprintf($$,"%s",""); } /* todos */
          | WHERE crit_list { sprintf($$,"where %s",$2); }
          ;
crit_list : TEXTO IGUAL dato
               { sprintf($$,"%s=%s",$1,$3); }
          | TEXTO IGUAL dato AND crit_list
               { sprintf($$,"%s=%s and %s",$1,$3,$5); }
          ;
cambios   :  TEXTO IGUAL dato
              { sprintf($$,"%s=%s",$1,$3); }
          | TEXTO IGUAL dato COMA cambios
              { sprintf($$,"%s=%s,%s",$1,$3,$5); }
view      : ASTERISCO { sprintf($$,"%s","*"); }
          | list_view { sprintf($$,"%s",$1); }
          ;
list_view : TEXTO { sprintf($$,"%s",$1); }
          | TEXTO COMA list_view { sprintf($$,"%s,%s",$1,$3); }
          ;
estructura: TEXTO tipo LEFT NUMERO RIGHT not_null
              { sprintf($$,"%s %s ( %s ) %s",$1,$2,$4,$6); }
          | TEXTO tipo LEFT NUMERO RIGHT not_null
            COMA estructura
              { sprintf($$,"%s %s ( %s ) %s, %s",$1,$2,$4,$6,$8); }
          ;
tipo      : CHAR    { strcpy($$,"char"); }
          | INT     { strcpy($$,"int");  }
          ;
not_null  :   { strcpy($$, " "); }
          | NOT_NULL
              { strcpy($$, " not null"); }
          ;
commit    : COMMIT TRANSACTION
            {
               if(begin_transaction)
               {
                  guarda_log("commit transaction");
                  begin_transaction = 0;
                  system(enlace_commit);
               }
               else
            }
          ;
rollback  : ROLLBACK TRANSACTION
            { system("rollback.pl"); }
          ;
begin     : BEGINX TRANSACTION
            {
               if(begin_transaction)
               else
               {
                  guarda_log("begin transaction");
                  begin_transaction = 1;
               }
            }
          ;
%%

/* funciones auxiliares */
#include <stdio.h>
#include <string.h>

void guarda_log(char log[]);
void ejecuta_instr_mslq(char instr[]);

extern int yylex();  /* Liga con la funcion yylex generada por LEX */
extern int yynerrs;

int yyparse();

void main(int argc, char *argv[])
{
   char decide[80];

   sprintf(enlace_commit, "commit.pl %s",argv[1]);
   sprintf(decide,"decide.pl %s",argv[1]);
   system("clear"); printf("\n"); 

   printf("-------------------------------------------\n");
   printf("   Monitor SQL - incrementado\n");
   printf("-------------------------------------------\n");
   system(decide);  /* rollback o commit */
   printf(":-) ");
   yyparse();
   printf("\n(8-)~ok\n");
}

yyerror(char *error)           /* llamado por yyparse() cuando ocurra */
{                             /*   un error                          */
  printf("\n%s \n",error);
  return 1;
}

void guarda_log(char log[])
{
   FILE *bitacora;
   printf("\n==>%s",log);

   bitacora = fopen("log.txt","a+");
   fputs(log,bitacora);
   fputc('\n',bitacora);
   fclose(bitacora);
}

void ejecuta_instr_mslq(char instr[])
{
   char cadena[275];
   strcpy(cadena,"apli_sql.pl ");
   strcat(cadena,instr);
   system(cadena);
}