sequel 3.19.0 → 3.20.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,19 @@
1
+ === 3.20.0 (2011-02-01)
2
+
3
+ * Allow a :partial option to Database#indexes on MySQL to include partial indexes (roland.swingler) (#324)
4
+
5
+ * Add a SQLite subadapter to the swift adapter, now that swift supports it (jeremyevans)
6
+
7
+ * Update swift adapter to support swift 0.8.1, older versions no longer supported (jeremyevans)
8
+
9
+ * Allow setting arbitrary JDBC properties in the jdbc adapter with the :jdbc_properties option (jeremyevans)
10
+
11
+ * Use a better error message if a validates_max_length validation is applied to a nil value (jeremyevans) (#322)
12
+
13
+ * Add some basic Microsoft Access support to the ado adapter, autoincrementing primary keys now work (jeremyevans)
14
+
15
+ * Make class_table_inheritance plugin handle subclass associations better (jeremyevans) (#320)
16
+
1
17
  === 3.19.0 (2011-01-03)
2
18
 
3
19
  * Handle Date and DateTime types in prepared statements when using the jdbc adapter (jeremyevans)
@@ -113,6 +113,18 @@ many things will be broken. The SQLNCLI10 provider appears to work well if you
113
113
  are connecting to Microsoft SQL Server, but it is not the default as that would
114
114
  break backwards compatability.
115
115
 
116
+ Example connections:
117
+
118
+ # SQL Server
119
+ Sequel.connect('ado:///sequel_test?host=server%5cdb_instance')
120
+ Sequel.connect('ado://user:password@server/database?host=server%5cdb_instance&provider=SQLNCLI10')
121
+ # Access 2007
122
+ Sequel.ado(:conn_string=>'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=drive:\\path\\filename.accdb')
123
+ # Access 2000
124
+ Sequel.ado(:conn_string=>'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=drive:\\path\\filename.mdb')
125
+ # Excel 2000 (for table names, use a dollar after the sheet name, e.g. Sheet1$)
126
+ Sequel.ado(:conn_string=>'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=drive:\\path\\filename.xls;Extended Properties=Excel 8.0;')
127
+
116
128
  === amalgalite
117
129
 
118
130
  Amalgalite is an ruby extension that provides self contained access to SQLite,
@@ -254,6 +266,8 @@ The following additional options are supported:
254
266
  * :encoding - Specify the encoding/character set to use for the connection.
255
267
  * :socket - Can be used to specify a Unix socket file to connect to instead of a TCP host and port.
256
268
  * :timeout - Sets the wait_timeout for the connection, defaults to 1 month.
269
+ * :read_timeout - Set the timeout in seconds for reading back results to a query.
270
+ * :connect_timeout - Set the timeout in seconds before a connection attempt is abandoned.
257
271
 
258
272
  === odbc
259
273
 
@@ -0,0 +1,41 @@
1
+ = New Features
2
+
3
+ * The swift adapter now supports an SQLite subadapter. Use the
4
+ :db_type => 'sqlite' option when connecting. You can use an
5
+ in memory database with the following connection string:
6
+
7
+ swift:///?database=:memory:&db_type=sqlite
8
+
9
+ * Arbitrary JDBC properties can now be set in the JDBC adapter
10
+ using the :jdbc_properties option when connecting. The value
11
+ of this option should be a hash where keys and values are JDBC
12
+ property keys and values.
13
+
14
+ * Basic Microsoft Access support was added to the ado adapter.
15
+ The creation of autoincrementing primary key integers now works,
16
+ and identifiers are now quoted with [].
17
+
18
+ * The Database#indexes method now supports a :partial option when
19
+ connecting to MySQL, which makes it include partial indexes (which
20
+ are usually excluded).
21
+
22
+ = Other Improvements
23
+
24
+ * The class_table_inheritance plugin now handles subclass
25
+ associations better. Previously, the implicit eager loading code
26
+ had issues when you called an association method that only existed
27
+ in the subclass.
28
+
29
+ * The error message used when a validates_max_length validation is
30
+ applied to a nil column value has been improved. You can override
31
+ the message yourself using the :nil_message option.
32
+
33
+ * The read_timeout and connect_timeout options now work correctly in
34
+ the mysql adapter.
35
+
36
+ * Another MySQL disconnect error message is now recognized.
37
+
38
+ = Backwards Compatibility
39
+
40
+ * The swift adapter was upgraded to support swift 0.8.1. Older
41
+ versions of swift are no longer supported.
@@ -8,11 +8,17 @@ module Sequel
8
8
 
9
9
  def initialize(opts)
10
10
  super
11
- @opts[:driver] ||= 'SQL Server'
12
- case @opts[:driver]
13
- when 'SQL Server'
14
- Sequel.ts_require 'adapters/ado/mssql'
15
- extend Sequel::ADO::MSSQL::DatabaseMethods
11
+ case @opts[:conn_string]
12
+ when /Microsoft\.(Jet|ACE)\.OLEDB/io
13
+ Sequel.ts_require 'adapters/shared/access'
14
+ extend Sequel::Access::DatabaseMethods
15
+ when nil
16
+ @opts[:driver] ||= 'SQL Server'
17
+ case @opts[:driver]
18
+ when 'SQL Server'
19
+ Sequel.ts_require 'adapters/ado/mssql'
20
+ extend Sequel::ADO::MSSQL::DatabaseMethods
21
+ end
16
22
  end
17
23
  end
18
24
 
@@ -168,6 +168,7 @@ module Sequel
168
168
  props.setProperty("user", opts[:user])
169
169
  props.setProperty("password", opts[:password])
170
170
  end
171
+ opts[:jdbc_properties].each{|k,v| props.setProperty(k.to_s, v)} if opts[:jdbc_properties]
171
172
  begin
172
173
  driver.new.connect(args[0], props)
173
174
  rescue => e2
@@ -86,7 +86,7 @@ module Sequel
86
86
  include Sequel::MySQL::DatabaseMethods
87
87
 
88
88
  # Mysql::Error messages that indicate the current connection should be disconnected
89
- MYSQL_DATABASE_DISCONNECT_ERRORS = /\A(Commands out of sync; you can't run this command now|Can't connect to local MySQL server through socket|MySQL server has gone away)/
89
+ MYSQL_DATABASE_DISCONNECT_ERRORS = /\A(Commands out of sync; you can't run this command now|Can't connect to local MySQL server through socket|MySQL server has gone away|Lost connection to MySQL server during query)/
90
90
 
91
91
  set_adapter_scheme :mysql
92
92
 
@@ -128,10 +128,10 @@ module Sequel
128
128
  # encoding we want to use, but this can be overridden by READ_DEFAULT_GROUP.
129
129
  conn.options(Mysql::SET_CHARSET_NAME, encoding)
130
130
  end
131
- if read_timeout = opts[:read_timeout] and Mysql::const_defined(Mysql::OPT_READ_TIMEOUT)
131
+ if read_timeout = opts[:read_timeout] and defined? Mysql::OPT_READ_TIMEOUT
132
132
  conn.options(Mysql::OPT_READ_TIMEOUT, read_timeout)
133
133
  end
134
- if connect_timeout = opts[:connect_timeout] and Mysql::const_defined(Mysql::OPT_CONNECT_TIMEOUT)
134
+ if connect_timeout = opts[:connect_timeout] and defined? Mysql::OPT_CONNECT_TIMEOUT
135
135
  conn.options(Mysql::OPT_CONNECT_TIMEOUT, connect_timeout)
136
136
  end
137
137
  conn.real_connect(
@@ -0,0 +1,52 @@
1
+ module Sequel
2
+ module Access
3
+ module DatabaseMethods
4
+ def database_type
5
+ :access
6
+ end
7
+
8
+ def dataset(opts = nil)
9
+ ds = super
10
+ ds.extend(DatasetMethods)
11
+ ds
12
+ end
13
+
14
+ # Doesn't work, due to security restrictions on MSysObjects
15
+ def tables
16
+ from(:MSysObjects).filter(:Type=>1, :Flags=>0).select_map(:Name).map{|x| x.to_sym}
17
+ end
18
+
19
+ def serial_primary_key_options
20
+ {:primary_key => true, :type=>:Counter}
21
+ end
22
+
23
+ private
24
+
25
+ def identifier_input_method_default
26
+ nil
27
+ end
28
+
29
+ def identifier_output_method_default
30
+ nil
31
+ end
32
+ end
33
+
34
+ module DatasetMethods
35
+ SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'limit distinct columns from join where group order having compounds')
36
+
37
+ def supports_intersect_except?
38
+ false
39
+ end
40
+
41
+ private
42
+
43
+ def quoted_identifier(v)
44
+ "[#{v}]"
45
+ end
46
+
47
+ def select_clause_methods
48
+ SELECT_CLAUSE_METHODS
49
+ end
50
+ end
51
+ end
52
+ end
@@ -49,7 +49,11 @@ module Sequel
49
49
  :mysql
50
50
  end
51
51
 
52
- # Use SHOW INDEX FROM to get the index information for the table.
52
+ # Use SHOW INDEX FROM to get the index information for the
53
+ # table.
54
+ #
55
+ # By default partial indexes are not included, you can use the
56
+ # option :partial to override this.
53
57
  def indexes(table, opts={})
54
58
  indexes = {}
55
59
  remove_indexes = []
@@ -59,7 +63,7 @@ module Sequel
59
63
  name = r[:Key_name]
60
64
  next if name == PRIMARY
61
65
  name = m.call(name)
62
- remove_indexes << name if r[:Sub_part]
66
+ remove_indexes << name if r[:Sub_part] && ! opts[:partial]
63
67
  i = indexes[name] ||= {:columns=>[], :unique=>r[:Non_unique] != 1}
64
68
  i[:columns] << m.call(r[:Column_name])
65
69
  end
@@ -22,6 +22,11 @@ module Sequel
22
22
  db.extend(Sequel::Swift::MySQL::DatabaseMethods)
23
23
  db.swift_class = ::Swift::DB::Mysql
24
24
  end,
25
+ :sqlite=>proc do |db|
26
+ Sequel.ts_require 'adapters/swift/sqlite'
27
+ db.extend(Sequel::Swift::SQLite::DatabaseMethods)
28
+ db.swift_class = ::Swift::DB::Sqlite3
29
+ end,
25
30
  }
26
31
 
27
32
  class Database < Sequel::Database
@@ -45,7 +50,7 @@ module Sequel
45
50
  raise(Error, "No :db_type option specified")
46
51
  end
47
52
  else
48
- raise(Error, ":db_type option not valid, should be postgres or mysql")
53
+ raise(Error, ":db_type option not valid, should be postgres, mysql, or sqlite")
49
54
  end
50
55
  end
51
56
 
@@ -63,14 +68,11 @@ module Sequel
63
68
  def execute(sql, opts={})
64
69
  synchronize(opts[:server]) do |conn|
65
70
  begin
66
- res = nil
67
- log_yield(sql){conn.execute(sql); res = conn.results}
71
+ res = log_yield(sql){conn.execute(sql)}
68
72
  yield res if block_given?
69
73
  nil
70
74
  rescue SwiftError => e
71
75
  raise_error(e)
72
- ensure
73
- res.finish if res
74
76
  end
75
77
  end
76
78
  end
@@ -80,7 +82,7 @@ module Sequel
80
82
  def execute_dui(sql, opts={})
81
83
  synchronize(opts[:server]) do |conn|
82
84
  begin
83
- log_yield(sql){conn.execute(sql)}
85
+ log_yield(sql){conn.execute(sql).rows}
84
86
  rescue SwiftError => e
85
87
  raise_error(e)
86
88
  end
@@ -92,12 +94,9 @@ module Sequel
92
94
  def execute_insert(sql, opts={})
93
95
  synchronize(opts[:server]) do |conn|
94
96
  begin
95
- res = nil
96
- log_yield(sql){conn.execute(sql); (res = conn.results).insert_id}
97
+ log_yield(sql){conn.execute(sql).insert_id}
97
98
  rescue SwiftError => e
98
99
  raise_error(e)
99
- ensure
100
- res.finish if res
101
100
  end
102
101
  end
103
102
  end
@@ -50,13 +50,11 @@ module Sequel
50
50
  def execute(sql, opts={})
51
51
  synchronize(opts[:server]) do |conn|
52
52
  begin
53
- conn.execute(sql)
54
- res = conn.results
53
+ res = conn.execute(sql)
55
54
  yield res if block_given?
55
+ nil
56
56
  rescue SwiftError => e
57
57
  raise_error(e)
58
- ensure
59
- res.finish if res
60
58
  end
61
59
  end
62
60
  end
@@ -66,7 +64,7 @@ module Sequel
66
64
  def execute_dui(sql, opts={})
67
65
  synchronize(opts[:server]) do |conn|
68
66
  begin
69
- conn.execute(sql)
67
+ conn.execute(sql).rows
70
68
  rescue SwiftError => e
71
69
  raise_error(e)
72
70
  end
@@ -0,0 +1,31 @@
1
+ Sequel.require 'adapters/shared/sqlite'
2
+
3
+ module Sequel
4
+ module Swift
5
+ # Database and Dataset instance methods for SQLite specific
6
+ # support via Swift.
7
+ module SQLite
8
+ # Database instance methods for SQLite databases accessed via Swift.
9
+ module DatabaseMethods
10
+ include Sequel::SQLite::DatabaseMethods
11
+
12
+ # Return instance of Sequel::Swift::SQL::Dataset with the given opts.
13
+ def dataset(opts=nil)
14
+ Sequel::Swift::SQLite::Dataset.new(self, opts)
15
+ end
16
+ end
17
+
18
+ # Dataset class for SQLite datasets accessed via Swift.
19
+ class Dataset < Swift::Dataset
20
+ include Sequel::SQLite::DatasetMethods
21
+
22
+ private
23
+
24
+ # Use Swift's escape method for quoting.
25
+ def literal_string(s)
26
+ db.synchronize{|c| "#{c.escape(s)}"}
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1473,7 +1473,7 @@ module Sequel
1473
1473
 
1474
1474
  # Make sure the association is valid for this model, and return the related AssociationReflection.
1475
1475
  def check_association(model, association)
1476
- raise(Sequel::Error, "Invalid association #{association} for #{model.name}") unless reflection = model.association_reflection(association)
1476
+ raise(Sequel::UndefinedAssociation, "Invalid association #{association} for #{model.name}") unless reflection = model.association_reflection(association)
1477
1477
  raise(Sequel::Error, "Eager loading is not allowed for #{model.name} association #{association}") if reflection[:allow_eager] == false
1478
1478
  reflection
1479
1479
  end
@@ -1538,7 +1538,7 @@ module Sequel
1538
1538
  # specific foreign/primary key
1539
1539
  key_hash = {}
1540
1540
  # Reflections for all associations to eager load
1541
- reflections = eager_assoc.keys.collect{|assoc| model.association_reflection(assoc)}
1541
+ reflections = eager_assoc.keys.collect{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
1542
1542
 
1543
1543
  # Populate keys to monitor
1544
1544
  reflections.each{|reflection| key_hash[reflection.eager_loader_key] ||= Hash.new{|h,k| h[k] = []}}
@@ -6,6 +6,9 @@ module Sequel
6
6
  # modify a single row.
7
7
  class NoExistingObject < Error; end
8
8
 
9
+ # Raised when an undefined association is used when eager loading.
10
+ class UndefinedAssociation < Error; end
11
+
9
12
  # Exception class raised when +raise_on_save_failure+ is set and validation fails
10
13
  class ValidationFailed < Error
11
14
  def initialize(errors)
@@ -44,7 +44,14 @@ module Sequel
44
44
  def load_associated_objects(opts, reload=false)
45
45
  name = opts[:name]
46
46
  if !associations.include?(name) && retrieved_by
47
- retrieved_by.send(:eager_load, retrieved_with, name=>{})
47
+ begin
48
+ retrieved_by.send(:eager_load, retrieved_with, name=>{})
49
+ rescue Sequel::UndefinedAssociation
50
+ # This can happen if class table inheritance is used and the association
51
+ # is only defined in a subclass. This particular instance can use the
52
+ # association, but it can't be eagerly loaded as the parent class doesn't
53
+ # have access to the association, and that's the class doing the eager loading.
54
+ end
48
55
  end
49
56
  super
50
57
  end
@@ -232,15 +232,17 @@ module Sequel
232
232
  # Possible Options:
233
233
  # * :is - The exact size required for the value to be valid (no default)
234
234
  # * :maximum - The maximum size allowed for the value (no default)
235
- # * :message - The message to use (no default, overrides :too_long, :too_short, and :wrong_length
235
+ # * :message - The message to use (no default, overrides :nil_message, :too_long, :too_short, and :wrong_length
236
236
  # options if present)
237
237
  # * :minimum - The minimum size allowed for the value (no default)
238
+ # * :nil_message - The message to use use if :maximum option is used and the value is nil (default: 'is not present')
238
239
  # * :too_long - The message to use use if it the value is too long (default: 'is too long')
239
240
  # * :too_short - The message to use use if it the value is too short (default: 'is too short')
240
241
  # * :within - The array/range that must include the size of the value for it to be valid (no default)
241
242
  # * :wrong_length - The message to use use if it the value is not valid (default: 'is the wrong length')
242
243
  def validates_length_of(*atts)
243
244
  opts = {
245
+ :nil_message => 'is not present',
244
246
  :too_long => 'is too long',
245
247
  :too_short => 'is too short',
246
248
  :wrong_length => 'is the wrong length'
@@ -251,7 +253,7 @@ module Sequel
251
253
  atts << opts
252
254
  validates_each(*atts) do |o, a, v|
253
255
  if m = opts[:maximum]
254
- o.errors.add(a, opts[:message] || opts[:too_long]) unless v && v.size <= m
256
+ o.errors.add(a, opts[:message] || (v ? opts[:too_long] : opts[:nil_message])) unless v && v.size <= m
255
257
  end
256
258
  if m = opts[:minimum]
257
259
  o.errors.add(a, opts[:message] || opts[:too_short]) unless v && v.size >= m
@@ -50,7 +50,7 @@ module Sequel
50
50
  :includes=>{:message=>lambda{|set| "is not in range or set: #{set.inspect}"}},
51
51
  :integer=>{:message=>lambda{"is not a number"}},
52
52
  :length_range=>{:message=>lambda{|range| "is too short or too long"}},
53
- :max_length=>{:message=>lambda{|max| "is longer than #{max} characters"}},
53
+ :max_length=>{:message=>lambda{|max| "is longer than #{max} characters"}, :nil_message=>lambda{"is not present"}},
54
54
  :min_length=>{:message=>lambda{|min| "is shorter than #{min} characters"}},
55
55
  :not_string=>{:message=>lambda{|type| type ? "is not a valid #{type}" : "is a string"}},
56
56
  :numeric=>{:message=>lambda{"is not a number"}},
@@ -93,8 +93,11 @@ module Sequel
93
93
  end
94
94
 
95
95
  # Check that the attribute values are not longer than the given max length.
96
+ #
97
+ # Accepts a :nil_message option that is the error message to use when the
98
+ # value is nil instead of being too long.
96
99
  def validates_max_length(max, atts, opts={})
97
- validatable_attributes_for_type(:max_length, atts, opts){|a,v,m| validation_error_message(m, max) unless v && v.length <= max}
100
+ validatable_attributes_for_type(:max_length, atts, opts){|a,v,m| v ? validation_error_message(m, max) : validation_error_message(opts[:nil_message] || DEFAULT_OPTIONS[:max_length][:nil_message]) unless v && v.length <= max}
98
101
  end
99
102
 
100
103
  # Check that the attribute values are not shorter than the given min length.
@@ -3,7 +3,7 @@ module Sequel
3
3
  MAJOR = 3
4
4
  # The minor version of Sequel. Bumped for every non-patch level
5
5
  # release, generally around once a month.
6
- MINOR = 19
6
+ MINOR = 20
7
7
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
8
8
  # releases that fix regressions from previous versions.
9
9
  TINY = 0
@@ -565,6 +565,18 @@ if %w'localhost 127.0.0.1 ::1'.include?(MYSQL_URI.host) and MYSQL_DB.adapter_sch
565
565
  end
566
566
  end
567
567
 
568
+ context "A MySQL database" do
569
+ specify "should accept a read_timeout option when connecting" do
570
+ db = Sequel.connect(MYSQL_DB.opts.merge(:read_timeout=>22342))
571
+ proc {db.test_connection}.should_not raise_error
572
+ end
573
+
574
+ specify "should accept a connect_timeout option when connecting" do
575
+ db = Sequel.connect(MYSQL_DB.opts.merge(:connect_timeout=>22342))
576
+ proc {db.test_connection}.should_not raise_error
577
+ end
578
+ end
579
+
568
580
  context "A grouped MySQL dataset" do
569
581
  before do
570
582
  MYSQL_DB[:test2].delete
@@ -648,6 +660,12 @@ context "A MySQL database" do
648
660
  @db << "CREATE INDEX posts_id_index ON posts (id(10))"
649
661
  @db.indexes(:posts).should == {}
650
662
  end
663
+
664
+ specify "should dump partial indexes if :partial option is set to true" do
665
+ @db.create_table(:posts){text :id}
666
+ @db << "CREATE INDEX posts_id_index ON posts (id(10))"
667
+ @db.indexes(:posts, :partial => true).should == {:posts_id_index => {:columns => [:id], :unique => false}}
668
+ end
651
669
  end
652
670
 
653
671
  context "MySQL::Dataset#insert and related methods" do
@@ -98,7 +98,7 @@ context "An SQLite database" do
98
98
  proc {@db.temp_store = :invalid}.should raise_error(Sequel::Error)
99
99
  end
100
100
 
101
- cspecify "should support timestamps and datetimes and respect datetime_class", :do, :jdbc, :amalgalite do
101
+ cspecify "should support timestamps and datetimes and respect datetime_class", :do, :jdbc, :amalgalite, :swift do
102
102
  @db.create_table!(:time){timestamp :t; datetime :d}
103
103
  t1 = Time.at(1)
104
104
  @db[:time] << {:t => t1, :d => t1}
@@ -168,7 +168,7 @@ context "A connection pool with a max size of 1" do
168
168
  cc,c1, c2 = nil
169
169
 
170
170
  t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup; while c == 'herro';sleep 0.01;end}}
171
- sleep 0.02
171
+ sleep 0.03
172
172
  cc.should == 'herro'
173
173
  c1.should == 'herro'
174
174
 
@@ -341,6 +341,20 @@ describe Sequel::Model do
341
341
  @m.should be_valid
342
342
  @m.value = '123456'
343
343
  @m.should_not be_valid
344
+ @m.errors[:value].should == ['is too long']
345
+ @m.value = nil
346
+ @m.should_not be_valid
347
+ @m.errors[:value].should == ['is not present']
348
+ end
349
+
350
+ specify "should validate length_of with maximum using customized error messages" do
351
+ @c.validates_length_of :value, :maximum => 5, :too_long=>'tl', :nil_message=>'np'
352
+ @m.value = '123456'
353
+ @m.should_not be_valid
354
+ @m.errors[:value].should == ['tl']
355
+ @m.value = nil
356
+ @m.should_not be_valid
357
+ @m.errors[:value].should == ['np']
344
358
  end
345
359
 
346
360
  specify "should validate length_of with minimum" do
@@ -210,6 +210,20 @@ describe "Sequel::Plugins::ValidationHelpers" do
210
210
  @m.should be_valid
211
211
  @m.value = '123456'
212
212
  @m.should_not be_valid
213
+ @m.errors[:value].should == ['is longer than 5 characters']
214
+ @m.value = nil
215
+ @m.should_not be_valid
216
+ @m.errors[:value].should == ['is not present']
217
+ end
218
+
219
+ specify "should support validates_max_length with nil value" do
220
+ @c.set_validations{validates_max_length(5, :value, :message=>'tl', :nil_message=>'np')}
221
+ @m.value = '123456'
222
+ @m.should_not be_valid
223
+ @m.errors[:value].should == ['tl']
224
+ @m.value = nil
225
+ @m.should_not be_valid
226
+ @m.errors[:value].should == ['np']
213
227
  end
214
228
 
215
229
  specify "should support validates_min_length" do
@@ -90,6 +90,10 @@ describe "Class Table Inheritance Plugin" do
90
90
  @db[:employees][:id=>i].should == nil
91
91
  end
92
92
 
93
+ specify "should handle associations only defined in subclasses" do
94
+ Employee.filter(:id=>@i2).all.first.manager.id.should == @i4
95
+ end
96
+
93
97
  # See http://www.sqlite.org/src/tktview/3338b3fa19ac4abee6c475126a2e6d9d61f26ab1
94
98
  cspecify "should insert rows into all tables", :sqlite do
95
99
  e = Executive.create(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
@@ -251,11 +251,11 @@ describe "Bound Argument Types" do
251
251
  @ds.filter(:t=>@ds.ba(:$x, :timestamp)).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[:t]
252
252
  end
253
253
 
254
- cspecify "should handle blob type", [:swift], [:jdbc, :postgres] do
254
+ cspecify "should handle blob type", [:swift] do
255
255
  @ds.filter(:file=>@ds.ba(:$x, :bytea)).prepare(:first, :ps_blob).call(:x=>@vs[:file])[:file].should == @vs[:file]
256
256
  end
257
257
 
258
- specify "should handle float type" do
258
+ cspecify "should handle float type", [:swift, :sqlite] do
259
259
  @ds.filter(:f=>@ds.ba(:$x, :"double precision")).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].should == @vs[:f]
260
260
  end
261
261
 
@@ -39,13 +39,13 @@ describe "Supported types" do
39
39
  ds.all.should == [{:number=>2**34}]
40
40
  end
41
41
 
42
- specify "should support generic float type" do
42
+ cspecify "should support generic float type", [:swift, :sqlite] do
43
43
  ds = create_items_table_with_column(:number, Float)
44
44
  ds.insert(:number => 2.1)
45
45
  ds.all.should == [{:number=>2.1}]
46
46
  end
47
47
 
48
- cspecify "should support generic numeric type", [:odbc, :mssql] do
48
+ cspecify "should support generic numeric type", [:odbc, :mssql], [:swift, :sqlite] do
49
49
  ds = create_items_table_with_column(:number, Numeric, :size=>[15, 10])
50
50
  ds.insert(:number => BigDecimal.new('2.123456789'))
51
51
  ds.all.should == [{:number=>BigDecimal.new('2.123456789')}]
@@ -79,7 +79,7 @@ describe "Supported types" do
79
79
  ds.first[:tim].strftime('%Y%m%d%H%M%S').should == t.strftime('%Y%m%d%H%M%S')
80
80
  end
81
81
 
82
- cspecify "should support generic file type", [:do], [:odbc, :mssql], [:mysql2], [:swift], [:jdbc, :postgres] do
82
+ cspecify "should support generic file type", [:do], [:odbc, :mssql], [:mysql2], [:swift] do
83
83
  ds = create_items_table_with_column(:name, File)
84
84
  ds.insert(:name => ("a\0"*300).to_sequel_blob)
85
85
  ds.all.should == [{:name=>("a\0"*300).to_sequel_blob}]
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- hash: 75
4
+ hash: 87
5
5
  prerelease: false
6
6
  segments:
7
7
  - 3
8
- - 19
8
+ - 20
9
9
  - 0
10
- version: 3.19.0
10
+ version: 3.20.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jeremy Evans
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-03 00:00:00 -08:00
18
+ date: 2011-02-01 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -83,6 +83,7 @@ extra_rdoc_files:
83
83
  - doc/release_notes/3.17.0.txt
84
84
  - doc/release_notes/3.18.0.txt
85
85
  - doc/release_notes/3.19.0.txt
86
+ - doc/release_notes/3.20.0.txt
86
87
  files:
87
88
  - MIT-LICENSE
88
89
  - CHANGELOG
@@ -133,6 +134,7 @@ files:
133
134
  - doc/release_notes/3.17.0.txt
134
135
  - doc/release_notes/3.18.0.txt
135
136
  - doc/release_notes/3.19.0.txt
137
+ - doc/release_notes/3.20.0.txt
136
138
  - doc/sharding.rdoc
137
139
  - doc/sql.rdoc
138
140
  - doc/virtual_rows.rdoc
@@ -311,12 +313,14 @@ files:
311
313
  - lib/sequel/adapters/shared/postgres.rb
312
314
  - lib/sequel/adapters/shared/progress.rb
313
315
  - lib/sequel/adapters/shared/sqlite.rb
316
+ - lib/sequel/adapters/shared/access.rb
314
317
  - lib/sequel/adapters/sqlite.rb
315
318
  - lib/sequel/adapters/utils/stored_procedures.rb
316
319
  - lib/sequel/adapters/mysql2.rb
317
320
  - lib/sequel/adapters/swift.rb
318
321
  - lib/sequel/adapters/swift/mysql.rb
319
322
  - lib/sequel/adapters/swift/postgres.rb
323
+ - lib/sequel/adapters/swift/sqlite.rb
320
324
  - lib/sequel/connection_pool.rb
321
325
  - lib/sequel/connection_pool/sharded_single.rb
322
326
  - lib/sequel/connection_pool/sharded_threaded.rb