Re: Ejecución automática por tiempo de procedimientos.

Lists: pgsql-es-ayuda
From: Pablo Braulio <brulics(at)gmail(dot)com>
To: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Ejecución automática por tiempo de procedimientos.
Date: 2007-12-11 08:40:47
Message-ID: 475E4D0F.5050407@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hola a todos.

Escribo esto, pues desconozco si es posible programar un procedimiento y
que este se ejecute pasado un cierto tiempo.

Lo que trato de hacer es que en una tabla tengo estos campos:

sesion boolean,
finsession timestamp,

El campo "sesion" recoge el valor true en el caso de que una sesión haya
sido iniciada (en mi programa en php) y el campo "finsession", marca la
fecha y hora de finalización de esta.

Lo que necesito es diseñar una función que compruebe cada cierto tiempo
(10 minutos, por ejemplo), si la hora y fecha actual supera a la que
marca el campo y en tal caso que cambie el valor del campo "sesion" a false.

¿Es posible hacer esto?.

Es que de no ser posible, tendría que hacer un script con php y ponerlo
en el cron, y no me parece lo mas apropiado.

Gracias a todos.
- --

< ¡¡Nos vemos!! >
----------------------------
\
\
.::!!!!!!!:.
.!!!!!:. .:!!!!!!!!!!!!
~~~~!!!!!!. .:!!!!!!!!!UWWW$$$
:$$NWX!!: .:!!!!!!XUWW$$$$$$$$$P
$$$$$##WX!: .<!!!!UW$$$$" $$$$$$$$#
$$$$$ $$$UX :!!UW$$$$$$$$$ 4$$$$$*
^$$$B $$$$\ $$$$$$$$$$$$ d$$R"
"*$bd$$$$ '*$$$$$$$$$$$o+#"
"""" """""""
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHXk0OK7lGsMchFswRAjufAJ9+HHanmQoYCG1PA/zScYvJHkfd1ACcC3iK
kN8CucQ5ABQYhbfH+jjQ8dY=
=GeRS
-----END PGP SIGNATURE-----


From: iescriva <iescriva(at)gmail(dot)com>
To: Pablo Braulio <brulics(at)gmail(dot)com>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Ejecución automática por tiempo de procedimientos.
Date: 2007-12-11 11:07:57
Message-ID: 475E6F8D.4010209@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Pablo Braulio wrote:
> Lo que necesito es diseñar una función que compruebe cada cierto tiempo
> (10 minutos, por ejemplo), si la hora y fecha actual supera a la que
> marca el campo y en tal caso que cambie el valor del campo "sesion" a false.

¿Y porque no simplemente si el tiempo actual es mayor que el de limite
de sesion la sesion ha caducado?
Con eso ya tienes una sesion a false sin necesitar un campo que lo
indique ni tener que comprobarlo cada cierto tiempo.

Tambien puees hacer una funcion que retorne false o true segun si la
sesion ha caducado o no.


From: Pablo Braulio <brulics(at)gmail(dot)com>
To: iescriva <iescriva(at)gmail(dot)com>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Ejecución automática por tiempo de procedimientos.
Date: 2007-12-11 11:21:05
Message-ID: 475E72A1.9030001@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

iescriva escribió:
> Pablo Braulio wrote:
>> Lo que necesito es diseñar una función que compruebe cada cierto tiempo
>> (10 minutos, por ejemplo), si la hora y fecha actual supera a la que
>> marca el campo y en tal caso que cambie el valor del campo "sesion" a false.
>
>
> ¿Y porque no simplemente si el tiempo actual es mayor que el de limite
> de sesion la sesion ha caducado?
> Con eso ya tienes una sesion a false sin necesitar un campo que lo
> indique ni tener que comprobarlo cada cierto tiempo.
>
> Tambien puees hacer una funcion que retorne false o true segun si la
> sesion ha caducado o no.
>
¿Te refieres en php?.

Si es así, eso lo tengo claro, que es como actua una sesión.

Pero lo que quiero es controlar de algún modo si la sesion ha sido
iniciada y para eso uso el campo boolean, que será true cuando la sesión
se haya iniciado y false cuando caduque o finalice.

El problema es que en php no puedo cambiar ese valor si la sesión caduca
o el usuario cierra el navegador sin darle al boton que pongo para que
finalize la sesión.

Por eso quiero saber si podría hacer un procedimiento que se ejecute
cada cierto tiempo y me haga dicha comprobación.

- --

< ¡¡Nos vemos!! >
----------------------------
\
\
.::!!!!!!!:.
.!!!!!:. .:!!!!!!!!!!!!
~~~~!!!!!!. .:!!!!!!!!!UWWW$$$
:$$NWX!!: .:!!!!!!XUWW$$$$$$$$$P
$$$$$##WX!: .<!!!!UW$$$$" $$$$$$$$#
$$$$$ $$$UX :!!UW$$$$$$$$$ 4$$$$$*
^$$$B $$$$\ $$$$$$$$$$$$ d$$R"
"*$bd$$$$ '*$$$$$$$$$$$o+#"
"""" """""""
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHXnKhK7lGsMchFswRAnVHAJwJXfxJTVnc9GHLU7QhoLGcomftEACghbce
A8hn7KQ2KDq93tg1w8wzc5I=
=fLeR
-----END PGP SIGNATURE-----


From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Pablo Braulio <brulics(at)gmail(dot)com>
Cc: iescriva <iescriva(at)gmail(dot)com>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Ejecución automática por tiempo de procedimientos.
Date: 2007-12-11 11:26:27
Message-ID: 20071211112627.GC4708@alvh.no-ip.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Pablo Braulio escribió:

> iescriva escribió:
> > Pablo Braulio wrote:
> >> Lo que necesito es diseñar una función que compruebe cada cierto tiempo
> >> (10 minutos, por ejemplo), si la hora y fecha actual supera a la que
> >> marca el campo y en tal caso que cambie el valor del campo "sesion" a false.
> >
> > ¿Y porque no simplemente si el tiempo actual es mayor que el de limite
> > de sesion la sesion ha caducado?
> > Con eso ya tienes una sesion a false sin necesitar un campo que lo
> > indique ni tener que comprobarlo cada cierto tiempo.
>
> ¿Te refieres en php?.

No, en SQL. Tener un campo "sesion" que es verdadero o falso
dependiendo de la hora actual no es una idea mala, sino que es pésima.

En lugar tener un campo que almacene la hora a la cual expirará la
sesión, guarda la hora a la que empezó. Luego puedes calcular
trivialmente si esa hora, más el delta de tiempo que duran las sesiones,
es mayor que la hora actual.

--
Alvaro Herrera http://www.flickr.com/photos/alvherre/
"En las profundidades de nuestro inconsciente hay una obsesiva necesidad
de un universo lógico y coherente. Pero el universo real se halla siempre
un paso más allá de la lógica" (Irulan)


From: Pablo Braulio <brulics(at)gmail(dot)com>
To: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Ejecución automática por tiempo de procedimientos.
Date: 2007-12-11 12:43:21
Message-ID: 475E85E9.9070504@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

> No, en SQL. Tener un campo "sesion" que es verdadero o falso
> dependiendo de la hora actual no es una idea mala, sino que es pésima.
>
> En lugar tener un campo que almacene la hora a la cual expirará la
> sesión, guarda la hora a la que empezó. Luego puedes calcular
> trivialmente si esa hora, más el delta de tiempo que duran las sesiones,
> es mayor que la hora actual.
>

Hola.

Me parece buena idea lo que dices de la hora, pero no entiendo con lo
que dices de la sesión.

Hay que tener en cuenta que he creado una tabla de usuarios, no estoy
usando los usuarios de postgres para que los usuarios se autentiquen.

Sólo hay un usuario que es con el cual se hace la conexión a la base de
datos antes de hacer los querys.

De todos modos, mi pregunta es sobre si se puede ejecutar el
procedimiento diseñado cada determinado tiempo.

Gracias por los comentarios.

- --

< ¡¡Nos vemos!! >
----------------------------
\
\
.::!!!!!!!:.
.!!!!!:. .:!!!!!!!!!!!!
~~~~!!!!!!. .:!!!!!!!!!UWWW$$$
:$$NWX!!: .:!!!!!!XUWW$$$$$$$$$P
$$$$$##WX!: .<!!!!UW$$$$" $$$$$$$$#
$$$$$ $$$UX :!!UW$$$$$$$$$ 4$$$$$*
^$$$B $$$$\ $$$$$$$$$$$$ d$$R"
"*$bd$$$$ '*$$$$$$$$$$$o+#"
"""" """""""
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHXoXpK7lGsMchFswRApgyAJ4yMhJruzurXftTiZUFnP0BefW6rQCgqxFD
GGiOf74i7xzgnFBdx0b6wW0=
=GtS/
-----END PGP SIGNATURE-----


From: Gunnar Wolf <gwolf(at)gwolf(dot)org>
To: Pablo Braulio <brulics(at)gmail(dot)com>
Cc: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Ejecución automática por tiempo de procedimientos.
Date: 2007-12-11 15:42:30
Message-ID: 20071211154230.GD23366@cajita.gateway.2wire.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Pablo Braulio dijo [Tue, Dec 11, 2007 at 01:43:21PM +0100]:
> Me parece buena idea lo que dices de la hora, pero no entiendo con lo
> que dices de la sesión.
>
> Hay que tener en cuenta que he creado una tabla de usuarios, no estoy
> usando los usuarios de postgres para que los usuarios se autentiquen.
>
> Sólo hay un usuario que es con el cual se hace la conexión a la base de
> datos antes de hacer los querys.
>
> De todos modos, mi pregunta es sobre si se puede ejecutar el
> procedimiento diseñado cada determinado tiempo.

¿Permites una sóla sesión por usuario, o varias? Bueno, te muestro acá
lo que yo haría para una sóla - extenderlo es trivial (y recomendable)
;-)

CREATE TABLE usuario (
id serial PRIMARY KEY,
login text NOT NULL UNIQUE,
passwd char(32) NOT NULL,
nombre text,
sesion char(32),
sesion_inicio timestamp default now()
);

Te conviene crear un índice sobre el campo sesion, pues estaremos
haciendo búsquedas sobre de él. A este campo y a passwd le pongo una
longitud fija (no son text como los demás), porque guardo ahí la
salida de md5, que es siempre de 32 caracteres. Tu implementación
puede variar.

Puedes tener una tabla con la configuración del sistema, por ejemplo,
para poder ajustar la duración de tus sesiones - por ahora, lo
limitamos a 10 minutos en duro.

Ahora, en vez de intentar validar la sesión del usuario desde tu PHP,
mejor llama a la función sesion_valida() - No va probada, pero es algo
como esto:

CREATE OR REPLACE FUNCTION sesion_valida(text) RETURNS integer AS
$$
DECLARE
la_sesion ALIAS FOR $1;
duracion interval;
user_id integer;
BEGIN
duracion = '10 min'::interval
-- Antes de otra cosa, vaciamos todas las sesiones expiradas
UPDATE usuario SET sesion=NULL WHERE sesion_inicio+duracion < now();
-- Buscamos a qué usuario pertenece esta sesión
SELECT INTO user_id id FROM usuario WHERE sesion = la_sesion;
RETURN la_sesion;
END;
$$ LANGUAGE 'plpgsql';

¿Te gusta? Claro está, es _mucho_ más eficiente (especialmente si
tienes cantidades grandes de usuarios) que crees una tabla
independiente para sesiones. Pero bueno, ahí ya te resolví la tarea de
cómo permitir más de una sesión por usuario. Claro, queda otra (muy
trivial) de cómo limitarlo ;-)

Saludos,

--
Gunnar Wolf - gwolf(at)gwolf(dot)org - (+52-55)5623-0154 / 1451-2244
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF


From: Pablo Braulio <brulics(at)gmail(dot)com>
To: Gunnar Wolf <gwolf(at)gwolf(dot)org>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Ejecución automática por tiempo de procedimientos.
Date: 2007-12-11 17:14:36
Message-ID: 475EC57C.8070209@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

>
> ¿Permites una sóla sesión por usuario, o varias? Bueno, te muestro acá
> lo que yo haría para una sóla - extenderlo es trivial (y recomendable)
> ;-)
>
> CREATE TABLE usuario (
> id serial PRIMARY KEY,
> login text NOT NULL UNIQUE,
> passwd char(32) NOT NULL,
> nombre text,
> sesion char(32),
> sesion_inicio timestamp default now()
> );
>
> Te conviene crear un índice sobre el campo sesion, pues estaremos
> haciendo búsquedas sobre de él. A este campo y a passwd le pongo una
> longitud fija (no son text como los demás), porque guardo ahí la
> salida de md5, que es siempre de 32 caracteres. Tu implementación
> puede variar.
>
> Puedes tener una tabla con la configuración del sistema, por ejemplo,
> para poder ajustar la duración de tus sesiones - por ahora, lo
> limitamos a 10 minutos en duro.
>
> Ahora, en vez de intentar validar la sesión del usuario desde tu PHP,
> mejor llama a la función sesion_valida() - No va probada, pero es algo
> como esto:
>
> CREATE OR REPLACE FUNCTION sesion_valida(text) RETURNS integer AS
> $$
> DECLARE
> la_sesion ALIAS FOR $1;
> duracion interval;
> user_id integer;
> BEGIN
> duracion = '10 min'::interval
> -- Antes de otra cosa, vaciamos todas las sesiones expiradas
> UPDATE usuario SET sesion=NULL WHERE sesion_inicio+duracion < now();
> -- Buscamos a qué usuario pertenece esta sesión
> SELECT INTO user_id id FROM usuario WHERE sesion = la_sesion;
> RETURN la_sesion;
> END;
> $$ LANGUAGE 'plpgsql';
>
> ¿Te gusta? Claro está, es _mucho_ más eficiente (especialmente si
> tienes cantidades grandes de usuarios) que crees una tabla
> independiente para sesiones. Pero bueno, ahí ya te resolví la tarea de
> cómo permitir más de una sesión por usuario. Claro, queda otra (muy
> trivial) de cómo limitarlo ;-)
>
> Saludos,
>

Hola.

Lo que pretendo es limitar el acceso de los usuarios a una sóla sesión.
Es decir que un usuario sólo pueda iniciarla una sóla vez
simultaneamente, que el mismo usuario no esté trabajando en dos sitios
al mismo tiempo.

Espero haberme explicado bien.

Viendo la tabla que creas, tengo la duda de que almacenas en el campo
sesion. ¿el identificador de la sesion de php?. :-(

Luego, ¿como ejecutas la función?. Perdona pero estoy muy verde con las
funciones.

Gracias por la ayuda.
- --

< ¡¡Nos vemos!! >
----------------------------
\
\
.::!!!!!!!:.
.!!!!!:. .:!!!!!!!!!!!!
~~~~!!!!!!. .:!!!!!!!!!UWWW$$$
:$$NWX!!: .:!!!!!!XUWW$$$$$$$$$P
$$$$$##WX!: .<!!!!UW$$$$" $$$$$$$$#
$$$$$ $$$UX :!!UW$$$$$$$$$ 4$$$$$*
^$$$B $$$$\ $$$$$$$$$$$$ d$$R"
"*$bd$$$$ '*$$$$$$$$$$$o+#"
"""" """""""
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHXsV8K7lGsMchFswRAqEqAJ4wLyvwCqWAGGOBCNyhfzFyk1RnsACgve/5
B+gRhGVj5wTDvaU13Xb3iBw=
=1P4I
-----END PGP SIGNATURE-----


From: Julio Cesar Sánchez González <knowhow(at)sistemasyconectividad(dot)com(dot)mx>
To: Pablo Braulio <brulics(at)gmail(dot)com>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Ejecución automática por tiempo de procedimientos.
Date: 2007-12-11 22:49:27
Message-ID: 1197413367.6863.3.camel@andromeda
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda


El mar, 11-12-2007 a las 09:40 +0100, Pablo Braulio escribió:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hola a todos.
>
> Escribo esto, pues desconozco si es posible programar un procedimiento y
> que este se ejecute pasado un cierto tiempo.
>
> Lo que trato de hacer es que en una tabla tengo estos campos:
>
> sesion boolean,
> finsession timestamp,
>
> El campo "sesion" recoge el valor true en el caso de que una sesión haya
> sido iniciada (en mi programa en php) y el campo "finsession", marca la
> fecha y hora de finalización de esta.
>
> Lo que necesito es diseñar una función que compruebe cada cierto tiempo
> (10 minutos, por ejemplo), si la hora y fecha actual supera a la que
> marca el campo y en tal caso que cambie el valor del campo "sesion" a false.
>
> ¿Es posible hacer esto?.
>
> Es que de no ser posible, tendría que hacer un script con php y ponerlo
> en el cron, y no me parece lo mas apropiado.
>
> Gracias a todos.

Lo del cron no es tan descabellado, de hecho es la unica forma que se me
ocurre, podrias hacerlo como dices con php pero creo que seria mejor con
perl, aunque es cuestion de gustos. Ahora veo que quieres manejar una
especie de estado mediante la base de datos, no seria mas facil dejar lo
de la sesion a tu aplicacion, en este caso PHP. PHP ya dispone de manejo
de sesiones, el tiempo de vida de la sesion lo configuras en el php.ini.

--
Saludos,

Julio Cesar Sánchez González.

--
Ahora me he convertido en la muerte, destructora de mundos.
Soy la Muerte que se lleva todo, la fuente de las cosas que vendran.

www.sistemasyconectividad.com.mx http://darkavngr.blogspot.com/


From: Gunnar Wolf <gwolf(at)gwolf(dot)org>
To: Pablo Braulio <brulics(at)gmail(dot)com>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Ejecución automática por tiempo de procedimientos.
Date: 2007-12-11 23:10:46
Message-ID: 20071211231046.GB29957@cajita.gateway.2wire.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Pablo Braulio dijo [Tue, Dec 11, 2007 at 06:14:36PM +0100]:
> > ¿Permites una sóla sesión por usuario, o varias? Bueno, te muestro acá
> > lo que yo haría para una sóla - extenderlo es trivial (y recomendable)
> > ;-)
> >
> > CREATE TABLE usuario (
> > id serial PRIMARY KEY,
> > login text NOT NULL UNIQUE,
> > passwd char(32) NOT NULL,
> > nombre text,
> > sesion char(32),
> > sesion_inicio timestamp default now()
> > );
> Hola.
>
> Lo que pretendo es limitar el acceso de los usuarios a una sóla sesión.
> Es decir que un usuario sólo pueda iniciarla una sóla vez
> simultaneamente, que el mismo usuario no esté trabajando en dos sitios
> al mismo tiempo.
>
> Espero haberme explicado bien.

Ok, perfecto - Veo que eres novato, escribo un poquito más a detalle.

Podría funcionarte tal como lo escribí, pero podría ser deseable que
la información la tuvieras en una tabla aparte - el principal
escenario donde habría diferencia es en la eficiencia al eliminar
registros expirados - pero bueno, como según mi función vas a hacer
esto cada que recibas una sesión, se vuelve asunto crítico. Puede que
esté equivocado, pero creo que es más barato marcar registros para su
eliminación (con DELETE) que realmente actualizarlos para marcar los
campos como nulos (como te lo había escrito en el ejemplo
anterior). Entonces, sugiero que la definición de las tablas quede:

CREATE TABLE usuario (
id serial PRIMARY KEY,
login text NOT NULL UNIQUE,
passwd char(32) NOT NULL,
nombre text
);

CREATE TABLE sesion (
sesion char(32) PRIMARY KEY,
id_usuario integer NOT NULL REFERENCES usuario(id),
ultimo_uso timestamp NOT NULL default now()
);
CREATE INDEX ultimo_uso_sesion ON sesion (ultimo_uso);
CREATE UNIQUE INDEX usuario_sesion ON sesion(id_usuario);

Con todo y el índice sobre la hora de último uso de sesión (sí, cambió
la nomenclatura: No importa en realidad el último inicio de sesión,
sino que la última vez que la usaste). Además, notarás un segundo
índice, usuario_sesion. ¿Para qué? Porque tienes el requisito de que
cada usuario tenga una sóla sesión.

Y la función queda:

CREATE OR REPLACE FUNCTION sesion_valida(text) RETURNS integer AS
$$
DECLARE
la_sesion ALIAS FOR $1;
duracion interval;
user_id integer;
BEGIN
duracion = '10 min'::interval;
-- Antes de otra cosa, vaciamos todas las sesiones expiradas
DELETE FROM sesion WHERE ultimo_uso+duracion < now();
-- Buscamos a qué usuario pertenece esta sesión
SELECT INTO user_id id_usuario FROM sesion WHERE sesion = la_sesion;
IF NOT FOUND THEN
RETURN NULL;
END IF;
UPDATE sesion SET ultimo_uso=now() WHERE sesion = la_sesion;
RETURN user_id;
END;
$$ LANGUAGE 'plpgsql';

¿Sí notas la direfencia? Acá sólo operao sobre la tabla sesion, ya no
sobre la tabla usuario. (y disculpa la errata: En la vuelta anterior,
estaba dándote un «RETURN la_sesion» cuando debe ser claramente
«RETURN user_id»).

Le agregué además una cláusula (¡todo en nombre del encapsulamiento!
Evita que la lógica de autenticación y manejo de sesiones esté regada
por todos lados) para que, al validar la sesión, automáticamente la
refresque.

> Viendo la tabla que creas, tengo la duda de que almacenas en el campo
> sesion. ¿el identificador de la sesion de php?. :-(

No sé, no conozco PHP... No sé qué tan confiable sea ese identificador
de sesión, ni cuál sea su semántica. Pero bueno, lo que te sugiero es
que generes las sesiones también desde Postgres. ¿Cómo? Así:

CREATE OR REPLACE FUNCTION crea_sesion(integer) RETURNS char(32) AS
$$
DECLARE
user_id ALIAS FOR $1;
nueva_sesion char(32);
BEGIN
DELETE FROM sesion WHERE id_usuario = user_id;
nueva_sesion = md5(now()::text||user_id::text);
INSERT INTO sesion (sesion, id_usuario, ultimo_uso) VALUES
(nueva_sesion, user_id, now());
RETURN nueva_sesion;
END;
$$ LANGUAGE 'plpgsql';

¿Qué es eso de «md5(now()::text||user_id::text)»? Simplemente una
manera de obtener 32 caracteres pseudoaleatorios, suficientemente
confiable como para usar como llave de sesión. De hecho, probablemente
quieras usar algo similar para guardar la contraseña únicamente
cifrada, no en texto claro - algo así como md5(id, contraseña) - pero
esa queda como ejercicio para el lector. Por ahora, creo una
contraseña (porque la BD la exige), pero no la uso.

> Luego, ¿como ejecutas la función?. Perdona pero estoy muy verde con las
> funciones.

Una vez que creaste las funciones, puedes usarlas tal como usarías
cualquier otra fuente de datos para un SELECT. Va, pues, un ejemplo -
en interactivo desde la consola psql, con las tablas y funciones
recién creadas. Primero creamos un usuario:

| mi_base=# INSERT INTO usuario (login, passwd) VALUES ('fulano', 'a');
| INSERT 0 1
| mi_base=# SELECT * FROM usuario;
| id | login | passwd | nombre
| ----+--------+----------------------------------+--------
| 1 | fulano | a |
| (1 row)

Claro está, la tabla de sesiones está vacía a estas alturas:

| mi_base=# SELECT * FROM sesion;
| sesion | id_usuario | ultimo_uso
| --------+------------+------------
| (0 rows)

¿Cómo puedo crear una sesión?

| mi_base=# SELECT crea_sesion(1);
| crea_sesion
| ----------------------------------
| 8faaabf6d5e192c32dcd54f3fe06021e
| (1 row)

Me regresó el ID de la sesión creada - Éste lo alimento a la lógica de
mi programa, hago lo que tenga que hacer... Podemos verificar ahora el
contenido de la tabla:

| mi_base=# SELECT * FROM sesion;
| sesion | id_usuario | ultimo_uso
| ----------------------------------+------------+---------------------------
| 8faaabf6d5e192c32dcd54f3fe06021e | 1 | 2007-12-11 16:59:32.67608
| (1 row)

Y ya luego, cuando el
usuario mande de nuevo una solicitud, paso de vuelta su sesión:

| mi_base=# SELECT sesion_valida('8faaabf6d5e192c32dcd54f3fe06021e');
| sesion_valida
| ---------------
| 1
| (1 row)

¡Listo! Me entregó el ID del usuario en cuestión. Ahora, ¿qué pasa
después de haber invocado a sesion_valida? Observa al ultimo_uso:

| mi_base=# SELECT * FROM sesion;
| sesion | id_usuario | ultimo_uso
| ----------------------------------+------------+----------------------------
| 8faaabf6d5e192c32dcd54f3fe06021e | 1 | 2007-12-11 17:00:38.711794
| (1 row)

Por último, ¿cómo manejas las sesiones expiradas? Sencillo: Vamos a
actualizar la sesión. Recuerda que la tenemos a 10 minutos.

| mi_base=# UPDATE sesion SET ultimo_uso = now()-'1 hour'::interval;
| UPDATE 1
| mi_base=# SELECT sesion_valida('8faaabf6d5e192c32dcd54f3fe06021e');
| sesion_valida
| ---------------
|
| (1 row)
|
| mi_base=# SELECT * FROM sesion;
| sesion | id_usuario | ultimo_uso
| --------+------------+------------
| (0 rows)

Como la sesión ya expiró, la eliminó del sistema. Y no sólo la de este
usuario, sino que todas las demás sesiones ya expiradas.

Espero que te sea de utilidad.

¡Ah! Claro, faltaba decirte: Para hacer esto, tienes que incluir el
soporte para el lenguaje plpgsql. Para esto (desde cualquier sistema
tipo Unix, desde fuera de psql):

$ createlang plpgsql mi_base

Saludos,

--
Gunnar Wolf - gwolf(at)gwolf(dot)org - (+52-55)5623-0154 / 1451-2244
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF