triggers kinda work
authorMarko Kreen <markokr@gmail.com>
Fri, 11 Apr 2008 12:27:38 +0000 (12:27 +0000)
committerMarko Kreen <markokr@gmail.com>
Fri, 11 Apr 2008 12:27:38 +0000 (12:27 +0000)
sql/londiste/expected/londiste_fkeys.out
sql/londiste/expected/londiste_provider.out
sql/londiste/expected/londiste_subscriber.out
sql/londiste/functions/londiste.node_add_table.sql
sql/londiste/functions/londiste.node_disable_triggers.sql [new file with mode: 0644]
sql/londiste/functions/londiste.node_prepare_triggers.sql [new file with mode: 0644]
sql/londiste/functions/londiste.node_refresh_triggers.sql [new file with mode: 0644]
sql/londiste/functions/londiste.node_remove_table.sql
sql/londiste/sql/londiste_install.sql
sql/londiste/structure/functions.sql
sql/londiste/structure/tables.sql

index 26a4adc1eb90e0ad7d73a1606d3914de0e861ceb..5c2a0cfbf711516413373ee745c63de46791cec0 100644 (file)
@@ -35,21 +35,21 @@ select * from londiste.set_add_table('branch_set', 'public.ref_3');
 (1 row)
 
 select * from londiste.node_add_table('branch_set', 'public.ref_1');
- ret_code | ret_desc 
-----------+----------
-      200 | OK
+ ret_code |         ret_desc          
+----------+---------------------------
+      200 | Table added: public.ref_1
 (1 row)
 
 select * from londiste.node_add_table('branch_set', 'public.ref_2');
- ret_code | ret_desc 
-----------+----------
-      200 | OK
+ ret_code |         ret_desc          
+----------+---------------------------
+      200 | Table added: public.ref_2
 (1 row)
 
 select * from londiste.node_add_table('branch_set', 'public.ref_3');
- ret_code | ret_desc 
-----------+----------
-      200 | OK
+ ret_code |         ret_desc          
+----------+---------------------------
+      200 | Table added: public.ref_3
 (1 row)
 
 select * from londiste.find_table_fkeys('public.ref_1');
index 727a3e04400717f7397e2b47dbe7489b747ed8e9..2fe6c83b009414e26b1f9ef5e1690d195c253231 100644 (file)
@@ -30,11 +30,15 @@ select * from pgq_set.create_node('aset', 'root', 'rnode', 'londiste_root', null
 (1 row)
 
 select * from londiste.node_add_table('aset', 'public.testdata_nopk');
-ERROR:  need key column
+ ret_code |                      ret_desc                      
+----------+----------------------------------------------------
+      400 | Primary key missing on table: public.testdata_nopk
+(1 row)
+
 select * from londiste.node_add_table('aset', 'public.testdata');
- ret_code | ret_desc 
-----------+----------
-      200 | OK
+ ret_code |           ret_desc           
+----------+------------------------------
+      200 | Table added: public.testdata
 (1 row)
 
 select * from londiste.node_get_table_list('aset');
@@ -44,9 +48,9 @@ select * from londiste.node_get_table_list('aset');
 (1 row)
 
 select * from londiste.node_remove_table('aset', 'public.testdata');
- ret_code | ret_desc 
-----------+----------
-      200 | OK
+ ret_code |            ret_desc            
+----------+--------------------------------
+      200 | Table removed: public.testdata
 (1 row)
 
 select * from londiste.node_remove_table('aset', 'public.testdata');
index b34a835e60c00501a7f6066df03d7fee53fb0257..b09399ae1b61ece5e4627fcbf13466530cc26188 100644 (file)
@@ -44,9 +44,9 @@ select * from londiste.set_add_table('branch_set', 'public.slavedata');
 (1 row)
 
 select * from londiste.node_add_table('branch_set', 'public.slavedata');
- ret_code | ret_desc 
-----------+----------
-      200 | OK
+ ret_code |           ret_desc            
+----------+-------------------------------
+      200 | Table added: public.slavedata
 (1 row)
 
 select * from londiste.node_get_table_list('branch_set');
@@ -56,9 +56,9 @@ select * from londiste.node_get_table_list('branch_set');
 (1 row)
 
 select * from londiste.node_remove_table('branch_set', 'public.slavedata');
- ret_code | ret_desc 
-----------+----------
-      200 | OK
+ ret_code |            ret_desc             
+----------+---------------------------------
+      200 | Table removed: public.slavedata
 (1 row)
 
 select * from londiste.node_remove_table('branch_set', 'public.slavedata');
index 09865a87078fa5121467965bffae2b20fec6d5f5..d3b3d82f04177ebc1d770e422d174ca4dcbee6f3 100644 (file)
@@ -20,7 +20,8 @@ begin
     fq_table_name := londiste.make_fqname(i_table_name);
     col_types := londiste.find_column_types(fq_table_name);
     if position('k' in col_types) < 1 then
-        raise exception 'need key column';
+        select 400, 'Primary key missing on table: ' || fq_table_name into ret_code, ret_desc;
+        return;
     end if;
 
     perform 1 from pgq_set.set_info where set_name = i_set_name;
@@ -36,7 +37,11 @@ begin
     end if;
 
     if pgq_set.is_root(i_set_name) then
-        perform londiste.set_add_table(i_set_name, fq_table_name);
+        select * into ret_code, ret_desc
+            from londiste.set_add_table(i_set_name, fq_table_name);
+        if ret_code <> 200 then
+            return;
+        end if;
     else
         perform 1 from londiste.set_table where set_name = i_set_name and table_name = fq_table_name;
         if not found then
@@ -45,16 +50,27 @@ begin
         end if;
     end if;
 
-    if pgq_set.is_root(i_set_name) then
-        select * into ret_code, ret_desc
-            from londiste.set_add_table(i_set_name, fq_table_name);
-        if ret_code <> 200 then
+    insert into londiste.node_table (set_name, table_name)
+        values (i_set_name, fq_table_name);
+
+    for ret_code, ret_desc in
+        select f.ret_code, f.ret_desc
+        from londiste.node_prepare_triggers(i_set_name, fq_table_name) f
+    loop
+        if ret_code > 299 then
             return;
         end if;
-    end if;
+    end loop;
+
+    for ret_code, ret_desc in
+        select f.ret_code, f.ret_desc
+        from londiste.node_refresh_triggers(i_set_name, fq_table_name) f
+    loop
+        if ret_code > 299 then
+            return;
+        end if;
+    end loop;
 
-    insert into londiste.node_table (set_name, table_name)
-        values (i_set_name, fq_table_name);
     select 200, 'Table added: ' || fq_table_name into ret_code, ret_desc;
     return;
 end;
diff --git a/sql/londiste/functions/londiste.node_disable_triggers.sql b/sql/londiste/functions/londiste.node_disable_triggers.sql
new file mode 100644 (file)
index 0000000..df5a075
--- /dev/null
@@ -0,0 +1,77 @@
+
+create or replace function londiste.node_disable_triggers(
+    in i_set_name   text,
+    in i_table_name text,
+    out ret_code    int4,
+    out ret_desc    text)
+returns setof record strict as $$
+-- ----------------------------------------------------------------------
+-- Function: londiste.node_disable_triggers(2)
+--
+--      Drop all registered triggers from particular table.
+-- ----------------------------------------------------------------------
+declare
+    tbl_oid oid;
+    fq_table_name text;
+    tg record;
+    is_active int4;
+begin
+    fq_table_name := londiste.make_fqname(i_table_name);
+    perform 1 from pgq_set.set_info where set_name = i_set_name;
+    if not found then
+        select 400, 'Unknown set: ' || i_set_name;
+        return next;
+        return;
+    end if;
+    tbl_oid := londiste.find_table_oid(fq_table_name);
+    for tg in
+        select tg_name, tg_type, tg_def from londiste.node_trigger
+         where set_name = i_set_name and table_name = fq_table_name
+         order by tg_name
+    loop
+        -- check if active
+        perform 1 from pg_catalog.pg_trigger
+         where tgrelid = tbl_oid
+           and tgname = tg.tg_name;
+        if found then
+            execute 'drop trigger ' || quote_ident(tg.tg_name)
+                || ' on ' || londiste.quote_fqname(fq_table_name);
+            select 200, 'Dropped trigger ' || tg.tg_name
+                || ' from table ' || fq_table_name
+                into ret_code, ret_desc;
+                return next;
+        end if;
+    end loop;
+    return;
+end;
+$$ language plpgsql security definer;
+
+create or replace function londiste.node_disable_triggers(
+    in i_set_name   text,
+    out ret_code    int4,
+    out ret_desc    text)
+returns setof record strict as $$
+-- ----------------------------------------------------------------------
+-- Function: londiste.node_disable_triggers(1)
+--
+--      Drop all registered triggers from set tables.
+-- ----------------------------------------------------------------------
+declare
+    t record;
+begin
+    for t in
+        select table_name from londiste.node_table
+         where set_name = i_set_name
+         order by nr
+    loop
+        for ret_code, ret_desc in
+            select f.ret_code, f.ret_desc
+                from londiste.node_disable_triggers(i_set_name, t.table_name) f
+        loop
+            return next;
+        end loop;
+    end loop;
+    return;
+end;
+$$ language plpgsql security definer;
+
diff --git a/sql/londiste/functions/londiste.node_prepare_triggers.sql b/sql/londiste/functions/londiste.node_prepare_triggers.sql
new file mode 100644 (file)
index 0000000..8e658fa
--- /dev/null
@@ -0,0 +1,50 @@
+
+create or replace function londiste.node_prepare_triggers(
+    in i_set_name   text,
+    in i_table_name text,
+    out ret_code    int4,
+    out ret_desc    text)
+returns setof record strict as $$
+-- ----------------------------------------------------------------------
+-- Function: londiste.node_prepare_triggers(2)
+--
+--      Regsiter Londiste trigger for table.
+-- ----------------------------------------------------------------------
+declare
+    t_name   text;
+    logtrg   text;
+    denytrg  text;
+    logtrg_name text;
+    denytrg_name text;
+    qname    text;
+    fq_table_name text;
+begin
+    fq_table_name := londiste.make_fqname(i_table_name);
+    select queue_name into qname from pgq_set.set_info where set_name = i_set_name;
+    if not found then
+        select 400, 'Set not found: ' || i_set_name into ret_code, ret_desc;
+        return next;
+        return;
+    end if;
+    logtrg_name := i_set_name || '_logtrigger';
+    denytrg_name := i_set_name || '_denytrigger';
+    logtrg := 'create trigger ' || quote_ident(logtrg_name)
+        || ' after insert or update or delete on ' || londiste.quote_fqname(fq_table_name)
+        || ' for each row execute procedure pgq.sqltriga(' || quote_literal(qname) || ')';
+    insert into londiste.node_trigger (set_name, table_name, tg_name, tg_type, tg_def)
+    values (i_set_name, fq_table_name, logtrg_name, 'root', logtrg);
+    select 200, logtrg into ret_code, ret_desc;
+    return next;
+
+    denytrg := 'create trigger ' || quote_ident(denytrg_name)
+        || ' before insert or update or delete on ' || londiste.quote_fqname(fq_table_name)
+        || ' for each row execute procedure pgq.denytriga(' || quote_literal(qname) || ')';
+    insert into londiste.node_trigger (set_name, table_name, tg_name, tg_type, tg_def)
+    values (i_set_name, fq_table_name, denytrg_name, 'non-root', denytrg);
+    select 200, denytrg into ret_code, ret_desc;
+    return next;
+
+    return;
+end;
+$$ language plpgsql security definer;
+
diff --git a/sql/londiste/functions/londiste.node_refresh_triggers.sql b/sql/londiste/functions/londiste.node_refresh_triggers.sql
new file mode 100644 (file)
index 0000000..76da2d2
--- /dev/null
@@ -0,0 +1,102 @@
+
+create or replace function londiste.node_refresh_triggers(
+    in i_set_name   text,
+    in i_table_name text,
+    out ret_code    int4,
+    out ret_desc    text)
+returns setof record strict as $$
+-- ----------------------------------------------------------------------
+-- Function: londiste.node_refresh_triggers(2)
+--
+--      Sync actual trigger state with registered triggers.
+-- ----------------------------------------------------------------------
+declare
+    tbl_oid oid;
+    fq_table_name text;
+    tg record;
+    is_root bool;
+    is_active int4;
+begin
+    fq_table_name := londiste.make_fqname(i_table_name);
+    perform 1 from pgq_set.set_info where set_name = i_set_name;
+    if not found then
+        select 400, 'Unknown set: ' || i_set_name;
+        return next;
+        return;
+    end if;
+    is_root := pgq_set.is_root(i_set_name);
+    tbl_oid := londiste.find_table_oid(fq_table_name);
+    for tg in
+        select tg_name, tg_type, tg_def from londiste.node_trigger
+         where set_name = i_set_name and table_name = fq_table_name
+         order by tg_name
+    loop
+        if tg.tg_type not in ('root', 'non-root') then
+            select 400, 'trigger ' || tg.tg_name
+                || ' on table ' || fq_table_name
+                || ' had unsupported type: ' || tg.tg_type
+                into ret_code, ret_desc;
+            return next;
+        else
+            -- check if active
+            select count(1) into is_active
+              from pg_catalog.pg_trigger
+             where tgrelid = tbl_oid
+               and tgname = tg.tg_name;
+
+            -- create or drop if needed
+            if (tg.tg_type = 'root') = is_root then
+                -- trigger must be active
+                if is_active = 0 then
+                    execute tg.tg_def;
+                    select 200, 'Created trigger ' || tg.tg_name
+                        || ' on table ' || fq_table_name
+                        into ret_code, ret_desc;
+                    return next;
+                end if;
+            else
+                -- trigger must be dropped
+                if is_active = 1 then
+                    execute 'drop trigger ' || quote_ident(tg.tg_name)
+                        || ' on ' || londiste.quote_fqname(fq_table_name);
+                    select 200, 'Dropped trigger ' || tg.tg_name
+                        || ' from table ' || fq_table_name
+                        into ret_code, ret_desc;
+                    return next;
+                end if;
+            end if;
+        end if;
+    end loop;
+    return;
+end;
+$$ language plpgsql security definer;
+
+create or replace function londiste.node_refresh_triggers(
+    in i_set_name   text,
+    out ret_code    int4,
+    out ret_desc    text)
+returns setof record strict as $$
+-- ----------------------------------------------------------------------
+-- Function: londiste.node_refresh_triggers(2)
+--
+--      Sync actual trigger state with registered triggers for all tables.
+-- ----------------------------------------------------------------------
+declare
+    t record;
+begin
+    for t in
+        select table_name from londiste.node_table
+         where set_name = i_set_name
+         order by nr
+    loop
+        for ret_code, ret_desc in
+            select f.ret_code, f.ret_desc
+                from londiste.node_refresh_triggers(i_set_name, t.table_name) f
+        loop
+            return next;
+        end loop;
+    end loop;
+    return;
+end;
+$$ language plpgsql security definer;
+
index ae350b067a5dca10dd5090f9fc5910f7ddec3d0d..b4875b12b0a1909877a0266fab6053a4a19195a9 100644 (file)
@@ -7,6 +7,17 @@ declare
     fq_table_name text;
 begin
     fq_table_name := londiste.make_fqname(i_table_name);
+
+    for ret_code, ret_desc in
+        select f.ret_code, f.ret_desc from londiste.node_disable_triggers(i_set_name, fq_table_name) f
+    loop
+        if ret_code > 299 then
+            return;
+        end if;
+    end loop;
+    delete from londiste.node_trigger
+        where set_name = i_set_name
+          and table_name = fq_table_name;
     delete from londiste.node_table
         where set_name = i_set_name
           and table_name = fq_table_name;
index 9bd55963152f2802a267ef0f43eb69cb2a495f3a..efb4f23e798282889dccd175251625bb4fb9c720 100644 (file)
@@ -3,6 +3,8 @@ set log_error_verbosity = 'terse';
 \i ../txid/txid.sql
 \i ../pgq/pgq.sql
 \i ../pgq_set/pgq_set.sql
-\i londiste.sql
+--\i londiste.sql
+\i structure/tables.sql
+\i structure/functions.sql
 \set ECHO all
 
index 06facfdffcfc63124f28397dd722ca0fc099efd1..bb2d8bb0392369028d7da9e2248ca6959e30aae6 100644 (file)
@@ -21,8 +21,9 @@
 
 -- Group: Internal functions
 \i functions/londiste.node_set_skip_truncate.sql
--- \i functions/londiste.node_create_trigger.sql
--- \i functions/londiste.node_refresh_trigger.sql
+\i functions/londiste.node_prepare_triggers.sql
+\i functions/londiste.node_refresh_triggers.sql
+\i functions/londiste.node_disable_triggers.sql
 -- \i functions/londiste.node_notify_change.sql
 
 -- Group: Utility functions
index 3b2e85335f1fea63bca08fdcba4f1692a2e7b411..b511b58b7069cf0266073a3d04b24fadf4b28244 100644 (file)
@@ -111,7 +111,7 @@ create table londiste.node_table (
 -- Columns:
 --      set_name        - set it belongs to
 --      table_name      - table name
---      tg_type         - any / root / non-root
+--      tg_type         - any / root / non-root / unknown?
 --      tg_name         - name for the trigger
 --      tg_def          - full statement for trigger creation
 -- ----------------------------------------------------------------------
@@ -122,7 +122,9 @@ create table londiste.node_trigger (
     tg_type             text not null,
     tg_def              text not null,
     foreign key (set_name, table_name) references londiste.node_table,
-    primary key (set_name, table_name, tg_name)
+    primary key (set_name, table_name, tg_name),
+    check (tg_type in ('root', 'non-root'))
+    -- check (tg_type in ('always', 'origin', 'replica', 'disabled'))
 );
 
 -- ----------------------------------------------------------------------