[darwinbuild-changes] [742] trunk/darwinup

source_changes at macosforge.org source_changes at macosforge.org
Mon Mar 8 11:40:44 PST 2010


Revision: 742
          http://trac.macosforge.org/projects/darwinbuild/changeset/742
Author:   wsiegrist at apple.com
Date:     2010-03-08 11:40:41 -0800 (Mon, 08 Mar 2010)
Log Message:
-----------
Start of schema versioning/upgrade support

Modified Paths:
--------------
    trunk/darwinup/DB.cpp
    trunk/darwinup/Database.cpp
    trunk/darwinup/Database.h

Modified: trunk/darwinup/DB.cpp
===================================================================
--- trunk/darwinup/DB.cpp	2010-03-07 04:16:09 UTC (rev 741)
+++ trunk/darwinup/DB.cpp	2010-03-08 19:40:41 UTC (rev 742)
@@ -34,6 +34,7 @@
 
 
 DarwinupDatabase::DarwinupDatabase(const char* path) : Database(path) {
+	m_schema_version = 1;
 	this->connect();
 }
 
@@ -41,7 +42,7 @@
 	// parent automatically deallocates schema objects
 }
 
-void DarwinupDatabase::init_schema() {
+int DarwinupDatabase::init_schema() {	
 	this->m_archives_table = new Table("archives");
 	ADD_PK(m_archives_table, "serial");
 	ADD_INDEX(m_archives_table, "uuid", TYPE_BLOB, true); 
@@ -49,6 +50,7 @@
 	ADD_INTEGER(m_archives_table, "date_added");
 	ADD_INTEGER(m_archives_table, "active");
 	ADD_INTEGER(m_archives_table, "info");	
+	ADD_TEXT(m_archives_table, "osbuild");
 	assert(this->add_table(this->m_archives_table)==0);
 	
 	this->m_files_table = new Table("files");
@@ -65,8 +67,19 @@
 	assert(this->m_files_table->set_custom_create("CREATE UNIQUE INDEX files_archive_path " 
 												  "ON files (archive, path);") == 0);
 	assert(this->add_table(this->m_files_table)==0);
+	
+	return 0;
 }
 
+int DarwinupDatabase::upgrade_schema(uint32_t fromversion) {
+
+	if (fromversion < 1) {
+		this->sql_once("ALTER TABLE archives ADD COLUMN osbuild TEXT");
+	}
+	
+	return 0;
+}
+
 int DarwinupDatabase::activate_archive(uint64_t serial) {
 	uint64_t active = 1;
 	return this->set_archive_active(serial, &active);

Modified: trunk/darwinup/Database.cpp
===================================================================
--- trunk/darwinup/Database.cpp	2010-03-07 04:16:09 UTC (rev 741)
+++ trunk/darwinup/Database.cpp	2010-03-08 19:40:41 UTC (rev 742)
@@ -40,6 +40,7 @@
 }
 
 Database::Database() {
+	m_schema_version = 0;
 	m_table_max = 2;
 	m_table_count = 0;
 	m_tables = (Table**)malloc(sizeof(Table*) * m_table_max);
@@ -51,6 +52,7 @@
 }
 
 Database::Database(const char* path) {
+	m_schema_version = 0;
 	m_table_max = 2;
 	m_table_count = 0;
 	m_tables = (Table**)malloc(sizeof(Table*) * m_table_max);
@@ -81,10 +83,14 @@
 }
 
 
-void Database::init_schema() {
+int Database::init_schema() {
 	// do nothing... children should implement this
 }
 
+int Database::upgrade_schema(uint32_t fromversion) {
+	// do nothing... children should implement this
+}
+
 const char* Database::path() {
 	return m_path;
 }
@@ -94,12 +100,19 @@
 }
 
 int Database::connect() {
+	int res = DB_OK;
+	
 	if (!m_path) {
 		fprintf(stderr, "Error: need to specify a path to Database.\n");
 		return -1;
 	}
-	int res = SQLITE_OK;
-	this->init_schema();
+
+	res = this->pre_connect();
+	if (res) {
+		fprintf(stderr, "Error: pre-connection failed.\n");
+		return res;
+	}
+	
 	res = sqlite3_open(m_path, &m_db);
 	if (res) {
 		sqlite3_close(m_db);
@@ -108,28 +121,56 @@
 				m_path);
 		return res;
 	}
+	
+	res = this->post_connect();
+	if (res) {
+		fprintf(stderr, "Error: post-connection failed.\n");
+		return res;
+	}
+	
+	return res;	
+}
 
+int Database::pre_connect() {	
+	int res = DB_OK;
+	res = this->init_internal_schema();
+	res = this->init_schema();
+	return res;
+}
+
+int Database::post_connect() {
+	int res = DB_OK
+	
+	// prepare transaction statements
+	if (res == DB_OK) 
+		res = sqlite3_prepare_v2(m_db, "BEGIN TRANSACTION", 18,
+								 &m_begin_transaction, NULL);
+	if (res == DB_OK) 
+		res = sqlite3_prepare_v2(m_db, "ROLLBACK TRANSACTION", 21,
+								 &m_rollback_transaction, NULL);
+	if (res == DB_OK) 
+		res = sqlite3_prepare_v2(m_db, "COMMIT TRANSACTION", 19,
+								 &m_commit_transaction, NULL);	
+
+	// debug settings
 	extern uint32_t verbosity;
 	if (verbosity & VERBOSE_SQL) {
 		sqlite3_trace(m_db, dbtrace, NULL);
 	}
 	
 	if (this->is_empty()) {
+		// create schema since it is empty
 		assert(this->create_tables() == 0);
+	} else {
+		// not empty, but upgrade schema if needed
+		version = this->get_schema_version();
+		if (version < this->m_schema_version) {
+			assert(this->upgrade_schema(version) == 0);
+			this->set_schema_version(this->m_schema_version);
+		}
 	}
 	
-	// prepare transaction statements
-	if (res == SQLITE_OK) 
-		res = sqlite3_prepare_v2(m_db, "BEGIN TRANSACTION", 18,
-								 &m_begin_transaction, NULL);
-	if (res == SQLITE_OK) 
-		res = sqlite3_prepare_v2(m_db, "ROLLBACK TRANSACTION", 21,
-								 &m_rollback_transaction, NULL);
-	if (res == SQLITE_OK) 
-		res = sqlite3_prepare_v2(m_db, "COMMIT TRANSACTION", 19,
-								 &m_commit_transaction, NULL);
-	
-	return res;	
+	return res;
 }
 
 int Database::connect(const char* path) {
@@ -589,6 +630,56 @@
 	return res;
 }
 
+int Database::init_internal_schema() {
+	this->m_information_table = new Table("database_information");
+	ADD_PK(m_information_table, "id");
+	ADD_INDEX(m_information_table, "variable", TYPE_TEXT, true);
+	ADD_TEXT(m_information_table, "value");
+	assert(this->add_table(this->m_information_table)==0);
+}
+
+int Database::get_information_value(char* variable, char** value) {
+	return this->get_value("get_information_value",
+						   value,
+						   this->m_information_table,
+						   this->m_information_table->columns(1), // value
+						   1,
+						   this->m_information_table->columns(0), // variable
+						   '=', variable);
+}
+
+uint32_t Database::get_schema_version() {
+	char* vertxt;
+	int res = DB_OK;
+	res = this->get_information_value("schema_version", &vertxt);
+	if (FOUND(res)) {
+		uint32_t version = (uint32_t)strtoul(vertxt, NULL, 10);
+		free(vertxt);
+		return version;
+	} else {
+		// lack of information table/value means we are 
+		//  upgrading an old database
+		return 0;
+	}
+}
+
+int Database::update_information_value(char* variable, char* value) {
+	return this->update_value("update_information_value",
+							  this->m_information_table,
+							  this->m_information_table->columns(1), // value
+							  value, 
+							  1,
+							  this->m_information_table->columns(0), // variable
+							  '=', variable);
+}
+
+int Database::set_schema_version(uint32_t version) {
+	int res = DB_OK;
+	res = this->update_information_value("schema_version", &version);
+	return res;
+}
+
+
 size_t Database::store_column(sqlite3_stmt* stmt, int column, uint8_t* output) {
 	size_t used;
 	int type = sqlite3_column_type(stmt, column);

Modified: trunk/darwinup/Database.h
===================================================================
--- trunk/darwinup/Database.h	2010-03-07 04:16:09 UTC (rev 741)
+++ trunk/darwinup/Database.h	2010-03-08 19:40:41 UTC (rev 742)
@@ -98,7 +98,12 @@
 	 * should use Table::add_column() or the ADD_*
 	 * macros in their init_schema() to define their schema
 	 */
-	virtual void init_schema();
+	virtual int init_schema();
+	/**
+	 * upgrade_schema should execute sql statements needed to
+	 * upgrade from fromversion to the current version
+	 */
+	virtual int upgrade_schema(uint32_t fromversion);
 	
 	const char*  path();
 	const char*  error();
@@ -168,17 +173,24 @@
 	
 protected:
 
+	// pre- and post- connection work
+	int   pre_connect();
+	int   post_connect();
+	
 	// execute query with printf-style format, does not cache statement
-	int sql_once(const char* fmt, ...);
+	int   sql_once(const char* fmt, ...);
 	// cache statement with name, execute query with printf-style format
-	int sql(const char* name, const char* fmt, ...);
-	int execute(sqlite3_stmt* stmt);
+	int   sql(const char* name, const char* fmt, ...);
+	int   execute(sqlite3_stmt* stmt);
 	
-	int  add_table(Table*);
+	int   add_table(Table*);
 	
 	// test if database has had its tables created
 	bool  is_empty();
+	// create tables for the client
 	int   create_tables();
+	// create tables for ourselves
+	int   create_internal_tables();
 
 	// bind all table columns from va_list
 	int   bind_all_columns(sqlite3_stmt* stmt, Table* table, va_list args);
@@ -201,7 +213,11 @@
 	
 	char*            m_path;
 	sqlite3*         m_db;
-
+	
+	uint32_t         m_schema_version;
+	Table*           m_information_table;
+	sqlite3_stmt     m_get_information_value;
+	
 	Table**          m_tables;
 	uint32_t         m_table_count;
 	uint32_t         m_table_max;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20100308/e47864bd/attachment.html>


More information about the darwinbuild-changes mailing list