  Artculo para la revista Linux Actual nmero 17: Bases de
  datos en WWW con Perl embedido
  Miguel Angel Nacenta Snchez y Javier Fernndez-Sanguino
  Pea
  9 noviembre 2000

  En este artculo veremos cmo se puede introducir Perl para la
  creacin, gestin y mantenimiento de bases de datos a travs de la
  WWW.

  11..  IInnttrroodduucccciinn


  Antes de comenzar se van a repasar algunos de los conceptos vistos ya
  en la serie, pero que refrescarn la memoria al lector adems de
  introducir algunos conceptos nuevos.

  Desde que la la WWW decidi que quera ser ms interactiva (hace ya
  unos cuantos aos) y dejar de limitarse a ofrecer contenidos
  estticos, han surgido muchas soluciones que permiten al usuario
  interactuar con el sistema. Estas soluciones se pueden separar
  claramente en dos tipos; soluciones ejecutadas en el cliente y
  soluciones ejecutadas en el servidor. Las primeras (Javascript,
  VBscript, applets etc.) fueron un avance considerable en la creacin
  de lugares Web; pero la mayora de las aplicaciones serias donde hay
  un flujo de informacin importante no se pueden gestionar de esta
  manera.

  Por eso hace mucho que existen los CGI scripts, de amplio uso sobre
  todo en pginas de servidor que ofrecen algn tipo de servicio en el
  que no se puede delegar el control al ordenador del cliente; bien por
  motivos de seguridad, o bien por razones de eficiencia. Pongamos un
  ejemplo: si queremos que un usuario extraiga una informacin de
  nuestra base de datos no podemos pasarle la base de datos al usuario
  para que el pueda hacer la consulta. Sera demasiado costoso en ancho
  de banda, y es probable que no queramos que acceda a toda la
  informacin (ni siquiera que la tenga).


  22..  CCGGII ssccrriippttss..

  La solucin que surge entonces es utilizar un programa que puede
  intercambiar datos con el usuario a travs de la WWW, ejecutado en
  nuestro servidor y que por lo tanto corre en un entorno seguro y que
  conocemos. Esos programas podan estar escritos y funcionando en
  prcticamente cualquier sistema o lenguaje de programacin.

  Nuestro script tpico tomara los datos que se le han proporcionado, y
  realizara alguna accin, devolviendo como resultado una pgina www
  que podra ser distinta dependiendo de los datos o del resultado del
  proceso en nuestra mquina. Esto significa interactividad con control
  en el servidor. Lo nico que controla el usuario son los datos que
  manda (esto tambin puede resultar un agujero de seguridad, pero ya
  hablaremos de ello ms adelante).

  Hasta hace relativamente poco, la solucin ms accesible (y la que
  probablemente siga siendo la ms adoptada) es usar Perl para procesar
  los datos y construir una pgina que se le pueda devolver al usuario.


  Perl es un lenguaje interpretado que posee unas caractersticas
  particularmente beneficiosas a la hora de escribir programas de este
  tipo, ya que fue inicialmente concebido como una herramienta de
  proceso de informes y muestra un comportamiento excelente en el
  proceso de datos de cualquier tipo. De hecho, PERL es el acrnimo de
  _P_r_a_c_t_i_c_a_l _E_x_t_r_a_c_t_i_o_n _a_n_d _R_e_p_o_r_t _L_a_n_g_u_a_g_e, es decir, lenguaje de
  programacin prctico para extraccin y generacin de informes.
  Adems Perl es completamente libre y hay desarrolladas una cantidad
  muy importante de libreras de funciones que implementan casi todas
  las funciones que uno pueda necesitar.  Pero en este punto surgen
  varios problemas:


    Cada vez que el script se tiene que ejecutar ha de iniciarse el
     intrprete de Perl, lo cual resulta en una sobrecarga inicial no
     despreciable. Esto limita nuestro uso del script: slo podremos
     utilizarlo en mquinas potentes o en sistemas que sepamos que van a
     tener pocos usuarios simultneos.

    El script que programemos ha de generar la pgina ntegramente. Es
     decir, que tenemos que programar nuestro script para que el
     documento resultante tenga etiquetas como <html>, <head>, <body>
     etc, y en el orden adecuado. Esto tiene repercusiones importantes a
     la hora del diseo de webs grandes, en los que el mantenimiento del
     estilo y las plantillas no resulta un problema trivial.


  22..11..  LLaass aalltteerrnnaattiivvaass..


  Como respuesta a estos problemas han surgido varios sistemas, algunos
  de ellos dependientes de plataforma, que alivian de algn modo las
  pesadillas de los webmasters y de los administradores.


    PHP/ASP.  Ahora mismo es el tipo de solucin ms popular. El
     concepto es sencillo: dentro de las propias pginas html se
     incluyen unas directivas escritas en un lenguaje especial que se
     ejecuta en el servidor (accesos a bases de datos, bucles etc). PHP
     por supuesto tiene la ventaja de que es libre y que est disponible
     para casi todas las plataformas y sistemas operativos, a diferencia
     de las Active Server Pages de Microsoft.

    Servlets.  Son programas ejecutados en el lado del servidor que
     pueden correr scripts en lenguajes como Java (Java Servlets) aunque
     ahora es posible utilizar otros lenguajes interpretados como Python
     etc...


  22..22..  LLaa ssoolluucciinn eelleeggiiddaa


  Perl Embebido es un mdulo de extensin de Perl que nos va a permitir
  la mxima interactividad posible desde el servidor usando Perl como
  lenguaje de programacin.


  Perl Embebido supera nuestras dos dificultades principales del
  siguiente modo:


    En primer lugar se ejecuta bajo mod_perl (aunque tambin puede
     ejecutarse al estilo de los antiguos CGI's). Mod_perl es un mdulo
     de Apache que introduce el intrprete de Perl dentro del mismo
     servidor Web y que optimiza la ejecucin de aplicaciones escritas
     en este lenguaje, evitando la sobrecarga de inicializacin antes
     mencionada y logrando un rendimiento muy superior al de otras
     alternativas.

    En segundo lugar y tal como reza el nombre, Perl embebido permite
     incluir cdigo Perl directamente dentro de las pginas web. Esto no
     slo resulta cmodo para el programador sino que permite la
     integracin con otras herramientas que el estilo Perl-CGI antiguo
     no nos permita, como por ejemplo con Website Meta Language.


  22..22..11..  PPrriinncciippaalleess vveennttaajjaass ddee PPeerrll EEmmbbeebbiiddoo..


  Es conveniente destacar algunas de las principales ventajas a la hora
  de utilizar Perl como elemento de acceso a la base de datos, algunas
  particulares del lenguaje de programacin en s y otras particulares
  de la forma de introducir Perl en servidores WWW:



    Perl es un lenguaje flexible, potente, maduro y muy rpido a la
     hora de escribir cdigo.



    Existe una tremenda cantidad de mdulos bien documentados que
     podemos usar dentro de nuestro cdigo y que nos permiten construir
     de forma sencilla aplicaciones web que hagan casi cualquier cosa
     (Ej: Acceso a bases de datos independiente de la implementacin de
     SQL, creacin automtica de imgenes, operacin sobre el sistema
     operativo...). Y toda esta funcionalidad se puede explotar con Perl
     embebido desde una pgina Web.



    La ejecucin sobre _m_o_d___p_e_r_l es muy veloz. Varias pruebas han
     revelado que es muchas veces ms rpida que la de CGI's
     convencionales.



    Todo el software que es necesario para hacer funcionar _m_o_d___p_e_r_l es
     libre y est bien documentado. Adems algunas distribuciones lo
     incluyen empaquetado y prcticamente listo para usar.



    _m_o_d___p_e_r_l Incluye algunas facilidades propias para manejar aspectos
     particulares de la programacin web que resultan muy tiles (datos
     de formularios, manejo de la sesin, etc).

  Quizs la ventaja ms importante es que no es necesario aprender un
  lenguaje de programacin que sirva para una nica aplicacin. Perl es
  multipropsito y tremendamente til en otros campos de utilizacin.



  22..22..22..  DDeessvveennttaajjaass


  Sin embargo Perl embedido no est exento de desventajas, puede
  resultar, a priori, un poco ms difcil de utilizar que sus rivales.
  Adems, el lenguaje de programacin Perl puede ser bastante difcil de
  leer (y por tanto mantener) si no se ha documentado lo suficiente. La
  premisa de Perl de poder realizar la misma cosa de muchas maneras
  distintas puede llevar a que el mantenimiento del cdigo por parte de
  otro programador sea dificultosa si las cosas no se han hecho de
  manera ordenada.



  33..  PPuueessttaa eenn ffuunncciioonnaammiieennttoo yy ccoonnffiigguurraacciinn..


  Antes de explicar cmo se instala y configura es necesario introducir
  los elementos que van a entrar en juego para la instalacin.


    Apache: Es el servidor web libre ms avanzado y el ms usado en
     Internet. Implementa un sistema de mdulos con los cuales se pueden
     aadir funcionalidades al servidor.

    Mod_perl: Es un mdulo de Apache que permite la ejecucin eficiente
     de programas escritos en Perl.

    Perl: Es el intrprete de Perl, con el cual podemos ejecutar
     scripts escritos en el lenguaje del mismo nombre.

    DBI: Es un mdulo (una biblioteca de funciones) de Perl que nos
     permitir el acceso a bases de datos de forma uniforme e
     independiente de la base a la que estemos accediendo (Postgres,
     Oracle, Informix, Interbase etc.)

    Postgresql: Es el sistema de base de datos libre ms avanzado. La
     utilizaremos como ejemplo del acceso a bases de datos desde Perl
     Embebido.

    DBD::Pg: Es el mdulo que usa DBI para acceder a funciones de
     Posgresql, que es la base de datos con la que implementamos
     nuestros ejemplos. En caso de utilizar otras bases de datos,
     tendremos que utilizar un "driver" distinto (Ej: DBD::Mysql).


  44..  IInnssttaallaacciinn


  En primer lugar, para poder hacer nuestras pruebas necesitamos tener
  un servidor Apache funcionando. La descripcin de la instalacin de
  Apache queda fuera de la intencin de este artculo, pero tampoco es
  un tema excesivamente complicado, sobre todo si se usa alguna
  distribucin como Debian o Red Hat. Para saber si tenemos un servidor
  Apache funcionando podemos probar en un navegador cualquiera que est
  en nuestra mquina a acceder a la direccin http://localhost/. Si no
  habamos introducido anteriormente ninguna pgina y tenemos nuestro
  servidor activo, deberamos ver una pgina de bienvenida de Apache.

  Perl tambin debe estar instalado en nuestra mquina. Al igual que en
  el caso de Apache, existe amplia documentacin sobre este proceso, y
  la mayora de las veces es extremadamente sencillo.


  Una vez que tenemos estos dos elementos instalados pasamos a la
  instalacin de _m_o_d___p_e_r_l. Como siempre, si utilizamos una buena
  distribucin este proceso resultar sencillsimo, tanto como pedirle
  al sistema que instale el paquete correspondiente a _m_o_d_-_p_e_r_l (en
  Debian se trata del paquete _l_i_b_a_p_a_c_h_e_-_m_o_d_-_p_e_r_l).


  Una vez que tenemos el fichero hay que decirle a Apache que lo
  utilice.  El fichero de configuracin de apache "httpd.conf" contiene
  los mdulos que se cargan al arrancarlo. Lo normal es que este fichero
  contenga una linea Loadmodule referente a mod perl, que tan slo hemos
  de descomentar (eliminar el "#" del principio). Si esta lnea no
  existe, debemos aadirla. La lnea tendr el siguiente aspecto:



     LoadModule perl_module /ruta/del/archivo/del/modulo/mod_perl.so



  Ahora ya tenemos un servidor con la capacidad de ejecutar scripts a
  travs de _m_o_d___p_e_r_l. Lo siguiente ser hacer que el Perl embebido
  funcione. De nuevo aparece la misma disyuntiva: si nuestro Linux est
  instalado a partir de una distribucin en la cual exista el paquete de
  _e_m_b_-_p_e_r_l (en Debian: _l_i_b_h_t_m_l_-_e_m_b_p_e_r_l_-_p_e_r_l) bastar decirle al sistema
  que lo instale. Si no, tendremos que bajarnos el archivo de
  instalacin (ver listado 1) y realizar los siguientes pasos:


               perl Makefile.PL
               make
               make test
               make install



  El penltimo de los pasos (make test) requiere que se hallen en su
  sistema algunas bibliotecas instaladas de antemano.

  Lo ltimo que nos queda por hacer es configurar Apache para que
  ciertos tipos de extensiones las procese con Embperl. En principio
  nuestro servidor web puede tener gran variedad de tipos de ficheros
  que procesar, y no queremos que procese todos a travs de Embperl. Por
  eso asignaremos a los documentos escritos con este propsito la
  extensin de fichero .epl, aunque por supuesto esta configuracin
  puede (o debe) ser modificada segn las necesidades concretas de
  nuestro servidor o servicios web.


  Para asignar la extensin .epl a los ficheros que deben ser procesados
  por Embperl puede bastar con aadir las siguientes lneas a alguno de
  los ficheros de configuracin de Apache (srm.conf o httpd.conf),
  aunque cualquier lector que haya trabajado con este servidor web es,
  probablemente, capaz de sugerir varias alternativas.



           <Files *.epl>
           SetHandler  perl-script
           PerlHandler HTML::Embperl
           Options     ExecCGI
           </files>

           AddType text/html .epl



  55..  CCmmoo ssee pprrooggrraammaa ccoonn PPeerrll eemmbbeebbiiddoo??


  El primer ejemplo que aqu se muestra, servir para introducir la
  sintaxis bsica del lenguaje y al mismo tiempo para comprobar que
  nuestro sistema est funcionando y procesa nuestros ficheros .epl.
  Pero antes necesitamos tener el esqueleto de un archivo escrito en
  HTML corriente en el que podamos empotrar nuestro cdigo Perl.
       <HTML>
       <HEAD>
       <TITLE>Pruebas de Embperl</TITLE>
       </HEAD>
       <BODY>
       <H1>Este es nuestro fichero de pruebas</H1>

       En este fichero todava no hay nada que tenga que ver con Perl embebido.

       </BODY>
       </HTML>



  El lector que todava no tenga claro si su servidor web est
  funcionando puede comprobarlo copiando este cdigo en un fichero y
  poniendo en las localizaciones tpicas (pruebe a ponerlo en /var/www/
  aunque debera mirar la variable DocumentRoot en su configuracin de
  Apache).


  Ahora comenzaremos a aadir capacidad de proceso a este archivo. En
  primer lugar parece bastante lgico que cuando insertemos nuestro Perl
  en el html tendremos que separarlo de alguna manera, para que el
  intrprete reconozca lo que tiene que procesar y lo que no (el resto
  del html). Esto en Perl embebido se hace con corchetes. Una sentencia
  tpica podra tener el siguiente aspecto.



               [- $variable1 = "Hola"; -]



  El grupo de caracteres "[-" y "-]" delimitan bloques de cdigo perl
  dentro del HTML. Cualquier cosa que est incluida entre estos smbolos
  ser interpretada como cdigo Perl. Tan slo hay que preocuparse de
  terminar las sentencias con ";" tal y cmo haramos en un archivo de
  Perl corriente.  Lo que hemos hecho en la lnea anterior es una simple
  asignacin, la variable "$variable1" contendr ahora la cadena de
  texto "Hola". Al programador Perl que vea esto lo ms probable es que
  se le ocurra introducir sentencias con la instruccin "print" dentro
  de los delimitadores que acabamos de aprender. Sin embargo, Perl no
  sabra dnde tiene que imprimir el resultado de la variable. El
  siguiente trozo de cdigo es incorrecto slo por la declaracin en la
  que aparece la instruccin _p_r_i_n_t:



               [-
                  $variable1 = "Hola";
                  $suma = 1 + 2;
                  if ($suma > 0) {
                    $texto = "Mayor que cero";
                    print $texto; # Esta es la lnea incorrecta
                  }
                  $variable2 = $variable1
                -]



  Pero entonces cmo imprimimos el resultado de nuestros clculos (o de
  nuestras operaciones interactivas) en la pgina web? Muy fcil,
  usaremos otros delimitadores: "[+" y "+]". El siguiente listado
  muestra un ejemplo muy sencillo de cmo podemos imprimir el resultado
  de una variable asignada previamente en nuestro cdigo, ya incluido
  dentro de nuestra pgina de prueba:



         <HTML>
          <HEAD>
           <TITLE>Pruebas de Embperl</TITLE>
          </HEAD>
          <BODY>
           <H1>Este es nuestro fichero de pruebas</H1>

            [- $variable1 = "hola";
               $variable2 = ", qu tal?" -]

            [+ $variable1 +]

          </BODY>
         </HTML>



  Con este ejemplo, ya podemos comprobar que Embperl est procesando
  nuestro fichero. Si nombramos al archivo que contiene el cdigo
  anterior "prueba.epl", lo situamos en el mismo lugar donde ya tengamos
  pginas funcionando e intentamos acceder a l desde el exterior,
  deberamos ver algo como la figura n 1.

  ****** IMAGEN 1 ****************************


  En este punto hay que aclarar algunas cuestiones que se pueden
  plantear habiendo visto los ejemplos anteriores. En primer lugar, como
  ya aparece implcito en los ejemplos anteriores, dentro de los
  delimitadores "[-" y "-]" podemos escribir cdigo en varias lneas, e
  incluso poner comentarios. El ltimo ";" que pongamos dentro de este
  cdigo es opcional, ya que Embperl lo cierra por nosotros en caso de
  que no nos demos cuenta.


  Podemos incluir cuantos grupos de cdigo queramos, y todos _c_o_m_p_a_r_t_e_n
  _e_l _m_i_s_m_o _e_s_p_a_c_i_o _d_e _v_a_r_i_a_b_l_e_s _d_e_n_t_r_o _d_e _u_n_a _m_i_s_m_a _p__g_i_n_a _y _u_n_a _m_i_s_m_a
  _l_l_a_m_a_d_a. Esto quiere decir por un lado que podemos dotar a las
  variables de un valor en un grupo de cdigo y luego usar esa variable
  (que ya contiene el valor que le hemos asignado previamente) en otro
  grupo, y por otra parte que si un usuario desde Internet decide hacer
  una recarga de nuestra pgina, los valores de las variables no se
  conservarn.


  Dentro de los delimitadores de impresin en la pgina ([+ +]) podemos
  poner cualquier cosa que pudiera ser argumento de la funcin print.
  Por ejemplo, si queremos que la pgina descrita unos prrafos ms
  arriba sea un poco ms educada, podemos sustituir la lnea "[+
  $variable1 +]" por esta otra "[+ "$variable1.$variable2" +]"


  Cuando decimos que podemos incluir cdigo dentro de nuestra pgina,
  tambin quiere decir que puede haber bucles, condiciones y cualquiera
  de las posibilidades de control de flujo de un programa que perl nos
  brinda (que no son pocas). Pero el verdadero poder que nos brinda Perl
  en una pgina web es la posibilidad de iterar y condicionar no slo la
  ejecucin de una parte programada, sino _t_a_m_b_i__n _l_a_s _e_t_i_q_u_e_t_a_s _H_T_M_L _y
  _s_u_s _c_o_n_t_e_n_i_d_o_s. Para explicar mejor esto, ponemos un ejemplo:


  Necesitamos que nuestra pgina ensee una imagen si el resultado de un
  clculo anterior es mayor que 5, y en caso contrario, que muestre un
  texto de cabecera de primer nivel (<H1>). Para hacer esto utilizaremos
  lo que se denomina en Embperl _M_e_t_a_-_c_o_m_a_n_d_o_s; aunque el nombre asusta
  un poco, tan slo se trata de separar las sentencias Perl de
  bifurcacin e iteracin en bloques separados. Por ejemplo [$ if
  (condicin) $] que hay que terminar con [$ endif $]. A continuacin
  listamos el cdigo que implementa el problema enunciado al principio
  del prrafo.



         <HTML>
           <HEAD>
             <TITLE>Pruebas de Embperl</TITLE>
           </HEAD>
           <BODY>
             <H1>Este es nuestro fichero de pruebas</H1>
              [-
                $variable=7;   #aqu podra haber algo ms complicado.
              -]
              [$ if ($condicion>5) $]
                <IMG SRC=imagen.gif>
              [$ else $]
                <H1>La variable es menor o igual a 5, mis disculpas.</H1>
              [$ endif $]
          </BODY>
         </HTML>



  Desde el punto de vista de la programacin Perl choca un poco el hecho
  de que haya que cerrar cada una de las sentencias, pero con un poco de
  detenimiento podr el lector observar que si no se le indicara al
  intrprete la finalizacin del bucle o la condicin ste no podra
  determinar sobre que trozo de cdigo iterar o decidir.  Adems del
  meta-comando que acabamos de utilizar existe uno para cada sentencia
  de control de flujo de Perl. A continuacin listamos unos cuantos con
  sus sentencias de cierre como referencia.



               [$ if (condicion) $]
               [$ elseif (condicion) $]
                   ...
               [$ else $]
               [$ endif $]

               [$ do $]
               [$ until $]

               [$ while (condicion) $]
               [$ endwhile $]

               [$ foreach $var (lista) $]
               [$ endforeach $]


  Pero el ejemplo descrito anteriormente no resulta de mucha utilidad,
  en primer lugar porque siempre producir la misma salida. Nuestra
  prxima tarea ser interactuar con el usuario.


  La manera ms directa y usual para interactuar con el usuario a travs
  de una pgina web es un formulario. Embperl nos permite acceder
  fcilmente a la informacin proveniente de los formularios que se ha
  enviado a nuestra pagina-Embperl_script. Para eso existe una
  estructura de tipo "hash" (tambien llamada array asociativo) con la
  cual podemos acceder directamente a estos datos. Este "hash" se llama
  %fdat contiene la informacin enviada de la siguiente forma:



               %fdat = (
                         nombre_del_campo  => informacin_del_campo,
                         nombre_otro_campo => informacin_del_otro_campo
                       )



  Para verlo ms claro supongamos que una pgina web que hemos hecho de
  antemano (que no tiene porqu tener nada que ver con Embperl) contiene
  las siguientes lneas:



               <FORM METHOD="POST" ACTION="prueba.epl">
               Ponga su comentario:<INPUT TYPE="text" NAME="comentario"><BR>
               Y su nombre:    <INPUT TYPE="text" NAME="nombre"><BR>
               <INPUT TYPE="submit" NAME="enviar" VALUE="enviar">
               </FORM>



  Cuando el usuario de esta pgina pulsa el botn en el que pone
  "enviar", el navegador enva una peticin http de la pgina-script
  "prueba.epl" (la que ahora nos ocupa) incluyendo la informacin del
  formulario que hemos descrito un poco antes. Para saber si el usuario
  que lo ha mandado ha tecleado en el campo de nombre la informacin
  "pepe", y obrar en consecuencia, podramos incluir en nuestra pgina
  el siguiente cdigo:



               [$ if ($fdat{nombre} eq "Pepe") $]
               [+ "Qu alegra Pepe, cuanto tiempo sin saber nada de t!" +]
               [$ else $]
               Lo siento, [+ $fdat{nombre} +], pero no nos han presentado.<br>
               [$ endif $]



  Ahora tenemos una visin ms amplia de lo que puede hacer Embperl por
  la interactividad de nuestras pginas. Pero todava no hemos abierto
  la caja de Pandora, o mejor dicho CPAN, el archivo de mdulos Perl.



  66..  PPrrooggrraammaacciinn eenn  PPeerrll::::DDBBII


  DBI es el acrnimo de _D_a_t_a_b_a_s_e _I_n_t_e_r_f_a_c_e, y es un mdulo que permite
  al programa abstraerse de la implementacin especfica del acceso a la
  base de datos, que puede ser distinta en cada base de datos, y le
  permite programar el acceso a una base de datos de manera
  transparente. De esta forma se est facilitando la portabilidad de los
  diversos programas ya que no estn "atados" a ninguna base de datos.

  Como se muestra en la figura 2, Perl::DBI encaja entre los programas y
  los interfaces particulares de cada base de datos, los llamados DBD
  (de _D_a_t_a_b_a_s_e _D_r_i_v_e_r_s) que son los que implementan el acceso a la base
  de datos en s.

  DBI tiene un interfaz muy sencillo que permitir al programador
  seleccionar la base de datos a utilizar y hacer consultas SQL,
  devolviendo los resultados en tablas o arrays asociativos que puedan
  ser fcilmente tratados en Perl.

  El acceso a una base de datos con Perl::DBI se limita a:


    La conexin a la base de datos, que se realiza con la funcin
     _c_o_n_n_e_c_t y en la que se indica la base de datos a utilizar, as como
     el usuario y contrasea para realizar la conexin.

    La preparacin de una llamada SQL con la funcin _p_r_e_p_a_r_e, que se
     utilizar para que el motor de la base de datos con la que se ha
     realizado la conexin "compile" la instruccin SQL y se prepare a
     ejecutarla.

    La ejecucin de la llamada SQL ya preparada con la funcin _e_x_e_c_u_t_e.

    La recuperacin de los datos resultados de la ejecucin de la orden
     SQL con las funciones _f_e_t_c_h_r_o_w___a_r_r_a_y, _f_e_t_c_h_r_o_w___a_r_r_a_y_r_e_f o
     _f_e_t_c_h_r_o_w___h_a_s_h_r_e_f.

    La finalizacin de la consulta con la funcin _f_i_n_i_s_h.

    La desconexin de la base de datos con la orden _d_i_s_c_o_n_n_e_c_t.



  77..  MMiiggrraacciinn ddee ppggssqqll aa PPeerrll EEmmbbeeddiiddoo


  En los artculos anteriores se ha desarrollado el acceso a una base de
  datos utilizando un preprocesador especfico para PostgreSQL que
  permita desarrollar intrpretes CGI rpidamente con los que acceder a
  la base de datos. Sin embargo este acercamiento no esta exento de
  problemas, algunos de los cuales ya se introdujeron en artculos
  previos, y que pueden concretarse en:


    dificultada en la intercepcin de errores.

    dificultad en la comprobacin de datos recibidos.

    dificultad en la elaboracin de interfaces complejos.

    necesidad de la separacin de los formularios y el acceso a la base
     de datos.

  Estos problemas van a poder ser solventados, pero no sin antes un
  esfuerzo adicional de programacin para contemplarlos y una
  reimplementacin haciendo uso de Perl embedido. Una vez hecha, sin
  embargo, la reimplementacin, la disponibilidad de un gran nmero de
  mdulos de Perl para las ms diversas tareas (envo de correos
  electrnicos, acceso a ficheros...) as como la integracin con el
  servidor de Apache para la gestin, por ejemplo, de cookies o de
  sesiones, nos permitirn poder abrir nuevos campos de aplicacin al
  interfaz ya realizado.

  Otra ventaja, adems, es que podremos coger consultas implementadas en
  Perl embedido y, con mnimos esfuerzo, convertirlas en programas
  interpretados escritos en Perl que se ejecuten en el servidor. Esto va
  a permitir, si fuera necesario, convertir el tratamiento dinmico de
  la informacin en esttico, si fuera necesario.



  77..11..  CCoonnssuullttaa ddee ddaattooss ccoonn PPeerrll eemmbbeeddiiddoo


  ************** LISTADO 2 ****************************+


  Como se puede ver en el listado 2, el acceso a las funciones de Perl
  embedido permiten programa muchas caractersticas dentro de una
  pgina. Vamos a tomar dicho listado como la base de un ejemplo para
  ver cmo se hara la migracin de las distintas consultas y
  formularios de introduccin de datos en este lenguaje, analizndolo
  por completo.

  En primer lugar se puede ver que el primer bloque hace que se carguen
  los distintos mdulos que van a ser utilizados por el intrprete, de
  particular inters sern DBI, ya comentado, y CGI::Cookie, que
  permitir acceder a las cookies que el usuario enve al servidor.
  Estas cookies, como ya se coment en artculos anteriores son las que
  se van a utilizar para identificar si el usuario ha sido autenticado.

  Posteriormente, se hace la conexin con la base de datos, utilizando
  la funcin correspondiente del mdulo DBI, preservando en variables la
  posibilidad o no de haber realizado la conexin. Esto va a permitir
  que, a continuacin se puedan tratar los casos de fallo de conexin a
  la base de datos.

  Como se puede ver en el bloque _i_f se pueden, dentro de una misma
  pgina introducir informacin que se va a mostrar en funcin de las
  acciones tomadas anteriormente. Este bloque permite mostrar una pgina
  determinada (en realidad va a reenviar al usuario con un _r_e_f_r_e_s_h a la
  pgina en cuestin) en el caso de que no se haya podido establecer la
  conexin a la base de datos. Los siguientes bloques se evaluarn slo
  en el caso de que la conexin haya sido exitosa, ya que, de no serlo,
  el intrprete saltar al bloque _e_n_d_i_f correspondiente.

  A continuacin se evala si la _c_o_o_k_i_e del usuario corresponde con una
  vlida, utilizando el valor de sta para realizar una consulta a la
  base de datos que nos indicar si est accediendo un usuario
  autorizado.

  En el caso de que no lo sea, hay un nuevo error que le indicar al
  usuario que no pertenece a la base de datos y deber autenticarse. Si
  lo es, se llegar a la construccin de la consulta que ser realizada
  en la base de datos, en este caso un listado de Antiguos Alumnos.

  Se utiliza Perl embedido para procesar la consulta a travs del
  interfaz DBI, y para mostrar la lista de columnas recibidas dentro de
  una tabla. En el caso de que no haya datos se muestra un mensaje
  explicativo indicando la razn.

  Asimismo se pueden introducir en una misma pgina tres pginas
  distintas que sern mostradas en funcin de las condiciones de
  ejecucin del programa.


  77..22..  AAuutteennttiiccaacciinn ddee uussuuaarriiooss ccoonn PPeerrll eemmbbeeddiiddoo


  ************** LISTADO 3 ***************************

  Finalmente, como ejemplo ms complejo se puede consultar el listado 3.
  ste sera el correspondiente a la pgina de acceso al servidor, que,
  como se puede ver es dinmica.

  En dicha pgina est incluido el formulario de entrada de datos del
  usuario, la comprobacin de los datos en s, y los mensajes de
  aceptacin y rechazo correspondientes. Como se puede ver se puede
  hacer de golpe todas estas operaciones sin tener que necesitar
  distintas pginas separadas que s eran necesarias en el caso de
  pgsql.

  Se deja, por limitaciones de espacion, como ejercicio al lector el
  determinar el exacto funcionamiento de este programa.



  88..  RReessuummeenn


  Como se ha visto en ste artculo es posible hacer uso de toda la
  potencia expresiva de Perl en la programacin de pginas dentro de
  servidores de WWW, esto, acompaado con la gran versatilidad del
  mdulo Perl::DBI permite a los programadores la definicin de
  interfaces desde WWW a servidores de bases de datos que sean
  fcilmente portables entre servidores, sistemas operativos y sistemas
  de gestin de bases de datos.


  99..  SSuummaarriiooss

  La solucin ms fcil para hacer CGIs es usar Perl.

  Perl posee beneficiosas caractersticas a la hora de escribir
  programas.

  Existen alternativas al uso de Perl embedido.

  Perl emebedido permite una gran interactividad en el servidor.

  Antes de nada es necesario introducir los elementos necesarios.

  La configuracin para Perl embedido no es complicada.

  No es difcil introducir Perl embedido en pginas HTML.

  DBI es un interfaz genrico de acceso a bases de datos.

  Se reimplementarn los ejemplos anteriores con Perl embedido.

  Es posible hacer uso de toda la potencia expresiva de Perl.



  1100..  LLiissttaaddooss


  LISTADO 1

  Algunos servidores de inters son:

    www.apache.org que contiene toda la informacin relativa al
     servidor Apache.

    www.perl.org, toda la informacin sobre el lenguaje de programacin
     Perl.

    perl.apache.org, que contiene toda la informacin sobre la
     integracin de Perl y Apache.

    www.cpan.org, servidor que ofrece todos los mdulos disponibles
     para Perl.

    www.postgresql.org, el servidor principal del sistema de gestin de
     bases de datos PostgreSQL.

    Se puede encontrar gran informacin sobre DBI en la pgina de
     recursos http://www.symbolstone.org/technology/perl/DBI/

    El proyecto WebDBI, www.wdbi.net, es tambin de gran inters en el
     sentido de que permite realizar rpidamente interfaces web a bases
     de datos con DBI y perl embedido. Merece la pena conocerlo.

    lucas.hispalinux.es, que contiene gran cantidad de documentacin
     traducida al castellano incluyendo el proyecto de traduccin de
     PostgreSQL al castellano. Otro servidor de gran inters para
     hispano parlantes es www.postgres.org.mx

  El libro de O'reilly de Perl::DBI "Programming the Perl DBI" de
  Alligator Descartes y Tim Bunce, los creadores del mdulo es una
  estupenda referencia sobre el tema (ISBN: 1565926994).

  PIE LISTADO 1: Ms informacin


  LISTADO 2



  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//ES">
  <HTML>
  <HEAD>
     <TITLE>Listado de antiguos alumnos por ao de promocin</TITLE>

   [-
     use DBI;
     use POSIX qw/strftime/;
     use CGI::Cookie;
     %cookies = fetch CGI::Cookie;
     $db="alumni2k";
     $uslec="lectura";
    -]
   [-
    $dbuser=$uslec;

    if (not(defined($dbhlectura))) {
     eval {$dbhlectura = DBI->connect("dbi:Pg:dbname=$db", "$dbuser", "")
     or die "No puedo abrir la base de datos $dbname con el usuario $dbuser\n"; };

     $falloconex = "fallo" if ( ! defined($dbhlectura) );
    };
    -]

   [$ if ($falloconex) $]
   [- $udat{errores}="Sin conexin";  -]
             <META http-equiv="refresh" content="1;URL=../error/fallo_conexion.epl">
             </HEAD>
             <BODY>
             Ha habido un <A HREF="../error/fallo_conexion.epl">error%lt;/A>
             </BODY>
             </HTML>
   [$ else $]

   [-  if (exists($cookies{'codigo'}) && $cookies{'codigo'}->value != 0 )
        {
          $codigo = $cookies{'codigo'}->value;
          @arraydatos = $dbhlectura->selectrow_array("SELECT DISTINCT codigo, nombre, apellido, id_persona FROM persona WHERE codigo = \'$codigo\'");
        }
        if (@arraydatos)
        {
           $ref = \@arraydatos;
          ($bogus,$nombreusuario,$apellidousuario,$idpersona)=@$ref;
         }
        else {$ref=""}
    -]

    [$ if (not($ref)) $]
    [- $udat{errores}="No es miembro o no autentificado"; -]
  <META http-equiv="refresh" content="0;URL=../error/no_pertenece.epl">
  </HEAD>
  <BODY>
  <STRONG>
  Ha habido algn error en el proceso, si su navegador no se lo muestra
  automticamente pulse <a HREF="../error/no_pertenece.epl">aqu</A>.
  </STRONG>
  </BODY>
  </HTML>

   [$ else $]

  </HEAD>
  <BODY>
  <H1>Listado de AAs por ao de promocin</H1>

  [-
     $consulta = "select nombre, apellido, graduacion  from persona, datos_academicos where persona.id_persona = datos_academicos.id_persona and autorizacion = 1 order by graduacion";
     $sth = $dbhlectura->prepare($consulta);
     $sth->execute or die "Lo siento, no puedo realizar la consulta en este momento";
     $head = $sth->{NAME};
     $data = $sth->fetchall_arrayref ;
     $rows = $sth->rows;
  -]
  [$ if $rows > 0 $]
  <table border=0>
  <tr><th>[+ $head->[$col] +]</th></tr>
  <tr><td>[+ $data -> [$row][$col] +]</td></tr>
  </table>
  [$ else $]
  <P>Lo lamentamos, pero no hay datos en la base de datos en respuesta
  a la consulta



  </BODY>
  </HTML>


  [$ endif $]

  [$ endif $]

  [-
   if (defined($dbhlectura)) {
       eval{$dbhlectura->disconnect or warn "La desconexin de la base de datos fall: $DBI::errstr\n";}
     };
   -]



  PIE LISTADO 2: Ejemplo de consulta con perl embedido

  LISTADO 3



  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//ES"gt;
  <HTMLgt;
  <HEADgt;
     <TITLEgt;Bienvenidos al sitio de la Asociacin de Antiguos Alumnos</TITLEgt;

    [-
     use DBI;
     use POSIX qw/strftime/;
     use CGI::Cookie;
     %cookies = fetch CGI::Cookie;
     $db="alumni2k";
     $uslec="lectura";
     $usesc="escritura";
     $uspub="sincompletar";
     $usadm="sincompletar";
     $passadm="sincompletar";
    -]


    [-
    $dbuser=$uslec;
  if (not(defined($dbhlectura))) {
  eval {$dbhlectura = DBI-gt;connect("dbi:Pg:dbname=$db", "$dbuser", "") or die "No puedo abrir la base de datos $dbname con el usuario $dbuser\n"; };
  if (not(defined($dbhlectura))) {$falloconex="fallo";}
  };
    -]


   [-  if (exists($cookies{'codigo'}) && $cookies{'codigo'}-gt;value != 0 )
        {
          $codigo = $cookies{'codigo'}-gt;value;
          @arraydatos = $dbhlectura-gt;selectrow_array("SELECT DISTINCT codigo, nombre, apellido, id_persona FROM persona WHERE codigo = \'$codigo\'");
        }
        if (@arraydatos)
        {
           $ref = \@arraydatos;
          ($bogus,$nombreusuario,$apellidousuario,$idpersona)=@$ref;
         }
        else {$ref=""}
   -]



  [-
  $dni=$fdat{donaid};
  $fecha=$fdat{fecha};
  -]

  [$ if ($dni && $fecha ) $]

  [-  sub compruebadate {
      use POSIX qw/strftime/;
      my $anno = strftime "%Y", localtime;
      $_=shift;
      if (not(m/(\d\d)-(\d\d)-(\d\d\d\d)/)) {push @erroresdate, "La fecha no cumple el formato, revsela. (DD-MM-AAAA)\n";}
      return @erroresdate;
  }
  -]
  [- sub compruebadni {
  my $dnip=shift;
  $_=$dnip;
  if (not(m/^(\d+)$/)) {push @erroresdni, "El dni que ha introducido no es vlido, por favor, asegrese de que no incluye espacios ni caracteres que no sean dgitos.\n";}
  return @erroresdni;
  }
  -]
  [-
     @edate= compruebadate($fecha);
     @edni = compruebadni($dni);
  -]
  [$ if (not(@edate||@edni)) $]

  [-
  $autentificable = "SELECT DISTINCT id_persona, nombre, apellido FROM persona WHERE fecha_nacimiento = \'$fecha\' and dni = \'$dni\'";
  $sthautentificable = $dbhlectura-gt;prepare($autentificable);
  $sthautentificable-gt;execute;
  @arrayautent = $sthautentificable-gt;fetchrow_array;
  -]
  [$ if (not(@arrayautent)) $]
  [-
  $autentificable = "SELECT DISTINCT id_persona, nombre, apellido FROM persona_sin_verif WHERE fecha_nacimiento = \'$fecha\' and dni = \'$dni\'";
  $sthautentificable = $dbhlectura-gt;prepare($autentificable);
  $sthautentificable-gt;execute;
  @arrayautent = $sthautentificable-gt;fetchrow_array;
  -]
  [$ if (not(@arrayautent)) $]
  [- push @egeneral,('Vd. no ha introducido an sus datos para solicitar ser miembro de la asociacin o ha cometido algun error en sus datos; si tiene algun problema, por favor <A HREF="mailto:alumni-admin@dat.etsit.upm.es"gt;contacte con el administrador</Agt;.'); -]
  [$ else $]
  [- push @egeneral,('Ya hemos recibido sus datos pero lamentamos decirle que an no hemos podido verificarlos. No podr acceder, an, a las consultas de la base de datos pero s podra <A HREF="datos/modificadatos.epl"gt;modificar</Agt; sus datos si lo desea. '); -]
  [- ($aid,$anom,$aape) = @arrayautent; -]


  [-
  $sec = strftime "%S", localtime;
  $criptado = crypt $anom, "$sec";
  $metecodigo="UPDATE persona_sin_verif SET codigo=\'$criptado\' WHERE id_persona=\'$aid\'";
  $sthcodigo=$dbhescritura-gt;prepare($metecodigo);
  $sthcodigo-gt;execute();
  -]


  <META HTTP-EQUIV="Set-Cookie" CONTENT="codigo =[+ $criptado +]"gt;


  [-
  $aumentaacceso="UPDATE accesos SET num_accesos = num_accesos + 1 WHERE persona_sin_verif.id_persona=\'$aid\'";
  $aumentaaccesotemp="UPDATE accesos SET num_accesos_parcial = num_accesos_parcial +1 WHERE persona_sin_verif.id_persona=\'$aid\'";
  $marcaultimoacceso="UPDATE accesos SET fecha_ultimo_acceso = \'now\' WHERE persona_sin_verif.id_persona=\'$aid\'";
  $sthaumenta=$dbhescritura-gt;prepare($aumentaacceso);
  $sthaumenta-gt;execute();
  $sthaumentatemp=$dbhescritura-gt;prepare($aumentaaccesotemp);
  $sthaumentatemp-gt;execute();
  $sthmarca=$dbhescritura-gt;prepare($marcaultimoacceso);
  $sthmarca-gt;execute();
  -]


  [$ endif $]
  [$ else $]
  [- ($aid,$anom,$aape) = @arrayautent; -]


  [-
  $sec = strftime "%S", localtime;
  $criptado = crypt $anom, "$sec";
  $metecodigo="UPDATE persona SET codigo=\'$criptado\' WHERE id_persona=\'$aid\'";
  $sthcodigo=$dbhescritura-gt;prepare($metecodigo);
  $sthcodigo-gt;execute();
  -]


  <META HTTP-EQUIV="Set-Cookie" CONTENT="codigo =[+ $criptado +]"gt;

  [-
  $aumentaacceso="UPDATE accesos SET num_accesos = num_accesos + 1 WHERE persona.id_persona=\'$aid\'";
  $aumentaaccesotemp="UPDATE accesos SET num_accesos_parcial = num_accesos_parcial +1 WHERE persona.id_persona=\'$aid\'";
  $marcaultimoacceso="UPDATE accesos SET fecha_ultimo_acceso = \'now\' WHERE persona.id_persona=\'$aid\'";
  $sthaumenta=$dbhescritura-gt;prepare($aumentaacceso);
  $sthaumenta-gt;execute();
  $sthaumentatemp=$dbhescritura-gt;prepare($aumentaaccesotemp);
  $sthaumentatemp-gt;execute();
  $sthmarca=$dbhescritura-gt;prepare($marcaultimoacceso);
  $sthmarca-gt;execute();
  -]

  [$ endif $]


  [$ endif $]

  [$ endif $]


            [$ if ($falloconex) $]
             [- $udat{errores}="Sin conexin";
             -]
             <META http-equiv="refresh" content="1;URL=error/fallo_conexion.epl"gt;
             </headgt;
             <bodygt;
             </bodygt;
             </htmlgt;
            [$ else $]

            [$ if ($falloconex) $]
             [- $udat{errores}="Sin conexin";
             -]
             <META http-equiv="refresh" content="1;URL=error/fallo_conexion.epl"gt;
             </headgt;
             <bodygt;
             </bodygt;
             </htmlgt;
            [$ else $]

  </HEADgt;
  <BODY BGCOLOR="white"gt;
  <H1gt;Bienvenido</H1gt;
  <Pgt;Bienvenido al servidor de la Asociacin de Antiguos Alumnos.

  <table border="0" cellpadding="0" cellspacing="0"gt;
   <trgt;
    <td width="280" valign="top" align="left"gt;
  [$ if not($aid) $]

  [$ if (not($ref)) $]

  <FORM METHOD="POST" ACTION="index.epl"gt;
  D.N.I.:<INPUT TYPE="PASSWORD" NAME="donaid" TABINDEX="1" SIZE="10"gt;
  Fecha de Nacimiento:
  (DD-MM-AAAA) <INPUT TYPE="TEXT" NAME="fecha" TABINDEX="2" SIZE="10"gt;
  <input type="submit" name="autent" value="Autentifcame"gt;
  </FORMgt;

  [$ endif $]
  [$ if ($ref) $]

  [+ $nombreusuario +] [+ $apellidousuario +]<brgt;
  Conectado al servidor, con los correspondientes permisos de usuario.

  [$ endif $]
  [$ endif $]
  [$ if ($aid) $]
  Ud. acaba de ser reconocido como<brgt;
  [+ $anom +] [+ $aape +],<brgt;
  Bienvenido al servidor.
  [$ endif $]

  [$ if ($dni) $]
  [$ if (@edate||@edni||@egeneral) $]

  [$ foreach $msg (@edni) $]
  [+ $msg +]<HRgt;
  [$ endforeach $]
  [$ foreach $msg (@edate) $]
  [+ $msg +]<HRgt;
  [$ endforeach $]
  [$ foreach $msg (@egeneral) $]
  [+ $msg +]<HRgt;
  [$ endforeach $]

  [$ else $]

  No olvide que una vez su acceso al servidor ha sido reconocido, ya puede
  acceder tanto a las <a href="consultas/"gt;consultas</Agt; como a
  la <A HREF="datos/modificadatos.epl"gt;modificacin o actualizacin</Agt; de sus datos guardados aqu.

  [$ endif $]
  [$ endif $]
  [$ if (not($aid)) $]

  [$ if (not($ref)) $]

  <FORM METHOD="POST" ACTION="datos/nuevosocio.epl"gt;
  Nombre: <INPUT TYPE="TEXT" NAME="nombre" TABINDEX="3" SIZE="20"gt;
  Apellidos: <INPUT TYPE="TEXT" NAME="apellidos" TABINDEX="4" SIZE="20"gt;
  <input type="submit" name="nuevosocio" value="Comenzar"gt;
  </FORMgt;

  [$ endif $]

  [$ endif $]

  </BODYgt;
  </HTMLgt;
  [$ endif $]
  [$ endif $]

    [- if (defined($dbhescritura)) {
       eval{$dbhescritura-gt;disconnect or warn "La desconexin de la base de datos fall: $DBI::errstr\n";}};
    -]


    [- if (defined($dbhlectura)) {
       eval{$dbhlectura-gt;disconnect or warn "La desconexin de la base de datos fall: $DBI::errstr\n";}};
    -]



  PIE LISTADO 3: Entrada al servidor



  1111..  CCaappttuurraass



    Figura 1: (fig1.bmp) Primer ejemplo con Perl embedido

    Figura 2: (ambitodbi.png) Ambito del mdulo Perl::DBI

    Figura 3: (entrada.png) Entrada al servidor



  1122..  NNoottaass ddee mmaaqquueettaacciinn



  1133..  NNoottaass ddee ccoooorrddiinnaacciinn


  Es posible seguir con artculos de esta serie con los siguientes
  temas:

    WDBI

    uso de WML para la creacin de webs

    programacin ms detallada del uso de Perl::DBI



