rod 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.travis.yml +1 -0
  2. data/README.rdoc +10 -9
  3. data/Rakefile +15 -5
  4. data/changelog.txt +18 -0
  5. data/features/append.feature +0 -2
  6. data/features/basic.feature +7 -7
  7. data/features/collection_proxy.feature +140 -0
  8. data/features/flat_indexing.feature +9 -8
  9. data/features/{fred.feature → persistence.feature} +5 -8
  10. data/features/{assoc_indexing.feature → relationship_indexing.feature} +36 -0
  11. data/features/segmented_indexing.feature +6 -6
  12. data/features/steps/collection_proxy.rb +89 -0
  13. data/features/steps/model.rb +15 -3
  14. data/features/steps/rod.rb +1 -1
  15. data/features/support/mocha.rb +16 -0
  16. data/features/update.feature +263 -0
  17. data/lib/rod.rb +10 -2
  18. data/lib/rod/abstract_database.rb +49 -111
  19. data/lib/rod/abstract_model.rb +26 -6
  20. data/lib/rod/collection_proxy.rb +235 -34
  21. data/lib/rod/constants.rb +1 -1
  22. data/lib/rod/database.rb +5 -6
  23. data/lib/rod/exception.rb +1 -1
  24. data/lib/rod/index/base.rb +97 -0
  25. data/lib/rod/index/flat_index.rb +72 -0
  26. data/lib/rod/index/segmented_index.rb +100 -0
  27. data/lib/rod/model.rb +172 -185
  28. data/lib/rod/reference_updater.rb +85 -0
  29. data/lib/rod/utils.rb +29 -0
  30. data/rod.gemspec +4 -1
  31. data/tests/migration_create.rb +33 -12
  32. data/tests/migration_migrate.rb +24 -7
  33. data/tests/migration_model1.rb +5 -0
  34. data/tests/migration_model2.rb +36 -0
  35. data/tests/migration_verify.rb +49 -42
  36. data/tests/missing_class_create.rb +21 -0
  37. data/tests/missing_class_verify.rb +20 -0
  38. data/tests/properties_order_create.rb +16 -0
  39. data/tests/properties_order_verify.rb +17 -0
  40. data/tests/unit/abstract_database.rb +13 -0
  41. data/tests/unit/model_tests.rb +3 -3
  42. data/utils/convert_index.rb +1 -1
  43. metadata +62 -18
  44. data/lib/rod/segmented_index.rb +0 -85
@@ -0,0 +1 @@
1
+ rvm: 1.9.2
@@ -18,7 +18,7 @@ fast access for data, which rarely changes.
18
18
  * compatibility check of data model
19
19
  * autogeneration of model (based on the database metadata)
20
20
  * automatic model migrations (addition/removal of properties so far)
21
- * append of the database (new objects, new elements in plural associations)
21
+ * full update of the database (removal of objects not available yet)
22
22
  * databases interlinking (via direct links or inverted indices)
23
23
 
24
24
  == PROBLEMS
@@ -39,9 +39,9 @@ The primary reason for designing it was to create storage facility for
39
39
  natural language dictionaries and corpora. The data in a fully fledged dictionary
40
40
  is interconnected in many ways, thus the relational model (joins) introduces
41
41
  unacceptable performance hit. The size of corpora forces them to be kept
42
- on disks. The in-memory data bases are unacceptable for larg corpora and
43
- would require the data to be kept mostly in the operational memory,
44
- which is not needed, while accessing dictionaries (in most cases only a fraction
42
+ on disks. The in-memory data bases are unacceptable for larg corpora.
43
+ They would also require the data of a dictionary to be kept mostly in the
44
+ operational memory, which is not needed (in most cases only a fraction
45
45
  of the data is used at the same time). That's why a storage facility which minimizes the
46
46
  number of disk reads was designed. The Ruby interface facilitates it's usage.
47
47
 
@@ -51,6 +51,7 @@ number of disk reads was designed. The Ruby interface facilitates it's usage.
51
51
  * RubyInline
52
52
  * english
53
53
  * ActiveModel
54
+ * bsearch
54
55
 
55
56
  == INSTALL
56
57
 
@@ -69,7 +70,7 @@ Grab from rubygems:
69
70
 
70
71
  class User < Model
71
72
  field :name, :string
72
- field :surname, :string, :index => true
73
+ field :surname, :string, :index => :flat
73
74
  field :age, :integer
74
75
  has_one :account
75
76
  has_many :files
@@ -77,12 +78,12 @@ Grab from rubygems:
77
78
 
78
79
  class Account < Model
79
80
  field :email, :string
80
- field :login, :string, :index => true
81
+ field :login, :string, :index => :flat
81
82
  field :password, :string
82
83
  end
83
84
 
84
85
  class File < Model
85
- field :title, :string, :index => true
86
+ field :title, :string, :index => :flat
86
87
  field :data, :string
87
88
  end
88
89
 
@@ -113,7 +114,7 @@ Grab from rubygems:
113
114
  puts "Name: #{user.name} surname: #{user.surname}"
114
115
  puts "login: #{user.account.login} e-mail: #{user.account.email}"
115
116
  user.files.each do |file|
116
- puts "File: #{file.title}
117
+ puts "File: #{file.title}"
117
118
  end
118
119
  end
119
120
 
@@ -130,7 +131,7 @@ You'll need bundler installed:
130
131
 
131
132
  Then you have to fetch all the dependencies:
132
133
 
133
- bunlde
134
+ bundle
134
135
 
135
136
  To run all the test simple type rake:
136
137
 
data/Rakefile CHANGED
@@ -47,12 +47,17 @@ 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"
51
- sh "ruby tests/migration_migrate.rb"
52
- sh "ruby tests/migration_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"
53
+ sh "ruby tests/missing_class_create.rb"
54
+ sh "ruby tests/missing_class_verify.rb"
55
+ sh "ruby tests/properties_order_create.rb"
56
+ sh "ruby tests/properties_order_verify.rb"
53
57
  sh "ruby tests/unit/model.rb"
54
58
  sh "ruby tests/unit/model_tests.rb"
55
59
  sh "ruby tests/unit/database.rb"
60
+ sh "ruby tests/unit/abstract_database.rb"
56
61
  end
57
62
 
58
63
  # Should be removed some time -- specs should cover all these cases
@@ -61,17 +66,22 @@ task :regression_test do
61
66
  sh "ruby tests/check_strings.rb"
62
67
  end
63
68
 
69
+ desc "Run all specs without the ignored ones"
64
70
  task :spec do
65
71
  sh "bundle exec cucumber --tags ~@ignore features/*"
66
72
  end
67
73
 
68
- # Work in progress
74
+ desc "Run only work-in-progress specs"
69
75
  task :wip do
70
76
  sh "bundle exec cucumber --tags @wip features/*"
71
77
  end
72
78
 
73
- desc "Clean"
79
+ desc "Clean all gems"
74
80
  task :clean do
75
81
  sh "rm #$gem_name*.gem"
76
82
  end
77
83
 
84
+ desc "Show changelog from the last release"
85
+ task :changelog do
86
+ sh "git log v#{Rod::VERSION}.. --pretty=%s | tee"
87
+ end
@@ -1,3 +1,21 @@
1
+ 0.6.3
2
+ - #94 indexing of unstored object in plural assoc
3
+ - #128 incompatible schema message is more specific
4
+ - #129 check properties order
5
+ - #131 check for missing classes
6
+ - #72 update of objects' state
7
+ - #117 get rid of signed/unsigned comparison warning
8
+ - #135 refactoring of indexes
9
+ - #140 remove key argument from AbstractDatabase#read_index
10
+ - #149 CollectionProxy insert, delete, delete_at
11
+ - #154 fix configuration of mocha for cucumber
12
+ - #153 fix: field values doesn't match
13
+ - #153 111122223333 is too big for ulong on 32bit systems
14
+ - #18 use latest RubyInline and fix 'require on ... failed'
15
+ - #152 travis-ci configuration: ruby 1.9.2
16
+ - #151 missing rake dependency
17
+ - #130 fix: canonicalize path
18
+ - #124 implement empty? for CollectionProxy
1
19
  0.6.2
2
20
  - #127 default implementation of inspect
3
21
  - #123 fix: warning on has_rdoc in gemspec
@@ -183,8 +183,6 @@ Feature: database with append
183
183
  And there should be 1 Caveman with the first Automobile as automobiles
184
184
  And there should be 1 Caveman with the second Automobile as automobiles
185
185
 
186
- # Enable for #94
187
- @ignore
188
186
  Scenario: append of has many associations with indexing with an unstored object
189
187
  Same as above, but with an object which is appended to the collection
190
188
  while it is not yet stored in the DB.
@@ -45,7 +45,7 @@ Feature: Store and load small amount of data from one class
45
45
  And I create a Caveman
46
46
  And his name is 'Fred'
47
47
  And his age is '25'
48
- And his identifier is '111122223333'
48
+ And his identifier is '111222333'
49
49
  And his height is '1.86'
50
50
  And his symbol is ':fred'
51
51
  # nil is converted to an empty string, consider using object field
@@ -59,7 +59,7 @@ Feature: Store and load small amount of data from one class
59
59
  Then there should be 1 Caveman
60
60
  And the name of the first Caveman should be 'Fred'
61
61
  And the age of the first Caveman should be '25'
62
- And the identifier of the first Caveman should be '111122223333'
62
+ And the identifier of the first Caveman should be '111222333'
63
63
  And the height of the first Caveman should be '1.86'
64
64
  And the symbol of the first Caveman should be ':fred'
65
65
  And the empty_string of the first Caveman should be ''
@@ -100,11 +100,11 @@ Feature: Store and load small amount of data from one class
100
100
  And I create a Caveman
101
101
  And his name is 'Fred'
102
102
  And his age is '25'
103
- And his identifier is '111122223333'
103
+ And his identifier is '111222333'
104
104
  And his height is '1.86'
105
105
  Then his name should be 'Fred'
106
106
  And his age should be '25'
107
- And his identifier should be '111122223333'
107
+ And his identifier should be '111222333'
108
108
  And his height should be '1.86'
109
109
 
110
110
  When database is created
@@ -134,9 +134,9 @@ Feature: Store and load small amount of data from one class
134
134
  And I create a Caveman
135
135
  And I fetch the first Caveman created
136
136
  Then his name should be ''
137
- And his age should be nil
138
- And his identifier should be nil
139
- And his height should be nil
137
+ And his age should be '0'
138
+ And his identifier should be '0'
139
+ And his height should be '0'
140
140
  And his symbol should be nil
141
141
  And his item should be nil
142
142
  And his items should be empty
@@ -0,0 +1,140 @@
1
+ Feature: collection proxy specification
2
+
3
+ Scenario: appending items
4
+ Given the initial size of the collection proxy is 10
5
+ When I append a new item 10 times
6
+ Then the size of the collection proxy should be 20
7
+ And the collection proxy should behave like an array
8
+
9
+ When I append a new item 10 times
10
+ Then the size of the collection proxy should be 30
11
+ And the collection proxy should behave like an array
12
+
13
+ Scenario: inserting items
14
+ Given the initial size of the collection proxy is 10
15
+ When I insert a new item at position 0
16
+ Then the size of the collection proxy should be 11
17
+ And the collection proxy should behave like an array
18
+ When I insert a new item at position 11
19
+ Then the size of the collection proxy should be 12
20
+ And the collection proxy should behave like an array
21
+ When I insert a new item at position 5
22
+ Then the size of the collection proxy should be 13
23
+ And the collection proxy should behave like an array
24
+ When I insert an item with rod_id = 1 at position 5 3 times
25
+ Then the size of the collection proxy should be 16
26
+ And the collection proxy should behave like an array
27
+
28
+ Scenario: deleting items
29
+ Given the initial size of the collection proxy is 5
30
+ When I delete an item at position 0 2 times
31
+ Then the size of the collection proxy should be 3
32
+ And the collection proxy should behave like an array
33
+ When I delete an item with rod_id = 3
34
+ Then the size of the collection proxy should be 2
35
+ And the collection proxy should behave like an array
36
+ When I delete an item with rod_id = 3
37
+ Then the size of the collection proxy should be 2
38
+ And the collection proxy should behave like an array
39
+ When I delete an item with rod_id = 4
40
+ Then the size of the collection proxy should be 1
41
+ And the collection proxy should behave like an array
42
+ When I delete an item at position 1
43
+ Then the size of the collection proxy should be 1
44
+ And the collection proxy should behave like an array
45
+ When I delete an item at position 0
46
+ Then the collection proxy should be empty
47
+ And the collection proxy should behave like an array
48
+
49
+ Scenario: deleting and inserting items
50
+ Given the initial size of the collection proxy is 5
51
+ When I delete an item with rod_id = 1
52
+ Then the size of the collection proxy should be 4
53
+ And the collection proxy should behave like an array
54
+ When I insert a new item at position 0
55
+ Then the size of the collection proxy should be 5
56
+ And the collection proxy should behave like an array
57
+ When I insert an item with rod_id = 6 at position 1
58
+ Then the size of the collection proxy should be 6
59
+ And the collection proxy should behave like an array
60
+ When I delete an item at position 2
61
+ Then the size of the collection proxy should be 5
62
+ And the collection proxy should behave like an array
63
+ When I insert a new item at position 2
64
+ Then the size of the collection proxy should be 6
65
+ And the collection proxy should behave like an array
66
+ When I delete an item with rod_id = 6
67
+ Then the size of the collection proxy should be 4
68
+ And the collection proxy should behave like an array
69
+ When I delete an item at position 1
70
+ Then the size of the collection proxy should be 3
71
+ And the collection proxy should behave like an array
72
+ When I delete an item at position 0
73
+ Then the size of the collection proxy should be 2
74
+ And the collection proxy should behave like an array
75
+ When I delete an item at position 0
76
+ Then the size of the collection proxy should be 1
77
+ And the collection proxy should behave like an array
78
+ When I delete an item at position 0
79
+ Then the size of the collection proxy should be 0
80
+ And the collection proxy should behave like an array
81
+ When I insert a new item at position 0
82
+ Then the size of the collection proxy should be 1
83
+ And the collection proxy should behave like an array
84
+
85
+ Scenario: deleting and appending items
86
+ Given the initial size of the collection proxy is 5
87
+ When I append a new item 5 times
88
+ Then the size of the collection proxy should be 10
89
+ And the collection proxy should behave like an array
90
+ When I delete an item at position 0
91
+ Then the size of the collection proxy should be 9
92
+ And the collection proxy should behave like an array
93
+ When I delete an item with rod_id = 6
94
+ Then the size of the collection proxy should be 8
95
+ And the collection proxy should behave like an array
96
+ When I append a new item
97
+ Then the size of the collection proxy should be 9
98
+ And the collection proxy should behave like an array
99
+
100
+ Scenario: inserting, deleting and appending items
101
+ Given the initial size of the collection proxy is 5
102
+ When I append a new item 5 times
103
+ Then the size of the collection proxy should be 10
104
+ And the collection proxy should behave like an array
105
+ When I insert a new item at position 2 3 times
106
+ Then the size of the collection proxy should be 13
107
+ And the collection proxy should behave like an array
108
+ When I insert an item with rod_id = 6 at position 12
109
+ Then the size of the collection proxy should be 14
110
+ And the collection proxy should behave like an array
111
+ When I insert a new item at position 0
112
+ Then the size of the collection proxy should be 15
113
+ And the collection proxy should behave like an array
114
+ When I delete an item with rod_id = 1
115
+ Then the size of the collection proxy should be 14
116
+ And the collection proxy should behave like an array
117
+ When I delete an item with rod_id = 6
118
+ Then the size of the collection proxy should be 12
119
+ And the collection proxy should behave like an array
120
+ When I delete an item with rod_id = 6
121
+ Then the size of the collection proxy should be 12
122
+ And the collection proxy should behave like an array
123
+ When I delete an item at position 5 2 times
124
+ Then the size of the collection proxy should be 10
125
+ And the collection proxy should behave like an array
126
+ When I insert a new item at position 0 5 times
127
+ Then the size of the collection proxy should be 15
128
+ And the collection proxy should behave like an array
129
+ When I delete an item at position 10 5 times
130
+ Then the size of the collection proxy should be 10
131
+ And the collection proxy should behave like an array
132
+ When I append a new item 5 times
133
+ Then the size of the collection proxy should be 15
134
+ And the collection proxy should behave like an array
135
+ When I delete an item at position 5 15 times
136
+ Then the size of the collection proxy should be 5
137
+ And the collection proxy should behave like an array
138
+ When I delete an item at position 0 5 times
139
+ Then the collection proxy should be empty
140
+ And the collection proxy should behave like an array
@@ -17,19 +17,19 @@ Feature: Access to objects with indexed fields
17
17
  And I create a Caveman
18
18
  And his name is 'Fred'
19
19
  And his age is '25'
20
- And his identifier is '111122223333'
20
+ And his identifier is '111222333'
21
21
  And his height is '1.86'
22
22
  And I store him in the database
23
23
  And I create another Caveman
24
24
  And his name is 'Barney'
25
25
  And his age is '26'
26
- And his identifier is '111122224444'
26
+ And his identifier is '111222444'
27
27
  And his height is '1.67'
28
28
  And I store him in the database
29
29
  And I create another Caveman
30
30
  And his name is 'Wilma'
31
31
  And his age is '25'
32
- And his identifier is '111122225555'
32
+ And his identifier is '111222555'
33
33
  And his height is '1.67'
34
34
  And I store him in the database
35
35
  And I reopen database for reading
@@ -39,9 +39,9 @@ Feature: Access to objects with indexed fields
39
39
  And there should be 1 Caveman with 'Barney' name
40
40
  And there should be 2 Caveman(s) with '25' age
41
41
  And there should be 1 Caveman with '26' age
42
- And there should be 1 Caveman with '111122223333' identifier
43
- And there should be 1 Caveman with '111122224444' identifier
44
- And there should be 1 Caveman with '111122225555' identifier
42
+ And there should be 1 Caveman with '111222333' identifier
43
+ And there should be 1 Caveman with '111222444' identifier
44
+ And there should be 1 Caveman with '111222555' identifier
45
45
  And there should be 2 Caveman(s) with '1.67' height
46
46
  And there should be 1 Caveman with '1.86' height
47
47
 
@@ -92,13 +92,14 @@ Feature: Access to objects with indexed fields
92
92
  | Adam | Parker | adam | 12 |
93
93
  | Adam | | noob1 | 33 |
94
94
  | | | noob2 | -1 |
95
+ | | Adam | noob1 | 33 |
95
96
  And I reopen database for reading
96
- Then there should be 5 Caveman(s)
97
+ Then there should be 6 Caveman(s)
97
98
  And there should be 1 Caveman with 'John' name
98
99
  And there should be 2 Caveman(s) with 'Adam' name
99
100
  And there should be 2 Caveman(s) with '12' age
100
101
  And there should be 1 Caveman with '-1' age
101
- And there should be 1 Caveman with '' name
102
+ And there should be 2 Caveman with '' name
102
103
  And there should be 2 Caveman(s) with '' surname
103
104
 
104
105
  Scenario: multiple object with indexed fields
@@ -1,7 +1,5 @@
1
- Feature: ROD Storage
2
- In order to persist data
3
- Potential users
4
- Must be able to store and load their objects.
1
+ Feature: Persistence model
2
+ This feature defines the persistence model of ROD.
5
3
  Background:
6
4
  Given the library works in development mode
7
5
  And the class space is cleared
@@ -9,10 +7,9 @@ Feature: ROD Storage
9
7
  And a class Fred has an age field of type integer
10
8
  And a class Fred has a sex field of type string with flat index
11
9
 
12
- Scenario Outline: Store Fred and modify his age
13
- So far Rod doesn't support changing of objects (especially
14
- plural associations). To keep the behavior consisten for
15
- all types of data, fields shouldn't be modifiable as well.
10
+ Scenario Outline: Persistence of unstored changes
11
+ If there are any changes made to the object after it has
12
+ been persisted, they are lost when the database is closed.
16
13
  When database is created
17
14
  And I create a Fred
18
15
  And his age is '<init_age>'
@@ -64,3 +64,39 @@ Feature: Access to objects with indexed associations
64
64
  And there should exist a Caveman with the second Automobile as automobiles
65
65
  And there should be 1 Caveman with the first Automobile as automobiles
66
66
  And there should be 1 Caveman with the second Automobile as automobiles
67
+
68
+ Scenario: indexing of plural associations with fresh objects
69
+ Given the class space is cleared
70
+ And the model is connected with the default database
71
+ And a class Automobile has a name field of type string
72
+ And a class Caveman has a name field of type string
73
+ And a class Caveman has many automobiles with flat index
74
+ When database is created
75
+ And I create an Automobile
76
+ And its name is 'Prehistoric car'
77
+ And I create another Automobile
78
+ And its name is 'Modern car'
79
+ And I create a Caveman
80
+ And his name is 'Fred'
81
+ And his automobiles contain the first Automobile created
82
+ And his automobiles contain the second Automobile created
83
+ And I store him in the database
84
+ And I create another Caveman
85
+ And his name is 'Allen'
86
+ And his automobiles contain the second Automobile created
87
+ And I store him in the database
88
+ And I fetch the first Automobile created
89
+ And I store it in the database
90
+ And I fetch the second Automobile created
91
+ And I store it in the database
92
+ And I create another Caveman
93
+ And her name is 'Linda'
94
+ And her automobiles contain the first Automobile created
95
+ And I store her in the database
96
+ And I reopen database for reading
97
+ Then there should be 3 Caveman(s)
98
+ And there should be 2 Automobile(s)
99
+ And there should exist a Caveman with the first Automobile as automobiles
100
+ And there should exist a Caveman with the second Automobile as automobiles
101
+ And there should be 2 Caveman(s) with the first Automobile as automobiles
102
+ And there should be 2 Caveman(s) with the second Automobile as automobiles