MySQL Forums
Forum List  »  Spanish

transaccion en funcion...
Posted by: Martín Colodrero
Date: December 11, 2007 11:32PM

Titulo tentador ese para entrar y decirle no se puede... pero bue'

Estoy trabajando en un pequeño framework que se basa mucho en SQL, hace ya un mes estoy luchando en el como hacer la sesiones, pense en Radios, PAS, LDAP, etc, pero nada me sirve... creo, termine por modificar un modulo de apache para que haga lo q necesito

En forma gráfica para q se den una idea:

Usuario <-> HTTPD <-> APACHE_MOD_MYSQL <-> MYSQL
                       |
                       +-> Permite acceso <-> Recurso
                       |
                  Deniega Acceso

Y ahora los taladro con un esquema de la idea:

/*recurso*/
DROP TABLE IF EXISTS `resource`; /* supongamos una página le asigno un id*/
CREATE TABLE `resource`(
   `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `name` VARCHAR(50) /*doesn't matter*/
);

DROP TABLE IF EXISTS `alloworrestrict`;
/*permitir o restringir*/
CREATE TABLE `alloworrestrict`(/*con el id del recurso, id del usuario y una clave con lo q hacer */
    resource_id INT,
    user_id INT,
    `lock` ENUM('ALLOW','RESTRICT')
);
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`(/*la tabla de usuario comun*/
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50),
  pass VARCHAR(50)
);
DROP TABLE IF EXISTS `session`;
CREATE TABLE session(/*las bendita sessiones, relacionada con el usuario y un hash*/
  user_id INT,
  hash VARCHAR(32)
) ENGINE=innoDB;

INSERT INTO resource(name) VALUES('first');
INSERT INTO resource(name) VALUES('second');
INSERT INTO user(name,pass) VALUES('john','123');
/*lo anterior cargamos datos, aquí le bloqueamos a john el recurso con id 2*/
INSERT INTO alloworrestrict(resource_id,user_id,`lock`) VALUES(2,1,'RESTRICT');

/*funcion para crear una sesion*/
DELIMITER $$ ;
CREATE FUNCTION create_session(id INT)
       RETURNS VARCHAR(32)
       READS SQL DATA
BEGIN
DECLARE `loop` INT DEFAULT 1;
DECLARE `THASH` VARCHAR(32) NOT NULL DEFAULT '';
/*todo esto crea una session, por favor notar q esta mal porque no puede haber transacciones es a modo de ejemplo*/
SET AUTOCOMMIT=0;
START TRANSACTION;
  WHILE loop > 0 DO
    SET THASH = MD5(RAND(9999999999999999999)*999999999999999999);
    IF NOT (SELECT `hash` FROM `session` WHERE `hash`=THASH LIMIT 1) THEN
        INSERT INTO session(user_id,hash) VALUES(id,THASH);
        SET `loop` = 0;
    END IF;
  END WHILE;
COMMIT;
RETURN THASH;
END $$
DELIMITER ; $$

/*hacemos como si navegamos, el usuario se valida*/
SET @tuid = SELECT id FROM `user` WHERE name='John' AND pass='123' LIMIT 1;
/* validado creamos la sesion*/
SET @hash = SELECT create_session(@tuid);
/*la sesion la enviamos en una cookie y la captura el modulo de apache, todo lo de abajo en realidad va en una funcion tambien pero no compliquemos*/
SET @uid = SELECT IFNULL(id,0) FROM session WHERE hash=@hash LIMIT 1;

/*chequemos si el recurso esta bloqueado para él o para alguien*/
IF @uid THEN
/*si hay sesion habrá @uid sino no, en este caso chequeamos que el recurso no este bloqueado para este especifico usuario*/
SET @rac = SELECT IFNULL(`lock`,'') FROM alloworrestrict WHERE resource=2 AND user_id = @uid LIMIT 1;
ELSE
/*no habiendo @uid chequeamo si hay alguien que fué bloqueado en ese caso denegamos tambien*/
SET @rac = SELECT IFNULL(`lock`,'') FROM alloworrestrict WHERE resource=2 LIMIT 1;
END IF;

/*hacemos la comprobación y resultado de lo anterios, si esta validado y no esta bloqueado lo mostramos*/
IF (@uid AND @rac <> 'RESTRICT') THEN
SELECT 'ACCESS';
/*si no esta registrado pero no hay bloqueo de recurso lo mostramos*/
ELSE IF (@uid =0 AND @rac <> 'RESTRICT') THEN
SELECT 'ACCESS';
ELSE
/*si no se da ninguna de las condiciones anteriores no mostramos nada*/
SELECT 'DENIED';
END IF;
/*el modulo de apache espera estas respuesta para saber que hacer*/

Más o menos es la idea, se que no se puede utilizar transaciones en funciones, pero probé las transacciones progresivas y tampoco funca, recibí este error ERROR 1400 (XAE09): XAER_OUTSIDE: Some work is done outside global transaction when execute the function.

Que puedo hacer que se les ocurre, como lo han implementado ustedes?

Esto es por si quieren probar las transciones progresiva q no funca.

DROP TABLE IF EXISTS `se`;

CREATE TABLE `se`(
	`id`INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`name` VARCHAR(25)
) ENGINE=innoDB;

DROP FUNCTION IF EXISTS `ses`;

DELIMITER $$ ;

CREATE FUNCTION `ses`()
	RETURNS INT(11) 
	READS SQL DATA
BEGIN
	XA START 'XAsession';
	INSERT INTO `se`(`name`) VALUES ('john'); 
	SET @tmp_password = LAST_INSERT_ID();
	XA END 'XAsession';
	XA PREPARE 'XAsession';
	XA COMMIT 'XAsession';
	RETURN @tmp_password;
END $$

DELIMITER ; $$
/*no funciona*/
SELECT ses();
/*funciona*/
XA START 'XAsession';
INSERT INTO `se`(`name`) VALUES ('john'); 
SET @tmp_password = LAST_INSERT_ID();
XA END 'XAsession';
XA PREPARE 'XAsession';
XA COMMIT 'XAsession';
SELECT @tmp_password;

Comentarios, sugerencia, ayuda, ejemplos, puteadas, alabanzas, delirio ha estas altura me parece q todo es bienvenido :-D.

Bueno si leyeron hasta acá se merecen un gran saludos!!!!

Martín

PD: sorry las partes q estan en mal ingles, pero lo había posteado en otro lado hace un tiempo y naranja.

Options: ReplyQuote


Subject
Views
Written By
Posted
transaccion en funcion...
7253
December 11, 2007 11:32PM
2216
December 15, 2007 12:17AM
2165
January 09, 2008 09:26AM


Sorry, you can't reply to this topic. It has been closed.

Content reproduced on this site is the property of the respective copyright holders. It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.