[LinuxFocus-icon]
LinuxFocus article number 331
http://linuxfocus.org

[Photo of the Author]
por Diego Alberto Arias Prado
<dariapra(at)yahoo.es>

Sobre el autor:

Soy un ingeniero de Telecomunicación de Lugo, España. No recuerdo exactamente cuándo empecé a utilizar Linux, fue en 1995 ó 1996. Antes era un usuario de Microsoft Windows y ni siquiera sabía de la existencia de Linux. La primera vez que vi un ordenador con sistema operativo Linux instalado fue en la universidad. Me pareció muy interesante y no tardé en instalarlo en mi ordenador en casa; recuerdo que mi primera distribución Linux fue Slackware.

Durante todos estos años me he divertido mucho utilizando otras distribuciones Linux y algunas versiones de BSD, programando en lenguajes como Java o Tcl, utilizando servidores de web, de bases de datos, de aplicaciones... Linux no ha sido sólo para mí una forma de divertirme ya que he tenido la opotunidad de utilizar Linux cuando trabajé en Telefónica I+D.



Traducido al español por:
Diego Alberto Arias Prado <dariapra(at)yahoo.es>

Introducción a la biblioteca TclMySQL

MySQLTcl

Resumen:

En este artículo se muestra la instalación y uso de MySQLTcl, una biblioteca del lenguaje de programación Tcl que permite hacer consultas SQL - en inglés, queries - (select, insert, delete...) desde scripts Tcl a servidores de bases de datos MySQL.

Tcl son las siglas de Tool Command Language, un lenguaje de programación de tipo scripting creado por John Ousterhout [1]. En realidad, Tcl consiste en dos cosas: además de ser un lenguaje de programación de tipo scripting, es también un intérprete de scripts Tcl. Tcl es un lenguaje de programación estructurado que utiliza tres estructuras con tres estructuras de datos básicas: cadenas (strings), listas y arrays. Otras características de Tcl son el uso de expresiones regulares [2], la posibilidad de poder utilizar bibliotecas Tcl escritas por terceras personas y Tk, un toolkit que permite la creación de aplicaciones Tcl gráficas.

MySQL es un servidor de bases de datos muy popular en el mundo del software libre que, en mi opinión, no necesita presentación.

MySQLTcl es una biblioteca Tcl que permite hacer consultas a un servidor de bases de datos MySQL desde scripts Tcl. Actualmente, Paolo Brutti, Tobias Ritzau and Artur Trzewick son los autores y quienes mantienen esta biblioteca Tcl.

_________________ _________________ _________________

 

Instalación de la biblioteca MySQLTcl

Si su distribución Linux o sistema operativo BSD utiliza un sistema de paquetes (como por ejemplo RPM o DEB) o un sistema de ports (como por ejemplo Crux Linux o FreeBSD), puede usar el sistema de paquetes o ports para instalar la biblioteca MySQLTcl y pasar así a la siguiente sección.

Si no es así o, simplemente, prefiere hacer la instalación de forma manual, en las siguientes líneas se muestran los pasos que hemos seguido. En vez de un pequeño manual que muestra paso a paso cómo hacer la instalación, estas líneas deben leerse como una especie de pequeña guía. En una distribución Linux Mandrake (version 9.2), desde bash:

$ ./configure --with-mysql-lib=/usr/lib
$ make
$ make install
Si algo ha ido mal durante el paso "configure", los mensajes de error le darán información que le ayudará a resolver el problema. Es frecuente que éste consista en que el script no consigue encontrar algunos ficheros o directorios. En casos como éste, la solución consiste en "jugar" con este script pasándole parámetros que le indiquen dónde puede encontrar esos ficheros y directorios "perdidos". Veamos otro ejemplo de instalación. En FreeBSD 5.0 la biblioteca MySQLTcl se puede instalar con las siguientes opciones:
$ export CPP=/usr/bin/cpp
$ ./configure --with-tcl=/usr/lib/local/tcl8.3
 --with-tclinclude=/usr/local/include/tcl8.3
 --with-mysql-include=/usr/local/include/mysql
 --with-mysql-lib=/usr/local/lib/mysql
$ make
$ make install
Como habrá notado, en este segundo ejemplo la versión de Tcl era 8.3; además, la versión de la biblioteca MySQLTcl era 2.15 y la versión del servidor de bases de datos MySQL era 3.23.54.

 

Rudimentos de Tcl

En esta sección se muestran de forma somera los rudimentos de Tcl a lectores que no sepan utilizar este lenguaje de programación. Si usted ya sabe programar en Tcl, puede pasar a la siguiente sección.

Los ejemplos mostrados en esta sección (y también en las demás) pueden ser reproducidos desde una consola Tcl (tclsh).

 

Variables. Substitución de variables y comandos.

En Tcl las variables se crean con el comando set. Veamos algunos ejemplos:

% set address {Edison Avenue, 83}
Edison Avenue, 83
% set zip_code 48631
48631
En estos dos ejemplos hemos creado dos variables, llamadas address y zip_code. Los valores que estas variables contienen son, respectivamente, Edison Avenue y 48361; ambos valores son cadenas (strings). Nótese que para la creación de la variable address se han utilizado llaves (caracteres { y }); esto es así porque dicha cadena contiene espacios. Los valores de las variables se pueden obtener utilizando también el comando set:
% set address
Edison Avenue, 83
% set zip_code
48631
Supongamos que queremos imprimir en pantalla el valor de la variable address. Esto se puede hacer utilizando el comando puts:
% puts stdout [set address]
Edison Avenue, 83
El comando puts recibe el parámetro stdout. Este parámetro indica al comando puts que debe imprimir en la salida standard (en inglés, standard output), que en nuestro caso es el monitor. El segundo parámetro que recibe el comando puts es [set address]. Los corchetes (caracteres [ y ]) de este parámetro indican al intérprete Tcl que lo que hay dentro es otro comando Tcl que debe ser ejecutado por el intérprete Tcl antes de que lo sea el comando puts; esto recibe el nombre de substitución de comandos. Lo hecho en el anterior ejemplo se puede hacer también de otra forma:
% puts stdout $address
Edison Avenue, 83
Lo que se ha hecho en este ejemplo se llama substitución de variable: el caracter $ que precede a un nombre de variable hace que dicha substitución ocurra.

En un ejemplo anterior hemos podido ver como utilizando llaves, distintas palabras separadas por espacios podían ser agrupadas para formar una cadena. Existe otra forma de agrupación, que consiste en utilizar comillas (el caracter ") en vez de llaves. Sin embargo, estas dos formas de agrupación no funcionan igual. Veámoslo con un ejemplo:
% puts stdout "the zip code is [set address]"
the zip code is 48631
% puts stdout "the zip code is $address"
the zip code is 48631
% puts stdout {the zip code is [set address]}
the zip code is [set address]
% puts stdout {the zip code is $address}
the zip code is $address
En este ejemplo se puede ver como al utilizar llaves para formar una agrupación no se hace substitución de comandos; sin embargo, esto sí ocurre si se utilizan comillas para formar dicha agrupación.

Para borrar variables se utiliza el comando unset:
% unset address
% set address
can't read "address": no such variable
% unset zip_code
% set zip_code
can't read "zip_code": no such variable

 

Cadenas en Tcl

La cadena (string) es una de las tres estructuras de datos básicas en Tcl. Una cadena es un conjunto de caracteres. Para crear una cadena se puede utilizar el comando set.

% set surname Westmoreland
Westmoreland
% set number 46.625
46.625
Tanto la variable surname como la variable number son cadenas. Para manipular cadenas se utiliza el comando string. Veamos algunos ejemplos que muestran cómo se puede utilizar este comando:
% string length $surname
12
% set surname [string range $surname 0 3]
West
% puts stdout $surname
West
% string tolower $surname
west
A diferencia de Pascal o Java, Tcl no es lenguaje de programación de "tipos fuertes". El siguiente ejemplo es una muestra de ello:
% set number [expr $number + 24.5]
70.125
% string range $number 2 5
.125
Con el comando expr, el valor de la variable number fue incrementado en 24,5. A continuación, con el comando string, la variable number fue tratadada como si fuese una cadena, siendo mostrados sus cuatro últimos caracteres.

El comando string permite hacer más manipulaciones con cadenas que las mostradas en los anteriores ejemplos.

 

Listas en Tcl

En Tcl, las listas (lists) son un caso especial de cadenas en las que los elementos de la lista están separados por espacios en blanco y que, además, tienen una interpretación distinta.

% set friends_list {Fany John Lisa Jack Michael}
Fany John Lisa Jack Michael
% set friends_list [string tolower $friends_list]
fany john lisa jack michael
% set friends_list
fany john lisa jack michael
En Tcl hay varios comandos que permiten manipular las listas. Veamos algunos ejemplos:
% lindex 2 $friends_list
lisa
% lrange $friends_list 2 4
lisa jack michael
% set friends_list [lsort -ascii $friends_list]
fany jack john lisa michael
% set friends_list
fany jack john lisa michael
% set friends_list [linsert $friends_list 2 Peter]
fany jack Peter john lisa michael
% string toupper $friends_list
FANY JACK PETER JOHN LISA MICHAEL
El último ejemplo muestra que cadenas (strings) y listas (lists) en el fondo son la misma estructura de datos.

 

Arrays en Tcl

Un array Tcl se puede ver como una lista cuyos índices son, a su vez, cadenas. Un array se puede crear como se muestra en el siguiente ejemplo:

% set phone_numbers(fany) 629
629
% set phone_numbers(michael) 513
513
% set phone_numbers(john) 286
286
Los valores del array se pueden mostrar utilizando conjuntamente el comando set y substitución de variables; como se mostró en el anterior ejemplo, el índice del array - que es una cadena - está entre paréntesis:
% set $phone_numers(michael)
513
El comando array muestra información sobre una variable de tipo array. Veamos algunos ejemplos que muestran qué se puede hacer con este comando:
% array size phone_numbers
3
% array names phone_numbers
fany john michael

 

Conexiones a bases de datos

Antes de hacer cualquier consulta a una base de datos desde un script Tcl, es necesario establecer una conexión a un servidor de bases de datos. En esta sección veremos cómo se hace y qué hacer con los errores que se pueden dar al intentar establecer dichas conexiones.

De ahora en adelante se utilizarán indistintmente los términos "conexión a bases de datos" y "conexión a servidores de bases de datos".

 

Estableciendo una conexión a una base de datos

Veamos el ejemplo de un script Tcl que establece una conexión con un servidor de bases de datos MySQL.

0:  #!/usr/bin/tclsh8.4
1:
2:  package require mysqltcl
3:  global mysqlstatus
4:
5:  set port {3306}
6:  set host {127.0.0.1}
7:  set user {john_smith}
8:  set password {jsmith_password}
9:
10: set mysql_handler [mysqlconnect -host $host
    -port $port -user $user -password $password]
11:
12: mysqlclose $mysql_handler
Nótese que los números mostrados en la columna izquierda junto con los dos puntos a continuación no son parte del script Tcl; se muestran para numerar las líneas del script. Nótese también que dependiendo de la distribución Linux utilizada es posible que haya que modificar la línea número 0 cambiando el path del intérprete Tcl.

La línea número 0 le dice al shell que el fichero es un script Tcl y dónde encontrar el intérprete Tcl.

La línea número 2 le dice al intéprete Tcl que busque en la biblioteca MySQLTcl cuando ejecute los restantes comandos del script. Por ejemplo, en la línea número 10 podemos ver el comando mysqlconnect; si la línea número 2 no existiese, al ejecutar el intérprete Tcl la línea número 10 el comando mysqlconnect no sería encontrado y habría un error.

En las líneas número 5 y 6 se fijan el puerto (port) y el host con el que el script Tcl intentará establecer la conexión. En este script el número de puerto es 3306 (el puerto por defecto en el que un servidor de bases de datos MySQL "escucha") y el host es la misma computadora en la que el script se está ejecutando.

En las líneas número 7 y 8 se fijan el nombre del usuario de la base de datos y su password.

En la línea número 10 es donde realmente se establece la conexión con el servidor de bases de datos. La salida del comando mysqlconnect se guarda en la variable de nombre mysql_handler. Esta variable - a la que llamaremos handler - se utiliza para hacer consultas SQL a las bases de datos y también para cerrar la conexión, tal y como se muestra en la línea número 12.

 

Manejo de los errores

En la anterior subsección no se explicó qué hacía la línea número 3; lo haremos en ésta.

Al ejecutarse los comandos de la biblioteca MySQLTcl pueden aparecer errores. Si dichos errores no son capturados (caught), la ejecución del script Tcl se detendrá y es posible que eso no nos interese.

10: if [catch {mysqlconnect -host $host -port $port
    -user $user -password $password} mysql_handler] {
11:     puts stderr {error, the database connection could not be established}
12:     exit
13: } else {
14:     mysqlclose mysql_handler
15: }
Si durante la ejecución del comando set mysql_handler [mysqlconnect -host $host... se produce algún error, dicho error será capturado por el comando catch. El comando catch devuelve 1 si al ejecutarse el comando que hay entre las llaves aparece un error o 0 si no hay ningún error. La variable mysql_handler guarda la salida del comando ejecutado que está entre las llaves (caracteres { y }).

Si hay algún error, se imprime en la salida standard de error (stderr) - que será, en nuestro caso, el monitor - un mensaje de error. Las posibles causas por las que puede haber un error al intentar establecer una conexión con una base de datos son varias: password incorrecto, host o número de puerto incorrectos... En casos así, el disponer de más información que la dada por un mensaje del tipo "se ha producido un error" puede ser útil.

En la línea número 3, la variable mysqlstatus se declaró global. Las variables globales son aquellas que son accesibles desde cualquier parte de un script Tcl; esto tiene que ver con el ámbito (scope) de las variables Tcl, tema que no trataremos en este artículo. La biblioteca MySQLTcl crea y mantiene un array global llamado mysqlstatus que tiene los siguientes elementos:

elemento significado
code Si no ha habido ningún error, entonces mysqlstatus(code) contiene 0; en caso contrario, el contenido de mysqlstatus(code) será el código númerico MySQL del error. Si ha habido un error y no tiene su origen en el servidor de bases de datos MySQL, entonces el contenido de mysqlstatus(code) será -1.

El contenido de mysqlstatus(code) se actualiza despúes de la ejecución de cualquier comando de la biblioteca MySQLTcl.
command El último comando de la biblioteca MySQLTcl que produjo un error se guarda en mysqlstatus(command).

El contenido de mysqlstatus(command) se actualiza después de la ejecución sin éxito de cualquier comando de la biblioteca MySQLTcl; por lo tanto, el contenido de mysqlstatus(command) no se actualiza después de la ejecución sin error - esto es, con éxito - de cualquier comando de la biblioteca MySQLTcl.
message El contenido de mysqlstatus(message) se actualiza después de la ejecución sin éxito de un comando cualquiera de la biblioteca MySQLTcl con una cadena que contiene un mensaje de error. Al igual que mysqlstatus(command), mysqlstatus(message) no se actualiza después de la ejecución sin error - esto es, con éxito - de cualquier comando de la biblioteca MySQLTcl.

Existe otro elemento en el array global mysqlstatus que no tiene relación con el manejo de errores:

elemento significado
nullvalue Cadena utilizada para representar el valor null cuando se muestran resultados de una consulta SQL.. El valor por defecto es cadena vacía y puede ser cambiado a la cadena que queramos.

Utilizando el array global mysqlstatus, el anterior fragmento de código se podría reescribir para que mostrase al usuario más información cuando se produjese un error al intentar establecer la conexión con el servidor de bases de datos:
10: catch {mysqlconnect -host $host -port $port
    -user $user -password $password} mysql_handler
11: if {$mysqltatus(code) != 0} {
12:     puts stderr $mysqlstatus(message)
13: } else {
14:     mysqlclose mysql_handler
15: }
Huelga decir que el array global mysqlstatus se puede utilizar para manejar más errores que los que se puedan producir al intentar establecer una conexión con el servidor de bases de datos.

 

Comandos básicos de la biblioteca MySQLTcl

En esta sección se muestra el uso de los comando más básicos de la biblioteca MySQLTcl con algunos ejemplos. Para mayor información, consulte la página man de la biblioteca MySQLTcl.
Los comandos cuyo uso se muestra en esta sección son los que aparecen en la siguiente tabla. Los parámetros están subrayados. Si un parámetro se muestra entre dos símbolos ?, significa que es opcional; el caracter | significa o lógico (or).

comando breve descripción
mysqlconnect ?option value ...? establece una conexión con un servidor de bases de datos; devuelve un handler que debe ser utilizado por otros comandos de la biblioteca MySQLTcl
mysqluse handle dbname asocia un handler MySQL con la base de datos especificada por dbname
mysqsel handle consulta_sql ?-list | -flatlist? envía una consulta SQL a una base de datos
mysqlexec handle sql_statement envía una consulta SQL distinta de select a una base de datos
mysqlclose handle cierra una conexión establecida a un servidor de bases de datos

 

mysqlconnect

El uso de este comando ya fue tratado en la sección "Estableciendo una conexión a una base de datos". Este comando acepta un parámetro extra no mostrado antes: -db. Con el parámetro -db se fija la base de datos que será objeto - o dicho de otra forma, base de datos asoaciada al handler - de futuras consultas SQL. Veamos un ejemplo:

% set mysql_handler [mysqlconnect -h 127.0.0.1 -p 3306 \\
  -user john_smith -password jsmith_password -db jsmith_database]
La base de datos objetivo de los comandos de la biblioteca MySQLTcl que utilicen el handler mysql_handler será la que tiene por nombre jsmith_database.

(Note que los caracteres \\ no son parte del comando; significan que que la siguiente línea también es parte del comando.).

 

mysqluse

Este comando permite cambiar la base de datos asociada del handler MySQL que este comando recibe como primer parámetro.

 

mysqlsel

Este comando envía una consulta SQL a la base de datos asociada al handler MySQL que este comando recibe como primer parámetro. Si el parámetro sql_statement no es una consulta SQL select, se producirá un error.

Hay un tercer parámetro opcional, que puede ser list o flat_list. Veamos con un ejemplo cómo afecta este parámetro a la salida de este comando. Supongamos que la base de datos asociada con el handler MySQL contiene una tabla como la mostrada a continuación:

id first_name last_ name phone
26 Karl Bauer 8245
47 James Brooks 1093
61 Roberto Castro Portela 6507

Utilizamos el comando mysqlsel para enviar una consulta SQL a la base de datos:

% mysqlsel $mysql_handler {select first_name, last_name from people order by id asc} -list
{Karl Bauer} {James Brooks} {Roberto {Castro Portela}}
% mysqlsel $mysql_handler {select first_name, last_name from people order by id asc} -flatlist
Karl Bauer James Brooks Roberto {Castro Portela}
En el primer ejemplo (-list parameter), el comando devuelve una lista cuyos elementos son, a su vez, listas. En el segundo ejemplo (-flatlist parameter), el comando devuelve una única lista cuyos elementos han sido concatenados en su totalidad.

¿Qué ocurre si el comando mysqlsel no recibe un tercer parámetro? En este caso, la salida del comando mysqlsel es el número de filas resultado de la consulta SQL:
% mysqlsel $mysql_handler {select first_name, last_name from people order by id asc}
3
 

mysqlexec

El comando mysqlexec envía una consulta SQL que no es select a la base de datos asociada con el handler que el comando recibe como primer parámetro. Si el parámetro sql_statement es una consulta SQL select no se producirá ningún error, pero tampoco el comando hará nada.

Supongamos que tenemos el ejemplo mostrado en la anterior subsección:

% mysqlexec $mysql_handler {delete from people where id=26}
1
% mysqlsel $mysql_handler {select first_name, last_name, phone from people order by id asc} -list
{James Brooks 1093} {Roberto {Castro Portela} 6507}
% mysqlexec $mysql_handler \\
  {insert into people (id, first_name, last_name, phone) values (58, "Carla", "di Bella", 8925)}
1
% mysqlsel $mysql_handler {select first_name, last_name, phone from people order by id asc} -list
{James Brooks 1093} {Carla {di Bella} 8925} {Roberto {Castro Portela} 6507}
Obviamente, se pueden hacer otras consultas SQL que no sean ni delete ni insert. Por ejemplo, es posible actualizar (update) el valor de una fila ya existente:
% mysqlexec $mysql_handler {update people set phone=3749 where first_name="James"}
1
% mysqlsel $mysql_handler {select first_name, last_name, phone from people order by id asc} -list
{James Brooks 3749} {Carla {di Bella} 8925} {Roberto {Castro Portela} 6507}
En caso de que no haya ningún error, el comando mysqlexec devuelve el número de filas afectdas por la consulta SQL non-select enviada a la base de datos.

 

mysqlclose

Como se vio con anteriodad, el comando mysqlclose cierra una conexión ya establecida a una base de datos. Este comando recibe un parámetro, el handler MySQL de la conexión que se quiere cerrar.

 

Otros comandos de la biblioteca MySQLTcl

La biblioteca MySQLTcl tiene más comandos que los vistos en esta sección. Estos comandos permiten obtener información sobre las propias bases de datos, transformar (escaping) cadenas para hacerlas aptas ser parte de consultas SQL, hacer consultas SQL anidadas... Una buena referencia es la propia página man de MySQLTcl, que es parte de la instalación de esta biblioteca.

 

Referencias

[1] una visión ligeramente escéptica sobre John K. Ousterhout y Tcl (en inglés):
http://www.softpanorama.org/People/Ousterhout/index.shtml

[2] tutorial sobre las expresiones regulares en Tcl (en inglés):
http://www.mapfree.com/sbf/tcl/book/select/Html/7.html

TclTutor es una aplicación gratuíta e interactiva para aprender Tcl (en inglés):
http://www.msen.com/~clif/TclTutor.html

documentación de MySQL, en varios formatos (HTML, PDF... ) e idiomas:
http://www.mysql.com/documentation/index.html



Contactar con el equipo de LinuFocus
© Diego Alberto Arias Prado
"some rights reserved" see linuxfocus.org/license/
http://www.LinuxFocus.org
Información sobre la traducción:
en --> -- : Diego Alberto Arias Prado <dariapra(at)yahoo.es>
en --> es: Diego Alberto Arias Prado <dariapra(at)yahoo.es>

2005-01-14, generated by lfparser_pdf version 2.51