[ic] Interchange and SQL-Ledger / dblink / and psql triggers (LONG)

Andrew Baerg andrewbaerg at yoursole.com
Tue Jan 25 16:09:37 EST 2005


On Tue, 25 Jan 2005 14:07:25 -0500, David Ratte wrote 
> Hello all, 
>  
> Last week I posed a question regarding getting data into SQL-Ledger  
> from a foreign application (i.e. interchange) and if anyone had any  
> successes with this configuration. 
>  
> The use of dblink and triggers. This was very interesting because it  
> means total independance of both applications as to keeping the data  
> in sync -- and either application changing would not effect this  
> stuff from working unless the db  structure changed. 
>  
> Pardon my length, but some might find what I'm doing useful, and  
> others to tell me why it won't work! 
>  
> Now this code here does work, but only if the sql-ledger customer  
> table is in the same database as interchanges userdb. 
>  
> I guess the ultimate question is, Can dblink be used inside an  
> plpgsql procedure, or is this just plain illegal?? 
 
As far as I know there is nothing illegal about this. Without taking the 
time to troubleshoot your code, I will give you a snippet of some plpgsql 
code using dblink which works for me. This code updates the userdb->company 
field with the customer->name field on insert/update on the sql-ledger 
customer table. The userdb and customer tables are in seperate databases, 
but on the same host, but it should make no difference if the databases were 
on different hosts. I am using postgresql 7.4.6 
 
===BEGIN CODE=== 
CREATE OR REPLACE FUNCTION customer_update() 
 RETURNS trigger AS 
'DECLARE 
    userdb_query text; 
    name text; 
    customernumber text; 
BEGIN 
    name := NEW.name; 
    customernumber := NEW.customernumber; 
    PERFORM dblink_connect(''dbname'',''dbname=dbname user=username''); 
    userdb_query :=  ''SELECT dblink_exec (''''dbname'''', ''''UPDATE userdb 
SET company = '''''' 
        || quote_literal(NEW.name) 
        || '''''' WHERE username = '''''' 
        || quote_literal(NEW.customernumber) 
        || '''''' '''')''; 
    EXECUTE userdb_query; 
    PERFORM dblink_disconnect(''edge''); 
RETURN NEW; 
END; 
' 
 LANGUAGE 'plpgsql' VOLATILE; 
 
drop trigger customer_update on customer; 
 
CREATE TRIGGER customer_update 
 AFTER UPDATE 
 ON customer 
 FOR EACH ROW 
 EXECUTE PROCEDURE customer_update(); 
 
===END CODE=== 
 
The quoting was enough to drive me crazy, but it does work very nicely. I am 
currently customizing interchange+sql-ledger for a company and will be 
making use of dblink for sql-ledger -> interchange synchronization.  
 
Andrew Baerg 
 
>  
> If I throw dblink into the mix, everything breaks: 
>  
> (working query) 
> select * from dblink_exec('testdb','insert into customer (id,name)values 
>  (DEFAULT,''i24NULL'')'); dblink_exec 
>    ----------------- 
>     INSERT 201975 1 
>     (1 row) 
>  
> this however, breaks down at hostname: 
> ===BAD CODE SNIP=== 
> CREATE OR REPLACE FUNCTION user_update() 
>  RETURNS trigger AS 
>  'BEGIN 
>    select * from dblink('hostaddr=192.168.1.1 dbname=test 
>  user=test','select name from customer') as t1(name varchar) ; 
>    if exists( select 1 from dblink ('hostaddr=192.168.1.1 dbname=test 
>  user=test', 'select * from customer WHERE customer.name = 
>  (new.lname||'', ''||NEW.fname)') ) then 
> ===END BAD CODE=== 
>  
> Here's what I came up with (and it works, but so far without dblink): 
>  
> ===BEGIN CODE update_user.sql=== 
> CREATE OR REPLACE FUNCTION user_update() 
>  RETURNS trigger AS ' 
>  BEGIN 
> --Let's see if the customer already exists in sql-ledger's customer 
database 
> --If the customer already exists, just update the existing record. 
>   if exists( select 1 from customer WHERE customer.name =  
> (new.lname||'', ''||NEW.fname) ) then UPDATE customer SET    --sql- 
> ledger has only one name field, interchange has lastname and  
> firstname -- Ucase(lcase(name)) normalizes 'jOe sMiTh' into 'Smith, 
>  Joe' to prevent dupes in sql-ledger     name = (initcap(NEW.lname) 
>  ||'', '' || initcap(NEW.fname)),    address1 = NEW.address1,         
>    address2=NEW.address2,           city=NEW.city,            
> state=NEW.state,           zipcode=NEW.zip,           
>  email=NEW.email,           phone=NEW.phone_day,            
> contact=initcap(NEW.fname)||'' ''||initcap(NEW.lname)        WHERE  
> customer.name = (new.lname||'', ''||NEW.fname);   else --Since we  
> decided the customer did not exist, lets add a new customer record  
> INSERT INTO customer ( name, address1, address2, city, state, 
>  zipcode, email, phone, contact ) VALUES (initcap(NEW.lname)||'', ''  
> ||initcap(NEW.fname),           NEW.address1,           NEW.address2, 
>            NEW.city,           NEW.state,           NEW.zip,          
>   NEW.email,           NEW.phone_day,           initcap(NEW.fname) 
> ||'' ''||initcap(NEW.lname)); 
>  
>    end if; 
>  
>    RETURN NEW; 
>    END; 
>    ' 
>    LANGUAGE 'plpgsql' VOLATILE; 
>  
> --If the trigger already exists, get rid of it so we can re-create it 
> DROP TRIGGER trans_update on transactions; 
>  
> CREATE TRIGGER trans_update 
>     BEFORE UPDATE 
>     ON transactions 
>     FOR EACH ROW 
> ====END CODE==== 
>  
> Thank you for your response, and please trim responses accordingly  
> to keep mail size down. 
>  
> -Dave Ratte 
>  
> ------------------------------------------------------- 
> _______________________________________________ 
> interchange-users mailing list 
> interchange-users at icdevgroup.org 
> http://www.icdevgroup.org/mailman/listinfo/interchange-users 
 
 
-- 
SOLE Custom Footbeds (http://www.yoursole.com) 
 


More information about the interchange-users mailing list