Sitios
web básicos con respaldo de bases de datos, AOLserver,
Tcl, SQL
Se requieren aplicaciones de descompresión
de archivos, como Winzip® o StuffIt®,
para poder abrir los archivos .tar incluidos en el sitio
del curso. Para importar los archivos .csv del curso
es suficiente contar con cualquier herramienta de software.
Lectura para esta semana
Archivos de ayuda y de ejemplo
(si no realiza este curso en el MIT): 6916.ps1.tar (TAR)
(Este archivo .tar incluye 1 archivo .txt, 1 archivo
.adp, 1 archivo .csv y 10 archivos .tcl.)
Objetivos
Intentaremos comprobar si todos
los estudiantes conocen lo siguiente:
- Cómo iniciar sesión
en el servidor de desarrollo.
- Nociones básicas de
Tcl.
- Cómo ejecutar Tcl a
través de tclsh.
- Nociones de la utilidad de
plantillas ADP de AOLserver.
- Cómo crear, ejecutar,
probar y depurar una página .tcl.
- Cómo diseñar
una página .tcl que realice consultas en un
servidor externo.
- Nociones básicas de
SQL.
- Cómo realizar consultas
en Oracle a partir del shell con SQL*Plus.
- Cómo diseñar
una página .tcl que realice consultas en Oracle.
- Cómo personalizar servicios
web emitiendo y leyendo cookies.
- Cómo leer y escribir
datos en XML.
- Cómo utilizar SQL*Loader.
Para realizar este primer boletín
de problemas deberá aprender a utilizar muchos
programas nuevos de software, por lo que es necesario
que se familiarice con estos programas cuanto antes:
prevea dedicar al menos dos o tres sesiones. No entrañan
gran dificultad, pero queremos que sea capaz de entender
la mecánica de Tcl, SQL y cómo ejecutar
el servidor Web.
Principios básicos
de Tcl
Principios básicos de SQL*Plus
Trabajo con AOLserver y Oracle
Personalización de servicios web
con cookies
Compartición de datos con XML
El vasto mundo de Oracle
Arquitectura de la información e
interfaz de usuario
Principios básicos de
Tcl
Comience por leer Using
the LCS Web/db Computing Facility y siga las
instrucciones para iniciar sesión en el servidor.
Ejercicio 1: Ejecutar Tcl
desde el shell
Ejecute Emacs. Escriba "m-x shell"
para obtener un shell de Unix®. Escriba
"tclsh" para iniciar el programa del shell de
Tcl. Defina un procedimiento de Fibonacci recursivo
en Tcl. Ejecútelo y pruébelo.
Sugerencia: si escribe programas
Tcl de más de dos o tres líneas, tal vez
le resulte más cómodo escribir el código
en un búfer Emacs independiente (definido en
modo tcl) y, después, cortar y pegar desde ahí
en el búfer del shell de Tcl.
Escriba la información
de la versión de tcl en la línea de comandos
de tclsh para comprobar que está ejecutando Tcl
8.2, la misma versión que está compilada
en AOLserver.
Ejercicio 2: Ejecutar Tcl
desde una página (casi) HTML
Consulte el archivo two-plus-two.adp (HTM) y
su fuente (TXT).
Se trata de un ejemplo de la utilidad de plantillas
ADP de AOLserver.
Aumente la página de tal
forma que (1) agregue un acuario suramericano Cichlid
de 4.000 $ como opción, (2) utilice un procedimiento
de constructores para crear cada elemento del acuario
(que no se limite simplemente a una lista de llamadas),
(3) agregue un elemento al acuario para el número
de tipos de acuarios que se instalarán, (4) utilice
procedimientos para extraer el tipo, el coste y la cantidad
de un elemento del acuario (que no se limite simplemente
a un índice de llamadas), (5) imprima los subtotales
que dependen de la cantidad y el total al final.
Ejercicio 3: Páginas
Tcl sencillas
Desde el navegador web de su equipo
local, vaya a la página
http://yourvirtualserver/psets/ps1/simple-tcl-page.tcl.
Utilizando Emacs en el servidor, analice el código
fuente de esta página en /web/yourvirtualserver/www/psets/ps1/simple-tcl-page.tcl.
Observe también el código fuente del formulario
ubicado en /web/yourvirtualserver/psets/ps1/simple-tcl-page-2.tcl.
(Si no dispone de estos archivos, descárguelos
del archivo 6916.ps1.tar (TAR) (Este
archivo .tar incluye 1 archivo .txt, 2 archivos .adp,
1 archivo .csv y 10 archivos .tcl.) y colóquelos
en /web/yourvirtualserver/www). Tenga en cuenta cómo
se utiliza Tcl para leer las variables del formulario.
Intente abrir el formulario un par de veces desde su
navegador. Ahora, depure la expresión común
de simple-tcl-page-2.tcl de tal forma que gestione correctamente
los nombres "Tammy Faye Baker" y "William H. Gates III".
Sugerencia 1: es más sencillo
si no intenta hacer esto en un regexp. Recurra a if
then else if then else if...
Sugerencia 2: regexp tiene un
"efecto secundario". Si utiliza una sentencia
con varias cláusulas, no olvide agrupar las llamadas
a regexp entre corchetes para que no se calculen todas
de forma inmediata.
Ejercicio 4: Páginas
Tcl que realizan consultas en servidores externos
Desde el navegador web de su equipo
local, vaya a Seeq.
Lea el análisis de este programa en el
Capítulo 10 de Philip and Alex's
Guide to Web Publishing. Tomando dicho programa
como modelo, cree un nuevo servicio web que tome el
ISBN de un libro desde un formulario y que, a continuación,
utilice
ns_httpget para realizar varias consultas en librerías
en línea para encontrar información de
precios y existencias, y muestre los resultados en una
tabla HTML. Guarde el programa en los archivos llamados
/web/yourvirtualserver/www/psets/ps1/books.tcl y books-2.tcl
de tal forma que el resto de usuarios puedan tener acceso
al servicio en la web.
Recomendamos que realice las consultas
en empresas como wordsworth.com, barnesandnoble.com
o www.1bookstreet.com (amazon.com suele responder con
un mensaje de redirección 302 si el cliente no
otorga un ID de sesión en la consulta). El programa
deberá ser sólido ante tiempos de espera,
errores en sitios externos y problemas de red. Puede
conseguir esta solidez agrupando una sentencia de captura
Tcl en la llamada a ns_httpget. Pruebe el programa con
los siguientes números de ISBN: 0385494238, 0062514792,
0140260404, 0679762906.
Calificación adicional:
¿De cuál de los siguientes libros se ha
extraído esta cita? (en inglés)
"The obvious mathematical breakthrough
would be development of an easy way to factor large
prime numbers."
Es buen momento para tomarnos
un descanso.
Principios
básicos de SQL*Plus
Inicie de nuevo Emacs (se ha tomado
un descanso, ¿verdad?) e inicie un shell
de Tcl tal como lo hizo anteriormente (primero "M-x
shell" y después "tclsh"). Escriba "M-x rename-buffer"
para cambiar el nombre del shell a "tcl-shell".
Escriba "M-x shell" para obtener un nuevo shell
de Unix®. Cambie el nombre de este búfer
a "sql-shell". En el shell de SQL, escriba "sqlplus"
para iniciar SQL*Plus, el cliente del shell de
Oracle. Se recomienda trabajar utilizando dos shell:
uno para Tcl y otro para SQL.
Ejercicio 5: Comunicación
con Oracle desde el shell
En SQL*Plus, escriba lo siguiente
en una tabla para llevar un seguimiento de las clases
de este semestre:
create table my_courses ( course_number
varchar(20));
Tenga en cuenta que debe terminar
los comandos de SQL con punto y coma en SQL*Plus. Éstos
no forman parte del lenguaje SQL y no debe utilizarlos
al escribir SQL en los programas Tcl de AOLserver.
Inserte varias filas, por ejemplo,
insert into my_courses (course_number)
values ('6.916');
Envíe los cambios:
commit;
Compruebe el resultado:
select * from my_courses;
Una de las múltiples ventajas
de utilizar un RDBMS es la persistencia. Todo lo que
cree seguirá ahí incluso cuando cierre
la sesión. Normalmente, se trata de una ventaja,
pero tal vez quiera limpiar el registro una
vez terminado este experimento:
drop table my_courses;
Salga de SQL*Plus escribiendo
"c-c c-d".
Ejercicio 6: Páginas
Tcl que se comunican con Oracle
Consulte el archivo /web/yourvirtualserver/www/psets/ps1/quotations.tcl,
que es el código fuente de una página
que muestra citas almacenadas en la base de datos de
Oracle. Si visita esta página desde su navegador
web, debería obtener un error. El motivo de este
error es que el programa llama a un procedimiento que
no existe: ad_header ("Encabezado ArsDigita"). Puede
confirmar sus sospechas utilizando Emacs para leer /home/nsadmin/log/yourvirtualserver-error.log,
ubicación en la que AOLserver registra todos
los avisos y problemas.
Para que AOLserver cargue las
definiciones del procedimiento en el inicio del servidor,
debe colocar archivos .tcl en la biblioteca Tcl privada
del servidor: /web/yourvirtualserver/tcl/. Cree un archivo
llamado "ps1-defs.tcl" en este directorio y defina los
siguientes procedimientos Tcl:
ad_header page_title --
devuelve etiquetas HTML, HEAD, TITLE y BODY con el argumento
encerrado entre etiquetas TITLE
ad_footer -- devuelve una cadena
que cerrará las etiquetas BODY y HTML
Vuelva a cargar la página
quotations.tcl y obtendrá... ¡el mismo
error! AOLserver no sabe que ha agregado un archivo
a la biblioteca privada; esto sólo se comprueba
en el inicio del servidor. Vaya a un shell de
Unix® y escriba "restart-aolserver yourservername"
(ésta es la acción definitiva: aniquila
el proceso
Unix® del servidor de tal forma que Unix®
reinicie AOLserver automáticamente). Si no se
restablece el reinicio al escribir "Killing 10234" o
cualquier otro ID de proceso, sabrá que no ha
conseguido hacerlo correctamente (tal vez haya cometido
algún error tipográfico al escribir el
nombre del servidor).
Vuelva a cargar la página
quotations.tcl y obtendrá... ¡un error
sensiblemente distinto! El programa está intentando
realizar una consulta en una tabla que no existe: quotations
(citas).
Vuelva al shell sql y reinicie
SQL*Plus. Copie la definición de la tabla en
los comentarios situados en la parte superior del archivo
quotations.tcl e introduzca esta definición en
Oracle. Regrese al navegador web y vuelva a cargar la
página con la que anteriormente obtenía
un error. Ahora sí debería funcionar,
aunque la tabla de citas estará vacía.
Utilice el formulario de la página
web para agregar manualmente la siguiente cita en la
categoría correspondiente que decida: "640K ought
to be enough for anybody" (Bill Gates). Tenga en cuenta
que sería interesante que en la tabla existiese
una columna para registrar la fecha de la cita (1981),
pero hemos limitado al máximo la complejidad
del modelo de datos a propósito.
Vuelva a SQL*Plus y seleccione
* en la tabla para ver la cita registrada. El formato
tan horroroso se debe a que ha declarado la columna
de la cita con una longitud de 4000 caracteres.
En SQL*Plus, inserte una cita
con código manual de SQL (si le da pereza, puede
cortar y pegar algo de SQL desde el registro de errores
de AOLserver; todas las sentencias de SQL que AOLserver
envía a Oracle se registran aquí). Ahora,
vuelva a cargar la URL de quotations.tcl desde el navegador
web. Si no ve la nueva cita es porque no escribió
COMMIT; en SQL*Plus. Ésta es una de las características
más importantes de un sistema de administración
de bases de datos relacionales: los usuarios conectados
simultáneamente no pueden ver las transacciones
incompletas del resto.
Cargar tablas desde archivos
.csv
Ha llegado el momento de precargar
la base de datos de citas con material interesante.
Cargue /web/yourvirtualserver/www/psets/ps1/quotations.csv
en Emacs y eche un vistazo al formato del archivo (es
el formato habitual que puede obtener en cualquier programa
de hojas de cálculo). Con SQL*Loader (consulte
el oraejercicio 1 más adelante), cargue estos
datos en la tabla de citas.
Trabajo
con AOLserver y Oracle
Veamos cómo acceder a la
base de datos desde programas Tcl. La idea básica
es que AOLServer incluye una abstracción de datos
denominada conjunto (set), definida por las
operaciones enumeradas en la API ns_set. Un conjunto
es una colección de pares (clave, valor), concepto
que debería resultarle familiar, ya que se estudió
en el curso 6.001.
Al seleccionar desde una tabla con ns_db select se devuelve
un identificador para un conjunto, cuyas claves son
los nombres de las columnas seleccionadas. Las llamadas
siguientes con
ns_db getrow rellenarán los valores de este conjunto
con valores de filas sucesivas seleccionadas. Por ejemplo,
supongamos que obtiene un identificador de conjunto
al seleccionar la siguiente tabla con
ns_select:
| Tolstoy |
Anna Karenina |
| Steinbeck |
Grapes
of Wrath |
| Greenspun |
Guide
to Web Publishing |
A continuación, tras la
primera llamada a ns_db getrow, el conjunto será:
{{writer Tolstoy} {book "Anna
Karenina"}}
Tras la segunda llamada a ns_db
getrow, el conjunto será
{writer Steinbeck}
{book "Grapes of Wrath"}}
Y tras la tercera llamada, el
conjunto será:
{{writer Greenspun}
{book "Guide to Web Publishing"}}
Los programas de los archivos
quotations.tcl y quotation-add.tcl ilustran estas ideas.
Le merecerá la pena estudiarlos bien hasta que
entienda cómo funcionan, ya que serán
muchos los programas de este tipo que tendrá
que realizar durante el semestre.
Ejercicio 6a: Eliminación
de la tabla de bloqueo mediante una secuencia
Lea lo referente al objeto de
la base de datos de secuencias de Oracle en la sección
Data
Modeling
(Modelado de datos). Mediante la creación de
una secuencia, debería poder editar el archivo
quotation-add.tcl para:
- Eliminar la tabla de bloqueo.
- Eliminar la transacción
de inicio y finalización (ya no va a unir varias
sentencias SQL).
- Generar una clave para la nueva
cita dentro de la sentencia INSERT.
Ejercicio 7: Mejora de la
interfaz de usuario para la introducción de datos
Vuelva a la página principal
de quotations.tcl y modifíquela de tal forma
que la introducción de categorías se realice
a través de un cuadro de selección de
las categorías existentes (deberá utilizar
el comando "SELECT DISTINCT" de SQL). Para las nuevas
categorías, proporcione un cuadro de entrada
de texto alternativo denominado "new category"
(nueva categoría). No olvide modificar quotation-add.tcl
para que pueda detectar la definición de las
nuevas categorías.
Ejercicio 8: Búsquedas
Agregue un breve formulario en
la parte superior de quotations.tcl que acepte una palabra
de consulta sencilla del usuario. Diseñe un objetivo
para este formulario que devuelva todas las citas que
contengan la palabra especificada. La búsqueda
deberá realizarse con distinción entre
mayúsculas y minúsculas y también
buscará en la columna de autores. Sugerencia:
similar a '%foo%'.
Personalización
de servicios web con cookies
Nos gustaría que diseñase
un sistema para implementar la personalización
de la base de datos de citas en función de cada
usuario. En general, el objetivo sería:
- Un usuario puede "aniquilar"
una cita y conseguir que no aparezca nunca en la página
principal o en la página de búsquedas.
- Aniquilar una cita es una acción
permanente y no queda cancelada al cerrar o reiniciar
el navegador.
- Las citas aniquiladas por un
usuario no afectan a lo que el resto de usuarios pueden
ver.
- Los usuarios pueden borrar
sus personalizaciones y ver toda la base de datos
de citas otra vez
haciendo clic en el vínculo "borrar mi personalización"
de la página principal. Este vínculo
sólo debe aparecer si el usuario ha personalizado
la base de datos de citas.
Puede personalizar los servicios
web con ayuda de las mágicas cookies.
Una cookie emitida por el servidor guía
al navegador para que almacene datos en el equipo. Para
emitir una cookie, el servidor incluye una línea
como ésta:
Set-Cookie: cookie_name=value;
path=/ ; expires=Fri, 01-Jan-2010 01:00:00 GMT
en el encabezado HTTP enviado
al navegador. En este caso, cookie_name es el nombre
de la cookie y "value" es el valor
asociado que puede contener cualquier carácter
excepto un punto y coma (reservado para finalizar la
cookie). La ruta de acceso especifica a qué
URL del servidor se aplica la cookie. Si la ruta
se designa con una barra (/), se incluirán todas
las URL del servidor.
Una vez que el navegador ha aceptado
una cookie del servidor, incluirá su nombre
y su valor como parte de las peticiones HTTP cada vez
que solicite al servidor una URL aplicable. Sus programas
Tcl pueden leer esta información gracias a la
API AOLServer
[ns_set get [ns_conn
headers] Cookie]
Una vez cumplida la fecha de
caducidad, el navegador ya no enviará la información
de la cookie. El servidor también puede
emitir cookies sin fecha de caducidad especificada,
en cuyo caso, la cookie no sería permanente:
el navegador la utilizaría únicamente para
esa sesión.
Puede ver un ejemplo sobre la
emisión y lectura de cookies en la URL
http://yourvirtualserver/psets/ps1/set-cookies.tcl y
analizar el Tcl para el archivo y las URL asociadas
check-cookies.tcl y expire-cookies.tcl. Observe el modo
en que expire-cookies se deshace de las cookies
volviendo a emitirlas con una fecha de caducidad ya
pasada.
Referencia: la información
sobre las cookies mágicas está
disponible (en inglés) en Persistent
Client State HTTP Cookies (Cookies HTTP persistentes
de estado de cliente).
Ejercicio 9
Implemente el sistema de citas
personalizado descrito anteriormente.
Sugerencia 1: es posible crear
este sistema utilizando un identificador de cookies
para el navegador y conservando el conjunto de citas
aniquiladas de Oracle. No obstante, si no pretende permitir
que los usuarios inicien sesión y diseñen
su perfil, no tiene mucho sentido conservar estos datos
en el servidor. De hecho, al conservar los ID de las
citas aniquiladas en las cookies del navegador
de los usuarios, habrá conseguido el santo grial
de los investigadores de sistemas de administración
de bases de datos académicas: ¡una base
de datos distribuida!
Sugerencia 2: esto no está
estrictamente relacionado con las cookies, pero
puede hacer que una de ellas contenga espacios. Tcl
almacena una lista de enteros internamente como números
separados por espacios. Así, la forma más
sencilla de almacenar las citas aniquiladas es en forma
de lista separada por espacios.
Sugerencia 3: no filtre las citas
en Tcl; esto suele ser un indicio de programación
incompleta al consultar más datos de Oracle de
los que se podrán mostrar al usuario final. SQL
es un lenguaje de consulta muy potente. Puede utilizar
la función NOT IN para excluir una lista de citas.
¿Qué tal si nos
tomamos otro descanso?
Compartición
de datos con XML
Tal como ha aprendido anteriormente
al realizar consultas en tiendas de libros, no es habitual
que los datos de la web estén formateados para
su uso en programas informáticos. En teoría,
los usuarios que desean intercambiar datos en la web
pueden cooperar utilizando XML, una norma de 1997 del
Web Consortium. En la práctica, casi nadie utiliza
XML actualmente (1999). Le tranquilizará saber
que para resolver este boletín de problemas podrá
colaborar con sus compañeros: el objetivo final
es realizar consultas en su base de datos y exportarlas
en un formato estructurado que el resto de estudiantes
pueda leer.
Para poder colaborar, necesitará:
- Una URL consensuada en el servidor
de todos los integrantes para obtener la base de datos
de citas: "/quotations-xml.tcl"
- Un formato consensuado para
las citas.
Daremos formato a las citas con
XML, que no es más que una convención
de notación para describir datos estructurados.
Las estructuras de XML constan de cadenas de datos encerradas
en etiquetas similares a las HTML con la forma <foo>
y </foo>, que describen qué tipo de datos
deben ser.
A continuación, se muestra
un ejemplo informal para estudiar la estructura que
utilizaremos en las citas:
<quotations>
<onequote>
<quotation_id>1</quotation_id>
<insertion_date>1999-02-04</insertion_date>
<author_name>Bill
Gates</author_name>
<category>Computer
Industry Punditry</category>
<quote>640K ought to be
enough for anybody.
</quote>
</onequote>
<onequote>
... otra fila de la tabla de
citas ...
</onequote>
... algunas filas más
</quotations>
Tenga en cuenta que hay una
etiqueta independiente para cada columna de nuestro modelo
de datos de SQL:
<quotation_id>
<insertion_date>
<author_name>
<category>
<quote>
También hay una etiqueta
"empaquetadora" que identifica cada fila como una
estructura <onequote> y un empaquetador externo
que identifica una secuencia de estructuras <onequote>
como un documento de <quotations>.
Creación de una DTD
Podemos dar una descripción
formal de nuestra estructura XML (y no un ejemplo informal)
por medio de una definición de tipo de documento
de XML (Document Type Definition - DTD).
Nuestra DTD comenzará con
la definición de la etiqueta "quotations"
(citas):
<!ELEMENT quotations
(onequote)+>
Esta sentencia dice que el elemento
"quotations" debe contener al menos una instancia
de "onequote", pero puede contener más
de una. Ahora debemos decir qué conforma un elemento
"onequote" válido:
<!ELEMENT onequote
(quotation_id,insertion_date,author_name,category,quote)>
Esta sentencia dice que los
subelementos como "quotation_id" deben aparecer
exactamente una vez y en el orden especificado. Ahora
debemos definir un elemento XML que realmente no contenga
sólo otros elementos XML:
<!ELEMENT quotation_id
(#PCDATA)>
Esta sentencia dice que todo
lo que se encuentre entre <quotation_id> y </quotation_id>
deberá interpretarse como caracteres brutos y no
como elementos con más etiquetas (PCDATA quiere
decir "datos de caracteres analizados").
Ésta es nuestra DTD completa:
<!-- quotations.dtd -->
<!ELEMENT quotations
(onequote)+>
<!ELEMENT onequote (quotation_id,insertion_date,author_name,category,quote)>
<!ELEMENT quotation_id (#PCDATA)>
<!ELEMENT insertion_date
(#PCDATA)>
<!ELEMENT author_name
(#PCDATA)>
<!ELEMENT category (#PCDATA)>
<!ELEMENT quote (#PCDATA)>
Le resultará de gran utilidad...
Bueno, en realidad esta DTD no le servirá de
nada para realizar esta parte del boletín de
problemas. Lo único para lo que las DTD son realmente
útiles es para alimentar analizadores de XML,
ya que con ellas podrá marcar automáticamente
un documento XML. Para implementar la página
quotations-xml.tcl, sólo necesitará estudiar
el ejemplo informal.
Ejercicio 10: Generación
de XML
Cree un programa Tcl que realice
consultas en la tabla de citas, genere un documento
XML en el formulario anterior y lo devuelva al cliente
con una "aplicación/xml" de tipo MIME.
Inserte el programa en un archivo quotations-xml.tcl
de tal forma que los usuarios puedan recuperar los datos
al visitar la URL.
Para que pueda comenzar, le ofrecemos
el archivo /psets/ps1/example-xml.tcl. Al solicitar
esta URL con un navegador web debería poder guardar
el documento en un archivo local y, a continuación,
analizarlo con un editor de texto en su equipo local.
(Asumimos que no ha definido ningún comportamiento
especial de su navegador para la aplicación/xml
de tipo MIME.) Las diferencias entre nuestro ejemplo
y su programa son que necesitará generar un documento
que contenga toda la tabla y necesitará hacerlo
sobre la marcha.
Ejercicio 11: Importación
de XML
Diseñe un programa para
importar una base de datos de citas desde la página
de salida XML de otro estudiante (si ha realizado el
ejercicio 9 pero sus compañeros aún no,
tal vez sea ésta una buena oportunidad para que
se esfuercen). Su programa deberá:
- Obtener el archivo /psets/ps1/quotations-xml.tcl
desde la base de datos de otro estudiante utilizando
ns_httpget
- Analizar el archivo y convertirlo
en registros que, a su vez, deberá convertir
en campos.
- Si el autor y el contenido
de la cita de un servidor externo coincide exactamente
con los de su propia base de datos, omítalos;
de lo contrario, inserte la cita en su base de datos
con un nuevo identificador quotation_id (recuerde
que no quiere que existan conflictos entre las claves
del servidor externo y las que ya existen en su base
de datos).
Sugerencia: tal vez desee definir
una tabla temporal utilizando el comando create table
quotations_temp as select * de las citas y, después,
liberarlo tras la depuración. Debería
utilizar DoubleApos al presentar los datos en Oracle
para las comparaciones.
En lugar de contar con un vínculo
en un programa de 100.000 líneas escrito en C
(o un programa Lisp de 5.000 líneas) que analice
documentos XML basados en una DTD, hemos optado por
la simplicidad y hemos predefinido un analizador en
Tcl que recoja esta DTD concreta para citas. El procedimiento
es parse_all (TXT) (deberá
instalar este archivo en la biblioteca Tcl privada de
su servidor, /web/yourvirtualserver/tcl/, para poder
llamar a esta función desde las páginas
.tcl y .adp). El procedimiento parse_all toma una estructura
de citas XML como argumento y lo devuelve a una lista
Tcl mostrando las secciones y subsecciones de la estructura.
Para ver un ejemplo del formato, utilice su navegador
para ir a la página http://yourvirtualserver/psets/ps1/xml-parse-test.tcl.
Nota: estos ejercicios están
pensados para que se familiarice con XML. En la mayoría
de los casos, el procesado de XML complejo debe realizarse
dentro de Oracle utilizando las bibliotecas de Java®.
Ejercicio 12: Seguimiento
de la popularidad de un libro
Los escritores neuróticos
consultan amazon.com constantemente para ver qué
puesto ocupan sus libros en la lista de ventas. El hecho
de que estas cifras se actualicen cada hora únicamente
contribuye a que este hábito se convierta en algo
más destructivo. Diseñe un programa para
realizar el seguimiento de la obra de un escritor realmente
neurótico (ISBN: 1558605347). Necesitará:
- Definir una tabla de Oracle
en la que incluir el ISBN, la fecha y la hora y el
puesto en la lista de ventas.
- Escriba un procedimiento que
obtenga la página de Amazon, extraiga REGEXP
de la lista de ventas y lo coloque en la tabla de
Oracle.
- Utilice la llamada a la API
AOLserver ns_schedule_proc para programar la ejecución
de procedimiento cada hora.
- Diseñe una página
.tcl para poder comparar la popularidad a lo largo
del tiempo.
Uno de los aspectos interesantes
de Amazon es que a menudo pierden el control de su grupo
de servidores y su base de datos (escriben mucho código
en C y los descuidos del programador pueden llevar a
un fallo catastrófico de todo el servicio). Deberá
crear su sistema de tal forma que registre: (a) las
horas en las que no es posible acceder a amazon.com
y (b) en cuáles de esas horas la página
ofrecida contiene la cadena "Our store is closed temporarily
for scheduled maintenance" (Nuestro establecimiento
está cerrado temporalmente por motivos de mantenimiento
programado). A veces este mensaje se obtiene en
días de diario en los que, definitivamente, no
debería haber ningún mantenimiento programado.
Ejercicio 13: Cómo
convertirse en un diseñador de gráficos
¿Por qué imprimir
una tabla con los libros más populares si podemos
imprimir un gráfico? Está a punto de descubrir
las maravillas de los GIF de píxel único
y de las etiquetas WIDTH y HEIGHT. Coloque el software en
el directorio Tcl privado del servidor (/web/nombre_del_servidor/tcl/).
Lea la documentación y, a continuación,
escriba el código para generar un gráfico
bonito de los datos del ejercicio 12.
Tenga en cuenta que se está
adentrando en el kit de herramientas de ArsDigita Community
System, el software que le mantendrá bien ocupado
en el boletín de problemas 2.
El vasto
mundo de Oracle
Vamos a cambiar de tema ahora
y adentrarnos en una parte del boletín de problemas
pensada para que sepa más de Oracle y SQL.
Oraejercicio 1: SQL*Loader
- Cree un archivo separado por
tabulaciones en Emacs que contenga cinco líneas,
cada una con el símbolo del valor que más
le guste, el número de acciones en propiedad
y la fecha de adquisición (con el formato MM/DD/AAAA).
- Cree una tabla de Oracle
en la que incluir estos datos:
create table my_stocks
(
symbol varchar(20) not null,
n_shares integer not null,
date_acquired date not null
);
- Utilice el comando sqlldr para
invocar SQL*Loader y convertir el archivo separado
por tabulaciones
en la tabla my_stocks (consulte la página 1183
de Oracle8: The Complete Reference y
la documentación oficial de Oracle).
Oraejercicio 2: Copia de datos
entre tablas
Este ejercicio existe porque
nos hemos dado cuenta de que, al afrontar la tarea de
mover datos entre tablas, los programadores arrastraban
los datos de SQL*Net desde Oracle hasta AOLserver, los
manipulaban en Tcl y, después, los devolvían
a Oracle a través de SQL*Net. ¡Así
no se hace! SQL es un lenguaje muy potente y no hay necesidad
de utilizar otras herramientas si lo que se quiere es
mover datos dentro de Oracle.
- Utilizando una sola sentencia
de SQL, cree una tabla llamada stock_prices (precios
de valores) con tres columnas: symbol (símbolo),
quote_date (fecha de valor), price (precio). Tras
esta sentencia, deberá crear la tabla y rellenarla
con una fila por símbolo en my_stocks (mis
valores). Las columnas de fecha y precio deberán
contener la fecha actual y el precio nominal. Sugerencia:
seleccione symbol y sysdate como quote_date (fecha
de cita) y 31.415 como precio para my_stocks;.
- Cree una nueva tabla:
create table newly_acquired_stocks (
symbol varchar(20) not null,
n_shares integer not null,
date_acquired date not null
);
- Utilizando una sentencia simple
insert into .. select ... (con una cláusula
WHERE según sus datos de muestra), copie aproximadamente
la mitad de las filas de my_stocks en newly_acquired_stocks
(valores de reciente adquisición).
Oraejercicio 3: JOIN
Con una sentencia simple de SQL
(JOIN), una my_stocks y stock_prices (precio de los
valores), genere un informe que muestre el símbolo,
el número de acciones, el precio por acción
y el valor actual.
Oraejercicio 4: OUTER JOIN
Inserte una fila en my_stocks.
Realice la consulta del oraejercicio 3. Tenga en cuenta
que el nuevo valor no aparecerá en el informe.
Esto se debe a que los ha unido (JOIN) con la limitación
de que el símbolo aparezca en las dos tablas.
Modifique la sentencia para que
utilice un OUTER JOIN y poder así obtener un
informe completo de todos los valores, pero no obtener
la información del precio si no hay ninguno disponible.
Oraejercicio 5: PL/SQL
Inspirándonos en los
métodos de Wall Street para evaluar las empresas
de Internet, hemos desarrollado nuestro propio método
de evaluación para este boletín de problemas:
un valor se evalúa como la suma de caracteres ASCII
que conforman su símbolo. (Tenga en cuenta que
los estudiantes que utilizan minúsculas para representar
símbolos tendrán informes con valores mayores
que los que utilicen siempre símbolos escritos
en mayúsculas; "IBM" sólo tiene un valor
de 216 $ mientras que "ibm" tiene un valor de 312 $).
- Defina una función PL/SQL
que tome un símbolo de comercio y su argumento,
y que devuelva el valor del valor (sugerencia: la
función ASCII incorporada en Oracle le será
de gran ayuda).
- Con una sentencia simple UPDATE,
actualice stock_prices para definir el valor de cada
valor en el resultado obtenido por este procedimiento
PL/SQL.
- Defina una función PL/SQL
que no tome ningún argumento y que devuelva
el valor agregado del informe (nº_acciones *
precio de cada valor). Deberá definir su JOIN
a partir del oraejercicio 3 (más arriba) como
un cursor y, a continuación, recurrir a la
utilidad FOR LOOP del cursor PL/SQL. Sugerencia: cuando
haya terminado, puede ejecutar este procedimiento
desde SQL*Plus con select portfolio_value() from dual;.
Sugerencia de SQL*Plus: aunque
esto no forma parte del lenguaje SQL, seguro que le resultará
útil escribir "/" después de las definiciones
PL/SQL si pretende insertarlas en Oracle a través
de la aplicación SQL*Plus. A no ser que escriba
un código perfecto, también le vendrá
bien conocer el comando "show errors" (mostrar
errores) de SQL*Plus. Si desea obtener información
completa sobre este tipo de oscurantismo, consulte la
referencia (en inglés) SQL*Plus User's Guide
and Reference.
Oraejercicio 6: Compre más
a los ganadores
En vez de compartir los beneficios
con los ganadores: ¡compre más!
- Utilice SELECT AVG() para deducir
el precio medio de sus participaciones.
- Utilizando una sentencia simple
INSERT con SELECT, duplique sus participaciones en
todas las acciones cuyo precio esté por encima
de la media (con date_acquired definida en sysdate).
Vuelva a realizar la consulta
del oraejercicio 4. Observe que, en ocasiones, tendrá
dos filas para el mismo símbolo. Si lo que realmente
le interesa es la posición actual, deberá
obtener un informe con una fila por símbolo como
máximo.
- Utilice una consulta SELECT
... GROUP BY desde my_stocks para generar un informe
de símbolos y el total de las acciones.
- Utilice una consulta SELECT
.. GROUP BY en combinación (JOIN) con stock_prices
para generar un informe de símbolos y el valor
total de cada uno de ellos.
- Utilice una consulta SELECT
.. GROUP BY .. HAVING para generar un informe de símbolos,
el total de las acciones y el valor total de cada
símbolo restringido a los símbolos
que tengan, al menos, dos bloques de acciones (esto
es, los "ganadores").
Oraejercicio 7: Encapsule
las consultas con una vista
Con la consulta final anterior,
cree una vista llamada stocks_i_like (acciones que me
gustan) que encapsule la consulta final.
Arquitectura
de la información e interfaz de usuario
Ya tiene una tabla de base de
datos llena de datos de valores. Hay un par de formas
de ofrecer una interfaz web a estos datos. El desarrollador
web fracasado presentaría una página con
opciones para recuperar los datos de los valores:
- Mostrar adquisiciones recientes.
- Mostrar mejores actores.
- Mostrar valores más
altos.
- Mostrar todo el informe.
Lo importante es que el usuario
no vea nada en la primera página. Por tanto, desde
el punto de vista de la presentación de la información,
la primera página no sirve.
Una alternativa es mostrar al
usuario una tabla con participaciones en la página
principal, con un buen subconjunto de datos predeterminados,
y facilitar botones para ajustar lo que se incluye en
la visualización. ¿Qué tipo de
botones? Podría contar con los descritos más
arriba, además de cualquier otra vista que el
creador del sitio y los usuarios consideren necesaria.
Suponga, no obstante, que puede organizar los botones
en dimensiones ortogonales. Si puede hacerlo simplemente
con un conjunto de "deslizadores dimensionales",
el usuario tendrá ante sí muchas opciones.
Por ejemplo, el sistema de supervisión
de tickets de ArsDigita se utiliza para almacenar informes
de errores y solicitudes de funciones. Se utilizan las
siguientes dimensiones:
- Involucración del usuario
conectado (valores: mío/de todos).
- Estado del ticket (valores:
abierto/+retrasado/+cerrado).
- Fecha del ticket (valores:
ayer/la semana pasada/el mes pasado/todos).
Observe que, aunque éstas
se han modelado como dimensiones continuas, el usuario
no obtiene
deslizadores continuos. El usuario selecciona un punto
discreto entre varios en cada dimensión.
Esta interfaz es compatible con el navegador Netscape
1.1 y ofrece al usuario 24 opciones en total. Aun
así, en vez de ver 24 opciones en una larga lista,
el usuario ve una línea en la parte superior del
navegador con nueve botones organizados con lógica
en tres dimensiones.
Si no bastase con estas 24 opciones,
el sistema de supervisión de tickets permite
que el usuario
reorganice la tabla en función de cualquiera
de las columnas haciendo clic en el encabezado de la
columna
en cuestión.
Intente crear algo parecido con
su informe de valores. Deberá obtener una página
.tcl que muestre el contenido de my_stocks y stock_prices.
Incluya botones en la parte superior (sugerencia: TABLE
WIDTH=100% y TD ALIGN= RIGHT le vendrán muy bien)
para las siguientes dimensiones:
- Fecha de las adquisiciones
(en la semana pasada/mes pasado/año pasado/todos).
- Valor de la participación
(más del 10% del informe total/más del
2%/todos).
Permita que los usuarios puedan
ordenar cualquiera de las columnas que aparecen (sugerencia:
export_ns_set_vars en $SERVER_HOME/tcl/00-ad-utilities.tcl
le será de ayuda, sobre todo por el argumento exclusion_list),
por ejemplo, símbolo, número de acciones,
precio por acción, valor de la participación.
Puede crear esto desde el principio
o utilizar las llamadas de la API del kit de herramientas
de ArsDigita Community System como bloque principal.
Quién ha redactado
esto y cuándo
Este boletín de problemas
lo escribieron Philip Greenspun y Hal Abelson
en enero de 1999. El copyright es
de 1999 pero puede reutilizarse siempre y cuando se
haga mención a los autores originales.
|