Skip to content

Commit

Permalink
Merge branch 'master' of github.com:joeyates/cpp-active-record
Browse files Browse the repository at this point in the history
  • Loading branch information
joeyates committed Aug 9, 2012
2 parents 8889452 + 701a97b commit 0328ac3
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 32 deletions.
5 changes: 5 additions & 0 deletions include/active_record/attribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <boost/assign/list_of.hpp>
#include <active_record/type.h>
#include <active_record/date.h>
#include <sqlite3.h>

using namespace std;
using namespace boost::assign;
Expand All @@ -17,6 +18,8 @@ typedef boost::variant< int, string, double, Date > AttributeType;

// N.B. boost::variant.which() returns a 0-based index into the AttributeType list
class Attribute : public AttributeType {
friend class Connection;
friend class Row;
public:
Attribute() : AttributeType(), initialised_( false ) {}
Attribute( int i ) : AttributeType( i ), initialised_( true ) {}
Expand All @@ -30,6 +33,8 @@ class Attribute : public AttributeType {
bool operator==( const Attribute& other ) const;

private:
static Attribute from_field( sqlite3_stmt *pStmt, int i );

bool initialised_;
};

Expand Down
8 changes: 3 additions & 5 deletions include/active_record/query.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,10 @@ QueryParametersPair Query< T >::query_and_parameters() {
template < class T >
vector< T > Query< T >::all() {
QueryParametersPair query = query_and_parameters();
RowSet rows = connection_->select_all( query.first, query.second );
Table t = connection_->get_table( T::class_name );
string primary_key = t.primary_key();
AttributeList ids = connection.select_values( query.first, query.second );
vector< T > results;
for( RowSet::iterator it = rows.begin(); it != rows.end(); ++it ) {
T record( it->get_integer( primary_key ) );
for( AttributeList::iterator it = ids.begin(); it != ids.end(); ++it ) {
T record( boost::get< int >( *it ) );
results.push_back( record );
}
return results;
Expand Down
10 changes: 9 additions & 1 deletion profiling/100000_greetings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,20 @@ void sqlite_retrieve() {
sqlite3_close( db );
}

/* With ACTIVE_RECORD defined, profiles ActiveRecord,
without, profiles straight SQLite */
int main( int argc, char **argv ) {
ar_setup();
#ifdef ACTIVE_RECORD
cout << "Profiling ActiveRecord version" << endl;
ar_query_retrieve();
#endif
ar_close();

//sqlite_retrieve();
#ifndef ACTIVE_RECORD
cout << "Profiling SQLite version" << endl;
sqlite_retrieve();
#endif

return 0;
}
16 changes: 15 additions & 1 deletion profiling/Rakefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
require 'rake/builder'

Rake::Builder.new do | builder |
builder.target = '100000_greetings'
builder.task_namespace = :active_record
builder.target = '100000_greetings_active_record'
builder.architecture = 'x86_64'
builder.compilation_options = [ '-pg -DACTIVE_RECORD' ]
builder.objects_path = 'active_record'
builder.include_paths = [ '../include' ]
builder.linker_options = [ '-pg' ]
builder.library_dependencies = [ 'sqlite3', 'active_record_sqlite_x86_64_profiled' ]
builder.library_paths = [ '../objects_x86_64_profiled' ]
end

Rake::Builder.new do | builder |
builder.task_namespace = :sqlite
builder.target = '100000_greetings_sqlite'
builder.architecture = 'x86_64'
builder.compilation_options = [ '-pg' ]
builder.objects_path = 'sqlite'
builder.include_paths = [ '../include' ]
builder.linker_options = [ '-pg' ]
builder.library_dependencies = [ 'sqlite3', 'active_record_sqlite_x86_64_profiled' ]
Expand Down
27 changes: 27 additions & 0 deletions src/attribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,33 @@ bool Attribute::operator==( const Attribute& other ) const {
}
}

Attribute Attribute::from_field(sqlite3_stmt *pStmt, int i) {
const char * type = sqlite3_column_decltype( pStmt, i );
if( type == NULL ) {
// http://www.sqlite.org/capi3ref.html#sqlite3_column_decltype
// expression or subquery - skip
const char * value = ( const char * ) sqlite3_column_text( pStmt, i );
if( value != 0 ) // TODO - throw exception?
return value;
} else if( strcasecmp( type, "INTEGER" ) == 0 ) {
return sqlite3_column_int( pStmt, i );
} else if( strcasecmp( type, "FLOAT" ) == 0 ) {
return sqlite3_column_double( pStmt, i );
} else if( strcasecmp( type, "TEXT" ) == 0 ) {
const char * value = ( const char * ) sqlite3_column_text( pStmt, i );
if( value != 0 ) // TODO - throw exception?
return value;
} else if( strcasecmp( type, "DATE" ) == 0 ) {
const char * value = ( const char * ) sqlite3_column_text( pStmt, i );
if( value != 0 )
return Date::parse( value );
} else {
stringstream error;
error << "Unhandled data type: " << type;
throw ActiveRecordException( error.str(), __FILE__, __LINE__ );
}
}

ostream & operator<<( ostream &cout, ActiveRecord::Date const &date ) {
cout << date.to_string();
return cout;
Expand Down
11 changes: 11 additions & 0 deletions src/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,17 @@ RowSet Connection::select_all( const string &query,
return results;
}

AttributeList Connection::select_values( const string &query,
const AttributeList &parameters ) {
sqlite3_stmt *ppStmt = prepare( query, parameters );
AttributeList results;
while( sqlite3_step( ppStmt ) == SQLITE_ROW ) {
results.push_back( Attribute::from_field( ppStmt, 0 ) );
}
sqlite3_finalize( ppStmt );
return results;
}

////////////////////////////////////////
// Private

Expand Down
26 changes: 1 addition & 25 deletions src/row.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,7 @@ Row::Row( sqlite3_stmt *pStmt ) {
int count = sqlite3_column_count( pStmt );
for( int i = 0; i < count; ++i ) {
string name = sqlite3_column_name( pStmt, i );
const char * type = sqlite3_column_decltype( pStmt, i );
if( type == NULL ) {
// http://www.sqlite.org/capi3ref.html#sqlite3_column_decltype
// expression or subquery - skip
const char * value = ( const char * ) sqlite3_column_text( pStmt, i );
if ( value != 0 )
attributes_[ name ] = value;
} else if( strcasecmp( type, "INTEGER" ) == 0 ) {
attributes_[ name ] = sqlite3_column_int( pStmt, i );
} else if( strcasecmp( type, "FLOAT" ) == 0 ) {
attributes_[ name ] = sqlite3_column_double( pStmt, i );
} else if( strcasecmp( type, "TEXT" ) == 0 ) {
const char * value = ( const char * ) sqlite3_column_text( pStmt, i );
if ( value != 0 )
attributes_[ name ] = value;
} else if( strcasecmp( type, "DATE" ) == 0 ) {
const char * value = ( const char * ) sqlite3_column_text( pStmt, i );
if ( value != 0 )
attributes_[ name ] = Date::parse( value );
}
else {
stringstream error;
error << "Unhandled data type: " << type;
throw ActiveRecordException( error.str(), __FILE__, __LINE__ );
}
attributes_[ name ] = Attribute::from_field( pStmt, i );
}
}

Expand Down

0 comments on commit 0328ac3

Please sign in to comment.