ON DUP*TE KEY UP*TE tylko moj "indeks" ma 2 pol

0

Chce zrobic w programie taka jakby liste ACL dla uzytkownikow z informacja co uzytkownicy moga zrobic a czego nie moga, wiec stworzylem sobie taka tabele:

			CREATE TABLE IF NOT EXISTS `$this->usersAclTable` (
				`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
				`name` VARCHAR( 32 ) NOT NULL ,
				`value` BOOL NOT NULL DEFAULT '0',
				`login` VARCHAR( 32 ) NOT NULL 
			)

problem pojawia się gdy chce zaktualizować jakiś wpis, nie chce tego robić za pomocą pola id bo w momecie aktualizowania znam jedynie pola name i value, więc robie coś takiego:

"DELETE FROM `$this->usersAclTable` WHERE `name`=\\0 AND `login`=\\1", array($what, $login));
"INSERT INTO `$this->usersAclTable` SET `name`=\\0, `login`=\\1, `value`=\\2", array($what, $login, $value));

Jak mozna sie domyslic moje pytanie brzmi, jak to zrobic jednym zapytaniem?

Moge niby zrobic jakies UNIQUE pole z jakims hashem ustawienia i po prostu ON DUPLICATE KEY UPDATE no ale za bardzo eleganckie to nie bedzie. Zalezaloby mi tez zeby rozwiazanie bylo jakies standardowe (korzystam z MySQL ale swiat sie na nim nie konczy).

A moze zle do tego podchodze i powiniem inaczej rozplanowac ten system (kontrakt tego wyglada tak, ze mam /chce miec/ metody bool User.getPermission(string), void User.setPermission(string, string) i Map<string, bool> User.getPermissions())? bo rzeczywiscie w tym momecie WHERE nie odnosi sie do indeksow czyli dostep jest liniowy jesli dobrze mysle.

BTW, za krotkie to pole tematu zeby zadac pytanie :)

0

Ja bym proponował rozbić to następująco:

  1. Tabela ACCESS_RIGHT trzymająca dostępne uprawnienia:
    acl_id - integer, klucz główny
    acl_name - varchar, unique - krótki opis uprawnienia, identyfikator publiczny
    desc - varchar - opis uprawnienia

np. 1,EDIT_ARTICLE,Edycja artykułów

  1. Tabela USER
    user_id - integer, klucz główny - id uzytkownika
    login - varchar, unique - login uzytkownika
    ... inne dane ...

  2. Tabela ACL_USER przechowująca informację o tym, że user X ma uprawnienie Y.
    user_id - integer, klucz obcy do USERS
    acl_id - integer, klucz obcy do ACCESS_RIGHT
    klucz glowny na (user_id,acl_id)

Wtedy operacje o których piszesz mogłyby wyglądać mniej więcej tak:

-- sprawdzenie czy 'userek' ma uprawnienie 'permission'
-- zwraca 1 lub NULL
select 1
from
ACCESS_RIGHT ar,
ACL_USER acl,
USER u
where
u.login='userek' and
ar.acl_name='permission' and
ar.acl_id=acl.acl_id and
u.user_id=acl.user_id;

-- set permission
insert into ACL_USER (user_id,value_id)
select
u.user_id,
acl.acl_id
from
USER u,
ACCESS_RIGHT acl
where
u.login='userek' and
acl.acl_name='permission' and
not exists (select * from ACL_USER au where au.user_id=u.user_id and au.acl_id=acl.acl_id)

-- get permissions
select
ar.acl_name
from
ACCESS_RIGHT ar,
ACL_USER acl,
USER u
where
u.login='userek' and
u.user_id=acl.user_id and
ar.acl_id=acl.acl_id

-- remove permissions
delete from acl_user acl where exists (
select * from
access_right ar,
user u
where
u.login='userek' and
ar.acl_name='permission' and
u.user_id=acl.user_id and
acl.acl_id=ar.acl_id
)

Nie zostalo to przetestowane, ale koncepcja mysle ze powinna byc jasna.

pozdr,
yarel

1 użytkowników online, w tym zalogowanych: 0, gości: 1