Триггер срабатывающий при Select!

Black Jaguar
Дата: 18.11.2003 15:59:08
Господа, скажите пжалса возможно ли сделать триггер который бы страбатывал перед select...
ну точнее судя по ману где написано
CREATE TRIGGER trigger [ BEFORE | AFTER ] [ INSERT | DELETE | UPDATE [ OR ... ] ]
ON relation FOR EACH [ ROW | STATEMENT ]
EXECUTE PROCEDURE procedure
(args);
это сделать нельзя...
но может поскажите технологию как мне перед select-ом из данной таблицы вызвать
хранимую процедуру?
Stellar.
Дата: 18.11.2003 18:12:42
триггер на select повесить нельзя.
но можно сделать RULE

http://www.postgresql.org/docs/7.3/static/sql-createrule.html
Shweik
Дата: 20.11.2003 19:05:53
Между прочим с правилами на SELECT не все так уж здорово.
Прежде всего там возможен только INSTEAD да и то выполнить группу запросов в "( )" в 7.3.x нельзя. Насчет 7.4 ничего не скажу -
я его пререлиз только скачал и еще не устанавливал.
Black Jaguar
Дата: 20.11.2003 19:30:34
Да блин... лажа получается... я так понял что правила на select это только VIEW...
чё мне собственно нужно...
freeradius делает выборку из таблицы radcheck а потом radreply, так вот обращается оно туда в момент подключения пользователя к радиусу, мне надо чтобы поле одной записаи в radreply было изменено и в новом состоянии было возвращено радиусу....

почему это изменение делается именно в момент подключения пользователя? правильно потому что значение зависит от текущего времени...

также есть ограничение: НЕЛЬЗЯ МЕНЯТЬ ЗАПРОС РАДИУСА к бд... а он там вида SELECT a,b,c,d FROM radreply WHERE b='blablabla';

а то в какой записи будет произведено изменение зависит от значения поля b..

ВОТ ТАКАЯ ВОТ ПЕТРУШКА...
кто чё-ть подобное решал или просто знает чё делать подскажите.... а?
Shweik
Дата: 20.11.2003 19:55:03
Чуть конкретнее опиши чего ты хочешь, впрочем думаю что правило на
SELECT модифицирующее результаты вполне справиться с этой задачей.
Нечто похожее уже было.
Black Jaguar
Дата: 25.11.2003 17:22:50
Вобщем примерно так...
есть таблица
CREATE TABLE radreply (
id DECIMAL ( 20 ) DEFAULT nextval('radreply_id_seq'::text) NOT NULL,
UserName VARCHAR ( 30 ) NOT NULL DEFAULT '',
Attribute VARCHAR ( 30 ) NOT NULL,
op VARCHAR ( 2 ) DEFAULT '=' NOT NULL,
Value VARCHAR ( 40 ),
CONSTRAINT PK_radreply_id PRIMARY KEY (id),
CONSTRAINT TC_radreply_id CHECK (id>=0)
);
в ней хранится что-т вроде
jradius=# select * from radreply;
id | username | attribute | op | value
----+----------------+-----------+----+-------
0 | test_login0001 | Session-Timeout | := | 7200
(1 запись)

Session-Timeout означает время через которое будет отключен пользователь.

как происходит сам процесс:
прграмулина под названием freeradius по запросу точки доступа (кажется это так называется) запрашивает в БД некоторые параметры... это происходит при помощи запросов
authorize_check_query = "SELECT id, UserName, Attribute, Value, Op \
FROM ${authcheck_table} \
WHERE Username = '%{SQL-User-Name}' \
ORDER BY id"
authorize_reply_query = "SELECT id, UserName, Attribute, Value, Op \
FROM ${authreply_table} \
WHERE Username = '%{SQL-User-Name}' \
ORDER BY id"

они вызываются именно в этой последовательности.

в результате выполнения второго запроса должны быть выданы записи вроде
123 test_login0001 Session-Timeout := 32131
подсчет количества секунд для Session-Timeout подключающегося пользователя должен быть посчитан в момент подключения, т.к. он зависист от времени подключения (ну типа ночной/дневной тариф)...
вопрос в том как это посчитать?
Shweik
Дата: 25.11.2003 20:16:28
Решить таки можно, только спать охота..... 8(
Впрочем попробуем.
alter table radreply rename to tb_radreply;
create or replace function ftb_radreply() returns SETOF tb_radreply as
'
/* Тут воротишь всякие поправки,тарифы,фискал и прочая
*/
select * from tb_radreply;-- ну и возвращаеш сет своей таблицы
' LANGUAGE SQL;
А дальше малехо камамлы....
делаем вьюшку.
create or replace view radreply as select * from tb_brokers limit 0;
пресловутое правило на select только так как оно не понимает группу запросов в () подставляем функцию.
Название строго такое как написано.
create or replace
rule "_RETURN" as on
SELECT to resellrs
do INSTEAD
select * from ftb_radreply() as set1;
Название правил на insert и update произвольное.
create or replace
rule radreply_ins as on
INSERT to resellrs
do INSTEAD
insert into tb_radreply
(UserName , дальше список колонок ........)
values
(NEW.UserName , дальше список значений обрати внимание на NEW. .......);
с Update тоже самое - ну появляется на сцене префикс OLD.
Хотя update tebe как раз и не нужен!
Имхо получается неплохо - главное что нужно смотреть - чтоб небыло
цикличиских вызовов правил.... Ну про это есть в доке.
Shweik
Дата: 25.11.2003 20:20:27
Перечитал пост и тут же нашел ляп:
Вьюшку правильно делать так.
create or replace view radreply as select * from tb_radreply limit 0;
Black Jaguar
Дата: 26.11.2003 21:12:04
Поясни плиз что значит
---------------------------------------------------------
rule "_RETURN" as on
SELECT to resellrs
do INSTEAD
select * from ftb_radreply() as set1;
--------------------------------------------------------
ато не могупонять к чему это...

и еще почему используется "limit 0" в
create or replace view radreply as select * from tb_radreply limit 0;
это чё значит что надо выбрать 0

но тем не менее на сколько я понял ты предлагаешь подменить раельную таблицу на view? но это значит что прикаждой выборке, view будет перегенерится заново... я правильно пониммаю? просто у меня там реально будет от 1000 записей... а вычисление каждого Session-Timeout довольно ёмкая операция (я прикидывал)... но если другого способа нет...
или я чё-т не правильно понял?
Shweik
Дата: 26.11.2003 21:49:35
Да это замедляет - ну а как ты хотел? Приведи примеры из других SQL - диалектов.
rule "_RETURN" as on
SELECT to radreply
do INSTEAD
select * from ftb_radreply() as set1;
Это просто правило определяющее, что при SELECT-е из
radreply -ЗАМЕСТО выборки из таблицы - будет вызвана
функция ftb_radreply(), кстати псевдоним as set1 наверное излишен -
все равно там Множество возвращается.
Теперь про create or replace view radreply as select * from tb_radreply limit 0;
Да - это быстрее чем описывать заново кучу полей. И вьюшка получается -
точное зеркало.
limit 0 - понимаешь ли если ты напишешь тут например напишешь '1<>1' - так
когда-то я делал 8) - получишь тот же результат - до создания правила
"_RETURN" - это будет вечно пустая вьюшка ну а после.... она будет
связана с нашей функцией и предыдущий select определявший вьюшку затрется. Кстати наверное можно сделать вьюшку как select * from ftb_radreply() as set1; разницв никакой не будет
Насчет тормозов - все будет зависить от твоей функции рачета и я уверен что триггер тут срабатывал бы с примерно той же потерей скорости.