sequel 3.11.0 → 3.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 (136) hide show
  1. data/CHANGELOG +70 -0
  2. data/Rakefile +1 -1
  3. data/doc/active_record.rdoc +896 -0
  4. data/doc/advanced_associations.rdoc +46 -31
  5. data/doc/association_basics.rdoc +14 -9
  6. data/doc/dataset_basics.rdoc +3 -3
  7. data/doc/migration.rdoc +1011 -0
  8. data/doc/model_hooks.rdoc +198 -0
  9. data/doc/querying.rdoc +811 -86
  10. data/doc/release_notes/3.12.0.txt +304 -0
  11. data/doc/sharding.rdoc +17 -0
  12. data/doc/sql.rdoc +537 -0
  13. data/doc/validations.rdoc +501 -0
  14. data/lib/sequel/adapters/jdbc.rb +19 -27
  15. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -7
  16. data/lib/sequel/adapters/mysql.rb +5 -4
  17. data/lib/sequel/adapters/odbc.rb +3 -2
  18. data/lib/sequel/adapters/shared/mssql.rb +7 -6
  19. data/lib/sequel/adapters/shared/mysql.rb +2 -7
  20. data/lib/sequel/adapters/shared/postgres.rb +2 -8
  21. data/lib/sequel/adapters/shared/sqlite.rb +2 -5
  22. data/lib/sequel/adapters/sqlite.rb +4 -4
  23. data/lib/sequel/core.rb +0 -1
  24. data/lib/sequel/database.rb +2 -1060
  25. data/lib/sequel/database/connecting.rb +227 -0
  26. data/lib/sequel/database/dataset.rb +58 -0
  27. data/lib/sequel/database/dataset_defaults.rb +127 -0
  28. data/lib/sequel/database/logging.rb +62 -0
  29. data/lib/sequel/database/misc.rb +246 -0
  30. data/lib/sequel/database/query.rb +390 -0
  31. data/lib/sequel/database/schema_generator.rb +7 -3
  32. data/lib/sequel/database/schema_methods.rb +351 -7
  33. data/lib/sequel/dataset/actions.rb +9 -2
  34. data/lib/sequel/dataset/misc.rb +6 -2
  35. data/lib/sequel/dataset/mutation.rb +3 -11
  36. data/lib/sequel/dataset/query.rb +49 -6
  37. data/lib/sequel/exceptions.rb +3 -0
  38. data/lib/sequel/extensions/migration.rb +395 -113
  39. data/lib/sequel/extensions/schema_dumper.rb +21 -13
  40. data/lib/sequel/model.rb +27 -25
  41. data/lib/sequel/model/associations.rb +72 -34
  42. data/lib/sequel/model/base.rb +74 -18
  43. data/lib/sequel/model/errors.rb +8 -1
  44. data/lib/sequel/plugins/active_model.rb +8 -0
  45. data/lib/sequel/plugins/association_pks.rb +87 -0
  46. data/lib/sequel/plugins/association_proxies.rb +8 -0
  47. data/lib/sequel/plugins/boolean_readers.rb +12 -6
  48. data/lib/sequel/plugins/caching.rb +14 -7
  49. data/lib/sequel/plugins/class_table_inheritance.rb +15 -9
  50. data/lib/sequel/plugins/composition.rb +2 -1
  51. data/lib/sequel/plugins/force_encoding.rb +10 -7
  52. data/lib/sequel/plugins/hook_class_methods.rb +12 -11
  53. data/lib/sequel/plugins/identity_map.rb +9 -0
  54. data/lib/sequel/plugins/instance_hooks.rb +23 -13
  55. data/lib/sequel/plugins/lazy_attributes.rb +4 -1
  56. data/lib/sequel/plugins/many_through_many.rb +18 -4
  57. data/lib/sequel/plugins/nested_attributes.rb +1 -0
  58. data/lib/sequel/plugins/optimistic_locking.rb +1 -1
  59. data/lib/sequel/plugins/rcte_tree.rb +9 -8
  60. data/lib/sequel/plugins/schema.rb +8 -0
  61. data/lib/sequel/plugins/serialization.rb +1 -3
  62. data/lib/sequel/plugins/sharding.rb +135 -0
  63. data/lib/sequel/plugins/single_table_inheritance.rb +117 -25
  64. data/lib/sequel/plugins/skip_create_refresh.rb +35 -0
  65. data/lib/sequel/plugins/string_stripper.rb +26 -0
  66. data/lib/sequel/plugins/tactical_eager_loading.rb +8 -0
  67. data/lib/sequel/plugins/timestamps.rb +15 -2
  68. data/lib/sequel/plugins/touch.rb +13 -0
  69. data/lib/sequel/plugins/update_primary_key.rb +48 -0
  70. data/lib/sequel/plugins/validation_class_methods.rb +8 -0
  71. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  72. data/lib/sequel/sql.rb +17 -20
  73. data/lib/sequel/version.rb +1 -1
  74. data/spec/adapters/postgres_spec.rb +5 -5
  75. data/spec/core/core_sql_spec.rb +17 -1
  76. data/spec/core/database_spec.rb +17 -5
  77. data/spec/core/dataset_spec.rb +31 -8
  78. data/spec/core/schema_generator_spec.rb +8 -1
  79. data/spec/core/schema_spec.rb +13 -0
  80. data/spec/extensions/association_pks_spec.rb +85 -0
  81. data/spec/extensions/hook_class_methods_spec.rb +9 -9
  82. data/spec/extensions/migration_spec.rb +339 -219
  83. data/spec/extensions/schema_dumper_spec.rb +28 -17
  84. data/spec/extensions/sharding_spec.rb +272 -0
  85. data/spec/extensions/single_table_inheritance_spec.rb +92 -4
  86. data/spec/extensions/skip_create_refresh_spec.rb +17 -0
  87. data/spec/extensions/string_stripper_spec.rb +23 -0
  88. data/spec/extensions/update_primary_key_spec.rb +65 -0
  89. data/spec/extensions/validation_class_methods_spec.rb +5 -5
  90. data/spec/files/bad_down_migration/001_create_alt_basic.rb +4 -0
  91. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +4 -0
  92. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  93. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +9 -0
  94. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +3 -0
  95. data/spec/files/bad_up_migration/001_create_alt_basic.rb +4 -0
  96. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +3 -0
  97. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +9 -0
  98. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +9 -0
  99. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +4 -0
  100. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +9 -0
  101. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +9 -0
  102. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +4 -0
  103. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +4 -0
  104. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  105. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +9 -0
  106. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +4 -0
  107. data/spec/files/integer_migrations/001_create_sessions.rb +9 -0
  108. data/spec/files/integer_migrations/002_create_nodes.rb +9 -0
  109. data/spec/files/integer_migrations/003_3_create_users.rb +4 -0
  110. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  111. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +9 -0
  112. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +9 -0
  113. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +9 -0
  114. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +4 -0
  115. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +4 -0
  116. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +4 -0
  117. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  118. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +4 -0
  119. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +9 -0
  120. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +9 -0
  121. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +4 -0
  122. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +9 -0
  123. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +9 -0
  124. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +4 -0
  125. data/spec/integration/eager_loader_test.rb +20 -20
  126. data/spec/integration/migrator_test.rb +187 -0
  127. data/spec/integration/plugin_test.rb +150 -0
  128. data/spec/integration/schema_test.rb +13 -2
  129. data/spec/model/associations_spec.rb +41 -14
  130. data/spec/model/base_spec.rb +69 -0
  131. data/spec/model/eager_loading_spec.rb +7 -3
  132. data/spec/model/record_spec.rb +79 -4
  133. data/spec/model/validations_spec.rb +21 -9
  134. metadata +66 -5
  135. data/doc/schema.rdoc +0 -36
  136. data/lib/sequel/database/schema_sql.rb +0 -320
@@ -0,0 +1,26 @@
1
+ module Sequel
2
+ module Plugins
3
+ # StringStripper is a very simple plugin that strips all input strings
4
+ # when assigning to the model's values. Example:
5
+ #
6
+ # album = Album.new(:name=>' A ')
7
+ # album.name # => 'A'
8
+ #
9
+ # Usage:
10
+ #
11
+ # # Make all model subclass instances strip strings (called before loading subclasses)
12
+ # Sequel::Model.plugin :string_stripper
13
+ #
14
+ # # Make the Album class strip strings
15
+ # Album.plugin :string_stripper
16
+ module StringStripper
17
+ module InstanceMethods
18
+ # Strip value if it is a string, before attempting to assign
19
+ # it to the model's values.
20
+ def []=(k, v)
21
+ v.is_a?(String) ? super(k, v.strip) : super
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -17,6 +17,14 @@ module Sequel
17
17
  # Album.filter{id<100}.all do |a|
18
18
  # a.artists
19
19
  # end
20
+ #
21
+ # Usage:
22
+ #
23
+ # # Make all model subclass instances use tactical eager loading (called before loading subclasses)
24
+ # Sequel::Model.plugin :tactical_eager_loading
25
+ #
26
+ # # Make the Album class use tactical eager loading
27
+ # Album.plugin :tactical_eager_loading
20
28
  module TacticalEagerLoading
21
29
  module InstanceMethods
22
30
  # The dataset that retrieved this object, set if the object was
@@ -5,6 +5,19 @@ module Sequel
5
5
  # can also set whether to overwrite existing create timestamps (false
6
6
  # by default), or whether to set the update timestamp when creating (also
7
7
  # false by default).
8
+ #
9
+ # Usage:
10
+ #
11
+ # # Timestamp all model instances using +created_at+ and +updated_at+
12
+ # # (called before loading subclasses)
13
+ # Sequel::Model.plugin :timestamps
14
+ #
15
+ # # Timestamp Album instances, with custom column names
16
+ # Album.plugin :timestamps, :create=>:created_on, :update=>:updated_on
17
+ #
18
+ # # Timestamp Artist instances, forcing an overwrite of the create
19
+ # # timestamp, and setting the update timestamp when creating
20
+ # Album.plugin :timestamps, :force=>true, :update_on_create=>true
8
21
  module Timestamps
9
22
  # Configure the plugin by setting the avialable options. Note that
10
23
  # if this method is run more than once, previous settings are ignored,
@@ -51,14 +64,14 @@ module Sequel
51
64
  module InstanceMethods
52
65
  # Set the create timestamp when creating
53
66
  def before_create
54
- super
55
67
  set_create_timestamp
68
+ super
56
69
  end
57
70
 
58
71
  # Set the update timestamp when updating
59
72
  def before_update
60
- super
61
73
  set_update_timestamp
74
+ super
62
75
  end
63
76
 
64
77
  private
@@ -13,6 +13,19 @@ module Sequel
13
13
  # on datasets, so it updates all related rows in a single query, using
14
14
  # the SQL standard CURRENT_TIMESTAMP. Both of these can be overridden
15
15
  # easily if necessary.
16
+ #
17
+ # Usage:
18
+ #
19
+ # # Allow touching of all model instances (called before loading subclasses)
20
+ # Sequel::Model.plugin :touch
21
+ #
22
+ # # Allow touching of Album instances, with a custom column
23
+ # Album.plugin :touch, :column=>:updated_on
24
+ #
25
+ # # Allow touching of Artist instances, updating the albums and tags
26
+ # # associations when touching, touching the +updated_on+ column for
27
+ # # albums and the +updated_at+ column for tags
28
+ # Artist.plugin :touch, :associations=>[{:albums=>:updated_on}, :tags]
16
29
  module Touch
17
30
  # The default column to update when touching
18
31
  TOUCH_COLUMN_DEFAULT = :updated_at
@@ -0,0 +1,48 @@
1
+ module Sequel
2
+ module Plugins
3
+ # The update_primary_key plugin allows you to modify an objects
4
+ # primary key and then save the record. Sequel does not work
5
+ # correctly with primary key modifications by default. Sequel
6
+ # is designed to work with surrogate primary keys that never need to be
7
+ # modified, but this plugin makes it work correctly with natural
8
+ # primary keys that may need to be modified. Example:
9
+ #
10
+ # album = Album[1]
11
+ # album.id = 2
12
+ # album.save
13
+ #
14
+ # Usage:
15
+ #
16
+ # # Make all model subclasses support primary key updates
17
+ # # (called before loading subclasses)
18
+ # Sequel::Model.plugin :update_primary_key
19
+ #
20
+ # # Make the Album class support primary key updates
21
+ # Album.plugin :update_primary_key
22
+ module UpdatePrimaryKey
23
+ module ClassMethods
24
+ # Cache the pk_hash when loading records
25
+ def load(h)
26
+ r = super(h)
27
+ r.pk_hash
28
+ r
29
+ end
30
+ end
31
+
32
+ module InstanceMethods
33
+ # Clear the pk_hash and object dataset cache, and recache
34
+ # the pk_hash
35
+ def after_update
36
+ super
37
+ @pk_hash = nil
38
+ pk_hash
39
+ end
40
+
41
+ # Cache the pk_hash instead of generating it every time
42
+ def pk_hash
43
+ @pk_hash ||= super
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -7,6 +7,14 @@ module Sequel
7
7
  #
8
8
  # It is recommended to use the validation_helpers plugin instead of this one,
9
9
  # as it is less complex and more flexible.
10
+ #
11
+ # Usage:
12
+ #
13
+ # # Add the validation class methods to all model subclasses (called before loading subclasses)
14
+ # Sequel::Model.plugin :validation_class_methods
15
+ #
16
+ # # Add the validation class methods to the Album class
17
+ # Album.plugin :validation_class_methods
10
18
  module ValidationClassMethods
11
19
  # Setup the validations hash for the given model.
12
20
  def self.apply(model)
@@ -3,8 +3,8 @@ module Sequel
3
3
  # The validation_helpers plugin contains instance method equivalents for most of the legacy
4
4
  # class-level validations. The names and APIs are different, though. Example:
5
5
  #
6
+ # Sequel::Model.plugin :validation_helpers
6
7
  # class Album < Sequel::Model
7
- # plugin :validation_helpers
8
8
  # def validate
9
9
  # validates_min_length 1, :num_tracks
10
10
  # end
data/lib/sequel/sql.rb CHANGED
@@ -68,23 +68,32 @@ module Sequel
68
68
  end
69
69
  private_class_method :to_s_method
70
70
 
71
+ # Alias of eql?
72
+ def ==(other)
73
+ eql?(other)
74
+ end
75
+
76
+ # Returns true if the receiver is the same expression as the
77
+ # the +other+ expression.
78
+ def eql?(other)
79
+ other.is_a?(self.class) && !self.class.comparison_attrs.find {|a| send(a) != other.send(a)}
80
+ end
81
+
82
+ # Make sure that the hash value is the same if the attributes are the same.
83
+ def hash
84
+ ([self.class] + self.class.comparison_attrs.map{|x| send(x)}).hash
85
+ end
86
+
71
87
  # Returns self, because SQL::Expression already acts like
72
88
  # LiteralString.
73
89
  def lit
74
90
  self
75
91
  end
76
92
 
77
- # Alias for to_s
93
+ # Alias of to_s
78
94
  def sql_literal(ds)
79
95
  to_s(ds)
80
96
  end
81
-
82
- # Returns true if the receiver is the same expression as the
83
- # the +other+ expression.
84
- def eql?(other)
85
- other.is_a?(self.class) && !self.class.comparison_attrs.find {|a| send(a) != other.send(a)}
86
- end
87
- alias == eql?
88
97
  end
89
98
 
90
99
  # Represents a complex SQL expression, with a given operator and one
@@ -559,12 +568,6 @@ module Sequel
559
568
  @table = table
560
569
  end
561
570
 
562
- # ColumnAll expressions are considered equivalent if they
563
- # have the same class and string representation
564
- def ==(x)
565
- x.class == self.class and @table == x.table
566
- end
567
-
568
571
  to_s_method :column_all_sql
569
572
  end
570
573
 
@@ -626,12 +629,6 @@ module Sequel
626
629
  @f, @args = f, args
627
630
  end
628
631
 
629
- # Functions are considered equivalent if they
630
- # have the same class, function, and arguments.
631
- def ==(x)
632
- x.class == self.class && @f == x.f && @args == x.args
633
- end
634
-
635
632
  to_s_method :function_sql
636
633
  end
637
634
 
@@ -1,6 +1,6 @@
1
1
  module Sequel
2
2
  MAJOR = 3
3
- MINOR = 11
3
+ MINOR = 12
4
4
  TINY = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join('.')
@@ -541,7 +541,7 @@ context "Postgres::Database schema qualified tables" do
541
541
  after do
542
542
  POSTGRES_DB.quote_identifiers = false
543
543
  POSTGRES_DB << "DROP SCHEMA schema_test CASCADE"
544
- POSTGRES_DB.default_schema = :public
544
+ POSTGRES_DB.default_schema = nil
545
545
  end
546
546
 
547
547
  specify "should be able to create, drop, select and insert into tables in a given schema" do
@@ -914,7 +914,7 @@ context "Postgres::Database functions, languages, and triggers" do
914
914
  specify "#create_trigger and #drop_trigger should create and drop triggers" do
915
915
  @d.create_language(:plpgsql)
916
916
  @d.create_function(:tf, 'BEGIN IF NEW.value IS NULL THEN RAISE EXCEPTION \'Blah\'; END IF; RETURN NEW; END;', :language=>:plpgsql, :returns=>:trigger)
917
- @d.send(:create_trigger_sql, :test, :identity, :tf, :each_row=>true).should == 'CREATE TRIGGER identity BEFORE INSERT OR UPDATE OR DELETE ON public.test FOR EACH ROW EXECUTE PROCEDURE tf()'
917
+ @d.send(:create_trigger_sql, :test, :identity, :tf, :each_row=>true).should == 'CREATE TRIGGER identity BEFORE INSERT OR UPDATE OR DELETE ON test FOR EACH ROW EXECUTE PROCEDURE tf()'
918
918
  @d.create_table(:test){String :name; Integer :value}
919
919
  @d.create_trigger(:test, :identity, :tf, :each_row=>true)
920
920
  @d[:test].insert(:name=>'a', :value=>1)
@@ -923,10 +923,10 @@ context "Postgres::Database functions, languages, and triggers" do
923
923
  @d[:test].filter(:name=>'a').all.should == [{:name=>'a', :value=>1}]
924
924
  @d[:test].filter(:name=>'a').update(:value=>3)
925
925
  @d[:test].filter(:name=>'a').all.should == [{:name=>'a', :value=>3}]
926
- @d.send(:drop_trigger_sql, :test, :identity).should == 'DROP TRIGGER identity ON public.test'
926
+ @d.send(:drop_trigger_sql, :test, :identity).should == 'DROP TRIGGER identity ON test'
927
927
  @d.drop_trigger(:test, :identity)
928
- @d.send(:create_trigger_sql, :test, :identity, :tf, :after=>true, :events=>:insert, :args=>[1, 'a']).should == 'CREATE TRIGGER identity AFTER INSERT ON public.test EXECUTE PROCEDURE tf(1, \'a\')'
929
- @d.send(:drop_trigger_sql, :test, :identity, :if_exists=>true, :cascade=>true).should == 'DROP TRIGGER IF EXISTS identity ON public.test CASCADE'
928
+ @d.send(:create_trigger_sql, :test, :identity, :tf, :after=>true, :events=>:insert, :args=>[1, 'a']).should == 'CREATE TRIGGER identity AFTER INSERT ON test EXECUTE PROCEDURE tf(1, \'a\')'
929
+ @d.send(:drop_trigger_sql, :test, :identity, :if_exists=>true, :cascade=>true).should == 'DROP TRIGGER IF EXISTS identity ON test CASCADE'
930
930
  # Make sure if exists works
931
931
  @d.drop_trigger(:test, :identity, :if_exists=>true, :cascade=>true)
932
932
  end
@@ -410,8 +410,24 @@ context "Sequel::SQL::OrderedExpression" do
410
410
  end
411
411
 
412
412
  context "Expression" do
413
- specify "should ==" do
413
+ specify "should consider objects == only if they have the same attributes" do
414
414
  :column.qualify(:table).cast(:type).*(:numeric_column).asc.should == :column.qualify(:table).cast(:type).*(:numeric_column).asc
415
415
  :other_column.qualify(:table).cast(:type).*(:numeric_column).asc.should_not == :column.qualify(:table).cast(:type).*(:numeric_column).asc
416
+
417
+ :column.qualify(:table).cast(:type).*(:numeric_column).asc.should eql(:column.qualify(:table).cast(:type).*(:numeric_column).asc)
418
+ :other_column.qualify(:table).cast(:type).*(:numeric_column).asc.should_not eql(:column.qualify(:table).cast(:type).*(:numeric_column).asc)
419
+ end
420
+
421
+ specify "should use the same hash value for objects that have the same attributes" do
422
+ :column.qualify(:table).cast(:type).*(:numeric_column).asc.hash.should == :column.qualify(:table).cast(:type).*(:numeric_column).asc.hash
423
+ :other_column.qualify(:table).cast(:type).*(:numeric_column).asc.hash.should_not == :column.qualify(:table).cast(:type).*(:numeric_column).asc.hash
424
+
425
+ h = {}
426
+ a = :column.qualify(:table).cast(:type).*(:numeric_column).asc
427
+ b = :column.qualify(:table).cast(:type).*(:numeric_column).asc
428
+ h[a] = 1
429
+ h[b] = 2
430
+ h[a].should == 2
431
+ h[b].should == 2
416
432
  end
417
433
  end
@@ -204,8 +204,8 @@ context "Sequel.extension" do
204
204
  end
205
205
 
206
206
  context "Database#connect" do
207
- specify "should raise NotImplementedError" do
208
- proc {Sequel::Database.new.connect(:default)}.should raise_error(NotImplementedError)
207
+ specify "should raise Sequel::NotImplemented" do
208
+ proc {Sequel::Database.new.connect(:default)}.should raise_error(Sequel::NotImplemented)
209
209
  end
210
210
  end
211
211
 
@@ -363,9 +363,21 @@ context "Database#dataset" do
363
363
  end
364
364
 
365
365
  context "Database#execute" do
366
- specify "should raise NotImplementedError" do
367
- proc {Sequel::Database.new.execute('blah blah')}.should raise_error(NotImplementedError)
368
- proc {Sequel::Database.new << 'blah blah'}.should raise_error(NotImplementedError)
366
+ specify "should raise Sequel::NotImplemented" do
367
+ proc {Sequel::Database.new.execute('blah blah')}.should raise_error(Sequel::NotImplemented)
368
+ proc {Sequel::Database.new << 'blah blah'}.should raise_error(Sequel::NotImplemented)
369
+ end
370
+ end
371
+
372
+ context "Database#tables" do
373
+ specify "should raise Sequel::NotImplemented" do
374
+ proc {Sequel::Database.new.tables}.should raise_error(Sequel::NotImplemented)
375
+ end
376
+ end
377
+
378
+ context "Database#indexes" do
379
+ specify "should raise Sequel::NotImplemented" do
380
+ proc {Sequel::Database.new.indexes(:table)}.should raise_error(Sequel::NotImplemented)
369
381
  end
370
382
  end
371
383
 
@@ -1316,24 +1316,47 @@ context "Dataset#order_by" do
1316
1316
  end
1317
1317
  end
1318
1318
 
1319
- context "Dataset#order_more" do
1319
+ context "Dataset#order_more and order_append" do
1320
1320
  before do
1321
1321
  @dataset = Sequel::Dataset.new(nil).from(:test)
1322
1322
  end
1323
1323
 
1324
1324
  specify "should include an ORDER BY clause in the select statement" do
1325
- @dataset.order_more(:name).sql.should ==
1326
- 'SELECT * FROM test ORDER BY name'
1325
+ @dataset.order_more(:name).sql.should == 'SELECT * FROM test ORDER BY name'
1326
+ @dataset.order_append(:name).sql.should == 'SELECT * FROM test ORDER BY name'
1327
1327
  end
1328
1328
 
1329
- specify "should add to a previous ordering" do
1330
- @dataset.order(:name).order_more(:stamp.desc).sql.should ==
1331
- 'SELECT * FROM test ORDER BY name, stamp DESC'
1329
+ specify "should add to the end of a previous ordering" do
1330
+ @dataset.order(:name).order_more(:stamp.desc).sql.should == 'SELECT * FROM test ORDER BY name, stamp DESC'
1331
+ @dataset.order(:name).order_append(:stamp.desc).sql.should == 'SELECT * FROM test ORDER BY name, stamp DESC'
1332
1332
  end
1333
1333
 
1334
1334
  specify "should accept a block that yields a virtual row" do
1335
1335
  @dataset.order(:a).order_more{|o| o.b}.sql.should == 'SELECT * FROM test ORDER BY a, b'
1336
1336
  @dataset.order(:a, :b).order_more(:c, :d){[e, f(1, 2)]}.sql.should == 'SELECT * FROM test ORDER BY a, b, c, d, e, f(1, 2)'
1337
+ @dataset.order(:a).order_append{|o| o.b}.sql.should == 'SELECT * FROM test ORDER BY a, b'
1338
+ @dataset.order(:a, :b).order_append(:c, :d){[e, f(1, 2)]}.sql.should == 'SELECT * FROM test ORDER BY a, b, c, d, e, f(1, 2)'
1339
+ end
1340
+ end
1341
+
1342
+ context "Dataset#order_prepend" do
1343
+ before do
1344
+ @dataset = Sequel::Dataset.new(nil).from(:test)
1345
+ end
1346
+
1347
+ specify "should include an ORDER BY clause in the select statement" do
1348
+ @dataset.order_prepend(:name).sql.should ==
1349
+ 'SELECT * FROM test ORDER BY name'
1350
+ end
1351
+
1352
+ specify "should add to the beginning of a previous ordering" do
1353
+ @dataset.order(:name).order_prepend(:stamp.desc).sql.should ==
1354
+ 'SELECT * FROM test ORDER BY stamp DESC, name'
1355
+ end
1356
+
1357
+ specify "should accept a block that yields a virtual row" do
1358
+ @dataset.order(:a).order_prepend{|o| o.b}.sql.should == 'SELECT * FROM test ORDER BY b, a'
1359
+ @dataset.order(:a, :b).order_prepend(:c, :d){[e, f(1, 2)]}.sql.should == 'SELECT * FROM test ORDER BY c, d, e, f(1, 2), a, b'
1337
1360
  end
1338
1361
  end
1339
1362
 
@@ -3074,8 +3097,8 @@ context "Dataset default #fetch_rows, #insert, #update, #delete, #truncate, #exe
3074
3097
  @ds = @db[:items]
3075
3098
  end
3076
3099
 
3077
- specify "#fetch_rows should raise a NotImplementedError" do
3078
- proc{@ds.fetch_rows(''){}}.should raise_error(NotImplementedError)
3100
+ specify "#fetch_rows should raise a Sequel::NotImplemented" do
3101
+ proc{@ds.fetch_rows(''){}}.should raise_error(Sequel::NotImplemented)
3079
3102
  end
3080
3103
 
3081
3104
  specify "#delete should execute delete SQL" do
@@ -12,6 +12,7 @@ describe Sequel::Schema::Generator do
12
12
  index :title
13
13
  index [:title, :body], :unique => true
14
14
  foreign_key :node_id, :nodes
15
+ foreign_key :deferrable_node_id, :nodes, :deferrable => true
15
16
  primary_key [:title, :parent_id], :name => :cpk
16
17
  foreign_key [:node_id, :prop_id], :nodes_props, :name => :cfk
17
18
  end
@@ -26,7 +27,7 @@ describe Sequel::Schema::Generator do
26
27
  end
27
28
 
28
29
  it "counts definitions correctly" do
29
- @columns.size.should == 5
30
+ @columns.size.should == 6
30
31
  @indexes.size.should == 2
31
32
  @constraints.size.should == 4
32
33
  end
@@ -48,6 +49,12 @@ describe Sequel::Schema::Generator do
48
49
  @columns[4][:name].should == :node_id
49
50
  @columns[4][:type].should == Integer
50
51
  end
52
+
53
+ it "creates deferrable altered foreign key column" do
54
+ @columns[5][:name].should == :deferrable_node_id
55
+ @columns[5][:type].should == Integer
56
+ @columns[5][:deferrable].should == true
57
+ end
51
58
 
52
59
  it "uses table for foreign key columns, if specified" do
53
60
  @columns[3][:table].should == nil
@@ -23,6 +23,12 @@ context "DB#create_table" do
23
23
  proc{@db.create_table(:cats.as(:c)) {}}.should raise_error(Sequel::Error)
24
24
  end
25
25
 
26
+ specify "should remove cached schema entry" do
27
+ @db.instance_variable_set(:@schemas, {'cats'=>[]})
28
+ @db.create_table(:cats){Integer :a}
29
+ @db.instance_variable_get(:@schemas).should be_empty
30
+ end
31
+
26
32
  specify "should accept multiple columns" do
27
33
  @db.create_table(:cats) do
28
34
  column :id, :integer
@@ -268,6 +274,13 @@ context "DB#create_table" do
268
274
  @db.sqls.clear
269
275
  end
270
276
 
277
+ specify "should accept foreign keys with deferrable option" do
278
+ @db.create_table(:cats) do
279
+ foreign_key :project_id, :projects, :deferrable=>true
280
+ end
281
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects DEFERRABLE INITIALLY DEFERRED)"]
282
+ end
283
+
271
284
  specify "should accept inline index definition" do
272
285
  @db.create_table(:cats) do
273
286
  integer :id, :index => true