sequel 2.11.0 → 2.12.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 (162) hide show
  1. data/CHANGELOG +168 -0
  2. data/README.rdoc +77 -95
  3. data/Rakefile +100 -80
  4. data/bin/sequel +2 -1
  5. data/doc/advanced_associations.rdoc +23 -32
  6. data/doc/cheat_sheet.rdoc +23 -40
  7. data/doc/dataset_filtering.rdoc +6 -6
  8. data/doc/prepared_statements.rdoc +22 -22
  9. data/doc/release_notes/2.12.0.txt +534 -0
  10. data/doc/schema.rdoc +3 -1
  11. data/doc/sharding.rdoc +8 -8
  12. data/doc/virtual_rows.rdoc +65 -0
  13. data/lib/sequel.rb +1 -1
  14. data/lib/{sequel_core → sequel}/adapters/ado.rb +3 -3
  15. data/lib/{sequel_core → sequel}/adapters/db2.rb +0 -0
  16. data/lib/{sequel_core → sequel}/adapters/dbi.rb +1 -1
  17. data/lib/{sequel_core → sequel}/adapters/do.rb +9 -5
  18. data/lib/{sequel_core → sequel}/adapters/do/mysql.rb +1 -1
  19. data/lib/{sequel_core → sequel}/adapters/do/postgres.rb +1 -1
  20. data/lib/{sequel_core → sequel}/adapters/do/sqlite.rb +1 -1
  21. data/lib/{sequel_core → sequel}/adapters/firebird.rb +84 -80
  22. data/lib/{sequel_core → sequel}/adapters/informix.rb +1 -1
  23. data/lib/{sequel_core → sequel}/adapters/jdbc.rb +21 -14
  24. data/lib/{sequel_core → sequel}/adapters/jdbc/h2.rb +14 -13
  25. data/lib/{sequel_core → sequel}/adapters/jdbc/mysql.rb +1 -1
  26. data/lib/{sequel_core → sequel}/adapters/jdbc/oracle.rb +1 -1
  27. data/lib/{sequel_core → sequel}/adapters/jdbc/postgresql.rb +1 -1
  28. data/lib/{sequel_core → sequel}/adapters/jdbc/sqlite.rb +1 -1
  29. data/lib/{sequel_core → sequel}/adapters/mysql.rb +60 -39
  30. data/lib/{sequel_core → sequel}/adapters/odbc.rb +8 -4
  31. data/lib/{sequel_core → sequel}/adapters/openbase.rb +0 -0
  32. data/lib/{sequel_core → sequel}/adapters/oracle.rb +38 -7
  33. data/lib/{sequel_core → sequel}/adapters/postgres.rb +24 -24
  34. data/lib/{sequel_core → sequel}/adapters/shared/mssql.rb +5 -5
  35. data/lib/{sequel_core → sequel}/adapters/shared/mysql.rb +126 -71
  36. data/lib/{sequel_core → sequel}/adapters/shared/oracle.rb +7 -10
  37. data/lib/{sequel_core → sequel}/adapters/shared/postgres.rb +159 -125
  38. data/lib/{sequel_core → sequel}/adapters/shared/progress.rb +1 -2
  39. data/lib/{sequel_core → sequel}/adapters/shared/sqlite.rb +72 -67
  40. data/lib/{sequel_core → sequel}/adapters/sqlite.rb +11 -7
  41. data/lib/{sequel_core → sequel}/adapters/utils/date_format.rb +0 -0
  42. data/lib/{sequel_core → sequel}/adapters/utils/stored_procedures.rb +0 -0
  43. data/lib/{sequel_core → sequel}/adapters/utils/unsupported.rb +19 -0
  44. data/lib/{sequel_core → sequel}/connection_pool.rb +7 -5
  45. data/lib/sequel/core.rb +221 -0
  46. data/lib/{sequel_core → sequel}/core_sql.rb +91 -49
  47. data/lib/{sequel_core → sequel}/database.rb +264 -149
  48. data/lib/{sequel_core/schema/generator.rb → sequel/database/schema_generator.rb} +6 -2
  49. data/lib/{sequel_core/database/schema.rb → sequel/database/schema_methods.rb} +12 -12
  50. data/lib/sequel/database/schema_sql.rb +224 -0
  51. data/lib/{sequel_core → sequel}/dataset.rb +78 -236
  52. data/lib/{sequel_core → sequel}/dataset/convenience.rb +99 -61
  53. data/lib/{sequel_core/object_graph.rb → sequel/dataset/graph.rb} +16 -14
  54. data/lib/{sequel_core → sequel}/dataset/prepared_statements.rb +1 -1
  55. data/lib/{sequel_core → sequel}/dataset/sql.rb +150 -99
  56. data/lib/sequel/deprecated.rb +593 -0
  57. data/lib/sequel/deprecated_migration.rb +91 -0
  58. data/lib/sequel/exceptions.rb +48 -0
  59. data/lib/sequel/extensions/blank.rb +42 -0
  60. data/lib/{sequel_model → sequel/extensions}/inflector.rb +8 -1
  61. data/lib/{sequel_core → sequel/extensions}/migration.rb +1 -1
  62. data/lib/{sequel_core/dataset → sequel/extensions}/pagination.rb +0 -0
  63. data/lib/{sequel_core → sequel/extensions}/pretty_table.rb +7 -0
  64. data/lib/{sequel_core/dataset → sequel/extensions}/query.rb +7 -0
  65. data/lib/sequel/extensions/string_date_time.rb +47 -0
  66. data/lib/sequel/metaprogramming.rb +43 -0
  67. data/lib/sequel/model.rb +110 -0
  68. data/lib/sequel/model/associations.rb +1300 -0
  69. data/lib/sequel/model/base.rb +937 -0
  70. data/lib/sequel/model/deprecated.rb +204 -0
  71. data/lib/sequel/model/deprecated_hooks.rb +103 -0
  72. data/lib/sequel/model/deprecated_inflector.rb +335 -0
  73. data/lib/sequel/model/deprecated_validations.rb +388 -0
  74. data/lib/sequel/model/errors.rb +39 -0
  75. data/lib/{sequel_model → sequel/model}/exceptions.rb +4 -4
  76. data/lib/sequel/model/inflections.rb +208 -0
  77. data/lib/sequel/model/plugins.rb +76 -0
  78. data/lib/sequel/plugins/caching.rb +122 -0
  79. data/lib/sequel/plugins/hook_class_methods.rb +122 -0
  80. data/lib/sequel/plugins/schema.rb +53 -0
  81. data/lib/sequel/plugins/serialization.rb +117 -0
  82. data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
  83. data/lib/sequel/plugins/validation_class_methods.rb +384 -0
  84. data/lib/sequel/plugins/validation_helpers.rb +150 -0
  85. data/lib/{sequel_core → sequel}/sql.rb +125 -190
  86. data/lib/{sequel_core → sequel}/version.rb +2 -1
  87. data/lib/sequel_core.rb +1 -172
  88. data/lib/sequel_model.rb +1 -91
  89. data/spec/adapters/firebird_spec.rb +5 -5
  90. data/spec/adapters/informix_spec.rb +1 -1
  91. data/spec/adapters/mysql_spec.rb +128 -42
  92. data/spec/adapters/oracle_spec.rb +47 -19
  93. data/spec/adapters/postgres_spec.rb +64 -52
  94. data/spec/adapters/spec_helper.rb +1 -1
  95. data/spec/adapters/sqlite_spec.rb +12 -17
  96. data/spec/{sequel_core → core}/connection_pool_spec.rb +10 -10
  97. data/spec/{sequel_core → core}/core_ext_spec.rb +19 -19
  98. data/spec/{sequel_core → core}/core_sql_spec.rb +68 -71
  99. data/spec/{sequel_core → core}/database_spec.rb +135 -99
  100. data/spec/{sequel_core → core}/dataset_spec.rb +398 -242
  101. data/spec/{sequel_core → core}/expression_filters_spec.rb +13 -13
  102. data/spec/core/migration_spec.rb +263 -0
  103. data/spec/{sequel_core → core}/object_graph_spec.rb +10 -10
  104. data/spec/{sequel_core → core}/pretty_table_spec.rb +2 -2
  105. data/spec/{sequel_core → core}/schema_generator_spec.rb +0 -0
  106. data/spec/{sequel_core → core}/schema_spec.rb +8 -10
  107. data/spec/{sequel_core → core}/spec_helper.rb +29 -2
  108. data/spec/{sequel_core → core}/version_spec.rb +0 -0
  109. data/spec/extensions/blank_spec.rb +67 -0
  110. data/spec/extensions/caching_spec.rb +201 -0
  111. data/spec/{sequel_model/hooks_spec.rb → extensions/hook_class_methods_spec.rb} +8 -23
  112. data/spec/{sequel_model → extensions}/inflector_spec.rb +3 -0
  113. data/spec/{sequel_core → extensions}/migration_spec.rb +4 -4
  114. data/spec/extensions/pagination_spec.rb +99 -0
  115. data/spec/extensions/pretty_table_spec.rb +91 -0
  116. data/spec/extensions/query_spec.rb +85 -0
  117. data/spec/{sequel_model → extensions}/schema_spec.rb +22 -1
  118. data/spec/extensions/serialization_spec.rb +109 -0
  119. data/spec/extensions/single_table_inheritance_spec.rb +53 -0
  120. data/spec/{sequel_model → extensions}/spec_helper.rb +13 -4
  121. data/spec/extensions/string_date_time_spec.rb +93 -0
  122. data/spec/{sequel_model/validations_spec.rb → extensions/validation_class_methods_spec.rb} +15 -103
  123. data/spec/extensions/validation_helpers_spec.rb +291 -0
  124. data/spec/integration/dataset_test.rb +31 -0
  125. data/spec/integration/eager_loader_test.rb +17 -30
  126. data/spec/integration/schema_test.rb +8 -5
  127. data/spec/integration/spec_helper.rb +17 -0
  128. data/spec/integration/transaction_test.rb +68 -0
  129. data/spec/{sequel_model → model}/association_reflection_spec.rb +0 -0
  130. data/spec/{sequel_model → model}/associations_spec.rb +23 -10
  131. data/spec/{sequel_model → model}/base_spec.rb +29 -20
  132. data/spec/{sequel_model → model}/caching_spec.rb +16 -14
  133. data/spec/{sequel_model → model}/dataset_methods_spec.rb +0 -0
  134. data/spec/{sequel_model → model}/eager_loading_spec.rb +8 -8
  135. data/spec/model/hooks_spec.rb +472 -0
  136. data/spec/model/inflector_spec.rb +126 -0
  137. data/spec/{sequel_model → model}/model_spec.rb +25 -20
  138. data/spec/model/plugins_spec.rb +142 -0
  139. data/spec/{sequel_model → model}/record_spec.rb +121 -62
  140. data/spec/model/schema_spec.rb +92 -0
  141. data/spec/model/spec_helper.rb +124 -0
  142. data/spec/model/validations_spec.rb +1080 -0
  143. metadata +136 -107
  144. data/lib/sequel_core/core_ext.rb +0 -217
  145. data/lib/sequel_core/dataset/callback.rb +0 -13
  146. data/lib/sequel_core/dataset/schema.rb +0 -15
  147. data/lib/sequel_core/deprecated.rb +0 -26
  148. data/lib/sequel_core/exceptions.rb +0 -44
  149. data/lib/sequel_core/schema.rb +0 -2
  150. data/lib/sequel_core/schema/sql.rb +0 -325
  151. data/lib/sequel_model/association_reflection.rb +0 -267
  152. data/lib/sequel_model/associations.rb +0 -499
  153. data/lib/sequel_model/base.rb +0 -539
  154. data/lib/sequel_model/caching.rb +0 -82
  155. data/lib/sequel_model/dataset_methods.rb +0 -26
  156. data/lib/sequel_model/eager_loading.rb +0 -370
  157. data/lib/sequel_model/hooks.rb +0 -101
  158. data/lib/sequel_model/plugins.rb +0 -62
  159. data/lib/sequel_model/record.rb +0 -568
  160. data/lib/sequel_model/schema.rb +0 -49
  161. data/lib/sequel_model/validations.rb +0 -429
  162. data/spec/sequel_model/plugins_spec.rb +0 -80
@@ -1,10 +1,11 @@
1
1
  module Sequel
2
2
  MAJOR = 2
3
- MINOR = 11
3
+ MINOR = 12
4
4
  TINY = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join('.')
7
7
 
8
+ # The version of Sequel you are using, as a string (e.g. "2.11.0")
8
9
  def self.version
9
10
  VERSION
10
11
  end
data/lib/sequel_core.rb CHANGED
@@ -1,172 +1 @@
1
- %w'bigdecimal bigdecimal/util date enumerator thread time uri yaml'.each do |f|
2
- require f
3
- end
4
- %w"core_ext sql core_sql connection_pool exceptions pretty_table
5
- dataset migration schema database object_graph version".each do |f|
6
- require "sequel_core/#{f}"
7
- end
8
-
9
- # Top level module for Sequel
10
- #
11
- # There are some class methods that are added via metaprogramming, one for
12
- # each supported adapter. For example:
13
- #
14
- # DB = Sequel.sqlite # Memory database
15
- # DB = Sequel.sqlite('blog.db')
16
- # DB = Sequel.postgres('database_name', :user=>'user',
17
- # :password=>'password', :host=>'host', :port=>5432,
18
- # :max_connections=>10)
19
- #
20
- # If a block is given to these methods, it is passed the opened Database
21
- # object, which is closed (disconnected) when the block exits. For example:
22
- #
23
- # Sequel.sqlite('blog.db'){|db| puts db.users.count}
24
- #
25
- # Sequel converts the column type tinyint to a boolean by default,
26
- # you can override the conversion to use tinyint as an integer:
27
- #
28
- # Sequel.convert_tinyint_to_bool = false
29
- #
30
- # Sequel converts two digit years in Dates and DateTimes by default,
31
- # so 01/02/03 is interpreted at January 2nd, 2003, and 12/13/99 is interpreted
32
- # as December 13, 1999.. You can override this # to treat those dates as
33
- # January 2nd, 0003 and December 13, 0099, respectively, by setting:
34
- #
35
- # Sequel.convert_two_digit_years = false
36
- #
37
- # Sequel can use either Time or DateTime for times returned from the
38
- # database. It defaults to Time. To change it to DateTime, use:
39
- #
40
- # Sequel.datetime_class = DateTime
41
- module Sequel
42
- @convert_tinyint_to_bool = true
43
- @convert_two_digit_years = true
44
- @datetime_class = Time
45
-
46
- metaattr_accessor :convert_tinyint_to_bool
47
- metaattr_accessor :convert_two_digit_years
48
- metaattr_accessor :datetime_class
49
-
50
- # Creates a new database object based on the supplied connection string
51
- # and optional arguments. The specified scheme determines the database
52
- # class used, and the rest of the string specifies the connection options.
53
- # For example:
54
- #
55
- # DB = Sequel.connect('sqlite:/') # Memory database
56
- # DB = Sequel.connect('sqlite://blog.db') # ./blog.db
57
- # DB = Sequel.connect('sqlite:///blog.db') # /blog.db
58
- # DB = Sequel.connect('postgres://user:password@host:port/database_name')
59
- # DB = Sequel.connect('sqlite:///blog.db', :max_connections=>10)
60
- #
61
- # If a block is given, it is passed the opened Database object, which is
62
- # closed when the block exits. For example:
63
- #
64
- # Sequel.connect('sqlite://blog.db'){|db| puts db.users.count}
65
- #
66
- # This is also aliased as Sequel.open.
67
- def self.connect(*args, &block)
68
- Database.connect(*args, &block)
69
- end
70
- metaalias :open, :connect
71
-
72
- # Set the method to call on identifiers going into the database. This affects
73
- # the literalization of identifiers by calling this method on them before they are input.
74
- # Sequel upcases identifiers in all SQL strings for most databases, so to turn that off:
75
- #
76
- # Sequel.identifier_input_method = nil
77
- #
78
- # to downcase instead:
79
- #
80
- # Sequel.identifier_input_method = :downcase
81
- #
82
- # Other string methods work as well.
83
- def self.identifier_input_method=(value)
84
- Database.identifier_input_method = value
85
- end
86
-
87
- # Set the method to call on identifiers coming out of the database. This affects
88
- # the literalization of identifiers by calling this method on them when they are
89
- # retrieved from the database. Sequel downcases identifiers retrieved for most
90
- # databases, so to turn that off:
91
- #
92
- # Sequel.identifier_output_method = nil
93
- #
94
- # to upcase instead:
95
- #
96
- # Sequel.identifier_output_method = :upcase
97
- #
98
- # Other string methods work as well.
99
- def self.identifier_output_method=(value)
100
- Database.identifier_output_method = value
101
- end
102
-
103
- # Set whether to quote identifiers for all databases by default. By default,
104
- # Sequel quotes identifiers in all SQL strings, so to turn that off:
105
- #
106
- # Sequel.quote_identifiers = false
107
- def self.quote_identifiers=(value)
108
- Database.quote_identifiers = value
109
- end
110
-
111
- # Set whether to set the single threaded mode for all databases by default. By default,
112
- # Sequel uses a threadsafe connection pool, which isn't as fast as the
113
- # single threaded connection pool. If your program will only have one thread,
114
- # and speed is a priority, you may want to set this to true:
115
- #
116
- # Sequel.single_threaded = true
117
- def self.single_threaded=(value)
118
- Database.single_threaded = value
119
- end
120
-
121
- # Set whether to upcase identifiers for all databases by default. By default,
122
- # Sequel upcases identifiers unless the database folds unquoted identifiers to
123
- # lower case (MySQL, PostgreSQL, and SQLite).
124
- #
125
- # Sequel.upcase_identifiers = false
126
- #
127
- # This will set the indentifier_input_method to :upcase if value is true
128
- # or nil if value is false.
129
- def self.upcase_identifiers=(value)
130
- Database.upcase_identifiers = value
131
- end
132
-
133
- # Always returns false, since ParseTree support has been removed.
134
- def self.use_parse_tree
135
- false
136
- end
137
-
138
- # Raises an error if attempting to turn ParseTree support on (since it no longer exists).
139
- # Otherwise, is a no-op.
140
- def self.use_parse_tree=(val)
141
- raise(Error, 'ParseTree support has been removed from Sequel') if val
142
- end
143
-
144
- ### Private Class Methods ###
145
-
146
- # Helper method that the database adapter class methods that are added to Sequel via
147
- # metaprogramming use to parse arguments.
148
- def self.adapter_method(adapter, *args, &block) # :nodoc:
149
- raise(::Sequel::Error, "Wrong number of arguments, 0-2 arguments valid") if args.length > 2
150
- opts = {:adapter=>adapter.to_sym}
151
- opts[:database] = args.shift if args.length >= 1 && !(args[0].is_a?(Hash))
152
- if Hash === (arg = args[0])
153
- opts.merge!(arg)
154
- elsif !arg.nil?
155
- raise ::Sequel::Error, "Wrong format of arguments, either use (), (String), (Hash), or (String, Hash)"
156
- end
157
- connect(opts, &block)
158
- end
159
-
160
- # Method that adds a database adapter class method to Sequel that calls
161
- # Sequel.adapter_method.
162
- def self.def_adapter_method(*adapters) # :nodoc:
163
- adapters.each do |adapter|
164
- instance_eval("def #{adapter}(*args, &block); adapter_method('#{adapter}', *args, &block) end")
165
- end
166
- end
167
-
168
- private_class_method :adapter_method, :def_adapter_method
169
-
170
- # Add the database adapter class methods to Sequel via metaprogramming
171
- def_adapter_method(*Database::ADAPTERS)
172
- end
1
+ require 'sequel/core'
data/lib/sequel_model.rb CHANGED
@@ -1,91 +1 @@
1
- require 'sequel_core'
2
- %w"inflector base hooks record schema association_reflection dataset_methods
3
- associations caching plugins validations eager_loading exceptions".each do |f|
4
- require "sequel_model/#{f}"
5
- end
6
-
7
- module Sequel
8
- # Holds the nameless subclasses that are created with
9
- # Sequel::Model(), necessary for reopening subclasses with the
10
- # Sequel::Model() superclass specified.
11
- @models = {}
12
-
13
- # Lets you create a Model subclass with its dataset already set.
14
- # source can be an existing dataset or a symbol (in which case
15
- # it will create a dataset using the default database with
16
- # source as the table name).
17
- #
18
- # Example:
19
- # class Comment < Sequel::Model(:something)
20
- # table_name # => :something
21
- # end
22
- def self.Model(source)
23
- @models[source] ||= Class.new(Model).set_dataset(source)
24
- end
25
-
26
- # Model has some methods that are added via metaprogramming:
27
- #
28
- # * All of the methods in DATASET_METHODS have class methods created that call
29
- # the Model's dataset with the method of the same name with the given
30
- # arguments.
31
- # * All of the methods in HOOKS have class methods created that accept
32
- # either a method name symbol or an optional tag and a block. These
33
- # methods run the code as a callback at the specified time. For example:
34
- #
35
- # Model.before_save :do_something
36
- # Model.before_save(:do_something_else){ self.something_else = 42}
37
- # object = Model.new
38
- # object.save
39
- #
40
- # Would run the object's :do_something method following by the code
41
- # block related to :do_something_else. Note that if you specify a
42
- # block, a tag is optional. If the tag is not nil, it will overwrite
43
- # a previous block with the same tag. This allows hooks to work with
44
- # systems that reload code.
45
- # * All of the methods in HOOKS also create instance methods, but you
46
- # should not override these instance methods.
47
- # * The following instance_methods all call the class method of the same
48
- # name: columns, dataset, db, primary_key, str_columns.
49
- # * The following class level attr_readers are created: allowed_columns,
50
- # cache_store, cache_ttl, dataset_methods, primary_key, restricted_columns,
51
- # sti_dataset, and sti_key. You should not usually need to
52
- # access these directly.
53
- # * All validation methods also accept the options specified in #validates_each,
54
- # in addition to the options specified in the RDoc for that method.
55
- # * The following class level attr_accessors are created: raise_on_typecast_failure,
56
- # raise_on_save_failure, strict_param_setting, typecast_empty_string_to_nil,
57
- # and typecast_on_assignment:
58
- #
59
- # # Don't raise an error if a validation attempt fails in
60
- # # save/create/save_changes/etc.
61
- # Model.raise_on_save_failure = false
62
- # Model.before_save{false}
63
- # Model.new.save # => nil
64
- # # Don't raise errors in new/set/update/etc. if an attempt to
65
- # # access a missing/restricted method occurs (just silently
66
- # # skip it)
67
- # Model.strict_param_setting = false
68
- # Model.new(:id=>1) # No Error
69
- # # Don't typecast attribute values on assignment
70
- # Model.typecast_on_assignment = false
71
- # m = Model.new
72
- # m.number = '10'
73
- # m.number # => '10' instead of 10
74
- # # Don't typecast empty string to nil for non-string, non-blob columns.
75
- # Model.typecast_empty_string_to_nil = false
76
- # m.number = ''
77
- # m.number # => '' instead of nil
78
- # # Don't raise if unable to typecast data for a column
79
- # Model.typecast_empty_string_to_nil = true
80
- # Model.raise_on_typecast_failure = false
81
- # m.not_null_column = '' # => nil
82
- # m.number = 'A' # => 'A'
83
- #
84
- # * The following class level method aliases are defined:
85
- # * Model.dataset= => set_dataset
86
- # * Model.is_a => is
87
- class Model
88
- extend Enumerable
89
- extend Associations
90
- end
91
- end
1
+ require 'sequel/model'
@@ -26,7 +26,7 @@ FIREBIRD_DB.create_table! :test5 do
26
26
  end
27
27
 
28
28
  context "A Firebird database" do
29
- setup do
29
+ before do
30
30
  @db = FIREBIRD_DB
31
31
  end
32
32
 
@@ -43,7 +43,7 @@ context "A Firebird database" do
43
43
  end
44
44
 
45
45
  context "A Firebird dataset" do
46
- setup do
46
+ before do
47
47
  @d = FIREBIRD_DB[:test]
48
48
  @d.delete # remove all records
49
49
  end
@@ -212,7 +212,7 @@ context "A Firebird dataset" do
212
212
  end
213
213
 
214
214
  context "A Firebird dataset with a timestamp field" do
215
- setup do
215
+ before do
216
216
  @d = FIREBIRD_DB[:test3]
217
217
  @d.delete
218
218
  end
@@ -226,7 +226,7 @@ context "A Firebird dataset with a timestamp field" do
226
226
  end
227
227
 
228
228
  context "A Firebird database" do
229
- setup do
229
+ before do
230
230
  @db = FIREBIRD_DB
231
231
  end
232
232
 
@@ -342,7 +342,7 @@ context "A Firebird database" do
342
342
  end
343
343
 
344
344
  context "Postgres::Dataset#insert" do
345
- setup do
345
+ before do
346
346
  @ds = FIREBIRD_DB[:test5]
347
347
  @ds.delete
348
348
  end
@@ -24,7 +24,7 @@ context "A Informix database" do
24
24
  end
25
25
 
26
26
  context "A Informix dataset" do
27
- setup do
27
+ before do
28
28
  @d = INFORMIX_DB[:test]
29
29
  @d.delete # remove all records
30
30
  end
@@ -44,7 +44,7 @@ else
44
44
  end
45
45
 
46
46
  context "MySQL", '#create_table' do
47
- setup do
47
+ before do
48
48
  @db = MYSQL_DB
49
49
  end
50
50
  after(:each) do
@@ -57,10 +57,10 @@ context "MySQL", '#create_table' do
57
57
  end
58
58
 
59
59
  context "A MySQL database" do
60
- setup do
60
+ before do
61
61
  @db = MYSQL_DB
62
62
  end
63
- teardown do
63
+ after do
64
64
  Sequel.convert_tinyint_to_bool = true
65
65
  end
66
66
 
@@ -96,14 +96,10 @@ context "A MySQL database" do
96
96
  Sequel.convert_tinyint_to_bool = false
97
97
  @db.schema(:booltest, :reload=>true).should == [[:value, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :db_type=>"tinyint(4)"}]]
98
98
  end
99
-
100
- specify "should get the schema all database tables if no table name is used" do
101
- @db.schema(:booltest, :reload=>true).should == @db.schema(nil, :reload=>true)[:booltest]
102
- end
103
99
  end
104
100
 
105
101
  context "A MySQL dataset" do
106
- setup do
102
+ before do
107
103
  @d = MYSQL_DB[:items]
108
104
  @d.delete # remove all records
109
105
  MYSQL_DB.sqls.clear
@@ -274,10 +270,10 @@ context "A MySQL dataset" do
274
270
  end
275
271
 
276
272
  context "MySQL datasets" do
277
- setup do
273
+ before do
278
274
  @d = MYSQL_DB[:orders]
279
275
  end
280
- teardown do
276
+ after do
281
277
  Sequel.convert_tinyint_to_bool = true
282
278
  end
283
279
 
@@ -285,11 +281,9 @@ context "MySQL datasets" do
285
281
  @d.quote_identifiers = true
286
282
  market = 'ICE'
287
283
  ack_stamp = Time.now - 15 * 60 # 15 minutes ago
288
- @d.query do
289
- select :market, :minute.sql_function(:from_unixtime.sql_function(:ack)).as(:minute)
290
- where {(:ack.sql_number > ack_stamp) & {:market => market}}
291
- group_by :minute.sql_function(:from_unixtime.sql_function(:ack))
292
- end.sql.should == \
284
+ @d.select(:market, :minute.sql_function(:from_unixtime.sql_function(:ack)).as(:minute)).
285
+ where{|o|(:ack.sql_number > ack_stamp) & {:market => market}}.
286
+ group_by(:minute.sql_function(:from_unixtime.sql_function(:ack))).sql.should == \
293
287
  "SELECT `market`, minute(from_unixtime(`ack`)) AS `minute` FROM `orders` WHERE ((`ack` > #{@d.literal(ack_stamp)}) AND (`market` = 'ICE')) GROUP BY minute(from_unixtime(`ack`))"
294
288
  end
295
289
 
@@ -319,7 +313,7 @@ context "MySQL datasets" do
319
313
  end
320
314
 
321
315
  context "MySQL join expressions" do
322
- setup do
316
+ before do
323
317
  @ds = MYSQL_DB[:nodes]
324
318
  @ds.db.meta_def(:server_version) {50014}
325
319
  end
@@ -370,7 +364,7 @@ context "MySQL join expressions" do
370
364
  end
371
365
 
372
366
  context "Joined MySQL dataset" do
373
- setup do
367
+ before do
374
368
  @ds = MYSQL_DB[:nodes]
375
369
  end
376
370
 
@@ -394,7 +388,7 @@ context "Joined MySQL dataset" do
394
388
  end
395
389
 
396
390
  context "A MySQL database" do
397
- setup do
391
+ before do
398
392
  @db = MYSQL_DB
399
393
  end
400
394
 
@@ -485,21 +479,21 @@ context "A MySQL database", "with table options" do
485
479
  end
486
480
 
487
481
  specify "should allow to pass custom options (engine, charset, collate) for table creation" do
488
- statements = @db.create_table_sql_list(:items, *(@g.create_info << @options))
482
+ statements = @db.send(:create_table_sql_list, :items, *(@g.create_info << @options))
489
483
  statements.should == [
490
484
  "CREATE TABLE items (size integer, name text) ENGINE=MyISAM DEFAULT CHARSET=latin2 DEFAULT COLLATE=swedish"
491
485
  ]
492
486
  end
493
487
 
494
488
  specify "should use default options if specified (engine, charset, collate) for table creation" do
495
- statements = @db.create_table_sql_list(:items, *(@g.create_info))
489
+ statements = @db.send(:create_table_sql_list, :items, *(@g.create_info))
496
490
  statements.should == [
497
491
  "CREATE TABLE items (size integer, name text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8"
498
492
  ]
499
493
  end
500
494
 
501
495
  specify "should not use default if option has a nil value" do
502
- statements = @db.create_table_sql_list(:items, *(@g.create_info << {:engine=>nil, :charset=>nil, :collate=>nil}))
496
+ statements = @db.send(:create_table_sql_list, :items, *(@g.create_info << {:engine=>nil, :charset=>nil, :collate=>nil}))
503
497
  statements.should == [
504
498
  "CREATE TABLE items (size integer, name text)"
505
499
  ]
@@ -507,7 +501,7 @@ context "A MySQL database", "with table options" do
507
501
  end
508
502
 
509
503
  context "A MySQL database" do
510
- setup do
504
+ before do
511
505
  @db = MYSQL_DB
512
506
  end
513
507
 
@@ -516,7 +510,7 @@ context "A MySQL database" do
516
510
  boolean :active1, :default => true
517
511
  boolean :active2, :default => false
518
512
  end
519
- statements = @db.create_table_sql_list(:items, *g.create_info)
513
+ statements = @db.send(:create_table_sql_list, :items, *g.create_info)
520
514
  statements.should == [
521
515
  "CREATE TABLE items (active1 boolean DEFAULT 1, active2 boolean DEFAULT 0)"
522
516
  ]
@@ -527,7 +521,7 @@ context "A MySQL database" do
527
521
  foreign_key :p_id, :table => :users, :key => :id,
528
522
  :null => false, :on_delete => :cascade
529
523
  end
530
- @db.create_table_sql_list(:items, *g.create_info).should == [
524
+ @db.send(:create_table_sql_list, :items, *g.create_info).should == [
531
525
  "CREATE TABLE items (p_id integer NOT NULL, FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE)"
532
526
  ]
533
527
  end
@@ -536,7 +530,7 @@ specify "should correctly format ALTER TABLE statements with foreign keys" do
536
530
  g = Sequel::Schema::AlterTableGenerator.new(@db) do
537
531
  add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade
538
532
  end
539
- @db.alter_table_sql_list(:items, g.operations).should == [[
533
+ @db.send(:alter_table_sql_list, :items, g.operations).should == [[
540
534
  "ALTER TABLE items ADD COLUMN p_id integer NOT NULL",
541
535
  "ALTER TABLE items ADD FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE"
542
536
  ]]
@@ -584,7 +578,7 @@ if %w'localhost 127.0.0.1 ::1'.include?(MYSQL_URI.host) and MYSQL_DB.class.adapt
584
578
  end
585
579
 
586
580
  context "A grouped MySQL dataset" do
587
- setup do
581
+ before do
588
582
  MYSQL_DB[:test2].delete
589
583
  MYSQL_DB[:test2] << {:name => '11', :value => 10}
590
584
  MYSQL_DB[:test2] << {:name => '11', :value => 20}
@@ -606,16 +600,13 @@ context "A grouped MySQL dataset" do
606
600
  end
607
601
 
608
602
  context "A MySQL database" do
609
- setup do
610
- end
611
-
612
603
  specify "should support fulltext indexes" do
613
604
  g = Sequel::Schema::Generator.new(MYSQL_DB) do
614
605
  text :title
615
606
  text :body
616
607
  full_text_index [:title, :body]
617
608
  end
618
- MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
609
+ MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
619
610
  "CREATE TABLE posts (title text, body text)",
620
611
  "CREATE FULLTEXT INDEX posts_title_body_index ON posts (title, body)"
621
612
  ]
@@ -637,7 +628,7 @@ context "A MySQL database" do
637
628
  point :geom
638
629
  spatial_index [:geom]
639
630
  end
640
- MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
631
+ MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
641
632
  "CREATE TABLE posts (geom point)",
642
633
  "CREATE SPATIAL INDEX posts_geom_index ON posts (geom)"
643
634
  ]
@@ -648,7 +639,7 @@ context "A MySQL database" do
648
639
  text :title
649
640
  index :title, :type => :hash
650
641
  end
651
- MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
642
+ MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
652
643
  "CREATE TABLE posts (title text)",
653
644
  "CREATE INDEX posts_title_index ON posts (title) USING hash"
654
645
  ]
@@ -659,7 +650,7 @@ context "A MySQL database" do
659
650
  text :title
660
651
  index :title, :type => :hash, :unique => true
661
652
  end
662
- MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
653
+ MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
663
654
  "CREATE TABLE posts (title text)",
664
655
  "CREATE UNIQUE INDEX posts_title_index ON posts (title) USING hash"
665
656
  ]
@@ -667,9 +658,9 @@ context "A MySQL database" do
667
658
  end
668
659
 
669
660
  context "MySQL::Dataset#insert" do
670
- setup do
661
+ before do
671
662
  @d = MYSQL_DB[:items]
672
- @d.delete # remove all records
663
+ @d.delete
673
664
  MYSQL_DB.sqls.clear
674
665
  end
675
666
 
@@ -711,9 +702,9 @@ context "MySQL::Dataset#insert" do
711
702
  end
712
703
 
713
704
  context "MySQL::Dataset#multi_insert" do
714
- setup do
705
+ before do
715
706
  @d = MYSQL_DB[:items]
716
- @d.delete # remove all records
707
+ @d.delete
717
708
  MYSQL_DB.sqls.clear
718
709
  end
719
710
 
@@ -774,7 +765,7 @@ context "MySQL::Dataset#multi_insert" do
774
765
  end
775
766
 
776
767
  specify "should support inserting using columns and values arrays" do
777
- @d.multi_insert([:name, :value], [['abc', 1], ['def', 2]])
768
+ @d.import([:name, :value], [['abc', 1], ['def', 2]])
778
769
 
779
770
  MYSQL_DB.sqls.should == [
780
771
  SQL_BEGIN,
@@ -789,8 +780,70 @@ context "MySQL::Dataset#multi_insert" do
789
780
  end
790
781
  end
791
782
 
783
+ context "MySQL::Dataset#insert_ignore" do
784
+ before do
785
+ @d = MYSQL_DB[:items]
786
+ @d.delete
787
+ MYSQL_DB.sqls.clear
788
+ end
789
+
790
+ specify "should add the IGNORE keyword when inserting" do
791
+ @d.insert_ignore.multi_insert([{:name => 'abc'}, {:name => 'def'}])
792
+
793
+ MYSQL_DB.sqls.should == [
794
+ SQL_BEGIN,
795
+ "INSERT IGNORE INTO items (name) VALUES ('abc'), ('def')",
796
+ SQL_COMMIT
797
+ ]
798
+
799
+ @d.all.should == [
800
+ {:name => 'abc', :value => nil}, {:name => 'def', :value => nil}
801
+ ]
802
+ end
803
+ end
804
+
805
+ context "MySQL::Dataset#on_duplicate_key_update" do
806
+ before do
807
+ @d = MYSQL_DB[:items]
808
+ @d.delete
809
+ MYSQL_DB.sqls.clear
810
+ end
811
+
812
+ specify "should add the ON DUPLICATE KEY UPDATE and ALL columns when no args given" do
813
+ @d.on_duplicate_key_update.import([:name,:value],
814
+ [['abc', 1], ['def',2]]
815
+ )
816
+
817
+ MYSQL_DB.sqls.should == [
818
+ SQL_BEGIN,
819
+ "INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE name=VALUES(name), value=VALUES(value)",
820
+ SQL_COMMIT
821
+ ]
822
+
823
+ @d.all.should == [
824
+ {:name => 'abc', :value => 1}, {:name => 'def', :value => 2}
825
+ ]
826
+ end
827
+ specify "should add the ON DUPLICATE KEY UPDATE and columns specified when args are given" do
828
+ @d.on_duplicate_key_update(:value).import([:name,:value],
829
+ [['abc', 1], ['def',2]]
830
+ )
831
+
832
+ MYSQL_DB.sqls.should == [
833
+ SQL_BEGIN,
834
+ "INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE value=VALUES(value)",
835
+ SQL_COMMIT
836
+ ]
837
+
838
+ @d.all.should == [
839
+ {:name => 'abc', :value => 1}, {:name => 'def', :value => 2}
840
+ ]
841
+ end
842
+
843
+ end
844
+
792
845
  context "MySQL::Dataset#replace" do
793
- setup do
846
+ before do
794
847
  MYSQL_DB.drop_table(:items) if MYSQL_DB.table_exists?(:items)
795
848
  MYSQL_DB.create_table :items do
796
849
  integer :id, :unique => true
@@ -814,7 +867,7 @@ context "MySQL::Dataset#replace" do
814
867
  end
815
868
 
816
869
  context "MySQL::Dataset#complex_expression_sql" do
817
- setup do
870
+ before do
818
871
  @d = MYSQL_DB.dataset
819
872
  end
820
873
 
@@ -832,7 +885,7 @@ context "MySQL::Dataset#complex_expression_sql" do
832
885
  specify "should handle string concatenation with CONCAT if more than one record" do
833
886
  @d.literal([:x, :y].sql_string_join).should == "CONCAT(x, y)"
834
887
  @d.literal([:x, :y].sql_string_join(' ')).should == "CONCAT(x, ' ', y)"
835
- @d.literal([:x.sql_function(:y), 1, 'z'.lit].sql_string_join(:y|1)).should == "CONCAT(x(y), y[1], '1', y[1], z)"
888
+ @d.literal([:x.sql_function(:y), 1, 'z'.lit].sql_string_join(:y.sql_subscript(1))).should == "CONCAT(x(y), y[1], '1', y[1], z)"
836
889
  end
837
890
 
838
891
  specify "should handle string concatenation as simple string if just one record" do
@@ -843,7 +896,7 @@ end
843
896
 
844
897
  unless MYSQL_DB.class.adapter_scheme == :do
845
898
  context "MySQL Stored Procedures" do
846
- teardown do
899
+ after do
847
900
  MYSQL_DB.execute('DROP PROCEDURE test_sproc')
848
901
  end
849
902
 
@@ -879,3 +932,36 @@ unless MYSQL_DB.class.adapter_scheme == :do
879
932
  end
880
933
  end
881
934
  end
935
+
936
+ if MYSQL_DB.class.adapter_scheme == :mysql
937
+ context "MySQL bad date/time conversions" do
938
+ after do
939
+ Sequel::MySQL.convert_invalid_date_time = false
940
+ end
941
+
942
+ specify "should raise an exception when a bad date/time is used and convert_invalid_date_time is false" do
943
+ Sequel::MySQL.convert_invalid_date_time = false
944
+ proc{MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value}.should raise_error(Sequel::InvalidValue)
945
+ proc{MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value}.should raise_error(Sequel::InvalidValue)
946
+ proc{MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value}.should raise_error(Sequel::InvalidValue)
947
+ end
948
+
949
+ specify "should not use a nil value bad date/time is used and convert_invalid_date_time is nil or :nil" do
950
+ Sequel::MySQL.convert_invalid_date_time = nil
951
+ MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
952
+ MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
953
+ MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
954
+ Sequel::MySQL.convert_invalid_date_time = :nil
955
+ MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
956
+ MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
957
+ MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
958
+ end
959
+
960
+ specify "should not use a nil value bad date/time is used and convert_invalid_date_time is :string" do
961
+ Sequel::MySQL.convert_invalid_date_time = :string
962
+ MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == '0000-00-00'
963
+ MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == '0000-00-00 00:00:00'
964
+ MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == '25:00:00'
965
+ end
966
+ end
967
+ end