getReferenceSequencesByRid(
Connection conn, String assembly, String schema) throws SQLException {
String sql =
- "SELECT _gri_rid, gri_refseq_name, gri_refseq_length, gri_assembly, gri_refget_id, gri_refseq_meta_json FROM ";
+ "SELECT _gri_rid, gri_refseq_name, gri_refseq_length, gri_assembly, gri_refget_id,"
+ + " gri_refseq_meta_json FROM ";
if (schema != null && schema.length() > 0) {
sql += schema + ".";
}
diff --git a/bindings/jdbc/genomicsqlite-jdbc/src/main/java/net/mlin/genomicsqlite/JdbcDriver.java b/bindings/jdbc/genomicsqlite-jdbc/src/main/java/net/mlin/genomicsqlite/JdbcDriver.java
index 3fc605a..fcd501e 100644
--- a/bindings/jdbc/genomicsqlite-jdbc/src/main/java/net/mlin/genomicsqlite/JdbcDriver.java
+++ b/bindings/jdbc/genomicsqlite-jdbc/src/main/java/net/mlin/genomicsqlite/JdbcDriver.java
@@ -40,7 +40,9 @@ public class JdbcDriver extends org.sqlite.JDBC {
}
}
- /** @see java.sql.Driver#acceptsURL(java.lang.String) */
+ /**
+ * @see java.sql.Driver#acceptsURL(java.lang.String)
+ */
@Override
public boolean acceptsURL(String url) {
return isValidURL(url);
@@ -56,7 +58,9 @@ public static boolean isValidURL(String url) {
return url != null && url.toLowerCase().startsWith(PREFIX);
}
- /** @see java.sql.Driver#connect(java.lang.String, java.util.Properties) */
+ /**
+ * @see java.sql.Driver#connect(java.lang.String, java.util.Properties)
+ */
@Override
public Connection connect(String url, Properties info) throws SQLException {
return createConnection(url, info);
diff --git a/bindings/python/genomicsqlite/__init__.py b/bindings/python/genomicsqlite/__init__.py
old mode 100755
new mode 100644
index ea9f3cf..266df4e
--- a/bindings/python/genomicsqlite/__init__.py
+++ b/bindings/python/genomicsqlite/__init__.py
@@ -2,12 +2,13 @@
"""
GenomicSQLite Python binding
"""
+
+import json
import os
-import sys
import platform
-import json
import sqlite3
-from typing import Optional, NamedTuple, Dict, Any
+import sys
+from typing import Any, Dict, NamedTuple, Optional
_HERE = os.path.dirname(__file__)
_YES = ("1", "true", "t", "yes", "y")
@@ -173,9 +174,9 @@ def get_reference_sequences_by_rid(
params = (assembly,)
ans = {}
for row in con.execute(sql, params):
- assert (
- isinstance(row[0], int) and row[0] not in ans
- ), "genomicsqlite: invalid or duplicate reference sequence rid"
+ assert isinstance(row[0], int) and row[0] not in ans, (
+ "genomicsqlite: invalid or duplicate reference sequence rid"
+ )
ans[row[0]] = ReferenceSequence(
rid=row[0],
name=row[1],
@@ -252,6 +253,7 @@ def _cli(argv=None):
sys.exit(1)
import shutil
+ import tempfile
if not shutil.which("sqlite3"):
print(
@@ -271,30 +273,36 @@ def _cli(argv=None):
uri = _execute1(_MEMCONN, "SELECT genomicsqlite_uri(?,?)", (argv[1], cfg))
tuning_sql = _execute1(_MEMCONN, "SELECT genomicsqlite_tuning_sql(?)", (cfg,))
- cmd = [
- "sqlite3",
- "-bail",
- "-cmd",
+ # Assemble the shell startup commands into a temporary -init file, instead of passing them
+ # as -cmd arguments: since SQLite 3.52, the shell quits immediately (with a success exit
+ # code, without reading any input) whenever -bail is combined with an SQL -cmd argument,
+ # which silently disabled this wrapper. os.execvp() below replaces this process, so the
+ # file can't be unlinked afterwards; leave it for the OS temp reaper.
+ tuning_sql = tuning_sql.strip()
+ if not tuning_sql.endswith(";"):
+ # in -init file context, an unterminated statement would absorb the following line
+ tuning_sql += ";"
+ init_lines = [
f".load {_DLL}",
- "-cmd",
f".open {uri}",
- "-cmd",
".once /dev/null",
- "-cmd",
tuning_sql,
- "-cmd",
'.prompt "GenomicSQLite> "',
]
if sys.stdout.isatty() and not next(
(arg for arg in argv[2:] if not arg.startswith("-")), False
):
- # interactive mode:
- cmd += [
- "-cmd",
- "SELECT 'GenomicSQLite ' || genomicsqlite_version()",
- "-cmd",
+ # interactive mode: print version banner, then turn on column headers
+ init_lines += [
+ "SELECT 'GenomicSQLite ' || genomicsqlite_version();",
".headers on",
]
+ with tempfile.NamedTemporaryFile(
+ "w", prefix="genomicsqlite-init-", suffix=".sql", delete=False
+ ) as init_file:
+ init_file.write("\n".join(init_lines) + "\n")
+
+ cmd = ["sqlite3", "-bail", "-init", init_file.name]
cmd.append(":memory:") # placeholder so remaining positional args are recognized as such
cmd += argv[2:]
diff --git a/bindings/python/genomicsqlite/__main__.py b/bindings/python/genomicsqlite/__main__.py
index ba91ed0..bd19d9c 100644
--- a/bindings/python/genomicsqlite/__main__.py
+++ b/bindings/python/genomicsqlite/__main__.py
@@ -1,4 +1,5 @@
import sys
+
from . import _cli
if __name__ == "__main__":
diff --git a/bindings/python/setup.py b/bindings/python/setup.py
old mode 100755
new mode 100644
index 13b2af2..141a0aa
--- a/bindings/python/setup.py
+++ b/bindings/python/setup.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
from os import path
-from setuptools import setup, find_packages
+
+from setuptools import find_packages, setup # pylint: disable=import-error
from version import get_version
HERE = path.abspath(path.dirname(__file__))
diff --git a/bindings/python/version.py b/bindings/python/version.py
index ddd2328..964f594 100644
--- a/bindings/python/version.py
+++ b/bindings/python/version.py
@@ -48,7 +48,6 @@
import subprocess
import sys
-
RELEASE_VERSION_FILE = "RELEASE-VERSION"
# http://www.python.org/dev/peps/pep-0386/
@@ -77,7 +76,7 @@ def read_git_version():
return None
match = re.search(_GIT_DESCRIPTION_RE, ver)
if not match:
- sys.stderr.write("version: git description (%s) is invalid, " "ignoring\n" % ver)
+ sys.stderr.write("version: git description (%s) is invalid, ignoring\n" % ver)
return None
commits = int(match.group("commits"))
@@ -91,9 +90,7 @@ def read_release_version():
with open(RELEASE_VERSION_FILE) as infile:
ver = infile.readline().strip()
if not re.search(_PEP386_VERSION_RE, ver):
- sys.stderr.write(
- "version: release version (%s) is invalid, " "will use it anyway\n" % ver
- )
+ sys.stderr.write("version: release version (%s) is invalid, will use it anyway\n" % ver)
return ver
except:
return None
diff --git a/bindings/rust/.gitignore b/bindings/rust/.gitignore
index 2d7878f..042eab2 100644
--- a/bindings/rust/.gitignore
+++ b/bindings/rust/.gitignore
@@ -13,3 +13,4 @@ Cargo.lock
# Cargo.toml is generated from Cargo.toml.in by ./cargo
Cargo.toml
libgenomicsqlite.*
+libgenomicsqlite-*
diff --git a/bindings/rust/Cargo.toml.in b/bindings/rust/Cargo.toml.in
index 7813476..d3979a9 100644
--- a/bindings/rust/Cargo.toml.in
+++ b/bindings/rust/Cargo.toml.in
@@ -7,7 +7,7 @@ edition = "2018"
license = "Apache-2.0"
repository = "https://github.com/mlin/GenomicSQLite"
documentation = "https://mlin.github.io/GenomicSQLite"
-include = ["src/**/*", "Cargo.toml", "libgenomicsqlite.*"]
+include = ["src/**/*", "Cargo.toml", "build.rs", "libgenomicsqlite.*", "libgenomicsqlite-*"]
[features]
# Use default-features=false to prevent bundling a platform-specific libgenomicsqlite into your
diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs
new file mode 100644
index 0000000..5460adf
--- /dev/null
+++ b/bindings/rust/build.rs
@@ -0,0 +1,74 @@
+// Build script for the genomicsqlite crate: inventory the prebuilt
+// libgenomicsqlite libraries bundled next to Cargo.toml.
+//
+// A bundled library is embedded into the compilation unit only for the
+// target it was built for, under a per-OS/architecture file name:
+// libgenomicsqlite-linux-x86_64.so
+// libgenomicsqlite-linux-aarch64.so
+// libgenomicsqlite-macos-aarch64.dylib
+// macOS x86_64 is deliberately not a bundled target (macOS CI builds
+// ARM-only), so it falls back to the runtime library search like any
+// other unsupported target.
+// For each candidate file that actually exists in the package, this script
+// sets a rustc cfg (bundled_linux_x86_64 etc.) gating the corresponding
+// include_bytes! arm in src/lib.rs. A missing file therefore degrades to
+// the runtime library search instead of breaking compilation with a
+// missing-file error.
+use std::env;
+use std::path::Path;
+
+// (target_os, target_arch, file name, cfg name) for each bundled candidate
+const CANDIDATES: &[(&str, &str, &str, &str)] = &[
+ (
+ "linux",
+ "x86_64",
+ "libgenomicsqlite-linux-x86_64.so",
+ "bundled_linux_x86_64",
+ ),
+ (
+ "linux",
+ "aarch64",
+ "libgenomicsqlite-linux-aarch64.so",
+ "bundled_linux_aarch64",
+ ),
+ (
+ "macos",
+ "aarch64",
+ "libgenomicsqlite-macos-aarch64.dylib",
+ "bundled_macos_aarch64",
+ ),
+];
+
+fn main() {
+ // Declare the custom cfg names unconditionally, so rustc's check-cfg
+ // validation accepts them wherever src/lib.rs mentions them.
+ for cand in CANDIDATES {
+ println!("cargo:rustc-check-cfg=cfg({})", cand.3);
+ }
+ println!("cargo:rustc-check-cfg=cfg(bundled_target)");
+
+ let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
+ let bundling = env::var_os("CARGO_FEATURE_BUNDLE_LIBGENOMICSQLITE").is_some();
+ let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
+ let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
+
+ for cand in CANDIDATES {
+ let path = Path::new(&manifest_dir).join(cand.2);
+ // Rerun this script if a bundled library appears or disappears.
+ println!("cargo:rerun-if-changed={}", path.display());
+ if path.is_file() {
+ println!("cargo:rustc-cfg={}", cand.3);
+ if cand.0 == target_os && cand.1 == target_arch {
+ // The compilation target has a bundled library, so one of
+ // the include_bytes! arms in src/lib.rs will be compiled.
+ println!("cargo:rustc-cfg=bundled_target");
+ }
+ } else if bundling && cand.0 == target_os && cand.1 == target_arch {
+ println!(
+ "cargo:warning=genomicsqlite: no bundled {} in the crate for {}-{}; \
+ the crate will fall back to searching for a system libgenomicsqlite at runtime",
+ cand.2, cand.0, cand.1
+ );
+ }
+ }
+}
diff --git a/bindings/rust/cargo b/bindings/rust/cargo
old mode 100755
new mode 100644
index 0aaa6bf..9056fd3
--- a/bindings/rust/cargo
+++ b/bindings/rust/cargo
@@ -4,7 +4,14 @@
set -e
cd `dirname $0`
-revision="$(git describe --tags --dirty)"
+revision="$(git describe --tags --dirty 2>/dev/null || true)"
+if [ -z "$revision" ]; then
+ # Tag-less checkout (e.g. actions/checkout fetches no tags): fall back to the
+ # latest release version with the short commit SHA as a prerelease suffix,
+ # keeping the generated crate version valid semver. (Update the release
+ # version here when cutting a new release.)
+ revision="0.9.4-$(git rev-parse --short HEAD)"
+fi
revision="${revision#v}" # strip 'v' prefix
>&2 echo "$revision"
diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs
index 96d41cf..1cdc6c7 100644
--- a/bindings/rust/src/lib.rs
+++ b/bindings/rust/src/lib.rs
@@ -7,9 +7,9 @@ use json::object::Object;
use rusqlite::{params, Connection, LoadExtensionGuard, OpenFlags, Result};
use std::collections::HashMap;
use std::env;
-#[cfg(feature = "bundle_libgenomicsqlite")]
+#[cfg(all(feature = "bundle_libgenomicsqlite", bundled_target))]
use std::fs::File;
-#[cfg(feature = "bundle_libgenomicsqlite")]
+#[cfg(all(feature = "bundle_libgenomicsqlite", bundled_target))]
use std::io::prelude::*;
use std::path::Path;
use std::sync::Once;
@@ -18,7 +18,7 @@ use tempfile::TempDir;
/* Helper functions for bundling libgenomicsqlite.{so,dylib} into the compilation unit */
// extract slice into basename under a temp directory
-#[cfg(feature = "bundle_libgenomicsqlite")]
+#[cfg(all(feature = "bundle_libgenomicsqlite", bundled_target))]
fn extract_libgenomicsqlite_impl(
bytes: &[u8],
basename: &str,
@@ -40,7 +40,7 @@ fn extract_libgenomicsqlite_impl(
Ok((libpath, tmp))
}
-#[cfg(feature = "bundle_libgenomicsqlite")]
+#[cfg(all(feature = "bundle_libgenomicsqlite", bundled_target))]
fn extract_libgenomicsqlite(bytes: &[u8], filename: &str) -> (String, TempDir) {
match extract_libgenomicsqlite_impl(bytes, filename) {
Ok(ans) => ans,
@@ -48,35 +48,76 @@ fn extract_libgenomicsqlite(bytes: &[u8], filename: &str) -> (String, TempDir) {
}
}
-#[cfg(not(feature = "bundle_libgenomicsqlite"))]
+/* Bundled libgenomicsqlite selection.
+ *
+ * With the bundle_libgenomicsqlite feature, the crate may embed a prebuilt
+ * libgenomicsqlite for its target, in a per-OS/architecture file next to
+ * Cargo.toml:
+ * libgenomicsqlite-linux-x86_64.so
+ * libgenomicsqlite-linux-aarch64.so
+ * libgenomicsqlite-macos-aarch64.dylib
+ * macOS x86_64 is deliberately not bundled (macOS CI builds ARM-only);
+ * it takes the fallback path below like any other unsupported target.
+ * build.rs inventories which of these files the package actually contains
+ * and sets a matching bundled_* cfg for each one present, so an arm below is
+ * compiled only when its file exists. On any other target -- or when the
+ * target's file isn't bundled -- bundle_libgenomicsqlite() returns None and
+ * open() falls back to the normal library search.
+ */
+
+#[cfg(all(
+ feature = "bundle_libgenomicsqlite",
+ target_os = "linux",
+ target_arch = "x86_64",
+ bundled_linux_x86_64
+))]
fn bundle_libgenomicsqlite() -> Option<(String, TempDir)> {
- None
+ Some(extract_libgenomicsqlite(
+ include_bytes!("../libgenomicsqlite-linux-x86_64.so"),
+ "libgenomicsqlite.so",
+ ))
}
#[cfg(all(
feature = "bundle_libgenomicsqlite",
target_os = "linux",
- target_arch = "x86_64"
+ target_arch = "aarch64",
+ bundled_linux_aarch64
))]
fn bundle_libgenomicsqlite() -> Option<(String, TempDir)> {
Some(extract_libgenomicsqlite(
- include_bytes!("../libgenomicsqlite.so"),
- &"libgenomicsqlite.so",
+ include_bytes!("../libgenomicsqlite-linux-aarch64.so"),
+ "libgenomicsqlite.so",
))
}
#[cfg(all(
feature = "bundle_libgenomicsqlite",
target_os = "macos",
- target_arch = "x86_64"
+ target_arch = "aarch64",
+ bundled_macos_aarch64
))]
fn bundle_libgenomicsqlite() -> Option<(String, TempDir)> {
Some(extract_libgenomicsqlite(
- include_bytes!("../libgenomicsqlite.dylib"),
+ include_bytes!("../libgenomicsqlite-macos-aarch64.dylib"),
"libgenomicsqlite.dylib",
))
}
+#[cfg(not(feature = "bundle_libgenomicsqlite"))]
+fn bundle_libgenomicsqlite() -> Option<(String, TempDir)> {
+ None
+}
+
+// Feature on, but no bundled library for this target (another OS, an
+// architecture the release didn't bundle, or the target's file absent from
+// the package -- build.rs sets bundled_target exactly when one of the
+// bundled arms above applies): fall back to the normal library search.
+#[cfg(all(feature = "bundle_libgenomicsqlite", not(bundled_target)))]
+fn bundle_libgenomicsqlite() -> Option<(String, TempDir)> {
+ None
+}
+
// helper for simple queries
fn query1str(conn: &Connection, sql: &str, params: P) -> Result
where
@@ -112,23 +153,32 @@ pub fn open>(path: P, flags: OpenFlags, config: &Object) -> Resul
// once: load libgenomicsqlite extension
START.call_once(|| {
let mut _tmpdir;
- let libgenomicsqlite = match env::var("LIBGENOMICSQLITE") {
- Ok(v) => v,
+ // Decide where to load libgenomicsqlite from, remembering how it was
+ // obtained, so a load failure can say exactly what was tried.
+ let (libgenomicsqlite, libgenomicsqlite_source) = match env::var("LIBGENOMICSQLITE") {
+ Ok(v) => (v, "path from the LIBGENOMICSQLITE environment variable"),
Err(_) => match bundle_libgenomicsqlite() {
Some((ans, td)) => {
_tmpdir = td;
- ans
+ (ans, "copy bundled into the genomicsqlite crate")
}
- None => "libgenomicsqlite".to_string(),
+ None => (
+ "libgenomicsqlite".to_string(),
+ "bare library name, to be searched by the system loader \
+ (no bundled copy available for this target)",
+ ),
},
};
let memconn = Connection::open_in_memory().unwrap();
unsafe {
let _guard = LoadExtensionGuard::new(&memconn).unwrap();
- match memconn.load_extension(libgenomicsqlite.clone(), None) {
+ match memconn.load_extension(libgenomicsqlite.clone(), None::<&str>) {
Err(err) => panic!(
- "genomicsqlite failed to load_extension(\"{}\"): {}",
- libgenomicsqlite, err
+ "genomicsqlite: failed to load_extension(\"{}\") [{}]: {}\n\
+ genomicsqlite needs a loadable libgenomicsqlite shared library. To provide one:\n\
+ - set the LIBGENOMICSQLITE environment variable to the path of a locally built libgenomicsqlite, or\n\
+ - install libgenomicsqlite where the system library loader can find it.",
+ libgenomicsqlite, libgenomicsqlite_source, err
),
Ok(()) => (),
}
diff --git a/docs/guide_db.md b/docs/guide_db.md
index 7b8abea..ac7ad07 100644
--- a/docs/guide_db.md
+++ b/docs/guide_db.md
@@ -94,9 +94,9 @@ First complete the [installation instructions](index.md).
=== "Python"
``` python3
dbconn = genomicsqlite.connect(
- db_filename,
- read_only=False,
- **kwargs # genomicsqlite + sqlite3.connect() arguments
+ db_filename,
+ read_only=False,
+ **kwargs, # genomicsqlite + sqlite3.connect() arguments
)
assert isinstance(dbconn, sqlite3.Connection)
```
diff --git a/docs/guide_gri.md b/docs/guide_gri.md
index 8bf7f66..747e0db 100644
--- a/docs/guide_gri.md
+++ b/docs/guide_gri.md
@@ -21,11 +21,7 @@ The extension provides routines to populate a small `_gri_refseq` table describi
=== "Python"
``` python3
create_gri_sql = genomicsqlite.create_genomic_range_index_sql(
- dbconn,
- 'tableName',
- 'chromosome',
- 'beginPosition',
- 'endPosition'
+ dbconn, "tableName", "chromosome", "beginPosition", "endPosition"
)
dbconn.executescript(create_gri_sql)
```
@@ -229,9 +225,7 @@ The following routines support the aforementioned, recommended convention for st
=== "Python"
``` python3
- refseq_sql = genomicsqlite.put_reference_assembly_sql(
- dbconn, 'GRCh38_no_alt_analysis_set'
- )
+ refseq_sql = genomicsqlite.put_reference_assembly_sql(dbconn, "GRCh38_no_alt_analysis_set")
dbconn.executescript(refseq_sql)
```
@@ -307,8 +301,10 @@ Available assemblies:
=== "Python"
``` python3
refseq_sql = genomicsqlite.put_reference_sequence_sql(
- dbconn, 'chr17', 83257441
- # optional: assembly, refget_id, meta (dict), rid
+ dbconn,
+ "chr17",
+ 83257441,
+ # optional: assembly, refget_id, meta (dict), rid
)
dbconn.executescript(refseq_sql)
```
@@ -407,12 +403,13 @@ If the `rid` argument is omitted or -1 then it will be assigned automatically up
=== "Python"
``` python3
class ReferenceSequence(NamedTuple):
- rid: int
- name: str
- length: int
- assembly: Optional[str]
- refget_id: Optional[str]
- meta: Dict[str, Any]
+ rid: int
+ name: str
+ length: int
+ assembly: Optional[str]
+ refget_id: Optional[str]
+ meta: Dict[str, Any]
+
refseq_by_rid = genomicsqlite.get_reference_sequences_by_rid(dbconn)
# refseq_by_rid: Dict[int, ReferenceSequence]
@@ -492,12 +489,13 @@ The optional `assembly` argument restricts the retrieved sequences to those with
=== "Python"
``` python3
class ReferenceSequence(NamedTuple):
- rid: int
- name: str
- length: int
- assembly: Optional[str]
- refget_id: Optional[str]
- meta: Dict[str, Any]
+ rid: int
+ name: str
+ length: int
+ assembly: Optional[str]
+ refget_id: Optional[str]
+ meta: Dict[str, Any]
+
refseq_by_name = genomicsqlite.get_reference_sequences_by_name(dbconn)
# refseq_by_name: Dict[str, ReferenceSequence]
diff --git a/docs/guide_helpers.md b/docs/guide_helpers.md
index d1cd9a7..95bc3e3 100644
--- a/docs/guide_helpers.md
+++ b/docs/guide_helpers.md
@@ -88,8 +88,8 @@ The [UINT collating sequence](https://www.sqlite.org/uintcseq.html) is also bund
=== "Python"
``` python3
- dbconn = sqlite3.connect('any.db', uri=True)
- attach_sql = genomicsqlite.attach_sql(dbconn, 'compressed.db', 'db2')
+ dbconn = sqlite3.connect("any.db", uri=True)
+ attach_sql = genomicsqlite.attach_sql(dbconn, "compressed.db", "db2")
# attach_sql() also takes configuration keyword arguments like
# genomicsqlite.connect()
dbconn.executescript(attach_sql)
@@ -190,13 +190,13 @@ The [UINT collating sequence](https://www.sqlite.org/uintcseq.html) is also bund
=== "Python"
``` python3
- dbconn = sqlite3.connect('existing.db', uri=True)
- vacuum_sql = genomicsqlite.vacuum_into_sql(dbconn, 'compressed.db')
+ dbconn = sqlite3.connect("existing.db", uri=True)
+ vacuum_sql = genomicsqlite.vacuum_into_sql(dbconn, "compressed.db")
# vacuum_into_sql() also takes configuration keyword arguments like
# genomicsqlite.connect() to control compression level & page sizes
dbconn.executescript(vacuum_sql)
- dbconn2 = genomicsqlite.connect('compressed.db')
+ dbconn2 = genomicsqlite.connect("compressed.db")
```
=== "Java"
diff --git a/docs/internals.md b/docs/internals.md
index df34720..01dd569 100644
--- a/docs/internals.md
+++ b/docs/internals.md
@@ -70,13 +70,19 @@ The extension also exposes the routine to generate the SQL subquery, which you c
=== "Python"
``` python3
query = (
- 'SELECT * FROM tableName WHERE tableName._rowid_ IN ' +
- genomicsqlite.genomic_range_rowids_sql(dbconn, 'tableName',
- # defaults:
- qrid='?1', qbeg='?2', qend='?3',
- ceiling=-1, floor=-1)
+ "SELECT * FROM tableName WHERE tableName._rowid_ IN "
+ + genomicsqlite.genomic_range_rowids_sql(
+ dbconn,
+ "tableName",
+ # defaults:
+ qrid="?1",
+ qbeg="?2",
+ qend="?3",
+ ceiling=-1,
+ floor=-1,
+ )
)
- cursor = dbconn.execute(query, ('chr12',111803912,111804012))
+ cursor = dbconn.execute(query, ("chr12", 111803912, 111804012))
```
=== "SQLiteCpp"
diff --git a/loaders/vcf_into_sqlite.cc b/loaders/vcf_into_sqlite.cc
index f3b0eb8..359f469 100644
--- a/loaders/vcf_into_sqlite.cc
+++ b/loaders/vcf_into_sqlite.cc
@@ -67,8 +67,7 @@ string schemaDDL(const string &table_prefix, vector