[sqlite] whish list for 2016

2016-01-03 Thread Eduardo Morras

I left the list some days and find this subject discussed and finished!!

Happy New Year 2016 to every colister and sqlite developer.

I add my list and a tiny explanation.

- Lock tables/indexes on cache (make them unevictable)

When a query use a big size table, other tables/index used in the query or 
other queries tables/indexes are dropped from sqlite cache. Lock content on 
cache could boost those queries that "fights" with a big size table. Mark a 
table as non cacheable could do the same in my use case.

As a working example I c from own code, a sqlite filesystem that stores file 
content as blob or as external file:

CREATE TABLE `file` (  \
`fid`   INTEGER,   \
`size`  INTEGER NOT NULL,  \
`permission`INTEGER NOT NULL DEFAULT 700,  \
`lock`  INTEGER NOT NULL DEFAULT 0,\
`blob_id`   INTEGER NOT NULL,  \
`owner_id`  INTEGER NOT NULL,  \
`group_id`  INTEGER NOT NULL,  \
`name`  TEXT NOT NULL, \
`external_path` TEXT NOT NULL, \
PRIMARY KEY(fid)   \
); 

CREATE TABLE `fsblob` (\
`bid`   INTEGER,   \
`size`  INTEGER NOT NULL,  \
`fid`   INTEGER NOT NULL,  \
`compressed`INTEGER NOT NULL DEFAULT 0,\
`content`   BLOB,  \
PRIMARY KEY(bid)   \
); \
   \

 Each time a user access a file, the "file" table (and others like "directory", 
"users") is evicted from cache (fsblob table fills cache) and needs to be 
reread and reparsed from disk for the next query. The problem is worse when 
multiple files are accessed. Making the cache bigger works upto some filesize, 
but locking the "important" tables on cache is the correct (I think) fix. As a 
workaround, I used multiple databases, one with fs metadata and attach others 
with file content (fsblob tables), but dropped it because other tecnical 
problems.

- Access table row by fileposition

In a read only scenario (no writer and/or no wal mode), read and parse the row 
content if we know it's absolute database file position or we know page number 
plus page position offset.

- Lock constant tables on file (stick table rows to page and/or fileposition)

This way, the file position of a row is fixed or easily calculated and can 
create/use hash indexes. Now I'm using a virtual table derived from Dr. Hipps 
csv virtual table years ago that creates a inmemory hash index of an external 
csv file, but it implies use of own sqlite3 version with virtual code and an 
additional file to database.

Additionally, if we can lock constant tables (defined as is by the developer) 
at the begining of the database file, mmap feature can cache constant/static 
data from those tables. In my app, it implies file, user, group, fs and other 
tiny tables (changes are rare) could be mmaped.

- Vacuum/backup reorder tables in database file

If we can tell vacuum or backup the order we want the tables be on the database 
file, on some scenarios (like mine;) ) moving tables to the begining (constant 
data) or the end (timestamp log growing table, f.ex.) could speed up queries 

- Vacuum/backup adds free pages for table/index grow

As far as I know, vacuum and backup write database tables, indexes and metadata 
without free pages. Adding free pages at the end of the pages that store a 
table or index, and reserve those pages for use of that table or index could 
hold back internal fragmentation.


There are others ideas but... hey 2017 is closer ;)

Thanks to Dr. Richard Hipps, Dan Kennedy and Joe Mistachkin for their 
exceptional work, and other colisters for their time and help.

---   ---
Eduardo Morras 


[sqlite] Apparent sqlite bug

2016-01-03 Thread Simon Slavin

> On 3 Jan 2016, at 6:52pm, Richard Hipp  wrote:
> 
> On 1/3/16, Simon Slavin  wrote:
>> 
>> I've seen references to imposter tables in the SQLite comments.  What is an
>> imposter table ?
> 
> An undocumented and unsupported feature that allows two or tables in
> the schema to refer to the same b-tree.  This is used by the RBU
> extension in order to update indexes and table independently of one
> another.

Thanks very much.  I liked the idea suggested by the name.  I can see how that 
would be useful.

Simon.


[sqlite] Apparent sqlite bug

2016-01-03 Thread Luuk


On 03-01-16 00:11, richard parkins wrote:
> An INSERT statement which fails with no explicit conflict clause appears to 
> throw away a pending SAVEPOINT.
> The following sequence demonstrates this behaviour
> SAVEPOINT demonstration;
> CREATE TABLE IF NOT EXISTS "PK" ( "first name" "TEXT",
> "last name" "TEXT",
> "address",
> PRIMARY KEY ( "first name", "last name" )
> ) WITHOUT ROWID;
> INSERT INTO "PK" default values;
> ROLLBACK TO demonstration;
>
> As expected, the insert fails with Error: NOT NULL constraint, but the 
> ROLLBACK statement then also fails with Error: no such savepoint.
> If INSERT is replaced by INSERT OR ABORT (which is supposed to be the 
> default), the ROLLBACK statement does not fail.
> Environment:- sqlite 3.9.2 built from the amalgamation, running on UBUNTU 
> Linux 14.04.3 LTS. SQL statements run with sqliteman built from 
> https://github.com/rparkins999/sqliteman.git.
>
> I originally saw this problem running the INSERT inside sqliiteman. If you 
> run sqliteman, create the PK table as shown but omitting the WITHOUT ROWID 
> clause, insert a row of all nulls, and then try using sqliteman's Alter Table 
> function (accessible by right click on the table name) and try to change it 
> to a WITHOUT ROWID table, you'll see no such savepoint: ALTER_TABLE Unable to 
> fetch row. This is caused by sqliteman's internal cleanup algorithm trying to 
> roll back after failing to insert the data from the old table into its newly 
> created WITHOUT ROWID table, and not being able to do so because the 
> savepoint has vanished. Changing INSERT in my code to INSERT OR ABORT makes 
> the rollback work properly.
> Richard Parkins
>


a ROLLBACK was done because of the Error...

compare your code with this example:
SQLite version 3.8.11.1 2015-07-29 20:00:57
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> CREATE TABLE IF NOT EXISTS "PK" ( "first name" "TEXT",
...> "last name" "TEXT",
...> "address",
...> PRIMARY KEY ( "first name", "last name" )
...> ) WITHOUT ROWID;
sqlite> SAVEPOINT demonstration;
sqlite> INSERT INTO "PK" values ("1","1","1");
sqlite> SELECT * FROM "PK";
1|1|1
sqlite> INSERT INTO "PK" default values;
Error: NOT NULL constraint failed: PK.first name
sqlite> SELECT * FROM "PK";
sqlite>
sqlite>





[sqlite] Apparent sqlite bug

2016-01-03 Thread Simon Slavin

On 3 Jan 2016, at 5:49pm, Richard Hipp  wrote:

>   /* Make sure every column of the PRIMARY KEY is NOT NULL.  (Except,
>   ** do not enforce this for imposter tables.) */

I've seen references to imposter tables in the SQLite comments.  What is an 
imposter table ?

Simon.


[sqlite] Apparent sqlite bug

2016-01-03 Thread Richard Hipp
On 1/3/16, Simon Slavin  wrote:
>
> On 3 Jan 2016, at 5:49pm, Richard Hipp  wrote:
>
>>   /* Make sure every column of the PRIMARY KEY is NOT NULL.  (Except,
>>   ** do not enforce this for imposter tables.) */
>
> I've seen references to imposter tables in the SQLite comments.  What is an
> imposter table ?
>

An undocumented and unsupported feature that allows two or tables in
the schema to refer to the same b-tree.  This is used by the RBU
extension in order to update indexes and table independently of one
another.
-- 
D. Richard Hipp
drh at sqlite.org


[sqlite] Apparent sqlite bug

2016-01-03 Thread Richard Hipp
On 1/3/16, Luuk  wrote:
>
>
> On 03-01-16 00:11, richard parkins wrote:
>> An INSERT statement which fails with no explicit conflict clause appears
>> to throw away a pending SAVEPOINT.
>> The following sequence demonstrates this behaviour
>> SAVEPOINT demonstration;
>> CREATE TABLE IF NOT EXISTS "PK" ( "first name" "TEXT",
>> "last name" "TEXT",
>> "address",
>> PRIMARY KEY ( "first name", "last name" )
>> ) WITHOUT ROWID;
>> INSERT INTO "PK" default values;
>> ROLLBACK TO demonstration;
>>
>> As expected, the insert fails with Error: NOT NULL constraint, but the
>> ROLLBACK statement then also fails with Error: no such savepoint.
>
> a ROLLBACK was done because of the Error...
>

Yeah, but a constraint failure should only terminate the one statement
that encountered the problem and should *not* rollback the
transaction.

The problem is that the NOT NULL constraint on the PRIMARY KEY of a
WITHOUT ROWID table was defaulting to give ON CONFLICT ROLLBACK
behavior instead of ON CONFLICT ABORT, as it should.  I'm currently
testing the following fix:

Index: src/build.c
==
--- src/build.c
+++ src/build.c
@@ -1772,11 +1772,11 @@

   /* Make sure every column of the PRIMARY KEY is NOT NULL.  (Except,
   ** do not enforce this for imposter tables.) */
   if( !db->init.imposterTable ){
 for(i=0; iaCol[pPk->aiColumn[i]].notNull = 1;
+  pTab->aCol[pPk->aiColumn[i]].notNull = OE_Abort;
 }
 pPk->uniqNotNull = 1;
   }

   /* The root page of the PRIMARY KEY is the table root page */

Assuming the patch above works, I'll check in the fix in a few minutes...
-- 
D. Richard Hipp
drh at sqlite.org