Thread: Affected # of Rows After TRIGGER/RULE Return

Affected # of Rows After TRIGGER/RULE Return

From
Volkan YAZICI
Date:
Hi,

I'm trying to fake DELETEs to a table using below methods:

  CREATE OR REPLACE FUNCTION mobileunit_fake_delete() RETURNS trigger AS $$
  BEGIN
      UPDATE mobileunit
         SET networkid = OLD.networkid + OLD.muid * 100000000000,
             groupid = 146688,
             plate = 'DELETED_' || OLD.plate
       WHERE muid = OLD.muid;

      RETURN NULL;
  END;
  $$ LANGUAGE plpgsql;

  CREATE TRIGGER mobileunit_fake_delete
      BEFORE DELETE ON mobileunit
      FOR EACH ROW EXECUTE PROCEDURE mobileunit_fake_delete();

or

  CREATE RULE mobileunit_fake_delete
  AS ON DELETE TO mobileunit
  DO INSTEAD
  UPDATE mobileunit
     SET networkid = CAST(OLD.networkid AS numeric(20)) + OLD.muid * 100000000000,
         groupid = 146688,
         plate = 'DELETED_' || OLD.plate
   WHERE muid = OLD.muid;

But unfortunately, both solutions make

  DELETE FROM mobileunit WHERE muid = ...

queries return 0 as # of affacted rows. And this causes JDBC
applications (specifically Hibernate) ROLLBACK query as some failure
occured. At least, shouldn't the latter one return 1 as # of affected
rows? Any ideas to fix this problem?


Regards.

P.S. Yep, I know code sucks badly. Trying to migrate a Microsoft SQL
     Server application to PostgreSQL.

Re: Affected # of Rows After TRIGGER/RULE Return

From
Gerald Quimpo
Date:
On Wednesday 14 May 2008 02:59:27 Volkan YAZICI wrote:
>       RETURN NULL;
<snip>

> queries return 0 as # of affacted rows.

> And this causes JDBC
> applications (specifically Hibernate) ROLLBACK query as some failure
> occured. At least, shouldn't the latter one return 1 as # of affected
> rows? Any ideas to fix this problem?
>
>
> Regards.
>
> P.S. Yep, I know code sucks badly. Trying to migrate a Microsoft SQL
>      Server application to PostgreSQL.

something to try (whether it's acceptable or not will depend on
requirements that you didn't mention in your original post).

Instead of trying to update the row in place, insert the row again,
but with the field you need to mangle (in your example, "plate",
in my example below, "k") already mangled.  this only works if
the field you're mangling is the primary key.  if some other field
is the primary key, you will need to mangle that too, if possible.
since you'll have already inserted the row, just return OLD and let
the old row actually be deleted.

there are other options but the above works pretty well unless
you have constraints that make it impossible.

here's an example:

drop table t cascade;

create table t(k text primary key,oldk text);

create or replace function t_trig_func() RETURNS TRIGGER
as $$
BEGIN
    raise notice '%',old.k;
    insert into t(k,oldk) values (OLD.k||'-DEL',OLD.k);
    return OLD;
END;
$$ language plpgsql;

create trigger t_trig AFTER delete on t
    for each row execute procedure t_trig_func();

insert into t values ('1','1');
insert into t values ('2','2');
insert into t values ('3','3');
insert into t values ('4','4');

delete from t where k=4;
select * from t;

when I run that, the delete gives:

NOTICE:  4
DELETE 1
Time: 0.888 ms

(the notice is from the raise notice in the trigger function).

tiger

--
Gerald Timothy Quimpo   bopolissimus@gmail.com
   It is no measure of health to be well adjusted to a profoundly sick
    society.
         -- Krishnamurti

Re: Affected # of Rows After TRIGGER/RULE Return

From
Volkan YAZICI
Date:
On Wed, 14 May 2008, Gerald Quimpo <bopolissimus.lists@gmail.com> writes:
> Instead of trying to update the row in place, insert the row again,
> but with the field you need to mangle (in your example, "plate",
> in my example below, "k") already mangled.  this only works if
> the field you're mangling is the primary key.  if some other field
> is the primary key, you will need to mangle that too, if possible.
> since you'll have already inserted the row, just return OLD and let
> the old row actually be deleted.

I've considered that too. But the problem is that there are nearly 50-60
tables referencing to the related row about the be deleted. Therefore,
if I'd return OLD from the trigger, all other rows referencing to OLD
will get deleted because of ON DELETE CASCADE. But, if there would be
some way to tell the ON DELETE CASCADE constraints that "Hey, don't move
yet. I'll INSERT a new row with what you thought to be missing
previously." there won't be a problem.

I hope I understand you correctly. Did I miss anything? Any ideas?


Regards.

Re: Affected # of Rows After TRIGGER/RULE Return

From
Gerald Quimpo
Date:
On Wednesday 14 May 2008 19:10:18 Volkan YAZICI wrote:
> On Wed, 14 May 2008, Gerald Quimpo <bopolissimus.lists@gmail.com> writes:
> > Instead of trying to update the row in place, insert the row again,
> > but with the field you need to mangle (in your example, "plate",
> > in my example below, "k") already mangled.  this only works if
> > the field you're mangling is the primary key.  if some other field
> > is the primary key, you will need to mangle that too, if possible.
> > since you'll have already inserted the row, just return OLD and let
> > the old row actually be deleted.
>
> I've considered that too. But the problem is that there are nearly 50-60
> tables referencing to the related row about the be deleted. Therefore,
> if I'd return OLD from the trigger, all other rows referencing to OLD
> will get deleted because of ON DELETE CASCADE. But, if there would be
> some way to tell the ON DELETE CASCADE constraints that "Hey, don't move
> yet. I'll INSERT a new row with what you thought to be missing
> previously." there won't be a problem.
>
> I hope I understand you correctly. Did I miss anything? Any ideas?

Not really :-).  I was just looking at the simplest possible thing that could
work.  I've looked at versioned/temporal databases.  But you probably
can't go there since it definitely adds a lot of complexity to your app
and queries.  Are you able to change your representation of "deleted"
rows?  e.g., can you have an

     is_deleted boolean not null default false

column there?  that's how i'd have gone, myself, instead of mangling
the plate number.

good luck.

tiger

--
Gerald Timothy Quimpo   bopolissimus@gmail.com
  What we call Progress is the exchange of one nuisance for anothe
   nuisance.
         -- Havelock Ellis

Re: Affected # of Rows After TRIGGER/RULE Return

From
Volkan YAZICI
Date:
On Wed, 14 May 2008, Gerald Quimpo <bopolissimus.lists@gmail.com> writes:
> Not really :-).  I was just looking at the simplest possible thing that could
> work.  I've looked at versioned/temporal databases.  But you probably
> can't go there since it definitely adds a lot of complexity to your app
> and queries.  Are you able to change your representation of "deleted"
> rows?  e.g., can you have an
>
>      is_deleted boolean not null default false
>
> column there?  that's how i'd have gone, myself, instead of mangling
> the plate number.

That's really how it should be done. But there are really significant
design mistakes made years ago, and I gave up messing with them. Will
just accomplish migration and that's all.


Regards.