og 0.11.0 → 0.12.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.
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: mysql.rb 266 2005-02-28 14:50:48Z gmosx $
3
+ # $Id: mysql.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  require 'mysql'
6
6
 
@@ -19,6 +19,7 @@ class MysqlAdapter < Adapter
19
19
  def initialize
20
20
  super
21
21
  @typemap.update(TrueClass => 'tinyint')
22
+ @typecast.update(TrueClass => "#\{:s: ? \"1\" : 'NULL' \}")
22
23
  end
23
24
 
24
25
  def self.escape(str)
@@ -118,6 +119,43 @@ class MysqlAdapter < Adapter
118
119
  res.free if res
119
120
  end
120
121
 
122
+ def create_fields(klass)
123
+ fields = []
124
+
125
+ klass.__props.each do |p|
126
+ klass.sql_index(p.symbol) if p.meta[:sql_index]
127
+
128
+ field = "#{p.symbol}"
129
+
130
+ if p.meta and p.meta[:sql]
131
+ field << " #{p.meta[:sql]}"
132
+ else
133
+ field << " #{@typemap[p.klass]}"
134
+
135
+ if p.meta
136
+ # set default value (gmosx: not that useful in the
137
+ # current implementation).
138
+ if default = p.meta[:default]
139
+ field << " DEFAULT #{default.inspect} NOT NULL"
140
+ end
141
+
142
+ # set unique
143
+ # FIXME: correctly handle UNIQUE constrain.
144
+ # field << " UNIQUE" if p.meta[:unique]
145
+
146
+ # attach extra sql
147
+ if extra_sql = p.meta[:extra_sql]
148
+ field << " #{extra_sql}"
149
+ end
150
+ end
151
+ end
152
+
153
+ fields << field
154
+ end
155
+
156
+ return fields
157
+ end
158
+
121
159
  def create_table(klass, db)
122
160
  conn = db.get_connection
123
161
 
@@ -165,11 +203,11 @@ class MysqlAdapter < Adapter
165
203
  if klass.__meta and joins = klass.__meta[:sql_join]
166
204
  for data in joins
167
205
  # the class to join to and some options.
168
- join_class, options = *data
206
+ join_name, join_class, options = *data
169
207
 
170
208
  # gmosx: dont use DBTABLE here, perhaps the join class
171
209
  # is not managed yet.
172
- join_table = "#{self.class.join_table(klass, join_class)}"
210
+ join_table = "#{self.class.join_table(klass, join_class, join_name)}"
173
211
  join_src = "#{self.class.encode(klass)}_oid"
174
212
  join_dst = "#{self.class.encode(join_class)}_oid"
175
213
  begin
@@ -1,7 +1,7 @@
1
1
  # * Matt Bowen <matt.bowen@farweststeel.com>
2
2
  # * George Moschovitis <gm@navel.gr>
3
3
  # (c) 2004-2005 Navel, all rights reserved.
4
- # $Id: oracle.rb 266 2005-02-28 14:50:48Z gmosx $
4
+ # $Id: oracle.rb 270 2005-03-07 17:52:16Z gmosx $
5
5
 
6
6
  require 'oracle'
7
7
 
@@ -28,6 +28,7 @@ class OracleAdapter < Adapter
28
28
  Array => 'varchar2(1024)',
29
29
  Hash => 'varchar2(1024)'
30
30
  )
31
+ @typecast.update(TrueClass => "#\{:s: ? \"1\" : 'NULL' \}")
31
32
  end
32
33
 
33
34
  def self.timestamp(time = Time.now)
@@ -190,11 +191,11 @@ class OracleAdapter < Adapter
190
191
  if klass.__meta and joins = klass.__meta[:sql_join]
191
192
  for data in joins
192
193
  # the class to join to and some options.
193
- join_class, options = *data
194
+ join_name, join_class, options = *data
194
195
 
195
196
  # gmosx: dont use DBTABLE here, perhaps the join class
196
197
  # is not managed yet.
197
- join_table = "#{self.class.join_table(klass, join_class)}"
198
+ join_table = "#{self.class.join_table(klass, join_class, join_name)}"
198
199
  join_src = "#{self.class.encode(klass)}_oid"
199
200
  join_dst = "#{self.class.encode(join_class)}_oid"
200
201
  begin
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: psql.rb 266 2005-02-28 14:50:48Z gmosx $
3
+ # $Id: psql.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  require 'postgres'
6
6
 
@@ -137,11 +137,11 @@ class PsqlAdapter < Adapter
137
137
  if klass.__meta and joins = klass.__meta[:sql_join]
138
138
  for data in joins
139
139
  # the class to join to and some options.
140
- join_class, options = *data
140
+ join_name, join_class, options = *data
141
141
 
142
142
  # gmosx: dont use DBTABLE here, perhaps the join class
143
143
  # is not managed yet.
144
- join_table = "#{self.class.join_table(klass, join_class)}"
144
+ join_table = "#{self.class.join_table(klass, join_class, join_name)}"
145
145
  join_src = "#{self.class.encode(klass)}_oid"
146
146
  join_dst = "#{self.class.encode(join_class)}_oid"
147
147
  begin
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: sqlite.rb 263 2005-02-23 13:45:08Z gmosx $
3
+ # $Id: sqlite.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  require 'sqlite3'
6
6
  require 'fileutils'
@@ -142,11 +142,11 @@ class SqliteAdapter < Adapter
142
142
  if klass.__meta and joins = klass.__meta[:sql_join]
143
143
  for data in joins
144
144
  # the class to join to and some options.
145
- join_class, options = *data
145
+ join_name, join_class, options = *data
146
146
 
147
147
  # gmosx: dont use DBTABLE here, perhaps the join class
148
148
  # is not managed yet.
149
- join_table = "#{self.class.join_table(klass, join_class)}"
149
+ join_table = "#{self.class.join_table(klass, join_class, join_name)}"
150
150
  join_src = "#{self.class.encode(klass)}_oid"
151
151
  join_dst = "#{self.class.encode(join_class)}_oid"
152
152
  begin
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: connection.rb 265 2005-02-24 08:46:54Z gmosx $
3
+ # $Id: connection.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  module Og;
6
6
 
@@ -270,6 +270,10 @@ class Connection
270
270
  #
271
271
  # obj_or_oid = Object or oid to delete.
272
272
  # klass = Class of object (can be nil if an object is passed)
273
+ #
274
+ #--
275
+ # TODO: pre evaluate for symmetry to the other methods
276
+ #++
273
277
 
274
278
  def delete(obj_or_oid, klass = nil, cascade = true)
275
279
  oid = obj_or_oid.to_i
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: database.rb 265 2005-02-24 08:46:54Z gmosx $
3
+ # $Id: database.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  require 'glue/logger'
6
6
  require 'glue/attribute'
@@ -12,6 +12,7 @@ require 'glue/pool'
12
12
 
13
13
  require 'og/enchant'
14
14
  require 'og/meta'
15
+ require 'og/observer'
15
16
 
16
17
  module Og
17
18
 
@@ -68,7 +69,6 @@ class Database
68
69
  @managed_classes = N::SafeHash.new
69
70
 
70
71
  @config[:connection_count].times do
71
- # @connection_pool << Og::Connection.new(self)
72
72
  @connection_pool << @adapter.new_connection(self)
73
73
  end
74
74
 
@@ -148,11 +148,10 @@ class Database
148
148
  end
149
149
  alias_method :open, :connect
150
150
 
151
-
152
151
  # Register a standard Ruby class as managed.
153
152
 
154
153
  def manage(klass)
155
- return if managed?(klass) or klass.ancestors.include?(Og::Unmanageable)
154
+ return if managed?(klass) or klass.ancestors.include?(Unmanageable)
156
155
 
157
156
  @managed_classes[klass] = ManagedClassMeta.new(klass)
158
157
 
@@ -194,22 +193,31 @@ class Database
194
193
  klass.class_eval %{
195
194
  DBTABLE = "#{Adapter.table(klass)}"
196
195
  DBSEQ = "#{Adapter.table(klass)}_oid_seq"
197
-
198
- def to_i()
196
+
197
+ cattr_accessor :og_db
198
+
199
+ def to_i
199
200
  @oid
200
201
  end
201
202
  }
202
203
 
204
+ # Set the adapter.
205
+
206
+ klass.og_db = self
207
+
208
+ # Add observer support.
209
+
210
+ klass.extend(Observable)
211
+
203
212
  # Create the schema for this class if not available.
213
+
204
214
  @adapter.create_table(klass, self) if Og.create_schema
205
215
 
206
- # Precompile some code that gets executed all the time.
207
- # Deletion code is not precompiled, because it is not used
208
- # as frequently.
216
+ # @adapter.eval_og_insert(klass, self)
217
+ # @adapter.eval_og_update(klass, self)
218
+ # @adapter.eval_og_read(klass, self)
209
219
 
210
- @adapter.eval_og_insert(klass, self)
211
- @adapter.eval_og_update(klass, self)
212
- @adapter.eval_og_read(klass, self)
220
+ @adapter.eval_lifecycle_methods(klass, self)
213
221
  end
214
222
 
215
223
  # Automatically wrap connection methods.
@@ -251,17 +259,23 @@ class Database
251
259
  wrap_method :exec, 'sql'
252
260
 
253
261
  class << self
262
+
263
+ # Create a new database.
264
+
254
265
  def create_db!(config)
255
266
  adapter = Adapter.for_name(config[:adapter])
256
267
  adapter.create_db(config[:database], config[:user], config[:password])
257
268
  end
258
269
  alias_method :create!, :create_db!
259
270
 
271
+ # Drop an existing database.
272
+
260
273
  def drop_db!(config)
261
274
  adapter = Adapter.for_name(config[:adapter])
262
275
  adapter.drop_db(config[:database], config[:user], config[:password])
263
276
  end
264
277
  alias_method :drop!, :drop_db!
278
+
265
279
  end
266
280
  end
267
281
 
@@ -10,54 +10,65 @@ module Enchant
10
10
  # to the class and its instances.
11
11
 
12
12
  def enchant(klass)
13
- klass.module_eval <<-"end_eval", __FILE__, __LINE__
13
+
14
+ # Generate standard methods.
15
+
16
+ klass.module_eval %{
14
17
  def self.create(*params, &block)
15
18
  obj = #{klass}.new(*params, &block)
16
19
  obj.save!
17
20
  end
18
21
 
19
22
  def self.save(obj)
20
- Og.db << obj
23
+ @@og_db << obj
21
24
  end
22
25
 
23
26
  def self.load(oid_or_name)
24
- Og.db.load(oid_or_name, #{klass})
27
+ @@og_db.load(oid_or_name, #{klass})
25
28
  end
26
29
 
27
30
  def self.get(oid_or_name)
28
- Og.db.load(oid_or_name, #{klass})
31
+ @@og_db.load(oid_or_name, #{klass})
29
32
  end
30
33
 
31
34
  def self.[](oid_or_name)
32
- Og.db.load(oid_or_name, #{klass})
35
+ @@og_db.load(oid_or_name, #{klass})
33
36
  end
34
37
 
35
38
  def self.load_all(extra_sql = nil)
36
- Og.db.load_all(#{klass}, extra_sql)
39
+ @@og_db.load_all(#{klass}, extra_sql)
37
40
  end
38
41
 
39
42
  def self.all(extra_sql = nil)
40
- Og.db.load_all(#{klass}, extra_sql)
43
+ @@og_db.load_all(#{klass}, extra_sql)
41
44
  end
42
45
 
43
46
  def self.count(sql = "SELECT COUNT(*) FROM #{klass::DBTABLE}")
44
- Og.db.count(sql, #{klass})
47
+ @@og_db.count(sql, #{klass})
45
48
  end
46
49
 
47
50
  def self.select(sql)
48
- Og.db.select(sql, #{klass})
51
+ @@og_db.select(sql, #{klass})
52
+ end
53
+
54
+ def self.find(sql)
55
+ @@og_db.select(sql, #{klass})
49
56
  end
50
57
 
51
58
  def self.select_one(sql)
52
- Og.db.select_one(sql, #{klass})
59
+ @@og_db.select_one(sql, #{klass})
60
+ end
61
+
62
+ def self.find_one(sql)
63
+ @@og_db.select_one(sql, #{klass})
53
64
  end
54
65
 
55
66
  def self.one(sql)
56
- Og.db.select_one(sql, #{klass})
67
+ @@og_db.select_one(sql, #{klass})
57
68
  end
58
69
 
59
70
  def self.delete(obj_or_oid)
60
- Og.db.delete(obj_or_oid, #{klass})
71
+ @@og_db.delete(obj_or_oid, #{klass})
61
72
  end
62
73
 
63
74
  def self.properties_and_relations
@@ -70,20 +81,43 @@ module Enchant
70
81
  include Enumerable
71
82
 
72
83
  def save
73
- Og.db << self
84
+ @@og_db << self
74
85
  return self
75
86
  end
76
87
  alias_method :save!, :save
77
88
 
78
89
  def update_properties(updatesql)
79
- Og.db.pupdate(updatesql, self.oid, #{klass})
90
+ @@og_db.pupdate(updatesql, self.oid, #{klass})
80
91
  end
81
92
  alias_method :pupdate!, :update_properties
82
93
 
83
94
  def delete!
84
- Og.db.delete(@oid, #{klass})
95
+ @@og_db.delete(@oid, #{klass})
85
96
  end
86
- end_eval
97
+ }
98
+
99
+ # Generate finder methods.
100
+
101
+ code = ''
102
+
103
+ for p in klass.__props
104
+ code << %{
105
+ def self.find_by_#{p.name}(val, operator = '=', extra_sql = nil)
106
+ }
107
+
108
+ val = klass.og_db.adapter.typecast[p.klass].gsub(/\:s\:/, 'val')
109
+
110
+ if p.meta[:unique]
111
+ code << %{@@og_db.select_one("#{p.name}\#\{operator\}#{val} \#\{extra_sql\}", #{klass})}
112
+ else
113
+ code << %{@@og_db.select("#{p.name}\#\{operator\}#{val} \#\{extra_sql\}", #{klass})}
114
+ end
115
+ code << %{
116
+ end;
117
+ }
118
+ end
119
+
120
+ klass.module_eval(code)
87
121
  end
88
122
 
89
123
  end
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: meta.rb 266 2005-02-28 14:50:48Z gmosx $
3
+ # $Id: meta.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
  #--
5
5
  # TODO:
6
6
  # - precreate the meta sql statements as much as possible to
@@ -135,7 +135,7 @@ module MetaLanguage
135
135
  # linkback is the property of the child object that 'links back'
136
136
  # to this object.
137
137
 
138
- linkback = options[:linkback] || "#{MetaUtils.expand(self)}_oid"
138
+ linkback = (options[:linkback].to_s || "#{MetaUtils.expand(self)}_oid").to_s
139
139
 
140
140
  meta :descendants, klass, linkback
141
141
  meta :props_and_relations, HasOne.new(name, klass, :linkback => linkback)
@@ -175,7 +175,7 @@ module MetaLanguage
175
175
  # linkback is the property of the child object that 'links back'
176
176
  # to this object.
177
177
 
178
- linkback = options[:linkback] || "#{MetaUtils.expand(self)}_oid"
178
+ linkback = (options[:linkback] || "#{MetaUtils.expand(self)}_oid").to_s
179
179
 
180
180
  # keep belongs to metadata, useful for
181
181
  # reflection/scaffolding.
@@ -231,7 +231,7 @@ module MetaLanguage
231
231
  def many_to_many(name, klass, options = {})
232
232
  list_o = name.to_s
233
233
  prop_o = N::Inflector.singularize(list_o)
234
- list_m = options[:linkback] || N::Inflector.plural_name(self)
234
+ list_m = (options[:linkback] || N::Inflector.plural_name(self)).to_s
235
235
  prop_m = N::Inflector.singularize(list_m)
236
236
 
237
237
  # Exit if the class is allready indirectly 'enchanted' from the
@@ -242,7 +242,7 @@ module MetaLanguage
242
242
  # Add some metadata to the class to allow for automatic join table
243
243
  # calculation.
244
244
 
245
- meta :sql_join, klass, options
245
+ meta :sql_join, name, klass, options
246
246
 
247
247
  # FIXME: should add metadata for cascading delete.
248
248
 
@@ -253,25 +253,25 @@ module MetaLanguage
253
253
 
254
254
  module_eval %{
255
255
  def #{list_o}(extrasql = nil)
256
- Og.db.select("SELECT d.* FROM #{Og::Adapter.table(klass)} d, #{Og::Adapter.join_table(self, klass)} j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
256
+ Og.db.select("SELECT d.* FROM #{Og::Adapter.table(klass)} d, #{Og::Adapter.join_table(self, klass, name)} j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
257
257
  end
258
258
 
259
259
  def #{list_o}_count(extrasql = nil)
260
- Og.db.select("SELECT COUNT(*) FROM #{Og::Adapter.table(klass)} d, #{Og::Adapter.join_table(self, klass)} j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
260
+ Og.db.select("SELECT COUNT(*) FROM #{Og::Adapter.table(klass)} d, #{Og::Adapter.join_table(self, klass, name)} j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
261
261
  end
262
262
 
263
263
  def add_#{prop_o}(obj = nil)
264
264
  yield(obj = #{klass}.new) unless obj
265
265
  obj.save! unless obj.oid
266
- Og.db.exec("INSERT INTO #{Og::Adapter.join_table(self, klass)} (key1, key2) VALUES (\#\@oid, \#\{obj.oid\})")
266
+ Og.db.exec("INSERT INTO #{Og::Adapter.join_table(self, klass, name)} (key1, key2) VALUES (\#\@oid, \#\{obj.oid\})")
267
267
  end
268
268
 
269
269
  def delete_#{prop_o}(obj_or_oid)
270
- Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass)} WHERE key2=\#\{obj_or_oid.to_i\}")
270
+ Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass, name)} WHERE key2=\#\{obj_or_oid.to_i\}")
271
271
  end
272
272
 
273
273
  def clear_#{list_o}
274
- Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass)} WHERE key1=\#\@oid")
274
+ Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass, name)} WHERE key1=\#\@oid")
275
275
  end
276
276
  }
277
277
 
@@ -279,25 +279,25 @@ module MetaLanguage
279
279
 
280
280
  klass.module_eval %{
281
281
  def #{list_m}(extrasql = nil)
282
- Og.db.select("SELECT s.* FROM #{Og::Adapter.table(self)} s, #{Og::Adapter.join_table(self, klass)} j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
282
+ Og.db.select("SELECT s.* FROM #{Og::Adapter.table(self)} s, #{Og::Adapter.join_table(self, klass, name)} j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
283
283
  end
284
284
 
285
285
  def #{list_m}_count(extrasql = nil)
286
- Og.db.select("SELECT COUNT(*) FROM #{Og::Adapter.table(self)} s, #{Og::Adapter.join_table(self, klass)} j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
286
+ Og.db.select("SELECT COUNT(*) FROM #{Og::Adapter.table(self)} s, #{Og::Adapter.join_table(self, klass, name)} j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
287
287
  end
288
288
 
289
289
  def add_#{prop_m}(obj = nil)
290
290
  yield(obj = #{self}.new) unless obj
291
291
  obj.save! unless obj.oid
292
- Og.db.exec("INSERT INTO #{Og::Adapter.join_table(self, klass)} (key1, key2) VALUES (\#\{obj.oid\}, \#\@oid)")
292
+ Og.db.exec("INSERT INTO #{Og::Adapter.join_table(self, klass, name)} (key1, key2) VALUES (\#\{obj.oid\}, \#\@oid)")
293
293
  end
294
294
 
295
295
  def delete_#{prop_m}(obj_or_oid)
296
- Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass)} WHERE key1=\#\{obj_or_oid.to_i\}")
296
+ Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass, name)} WHERE key1=\#\{obj_or_oid.to_i\}")
297
297
  end
298
298
 
299
299
  def clear_#{list_m}
300
- Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass)} WHERE key2=\#\@oid")
300
+ Og.db.exec("DELETE FROM #{Og::Adapter.join_table(self, klass, name)} WHERE key2=\#\@oid")
301
301
  end
302
302
  }
303
303
  end