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
@@ -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)