sequel 2.2.0 → 2.3.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 (98) hide show
  1. data/CHANGELOG +1551 -4
  2. data/README +306 -19
  3. data/Rakefile +84 -56
  4. data/bin/sequel +106 -0
  5. data/doc/cheat_sheet.rdoc +225 -0
  6. data/doc/dataset_filtering.rdoc +182 -0
  7. data/lib/sequel_core.rb +136 -0
  8. data/lib/sequel_core/adapters/adapter_skeleton.rb +54 -0
  9. data/lib/sequel_core/adapters/ado.rb +80 -0
  10. data/lib/sequel_core/adapters/db2.rb +148 -0
  11. data/lib/sequel_core/adapters/dbi.rb +117 -0
  12. data/lib/sequel_core/adapters/informix.rb +78 -0
  13. data/lib/sequel_core/adapters/jdbc.rb +186 -0
  14. data/lib/sequel_core/adapters/jdbc/mysql.rb +55 -0
  15. data/lib/sequel_core/adapters/jdbc/postgresql.rb +66 -0
  16. data/lib/sequel_core/adapters/jdbc/sqlite.rb +47 -0
  17. data/lib/sequel_core/adapters/mysql.rb +231 -0
  18. data/lib/sequel_core/adapters/odbc.rb +155 -0
  19. data/lib/sequel_core/adapters/odbc_mssql.rb +106 -0
  20. data/lib/sequel_core/adapters/openbase.rb +64 -0
  21. data/lib/sequel_core/adapters/oracle.rb +170 -0
  22. data/lib/sequel_core/adapters/postgres.rb +199 -0
  23. data/lib/sequel_core/adapters/shared/mysql.rb +275 -0
  24. data/lib/sequel_core/adapters/shared/postgres.rb +351 -0
  25. data/lib/sequel_core/adapters/shared/sqlite.rb +146 -0
  26. data/lib/sequel_core/adapters/sqlite.rb +138 -0
  27. data/lib/sequel_core/connection_pool.rb +194 -0
  28. data/lib/sequel_core/core_ext.rb +203 -0
  29. data/lib/sequel_core/core_sql.rb +184 -0
  30. data/lib/sequel_core/database.rb +471 -0
  31. data/lib/sequel_core/database/schema.rb +156 -0
  32. data/lib/sequel_core/dataset.rb +457 -0
  33. data/lib/sequel_core/dataset/callback.rb +13 -0
  34. data/lib/sequel_core/dataset/convenience.rb +245 -0
  35. data/lib/sequel_core/dataset/pagination.rb +96 -0
  36. data/lib/sequel_core/dataset/query.rb +41 -0
  37. data/lib/sequel_core/dataset/schema.rb +15 -0
  38. data/lib/sequel_core/dataset/sql.rb +889 -0
  39. data/lib/sequel_core/deprecated.rb +26 -0
  40. data/lib/sequel_core/exceptions.rb +42 -0
  41. data/lib/sequel_core/migration.rb +187 -0
  42. data/lib/sequel_core/object_graph.rb +216 -0
  43. data/lib/sequel_core/pretty_table.rb +71 -0
  44. data/lib/sequel_core/schema.rb +2 -0
  45. data/lib/sequel_core/schema/generator.rb +239 -0
  46. data/lib/sequel_core/schema/sql.rb +325 -0
  47. data/lib/sequel_core/sql.rb +812 -0
  48. data/lib/sequel_model.rb +5 -1
  49. data/lib/sequel_model/association_reflection.rb +3 -8
  50. data/lib/sequel_model/base.rb +15 -10
  51. data/lib/sequel_model/inflector.rb +3 -5
  52. data/lib/sequel_model/plugins.rb +1 -1
  53. data/lib/sequel_model/record.rb +11 -3
  54. data/lib/sequel_model/schema.rb +4 -4
  55. data/lib/sequel_model/validations.rb +6 -1
  56. data/spec/adapters/ado_spec.rb +17 -0
  57. data/spec/adapters/informix_spec.rb +96 -0
  58. data/spec/adapters/mysql_spec.rb +764 -0
  59. data/spec/adapters/oracle_spec.rb +222 -0
  60. data/spec/adapters/postgres_spec.rb +441 -0
  61. data/spec/adapters/spec_helper.rb +7 -0
  62. data/spec/adapters/sqlite_spec.rb +400 -0
  63. data/spec/integration/dataset_test.rb +51 -0
  64. data/spec/integration/eager_loader_test.rb +702 -0
  65. data/spec/integration/schema_test.rb +102 -0
  66. data/spec/integration/spec_helper.rb +44 -0
  67. data/spec/integration/type_test.rb +43 -0
  68. data/spec/rcov.opts +2 -0
  69. data/spec/sequel_core/connection_pool_spec.rb +363 -0
  70. data/spec/sequel_core/core_ext_spec.rb +156 -0
  71. data/spec/sequel_core/core_sql_spec.rb +427 -0
  72. data/spec/sequel_core/database_spec.rb +964 -0
  73. data/spec/sequel_core/dataset_spec.rb +2977 -0
  74. data/spec/sequel_core/expression_filters_spec.rb +346 -0
  75. data/spec/sequel_core/migration_spec.rb +261 -0
  76. data/spec/sequel_core/object_graph_spec.rb +234 -0
  77. data/spec/sequel_core/pretty_table_spec.rb +58 -0
  78. data/spec/sequel_core/schema_generator_spec.rb +122 -0
  79. data/spec/sequel_core/schema_spec.rb +497 -0
  80. data/spec/sequel_core/spec_helper.rb +51 -0
  81. data/spec/{association_reflection_spec.rb → sequel_model/association_reflection_spec.rb} +6 -6
  82. data/spec/{associations_spec.rb → sequel_model/associations_spec.rb} +47 -18
  83. data/spec/{base_spec.rb → sequel_model/base_spec.rb} +2 -1
  84. data/spec/{caching_spec.rb → sequel_model/caching_spec.rb} +0 -0
  85. data/spec/{dataset_methods_spec.rb → sequel_model/dataset_methods_spec.rb} +13 -1
  86. data/spec/{eager_loading_spec.rb → sequel_model/eager_loading_spec.rb} +75 -14
  87. data/spec/{hooks_spec.rb → sequel_model/hooks_spec.rb} +4 -4
  88. data/spec/sequel_model/inflector_spec.rb +119 -0
  89. data/spec/{model_spec.rb → sequel_model/model_spec.rb} +30 -11
  90. data/spec/{plugins_spec.rb → sequel_model/plugins_spec.rb} +0 -0
  91. data/spec/{record_spec.rb → sequel_model/record_spec.rb} +47 -6
  92. data/spec/{schema_spec.rb → sequel_model/schema_spec.rb} +18 -4
  93. data/spec/{spec_helper.rb → sequel_model/spec_helper.rb} +3 -2
  94. data/spec/{validations_spec.rb → sequel_model/validations_spec.rb} +37 -17
  95. data/spec/spec_config.rb +9 -0
  96. data/spec/spec_config.rb.example +10 -0
  97. metadata +110 -37
  98. data/spec/inflector_spec.rb +0 -34
@@ -0,0 +1,234 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Sequel::Dataset, " graphing" do
4
+ before do
5
+ dbc = Class.new
6
+ @db = dbc.new
7
+ @ds1 = Sequel::Dataset.new(@db).from(:points)
8
+ @ds2 = Sequel::Dataset.new(@db).from(:lines)
9
+ @ds3 = Sequel::Dataset.new(@db).from(:graphs)
10
+ dss = {:points=>@ds1, :lines=>@ds2, :graphs=>@ds3}
11
+ dbc.send(:define_method, :[]){|ds| dss[ds]}
12
+ def @ds1.columns; [:id, :x, :y] end
13
+ def @ds2.columns; [:id, :x, :y, :graph_id] end
14
+ def @ds3.columns; [:id, :name, :x, :y, :lines_x] end
15
+ end
16
+
17
+ it "#graph should not modify the current dataset's opts" do
18
+ o1 = @ds1.opts
19
+ o2 = o1.dup
20
+ ds1 = @ds1.graph(@ds2, :x=>:id)
21
+ @ds1.opts.should == o1
22
+ @ds1.opts.should == o2
23
+ ds1.opts.should_not == o1
24
+ end
25
+
26
+ it "#graph should accept a dataset as the dataset" do
27
+ ds = @ds1.graph(@ds2, :x=>:id)
28
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
29
+ end
30
+
31
+ it "#graph should accept a symbol table name as the dataset" do
32
+ ds = @ds1.graph(:lines, :x=>:id)
33
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
34
+ end
35
+
36
+ it "#graph should accept an object that responds to dataset as the dataset" do
37
+ oc = Class.new
38
+ o = oc.new
39
+ ds = @ds2
40
+ oc.send(:define_method, :dataset){ds}
41
+ ds = @ds1.graph(o, :x=>:id)
42
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
43
+ ds = :lines
44
+ oc.send(:define_method, :dataset){ds}
45
+ ds = @ds1.graph(o, :x=>:id)
46
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
47
+ end
48
+
49
+ it "#graph should raise an error if a symbol, dataset, or model is not used" do
50
+ proc{@ds1.graph(Object.new, :x=>:id)}.should raise_error(Sequel::Error)
51
+ end
52
+
53
+ it "#graph should accept a :table_alias option" do
54
+ ds = @ds1.graph(:lines, {:x=>:id}, :table_alias=>:planes)
55
+ ds.sql.should == 'SELECT points.id, points.x, points.y, planes.id AS planes_id, planes.x AS planes_x, planes.y AS planes_y, planes.graph_id FROM points LEFT OUTER JOIN lines AS planes ON (planes.x = points.id)'
56
+ end
57
+
58
+ it "#graph should accept a :join_type option" do
59
+ ds = @ds1.graph(:lines, {:x=>:id}, :join_type=>:inner)
60
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points INNER JOIN lines ON (lines.x = points.id)'
61
+ end
62
+
63
+ it "#graph should not select any columns from the graphed table if :select option is false" do
64
+ ds = @ds1.graph(:lines, {:x=>:id}, :select=>false).graph(:graphs, :id=>:graph_id)
65
+ ds.sql.should == 'SELECT points.id, points.x, points.y, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
66
+ end
67
+
68
+ it "#graph should use the given columns if :select option is used" do
69
+ ds = @ds1.graph(:lines, {:x=>:id}, :select=>[:x, :graph_id]).graph(:graphs, :id=>:graph_id)
70
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.x AS lines_x, lines.graph_id, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x AS graphs_lines_x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
71
+ end
72
+
73
+ it "#graph should pass all join_conditions to join_table" do
74
+ ds = @ds1.graph(@ds2, [[:x, :id], [:y, :id]])
75
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON ((lines.x = points.id) AND (lines.y = points.id))'
76
+ end
77
+
78
+ it "#graph should accept a block instead of conditions and pass it to join_table" do
79
+ ds = @ds1.graph(@ds2){|ja, lja, js| [[:x.qualify(ja), :id.qualify(lja)], [:y.qualify(ja), :id.qualify(lja)]]}
80
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON ((lines.x = points.id) AND (lines.y = points.id))'
81
+ end
82
+
83
+ it "#graph should not add columns if graph is called after set_graph_aliases" do
84
+ ds = @ds1.set_graph_aliases([[:x,[:points, :x]], [:y,[:lines, :y]]])
85
+ ds.sql.should == 'SELECT points.x, lines.y FROM points'
86
+ ds = ds.graph(:lines, :x=>:id)
87
+ ds.sql.should == 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
88
+ end
89
+
90
+ it "#graph should allow graphing of multiple datasets" do
91
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id)
92
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x AS graphs_lines_x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
93
+ end
94
+
95
+ it "#graph should allow graphing of the same dataset multiple times" do
96
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>:points__id}, :table_alias=>:graph)
97
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id, graph.id AS graph_id_0, graph.x AS graph_x, graph.y AS graph_y, graph.graph_id AS graph_graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN lines AS graph ON (graph.y = points.id)'
98
+ end
99
+
100
+ it "#graph should raise an error if the table/table alias has already been used" do
101
+ proc{@ds1.graph(@ds1, :x=>:id)}.should raise_error(Sequel::Error)
102
+ proc{@ds1.graph(@ds2, :x=>:id)}.should_not raise_error
103
+ proc{@ds1.graph(@ds2, :x=>:id).graph(@ds2, :x=>:id)}.should raise_error(Sequel::Error)
104
+ proc{@ds1.graph(@ds2, :x=>:id).graph(@ds2, {:x=>:id}, :table_alias=>:blah)}.should_not raise_error
105
+ end
106
+
107
+ it "#set_graph_aliases should not modify the current dataset's opts" do
108
+ o1 = @ds1.opts
109
+ o2 = o1.dup
110
+ ds1 = @ds1.set_graph_aliases(:x=>[:graphs,:id])
111
+ @ds1.opts.should == o1
112
+ @ds1.opts.should == o2
113
+ ds1.opts.should_not == o1
114
+ end
115
+
116
+ it "#set_graph_aliases should specify the graph mapping" do
117
+ ds = @ds1.graph(:lines, :x=>:id)
118
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
119
+ ds = ds.set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
120
+ ['SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)',
121
+ 'SELECT lines.y, points.x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
122
+ ].should(include(ds.sql))
123
+ end
124
+
125
+ it "#set_graph_aliases should only alias columns if necessary" do
126
+ ds = @ds1.set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
127
+ ['SELECT points.x, lines.y FROM points',
128
+ 'SELECT lines.y, points.x FROM points'
129
+ ].should(include(ds.sql))
130
+
131
+ ds = @ds1.set_graph_aliases(:x1=>[:points, :x], :y=>[:lines, :y])
132
+ ['SELECT points.x AS x1, lines.y FROM points',
133
+ 'SELECT lines.y, points.x AS x1 FROM points'
134
+ ].should(include(ds.sql))
135
+ end
136
+
137
+ it "#graph_each should split the result set into component tables" do
138
+ ds = @ds1.graph(@ds2, :x=>:id)
139
+ def ds.fetch_rows(sql, &block)
140
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7})
141
+ end
142
+ results = ds.all
143
+ results.length.should == 1
144
+ results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}}
145
+
146
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id)
147
+ def ds.fetch_rows(sql, &block)
148
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :graphs_lines_x=>12})
149
+ end
150
+ results = ds.all
151
+ results.length.should == 1
152
+ results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}
153
+
154
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>:points__id}, :table_alias=>:graph)
155
+ def ds.fetch_rows(sql, &block)
156
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graph_id_0=>8, :graph_x=>9, :graph_y=>10, :graph_graph_id=>11})
157
+ end
158
+ results = ds.all
159
+ results.length.should == 1
160
+ results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graph=>{:id=>8, :x=>9, :y=>10, :graph_id=>11}}
161
+ end
162
+
163
+ it "#graph_each should give a nil value instead of a hash when all values for a table are nil" do
164
+ ds = @ds1.graph(@ds2, :x=>:id)
165
+ def ds.fetch_rows(sql, &block)
166
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>nil,:lines_x=>nil,:lines_y=>nil,:graph_id=>nil})
167
+ end
168
+ results = ds.all
169
+ results.length.should == 1
170
+ results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>nil}
171
+
172
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id)
173
+ def ds.fetch_rows(sql, &block)
174
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>nil, :name=>nil, :graphs_x=>nil, :graphs_y=>nil, :graphs_lines_x=>nil})
175
+ yield({:id=>2,:x=>4,:y=>5,:lines_id=>nil,:lines_x=>nil,:lines_y=>nil,:graph_id=>nil, :graphs_id=>nil, :name=>nil, :graphs_x=>nil, :graphs_y=>nil, :graphs_lines_x=>nil})
176
+ yield({:id=>3,:x=>5,:y=>6,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>7, :name=>8, :graphs_x=>9, :graphs_y=>10, :graphs_lines_x=>11})
177
+ yield({:id=>3,:x=>5,:y=>6,:lines_id=>7,:lines_x=>5,:lines_y=>8,:graph_id=>9, :graphs_id=>9, :name=>10, :graphs_x=>10, :graphs_y=>11, :graphs_lines_x=>12})
178
+ end
179
+ results = ds.all
180
+ results.length.should == 4
181
+ results[0].should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>nil}
182
+ results[1].should == {:points=>{:id=>2, :x=>4, :y=>5}, :lines=>nil, :graphs=>nil}
183
+ results[2].should == {:points=>{:id=>3, :x=>5, :y=>6}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>7, :name=>8, :x=>9, :y=>10, :lines_x=>11}}
184
+ results[3].should == {:points=>{:id=>3, :x=>5, :y=>6}, :lines=>{:id=>7, :x=>5, :y=>8, :graph_id=>9}, :graphs=>{:id=>9, :name=>10, :x=>10, :y=>11, :lines_x=>12}}
185
+ end
186
+
187
+ it "#graph_each should not included tables graphed with the :select => false option in the result set" do
188
+ ds = @ds1.graph(:lines, {:x=>:id}, :select=>false).graph(:graphs, :id=>:graph_id)
189
+ def ds.fetch_rows(sql, &block)
190
+ yield({:id=>1,:x=>2,:y=>3,:graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :lines_x=>12})
191
+ end
192
+ results = ds.all
193
+ results.length.should == 1
194
+ results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}
195
+ end
196
+
197
+ it "#graph_each should only include the columns selected with #set_graph_aliases, if called" do
198
+ ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
199
+ def ds.fetch_rows(sql, &block)
200
+ yield({:x=>2,:y=>3})
201
+ end
202
+ results = ds.all
203
+ results.length.should == 1
204
+ results.first.should == {:points=>{:x=>2}, :lines=>{:y=>3}}
205
+
206
+ ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x])
207
+ def ds.fetch_rows(sql, &block)
208
+ yield({:x=>2})
209
+ end
210
+ results = ds.all
211
+ results.length.should == 1
212
+ results.first.should == {:points=>{:x=>2}, :lines=>nil}
213
+ end
214
+
215
+ it "#graph_each should run the row_proc and transform for graphed datasets" do
216
+ @ds1.row_proc = proc{|h| h.keys.each{|k| h[k] *= 2}; h}
217
+ @ds2.row_proc = proc{|h| h.keys.each{|k| h[k] *= 3}; h}
218
+ @ds1.transform(:x=>[
219
+ proc{|v| 123},
220
+ proc{|v| 123}
221
+ ])
222
+ @ds2.transform(:x=>[
223
+ proc{|v| 321},
224
+ proc{|v| 321}
225
+ ])
226
+ ds = @ds1.graph(@ds2, :x=>:id)
227
+ def ds.fetch_rows(sql, &block)
228
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7})
229
+ end
230
+ results = ds.all
231
+ results.length.should == 1
232
+ results.first.should == {:points=>{:id=>2, :x=>246, :y=>6}, :lines=>{:id=>12, :x=>963, :y=>18, :graph_id=>21}}
233
+ end
234
+ end
@@ -0,0 +1,58 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ require 'stringio'
4
+
5
+ context "PrettyTable" do
6
+ setup do
7
+ @data1 = [
8
+ {:x => 3, :y => 4}
9
+ ]
10
+
11
+ @data2 = [
12
+ {:a => 23, :b => 45},
13
+ {:a => 45, :b => 2377}
14
+ ]
15
+
16
+ @data3 = [
17
+ {:aaa => 1},
18
+ {:bb => 2},
19
+ {:c => 3}
20
+ ]
21
+
22
+ @output = StringIO.new
23
+ @orig_stdout = $stdout
24
+ $stdout = @output
25
+ end
26
+
27
+ teardown do
28
+ $stdout = @orig_stdout
29
+ end
30
+
31
+ specify "should infer the columns if not given" do
32
+ Sequel::PrettyTable.print(@data1)
33
+ @output.rewind
34
+ @output.read.should =~ \
35
+ /\n(\|x\|y\|)|(\|y\|x\|)\n/
36
+ end
37
+
38
+ specify "should calculate the maximum width of each column correctly" do
39
+ Sequel::PrettyTable.print(@data2, [:a, :b])
40
+ @output.rewind
41
+ @output.read.should == \
42
+ "+--+----+\n|a |b |\n+--+----+\n|23| 45|\n|45|2377|\n+--+----+\n"
43
+ end
44
+
45
+ specify "should also take header width into account" do
46
+ Sequel::PrettyTable.print(@data3, [:aaa, :bb, :c])
47
+ @output.rewind
48
+ @output.read.should == \
49
+ "+---+--+-+\n|aaa|bb|c|\n+---+--+-+\n| 1| | |\n| | 2| |\n| | |3|\n+---+--+-+\n"
50
+ end
51
+
52
+ specify "should print only the specified columns" do
53
+ Sequel::PrettyTable.print(@data2, [:a])
54
+ @output.rewind
55
+ @output.read.should == \
56
+ "+--+\n|a |\n+--+\n|23|\n|45|\n+--+\n"
57
+ end
58
+ end
@@ -0,0 +1,122 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Sequel::Schema::Generator do
4
+ before do
5
+ @generator = Sequel::Schema::Generator.new(SchemaDummyDatabase.new) do
6
+ string :title
7
+ column :body, :text
8
+ foreign_key :parent_id
9
+ primary_key :id
10
+ check 'price > 100'
11
+ constraint(:xxx) {:yyy == :zzz}
12
+ index :title
13
+ index [:title, :body]
14
+ foreign_key :node_id, :nodes
15
+ end
16
+ @columns, @indexes = @generator.create_info
17
+ end
18
+
19
+ {:name => :id, :primary_key => true}.each do |column, expected|
20
+ it "uses default primary key #{column}" do
21
+ @columns.first[column].should == expected
22
+ end
23
+ end
24
+
25
+ it "counts primary key, column and constraint definitions as columns" do
26
+ @columns.size.should == 7
27
+ end
28
+
29
+ it "places primary key first" do
30
+ @columns[0][:primary_key].should be_true
31
+ @columns[1][:primary_key].should_not be_true
32
+ @columns[2][:primary_key].should_not be_true
33
+ end
34
+
35
+ it "retrieves primary key name" do
36
+ @generator.primary_key_name.should == :id
37
+ end
38
+
39
+ it "keeps columns in order" do
40
+ @columns[1][:name].should == :title
41
+ @columns[1][:type].should == :string
42
+ @columns[2][:name].should == :body
43
+ @columns[2][:type].should == :text
44
+ end
45
+
46
+ it "creates foreign key column" do
47
+ @columns[3][:name].should == :parent_id
48
+ @columns[3][:type].should == :integer
49
+ @columns[6][:name].should == :node_id
50
+ @columns[6][:type].should == :integer
51
+ end
52
+
53
+ it "uses table for foreign key columns, if specified" do
54
+ @columns[6][:table].should == :nodes
55
+ @columns[3][:table].should == nil
56
+ end
57
+
58
+ it "finds columns" do
59
+ [:title, :body, :parent_id, :id].each do |col|
60
+ @generator.has_column?(col).should be_true
61
+ end
62
+ @generator.has_column?(:foo).should_not be_true
63
+ end
64
+
65
+ it "creates constraints" do
66
+ @columns[4][:name].should == nil
67
+ @columns[4][:type].should == :check
68
+ @columns[4][:check].should == ['price > 100']
69
+
70
+ @columns[5][:name].should == :xxx
71
+ @columns[5][:type].should == :check
72
+ @columns[5][:check].should be_a_kind_of(Proc)
73
+ end
74
+
75
+ it "creates indexes" do
76
+ @indexes[0][:columns].should include(:title)
77
+ @indexes[1][:columns].should include(:title)
78
+ @indexes[1][:columns].should include(:body)
79
+ end
80
+ end
81
+
82
+ describe Sequel::Schema::AlterTableGenerator do
83
+ before do
84
+ @generator = Sequel::Schema::AlterTableGenerator.new(SchemaDummyDatabase.new) do
85
+ add_column :aaa, :text
86
+ drop_column :bbb
87
+ rename_column :ccc, :ho
88
+ set_column_type :ddd, :float
89
+ set_column_default :eee, 1
90
+ add_index [:fff, :ggg]
91
+ drop_index :hhh
92
+ add_full_text_index :blah
93
+ add_spatial_index :geom
94
+ add_index :blah, :type => :hash
95
+ add_index :blah, :where => {:something => true}
96
+ add_constraint :con1, ':fred > 100'
97
+ drop_constraint :con2
98
+ add_primary_key :id
99
+ add_foreign_key :node_id, :nodes
100
+ end
101
+ end
102
+
103
+ specify "should generate operation records" do
104
+ @generator.operations.should == [
105
+ {:op => :add_column, :name => :aaa, :type => :text},
106
+ {:op => :drop_column, :name => :bbb},
107
+ {:op => :rename_column, :name => :ccc, :new_name => :ho},
108
+ {:op => :set_column_type, :name => :ddd, :type => :float},
109
+ {:op => :set_column_default, :name => :eee, :default => 1},
110
+ {:op => :add_index, :columns => [:fff, :ggg]},
111
+ {:op => :drop_index, :columns => [:hhh]},
112
+ {:op => :add_index, :columns => [:blah], :type => :full_text},
113
+ {:op => :add_index, :columns => [:geom], :type => :spatial},
114
+ {:op => :add_index, :columns => [:blah], :type => :hash},
115
+ {:op => :add_index, :columns => [:blah], :where => {:something => true}},
116
+ {:op => :add_constraint, :type => :check, :name => :con1, :check => [':fred > 100']},
117
+ {:op => :drop_constraint, :name => :con2},
118
+ {:op => :add_column, :name => :id, :type => :integer, :primary_key=>true, :auto_increment=>true},
119
+ {:op => :add_column, :name => :node_id, :type => :integer, :table=>:nodes}
120
+ ]
121
+ end
122
+ end
@@ -0,0 +1,497 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ context "DB#create_table" do
4
+ setup do
5
+ @db = SchemaDummyDatabase.new
6
+ end
7
+
8
+ specify "should accept the table name" do
9
+ @db.create_table(:cats) {}
10
+ @db.sqls.should == ['CREATE TABLE cats ()']
11
+ end
12
+
13
+ specify "should accept multiple columns" do
14
+ @db.create_table(:cats) do
15
+ column :id, :integer
16
+ column :name, :text
17
+ end
18
+ @db.sqls.should == ['CREATE TABLE cats (id integer, name text)']
19
+ end
20
+
21
+ specify "should accept method calls as data types" do
22
+ @db.create_table(:cats) do
23
+ integer :id
24
+ text :name
25
+ end
26
+ @db.sqls.should == ['CREATE TABLE cats (id integer, name text)']
27
+ end
28
+
29
+ specify "should accept primary key definition" do
30
+ @db.create_table(:cats) do
31
+ primary_key :id
32
+ end
33
+ @db.sqls.should == ['CREATE TABLE cats (id integer PRIMARY KEY AUTOINCREMENT)']
34
+
35
+ @db.sqls.clear
36
+ @db.create_table(:cats) do
37
+ primary_key :id, :serial, :auto_increment => false
38
+ end
39
+ @db.sqls.should == ['CREATE TABLE cats (id serial PRIMARY KEY)']
40
+
41
+ @db.sqls.clear
42
+ @db.create_table(:cats) do
43
+ primary_key :id, :type => :serial, :auto_increment => false
44
+ end
45
+ @db.sqls.should == ['CREATE TABLE cats (id serial PRIMARY KEY)']
46
+ end
47
+
48
+ specify "should accept and literalize default values" do
49
+ @db.create_table(:cats) do
50
+ integer :id, :default => 123
51
+ text :name, :default => "abc'def"
52
+ end
53
+ @db.sqls.should == ["CREATE TABLE cats (id integer DEFAULT 123, name text DEFAULT 'abc''def')"]
54
+ end
55
+
56
+ specify "should accept not null definition" do
57
+ @db.create_table(:cats) do
58
+ integer :id
59
+ text :name, :null => false
60
+ end
61
+ @db.sqls.should == ["CREATE TABLE cats (id integer, name text NOT NULL)"]
62
+ end
63
+
64
+ specify "should accept null definition" do
65
+ @db.create_table(:cats) do
66
+ integer :id
67
+ text :name, :null => true
68
+ end
69
+ @db.sqls.should == ["CREATE TABLE cats (id integer, name text NULL)"]
70
+ end
71
+
72
+ specify "should accept unique definition" do
73
+ @db.create_table(:cats) do
74
+ integer :id
75
+ text :name, :unique => true
76
+ end
77
+ @db.sqls.should == ["CREATE TABLE cats (id integer, name text UNIQUE)"]
78
+ end
79
+
80
+ specify "should accept unsigned definition" do
81
+ @db.create_table(:cats) do
82
+ integer :value, :unsigned => true
83
+ end
84
+ @db.sqls.should == ["CREATE TABLE cats (value integer UNSIGNED)"]
85
+ end
86
+
87
+ specify "should accept [SET|ENUM](...) types" do
88
+ @db.create_table(:cats) do
89
+ set :color, :elements => ['black', 'tricolor', 'grey']
90
+ end
91
+ @db.sqls.should == ["CREATE TABLE cats (color set('black', 'tricolor', 'grey'))"]
92
+ end
93
+
94
+ specify "should accept varchar size" do
95
+ @db.create_table(:cats) do
96
+ varchar :name
97
+ end
98
+ @db.sqls.should == ["CREATE TABLE cats (name varchar(255))"]
99
+ @db.sqls.clear
100
+ @db.create_table(:cats) do
101
+ varchar :name, :size => 51
102
+ end
103
+ @db.sqls.should == ["CREATE TABLE cats (name varchar(51))"]
104
+ end
105
+
106
+ specify "should accept varchar size as sql function" do
107
+ @db.create_table(:cats) do
108
+ column :name, :varchar[102]
109
+ end
110
+ @db.sqls.should == ["CREATE TABLE cats (name varchar(102))"]
111
+ end
112
+
113
+ specify "should accept foreign keys without options" do
114
+ @db.create_table(:cats) do
115
+ foreign_key :project_id
116
+ end
117
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer)"]
118
+ end
119
+
120
+ specify "should accept foreign keys with options" do
121
+ @db.create_table(:cats) do
122
+ foreign_key :project_id, :table => :projects
123
+ end
124
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects)"]
125
+ end
126
+
127
+ specify "should accept foreign keys with separate table argument" do
128
+ @db.create_table(:cats) do
129
+ foreign_key :project_id, :projects, :default=>3
130
+ end
131
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer DEFAULT 3 REFERENCES projects)"]
132
+ end
133
+
134
+ specify "should raise an error if the table argument to foreign_key isn't a hash, symbol, or nil" do
135
+ proc{@db.create_table(:cats){foreign_key :project_id, Object.new, :default=>3}}.should raise_error(Sequel::Error)
136
+ end
137
+
138
+ specify "should accept foreign keys with arbitrary keys" do
139
+ @db.create_table(:cats) do
140
+ foreign_key :project_id, :table => :projects, :key => :id
141
+ end
142
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects(id))"]
143
+
144
+ @db.sqls.clear
145
+ @db.create_table(:cats) do
146
+ foreign_key :project_id, :table => :projects, :key => :zzz
147
+ end
148
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects(zzz))"]
149
+ end
150
+
151
+ specify "should accept foreign keys with ON DELETE clause" do
152
+ @db.create_table(:cats) do
153
+ foreign_key :project_id, :table => :projects, :on_delete => :restrict
154
+ end
155
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE RESTRICT)"]
156
+
157
+ @db.sqls.clear
158
+ @db.create_table(:cats) do
159
+ foreign_key :project_id, :table => :projects, :on_delete => :cascade
160
+ end
161
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE CASCADE)"]
162
+
163
+ @db.sqls.clear
164
+ @db.create_table(:cats) do
165
+ foreign_key :project_id, :table => :projects, :on_delete => :no_action
166
+ end
167
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE NO ACTION)"]
168
+ @db.sqls.clear
169
+
170
+ @db.sqls.clear
171
+ @db.create_table(:cats) do
172
+ foreign_key :project_id, :table => :projects, :on_delete => :set_null
173
+ end
174
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE SET NULL)"]
175
+ @db.sqls.clear
176
+
177
+ @db.sqls.clear
178
+ @db.create_table(:cats) do
179
+ foreign_key :project_id, :table => :projects, :on_delete => :set_default
180
+ end
181
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE SET DEFAULT)"]
182
+ @db.sqls.clear
183
+ end
184
+
185
+ specify "should accept inline index definition" do
186
+ @db.create_table(:cats) do
187
+ integer :id, :index => true
188
+ end
189
+ @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_id_index ON cats (id)"]
190
+ end
191
+
192
+ specify "should accept inline index definition for foreign keys" do
193
+ @db.create_table(:cats) do
194
+ foreign_key :project_id, :table => :projects, :on_delete => :cascade, :index => true
195
+ end
196
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE CASCADE)",
197
+ "CREATE INDEX cats_project_id_index ON cats (project_id)"]
198
+ end
199
+
200
+ specify "should accept index definitions" do
201
+ @db.create_table(:cats) do
202
+ integer :id
203
+ index :id
204
+ end
205
+ @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_id_index ON cats (id)"]
206
+ end
207
+
208
+ specify "should accept unique index definitions" do
209
+ @db.create_table(:cats) do
210
+ text :name
211
+ unique :name
212
+ end
213
+ @db.sqls.should == ["CREATE TABLE cats (name text)", "CREATE UNIQUE INDEX cats_name_index ON cats (name)"]
214
+ end
215
+
216
+ specify "should raise on full-text index definitions" do
217
+ proc {
218
+ @db.create_table(:cats) do
219
+ text :name
220
+ full_text_index :name
221
+ end
222
+ }.should raise_error(Sequel::Error)
223
+ end
224
+
225
+ specify "should raise on spatial index definitions" do
226
+ proc {
227
+ @db.create_table(:cats) do
228
+ point :geom
229
+ spatial_index :geom
230
+ end
231
+ }.should raise_error(Sequel::Error)
232
+ end
233
+
234
+ specify "should raise on partial index definitions" do
235
+ proc {
236
+ @db.create_table(:cats) do
237
+ text :name
238
+ index :name, :where => {:something => true}
239
+ end
240
+ }.should raise_error(Sequel::Error)
241
+ end
242
+
243
+ specify "should raise index definitions with type" do
244
+ proc {
245
+ @db.create_table(:cats) do
246
+ text :name
247
+ index :name, :type => :hash
248
+ end
249
+ }.should raise_error(Sequel::Error)
250
+ end
251
+
252
+ specify "should accept multiple index definitions" do
253
+ @db.create_table(:cats) do
254
+ integer :id
255
+ index :id
256
+ index :name
257
+ end
258
+ @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_id_index ON cats (id)", "CREATE INDEX cats_name_index ON cats (name)"]
259
+ end
260
+
261
+ specify "should accept custom index names" do
262
+ @db.create_table(:cats) do
263
+ integer :id
264
+ index :id, :name => 'abc'
265
+ end
266
+ @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX abc ON cats (id)"]
267
+ end
268
+
269
+ specify "should accept unique index definitions" do
270
+ @db.create_table(:cats) do
271
+ integer :id
272
+ index :id, :unique => true
273
+ end
274
+ @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE UNIQUE INDEX cats_id_index ON cats (id)"]
275
+ end
276
+
277
+ specify "should accept composite index definitions" do
278
+ @db.create_table(:cats) do
279
+ integer :id
280
+ index [:id, :name], :unique => true
281
+ end
282
+ @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE UNIQUE INDEX cats_id_name_index ON cats (id, name)"]
283
+ end
284
+
285
+ specify "should accept unnamed constraint definitions with blocks" do
286
+ @db.create_table(:cats) do
287
+ integer :score
288
+ check {(:x > 0) & (:y < 1)}
289
+ end
290
+ @db.sqls.should == ["CREATE TABLE cats (score integer, CHECK ((x > 0) AND (y < 1)))"]
291
+ end
292
+
293
+ specify "should accept unnamed constraint definitions" do
294
+ @db.create_table(:cats) do
295
+ check 'price < ?', 100
296
+ end
297
+ @db.sqls.should == ["CREATE TABLE cats (CHECK (price < 100))"]
298
+ end
299
+
300
+ specify "should accept named constraint definitions" do
301
+ @db.create_table(:cats) do
302
+ integer :score
303
+ constraint :valid_score, 'score <= 100'
304
+ end
305
+ @db.sqls.should == ["CREATE TABLE cats (score integer, CONSTRAINT valid_score CHECK (score <= 100))"]
306
+ end
307
+
308
+ specify "should accept named constraint definitions with block" do
309
+ @db.create_table(:cats) do
310
+ constraint(:blah_blah) {(:x > 0) & (:y < 1)}
311
+ end
312
+ @db.sqls.should == ["CREATE TABLE cats (CONSTRAINT blah_blah CHECK ((x > 0) AND (y < 1)))"]
313
+ end
314
+ end
315
+
316
+ context "DB#create_table!" do
317
+ setup do
318
+ @db = SchemaDummyDatabase.new
319
+ end
320
+
321
+ specify "should drop the table and then create it" do
322
+ @db.create_table!(:cats) {}
323
+ @db.sqls.should == ['DROP TABLE cats', 'CREATE TABLE cats ()']
324
+ end
325
+ end
326
+
327
+ context "DB#drop_table" do
328
+ setup do
329
+ @db = SchemaDummyDatabase.new
330
+ end
331
+
332
+ specify "should generate a DROP TABLE statement" do
333
+ @db.drop_table :cats
334
+ @db.sqls.should == ['DROP TABLE cats']
335
+ end
336
+ end
337
+
338
+ context "DB#alter_table" do
339
+ setup do
340
+ @db = SchemaDummyDatabase.new
341
+ end
342
+
343
+ specify "should support add_column" do
344
+ @db.alter_table(:cats) do
345
+ add_column :score, :integer
346
+ end
347
+ @db.sqls.should == ["ALTER TABLE cats ADD COLUMN score integer"]
348
+ end
349
+
350
+ specify "should support add_constraint" do
351
+ @db.alter_table(:cats) do
352
+ add_constraint :valid_score, 'score <= 100'
353
+ end
354
+ @db.sqls.should == ["ALTER TABLE cats ADD CONSTRAINT valid_score CHECK (score <= 100)"]
355
+ end
356
+
357
+ specify "should support add_constraint with block" do
358
+ @db.alter_table(:cats) do
359
+ add_constraint(:blah_blah) {(:x > 0) & (:y < 1)}
360
+ end
361
+ @db.sqls.should == ["ALTER TABLE cats ADD CONSTRAINT blah_blah CHECK ((x > 0) AND (y < 1))"]
362
+ end
363
+
364
+ specify "should support add_foreign_key" do
365
+ @db.alter_table(:cats) do
366
+ add_foreign_key :node_id, :nodes
367
+ end
368
+ @db.sqls.should == ["ALTER TABLE cats ADD COLUMN node_id integer REFERENCES nodes"]
369
+ end
370
+
371
+ specify "should support add_index" do
372
+ @db.alter_table(:cats) do
373
+ add_index :name
374
+ end
375
+ @db.sqls.should == ["CREATE INDEX cats_name_index ON cats (name)"]
376
+ end
377
+
378
+ specify "should support add_primary_key" do
379
+ @db.alter_table(:cats) do
380
+ add_primary_key :id
381
+ end
382
+ @db.sqls.should == ["ALTER TABLE cats ADD COLUMN id integer PRIMARY KEY AUTOINCREMENT"]
383
+ end
384
+
385
+ specify "should support drop_column" do
386
+ @db.alter_table(:cats) do
387
+ drop_column :score
388
+ end
389
+ @db.sqls.should == ["ALTER TABLE cats DROP COLUMN score"]
390
+ end
391
+
392
+ specify "should support drop_constraint" do
393
+ @db.alter_table(:cats) do
394
+ drop_constraint :valid_score
395
+ end
396
+ @db.sqls.should == ["ALTER TABLE cats DROP CONSTRAINT valid_score"]
397
+ end
398
+
399
+ specify "should support drop_index" do
400
+ @db.alter_table(:cats) do
401
+ drop_index :name
402
+ end
403
+ @db.sqls.should == ["DROP INDEX cats_name_index"]
404
+ end
405
+
406
+ specify "should support rename_column" do
407
+ @db.alter_table(:cats) do
408
+ rename_column :name, :old_name
409
+ end
410
+ @db.sqls.should == ["ALTER TABLE cats RENAME COLUMN name TO old_name"]
411
+ end
412
+
413
+ specify "should support set_column_default" do
414
+ @db.alter_table(:cats) do
415
+ set_column_default :score, 3
416
+ end
417
+ @db.sqls.should == ["ALTER TABLE cats ALTER COLUMN score SET DEFAULT 3"]
418
+ end
419
+
420
+ specify "should support set_column_type" do
421
+ @db.alter_table(:cats) do
422
+ set_column_type :score, :real
423
+ end
424
+ @db.sqls.should == ["ALTER TABLE cats ALTER COLUMN score TYPE real"]
425
+ end
426
+ end
427
+
428
+ context "Schema Parser" do
429
+ setup do
430
+ sqls = @sqls = []
431
+ @db = Sequel::Database.new
432
+ @db.meta_def(:dataset) do
433
+ ds = super()
434
+ ds.instance_variable_set(:@sqls, sqls)
435
+ def ds.fetch_rows(sql)
436
+ @sqls << sql
437
+ table = /'(.*)'/.match(sql)[1]
438
+ h = {:column=>"a", :db_type=>table, :max_chars=>nil, :numeric_precision=>nil, :default=>'', :allow_null=>'YES'}
439
+ (h[:column] = h[:table_name] = :x) if sql =~ /BASE TABLE/
440
+ yield h
441
+ end
442
+ ds
443
+ end
444
+ end
445
+ after do
446
+ Sequel.convert_tinyint_to_bool = true
447
+ end
448
+
449
+ specify "should parse the schema correctly for a single table" do
450
+ @db.schema(:x).should == [[:a, {:type=>nil, :db_type=>"x", :max_chars=>nil, :numeric_precision=>nil, :default=>nil, :allow_null=>true}]]
451
+ @sqls.should == ["SELECT column_name AS column, data_type AS db_type, character_maximum_length AS max_chars, numeric_precision, column_default AS default, is_nullable AS allow_null FROM information_schema.tables AS t INNER JOIN information_schema.columns AS c USING (table_catalog, table_schema, table_name) WHERE (c.table_name = 'x')"]
452
+ @db.schema(:x).should == [[:a, {:type=>nil, :db_type=>"x", :max_chars=>nil, :numeric_precision=>nil, :default=>nil, :allow_null=>true}]]
453
+ @sqls.length.should == 1
454
+ @db.schema(:x, :reload=>true).should == [[:a, {:type=>nil, :db_type=>"x", :max_chars=>nil, :numeric_precision=>nil, :default=>nil, :allow_null=>true}]]
455
+ @sqls.length.should == 2
456
+ end
457
+
458
+ specify "should parse the schema correctly for all tables" do
459
+ @db.schema.should == {:x=>[[:x, {:type=>nil, :db_type=>"BASE TABLE", :max_chars=>nil, :numeric_precision=>nil, :default=>nil, :allow_null=>true}]]}
460
+ @sqls.should == ["SELECT column_name AS column, data_type AS db_type, character_maximum_length AS max_chars, numeric_precision, column_default AS default, is_nullable AS allow_null, c.table_name FROM information_schema.tables AS t INNER JOIN information_schema.columns AS c USING (table_catalog, table_schema, table_name) WHERE (t.table_type = 'BASE TABLE')"]
461
+ @db.schema.should == {:x=>[[:x, {:type=>nil, :db_type=>"BASE TABLE", :max_chars=>nil, :numeric_precision=>nil, :default=>nil, :allow_null=>true}]]}
462
+ @sqls.length.should == 1
463
+ @db.schema(nil, :reload=>true).should == {:x=>[[:x, {:type=>nil, :db_type=>"BASE TABLE", :max_chars=>nil, :numeric_precision=>nil, :default=>nil, :allow_null=>true}]]}
464
+ @sqls.length.should == 2
465
+ end
466
+
467
+ specify "should correctly parse all supported data types" do
468
+ @db.schema(:tinyint).first.last[:type].should == :boolean
469
+ Sequel.convert_tinyint_to_bool = false
470
+ @db.schema(:tinyint, :reload=>true).first.last[:type].should == :integer
471
+ @db.schema(:int).first.last[:type].should == :integer
472
+ @db.schema(:integer).first.last[:type].should == :integer
473
+ @db.schema(:bigint).first.last[:type].should == :integer
474
+ @db.schema(:smallint).first.last[:type].should == :integer
475
+ @db.schema(:character).first.last[:type].should == :string
476
+ @db.schema(:"character varying").first.last[:type].should == :string
477
+ @db.schema(:varchar).first.last[:type].should == :string
478
+ @db.schema(:text).first.last[:type].should == :string
479
+ @db.schema(:date).first.last[:type].should == :date
480
+ @db.schema(:datetime).first.last[:type].should == :datetime
481
+ @db.schema(:timestamp).first.last[:type].should == :datetime
482
+ @db.schema(:"timestamp with time zone").first.last[:type].should == :datetime
483
+ @db.schema(:"timestamp without time zone").first.last[:type].should == :datetime
484
+ @db.schema(:time).first.last[:type].should == :time
485
+ @db.schema(:"time with time zone").first.last[:type].should == :time
486
+ @db.schema(:"time without time zone").first.last[:type].should == :time
487
+ @db.schema(:boolean).first.last[:type].should == :boolean
488
+ @db.schema(:real).first.last[:type].should == :float
489
+ @db.schema(:float).first.last[:type].should == :float
490
+ @db.schema(:double).first.last[:type].should == :float
491
+ @db.schema(:"double precision").first.last[:type].should == :float
492
+ @db.schema(:numeric).first.last[:type].should == :decimal
493
+ @db.schema(:decimal).first.last[:type].should == :decimal
494
+ @db.schema(:money).first.last[:type].should == :decimal
495
+ @db.schema(:bytea).first.last[:type].should == :blob
496
+ end
497
+ end