sequel 2.12.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/CHANGELOG +62 -0
  2. data/README.rdoc +3 -3
  3. data/Rakefile +7 -0
  4. data/doc/advanced_associations.rdoc +44 -0
  5. data/doc/release_notes/3.0.0.txt +221 -0
  6. data/lib/sequel/adapters/amalgalite.rb +208 -0
  7. data/lib/sequel/adapters/db2.rb +3 -0
  8. data/lib/sequel/adapters/dbi.rb +9 -0
  9. data/lib/sequel/adapters/do.rb +0 -4
  10. data/lib/sequel/adapters/firebird.rb +16 -18
  11. data/lib/sequel/adapters/informix.rb +5 -3
  12. data/lib/sequel/adapters/jdbc.rb +24 -20
  13. data/lib/sequel/adapters/jdbc/h2.rb +15 -4
  14. data/lib/sequel/adapters/mysql.rb +4 -8
  15. data/lib/sequel/adapters/odbc.rb +0 -4
  16. data/lib/sequel/adapters/oracle.rb +0 -4
  17. data/lib/sequel/adapters/shared/mssql.rb +16 -5
  18. data/lib/sequel/adapters/shared/mysql.rb +87 -86
  19. data/lib/sequel/adapters/shared/oracle.rb +92 -3
  20. data/lib/sequel/adapters/shared/postgres.rb +85 -29
  21. data/lib/sequel/adapters/shared/progress.rb +8 -3
  22. data/lib/sequel/adapters/shared/sqlite.rb +53 -23
  23. data/lib/sequel/adapters/sqlite.rb +4 -7
  24. data/lib/sequel/adapters/utils/unsupported.rb +3 -3
  25. data/lib/sequel/connection_pool.rb +18 -25
  26. data/lib/sequel/core.rb +2 -21
  27. data/lib/sequel/database.rb +60 -44
  28. data/lib/sequel/database/schema_generator.rb +26 -31
  29. data/lib/sequel/database/schema_methods.rb +8 -3
  30. data/lib/sequel/database/schema_sql.rb +114 -28
  31. data/lib/sequel/dataset.rb +14 -41
  32. data/lib/sequel/dataset/convenience.rb +31 -54
  33. data/lib/sequel/dataset/graph.rb +7 -13
  34. data/lib/sequel/dataset/sql.rb +43 -54
  35. data/lib/sequel/extensions/inflector.rb +0 -5
  36. data/lib/sequel/extensions/schema_dumper.rb +238 -0
  37. data/lib/sequel/metaprogramming.rb +0 -20
  38. data/lib/sequel/model.rb +1 -2
  39. data/lib/sequel/model/base.rb +18 -16
  40. data/lib/sequel/model/inflections.rb +6 -9
  41. data/lib/sequel/plugins/caching.rb +0 -6
  42. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  43. data/lib/sequel/sql.rb +2 -0
  44. data/lib/sequel/version.rb +2 -2
  45. data/spec/adapters/firebird_spec.rb +35 -8
  46. data/spec/adapters/mysql_spec.rb +173 -266
  47. data/spec/adapters/oracle_spec.rb +13 -0
  48. data/spec/adapters/postgres_spec.rb +127 -227
  49. data/spec/adapters/sqlite_spec.rb +13 -171
  50. data/spec/core/connection_pool_spec.rb +15 -4
  51. data/spec/core/core_sql_spec.rb +14 -170
  52. data/spec/core/database_spec.rb +50 -132
  53. data/spec/core/dataset_spec.rb +47 -930
  54. data/spec/core/expression_filters_spec.rb +12 -0
  55. data/spec/core/schema_generator_spec.rb +37 -45
  56. data/spec/core/schema_spec.rb +26 -16
  57. data/spec/core/spec_helper.rb +0 -25
  58. data/spec/extensions/inflector_spec.rb +0 -3
  59. data/spec/extensions/schema_dumper_spec.rb +292 -0
  60. data/spec/extensions/serialization_spec.rb +9 -0
  61. data/spec/extensions/single_table_inheritance_spec.rb +6 -1
  62. data/spec/extensions/spec_helper.rb +1 -3
  63. data/spec/extensions/validation_helpers_spec.rb +4 -4
  64. data/spec/integration/database_test.rb +18 -0
  65. data/spec/integration/dataset_test.rb +112 -1
  66. data/spec/integration/eager_loader_test.rb +70 -9
  67. data/spec/integration/prepared_statement_test.rb +2 -2
  68. data/spec/integration/schema_test.rb +76 -27
  69. data/spec/integration/spec_helper.rb +0 -14
  70. data/spec/integration/transaction_test.rb +27 -0
  71. data/spec/model/associations_spec.rb +0 -36
  72. data/spec/model/base_spec.rb +18 -123
  73. data/spec/model/hooks_spec.rb +2 -235
  74. data/spec/model/inflector_spec.rb +15 -115
  75. data/spec/model/model_spec.rb +0 -120
  76. data/spec/model/plugins_spec.rb +0 -70
  77. data/spec/model/record_spec.rb +35 -93
  78. data/spec/model/spec_helper.rb +0 -27
  79. data/spec/model/validations_spec.rb +0 -931
  80. metadata +9 -14
  81. data/lib/sequel/deprecated.rb +0 -593
  82. data/lib/sequel/deprecated_migration.rb +0 -91
  83. data/lib/sequel/model/deprecated.rb +0 -204
  84. data/lib/sequel/model/deprecated_hooks.rb +0 -103
  85. data/lib/sequel/model/deprecated_inflector.rb +0 -335
  86. data/lib/sequel/model/deprecated_validations.rb +0 -388
  87. data/spec/core/core_ext_spec.rb +0 -156
  88. data/spec/core/migration_spec.rb +0 -263
  89. data/spec/core/pretty_table_spec.rb +0 -58
  90. data/spec/model/caching_spec.rb +0 -217
  91. data/spec/model/schema_spec.rb +0 -92
@@ -202,6 +202,12 @@ context "Blockless Ruby Filters" do
202
202
  @d.l(:x => nil, :y => [1,2,3])[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
203
203
  end
204
204
 
205
+ it "should support sql_expr on hashes" do
206
+ @d.l({:x => 100, :y => 'a'}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x = 100)', '(y = \'a\')']
207
+ @d.l({:x => true, :y => false}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
208
+ @d.l({:x => nil, :y => [1,2,3]}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
209
+ end
210
+
205
211
  it "should support sql_negate on hashes" do
206
212
  @d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x != 100)', '(y != \'a\')']
207
213
  @d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
@@ -226,6 +232,12 @@ context "Blockless Ruby Filters" do
226
232
  @d.l([[:x, nil], [:y, [1,2,3]]]).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
227
233
  end
228
234
 
235
+ it "should support sql_expr on arrays with all two pairs" do
236
+ @d.l([[:x, 100],[:y, 'a']].sql_expr).should == '((x = 100) AND (y = \'a\'))'
237
+ @d.l([[:x, true], [:y, false]].sql_expr).should == '((x IS TRUE) AND (y IS FALSE))'
238
+ @d.l([[:x, nil], [:y, [1,2,3]]].sql_expr).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
239
+ end
240
+
229
241
  it "should support sql_negate on arrays with all two pairs" do
230
242
  @d.l([[:x, 100],[:y, 'a']].sql_negate).should == '((x != 100) AND (y != \'a\'))'
231
243
  @d.l([[:x, true], [:y, false]].sql_negate).should == '((x IS NOT TRUE) AND (y IS NOT FALSE))'
@@ -10,30 +10,27 @@ describe Sequel::Schema::Generator do
10
10
  check 'price > 100'
11
11
  constraint(:xxx) {:yyy == :zzz}
12
12
  index :title
13
- index [:title, :body]
13
+ index [:title, :body], :unique => true
14
14
  foreign_key :node_id, :nodes
15
15
  primary_key [:title, :parent_id], :name => :cpk
16
16
  foreign_key [:node_id, :prop_id], :nodes_props, :name => :cfk
17
17
  end
18
- @columns, @indexes = @generator.create_info
18
+ @columns, @indexes, @constraints = @generator.columns, @generator.indexes, @generator.constraints
19
19
  end
20
20
 
21
- {:name => :id, :primary_key => true}.each do |column, expected|
22
- it "uses default primary key #{column}" do
23
- @columns.first[column].should == expected
24
- end
21
+ it "should primary key column first" do
22
+ @columns.first[:name].should == :id
23
+ @columns.first[:primary_key].should == true
24
+ @columns[3][:name].should == :parent_id
25
+ @columns[3][:primary_key].should == nil
25
26
  end
26
27
 
27
- it "counts primary key, column and constraint definitions as columns" do
28
- @columns.size.should == 9
28
+ it "counts definitions correctly" do
29
+ @columns.size.should == 5
30
+ @indexes.size.should == 2
31
+ @constraints.size.should == 4
29
32
  end
30
33
 
31
- it "places primary key first" do
32
- @columns[0][:primary_key].should be_true
33
- @columns[1][:primary_key].should_not be_true
34
- @columns[2][:primary_key].should_not be_true
35
- end
36
-
37
34
  it "retrieves primary key name" do
38
35
  @generator.primary_key_name.should == :id
39
36
  end
@@ -48,14 +45,14 @@ describe Sequel::Schema::Generator do
48
45
  it "creates foreign key column" do
49
46
  @columns[3][:name].should == :parent_id
50
47
  @columns[3][:type].should == Integer
51
- @columns[6][:name].should == :node_id
52
- @columns[6][:type].should == Integer
48
+ @columns[4][:name].should == :node_id
49
+ @columns[4][:type].should == Integer
53
50
  end
54
51
 
55
52
  it "uses table for foreign key columns, if specified" do
56
- @columns[6][:table].should == :nodes
57
53
  @columns[3][:table].should == nil
58
- @columns[8][:table].should == :nodes_props
54
+ @columns[4][:table].should == :nodes
55
+ @constraints[3][:table].should == :nodes_props
59
56
  end
60
57
 
61
58
  it "finds columns" do
@@ -66,24 +63,22 @@ describe Sequel::Schema::Generator do
66
63
  end
67
64
 
68
65
  it "creates constraints" do
69
- @columns[4][:name].should == nil
70
- @columns[4][:type].should == :check
71
- @columns[4][:check].should == ['price > 100']
66
+ @constraints[0][:name].should == nil
67
+ @constraints[0][:type].should == :check
68
+ @constraints[0][:check].should == ['price > 100']
72
69
 
73
- @columns[5][:name].should == :xxx
74
- @columns[5][:type].should == :check
75
- @columns[5][:check].should be_a_kind_of(Proc)
70
+ @constraints[1][:name].should == :xxx
71
+ @constraints[1][:type].should == :check
72
+ @constraints[1][:check].should be_a_kind_of(Proc)
76
73
 
77
- @columns[7][:name].should == :cpk
78
- @columns[7][:type].should == :check
79
- @columns[7][:constraint_type].should == :primary_key
80
- @columns[7][:columns].should == [ :title, :parent_id ]
74
+ @constraints[2][:name].should == :cpk
75
+ @constraints[2][:type].should == :primary_key
76
+ @constraints[2][:columns].should == [ :title, :parent_id ]
81
77
 
82
- @columns[8][:name].should == :cfk
83
- @columns[8][:type].should == :check
84
- @columns[8][:constraint_type].should == :foreign_key
85
- @columns[8][:columns].should == [ :node_id, :prop_id ]
86
- @columns[8][:table].should == :nodes_props
78
+ @constraints[3][:name].should == :cfk
79
+ @constraints[3][:type].should == :foreign_key
80
+ @constraints[3][:columns].should == [ :node_id, :prop_id ]
81
+ @constraints[3][:table].should == :nodes_props
87
82
  end
88
83
 
89
84
  it "creates indexes" do
@@ -103,6 +98,7 @@ describe Sequel::Schema::AlterTableGenerator do
103
98
  set_column_default :eee, 1
104
99
  add_index [:fff, :ggg]
105
100
  drop_index :hhh
101
+ drop_index :hhh, :name=>:blah_blah
106
102
  add_full_text_index :blah
107
103
  add_spatial_index :geom
108
104
  add_index :blah, :type => :hash
@@ -126,24 +122,25 @@ describe Sequel::Schema::AlterTableGenerator do
126
122
  {:op => :set_column_default, :name => :eee, :default => 1},
127
123
  {:op => :add_index, :columns => [:fff, :ggg]},
128
124
  {:op => :drop_index, :columns => [:hhh]},
125
+ {:op => :drop_index, :columns => [:hhh], :name=>:blah_blah},
129
126
  {:op => :add_index, :columns => [:blah], :type => :full_text},
130
127
  {:op => :add_index, :columns => [:geom], :type => :spatial},
131
128
  {:op => :add_index, :columns => [:blah], :type => :hash},
132
129
  {:op => :add_index, :columns => [:blah], :where => {:something => true}},
133
- {:op => :add_constraint, :type => :check, :constraint_type => :check, :name => :con1, :check => ['fred > 100']},
130
+ {:op => :add_constraint, :type => :check, :name => :con1, :check => ['fred > 100']},
134
131
  {:op => :drop_constraint, :name => :con2},
135
- {:op => :add_constraint, :type => :check, :constraint_type => :unique, :name => :con3, :columns => [:aaa, :bbb, :ccc]},
132
+ {:op => :add_constraint, :type => :unique, :name => :con3, :columns => [:aaa, :bbb, :ccc]},
136
133
  {:op => :add_column, :name => :id, :type => Integer, :primary_key=>true, :auto_increment=>true},
137
134
  {:op => :add_column, :name => :node_id, :type => Integer, :table=>:nodes},
138
- {:op => :add_constraint, :type => :check, :constraint_type => :primary_key, :columns => [:aaa, :bbb]},
139
- {:op => :add_constraint, :type => :check, :constraint_type => :foreign_key, :columns => [:node_id, :prop_id], :table => :nodes_props}
135
+ {:op => :add_constraint, :type => :primary_key, :columns => [:aaa, :bbb]},
136
+ {:op => :add_constraint, :type => :foreign_key, :columns => [:node_id, :prop_id], :table => :nodes_props}
140
137
  ]
141
138
  end
142
139
  end
143
140
 
144
141
  describe "Sequel::Schema::Generator generic type methods" do
145
- before do
146
- @generator = Sequel::Schema::Generator.new(SchemaDummyDatabase.new) do
142
+ it "should store the type class in :type for each column" do
143
+ Sequel::Schema::Generator.new(SchemaDummyDatabase.new) do
147
144
  String :a
148
145
  Integer :b
149
146
  Fixnum :c
@@ -157,11 +154,6 @@ describe "Sequel::Schema::Generator generic type methods" do
157
154
  File :k
158
155
  TrueClass :l
159
156
  FalseClass :m
160
- end
161
- @columns, @indexes = @generator.create_info
162
- end
163
-
164
- it "should store the type class in :type for each column" do
165
- @columns.map{|c| c[:type]}.should == [String, Integer, Fixnum, Bignum, Float, BigDecimal, Date, DateTime, Time, Numeric, File, TrueClass, FalseClass]
157
+ end.columns.map{|c| c[:type]}.should == [String, Integer, Fixnum, Bignum, Float, BigDecimal, Date, DateTime, Time, Numeric, File, TrueClass, FalseClass]
166
158
  end
167
159
  end
@@ -61,6 +61,21 @@ context "DB#create_table" do
61
61
  @db.sqls.should == ['CREATE TABLE cats (o varchar(255) PRIMARY KEY AUTOINCREMENT, a varchar(255), b integer, c integer, d bigint, e double precision, f numeric, g date, h timestamp, i timestamp, j numeric, k blob, l boolean, m boolean, n integer, p date REFERENCES f)']
62
62
  end
63
63
 
64
+ specify "should allow the use of modifiers with ruby class types" do
65
+ @db.create_table(:cats) do
66
+ String :a, :size=>50
67
+ String :b, :text=>true
68
+ String :c, :fixed=>true, :size=>40
69
+ Time :d, :only_time=>true
70
+ BigDecimal :e, :size=>[11,2]
71
+ end
72
+ @db.sqls.should == ['CREATE TABLE cats (a varchar(50), b text, c char(40), d time, e numeric(11, 2))']
73
+ end
74
+
75
+ specify "should raise an error if you use a ruby class that isn't handled" do
76
+ proc{@db.create_table(:cats){column :a, Class}}.should raise_error(Sequel::Error)
77
+ end
78
+
64
79
  specify "should accept primary key definition" do
65
80
  @db.create_table(:cats) do
66
81
  primary_key :id
@@ -404,6 +419,10 @@ context "DB#create_table" do
404
419
  @db.sqls.should == ["CREATE TABLE cats (CONSTRAINT blah_blah CHECK ((x > 0) AND (y < 1)))"]
405
420
  end
406
421
 
422
+ specify "should raise an error if an invalid constraint type is used" do
423
+ proc{@db.create_table(:cats){unique [:a, :b], :type=>:bb}}.should raise_error(Sequel::Error)
424
+ end
425
+
407
426
  specify "should accept composite primary keys" do
408
427
  @db.create_table(:cats) do
409
428
  integer :a
@@ -646,6 +665,13 @@ context "DB#alter_table" do
646
665
  @db.sqls.should == ["DROP INDEX cats_name_index"]
647
666
  end
648
667
 
668
+ specify "should support drop_index with a given name" do
669
+ @db.alter_table(:cats) do
670
+ drop_index :name, :name=>:blah_blah
671
+ end
672
+ @db.sqls.should == ["DROP INDEX blah_blah"]
673
+ end
674
+
649
675
  specify "should support rename_column" do
650
676
  @db.alter_table(:cats) do
651
677
  rename_column :name, :old_name
@@ -710,22 +736,6 @@ context "Schema Parser" do
710
736
  @sqls.should == ['x', 'x']
711
737
  end
712
738
 
713
- deprec_specify "should parse the schema correctly for all tables" do
714
- sqls = @sqls
715
- proc{@db.schema}.should raise_error(Sequel::Error)
716
- @db.meta_def(:tables){[:x]}
717
- @db.meta_def(:schema_parse_table) do |t, opts|
718
- sqls << t
719
- [[:x, {:db_type=>t.to_s}]]
720
- end
721
- @db.schema.should == {'x'=>[[:x, {:db_type=>"x"}]]}
722
- @sqls.should == ['x']
723
- @db.schema.should == {'x'=>[[:x, {:db_type=>"x"}]]}
724
- @sqls.should == ['x']
725
- @db.schema(nil, :reload=>true).should == {'x'=>[[:x, {:db_type=>"x"}]]}
726
- @sqls.should == ['x', 'x']
727
- end
728
-
729
739
  specify "should convert various types of table name arguments" do
730
740
  @db.meta_def(:schema_parse_table) do |t, opts|
731
741
  [[t, {:db_type=>t}]]
@@ -6,31 +6,6 @@ end
6
6
 
7
7
  Sequel.virtual_row_instance_eval = true
8
8
 
9
- module Spec::Example::ExampleMethods
10
- def deprec
11
- output = Sequel::Deprecation.output = nil
12
- begin
13
- yield
14
- ensure
15
- Sequel::Deprecation.output = output
16
- end
17
- end
18
- end
19
-
20
- module Spec::Example::ExampleGroupMethods
21
- def deprec_specify(*args, &block)
22
- specify(*args) do
23
- output = Sequel::Deprecation.output
24
- Sequel::Deprecation.output = nil
25
- begin
26
- instance_eval(&block)
27
- ensure
28
- Sequel::Deprecation.output = output
29
- end
30
- end
31
- end
32
- end
33
-
34
9
  class MockDataset < Sequel::Dataset
35
10
  def insert(*args)
36
11
  @db.execute insert_sql(*args)
@@ -86,9 +86,6 @@ describe String::Inflections do
86
86
  String.inflections.plurals.replace(@plurals)
87
87
  String.inflections.singulars.replace(@singulars)
88
88
  String.inflections.uncountables.replace(@uncountables)
89
- Sequel.inflections.plurals.replace(@plurals)
90
- Sequel.inflections.singulars.replace(@singulars)
91
- Sequel.inflections.uncountables.replace(@uncountables)
92
89
  end
93
90
 
94
91
  it "should be possible to clear the list of singulars, plurals, and uncountables" do
@@ -0,0 +1,292 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "Sequel::Schema::Generator dump methods" do
4
+ before do
5
+ @d = Sequel::Database.new
6
+ @g = Sequel::Schema::Generator
7
+ end
8
+
9
+ it "should allow the same table information to be converted to a string for evaling inside of another instance with the same result" do
10
+ g = @g.new(@d) do
11
+ Integer :a
12
+ varchar :b
13
+ column :dt, DateTime
14
+ column :vc, :varchar
15
+ primary_key :c
16
+ foreign_key :d, :a
17
+ foreign_key :e
18
+ foreign_key [:d, :e], :name=>:cfk
19
+ constraint :blah, "a=1"
20
+ check :a=>1
21
+ unique [:e]
22
+ index :a
23
+ index [:c, :e]
24
+ index [:b, :c], :type=>:hash
25
+ index [:d], :unique=>true
26
+ spatial_index :a
27
+ full_text_index [:b, :c]
28
+ end
29
+ g2 = @g.new(@d) do
30
+ instance_eval(g.dump_columns, __FILE__, __LINE__)
31
+ instance_eval(g.dump_constraints, __FILE__, __LINE__)
32
+ instance_eval(g.dump_indexes, __FILE__, __LINE__)
33
+ end
34
+ g.columns.should == g2.columns
35
+ g.constraints.should == g2.constraints
36
+ g.indexes.should == g2.indexes
37
+ end
38
+
39
+ it "should allow dumping indexes as separate add_index and drop_index methods" do
40
+ g = @g.new(@d) do
41
+ index :a
42
+ index [:c, :e], :name=>:blah
43
+ index [:b, :c], :unique=>true
44
+ end
45
+
46
+ t = <<END_CODE
47
+ add_index :t, [:a]
48
+ add_index :t, [:c, :e], :name=>:blah
49
+ add_index :t, [:b, :c], :unique=>true
50
+ END_CODE
51
+ g.dump_indexes(:add_index=>:t).should == t.strip
52
+
53
+ t = <<END_CODE
54
+ drop_index :t, [:a]
55
+ drop_index :t, [:c, :e], :name=>:blah
56
+ drop_index :t, [:b, :c], :unique=>true
57
+ END_CODE
58
+ g.dump_indexes(:drop_index=>:t).should == t.strip
59
+ end
60
+
61
+ it "should raise an error if you try to dump a Generator that uses a constraint with a proc" do
62
+ proc{@g.new(@d){check{a>1}}.dump_constraints}.should raise_error(Sequel::Error)
63
+ end
64
+ end
65
+
66
+ describe "Sequel::Database dump methods" do
67
+ before do
68
+ @d = Sequel::Database.new
69
+ @d.meta_def(:tables){[:t1, :t2]}
70
+ @d.meta_def(:schema) do |t, *o|
71
+ case t
72
+ when :t1
73
+ [[:c1, {:db_type=>'integer', :primary_key=>true, :allow_null=>false}],
74
+ [:c2, {:db_type=>'varchar(20)', :allow_null=>true}]]
75
+ when :t2
76
+ [[:c1, {:db_type=>'integer', :primary_key=>true, :allow_null=>false}],
77
+ [:c2, {:db_type=>'numeric', :primary_key=>true, :allow_null=>false}]]
78
+ when :t3
79
+ [[:c1, {:db_type=>'date', :default=>"'now()'", :allow_null=>true}],
80
+ [:c2, {:db_type=>'datetime', :allow_null=>false}]]
81
+ when :t4
82
+ [[:c1, {:db_type=>'boolean', :default=>"false", :allow_null=>true}],
83
+ [:c2, {:db_type=>'boolean', :default=>"true", :allow_null=>true}],
84
+ [:c3, {:db_type=>'varchar', :default=>"'blah'", :allow_null=>true}],
85
+ [:c4, {:db_type=>'integer', :default=>"35", :allow_null=>true}]]
86
+ when :t5
87
+ [[:c1, {:db_type=>'blahblah', :allow_null=>true}]]
88
+ end
89
+ end
90
+ end
91
+
92
+ it "should support dumping table schemas as create_table method calls" do
93
+ @d.dump_table_schema(:t1).should == "create_table(:t1) do\n primary_key :c1\n String :c2, :size=>20\nend"
94
+ end
95
+
96
+ it "should use a composite primary_key calls if there is a composite primary key" do
97
+ @d.dump_table_schema(:t2).should == "create_table(:t2) do\n Integer :c1, :null=>false\n BigDecimal :c2, :null=>false\n \n primary_key [:c1, :c2]\nend"
98
+ end
99
+
100
+ it "should include index information if available" do
101
+ @d.meta_def(:indexes) do |t|
102
+ {:i1=>{:columns=>[:c1], :unique=>false},
103
+ :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>true}}
104
+ end
105
+ @d.dump_table_schema(:t1).should == "create_table(:t1) do\n primary_key :c1\n String :c2, :size=>20\n \n index [:c1], :name=>:i1\n index [:c2, :c1], :unique=>true\nend"
106
+ end
107
+
108
+ it "should support dumping the whole database as a migration" do
109
+ @d.dump_schema_migration.should == <<-END_MIG
110
+ Class.new(Sequel::Migration) do
111
+ def up
112
+ create_table(:t1) do
113
+ primary_key :c1
114
+ String :c2, :size=>20
115
+ end
116
+
117
+ create_table(:t2) do
118
+ Integer :c1, :null=>false
119
+ BigDecimal :c2, :null=>false
120
+
121
+ primary_key [:c1, :c2]
122
+ end
123
+ end
124
+
125
+ def down
126
+ drop_table(:t1, :t2)
127
+ end
128
+ end
129
+ END_MIG
130
+ end
131
+
132
+ it "should honor the :same_db option to not convert types" do
133
+ @d.dump_table_schema(:t1, :same_db=>true).should == "create_table(:t1) do\n primary_key :c1\n column :c2, \"varchar(20)\"\nend"
134
+ @d.dump_schema_migration(:same_db=>true).should == <<-END_MIG
135
+ Class.new(Sequel::Migration) do
136
+ def up
137
+ create_table(:t1) do
138
+ primary_key :c1
139
+ column :c2, "varchar(20)"
140
+ end
141
+
142
+ create_table(:t2) do
143
+ column :c1, "integer", :null=>false
144
+ column :c2, "numeric", :null=>false
145
+
146
+ primary_key [:c1, :c2]
147
+ end
148
+ end
149
+
150
+ def down
151
+ drop_table(:t1, :t2)
152
+ end
153
+ end
154
+ END_MIG
155
+ end
156
+
157
+ it "should honor the :indexes => false option to not include indexes" do
158
+ @d.meta_def(:indexes) do |t|
159
+ {:i1=>{:columns=>[:c1], :unique=>false},
160
+ :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>true}}
161
+ end
162
+ @d.dump_table_schema(:t1, :indexes=>false).should == "create_table(:t1) do\n primary_key :c1\n String :c2, :size=>20\nend"
163
+ @d.dump_schema_migration(:indexes=>false).should == <<-END_MIG
164
+ Class.new(Sequel::Migration) do
165
+ def up
166
+ create_table(:t1) do
167
+ primary_key :c1
168
+ String :c2, :size=>20
169
+ end
170
+
171
+ create_table(:t2) do
172
+ Integer :c1, :null=>false
173
+ BigDecimal :c2, :null=>false
174
+
175
+ primary_key [:c1, :c2]
176
+ end
177
+ end
178
+
179
+ def down
180
+ drop_table(:t1, :t2)
181
+ end
182
+ end
183
+ END_MIG
184
+ end
185
+
186
+ it "should support dumping just indexes as a migration" do
187
+ @d.meta_def(:tables){[:t1]}
188
+ @d.meta_def(:indexes) do |t|
189
+ {:i1=>{:columns=>[:c1], :unique=>false},
190
+ :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>true}}
191
+ end
192
+ @d.dump_indexes_migration.should == <<-END_MIG
193
+ Class.new(Sequel::Migration) do
194
+ def up
195
+ add_index :t1, [:c1], :name=>:i1
196
+ add_index :t1, [:c2, :c1], :unique=>true
197
+ end
198
+
199
+ def down
200
+ drop_index :t1, [:c1], :name=>:i1
201
+ drop_index :t1, [:c2, :c1], :unique=>true
202
+ end
203
+ end
204
+ END_MIG
205
+ end
206
+
207
+ it "should handle not null values and defaults" do
208
+ @d.dump_table_schema(:t3).should == "create_table(:t3) do\n Date :c1, :default=>\"'now()'\".lit\n DateTime :c2, :null=>false\nend"
209
+ end
210
+
211
+ it "should handle converting common defaults" do
212
+ @d.dump_table_schema(:t4).should == "create_table(:t4) do\n TrueClass :c1, :default=>false\n TrueClass :c2, :default=>true\n String :c3, :default=>\"'blah'\".lit\n Integer :c4, :default=>35\nend"
213
+ end
214
+
215
+ it "should convert unknown database types to strings" do
216
+ @d.dump_table_schema(:t5).should == "create_table(:t5) do\n String :c1\nend"
217
+ end
218
+
219
+ it "should convert many database types to ruby types" do
220
+ types = %w"mediumint smallint int integer mediumint(6) smallint(7) int(8) integer(9)
221
+ tinyint tinyint(1) bigint bigint(20) real float double boolean tinytext mediumtext
222
+ longtext text clob date datetime timestamp time char character
223
+ varchar varchar(255) varchar(30) bpchar string money
224
+ decimal decimal(10,2) numeric numeric(15,3) number bytea tinyblob mediumblob longblob
225
+ blob varbinary varbinary(10) binary binary(20) year" +
226
+ ["double precision", "timestamp with time zone", "timestamp without time zone",
227
+ "time with time zone", "time without time zone", "character varying(20)"]
228
+ @d.meta_def(:schema) do |t, *o|
229
+ i = 0
230
+ types.map{|x| [:"c#{i+=1}", {:db_type=>x, :allow_null=>true}]}
231
+ end
232
+ table = <<END_MIG
233
+ create_table(:x) do
234
+ Integer :c1
235
+ Integer :c2
236
+ Integer :c3
237
+ Integer :c4
238
+ Integer :c5
239
+ Integer :c6
240
+ Integer :c7
241
+ Integer :c8
242
+ TrueClass :c9
243
+ TrueClass :c10
244
+ Bignum :c11
245
+ Bignum :c12
246
+ Float :c13
247
+ Float :c14
248
+ Float :c15
249
+ TrueClass :c16
250
+ String :c17, :text=>true
251
+ String :c18, :text=>true
252
+ String :c19, :text=>true
253
+ String :c20, :text=>true
254
+ String :c21, :text=>true
255
+ Date :c22
256
+ DateTime :c23
257
+ DateTime :c24
258
+ Time :c25, :only_time=>true
259
+ String :c26, :fixed=>true
260
+ String :c27, :fixed=>true
261
+ String :c28
262
+ String :c29
263
+ String :c30, :size=>30
264
+ String :c31
265
+ String :c32
266
+ BigDecimal :c33, :size=>[19, 2]
267
+ BigDecimal :c34
268
+ BigDecimal :c35, :size=>[10, 2]
269
+ BigDecimal :c36
270
+ BigDecimal :c37, :size=>[15, 3]
271
+ BigDecimal :c38
272
+ File :c39
273
+ File :c40
274
+ File :c41
275
+ File :c42
276
+ File :c43
277
+ File :c44
278
+ File :c45, :size=>10
279
+ File :c46
280
+ File :c47, :size=>20
281
+ Integer :c48
282
+ Float :c49
283
+ DateTime :c50
284
+ DateTime :c51
285
+ Time :c52, :only_time=>true
286
+ Time :c53, :only_time=>true
287
+ String :c54, :size=>20
288
+ end
289
+ END_MIG
290
+ @d.dump_table_schema(:x).should == table.chomp
291
+ end
292
+ end