martes, julio 26, 2005

Api de Base de datos en OpenACS 5.1 (Cuarta Parte) Otras funciones

Completaremos la Api de BD de openAcs con la mención a otras funciones de interés que serán a veces necesarias para dar funcionalidad a nuestras aplicaciones.
Su uso es en la mayoria de las veces practicamente identico en el caso de las funciones que devuelven el resultado de una busqyeda asi que tan solo haremos mención a su sintaxis.

db_null -> Es un valor que representa el valor NULL, OpenACS necesita este valor para proporcionar independencia
sobre la base de datos.
Así utilizaremos este valor en vez del null nativo de nuestro gestor de base de datos.

db_type -> Devuelve el Gestor de base de datos que está siendo utilizado.

db_version -> Nos proporciona la versión del Gestor de BD utilizado.

db_name -> Nos dá el nombre de la Base de datos del Sistema OpenACS.

db_nexval -> Proporciona el siguiente valor de una secuencia de nuestra base de datos.
Su uso es el siguente: db_nexval secuencia.
Por ejemplo supongamos que tenemos una secuencia llamada numero_factura y queremos generar el valor siguiente:
set nuevo_numero= db_nextval numero_factura

db_resultrows -> Nos devuelve el numero de filas afectadas (en una operación de actualizacion,borrado, insercion,etc) o devueltas en
en una sentencia sql anterior.

db_string -> Devuelve la primera columna del resultado de una consulta.Si la consulta no devuelve filas entonces
se devuelve el valor default y en caso de que este no haya sido definido se genera un error.
Ejemplo de uso:
db_string nombre "SELECT nombre FROM amigos WHERE amigo_id=id" - default db_null

db_list -> Devuelve una lista TCL con los valores de la primera columna de los resultados.
Ejemplo:
db_list lista_nombres "SELECT nombre FROM amigos"

db_list_of_lists -> Nos devuelve una lista de listas en TCL con todos los valores de todas las columnas de las filas resultado que nos
proporcione la sentencia SQL.
Ejemplo:
db_list_of_lists lista_datos_amigos "SELECT nombre,apellidos,telefono FROM amigos"

db_list_of_ns_sets -> Devuelve una lista de ns_sets con los valores devueltos por la sentencia sql.
Un ns_sets es un conjunto clave-valor, para mas información revisar la documentación de la Api de Aol-server:
http://aolserver.com/docs/devel/tcl/api/general.html#ns_set

Existen otras funciones en la API para bases de datos pero con las funciones que hemos comentado en estas cuatro partes tenemos toda la funcionalidad que requerimos para desarrollar nuestras aplicaciones.
Para mayor detalle podemos consultar la documentación oficial para la Api de BD en Ingles:
http://openacs.org/doc/openacs-5-1/db-api-detailed.html

lunes, julio 25, 2005

Api de Base de datos en OpenACS , Transacciones

Api de Base de datos en OpenACS 5.1 Transacciones.....

(Tercera Parte)

Una transacción es un grupo de instrucciones sobre Bases de datos que se ejecutan en conjunto para realizar una determinada funcionalidad.
La característica más importante de una transaccion es el hecho de que la transacción o se realiza completamente o en caso de algún error se deshacen las instrucciones ejecutadas para dar consistencia a los datos almacenados.

Un ejemplo de su uso....

* Imaginemos un cajero automático que funciona realizando consultas y ejecutando intrucciones SQL sobre su BD.
* Pongamonos en la situación de un cliente que desea sacar 50€ de su cuenta a través del cajero.
Introduce su tarjeta, teclea su codigo y solicita retirar 50€ de su cuenta.
* El cajero realiza lo siguiente:
- Comprueba que el cliente posee suficiente saldo en la cuenta.
- Pedirá confirmación al cliente.
- Actualizará el saldo restando 50€.
- Enviará el dinero al cliente.
- Imprimirá el recibo.

Con esta situación y para ver la utilidad de las transacciones de BD sobre servicios "criticos" implementados con BD supongamos que hay un corte de suministro eléctrico justo en el momento en que el cajero acaba de actualizar el saldo.
Tenemos entonces un cliente que posee 50€ menos en su cuenta sin haberlos recibido realmente.

Si se hubieran utilizado transacciones se hubiera abortado la operación con lo cual no se habria descontado la cantidad hasta finalizar toda la operación.

Veamos algunas de las funciones que la API de OpenACS pone a nuestra disposición para el manejo de transacciones:

* db_transaction: Es la encargada de definir una operación de transacción.
Su síntaxis es : db_transaction bloque_codigo [on_error bloque_codigo_error]
bloque_codigo recoje las instrucciones que forman parte de la transacción, y la seccion on_error ejecuta el bloque de codigo bloque_codigo_error en el caso de que haya algun error al ejecutar la transacción.

Veamos como quedaria nuestro ejemplo del cajero:

db_transaction{
db_1row saldo "SELECT saldo FROM clientes WHERE cliente_id=id"
if [ saldo > 50 ]{
confirmar
actualizar_saldo $dinero_sol
proporcionar_cantidad $dinero_sol
imprimir_recibo
}
else{
doc_body_append "Error: Saldo Insuficiente"
}
db_abort_transaction
}
on_error{
doc_body_append "Error en transaccion"
}

Notas sobre el ejemplo:
1) las funciones actualizar, proporcionar_cantidad e imprimir_recibo son procedimientos en Tcl que deben ser implementados, pero que para no complicar el codigo expuesto considero que para nuestro ejemplo son suficientemente autoexplicativos.
2) Utilizamos en el codigo la función "doc_body_append", esta función de openacs toma una cadena de texto y la incorpora el en BODY de la pagina de nuestro portal.
3) Como podemos ver una transacción finaliza con la instrucción " db_abort_transaction" la cual aborta la transacción.


Una característica muy útil es la posibilidad de definir transacciones anidadas, en estos casos deberemos tener en cuenta que la instrucción "db_abort_transaction" no solo finaliza la transacción en la que se la llama sino todas las demas en las que esté anidada.
Deberemos entonces tener la precaución de utilizar esta instrucción al final de la transaccion principal.

lunes, julio 04, 2005

API Base de datos OpenAcs, Variables ligadas

Api de Base de datos en OpenACS 5.1 Variables ligadas.....

(Segunda Parte)

Las variables ligadas tienen como finalidad "pasar" datos que normalmente solicita el usuario a las sentencias SQL que utilizamos para obtener información de la Base de datos.
Un ejemplo tipico de su uso es presentar un formulario en pantalla para pedir los datos de nombre y apellidos para crear un nuevo amigo, estos valores los almacenamos en variables y llamamos a una funcion para insertar amigos a la cual le pasamos ambas variables.
Esta función sería de la forma:
db_dml insertar_amigo "insert into amigos(nombre,apellidos) values (:form_nombre,:form_apellidos)"
Como vemos las variables ligadas en el codigo SQL se anteponen con el caracter de dos puntos ":".

Ahora veamos otra consideración, ¿podriamos sustituir este mismo codigo sin utilizar variables ligadas?.
Podiamos pensar en hacerlo de la siguiente manera:
db_dml insertar_amigo "insert into amigos(nombre,apellidos) values ($form_nombre,$form_apellidos)"
con lo cual llamariamos a las variables TCL directamente, entonces ¿para que son necesarias las variables ligadas?.
La respuesta es simple, una variable ligada nunca es interpretada, es decir su valor SIEMPRE será un literal con lo cual no tendremos el problema por ejemplo de que alguien introduzca codigo en una variable y este codigo llegue a ejecutarse.
Un ejemplo de esto ultimo:
Imaginemos que dentro de nuestra tabla de amigos alguien introduce una entrada con la siguiente información para crear un nuevo amigo:
nombre = "miguel or pepe"
imaginemos ahora que queremos borrar esta entrada y que nuestra funcion de borrado no utiliza variables ligadas, la funcion sería :
db_dml borrar_amigo "delete from amigos where nombre=$form_nombre"
el resultado seria que borrariamos de la base de Datos los valosres correspondientes a "miguel" y "pepe" comportamiento que no deseamos pues solo queremos borrar 1 valor.
Esto se soluciona utilizando variables ligadas que NUNCA serán interpretadas, nuestra función sería de la siguiente manera:
db_dml borrar_amigo "delete from amigos where nombre=:form_nombre"
de esta manera solo borrariamos aquella entrada con el valor "miguel or pepe" en el campo nombre.
Por este motivo es recomendable utilizar este tipo de variables.

API Base de Datos OPENACS

Api de Base de datos en OpenACS 5.1.....

(Primera Parte)

Pasaremos ahora a explicar las funciones del API que OpenACS utiliza para comunicación con la Base de datos
En primer lugar la esta API es necesaria para tener una independencia de la BD elegida, ya que al hacer las llamadas a las funciones ACS se encargará de traducirlas al lenguaje de la BD correspondiente.
Una característica de la utilización de BD es que al contrario de lo que ocurre en otros lenguajes no necesitamos definir objetos de conexión ni manejadores de datos, incluso podemos obviar las funciones del servidor AOL para manejar la conexión a BD, todo este proceso es trasparente al usuario y OpenACS se encargará de realizarlo pudiendo concentrarnos en hacer peticiones a la BD.

Procedimientos para Obtener Información de la BD:

Normalmente la forma general de las funciones será la siguiente:
funcion identificador_variableTCL " sentencia sql" [modificadores]
Los modificadores tienen varios usos como indicar a ACS que guarde el resultado en un array etc, de momento no los utilizaremos, más adelante incluiremos algun ejemplo de su uso

Funciones:
db_1row :
Obtiene una y solo una linea correspondiente a la ejecución de la sentencia sql ligada a ella.
En caso de que el resultado no sea exactamente una fila genera un error.

Ejemplo:
db_1row select_amigo "select nombre, apellidos from amigos where amigos_id = $temp_id"

db_0or1row:
Obtiene cero o una fila correspondiente a la ejecución de la sentencia sql.
En caso de obtenerse más de una fila genera error.

ejemplo:
db_0or1row select_amigo "select nombre,apellidos from amigos where amigos_id=$temp_amigos"

db_multirow:
Obtiene multiples filas a partir de una sentencia SQL.

ejemplo:
db_multirow select_all_amigos "select nombre,apellidos from amigos"

db_foreach:
Nos permite ejecutar operaciones con cada una de las filas obtenidas de la Base de datos.
Su sintaxis es la siguiente: db_foreach variable "sentencia sql" bloque_codigo [if_no_rows bloque_codigo2]
la ultima parte de if_no_rows es opcional para permitirnos hacer alguna operación en el caso de no haberse encontrado filas, en ese caso se ejecutaría bloque_codigo2.Veamos un ejemplo

ejemplo:
db_foreach select_amigos "select nombre, apellidos from amigos" {
doc_body_append "
  • nombre=$nombre; apellido=$apellido\n"
    }
    if_no_rows {
    doc_body_append "
  • Lo siento, peno no tiene amigos k triste ¿no?.\n"
    }

    db_dml:
    Nos permite ejecutar las operaciones de modificacion sobre nuestra BD.

    ejemplo:
    db_dml borra_amigo "delete form amigos where amigos_id=$temp_amigoid"

    Con esto tendremos las operaciones basicas sobre BD, expongo otras aqui como referencia, su uso es practicamente el mismo que el de las aqui utilizadas:

    db_list: Genera una lista en tcl con los valores que devuelve la sentencia sql.En caso de no obtener ninguna fila genera una lista vacia.
    uso: dblist varble "sentencia sql"

    db_list_of_list: Es analoga a la anterior solo que cada elemento devuelto es a su vez una lista.
    dblist varble "sentencia sql"

    db_write_clob, db_write_blob, db_blob_get_file: Permiten manejar campos de la base de datos de alta capacidad.
    Por ejemplo los usamos cuando queremos almacenar un video, una foto o algo similar en la base de datos.
    su uso es el mismo que las funciones anteriores.
    funcion vrble_tcl "sentencia sql"
  • viernes, julio 01, 2005

    Modelo de Datos de OpenAcs Segunda Parte

    Modelo de Datos en OpenACS 5.1.....

    (Segunda Parte Eliminación de tipos y atributos)

    En la primera parte del modelo de datos de OpenAcs vimos como crear un nuevo objeto y atributos, ahora veremos el método para eliminarlos del sistema OpenAcs.
    Siguiendo con nuestro ejemplo del paquete "amigos" eliminaremos el tipo Amigo y sus atributos "Nombre" y "Apellidos" para ello crearemos un fichero "amigos-drop.sql" que introduciremos en el directorio sql de nuestro paquete amigos.

    Veamos las funciones a las cuales haremos referencia:

    content_type__drop_attribute --> Con esta funcion eliminaremos los atributos.
    content_type_drop_type --> Eliminamos el tipo definido.

    Veamos el contenido detallado de nuestro fichero "amigos-drop.sql":

    select content_type__drop_attribute(
    'amigo', -- Nombre del tipo al que pertenece el atributo.
    'nombre', -- Nombre del attributo que deseamos eliminar.
    't' -- Borrar la columna del attributo, especificamos true "t" para eliminarla "f" para no modificar la tabla.
    );

    select content_type__drop_attribute(
    'amigo', -- Nombre del tipo al que pertenece el atributo.
    'apellidos', -- Nombre del attributo que deseamos eliminar.
    't' -- Borrar la columna del attributo, especificamos true "t" para eliminarla "f" para no modificar la tabla.
    );

    select content_type__drop_type(
    'amigo', -- Nombre del Tipo a Eliminar
    't', -- Borrar los tipos derivados de esta clase, especificamos true "t" para borrarlos "f" para mantenerlos,
    -- por consistencia en el sistema de objetos es aconsejable hacerlo pero se deja a opcion del desarrollador.
    't' -- Borrar la Tabla del tipo, especificamos true "t" para eliminarla "f" para no modificar la tabla.
    );