| 3432 |
mrmanese |
1 |
Implementation notes for those who want to modify the code
|
|
|
2 |
|
|
|
3 |
A. sql buffers
|
|
|
4 |
1. Much of the logic is concerned with constructing the SQL to be executed.
|
|
|
5 |
These sql's are stored in one of the global buffers (g_sql_buf).
|
|
|
6 |
2. Currently, there are 4 of them (controlled by constant NBUFS in
|
|
|
7 |
src/sqlite_dataframe.h).
|
|
|
8 |
3. It is assumed that R is running on a single thread, so this approach will
|
|
|
9 |
work.
|
|
|
10 |
4. Initially, all buffers are 1024 characters long. The buffer sizes are
|
|
|
11 |
stored in the global int array g_sql_buf_sz.
|
|
|
12 |
5. When writing strings to a buf with variable length, use
|
|
|
13 |
_expand_buf([index of buffer], [approx size]). If approx size is greater
|
|
|
14 |
than the buffer's length, it will be reallocated with twice the current
|
|
|
15 |
size.
|
|
|
16 |
6. Functions use a naming convention with respect to the buffer it uses.
|
|
|
17 |
Top-level functions may use any of the buffers. Those with name
|
|
|
18 |
ending in a number are expected to use buffers a buffer with that number
|
|
|
19 |
as index, and those "below" it. For example, the function USE_SDF1 may
|
|
|
20 |
use buffers 1 and 2, so those calling it should not store data in those
|
|
|
21 |
buffers that they will need after the function call. Initially I was able
|
|
|
22 |
to make do with 3 buffers (0, 1 & 2), but somewhere I had to add another
|
|
|
23 |
buffer (w/c makes it 4). In most cases, the buffers "below" a number are
|
|
|
24 |
only those buffers up to 2 (e.g., USE_SDF1 uses only buffers 1 & 2) so
|
|
|
25 |
3 can be used by the calling function.
|
|
|
26 |
|
| 3434 |
mrmanese |
27 |
B. MAX_ATTACHED, USE_SDF1, UNUSE_SDF2
|
|
|
28 |
1. The number of DB attached to the SQLite engine is limited by the value
|
|
|
29 |
of the macro MAX_ATTACHED in SQLite.
|
|
|
30 |
2. By default, MAX_ATTACHED is 10. This package modifies it to 31. This
|
|
|
31 |
is the maximum, according to the SQLite docs. SQLite uses bitfields
|
|
|
32 |
somewhere, where the nth bit probably represents the nth attached db.
|
|
|
33 |
3. SQLiteDF produces a lot of SDF. Most operations creates SDF where
|
|
|
34 |
intermediate values are stored.
|
|
|
35 |
4. On startup, it opens workspace.db in the current directory. Then it
|
|
|
36 |
attaches SDF's listed in workspace.db.
|
|
|
37 |
5. The package "juggles" with db's attached by using USE_SDF1 and UNUSE_SDF2.
|
|
|
38 |
6. USE_SDF1 checks if a SDF is loaded. If not, and there is a free "slot,"
|
|
|
39 |
it is attached. If there is no free slot, then the least used among those
|
|
|
40 |
loaded is detached to make room for this one. The use count of the SDF
|
|
|
41 |
loaded is increased.
|
|
|
42 |
7. On USE_SDF1, there is an option to "protect" it from being unloaded. There
|
|
|
43 |
are cases where a function uses 2 SDF and the second USE_SDF may unload
|
|
|
44 |
the 1st. In general, top-level functions that will use 2 SDF's, including
|
|
|
45 |
those that will store results in an SDF, will have to set the protect
|
|
|
46 |
statement. The protect options sets a bit in the workspace db to flag that
|
|
|
47 |
it should not be detached.
|
|
|
48 |
8. When the protect option is used, make sure to do UNUSE_SDF2. This clears
|
|
|
49 |
the flag in workspace.db.
|
|
|
50 |
9. _prepare_attach2() contains the logic for detaching SDF's.
|
|
|
51 |
|
|
|
52 |
C. transactions
|
|
|
53 |
1. when doing bulk modifications (insert/update/delete), enclose them in a
|
|
|
54 |
transaction, otherwise it will be real slow (see SQLite benchmarks in
|
|
|
55 |
SQLite site).
|
|
|
56 |
2. Statements that are sqlite_step()-ed inside a transaction, even if they are
|
|
|
57 |
sqlite_prepare()-ed before a BEGIN.
|
|
|
58 |
3. You may use macros _sqlite_begin and _sqlite_commit. When __SQLITE_DEBUG__
|
|
|
59 |
is defined, file and lines where the BEGIN or COMMIT occurred. Besides that
|
|
|
60 |
it is convenient.
|
|
|
61 |
|