sequel 3.21.0 → 3.36.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 (311) hide show
  1. data/CHANGELOG +855 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +23 -7
  4. data/Rakefile +42 -24
  5. data/bin/sequel +26 -8
  6. data/doc/active_record.rdoc +1 -0
  7. data/doc/advanced_associations.rdoc +171 -11
  8. data/doc/association_basics.rdoc +293 -43
  9. data/doc/dataset_basics.rdoc +5 -5
  10. data/doc/dataset_filtering.rdoc +8 -0
  11. data/doc/mass_assignment.rdoc +56 -0
  12. data/doc/migration.rdoc +85 -552
  13. data/doc/model_hooks.rdoc +78 -27
  14. data/doc/object_model.rdoc +541 -0
  15. data/doc/opening_databases.rdoc +97 -50
  16. data/doc/prepared_statements.rdoc +40 -14
  17. data/doc/querying.rdoc +28 -4
  18. data/doc/reflection.rdoc +30 -4
  19. data/doc/release_notes/3.22.0.txt +39 -0
  20. data/doc/release_notes/3.23.0.txt +172 -0
  21. data/doc/release_notes/3.24.0.txt +420 -0
  22. data/doc/release_notes/3.25.0.txt +88 -0
  23. data/doc/release_notes/3.26.0.txt +88 -0
  24. data/doc/release_notes/3.27.0.txt +82 -0
  25. data/doc/release_notes/3.28.0.txt +304 -0
  26. data/doc/release_notes/3.29.0.txt +459 -0
  27. data/doc/release_notes/3.30.0.txt +135 -0
  28. data/doc/release_notes/3.31.0.txt +146 -0
  29. data/doc/release_notes/3.32.0.txt +202 -0
  30. data/doc/release_notes/3.33.0.txt +157 -0
  31. data/doc/release_notes/3.34.0.txt +671 -0
  32. data/doc/release_notes/3.35.0.txt +144 -0
  33. data/doc/release_notes/3.36.0.txt +245 -0
  34. data/doc/schema_modification.rdoc +572 -0
  35. data/doc/sharding.rdoc +95 -3
  36. data/doc/testing.rdoc +129 -0
  37. data/doc/thread_safety.rdoc +17 -0
  38. data/doc/transactions.rdoc +137 -0
  39. data/doc/virtual_rows.rdoc +51 -2
  40. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  41. data/lib/sequel/adapters/ado.rb +40 -18
  42. data/lib/sequel/adapters/amalgalite.rb +17 -9
  43. data/lib/sequel/adapters/db2.rb +175 -86
  44. data/lib/sequel/adapters/dbi.rb +15 -15
  45. data/lib/sequel/adapters/do/mysql.rb +17 -11
  46. data/lib/sequel/adapters/do/postgres.rb +1 -57
  47. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  48. data/lib/sequel/adapters/do.rb +18 -36
  49. data/lib/sequel/adapters/firebird.rb +27 -208
  50. data/lib/sequel/adapters/ibmdb.rb +453 -0
  51. data/lib/sequel/adapters/informix.rb +6 -23
  52. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  53. data/lib/sequel/adapters/jdbc/db2.rb +47 -0
  54. data/lib/sequel/adapters/jdbc/derby.rb +287 -0
  55. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  56. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  57. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  58. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  59. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  61. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  62. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
  64. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  65. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  66. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  67. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  68. data/lib/sequel/adapters/jdbc.rb +265 -94
  69. data/lib/sequel/adapters/mock.rb +361 -0
  70. data/lib/sequel/adapters/mysql.rb +118 -222
  71. data/lib/sequel/adapters/mysql2.rb +58 -57
  72. data/lib/sequel/adapters/odbc/mssql.rb +15 -7
  73. data/lib/sequel/adapters/odbc.rb +28 -9
  74. data/lib/sequel/adapters/openbase.rb +3 -5
  75. data/lib/sequel/adapters/oracle.rb +349 -53
  76. data/lib/sequel/adapters/postgres.rb +356 -107
  77. data/lib/sequel/adapters/shared/access.rb +32 -9
  78. data/lib/sequel/adapters/shared/db2.rb +342 -0
  79. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  80. data/lib/sequel/adapters/shared/informix.rb +53 -0
  81. data/lib/sequel/adapters/shared/mssql.rb +335 -118
  82. data/lib/sequel/adapters/shared/mysql.rb +340 -76
  83. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  84. data/lib/sequel/adapters/shared/oracle.rb +243 -45
  85. data/lib/sequel/adapters/shared/postgres.rb +524 -279
  86. data/lib/sequel/adapters/shared/progress.rb +5 -8
  87. data/lib/sequel/adapters/shared/sqlite.rb +265 -89
  88. data/lib/sequel/adapters/sqlite.rb +101 -39
  89. data/lib/sequel/adapters/swift/mysql.rb +9 -12
  90. data/lib/sequel/adapters/swift/postgres.rb +9 -74
  91. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  92. data/lib/sequel/adapters/swift.rb +8 -7
  93. data/lib/sequel/adapters/tinytds.rb +161 -21
  94. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  95. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  96. data/lib/sequel/ast_transformer.rb +194 -0
  97. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  98. data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
  99. data/lib/sequel/connection_pool/single.rb +5 -0
  100. data/lib/sequel/connection_pool/threaded.rb +38 -14
  101. data/lib/sequel/connection_pool.rb +10 -2
  102. data/lib/sequel/core.rb +118 -11
  103. data/lib/sequel/database/connecting.rb +38 -28
  104. data/lib/sequel/database/dataset.rb +4 -4
  105. data/lib/sequel/database/dataset_defaults.rb +63 -2
  106. data/lib/sequel/database/logging.rb +7 -2
  107. data/lib/sequel/database/misc.rb +150 -46
  108. data/lib/sequel/database/query.rb +215 -65
  109. data/lib/sequel/database/schema_generator.rb +64 -20
  110. data/lib/sequel/database/schema_methods.rb +212 -54
  111. data/lib/sequel/dataset/actions.rb +322 -85
  112. data/lib/sequel/dataset/features.rb +96 -8
  113. data/lib/sequel/dataset/graph.rb +38 -11
  114. data/lib/sequel/dataset/misc.rb +50 -23
  115. data/lib/sequel/dataset/mutation.rb +12 -7
  116. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  117. data/lib/sequel/dataset/query.rb +237 -44
  118. data/lib/sequel/dataset/sql.rb +698 -278
  119. data/lib/sequel/dataset.rb +8 -0
  120. data/lib/sequel/exceptions.rb +4 -0
  121. data/lib/sequel/extensions/_pretty_table.rb +79 -0
  122. data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
  123. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  124. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
  125. data/lib/sequel/extensions/migration.rb +97 -11
  126. data/lib/sequel/extensions/named_timezones.rb +5 -0
  127. data/lib/sequel/extensions/null_dataset.rb +90 -0
  128. data/lib/sequel/extensions/pg_array.rb +460 -0
  129. data/lib/sequel/extensions/pg_array_ops.rb +220 -0
  130. data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
  131. data/lib/sequel/extensions/pg_hstore.rb +296 -0
  132. data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
  133. data/lib/sequel/extensions/pg_inet.rb +89 -0
  134. data/lib/sequel/extensions/pg_json.rb +178 -0
  135. data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
  136. data/lib/sequel/extensions/pretty_table.rb +5 -71
  137. data/lib/sequel/extensions/query.rb +1 -1
  138. data/lib/sequel/extensions/query_literals.rb +79 -0
  139. data/lib/sequel/extensions/schema_caching.rb +76 -0
  140. data/lib/sequel/extensions/schema_dumper.rb +251 -37
  141. data/lib/sequel/extensions/select_remove.rb +35 -0
  142. data/lib/sequel/extensions/server_block.rb +139 -0
  143. data/lib/sequel/extensions/sql_expr.rb +4 -110
  144. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  145. data/lib/sequel/extensions/to_dot.rb +95 -83
  146. data/lib/sequel/model/associations.rb +1187 -393
  147. data/lib/sequel/model/base.rb +578 -170
  148. data/lib/sequel/model/errors.rb +1 -1
  149. data/lib/sequel/model/exceptions.rb +5 -1
  150. data/lib/sequel/model/inflections.rb +1 -1
  151. data/lib/sequel/model.rb +30 -11
  152. data/lib/sequel/no_core_ext.rb +2 -0
  153. data/lib/sequel/plugins/active_model.rb +13 -1
  154. data/lib/sequel/plugins/association_pks.rb +22 -4
  155. data/lib/sequel/plugins/caching.rb +25 -18
  156. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  157. data/lib/sequel/plugins/composition.rb +44 -12
  158. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  159. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  160. data/lib/sequel/plugins/dirty.rb +214 -0
  161. data/lib/sequel/plugins/eager_each.rb +59 -0
  162. data/lib/sequel/plugins/force_encoding.rb +6 -6
  163. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  164. data/lib/sequel/plugins/identity_map.rb +123 -8
  165. data/lib/sequel/plugins/instance_filters.rb +10 -0
  166. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  167. data/lib/sequel/plugins/json_serializer.rb +58 -6
  168. data/lib/sequel/plugins/list.rb +12 -2
  169. data/lib/sequel/plugins/many_through_many.rb +79 -28
  170. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  171. data/lib/sequel/plugins/nested_attributes.rb +139 -63
  172. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  173. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  174. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  175. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  176. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  177. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  178. data/lib/sequel/plugins/schema.rb +7 -2
  179. data/lib/sequel/plugins/serialization.rb +98 -49
  180. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  181. data/lib/sequel/plugins/sharding.rb +21 -54
  182. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  183. data/lib/sequel/plugins/static_cache.rb +99 -0
  184. data/lib/sequel/plugins/subclasses.rb +10 -2
  185. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  186. data/lib/sequel/plugins/timestamps.rb +1 -1
  187. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  188. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  189. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  190. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  191. data/lib/sequel/sql.rb +526 -59
  192. data/lib/sequel/timezones.rb +57 -38
  193. data/lib/sequel/version.rb +1 -1
  194. data/spec/adapters/db2_spec.rb +146 -0
  195. data/spec/adapters/firebird_spec.rb +1 -1
  196. data/spec/adapters/mssql_spec.rb +142 -40
  197. data/spec/adapters/mysql_spec.rb +380 -234
  198. data/spec/adapters/oracle_spec.rb +67 -77
  199. data/spec/adapters/postgres_spec.rb +1050 -212
  200. data/spec/adapters/spec_helper.rb +8 -5
  201. data/spec/adapters/sqlite_spec.rb +139 -27
  202. data/spec/core/connection_pool_spec.rb +196 -93
  203. data/spec/core/database_spec.rb +879 -510
  204. data/spec/core/dataset_spec.rb +1415 -1086
  205. data/spec/core/expression_filters_spec.rb +554 -109
  206. data/spec/core/mock_adapter_spec.rb +449 -0
  207. data/spec/core/object_graph_spec.rb +86 -114
  208. data/spec/core/schema_generator_spec.rb +4 -4
  209. data/spec/core/schema_spec.rb +482 -38
  210. data/spec/core/spec_helper.rb +6 -48
  211. data/spec/extensions/active_model_spec.rb +13 -0
  212. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  213. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  214. data/spec/extensions/association_dependencies_spec.rb +15 -25
  215. data/spec/extensions/association_pks_spec.rb +66 -32
  216. data/spec/extensions/association_proxies_spec.rb +4 -4
  217. data/spec/extensions/caching_spec.rb +47 -51
  218. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  219. data/spec/extensions/columns_introspection_spec.rb +91 -0
  220. data/spec/extensions/composition_spec.rb +18 -13
  221. data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
  222. data/spec/extensions/dataset_associations_spec.rb +199 -0
  223. data/spec/extensions/defaults_setter_spec.rb +64 -0
  224. data/spec/extensions/dirty_spec.rb +155 -0
  225. data/spec/extensions/eager_each_spec.rb +34 -0
  226. data/spec/extensions/force_encoding_spec.rb +4 -2
  227. data/spec/extensions/hook_class_methods_spec.rb +69 -92
  228. data/spec/extensions/identity_map_spec.rb +131 -22
  229. data/spec/extensions/inflector_spec.rb +0 -4
  230. data/spec/extensions/instance_filters_spec.rb +11 -21
  231. data/spec/extensions/instance_hooks_spec.rb +72 -0
  232. data/spec/extensions/json_serializer_spec.rb +49 -6
  233. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  234. data/spec/extensions/list_spec.rb +48 -39
  235. data/spec/extensions/many_through_many_spec.rb +283 -250
  236. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  237. data/spec/extensions/migration_spec.rb +140 -35
  238. data/spec/extensions/named_timezones_spec.rb +29 -11
  239. data/spec/extensions/nested_attributes_spec.rb +251 -89
  240. data/spec/extensions/null_dataset_spec.rb +85 -0
  241. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  242. data/spec/extensions/pg_array_ops_spec.rb +105 -0
  243. data/spec/extensions/pg_array_spec.rb +196 -0
  244. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  245. data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
  246. data/spec/extensions/pg_hstore_spec.rb +195 -0
  247. data/spec/extensions/pg_inet_spec.rb +44 -0
  248. data/spec/extensions/pg_json_spec.rb +101 -0
  249. data/spec/extensions/pg_statement_cache_spec.rb +209 -0
  250. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  251. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  252. data/spec/extensions/prepared_statements_spec.rb +87 -0
  253. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  254. data/spec/extensions/pretty_table_spec.rb +7 -6
  255. data/spec/extensions/query_literals_spec.rb +168 -0
  256. data/spec/extensions/query_spec.rb +6 -0
  257. data/spec/extensions/rcte_tree_spec.rb +50 -43
  258. data/spec/extensions/schema_caching_spec.rb +41 -0
  259. data/spec/extensions/schema_dumper_spec.rb +429 -22
  260. data/spec/extensions/schema_spec.rb +25 -21
  261. data/spec/extensions/select_remove_spec.rb +38 -0
  262. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  263. data/spec/extensions/serialization_spec.rb +85 -43
  264. data/spec/extensions/server_block_spec.rb +90 -0
  265. data/spec/extensions/sharding_spec.rb +69 -143
  266. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  267. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  268. data/spec/extensions/spec_helper.rb +22 -61
  269. data/spec/extensions/sql_expr_spec.rb +29 -60
  270. data/spec/extensions/static_cache_spec.rb +145 -0
  271. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  272. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  273. data/spec/extensions/timestamps_spec.rb +6 -6
  274. data/spec/extensions/to_dot_spec.rb +4 -7
  275. data/spec/extensions/touch_spec.rb +13 -14
  276. data/spec/extensions/tree_spec.rb +11 -26
  277. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  278. data/spec/extensions/update_primary_key_spec.rb +30 -24
  279. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  280. data/spec/extensions/validation_helpers_spec.rb +16 -35
  281. data/spec/extensions/xml_serializer_spec.rb +29 -4
  282. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  283. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  284. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  285. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  286. data/spec/integration/associations_test.rb +659 -21
  287. data/spec/integration/database_test.rb +9 -3
  288. data/spec/integration/dataset_test.rb +605 -91
  289. data/spec/integration/eager_loader_test.rb +19 -21
  290. data/spec/integration/migrator_test.rb +2 -3
  291. data/spec/integration/model_test.rb +81 -2
  292. data/spec/integration/plugin_test.rb +454 -143
  293. data/spec/integration/prepared_statement_test.rb +263 -128
  294. data/spec/integration/schema_test.rb +309 -43
  295. data/spec/integration/spec_helper.rb +40 -30
  296. data/spec/integration/timezone_test.rb +38 -12
  297. data/spec/integration/transaction_test.rb +183 -8
  298. data/spec/integration/type_test.rb +18 -4
  299. data/spec/model/association_reflection_spec.rb +201 -7
  300. data/spec/model/associations_spec.rb +1067 -661
  301. data/spec/model/base_spec.rb +329 -95
  302. data/spec/model/dataset_methods_spec.rb +7 -27
  303. data/spec/model/eager_loading_spec.rb +677 -676
  304. data/spec/model/hooks_spec.rb +349 -67
  305. data/spec/model/model_spec.rb +240 -168
  306. data/spec/model/plugins_spec.rb +24 -13
  307. data/spec/model/record_spec.rb +490 -232
  308. data/spec/model/spec_helper.rb +14 -71
  309. data/spec/model/validations_spec.rb +11 -0
  310. data/spec/rcov.opts +2 -0
  311. metadata +178 -80
@@ -23,22 +23,19 @@ describe Sequel::Model, "dataset & schema" do
23
23
  end
24
24
 
25
25
  describe Sequel::Model, "table_exists?" do
26
-
27
- before(:each) do
26
+ before do
28
27
  MODEL_DB.reset
29
28
  @model = Class.new(Sequel::Model(:items))
30
29
  end
31
30
 
32
31
  it "should get the table name and question the model's db if table_exists?" do
33
- @model.should_receive(:table_name).and_return(:items)
34
- @model.db.should_receive(:table_exists?)
35
- @model.table_exists?
32
+ @model.db.should_receive(:table_exists?).and_return(false)
33
+ @model.table_exists?.should == false
36
34
  end
37
35
  end
38
36
 
39
37
  describe Sequel::Model, "create_table and schema" do
40
-
41
- before(:each) do
38
+ before do
42
39
  MODEL_DB.reset
43
40
  @model = Class.new(Sequel::Model) do
44
41
  set_schema(:items) do
@@ -60,7 +57,7 @@ describe Sequel::Model, "create_table and schema" do
60
57
 
61
58
  it "should reload the schema from the database" do
62
59
  schem = {:name=>{:type=>:string}, :price=>{:type=>:float}}
63
- @model.db.should_receive(:schema).with(:items, :reload=>true).and_return(schem.to_a.sort_by{|x| x[0].to_s})
60
+ @model.db.should_receive(:schema).with(@model.dataset, :reload=>true).and_return(schem.to_a.sort_by{|x| x[0].to_s})
64
61
  @model.create_table
65
62
  @model.db_schema.should == schem
66
63
  @model.instance_variable_get(:@columns).should == [:name, :price]
@@ -84,19 +81,27 @@ describe Sequel::Model, "create_table and schema" do
84
81
  end
85
82
 
86
83
  describe Sequel::Model, "drop_table" do
87
-
88
- before(:each) do
89
- MODEL_DB.reset
84
+ before do
90
85
  @model = Class.new(Sequel::Model(:items))
86
+ MODEL_DB.reset
91
87
  end
92
88
 
93
- it "should get the drop table SQL for the associated table and then execute the SQL." do
94
- @model.should_receive(:table_name).and_return(:items)
95
- @model.db.should_receive(:drop_table_sql).with(:items)
96
- @model.db.should_receive(:execute).and_return(:true)
89
+ it "should drop the related table" do
97
90
  @model.drop_table
91
+ MODEL_DB.sqls.should == ['DROP TABLE items']
98
92
  end
93
+ end
99
94
 
95
+ describe Sequel::Model, "drop_table?" do
96
+ before do
97
+ @model = Class.new(Sequel::Model(:items))
98
+ MODEL_DB.reset
99
+ end
100
+
101
+ it "should drop the table if it exists" do
102
+ @model.drop_table?
103
+ MODEL_DB.sqls.should == ["SELECT NULL FROM items LIMIT 1", 'DROP TABLE items']
104
+ end
100
105
  end
101
106
 
102
107
  describe Sequel::Model, "create_table!" do
@@ -106,9 +111,8 @@ describe Sequel::Model, "create_table!" do
106
111
  end
107
112
 
108
113
  it "should drop table if it exists and then create the table" do
109
- @model.should_receive(:drop_table).and_return(true)
110
- @model.should_receive(:create_table).and_return(true)
111
114
  @model.create_table!
115
+ MODEL_DB.sqls.should == ["SELECT NULL FROM items LIMIT 1", 'DROP TABLE items', 'CREATE TABLE items ()']
112
116
  end
113
117
  end
114
118
 
@@ -120,13 +124,13 @@ describe Sequel::Model, "create_table?" do
120
124
 
121
125
  it "should not create the table if it already exists" do
122
126
  @model.should_receive(:table_exists?).and_return(true)
123
- @model.should_not_receive(:create_table)
124
- @model.create_table?.should == nil
127
+ @model.create_table?
128
+ MODEL_DB.sqls.should == []
125
129
  end
126
130
 
127
131
  it "should create the table if it doesn't exist" do
128
132
  @model.should_receive(:table_exists?).and_return(false)
129
- @model.should_receive(:create_table).and_return(3)
130
- @model.create_table?.should == 3
133
+ @model.create_table?
134
+ MODEL_DB.sqls.should == ['CREATE TABLE items ()']
131
135
  end
132
136
  end
@@ -0,0 +1,38 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Dataset#select_remove" do
4
+ before do
5
+ @d = Sequel.mock.from(:test)
6
+ @d.columns :a, :b, :c
7
+ end
8
+
9
+ specify "should remove columns from the selected columns" do
10
+ @d.sql.should == 'SELECT * FROM test'
11
+ @d.select_remove(:a).sql.should == 'SELECT b, c FROM test'
12
+ @d.select_remove(:b).sql.should == 'SELECT a, c FROM test'
13
+ @d.select_remove(:c).sql.should == 'SELECT a, b FROM test'
14
+ end
15
+
16
+ specify "should work correctly if there are already columns selected" do
17
+ d = @d.select(:a, :b, :c)
18
+ d.columns :a, :b, :c
19
+ d.select_remove(:c).sql.should == 'SELECT a, b FROM test'
20
+ end
21
+
22
+ specify "should have no effect if the columns given are not currently selected" do
23
+ @d.select_remove(:d).sql.should == 'SELECT a, b, c FROM test'
24
+ end
25
+
26
+ specify "should handle expressions where Sequel can't determine the alias by itself" do
27
+ d = @d.select(:a, :b.sql_function, :c.as(:b))
28
+ d.columns :a, :"b()", :b
29
+ d.select_remove(:"b()").sql.should == 'SELECT a, c AS b FROM test'
30
+ end
31
+
32
+ specify "should remove expressions if given exact expressions" do
33
+ d = @d.select(:a, :b.sql_function, :c.as(:b))
34
+ d.columns :a, :"b()", :b
35
+ d.select_remove(:b.sql_function).sql.should == 'SELECT a, c AS b FROM test'
36
+ d.select_remove(:c.as(:b)).sql.should == 'SELECT a, b() FROM test'
37
+ end
38
+ end
@@ -0,0 +1,72 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+ require 'yaml'
3
+
4
+ describe "serialization_modification_detection plugin" do
5
+ before do
6
+ @c = Class.new(Sequel::Model(:items))
7
+ @c.class_eval do
8
+ columns :id, :h
9
+ plugin :serialization, :yaml, :h
10
+ plugin :serialization_modification_detection
11
+ end
12
+ @o1 = @c.new(:h=>{})
13
+ @o2 = @c.load(:id=>1, :h=>"--- {}\n\n")
14
+ @o3 = @c.new
15
+ @o4 = @c.load(:id=>1, :h=>nil)
16
+ MODEL_DB.reset
17
+ end
18
+
19
+ it "should not detect columns that haven't been changed" do
20
+ @o1.changed_columns.should == []
21
+ @o1.h.should == {}
22
+ @o1.h[1] = 2
23
+ @o1.h.clear
24
+ @o1.changed_columns.should == []
25
+
26
+ @o2.changed_columns.should == []
27
+ @o2.h.should == {}
28
+ @o2.h[1] = 2
29
+ @o2.h.clear
30
+ @o2.changed_columns.should == []
31
+ end
32
+
33
+ it "should detect columns that have been changed" do
34
+ @o1.changed_columns.should == []
35
+ @o1.h.should == {}
36
+ @o1.h[1] = 2
37
+ @o1.changed_columns.should == [:h]
38
+
39
+ @o2.changed_columns.should == []
40
+ @o2.h.should == {}
41
+ @o2.h[1] = 2
42
+ @o2.changed_columns.should == [:h]
43
+
44
+ @o3.changed_columns.should == []
45
+ @o3.h.should == nil
46
+ @o3.h = {}
47
+ @o3.changed_columns.should == [:h]
48
+
49
+ @o4.changed_columns.should == []
50
+ @o4.h.should == nil
51
+ @o4.h = {}
52
+ @o4.changed_columns.should == [:h]
53
+ end
54
+
55
+ it "should report correct changed_columns after saving" do
56
+ @o1.h[1] = 2
57
+ @o1.save
58
+ @o1.changed_columns.should == []
59
+
60
+ @o2.h[1] = 2
61
+ @o2.save_changes
62
+ @o2.changed_columns.should == []
63
+
64
+ @o3.h = {1=>2}
65
+ @o3.save
66
+ @o3.changed_columns.should == []
67
+
68
+ @o4.h = {1=>2}
69
+ @o4.save
70
+ @o4.changed_columns.should == []
71
+ end
72
+ end
@@ -9,10 +9,6 @@ else
9
9
  describe "Serialization plugin" do
10
10
  before do
11
11
  @c = Class.new(Sequel::Model(:items)) do
12
- include(Module.new do
13
- def before_save
14
- end
15
- end)
16
12
  no_primary_key
17
13
  columns :id, :abc, :def, :ghi
18
14
  end
@@ -22,11 +18,11 @@ describe "Serialization plugin" do
22
18
  it "should allow setting additional serializable attributes via plugin :serialization call" do
23
19
  @c.plugin :serialization, :yaml, :abc
24
20
  @c.create(:abc => 1, :def=> 2)
25
- MODEL_DB.sqls.last.should =~ /INSERT INTO items \((abc, def|def, abc)\) VALUES \(('--- 1\n', 2|2, '--- 1\n')\)/
21
+ MODEL_DB.sqls.last.should =~ /INSERT INTO items \((abc, def|def, abc)\) VALUES \(('--- 1\n(\.\.\.\n)?', 2|2, '--- 1\n(\.\.\.\n)?')\)/
26
22
 
27
23
  @c.plugin :serialization, :marshal, :def
28
24
  @c.create(:abc => 1, :def=> 1)
29
- MODEL_DB.sqls.last.should =~ /INSERT INTO items \((abc, def|def, abc)\) VALUES \(('--- 1\n', 'BAhpBg==\n'|'BAhpBg==\n', '--- 1\n')\)/
25
+ MODEL_DB.sqls.last.should =~ /INSERT INTO items \((abc, def|def, abc)\) VALUES \(('--- 1\n(\.\.\.\n)?', 'BAhpBg==\n'|'BAhpBg==\n', '--- 1\n(\.\.\.\n)?')\)/
30
26
 
31
27
  @c.plugin :serialization, :json, :ghi
32
28
  @c.create(:ghi => [123])
@@ -38,15 +34,7 @@ describe "Serialization plugin" do
38
34
  @c.create(:abc => 1)
39
35
  @c.create(:abc => "hello")
40
36
 
41
- MODEL_DB.sqls.should == [ \
42
- "INSERT INTO items (abc) VALUES ('--- 1\n')", \
43
- "INSERT INTO items (abc) VALUES ('--- hello\n')", \
44
- ]
45
- end
46
-
47
- it "serialization_format should be the serialization format used" do
48
- @c.plugin :serialization, :yaml, :abc
49
- @c.serialization_format.should == :yaml
37
+ MODEL_DB.sqls.map{|s| s.sub("...\n", '')}.should == ["INSERT INTO items (abc) VALUES ('--- 1\n')", "INSERT INTO items (abc) VALUES ('--- hello\n')"]
50
38
  end
51
39
 
52
40
  it "serialized_columns should be the columns serialized" do
@@ -78,15 +66,21 @@ describe "Serialization plugin" do
78
66
  ]
79
67
  end
80
68
 
69
+ it "should allow serializing attributes using arbitrary callable" do
70
+ @c.plugin :serialization, [proc{|s| s.reverse}, proc{}], :abc
71
+ @c.create(:abc => "hello")
72
+ MODEL_DB.sqls.should == ["INSERT INTO items (abc) VALUES ('olleh')"]
73
+ end
74
+
75
+ it "should raise an error if specificing serializer as an unregistered symbol" do
76
+ proc{@c.plugin :serialization, :foo, :abc}.should raise_error(Sequel::Error)
77
+ end
78
+
81
79
  it "should translate values to and from yaml serialization format using accessor methods" do
82
80
  @c.set_primary_key :id
83
81
  @c.plugin :serialization, :yaml, :abc, :def
84
82
  vals = nil
85
-
86
- ds = @c.dataset
87
- def ds.fetch_rows(sql, &block)
88
- block.call(:id => 1, :abc => "--- 1\n", :def => "--- hello\n")
89
- end
83
+ @c.dataset._fetch = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
90
84
 
91
85
  o = @c.first
92
86
  o.id.should == 1
@@ -97,18 +91,16 @@ describe "Serialization plugin" do
97
91
 
98
92
  o.update(:abc => 23)
99
93
  @c.create(:abc => [1, 2, 3])
100
- MODEL_DB.sqls.should == ["UPDATE items SET abc = '--- 23\n' WHERE (id = 1)",
101
- "INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')"]
94
+ MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
95
+ "UPDATE items SET abc = '#{23.to_yaml}' WHERE (id = 1)",
96
+ "INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')",
97
+ "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
102
98
  end
103
99
 
104
100
  it "should translate values to and from marshal serialization format using accessor methods" do
105
101
  @c.set_primary_key :id
106
102
  @c.plugin :serialization, :marshal, :abc, :def
107
-
108
- ds = @c.dataset
109
- def ds.fetch_rows(sql, &block)
110
- block.call(:id => 1, :abc =>[Marshal.dump(1)].pack('m'), :def =>[Marshal.dump('hello')].pack('m'))
111
- end
103
+ @c.dataset._fetch = [:id => 1, :abc =>[Marshal.dump(1)].pack('m'), :def =>[Marshal.dump('hello')].pack('m')]
112
104
 
113
105
  o = @c.first
114
106
  o.id.should == 1
@@ -119,18 +111,16 @@ describe "Serialization plugin" do
119
111
 
120
112
  o.update(:abc => 23)
121
113
  @c.create(:abc => [1, 2, 3])
122
- MODEL_DB.sqls.should == ["UPDATE items SET abc = '#{[Marshal.dump(23)].pack('m')}' WHERE (id = 1)",
123
- "INSERT INTO items (abc) VALUES ('#{[Marshal.dump([1, 2, 3])].pack('m')}')"]
114
+ MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
115
+ "UPDATE items SET abc = '#{[Marshal.dump(23)].pack('m')}' WHERE (id = 1)",
116
+ "INSERT INTO items (abc) VALUES ('#{[Marshal.dump([1, 2, 3])].pack('m')}')",
117
+ "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
124
118
  end
125
119
 
126
120
  it "should translate values to and from json serialization format using accessor methods" do
127
121
  @c.set_primary_key :id
128
122
  @c.plugin :serialization, :json, :abc, :def
129
-
130
- ds = @c.dataset
131
- def ds.fetch_rows(sql, &block)
132
- block.call(:id => 1, :abc => [1].to_json, :def => ["hello"].to_json)
133
- end
123
+ @c.dataset._fetch = {:id => 1, :abc => [1].to_json, :def => ["hello"].to_json}
134
124
 
135
125
  o = @c.first
136
126
  o.id.should == 1
@@ -142,18 +132,59 @@ describe "Serialization plugin" do
142
132
  o.update(:abc => [23])
143
133
  @c.create(:abc => [1,2,3])
144
134
 
145
- MODEL_DB.sqls.should == ["UPDATE items SET abc = '#{[23].to_json}' WHERE (id = 1)",
146
- "INSERT INTO items (abc) VALUES ('#{[1,2,3].to_json}')"]
135
+ MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
136
+ "UPDATE items SET abc = '#{[23].to_json}' WHERE (id = 1)",
137
+ "INSERT INTO items (abc) VALUES ('#{[1,2,3].to_json}')",
138
+ "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
139
+ end
140
+
141
+ it "should translate values to and from arbitrary callables using accessor methods" do
142
+ @c.set_primary_key :id
143
+ @c.plugin :serialization, [proc{|s| s.reverse}, proc{|s| s.reverse}], :abc, :def
144
+ @c.dataset._fetch = {:id => 1, :abc => 'cba', :def => 'olleh'}
145
+
146
+ o = @c.first
147
+ o.id.should == 1
148
+ o.abc.should == 'abc'
149
+ o.abc.should == 'abc'
150
+ o.def.should == "hello"
151
+ o.def.should == "hello"
152
+
153
+ o.update(:abc => 'foo')
154
+ @c.create(:abc => 'bar')
155
+
156
+ MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
157
+ "UPDATE items SET abc = 'oof' WHERE (id = 1)",
158
+ "INSERT INTO items (abc) VALUES ('rab')",
159
+ "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
160
+ end
161
+
162
+ it "should handle registration of custom serializer/deserializer pairs" do
163
+ @c.set_primary_key :id
164
+ Sequel::Plugins::Serialization.register_format(:reverse, proc{|s| s.reverse}, proc{|s| s.reverse})
165
+ @c.plugin :serialization, :reverse, :abc, :def
166
+ @c.dataset._fetch = {:id => 1, :abc => 'cba', :def => 'olleh'}
167
+
168
+ o = @c.first
169
+ o.id.should == 1
170
+ o.abc.should == 'abc'
171
+ o.abc.should == 'abc'
172
+ o.def.should == "hello"
173
+ o.def.should == "hello"
174
+
175
+ o.update(:abc => 'foo')
176
+ @c.create(:abc => 'bar')
177
+
178
+ MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
179
+ "UPDATE items SET abc = 'oof' WHERE (id = 1)",
180
+ "INSERT INTO items (abc) VALUES ('rab')",
181
+ "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
147
182
  end
148
183
 
149
184
  it "should copy serialization formats and columns to subclasses" do
150
185
  @c.set_primary_key :id
151
186
  @c.plugin :serialization, :yaml, :abc, :def
152
-
153
- ds = @c.dataset
154
- def ds.fetch_rows(sql, &block)
155
- block.call(:id => 1, :abc => "--- 1\n", :def => "--- hello\n")
156
- end
187
+ @c.dataset._fetch = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
157
188
 
158
189
  o = Class.new(@c).first
159
190
  o.id.should == 1
@@ -164,8 +195,10 @@ describe "Serialization plugin" do
164
195
 
165
196
  o.update(:abc => 23)
166
197
  Class.new(@c).create(:abc => [1, 2, 3])
167
- MODEL_DB.sqls.should == ["UPDATE items SET abc = '--- 23\n' WHERE (id = 1)",
168
- "INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')"]
198
+ MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
199
+ "UPDATE items SET abc = '#{23.to_yaml}' WHERE (id = 1)",
200
+ "INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')",
201
+ "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
169
202
  end
170
203
 
171
204
  it "should clear the deserialized columns when refreshing" do
@@ -179,6 +212,15 @@ describe "Serialization plugin" do
179
212
  o.deserialized_values.length.should == 0
180
213
  end
181
214
 
215
+ it "should clear the deserialized columns when refreshing after saving a new object" do
216
+ @c.set_primary_key :id
217
+ @c.plugin :serialization, :yaml, :abc, :def
218
+ o = @c.new(:abc => "--- 1\n", :def => "--- hello\n")
219
+ o.deserialized_values.length.should == 2
220
+ o.save
221
+ o.deserialized_values.length.should == 0
222
+ end
223
+
182
224
  it "should raise an error if calling internal serialization methods with bad columns" do
183
225
  @c.set_primary_key :id
184
226
  @c.plugin :serialization
@@ -0,0 +1,90 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ shared_examples_for "Database#with_server" do
4
+ specify "should set the default server to use in the block" do
5
+ @db.with_server(:a){@db[:t].all}
6
+ @db.sqls.should == ["SELECT * FROM t -- a"]
7
+ @db.with_server(:b){@db[:t].all}
8
+ @db.sqls.should == ["SELECT * FROM t -- b"]
9
+ end
10
+
11
+ specify "should have no affect after the block" do
12
+ @db.with_server(:a){@db[:t].all}
13
+ @db.sqls.should == ["SELECT * FROM t -- a"]
14
+ @db[:t].all
15
+ @db.sqls.should == ["SELECT * FROM t"]
16
+ end
17
+
18
+ specify "should not override specific server inside the block" do
19
+ @db.with_server(:a){@db[:t].server(:b).all}
20
+ @db.sqls.should == ["SELECT * FROM t -- b"]
21
+ end
22
+
23
+ specify "should work correctly when blocks are nested" do
24
+ @db[:t].all
25
+ @db.with_server(:a) do
26
+ @db[:t].all
27
+ @db.with_server(:b){@db[:t].all}
28
+ @db[:t].all
29
+ end
30
+ @db[:t].all
31
+ @db.sqls.should == ["SELECT * FROM t", "SELECT * FROM t -- a", "SELECT * FROM t -- b", "SELECT * FROM t -- a", "SELECT * FROM t"]
32
+ end
33
+
34
+ specify "should work correctly for inserts/updates/deletes" do
35
+ @db.with_server(:a) do
36
+ @db[:t].insert
37
+ @db[:t].update(:a=>1)
38
+ @db[:t].delete
39
+ end
40
+ @db.sqls.should == ["INSERT INTO t DEFAULT VALUES -- a", "UPDATE t SET a = 1 -- a", "DELETE FROM t -- a"]
41
+ end
42
+ end
43
+
44
+ describe "Database#with_server single threaded" do
45
+ before do
46
+ @db = Sequel.mock(:single_threaded=>true, :servers=>{:a=>{}, :b=>{}})
47
+ @db.extend Sequel::ServerBlock
48
+ end
49
+
50
+ it_should_behave_like "Database#with_server"
51
+ end
52
+
53
+ describe "Database#with_server multi threaded" do
54
+ before do
55
+ @db = Sequel.mock(:servers=>{:a=>{}, :b=>{}, :c=>{}, :d=>{}})
56
+ @db.extend Sequel::ServerBlock
57
+ end
58
+
59
+ it_should_behave_like "Database#with_server"
60
+
61
+ specify "should respect multithreaded access" do
62
+ q, q1 = Queue.new, Queue.new
63
+
64
+ t = nil
65
+ @db[:t].all
66
+ @db.with_server(:a) do
67
+ @db[:t].all
68
+ t = Thread.new do
69
+ @db[:t].all
70
+ @db.with_server(:c) do
71
+ @db[:t].all
72
+ @db.with_server(:d){@db[:t].all}
73
+ q.push nil
74
+ q1.pop
75
+ @db[:t].all
76
+ end
77
+ @db[:t].all
78
+ end
79
+ q.pop
80
+ @db.with_server(:b){@db[:t].all}
81
+ @db[:t].all
82
+ end
83
+ @db[:t].all
84
+ q1.push nil
85
+ t.join
86
+ @db.sqls.should == ["SELECT * FROM t", "SELECT * FROM t -- a", "SELECT * FROM t", "SELECT * FROM t -- c", "SELECT * FROM t -- d",
87
+ "SELECT * FROM t -- b", "SELECT * FROM t -- a", "SELECT * FROM t", "SELECT * FROM t -- c", "SELECT * FROM t"]
88
+ end
89
+ end
90
+