dm-core 0.9.11 → 0.10.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.
Files changed (194) hide show
  1. data/.autotest +17 -14
  2. data/.gitignore +3 -1
  3. data/FAQ +6 -5
  4. data/History.txt +5 -50
  5. data/Manifest.txt +66 -76
  6. data/QUICKLINKS +1 -1
  7. data/README.txt +21 -15
  8. data/Rakefile +6 -7
  9. data/SPECS +2 -29
  10. data/TODO +1 -1
  11. data/deps.rip +2 -0
  12. data/dm-core.gemspec +11 -15
  13. data/lib/dm-core.rb +105 -110
  14. data/lib/dm-core/adapters.rb +135 -16
  15. data/lib/dm-core/adapters/abstract_adapter.rb +251 -181
  16. data/lib/dm-core/adapters/data_objects_adapter.rb +482 -534
  17. data/lib/dm-core/adapters/in_memory_adapter.rb +90 -69
  18. data/lib/dm-core/adapters/mysql_adapter.rb +22 -115
  19. data/lib/dm-core/adapters/oracle_adapter.rb +249 -0
  20. data/lib/dm-core/adapters/postgres_adapter.rb +7 -173
  21. data/lib/dm-core/adapters/sqlite3_adapter.rb +4 -97
  22. data/lib/dm-core/adapters/yaml_adapter.rb +116 -0
  23. data/lib/dm-core/associations/many_to_many.rb +372 -90
  24. data/lib/dm-core/associations/many_to_one.rb +220 -73
  25. data/lib/dm-core/associations/one_to_many.rb +319 -255
  26. data/lib/dm-core/associations/one_to_one.rb +66 -53
  27. data/lib/dm-core/associations/relationship.rb +561 -156
  28. data/lib/dm-core/collection.rb +1101 -379
  29. data/lib/dm-core/core_ext/kernel.rb +12 -0
  30. data/lib/dm-core/core_ext/symbol.rb +10 -0
  31. data/lib/dm-core/identity_map.rb +4 -34
  32. data/lib/dm-core/migrations.rb +1283 -0
  33. data/lib/dm-core/model.rb +570 -369
  34. data/lib/dm-core/model/descendant_set.rb +81 -0
  35. data/lib/dm-core/model/hook.rb +45 -0
  36. data/lib/dm-core/model/is.rb +32 -0
  37. data/lib/dm-core/model/property.rb +247 -0
  38. data/lib/dm-core/model/relationship.rb +335 -0
  39. data/lib/dm-core/model/scope.rb +90 -0
  40. data/lib/dm-core/property.rb +808 -273
  41. data/lib/dm-core/property_set.rb +141 -98
  42. data/lib/dm-core/query.rb +1037 -483
  43. data/lib/dm-core/query/conditions/comparison.rb +872 -0
  44. data/lib/dm-core/query/conditions/operation.rb +221 -0
  45. data/lib/dm-core/query/direction.rb +43 -0
  46. data/lib/dm-core/query/operator.rb +84 -0
  47. data/lib/dm-core/query/path.rb +138 -0
  48. data/lib/dm-core/query/sort.rb +45 -0
  49. data/lib/dm-core/repository.rb +210 -94
  50. data/lib/dm-core/resource.rb +641 -421
  51. data/lib/dm-core/spec/adapter_shared_spec.rb +294 -0
  52. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +106 -0
  53. data/lib/dm-core/support/chainable.rb +22 -0
  54. data/lib/dm-core/support/deprecate.rb +12 -0
  55. data/lib/dm-core/support/logger.rb +13 -0
  56. data/lib/dm-core/{naming_conventions.rb → support/naming_conventions.rb} +6 -6
  57. data/lib/dm-core/transaction.rb +333 -92
  58. data/lib/dm-core/type.rb +98 -60
  59. data/lib/dm-core/types/boolean.rb +1 -1
  60. data/lib/dm-core/types/discriminator.rb +34 -20
  61. data/lib/dm-core/types/object.rb +7 -4
  62. data/lib/dm-core/types/paranoid_boolean.rb +11 -9
  63. data/lib/dm-core/types/paranoid_datetime.rb +11 -9
  64. data/lib/dm-core/types/serial.rb +3 -3
  65. data/lib/dm-core/types/text.rb +3 -4
  66. data/lib/dm-core/version.rb +1 -1
  67. data/script/performance.rb +102 -109
  68. data/script/profile.rb +169 -38
  69. data/spec/lib/adapter_helpers.rb +105 -0
  70. data/spec/lib/collection_helpers.rb +18 -0
  71. data/spec/lib/counter_adapter.rb +34 -0
  72. data/spec/lib/pending_helpers.rb +27 -0
  73. data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
  74. data/spec/public/associations/many_to_many_spec.rb +193 -0
  75. data/spec/public/associations/many_to_one_spec.rb +73 -0
  76. data/spec/public/associations/one_to_many_spec.rb +77 -0
  77. data/spec/public/associations/one_to_one_spec.rb +156 -0
  78. data/spec/public/collection_spec.rb +65 -0
  79. data/spec/public/migrations_spec.rb +359 -0
  80. data/spec/public/model/relationship_spec.rb +924 -0
  81. data/spec/public/model_spec.rb +159 -0
  82. data/spec/public/property_spec.rb +829 -0
  83. data/spec/public/resource_spec.rb +71 -0
  84. data/spec/public/sel_spec.rb +44 -0
  85. data/spec/public/setup_spec.rb +145 -0
  86. data/spec/public/shared/association_collection_shared_spec.rb +317 -0
  87. data/spec/public/shared/collection_shared_spec.rb +1670 -0
  88. data/spec/public/shared/finder_shared_spec.rb +1619 -0
  89. data/spec/public/shared/resource_shared_spec.rb +924 -0
  90. data/spec/public/shared/sel_shared_spec.rb +112 -0
  91. data/spec/public/transaction_spec.rb +129 -0
  92. data/spec/public/types/discriminator_spec.rb +130 -0
  93. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  94. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
  95. data/spec/semipublic/adapters/mysql_adapter_spec.rb +17 -0
  96. data/spec/semipublic/adapters/oracle_adapter_spec.rb +194 -0
  97. data/spec/semipublic/adapters/postgres_adapter_spec.rb +17 -0
  98. data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +17 -0
  99. data/spec/semipublic/adapters/yaml_adapter_spec.rb +12 -0
  100. data/spec/semipublic/associations/many_to_one_spec.rb +53 -0
  101. data/spec/semipublic/associations/relationship_spec.rb +194 -0
  102. data/spec/semipublic/associations_spec.rb +177 -0
  103. data/spec/semipublic/collection_spec.rb +142 -0
  104. data/spec/semipublic/property_spec.rb +61 -0
  105. data/spec/semipublic/query/conditions_spec.rb +528 -0
  106. data/spec/semipublic/query/path_spec.rb +443 -0
  107. data/spec/semipublic/query_spec.rb +2626 -0
  108. data/spec/semipublic/resource_spec.rb +47 -0
  109. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  110. data/spec/semipublic/shared/resource_shared_spec.rb +126 -0
  111. data/spec/spec.opts +3 -1
  112. data/spec/spec_helper.rb +80 -57
  113. data/tasks/ci.rb +19 -31
  114. data/tasks/dm.rb +43 -48
  115. data/tasks/doc.rb +8 -11
  116. data/tasks/gemspec.rb +5 -5
  117. data/tasks/hoe.rb +15 -16
  118. data/tasks/install.rb +8 -10
  119. metadata +74 -111
  120. data/lib/dm-core/associations.rb +0 -207
  121. data/lib/dm-core/associations/relationship_chain.rb +0 -81
  122. data/lib/dm-core/auto_migrations.rb +0 -105
  123. data/lib/dm-core/dependency_queue.rb +0 -32
  124. data/lib/dm-core/hook.rb +0 -11
  125. data/lib/dm-core/is.rb +0 -16
  126. data/lib/dm-core/logger.rb +0 -232
  127. data/lib/dm-core/migrations/destructive_migrations.rb +0 -17
  128. data/lib/dm-core/migrator.rb +0 -29
  129. data/lib/dm-core/scope.rb +0 -58
  130. data/lib/dm-core/support.rb +0 -7
  131. data/lib/dm-core/support/array.rb +0 -13
  132. data/lib/dm-core/support/assertions.rb +0 -8
  133. data/lib/dm-core/support/errors.rb +0 -23
  134. data/lib/dm-core/support/kernel.rb +0 -11
  135. data/lib/dm-core/support/symbol.rb +0 -41
  136. data/lib/dm-core/type_map.rb +0 -80
  137. data/lib/dm-core/types.rb +0 -19
  138. data/script/all +0 -4
  139. data/spec/integration/association_spec.rb +0 -1382
  140. data/spec/integration/association_through_spec.rb +0 -203
  141. data/spec/integration/associations/many_to_many_spec.rb +0 -449
  142. data/spec/integration/associations/many_to_one_spec.rb +0 -163
  143. data/spec/integration/associations/one_to_many_spec.rb +0 -188
  144. data/spec/integration/auto_migrations_spec.rb +0 -413
  145. data/spec/integration/collection_spec.rb +0 -1073
  146. data/spec/integration/data_objects_adapter_spec.rb +0 -32
  147. data/spec/integration/dependency_queue_spec.rb +0 -46
  148. data/spec/integration/model_spec.rb +0 -197
  149. data/spec/integration/mysql_adapter_spec.rb +0 -85
  150. data/spec/integration/postgres_adapter_spec.rb +0 -731
  151. data/spec/integration/property_spec.rb +0 -253
  152. data/spec/integration/query_spec.rb +0 -514
  153. data/spec/integration/repository_spec.rb +0 -61
  154. data/spec/integration/resource_spec.rb +0 -513
  155. data/spec/integration/sqlite3_adapter_spec.rb +0 -352
  156. data/spec/integration/sti_spec.rb +0 -273
  157. data/spec/integration/strategic_eager_loading_spec.rb +0 -156
  158. data/spec/integration/transaction_spec.rb +0 -75
  159. data/spec/integration/type_spec.rb +0 -275
  160. data/spec/lib/logging_helper.rb +0 -18
  161. data/spec/lib/mock_adapter.rb +0 -27
  162. data/spec/lib/model_loader.rb +0 -100
  163. data/spec/lib/publicize_methods.rb +0 -28
  164. data/spec/models/content.rb +0 -16
  165. data/spec/models/vehicles.rb +0 -34
  166. data/spec/models/zoo.rb +0 -48
  167. data/spec/unit/adapters/abstract_adapter_spec.rb +0 -133
  168. data/spec/unit/adapters/adapter_shared_spec.rb +0 -15
  169. data/spec/unit/adapters/data_objects_adapter_spec.rb +0 -632
  170. data/spec/unit/adapters/in_memory_adapter_spec.rb +0 -98
  171. data/spec/unit/adapters/postgres_adapter_spec.rb +0 -133
  172. data/spec/unit/associations/many_to_many_spec.rb +0 -32
  173. data/spec/unit/associations/many_to_one_spec.rb +0 -159
  174. data/spec/unit/associations/one_to_many_spec.rb +0 -393
  175. data/spec/unit/associations/one_to_one_spec.rb +0 -7
  176. data/spec/unit/associations/relationship_spec.rb +0 -71
  177. data/spec/unit/associations_spec.rb +0 -242
  178. data/spec/unit/auto_migrations_spec.rb +0 -111
  179. data/spec/unit/collection_spec.rb +0 -182
  180. data/spec/unit/data_mapper_spec.rb +0 -35
  181. data/spec/unit/identity_map_spec.rb +0 -126
  182. data/spec/unit/is_spec.rb +0 -80
  183. data/spec/unit/migrator_spec.rb +0 -33
  184. data/spec/unit/model_spec.rb +0 -321
  185. data/spec/unit/naming_conventions_spec.rb +0 -36
  186. data/spec/unit/property_set_spec.rb +0 -90
  187. data/spec/unit/property_spec.rb +0 -753
  188. data/spec/unit/query_spec.rb +0 -571
  189. data/spec/unit/repository_spec.rb +0 -93
  190. data/spec/unit/resource_spec.rb +0 -649
  191. data/spec/unit/scope_spec.rb +0 -142
  192. data/spec/unit/transaction_spec.rb +0 -493
  193. data/spec/unit/type_map_spec.rb +0 -114
  194. data/spec/unit/type_spec.rb +0 -119
@@ -0,0 +1,77 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ # run the specs once with a loaded association and once not
4
+ [ false, true ].each do |loaded|
5
+ describe 'One to Many Associations' do
6
+ extend DataMapper::Spec::CollectionHelpers::GroupMethods
7
+
8
+ self.loaded = loaded
9
+
10
+ # define the model prior to supported_by
11
+ before :all do
12
+ module ::Blog
13
+ class Author
14
+ include DataMapper::Resource
15
+
16
+ property :id, Serial
17
+ property :name, String
18
+
19
+ has n, :articles
20
+ end
21
+
22
+ class Article
23
+ include DataMapper::Resource
24
+
25
+ property :id, Serial
26
+ property :title, String, :nullable => false
27
+ property :content, Text
28
+ property :subtitle, String
29
+
30
+ belongs_to :author, :nullable => true
31
+ belongs_to :original, self, :nullable => true
32
+ has n, :revisions, self, :child_key => [ :original_id ]
33
+ has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
34
+ has n, :publications, :through => Resource
35
+ end
36
+
37
+ class Publication
38
+ include DataMapper::Resource
39
+
40
+ property :id, Serial
41
+ property :name, String
42
+
43
+ has n, :articles, :through => Resource
44
+ end
45
+ end
46
+
47
+ @author_model = Blog::Author
48
+ @article_model = Blog::Article
49
+ @publication_model = Blog::Publication
50
+ end
51
+
52
+ supported_by :all do
53
+ before :all do
54
+ @author = @author_model.create(:name => 'Dan Kubb')
55
+
56
+ @original = @author.articles.create(:title => 'Original Article')
57
+ @article = @author.articles.create(:title => 'Sample Article', :content => 'Sample', :original => @original)
58
+ @other = @author.articles.create(:title => 'Other Article', :content => 'Other')
59
+
60
+ # load the targets without references to a single source
61
+ load_collection = lambda do |query|
62
+ @author_model.get(*@author.key).articles(query)
63
+ end
64
+
65
+ @articles = load_collection.call(:title => 'Sample Article')
66
+ @other_articles = load_collection.call(:title => 'Other Article')
67
+
68
+ @articles.entries if loaded
69
+ end
70
+
71
+ it_should_behave_like 'A public Collection'
72
+ it_should_behave_like 'A public Association Collection'
73
+ it_should_behave_like 'A Collection supporting Strategic Eager Loading'
74
+ it_should_behave_like 'Finder Interface'
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,156 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe 'One to One Associations' do
4
+ before :all do
5
+ module ::Blog
6
+ class User
7
+ include DataMapper::Resource
8
+
9
+ property :name, String, :key => true
10
+ property :age, Integer
11
+ property :summary, Text
12
+ property :description, Text
13
+ property :admin, Boolean, :accessor => :private
14
+
15
+ belongs_to :referrer, self, :nullable => true
16
+ belongs_to :comment
17
+
18
+ # TODO: remove this after Relationship#inverse can dynamically
19
+ # create an inverse relationship when no perfect match can be found
20
+ has n, :referree, self, :child_key => [ :referrer_name ]
21
+ end
22
+
23
+ class Author < User; end
24
+
25
+ class Comment
26
+ include DataMapper::Resource
27
+
28
+ property :id, Serial
29
+ property :body, Text
30
+
31
+ has 1, :user
32
+ end
33
+
34
+ class Article
35
+ include DataMapper::Resource
36
+
37
+ property :id, Serial
38
+ property :body, Text
39
+
40
+ has 1, :paragraph
41
+ end
42
+
43
+ class Paragraph
44
+ include DataMapper::Resource
45
+
46
+ property :id, Serial
47
+ property :text, String
48
+
49
+ belongs_to :article
50
+ end
51
+ end
52
+
53
+ @user_model = Blog::User
54
+ @author_model = Blog::Author
55
+ @comment_model = Blog::Comment
56
+ @article_model = Blog::Article
57
+ @paragraph_model = Blog::Paragraph
58
+ end
59
+
60
+ supported_by :all do
61
+ before :all do
62
+ comment = @comment_model.create(:body => 'Cool spec')
63
+ user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test', :comment => comment)
64
+
65
+ @comment = @comment_model.get(*comment.key)
66
+ @user = @comment.user
67
+ end
68
+
69
+ it_should_behave_like 'A public Resource'
70
+ it_should_behave_like 'A Resource supporting Strategic Eager Loading'
71
+ end
72
+ end
73
+
74
+ describe 'One to One Through Associations' do
75
+ before :all do
76
+ module ::Blog
77
+ class Referral
78
+ include DataMapper::Resource
79
+
80
+ property :referrer_name, String, :key => true
81
+ property :referree_name, String, :key => true
82
+
83
+ belongs_to :referrer, 'User', :child_key => [ :referrer_name ]
84
+ belongs_to :referree, 'User', :child_key => [ :referree_name ]
85
+ end
86
+
87
+ class User
88
+ include DataMapper::Resource
89
+
90
+ property :name, String, :key => true
91
+ property :age, Integer
92
+ property :summary, Text
93
+ property :description, Text
94
+ property :admin, Boolean, :accessor => :private
95
+
96
+ has 1, :referral_from, Referral, :child_key => [ :referree_name ]
97
+ has 1, :referral_to, Referral, :child_key => [ :referrer_name ]
98
+
99
+ has 1, :referrer, self, :through => :referral_from
100
+ has 1, :referree, self, :through => :referral_to
101
+ has 1, :comment, :through => Resource
102
+ end
103
+
104
+ class Author < User; end
105
+
106
+ class Comment
107
+ include DataMapper::Resource
108
+
109
+ property :id, Serial
110
+ property :body, Text
111
+
112
+ has 1, :user, :through => Resource
113
+ end
114
+
115
+ class Article
116
+ include DataMapper::Resource
117
+
118
+ property :id, Serial
119
+ property :body, Text
120
+
121
+ has 1, :paragraph, :through => Resource
122
+ end
123
+
124
+ class Paragraph
125
+ include DataMapper::Resource
126
+
127
+ property :id, Serial
128
+ property :text, String
129
+
130
+ has 1, :article, :through => Resource
131
+ end
132
+ end
133
+
134
+ @referral_model = Blog::Referral
135
+ @user_model = Blog::User
136
+ @author_model = Blog::Author
137
+ @comment_model = Blog::Comment
138
+ @article_model = Blog::Article
139
+ @paragraph_model = Blog::Paragraph
140
+ end
141
+
142
+ supported_by :all do
143
+ before :all do
144
+ comment = @comment_model.create(:body => 'Cool spec')
145
+ user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test', :comment => comment)
146
+
147
+ @comment = @comment_model.get(*comment.key)
148
+ @user = @comment.user
149
+ end
150
+
151
+ it_should_behave_like 'A public Resource'
152
+
153
+ # TODO: make this pass
154
+ #it_should_behave_like 'A Resource supporting Strategic Eager Loading'
155
+ end
156
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ # run the specs once with a loaded collection and once not
4
+ [ false, true ].each do |loaded|
5
+ describe DataMapper::Collection do
6
+ extend DataMapper::Spec::CollectionHelpers::GroupMethods
7
+
8
+ self.loaded = loaded
9
+
10
+ before :all do
11
+ module ::Blog
12
+ class Article
13
+ include DataMapper::Resource
14
+
15
+ property :id, Serial
16
+ property :title, String, :nullable => false
17
+ property :content, Text
18
+ property :subtitle, String
19
+ property :author, String, :nullable => false
20
+
21
+ belongs_to :original, self, :nullable => true
22
+ has n, :revisions, self, :child_key => [ :original_id ]
23
+ has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
24
+ has n, :publications, :through => Resource
25
+ end
26
+
27
+ class Publication
28
+ include DataMapper::Resource
29
+
30
+ property :id, Serial
31
+ property :name, String
32
+
33
+ has n, :articles, :through => Resource
34
+ end
35
+ end
36
+
37
+ @article_model = Blog::Article
38
+ @publication_model = Blog::Publication
39
+ end
40
+
41
+ supported_by :all do
42
+ before :all do
43
+ @author = 'Dan Kubb'
44
+
45
+ @original = @article_model.create(:title => 'Original Article', :author => @author)
46
+ @article = @article_model.create(:title => 'Sample Article', :content => 'Sample', :original => @original, :author => @author)
47
+ @other = @article_model.create(:title => 'Other Article', :content => 'Other', :author => @author)
48
+
49
+ # load the targets without references to a single source
50
+ load_collection = lambda do |query|
51
+ @article_model.all(query)
52
+ end
53
+
54
+ @articles = load_collection.call(:title => 'Sample Article', :author => @author)
55
+ @other_articles = load_collection.call(:title => 'Other Article', :author => @author)
56
+
57
+ @articles.entries if loaded
58
+ end
59
+
60
+ it_should_behave_like 'A public Collection'
61
+ it_should_behave_like 'A Collection supporting Strategic Eager Loading'
62
+ it_should_behave_like 'Finder Interface'
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,359 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe DataMapper::Migrations do
4
+ def capture_log(mod)
5
+ original, mod.logger = mod.logger, DataObjects::Logger.new(@log = StringIO.new, :debug)
6
+ yield
7
+ ensure
8
+ @log.rewind
9
+ @output = @log.readlines.map do |line|
10
+ line.chomp.gsub(/\A.+?~ \(\d+\.?\d*\)\s+/, '')
11
+ end
12
+
13
+ mod.logger = original
14
+ end
15
+
16
+ supported_by :mysql do
17
+ before :all do
18
+ module ::Blog
19
+ class Article
20
+ include DataMapper::Resource
21
+ end
22
+ end
23
+
24
+ @model = ::Blog::Article
25
+ end
26
+
27
+ describe '#auto_migrate' do
28
+ describe 'Integer property' do
29
+ [
30
+ [ 0, 1, 'TINYINT(1) UNSIGNED' ],
31
+ [ 0, 9, 'TINYINT(1) UNSIGNED' ],
32
+ [ 0, 10, 'TINYINT(2) UNSIGNED' ],
33
+ [ 0, 99, 'TINYINT(2) UNSIGNED' ],
34
+ [ 0, 100, 'TINYINT(3) UNSIGNED' ],
35
+ [ 0, 255, 'TINYINT(3) UNSIGNED' ],
36
+ [ 0, 256, 'SMALLINT(3) UNSIGNED' ],
37
+ [ 0, 999, 'SMALLINT(3) UNSIGNED' ],
38
+ [ 0, 1000, 'SMALLINT(4) UNSIGNED' ],
39
+ [ 0, 9999, 'SMALLINT(4) UNSIGNED' ],
40
+ [ 0, 10000, 'SMALLINT(5) UNSIGNED' ],
41
+ [ 0, 65535, 'SMALLINT(5) UNSIGNED' ],
42
+ [ 0, 65536, 'MEDIUMINT(5) UNSIGNED' ],
43
+ [ 0, 99999, 'MEDIUMINT(5) UNSIGNED' ],
44
+ [ 0, 100000, 'MEDIUMINT(6) UNSIGNED' ],
45
+ [ 0, 999999, 'MEDIUMINT(6) UNSIGNED' ],
46
+ [ 0, 1000000, 'MEDIUMINT(7) UNSIGNED' ],
47
+ [ 0, 9999999, 'MEDIUMINT(7) UNSIGNED' ],
48
+ [ 0, 10000000, 'MEDIUMINT(8) UNSIGNED' ],
49
+ [ 0, 16777215, 'MEDIUMINT(8) UNSIGNED' ],
50
+ [ 0, 16777216, 'INT(8) UNSIGNED' ],
51
+ [ 0, 99999999, 'INT(8) UNSIGNED' ],
52
+ [ 0, 100000000, 'INT(9) UNSIGNED' ],
53
+ [ 0, 999999999, 'INT(9) UNSIGNED' ],
54
+ [ 0, 1000000000, 'INT(10) UNSIGNED' ],
55
+ [ 0, 4294967295, 'INT(10) UNSIGNED' ],
56
+ [ 0, 4294967296, 'BIGINT(10) UNSIGNED' ],
57
+ [ 0, 9999999999, 'BIGINT(10) UNSIGNED' ],
58
+ [ 0, 10000000000, 'BIGINT(11) UNSIGNED' ],
59
+ [ 0, 99999999999, 'BIGINT(11) UNSIGNED' ],
60
+ [ 0, 100000000000, 'BIGINT(12) UNSIGNED' ],
61
+ [ 0, 999999999999, 'BIGINT(12) UNSIGNED' ],
62
+ [ 0, 1000000000000, 'BIGINT(13) UNSIGNED' ],
63
+ [ 0, 9999999999999, 'BIGINT(13) UNSIGNED' ],
64
+ [ 0, 10000000000000, 'BIGINT(14) UNSIGNED' ],
65
+ [ 0, 99999999999999, 'BIGINT(14) UNSIGNED' ],
66
+ [ 0, 100000000000000, 'BIGINT(15) UNSIGNED' ],
67
+ [ 0, 999999999999999, 'BIGINT(15) UNSIGNED' ],
68
+ [ 0, 1000000000000000, 'BIGINT(16) UNSIGNED' ],
69
+ [ 0, 9999999999999999, 'BIGINT(16) UNSIGNED' ],
70
+ [ 0, 10000000000000000, 'BIGINT(17) UNSIGNED' ],
71
+ [ 0, 99999999999999999, 'BIGINT(17) UNSIGNED' ],
72
+ [ 0, 100000000000000000, 'BIGINT(18) UNSIGNED' ],
73
+ [ 0, 999999999999999999, 'BIGINT(18) UNSIGNED' ],
74
+ [ 0, 1000000000000000000, 'BIGINT(19) UNSIGNED' ],
75
+ [ 0, 9999999999999999999, 'BIGINT(19) UNSIGNED' ],
76
+ [ 0, 10000000000000000000, 'BIGINT(20) UNSIGNED' ],
77
+ [ 0, 18446744073709551615, 'BIGINT(20) UNSIGNED' ],
78
+
79
+ [ -1, 0, 'TINYINT(2)' ],
80
+ [ -1, 9, 'TINYINT(2)' ],
81
+ [ -1, 10, 'TINYINT(2)' ],
82
+ [ -1, 99, 'TINYINT(2)' ],
83
+ [ -1, 100, 'TINYINT(3)' ],
84
+ [ -1, 127, 'TINYINT(3)' ],
85
+ [ -1, 128, 'SMALLINT(3)' ],
86
+ [ -1, 999, 'SMALLINT(3)' ],
87
+ [ -1, 1000, 'SMALLINT(4)' ],
88
+ [ -1, 9999, 'SMALLINT(4)' ],
89
+ [ -1, 10000, 'SMALLINT(5)' ],
90
+ [ -1, 32767, 'SMALLINT(5)' ],
91
+ [ -1, 32768, 'MEDIUMINT(5)' ],
92
+ [ -1, 99999, 'MEDIUMINT(5)' ],
93
+ [ -1, 100000, 'MEDIUMINT(6)' ],
94
+ [ -1, 999999, 'MEDIUMINT(6)' ],
95
+ [ -1, 1000000, 'MEDIUMINT(7)' ],
96
+ [ -1, 8388607, 'MEDIUMINT(7)' ],
97
+ [ -1, 8388608, 'INT(7)' ],
98
+ [ -1, 9999999, 'INT(7)' ],
99
+ [ -1, 10000000, 'INT(8)' ],
100
+ [ -1, 99999999, 'INT(8)' ],
101
+ [ -1, 100000000, 'INT(9)' ],
102
+ [ -1, 999999999, 'INT(9)' ],
103
+ [ -1, 1000000000, 'INT(10)' ],
104
+ [ -1, 2147483647, 'INT(10)' ],
105
+ [ -1, 2147483648, 'BIGINT(10)' ],
106
+ [ -1, 9999999999, 'BIGINT(10)' ],
107
+ [ -1, 10000000000, 'BIGINT(11)' ],
108
+ [ -1, 99999999999, 'BIGINT(11)' ],
109
+ [ -1, 100000000000, 'BIGINT(12)' ],
110
+ [ -1, 999999999999, 'BIGINT(12)' ],
111
+ [ -1, 1000000000000, 'BIGINT(13)' ],
112
+ [ -1, 9999999999999, 'BIGINT(13)' ],
113
+ [ -1, 10000000000000, 'BIGINT(14)' ],
114
+ [ -1, 99999999999999, 'BIGINT(14)' ],
115
+ [ -1, 100000000000000, 'BIGINT(15)' ],
116
+ [ -1, 999999999999999, 'BIGINT(15)' ],
117
+ [ -1, 1000000000000000, 'BIGINT(16)' ],
118
+ [ -1, 9999999999999999, 'BIGINT(16)' ],
119
+ [ -1, 10000000000000000, 'BIGINT(17)' ],
120
+ [ -1, 99999999999999999, 'BIGINT(17)' ],
121
+ [ -1, 100000000000000000, 'BIGINT(18)' ],
122
+ [ -1, 999999999999999999, 'BIGINT(18)' ],
123
+ [ -1, 1000000000000000000, 'BIGINT(19)' ],
124
+ [ -1, 9223372036854775807, 'BIGINT(19)' ],
125
+
126
+ [ -1, 0, 'TINYINT(2)' ],
127
+ [ -9, 0, 'TINYINT(2)' ],
128
+ [ -10, 0, 'TINYINT(3)' ],
129
+ [ -99, 0, 'TINYINT(3)' ],
130
+ [ -100, 0, 'TINYINT(4)' ],
131
+ [ -128, 0, 'TINYINT(4)' ],
132
+ [ -129, 0, 'SMALLINT(4)' ],
133
+ [ -999, 0, 'SMALLINT(4)' ],
134
+ [ -1000, 0, 'SMALLINT(5)' ],
135
+ [ -9999, 0, 'SMALLINT(5)' ],
136
+ [ -10000, 0, 'SMALLINT(6)' ],
137
+ [ -32768, 0, 'SMALLINT(6)' ],
138
+ [ -32769, 0, 'MEDIUMINT(6)' ],
139
+ [ -99999, 0, 'MEDIUMINT(6)' ],
140
+ [ -100000, 0, 'MEDIUMINT(7)' ],
141
+ [ -999999, 0, 'MEDIUMINT(7)' ],
142
+ [ -1000000, 0, 'MEDIUMINT(8)' ],
143
+ [ -8388608, 0, 'MEDIUMINT(8)' ],
144
+ [ -8388609, 0, 'INT(8)' ],
145
+ [ -9999999, 0, 'INT(8)' ],
146
+ [ -10000000, 0, 'INT(9)' ],
147
+ [ -99999999, 0, 'INT(9)' ],
148
+ [ -100000000, 0, 'INT(10)' ],
149
+ [ -999999999, 0, 'INT(10)' ],
150
+ [ -1000000000, 0, 'INT(11)' ],
151
+ [ -2147483648, 0, 'INT(11)' ],
152
+ [ -2147483649, 0, 'BIGINT(11)' ],
153
+ [ -9999999999, 0, 'BIGINT(11)' ],
154
+ [ -10000000000, 0, 'BIGINT(12)' ],
155
+ [ -99999999999, 0, 'BIGINT(12)' ],
156
+ [ -100000000000, 0, 'BIGINT(13)' ],
157
+ [ -999999999999, 0, 'BIGINT(13)' ],
158
+ [ -1000000000000, 0, 'BIGINT(14)' ],
159
+ [ -9999999999999, 0, 'BIGINT(14)' ],
160
+ [ -10000000000000, 0, 'BIGINT(15)' ],
161
+ [ -99999999999999, 0, 'BIGINT(15)' ],
162
+ [ -100000000000000, 0, 'BIGINT(16)' ],
163
+ [ -999999999999999, 0, 'BIGINT(16)' ],
164
+ [ -1000000000000000, 0, 'BIGINT(17)' ],
165
+ [ -9999999999999999, 0, 'BIGINT(17)' ],
166
+ [ -10000000000000000, 0, 'BIGINT(18)' ],
167
+ [ -99999999999999999, 0, 'BIGINT(18)' ],
168
+ [ -100000000000000000, 0, 'BIGINT(19)' ],
169
+ [ -999999999999999999, 0, 'BIGINT(19)' ],
170
+ [ -1000000000000000000, 0, 'BIGINT(20)' ],
171
+ [ -9223372036854775808, 0, 'BIGINT(20)' ],
172
+
173
+ [ nil, 2147483647, 'INT(10) UNSIGNED' ],
174
+ [ 0, nil, 'INT(10) UNSIGNED' ],
175
+ [ nil, nil, 'INTEGER' ],
176
+ ].each do |min, max, statement|
177
+ options = { :key => true }
178
+ options[:min] = min if min
179
+ options[:max] = max if max
180
+
181
+ describe "with a min of #{min} and a max of #{max}" do
182
+ before :all do
183
+ @property = @model.property(:id, Integer, options)
184
+
185
+ @response = capture_log(DataObjects::Mysql) { @model.auto_migrate! }
186
+ end
187
+
188
+ it 'should return true' do
189
+ @response.should be_true
190
+ end
191
+
192
+ it "should create a #{statement} column" do
193
+ @output.last.should =~ %r{\ACREATE TABLE `blog_articles` \(`id` #{Regexp.escape(statement)} NOT NULL, PRIMARY KEY\(`id`\)\) ENGINE = InnoDB CHARACTER SET [a-z\d]+ COLLATE (?:[a-z\d](?:_?[a-z\d]+)*)\z}
194
+ end
195
+
196
+ options.only(:min, :max).each do |key, value|
197
+ it "should allow the #{key} value #{value} to be stored" do
198
+ lambda {
199
+ resource = @model.create(@property => value)
200
+ @model.first(@property => value).should eql(resource)
201
+ }.should_not raise_error
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ describe 'Text property' do
209
+ before :all do
210
+ @model.property(:id, DataMapper::Types::Serial)
211
+ end
212
+
213
+ [
214
+ [ 0, 'TINYTEXT' ],
215
+ [ 1, 'TINYTEXT' ],
216
+ [ 255, 'TINYTEXT' ],
217
+ [ 256, 'TEXT' ],
218
+ [ 65535, 'TEXT' ],
219
+ [ 65536, 'MEDIUMTEXT' ],
220
+ [ 16777215, 'MEDIUMTEXT' ],
221
+ [ 16777216, 'LONGTEXT' ],
222
+ [ 4294967295, 'LONGTEXT' ],
223
+
224
+ [ nil, 'TEXT' ],
225
+ ].each do |length, statement|
226
+ options = {}
227
+ options[:length] = length if length
228
+
229
+ describe "with a length of #{length}" do
230
+ before :all do
231
+ @property = @model.property(:body, DataMapper::Types::Text, options)
232
+
233
+ @response = capture_log(DataObjects::Mysql) { @model.auto_migrate! }
234
+ end
235
+
236
+ it 'should return true' do
237
+ @response.should be_true
238
+ end
239
+
240
+ it "should create a #{statement} column" do
241
+ @output.last.should =~ %r{\ACREATE TABLE `blog_articles` \(`id` INT\(10\) UNSIGNED NOT NULL AUTO_INCREMENT, `body` #{Regexp.escape(statement)}, PRIMARY KEY\(`id`\)\) ENGINE = InnoDB CHARACTER SET [a-z\d]+ COLLATE (?:[a-z\d](?:_?[a-z\d]+)*)\z}
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
248
+
249
+ supported_by :postgres do
250
+ before :all do
251
+ module ::Blog
252
+ class Article
253
+ include DataMapper::Resource
254
+ end
255
+ end
256
+
257
+ @model = ::Blog::Article
258
+ end
259
+
260
+ describe '#auto_migrate' do
261
+ describe 'Integer property' do
262
+ [
263
+ [ 0, 1, 'SMALLINT' ],
264
+ [ 0, 32767, 'SMALLINT' ],
265
+ [ 0, 32768, 'INTEGER' ],
266
+ [ 0, 2147483647, 'INTEGER' ],
267
+ [ 0, 2147483648, 'BIGINT' ],
268
+ [ 0, 9223372036854775807, 'BIGINT' ],
269
+
270
+ [ -1, 1, 'SMALLINT' ],
271
+ [ -1, 32767, 'SMALLINT' ],
272
+ [ -1, 32768, 'INTEGER' ],
273
+ [ -1, 2147483647, 'INTEGER' ],
274
+ [ -1, 2147483648, 'BIGINT' ],
275
+ [ -1, 9223372036854775807, 'BIGINT' ],
276
+
277
+ [ -1, 0, 'SMALLINT' ],
278
+ [ -32768, 0, 'SMALLINT' ],
279
+ [ -32769, 0, 'INTEGER' ],
280
+ [ -2147483648, 0, 'INTEGER' ],
281
+ [ -2147483649, 0, 'BIGINT' ],
282
+ [ -9223372036854775808, 0, 'BIGINT' ],
283
+
284
+ [ nil, 2147483647, 'INTEGER' ],
285
+ [ 0, nil, 'INTEGER' ],
286
+ [ nil, nil, 'INTEGER' ],
287
+ ].each do |min, max, statement|
288
+ options = { :key => true }
289
+ options[:min] = min if min
290
+ options[:max] = max if max
291
+
292
+ describe "with a min of #{min} and a max of #{max}" do
293
+ before :all do
294
+ @property = @model.property(:id, Integer, options)
295
+
296
+ @response = capture_log(DataObjects::Postgres) { @model.auto_migrate! }
297
+ end
298
+
299
+ it 'should return true' do
300
+ @response.should be_true
301
+ end
302
+
303
+ it "should create a #{statement} column" do
304
+ @output[-2].should == "CREATE TABLE \"blog_articles\" (\"id\" #{statement} NOT NULL, PRIMARY KEY(\"id\"))"
305
+ end
306
+
307
+ options.only(:min, :max).each do |key, value|
308
+ it "should allow the #{key} value #{value} to be stored" do
309
+ lambda {
310
+ resource = @model.create(@property => value)
311
+ @model.first(@property => value).should eql(resource)
312
+ }.should_not raise_error
313
+ end
314
+ end
315
+ end
316
+ end
317
+ end
318
+
319
+ describe 'Serial property' do
320
+ [
321
+ [ 1, 'SERIAL' ],
322
+ [ 2147483647, 'SERIAL' ],
323
+ [ 2147483648, 'BIGSERIAL' ],
324
+ [ 9223372036854775807, 'BIGSERIAL' ],
325
+
326
+ [ nil, 'SERIAL' ],
327
+ ].each do |max, statement|
328
+ options = {}
329
+ options[:max] = max if max
330
+
331
+ describe "with a max of #{max}" do
332
+ before :all do
333
+ @property = @model.property(:id, DataMapper::Types::Serial, options)
334
+
335
+ @response = capture_log(DataObjects::Postgres) { @model.auto_migrate! }
336
+ end
337
+
338
+ it 'should return true' do
339
+ @response.should be_true
340
+ end
341
+
342
+ it "should create a #{statement} column" do
343
+ @output[-2].should == "CREATE TABLE \"blog_articles\" (\"id\" #{statement} NOT NULL, PRIMARY KEY(\"id\"))"
344
+ end
345
+
346
+ options.only(:min, :max).each do |key, value|
347
+ it "should allow the #{key} value #{value} to be stored" do
348
+ lambda {
349
+ resource = @model.create(@property => value)
350
+ @model.first(@property => value).should eql(resource)
351
+ }.should_not raise_error
352
+ end
353
+ end
354
+ end
355
+ end
356
+ end
357
+ end
358
+ end
359
+ end