dbd-pg 0.3.3

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.
@@ -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;