sequel 3.0.0 → 3.1.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.
- data/CHANGELOG +100 -0
- data/README.rdoc +3 -3
- data/bin/sequel +102 -19
- data/doc/reflection.rdoc +83 -0
- data/doc/release_notes/3.1.0.txt +406 -0
- data/lib/sequel/adapters/ado.rb +11 -0
- data/lib/sequel/adapters/amalgalite.rb +5 -20
- data/lib/sequel/adapters/do.rb +44 -36
- data/lib/sequel/adapters/firebird.rb +29 -43
- data/lib/sequel/adapters/jdbc.rb +17 -27
- data/lib/sequel/adapters/mysql.rb +35 -40
- data/lib/sequel/adapters/odbc.rb +4 -23
- data/lib/sequel/adapters/oracle.rb +22 -19
- data/lib/sequel/adapters/postgres.rb +6 -15
- data/lib/sequel/adapters/shared/mssql.rb +1 -1
- data/lib/sequel/adapters/shared/mysql.rb +29 -10
- data/lib/sequel/adapters/shared/oracle.rb +6 -8
- data/lib/sequel/adapters/shared/postgres.rb +28 -72
- data/lib/sequel/adapters/shared/sqlite.rb +5 -3
- data/lib/sequel/adapters/sqlite.rb +5 -20
- data/lib/sequel/adapters/utils/savepoint_transactions.rb +80 -0
- data/lib/sequel/adapters/utils/unsupported.rb +0 -12
- data/lib/sequel/core.rb +12 -3
- data/lib/sequel/core_sql.rb +1 -8
- data/lib/sequel/database.rb +107 -43
- data/lib/sequel/database/schema_generator.rb +1 -0
- data/lib/sequel/database/schema_methods.rb +38 -4
- data/lib/sequel/dataset.rb +6 -0
- data/lib/sequel/dataset/convenience.rb +2 -2
- data/lib/sequel/dataset/graph.rb +2 -2
- data/lib/sequel/dataset/prepared_statements.rb +3 -8
- data/lib/sequel/dataset/sql.rb +93 -19
- data/lib/sequel/extensions/blank.rb +2 -1
- data/lib/sequel/extensions/inflector.rb +4 -3
- data/lib/sequel/extensions/migration.rb +13 -2
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pretty_table.rb +4 -0
- data/lib/sequel/extensions/query.rb +4 -0
- data/lib/sequel/extensions/schema_dumper.rb +100 -24
- data/lib/sequel/extensions/string_date_time.rb +3 -4
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +96 -38
- data/lib/sequel/model/base.rb +14 -14
- data/lib/sequel/model/plugins.rb +32 -21
- data/lib/sequel/plugins/caching.rb +13 -15
- data/lib/sequel/plugins/identity_map.rb +107 -0
- data/lib/sequel/plugins/lazy_attributes.rb +65 -0
- data/lib/sequel/plugins/many_through_many.rb +188 -0
- data/lib/sequel/plugins/schema.rb +13 -0
- data/lib/sequel/plugins/serialization.rb +53 -37
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
- data/lib/sequel/plugins/validation_class_methods.rb +28 -7
- data/lib/sequel/plugins/validation_helpers.rb +31 -24
- data/lib/sequel/sql.rb +16 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/ado_spec.rb +47 -1
- data/spec/adapters/firebird_spec.rb +39 -36
- data/spec/adapters/mysql_spec.rb +25 -9
- data/spec/adapters/postgres_spec.rb +11 -24
- data/spec/core/database_spec.rb +54 -13
- data/spec/core/dataset_spec.rb +147 -29
- data/spec/core/object_graph_spec.rb +6 -1
- data/spec/core/schema_spec.rb +34 -0
- data/spec/core/spec_helper.rb +0 -2
- data/spec/extensions/caching_spec.rb +7 -0
- data/spec/extensions/identity_map_spec.rb +158 -0
- data/spec/extensions/lazy_attributes_spec.rb +113 -0
- data/spec/extensions/many_through_many_spec.rb +813 -0
- data/spec/extensions/migration_spec.rb +4 -4
- data/spec/extensions/schema_dumper_spec.rb +114 -13
- data/spec/extensions/schema_spec.rb +19 -3
- data/spec/extensions/serialization_spec.rb +28 -0
- data/spec/extensions/single_table_inheritance_spec.rb +25 -1
- data/spec/extensions/spec_helper.rb +2 -7
- data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
- data/spec/extensions/validation_class_methods_spec.rb +10 -5
- data/spec/integration/dataset_test.rb +39 -6
- data/spec/integration/eager_loader_test.rb +7 -7
- data/spec/integration/spec_helper.rb +0 -1
- data/spec/integration/transaction_test.rb +28 -1
- data/spec/model/association_reflection_spec.rb +29 -3
- data/spec/model/associations_spec.rb +1 -0
- data/spec/model/eager_loading_spec.rb +70 -1
- data/spec/model/plugins_spec.rb +236 -50
- data/spec/model/spec_helper.rb +0 -2
- metadata +18 -5
@@ -1,5 +1,13 @@
|
|
1
1
|
module Sequel
|
2
2
|
module Plugins
|
3
|
+
# Sequel's built in schema plugin allows you to define your schema
|
4
|
+
# directly in the model using Model.set_schema (which takes a block
|
5
|
+
# similar to Database#create_table), and use Model.create_table to
|
6
|
+
# create a table using the schema information.
|
7
|
+
#
|
8
|
+
# This plugin is mostly suited to test code. If there is any
|
9
|
+
# chance that your application's schema could change, you should
|
10
|
+
# be using the migration extension instead.
|
3
11
|
module Schema
|
4
12
|
module ClassMethods
|
5
13
|
# Creates table, using the column information from set_schema.
|
@@ -15,6 +23,11 @@ module Sequel
|
|
15
23
|
drop_table rescue nil
|
16
24
|
create_table
|
17
25
|
end
|
26
|
+
|
27
|
+
# Creates the table unless the table already exists
|
28
|
+
def create_table?
|
29
|
+
create_table unless table_exists?
|
30
|
+
end
|
18
31
|
|
19
32
|
# Drops table.
|
20
33
|
def drop_table
|
@@ -21,47 +21,59 @@ module Sequel
|
|
21
21
|
module Serialization
|
22
22
|
# Set up the column readers to do deserialization and the column writers
|
23
23
|
# to save the value in deserialized_values.
|
24
|
-
def self.apply(model,
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
InstanceMethods.module_eval do
|
31
|
-
columns.each do |column|
|
32
|
-
define_method(column) do
|
33
|
-
if deserialized_values.has_key?(column)
|
34
|
-
deserialized_values[column]
|
35
|
-
else
|
36
|
-
deserialized_values[column] = deserialize_value(@values[column])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
define_method("#{column}=") do |v|
|
40
|
-
changed_columns << column unless changed_columns.include?(column)
|
41
|
-
deserialized_values[column] = v
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
24
|
+
def self.apply(model, *args)
|
25
|
+
model.instance_eval{@serialization_map = {}}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.configure(model, format=nil, *columns)
|
29
|
+
model.serialize_attributes(format, *columns) unless columns.empty?
|
46
30
|
end
|
47
31
|
|
48
32
|
module ClassMethods
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
# The columns to serialize
|
53
|
-
attr_reader :serialized_columns
|
33
|
+
# A map of the serialized columns for this model. Keys are column
|
34
|
+
# symbols, values are serialization formats (:marshal or :yaml).
|
35
|
+
attr_reader :serialization_map
|
54
36
|
|
55
37
|
# Copy the serialization format and columns to serialize into the subclass.
|
56
38
|
def inherited(subclass)
|
57
39
|
super
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
40
|
+
sm = serialization_map.dup
|
41
|
+
subclass.instance_eval{@serialization_map = sm}
|
42
|
+
end
|
43
|
+
|
44
|
+
# The first value in the serialization map. This is only for
|
45
|
+
# backwards compatibility, use serialization_map in new code.
|
46
|
+
def serialization_format
|
47
|
+
serialization_map.values.first
|
48
|
+
end
|
49
|
+
|
50
|
+
# Create instance level reader that deserializes column values on request,
|
51
|
+
# and instance level writer that stores new deserialized value in deserialized
|
52
|
+
# columns
|
53
|
+
def serialize_attributes(format, *columns)
|
54
|
+
raise(Error, "Unsupported serialization format (#{format}), should be :marshal or :yaml") unless [:marshal, :yaml].include?(format)
|
55
|
+
raise(Error, "No columns given. The serialization plugin requires you specify which columns to serialize") if columns.empty?
|
56
|
+
columns.each do |column|
|
57
|
+
serialization_map[column] = format
|
58
|
+
define_method(column) do
|
59
|
+
if deserialized_values.has_key?(column)
|
60
|
+
deserialized_values[column]
|
61
|
+
else
|
62
|
+
deserialized_values[column] = deserialize_value(column, @values[column])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
define_method("#{column}=") do |v|
|
66
|
+
changed_columns << column unless changed_columns.include?(column)
|
67
|
+
deserialized_values[column] = v
|
68
|
+
end
|
63
69
|
end
|
64
70
|
end
|
71
|
+
|
72
|
+
# The columns that will be serialized. This is only for
|
73
|
+
# backwards compatibility, use serialization_map in new code.
|
74
|
+
def serialized_columns
|
75
|
+
serialization_map.keys
|
76
|
+
end
|
65
77
|
end
|
66
78
|
|
67
79
|
module InstanceMethods
|
@@ -78,7 +90,7 @@ module Sequel
|
|
78
90
|
def before_save
|
79
91
|
super
|
80
92
|
deserialized_values.each do |k,v|
|
81
|
-
@values[k] = serialize_value(v)
|
93
|
+
@values[k] = serialize_value(k, v)
|
82
94
|
end
|
83
95
|
end
|
84
96
|
|
@@ -91,24 +103,28 @@ module Sequel
|
|
91
103
|
private
|
92
104
|
|
93
105
|
# Deserialize the column from either marshal or yaml format
|
94
|
-
def deserialize_value(v)
|
106
|
+
def deserialize_value(column, v)
|
95
107
|
return v if v.nil?
|
96
|
-
case model.
|
108
|
+
case model.serialization_map[column]
|
97
109
|
when :marshal
|
98
110
|
Marshal.load(v.unpack('m')[0]) rescue Marshal.load(v)
|
99
111
|
when :yaml
|
100
112
|
YAML.load v if v
|
113
|
+
else
|
114
|
+
raise Error, "Bad serialization format (#{model.serialization_map[column].inspect}) for column #{column.inspect}"
|
101
115
|
end
|
102
116
|
end
|
103
117
|
|
104
118
|
# Serialize the column to either marshal or yaml format
|
105
|
-
def serialize_value(v)
|
119
|
+
def serialize_value(column, v)
|
106
120
|
return v if v.nil?
|
107
|
-
case model.
|
121
|
+
case model.serialization_map[column]
|
108
122
|
when :marshal
|
109
123
|
[Marshal.dump(v)].pack('m')
|
110
124
|
when :yaml
|
111
125
|
v.to_yaml
|
126
|
+
else
|
127
|
+
raise Error, "Bad serialization format (#{model.serialization_map[column].inspect}) for column #{column.inspect}"
|
112
128
|
end
|
113
129
|
end
|
114
130
|
end
|
@@ -18,7 +18,7 @@ module Sequel
|
|
18
18
|
# Set the sti_key and sti_dataset for the model, and change the
|
19
19
|
# dataset's row_proc so that the dataset yields objects of varying classes,
|
20
20
|
# where the class used has the same name as the key field.
|
21
|
-
def self.
|
21
|
+
def self.configure(model, key)
|
22
22
|
m = model.method(:constantize)
|
23
23
|
model.instance_eval do
|
24
24
|
@sti_key = key
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
|
+
# The tactical_eager_loading plugin allows you to eagerly load
|
4
|
+
# an association for all objects retrieved from the same dataset
|
5
|
+
# without calling eager on the dataset. If you attempt to load
|
6
|
+
# associated objects for a record and the association for that
|
7
|
+
# object is currently not cached, it assumes you want to get
|
8
|
+
# the associated objects for all objects retrieved with the dataset that
|
9
|
+
# retrieved the current object.
|
10
|
+
#
|
11
|
+
# Tactical eager loading only takes affect if you retrieved the
|
12
|
+
# current object with Dataset#all, it doesn't work if you
|
13
|
+
# retrieved the current object with Dataset#each.
|
14
|
+
#
|
15
|
+
# Basically, this allows the following code to issue only two queries:
|
16
|
+
#
|
17
|
+
# Album.filter{id<100}.all do |a|
|
18
|
+
# a.artists
|
19
|
+
# end
|
20
|
+
module TacticalEagerLoading
|
21
|
+
module InstanceMethods
|
22
|
+
# The dataset that retrieved this object, set if the object was
|
23
|
+
# reteived via Dataset#all with an active identity map.
|
24
|
+
attr_accessor :retrieved_by
|
25
|
+
|
26
|
+
# All model objects retrieved with this object, set if the object was
|
27
|
+
# reteived via Dataset#all with an active identity map.
|
28
|
+
attr_accessor :retrieved_with
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# If there is an active identity map and the association is not in the
|
33
|
+
# associations cache and the object was reteived via Dataset#all,
|
34
|
+
# eagerly load the association for all model objects retrieved with the
|
35
|
+
# current object.
|
36
|
+
def load_associated_objects(opts, reload=false)
|
37
|
+
name = opts[:name]
|
38
|
+
if !associations.include?(name) && retrieved_by
|
39
|
+
retrieved_by.send(:eager_load, retrieved_with, name=>{})
|
40
|
+
end
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module DatasetMethods
|
46
|
+
private
|
47
|
+
|
48
|
+
# If there is an active identity map, set the reteived_with attribute for the object
|
49
|
+
# with the current dataset and array of all objects.
|
50
|
+
def post_load(objects)
|
51
|
+
super
|
52
|
+
objects.each do |o|
|
53
|
+
next unless o.is_a?(Sequel::Model)
|
54
|
+
o.retrieved_by = self
|
55
|
+
o.retrieved_with = objects
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,9 +1,26 @@
|
|
1
1
|
module Sequel
|
2
|
-
|
2
|
+
extension :blank
|
3
3
|
|
4
4
|
module Plugins
|
5
|
+
# Sequel's built-in validation_class_methods plugin adds backwards compatibility
|
6
|
+
# for the legacy class-level validation methods (e.g. validates_presence_of :column).
|
7
|
+
#
|
8
|
+
# It is recommended to use the validation_helpers plugin instead of this one,
|
9
|
+
# as it is less complex and more flexible.
|
5
10
|
module ValidationClassMethods
|
11
|
+
# Setup the validations hash for the given model.
|
12
|
+
def self.apply(model)
|
13
|
+
model.class_eval do
|
14
|
+
@validation_mutex = Mutex.new
|
15
|
+
@validations = {}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
6
19
|
module ClassMethods
|
20
|
+
# A hash of associations for this model class. Keys are column symbols,
|
21
|
+
# values are arrays of validation procs.
|
22
|
+
attr_reader :validations
|
23
|
+
|
7
24
|
# The Generator class is used to generate validation definitions using
|
8
25
|
# the validates {} idiom.
|
9
26
|
class Generator
|
@@ -23,6 +40,15 @@ module Sequel
|
|
23
40
|
def has_validations?
|
24
41
|
!validations.empty?
|
25
42
|
end
|
43
|
+
|
44
|
+
# Setup the validations hash in the subclass
|
45
|
+
def inherited(subclass)
|
46
|
+
super
|
47
|
+
subclass.class_eval do
|
48
|
+
@validation_mutex = Mutex.new
|
49
|
+
@validations = {}
|
50
|
+
end
|
51
|
+
end
|
26
52
|
|
27
53
|
# Instructs the model to skip validations defined in superclasses
|
28
54
|
def skip_superclass_validations
|
@@ -146,7 +172,7 @@ module Sequel
|
|
146
172
|
end
|
147
173
|
tag = opts[:tag]
|
148
174
|
atts.each do |a|
|
149
|
-
a_vals = validations[a]
|
175
|
+
a_vals = @validation_mutex.synchronize{validations[a] ||= []}
|
150
176
|
if tag && (old = a_vals.find{|x| x[0] == tag})
|
151
177
|
old[1] = blk
|
152
178
|
else
|
@@ -348,11 +374,6 @@ module Sequel
|
|
348
374
|
end
|
349
375
|
end
|
350
376
|
|
351
|
-
# Returns the validations hash for the class.
|
352
|
-
def validations
|
353
|
-
@validations ||= Hash.new {|h, k| h[k] = []}
|
354
|
-
end
|
355
|
-
|
356
377
|
private
|
357
378
|
|
358
379
|
# Removes and returns the last member of the array if it is a hash. Otherwise,
|
@@ -1,30 +1,37 @@
|
|
1
1
|
module Sequel
|
2
2
|
module Plugins
|
3
|
+
# The validation_helpers plugin contains instance method equivalents for most of the legacy
|
4
|
+
# class-level validations. The names and APIs are different, though. Example:
|
5
|
+
#
|
6
|
+
# class Album < Sequel::Model
|
7
|
+
# plugin :validation_helpers
|
8
|
+
# def validate
|
9
|
+
# validates_min_length 1, :num_tracks
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# The validates_unique validation has a unique API, but the other validations have
|
14
|
+
# the API explained here:
|
15
|
+
#
|
16
|
+
# Arguments:
|
17
|
+
# * atts - Single attribute symbol or an array of attribute symbols specifying the
|
18
|
+
# attribute(s) to validate.
|
19
|
+
# Options:
|
20
|
+
# * :allow_blank - Whether to skip the validation if the value is blank. You should
|
21
|
+
# make sure all objects respond to blank if you use this option, which you can do by
|
22
|
+
# requiring 'sequel/extensions/blank'
|
23
|
+
# * :allow_missing - Whether to skip the validation if the attribute isn't a key in the
|
24
|
+
# values hash. This is different from allow_nil, because Sequel only sends the attributes
|
25
|
+
# in the values when doing an insert or update. If the attribute is not present, Sequel
|
26
|
+
# doesn't specify it, so the database will use the table's default value. This is different
|
27
|
+
# from having an attribute in values with a value of nil, which Sequel will send as NULL.
|
28
|
+
# If your database table has a non NULL default, this may be a good option to use. You
|
29
|
+
# don't want to use allow_nil, because if the attribute is in values but has a value nil,
|
30
|
+
# Sequel will attempt to insert a NULL value into the database, instead of using the
|
31
|
+
# database's default.
|
32
|
+
# * :allow_nil - Whether to skip the validation if the value is nil.
|
33
|
+
# * :message - The message to use
|
3
34
|
module ValidationHelpers
|
4
|
-
# ValidationHelpers contains instance method equivalents for most of the previous
|
5
|
-
# default validations. The names and APIs have changed, though.
|
6
|
-
#
|
7
|
-
# The validates_unique validation has a unique API, but the other validations have
|
8
|
-
# the API explained here:
|
9
|
-
#
|
10
|
-
# Arguments:
|
11
|
-
# * atts - Single attribute symbol or an array of attribute symbols specifying the
|
12
|
-
# attribute(s) to validate.
|
13
|
-
# Options:
|
14
|
-
# * :allow_blank - Whether to skip the validation if the value is blank. You should
|
15
|
-
# make sure all objects respond to blank if you use this option, which you can do by
|
16
|
-
# requiring 'sequel/extensions/blank'
|
17
|
-
# * :allow_missing - Whether to skip the validation if the attribute isn't a key in the
|
18
|
-
# values hash. This is different from allow_nil, because Sequel only sends the attributes
|
19
|
-
# in the values when doing an insert or update. If the attribute is not present, Sequel
|
20
|
-
# doesn't specify it, so the database will use the table's default value. This is different
|
21
|
-
# from having an attribute in values with a value of nil, which Sequel will send as NULL.
|
22
|
-
# If your database table has a non NULL default, this may be a good option to use. You
|
23
|
-
# don't want to use allow_nil, because if the attribute is in values but has a value nil,
|
24
|
-
# Sequel will attempt to insert a NULL value into the database, instead of using the
|
25
|
-
# database's default.
|
26
|
-
# * :allow_nil - Whether to skip the validation if the value is nil.
|
27
|
-
# * :message - The message to use
|
28
35
|
module InstanceMethods
|
29
36
|
# Check that the attribute values are the given exact length.
|
30
37
|
def validates_exact_length(exact, atts, opts={})
|
data/lib/sequel/sql.rb
CHANGED
@@ -351,10 +351,22 @@ module Sequel
|
|
351
351
|
end
|
352
352
|
end
|
353
353
|
|
354
|
+
# Methods that create Subscripts (SQL array accesses).
|
355
|
+
module SubscriptMethods
|
356
|
+
# Return an SQL array subscript with the given arguments.
|
357
|
+
#
|
358
|
+
# :array.sql_subscript(1) # SQL: array[1]
|
359
|
+
# :array.sql_subscript(1, 2) # SQL: array[1, 2]
|
360
|
+
def sql_subscript(*sub)
|
361
|
+
Subscript.new(self, sub.flatten)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
354
365
|
class ComplexExpression
|
355
366
|
include AliasMethods
|
356
367
|
include CastMethods
|
357
368
|
include OrderMethods
|
369
|
+
include SubscriptMethods
|
358
370
|
end
|
359
371
|
|
360
372
|
class GenericExpression
|
@@ -365,6 +377,7 @@ module Sequel
|
|
365
377
|
include BooleanMethods
|
366
378
|
include NumericMethods
|
367
379
|
include StringMethods
|
380
|
+
include SubscriptMethods
|
368
381
|
include InequalityMethods
|
369
382
|
end
|
370
383
|
|
@@ -709,6 +722,9 @@ module Sequel
|
|
709
722
|
# ruby array of all two pairs as an SQL array instead of an ordered
|
710
723
|
# hash-like conditions specifier.
|
711
724
|
class SQLArray < Expression
|
725
|
+
# The array of objects this SQLArray wraps
|
726
|
+
attr_reader :array
|
727
|
+
|
712
728
|
# Create an object with the given array.
|
713
729
|
def initialize(array)
|
714
730
|
@array = array
|
data/lib/sequel/version.rb
CHANGED
data/spec/adapters/ado_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
2
2
|
|
3
3
|
unless defined?(ADO_DB)
|
4
|
-
ADO_DB = Sequel.ado(:host => 'MY_SQL_SERVER', :database => 'MyDB', :user => '
|
4
|
+
ADO_DB = Sequel.ado(:host => 'MY_SQL_SERVER', :database => 'MyDB', :user => 'my_usr', :password => 'my_pwd')
|
5
5
|
end
|
6
6
|
|
7
7
|
context "An ADO dataset" do
|
@@ -14,6 +14,52 @@ context "An ADO dataset" do
|
|
14
14
|
ADO_DB[:items].all
|
15
15
|
}.should_not raise_error
|
16
16
|
end
|
17
|
+
|
18
|
+
describe 'setting the :command_timeout option' do
|
19
|
+
before(:each) do
|
20
|
+
@conn_options = {:host => 'MY_SQL_SERVER',
|
21
|
+
:database => 'MyDB',
|
22
|
+
:user => 'my_usr',
|
23
|
+
:password => 'my_pwd',
|
24
|
+
:command_timeout => 120}
|
25
|
+
end
|
26
|
+
|
27
|
+
specify 'it should set the CommandTimeout parameter on the ADO handle' do
|
28
|
+
db = Sequel::ADO::Database.new(@conn_options)
|
29
|
+
db.connect(@conn_options).CommandTimeout.should == 120
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'when the :command_timeout option is not implicitly set' do
|
34
|
+
before(:each) do
|
35
|
+
@conn_options = {:host => 'MY_SQL_SERVER',
|
36
|
+
:database => 'MyDB',
|
37
|
+
:user => 'my_usr',
|
38
|
+
:password => 'my_pwd'}
|
39
|
+
end
|
40
|
+
|
41
|
+
specify 'it should remain as the default of 30 seconds' do
|
42
|
+
db = Sequel::ADO::Database.new(@conn_options)
|
43
|
+
db.connect(@conn_options).CommandTimeout.should == 30
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'setting the :provider option' do
|
48
|
+
before(:each) do
|
49
|
+
@conn_options = {:host => 'MY_SQL_SERVER',
|
50
|
+
:database => 'MyDB',
|
51
|
+
:user => 'my_usr',
|
52
|
+
:password => 'my_pwd',
|
53
|
+
:provider => "SQLOLEDB"}
|
54
|
+
end
|
55
|
+
|
56
|
+
specify 'it should set the CommandTimeout parameter on the ADO handle' do
|
57
|
+
db = Sequel::ADO::Database.new(@conn_options)
|
58
|
+
db.connect(@conn_options).Provider.should match /sqloledb/i
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
17
63
|
end
|
18
64
|
|
19
65
|
context "An MSSQL dataset" do
|