dm-metamapper 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *~
2
+ *.sw[p|o]
3
+ .bundle/*
4
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source :rubygems
2
+
3
+ gem "dm-core", :git => "git://github.com/datamapper/dm-core"
4
+
5
+ group :test do
6
+ gem "rspec"
7
+ gem "dm-sqlite-adapter", :git => "git://github.com/datamapper/dm-sqlite-adapter"
8
+ gem "dm-mysql-adapter", :git => "git://github.com/datamapper/dm-mysql-adapter"
9
+ gem "dm-migrations", :git => "git://github.com/datamapper/dm-migrations"
10
+ end
11
+
12
+ group :deploy do
13
+ gem "jeweler"
14
+ end
15
+
16
+ # vim: set ft=ruby:
data/README.md ADDED
File without changes
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1 @@
1
+ example
data/example/Makefile ADDED
@@ -0,0 +1,4 @@
1
+ all:
2
+ echo "generating code"
3
+ cd ..; bundle exec ruby -r example/example.rb -e "DataMapper::MetaMapper.generate(:cpp)"
4
+ g++ ../output/dmmm_utils.cpp ../output/dmmm_dbface.cpp example.cpp -I ../output -I /usr/include/mysql -I /usr/local/include/mysql++ -I /usr/local/mysql/include/mysql -lmysqlpp -lmysqlclient /usr/lib/libboost_thread-mt.so -L/usr/lib -L/usr/local/lib -Wall -o example
@@ -0,0 +1,74 @@
1
+ #include <vector>
2
+ #include "dmmm_dbface.h"
3
+ #include "T_User.hpp"
4
+ #include "T_Dog.hpp"
5
+ #include "T_LittleFlea.hpp"
6
+
7
+ using namespace std;
8
+ using namespace DMMM;
9
+
10
+ int main(int argc, char* argv[])
11
+ {
12
+ string host("localhost");
13
+ string user("root");
14
+ string database("dmmm");
15
+ string password("");
16
+ DBFace dbFace(database, host, user, password);
17
+
18
+ T_Dog d;
19
+ T_User u;
20
+ d.erase();
21
+ u.erase();
22
+
23
+ O_User u1;
24
+ u1._name() = "omer";
25
+ u1._balance() = 5.3;
26
+ u1._weight() = 10;
27
+ u1.insert();
28
+
29
+ O_Dog d1;
30
+ d1._user_id() = u1._id();
31
+ d1._name() = "spot";
32
+ d1._stinks() = true;
33
+ d1.insert();
34
+
35
+ d1 = d.select(d1._id()).first;
36
+
37
+ O_Dog d2(u1);
38
+ d2._name() = "rover";
39
+ d2._stinks() = false;
40
+ d2.insert();
41
+
42
+ O_User u2;
43
+ u2._name() = "jonah";
44
+ u2.insert();
45
+
46
+ O_Dog d3(u2._id());
47
+ d3._name() = "rover";
48
+ d3._stinks() = false;
49
+ d3.insert();
50
+
51
+ O_LittleFlea f1(d3);
52
+ f1.insert();
53
+
54
+ vector<O_Dog> dogs;
55
+ d.select((d._stinks() == false) && (d._name() %= "\%over"), dogs);
56
+ for(size_t i = 0; i < dogs.size(); ++i){
57
+ dogs[i]._name() = string("good_") + dogs[i]._name();
58
+ dogs[i].update();
59
+ cout << dogs[i]._name()
60
+ << " belongs to " << dogs[i].user().first._name()
61
+ << endl;
62
+ }
63
+
64
+
65
+ T_Dog dconst(T_User(u._name() == "omer"));
66
+ dogs.clear();
67
+ dconst.select(d._stinks() == true, dogs);
68
+ cout << dogs.size() << " dogs meet criterion" << endl;
69
+ dconst.erase();
70
+
71
+ d.erase(d._user_id() == u2._id());
72
+
73
+ return 0;
74
+ }
@@ -0,0 +1,51 @@
1
+ require "erb"
2
+ require "rubygems"
3
+ require "bundler"
4
+ Bundler.setup(:default, :test)
5
+ require "dm-core"
6
+ require "lib/dm-metamapper.rb"
7
+ require "dm-migrations"
8
+
9
+ #DataMapper.setup(:default, "sqlite3::memory:")
10
+ DataMapper.setup(:default, "mysql://root@localhost/dmmm")
11
+
12
+ class User
13
+ include DataMapper::Resource
14
+ extend DataMapper::MetaMapper::Extension
15
+
16
+ generates :cpp
17
+
18
+ has n, :dogs
19
+
20
+ property :id, Serial
21
+ property :name, String
22
+ property :balance, Float
23
+ property :weight, Integer
24
+ end
25
+
26
+ class Dog
27
+ include DataMapper::Resource
28
+ extend DataMapper::MetaMapper::Extension
29
+
30
+ generates :cpp
31
+
32
+ belongs_to :user
33
+ has n, :little_fleas
34
+
35
+ property :id, Serial
36
+ property :user_id, Integer
37
+ property :name, String
38
+ property :stinks, Boolean
39
+ end
40
+
41
+ class LittleFlea
42
+ include DataMapper::Resource
43
+ extend DataMapper::MetaMapper::Extension
44
+
45
+ generates :cpp
46
+
47
+ belongs_to :dog
48
+
49
+ property :id, Serial
50
+ property :dog_id, Integer
51
+ end
@@ -0,0 +1,35 @@
1
+ module DataMapper
2
+ module MetaMapper
3
+ module Extension
4
+ def generates(*layouts)
5
+ @_generation_formats = Array(layouts)
6
+ end
7
+
8
+ def generates?(format)
9
+ @_generation_formats.include?(format)
10
+ end
11
+
12
+ def generate(format)
13
+ DataMapper::MetaMapper.generate(format, self)
14
+ end
15
+
16
+ def generated_properties
17
+ @_generated_properties ||= properties.select {|prop|
18
+ !prop.options[:skip_generation]
19
+ }
20
+ end
21
+
22
+ def _get_binding
23
+ binding
24
+ end
25
+
26
+ def self.extended(base)
27
+ DataMapper::MetaMapper.register(base)
28
+ base.instance_variable_set(:@_generation_formats, [])
29
+ class <<base; attr_reader :_generation_formats end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,113 @@
1
+ module DataMapper
2
+ module MetaMapper
3
+ class Generator
4
+ class GeneratedFile
5
+ def initialize(&blk)
6
+ instance_eval(&blk) if block_given?
7
+ end
8
+
9
+ attr_reader :template, :file_name_prefix, :file_name_suffix
10
+
11
+ def template_name(template)
12
+ @template = template
13
+ end
14
+
15
+ def prefix(str)
16
+ @file_name_prefix = str
17
+ end
18
+
19
+ def suffix(str)
20
+ @file_name_suffix = str
21
+ end
22
+ end
23
+
24
+ @subclasses = []
25
+
26
+ class << self
27
+ attr_reader :subclasses,
28
+ :generated_model_files,
29
+ :generated_global_files,
30
+ :proxy_blk
31
+
32
+ def [](generator)
33
+ @subclasses.find {|klass| klass.generator_name == generator}
34
+ end
35
+
36
+ def generator_name(name=nil)
37
+ return @generator_name unless name
38
+ @generator_name = name
39
+ end
40
+
41
+ private
42
+
43
+ def generates_file(&blk)
44
+ @generated_model_files ||= []
45
+ @generated_model_files << GeneratedFile.new(&blk)
46
+ end
47
+
48
+ def generates_global_file(&blk)
49
+ @generated_global_files ||= []
50
+ @generated_global_files << GeneratedFile.new(&blk)
51
+ end
52
+
53
+ def proxy(&blk)
54
+ @proxy_blk = blk
55
+ end
56
+
57
+ def inherited(klass)
58
+ @subclasses ||= []
59
+ @subclasses << klass
60
+ klass.instance_variable_set(:@generator_name, @generator_name)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ class DataMapper::MetaMapper::Proxy; end
68
+
69
+ class CPPGenerator < DataMapper::MetaMapper::Generator
70
+ generator_name :cpp
71
+
72
+ generates_global_file{ template_name "dmmm_identifiers.hpp.erb" }
73
+ generates_global_file{ template_name "dmmm_comparators.hpp.erb" }
74
+ generates_global_file{ template_name "dmmm_fields.hpp.erb" }
75
+ generates_global_file{ template_name "dmmm_utils.hpp.erb" }
76
+ generates_global_file{ template_name "dmmm_utils.cpp.erb" }
77
+ generates_global_file{ template_name "dmmm_dbface.cpp.erb" }
78
+ generates_global_file{ template_name "dmmm_dbface.h.erb" }
79
+ generates_global_file{ template_name "dmmm_id.hpp.erb" }
80
+
81
+ proxy do
82
+ key_to_parent = {}
83
+ relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |r|
84
+ key_to_parent[r[1].child_key.first.name.to_s] = r[0].to_const_string
85
+ puts "#{r[1].child_key.first.name.to_s} -> #{r[0].to_const_string}"
86
+ end
87
+
88
+ properties.each do |e|
89
+ cpp_name = if e.serial?
90
+ "Field<I_#{e.model.name}>"
91
+ elsif !key_to_parent[e.name.to_s].nil?
92
+ "Field<I_#{key_to_parent[e.name.to_s]}>"
93
+ else
94
+ "F_#{e.class.primitive}"
95
+ end
96
+
97
+ e.instance_variable_set(:@cpp_name, cpp_name)
98
+ end
99
+ end
100
+
101
+ generates_file do
102
+ suffix ".hpp"
103
+ prefix "O_"
104
+ template_name "instance.hpp.erb"
105
+ end
106
+
107
+ generates_file do
108
+ suffix".hpp"
109
+ prefix "T_"
110
+ template_name "class.hpp.erb"
111
+ end
112
+ end
113
+
@@ -0,0 +1,60 @@
1
+ module DataMapper
2
+ module MetaMapper
3
+ class << self
4
+ attr_reader :models
5
+
6
+ def register(klass)
7
+ (@models ||= []) << klass
8
+ end
9
+
10
+ def generate(format, context=nil)
11
+ generator = Generator[format]
12
+
13
+ if context
14
+ context.instance_eval(&generator.proxy_blk) if generator.proxy_blk
15
+ type, _binding = :generated_model_files, context._get_binding
16
+ else
17
+ type, _binding = :generated_global_files, binding
18
+ end
19
+
20
+ generator.send(type).each do |generated_file|
21
+ temp_filename = [
22
+ File.dirname(__FILE__),
23
+ "../templates",
24
+ generator.generator_name,
25
+ generated_file.template
26
+ ].join('/')
27
+
28
+ result_base_name = context ? context.name.to_s : generated_file.template.sub(/\.erb$/,'')
29
+
30
+ result_filename = File.join(
31
+ File.dirname(__FILE__), "../../output", [
32
+ generated_file.file_name_prefix,
33
+ result_base_name,
34
+ generated_file.file_name_suffix
35
+ ].join
36
+ )
37
+
38
+ if File.exists?(temp_filename)
39
+ STDOUT.puts "writing file " + result_filename
40
+ template = ERB.new(File.read(temp_filename))
41
+ result = template.result(_binding)
42
+ File.open(result_filename, 'w') { |f| f << result }
43
+ else
44
+ STDERR.puts "ERROR: " + temp_filename + " does not exist"
45
+ end
46
+ end
47
+
48
+ if !context
49
+ models.select {|model|
50
+ model.generates?(format)
51
+ }.each {|model|
52
+ model.generate(format)
53
+ }
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
60
+
@@ -0,0 +1,6 @@
1
+ module DataMapper
2
+ class Property
3
+ accept_options :skip_generation
4
+ end
5
+ end
6
+
@@ -0,0 +1,8 @@
1
+ $:.push File.dirname(__FILE__)
2
+
3
+ require 'dm-core'
4
+ require 'dm-metamapper/property'
5
+ require 'dm-metamapper/metamapper'
6
+ require 'dm-metamapper/extension'
7
+ require 'dm-metamapper/generator'
8
+
@@ -0,0 +1,134 @@
1
+ <% class_name = self.name %>
2
+ <% all_caps_name = class_name.upcase %>
3
+ #ifndef T_<%= all_caps_name %>
4
+ #define T_<%= all_caps_name %>
5
+ #include "O_<%= class_name %>.hpp"
6
+ namespace DMMM {
7
+
8
+ class T_<%= class_name %>{
9
+ public:
10
+
11
+ struct Condition{
12
+ bool nil() const { return _cond.size() == 0; }
13
+ std::string _cond;
14
+ };
15
+
16
+ T_<%= class_name %>()
17
+ {
18
+ _tables.push_back("<%= storage_name %>");
19
+ }
20
+ T_<%= class_name %>(const Condition& c)
21
+ : _constraint(c)
22
+ {
23
+ _tables.push_back("<%= storage_name %>");
24
+ }
25
+ <% self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |r| %>
26
+ <% parent = r[0].to_const_string %>
27
+ T_<%= class_name %>(const T_<%= parent %>& parent)
28
+ {
29
+ _tables.push_back("<%= storage_name %>");
30
+ _tables.insert(_tables.end(),
31
+ parent._tables.begin(), parent._tables.end());
32
+
33
+ _constraint._cond = "(<%= storage_name + "." + r[1].child_key.first.name.to_s %> = " + parent._tables[0] + ".<%= r[1].parent_key.first.name.to_s %>)";
34
+ if (!parent._constraint.nil())
35
+ _constraint._cond += " AND " + parent._constraint._cond;
36
+ }
37
+
38
+ <% end %>
39
+
40
+ <% generated_properties.each do |property| %>
41
+ struct E_<%= property.name %>{
42
+ E_<%= property.name %>()
43
+ {
44
+ _field = "<%= storage_name %>.<%= property.name.to_s %>";
45
+ }
46
+ std::string _field;
47
+ typedef T_<%= class_name %>::Condition ConditionType;
48
+ typedef <%= property.instance_variable_get(:@cpp_name) %>::Base ComparerType;
49
+ };
50
+
51
+ E_<%= property.name %> _<%= property.name %>(){
52
+ return E_<%= property.name %>();
53
+ }
54
+
55
+ <% end %>
56
+
57
+ void getFields(std::vector<std::string>& rFields)
58
+ {
59
+ rFields.clear();
60
+ <% generated_properties.each do |property| %>
61
+ rFields.push_back("<%= property.name %>");
62
+ <% end %>
63
+ }
64
+
65
+ void select(const Condition& c,
66
+ const std::string& additional,
67
+ std::vector<O_<%= class_name %>>& r)
68
+ {
69
+ Condition c1 = _constraint.nil() ? c : _constraint && c;
70
+ std::vector<std::string> fields;
71
+ getFields(fields);
72
+ QueryRes res;
73
+ DBFace::instance()->select(_tables, fields, c1._cond,
74
+ additional, res);
75
+ r.resize(res.size());
76
+ for(size_t i = 0; i < res.size(); ++i){
77
+ <% generated_properties.each do |property| %>
78
+ r[i]._f_<%= property.name %>._base =
79
+ fromString<<%= property.instance_variable_get(:@cpp_name) %>::Base>(res[i]["<%= property.name %>"]);
80
+ <% end %>
81
+ }
82
+ }
83
+
84
+ void erase(const Condition& c)
85
+ {
86
+ Condition c1 = _constraint.nil() ? c : _constraint && c;
87
+ DBFace::instance()->erase(_tables, c1._cond);
88
+ }
89
+ void erase()
90
+ {
91
+ DBFace::instance()->erase(_tables, _constraint._cond);
92
+ }
93
+
94
+
95
+ void select(const Condition& c,
96
+ std::vector<O_<%= class_name %>>& r)
97
+ {
98
+ Condition c1 = _constraint.nil() ? c : _constraint && c;
99
+ select(c1, "", r);
100
+ }
101
+ void select(std::vector<O_<%= class_name %>>& r)
102
+ {
103
+ select(_constraint, "", r);
104
+ }
105
+
106
+ std::pair<O_<%= class_name %>, bool> select(const I_<%= class_name %>& id){
107
+ return first(E_<%= serial.name %>() == id);
108
+ }
109
+
110
+ std::pair<O_<%= class_name %>, bool> first(const Condition& c)
111
+ {
112
+ Condition c1 = _constraint.nil() ? c : _constraint && c;
113
+ std::vector<O_<%= class_name %>> r;
114
+ select(c, "limit 1", r);
115
+ if(r.size() > 0)
116
+ return std::make_pair(r[0], true);
117
+ else
118
+ return std::make_pair(O_<%= class_name %>(), false);
119
+ }
120
+
121
+ std::pair<O_<%= class_name %>, bool> first(){
122
+ return first(_constraint);
123
+ }
124
+
125
+
126
+
127
+
128
+
129
+ Condition _constraint;
130
+ std::vector<std::string> _tables;
131
+ };
132
+
133
+ } //namespace DMMM
134
+ #endif //T_<%= all_caps_name %>
@@ -0,0 +1,74 @@
1
+ #ifndef DMMM_COMPARATORS_H
2
+ #define DMMM_COMPARATORS_H
3
+
4
+ #include <string>
5
+ #include <sstream>
6
+
7
+ namespace DMMM {
8
+ template<class E>
9
+ typename E::ConditionType operator== (E e, const typename E::ComparerType& x){
10
+ typename E::ConditionType c;
11
+ c._cond = e._field + " = '" + toString(x) + "'";
12
+ return c;
13
+ }
14
+
15
+ template<class E>
16
+ typename E::ConditionType operator< (E e, const typename E::ComparerType& x){
17
+ typename E::ConditionType c;
18
+ c._cond = e._field + " < '" + toString(x) + "'";
19
+ return c;
20
+ }
21
+
22
+ template<class E>
23
+ typename E::ConditionType operator<= (E e, const typename E::ComparerType& x){
24
+ typename E::ConditionType c;
25
+ c._cond = e._field + " <= '" + toString(x) + "'";
26
+ return c;
27
+ }
28
+
29
+ template<class E>
30
+ typename E::ConditionType operator> (E e, const typename E::ComparerType& x){
31
+ typename E::ConditionType c;
32
+ c._cond = e._field + " > '" + toString(x) + "'";
33
+ return c;
34
+ }
35
+
36
+ template<class E>
37
+ typename E::ConditionType operator>= (E e, const typename E::ComparerType& x){
38
+ typename E::ConditionType c;
39
+ c._cond = e._field + " >= '" + toString(x) + "'";
40
+ return c;
41
+ }
42
+
43
+ template<class E>
44
+ typename E::ConditionType operator!= (E e, const typename E::ComparerType& x){
45
+ typename E::ConditionType c;
46
+ c._cond = e._field + " != '" + toString(x) + "'";
47
+ return c;
48
+ }
49
+
50
+ template<class E>
51
+ typename E::ConditionType operator%= (E e, const typename E::ComparerType& x){
52
+ typename E::ConditionType c;
53
+ c._cond = e._field + " LIKE '" + toString(x) + "'";
54
+ return c;
55
+ }
56
+
57
+ template<class C>
58
+ C operator&& (const C& c1, const C& c2){
59
+ C c;
60
+ c._cond = "(" + c1._cond + ") AND (" + c2._cond + ")";
61
+ return c;
62
+ }
63
+
64
+ template<class C>
65
+ C operator|| (const C& c1, const C& c2){
66
+ C c;
67
+ c._cond = "(" + c1._cond + ") OR (" + c2._cond + ")";
68
+ return c;
69
+ }
70
+
71
+
72
+ } //namespace DMMM
73
+
74
+ #endif //DMMM_COMPARATORS_H
@@ -0,0 +1,176 @@
1
+ #include "dmmm_dbface.h"
2
+ #include "dmmm_utils.hpp"
3
+ using namespace mysqlpp;
4
+ using namespace std;
5
+ using namespace DMMM;
6
+
7
+ DBFace* DBFace::_this = NULL;
8
+
9
+ DBFace::DBFace(const string& database, const string& host,
10
+ const string& user, const string& password)
11
+ {
12
+ _this = this;
13
+ if (!_connection.connect(database.c_str(), host.c_str(),
14
+ user.c_str(), password.c_str())){
15
+ cerr << "Could not connect to DB";
16
+ exit(-1);
17
+ }
18
+ }
19
+
20
+ bool
21
+ DBFace::select(const std::vector<std::string>& tables,
22
+ const std::vector<string>& columns,
23
+ const std::string& where,
24
+ const std::string& additional,
25
+ QueryRes& rRes)
26
+ {
27
+ boost::mutex::scoped_lock lock(_mutex);
28
+
29
+ Query q = _connection.query();
30
+
31
+ q << "SELECT ";
32
+ for (size_t i = 0; i < columns.size(); ++i){
33
+ if (i > 0)
34
+ q << ",";
35
+ q << tables[0] << "." << columns[i];
36
+ }
37
+ q << " FROM " << tables[0];
38
+ for (size_t i = 1; i < tables.size(); ++i)
39
+ q << ", " + tables[i];
40
+ if (where.size())
41
+ q << " WHERE " << where;
42
+ if (additional.size())
43
+ q << " " << additional;
44
+ cout << q << endl;
45
+ StoreQueryResult mysqlRes;
46
+ try{
47
+ mysqlRes = q.store();
48
+ }
49
+ catch (const mysqlpp::Exception& er) {
50
+ cerr << "Query failed: " << q << endl << er.what();
51
+ return false;
52
+ }
53
+
54
+ for (size_t i = 0; i < mysqlRes.num_rows(); ++i){
55
+ rRes.resize(rRes.size() + 1);
56
+ for (size_t j = 0; j < columns.size(); ++j)
57
+ rRes.back()[columns[j]] = toString(mysqlRes[i][columns[j].c_str()]);
58
+ }
59
+ return true;
60
+ }
61
+
62
+
63
+ bool
64
+ DBFace::erase(const std::vector<std::string>& tables,
65
+ const std::string& where)
66
+ {
67
+ Query q = _connection.query();
68
+ q << "DELETE FROM " << tables[0];
69
+ if (tables.size() > 1)
70
+ q << " USING " + tables[0] + " ";
71
+ for (size_t i = 1; i < tables.size(); ++i)
72
+ q << " INNER JOIN " + tables[i];
73
+ if (where.size())
74
+ q << " WHERE " << where;
75
+ cout << q << endl;
76
+ return executeQuery(q);
77
+
78
+ }
79
+
80
+
81
+ bool
82
+ DBFace::executeQuery(Query& q)
83
+ {
84
+ boost::mutex::scoped_lock lock(_mutex);
85
+ try{
86
+ q.execute();
87
+ }
88
+ catch (const mysqlpp::Exception& er) {
89
+ cerr << "Query failed: " << q << endl << er.what();
90
+ return false;
91
+ }
92
+ return true;
93
+ }
94
+
95
+ bool
96
+ DBFace::getLastInsertId(Query& rQuery, size_t& rId)
97
+ {
98
+ try{
99
+ rId = rQuery.insert_id();
100
+ cout << "got last insert ID: " << rId << endl;
101
+ }
102
+ catch (const mysqlpp::Exception& er) {
103
+ return false;
104
+ }
105
+ return true;
106
+ }
107
+
108
+ bool
109
+ DBFace::insert(const string& table,
110
+ const map<string, string>& field2Val,
111
+ size_t& rInsertId)
112
+ {
113
+ if (field2Val.size() == 0)
114
+ return true;
115
+
116
+ Query q = _connection.query();
117
+ q << "INSERT INTO " << table << " (";
118
+ for (map<string, string>::const_iterator it = field2Val.begin();
119
+ it != field2Val.end(); ++it)
120
+ {
121
+ if (it != field2Val.begin())
122
+ q << ",";
123
+ q << it->first;
124
+ }
125
+ q << ")VALUES(";
126
+ for (map<string, string>::const_iterator it = field2Val.begin();
127
+ it != field2Val.end(); ++it)
128
+ {
129
+ if (it != field2Val.begin())
130
+ q << ",";
131
+ q << quote << it->second;
132
+ }
133
+ q << ")";
134
+ cout << q << endl;
135
+ bool ok = executeQuery(q);
136
+ ok = ok && getLastInsertId(q, rInsertId);
137
+ return ok;
138
+ }
139
+
140
+ bool
141
+ DBFace::update(const string& table,
142
+ const map<string, string>& field2Val,
143
+ const string& where)
144
+ {
145
+ Query q = _connection.query();
146
+
147
+ q << "UPDATE " << table << " SET ";
148
+ for (map<string, string>::const_iterator it = field2Val.begin();
149
+ it != field2Val.end(); ++it)
150
+ {
151
+ if (it != field2Val.begin())
152
+ q << ",";
153
+ q << it->first << "=" << quote << it->second;
154
+ }
155
+ if (where.size())
156
+ q << " WHERE " << where;
157
+ cout << q << endl;
158
+ return executeQuery(q);
159
+ }
160
+
161
+ string
162
+ DBFace::now()
163
+ {
164
+ Query q = _connection.query();
165
+
166
+ q << "SELECT NOW()";
167
+ StoreQueryResult mysqlRes;
168
+ try{
169
+ mysqlRes = q.store();
170
+ }
171
+ catch (const mysqlpp::Exception& er) {
172
+ cerr << "Query failed: " << q << endl << er.what();
173
+ return string();
174
+ }
175
+ return toString(mysqlRes[0]["now()"]);
176
+ }
@@ -0,0 +1,47 @@
1
+ #ifndef DMMM_DBFACE_H
2
+ #define DMMM_DBFACE_H
3
+
4
+ #include <map>
5
+ #include <mysql++.h>
6
+ #include <boost/thread/mutex.hpp>
7
+
8
+ namespace DMMM {
9
+
10
+ typedef std::vector<std::map<std::string, std::string> > QueryRes;
11
+
12
+ class DBFace{
13
+ public:
14
+ static DBFace* instance() { return _this; }
15
+
16
+ DBFace(const std::string& database, const std::string& host,
17
+ const std::string& user, const std::string& password);
18
+
19
+ bool insert(const std::string& table,
20
+ const std::map<std::string, std::string>& field2Val,
21
+ size_t& rInsertId);
22
+ bool update(const std::string& table,
23
+ const std::map<std::string, std::string>& field2Val,
24
+ const std::string& where);
25
+ bool select(const std::vector<std::string>& table,
26
+ const std::vector<std::string>& columns,
27
+ const std::string& where,
28
+ const std::string& additional,
29
+ QueryRes& rRes);
30
+ bool erase(const std::vector<std::string>& table,
31
+ const std::string& where);
32
+
33
+ std::string now();
34
+
35
+ private:
36
+ bool getLastInsertId(mysqlpp::Query& rQuery, size_t& rId);
37
+ bool executeQuery(mysqlpp::Query& rQuery);
38
+
39
+ private:
40
+ mysqlpp::Connection _connection;
41
+ mutable boost::mutex _mutex;
42
+ static DBFace* _this;
43
+ };
44
+
45
+ } //namespace DMMM
46
+
47
+ #endif //DB_H
@@ -0,0 +1,28 @@
1
+ #ifndef DMMM_FIELDS_H
2
+ #define DMMM_FIELDS_H
3
+
4
+ #include <string>
5
+
6
+ #include <sstream>
7
+
8
+ #include "dmmm_utils.hpp"
9
+
10
+ namespace DMMM {
11
+
12
+ template<class T>
13
+ struct Field{
14
+ Field<T>() :_dirty(false) {}
15
+ Field<T>(const T& t) :_dirty(true), _base(t) {}
16
+ typedef T Base;
17
+ bool _dirty;
18
+ T _base;
19
+ }; //class Field
20
+
21
+ typedef Field<int> F_Integer;
22
+ typedef Field<double> F_Float;
23
+ typedef Field<std::string> F_String;
24
+ typedef Field<bool> F_TrueClass;
25
+
26
+ } //namespace DMMM
27
+
28
+ #endif //DMMM_FIELDS_H
@@ -0,0 +1,78 @@
1
+ #ifndef _DMMM_ID_HPP
2
+ #define _DMMM_ID_HPP
3
+
4
+ #include <iosfwd>
5
+ #include <string>
6
+ #include <sstream>
7
+
8
+ namespace DMMM{
9
+ template<class T>
10
+ class Id {
11
+
12
+ public:
13
+ explicit Id(size_t id) : _id(id) {}
14
+ Id() {}
15
+
16
+ inline Id operator++() {
17
+ ++_id; return *this;
18
+ }
19
+
20
+ inline Id operator++(int) {
21
+ Id val=*this;
22
+ ++*this;
23
+ return val;
24
+ }
25
+
26
+ inline bool operator==(const Id& that) const {
27
+ return _id == that._id;
28
+ }
29
+ inline bool operator< (const Id& that) const {
30
+ return _id < that._id;
31
+ }
32
+ inline bool operator<=(const Id& that) const {
33
+ return _id <= that._id;
34
+ }
35
+ inline bool operator> (const Id& that) const {
36
+ return _id > that._id;
37
+ }
38
+ inline bool operator>= (const Id& that) const {
39
+ return _id >= that._id;
40
+ }
41
+ inline bool operator!=(const Id& that) const {
42
+ return ! (*this == that);
43
+ }
44
+
45
+ std::string to_s() const {
46
+ std::ostringstream oss;
47
+ oss << _id;
48
+ return oss.str();
49
+ }
50
+
51
+
52
+ inline size_t& serialization() { return _id; }
53
+
54
+ private:
55
+ size_t _id;
56
+
57
+ };
58
+
59
+
60
+ } //namespace DMMM
61
+
62
+ template<class T>
63
+ std::ostream&
64
+ operator<< (std::ostream& os, const DMMM::Id<T>& id)
65
+ {
66
+ os << id.to_s();
67
+ return os;
68
+ }
69
+
70
+ template<class T>
71
+ std::istream&
72
+ operator>> (std::istream& is, DMMM::Id<T>& id)
73
+ {
74
+ is >> id.serialization();
75
+ return is;
76
+ }
77
+
78
+ #endif //_DMMM_ID_HPP
@@ -0,0 +1,15 @@
1
+ #ifndef DMMM_IDENTIFIERS_HPP
2
+ #define DMMM_IDENTIFIERS_HPP
3
+
4
+ #include "dmmm_id.hpp"
5
+
6
+ namespace DMMM {
7
+
8
+ <% models.each do |model| %>
9
+ class DummyO_<%= model.name %>;
10
+ typedef Id<DummyO_<%= model.name %>> I_<%= model.name %>;
11
+ <% end %>
12
+
13
+
14
+ } //namespace DMMM
15
+ #endif //DMMM_IDENTIFIERS_HPP
@@ -0,0 +1,11 @@
1
+ #include "dmmm_utils.hpp"
2
+
3
+ namespace DMMM {
4
+ template<>
5
+ std::string
6
+ fromString<std::string>(const std::string& s)
7
+ {
8
+ return s;
9
+ }
10
+
11
+ } //namespace DMMM
@@ -0,0 +1,40 @@
1
+ #ifndef DMMM_UTILS_HPP
2
+ #define DMMM_UTILS_HPP
3
+
4
+ #include <vector>
5
+ #include <map>
6
+ #include <sstream>
7
+ #include <dmmm_id.hpp>
8
+
9
+ namespace DMMM {
10
+
11
+ template<class T>
12
+ std::string
13
+ toString(const T& t)
14
+ {
15
+ std::ostringstream oss;
16
+ oss << t;
17
+
18
+ return oss.str();
19
+ }
20
+
21
+ template<class T>
22
+ T
23
+ fromString(const std::string& s)
24
+ {
25
+ std::istringstream iss;
26
+ iss.str(s);
27
+
28
+ T ret;
29
+ iss >> ret;
30
+
31
+ return ret;
32
+ }
33
+
34
+ template<>
35
+ std::string
36
+ fromString<std::string>(const std::string& s);
37
+
38
+ } //namespace DMMM
39
+
40
+ #endif //DMMM_UTILS_HPP
@@ -0,0 +1,102 @@
1
+ <% class_name = self.name %>
2
+ <% all_caps_name = class_name.upcase %>
3
+ #ifndef O_<%= all_caps_name %>
4
+ #define O_<%= all_caps_name %>
5
+
6
+ #include <map>
7
+ #include <string>
8
+ #include "dmmm_utils.hpp"
9
+ #include "dmmm_dbface.h"
10
+ #include "dmmm_identifiers.hpp"
11
+ #include "dmmm_fields.hpp"
12
+ #include "dmmm_comparators.hpp"
13
+ <% self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |relative| %>
14
+ #include "T_<%= relative[1].parent_model.to_s %>.hpp"
15
+ <% end %>
16
+
17
+ <%# self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::OneToMany::Relationship'}.each do |relative| %>
18
+ <%# end %>
19
+ namespace DMMM {
20
+
21
+ class O_<%= class_name %>{
22
+ public:
23
+
24
+ O_<%= class_name %>() {}
25
+ <% self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |r| %>
26
+ <% parent = r[0].to_const_string %>
27
+ O_<%= class_name %>(const O_<%= parent %>& parent)
28
+ : _f_<%= r[1].child_key.first.name.to_s %>(parent._<%= r[1].parent_key.first.name.to_s %>())
29
+ {}
30
+ O_<%= class_name %>(const I_<%= parent %>& parent_id)
31
+ : _f_<%= r[1].child_key.first.name.to_s %>(parent_id)
32
+ {}
33
+ <% end %>
34
+
35
+ <% generated_properties.each do |property| %>
36
+ const <%= property.instance_variable_get(:@cpp_name) %>::Base& _<%= property.name %>() const {
37
+ return _f_<%= property.name %>._base;
38
+ }
39
+ <%= property.instance_variable_get(:@cpp_name) %>::Base& _<%= property.name %>() {
40
+ _f_<%= property.name %>._dirty = true;
41
+ return _f_<%= property.name %>._base;
42
+ }
43
+
44
+ <% end %>
45
+
46
+ <% if serial %>
47
+ bool update(){
48
+ std::map<std::string, std::string> field2Val;
49
+ <% generated_properties.each do |property| %>
50
+ if (_f_<%= property.name %>._dirty)
51
+ field2Val["<%= property.name %>"] =
52
+ toString(_f_<%= property.name %>._base);
53
+ <% end %>
54
+ std::string where =
55
+ "<%= serial.name %>=" + toString(_f_<%= serial.name %>._base);
56
+ return DBFace::instance()->update("<%= storage_name %>",
57
+ field2Val, where);
58
+ }
59
+
60
+ <% end %>
61
+
62
+
63
+ bool insert(){
64
+ std::map<std::string, std::string> field2Val;
65
+ <% generated_properties.each do |property| %>
66
+ if (_f_<%= property.name %>._dirty)
67
+ field2Val["<%= property.name %>"] =
68
+ toString(_f_<%= property.name %>._base);
69
+ <% end %>
70
+ <% if serial %>
71
+ return DBFace::instance()->
72
+ insert("<%= storage_name %>", field2Val,
73
+ _f_<%= serial.name %>._base.serialization());
74
+ <% else %>
75
+ size_t id;
76
+ return DBFace::instance()->
77
+ insert("<%= storage_name %>", field2Val,
78
+ id);
79
+ <% end %>
80
+
81
+ }
82
+
83
+ <% self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |r| %>
84
+ <% parent = r[0].to_const_string %>
85
+ std::pair<O_<%= parent %>, bool> <%= r[0] %>(){
86
+ T_<%= parent %> T(T_<%= parent %>::E_<%= r[1].parent_key.first.name.to_s %>() == _<%= r[1].child_key.first.name.to_s %>());
87
+ return T.first();
88
+ }
89
+ <% end %>
90
+
91
+
92
+ private:
93
+ <% generated_properties.each do |property| %>
94
+ <%= property.instance_variable_get(:@cpp_name) %> _f_<%= property.name %>;
95
+ <% end %>
96
+
97
+
98
+ friend class T_<%= class_name %>;
99
+ };
100
+
101
+ } //namespace DMMM
102
+ #endif //O_<%= all_caps_name %>
data/output/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *
@@ -0,0 +1,8 @@
1
+ $:.push(File.join(File.dirname(__FILE__), "../lib"))
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ Bundler.setup(:default, :test)
6
+ require 'spec'
7
+
8
+ require 'dm-metamapper'
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dm-metamapper
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 0
9
+ version: 0.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Jonah Honeyman
13
+ - Omer Tamuz
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-08 00:00:00 +03:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: C++ API for databases created with DM. Hard typing, compile time checked queries.
23
+ email: jonah@honeyman.org
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.md
30
+ files:
31
+ - .gitignore
32
+ - Gemfile
33
+ - README.md
34
+ - VERSION
35
+ - example/.gitignore
36
+ - example/Makefile
37
+ - example/example.cpp
38
+ - example/example.rb
39
+ - lib/dm-metamapper.rb
40
+ - lib/dm-metamapper/extension.rb
41
+ - lib/dm-metamapper/generator.rb
42
+ - lib/dm-metamapper/metamapper.rb
43
+ - lib/dm-metamapper/property.rb
44
+ - lib/templates/cpp/class.hpp.erb
45
+ - lib/templates/cpp/dmmm_comparators.hpp.erb
46
+ - lib/templates/cpp/dmmm_dbface.cpp.erb
47
+ - lib/templates/cpp/dmmm_dbface.h.erb
48
+ - lib/templates/cpp/dmmm_fields.hpp.erb
49
+ - lib/templates/cpp/dmmm_id.hpp.erb
50
+ - lib/templates/cpp/dmmm_identifiers.hpp.erb
51
+ - lib/templates/cpp/dmmm_utils.cpp.erb
52
+ - lib/templates/cpp/dmmm_utils.hpp.erb
53
+ - lib/templates/cpp/instance.hpp.erb
54
+ - output/.gitignore
55
+ - spec/spec_helper.rb
56
+ has_rdoc: true
57
+ homepage: http://github.com/jonuts/dm-metamapper
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --charset=UTF-8
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.6
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Code generating C++ ORM
86
+ test_files:
87
+ - spec/spec_helper.rb