Thread: Conditional NOTIFY is not implemented

Conditional NOTIFY is not implemented

From
tomas@fabula.de
Date:
Hi,

Upgrading from 7.0.2 to 7.1.3 (great job, btw!), brought us
some problems. Watch the following:

|  versuch=# create table chkntfy (
|  versuch(#         NUMMER          integer         default 0        not null,
|  versuch(#         TEXT            varchar(255)    default '?'      not null
|  versuch(# );
|  CREATE
|  versuch=#
|  versuch=# CREATE RULE ru_u_chkntfy AS ON UPDATE TO chkntfy DO NOTIFY CHKNTFY;
|  CREATE
|  versuch=# insert into chkntfy (nummer,text) values ('1','eins');
|  INSERT 110522 1
|  versuch=# update chkntfy set nummer=10 where nummer = 1;
|  ERROR:  Conditional NOTIFY is not implemented
|  versuch=#

Matthew Copeland noted the same in pgsql-admin and was told to use triggers
instead of rules. Well, it's a little nuisance, since we don't have statement
triggers (you'd get a notify for each row modified, which in our case can
be a killer.)

Somehow the notify seems to take up the `where' qualifier of the query
triggering the rule (you don't get the error message if you use an unqualified
query).

Is this considered a bug? Is a fix in sight?

Regards
-- tomas

Re: Conditional NOTIFY is not implemented

From
Tom Lane
Date:
tomas@fabula.de writes:
>  versuch=# CREATE RULE ru_u_chkntfy AS ON UPDATE TO chkntfy DO NOTIFY CHKNTFY;
>  CREATE
>  versuch=# update chkntfy set nummer=10 where nummer = 1;
>  ERROR:  Conditional NOTIFY is not implemented

> Somehow the notify seems to take up the `where' qualifier of the query
> triggering the rule (you don't get the error message if you use an
> unqualified query).

> Is this considered a bug? Is a fix in sight?

Before 7.1, the system simply failed to account for the condition that
should be applied to the notify --- the notify ended up being fired all
the time, even if it shouldn't have been.  In this case, the notify
should only occur if there are rows in chkntfy with nummer = 1 --- but
pre-7.1, it'd occur regardless.  (We were rather fortunate to avoid a
crash, actually, since the code would attach a condition to a NOTIFY
querytree that should never have had one ... but then ignore it.)

Present behavior is to error out if the rewriter tries to attach a
nonempty condition to a NOTIFY query.

It'd be a simple code change to revert to the pre-7.1 behavior (notify
fires unconditionally), but actually making it work *correctly* is a
lot harder.  NOTIFYs don't normally have any plan associated with them
at all, so there's no way to test a query condition.

Since we've seen several complaints about the new behavior, whereas
no one ever complained about excess NOTIFYs pre-7.1, perhaps the best
solution in the short run is to revert to the old behavior.  We could
just document that NOTIFYs in rules are fired unconditionally.

Comments?
        regards, tom lane


Re: Conditional NOTIFY is not implemented

From
tomas@fabula.de
Date:
On Thu, Sep 06, 2001 at 03:16:26PM -0400, Tom Lane wrote:
> tomas@fabula.de writes:
> >  versuch=# CREATE RULE ru_u_chkntfy AS ON UPDATE TO chkntfy DO NOTIFY CHKNTFY;
> >  CREATE
> >  versuch=# update chkntfy set nummer=10 where nummer = 1;
> >  ERROR:  Conditional NOTIFY is not implemented
> 
> > Somehow the notify seems to take up the `where' qualifier of the query
> > triggering the rule (you don't get the error message if you use an
> > unqualified query).
> 
> > Is this considered a bug? Is a fix in sight?
> 
> Before 7.1, the system simply failed to account for the condition that
> should be applied to the notify --- the notify ended up being fired all
> the time, even if it shouldn't have been.  In this case, the notify
> should only occur if there are rows in chkntfy with nummer = 1 --- but
> pre-7.1, it'd occur regardless.  (We were rather fortunate to avoid a
> crash, actually, since the code would attach a condition to a NOTIFY
> querytree that should never have had one ... but then ignore it.)
> 
> Present behavior is to error out if the rewriter tries to attach a
> nonempty condition to a NOTIFY query.
> 
> It'd be a simple code change to revert to the pre-7.1 behavior (notify
> fires unconditionally), but actually making it work *correctly* is a
> lot harder.  NOTIFYs don't normally have any plan associated with them
> at all, so there's no way to test a query condition.
> 
> Since we've seen several complaints about the new behavior, whereas
> no one ever complained about excess NOTIFYs pre-7.1, perhaps the best
> solution in the short run is to revert to the old behavior.  We could
> just document that NOTIFYs in rules are fired unconditionally.
> 
> Comments?

Thanks for the clear explanation. I see now. Well -- I think either behavior
is a little strange, so I'd go for the one you think best for the moment
and stick with it, putting on a big red warning sign ;-)

My pattern of use for ``CREATE RULE... NOTIFY...'' was, up to now, to get
a notice when anything changed on a table and then go look what happened;
a `poor man's statement level trigger' if you wish. Thus, the old behavior
didn't bother me that much. I don't know how others are using it.

Come to think of it, the CREATE RULE ``triggers'' on statements anyway --
it looks at the parsed statement and is independent of the actual content
of the database: so the old behaviour seems a bit more natural to me:

``Look: someone has called an UPDATE on this table: I don't know whether it is going to hit any records, but...''

the CREATE RULE acts then as a kind of `qualifier barrier' and therefore the
NOTIFY doesn't see it.

What do you think?

Thanks again for your great work

Cheers
-- tomas


Re: Conditional NOTIFY is not implemented

From
Tom Lane
Date:
tomas@fabula.de writes:
> My pattern of use for ``CREATE RULE... NOTIFY...'' was, up to now, to get
> a notice when anything changed on a table and then go look what happened;
> a `poor man's statement level trigger' if you wish. Thus, the old behavior
> didn't bother me that much. I don't know how others are using it.

Yeah, that is the normal and recommended usage pattern for NOTIFY, so
getting a NOTIFY when nothing actually happened is fairly harmless.
(Undoubtedly that's why no one complained before.)

Changing the rewriter to error out when it couldn't really Do The Right
Thing seemed like a good idea at the time, but now it seems clear that
this didn't do anything to enhance the usefulness of the system.  Unless
someone objects, I'll change it back for 7.2.
        regards, tom lane


Re: Conditional NOTIFY is not implemented

From
tomas@fabula.de
Date:
On Fri, Sep 07, 2001 at 12:30:44AM -0400, Tom Lane wrote:
> tomas@fabula.de writes:
> > My pattern of use for ``CREATE RULE... NOTIFY...'' was [...]

> Yeah, that is the normal and recommended usage pattern for NOTIFY, so
> getting a NOTIFY when nothing actually happened is fairly harmless.
> (Undoubtedly that's why no one complained before.)
>
> Changing the rewriter to error out when it couldn't really Do The Right
> Thing seemed like a good idea at the time, but now it seems clear that
> this didn't do anything to enhance the usefulness of the system.  Unless
> someone objects, I'll change it back for 7.2.
>
>             regards, tom lane

I won't object ;-)

Thank you again
-- tomas

Re: Conditional NOTIFY is not implemented

From
Tom Lane
Date:
I said:
> Changing the rewriter to error out when it couldn't really Do The Right
> Thing seemed like a good idea at the time, but now it seems clear that
> this didn't do anything to enhance the usefulness of the system.  Unless
> someone objects, I'll change it back for 7.2.

Not having seen any objections, I've committed the change.  If you need
a fix in place before 7.2, it's really a trivial change: just replace
the elog calls (there are two) by "return".  See attached patch against
current sources.

            regards, tom lane


*** /home/postgres/pgsql/src/backend/rewrite/rewriteManip.c.orig    Wed Apr 18 16:42:55 2001
--- /home/postgres/pgsql/src/backend/rewrite/rewriteManip.c    Fri Sep  7 16:52:31 2001
***************
*** 592,606 ****

      if (parsetree->commandType == CMD_UTILITY)
      {
-
          /*
!          * Noplace to put the qual on a utility statement.
           *
!          * For now, we expect utility stmt to be a NOTIFY, so give a specific
!          * error message for that case.
           */
          if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
!             elog(ERROR, "Conditional NOTIFY is not implemented");
          else
              elog(ERROR, "Conditional utility statements are not implemented");
      }
--- 592,612 ----

      if (parsetree->commandType == CMD_UTILITY)
      {
          /*
!          * There's noplace to put the qual on a utility statement.
!          *
!          * If it's a NOTIFY, silently ignore the qual; this means that the
!          * NOTIFY will execute, whether or not there are any qualifying rows.
!          * While clearly wrong, this is much more useful than refusing to
!          * execute the rule at all, and extra NOTIFY events are harmless for
!          * typical uses of NOTIFY.
           *
!          * If it isn't a NOTIFY, error out, since unconditional execution
!          * of other utility stmts is unlikely to be wanted.  (This case is
!          * not currently allowed anyway, but keep the test for safety.)
           */
          if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
!             return;
          else
              elog(ERROR, "Conditional utility statements are not implemented");
      }
***************
*** 634,648 ****

      if (parsetree->commandType == CMD_UTILITY)
      {
-
          /*
!          * Noplace to put the qual on a utility statement.
           *
!          * For now, we expect utility stmt to be a NOTIFY, so give a specific
!          * error message for that case.
           */
          if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
!             elog(ERROR, "Conditional NOTIFY is not implemented");
          else
              elog(ERROR, "Conditional utility statements are not implemented");
      }
--- 640,652 ----

      if (parsetree->commandType == CMD_UTILITY)
      {
          /*
!          * There's noplace to put the qual on a utility statement.
           *
!          * See comments in AddQual for motivation.
           */
          if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
!             return;
          else
              elog(ERROR, "Conditional utility statements are not implemented");
      }

Re: Conditional NOTIFY is not implemented

From
Date:
On Fri, 7 Sep 2001 tomas@fabula.de wrote:

> On Fri, Sep 07, 2001 at 12:30:44AM -0400, Tom Lane wrote:
> > tomas@fabula.de writes:
> > > My pattern of use for ``CREATE RULE... NOTIFY...'' was [...]
>
> > Yeah, that is the normal and recommended usage pattern for NOTIFY, so
> > getting a NOTIFY when nothing actually happened is fairly harmless.
> > (Undoubtedly that's why no one complained before.)
> >
> > Changing the rewriter to error out when it couldn't really Do The Right
> > Thing seemed like a good idea at the time, but now it seems clear that
> > this didn't do anything to enhance the usefulness of the system.  Unless
> > someone objects, I'll change it back for 7.2.
> >
> >             regards, tom lane
>
> I won't object ;-)
>
> Thank you again
> -- tomas

I wouldn't really mind that either.  My employer wouldn't allow me to
change the current set of RULE/NOTIFY's to triggers so that we could
upgrade to 7.1.3 from 7.0.3, so having it act the same way in 7.2 as it
did in 7.0.3 would be nice for me.  :)

Matthew M. Copeland