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:
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
itself, and should be initialized to false.
a database (below). The valid flag and id counter will be managed by
the database itself, and should be initialized to false and 0.
- DatabaseEntry:
class DatabaseEntry {
public:
bool valid;
unsigned int id;
DatabaseEntry();
virtual void ~DatabaseEntry() = 0;
@ -211,7 +212,7 @@ Database Entry:
- API:
DatabaseEntry :: DatabaseEntry():
Set valid = false.
Set valid = false and id = 0.
const std::string DatabaseEntry :: primary_key();
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
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
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
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
uniqueness. This key is used when inserting a new value into the
Database, and will not be updated after.
- Valid bit
- Valid bit:
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
and false when deleted. The Database is also in charge of writing the
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:
template <class T>
class Database {
@ -313,9 +319,10 @@ Database:
- Add the new item to the end of the _db.
- Add the new item to _keys.
- Set item.valid = true.
- Set item.id to the index of the new item.
_ Increment _size.
- If autosave == true: save().
- Return the index of the new item.
- Return item.id.
unsigned int Database :: remove();
- Remove the item from the _keys map.

View File

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

View File

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

View File

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

View File

@ -10,7 +10,7 @@ function test_entry
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
@ -30,7 +30,7 @@ function test_read
rm $DATA_DIR/db_entry.txt 2>/dev/null || true
echo 0 > $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;
unsigned int index = 1;
for (it = db.begin(); it != db.end(); it = db.next(it)) {
if ((*it).val != index)
test_results(false, __LINE__);
if ((*it).id != index)
test_results(false, __LINE__);
index+=2;
};
test_results(true, __LINE__);
@ -212,9 +214,12 @@ int main(int argc, char **argv)
if (it->valid == true) {
if (it->val != it2->val)
test_results(false, __LINE__);
if (it->id != it2->id)
test_results(false, __LINE__);
}
it2++;
}
test_results(true, __LINE__);
return 0;
}

View File

@ -48,7 +48,7 @@ void IntEntry :: read(File &f)
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);
}