dm-metamapper 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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