sqlpostgres 1.2.4
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.
- data/Gemfile +8 -0
- data/Gemfile.lock +22 -0
- data/LICENSE.md +23 -0
- data/README.rdoc +59 -0
- data/Rakefile +32 -0
- data/VERSION +1 -0
- data/doc/BUGS +2 -0
- data/doc/examples/README +6 -0
- data/doc/examples/connection.rb +16 -0
- data/doc/examples/connection_auto.rb +22 -0
- data/doc/examples/connection_ctor.rb +18 -0
- data/doc/examples/connection_default.rb +15 -0
- data/doc/examples/connection_exec.rb +18 -0
- data/doc/examples/connection_manual.rb +12 -0
- data/doc/examples/connection_wrapped_new.rb +13 -0
- data/doc/examples/connection_wrapped_open.rb +13 -0
- data/doc/examples/cursor.rb +38 -0
- data/doc/examples/include_module.rb +9 -0
- data/doc/examples/include_module2.rb +12 -0
- data/doc/examples/insert.rb +30 -0
- data/doc/examples/insert2.rb +36 -0
- data/doc/examples/insert_bytea.rb +16 -0
- data/doc/examples/insert_bytea_array.rb +17 -0
- data/doc/examples/insert_default_values.rb +16 -0
- data/doc/examples/insert_insert.rb +16 -0
- data/doc/examples/insert_insert_default.rb +16 -0
- data/doc/examples/insert_insert_select.rb +20 -0
- data/doc/examples/insert_select.rb +20 -0
- data/doc/examples/interval.rb +17 -0
- data/doc/examples/savepoint.rb +38 -0
- data/doc/examples/select.rb +33 -0
- data/doc/examples/select2.rb +36 -0
- data/doc/examples/select_cross_join.rb +18 -0
- data/doc/examples/select_distinct.rb +18 -0
- data/doc/examples/select_distinct_on +19 -0
- data/doc/examples/select_for_update.rb +18 -0
- data/doc/examples/select_from.rb +17 -0
- data/doc/examples/select_from_subselect.rb +20 -0
- data/doc/examples/select_group_by.rb +19 -0
- data/doc/examples/select_having.rb +20 -0
- data/doc/examples/select_join_on.rb +18 -0
- data/doc/examples/select_join_using.rb +18 -0
- data/doc/examples/select_limit.rb +19 -0
- data/doc/examples/select_natural_join.rb +18 -0
- data/doc/examples/select_offset.rb +19 -0
- data/doc/examples/select_order_by.rb +20 -0
- data/doc/examples/select_select.rb +30 -0
- data/doc/examples/select_select_alias.rb +30 -0
- data/doc/examples/select_select_expression.rb +31 -0
- data/doc/examples/select_select_literal.rb +24 -0
- data/doc/examples/select_union.rb +21 -0
- data/doc/examples/select_where_array.rb +18 -0
- data/doc/examples/select_where_in.rb +18 -0
- data/doc/examples/select_where_string.rb +18 -0
- data/doc/examples/simple.rb +34 -0
- data/doc/examples/transaction.rb +30 -0
- data/doc/examples/transaction_abort.rb +30 -0
- data/doc/examples/transaction_commit.rb +34 -0
- data/doc/examples/translate_substitute_values.rb +17 -0
- data/doc/examples/update.rb +32 -0
- data/doc/examples/update2.rb +44 -0
- data/doc/examples/update_only.rb +17 -0
- data/doc/examples/update_set.rb +17 -0
- data/doc/examples/update_set_array.rb +16 -0
- data/doc/examples/update_set_bytea.rb +16 -0
- data/doc/examples/update_set_expression.rb +16 -0
- data/doc/examples/update_set_subselect.rb +20 -0
- data/doc/examples/update_where.rb +17 -0
- data/doc/examples/use_prefix.rb +8 -0
- data/doc/examples/use_prefix2.rb +11 -0
- data/doc/index.html +31 -0
- data/doc/insertexamples.rb +9 -0
- data/doc/makemanual +4 -0
- data/doc/makerdoc +5 -0
- data/doc/manual.dbk +622 -0
- data/lib/sqlpostgres/Connection.rb +198 -0
- data/lib/sqlpostgres/Cursor.rb +157 -0
- data/lib/sqlpostgres/Delete.rb +67 -0
- data/lib/sqlpostgres/Exceptions.rb +15 -0
- data/lib/sqlpostgres/Insert.rb +279 -0
- data/lib/sqlpostgres/NullConnection.rb +22 -0
- data/lib/sqlpostgres/PgBit.rb +73 -0
- data/lib/sqlpostgres/PgBox.rb +37 -0
- data/lib/sqlpostgres/PgCidr.rb +21 -0
- data/lib/sqlpostgres/PgCircle.rb +75 -0
- data/lib/sqlpostgres/PgInet.rb +21 -0
- data/lib/sqlpostgres/PgInterval.rb +208 -0
- data/lib/sqlpostgres/PgLineSegment.rb +37 -0
- data/lib/sqlpostgres/PgMacAddr.rb +21 -0
- data/lib/sqlpostgres/PgPath.rb +64 -0
- data/lib/sqlpostgres/PgPoint.rb +65 -0
- data/lib/sqlpostgres/PgPolygon.rb +56 -0
- data/lib/sqlpostgres/PgTime.rb +77 -0
- data/lib/sqlpostgres/PgTimeWithTimeZone.rb +98 -0
- data/lib/sqlpostgres/PgTimestamp.rb +93 -0
- data/lib/sqlpostgres/PgTwoPoints.rb +54 -0
- data/lib/sqlpostgres/PgType.rb +34 -0
- data/lib/sqlpostgres/PgWrapper.rb +41 -0
- data/lib/sqlpostgres/Savepoint.rb +98 -0
- data/lib/sqlpostgres/Select.rb +855 -0
- data/lib/sqlpostgres/Transaction.rb +120 -0
- data/lib/sqlpostgres/Translate.rb +436 -0
- data/lib/sqlpostgres/Update.rb +188 -0
- data/lib/sqlpostgres.rb +67 -0
- data/test/Assert.rb +72 -0
- data/test/Connection.test.rb +246 -0
- data/test/Cursor.test.rb +190 -0
- data/test/Delete.test.rb +68 -0
- data/test/Insert.test.rb +123 -0
- data/test/MockPGconn.rb +62 -0
- data/test/NullConnection.test.rb +32 -0
- data/test/PgBit.test.rb +98 -0
- data/test/PgBox.test.rb +108 -0
- data/test/PgCidr.test.rb +61 -0
- data/test/PgCircle.test.rb +107 -0
- data/test/PgInet.test.rb +61 -0
- data/test/PgInterval.test.rb +180 -0
- data/test/PgLineSegment.test.rb +108 -0
- data/test/PgMacAddr.test.rb +61 -0
- data/test/PgPath.test.rb +106 -0
- data/test/PgPoint.test.rb +100 -0
- data/test/PgPolygon.test.rb +95 -0
- data/test/PgTime.test.rb +120 -0
- data/test/PgTimeWithTimeZone.test.rb +117 -0
- data/test/PgTimestamp.test.rb +134 -0
- data/test/RandomThings.rb +25 -0
- data/test/Savepoint.test.rb +286 -0
- data/test/Select.test.rb +930 -0
- data/test/Test.rb +62 -0
- data/test/TestConfig.rb +21 -0
- data/test/TestSetup.rb +13 -0
- data/test/TestUtil.rb +92 -0
- data/test/Transaction.test.rb +275 -0
- data/test/Translate.test.rb +354 -0
- data/test/Update.test.rb +227 -0
- data/test/roundtrip.test.rb +565 -0
- data/test/test +34 -0
- data/tools/exampleinserter/ExampleInserter.rb +177 -0
- data/tools/rdoc/ChangeLog +796 -0
- data/tools/rdoc/EXAMPLE.rb +48 -0
- data/tools/rdoc/MANIFEST +58 -0
- data/tools/rdoc/Makefile +27 -0
- data/tools/rdoc/NEW_FEATURES +226 -0
- data/tools/rdoc/README +390 -0
- data/tools/rdoc/ToDo +6 -0
- data/tools/rdoc/contrib/Index +6 -0
- data/tools/rdoc/contrib/xslfo/ChangeLog +181 -0
- data/tools/rdoc/contrib/xslfo/README +106 -0
- data/tools/rdoc/contrib/xslfo/TODO +10 -0
- data/tools/rdoc/contrib/xslfo/convert.xsl +151 -0
- data/tools/rdoc/contrib/xslfo/demo/README +21 -0
- data/tools/rdoc/contrib/xslfo/demo/rdocfo +99 -0
- data/tools/rdoc/contrib/xslfo/fcm.xsl +54 -0
- data/tools/rdoc/contrib/xslfo/files.xsl +62 -0
- data/tools/rdoc/contrib/xslfo/labeled-lists.xsl +66 -0
- data/tools/rdoc/contrib/xslfo/lists.xsl +44 -0
- data/tools/rdoc/contrib/xslfo/modules.xsl +152 -0
- data/tools/rdoc/contrib/xslfo/rdoc.xsl +75 -0
- data/tools/rdoc/contrib/xslfo/source.xsl +66 -0
- data/tools/rdoc/contrib/xslfo/styles.xsl +69 -0
- data/tools/rdoc/contrib/xslfo/tables.xsl +67 -0
- data/tools/rdoc/contrib/xslfo/utils.xsl +21 -0
- data/tools/rdoc/debian/changelog +33 -0
- data/tools/rdoc/debian/compat +1 -0
- data/tools/rdoc/debian/control +20 -0
- data/tools/rdoc/debian/copyright +10 -0
- data/tools/rdoc/debian/dirs +2 -0
- data/tools/rdoc/debian/docs +2 -0
- data/tools/rdoc/debian/rdoc.1 +252 -0
- data/tools/rdoc/debian/rdoc.manpages +1 -0
- data/tools/rdoc/debian/rdoc.pod +149 -0
- data/tools/rdoc/debian/rules +9 -0
- data/tools/rdoc/dot/dot.rb +255 -0
- data/tools/rdoc/etc/rdoc.dtd +203 -0
- data/tools/rdoc/install.rb +137 -0
- data/tools/rdoc/markup/install.rb +43 -0
- data/tools/rdoc/markup/sample/sample.rb +42 -0
- data/tools/rdoc/markup/simple_markup/fragments.rb +323 -0
- data/tools/rdoc/markup/simple_markup/inline.rb +348 -0
- data/tools/rdoc/markup/simple_markup/lines.rb +147 -0
- data/tools/rdoc/markup/simple_markup/preprocess.rb +68 -0
- data/tools/rdoc/markup/simple_markup/to_html.rb +281 -0
- data/tools/rdoc/markup/simple_markup.rb +474 -0
- data/tools/rdoc/markup/test/AllTests.rb +2 -0
- data/tools/rdoc/markup/test/TestInline.rb +151 -0
- data/tools/rdoc/markup/test/TestParse.rb +411 -0
- data/tools/rdoc/rdoc/code_objects.rb +536 -0
- data/tools/rdoc/rdoc/diagram.rb +331 -0
- data/tools/rdoc/rdoc/generators/chm_generator.rb +112 -0
- data/tools/rdoc/rdoc/generators/html_generator.rb +1268 -0
- data/tools/rdoc/rdoc/generators/template/chm/chm.rb +86 -0
- data/tools/rdoc/rdoc/generators/template/html/html.rb +705 -0
- data/tools/rdoc/rdoc/generators/template/html/kilmer.rb +377 -0
- data/tools/rdoc/rdoc/generators/template/xml/rdf.rb +110 -0
- data/tools/rdoc/rdoc/generators/template/xml/xml.rb +110 -0
- data/tools/rdoc/rdoc/generators/xml_generator.rb +130 -0
- data/tools/rdoc/rdoc/options.rb +451 -0
- data/tools/rdoc/rdoc/parsers/parse_c.rb +287 -0
- data/tools/rdoc/rdoc/parsers/parse_f95.rb +118 -0
- data/tools/rdoc/rdoc/parsers/parse_rb.rb +2311 -0
- data/tools/rdoc/rdoc/parsers/parse_simple.rb +37 -0
- data/tools/rdoc/rdoc/parsers/parserfactory.rb +75 -0
- data/tools/rdoc/rdoc/rdoc.rb +219 -0
- data/tools/rdoc/rdoc/template.rb +234 -0
- data/tools/rdoc/rdoc/tokenstream.rb +25 -0
- data/tools/rdoc/rdoc.rb +9 -0
- metadata +291 -0
data/test/Select.test.rb
ADDED
|
@@ -0,0 +1,930 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
$:.unshift(File.dirname(__FILE__))
|
|
6
|
+
require 'TestSetup'
|
|
7
|
+
require 'date'
|
|
8
|
+
|
|
9
|
+
# Much of Select is tested in the "roundtrip" test.
|
|
10
|
+
|
|
11
|
+
class SelectTest < Test
|
|
12
|
+
|
|
13
|
+
include SqlPostgres
|
|
14
|
+
include TestUtil
|
|
15
|
+
|
|
16
|
+
def test
|
|
17
|
+
makeTestConnection do |connection|
|
|
18
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
19
|
+
select = Select.new(connection)
|
|
20
|
+
select.select('i')
|
|
21
|
+
select.from(table1)
|
|
22
|
+
select.order_by('i')
|
|
23
|
+
assertEquals(select.statement, "select i from #{table1} order by i")
|
|
24
|
+
assertEquals(select.exec, [])
|
|
25
|
+
connection.exec("insert into #{table1} (i) values (1)")
|
|
26
|
+
assertEquals(select.exec, [{'i' => 1}])
|
|
27
|
+
connection.exec("insert into #{table1} (i) values (2)")
|
|
28
|
+
assertEquals(select.exec, [{'i' => 1}, {'i' => 2}])
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def testDefaultConnection
|
|
33
|
+
makeTestConnection do |connection|
|
|
34
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
35
|
+
connection.exec("insert into #{table1} values (1)")
|
|
36
|
+
setDefaultConnection(connection) do
|
|
37
|
+
select = Select.new(connection)
|
|
38
|
+
select.select('i')
|
|
39
|
+
select.from(table1)
|
|
40
|
+
assertEquals(select.exec, [{'i'=>1}])
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def testGiveConnectionToExec
|
|
46
|
+
makeTestConnection do |connection|
|
|
47
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
48
|
+
connection.exec("insert into #{table1} values (1)")
|
|
49
|
+
setDefaultConnection(connection) do
|
|
50
|
+
select = Select.new
|
|
51
|
+
select.select('i')
|
|
52
|
+
select.from(table1)
|
|
53
|
+
assertEquals(select.exec(connection), [{'i'=>1}])
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def testOrderBy
|
|
59
|
+
makeTestConnection do |connection|
|
|
60
|
+
connection.exec("create temporary table #{table1} (i int, j int, k int)")
|
|
61
|
+
connection.exec("insert into #{table1} values (0, 0, 0)")
|
|
62
|
+
connection.exec("insert into #{table1} values (0, 0, 1)")
|
|
63
|
+
connection.exec("insert into #{table1} values (0, 1, 0)")
|
|
64
|
+
connection.exec("insert into #{table1} values (0, 1, 1)")
|
|
65
|
+
connection.exec("insert into #{table1} values (1, 0, 0)")
|
|
66
|
+
connection.exec("insert into #{table1} values (1, 0, 1)")
|
|
67
|
+
connection.exec("insert into #{table1} values (1, 1, 0)")
|
|
68
|
+
connection.exec("insert into #{table1} values (1, 1, 1)")
|
|
69
|
+
select = Select.new(connection)
|
|
70
|
+
select.select("i")
|
|
71
|
+
select.select("j")
|
|
72
|
+
select.select("k")
|
|
73
|
+
select.from(table1)
|
|
74
|
+
select.order_by('i')
|
|
75
|
+
select.order_by('j', 'asc')
|
|
76
|
+
select.order_by('k', 'desc')
|
|
77
|
+
assertEquals(select.statement,
|
|
78
|
+
"select i, j, k from #{table1} order by i, j asc, k desc")
|
|
79
|
+
assertEquals(select.exec, [
|
|
80
|
+
{'i'=>0, 'j'=>0, 'k'=>1},
|
|
81
|
+
{'i'=>0, 'j'=>0, 'k'=>0},
|
|
82
|
+
{'i'=>0, 'j'=>1, 'k'=>1},
|
|
83
|
+
{'i'=>0, 'j'=>1, 'k'=>0},
|
|
84
|
+
{'i'=>1, 'j'=>0, 'k'=>1},
|
|
85
|
+
{'i'=>1, 'j'=>0, 'k'=>0},
|
|
86
|
+
{'i'=>1, 'j'=>1, 'k'=>1},
|
|
87
|
+
{'i'=>1, 'j'=>1, 'k'=>0},
|
|
88
|
+
])
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def testOrderBy_ArbitraryExpression
|
|
93
|
+
makeTestConnection do |connection|
|
|
94
|
+
connection.exec("create temporary table #{table1} (t text)")
|
|
95
|
+
connection.exec("insert into #{table1} values ('aaa')")
|
|
96
|
+
connection.exec("insert into #{table1} values ('bb')")
|
|
97
|
+
connection.exec("insert into #{table1} values ('c')")
|
|
98
|
+
select = Select.new(connection)
|
|
99
|
+
select.select('t')
|
|
100
|
+
select.from(table1)
|
|
101
|
+
select.order_by('char_length(t)')
|
|
102
|
+
assertEquals(select.statement,
|
|
103
|
+
"select t from #{table1} order by char_length(t)")
|
|
104
|
+
assertEquals(select.exec, [{'t'=>'c'}, {'t'=>'bb'}, {'t'=>'aaa'}])
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def testOrderBy_ExpressionWithSubstitution
|
|
109
|
+
makeTestConnection do |connection|
|
|
110
|
+
connection.exec("create temporary table #{table1} (t text)")
|
|
111
|
+
connection.exec("insert into #{table1} values ('a')")
|
|
112
|
+
connection.exec("insert into #{table1} values ('b')")
|
|
113
|
+
connection.exec("insert into #{table1} values ('c')")
|
|
114
|
+
select = Select.new(connection)
|
|
115
|
+
select.select('t')
|
|
116
|
+
select.from(table1)
|
|
117
|
+
select.order_by(['case when t = %s then %s else t end', 'b', '0'])
|
|
118
|
+
assertEquals(select.statement,
|
|
119
|
+
"select t from #{table1} order by "\
|
|
120
|
+
"case when t = E'b' then E'0' else t end")
|
|
121
|
+
assertEquals(select.exec, [{'t'=>'b'}, {'t'=>'a'}, {'t'=>'c'}])
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def testSelectInteger_Expression
|
|
126
|
+
makeTestConnection do |connection|
|
|
127
|
+
select = Select.new(connection)
|
|
128
|
+
select.select(["%s * 2", 2], 'double')
|
|
129
|
+
assertEquals(select.statement, "select 2 * 2 as double")
|
|
130
|
+
assertEquals(select.exec, [{'double'=>4}])
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def testSelectFloat_Expression
|
|
135
|
+
makeTestConnection do |connection|
|
|
136
|
+
select = Select.new(connection)
|
|
137
|
+
select.select(["%s * 2", 1.414], 'double')
|
|
138
|
+
assertEquals(select.statement, "select 1.414 * 2 as double")
|
|
139
|
+
assertEquals(select.exec, [{'double'=>2.828}])
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def testSelectString_Expression
|
|
144
|
+
makeTestConnection do |connection|
|
|
145
|
+
select = Select.new(connection)
|
|
146
|
+
select.select(["%s || %s", "Fred's", " Place"], 'title')
|
|
147
|
+
assertEquals(select.statement,
|
|
148
|
+
%q"select E'Fred\\047s' || E' Place' as title")
|
|
149
|
+
assertEquals(select.exec, [{'title'=>"Fred's Place"}])
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def testSelectTime_Expression
|
|
154
|
+
makeTestConnection do |connection|
|
|
155
|
+
now = Time.local(2001, 1, 1)
|
|
156
|
+
select = Select.new(connection)
|
|
157
|
+
select.select(
|
|
158
|
+
[
|
|
159
|
+
"%s + %s",
|
|
160
|
+
PgTime.new(12, 0, 0),
|
|
161
|
+
PgInterval.new('hours'=>1)
|
|
162
|
+
],
|
|
163
|
+
'later')
|
|
164
|
+
assertEquals(select.exec, [{'later'=>PgTime.new(13, 0, 0)}])
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def testSelectBoolean_Expression
|
|
169
|
+
makeTestConnection do |connection|
|
|
170
|
+
select = Select.new(connection)
|
|
171
|
+
select.select(["not %s", false], 'opposite')
|
|
172
|
+
assertEquals(select.statement, "select not false as opposite")
|
|
173
|
+
assertEquals(select.exec, [{'opposite'=>true}])
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_select_literal
|
|
178
|
+
values = [
|
|
179
|
+
"Fool's errand",
|
|
180
|
+
1,
|
|
181
|
+
-9223372036854775808,
|
|
182
|
+
+9223372036854775807,
|
|
183
|
+
1.414,
|
|
184
|
+
1e290,
|
|
185
|
+
true,
|
|
186
|
+
false,
|
|
187
|
+
PgTime.new(23, 59, 59),
|
|
188
|
+
nil,
|
|
189
|
+
PgInterval.new('days'=>1),
|
|
190
|
+
PgTime.new(12, 0, 0),
|
|
191
|
+
PgTimeWithTimeZone.new(12, 0, 0, -8, 0),
|
|
192
|
+
PgTimestamp.new(2001, 1, 1, 12, 0, 0),
|
|
193
|
+
PgPoint.new(1, 2),
|
|
194
|
+
PgLineSegment.new(0, 1, 2, 3),
|
|
195
|
+
PgBox.new(3, 4, 1, 2),
|
|
196
|
+
PgPath.new(true, PgPoint.new(1, 2), PgPoint.new(3, 4)),
|
|
197
|
+
PgPolygon.new(PgPoint.new(1, 2), PgPoint.new(3, 4)),
|
|
198
|
+
PgCircle.new(1, 2, 3),
|
|
199
|
+
PgBit.new("010101"),
|
|
200
|
+
PgInet.new("1.2.0.0/16"),
|
|
201
|
+
PgCidr.new("1.2.3.0/24"),
|
|
202
|
+
PgMacAddr.new("08:00:2b:01:02:03"),
|
|
203
|
+
]
|
|
204
|
+
makeTestConnection do |connection|
|
|
205
|
+
for value in values
|
|
206
|
+
assertInfo("For value #{value.inspect}") do
|
|
207
|
+
|
|
208
|
+
select = Select.new(connection)
|
|
209
|
+
select.select_literal(value)
|
|
210
|
+
assertEquals(select.statement,
|
|
211
|
+
"select #{Translate.escape_sql(value)}")
|
|
212
|
+
|
|
213
|
+
select = Select.new(connection)
|
|
214
|
+
select.select_literal(value, 'v')
|
|
215
|
+
assertEquals(select.exec, [{'v'=>value}])
|
|
216
|
+
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def testSelectExpression
|
|
223
|
+
makeTestConnection do |connection|
|
|
224
|
+
select = Select.new(connection)
|
|
225
|
+
select.select(["%s || %s || %s", "Cat", " ", "Dog"], 'animal')
|
|
226
|
+
assertEquals(select.statement, "select E'Cat' || E' ' || E'Dog' as animal")
|
|
227
|
+
assertEquals(select.exec, [{'animal'=>'Cat Dog'}])
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def testUserConversion
|
|
232
|
+
makeTestConnection do |connection|
|
|
233
|
+
select = Select.new(connection)
|
|
234
|
+
select.select(["%s", "abc"], 'letters') do |s|
|
|
235
|
+
s.scan(/./)
|
|
236
|
+
end
|
|
237
|
+
assertEquals(select.exec, [{'letters'=>['a', 'b', 'c']}])
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def testWhere
|
|
242
|
+
makeTestConnection do |connection|
|
|
243
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
244
|
+
connection.exec("insert into #{table1} values (1)")
|
|
245
|
+
connection.exec("insert into #{table1} values (2)")
|
|
246
|
+
connection.exec("insert into #{table1} values (3)")
|
|
247
|
+
select = Select.new(connection)
|
|
248
|
+
select.select('i')
|
|
249
|
+
select.from(table1)
|
|
250
|
+
select.where("i = 1")
|
|
251
|
+
assertEquals(select.statement, "select i from #{table1} where i = 1")
|
|
252
|
+
assertEquals(select.exec, [{'i'=>1}])
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def testWhere_Multiple
|
|
257
|
+
makeTestConnection do |connection|
|
|
258
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
259
|
+
connection.exec("insert into #{table1} values (1)")
|
|
260
|
+
connection.exec("insert into #{table1} values (2)")
|
|
261
|
+
connection.exec("insert into #{table1} values (3)")
|
|
262
|
+
select = Select.new(connection)
|
|
263
|
+
select.select('i')
|
|
264
|
+
select.from(table1)
|
|
265
|
+
select.where("i > 1")
|
|
266
|
+
select.where("i < 3")
|
|
267
|
+
assertEquals(select.statement,
|
|
268
|
+
"select i from #{table1} where i > 1 and i < 3")
|
|
269
|
+
assertEquals(select.exec, [{'i'=>2}])
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def testWhere_WithValues
|
|
274
|
+
makeTestConnection do |connection|
|
|
275
|
+
connection.exec("create temporary table #{table1} (t text)")
|
|
276
|
+
connection.exec("insert into #{table1} values ('bar')")
|
|
277
|
+
connection.exec("insert into #{table1} values ('baz')")
|
|
278
|
+
select = Select.new(connection)
|
|
279
|
+
select.select('t')
|
|
280
|
+
select.from(table1)
|
|
281
|
+
select.where(["t = %s", 'bar'])
|
|
282
|
+
assertEquals(select.statement, "select t from #{table1} where t = E'bar'")
|
|
283
|
+
assertEquals(select.exec, [{'t'=>'bar'}])
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def testSelectSubselect
|
|
288
|
+
makeTestConnection do |connection|
|
|
289
|
+
time = PgTime.new(12, 0, 0)
|
|
290
|
+
select1 = Select.new
|
|
291
|
+
select1.select_literal(1)
|
|
292
|
+
select2 = Select.new
|
|
293
|
+
select2.select_literal(time)
|
|
294
|
+
select3 = Select.new(connection)
|
|
295
|
+
select3.select(select1, 'i')
|
|
296
|
+
select3.select(select2, 't')
|
|
297
|
+
assertEquals(select3.exec, [{'i'=>1, 't'=>time}])
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def testFromAlias
|
|
302
|
+
select = Select.new
|
|
303
|
+
select.select('i')
|
|
304
|
+
select.from('foo', 'bar')
|
|
305
|
+
assertEquals(select.statement, "select i from foo as bar")
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def testFromSubselect
|
|
309
|
+
makeTestConnection do |connection|
|
|
310
|
+
time = Time.now
|
|
311
|
+
select1 = Select.new
|
|
312
|
+
select1.select_literal(1, 'i')
|
|
313
|
+
select2 = Select.new(connection)
|
|
314
|
+
select2.select('i')
|
|
315
|
+
select2.from(select1, 'foo')
|
|
316
|
+
assertEquals(select2.statement, "select i from (select 1 as i) as foo")
|
|
317
|
+
assertEquals(select2.exec, [{'i'=>1}])
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def testNoConnection
|
|
322
|
+
select = Select.new
|
|
323
|
+
assertException(NoConnection) do
|
|
324
|
+
select.exec
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def testGroupBy
|
|
329
|
+
makeTestConnection do |connection|
|
|
330
|
+
connection.exec("create temporary table #{table1} (i int, j int)")
|
|
331
|
+
1.times do connection.exec("insert into #{table1} values (0, 0)") end
|
|
332
|
+
2.times do connection.exec("insert into #{table1} values (0, 1)") end
|
|
333
|
+
3.times do connection.exec("insert into #{table1} values (1, 0)") end
|
|
334
|
+
4.times do connection.exec("insert into #{table1} values (1, 1)") end
|
|
335
|
+
select = Select.new(connection)
|
|
336
|
+
select.select('i')
|
|
337
|
+
select.select('j')
|
|
338
|
+
select.select('count(*)', 'count')
|
|
339
|
+
select.from(table1)
|
|
340
|
+
select.group_by('i')
|
|
341
|
+
select.group_by('j')
|
|
342
|
+
select.order_by('i')
|
|
343
|
+
select.order_by('j')
|
|
344
|
+
assertEquals(select.statement,
|
|
345
|
+
"select i, j, count(*) as count from #{table1} "\
|
|
346
|
+
"group by i, j order by i, j")
|
|
347
|
+
assertEquals(select.exec,
|
|
348
|
+
[
|
|
349
|
+
{"i"=>0, "j"=>0, "count"=>1},
|
|
350
|
+
{"i"=>0, "j"=>1, "count"=>2},
|
|
351
|
+
{"i"=>1, "j"=>0, "count"=>3},
|
|
352
|
+
{"i"=>1, "j"=>1, "count"=>4}
|
|
353
|
+
])
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def testGroupBy_Expression
|
|
358
|
+
makeTestConnection do |connection|
|
|
359
|
+
connection.exec("create temporary table #{table1} (t text)")
|
|
360
|
+
connection.exec("insert into #{table1} values ('alpha')")
|
|
361
|
+
connection.exec("insert into #{table1} values ('beta')")
|
|
362
|
+
connection.exec("insert into #{table1} values ('gamma')")
|
|
363
|
+
select = Select.new(connection)
|
|
364
|
+
select.select('count(*)', 'count')
|
|
365
|
+
select.from(table1)
|
|
366
|
+
select.group_by(['case t when %s then 0 else 1 end', 'alpha'])
|
|
367
|
+
select.order_by('count')
|
|
368
|
+
assertEquals(select.exec, [{'count'=>1}, {'count'=>2}])
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def testHaving
|
|
373
|
+
makeTestConnection do |connection|
|
|
374
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
375
|
+
connection.exec("insert into #{table1} values (0)")
|
|
376
|
+
connection.exec("insert into #{table1} values (1)")
|
|
377
|
+
connection.exec("insert into #{table1} values (1)")
|
|
378
|
+
connection.exec("insert into #{table1} values (2)")
|
|
379
|
+
connection.exec("insert into #{table1} values (2)")
|
|
380
|
+
connection.exec("insert into #{table1} values (2)")
|
|
381
|
+
select = Select.new(connection)
|
|
382
|
+
select.select('count(*)', 'count')
|
|
383
|
+
select.from(table1)
|
|
384
|
+
select.group_by('i')
|
|
385
|
+
select.having('count(*) > 1')
|
|
386
|
+
select.having('count(*) < 3')
|
|
387
|
+
assertEquals(select.exec, [{'count'=>2}])
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def testHaving_Expression
|
|
392
|
+
makeTestConnection do |connection|
|
|
393
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
394
|
+
connection.exec("insert into #{table1} values (0)")
|
|
395
|
+
connection.exec("insert into #{table1} values (1)")
|
|
396
|
+
connection.exec("insert into #{table1} values (1)")
|
|
397
|
+
select = Select.new(connection)
|
|
398
|
+
select.select('count(*)', 'count')
|
|
399
|
+
select.from(table1)
|
|
400
|
+
select.group_by('i')
|
|
401
|
+
select.having(['count(*) > %s', 1])
|
|
402
|
+
assertEquals(select.exec, [{'count'=>2}])
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def testCrossJoin
|
|
407
|
+
makeTestConnection do |connection|
|
|
408
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
409
|
+
connection.exec("create temporary table #{table2} (i int)")
|
|
410
|
+
connection.exec("insert into #{table1} (i) values (1)")
|
|
411
|
+
connection.exec("insert into #{table1} (i) values (2)")
|
|
412
|
+
connection.exec("insert into #{table2} (i) values (3)")
|
|
413
|
+
connection.exec("insert into #{table2} (i) values (4)")
|
|
414
|
+
select = Select.new(connection)
|
|
415
|
+
select.select("#{table1}.i", "i1")
|
|
416
|
+
select.select("#{table2}.i", "i2")
|
|
417
|
+
select.from(table1)
|
|
418
|
+
select.cross_join(table2)
|
|
419
|
+
select.order_by('i1')
|
|
420
|
+
select.order_by('i2')
|
|
421
|
+
assertEquals(select.statement,
|
|
422
|
+
"select #{table1}.i as i1, #{table2}.i as i2 "\
|
|
423
|
+
"from #{table1} cross join #{table2} "\
|
|
424
|
+
"order by i1, i2")
|
|
425
|
+
assertEquals(select.exec, [
|
|
426
|
+
{"i1"=>1, "i2"=>3},
|
|
427
|
+
{"i1"=>1, "i2"=>4},
|
|
428
|
+
{"i1"=>2, "i2"=>3},
|
|
429
|
+
{"i1"=>2, "i2"=>4}
|
|
430
|
+
])
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def testNaturalJoin
|
|
435
|
+
makeTestConnection do |connection|
|
|
436
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
437
|
+
connection.exec("create temporary table #{table2} (i int)")
|
|
438
|
+
connection.exec("insert into #{table1} (i) values (1)")
|
|
439
|
+
connection.exec("insert into #{table1} (i) values (2)")
|
|
440
|
+
connection.exec("insert into #{table2} (i) values (2)")
|
|
441
|
+
connection.exec("insert into #{table2} (i) values (3)")
|
|
442
|
+
select = Select.new(connection)
|
|
443
|
+
select.select("i")
|
|
444
|
+
select.from(table1)
|
|
445
|
+
select.natural_join(table2)
|
|
446
|
+
assertEquals(select.statement,
|
|
447
|
+
"select i from #{table1} natural join #{table2}")
|
|
448
|
+
assertEquals(select.exec, [{'i'=>2}])
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def testNaturalJoin_ThreeTables
|
|
453
|
+
makeTestConnection do |connection|
|
|
454
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
455
|
+
connection.exec("create temporary table #{table2} (i int)")
|
|
456
|
+
connection.exec("create temporary table #{table3} (i int)")
|
|
457
|
+
connection.exec("insert into #{table1} (i) values (1)")
|
|
458
|
+
connection.exec("insert into #{table1} (i) values (2)")
|
|
459
|
+
connection.exec("insert into #{table1} (i) values (3)")
|
|
460
|
+
connection.exec("insert into #{table2} (i) values (2)")
|
|
461
|
+
connection.exec("insert into #{table2} (i) values (3)")
|
|
462
|
+
connection.exec("insert into #{table3} (i) values (1)")
|
|
463
|
+
connection.exec("insert into #{table3} (i) values (2)")
|
|
464
|
+
select = Select.new(connection)
|
|
465
|
+
select.select("i")
|
|
466
|
+
select.from(table1)
|
|
467
|
+
select.natural_join(table2)
|
|
468
|
+
select.natural_join(table3)
|
|
469
|
+
assertEquals(select.statement,
|
|
470
|
+
"select i from #{table1} natural join #{table2} "\
|
|
471
|
+
"natural join #{table3}")
|
|
472
|
+
assertEquals(select.exec, [{'i'=>2}])
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
def testJoinUsing
|
|
477
|
+
testCases = [
|
|
478
|
+
[
|
|
479
|
+
"inner",
|
|
480
|
+
[
|
|
481
|
+
{'i1'=>2, 'i2'=>2},
|
|
482
|
+
]
|
|
483
|
+
],
|
|
484
|
+
[
|
|
485
|
+
"left outer",
|
|
486
|
+
[
|
|
487
|
+
{'i1'=>1, 'i2'=>nil},
|
|
488
|
+
{'i1'=>2, 'i2'=>2},
|
|
489
|
+
]
|
|
490
|
+
],
|
|
491
|
+
[
|
|
492
|
+
"right outer",
|
|
493
|
+
[
|
|
494
|
+
{'i1'=>2, 'i2'=>2},
|
|
495
|
+
{'i1'=>nil, 'i2'=>3},
|
|
496
|
+
]
|
|
497
|
+
],
|
|
498
|
+
[
|
|
499
|
+
"full outer",
|
|
500
|
+
[
|
|
501
|
+
{'i1'=>1, 'i2'=>nil},
|
|
502
|
+
{'i1'=>2, 'i2'=>2},
|
|
503
|
+
{'i1'=>nil, 'i2'=>3},
|
|
504
|
+
]
|
|
505
|
+
],
|
|
506
|
+
]
|
|
507
|
+
for joinType, result in testCases
|
|
508
|
+
assertInfo("For joinType=#{joinType.inspect}") do
|
|
509
|
+
makeTestConnection do |connection|
|
|
510
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
511
|
+
connection.exec("create temporary table #{table2} (i int)")
|
|
512
|
+
connection.exec("insert into #{table1} (i) values (1)")
|
|
513
|
+
connection.exec("insert into #{table1} (i) values (2)")
|
|
514
|
+
connection.exec("insert into #{table2} (i) values (2)")
|
|
515
|
+
connection.exec("insert into #{table2} (i) values (3)")
|
|
516
|
+
select = Select.new(connection)
|
|
517
|
+
select.select("#{table1}.i", 'i1')
|
|
518
|
+
select.select("#{table2}.i", 'i2')
|
|
519
|
+
select.from(table1)
|
|
520
|
+
select.join_using(joinType, table2, 'i')
|
|
521
|
+
select.order_by('i1')
|
|
522
|
+
select.order_by('i2')
|
|
523
|
+
assertEquals(select.statement,
|
|
524
|
+
"select #{table1}.i as i1, #{table2}.i as i2 "\
|
|
525
|
+
"from #{table1} #{joinType} join #{table2} "\
|
|
526
|
+
"using (i) order by i1, i2")
|
|
527
|
+
assertEquals(select.exec, result)
|
|
528
|
+
end
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
def testJoinUsing_MultipleColumns
|
|
534
|
+
makeTestConnection do |connection|
|
|
535
|
+
connection.exec("create temporary table #{table1} (i int, j int)")
|
|
536
|
+
connection.exec("create temporary table #{table2} (i int, j int)")
|
|
537
|
+
connection.exec("insert into #{table1} (i, j) values (1, 1)")
|
|
538
|
+
connection.exec("insert into #{table1} (i, j) values (1, 2)")
|
|
539
|
+
connection.exec("insert into #{table2} (i, j) values (1, 2)")
|
|
540
|
+
connection.exec("insert into #{table2} (i, j) values (2, 2)")
|
|
541
|
+
select = Select.new(connection)
|
|
542
|
+
select.select("i")
|
|
543
|
+
select.select("j")
|
|
544
|
+
select.from(table1)
|
|
545
|
+
select.join_using('inner', table2, 'i', 'j')
|
|
546
|
+
assertEquals(select.statement,
|
|
547
|
+
"select i, j from #{table1} inner join #{table2} "\
|
|
548
|
+
"using (i, j)")
|
|
549
|
+
assertEquals(select.exec, [{'i'=>1, 'j'=>2}])
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
def testJoinOn
|
|
554
|
+
testCases = [
|
|
555
|
+
[
|
|
556
|
+
"inner",
|
|
557
|
+
[
|
|
558
|
+
{"i"=>2, "j"=>2}
|
|
559
|
+
]
|
|
560
|
+
],
|
|
561
|
+
[
|
|
562
|
+
"left outer",
|
|
563
|
+
[
|
|
564
|
+
{"i"=>1, "j"=>nil},
|
|
565
|
+
{"i"=>2, 'j'=>2}
|
|
566
|
+
]
|
|
567
|
+
],
|
|
568
|
+
[
|
|
569
|
+
"right outer",
|
|
570
|
+
[
|
|
571
|
+
{"i"=>2, "j"=>2},
|
|
572
|
+
{"i"=>nil, 'j'=>3}
|
|
573
|
+
]
|
|
574
|
+
],
|
|
575
|
+
[
|
|
576
|
+
"full outer",
|
|
577
|
+
[
|
|
578
|
+
{"i"=>1, "j"=>nil},
|
|
579
|
+
{"i"=>2, "j"=>2},
|
|
580
|
+
{"i"=>nil, 'j'=>3}
|
|
581
|
+
]
|
|
582
|
+
],
|
|
583
|
+
]
|
|
584
|
+
makeTestConnection do |connection|
|
|
585
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
586
|
+
connection.exec("create temporary table #{table2} (j int)")
|
|
587
|
+
connection.exec("insert into #{table1} (i) values (1)")
|
|
588
|
+
connection.exec("insert into #{table1} (i) values (2)")
|
|
589
|
+
connection.exec("insert into #{table2} (j) values (2)")
|
|
590
|
+
connection.exec("insert into #{table2} (j) values (3)")
|
|
591
|
+
for joinType, result in testCases
|
|
592
|
+
assertInfo("for joinType=#{joinType.inspect}") do
|
|
593
|
+
select = Select.new(connection)
|
|
594
|
+
select.select("i")
|
|
595
|
+
select.select("j")
|
|
596
|
+
select.from(table1)
|
|
597
|
+
select.join_on(joinType, table2, 'i = j')
|
|
598
|
+
select.order_by('i')
|
|
599
|
+
select.order_by('j')
|
|
600
|
+
assertEquals(select.statement,
|
|
601
|
+
"select i, j from #{table1} "\
|
|
602
|
+
"#{joinType} join #{table2} on (i = j) "\
|
|
603
|
+
"order by i, j")
|
|
604
|
+
assertEquals(select.exec, result)
|
|
605
|
+
end
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
def testJoinOn_SubstituteValues
|
|
611
|
+
makeTestConnection do |connection|
|
|
612
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
613
|
+
connection.exec("create temporary table #{table2} (j int)")
|
|
614
|
+
connection.exec("insert into #{table1} (i) values (1)")
|
|
615
|
+
connection.exec("insert into #{table1} (i) values (2)")
|
|
616
|
+
connection.exec("insert into #{table2} (j) values (1)")
|
|
617
|
+
connection.exec("insert into #{table2} (j) values (2)")
|
|
618
|
+
connection.exec("insert into #{table2} (j) values (3)")
|
|
619
|
+
select = Select.new(connection)
|
|
620
|
+
select.select("i")
|
|
621
|
+
select.select("j")
|
|
622
|
+
select.from(table1)
|
|
623
|
+
select.join_on('inner', table2, ['i = j and i > %s', 1])
|
|
624
|
+
assertEquals(select.statement,
|
|
625
|
+
"select i, j from #{table1} "\
|
|
626
|
+
"inner join #{table2} on (i = j and i > 1)")
|
|
627
|
+
assertEquals(select.exec, [{'i'=>2, 'j'=>2}])
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
def testLimit
|
|
632
|
+
makeTestConnection do |connection|
|
|
633
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
634
|
+
connection.exec("insert into #{table1} values (1)")
|
|
635
|
+
connection.exec("insert into #{table1} values (2)")
|
|
636
|
+
connection.exec("insert into #{table1} values (3)")
|
|
637
|
+
select = Select.new(connection)
|
|
638
|
+
select.select('i')
|
|
639
|
+
select.from(table1)
|
|
640
|
+
select.order_by('i')
|
|
641
|
+
select.limit(2)
|
|
642
|
+
assertEquals(select.statement,
|
|
643
|
+
"select i from #{table1} order by i limit 2")
|
|
644
|
+
assertEquals(select.exec, [{'i'=>1}, {'i'=>2}])
|
|
645
|
+
end
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
def testOffset
|
|
649
|
+
makeTestConnection do |connection|
|
|
650
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
651
|
+
connection.exec("insert into #{table1} values (1)")
|
|
652
|
+
connection.exec("insert into #{table1} values (2)")
|
|
653
|
+
connection.exec("insert into #{table1} values (3)")
|
|
654
|
+
select = Select.new(connection)
|
|
655
|
+
select.select('i')
|
|
656
|
+
select.from(table1)
|
|
657
|
+
select.order_by('i')
|
|
658
|
+
select.limit(1)
|
|
659
|
+
select.offset(1)
|
|
660
|
+
assertEquals(select.statement,
|
|
661
|
+
"select i from #{table1} order by i limit 1 offset 1")
|
|
662
|
+
assertEquals(select.exec, [{'i'=>2}])
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
def testDistinct
|
|
667
|
+
makeTestConnection do |connection|
|
|
668
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
669
|
+
connection.exec("insert into #{table1} values (1)")
|
|
670
|
+
connection.exec("insert into #{table1} values (1)")
|
|
671
|
+
connection.exec("insert into #{table1} values (2)")
|
|
672
|
+
select = Select.new(connection)
|
|
673
|
+
select.distinct
|
|
674
|
+
select.select('i')
|
|
675
|
+
select.from(table1)
|
|
676
|
+
select.order_by('i')
|
|
677
|
+
assertEquals(select.statement,
|
|
678
|
+
"select distinct i from #{table1} order by i")
|
|
679
|
+
assertEquals(select.exec, [{'i'=>1}, {'i'=>2}])
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
def testDistinctOn
|
|
684
|
+
makeTestConnection do |connection|
|
|
685
|
+
connection.exec("create temporary table #{table1} (i int, j int, k int)")
|
|
686
|
+
connection.exec("insert into #{table1} values (0, 0, 0)")
|
|
687
|
+
connection.exec("insert into #{table1} values (0, 0, 1)")
|
|
688
|
+
connection.exec("insert into #{table1} values (0, 1, 0)")
|
|
689
|
+
connection.exec("insert into #{table1} values (0, 1, 1)")
|
|
690
|
+
connection.exec("insert into #{table1} values (1, 0, 0)")
|
|
691
|
+
connection.exec("insert into #{table1} values (1, 0, 1)")
|
|
692
|
+
connection.exec("insert into #{table1} values (1, 1, 0)")
|
|
693
|
+
connection.exec("insert into #{table1} values (1, 1, 1)")
|
|
694
|
+
select = Select.new(connection)
|
|
695
|
+
select.distinct_on('i')
|
|
696
|
+
select.select('i')
|
|
697
|
+
select.select('j')
|
|
698
|
+
select.select('k')
|
|
699
|
+
select.from(table1)
|
|
700
|
+
select.order_by('i')
|
|
701
|
+
select.order_by('j')
|
|
702
|
+
select.order_by('k')
|
|
703
|
+
assertEquals(select.statement,
|
|
704
|
+
"select distinct on (i) i, j, k from #{table1} "\
|
|
705
|
+
"order by i, j, k")
|
|
706
|
+
assertEquals(select.exec, [
|
|
707
|
+
{"i"=>0, "j"=>0, "k"=>0},
|
|
708
|
+
{"i"=>1, "j"=>0, "k"=>0}
|
|
709
|
+
])
|
|
710
|
+
end
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
def testDistinctOn_TwoColumns
|
|
714
|
+
makeTestConnection do |connection|
|
|
715
|
+
connection.exec("create temporary table #{table1} (i int, j int, k int)")
|
|
716
|
+
connection.exec("insert into #{table1} values (0, 0, 0)")
|
|
717
|
+
connection.exec("insert into #{table1} values (0, 0, 1)")
|
|
718
|
+
connection.exec("insert into #{table1} values (0, 1, 0)")
|
|
719
|
+
connection.exec("insert into #{table1} values (0, 1, 1)")
|
|
720
|
+
connection.exec("insert into #{table1} values (1, 0, 0)")
|
|
721
|
+
connection.exec("insert into #{table1} values (1, 0, 1)")
|
|
722
|
+
connection.exec("insert into #{table1} values (1, 1, 0)")
|
|
723
|
+
connection.exec("insert into #{table1} values (1, 1, 1)")
|
|
724
|
+
select = Select.new(connection)
|
|
725
|
+
select.distinct_on('i')
|
|
726
|
+
select.distinct_on('j')
|
|
727
|
+
select.select('i')
|
|
728
|
+
select.select('j')
|
|
729
|
+
select.select('k')
|
|
730
|
+
select.from(table1)
|
|
731
|
+
select.order_by('i')
|
|
732
|
+
select.order_by('j')
|
|
733
|
+
select.order_by('k')
|
|
734
|
+
assertEquals(select.statement,
|
|
735
|
+
"select distinct on (i, j) i, j, k from #{table1} "\
|
|
736
|
+
"order by i, j, k")
|
|
737
|
+
assertEquals(select.exec, [
|
|
738
|
+
{"i"=>0, "j"=>0, "k"=>0},
|
|
739
|
+
{"i"=>0, "j"=>1, "k"=>0},
|
|
740
|
+
{"i"=>1, "j"=>0, "k"=>0},
|
|
741
|
+
{"i"=>1, "j"=>1, "k"=>0},
|
|
742
|
+
])
|
|
743
|
+
end
|
|
744
|
+
end
|
|
745
|
+
|
|
746
|
+
def testSetOps
|
|
747
|
+
testCases = [
|
|
748
|
+
[:union, 'union', [1, 2, 3, 4]],
|
|
749
|
+
[:union_all, 'union all', [1, 1, 2, 2, 3, 3, 3, 3, 4]],
|
|
750
|
+
[:intersect, 'intersect', [2, 3]],
|
|
751
|
+
[:intersect_all, 'intersect all', [2, 3, 3]],
|
|
752
|
+
[:except, 'except', [1]],
|
|
753
|
+
[:except_all, 'except all', [1, 1]],
|
|
754
|
+
]
|
|
755
|
+
makeTestConnection do |connection|
|
|
756
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
757
|
+
connection.exec("create temporary table #{table2} (i int)")
|
|
758
|
+
connection.exec("insert into #{table1} values (1)")
|
|
759
|
+
connection.exec("insert into #{table1} values (1)")
|
|
760
|
+
connection.exec("insert into #{table1} values (2)")
|
|
761
|
+
connection.exec("insert into #{table1} values (3)")
|
|
762
|
+
connection.exec("insert into #{table1} values (3)")
|
|
763
|
+
connection.exec("insert into #{table2} values (2)")
|
|
764
|
+
connection.exec("insert into #{table2} values (3)")
|
|
765
|
+
connection.exec("insert into #{table2} values (3)")
|
|
766
|
+
connection.exec("insert into #{table2} values (4)")
|
|
767
|
+
subselect = Select.new
|
|
768
|
+
subselect.select('i')
|
|
769
|
+
subselect.from(table2)
|
|
770
|
+
for function, op, expectedValues in testCases
|
|
771
|
+
assertInfo("For function #{function}:") do
|
|
772
|
+
select = Select.new(connection)
|
|
773
|
+
select.select('i')
|
|
774
|
+
select.from(table1)
|
|
775
|
+
select.send(function, subselect)
|
|
776
|
+
select.order_by('i')
|
|
777
|
+
assertEquals(select.statement, "select i from #{table1} "\
|
|
778
|
+
"#{op} (select i from #{table2}) order by i")
|
|
779
|
+
expectedResult = expectedValues.collect do |i| {'i'=>i} end
|
|
780
|
+
assertEquals(select.exec, expectedResult)
|
|
781
|
+
end
|
|
782
|
+
end
|
|
783
|
+
end
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
def testMultipleSetOps
|
|
787
|
+
makeTestConnection do |connection|
|
|
788
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
789
|
+
connection.exec("create temporary table #{table2} (i int)")
|
|
790
|
+
connection.exec("create temporary table #{table3} (i int)")
|
|
791
|
+
connection.exec("insert into #{table1} values (1)")
|
|
792
|
+
connection.exec("insert into #{table1} values (2)")
|
|
793
|
+
connection.exec("insert into #{table2} values (1)")
|
|
794
|
+
connection.exec("insert into #{table3} values (1)")
|
|
795
|
+
subselect2 = Select.new
|
|
796
|
+
subselect2.select('i')
|
|
797
|
+
subselect2.from(table2)
|
|
798
|
+
subselect3 = Select.new
|
|
799
|
+
subselect3.select('i')
|
|
800
|
+
subselect3.from(table3)
|
|
801
|
+
select = Select.new(connection)
|
|
802
|
+
select.select('i')
|
|
803
|
+
select.from(table1)
|
|
804
|
+
select.except(subselect2)
|
|
805
|
+
select.union(subselect3)
|
|
806
|
+
select.order_by('i')
|
|
807
|
+
assertEquals(select.statement, "select i from #{table1} "\
|
|
808
|
+
"except (select i from #{table2}) "\
|
|
809
|
+
"union (select i from #{table3}) order by i")
|
|
810
|
+
assertEquals(select.exec, [{'i'=>1}, {'i'=>2}])
|
|
811
|
+
end
|
|
812
|
+
end
|
|
813
|
+
|
|
814
|
+
def testUnionWithWhereClause
|
|
815
|
+
makeTestConnection do |connection|
|
|
816
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
817
|
+
10.downto(1) do |i|
|
|
818
|
+
connection.exec("insert into #{table1} values (#{i})")
|
|
819
|
+
end
|
|
820
|
+
sql1 = Select.new
|
|
821
|
+
sql1.select('i')
|
|
822
|
+
sql1.from(table1)
|
|
823
|
+
sql1.where('i % 2 = 0')
|
|
824
|
+
sql2 = Select.new(connection)
|
|
825
|
+
sql2.select('i')
|
|
826
|
+
sql2.from(table1)
|
|
827
|
+
sql2.where('i % 1 = 0')
|
|
828
|
+
sql2.union(sql1)
|
|
829
|
+
sql3 = Select.new(connection)
|
|
830
|
+
sql3.select('i')
|
|
831
|
+
sql3.from(sql2, 'foo')
|
|
832
|
+
sql3.order_by('i')
|
|
833
|
+
values = sql3.exec.collect do |row|
|
|
834
|
+
row['i']
|
|
835
|
+
end
|
|
836
|
+
assertEquals(values, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
837
|
+
end
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
def testMultipleSetOps_Nested
|
|
841
|
+
makeTestConnection do |connection|
|
|
842
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
843
|
+
connection.exec("create temporary table #{table2} (i int)")
|
|
844
|
+
connection.exec("create temporary table #{table3} (i int)")
|
|
845
|
+
connection.exec("insert into #{table1} values (1)")
|
|
846
|
+
connection.exec("insert into #{table1} values (2)")
|
|
847
|
+
connection.exec("insert into #{table2} values (1)")
|
|
848
|
+
connection.exec("insert into #{table3} values (1)")
|
|
849
|
+
subselect3 = Select.new
|
|
850
|
+
subselect3.select('i')
|
|
851
|
+
subselect3.from(table3)
|
|
852
|
+
subselect2 = Select.new
|
|
853
|
+
subselect2.select('i')
|
|
854
|
+
subselect2.union(subselect3)
|
|
855
|
+
subselect2.from(table2)
|
|
856
|
+
select = Select.new(connection)
|
|
857
|
+
select.select('i')
|
|
858
|
+
select.from(table1)
|
|
859
|
+
select.except(subselect2)
|
|
860
|
+
select.order_by('i')
|
|
861
|
+
assertEquals(select.statement, "select i from #{table1} "\
|
|
862
|
+
"except (select i from #{table2} "\
|
|
863
|
+
"union (select i from #{table3})) order by i")
|
|
864
|
+
assertEquals(select.exec, [{'i'=>2}])
|
|
865
|
+
end
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
def testWhereIn
|
|
869
|
+
makeTestConnection do |connection|
|
|
870
|
+
connection.exec("create temporary table #{table1} (i int)")
|
|
871
|
+
for i in (0..9)
|
|
872
|
+
insert = Insert.new(table1, connection)
|
|
873
|
+
insert.insert('i', i)
|
|
874
|
+
insert.exec
|
|
875
|
+
end
|
|
876
|
+
select = Select.new(connection)
|
|
877
|
+
select.select('i')
|
|
878
|
+
select.from(table1)
|
|
879
|
+
select.where(['i in %s', [:in, 2, 4]])
|
|
880
|
+
assertEquals(select.exec, [{'i'=>2}, {'i'=>4}])
|
|
881
|
+
end
|
|
882
|
+
end
|
|
883
|
+
|
|
884
|
+
def testForUpdate
|
|
885
|
+
makeTestConnection do |db1|
|
|
886
|
+
db1.exec("create temporary table #{table1} (i int)")
|
|
887
|
+
db1.exec("insert into #{table1} (i) values (1)")
|
|
888
|
+
db1.exec("begin")
|
|
889
|
+
sql = Select.new(db1)
|
|
890
|
+
sql.select('i')
|
|
891
|
+
sql.from(table1)
|
|
892
|
+
sql.where(['i = %s', 1])
|
|
893
|
+
sql.for_update
|
|
894
|
+
assertEquals(sql.exec, [{'i'=>1}])
|
|
895
|
+
end
|
|
896
|
+
end
|
|
897
|
+
|
|
898
|
+
def testStatemenIdempotentWithRandomOrder
|
|
899
|
+
sql = Select.new
|
|
900
|
+
sql.select('i')
|
|
901
|
+
sql.from('foo')
|
|
902
|
+
setenv('RANDOM_SQL_ORDER', '1') do
|
|
903
|
+
assertEquals(sql.statement, "select i from foo order by random()")
|
|
904
|
+
assertEquals(sql.statement, "select i from foo order by random()")
|
|
905
|
+
end
|
|
906
|
+
end
|
|
907
|
+
|
|
908
|
+
def test_enum
|
|
909
|
+
enum_name = "foo"
|
|
910
|
+
makeTestConnection do |db1|
|
|
911
|
+
db1.exec("begin")
|
|
912
|
+
db1.exec("create type #{enum_name} as enum ('foo', 'bar', 'baz')")
|
|
913
|
+
db1.exec("create temporary table #{table1} (e #{enum_name})")
|
|
914
|
+
db1.exec("insert into #{table1} (e) values ('foo')")
|
|
915
|
+
sql = Select.new(db1)
|
|
916
|
+
sql.select('e')
|
|
917
|
+
sql.from(table1)
|
|
918
|
+
assertEquals(sql.exec, [{'e' => 'foo'}])
|
|
919
|
+
end
|
|
920
|
+
end
|
|
921
|
+
|
|
922
|
+
end
|
|
923
|
+
|
|
924
|
+
SelectTest.new.run if $0 == __FILE__
|
|
925
|
+
|
|
926
|
+
# Local Variables:
|
|
927
|
+
# tab-width: 2
|
|
928
|
+
# ruby-indent-level: 2
|
|
929
|
+
# indent-tabs-mode: nil
|
|
930
|
+
# End:
|