database: Each DatabaseEntry should know its id

This will let me set up a Track class that has pointers to the
corresponding artist, album and genre information without needing to
know their IDs directly.  Having this information available means I
won't need to keep a "join struct" when doing lookups - instead I can
return a pointer to a Track class that already knows everything.

Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
Anna Schumaker 2014-03-16 18:32:20 -04:00 committed by Anna Schumaker
parent 14879b03fd
commit 81f3ef458f
7 changed files with 27 additions and 12 deletions

21
DESIGN
View File

@ -193,13 +193,14 @@ On-disk files:
Database Entry: Database Entry:
The database entry class is a base class used for storing data inside The database entry class is a base class used for storing data inside
a database (below). The valid flag will be managed by the database a database (below). The valid flag and id counter will be managed by
itself, and should be initialized to false. the database itself, and should be initialized to false and 0.
- DatabaseEntry: - DatabaseEntry:
class DatabaseEntry { class DatabaseEntry {
public: public:
bool valid; bool valid;
unsigned int id;
DatabaseEntry(); DatabaseEntry();
virtual void ~DatabaseEntry() = 0; virtual void ~DatabaseEntry() = 0;
@ -211,7 +212,7 @@ Database Entry:
- API: - API:
DatabaseEntry :: DatabaseEntry(): DatabaseEntry :: DatabaseEntry():
Set valid = false. Set valid = false and id = 0.
const std::string DatabaseEntry :: primary_key(); const std::string DatabaseEntry :: primary_key();
This function should return a unique string representing this This function should return a unique string representing this
@ -239,23 +240,28 @@ Database:
include/database.hpp, which will be included by database.h. Any include/database.hpp, which will be included by database.h. Any
function not relying on a template can be written in lib/database.cpp. function not relying on a template can be written in lib/database.cpp.
- Automatic saving - Automatic saving:
Databases can save automatically whenever a new value is inserted or Databases can save automatically whenever a new value is inserted or
deleted. This will be more efficient for Databases that do not change deleted. This will be more efficient for Databases that do not change
often but will be a huge performance hit for Databases that have many often but will be a huge performance hit for Databases that have many
changes at once. All databases will be loaded automatically from disk. changes at once. All databases will be loaded automatically from disk.
- Primary keys - Primary keys:
Databases use the primary_key() function of a DatabaseEntry to enforce Databases use the primary_key() function of a DatabaseEntry to enforce
uniqueness. This key is used when inserting a new value into the uniqueness. This key is used when inserting a new value into the
Database, and will not be updated after. Database, and will not be updated after.
- Valid bit - Valid bit:
The "valid" bit of a DatabaseEntry is completely managed by the entry's The "valid" bit of a DatabaseEntry is completely managed by the entry's
Database container. It will be set to true when an entry is inserted Database container. It will be set to true when an entry is inserted
and false when deleted. The Database is also in charge of writing the and false when deleted. The Database is also in charge of writing the
valid bit to file. valid bit to file.
- Id:
The "id" field of a DatabaseEntry is also managed by the entry's
Database container It will be set to the entry's ID when the entry is
inserted into the database.
- Database: - Database:
template <class T> template <class T>
class Database { class Database {
@ -313,9 +319,10 @@ Database:
- Add the new item to the end of the _db. - Add the new item to the end of the _db.
- Add the new item to _keys. - Add the new item to _keys.
- Set item.valid = true. - Set item.valid = true.
- Set item.id to the index of the new item.
_ Increment _size. _ Increment _size.
- If autosave == true: save(). - If autosave == true: save().
- Return the index of the new item. - Return item.id.
unsigned int Database :: remove(); unsigned int Database :: remove();
- Remove the item from the _keys map. - Remove the item from the _keys map.

View File

@ -14,6 +14,7 @@
class DatabaseEntry { class DatabaseEntry {
public: public:
bool valid; bool valid;
unsigned int id;
DatabaseEntry(); DatabaseEntry();
virtual const std::string primary_key() = 0; virtual const std::string primary_key() = 0;

View File

@ -60,6 +60,7 @@ void Database<T> :: load()
_file >> _db[i].valid; _file >> _db[i].valid;
if (_db[i].valid == true) { if (_db[i].valid == true) {
_db[i].read(_file); _db[i].read(_file);
_db[i].id = i;
_keys.insert(std::pair<std::string, unsigned int>(_db[i].primary_key(), i)); _keys.insert(std::pair<std::string, unsigned int>(_db[i].primary_key(), i));
_size++; _size++;
} }
@ -84,6 +85,7 @@ unsigned int Database<T> :: insert(T val)
_db.push_back(val); _db.push_back(val);
_keys[val.primary_key()] = id; _keys[val.primary_key()] = id;
_db[id].valid = true; _db[id].valid = true;
_db[id].id = id;
_size++; _size++;
autosave(); autosave();
return id; return id;

View File

@ -5,6 +5,6 @@
DatabaseEntry :: DatabaseEntry() DatabaseEntry :: DatabaseEntry()
: valid(false) : valid(false), id(0)
{ {
} }

View File

@ -10,7 +10,7 @@ function test_entry
function test_print function test_print
{ {
test_entry $1 $2 "Value: $1 Key: $2 Valid: 0" test_entry $1 $2 "Value: $1 Key: $2 Valid: 0 Id: 0"
} }
function test_primary_key function test_primary_key
@ -30,7 +30,7 @@ function test_read
rm $DATA_DIR/db_entry.txt 2>/dev/null || true rm $DATA_DIR/db_entry.txt 2>/dev/null || true
echo 0 > $DATA_DIR/db_entry.txt echo 0 > $DATA_DIR/db_entry.txt
echo $1 $2 >> $DATA_DIR/db_entry.txt echo $1 $2 >> $DATA_DIR/db_entry.txt
test_entry "-r $1" $2 "Value: $1 Key: $2 Valid: 0" test_entry "-r $1" $2 "Value: $1 Key: $2 Valid: 0 Id: 0"
} }

View File

@ -137,13 +137,15 @@ int main(int argc, char **argv)
/** /**
* 7: Test iterating * 7: Test iterating and setting ID
*/ */
Database<IntEntry>::iterator it; Database<IntEntry>::iterator it;
unsigned int index = 1; unsigned int index = 1;
for (it = db.begin(); it != db.end(); it = db.next(it)) { for (it = db.begin(); it != db.end(); it = db.next(it)) {
if ((*it).val != index) if ((*it).val != index)
test_results(false, __LINE__); test_results(false, __LINE__);
if ((*it).id != index)
test_results(false, __LINE__);
index+=2; index+=2;
}; };
test_results(true, __LINE__); test_results(true, __LINE__);
@ -212,9 +214,12 @@ int main(int argc, char **argv)
if (it->valid == true) { if (it->valid == true) {
if (it->val != it2->val) if (it->val != it2->val)
test_results(false, __LINE__); test_results(false, __LINE__);
if (it->id != it2->id)
test_results(false, __LINE__);
} }
it2++; it2++;
} }
test_results(true, __LINE__); test_results(true, __LINE__);
return 0; return 0;
} }

View File

@ -48,7 +48,7 @@ void IntEntry :: read(File &f)
void IntEntry :: print() void IntEntry :: print()
{ {
:: print("Value: %u Key: %s Valid: %d\n", val, key.c_str(), valid); :: print("Value: %u Key: %s Valid: %d Id: %u\n", val, key.c_str(), valid, id);
} }