tags:

views:

304

answers:

6
+4  Q: 

C++ memory table

Can anyone recommend a lightweight open source C++ table data structure that has data access similar to a database table? (i.e. a 2D array but with named columns - ideally, each column will hold data of a single type [see below]).

I have had a quick look on Google, but have not found anything very useful.

The way I see it, these are the options available to me:

  1. Write my own from scratch (don't really want to invent the wheel)
  2. rip out the SimpleResult class from mySQL++ and hack around it
  3. use sqlite (don't know how lightwight this will be - since I dont need the querying engine and all the other stuff)
  4. Ask in here to see if anyone is aware of such a library

So here I am, choosing the quickest route (hopefully one that will also prove to be the the most efficient use of my time - since whatever is recommended here is likely to be peer reviewed).

So, can anyone recommend a C++ class/ set of classes that provides a "database table like" interface?

The main requirements are:

  1. Columns have names
  2. Cells can be accessed using row, column indexes
  3. I Can add rows and columns to the table (ideally, I can remove them too)
  4. (Nice to have): columns can have types, so it saves teh cost of converting to/from strings

[Edit]

To further demonstrate how I want to use the library, please see the pseudo code below to see simple use of such a class (simple, meaning now iteration of rows and columns - which would be really cool). For now just keoping things simple:

typedef MemoryTable::ColType ColumnType;

table = new MemoryTable();

// Set up the structure (this can be modified later using removeColumn() etc
table->addColumn(ColumnType::Integer, 'id');
table->addColumn(ColumnType::String,  'name');
table->addColumn(ColumnType::Boolean, 'gender');
table->addColumn(ColumnType::Double,  'weight');

for (size_t i=0; i<10; i++)
{
    table->addRow();
    numrows = table->getNumRows();
    std::cout << "We now have " << numrows << " rows.\n";

    // Note can access cells using column name or index 
    // Also using generic value getter/setter methods. Can throw exception on type mismatch
    table->setValue(i, 'id', i*i);
    table->setValue(i, 'name', getRandomSimpsonCharacterName());

    //just to show use of a getter method
    table->setValue(i, 'gender', checkGender(table->getValue(i, 'name')));
    table->setValue(i, 3, guessWeight(table->getValue(i, 'name')));
}
+3  A: 

For creating from scratch (very big scratch) try Boost Multi-index Container. It is not really a database implementation but it could help.

Kirill V. Lyadvinsky
Can columns be dynamically added to a multi_index?
Éric Malenfant
It is not possible to add indices at runtime, but your structure could contain dynamic list of columns.
Kirill V. Lyadvinsky
+1  A: 

Can std::vector<std::vector<std::string/boost::any?> > be considered a candidate?

rmn
Possibly, yes. I have used it sparingly in the past, so I'll have to take a second look. I am going to have a stab at writing a simple class first
Stick it to THE MAN
+3  A: 

I would go with sqlite or Berkeley DB. They're fast, are designed to run well with "in memory" tables. Google for "embedded database" for other options.

Draemon
A: 

Personally, I would use a std::map. Simply create an object type that represents a row:

struct person {
   int id;
   std::string name;
   bool gender;
   double weight;
};

std::map<std::string, person> table;

// ... insert data, etc.

std::cout << "Homer is " << table["Homer"].weight << " lbs.\n";
person p = table["Marge"];
Max Lybbert
This fails the "I Can add … columns to the table" requirement since the struct layout cannot be modified at runtime.
KennyTM
Thank you KennyTM - I'm glad someone is paying attention :) (Just joking ofcourse!). But yes Max, it is to simple for what I need to do. Thanks all the same however, for your input.
Stick it to THE MAN
A: 

If you want something smarter than std::map (my other answer), you may consider Berkeley DB, NetCDF, HDF5, trivial database or similar libraries. Unfortunately they often generate files, which seems to violate the title of the question.

You may also be interested in embedded systems, such as embedded MySQL, embedded Firebird, or SQL Server Compact.

Max Lybbert
Actually, I am using BDB as the data source, but I need a nice simple data type that I can use to pass the data around in my application. Ideally, that data type will also provide a simple intrterface of accesing rows/columns etc. To clarify, its not db functionality that I want, but rather the ability to get/Set (and find) values in named columns
Stick it to THE MAN
+2  A: 

This is isn't answer so please don't up or down vote it - it's simply the easiest way of answering one of the OP's question that won't fit in a comment:

#include <iostream>
#include "a_table.h"

using namespace std;
using namespace ALib;

int main()
{
    Table table;
    table.AddColumn( Column( "id", Column::Integer ));
    cout << "We now have " <<table.Depth() << " rows.\n";
    TableRow row;
    row.push_back( TableValue( 42 ) );
    table.AddRow( row );
    cout << "We now have " <<table.Depth() << " rows.\n";
    string s = table.Value( 0, 0 ).AsString();
    cout << "row[0][0] is " << s << "\n";
    cout << "id[0] value is "
          << table.Value( table.ColumnIndex("id"),0).AsInteger();
}
anon
You could CW it?
Draemon
Pastebin + link also works in this situation.
Josh Matthews
But Neil, this is the closest thing to an answer I have got so far :). I will vote it up (and it may well be the answer I choose in the end). It comes nearest to what it is I want to do. I'll download your code a bit to familiarize myself with it.
Stick it to THE MAN
@Draemon Of course I could. Brain not working, too well - I tend to think (wrongly) CW is only for questions.
anon