dbd-pg 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ class TestPostgresPing < DBDConfig.testbase(:postgresql)
2
+ def test_ping
3
+ config = DBDConfig.get_config['postgresql']
4
+ dbh = DBI.connect("dbi:Pg:#{config['dbname']}", config['username'], config['password'])
5
+ assert dbh
6
+ assert dbh.ping
7
+ dbh.disconnect
8
+ assert_raise(DBI::InterfaceError) { dbh.ping }
9
+ end
10
+ end
@@ -0,0 +1,77 @@
1
+ class TestPostgresTimestamp < DBDConfig.testbase(:postgresql)
2
+ def get_tstamp
3
+ DateTime.parse("2008-03-08 10:39:01.012300")
4
+ end
5
+
6
+ # XXX DateTime is not allowed to modify the sec_fraction component, so this test is moot.
7
+ # perhaps we need to fix DateTime.
8
+ def skip_test_timestamp_altered_fraction
9
+ ts = nil
10
+
11
+ assert_nothing_raised do
12
+ @sth = @dbh.prepare("insert into timestamp_test (mytimestamp) values (?)")
13
+ ts = DateTime.parse(Time.now.to_s)
14
+ ts.sec_fraction = 22200000
15
+ @sth.execute(ts)
16
+ @sth.finish
17
+ end
18
+
19
+ assert_nothing_raised do
20
+ @sth = @dbh.prepare("select * from timestamp_test")
21
+ @sth.execute
22
+ row = @sth.fetch
23
+ @sth.finish
24
+ assert_equal ts.sec_fraction, row[0].sec_fraction
25
+ end
26
+ end
27
+
28
+ def test_current_timestamp
29
+ assert @dbh
30
+ # syntax db-specific (e.g., "from dual", "...timestamp()", etc.)
31
+ ts = @dbh.select_one("SELECT CURRENT_TIMESTAMP")[0]
32
+ assert_kind_of DateTime, ts
33
+ assert_not_nil ts.sec_fraction
34
+ end
35
+
36
+ # Just like the 'general' test, but checking for fractional seconds
37
+ def test_timestamp_fractional
38
+ assert @dbh
39
+ @sth = nil
40
+ t = get_tstamp
41
+ assert_nothing_raised do
42
+ @sth = @dbh.prepare("insert into timestamp_test (mytimestamp) values (?)")
43
+ @sth.execute(t)
44
+ @sth.finish
45
+ end
46
+
47
+ assert_nothing_raised do
48
+ @sth = @dbh.prepare("select * from timestamp_test")
49
+ @sth.execute
50
+ row = @sth.fetch
51
+ assert_kind_of DateTime, row[0]
52
+ assert_equal t.year, row[0].year
53
+ assert_equal t.month, row[0].month
54
+ assert_equal t.day, row[0].day
55
+ assert_equal t.hour, row[0].hour
56
+ assert_equal t.min, row[0].min
57
+ assert_equal t.sec, row[0].sec
58
+ assert_not_nil row[0].sec_fraction
59
+ assert_equal t.sec_fraction, row[0].sec_fraction
60
+ @sth.finish
61
+ end
62
+ end
63
+
64
+ # Is our DBI::Timestamp equivalent to its canonical string literal
65
+ # form cast appropriately?
66
+ def test_timestamp_from_cast
67
+ assert @dbh
68
+ sql_ts = "SELECT CAST('2008-03-08 10:39:01.012300' AS TIMESTAMP)"
69
+
70
+ row = @dbh.select_one(sql_ts)
71
+ assert_not_nil row
72
+ assert_equal 1, row.size
73
+
74
+ assert_kind_of DateTime, row[0]
75
+ assert_equal row[0], get_tstamp
76
+ end
77
+ end
@@ -0,0 +1,58 @@
1
+ class TestPostgresTransaction < DBDConfig.testbase(:postgresql)
2
+ def test_rollback
3
+ dbh = get_dbh
4
+ dbh["AutoCommit"] = false
5
+ @sth = dbh.prepare('insert into names (name, age) values (?, ?)')
6
+ @sth.execute("Foo", 51)
7
+ dbh.rollback
8
+ assert_equal 1, @sth.rows
9
+ @sth.finish
10
+
11
+
12
+ @sth = dbh.prepare('select name, age from names where name=?')
13
+ @sth.execute("Foo")
14
+ assert !@sth.fetch
15
+ @sth.finish
16
+ dbh.disconnect
17
+ end
18
+
19
+ def test_commit
20
+ dbh = get_dbh
21
+ dbh["AutoCommit"] = false
22
+ @sth = dbh.prepare('insert into names (name, age) values (?, ?)')
23
+ @sth.execute("Foo", 51)
24
+ dbh.commit
25
+ assert_equal 1, @sth.rows
26
+ @sth.finish
27
+
28
+ @sth = dbh.prepare('select name, age from names where name=?')
29
+ @sth.execute("Foo")
30
+ row = @sth.fetch
31
+ assert row
32
+ assert_equal "Foo", row[0]
33
+ assert_equal 51, row[1]
34
+ @sth.finish
35
+ dbh.disconnect
36
+ end
37
+
38
+ def test_select_transaction
39
+ # per bug #10466
40
+ dbh = get_dbh
41
+ dbh["AutoCommit"] = false
42
+ @sth = dbh.prepare('select * from test_insert(?, ?)');
43
+ @sth.execute("Foo", 51)
44
+ dbh.rollback
45
+ @sth.finish
46
+
47
+ @sth = dbh.prepare('select name, age from names where name=?')
48
+ @sth.execute("Foo")
49
+ assert !@sth.fetch
50
+ @sth.finish
51
+ dbh.disconnect
52
+ end
53
+
54
+ def get_dbh
55
+ config = DBDConfig.get_config
56
+ DBI.connect("dbi:Pg:#{config['postgresql']['dbname']}", config['postgresql']['username'], config['postgresql']['password'])
57
+ end
58
+ end
@@ -0,0 +1,254 @@
1
+ require 'dbd/Pg'
2
+
3
+ ######################################################################
4
+ # Test the PostgreSql DBD driver. This test exercises options
5
+ # difficult to test through the standard DBI interface.
6
+ #
7
+ class TestDbdPostgres < DBDConfig.testbase(:postgresql)
8
+
9
+ # FIXME this is a feature that should be there, but currently isn't.
10
+ # def test_connect
11
+ # dbd = get_dbd
12
+ # assert_not_nil dbd.connection
13
+ # assert_equal 'localhost', dbd.connection.host
14
+ # assert_equal 'erikh', dbd.connection.user
15
+ # assert_equal 'rubytest', dbd.connection.db
16
+ # assert_equal 5432, dbd.connection.port
17
+ # ensure
18
+ # dbd.disconnect if dbd
19
+ # end
20
+
21
+ def test_binding
22
+ assert(@dbh["pg_native_binding"])
23
+
24
+ assert_raise(DBI::ProgrammingError) do
25
+ @sth = @dbh.prepare("select * from names where age IS NOT ?")
26
+ @sth.execute("NULL")
27
+ @sth.finish
28
+ end
29
+
30
+ assert_nothing_raised do
31
+ @dbh["pg_native_binding"] = false
32
+ @sth = @dbh.prepare("select * from names where age IS NOT ? order by age")
33
+ @sth.execute("NULL")
34
+ assert_equal(
35
+ [
36
+ ["Joe", 19],
37
+ ["Bob", 21],
38
+ ["Jim", 30],
39
+ ],
40
+ @sth.fetch_all
41
+ )
42
+
43
+ @sth.finish
44
+
45
+ @sth = @dbh.prepare("select * from names where age = ?")
46
+ @sth.execute(19)
47
+ assert_equal(
48
+ [
49
+ ["Joe", 19]
50
+ ],
51
+ @sth.fetch_all
52
+ )
53
+
54
+ @sth.finish
55
+ end
56
+ end
57
+
58
+ def test_function_multiple_return_values
59
+ @sth = @dbh.prepare("SELECT age, select_subproperty(age, NULL), select_subproperty(age, 1) FROM names WHERE age = 19")
60
+ @sth.execute
61
+ assert_equal([[19, nil, 19]], @sth.fetch_all)
62
+ @sth.finish
63
+ end
64
+
65
+ def test_tables
66
+ assert_equal(
67
+ [
68
+ "array_test",
69
+ "bit_test",
70
+ "blob_test",
71
+ "boolean_test",
72
+ "bytea_test",
73
+ "field_types_test",
74
+ "names",
75
+ "precision_test",
76
+ "time_test",
77
+ "timestamp_test",
78
+ "view_names"
79
+ ], @dbh.tables.reject { |x| x =~ /^pg_/ }.sort)
80
+ end
81
+
82
+ def test_columns
83
+ assert_equal(
84
+ [
85
+ {
86
+ :name =>"age",
87
+ :default =>nil,
88
+ :primary =>nil,
89
+ :scale =>nil,
90
+ :sql_type =>4,
91
+ :nullable =>true,
92
+ :indexed =>false,
93
+ :precision =>4,
94
+ :type_name =>"integer",
95
+ :unique =>nil,
96
+ :array_of_type =>nil
97
+ },
98
+ {
99
+ :name =>"name",
100
+ :default =>nil,
101
+ :primary =>nil,
102
+ :scale =>nil,
103
+ :sql_type =>12,
104
+ :nullable =>true,
105
+ :indexed =>false,
106
+ :precision =>255,
107
+ :type_name =>"character varying",
108
+ :unique =>nil,
109
+ :array_of_type =>nil
110
+ }
111
+ ], @dbh.columns("names").sort_by { |x| x["name"] })
112
+
113
+ assert_equal(2, @dbh.columns("names").size) # make sure this works before the search path change
114
+
115
+ assert_equal(0, @dbh.columns("tbl").size) # tbl doesn't exist in public
116
+
117
+ @dbh.do('SET search_path TO schema1,schema2,"$user",public')
118
+
119
+ assert_equal(1, @dbh.columns('tbl').size);
120
+ assert_equal(
121
+ [
122
+ {
123
+ :name =>"foo",
124
+ :default =>nil,
125
+ :primary =>nil,
126
+ :scale =>nil,
127
+ :sql_type =>4,
128
+ :nullable =>true,
129
+ :indexed =>false,
130
+ :precision =>4,
131
+ :type_name =>"integer",
132
+ :unique =>nil,
133
+ :array_of_type =>nil
134
+
135
+ }
136
+ ],
137
+ @dbh.columns('tbl')
138
+ )
139
+
140
+ end
141
+
142
+ def test_connect_errors
143
+ dbd = nil
144
+ ex = assert_raise(DBI::OperationalError) {
145
+ dbd = DBI::DBD::Pg::Database.new('rubytest:1234', 'jim', nil, {})
146
+ }
147
+ ex = assert_raise(DBI::OperationalError) {
148
+ dbd = DBI::DBD::Pg::Database.new('bad_db_name', 'jim', nil, {})
149
+ }
150
+
151
+ # this corresponds to the test_parse_url_expected_errors test in tc_dbi.rb
152
+ assert_raise(DBI::InterfaceError) do
153
+ DBI.connect("dbi:Pg").disconnect
154
+ end
155
+
156
+ ensure
157
+ dbd.disconnect if dbd
158
+ end
159
+
160
+ def skip_test_type_map
161
+ dbd = get_dbd
162
+ def dbd.type_map
163
+ @type_map
164
+ end
165
+ assert dbd.type_map
166
+ assert_equal 21, dbd.convert("21", 23)
167
+ assert_equal "21", dbd.convert("21", 1043)
168
+ assert_equal 21.5, dbd.convert("21.5", 701)
169
+ end
170
+
171
+ def test_simple_command
172
+ dbd = get_dbd
173
+ res = dbd.do("INSERT INTO names (name, age) VALUES('Dan', 16)")
174
+ assert_equal 1, res
175
+
176
+ @sth = get_dbi.prepare("SELECT name FROM names WHERE age=16")
177
+ @sth.execute
178
+ assert @sth.fetchable?
179
+ # XXX FIXME This is a bug in the DBD. #rows should equal 1 for select statements.
180
+ assert_equal 0, @sth.rows
181
+ ensure
182
+ dbd.do("DELETE FROM names WHERE age < 20")
183
+ dbd.disconnect if dbd
184
+ end
185
+
186
+ def test_bad_command
187
+ dbd = get_dbd
188
+ assert_raise(DBI::ProgrammingError) {
189
+ dbd.do("INSERT INTO bad_table (name, age) VALUES('Dave', 12)")
190
+ }
191
+ ensure
192
+ dbd.disconnect if dbd
193
+ end
194
+
195
+ def test_query_single
196
+ dbd = get_dbi
197
+ res = dbd.prepare("SELECT name, age FROM names WHERE age=21;")
198
+ assert res
199
+ res.execute
200
+ fields = res.column_info
201
+ assert_equal 2, fields.length
202
+ assert_equal 'name', fields[0]['name']
203
+ assert_equal 'varchar', fields[0]['type_name']
204
+ assert_equal 'age', fields[1]['name']
205
+ assert_equal 'int4', fields[1]['type_name']
206
+
207
+ row = res.fetch
208
+
209
+ assert_equal 'Bob', row[0]
210
+ assert_equal 21, row[1]
211
+
212
+ row = res.fetch
213
+ assert_nil row
214
+
215
+ res.finish
216
+ ensure
217
+ dbd.disconnect if dbd
218
+ end
219
+
220
+ def test_query_multi
221
+ dbd = get_dbd
222
+ res = dbd.prepare("SELECT name, age FROM names WHERE age > 20;")
223
+
224
+ expected_list = ['Jim', 'Bob', 'Charlie']
225
+ res.execute
226
+ while row=res.fetch
227
+ expected = expected_list.shift
228
+ assert_equal expected, row[0]
229
+ end
230
+
231
+ res.finish
232
+ ensure
233
+ dbd.disconnect if dbd
234
+ end
235
+
236
+ def test_tables_call
237
+ # per bug #1082, views do not show up in tables listing.
238
+ assert get_dbi.tables.include?("view_names")
239
+ end
240
+
241
+ def get_dbi
242
+ config = DBDConfig.get_config
243
+ DBI.connect("dbi:Pg:#{config['postgresql']['dbname']}", config['postgresql']['username'], config['postgresql']['password'])
244
+ end
245
+
246
+ def get_dbd
247
+ config = DBDConfig.get_config['postgresql']
248
+ result = DBI::DBD::Pg::Database.new(config['dbname'], config['username'], config['password'], {})
249
+ result['AutoCommit'] = true
250
+ result
251
+ end
252
+ end
253
+
254
+ # --------------------------------------------------------------------
@@ -0,0 +1,54 @@
1
+ create table names (
2
+ name varchar(255),
3
+ age integer
4
+ );
5
+ ---
6
+ insert into names (name, age) values ('Joe', 19);
7
+ ---
8
+ insert into names (name, age) values ('Jim', 30);
9
+ ---
10
+ insert into names (name, age) values ('Bob', 21);
11
+ ---
12
+ create table precision_test (text_field varchar(20) primary key not null, integer_field decimal(2,1));
13
+ ---
14
+ CREATE TABLE blob_test (name VARCHAR(30), data OID);
15
+ ---
16
+ create view view_names as select * from names;
17
+ ---
18
+ create or replace function test_insert (varchar(255), integer)
19
+ returns integer
20
+ language sql
21
+ as 'insert into names (name, age) values ($1, $2); select age from names where name = $1';
22
+ ---
23
+ create table boolean_test (num integer, mybool boolean);
24
+ ---
25
+ create table time_test (mytime time);
26
+ ---
27
+ create table timestamp_test (mytimestamp timestamp);
28
+ ---
29
+ create table bit_test (mybit bit);
30
+ ---
31
+ create table field_types_test (foo integer not null primary key default 1);
32
+ ---
33
+ create table array_test (foo integer[], bar integer[3], baz integer[3][3], quux varchar[2]);
34
+ ---
35
+ create table bytea_test (foo bytea);
36
+ ---
37
+ create schema schema1;
38
+ ---
39
+ create schema schema2;
40
+ ---
41
+ create table schema1.tbl (foo integer);
42
+ ---
43
+ create table schema2.tbl (bar integer);
44
+ ---
45
+ create or replace function
46
+ select_subproperty(value names.age%TYPE, sub names.age%TYPE, out retval names.age%TYPE)
47
+ as $$
48
+ select
49
+ case
50
+ when $2 is not null
51
+ then $1
52
+ else null
53
+ end
54
+ $$ language sql;