sequel 2.12.0 → 3.0.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 (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
@@ -1,5 +1,7 @@
1
1
  require File.join(File.dirname(__FILE__), "spec_helper")
2
2
 
3
+ require 'yaml'
4
+
3
5
  describe "Serialization plugin" do
4
6
  before do
5
7
  @c = Class.new(Sequel::Model(:items)) do
@@ -49,6 +51,8 @@ describe "Serialization plugin" do
49
51
  o = @c.first
50
52
  o.id.should == 1
51
53
  o.abc.should == 1
54
+ o.abc.should == 1
55
+ o.def.should == "hello"
52
56
  o.def.should == "hello"
53
57
 
54
58
  o.update(:abc => 23)
@@ -69,6 +73,8 @@ describe "Serialization plugin" do
69
73
  o = @c.first
70
74
  o.id.should == 1
71
75
  o.abc.should == 1
76
+ o.abc.should == 1
77
+ o.def.should == "hello"
72
78
  o.def.should == "hello"
73
79
 
74
80
  o.update(:abc => 23)
@@ -89,6 +95,8 @@ describe "Serialization plugin" do
89
95
  o = Class.new(@c).first
90
96
  o.id.should == 1
91
97
  o.abc.should == 1
98
+ o.abc.should == 1
99
+ o.def.should == "hello"
92
100
  o.def.should == "hello"
93
101
 
94
102
  o.update(:abc => 23)
@@ -103,6 +111,7 @@ describe "Serialization plugin" do
103
111
  o = @c.load(:id => 1, :abc => "--- 1\n", :def => "--- hello\n")
104
112
  o.abc = 23
105
113
  o.deserialized_values.length.should == 1
114
+ o.abc.should == 23
106
115
  o.refresh
107
116
  o.deserialized_values.length.should == 0
108
117
  end
@@ -4,7 +4,7 @@ describe Sequel::Model, "#sti_key" do
4
4
  before do
5
5
  class ::StiTest < Sequel::Model
6
6
  def kind=(x); self[:kind] = x; end
7
- def refresh; end
7
+ def _refresh(x); end
8
8
  plugin :single_table_inheritance, :kind
9
9
  end
10
10
  class ::StiTestSub1 < StiTest
@@ -14,6 +14,11 @@ describe Sequel::Model, "#sti_key" do
14
14
  @ds = StiTest.dataset
15
15
  MODEL_DB.reset
16
16
  end
17
+
18
+ specify "should have simple_table = nil" do
19
+ StiTest.simple_table.should == nil
20
+ StiTestSub1.simple_table.should == nil
21
+ end
17
22
 
18
23
  it "should return rows with the correct class based on the polymorphic_key value" do
19
24
  def @ds.fetch_rows(sql)
@@ -10,7 +10,7 @@ end
10
10
 
11
11
  Sequel.virtual_row_instance_eval = true
12
12
 
13
- extensions = %w'string_date_time inflector pagination query pretty_table blank migration'
13
+ extensions = %w'string_date_time inflector pagination query pretty_table blank migration schema_dumper'
14
14
  plugins = {:hook_class_methods=>[], :schema=>[], :validation_class_methods=>[]}
15
15
 
16
16
  extensions.each{|e| require "sequel/extensions/#{e}"}
@@ -70,12 +70,10 @@ end
70
70
 
71
71
  class << Sequel::Model
72
72
  alias orig_columns columns
73
- alias orig_str_columns str_columns
74
73
  def columns(*cols)
75
74
  return if cols.empty?
76
75
  define_method(:columns){cols}
77
76
  @dataset.instance_variable_set(:@columns, cols) if @dataset
78
- define_method(:str_columns){cols.map{|x|x.to_s.freeze}}
79
77
  def_column_accessor(*cols)
80
78
  @columns = cols
81
79
  @db_schema = {}
@@ -241,10 +241,10 @@ describe "Sequel::Plugins::ValidationHelpers" do
241
241
 
242
242
  @user = @c.load(:id=>1, :username => "0records", :password => "anothertest")
243
243
  @user.should be_valid
244
- MODEL_DB.sqls.last.should == "SELECT COUNT(*) FROM items WHERE ((username = '0records') AND (id != 1)) LIMIT 1"
244
+ MODEL_DB.sqls.last.should == "SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND (id != 1)) LIMIT 1"
245
245
  @user = @c.new(:username => "0records", :password => "anothertest")
246
246
  @user.should be_valid
247
- MODEL_DB.sqls.last.should == "SELECT COUNT(*) FROM items WHERE (username = '0records') LIMIT 1"
247
+ MODEL_DB.sqls.last.should == "SELECT COUNT(*) AS count FROM items WHERE (username = '0records') LIMIT 1"
248
248
  end
249
249
 
250
250
  it "should support validates_unique with multiple attributes" do
@@ -283,9 +283,9 @@ describe "Sequel::Plugins::ValidationHelpers" do
283
283
 
284
284
  @user = @c.load(:id=>1, :username => "0records", :password => "anothertest")
285
285
  @user.should be_valid
286
- MODEL_DB.sqls.last.should == "SELECT COUNT(*) FROM items WHERE (((username = '0records') AND (password = 'anothertest')) AND (id != 1)) LIMIT 1"
286
+ MODEL_DB.sqls.last.should == "SELECT COUNT(*) AS count FROM items WHERE (((username = '0records') AND (password = 'anothertest')) AND (id != 1)) LIMIT 1"
287
287
  @user = @c.new(:username => "0records", :password => "anothertest")
288
288
  @user.should be_valid
289
- MODEL_DB.sqls.last.should == "SELECT COUNT(*) FROM items WHERE ((username = '0records') AND (password = 'anothertest')) LIMIT 1"
289
+ MODEL_DB.sqls.last.should == "SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND (password = 'anothertest')) LIMIT 1"
290
290
  end
291
291
  end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
2
+
3
+ describe Sequel::Database do
4
+ specify "should provide disconnect functionality" do
5
+ INTEGRATION_DB.test_connection
6
+ INTEGRATION_DB.pool.size.should == 1
7
+ INTEGRATION_DB.disconnect
8
+ INTEGRATION_DB.pool.size.should == 0
9
+ end
10
+
11
+ specify "should raise Sequel::DatabaseError on invalid SQL" do
12
+ proc{INTEGRATION_DB << "SELECT"}.should raise_error(Sequel::DatabaseError)
13
+ end
14
+
15
+ specify "should not have the connection pool swallow non-StandardError based exceptions" do
16
+ proc{INTEGRATION_DB.pool.hold{raise Interrupt, "test"}}.should raise_error(Interrupt)
17
+ end
18
+ end
@@ -4,7 +4,7 @@ describe "Simple Dataset operations" do
4
4
  before do
5
5
  INTEGRATION_DB.create_table!(:items) do
6
6
  primary_key :id
7
- integer :number
7
+ Integer :number
8
8
  end
9
9
  @ds = INTEGRATION_DB[:items]
10
10
  @ds.insert(:number=>10)
@@ -14,6 +14,15 @@ describe "Simple Dataset operations" do
14
14
  INTEGRATION_DB.drop_table(:items)
15
15
  end
16
16
 
17
+ specify "should support sequential primary keys" do
18
+ @ds << {:number=>20}
19
+ @ds << {:number=>30}
20
+ @ds.order(:number).all.should == [
21
+ {:id => 1, :number=>10},
22
+ {:id => 2, :number=>20},
23
+ {:id => 3, :number=>30} ]
24
+ end
25
+
17
26
  specify "should insert with a primary key specified" do
18
27
  @ds.insert(:id=>100, :number=>20)
19
28
  sqls_should_be(/INSERT INTO items \((number, id|id, number)\) VALUES \((100, 20|20, 100)\)/)
@@ -55,6 +64,108 @@ describe "Simple Dataset operations" do
55
64
  end
56
65
  end
57
66
 
67
+ describe Sequel::Dataset do
68
+ before do
69
+ INTEGRATION_DB.create_table!(:test) do
70
+ String :name
71
+ Integer :value
72
+ end
73
+ @d = INTEGRATION_DB[:test]
74
+ clear_sqls
75
+ end
76
+ after do
77
+ INTEGRATION_DB.drop_table(:test)
78
+ end
79
+
80
+ specify "should return the correct record count" do
81
+ @d.count.should == 0
82
+ @d << {:name => 'abc', :value => 123}
83
+ @d << {:name => 'abc', :value => 456}
84
+ @d << {:name => 'def', :value => 789}
85
+ @d.count.should == 3
86
+ end
87
+
88
+ specify "should return the correct records" do
89
+ @d.to_a.should == []
90
+ @d << {:name => 'abc', :value => 123}
91
+ @d << {:name => 'abc', :value => 456}
92
+ @d << {:name => 'def', :value => 789}
93
+
94
+ @d.order(:value).to_a.should == [
95
+ {:name => 'abc', :value => 123},
96
+ {:name => 'abc', :value => 456},
97
+ {:name => 'def', :value => 789}
98
+ ]
99
+ end
100
+
101
+ specify "should update records correctly" do
102
+ @d << {:name => 'abc', :value => 123}
103
+ @d << {:name => 'abc', :value => 456}
104
+ @d << {:name => 'def', :value => 789}
105
+ @d.filter(:name => 'abc').update(:value => 530)
106
+ @d[:name => 'def'][:value].should == 789
107
+ @d.filter(:value => 530).count.should == 2
108
+ end
109
+
110
+ specify "should delete records correctly" do
111
+ @d << {:name => 'abc', :value => 123}
112
+ @d << {:name => 'abc', :value => 456}
113
+ @d << {:name => 'def', :value => 789}
114
+ @d.filter(:name => 'abc').delete
115
+ @d.count.should == 1
116
+ @d.first[:name].should == 'def'
117
+ end
118
+
119
+ specify "should be able to literalize booleans" do
120
+ proc {@d.literal(true)}.should_not raise_error
121
+ proc {@d.literal(false)}.should_not raise_error
122
+ end
123
+
124
+ specify "should correctly escape strings" do
125
+ INTEGRATION_DB.get("\\dingo".as(:a)) == "\\dingo"
126
+ end
127
+
128
+ specify "should correctly escape strings with quotes" do
129
+ INTEGRATION_DB.get("\\'dingo".as(:a)) == "\\'dingo"
130
+ end
131
+
132
+ specify "should properly escape binary data" do
133
+ INTEGRATION_DB.get("\1\2\3".to_sequel_blob.as(:a)) == "\1\2\3"
134
+ end
135
+ end
136
+
137
+ context "An SQLite dataset" do
138
+ before do
139
+ INTEGRATION_DB.create_table! :items do
140
+ primary_key :id
141
+ Integer :value
142
+ end
143
+ @d = INTEGRATION_DB[:items]
144
+ @d << {:value => 123}
145
+ @d << {:value => 456}
146
+ @d << {:value => 789}
147
+ end
148
+ after do
149
+ INTEGRATION_DB.drop_table(:items)
150
+ end
151
+
152
+ specify "should correctly return avg" do
153
+ @d.avg(:value).to_i.should == 456
154
+ end
155
+
156
+ specify "should correctly return sum" do
157
+ @d.sum(:value).to_i.should == 1368
158
+ end
159
+
160
+ specify "should correctly return max" do
161
+ @d.max(:value).to_i.should == 789
162
+ end
163
+
164
+ specify "should correctly return min" do
165
+ @d.min(:value).to_i.should == 123
166
+ end
167
+ end
168
+
58
169
  describe "Simple Dataset operations" do
59
170
  before do
60
171
  INTEGRATION_DB.create_table!(:items) do
@@ -154,7 +154,7 @@ describe "Association Extensions" do
154
154
  INTEGRATION_DB.create_table!(:authorships) do
155
155
  primary_key :id
156
156
  foreign_key :author_id, :authors
157
- text :name
157
+ String :name
158
158
  end
159
159
  class ::Authorship < Sequel::Model
160
160
  many_to_one :author
@@ -170,26 +170,26 @@ describe "Association Extensions" do
170
170
 
171
171
  it "should allow methods to be called on the dataset method" do
172
172
  Authorship.count.should == 0
173
- sqls_should_be('SELECT COUNT(*) FROM authorships LIMIT 1')
173
+ sqls_should_be('SELECT COUNT(*) AS \'count\' FROM authorships LIMIT 1')
174
174
  authorship = @author.authorships_dataset.find_or_create_by_name('Bob')
175
175
  sqls_should_be("SELECT * FROM authorships WHERE ((authorships.author_id = 1) AND (name = 'Bob')) LIMIT 1",
176
176
  /INSERT INTO authorships \((author_id, name|name, author_id)\) VALUES \((1, 'Bob'|'Bob', 1)\)/,
177
177
  "SELECT * FROM authorships WHERE (id = 1) LIMIT 1")
178
178
  Authorship.count.should == 1
179
179
  Authorship.first.should == authorship
180
- sqls_should_be('SELECT COUNT(*) FROM authorships LIMIT 1', "SELECT * FROM authorships LIMIT 1")
180
+ sqls_should_be('SELECT COUNT(*) AS \'count\' FROM authorships LIMIT 1', "SELECT * FROM authorships LIMIT 1")
181
181
  authorship.name.should == 'Bob'
182
182
  authorship.author_id.should == @author.id
183
183
  @author.authorships_dataset.find_or_create_by_name('Bob').should == authorship
184
184
  sqls_should_be("SELECT * FROM authorships WHERE ((authorships.author_id = 1) AND (name = 'Bob')) LIMIT 1")
185
185
  Authorship.count.should == 1
186
- sqls_should_be('SELECT COUNT(*) FROM authorships LIMIT 1')
186
+ sqls_should_be('SELECT COUNT(*) AS \'count\' FROM authorships LIMIT 1')
187
187
  authorship2 = @author.authorships_dataset.find_or_create(:name=>'Jim')
188
188
  sqls_should_be("SELECT * FROM authorships WHERE ((authorships.author_id = 1) AND (name = 'Jim')) LIMIT 1",
189
189
  /INSERT INTO authorships \((author_id, name|name, author_id)\) VALUES \((1, 'Jim'|'Jim', 1)\)/,
190
190
  "SELECT * FROM authorships WHERE (id = 2) LIMIT 1")
191
191
  Authorship.count.should == 2
192
- sqls_should_be('SELECT COUNT(*) FROM authorships LIMIT 1')
192
+ sqls_should_be('SELECT COUNT(*) AS \'count\' FROM authorships LIMIT 1')
193
193
  Authorship.order(:name).map(:name).should == ['Bob', 'Jim']
194
194
  sqls_should_be('SELECT * FROM authorships ORDER BY name')
195
195
  authorship2.name.should == 'Jim'
@@ -364,8 +364,8 @@ describe "Polymorphic Associations" do
364
364
  INTEGRATION_DB.instance_variable_set(:@schemas, nil)
365
365
  INTEGRATION_DB.create_table!(:assets) do
366
366
  primary_key :id
367
- integer :attachable_id
368
- text :attachable_type
367
+ Integer :attachable_id
368
+ String :attachable_type
369
369
  end
370
370
  class ::Asset < Sequel::Model
371
371
  m = method(:constantize)
@@ -536,7 +536,7 @@ describe "many_to_one/one_to_many not referencing primary key" do
536
536
  INTEGRATION_DB.instance_variable_set(:@schemas, nil)
537
537
  INTEGRATION_DB.create_table!(:clients) do
538
538
  primary_key :id
539
- text :name
539
+ String :name
540
540
  end
541
541
  class ::Client < Sequel::Model
542
542
  one_to_many :invoices, :reciprocal=>:client, \
@@ -570,7 +570,7 @@ describe "many_to_one/one_to_many not referencing primary key" do
570
570
 
571
571
  INTEGRATION_DB.create_table!(:invoices) do
572
572
  primary_key :id
573
- text :client_name
573
+ String :client_name
574
574
  end
575
575
  class ::Invoice < Sequel::Model
576
576
  many_to_one :client, :key=>:client_name, \
@@ -681,3 +681,64 @@ describe "many_to_one/one_to_many not referencing primary key" do
681
681
  @invoice2.client_name.should == nil
682
682
  end
683
683
  end
684
+
685
+ describe "statistics associations" do
686
+ before do
687
+ INTEGRATION_DB.create_table!(:projects) do
688
+ primary_key :id
689
+ String :name
690
+ end
691
+ class ::Project < Sequel::Model
692
+ many_to_one :ticket_hours, :read_only=>true, :key=>:id,
693
+ :dataset=>proc{Ticket.filter(:project_id=>id).select{sum(hours).as(hours)}},
694
+ :eager_loader=>(proc do |kh, projects, a|
695
+ projects.each{|p| p.associations[:ticket_hours] = nil}
696
+ Ticket.filter(:project_id=>kh[:id].keys).
697
+ group(:project_id).
698
+ select{[project_id.as(project_id), sum(hours).as(hours)]}.
699
+ all do |t|
700
+ p = kh[:id][t.values.delete(:project_id)].first
701
+ p.associations[:ticket_hours] = t
702
+ end
703
+ end)
704
+ def ticket_hours
705
+ if s = super
706
+ s[:hours]
707
+ end
708
+ end
709
+ end
710
+
711
+ INTEGRATION_DB.create_table!(:tickets) do
712
+ primary_key :id
713
+ foreign_key :project_id, :projects
714
+ Integer :hours
715
+ end
716
+ class ::Ticket < Sequel::Model
717
+ many_to_one :project
718
+ end
719
+
720
+ @project1 = Project.create(:name=>'X')
721
+ @project2 = Project.create(:name=>'Y')
722
+ @ticket1 = Ticket.create(:project=>@project1, :hours=>1)
723
+ @ticket2 = Ticket.create(:project=>@project1, :hours=>10)
724
+ @ticket3 = Ticket.create(:project=>@project2, :hours=>2)
725
+ @ticket4 = Ticket.create(:project=>@project2, :hours=>20)
726
+ clear_sqls
727
+ end
728
+ after do
729
+ INTEGRATION_DB.drop_table :tickets, :projects
730
+ Object.send(:remove_const, :Project)
731
+ Object.send(:remove_const, :Ticket)
732
+ end
733
+
734
+ it "should give the correct sum of ticket hours for each project" do
735
+ @project1.ticket_hours.to_i.should == 11
736
+ @project2.ticket_hours.to_i.should == 22
737
+ end
738
+
739
+ it "should give the correct sum of ticket hours for each project when eager loading" do
740
+ p1, p2 = Project.order(:name).eager(:ticket_hours).all
741
+ p1.ticket_hours.to_i.should == 11
742
+ p2.ticket_hours.to_i.should == 22
743
+ end
744
+ end
@@ -76,7 +76,7 @@ describe "Prepared Statements and Bound Arguments" do
76
76
  INTEGRATION_DB.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
77
77
  @ds.filter(:number=>@ds.ba(:$n)).prepare(:first, :select_n)
78
78
  INTEGRATION_DB.call(:select_n, :n=>10).should == {:id=>1, :number=>10}
79
- if INTEGRATION_DB.uri =~ /jdbc:sqlite:/
79
+ if INTEGRATION_DB.class.adapter_scheme == :jdbc and INTEGRATION_DB.database_type == :sqlite
80
80
  # Work around for open prepared statements on a table not allowing the
81
81
  # dropping of a table when using SQLite over JDBC
82
82
  INTEGRATION_DB.synchronize{|c| c.prepared_statements[:select_n][1].close}
@@ -121,7 +121,7 @@ describe "Prepared Statements and Bound Arguments" do
121
121
  INTEGRATION_DB.call(:select_n, :n=>10).should == [@c.load(:id=>1, :number=>10)]
122
122
  @c.filter(:number=>@ds.ba(:$n)).prepare(:first, :select_n)
123
123
  INTEGRATION_DB.call(:select_n, :n=>10).should == @c.load(:id=>1, :number=>10)
124
- if INTEGRATION_DB.uri =~ /jdbc:sqlite:/
124
+ if INTEGRATION_DB.class.adapter_scheme == :jdbc and INTEGRATION_DB.database_type == :sqlite
125
125
  # Work around for open prepared statements on a table not allowing the
126
126
  # dropping of a table when using SQLite over JDBC
127
127
  INTEGRATION_DB.synchronize{|c| c.prepared_statements[:select_n][1].close}
@@ -19,20 +19,13 @@ describe "Database schema parser" do
19
19
  INTEGRATION_DB.identifier_output_method = :reverse
20
20
  INTEGRATION_DB.identifier_input_method = :reverse
21
21
  INTEGRATION_DB.default_schema = nil if INTEGRATION_DB.default_schema
22
- INTEGRATION_DB.create_table!(:items){integer :number}
22
+ INTEGRATION_DB.create_table!(:items){Integer :number}
23
23
  INTEGRATION_DB.schema(:items, :reload=>true).should be_a_kind_of(Array)
24
24
  INTEGRATION_DB.schema(:items, :reload=>true).first.first.should == :number
25
25
  end
26
26
 
27
- deprec_specify "should be a hash with table_names as symbols" do
28
- INTEGRATION_DB.create_table!(:items){integer :number}
29
- schema = INTEGRATION_DB.schema(nil, :reload=>true)
30
- schema.should be_a_kind_of(Hash)
31
- schema[:items].should_not == nil
32
- end
33
-
34
27
  specify "should not issue an sql query if the schema has been loaded unless :reload is true" do
35
- INTEGRATION_DB.create_table!(:items){integer :number}
28
+ INTEGRATION_DB.create_table!(:items){Integer :number}
36
29
  INTEGRATION_DB.schema(:items, :reload=>true)
37
30
  clear_sqls
38
31
  INTEGRATION_DB.schema(:items)
@@ -42,17 +35,12 @@ describe "Database schema parser" do
42
35
  sqls_should_be "PRAGMA table_info('items')"
43
36
  end
44
37
 
45
- deprec_specify "should give the same result for a single table regardless of whether schema was called for a single table" do
46
- INTEGRATION_DB.create_table!(:items){integer :number}
47
- INTEGRATION_DB.schema(:items, :reload=>true).should == INTEGRATION_DB.schema(nil, :reload=>true)[:items]
48
- end
49
-
50
38
  specify "should raise an error when the table doesn't exist" do
51
39
  proc{INTEGRATION_DB.schema(:no_table)}.should raise_error(Sequel::Error)
52
40
  end
53
41
 
54
42
  specify "should return the schema correctly" do
55
- INTEGRATION_DB.create_table!(:items){integer :number}
43
+ INTEGRATION_DB.create_table!(:items){Integer :number}
56
44
  schema = INTEGRATION_DB.schema(:items, :reload=>true)
57
45
  schema.should be_a_kind_of(Array)
58
46
  schema.length.should == 1
@@ -69,35 +57,96 @@ describe "Database schema parser" do
69
57
  end
70
58
 
71
59
  specify "should parse primary keys from the schema properly" do
72
- INTEGRATION_DB.create_table!(:items){integer :number}
60
+ INTEGRATION_DB.create_table!(:items){Integer :number}
73
61
  INTEGRATION_DB.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == []
74
62
  INTEGRATION_DB.create_table!(:items){primary_key :number}
75
63
  INTEGRATION_DB.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == [:number]
76
- INTEGRATION_DB.create_table!(:items){integer :number1; integer :number2; primary_key [:number1, :number2]}
64
+ INTEGRATION_DB.create_table!(:items){Integer :number1; Integer :number2; primary_key [:number1, :number2]}
77
65
  INTEGRATION_DB.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == [:number1, :number2]
78
66
  end
79
67
 
80
68
  specify "should parse NULL/NOT NULL from the schema properly" do
81
- INTEGRATION_DB.create_table!(:items){integer :number, :null=>true}
69
+ INTEGRATION_DB.create_table!(:items){Integer :number, :null=>true}
82
70
  INTEGRATION_DB.schema(:items).first.last[:allow_null].should == true
83
- INTEGRATION_DB.create_table!(:items){integer :number, :null=>false}
71
+ INTEGRATION_DB.create_table!(:items){Integer :number, :null=>false}
84
72
  INTEGRATION_DB.schema(:items).first.last[:allow_null].should == false
85
73
  end
86
74
 
87
75
  specify "should parse defaults from the schema properly" do
88
- INTEGRATION_DB.create_table!(:items){integer :number}
76
+ INTEGRATION_DB.create_table!(:items){Integer :number}
89
77
  INTEGRATION_DB.schema(:items).first.last[:default].should == nil
90
- INTEGRATION_DB.create_table!(:items){integer :number, :default=>0}
78
+ INTEGRATION_DB.create_table!(:items){Integer :number, :default=>0}
91
79
  INTEGRATION_DB.schema(:items).first.last[:default].to_s.should == "0"
92
- INTEGRATION_DB.create_table!(:items){varchar :a, :default=>"blah", :size=>4}
93
- INTEGRATION_DB.schema(:items).first.last[:default].gsub(/::character varying\z/, '').gsub("'", '').should == "blah"
80
+ INTEGRATION_DB.create_table!(:items){String :a, :default=>"blah"}
81
+ INTEGRATION_DB.schema(:items).first.last[:default].should include('blah')
82
+ end
83
+
84
+ specify "should parse types from the schema properly" do
85
+ INTEGRATION_DB.create_table!(:items){Integer :number}
86
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :integer
87
+ INTEGRATION_DB.create_table!(:items){Fixnum :number}
88
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :integer
89
+ INTEGRATION_DB.create_table!(:items){Bignum :number}
90
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :integer
91
+ INTEGRATION_DB.create_table!(:items){Float :number}
92
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :float
93
+ INTEGRATION_DB.create_table!(:items){BigDecimal :number}
94
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :decimal
95
+ INTEGRATION_DB.create_table!(:items){Numeric :number}
96
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :decimal
97
+ INTEGRATION_DB.create_table!(:items){String :number}
98
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :string
99
+ INTEGRATION_DB.create_table!(:items){Date :number}
100
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :date
101
+ INTEGRATION_DB.create_table!(:items){Time :number}
102
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :datetime
103
+ INTEGRATION_DB.create_table!(:items){DateTime :number}
104
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :datetime
105
+ INTEGRATION_DB.create_table!(:items){File :number}
106
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :blob
107
+ INTEGRATION_DB.create_table!(:items){TrueClass :number}
108
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :boolean
109
+ INTEGRATION_DB.create_table!(:items){FalseClass :number}
110
+ INTEGRATION_DB.schema(:items).first.last[:type].should == :boolean
111
+ end
112
+ end
113
+ end
114
+
115
+ if INTEGRATION_DB.respond_to?(:indexes)
116
+ describe "Database index parsing" do
117
+ after do
118
+ INTEGRATION_DB.drop_table(:items)
119
+ end
120
+
121
+ specify "should parse indexes into a hash" do
122
+ INTEGRATION_DB.create_table!(:items){Integer :n; Integer :a}
123
+ INTEGRATION_DB.indexes(:items).should == {}
124
+ INTEGRATION_DB.add_index(:items, :n)
125
+ INTEGRATION_DB.indexes(:items).should == {:items_n_index=>{:columns=>[:n], :unique=>false}}
126
+ INTEGRATION_DB.drop_index(:items, :n)
127
+ INTEGRATION_DB.indexes(:items).should == {}
128
+ INTEGRATION_DB.add_index(:items, :n, :unique=>true, :name=>:blah_blah_index)
129
+ INTEGRATION_DB.indexes(:items).should == {:blah_blah_index=>{:columns=>[:n], :unique=>true}}
130
+ INTEGRATION_DB.add_index(:items, [:n, :a])
131
+ INTEGRATION_DB.indexes(:items).should == {:blah_blah_index=>{:columns=>[:n], :unique=>true}, :items_n_a_index=>{:columns=>[:n, :a], :unique=>false}}
132
+ INTEGRATION_DB.drop_index(:items, :n, :name=>:blah_blah_index)
133
+ INTEGRATION_DB.indexes(:items).should == {:items_n_a_index=>{:columns=>[:n, :a], :unique=>false}}
134
+ INTEGRATION_DB.drop_index(:items, [:n, :a])
135
+ INTEGRATION_DB.indexes(:items).should == {}
136
+ end
137
+
138
+ specify "should not include a primary key index" do
139
+ INTEGRATION_DB.create_table!(:items){primary_key :n}
140
+ INTEGRATION_DB.indexes(:items).should == {}
141
+ INTEGRATION_DB.create_table!(:items){Integer :n; Integer :a; primary_key [:n, :a]}
142
+ INTEGRATION_DB.indexes(:items).should == {}
94
143
  end
95
144
  end
96
145
  end
97
146
 
98
147
  describe "Database schema modifiers" do
99
148
  before do
100
- INTEGRATION_DB.create_table!(:items){integer :number}
149
+ INTEGRATION_DB.create_table!(:items){Integer :number}
101
150
  @ds = INTEGRATION_DB[:items]
102
151
  @ds.insert([10])
103
152
  clear_sqls
@@ -118,7 +167,7 @@ describe "Database schema modifiers" do
118
167
  INTEGRATION_DB.alter_table(:items){add_column :name, :text}
119
168
  INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name]
120
169
  @ds.columns!.should == [:number, :name]
121
- unless INTEGRATION_DB.url =~ /sqlite/
170
+ unless INTEGRATION_DB.database_type == :sqlite
122
171
  INTEGRATION_DB.alter_table(:items){add_primary_key :id}
123
172
  INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name, :id]
124
173
  @ds.columns!.should == [:number, :name, :id]
@@ -131,8 +180,8 @@ describe "Database schema modifiers" do
131
180
  specify "should remove columns from tables correctly" do
132
181
  INTEGRATION_DB.create_table!(:items) do
133
182
  primary_key :id
134
- text :name
135
- integer :number
183
+ String :name
184
+ Integer :number
136
185
  foreign_key :item_id, :items
137
186
  end
138
187
  @ds.insert(:number=>10)