Trigger with parameters

From: lucas(at)presserv(dot)org
To: pgsql-sql(at)postgresql(dot)org
Subject: Trigger with parameters
Date: 2005-03-18 19:10:58
Message-ID: 20050318161058.34vug165zg9c8o88@www.presserv.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-sql

Hi,
I am building a generic database in postgresql.
And I am having a lot of problem.... Yes, I am just studing and learning about
postgres.
Lets go:
My database have two schemas:
1 - The MAIN schema
2 - The System schema.
I created the system schema that contains the table_fields register for the Main
tables.
Ie:
...# createdb -U postgres test
...# createlang -d test -U postgres plpgsql
...# createlang -d test -U postgres pltcl
...# psql -U postgres test

CREATE SCHEMA main_system;
CREATE SCHEMA main;

CREATE TABLE main_system.products_codes (field varchar(30) primary key, "check"
text);
INSERT INTO main_system.products_codes VALUES ('internal',$$NOT EXISTS(select *
from main.products_codes where field_name='internal' and value='$value')$$);
INSERT INTO main_system.products_codes VALUES ('barcode','true');

CREATE TABLE main.products (id serial primary key, description varchar(100),
field1 integer, fieldx varchar(10));
INSERT INTO main.products(id,description) VALUES (1,'Computer product');

CREATE TABLE main.products_codes (id serial primary key, "references" integer
references MAIN.PRODUCTS, field_name varchar(30) references
MAIN_SYSTEM.PRODUCTS_CODES, "value" varchar(50));
INSERT INTO main.products_codes("references",field_name,"value") values
(1,'internal','COMPUTER-1');
INSERT INTO main.products_codes("references",field_name,"value") values
(1,'barcode','1234567890123');

In my database I can create how much products codes fields I like just inserting
a record into MAIN_SYSTEM.PRODUCTS_CODES table.
Okay, then I created another function that cat the fields types for the main
table:

create or replace FUNCTION getfieldvalue(text,text,integer,varchar(30)) returns
text as
$$
set schema_name $1;
set table_name $2;
set references_value $3;
set field_value $4;
set references_name {"references"}
set field_name {"field_name"}
set point "."
spi_exec "select value as getfieldvalue from $schema_name$point$table_name
where $references_name = $references_value and $field_name = '$field_value'";
return $getfieldvalue;
$$ language 'pltcl';

SELECT getfieldvalue('main','products_codes',1,'internal'); --Will return the
Internal product code for product id 1
SELECT getfieldvalue('main','products_codes',1,'barcode'); --Will return the
Barcode for product id 1

With this function I can view the "main_system fields", If in the future I would
need to create a new code field (ie), its so easy, just type:
INSERT INTO main_system.products_codes values ('mynewcodefield','true');
And the main.products_codes will references to this new field.

The main_system.products_codes have two colums:
1-"field" as a field name
2-"check" as a validate check before insert into the main table references.
This check (2) will be executed before all "insert or update" (trigger) the
main table references (main.products_codes), for example if I want to UNIQUE
internal fields (inserted to me) I need to type "check" colums like: "NOT
EXISTS(select * from main.products_codes where field_name='internal' and
value='$value')";
The $value variable will be used into another function (pltcl) called by
Trigger.
The function:

--system_getcheckfieldvalue(schema name, table name, field name) will return
the CHECK necessary to Trigger.
CREATE or REPLACE FUNCTION system_getcheckfieldvalue(text, text, text) returns
text as
$$
set system_name "_system";
set schema_name $1;
set table_name $2;
set field_name $3;
set select_query {select "check" AS system_getcheckfieldvalue from };
set select_filter { where "field"='};
set close_select_filter "'";
set point ".";
spi_exec
$select_query$schema_name$system_name$point$table_name$select_filter$field_name$close_select_filter;
return $system_getcheckfieldvalue;
$$ language 'pltcl';
SELECT system_getcheckfieldvalue('main','products_codes','internal'); --Will
return the query (not exists(select......
SELECT system_getcheckfieldvalue('main','products_codes','barcode'); --Will
return "TRUE"

--system_checkfieldvalue (schema name, table name, field name, value
simulation) will return if the "value simulation" is Correct - True/False
CREATE or REPLACE FUNCTION system_checkfieldvalue (text, text, text, text)
returns bool as
$$
set schema_name $1;
set table_name $2;
set field_name $3;
set value $4;
set result true;
spi_exec "select
system_getcheckfieldvalue('$schema_name','$table_name','$field_name')";
set sql_query [subst -nocommands $system_getcheckfieldvalue];
spi_exec "select $sql_query as result";
return $result;
$$ language 'pltcl';
SELECT system_checkfieldvalue('main','products_codes','internal','COMPUTER-1');
--Will return FALSE (becouse there is a product with internal code COMPUTER-1
SELECT system_checkfieldvalue('main','products_codes','internal','COMPUTER-2');
--Will return TRUE (becouse there is NOT a product with internal code COMPUTER-2

Okay, but look the problem:
When I try to create a Trigger procedure to check (with the
system_checkfieldvalue() function) the Postgresql doesn't support the function
with parameters!!!

CREATE FUNCTION trigger_system_checkfieldvalue(schema_name text, table_name
text) RETURNS trigger AS
$$
BEGIN
select
system_checkfieldvalue(schema_name,table_name,NEW.field_name,NEW.value) as
result;
IF NOT result THEN
RAISE EXCEPTION 'The validate of the system field name is False';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER products_codes_checkfieldvalue BEFORE INSERT OR UPDATE ON
main.products_codes FOR EACH ROW EXECUTE PROCEDURE
trigger_system_checkfieldvalue('main','products_codes');
------- ERROR: function trigger_system_checkfieldvalue() does not exist

But the function trigger_system_checkfieldvalue() EXIST! With (text,text)
parameters.
I can't built the trigger for this table (main.products_codes) using the check
field in main_system.products_codes.
What is wrong???

Sorry for the big text mail message, but I think if I did not put the database
definitions, it will be very difficult to understand.
Thanks (and sorry again)...

Lucas Vendramin,
Brazil

Responses

Browse pgsql-sql by date

  From Date Subject
Next Message PFC 2005-03-18 19:54:45 Re: best way to swap two records (computer details)
Previous Message Octavio Alvarez 2005-03-18 17:57:25