Re: [sqlite] Conflict between snapshots and checkpoints

2019-09-29 Thread Gwendal Roué
Yes, this is exactly as you say. Isolation is very important, and I
carefully make sure that it is guaranteed to users who need it. This has
been working well for a few years now, GRDB.swift is very robust. My recent
focus was on SQLite snapshots, and you and other members of this mailing
list have been very helpful by completing the existing documentation :-)

Gwendal

On Sun, Sep 29, 2019 at 7:41 PM Richard Damon 
wrote:

> On 9/29/19 11:40 AM, Gwendal Roué wrote:
> > Thank you very much Keith.
> >
> > Apologies for my imprecise vocabulary, and the use of the same "snapshot"
> > word with different meanings.
> >
> > I have used the term "snapshot isolation" as used in
> > https://www.sqlite.org/isolation.html; But I'll remember about
> > REPEATABLE-READ isolation.
> >
> > I also thank you very much for confirming that preventing checkpoints
> > allows the WAL markers to remain valid.
> >
> > My goal is to provide a set of concurrency primitives that are useful for
> > GUI app developers. I'm learning a lot about SQLite in the process, of
> > course.
>
> And since you reused the connection (otherwise you just need to keep the
> transaction open and the snapshot was preserved) you don't have isolation.
>
> Quote:
>
>
> No Isolation Between Operations On The Same Database Connection
>
> SQLite provides isolation between operations in separate database
> connections. However, there is no isolation between operations that
> occur within the same database connection.
>
>
>
> --
> Richard Damon
>
> ___
> 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


Re: [sqlite] Conflict between snapshots and checkpoints

2019-09-29 Thread Richard Damon
On 9/29/19 11:40 AM, Gwendal Roué wrote:
> Thank you very much Keith.
>
> Apologies for my imprecise vocabulary, and the use of the same "snapshot"
> word with different meanings.
>
> I have used the term "snapshot isolation" as used in
> https://www.sqlite.org/isolation.html; But I'll remember about
> REPEATABLE-READ isolation.
>
> I also thank you very much for confirming that preventing checkpoints
> allows the WAL markers to remain valid.
>
> My goal is to provide a set of concurrency primitives that are useful for
> GUI app developers. I'm learning a lot about SQLite in the process, of
> course.

And since you reused the connection (otherwise you just need to keep the
transaction open and the snapshot was preserved) you don't have isolation.

Quote:


No Isolation Between Operations On The Same Database Connection

SQLite provides isolation between operations in separate database
connections. However, there is no isolation between operations that
occur within the same database connection.



-- 
Richard Damon

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


Re: [sqlite] Conflict between snapshots and checkpoints

2019-09-29 Thread Gwendal Roué
Thank you very much Keith.

Apologies for my imprecise vocabulary, and the use of the same "snapshot"
word with different meanings.

I have used the term "snapshot isolation" as used in
https://www.sqlite.org/isolation.html; But I'll remember about
REPEATABLE-READ isolation.

I also thank you very much for confirming that preventing checkpoints
allows the WAL markers to remain valid.

My goal is to provide a set of concurrency primitives that are useful for
GUI app developers. I'm learning a lot about SQLite in the process, of
course.

On Sun, Sep 29, 2019 at 2:13 PM Keith Medcalf  wrote:

>
> On Sunday, 29 September, 2019 01:28, Gwendal Roué 
> wrote:
>
> >But now I fail to understand the indented use case of sqlite3 snapshots..
> >Why allow to reuse snapshots with several calls to open()? Why do they
> >exist at all, since we can already profit from snapshot isolation with
> >one transaction (at the cost of keeping it open)?
>
> The sqlite3_snapshot_* interfaces allow you to record information about
> transactions maintained by the WAL transaction manager.  The interface DOES
> NOT manage the WAL transaction manager nor does it manage your so-called
> snapshots (which are not snapshots).  It allows you to "get" information
> about a particular point-in-time location in the WAL transaction log and
> "goto" a specific point-in-time in the WAL transaction log, to "free" the
> memory used to record this information, and to "cmp" which of two
> structures point to a later point-in-time in the WAL transaction log.
>
> They do NOT modify or control the WAL transaction system or the WAL file.
> You are responsible for doing this.
>
> https://sqlite.org/wal.html
>
> So, *IF* you want to maintain the availability of a specific point in time
> in the WAL transaction history, they YOU must make sure that YOU do not
> erase that particular point-in-time location by checkpointing the WAL
> transaction log.  You have the capability of doing this by disabling the
> autocheckpoint mechanism and controlling when you do checkpoints.  The WAL
> transaction system neither knows nor cares that you happen to have recorded
> some information about a particular point-in-time offset in the WAL file.
>
> It is sort of like "No Smoking" signs.  The sign does not mean that you
> cannot smoke.  It means that someone posted a sign that says "No Smoking".
> The fact that there is a sign and what it says is an entirely separate fact
> that has no bearing at all on whether or not one may smoke, nor does the
> sign somehow magically prevent smoking, nor will it prevent you from
> catching on fire and smoking as a result thereof.  It is merely a sign that
> has something written on it which someone stuck up on the wall (or whatever
> support structure it is stuck to).  And what is written on the sign is
> entirely independent of any other state of affairs.
>
> >For information, my quest for snapshot protection has met some success (
> >https://github.com/groue/GRDB.swift/pull/625)
>
> This appears to be updating a wrapper interface to SQLite3 so that if you
> happen to have a point-in-time location recorded, then the automatic WAL
> checkpoint system is disabled, plus doing some prevention to protect users
> of the wrapper from modifying (checkpointing) the WAL transaction log if
> they happen to have some recorded "points-in-time" that are dependent on
> not modifying the WAL transaction log.  (ie, things that you should be
> doing yourself so as to not shoot yourself in the foot).
>
> >Given I control the connections to a given database file, I am able to
> >open one writer connection, and, on demand, up to N read-only connections.
>
> >Those N reader connections allow concurrent database reads. Those "reads"
> are
> >generally wrapped in a deferred transaction which provides snapshot
> >isolation.
>
> No, it provides REPEATABLE-READ isolation.  There is no actual "snapshot"
> taken and no snapshot exists.  You are merely not seeing data written to
> the WAL transaction log at a point-in-time subsequent to the point in time
> at which you commenced the "repeatable-read".
>
> The sqlite3_snapshot_* interface merely provides a way to record
> information about this repeatable-read point-in-time position in the WAL
> file so that you can go back to that "repeatable-read" point-in-time
> location sometime in the future IF IT STILL EXISTS in the WAL transaction
> log.  Since YOU are in control of whether or not the WAL file is
> checkpointed, then YOU are in control of whether this point-in-time still
> exists in the WAL transaction log.  If you remove data from the WAL
> transaction log by performing a checkpoint (which moves transactions into
> the main database file) then this recorded "point-in-time" may no longer
> exist in the WAL transaction log.
>
> >At the end of this transaction, the reader connection becomes
> >available for another read.
>
> Yes.  And by default when the transaction starts it gets a repeatable-read
> isolation 

Re: [sqlite] Conflict between snapshots and checkpoints

2019-09-29 Thread Keith Medcalf

On Sunday, 29 September, 2019 01:28, Gwendal Roué  
wrote:

>But now I fail to understand the indented use case of sqlite3 snapshots..
>Why allow to reuse snapshots with several calls to open()? Why do they
>exist at all, since we can already profit from snapshot isolation with
>one transaction (at the cost of keeping it open)?

The sqlite3_snapshot_* interfaces allow you to record information about 
transactions maintained by the WAL transaction manager.  The interface DOES NOT 
manage the WAL transaction manager nor does it manage your so-called snapshots 
(which are not snapshots).  It allows you to "get" information about a 
particular point-in-time location in the WAL transaction log and "goto" a 
specific point-in-time in the WAL transaction log, to "free" the memory used to 
record this information, and to "cmp" which of two structures point to a later 
point-in-time in the WAL transaction log.

They do NOT modify or control the WAL transaction system or the WAL file.  You 
are responsible for doing this.

https://sqlite.org/wal.html

So, *IF* you want to maintain the availability of a specific point in time in 
the WAL transaction history, they YOU must make sure that YOU do not erase that 
particular point-in-time location by checkpointing the WAL transaction log.  
You have the capability of doing this by disabling the autocheckpoint mechanism 
and controlling when you do checkpoints.  The WAL transaction system neither 
knows nor cares that you happen to have recorded some information about a 
particular point-in-time offset in the WAL file.  

It is sort of like "No Smoking" signs.  The sign does not mean that you cannot 
smoke.  It means that someone posted a sign that says "No Smoking".  The fact 
that there is a sign and what it says is an entirely separate fact that has no 
bearing at all on whether or not one may smoke, nor does the sign somehow 
magically prevent smoking, nor will it prevent you from catching on fire and 
smoking as a result thereof.  It is merely a sign that has something written on 
it which someone stuck up on the wall (or whatever support structure it is 
stuck to).  And what is written on the sign is entirely independent of any 
other state of affairs.

>For information, my quest for snapshot protection has met some success (
>https://github.com/groue/GRDB.swift/pull/625)

This appears to be updating a wrapper interface to SQLite3 so that if you 
happen to have a point-in-time location recorded, then the automatic WAL 
checkpoint system is disabled, plus doing some prevention to protect users of 
the wrapper from modifying (checkpointing) the WAL transaction log if they 
happen to have some recorded "points-in-time" that are dependent on not 
modifying the WAL transaction log.  (ie, things that you should be doing 
yourself so as to not shoot yourself in the foot).

>Given I control the connections to a given database file, I am able to
>open one writer connection, and, on demand, up to N read-only connections.

>Those N reader connections allow concurrent database reads. Those "reads" are
>generally wrapped in a deferred transaction which provides snapshot
>isolation.   

No, it provides REPEATABLE-READ isolation.  There is no actual "snapshot" taken 
and no snapshot exists.  You are merely not seeing data written to the WAL 
transaction log at a point-in-time subsequent to the point in time at which you 
commenced the "repeatable-read".

The sqlite3_snapshot_* interface merely provides a way to record information 
about this repeatable-read point-in-time position in the WAL file so that you 
can go back to that "repeatable-read" point-in-time location sometime in the 
future IF IT STILL EXISTS in the WAL transaction log.  Since YOU are in control 
of whether or not the WAL file is checkpointed, then YOU are in control of 
whether this point-in-time still exists in the WAL transaction log.  If you 
remove data from the WAL transaction log by performing a checkpoint (which 
moves transactions into the main database file) then this recorded 
"point-in-time" may no longer exist in the WAL transaction log.

>At the end of this transaction, the reader connection becomes
>available for another read.

Yes.  And by default when the transaction starts it gets a repeatable-read 
isolation "point-in-time" stamp corresponding to the last transaction written 
to the WAL transaction log which has been committed, or gets the current 
point-in-time representing the "current database" if there are no committed 
transactions in the WAL transaction log.

>One can now create a "snapshot". Those snapshots use the same pool of N
>readers: snapshot reads are then wrapped in a deferred transaction and
>sqlite3_snapshot_open. At the end of this transaction, the reader
>connection becomes available for another regular read or for another
>snapshot read.

There is the error.  There is no "snapshot".  You do not "create a snapshot".  
You record a point-in-time marker location within the WAL 

Re: [sqlite] Conflict between snapshots and checkpoints

2019-09-29 Thread Richard Damon
On 9/29/19 3:27 AM, Gwendal Roué wrote:
> Thank you, Richard
>
> But now I fail to understand the indented use case of sqlite3 snapshots..
> Why allow to reuse snapshots with several calls to open()? Why do they
> exist at all, since we can already profit from snapshot isolation with one
> transaction (at the cost of keeping it open)?
>
> For information, my quest for snapshot protection has met some success (
> https://github.com/groue/GRDB.swift/pull/625)
>
> Given I control the connections to a given database file, I am able to open
> one writer connection, and, on demand, up to N read-only connections. Those
> N reader connections allow concurrent database reads. Those "reads" are
> generally wrapped in a deferred transaction which provides snapshot
> isolation. At the end of this transaction, the reader connection becomes
> available for another read.
>
> One can now create a "snapshot". Those snapshots use the same pool of N
> readers: snapshot reads are then wrapped in a deferred transaction and
> sqlite3_snapshot_open. At the end of this transaction, the reader
> connection becomes available for another regular read or for another
> snapshot read.
>
> In order to protect unused snapshots, checkpoints are prevented as long as
> there exists snapshots, with sqlite3_wal_hook().
>
> I **really** hope this protects snapshots for good. Of course, a
> confirmation from knowledgeable people would be appreciated :-)
>
> Gwendal
I won;t say I know why they were put in, but here is one possibility
that I can think of. First, your model assumes that you have total
control and confidence over the entire application (and if you do, then
you can protect the snapshots yourself). By passing the snapshot and not
the connection with transaction with the snapshot, you can be sure that
the receiver can't disturb the session and invalidate the snapshot. By
opening the snapshot, the receiver is able to recreate the database at
that point, to read its state, but can't accidentally invalidate it.

-- 
Richard Damon

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


[sqlite] Segfault in fts3IncrmergeLoad in v3.29

2019-09-29 Thread Conrad Irwin
Hi SQLite,

I'd like to report a bug I've encountered using SQLite v3.29, where it reliably 
segfaults when trying to insert a row into a fts3 table in a database created 
with a previous version of SQLite.

Please let me know if I can provide more information than what's below, as I'm 
keen to get this resolved (and/or find a work around) urgently — this is 
affecting hundreds of our users in production.

The SQL is `INSERT INTO thread_search(subject) VALUES ('a')`, but it seems that 
any insert to this table will cause a problem. The table was created using 
`CREATE VIRTUAL TABLE thread_search USING fts3(thread_id, subject, content, 
from, to, cc, bcc, replyto, deliveredto, attachments, labels, list, 
rfc822msgid, meta, tokenize=porter)` on a previous version of  SQLite (though 
I'm not sure which one).

I am happy to share a broken database privately (we have reproduced this once 
internally, and are seeing it in the wild for a large number of customers, but 
have not yet been able to create a shareable database that reproduces the 
problem). If it makes a difference, one potentially unusual thing we do when 
writing to the table in normal operations is setting the `rowid` to a value we 
control (so that search results are returned in the correct order without a 
post-sort).

I'm using SQLite as part of Chromium, and the stacktrace I get from Chromium 
looks like this:

5 libsystem_platform.dylib 0x7fff70be7b5d _sigtramp + 29

6 libchromium_sqlite3.dylib 0x00016e5b2fe8 sqlite3DbMallocRawNN + 56

7 libchromium_sqlite3.dylib 0x00016e67053c fts3IncrmergeLoad + 1388

8 libchromium_sqlite3.dylib 0x00016e66f6d7 sqlite3Fts3Incrmerge + 1031

9 libchromium_sqlite3.dylib 0x00016e660b12 fts3SyncMethod + 210

10 libchromium_sqlite3.dylib 0x00016e5d1e70 sqlite3VtabSync + 176

11 libchromium_sqlite3.dylib 0x00016e5d0813 vdbeCommit + 67

12 libchromium_sqlite3.dylib 0x00016e5cff8d sqlite3VdbeHalt + 701

13 libchromium_sqlite3.dylib 0x00016e5d8c0b sqlite3VdbeExec + 16459

14 libchromium_sqlite3.dylib 0x00016e5a57f1 sqlite3Step + 433

15 libchromium_sqlite3.dylib 0x00016e5a54bd chrome_sqlite3_step + 125

That said, when I run the commandline version sqlite3 (built after running 
fossil checkout branch-3.29 --force) inside lldb, I get a slightly 
different-looking crash:

* thread #1, queue = ' com.apple.main-thread ( http://com.apple.main-thread/ ) 
', stop reason = EXC_BAD_ACCESS (code=1, address=0x0) frame #0: 
0x00010a2b8098 sqlite3`sqlite3Fts3Incrmerge [inlined] 
nodeReaderInit(aNode=0x, nNode=0) at sqlite3.c:174812:7 [opt] 
174809 p->nNode = nNode; 174810 174811 /* Figure out if this is a leaf or an 
internal node. */ -> 174812 if( p->aNode[0] ){ 174813 /* An internal node. */ 
174814 p->iOff = 1 + sqlite3Fts3GetVarint(>aNode[1], >iChild); 174815 
}else{ Target 0: (sqlite3) stopped. (lldb) bt * thread #1, queue = ' 
com.apple.main-thread ( http://com.apple.main-thread/ ) ', stop reason = 
EXC_BAD_ACCESS (code=1, address=0x0) * frame #0: 0x00010a2b8098 
sqlite3`sqlite3Fts3Incrmerge [inlined] nodeReaderInit(aNode=0x, 
nNode=0) at sqlite3.c:174812:7 [opt] frame #1: 0x00010a2b806b 
sqlite3`sqlite3Fts3Incrmerge at sqlite3.c:175310 [opt] frame #2: 
0x00010a2b7e6d sqlite3`sqlite3Fts3Incrmerge(p=, 
nMerge=, nMin=) at sqlite3.c:175967 [opt] frame #3: 
0x00010a2a6bf3 sqlite3`fts3SyncMethod(pVtab=0x7fcc74004ba0) at 
sqlite3.c:164365:33 [opt] frame #4: 0x00010a1dbe15 sqlite3`sqlite3VdbeHalt 
at sqlite3.c:135756:12 [opt] frame #5: 0x00010a1dbd8c 
sqlite3`sqlite3VdbeHalt [inlined] vdbeCommit(db=, p=) 
at sqlite3.c:78914 [opt] frame #6: 0x00010a1dbd8c 
sqlite3`sqlite3VdbeHalt(p=) at sqlite3.c:79379 [opt] frame #7: 
0x00010a1ee6ff sqlite3`sqlite3VdbeExec(p=) at 
sqlite3.c:84884:8 [opt] frame #8: 0x00010a1aa02e sqlite3`sqlite3_step 
[inlined] sqlite3Step(p=) at sqlite3.c:82160:10 [opt] frame #9: 
0x00010a1a9e98 sqlite3`sqlite3_step(pStmt=) at sqlite3.c:82225 
[opt]

I can also confirm that with sqlite v3.28, the INSERT works without failing:

$ ~/Downloads/sqlite-tools-osx-x86-328/sqlite3 
~/debug/gabes-database-25-copy 'INSERT INTO thread_search (subject) 
VALUES("a")' $

Interestingly, if I first run the insert first using v3.28; then it works fine 
with v3.29 — I assume that this is because I no longer hitting the incremental 
merge path in the newer version of the code.

It also seems to succeed in v3.29 if I first run `INSERT INTO 
thread_search(thread_search) VALUES ('optimize')` before running the insert. I 
don't yet know whether this is a permanent fix or whether if I continue 
inserting until sqlite3Fts3Incmerge runs again, it will crash again.

Conrad

P.S. I'm happy to run more debugging here, in particular I'm not sure how to 
get more information out when this breaks. 

P.S. Superhuman is hiring — referral bonus for Full Stack Engineers ( 
https://superhuman.com/roles?gh_jid=260350 ) : 

Re: [sqlite] Segfault in fts3IncrmergeLoad in v3.29

2019-09-29 Thread Conrad Irwin
I've done some further digging here, and using git bisect, it seems like the 
problem was this change: https://sqlite.org/src/info/c736c40aab071a69. I can 
happily send a patch that fixes this for me, but I would like help producing a 
minimal test case to add to the test suite.

In the database I have as an example, there is one section of 
thread_search_segdir that has a negative size (indicative of being part-way 
through a rebuild?).

level|idx|start_block|leaves_end_block|end_block|hex(root) 
8|0|491439|492126|530222 -782471|02A7921E04363233660005633436623800046A396B67

Decoding the root, the left_child_id is 493863, and in fact there are four 
height=1 nodes (493863, 493864, 493865, and 493866).

Node 493866 is interesting, because it is an interior node with no terms:

blockid|hex(block) 493866|01DE841E # left-child 492126

When we try and insert a new row into the table, it triggers an incremental 
merge. As part of that merge, we loop down the tree looking for nodes to merge 
together. We first hit node 496287 at height=2, then node 493866 at height=1 
and then 492126 (a leaf node).

Before this commit, everything works ok; but after this commit, when we run 
`nodeReaderInit` on node 492166 it segfaults because we pass in 
`pNode->block.a` which is 0, and then try and read the memory it points to.

The reason that `pNode->block.a` is 0 on the leaf node is because we have 
(erroneously) skipped the loop body on the height=1 node and the code assumes 
that the previous iteration will have initialized pNode.

There are a few ways to fix the crash while keeping the test-suite passing, but 
I think the correct thing to do is to move the new check earlier:

In ./ext/fts3/fts3_write.c:4926 - rc = nodeReaderInit(, pNode->block.a, 
pNode->block.n); - if( reader.aNode ){ + if( pNode->block.a ){ + rc = 
nodeReaderInit(, pNode->block.a, pNode->block.n);

Although it might seem like this change is equivalent, `pNode->block.a` will 
exist more often than `reader.aNode`. This is because `nodeReaderInit` calls 
`nodeReaderNext`, which has the side-effect of setting `reader.aNode = 0` when 
there are no more terms to be read. In the case of node 493866 (above) 
pNode->block.a exists (and it contains a pointer to the left-mode-child) but 
calling nodeReaderNext sets reader.aNode to 0 because it contains no terms.

This change allows the loop to finish iterating correctly in the case above, 
where there is no corruption but there is an interior node with no terms. This 
change will also fix a potential crash on the leaf node in the case of an 
actually corrupt interior node as we will skip the initialization of 
`aNodeWriter[i-1]` later in the loop and so pNode->block.a will still be 0 from 
when it was first created.

Please let me know if I can be further helpful in getting this fixed,

Conrad

P.S. Superhuman is hiring — referral bonus for Full Stack Engineers ( 
https://superhuman.com/roles?gh_jid=260350 ) : $1,947.

On Sat, Sep 28, 2019 at 10:35 PM, Conrad Irwin < con...@superhuman.com > wrote:

> 
> Hi SQLite,
> 
> 
> 
> I'd like to report a bug I've encountered using SQLite v3.29, where it
> reliably segfaults when trying to insert a row into a fts3 table in a
> database created with a previous version of SQLite.
> 
> 
> 
> Please let me know if I can provide more information than what's below, as
> I'm keen to get this resolved (and/or find a work around) urgently — this
> is affecting hundreds of our users in production.
> 
> 
> The SQL is `INSERT INTO thread_search(subject) VALUES ('a')`, but it seems
> that any insert to this table will cause a problem. The table was created
> using `CREATE VIRTUAL TABLE thread_search USING fts3(thread_id, subject,
> content, from, to, cc, bcc, replyto, deliveredto, attachments, labels,
> list, rfc822msgid, meta, tokenize=porter)` on a previous version of 
> SQLite (though I'm not sure which one).
> 
> 
> 
> I am happy to share a broken database privately (we have reproduced this
> once internally, and are seeing it in the wild for a large number of
> customers, but have not yet been able to create a shareable database that
> reproduces the problem). If it makes a difference, one potentially unusual
> thing we do when writing to the table in normal operations is setting the
> `rowid` to a value we control (so that search results are returned in the
> correct order without a post-sort).
> 
> 
> 
> I'm using SQLite as part of Chromium, and the stacktrace I get from
> Chromium looks like this:
> 
> 5 libsystem_platform.dylib 0x7fff70be7b5d _sigtramp + 29
> 
> 6 libchromium_sqlite3.dylib 0x00016e5b2fe8 sqlite3DbMallocRawNN + 56
> 
> 7 libchromium_sqlite3.dylib 0x00016e67053c fts3IncrmergeLoad + 1388
> 
> 8 libchromium_sqlite3.dylib 0x00016e66f6d7 sqlite3Fts3Incrmerge + 1031
> 
> 
> 9 libchromium_sqlite3.dylib 0x00016e660b12 fts3SyncMethod + 210
> 
> 10 libchromium_sqlite3.dylib 0x00016e5d1e70 sqlite3VtabSync + 176
> 
> 11 libchromium_sqlite3.dylib 

[sqlite] PRAGMA table_info fails with "no such tokenizer"

2019-09-29 Thread Anatoli Babenia
Python 3.7.4 (default, Jul  9 2019, 16:32:37)
[GCC 9.1.1 20190503 (Red Hat 9.1.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
>>> conn = sqlite3.connect("/home/anatoli/.cache/tracker/meta.db")
>>> cursor = conn.cursor()
>>> cursor.execute('PRAGMA main.table_info("fts5")')
Traceback (most recent call last):
  File "", line 1, in 
sqlite3.OperationalError: no such tokenizer: TrackerTokenizer


The `sqlite3 meta.db .dump` works without errors. The `fts5` table
referenced in the dump.

INSERT INTO 
sqlite_master(type,name,tbl_name,rootpage,sql)VALUES('table','fts5','fts5',0,'CREATE
VIRTUAL TABLE fts5 USING fts5(content="fts_view", "nfo:fileName",
"nco:title", "nfo:genre", "nmm:genre", "mtp:creator",
"nco:nameFamily", "nco:nameGiven", "nco:nameAdditional",
"nco:phoneNumber", "nao:prefLabel", "nao:description", "nco:fullname",
"nco:nickname", "nco:contactGroupName", "nfo:tableOfContents",
"ncal:comment", "ncal:location", "ncal:summary", "ncal:contact",
"ncal:description", "nmo:messageSubject", "nmm:albumTitle",
"nmm:artistName", "nco:department", "nco:role", "nco:note",
"nie:keyword", "nco:imID", "nco:imNickname", "nco:emailAddress",
"nmm:category", "nfo:fontFamily", "nco:region", "nco:country",
"nco:extendedAddress", "nco:streetAddress", "nco:postalcode",
"nco:locality", "nco:county", "nco:district", "nco:pobox",
"nie:title", "nie:subject", "nie:plainTextContent", "nie:description",
"nie:comment", "nid3:title", "nid3:albumTitle", "nid3:contentType",
tokenize=TrackerTokenizer)');


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


Re: [sqlite] Conflict between snapshots and checkpoints

2019-09-29 Thread Gwendal Roué
Thank you, Richard

But now I fail to understand the indented use case of sqlite3 snapshots..
Why allow to reuse snapshots with several calls to open()? Why do they
exist at all, since we can already profit from snapshot isolation with one
transaction (at the cost of keeping it open)?

For information, my quest for snapshot protection has met some success (
https://github.com/groue/GRDB.swift/pull/625)

Given I control the connections to a given database file, I am able to open
one writer connection, and, on demand, up to N read-only connections. Those
N reader connections allow concurrent database reads. Those "reads" are
generally wrapped in a deferred transaction which provides snapshot
isolation. At the end of this transaction, the reader connection becomes
available for another read.

One can now create a "snapshot". Those snapshots use the same pool of N
readers: snapshot reads are then wrapped in a deferred transaction and
sqlite3_snapshot_open. At the end of this transaction, the reader
connection becomes available for another regular read or for another
snapshot read.

In order to protect unused snapshots, checkpoints are prevented as long as
there exists snapshots, with sqlite3_wal_hook().

I **really** hope this protects snapshots for good. Of course, a
confirmation from knowledgeable people would be appreciated :-)

Gwendal

On Sat, Sep 28, 2019 at 4:06 PM Richard Damon 
wrote:

> On 9/26/19 12:13 PM, Gwendal Roué wrote:
> > Hello,
> >
> > The documentation for sqlite3_snapshot_open() [1] says:
> >
> >> A call to sqlite3_snapshot_open() will fail to open if the specified
> > snapshot has been overwritten by a checkpoint.
> >
> > And indeed I am able to create a snapshot with sqlite3_snapshot_get()
> [2],
> > then run checkpoints with sqlite3_wal_checkpoint_v2() [3], and finally
> have
> > sqlite3_snapshot_open() fail.
> >
> > I have a concern, because this turns automatic checkpointing into a
> mortal
> > danger for all snapshots. As soon as a checkpoint is performed, snapshots
> > are invalidated, and whoever is relying on them has lost the database
> state
> > he's interested into.
> >
> > My question is: is it possible to prevent checkpoints from completing
> > successfully when a snapshot is alive?
> >
> > I know this is possible with a "hand-made checkpoint", made of a distinct
> > connection which has started a deferred transaction and has performed an
> > initial read. Such hand-made checkpoint has SQLITE_CHECKPOINT_RESTART and
> > SQLITE_CHECKPOINT_TRUNCATE fail, and are still able to access their
> > precious database state after a SQLITE_CHECKPOINT_PASSIVE or a
> > SQLITE_CHECKPOINT_FULL.
> >
> > The behavior of those "hand-made checkpoint" matches well the needs of
> > users who want to use WAL without thinking too much about it: they do not
> > disable automatic checkpointing, and are guaranteed with a stable access
> to
> > a given database state as long as they need it.
> >
> > I was wondering if such a behavior is possible with snapshots returned
> from
> > sqlite3_snapshot_get().
> >
> > If it is not, then I humbly suggest that this feature would be added, and
> > am willing to listen to the opinion of SQLite experts on this subject.
> >
> > Regards,
> > Gwendal Roué
> >
> > [1] https://www.sqlite.org/c3ref/snapshot_open.html
> > [2] https://www.sqlite.org/c3ref/snapshot_get.html
> > [3] https://www.sqlite.org/c3ref/wal_checkpoint_v2.html
>
> I think you have a fundamental issue here. Snapshots are tied to a
> Transaction, and as long as that transaction doesn't invalidate that
> snapshot, nothing else can. (This is what you hand-mand checkpoint does
> right). The issue is that if you are reusing the connection, you are
> sharing the Transaction and thus not protecting your snapshot. Once
> someone else using that connection breaks the transaction, then the
> snapshot is no longer protected.
>
> The issue trying to increase the protection on a snapshot is that
> currently sqlite_snapshot_free() isn't defined as protecting the
> snapshot, but is merely a memory management tool, so many applications
> likely don't free all their snapshots before they allow for the
> possibility of them being invalidated by ending the Transaction, thus
> this change would break many existing programs. I suppose it could be
> implemented with a pragma or the like that doesn't allow that
> transaction to be committed or invalidate the snapshot until the
> snapshot is freed.
>
> What that would ultimately do is cause your program to get an error from
> SQLite3 farther down the road when you did some action on the connection
> that would potentially invalidate your precious snapshot, and you now
> have one more source of 'unexplained' errors returns.
>
> --
> Richard Damon
>
> ___
> sqlite-users mailing list
> sqlite-users@mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>