RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 07-May-2012 19:01:09 Branch: rpm-5_4 Handle: 2012050717010900 Modified files: (Branch: rpm-5_4) rpm/rpmdb rpmdb.h sqlite.c Log: - sqldb: improved schema instantiation using sql_exec callback. - sqldb: use strtoll with stricter check on callback integer coercion. Summary: Revision Changes Path 1.141.2.8 +2 -0 rpm/rpmdb/rpmdb.h 1.44.4.9 +119 -115 rpm/rpmdb/sqlite.c ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/rpmdb/rpmdb.h ============================================================================ $ cvs diff -u -r1.141.2.7 -r1.141.2.8 rpmdb.h --- rpm/rpmdb/rpmdb.h 7 May 2012 14:10:21 -0000 1.141.2.7 +++ rpm/rpmdb/rpmdb.h 7 May 2012 17:01:09 -0000 1.141.2.8 @@ -432,6 +432,8 @@ rpmTag dbi_rpmtag; /*!< rpm tag used for index */ size_t dbi_jlen; /*!< size of join key */ + int dbi_table_exists; /*!< Sqlite3: table exists? */ + /*@only@*/ /*@relnull@*/ void * dbi_seq; /*!< Berkeley DB_SEQUENCE handle */ /*@only@*/ /*@relnull@*/ @@ . patch -p0 <<'@@ .' Index: rpm/rpmdb/sqlite.c ============================================================================ $ cvs diff -u -r1.44.4.8 -r1.44.4.9 sqlite.c --- rpm/rpmdb/sqlite.c 7 May 2012 14:10:21 -0000 1.44.4.8 +++ rpm/rpmdb/sqlite.c 7 May 2012 17:01:09 -0000 1.44.4.9 @@ -927,70 +927,7 @@ return rc; } -#ifdef REFERENCE -DROP TABLE IF EXISTS Packages; -CREATE TABLE Packages ( - v INTEGER UNIQUE PRIMARY KEY NOT NULL, - k BLOB NOT NULL -); - -CREATE TRIGGER insert_Packages AFTER INSERT ON Packages - BEGIN - INSERT INTO Nvra (k,v) VALUES ( - new.k, new.rowid ); - INSERT INTO Name (k,v) VALUES ( - SUBSTR(new.k, 1, 4), new.rowid ); - INSERT INTO Version (k,v) VALUES ( - SUBSTR(new.k, 6, 3), new.rowid ); - INSERT INTO Release (k,v) VALUES ( - SUBSTR(new.k, 10, 1), new.rowid ); - INSERT INTO Arch (k,v) VALUES ( - SUBSTR(new.k, 12), new.rowid ); - END; -CREATE TRIGGER delete_Packages BEFORE DELETE ON Packages - BEGIN - DELETE FROM Nvra WHERE v = old.rowid; - DELETE FROM Name WHERE v = old.rowid; - DELETE FROM Version WHERE v = old.rowid; - DELETE FROM Release WHERE v = old.rowid; - DELETE FROM Arch WHERE v = old.rowid; - END; - -DROP TABLE IF EXISTS Nvra; -CREATE TABLE Nvra ( - k TEXT NOT NULL, - v INTEGER REFERENCES Packages -); - -DROP TABLE IF EXISTS Name; -CREATE TABLE Name ( - k TEXT NOT NULL, - v INTEGER REFERENCES Packages -); - -DROP TABLE IF EXISTS Version; -CREATE TABLE Version ( - k TEXT NOT NULL, - v INTEGER REFERENCES Packages -); - -DROP TABLE IF EXISTS Release; -CREATE TABLE Release ( - k TEXT NOT NULL, - v INTEGER REFERENCES Packages -); - -DROP TABLE IF EXISTS Arch; -CREATE TABLE Arch ( - k TEXT NOT NULL, - v INTEGER REFERENCES Packages -); - - - - -#endif - +/* XXX FIXME: all the "new.key" fields in trigger need headerGet() getter */ static const char _Packages_sql_init[] = "\ CREATE TABLE IF NOT EXISTS 'Packages' (\n\ key INTEGER UNIQUE PRIMARY KEY NOT NULL,\n\ @@ -1090,6 +1027,33 @@ );\n\ "; +static const char * tagTypes[] = { + "", + "INTEGER NOT NULL", /* RPM_UINT8_TYPE */ + "INTEGER NOT NULL", /* RPM_UINT8_TYPE */ + "INTEGER NOT NULL", /* RPM_UINT16_TYPE */ + "INTEGER NOT NULL", /* RPM_UINT32_TYPE */ + "INTEGER NOT NULL", /* RPM_UINT64_TYPE */ + "TEXT NOT NULL", /* RPM_STRING_TYPE */ + "BLOB NOT NULL", /* RPM_BIN_TYPE */ + "TEXT NOT NULL", /* RPM_STRING_ARRAY_TYPE */ + "TEXT NOT NULL", /* RPM_I18NSTRING_TYPE */ +}; +static size_t ntagTypes = sizeof(tagTypes) / sizeof(tagTypes[0]); + +static int sql_initDB_cb(void * _dbi, int argc, char ** argv, char ** cols) +{ + dbiIndex dbi = (dbiIndex) _dbi; + int rc = -1; + if (dbi && argc == 1) { + char * end = NULL; + dbi->dbi_table_exists = strtoll(argv[0], &end, 10); + if (end && *end == '\0') rc = 0; + } +SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p[%d],%p) rc %d table_exists %llu\n", __FUNCTION__, _dbi, argv, argc, cols, rc, (unsigned long long) (dbi ? dbi->dbi_table_exists : 0))); + return rc; +} + /** * Verify the DB is setup.. if not initialize it * @@ -1099,11 +1063,59 @@ /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ /*@modifies internalState @*/ { - rpmsql sql = (rpmsql) dbi->dbi_db; - SCP_t scp = scpNew(sql); char cmd[BUFSIZ]; int rc = 0; -int xx; + +#ifdef REFERENCE +PRAGMA auto_vacuum = 0 | NONE | 1 | FULL | 2 | INCREMENTAL; +PRAGMA automatic_index = boolean; +PRAGMA cache_size = pages | -kibibytes; +PRAGMA case_sensitive_like = boolean; +PRAGMA checkpoint_fullfsync = boolean; +PRAGMA collation_list; +PRAGMA compile_options; +PRAGMA count_changes = boolean; +PRAGMA database_list; +PRAGMA default_cache_size = Number-of-pages; +PRAGMA empty_result_callbacks = boolean; +PRAGMA encoding = "UTF-8" | "UTF-16" | "UTF-16le" | "UTF-16be"; +PRAGMA foreign_key_list(table-name); +PRAGMA foreign_keys = boolean; +PRAGMA freelist_count; +PRAGMA full_column_names = boolean; +PRAGMA fullfsync = boolean; +PRAGMA ignore_check_constraints = boolean; +PRAGMA incremental_vacuum(N); +PRAGMA index_info(index-name); +PRAGMA index_list(table-name); +PRAGMA integrity_check(integer) +PRAGMA database.journal_mode = DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF; +PRAGMA journal_size_limit = N; +PRAGMA legacy_file_format = boolean; +PRAGMA locking_mode = NORMAL | EXCLUSIVE; +PRAGMA max_page_count = N; +PRAGMA page_count; +PRAGMA page_size = bytes; +PRAGMA parser_trace = boolean; +PRAGMA quick_check(integer); +PRAGMA read_uncommitted = boolean; +PRAGMA recursive_triggers = boolean; +PRAGMA reverse_unordered_selects = boolean; +PRAGMA schema_version = integer; +PRAGMA user_version = integer; +PRAGMA database.secure_delete = boolean; +PRAGMA short_column_names = boolean; (deprecated) +PRAGMA shrink_memory; +PRAGMA synchronous = 0 | OFF | 1 | NORMAL | 2 | FULL; +PRAGMA table_info(table-name); +PRAGMA temp_store = 0 | DEFAULT | 1 | FILE | 2 | MEMORY; +PRAGMA temp_store_directory = 'directory-name'; +PRAGMA vdbe_listing = boolean; +PRAGMA vdbe_trace = boolean; +PRAGMA wal_autocheckpoint=N; +PRAGMA database.wal_checkpoint(PASSIVE | FULL | RESTART); +PRAGMA writable_schema = boolean; +#endif if (dbi->dbi_tmpdir) { const char *root; @@ -1114,41 +1126,46 @@ tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL); if (rpmioMkpath(tmpdir, 0755, getuid(), getgid()) == 0) { sprintf(cmd, " PRAGMA temp_store_directory = '%s';", tmpdir); - xx = sql_exec(dbi, cmd, NULL, NULL); + rc = sql_exec(dbi, cmd, NULL, NULL); } tmpdir = _free(tmpdir); } if (dbi->dbi_eflags & DB_EXCL) { sprintf(cmd, " PRAGMA locking_mode = EXCLUSIVE;"); - xx = sql_exec(dbi, cmd, NULL, NULL); + rc = sql_exec(dbi, cmd, NULL, NULL); + } + + if (dbi->dbi_no_fsync) { + static const char _cmd[] = " PRAGMA synchronous = OFF;"; + rc = sql_exec(dbi, _cmd, NULL, NULL); } #ifdef DYING if (dbi->dbi_pagesize > 0) { sprintf(cmd, " PRAGMA cache_size = %d;", dbi->dbi_cachesize); - xx = sql_exec(dbi, cmd, NULL, NULL); + rc = sql_exec(dbi, cmd, NULL, NULL); } if (dbi->dbi_cachesize > 0) { sprintf(cmd, " PRAGMA page_size = %d;", dbi->dbi_pagesize); - xx = sql_exec(dbi, cmd, NULL, NULL); + rc = sql_exec(dbi, cmd, NULL, NULL); } #endif - /* Check if the table exists... */ - /* XXX add dbi->exists? to avoid endless repetition. */ - sprintf(cmd, - " SELECT name FROM 'sqlite_master' WHERE type='table' and name='%s';", - dbi->dbi_subfile); -/*@-nullstate@*/ - rc = sql_get_table(dbi, scp, cmd); -/*@=nullstate@*/ - if (rc) - goto exit; + /* Create the table schema (if not already done). */ + if (!dbi->dbi_table_exists) { + sprintf(cmd, "\ + SELECT count(type) FROM 'sqlite_master' WHERE type='table' and name='%s';\n\ +", dbi->dbi_subfile); + rc = sql_exec(dbi, cmd, sql_initDB_cb, dbi); + if (rc) + goto exit; + } - if (scp->nr < 1) { + if (!dbi->dbi_table_exists) { const char * valtype = "INTEGER REFERENCES Packages"; const char * keytype; + int kt; switch (dbi->dbi_rpmtag) { case RPMDBI_PACKAGES: @@ -1156,44 +1173,29 @@ /*@ fallthrough @*/ case RPMTAG_PUBKEYS: case RPMDBI_SEQNO: - goto bottom; + keytype = NULL; + break; default: - switch (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE) { - case RPM_BIN_TYPE: - default: - keytype = "BLOB UNIQUE"; - /*@innerbreak@*/ break; - case RPM_UINT8_TYPE: - case RPM_UINT16_TYPE: - case RPM_UINT32_TYPE: - case RPM_UINT64_TYPE: - keytype = "INTEGER UNIQUE"; - /*@innerbreak@*/ break; - case RPM_STRING_TYPE: - case RPM_STRING_ARRAY_TYPE: - case RPM_I18NSTRING_TYPE: - keytype = "TEXT UNIQUE"; - /*@innerbreak@*/ break; - } + kt = (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE); + keytype = tagTypes[(kt > 0 && kt < (int)ntagTypes ? kt : 0)]; + break; } -SQLDBDEBUG(dbi, (stderr, "\t%s(%d) type(%d) keytype %s\n", tagName(dbi->dbi_rpmtag), dbi->dbi_rpmtag, (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE), keytype)); - /* XXX no need for IF NOT EXISTS */ - sprintf(cmd, " CREATE %sTABLE IF NOT EXISTS '%s' (key %s, value %s)", + + if (keytype) { + /* XXX no need for IF NOT EXISTS */ + /* XXX add per-table triggers? */ + sprintf(cmd, "\ + CREATE %sTABLE IF NOT EXISTS '%s' (key %s, value %s);\ +", dbi->dbi_temporary ? "TEMPORARY " : "", dbi->dbi_subfile, keytype, valtype); - rc = sql_exec(dbi, cmd, NULL, NULL); - if (rc) - goto exit; - } - -bottom: - if (dbi->dbi_no_fsync) { - static const char _cmd[] = " PRAGMA synchronous = OFF;"; - xx = sql_exec(dbi, _cmd, NULL, NULL); + rc = sql_exec(dbi, cmd, NULL, NULL); + if (rc) + goto exit; + } } exit: - scp = scpFree(scp); SQLDBDEBUG(dbi, (stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, dbi, rc)); @@ -1497,8 +1499,10 @@ dbiIndex dbi = (dbiIndex) _dbi; int rc = -1; if (dbi && argc == 1) { - dbi->dbi_seqno = atoll(argv[0]); - rc = 0; + char * end = NULL; + dbi->dbi_seqno = strtoll(argv[0], &end, 10); + if (end && *end) rc = 0; + if (end && *end == '\0') rc = 0; } SQLDBDEBUG(dbi, (stderr, "<-- %s(%p,%p[%d],%p) rc %d seqno %llu\n", __FUNCTION__, _dbi, argv, argc, cols, rc, (unsigned long long) (dbi ? dbi->dbi_seqno : 0))); return rc; @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org