Re: [sqlite] Trigger firing order

2017-07-22 Thread Jean-Luc Hainaut

On 21/07/2017 19:00, Simon Slavin wrote:


I’m minded to leave things as they are, with the order undefined.  If you 
really want to trigger a number of different operations in a specific order, 
put those operations all in one trigger, one after another.


Yes, possible now with the reminder of Peter: inserts can be conditional 
as well.



Alternatively, instead of having
...
have

Operation A
Trigger A1 on operation A performs operation B
Trigger B1 on operation B performs operation C
Trigger A3 on operation A performs operation D

That way you’ll know that you’ll get either ABCD or ABDC, but either way C will 
be executed after B.


Right, but not applicable in my special case: B is a global timestamp 
server that delivers unique timestamp Id's that are further used by 
several operations (e.g., closing the current state then creating a new 
current state). So trigger B1 does not know which operation will be 
performed next. Only triggers of type A1 know.



I have a question.  Would you expect to see depth-first or width-first 
recursion, and why ?


I suppose you refer to the order cascading triggers must be fired, as in 
the architecture mentioned above. Am I right?
Quite difficult question, to which I have no general answer (probably, 
there is none). In MY case (automatic management of transaction time 
temporal DB), I would say that a depth-first execution would be the most 
natural.
 If action A triggers actions B1 and B2, and action B1 triggers actions 
C11 and C12, I think that the final state of the data should be easier 
to understand if it results from sequence A.B1.C11.C12.B2, even if B2 
modifies the result of A.B1.C11.C12. I can imagine that the result of 
A.B1.B2.C11.C12 could lead, in some cases, to unexpected final states.
It seems that depth-first order is applied by Oracle (I don't know for 
others), though the protocol is fairly complicated by their "mutating 
table" concept, which often leads to convoluted programming.
The documentation is unclear but it seems to suggest that the 
"follows/precedes" clauses apply to select the next sibling trigger 
after the child triggers have completed. But I may be wrong!


Thanks for the suggestions and discussion

JL

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] Trigger firing order

2017-07-22 Thread Jean-Luc Hainaut

On 21/07/2017 18:13, petern wrote:

a programming pattern that is missing in SQLite trigger body: "if (new.C1

<> old.C1) then ".  It can be simulated for updates ("update
... where ... and new.C1 <> old.C1") but not for inserts ("insert" has no
"where" clause).

Maybe so.  But, INSERT can accept data rows from a SELECT statement which
both does have a WHERE clause and is aware of the trigger body variables.


Quite right! Didn't think of this.  Now, all invidual triggers have been 
gathered into a single one.


Thanks

JL


___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] Trigger firing order

2017-07-21 Thread Simon Slavin
On 21 Jul 2017, at 5:52pm, Simon Slavin  wrote:

> On 21 Jul 2017, at 4:27pm, Jean-Luc Hainaut  
> wrote:
> 
>> Hence my modest proposal: wouldn't it be a nice idea to make this unofficial 
>> order a feature of SQLite (just like DB2)? This would make the multiple 
>> triggers of a kind much more useful as it currently are.
> 
> I’m minded to leave things as they are, with the order undefined.  If you 
> really want to trigger a number of different operations in a specific order, 
> put those operations all in one trigger, one after another.

Alternatively, instead of having

Operation A
Trigger A1 on operation A performs operation B
Trigger A2 on operation A performs operation C
Trigger A3 on operation A performs operation D

have

Operation A
Trigger A1 on operation A performs operation B
Trigger B1 on operation B performs operation C
Trigger A3 on operation A performs operation D

That way you’ll know that you’ll get either ABCD or ABDC, but either way C will 
be executed after B.

> I have a question.  Would you expect to see depth-first or width-first 
> recursion, and why ?

Still interested in this.

Simon.
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] Trigger firing order

2017-07-21 Thread Simon Slavin


On 21 Jul 2017, at 4:27pm, Jean-Luc Hainaut  wrote:

> Hence my modest proposal: wouldn't it be a nice idea to make this unofficial 
> order a feature of SQLite (just like DB2)? This would make the multiple 
> triggers of a kind much more useful as it currently are.

I’m minded to leave things as they are, with the order undefined.  If you 
really want to trigger a number of different operations in a specific order, 
put those operations all in one trigger, one after another.

I have a question.  Would you expect to see depth-first or width-first 
recursion, and why ?

Simon.
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] Trigger firing order

2017-07-21 Thread petern
> a programming pattern that is missing in SQLite trigger body: "if (new.C1
<> old.C1) then ".  It can be simulated for updates ("update
... where ... and new.C1 <> old.C1") but not for inserts ("insert" has no
"where" clause).

Maybe so.  But, INSERT can accept data rows from a SELECT statement which
both does have a WHERE clause and is aware of the trigger body variables.

https://sqlite.org/lang_insert.html

Taking your example NEW.C1 and OLD.C1,  statements like  INSERT INTO 
SELECT  [FROM ] WHERE   AND/OR 
are perfectly well formed.

SELECT statements without FROM clause are also perfectly well formed:

INSERT INTO   SELECT NEW.C1 WHERE NEW.C1<>OLD.C1;

I've often read complaints on this forum about how SQLite's
non-deterministic trigger firing order is somehow "deliberately crazy".
The truth is the documentation is simply telling you that race conditions
are possible due to idiosyncratic query plans or lock acquisition order.
Yes, I too would prefer to have conditional statements better than SELECT
RAISE(IGNORE) in the trigger body.  It would save a lot of duplicate code
in terms of triggers that differ only by a few characters in the body and
WHEN clause.  But, one learns to make do.











On Fri, Jul 21, 2017 at 8:27 AM, Jean-Luc Hainaut <
jean-luc.hain...@unamur.be> wrote:

> Hello all,
>
> My question concerns the order (deterministic or not) in which triggers of
> the same kind (same table, same event, same position) fire.
>
> My application is a temporal database in which each table stores the
> history of one attribute of a set of entities. A view collects the last
> value of each table to build the current state of these entities.
>
> Let us simplify the problem as follows:
> 1. The DB comprises base tables T1(K,C1,..), T2(K,C2,..), T3(K,C3,..).
> Each table comprises primary key K + column Ci + some system data.
> 2. SQL view T(K,C1,C2,C3) collects, for each value of K, the last value
> from each base table.
> 3. Users update data through view T with such queries as "update T set
> C1='f', C3='g' where K=12"
> 4. "instead of" triggers translate this update into operations on those
> base tables that are affected by the update, here T1 and T3.
> 5. More precisely, the translation of this update proceeds in two steps:
> 5.1 a value "v" is computed and stored in a reference table (typically
> the current_date). This operation must be performed first.
> 5.2 for each base table affected, an "update" then an " insert" are
> performed, using value "v". These operations can be performed in any order.
>
> Each operation is controlled by a trigger "instead of update on T".  The
> trigger of the first step is unconditional (no "when" clause). Each
> operation of step 2 is controlled by a trigger with a filter like "when
> new.C1 <> old.C1".
>
> The problem is that the operation of step 1 MUST be performed BEFORE the
> operations of step 2. So, technically, the trigger of step 1 must fire
> before those of step 2.
> In most DBMS (notably Oracle, DB2, PostgreSQL, SQL Server, InterBase),
> firing order of similar triggers can be specified, either explicitly or
> according to naming or creation time rules (no problem in MySQL: only one
> trigger of a kind is allowed!).
> SQLite allows multiple triggers of the same kind, which is a very good
> thing, but its documentation tells nothing on the firing order issue, which
> seems to be interpreted as: "firing order is arbitrary".  This considerably
> limits its usefulness.
>
> The usual responses to trigger ordering problems in forums are of two
> kinds:
> - "Your schema probably is flawed. Fix it."
> - "Gather all your triggers into a single one."
>
> No, my schema is not flawed and gathering my triggers into a single one is
> impossible since it would require a programming pattern that is missing in
> SQLite trigger body: "if (new.C1 <> old.C1) then ".  It can
> be simulated for updates ("update ... where ... and new.C1 <> old.C1") but
> not for inserts ("insert" has no "where" clause).
>
> It seems that, in current SQLite implementations, trigger firing order is
> not quite arbitrary. In several tests I (and others) performed, triggers
> appear to always fire in "inverse creation time" order.
>
> Hence my modest proposal: wouldn't it be a nice idea to make this
> unofficial order a feature of SQLite (just like DB2)? This would make the
> multiple triggers of a kind much more useful as it currently are.
>
> Thanks for your attention
>
> Have a nice day
>
> Jean-Luc Hainaut
>
> ___
> sqlite-users mailing list
> sqlite-users@mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


[sqlite] Trigger firing order

2017-07-21 Thread Jean-Luc Hainaut

Hello all,

My question concerns the order (deterministic or not) in which triggers 
of the same kind (same table, same event, same position) fire.


My application is a temporal database in which each table stores the 
history of one attribute of a set of entities. A view collects the last 
value of each table to build the current state of these entities.


Let us simplify the problem as follows:
1. The DB comprises base tables T1(K,C1,..), T2(K,C2,..), T3(K,C3,..). 
Each table comprises primary key K + column Ci + some system data.
2. SQL view T(K,C1,C2,C3) collects, for each value of K, the last value 
from each base table.
3. Users update data through view T with such queries as "update T set 
C1='f', C3='g' where K=12"
4. "instead of" triggers translate this update into operations on those 
base tables that are affected by the update, here T1 and T3.

5. More precisely, the translation of this update proceeds in two steps:
5.1 a value "v" is computed and stored in a reference table 
(typically the current_date). This operation must be performed first.
5.2 for each base table affected, an "update" then an " insert" are 
performed, using value "v". These operations can be performed in any order.


Each operation is controlled by a trigger "instead of update on T".  The 
trigger of the first step is unconditional (no "when" clause). Each 
operation of step 2 is controlled by a trigger with a filter like "when 
new.C1 <> old.C1".


The problem is that the operation of step 1 MUST be performed BEFORE the 
operations of step 2. So, technically, the trigger of step 1 must fire 
before those of step 2.
In most DBMS (notably Oracle, DB2, PostgreSQL, SQL Server, InterBase), 
firing order of similar triggers can be specified, either explicitly or 
according to naming or creation time rules (no problem in MySQL: only 
one trigger of a kind is allowed!).
SQLite allows multiple triggers of the same kind, which is a very good 
thing, but its documentation tells nothing on the firing order issue, 
which seems to be interpreted as: "firing order is arbitrary".  This 
considerably limits its usefulness.


The usual responses to trigger ordering problems in forums are of two kinds:
- "Your schema probably is flawed. Fix it."
- "Gather all your triggers into a single one."

No, my schema is not flawed and gathering my triggers into a single one 
is impossible since it would require a programming pattern that is 
missing in SQLite trigger body: "if (new.C1 <> old.C1) then statement>".  It can be simulated for updates ("update ... where ... and 
new.C1 <> old.C1") but not for inserts ("insert" has no "where" clause).


It seems that, in current SQLite implementations, trigger firing order 
is not quite arbitrary. In several tests I (and others) performed, 
triggers appear to always fire in "inverse creation time" order.


Hence my modest proposal: wouldn't it be a nice idea to make this 
unofficial order a feature of SQLite (just like DB2)? This would make 
the multiple triggers of a kind much more useful as it currently are.


Thanks for your attention

Have a nice day

Jean-Luc Hainaut

___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users