Re: [sqlite] Regarding sqlite3 reliability in using in service oriented architecture

2019-04-28 Thread Rowan Worth
On Mon, 29 Apr 2019 at 01:22, Lullaby Dayal 
wrote:

>
> Considering all this, I have written a test application running on Linux
> with sqlite3 library in serialized mode. My test application has 200
> parallel threads in which 100 threads are executing SELECT * operation from
> a table and 100 are executing update table (alternate fields in alternate
> run) command in auto-commit mode (while(1)). I haven't verified the data
> correctly written in database as I only rely on return code and I was
> stress testing. I expect at some point it should produce SQLITE_BUSY
> command at some point of time. But it didn't.
>
> Only thing I got is:- while the test application is running, in a separate
> SQLite command prompt I open the same database and executed .tables
> command.  This time, I got a database locked error in my test application.
>
> So my questions are:-
>
> 1. In auto-commit mode in serialized threading mode, how command queueing
> works?
>
2. Multiple simultaneous calls to sqlite_exec() performing Multiple write
> commands or read commands while write is in progress - will this be handled
> by sqlite_exec() itself? Or does the application need to do some kind of
> locking to avoid such situation as mentioned in the FAQ? In serialized
> mode, sqlite3 implements its own locking, right? Do application need to do
> a high level locking beyond this?
>

In serialized threading mode using sqlite3_exec, I don't believe you'll get
any DB concurrency between threads -- rather each thread will take turns to
run sqlite3_exec (which holds a connection-level mutex while it executes).
This is why you never see SQLITE_BUSY.

To allow different threads to access the DB concurrently, they need to use
separate connections. However given that a lot of what sqlite does is i/o
bound you won't necessarily find any performance benefits from
multi-threading. If your DB is small enough and no other processes are
updating the DB, you could think about upping the cache_size PRAGMA and
using shared-cache mode for the connections to minimise i/o.

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


Re: [sqlite] Regarding sqlite3 reliability in using in service oriented architecture

2019-04-28 Thread Keith Medcalf

On Thursday, 25 April, 2019 19:10, Lullaby Dayal  
wrote:

>We use sqlite3 in an embedded automotive system based on QNX
>hypervisor running multiple virtual machines. Software is 
>architectured in a service oriented way.

Interestingly, the default "database" service in QNX is (or at least was at one 
time) based on an implementation of SQLite.  I do not know if this is still the 
case as it is a long time since I looked at and used QNX (It has been bought 
and sold several times since then).

At the time the database service worked thusly:

When you "connected" to the database service (by sending it a connect and open 
request) the underlying service created an SQLite connection object for you in 
the service context.  All further requests that you submitted (by sending 
messages to your open context) occurred within this connection context.  If you 
created another "connection" to the database service, then another SQLite 
connection context was created for that connection.  It did not matter from 
whence the QNX database connection originated (ie, on the same machine or from 
another machine) as each connection was an independant SQLite connection from 
the QNX "database service process" to a local data file.  Thus every "client" 
of the shared service was a separate connection context and isolated from every 
other client connection.  Because of the way that the microkernel handled the 
message passing, all the connections were kept straight and the "going away" of 
a client (ie, a client program crash) was detected by the microkernel so the 
proper cleanup could occur automatically.

In your service how do you identify the "client" and "connection on the client" 
in order to maintain isolation?  And if you do it with session tokens or 
identifiers of some type passed back the the "client connection" how do you 
detect that a client has "gone missing" so that you can close and clean up the 
actual database connection?

Just curious ...

---
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.





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


Re: [sqlite] Regarding sqlite3 reliability in using in service oriented architecture

2019-04-28 Thread Keith Medcalf

On Sunday, 28 April, 2019 11:23, Lullaby Dayal  asked:

To answer your specific questions:

>So my questions are:-

>1. In auto-commit mode in serialized threading mode, how command
>queueing works?

auto-commit and transactions are an attribute of the connection and have 
nothing whatsoever to do with serialized threading mode.  You may place a 
connection within a transaction either explicitly or implicitly from any thread 
at any time, just as you may commit or rollback that transaction on that 
connection from any thread at any time.  The transaction status (and thus the 
"queueing" of updates as you put it) only applies to a connection.

Serialized Threading mode is simply a safety net to ensure that you do not 
mutate shared state (the connection) from multiple threads at the same time.  
As you can imagine, if you were permitted to do this (update shared context at 
the same time) then all hell would break loose.  Threading mode is simply a way 
to control access to shared state (the connection) from multiple threads at the 
same time.  

SERIALIZED MODE means "please check and enforce that I am not attempting to 
mutate shared context from multiple threads and protect me from the explosions 
that would result if I do so by not permitting it to happen".  

MULTITHREADING mode means "Do not bother to check whether or not I am 
attempting to mutate shared context from multiple threads and if I do so then 
permit the resulting explosions to annihilate me".  

SINGLE_THREAD mode means "I am only using a single thread in this program so do 
not do anything that may require multiple threads or thread local storage, nor 
check or protect me from any explosions resulting from me lying about this".

>2. Multiple simultaneous calls to sqlite_exec() performing Multiple
>write commands or read commands while write is in progress - will 
>this be handled by sqlite_exec() itself? Or does the application 
>need to do some kind of locking to avoid such situation as 
>mentioned in the FAQ? 

No, isolation is between CONNECTIONS and not between STATEMENTS (which are 
derived from the same connection).  All things derived from a single connection 
share the same context.

>In serialized mode, sqlite3 implements its own locking, right? 

Yes, however, serialized mode is simple to prevent simultaneous mutation of 
shared state (the connection) concurrently from multiple threads.  It does not 
have anything whatsoever to do with "locking" or transactions or any other ACID 
property of the database.

>Do application need to do a high level locking beyond this?

No.  Concurrency protection is inherent between connections (and things derived 
from DIFFERENT connection).  SERIALIZED mode will prevent you from causing 
explosions that result from failing to follow the entrance requirements of the 
library but otherwise has nothing whatsoever to do with concurrency nor 
isolation.

>3. Will there be a case the database can become corrupt or some
>operations missed to get performed in such a case?

Since isolation is between connections, then all changes made on a connection 
are visible to all other "things" on that connection at the instant those 
changes are made.  That means that if you delete a row from a table while you 
are also reading that table, then that row will "vanish" at the time the update 
made.  Since this will mutate the indexes on the table, any manner of result 
could ensue.  This is why you should not do this and why you should utilize 
isolation (provided by connections) to prevent an "update" from occurring in 
the middle of reading.


---
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.





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


Re: [sqlite] PRAGMA case_sensitive_like conflicts with LIKE operator when creating an index

2019-04-28 Thread Simon Slavin
On 28 Apr 2019, at 7:58pm, Manuel Rigger  wrote:

> It seems that setting "PRAGMA case_sensitive_like" to either false (the 
> default behavior) or true results in no longer being able to use a LIKE or 
> GLOB clause when creating an index.

Correct.  Because you cannot depend that every connection that opens the 
database has PRAGMA case_sensitive_like set the same way.  And that might lead 
to an inconsistent index.
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


[sqlite] PRAGMA case_sensitive_like conflicts with LIKE operator when creating an index

2019-04-28 Thread Manuel Rigger
Hi everyone,

It seems that setting "PRAGMA case_sensitive_like" to either false (the
default behavior) or true results in no longer being able to use a LIKE or
GLOB clause when creating an index. For example, the example below results
in "Error: non-deterministic functions prohibited in index expressions".

PRAGMA case_sensitive_like=false; CREATE TABLE test (c0); CREATE INDEX IF
NOT EXISTS index_1 ON test(c0 LIKE "a");

Is this a bug or intended? From the documentation, I would guess that when
registering the LIKE and GLOB functions, they are not registered as being
deterministic.

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


Re: [sqlite] Regarding sqlite3 reliability in using in service oriented architecture

2019-04-28 Thread Keith Medcalf

I will leave aside the use of SHARED_CACHE which massively trades performance 
for memory usage (that is, it "totally kills" performance but also "hugely 
reduces" memory requirements) -- it trades a huge reduction in performance for 
a huge reduction in memory usage and changes some other things as well.  It is 
designed for truly itty bitty things with no memory that only perform 
relatively simple tasks.  Technically, it places multiple connections to the 
same shared cache (within the same process) within the same context and 
implements concurrency between those connections by software emulation rather 
than locking semantics.  The context unit is the shared cache, not the 
connection to the shared cache.  While this description is not perfectly true, 
it suffices to demonstrate that using SHARED_CACHE significantly changes the 
semantics and its use, where appropriate, significantly changes connection 
semantics and below describes normal (non SHARED_CACHE) semantics only.

All concurrency in SQLite3 is based on the CONNECTION (created by one of the 
sqlite3_open APIs).  All children (example STATEMENTS) of the same CONNECTION 
share the identical single context which at its very lowest level includes 
concurrency and transaction control.

Concurrency only applies between statements executed against different 
connections.  Statements executed against the same connection all occur within 
the same context.  When a transaction is commenced (whether implicitly or 
explicitly) that transaction applies to the context (connection).  In other 
words, if all statements are executed against the same connection, then they 
all share the same context, and there is no concurrency (isolation) of 
execution between the statements whatsoever.  The default SERIALIZED 
multithreading mode is NOT a concurrency control.  It is there to prevent 
multiple threads from mutating the context (connection) at the same time.  If 
that were permitted, great explosions would occur.

>SQLite allows multiple processes to have the database file open at
>once, and for multiple processes to read the database at once. When 
>any process wants to write, it must lock the entire database file 
>for the duration of its update. But that normally only takes a few 
>milliseconds. Other processes just wait on the writer to finish 
>then continue about their business.

The word "process" and "processes" is incorrect.  It should say:

>SQLite allows multiple connections to have the database file open 
>at once (and these connections may be within the same or separate
>processes), and for multiple connections to read the database at 
>once.  When any connection wants to write, it must lock the entire 
>database file for the duration of its update.  But that normally 
>only takes a few milliseconds. Other connections just wait on the 
>writer to finish then continue about their business*.
>*assuming that busy_timeout is set to a non-zero value

Does this help explain what you are seeing?


---
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.

>-Original Message-
>From: sqlite-users [mailto:sqlite-users-
>boun...@mailinglists.sqlite.org] On Behalf Of Lullaby Dayal
>Sent: Sunday, 28 April, 2019 11:23
>To: SQLite mailing list
>Subject: Re: [sqlite] Regarding sqlite3 reliability in using in
>service oriented architecture
>
>Thank you for your valuable suggestion.
>
>As you mentioned, the possibility of a concurrent transaction with
>auto-commit transaction is already handled in our design using some
>flag
>variables.
>
>I would like to understand some points discussed in sqlite3
>documentation
>in detail.
>
>1. Compile time configuration of sqlite3 library is serialized
>threading
>mode. As per Sqlite3 documentation, this mode can be used reliably in
>multithreaded application with no restriction.
>
>2. Excerpt from https://sqlite.org/faq.html#q5 is as follows:
>
>SQLite allows multiple processes to have the database file open at
>once,
>and for multiple processes to read the database at once. When any
>process
>wants to write, it must lock the entire database file for the
>duration of
>its update. But that normally only takes a few milliseconds. Other
>processes just wait on the writer to finish then continue about their
>business.
>
>3. *High Concurrency*
>
>SQLite supports an unlimited number of simultaneous readers, but it
>will
>only allow one writer at any instant in time. For many situations,
>this is
>not a problem. Writers queue up. Each application does its database
>work
>quickly and moves on, and no lock lasts for more than a few dozen
>milliseconds. But there are some applications that require more
>concurrency, and those applications may need to seek a different
>solution.
>
>The above three items are quite confusing.
>
>Our application requires a little bit of concurrency for a small
>amount of
>time. As these words are quite subjective, I do a funny stress

Re: [sqlite] Unexpected result when using "without rowid" and creating a "collate nocase" index

2019-04-28 Thread Manuel Rigger
Great, thanks for opening the bug report and for the attribution!

Best,
Manuel

Am So., 28. Apr. 2019 um 17:07 Uhr schrieb Richard Hipp :

> On 4/28/19, Manuel Rigger  wrote:
> >
> > CREATE TABLE test (c1 TEXT PRIMARY KEY) WITHOUT ROWID;
> > CREATE INDEX index_0 ON test(c1 COLLATE NOCASE);
> > INSERT INTO test(c1) VALUES ('A');
> > INSERT INTO test(c1) VALUES ('a');
> > SELECT * FROM test;
> >
> > Is this indeed a bug, or a misunderstanding on my side?
>
> https://www.sqlite.org/src/tktview/3182d3879020ef3b2e6db56be2470a0266d3c773
> --
> D. Richard Hipp
> d...@sqlite.org
> ___
> 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] Regarding sqlite3 reliability in using in service oriented architecture

2019-04-28 Thread Simon Slavin
On 28 Apr 2019, at 6:22pm, Lullaby Dayal  wrote:

> SQLite supports an unlimited number of simultaneous readers, but it will only 
> allow one writer at any instant in time.

Please note that this is a statement about how one journal mode (WAL) works.  
Are you telling us that you're using that mode ?

Also note that SQLite has no client/server element.  It doesn't keep the 
database in memory.  Unless your threads are sharing a connection, or you're 
using shared-cache mode, your threads don't communicate with each other.  Every 
command that accesses the database accesses its storage medium.  And since your 
storage medium can process only one command at a time, really only one thread 
has access to the database at a time.

> I have written a test application running on Linux with sqlite3 library in 
> serialized mode. My test application has 200 parallel threads in which 100 
> threads are executing SELECT * operation from a table and 100 are executing 
> update table (alternate fields in alternate run) command in auto-commit mode 
> (while(1)). 

Your post misses a detail which changes the answers to your questions: are 
these threads each using their own connection or do they share one connection ? 
 If more than one connection is involved, are your connections sharing cache as 
described here:



Once you've answered that, there are other considerations:

Have you set any timeout on each connection your application uses ?

Are you enforcing a mutex in your threads or are you depending on SQLite to do 
all locking necessary ?

If your application uses many separate connections, with timeouts set, SQLite 
takes care of a lot of the locking involved.  If your application tried to use 
one connection to do many things at once, you, as a programmer, have to pay 
more attention to problems which simultaneous access might involve.

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


Re: [sqlite] Regarding sqlite3 reliability in using in service oriented architecture

2019-04-28 Thread Lullaby Dayal
Thank you for your valuable suggestion.

As you mentioned, the possibility of a concurrent transaction with
auto-commit transaction is already handled in our design using some flag
variables.

I would like to understand some points discussed in sqlite3 documentation
in detail.

1. Compile time configuration of sqlite3 library is serialized threading
mode. As per Sqlite3 documentation, this mode can be used reliably in
multithreaded application with no restriction.

2. Excerpt from https://sqlite.org/faq.html#q5 is as follows:

SQLite allows multiple processes to have the database file open at once,
and for multiple processes to read the database at once. When any process
wants to write, it must lock the entire database file for the duration of
its update. But that normally only takes a few milliseconds. Other
processes just wait on the writer to finish then continue about their
business.

3. *High Concurrency*

SQLite supports an unlimited number of simultaneous readers, but it will
only allow one writer at any instant in time. For many situations, this is
not a problem. Writers queue up. Each application does its database work
quickly and moves on, and no lock lasts for more than a few dozen
milliseconds. But there are some applications that require more
concurrency, and those applications may need to seek a different solution.

The above three items are quite confusing.

Our application requires a little bit of concurrency for a small amount of
time. As these words are quite subjective, I do a funny stress experiment
with sqlite3.

Considering all this, I have written a test application running on Linux
with sqlite3 library in serialized mode. My test application has 200
parallel threads in which 100 threads are executing SELECT * operation from
a table and 100 are executing update table (alternate fields in alternate
run) command in auto-commit mode (while(1)). I haven't verified the data
correctly written in database as I only rely on return code and I was
stress testing. I expect at some point it should produce SQLITE_BUSY
command at some point of time. But it didn't.

Only thing I got is:- while the test application is running, in a separate
SQLite command prompt I open the same database and executed .tables
command.  This time, I got a database locked error in my test application.

So my questions are:-

1. In auto-commit mode in serialized threading mode, how command queueing
works?
2. Multiple simultaneous calls to sqlite_exec() performing Multiple write
commands or read commands while write is in progress - will this be handled
by sqlite_exec() itself? Or does the application need to do some kind of
locking to avoid such situation as mentioned in the FAQ? In serialized
mode, sqlite3 implements its own locking, right? Do application need to do
a high level locking beyond this?
3. Will there be a case the database can become corrupt or some operations
missed to get performed in such a case?

Thank you,
Lullaby






On Fri, Apr 26, 2019, 9:07 PM Jens Alfke  wrote:

>
>
> > On Apr 25, 2019, at 6:09 PM, Lullaby Dayal 
> wrote:
> >
> > A single database connection is shared
> > among all these services. More than one service access the service API to
> > read/write database at the same time. No locking is implemented in our
> > service accessing the database.
>
> The one issue that comes to mind is transactions: your design has no
> isolation (the I in ACID) between threads.
>
> In more detail: if a thread executes "BEGIN", does some
> inserts/updates/deletes, and then executes "END", other threads that issue
> SQLite calls at the same time will see the uncommitted changes being made
> by the first thread. Depending on your design, this can cause problems,
> especially if the first thread ever ends up aborting the transaction
> (leaving the other threads with stale data that isn't in the database.)
>
> It gets even more "fun" if the secondary threads are making their own
> changes (without BEGIN/END), because those changes will become part of the
> first thread's transaction, so if the first thread aborts, the other
> threads' changes will be lost.
>
> For this reason it's usually good to have a mutex for transactions: you
> lock the mutex before calling BEGIN and unlock it after calling END. (If
> you make one-off changes without BEGIN/END, you have to lock the mutex
> around those calls too.)
>
> If this isn't a problem for you because you never use transactions, then
> you may have a different problem: write performance. Issuing multiple
> writes without a transaction is inefficient, because each write has to
> begin and commit its own transaction, and the commits tend to be expensive
> (depending on the filesystem) because they have to ensure durability.
>
> —Jens
> ___
> sqlite-users mailing list
> sqlite-users@mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>

Re: [sqlite] Unexpected result when using "without rowid" and creating a "collate nocase" index

2019-04-28 Thread Richard Hipp
On 4/28/19, Manuel Rigger  wrote:
>
> CREATE TABLE test (c1 TEXT PRIMARY KEY) WITHOUT ROWID;
> CREATE INDEX index_0 ON test(c1 COLLATE NOCASE);
> INSERT INTO test(c1) VALUES ('A');
> INSERT INTO test(c1) VALUES ('a');
> SELECT * FROM test;
>
> Is this indeed a bug, or a misunderstanding on my side?

https://www.sqlite.org/src/tktview/3182d3879020ef3b2e6db56be2470a0266d3c773
-- 
D. Richard Hipp
d...@sqlite.org
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


[sqlite] Unexpected result when using "without rowid" and creating a "collate nocase" index

2019-04-28 Thread Manuel Rigger
Hi everyone,

I found what could be a bug. Consider the example below:

CREATE TABLE test (c1 TEXT PRIMARY KEY) WITHOUT ROWID;
CREATE INDEX index_0 ON test(c1 COLLATE NOCASE);
INSERT INTO test(c1) VALUES ('A');
INSERT INTO test(c1) VALUES ('a');
SELECT * FROM test;

The query returns only one result, namely ('a'), while I would have
expected both rows to be fetched. It seems that this bug only exists when
(1) a COLLATE NOCASE index is created and (2) WITHOUT ROWID is used. When
using COUNT(*), the expected number of 2 is returned.

Is this indeed a bug, or a misunderstanding on my side?

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


Re: [sqlite] String interpreted as a column name when creating an index

2019-04-28 Thread Manuel Rigger
@Simon: Thanks for pointing that out! The difference in the effects of
using single vs. double quotes in the select query is still the same though.

@Richard: Thanks for taking time to explain this to me and for pointing me
to the comment in the source code! I've found another case where, depending
on the context, a string in the ORDER BY clause is either interpreted as a
column name or a string (see below).

CREATE TABLE test (c0);
SELECT * FROM test ORDER BY 'asdf';
SELECT (0) INTERSECT SELECT * FROM test ORDER BY 'asdf'

In the first query, ORDER BY 'asdf' is interpreted as a string and does not
cause any error, while in the second query it causes "1st ORDER BY term
does not match any column in the result set". As you pointed out, there is
no point in having a constant expression in such contexts, and I assume
that this case is also related to backward compatibility.

Best,
Manuel


Am Sa., 27. Apr. 2019 um 22:14 Uhr schrieb Richard Hipp :

> On 4/27/19, Manuel Rigger  wrote:
> > Thanks for your quick and helpful reply! So if I understood correctly,
> > there is no way to ensure that a string is not interpreted as a column in
> > an arbitrary expression, right?
>
> String literal is always just a string literal in an arbitrary
> expression.  String literals can only be interpreted as an identifier
> in a context where only an identifier is allowed, such as after
> "CREATE TABLE", for example.
>
> The one exception to the above is that if the argument to CREATE INDEX
> is an expression that is comprised of a single string literal, then
> that string literal is interpreted as a column name rather than as an
> expression.  This is done for historical compatibility, and because
> there is no point in having an index on a constant expression.  See
> the implementation at
> https://www.sqlite.org/src/artifact/61655dad911a?ln=1319-1341
> --
> D. Richard Hipp
> d...@sqlite.org
> ___
> 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] sqlite3 java.lang.IllegalStateException: SQLite JDBC: inconsistent internal state

2019-04-28 Thread Frank Kemmer
Simon Slavin  schrieb am Sa. 27. Apr. 2019 um 14:28:

> On 27 Apr 2019, at 10:47am, Frank Kemmer  wrote:
>
> > I can connect to the database, create a table, select from the table,
> insert into the table, but the first time I try to read after an insert I
> get the following exception:
>
> >> Are you checking the result codes from all these operations ?


All these operations happen on one connection in one session. My first
operation is to list the tables and then I do the select.

When I insert the lines with the sqlite3 command line tool everything is
fine. But when I use sqlline with the sqlite JDBC Driver, I get this
exception with the first select statement.

I can even insert the lines with sqlline and select them in sqlite3 ... but
I can‘t do a select in sqlline. This results in the exception given above.

It reminds me on the problem that after the iteration over the resultSet,
the resultSet was closed and you no longer could access the metadata ...
but I am just guessing here.

> --
Wir ertrinken in Information, aber hungern nach Wissen [John Naisbitt]
___
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users