You are correct.

Even though the standard says 'statement stability', I think that is less 
useful than transaction stability.  I personally think a reference to 'now' 
should be stable throughout a transaction (a static value set when 'now' first 
accessed in a transaction and  cleared on a commit or rollback [of the outer 
transaction only -- not changed on interim savepoint operations]) would be the 
most useful and logically consistent implementation.

If transactions are disabled then no static value is saved for the transaction 
and the behavior stays as it is.

This would require that the value of 'now' be cached in the transaction 
structure I suppose ...

On the other hand, if one knows that the value of 'now' is not stable then one 
can always bind a parameter with the appropriate value set from the host 
language (which is what I usually do anyway, even with other SQL 
implementations that do claim to have either statement or transaction stable 
concepts of 'now' since that is usually what one wants anyway).

> Keith Medcalf wrote:
> >> In C there are local variables, where you can save result of impure
> >> functions when it is important. There are no local variables in SQL
> >> - with even more extreme example shown in E.Pasma message nearby -
> >> `SELECT strftime('%f') AS q FROM t WHERE q <> q`;
> >> oh, by the way, `SELECT CURRENT_TIME AS q FROM t WHERE q <> q`
> >> trigger that bug too, I've just checked (and it took less than 2
> >> seconds to trigger).
> >
> > That is version specific.  What version of SQLite are you using?  The
> current version optimizes out the clause q <> q thusly:
> 
> No, it is NOT version specific.
> 
> strftime vs. CURRENT_TIME triggers racing differently (strftime trigger
> in inner
> loop [and return *random* rows, easily triggered in shell with big
> enough
> table], CURRENT_TIME trigger in outer loop [and *randomly* return all
> rows; not
> easy to trigger in shell, but still it is triggered by my perl script
> without
> much problem]), but still triggers it.
> 
> (By the way, better optimizer should've moved strftime out of inner loop
> as
> well; and even better optimizer should've eliminated all repeated calls
> for pure
> functions with constant arguments; but that's just "missing optimization
> opportunity/missing feature", not a "real bug"; and even if that
> optimization
> was implemented, it still would not have fixed racing between
> DATE('now',$foo)
> and DATE('now',$bar), as in OP's query).
> 
> > sqlite> .explain
> > sqlite> explain select value, current_time as q from x where q <> q
> and value < 1000000000;
> > SELECT item[0] = {0:0}
> >        item[1] = FUNCTION:current_time() AS q
> > FROM {0,*} = x
> > WHERE AND(REGISTER(1),LT({0:0},REGISTER(4)))
> > END
> > addr  opcode         p1    p2    p3    p4             p5  comment
> > ----  -------------  ----  ----  ----  -------------  --  ------------
> -
> > 0     Trace          0     0     0                    00
> > 1     Function       0     0     2     current_time(0)  00
> > 2     Function       0     0     3     current_time(0)  00
> 
> ...And as you see, current_time function evaluated *many* times (and
> there are
> no caching *inside* of current_time function, in *any* sqlite version).
> 
> > 3     Ne             3     1     2                    72
> > 4     Integer        1000000000  4     0                    00
> > 5     Goto           0     18    0                    00
> > 6     VOpen          0     0     0     vtab:6E06F0:50B800  00
> > 7     Copy           4     7     0                    00
> > 8     Integer        4     5     0                    00
> > 9     Integer        1     6     0                    00
> > 10    VFilter        0     16    5                    00
> > 11    IfNot          1     15    1                    00
> > 12    VColumn        0     0     8                    00
> > 13    Function       0     0     9     current_time(0)  00
> > 14    ResultRow      8     2     0                    00
> > 15    VNext          0     11    0                    00
> > 16    Close          0     0     0                    00
> > 17    Halt           0     0     0                    00
> > 18    Transaction    0     0     0                    00
> > 19    VerifyCookie   0     1     0                    00
> > 20    Goto           0     6     0                    00
> >
> > So you will either get all rows or none.
> 
> And? It should ALWAYS return NONE. It does not.
> 
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users



_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to