rod 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/.travis.yml +1 -1
  2. data/README.rdoc +38 -10
  3. data/Rakefile +20 -9
  4. data/changelog.txt +25 -0
  5. data/contributors.txt +1 -0
  6. data/data/backward/0.7.0/_join_element.dat +0 -0
  7. data/data/backward/0.7.0/_polymorphic_join_element.dat +0 -0
  8. data/data/backward/0.7.0/char.dat +0 -0
  9. data/data/backward/0.7.0/database.yml +58 -0
  10. data/data/backward/0.7.0/rod_test__automobile.dat +0 -0
  11. data/data/backward/0.7.0/rod_test__caveman.dat +0 -0
  12. data/data/backward/0.7.0/rod_test__dog.dat +0 -0
  13. data/data/backward/0.7.0/rod_test__test_model.dat +0 -0
  14. data/data/portability/_join_element.dat +0 -0
  15. data/data/portability/_polymorphic_join_element.dat +0 -0
  16. data/data/portability/char.dat +0 -0
  17. data/data/portability/database.yml +49 -0
  18. data/data/portability/rod_test__automobile.dat +0 -0
  19. data/data/portability/rod_test__caveman.dat +0 -0
  20. data/data/portability/rod_test__dog.dat +0 -0
  21. data/data/portability/rod_test__test_model.dat +0 -0
  22. data/features/backward.feature +33 -0
  23. data/features/basic.feature +3 -0
  24. data/features/collection_proxy.feature +95 -0
  25. data/features/flat_indexing.feature +44 -2
  26. data/features/hash_indexing.feature +63 -9
  27. data/features/portability.feature +72 -0
  28. data/features/segmented_indexing.feature +45 -2
  29. data/features/steps/collection_proxy.rb +1 -1
  30. data/features/steps/model.rb +48 -5
  31. data/features/steps/rod.rb +15 -16
  32. data/lib/rod.rb +11 -1
  33. data/lib/rod/abstract_database.rb +52 -42
  34. data/lib/rod/berkeley/collection_proxy.rb +96 -0
  35. data/lib/rod/berkeley/database.rb +337 -0
  36. data/lib/rod/berkeley/environment.rb +209 -0
  37. data/lib/rod/berkeley/sequence.rb +222 -0
  38. data/lib/rod/berkeley/transaction.rb +233 -0
  39. data/lib/rod/collection_proxy.rb +76 -1
  40. data/lib/rod/constants.rb +3 -2
  41. data/lib/rod/database.rb +127 -14
  42. data/lib/rod/index/base.rb +12 -3
  43. data/lib/rod/index/hash_index.rb +295 -70
  44. data/lib/rod/index/segmented_index.rb +3 -0
  45. data/lib/rod/model.rb +154 -531
  46. data/lib/rod/property/base.rb +190 -0
  47. data/lib/rod/property/field.rb +258 -0
  48. data/lib/rod/property/plural_association.rb +145 -0
  49. data/lib/rod/property/singular_association.rb +139 -0
  50. data/rod.gemspec +6 -4
  51. data/spec/berkeley/database.rb +83 -0
  52. data/spec/berkeley/environment.rb +58 -0
  53. data/spec/berkeley/sequence.rb +101 -0
  54. data/spec/berkeley/transaction.rb +92 -0
  55. data/spec/collection_proxy.rb +38 -0
  56. data/spec/database.rb +36 -0
  57. data/spec/model.rb +26 -0
  58. data/spec/property/base.rb +73 -0
  59. data/spec/property/field.rb +244 -0
  60. data/spec/property/plural_association.rb +67 -0
  61. data/spec/property/singular_association.rb +65 -0
  62. data/tests/class_compatibility_create.rb +2 -2
  63. data/tests/eff1_test.rb +1 -1
  64. data/tests/eff2_test.rb +1 -1
  65. data/tests/full_runs.rb +1 -1
  66. data/tests/generate_classes_create.rb +14 -14
  67. data/tests/migration_create.rb +47 -47
  68. data/tests/migration_verify.rb +1 -1
  69. data/tests/missing_class_create.rb +6 -6
  70. data/tests/properties_order_create.rb +4 -4
  71. data/tests/read_on_create.rb +33 -34
  72. data/tests/save_struct.rb +40 -39
  73. data/tests/unit/database.rb +1 -1
  74. data/tests/unit/model_tests.rb +73 -65
  75. metadata +71 -15
  76. data/tests/unit/model.rb +0 -36
@@ -1,3 +1,3 @@
1
1
  rvm: 1.9.2
2
2
  before_script:
3
- - "apt-get install libdb4.6-dev"
3
+ - "sudo apt-get install libdb4.8-dev"
@@ -1,6 +1,8 @@
1
1
  = ROD -- Ruby Object Database
2
2
 
3
- * http://github.com/apohllo/rod
3
+ * http://github.com/apohllo/rod - source code
4
+ * http://rubydoc.info/github/apohllo/rod/master/frames - API
5
+ * https://www.relishapp.com/apohllo/rod - Cucumber features
4
6
 
5
7
  == WARNING
6
8
 
@@ -15,22 +17,28 @@ fast access for data, which rarely changes.
15
17
 
16
18
  == FEATURES:
17
19
 
18
- * nice Ruby interface which mimicks Active Record
20
+ * object-oriented Ruby interface
19
21
  * Ruby-to-C on-the-fly translation based on mmap and RubyInline
20
22
  * optimized for (reading) speed
21
23
  * weak reference collections for easy memory reclaims
22
24
  * Berkeley DB hash index for the best index performance
25
+ * immediate updates of hash indices
23
26
  * compatibility check of library version
24
27
  * compatibility check of data model
25
- * autogeneration of model (based on the database metadata)
26
- * automatic model migrations (limitied to addition/removal of properties and indexes)
28
+ * auto-generation of model (based on the database meta-data)
29
+ * automatic model migrations (limited to addition/removal of properties and indexes)
27
30
  * full update of the database (removal of objects not available yet)
28
31
  * databases interlinking (via direct links or inverted indices)
32
+ * data portability between big and little-endian systems
33
+ * works on Linux and BSD
29
34
 
30
35
  == PROBLEMS
31
36
 
32
37
  * tested mostly on 64-bit systems
33
38
  * doesn't work on Windows
39
+ * concurrent writes not supported
40
+ * batch-only data input/update
41
+ * data removal not supported
34
42
 
35
43
  == SYNOPSIS:
36
44
 
@@ -71,7 +79,7 @@ number of disk reads was designed. The Ruby interface facilitates it's usage.
71
79
 
72
80
  == TROUBLESHOOTING
73
81
 
74
- If you get the following error during library usage:
82
+ If you get the following error:
75
83
 
76
84
  error: db.h: No such file or directory
77
85
 
@@ -79,6 +87,19 @@ then you don't have Berkeley DB installed or its header fiels are not available
79
87
  on the default path. Make sure that the library is installed and the headers
80
88
  are available.
81
89
 
90
+ If you get the following error:
91
+
92
+ .ruby: symbol lookup error: /home/vagrant/.ruby_inline/... undefined symbol: db_env_create
93
+
94
+ then you have to provide system-specific linker information. By default the library
95
+ is linked with '-ldb' linker flag. To change it you have to set up ROD_BDB_LINK_FLAGS
96
+ environment variable, e.g.
97
+
98
+ ROD_BDB_LINK_FLAGS='-ldb-4.8'
99
+ export ROD_BDB_LINK_FLAGS
100
+
101
+ This configuration option will select the libdb-4.8.so library.
102
+
82
103
  == BASIC USAGE:
83
104
 
84
105
  class MyDatabase < Rod::Database
@@ -107,7 +128,7 @@ are available.
107
128
  field :data, :string
108
129
  end
109
130
 
110
- MyDatabase.create_database("data")
131
+ MyDatabase.instance.create_database("data")
111
132
  user = User.new(:name => 'Fred',
112
133
  :surname => 'Smith',
113
134
  :age => 22)
@@ -127,9 +148,9 @@ are available.
127
148
  account.store
128
149
  file1.store
129
150
  file2.store
130
- MyDatabase.close_database
151
+ MyDatabase.instance.close_database
131
152
 
132
- MyDatabase.open_database("data")
153
+ MyDatabase.instance.open_database("data")
133
154
  User.each do |user|
134
155
  puts "Name: #{user.name} surname: #{user.surname}"
135
156
  puts "login: #{user.account.login} e-mail: #{user.account.email}"
@@ -170,11 +191,18 @@ Then be sure to write tests covering the added feature/fixed bug.
170
191
  Include the tests in Rakefile, run the tests and if everything is fine
171
192
  send me a pull request.
172
193
 
194
+ == BENCHMARKS:
195
+
196
+ There is a separate project available under http://github.com/apohllo/rod-benchmark
197
+ that shows how ROD behave compared to the other storage engines.
198
+ It should be noted that this benchmarks are biased towards the design goals
199
+ of ROD. So don't expect general purpose database tests.
200
+
173
201
  == LICENSE:
174
202
 
175
- (The MIT License)
203
+ (The MIT/X11 License)
176
204
 
177
- Copyright (c) 2008-2011 Aleksander Pohl
205
+ Copyright (c) 2008-2012 Aleksander Pohl
178
206
 
179
207
  Permission is hereby granted, free of charge, to any person obtaining
180
208
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -27,7 +27,7 @@ task :uninstall do
27
27
  sh "sudo gem uninstall #$gem_name"
28
28
  end
29
29
 
30
- task :all_tests => [:test,:regression_test,:spec] do
30
+ task :all_tests => [:test,:unit_test,:regression_test,:features] do
31
31
  end
32
32
 
33
33
  desc "Run performence tests"
@@ -37,7 +37,7 @@ task :perf do
37
37
  sh "ruby tests/full_runs.rb"
38
38
  end
39
39
 
40
- desc "Run tests and specs"
40
+ desc "Run multi-step tests"
41
41
  task :test do
42
42
  sh "ruby tests/save_struct.rb"
43
43
  sh "ruby tests/load_struct.rb"
@@ -47,17 +47,28 @@ task :test do
47
47
  sh "ruby tests/generate_classes_rewrite.rb"
48
48
  sh "ruby tests/generate_classes_rewrite.rb"
49
49
  sh "ruby tests/generate_classes_verify.rb"
50
- sh "ruby tests/migration_create.rb 1000"
51
- sh "ruby tests/migration_migrate.rb 1000"
52
- sh "ruby tests/migration_verify.rb 1000"
50
+ # TODO #206 fix index migration
51
+ #sh "ruby tests/migration_create.rb 1000"
52
+ #sh "ruby tests/migration_migrate.rb 1000"
53
+ #sh "ruby tests/migration_verify.rb 1000"
53
54
  sh "ruby tests/missing_class_create.rb"
54
55
  sh "ruby tests/missing_class_verify.rb"
55
56
  sh "ruby tests/properties_order_create.rb"
56
57
  sh "ruby tests/properties_order_verify.rb"
57
- sh "ruby tests/unit/model.rb"
58
+ end
59
+
60
+ desc "Run unit tests and model specs"
61
+ task :unit_test do
58
62
  sh "ruby tests/unit/model_tests.rb"
59
63
  sh "ruby tests/unit/database.rb"
60
64
  sh "ruby tests/unit/abstract_database.rb"
65
+ sh "ruby spec/property/base.rb"
66
+ sh "ruby spec/property/field.rb"
67
+ sh "ruby spec/property/singular_association.rb"
68
+ sh "ruby spec/property/plural_association.rb"
69
+ sh "ruby spec/berkeley/environment.rb"
70
+ sh "ruby spec/berkeley/database.rb"
71
+ sh "ruby spec/berkeley/transaction.rb"
61
72
  end
62
73
 
63
74
  # Should be removed some time -- specs should cover all these cases
@@ -66,12 +77,12 @@ task :regression_test do
66
77
  sh "ruby tests/check_strings.rb"
67
78
  end
68
79
 
69
- desc "Run all specs without the ignored ones"
70
- task :spec do
80
+ desc "Run all cucumber features without the ignored ones"
81
+ task :features do
71
82
  sh "bundle exec cucumber --tags ~@ignore features/*"
72
83
  end
73
84
 
74
- desc "Run only work-in-progress specs"
85
+ desc "Run only work-in-progress features"
75
86
  task :wip do
76
87
  sh "bundle exec cucumber --tags @wip features/*"
77
88
  end
@@ -1,3 +1,28 @@
1
+ 0.7.2
2
+ - Fix variable declaration place #118
3
+ - Implementation of & and | for collection proxies
4
+ - Fix strange error caused by mocha #219
5
+ - Change compile flags to link flags and API accordingly #200
6
+ - Fix memleak when growing DB file #211
7
+ - Change hash cache size to 0.5 MB
8
+ - Add flags needed on BSD #215
9
+ - Fix destroy of hash index #217 #218
10
+ - Immediate hash index updates #209 #213
11
+ - Add method for computing collections' intersection size #224
12
+ - Add hash index compile flags env. variable #223
13
+ - Add negative float values in basic feature
14
+ - #204 fix features for out-of-scope indexing
15
+ - Fix: too large values for 32-bit systems in tests
16
+ - Remove old unit tests
17
+ - Change directory of Berkeley env
18
+ - #199 spec and new implementation for Model#[]
19
+ - Change libdb to 4.8 in travis script
20
+ - Updated links and year, note about benchmarks
21
+ - Berkeley DB building blocks
22
+ - Update requires for latest Active Model
23
+ - Allow latest version of active model to be used
24
+ - Fix example in README
25
+ - #190 #98 #173 refactoring of properties
1
26
  0.7.1
2
27
  - #189 guard object load against empty strings.
3
28
  - Don't close hash index when it is destroyed.
@@ -1,3 +1,4 @@
1
1
  People who contributed to Ruby Object Database:
2
2
  * Piotr Gurgul
3
3
  * Marcin Sieniek
4
+ * Rafal Michalski
@@ -0,0 +1,58 @@
1
+ ---
2
+ Rod:
3
+ :version: 0.7.0
4
+ :created_at: 2012-04-30 10:49:34.260940 +02:00
5
+ :updated_at: 2012-04-30 10:49:34.281290 +02:00
6
+ Rod::JoinElement:
7
+ :superclass: Rod::AbstractModel
8
+ :count: 1
9
+ Rod::PolymorphicJoinElement:
10
+ :superclass: Rod::JoinElement
11
+ :count: 0
12
+ Rod::StringElement:
13
+ :superclass: Rod::AbstractModel
14
+ :count: 25
15
+ RodTest::Automobile:
16
+ :superclass: RodTest::TestModel
17
+ :fields:
18
+ :name:
19
+ :options:
20
+ :type: :string
21
+ :count: 1
22
+ RodTest::Caveman:
23
+ :superclass: RodTest::TestModel
24
+ :fields:
25
+ :name:
26
+ :options:
27
+ :type: :string
28
+ :age:
29
+ :options:
30
+ :type: :integer
31
+ :identifier:
32
+ :options:
33
+ :type: :ulong
34
+ :height:
35
+ :options:
36
+ :type: :float
37
+ :account_balance:
38
+ :options:
39
+ :type: :float
40
+ :has_one:
41
+ :automobile:
42
+ :options: {}
43
+
44
+ :has_many:
45
+ :dogs:
46
+ :options: {}
47
+
48
+ :count: 1
49
+ RodTest::Dog:
50
+ :superclass: RodTest::TestModel
51
+ :fields:
52
+ :nickname:
53
+ :options:
54
+ :type: :string
55
+ :count: 1
56
+ RodTest::TestModel:
57
+ :superclass: Rod::Model
58
+ :count: 0
Binary file
@@ -0,0 +1,49 @@
1
+ ---
2
+ Rod:
3
+ :version: 0.7.1
4
+ :created_at: 2012-05-02 01:00:18.322307 +02:00
5
+ :updated_at: 2012-05-02 01:00:18.380358 +02:00
6
+ Rod::JoinElement:
7
+ :superclass: Rod::AbstractModel
8
+ :count: 1
9
+ Rod::PolymorphicJoinElement:
10
+ :superclass: Rod::JoinElement
11
+ :count: 0
12
+ Rod::StringElement:
13
+ :superclass: Rod::AbstractModel
14
+ :count: 25
15
+ RodTest::Automobile:
16
+ :superclass: RodTest::TestModel
17
+ :fields:
18
+ :name:
19
+ :type: :string
20
+ :count: 1
21
+ RodTest::Caveman:
22
+ :superclass: RodTest::TestModel
23
+ :fields:
24
+ :name:
25
+ :type: :string
26
+ :age:
27
+ :type: :integer
28
+ :identifier:
29
+ :type: :ulong
30
+ :height:
31
+ :type: :float
32
+ :account_balance:
33
+ :type: :float
34
+ :has_one:
35
+ :automobile: {}
36
+
37
+ :has_many:
38
+ :dogs: {}
39
+
40
+ :count: 1
41
+ RodTest::Dog:
42
+ :superclass: RodTest::TestModel
43
+ :fields:
44
+ :nickname:
45
+ :type: :string
46
+ :count: 1
47
+ RodTest::TestModel:
48
+ :superclass: Rod::Model
49
+ :count: 0
@@ -0,0 +1,33 @@
1
+ Feature: Data backward compatiblity
2
+ The data scheme should be compatible between certain library versions.
3
+ Some of the scenarios might be ignored and run only directly to
4
+ indicate the incompatiblities.
5
+ Background:
6
+ Given the library works in development mode
7
+
8
+ @ignore
9
+ Scenario: compatiblity with version 0.7.0
10
+ To make the data compatible, the 'options' key should be removed from
11
+ the database.yml
12
+ Given the class space is cleared
13
+ And the model is connected with the default database
14
+ And a class Caveman has a name field of type string
15
+ And a class Caveman has an age field of type integer
16
+ And a class Caveman has an identifier field of type ulong
17
+ And a class Caveman has a height field of type float
18
+ And a class Caveman has a account_balance field of type float
19
+ And a class Automobile has a name field of type string
20
+ And a class Caveman has one automobile
21
+ And a class Dog has a nickname field of type string
22
+ And a class Caveman has many dogs
23
+ When I open the database for reading in data/backward/0.7.0
24
+ Then there should be 1 Caveman
25
+ And there should be 1 Dog
26
+ And there should be 1 Automobile
27
+ And the name of the first Caveman should be 'Fred'
28
+ And the age of the first Caveman should be '25'
29
+ And the identifier of the first Caveman should be '111222333'
30
+ And the height of the first Caveman should be '1.86'
31
+ And the account_balance of the first Caveman should be '-0.00000001'
32
+ And the automobile of the first Caveman should be equal to the first Automobile persisted
33
+ And the first of dogs of the first Caveman should be equal to the first Dog persisted
@@ -38,6 +38,7 @@ Feature: Store and load small amount of data from one class
38
38
  And a class Caveman has an age field of type integer
39
39
  And a class Caveman has an identifier field of type ulong
40
40
  And a class Caveman has a height field of type float
41
+ And a class Caveman has a account_balance field of type float
41
42
  And a class Caveman has a symbol field of type object
42
43
  And a class Caveman has a empty_string field of type string
43
44
  And a class Caveman has a empty_object field of type object
@@ -47,6 +48,7 @@ Feature: Store and load small amount of data from one class
47
48
  And his age is '25'
48
49
  And his identifier is '111222333'
49
50
  And his height is '1.86'
51
+ And his account_balance is '-0.00000001'
50
52
  And his symbol is ':fred'
51
53
  # nil is converted to an empty string, consider using object field
52
54
  # if you wish to store nil for string fields
@@ -61,6 +63,7 @@ Feature: Store and load small amount of data from one class
61
63
  And the age of the first Caveman should be '25'
62
64
  And the identifier of the first Caveman should be '111222333'
63
65
  And the height of the first Caveman should be '1.86'
66
+ And the account_balance of the first Caveman should be '-0.00000001'
64
67
  And the symbol of the first Caveman should be ':fred'
65
68
  And the empty_string of the first Caveman should be ''
66
69
  And the empty_object of the first Caveman should be nil
@@ -143,3 +143,98 @@ Feature: collection proxy specification
143
143
  Given the initial size of the collection proxy is 5
144
144
  # Can't figure out anything better.
145
145
  Then an exception should be raised when the collection is modified during iteration
146
+
147
+ Scenario: fast intersection computing
148
+ Given the class space is cleared
149
+ And the model is connected with the default database
150
+ And a class Caveman has a name field of type string
151
+ And a class Automobile has a name field of type string
152
+ And a class Caveman has many automobiles
153
+ When the database is created
154
+ And I create an Automobile
155
+ And its name is 'Car 1'
156
+ And I store it in the database
157
+ And I create another Automobile
158
+ And its name is 'Car 2'
159
+ And I store it in the database
160
+ And I create another Automobile
161
+ And its name is 'Car 3'
162
+ And I store it in the database
163
+ And I create another Automobile
164
+ And its name is 'Car 4'
165
+ And I store it in the database
166
+ And I create another Automobile
167
+ And its name is 'Car 5'
168
+ And I store it in the database
169
+ And I create another Automobile
170
+ And its name is 'Car 6'
171
+ And I store it in the database
172
+ And I create another Automobile
173
+ And its name is 'Car 7'
174
+ And I store it in the database
175
+ And I create a Caveman
176
+ And his name is 'Fred'
177
+ # The automobiles have to be in the creation order, since this is assumed by the
178
+ # fast intersection computation routine.
179
+ And his automobiles contain the first Automobile created
180
+ And his automobiles contain the second Automobile created
181
+ And his automobiles contain the third Automobile created
182
+ And his automobiles contain the fourth Automobile created
183
+ And I store him in the database
184
+ And I create another Caveman
185
+ And his name is 'Bill'
186
+ And his automobiles contain the third Automobile created
187
+ And his automobiles contain the fourth Automobile created
188
+ And his automobiles contain the fifth Automobile created
189
+ And his automobiles contain the sixth Automobile created
190
+ And his automobiles contain the seventh Automobile created
191
+ And I store him in the database
192
+ And I reopen database for reading
193
+ Then there should be 2 Caveman(s)
194
+ And there should be 7 Automobile(s)
195
+ And the first Caveman should have 4 automobiles
196
+ And the second Caveman should have 5 automobiles
197
+ And the intersection size of automobiles of the first and the second Caveman should equal 2
198
+
199
+ When the database is created
200
+ And I create an Automobile
201
+ And its name is 'Car 1'
202
+ And I store it in the database
203
+ And I create another Automobile
204
+ And its name is 'Car 2'
205
+ And I store it in the database
206
+ And I create another Automobile
207
+ And its name is 'Car 3'
208
+ And I store it in the database
209
+ And I create another Automobile
210
+ And its name is 'Car 4'
211
+ And I store it in the database
212
+ And I create another Automobile
213
+ And its name is 'Car 5'
214
+ And I store it in the database
215
+ And I create another Automobile
216
+ And its name is 'Car 6'
217
+ And I store it in the database
218
+ And I create another Automobile
219
+ And its name is 'Car 7'
220
+ And I store it in the database
221
+ And I create a Caveman
222
+ And his name is 'Fred'
223
+ And his automobiles contain the first Automobile created
224
+ And his automobiles contain the fifth Automobile created
225
+ And his automobiles contain the sixth Automobile created
226
+ And his automobiles contain the seventh Automobile created
227
+ And I store him in the database
228
+ And I create another Caveman
229
+ And his name is 'Bill'
230
+ And his automobiles contain the first Automobile created
231
+ And his automobiles contain the second Automobile created
232
+ And his automobiles contain the third Automobile created
233
+ And his automobiles contain the sixth Automobile created
234
+ And I store him in the database
235
+ And I reopen database for reading
236
+ Then there should be 2 Caveman(s)
237
+ And there should be 7 Automobile(s)
238
+ And the first Caveman should have 4 automobiles
239
+ And the second Caveman should have 4 automobiles
240
+ And the intersection size of automobiles of the first and the second Caveman should equal 2