On Tue, 31 Dec 2013 22:20:15 +0000
Simon Slavin <slav...@bigfraud.org> wrote:

> > Meanwhile, here's a much more important failing that cannot be
> > worked around within SQL without a temporary table:
> > 
> >     sqlite> create table i ( i int primary key );
> >     sqlite> insert into i values (1);
> >     sqlite> insert into i values (2);
> >     sqlite> update i set i = i + 1;
> >     SQL error: column i is not unique
> 
> Is that not actually a serious bug in SQLite ?  

Well, a *bug* is defined as behavior in exception to the
documentation; I don't know if this behavior is documented.  

Definitely it's a flaw, and IMO the worst one.  As I said, it affects
any UPDATE of a column with a unique constraint or index.  

> My understanding of SQL is that checks for consistency should occur
> at the end of a transaction, not at each row of an UPDATE.  

Correct.  That's what the standard says, and what atomicity requires.  

The user interacts with the DBMS on a the basis of sets, a statement at
a time.  The above update statement can logically be executed, and the
user by definition has no control over *how* it is executed.  

> I hadn't realised this problem existed.

It's known to the developers; see the thread in around 6 September 2013
with the subject "UPDATE question".  

Since we're on the topic, let me describe a possible shortcut.  

The only general successful implementation strategy (within SQLite)
would be to write the updated rows to a temporary table, delete them
from the target table, and insert from the temporary.  But that's not
always necessary.  

In the update statement above, the query engine can ascertain that the
output of the update is greater than the input.  By working "backwards"
over the index -- updating the "last" row first -- the row-by-row
update could succeed.  With "just a little" work, the in-place update
algorithm could decide whether to work "backwards" or "forwards", and
succeed more often than it now does.  By brute force it could try one
and then the other before giving up.  

Will that always work?  No.  Consider

        sqlite> update i set i = random();
or 
        sqlite> update i set i = (select min(t) from T where i.i = T.i);
        
Nevertheless, a slightly more intelligent algorithm for in-place
updates would solve the class of problem for which the output is a
determinisitic function of the same column.  It might be easier to
implement within the existing framework than a general
copy-delete-insert strategy.  Whether it's worthwhile to bother, I
don't know.  

Happy New Year.  

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

Reply via email to