@@ -58,8 +58,10 @@ static void sqlfn_genomicsqlite_version(sqlite3_context *ctx, int argc,
5858std::string GenomicSQLiteDefaultConfigJSON () {
5959 return R"( {
6060 "unsafe_load": false,
61+ "immutable": false,
6162 "page_cache_MiB": 1024,
6263 "threads": -1,
64+ "force_prefetch": false,
6365 "zstd_level": 6,
6466 "inner_page_KiB": 16,
6567 "outer_page_KiB": 32
@@ -93,6 +95,13 @@ string GenomicSQLiteURI(const string &dbfile, const string &config_json = "") {
9395 SQLite::Database tmpdb (" :memory:" , SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE);
9496 auto extract = ConfigExtractor (tmpdb, config_json);
9597
98+ extract->bind (2 , " $.immutable" );
99+ if (!extract->executeStep () || extract->getColumnCount () != 1 ||
100+ !extract->getColumn (0 ).isInteger ())
101+ throw std::runtime_error (" error processing config JSON $.immutable" );
102+ bool immutable = extract->getColumn (0 ).getInt () != 0 ;
103+ extract->reset ();
104+
96105 extract->bind (2 , " $.unsafe_load" );
97106 if (!extract->executeStep () || extract->getColumnCount () != 1 ||
98107 !extract->getColumn (0 ).isInteger ())
@@ -107,6 +116,20 @@ string GenomicSQLiteURI(const string &dbfile, const string &config_json = "") {
107116 int threads = extract->getColumn (0 ).getInt ();
108117 extract->reset ();
109118
119+ extract->bind (2 , " $.force_prefetch" );
120+ if (!extract->executeStep () || extract->getColumnCount () != 1 ||
121+ !extract->getColumn (0 ).isInteger ())
122+ throw std::runtime_error (" error processing config JSON $.force_prefetch" );
123+ bool force_prefetch = extract->getColumn (0 ).getInt () != 0 ;
124+ extract->reset ();
125+
126+ extract->bind (2 , " $.inner_page_KiB" );
127+ if (!extract->executeStep () || extract->getColumnCount () != 1 ||
128+ !extract->getColumn (0 ).isInteger ())
129+ throw std::runtime_error (" error processing config JSON $.inner_page_KiB" );
130+ int inner_page_KiB = extract->getColumn (0 ).getInt ();
131+ extract->reset ();
132+
110133 extract->bind (2 , " $.outer_page_KiB" );
111134 if (!extract->executeStep () || extract->getColumnCount () != 1 ||
112135 !extract->getColumn (0 ).isInteger ())
@@ -122,13 +145,20 @@ string GenomicSQLiteURI(const string &dbfile, const string &config_json = "") {
122145 extract->reset ();
123146
124147 ostringstream uri;
125- uri << " file:" << dbfile << " ?vfs=zstd" ;
148+ uri << " file:" << dbfile << " ?vfs=zstd" ; // TODO: URI-encode dbfile
126149 uri << " &threads=" << to_string (threads);
127150 uri << " &outer_page_size=" << to_string (outer_page_KiB * 1024 );
128151 uri << " &outer_cache_size=-65536" ; // enlarge to hold index b-tree pages for large db's
129152 uri << " &level=" << to_string (zstd_level);
153+ if (threads > 1 && inner_page_KiB < 16 && !force_prefetch) {
154+ // prefetch is usually counterproductive if inner_page_KiB < 16
155+ uri << " &noprefetch=1" ;
156+ }
157+ if (immutable) {
158+ uri << " &immutable=1" ;
159+ }
130160 if (unsafe_load) {
131- uri << " &outer_unsafe" ;
161+ uri << " &nolock=1& outer_unsafe" ;
132162 }
133163 return uri.str ();
134164}
@@ -227,12 +257,14 @@ string GenomicSQLiteTuningSQL(const string &config_json, const string &schema =
227257 }
228258 map<string, string> pragmas;
229259 pragmas[schema_prefix + " cache_size" ] = to_string (-1024 * page_cache_MiB);
260+ pragmas[schema_prefix + " max_page_count" ] = " 2147483646" ;
230261 pragmas[" threads" ] =
231262 to_string (threads >= 0 ? threads : std::min (8 , (int )thread::hardware_concurrency ()));
232263 if (unsafe_load) {
233264 pragmas[schema_prefix + " journal_mode" ] = " OFF" ;
234265 pragmas[schema_prefix + " synchronous" ] = " OFF" ;
235266 pragmas[schema_prefix + " auto_vacuum" ] = " FULL" ;
267+ pragmas[schema_prefix + " locking_mode" ] = " EXCLUSIVE" ;
236268 } else {
237269 pragmas[schema_prefix + " journal_mode" ] = " MEMORY" ;
238270 }
0 commit comments