og 0.14.0 → 0.15.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/CHANGELOG +68 -0
- data/README +16 -7
- data/doc/AUTHORS +3 -6
- data/doc/RELEASES +44 -1
- data/examples/run.rb +1 -1
- data/examples/test.db +0 -0
- data/lib/og.rb +2 -2
- data/lib/og/adapters/oracle.rb +1 -7
- data/lib/og/adapters/sqlserver.rb +360 -0
- data/lib/og/meta.rb +1 -4
- data/lib/og/mixins/hierarchical.rb +134 -0
- data/lib/og/mixins/{list.rb → orderable.rb} +25 -23
- data/lib/og/typemacros.rb +4 -3
- data/test/og/mixins/tc_hierarchical.rb +79 -0
- data/test/og/mixins/{tc_list.rb → tc_orderable.rb} +5 -2
- data/test/og/tc_sqlserver.rb +93 -0
- metadata +10 -7
- data/lib/og/backend.rb +0 -297
- data/test/og/mixins/tc_tree.rb +0 -59
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
|
|
3
3
|
specification_version: 1
|
4
4
|
name: og
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2005-
|
6
|
+
version: 0.15.0
|
7
|
+
date: 2005-04-04
|
8
8
|
summary: Og (ObjectGraph)
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -37,6 +37,7 @@ files:
|
|
37
37
|
- benchmark/sqlite-no-prepare.1.txt
|
38
38
|
- benchmark/bench.rb
|
39
39
|
- benchmark/sqlite-prepare.1.txt
|
40
|
+
- examples/test.db
|
40
41
|
- examples/mysql_to_psql.rb
|
41
42
|
- examples/run.rb
|
42
43
|
- examples/mock_example.rb
|
@@ -59,14 +60,15 @@ files:
|
|
59
60
|
- lib/og/meta.rb
|
60
61
|
- lib/og/validation.rb
|
61
62
|
- lib/og/typemacros.rb
|
62
|
-
- lib/og/backend.rb
|
63
63
|
- lib/og/testing/mock.rb
|
64
|
-
- lib/og/mixins/
|
64
|
+
- lib/og/mixins/hierarchical.rb
|
65
|
+
- lib/og/mixins/orderable.rb
|
65
66
|
- lib/og/mixins/tree.rb
|
66
67
|
- lib/og/adapters/oracle.rb
|
67
68
|
- lib/og/adapters/filesys.rb
|
68
69
|
- lib/og/adapters/mysql.rb
|
69
70
|
- lib/og/adapters/sqlite.rb
|
71
|
+
- lib/og/adapters/sqlserver.rb
|
70
72
|
- lib/og/adapters/psql.rb
|
71
73
|
- test/tc_og.rb
|
72
74
|
- test/og
|
@@ -76,11 +78,12 @@ files:
|
|
76
78
|
- test/og/tc_observer.rb
|
77
79
|
- test/og/tc_automanage.rb
|
78
80
|
- test/og/tc_filesys.rb
|
81
|
+
- test/og/tc_sqlserver.rb
|
79
82
|
- test/og/tc_meta.rb
|
80
83
|
- test/og/tc_many_to_many.rb
|
81
84
|
- test/og/tc_lifecycle.rb
|
82
|
-
- test/og/mixins/
|
83
|
-
- test/og/mixins/
|
85
|
+
- test/og/mixins/tc_hierarchical.rb
|
86
|
+
- test/og/mixins/tc_orderable.rb
|
84
87
|
test_files: []
|
85
88
|
rdoc_options:
|
86
89
|
- "--main"
|
@@ -106,5 +109,5 @@ dependencies:
|
|
106
109
|
-
|
107
110
|
- "="
|
108
111
|
- !ruby/object:Gem::Version
|
109
|
-
version: 0.
|
112
|
+
version: 0.15.0
|
110
113
|
version:
|
data/lib/og/backend.rb
DELETED
@@ -1,297 +0,0 @@
|
|
1
|
-
# * George Moschovitis <gm@navel.gr>
|
2
|
-
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
-
# $Id: backend.rb 281 2005-03-10 12:24:14Z gmosx $
|
4
|
-
|
5
|
-
require 'yaml'
|
6
|
-
|
7
|
-
require 'og/connection'
|
8
|
-
|
9
|
-
module Og
|
10
|
-
|
11
|
-
# Abstract backend. A backend communicates with the RDBMS.
|
12
|
-
# This is the base class for the various backend implementations.
|
13
|
-
|
14
|
-
class Backend
|
15
|
-
|
16
|
-
# The actual connection to the database
|
17
|
-
attr_accessor :conn
|
18
|
-
|
19
|
-
# Intitialize the connection to the RDBMS.
|
20
|
-
|
21
|
-
def initialize(config)
|
22
|
-
raise "Not implemented"
|
23
|
-
end
|
24
|
-
|
25
|
-
# Close the connection to the RDBMS.
|
26
|
-
|
27
|
-
def close()
|
28
|
-
@conn.close()
|
29
|
-
end
|
30
|
-
|
31
|
-
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
32
|
-
# :section: Utilities
|
33
|
-
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
34
|
-
|
35
|
-
# Encode the name of the klass as an sql safe string.
|
36
|
-
# The Module separators are replaced with _ and NOT stripped
|
37
|
-
# out so that we can convert back to the original notation if
|
38
|
-
# needed. The leading module if available is removed.
|
39
|
-
|
40
|
-
def self.encode(klass)
|
41
|
-
"#{klass.name.gsub(/^.*::/, "")}".gsub(/::/, "_").downcase
|
42
|
-
end
|
43
|
-
|
44
|
-
# The name of the SQL table where objects of this class
|
45
|
-
# are stored.
|
46
|
-
|
47
|
-
def self.table(klass)
|
48
|
-
"_#{Og.table_prefix}#{encode(klass)}"
|
49
|
-
end
|
50
|
-
|
51
|
-
# The name of the join table for the two given classes.
|
52
|
-
|
53
|
-
def self.join_table(klass1, klass2)
|
54
|
-
"_#{Og.table_prefix}j_#{encode(klass1)}_#{encode(klass2)}"
|
55
|
-
end
|
56
|
-
|
57
|
-
# Returns the props that will be included in the insert query.
|
58
|
-
# For some backends the oid should be stripped.
|
59
|
-
|
60
|
-
def self.props_for_insert(klass)
|
61
|
-
klass.__props
|
62
|
-
end
|
63
|
-
|
64
|
-
# Precompile the insert code for the given class.
|
65
|
-
# The generated code sets the oid when inserting!
|
66
|
-
|
67
|
-
def self.eval_og_insert(klass)
|
68
|
-
props = props_for_insert(klass)
|
69
|
-
|
70
|
-
values = props.collect { |p| write_prop(p) }
|
71
|
-
|
72
|
-
sql = "INSERT INTO #{table(klass)} (#{props.collect {|p| p.name}.join(',')}) VALUES (#{values.join(',')})"
|
73
|
-
|
74
|
-
if klass.instance_methods.include?("og_pre_insert")
|
75
|
-
pre_cb = "og_pre_insert(conn);"
|
76
|
-
else
|
77
|
-
pre_cb = ""
|
78
|
-
end
|
79
|
-
|
80
|
-
if klass.instance_methods.include?("og_post_insert")
|
81
|
-
post_cb = "og_post_insert(conn);"
|
82
|
-
else
|
83
|
-
post_cb = ""
|
84
|
-
end
|
85
|
-
|
86
|
-
if klass.instance_methods.include?("og_pre_insert_update")
|
87
|
-
pre_cb << "og_pre_insert_update(conn);"
|
88
|
-
end
|
89
|
-
|
90
|
-
if klass.instance_methods.include?("og_post_insert_update")
|
91
|
-
post_cb << "og_post_insert_update(conn);"
|
92
|
-
end
|
93
|
-
|
94
|
-
klass.class_eval %{
|
95
|
-
def og_insert(conn)
|
96
|
-
#{insert_code(klass, sql, pre_cb, post_cb)}
|
97
|
-
end
|
98
|
-
}
|
99
|
-
end
|
100
|
-
|
101
|
-
# Precompile the update code for the given class.
|
102
|
-
# Ignore the oid when updating!
|
103
|
-
|
104
|
-
def self.eval_og_update(klass)
|
105
|
-
props = klass.__props.reject { |p| :oid == p.symbol }
|
106
|
-
|
107
|
-
updates = props.collect { |p|
|
108
|
-
"#{p.name}=#{write_prop(p)}"
|
109
|
-
}
|
110
|
-
|
111
|
-
sql = "UPDATE #{klass::DBTABLE} SET #{updates.join(', ')} WHERE oid=#\{@oid\}"
|
112
|
-
|
113
|
-
if klass.instance_methods.include?("og_pre_update")
|
114
|
-
pre_cb = "og_pre_update(conn);"
|
115
|
-
else
|
116
|
-
pre_cb = ""
|
117
|
-
end
|
118
|
-
|
119
|
-
if klass.instance_methods.include?("og_post_update")
|
120
|
-
post_cb = "og_post_update(conn);"
|
121
|
-
else
|
122
|
-
post_cb = ""
|
123
|
-
end
|
124
|
-
|
125
|
-
if klass.instance_methods.include?("og_pre_insert_update")
|
126
|
-
pre_cb << "og_pre_insert_update(conn);"
|
127
|
-
end
|
128
|
-
|
129
|
-
if klass.instance_methods.include?("og_post_insert_update")
|
130
|
-
post_cb << "og_post_insert_update(conn);"
|
131
|
-
end
|
132
|
-
|
133
|
-
klass.class_eval %{
|
134
|
-
def og_update(conn)
|
135
|
-
#{pre_cb}
|
136
|
-
conn.exec "#{sql}"
|
137
|
-
#{post_cb}
|
138
|
-
end
|
139
|
-
}
|
140
|
-
end
|
141
|
-
|
142
|
-
# Precompile the code to read objects of the given class
|
143
|
-
# from the backend. In order to allow for changing
|
144
|
-
# field/attribute orders we have to use a field mapping hash.
|
145
|
-
|
146
|
-
def self.eval_og_deserialize(klass, og)
|
147
|
-
calc_field_index(klass, og)
|
148
|
-
|
149
|
-
props = klass.__props
|
150
|
-
code = []
|
151
|
-
|
152
|
-
props.each do |p|
|
153
|
-
if idx = og.managed_classes[klass].field_index[p.name]
|
154
|
-
# more fault tolerant if a new field is added and it
|
155
|
-
# doesnt exist in the database.
|
156
|
-
code << "@#{p.name} = #{read_prop(p, idx)}"
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
klass.class_eval %{
|
161
|
-
def og_deserialize(res, tuple = nil)
|
162
|
-
#{code.join('; ')}
|
163
|
-
end
|
164
|
-
}
|
165
|
-
end
|
166
|
-
|
167
|
-
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
168
|
-
# :section: Connection methods.
|
169
|
-
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
170
|
-
|
171
|
-
# Create the database.
|
172
|
-
|
173
|
-
def self.create_db(database, user = nil, password = nil)
|
174
|
-
Logger.info "Creating database '#{database}'."
|
175
|
-
end
|
176
|
-
|
177
|
-
# Drop the database.
|
178
|
-
|
179
|
-
def self.drop_db(database, user = nil, password = nil)
|
180
|
-
Logger.info "Dropping database '#{database}'."
|
181
|
-
end
|
182
|
-
|
183
|
-
# Execute an SQL query and return the result.
|
184
|
-
|
185
|
-
def query(sql)
|
186
|
-
raise "Not implemented"
|
187
|
-
end
|
188
|
-
|
189
|
-
# Execute an SQL query, no result returned.
|
190
|
-
|
191
|
-
def exec(sql)
|
192
|
-
raise "Not implemented"
|
193
|
-
end
|
194
|
-
|
195
|
-
# Execute an SQL query and return the result. Wrapped in a
|
196
|
-
# rescue block.
|
197
|
-
|
198
|
-
def safe_query(sql)
|
199
|
-
raise "Not implemented"
|
200
|
-
end
|
201
|
-
|
202
|
-
# Execute an SQL query, no result returned. Wrapped in a
|
203
|
-
# rescue block.
|
204
|
-
|
205
|
-
def safe_exec(sql)
|
206
|
-
raise "Not implemented"
|
207
|
-
end
|
208
|
-
|
209
|
-
# Check if it is a valid resultset.
|
210
|
-
|
211
|
-
def valid?(res)
|
212
|
-
raise "Not implemented"
|
213
|
-
end
|
214
|
-
|
215
|
-
# Start a new transaction.
|
216
|
-
|
217
|
-
def start
|
218
|
-
exec "START TRANSACTION"
|
219
|
-
end
|
220
|
-
|
221
|
-
# Commit a transaction.
|
222
|
-
|
223
|
-
def commit
|
224
|
-
exec "COMMIT"
|
225
|
-
end
|
226
|
-
|
227
|
-
# Rollback transaction.
|
228
|
-
|
229
|
-
def rollback
|
230
|
-
exec "ROLLBACK"
|
231
|
-
end
|
232
|
-
|
233
|
-
# Create the fields that correpsond to the klass properties.
|
234
|
-
# The generated fields array is used in create_table.
|
235
|
-
# If the property has an :sql metadata this overrides the
|
236
|
-
# default mapping. If the property has an :extra_sql metadata
|
237
|
-
# the extra sql is appended after the default mapping.
|
238
|
-
|
239
|
-
def create_fields(klass, typemap)
|
240
|
-
fields = []
|
241
|
-
|
242
|
-
klass.__props.each do |p|
|
243
|
-
klass.sql_index(p.symbol) if p.meta[:sql_index]
|
244
|
-
|
245
|
-
field = "#{p.symbol}"
|
246
|
-
|
247
|
-
if p.meta and p.meta[:sql]
|
248
|
-
field << " #{p.meta[:sql]}"
|
249
|
-
else
|
250
|
-
field << " #{typemap[p.klass]}"
|
251
|
-
# attach extra sql
|
252
|
-
if p.meta and extra_sql = p.meta[:extra_sql]
|
253
|
-
field << " #{extra_sql}"
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
fields << field
|
258
|
-
end
|
259
|
-
|
260
|
-
return fields
|
261
|
-
end
|
262
|
-
|
263
|
-
# Create the managed object table. The properties of the
|
264
|
-
# object are mapped to the table columns. Additional sql relations
|
265
|
-
# and constrains are created (indicices, sequences, etc).
|
266
|
-
|
267
|
-
def create_table(klass)
|
268
|
-
return if query("SELECT * FROM #{klass::DBTABLE} LIMIT 1")
|
269
|
-
end
|
270
|
-
|
271
|
-
# Drop the managed object table
|
272
|
-
|
273
|
-
def drop_table(klass)
|
274
|
-
exec "DROP TABLE #{klass::DBTABLE}"
|
275
|
-
end
|
276
|
-
|
277
|
-
# Deserialize one row of the resultset.
|
278
|
-
|
279
|
-
def deserialize_one(res, klass)
|
280
|
-
raise 'Not implemented'
|
281
|
-
end
|
282
|
-
|
283
|
-
# Deserialize all rows of the resultset.
|
284
|
-
|
285
|
-
def deserialize_all(res, klass)
|
286
|
-
raise 'Not implemented'
|
287
|
-
end
|
288
|
-
|
289
|
-
# Return a single integer value from the resultset.
|
290
|
-
|
291
|
-
def get_int(res, idx = 0)
|
292
|
-
raise 'Not implemented'
|
293
|
-
end
|
294
|
-
|
295
|
-
end
|
296
|
-
|
297
|
-
end
|
data/test/og/mixins/tc_tree.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
$:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
|
2
|
-
|
3
|
-
require 'test/unit'
|
4
|
-
require 'ostruct'
|
5
|
-
|
6
|
-
require 'og'
|
7
|
-
|
8
|
-
$og = Og::Database.new(
|
9
|
-
:adapter => 'psql',
|
10
|
-
:database => 'test',
|
11
|
-
:user => 'postgres',
|
12
|
-
:password => 'navelrulez',
|
13
|
-
:drop => true
|
14
|
-
)
|
15
|
-
|
16
|
-
class TestCaseOgTree < Test::Unit::TestCase # :nodoc: all
|
17
|
-
include N
|
18
|
-
|
19
|
-
class Comment; end
|
20
|
-
|
21
|
-
class Article
|
22
|
-
property :title, :body, String
|
23
|
-
has_many :comments, Comment, :tree => true
|
24
|
-
|
25
|
-
def initialize(title = nil)
|
26
|
-
@title = title
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class Comment
|
31
|
-
property :body, String
|
32
|
-
belongs_to :article, Article
|
33
|
-
belongs_to :comment, Comment
|
34
|
-
has_many :comments, Comment, :tree => true
|
35
|
-
|
36
|
-
def initialize(body = nil)
|
37
|
-
@body = body
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_all
|
42
|
-
$og.auto_manage_classes
|
43
|
-
|
44
|
-
a = Article.new('article')
|
45
|
-
a.save
|
46
|
-
|
47
|
-
c1 = Comment.new('1')
|
48
|
-
a.add_comment(c1)
|
49
|
-
c11 = Comment.new('1.1')
|
50
|
-
c1.add_comment(c11)
|
51
|
-
c1.save
|
52
|
-
|
53
|
-
puts "\n\n"
|
54
|
-
a.comments_tree.each do |c|
|
55
|
-
puts "#{c.body.ljust(16)}[#{c.tree_x},#{c.tree_y}]"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|