diff options
-rwxr-xr-x | compatcheck/sqlite3-difftbl-check.py.in | 6 | ||||
-rw-r--r-- | src/lib/datasrc/sqlite3_accessor.cc | 33 | ||||
-rw-r--r-- | src/lib/datasrc/sqlite3_datasrc.cc | 46 | ||||
-rw-r--r-- | src/lib/python/isc/datasrc/sqlite3_ds.py | 44 |
4 files changed, 75 insertions, 54 deletions
diff --git a/compatcheck/sqlite3-difftbl-check.py.in b/compatcheck/sqlite3-difftbl-check.py.in index e3b7b91a18..a874b33de6 100755 --- a/compatcheck/sqlite3-difftbl-check.py.in +++ b/compatcheck/sqlite3-difftbl-check.py.in @@ -47,9 +47,9 @@ except sqlite3.OperationalError as ex: 'zone_id INTEGER NOT NULL, ' + 'version INTEGER NOT NULL, ' + 'operation INTEGER NOT NULL, ' + - 'name STRING NOT NULL COLLATE NOCASE, ' + - 'rrtype STRING NOT NULL COLLATE NOCASE, ' + - 'ttl INTEGER NOT NULL, rdata STRING NOT NULL)') + 'name TEXT NOT NULL COLLATE NOCASE, ' + + 'rrtype TEXT NOT NULL COLLATE NOCASE, ' + + 'ttl INTEGER NOT NULL, rdata TEXT NOT NULL)') else: sys.stdout.write('Found an older version of SQLite3 DB file: ' + db_file + '\n' + "Perform '" + os.getcwd() + diff --git a/src/lib/datasrc/sqlite3_accessor.cc b/src/lib/datasrc/sqlite3_accessor.cc index 308df607a3..8b90b91420 100644 --- a/src/lib/datasrc/sqlite3_accessor.cc +++ b/src/lib/datasrc/sqlite3_accessor.cc @@ -258,31 +258,38 @@ const char* const SCHEMA_LIST[] = { "CREATE TABLE schema_version (version INTEGER NOT NULL)", "INSERT INTO schema_version VALUES (1)", "CREATE TABLE zones (id INTEGER PRIMARY KEY, " - "name STRING NOT NULL COLLATE NOCASE, " - "rdclass STRING NOT NULL COLLATE NOCASE DEFAULT 'IN', " + "name TEXT NOT NULL COLLATE NOCASE, " + "rdclass TEXT NOT NULL COLLATE NOCASE DEFAULT 'IN', " "dnssec BOOLEAN NOT NULL DEFAULT 0)", "CREATE INDEX zones_byname ON zones (name)", "CREATE TABLE records (id INTEGER PRIMARY KEY, " - "zone_id INTEGER NOT NULL, name STRING NOT NULL COLLATE NOCASE, " - "rname STRING NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, " - "rdtype STRING NOT NULL COLLATE NOCASE, sigtype STRING COLLATE NOCASE, " - "rdata STRING NOT NULL)", + "zone_id INTEGER NOT NULL, name TEXT NOT NULL COLLATE NOCASE, " + "rname TEXT NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, " + "rdtype TEXT NOT NULL COLLATE NOCASE, sigtype TEXT COLLATE NOCASE, " + "rdata TEXT NOT NULL)", "CREATE INDEX records_byname ON records (name)", "CREATE INDEX records_byrname ON records (rname)", + // The next index is a tricky one. It's necessary for + // FIND_PREVIOUS to use the index efficiently; since there's an + // "inequality", the rname column must be placed later. records_byrname + // may not be sufficient especially when the zone is not signed (and + // defining a separate index for rdtype only doesn't work either; SQLite3 + // would then create a temporary B-tree for "ORDER BY"). + "CREATE INDEX records_bytype_and_rname ON records (rdtype, rname)", "CREATE TABLE nsec3 (id INTEGER PRIMARY KEY, zone_id INTEGER NOT NULL, " - "hash STRING NOT NULL COLLATE NOCASE, " - "owner STRING NOT NULL COLLATE NOCASE, " - "ttl INTEGER NOT NULL, rdtype STRING NOT NULL COLLATE NOCASE, " - "rdata STRING NOT NULL)", + "hash TEXT NOT NULL COLLATE NOCASE, " + "owner TEXT NOT NULL COLLATE NOCASE, " + "ttl INTEGER NOT NULL, rdtype TEXT NOT NULL COLLATE NOCASE, " + "rdata TEXT NOT NULL)", "CREATE INDEX nsec3_byhash ON nsec3 (hash)", "CREATE TABLE diffs (id INTEGER PRIMARY KEY, " "zone_id INTEGER NOT NULL, " "version INTEGER NOT NULL, " "operation INTEGER NOT NULL, " - "name STRING NOT NULL COLLATE NOCASE, " - "rrtype STRING NOT NULL COLLATE NOCASE, " + "name TEXT NOT NULL COLLATE NOCASE, " + "rrtype TEXT NOT NULL COLLATE NOCASE, " "ttl INTEGER NOT NULL, " - "rdata STRING NOT NULL)", + "rdata TEXT NOT NULL)", NULL }; diff --git a/src/lib/datasrc/sqlite3_datasrc.cc b/src/lib/datasrc/sqlite3_datasrc.cc index 7cd565d81d..67f9b45d68 100644 --- a/src/lib/datasrc/sqlite3_datasrc.cc +++ b/src/lib/datasrc/sqlite3_datasrc.cc @@ -26,7 +26,7 @@ #include <dns/rrset.h> #include <dns/rrsetlist.h> -#define SQLITE_SCHEMA_VERSION 1 +#define SQLITE_SCHEMA_VERSION 2 using namespace std; using namespace isc::dns; @@ -57,33 +57,34 @@ struct Sqlite3Parameters { namespace { const char* const SCHEMA_LIST[] = { "CREATE TABLE schema_version (version INTEGER NOT NULL)", - "INSERT INTO schema_version VALUES (1)", + "INSERT INTO schema_version VALUES (2)", "CREATE TABLE zones (id INTEGER PRIMARY KEY, " - "name STRING NOT NULL COLLATE NOCASE, " - "rdclass STRING NOT NULL COLLATE NOCASE DEFAULT 'IN', " + "name TEXT NOT NULL COLLATE NOCASE, " + "rdclass TEXT NOT NULL COLLATE NOCASE DEFAULT 'IN', " "dnssec BOOLEAN NOT NULL DEFAULT 0)", "CREATE INDEX zones_byname ON zones (name)", "CREATE TABLE records (id INTEGER PRIMARY KEY, " - "zone_id INTEGER NOT NULL, name STRING NOT NULL COLLATE NOCASE, " - "rname STRING NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, " - "rdtype STRING NOT NULL COLLATE NOCASE, sigtype STRING COLLATE NOCASE, " - "rdata STRING NOT NULL)", + "zone_id INTEGER NOT NULL, name TEXT NOT NULL COLLATE NOCASE, " + "rname TEXT NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, " + "rdtype TEXT NOT NULL COLLATE NOCASE, sigtype TEXT COLLATE NOCASE, " + "rdata TEXT NOT NULL)", "CREATE INDEX records_byname ON records (name)", "CREATE INDEX records_byrname ON records (rname)", + "CREATE INDEX records_bytype_and_rname ON records (rdtype, rname)", "CREATE TABLE nsec3 (id INTEGER PRIMARY KEY, zone_id INTEGER NOT NULL, " - "hash STRING NOT NULL COLLATE NOCASE, " - "owner STRING NOT NULL COLLATE NOCASE, " - "ttl INTEGER NOT NULL, rdtype STRING NOT NULL COLLATE NOCASE, " - "rdata STRING NOT NULL)", + "hash TEXT NOT NULL COLLATE NOCASE, " + "owner TEXT NOT NULL COLLATE NOCASE, " + "ttl INTEGER NOT NULL, rdtype TEXT NOT NULL COLLATE NOCASE, " + "rdata TEXT NOT NULL)", "CREATE INDEX nsec3_byhash ON nsec3 (hash)", "CREATE TABLE diffs (id INTEGER PRIMARY KEY, " "zone_id INTEGER NOT NULL, " "version INTEGER NOT NULL, " "operation INTEGER NOT NULL, " - "name STRING NOT NULL COLLATE NOCASE, " - "rrtype STRING NOT NULL COLLATE NOCASE, " + "name TEXT NOT NULL COLLATE NOCASE, " + "rrtype TEXT NOT NULL COLLATE NOCASE, " "ttl INTEGER NOT NULL, " - "rdata STRING NOT NULL)", + "rdata TEXT NOT NULL)", NULL }; @@ -109,12 +110,16 @@ const char* const q_referral_str = "SELECT rdtype, ttl, sigtype, rdata FROM " const char* const q_any_str = "SELECT rdtype, ttl, sigtype, rdata " "FROM records WHERE zone_id=?1 AND name=?2"; +// Note: the wildcard symbol '%' is expected to be added to the text +// for the placeholder for LIKE given via sqlite3_bind_text(). We don't +// use the expression such as (?2 || '%') because it would disable the use +// of indices and could result in terrible performance. const char* const q_count_str = "SELECT COUNT(*) FROM records " - "WHERE zone_id=?1 AND rname LIKE (?2 || '%');"; + "WHERE zone_id=?1 AND rname LIKE ?2;"; const char* const q_previous_str = "SELECT name FROM records " - "WHERE zone_id=?1 AND rdtype = 'NSEC' AND " - "rname < $2 ORDER BY rname DESC LIMIT 1"; + "WHERE rname < ?2 AND zone_id=?1 AND rdtype = 'NSEC' " + "ORDER BY rname DESC LIMIT 1"; const char* const q_nsec3_str = "SELECT rdtype, ttl, rdata FROM nsec3 " "WHERE zone_id = ?1 AND hash = $2"; @@ -314,8 +319,9 @@ Sqlite3DataSrc::findRecords(const Name& name, const RRType& rdtype, " to SQL statement (qcount)"); } - const string revname_text = name.reverse().toText(); - rc = sqlite3_bind_text(dbparameters->q_count_, 2, revname_text.c_str(), + const string revname_text = name.reverse().toText() + "%"; + rc = sqlite3_bind_text(dbparameters->q_count_, 2, + revname_text.c_str(), -1, SQLITE_STATIC); if (rc != SQLITE_OK) { isc_throw(Sqlite3Error, "Could not bind name " << name.reverse() << diff --git a/src/lib/python/isc/datasrc/sqlite3_ds.py b/src/lib/python/isc/datasrc/sqlite3_ds.py index daa12fc117..c0dcc2c3e6 100644 --- a/src/lib/python/isc/datasrc/sqlite3_ds.py +++ b/src/lib/python/isc/datasrc/sqlite3_ds.py @@ -23,6 +23,9 @@ RR_NAME_INDEX = 2 RR_TTL_INDEX = 4 RR_RDATA_INDEX = 7 +# Current version of schema (maybe we need a minor version, too) +SCHEMA_VERSION = 2 + class Sqlite3DSError(Exception): """ Define exceptions.""" pass @@ -48,39 +51,43 @@ def create(cur): row = cur.fetchone() except sqlite3.OperationalError: cur.execute("CREATE TABLE schema_version (version INTEGER NOT NULL)") - cur.execute("INSERT INTO schema_version VALUES (1)") + cur.execute("INSERT INTO schema_version VALUES (" + + str(SCHEMA_VERSION) + ")") cur.execute("""CREATE TABLE zones (id INTEGER PRIMARY KEY, - name STRING NOT NULL COLLATE NOCASE, - rdclass STRING NOT NULL COLLATE NOCASE DEFAULT 'IN', + name TEXT NOT NULL COLLATE NOCASE, + rdclass TEXT NOT NULL COLLATE NOCASE DEFAULT 'IN', dnssec BOOLEAN NOT NULL DEFAULT 0)""") cur.execute("CREATE INDEX zones_byname ON zones (name)") cur.execute("""CREATE TABLE records (id INTEGER PRIMARY KEY, zone_id INTEGER NOT NULL, - name STRING NOT NULL COLLATE NOCASE, - rname STRING NOT NULL COLLATE NOCASE, + name TEXT NOT NULL COLLATE NOCASE, + rname TEXT NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, - rdtype STRING NOT NULL COLLATE NOCASE, - sigtype STRING COLLATE NOCASE, - rdata STRING NOT NULL)""") + rdtype TEXT NOT NULL COLLATE NOCASE, + sigtype TEXT COLLATE NOCASE, + rdata TEXT NOT NULL)""") cur.execute("CREATE INDEX records_byname ON records (name)") cur.execute("CREATE INDEX records_byrname ON records (rname)") + cur.execute("""CREATE INDEX records_bytype_and_rname ON records + (rdtype, rname)""") cur.execute("""CREATE TABLE nsec3 (id INTEGER PRIMARY KEY, zone_id INTEGER NOT NULL, - hash STRING NOT NULL COLLATE NOCASE, - owner STRING NOT NULL COLLATE NOCASE, + hash TEXT NOT NULL COLLATE NOCASE, + owner TEXT NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, - rdtype STRING NOT NULL COLLATE NOCASE, - rdata STRING NOT NULL)""") + rdtype TEXT NOT NULL COLLATE NOCASE, + rdata TEXT NOT NULL)""") cur.execute("CREATE INDEX nsec3_byhash ON nsec3 (hash)") cur.execute("""CREATE TABLE diffs (id INTEGER PRIMARY KEY, zone_id INTEGER NOT NULL, version INTEGER NOT NULL, operation INTEGER NOT NULL, - name STRING NOT NULL COLLATE NOCASE, - rrtype STRING NOT NULL COLLATE NOCASE, + name TEXT NOT NULL COLLATE NOCASE, + rrtype TEXT NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, - rdata STRING NOT NULL)""") - row = [1] + rdata TEXT NOT NULL)""") + cur.execute("SELECT version FROM schema_version") + row = cur.fetchone() cur.execute("COMMIT TRANSACTION") return row @@ -115,8 +122,9 @@ def open(dbfile, connect_timeout=5.0): row = create(cur) conn.isolation_level = iso_lvl - if row == None or row[0] != 1: - raise Sqlite3DSError("Bad database schema version") + if row == None or row[0] != SCHEMA_VERSION: + bad_version = "(unknown)" if row is None else str(row[0]) + raise Sqlite3DSError("Bad database schema version: " + bad_version) return conn, cur |