/** * Creates tables in the registry. This function is called upon an uninitialized * database to create the tables needed to record state between invocations of * `port`. * * @param [in] db database with an attached registry db * @param [out] errPtr on error, a description of the error that occurred * @return true if success; false if failure */ int create_tables(sqlite3* db, reg_error* errPtr) { static char* queries[] = { "BEGIN", /* metadata table */ "CREATE TABLE registry.metadata (key UNIQUE, value)", "INSERT INTO registry.metadata (key, value) VALUES ('version', '1.200')", "INSERT INTO registry.metadata (key, value) VALUES ('created', strftime('%s', 'now'))", /* ports table */ "CREATE TABLE registry.ports (" "id INTEGER PRIMARY KEY, " "name TEXT COLLATE NOCASE, portfile TEXT, url TEXT, " "location TEXT, epoch INTEGER, version TEXT COLLATE VERSION, " "revision INTEGER, variants TEXT, negated_variants TEXT, " "state TEXT, date DATETIME, installtype TEXT, archs TEXT, " "requested INT, os_platform TEXT, os_major INTEGER, " "UNIQUE (name, epoch, version, revision, variants), " "UNIQUE (url, epoch, version, revision, variants)" ")", "CREATE INDEX registry.port_name ON ports " "(name, epoch, version, revision, variants)", "CREATE INDEX registry.port_url ON ports " "(url, epoch, version, revision, variants)", "CREATE INDEX registry.port_state ON ports (state)", /* file map */ "CREATE TABLE registry.files (id INTEGER, path TEXT, actual_path TEXT, " "active INT, mtime DATETIME, md5sum TEXT, editable INT, binary BOOL, " "FOREIGN KEY(id) REFERENCES ports(id))", "CREATE INDEX registry.file_port ON files (id)", "CREATE INDEX registry.file_path ON files(path)", "CREATE INDEX registry.file_actual ON files(actual_path)", "CREATE INDEX registry.file_binary ON files(binary)", /* dependency map */ "CREATE TABLE registry.dependencies (id INTEGER, name TEXT, variants TEXT, " "FOREIGN KEY(id) REFERENCES ports(id))", "CREATE INDEX registry.dep_name ON dependencies (name)", /* portgroups table */ "CREATE TABLE registry.portgroups (id INTEGER, " "name TEXT, version TEXT COLLATE VERSION, size INTEGER, sha256 TEXT, " "FOREIGN KEY(id) REFERENCES ports(id))", "COMMIT", NULL }; return do_queries(db, queries, errPtr); }
int main( int argc, char *argv[] ) { int size = atol(argv[1]); int skew = atoi(argv[2]); int skew_res = atoi(argv[3]); int *input = malloc(size * sizeof(int)); int i; for (i = 0; i < size; i++) { input[i] = rand(); } qsort(input, sizeof(input)/sizeof(int), sizeof(int), icmpr); struct btree *tree = make_tree(input, 0, size-1, skew, skew_res); free(input); /* do experiments */ do_queries(pred, tree, size); return 0; }
/** * Initializes database connection. This function creates all the temporary * tables used by the registry. It also registers the user functions and * collations declared here, making them available. * * @param [in] db database to initialize * @param [out] errPtr on error, a description of the error that occurred * @return true if success; false if failure */ int init_db(sqlite3* db, reg_error* errPtr) { static char* queries[] = { "BEGIN", /* items cache */ "CREATE TEMPORARY TABLE items (refcount, proc UNIQUE, name, url, path, " "worker, options, variants)", /* indexes list */ "CREATE TEMPORARY TABLE indexes (file, name, attached)", "COMMIT", NULL }; /* I'm not error-checking these. I don't think I need to. */ sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, NULL, sql_regexp, NULL, NULL); sqlite3_create_collation(db, "VERSION", SQLITE_UTF8, NULL, sql_version); return do_queries(db, queries, errPtr); }
/** * Updates the database if necessary. This function queries the current database version * from the metadata table and executes SQL to update the schema to newer versions if needed. * After that, this function updates the database version number * * @param [in] db database to update * @param [out] errPtr on error, a description of the error that occurred * @return true if success; false if failure */ int update_db(sqlite3* db, reg_error* errPtr) { const char* version; int r; int did_update = 0; /* true, if an update was done and the loop should be run again */ char* q_begin = "BEGIN"; char* q_version = "SELECT value FROM registry.metadata WHERE key = 'version'"; char* query = q_begin; sqlite3_stmt* stmt = NULL; do { did_update = 0; /* open a transaction to prevent a check-and-change race condition between * multiple port(1) instances */ if ((r = sqlite3_prepare_v2(db, query, -1, &stmt, NULL)) != SQLITE_OK) { break; } if ((r = sqlite3_step(stmt)) != SQLITE_DONE) { break; } sqlite3_finalize(stmt); stmt = NULL; /* query current version number */ query = q_version; if ((r = sqlite3_prepare_v2(db, query, -1, &stmt, NULL)) != SQLITE_OK) { break; } r = sqlite3_step(stmt); if (r == SQLITE_DONE) { /* the version number was not found */ reg_throw(errPtr, REG_INVALID, "Version number in metadata table not found."); sqlite3_finalize(stmt); rollback_db(db); return 0; } if (r != SQLITE_ROW) { /* an error occured querying */ break; } if (NULL == (version = (const char *)sqlite3_column_text(stmt, 0))) { reg_throw(errPtr, REG_INVALID, "Version number in metadata table is NULL."); sqlite3_finalize(stmt); rollback_db(db); return 0; } /* we can't call vercmp directly because it's static, but we have * sql_version, which is basically an alias */ if (sql_version(NULL, -1, version, -1, "1.1") < 0) { /* we need to update to 1.1, add binary field and index to files * table */ static char* version_1_1_queries[] = { #if SQLITE_VERSION_NUMBER >= 3002000 "ALTER TABLE registry.files ADD COLUMN binary BOOL", #else /* * SQLite < 3.2.0 doesn't support ALTER TABLE ADD COLUMN * Unfortunately, Tiger ships with SQLite < 3.2.0 (#34463) * This is taken from http://www.sqlite.org/faq.html#q11 */ /* Create a temporary table */ "CREATE TEMPORARY TABLE mp_files_backup (id INTEGER, path TEXT, " "actual_path TEXT, active INT, mtime DATETIME, md5sum TEXT, editable INT, " "FOREIGN KEY(id) REFERENCES ports(id))", /* Copy all data into the temporary table */ "INSERT INTO mp_files_backup SELECT id, path, actual_path, active, mtime, " "md5sum, editable FROM registry.files", /* Drop the original table and re-create it with the new structure */ "DROP TABLE registry.files", "CREATE TABLE registry.files (id INTEGER, path TEXT, actual_path TEXT, " "active INT, mtime DATETIME, md5sum TEXT, editable INT, binary BOOL, " "FOREIGN KEY(id) REFERENCES ports(id))", "CREATE INDEX registry.file_port ON files(id)", "CREATE INDEX registry.file_path ON files(path)", "CREATE INDEX registry.file_actual ON files(actual_path)", /* Copy all data back from temporary table */ "INSERT INTO registry.files (id, path, actual_path, active, mtime, md5sum, " "editable) SELECT id, path, actual_path, active, mtime, md5sum, " "editable FROM mp_files_backup", /* Remove temporary table */ "DROP TABLE mp_files_backup", #endif "CREATE INDEX registry.file_binary ON files(binary)", "UPDATE registry.metadata SET value = '1.100' WHERE key = 'version'", "COMMIT", NULL }; /* don't forget to finalize the version query here, or it might * cause "cannot commit transaction - SQL statements in progress", * see #32686 */ sqlite3_finalize(stmt); stmt = NULL; if (!do_queries(db, version_1_1_queries, errPtr)) { rollback_db(db); return 0; } did_update = 1; continue; } /* add new versions here, but remember to: * - finalize the version query statement and set stmt to NULL * - do _not_ use "BEGIN" in your query list, since a transaction has * already been started for you * - end your query list with "COMMIT", NULL * - set did_update = 1 and continue; */ /* if we arrive here, no update was done and we should end the * transaction. Using ROLLBACK here causes problems when rolling back * other transactions later in the program. */ sqlite3_finalize(stmt); stmt = NULL; r = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL); } while (did_update); sqlite3_finalize(stmt); switch (r) { case SQLITE_OK: case SQLITE_DONE: case SQLITE_ROW: return 1; default: reg_sqlite_error(db, errPtr, query); return 0; } }