ydbd-pg 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ require 'fileutils'
2
+
3
+ DBDConfig.set_testbase(:postgresql, Class.new(Test::Unit::TestCase) do
4
+
5
+ def dbtype
6
+ "postgresql"
7
+ end
8
+
9
+ def test_base
10
+ assert_equal(@dbh.driver_name, "Pg")
11
+ assert_kind_of(DBI::DBD::Pg::Database, @dbh.instance_variable_get(:@handle))
12
+ end
13
+
14
+ def set_base_dbh
15
+ config = DBDConfig.get_config['postgresql']
16
+ @dbh = DBI.connect("dbi:Pg:#{config['dbname']}", config['username'], config['password'])
17
+ end
18
+
19
+ def setup
20
+ set_base_dbh
21
+ DBDConfig.inject_sql(@dbh, dbtype, "dbd/postgresql/up.sql")
22
+ end
23
+
24
+ def teardown
25
+ @sth.finish if @sth && !@sth.finished?
26
+ config = DBDConfig.get_config['postgresql']
27
+ DBDConfig.inject_sql(@dbh, dbtype, "dbd/postgresql/down.sql")
28
+ @dbh.disconnect
29
+ end
30
+ end
31
+ )
@@ -0,0 +1,31 @@
1
+ drop view view_names;
2
+ ---
3
+ drop table names;
4
+ ---
5
+ drop table blob_test;
6
+ ---
7
+ drop table boolean_test;
8
+ ---
9
+ drop table time_test;
10
+ ---
11
+ drop table timestamp_test;
12
+ ---
13
+ drop table bit_test;
14
+ ---
15
+ drop table field_types_test;
16
+ ---
17
+ drop table db_specific_types_test;
18
+ ---
19
+ drop table array_test;
20
+ ---
21
+ drop table bytea_test;
22
+ ---
23
+ drop table precision_test;
24
+ ---
25
+ drop table enum_type_test;
26
+ ---
27
+ drop type enum_test;
28
+ ---
29
+ drop schema schema1 cascade;
30
+ ---
31
+ drop schema schema2 cascade;
@@ -0,0 +1,179 @@
1
+ class TestPostgresArray < DBDConfig.testbase(:postgresql)
2
+ def test_array_type
3
+ assert_nothing_raised do
4
+ cols = @dbh.columns("array_test")
5
+ assert_equal(
6
+ [
7
+ {
8
+ :name =>"foo",
9
+ :default =>nil,
10
+ :primary =>nil,
11
+ :scale =>nil,
12
+ :sql_type =>DBI::SQL_INTEGER,
13
+ :nullable =>true,
14
+ :indexed =>false,
15
+ :precision =>-1,
16
+ :type_name =>"integer",
17
+ :unique =>nil,
18
+ :array_of_type => true
19
+ },
20
+ {
21
+ :name =>"bar",
22
+ :default =>nil,
23
+ :primary =>nil,
24
+ :scale =>nil,
25
+ :sql_type =>DBI::SQL_INTEGER,
26
+ :nullable =>true,
27
+ :indexed =>false,
28
+ :precision =>-1,
29
+ :type_name =>"integer",
30
+ :unique =>nil,
31
+ :array_of_type => true
32
+ },
33
+ {
34
+ :name =>"baz",
35
+ :default =>nil,
36
+ :primary =>nil,
37
+ :scale =>nil,
38
+ :sql_type =>DBI::SQL_INTEGER,
39
+ :nullable =>true,
40
+ :indexed =>false,
41
+ :precision =>-1,
42
+ :type_name =>"integer",
43
+ :unique =>nil,
44
+ :array_of_type => true
45
+ },
46
+ {
47
+ :array_of_type=>true,
48
+ :unique=>nil,
49
+ :precision=>-1,
50
+ :name=>"quux",
51
+ :default=>nil,
52
+ :indexed=>false,
53
+ :scale=>nil,
54
+ :primary=>nil,
55
+ :sql_type=>12,
56
+ :nullable=>true,
57
+ :type_name=>"character varying"
58
+ }
59
+ ], cols.collect { |x| x.reject { |key, value| key == :dbi_type } }
60
+ )
61
+
62
+ assert_equal(([DBI::DBD::Pg::Type::Array] * 4), cols.collect { |x| x["dbi_type"].class })
63
+ assert_equal((([DBI::Type::Integer] * 3) + [DBI::Type::Varchar]), cols.collect { |x| x["dbi_type"].base_type })
64
+ end
65
+ end
66
+
67
+ def test_array_parser
68
+ # string representation
69
+ assert_nothing_raised do
70
+ sth = @dbh.prepare('insert into array_test (foo) values (?)')
71
+ sth.execute('{1,2,3}')
72
+ sth.finish
73
+ end
74
+
75
+ assert_nothing_raised do
76
+ sth = @dbh.prepare('insert into array_test (foo) values (?)')
77
+ sth.execute([1,2,3])
78
+ sth.finish
79
+ end
80
+
81
+ assert_nothing_raised do
82
+ sth = @dbh.prepare('insert into array_test (quux) values (?)')
83
+ sth.execute(["Hello\\ World", "Again\\"])
84
+ sth.finish
85
+ end
86
+
87
+ assert_nothing_raised do
88
+ sth = @dbh.prepare('select foo from array_test where foo is not null')
89
+ sth.execute
90
+ assert_equal(
91
+ [
92
+ [[1,2,3]],
93
+ [[1,2,3]],
94
+ ], sth.fetch_all
95
+ )
96
+ sth.finish
97
+
98
+ sth = @dbh.prepare('select quux from array_test where quux is not null')
99
+ sth.execute
100
+
101
+ assert_equal(
102
+ [
103
+ [["Hello\\ World", "Again\\"]]
104
+ ], sth.fetch_all
105
+ )
106
+
107
+ sth.finish
108
+ end
109
+ end
110
+
111
+ def test_array_boundaries
112
+ # bar has a max extents of 3
113
+ sth = @dbh.prepare('insert into array_test (bar) values (?)')
114
+
115
+ assert_nothing_raised do
116
+ sth.execute('{1,2,3}')
117
+ end
118
+
119
+ # XXX postgresql does not enforce extents on single-dimension arrays
120
+ assert_nothing_raised do
121
+ sth.execute('{1,2,3,4}')
122
+ end
123
+
124
+ sth.finish
125
+ sth = @dbh.prepare('insert into array_test(baz) values (?)')
126
+
127
+ assert_nothing_raised do
128
+ sth.execute('{{1,2,3}, {1,2,3}}')
129
+ end
130
+
131
+ assert_nothing_raised do
132
+ # XXX for the record, I have no fucking idea why this works, what
133
+ # it's technically represented as and what backwards array
134
+ # implementation would allow it to work.
135
+ #
136
+ # I'm hoping it'll break on some future version of postgresql so I
137
+ # can fix it.
138
+ sth.execute('{1,2,3}')
139
+ end
140
+
141
+ assert_raises(DBI::ProgrammingError) do
142
+ sth.execute('{{1,2,3,4}, {1,2,3}}')
143
+ end
144
+
145
+ assert_raises(DBI::ProgrammingError) do
146
+ sth.execute('{{1,2,3}, {1,2,3,4}}')
147
+ end
148
+
149
+ sth.finish
150
+ end
151
+
152
+ def test_array_type_parser
153
+ pc = DBI::DBD::Pg::Type::Array
154
+
155
+ assert_nothing_raised do
156
+ po = pc.new(DBI::Type::Integer)
157
+ assert_equal([1,2,3], po.parse("{1,2,3}"))
158
+ assert_equal([[1,2,3],[4,5,6]], po.parse("{{1,2,3},{4,5,6}}"))
159
+ end
160
+
161
+ assert_nothing_raised do
162
+ po = pc.new(DBI::Type::Varchar)
163
+ assert_equal(["one", "two", "three"], po.parse("{\"one\",\"two\",\"three\"}"))
164
+ assert_equal([["one"], ["two\\"]], po.parse("{{\"one\"},{\"two\\\\\"}}"))
165
+ assert_equal([["one", "two\\"], ["three\\", "four"]], po.parse("{{\"one\",\"two\\\\\"},{\"three\\\\\",\"four\"}}"))
166
+ end
167
+ end
168
+
169
+ def test_array_generator
170
+ pg = DBI::DBD::Pg
171
+
172
+ assert_nothing_raised do
173
+ assert_equal("{1,2,3}", pg.generate_array([1,2,3]))
174
+ assert_equal("{{1,2,3},{1,2,3}}", pg.generate_array([[1,2,3],[1,2,3]]))
175
+ assert_equal("{\"one\",\"two\"}", pg.generate_array(["one", "two"]))
176
+ assert_equal("{\"hello\\\\ world\",\"again\"}", pg.generate_array(["hello\\ world", "again"]))
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,121 @@
1
+ class TestPostgresAsync < DBDConfig.testbase(:postgresql)
2
+ def get_dbh
3
+ config = DBDConfig.get_config['postgresql']
4
+ DBI.connect("dbi:Pg:#{config['dbname']}", config['username'], config['password'])
5
+ end
6
+
7
+ def get_db_info
8
+ config = DBDConfig.get_config['postgresql']
9
+ dsn = "dbi:Pg:database=#{config['dbname']}"
10
+ user = config['username']
11
+ pass = config['password']
12
+
13
+ return [dsn, user, pass]
14
+ end
15
+
16
+ def test_async_default
17
+ dsn, user, pass = get_db_info
18
+
19
+ DBI.connect(dsn, user, pass) do |dbh|
20
+ assert_equal false, dbh['pg_async']
21
+ assert_equal false, dbh['NonBlocking']
22
+ dbh.prepare('SELECT 1') do |sth| # Statement inherits
23
+ assert_equal false, sth['pg_async']
24
+ assert_equal false, sth['NonBlocking']
25
+ end
26
+ end
27
+ end
28
+
29
+ def test_async_dsn_enable
30
+ dsn, user, pass = get_db_info
31
+
32
+ for enable in ['true', 'TRUE', 'tRuE']
33
+ DBI.connect(dsn + ";pg_async=#{enable}", user, pass) do |dbh|
34
+ assert_equal true, dbh['pg_async']
35
+ assert_equal true, dbh['NonBlocking']
36
+ dbh.prepare('SELECT 1') do |sth| # Statement inherits
37
+ assert_equal true, sth['pg_async']
38
+ assert_equal true, sth['NonBlocking']
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def test_async_attr_enable
45
+ dsn, user, pass = get_db_info
46
+
47
+ for enable in ['true', 'TRUE', 'tRuE']
48
+ DBI.connect(dsn, user, pass, { 'pg_async' => enable } ) do |dbh|
49
+ assert_equal true, dbh['pg_async']
50
+ assert_equal true, dbh['NonBlocking']
51
+ dbh.prepare('SELECT 1') do |sth| # Statement inherits
52
+ assert_equal true, sth['pg_async']
53
+ assert_equal true, sth['NonBlocking']
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ def test_async_dsn_disable
60
+ dsn, user, pass = get_db_info
61
+
62
+ for disable in ['false', 'FALSE', 'fAlSe']
63
+ DBI.connect(dsn + ";pg_async=#{disable}", user, pass) do |dbh|
64
+ assert_equal false, dbh['pg_async']
65
+ assert_equal false, dbh['NonBlocking']
66
+ dbh.prepare('SELECT 1') do |sth| # Statement inherits
67
+ assert_equal false, sth['pg_async']
68
+ assert_equal false, sth['NonBlocking']
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def test_async_attr_disable
75
+ dsn, user, pass = get_db_info
76
+
77
+ for disable in ['false', 'FALSE', 'fAlSe']
78
+ DBI.connect(dsn, user, pass, { 'pg_async' => disable }) do |dbh|
79
+ assert_equal false, dbh['pg_async']
80
+ assert_equal false, dbh['NonBlocking']
81
+ dbh.prepare('SELECT 1') do |sth| # Statement inherits
82
+ assert_equal false, sth['pg_async']
83
+ assert_equal false, sth['NonBlocking']
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ def test_manual_enable
90
+ dsn, user, pass = get_db_info
91
+
92
+ DBI.connect(dsn, user, pass) do |dbh|
93
+ dbh['pg_async'] = true
94
+ assert_equal true, dbh['pg_async']
95
+ assert_equal true, dbh['NonBlocking']
96
+ dbh.prepare('SELECT 1') do |sth| # Statement inherits
97
+ assert_equal true, sth['pg_async']
98
+ assert_equal true, sth['NonBlocking']
99
+ end
100
+ end
101
+ end
102
+
103
+ def test_async_commands
104
+ dsn, user, pass = get_db_info
105
+
106
+ DBI.connect(dsn + ";pg_async=true", user, pass) do |dbh|
107
+ assert_equal true, dbh['pg_async']
108
+ assert_equal true, dbh['NonBlocking']
109
+ ret = dbh.select_all('SELECT 1')
110
+ assert_equal [[1]], ret
111
+
112
+ ret = dbh.select_all(%q{SELECT 1 WHERE 'foo' = ?}, 'bar')
113
+ assert_equal [], ret
114
+
115
+ dbh.prepare(%q{SELECT 1 WHERE 'foo' = ?}) do |sth|
116
+ sth.execute('bar')
117
+ assert_equal [], sth.fetch_all
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,36 @@
1
+ class TestPostgresBlob < DBDConfig.testbase(:postgresql)
2
+ DATA = "this is my new binary object"
3
+
4
+ def test_insert
5
+ assert @dbh
6
+ assert @dbh.ping
7
+
8
+ # test with DBI::Binary
9
+ assert_equal 1, @dbh.do("INSERT INTO blob_test (name, data) VALUES (?,?)", "test", DBI::Binary.new(DATA))
10
+
11
+ # test with blob_create directly
12
+ blob = @dbh.func(:blob_create, PGconn::INV_WRITE)
13
+ assert blob
14
+ assert @dbh.func(:blob_write, blob, DATA)
15
+ assert_equal 1, @dbh.do("INSERT INTO blob_test (name, data) VALUES (?,?)", "test (2)", blob)
16
+
17
+ # test with blob_import directly
18
+ File.open('/tmp/pg_dbi_import_test', 'w') { |f| f << DATA }
19
+ blob = @dbh.func(:blob_import, '/tmp/pg_dbi_import_test')
20
+ assert blob
21
+ assert_equal 1, @dbh.do("INSERT INTO blob_test (name, data) VALUES (?,?)", "test (2)", blob)
22
+
23
+ index = 0
24
+ @dbh.select_all("SELECT name, data FROM blob_test") do |name, data|
25
+ index += 1
26
+ assert_equal DATA, @dbh.func(:blob_read, data, DATA.length)
27
+ @dbh.func(:blob_export, data, '/tmp/pg_dbi_read_test')
28
+ assert_equal DATA, File.read('/tmp/pg_dbi_read_test')
29
+ end
30
+
31
+ assert_equal 3, index
32
+
33
+ File.unlink("/tmp/pg_dbi_read_test")
34
+ File.unlink("/tmp/pg_dbi_import_test")
35
+ end
36
+ end
@@ -0,0 +1,87 @@
1
+ require 'dbd/Pg'
2
+
3
+ begin
4
+ require 'rubygems'
5
+ gem 'pg'
6
+ rescue Exception => e
7
+ end
8
+
9
+ require 'pg'
10
+
11
+ LEN = 50
12
+
13
+ class TestPostgresByteA < DBDConfig.testbase(:postgresql)
14
+ # FIXME the 'pg' module is broken and doesn't encode/decode properly.
15
+ # this test should prove that the 'pg' module works so we can back out our
16
+ # hacks.
17
+ def skip_underlying_driver
18
+ str = generate_random_string
19
+
20
+ encoded = PGconn.escape_bytea(str.dup)
21
+ decoded = PGconn.unescape_bytea(encoded)
22
+
23
+ assert_equal str, decoded
24
+ end
25
+
26
+ def test_encode_decode
27
+ bytea = DBI::DBD::Pg::Type::ByteA
28
+
29
+ # some specific cases that were failing intermittenly
30
+ # poor \\ handling
31
+ str = "\236\000\257\202G<\371\035TPEO\211\005*AH'H\3136\360\004\245\261\037\340u\003s\\772X\231\002\200\n\327\202\217\353\177r\317o\341\237\341"
32
+ encoded = bytea.escape_bytea(str)
33
+ decoded = bytea.parse(encoded)
34
+
35
+ assert_equal str, decoded
36
+
37
+ # the split hack not working
38
+ str = "\343\336e\260\337\373\314\026\323#\237i\035\0302\024\346X\274\016\324\371\206\036\230\374\206#rA\n\214\272\316\330\025\374\000\2663\244M\255x\360\002\266q\336\231"
39
+
40
+ encoded = bytea.escape_bytea(str)
41
+ decoded = bytea.parse(encoded)
42
+
43
+ assert_equal str, decoded
44
+
45
+ # delimiter at the end
46
+ str = "\343\336e\260\337\373\314\026\323#\237i\035\0302\024\346X\274\016\324\371\206\036\230\374\206#rA\n\214\272\316\330\025\374\000\2663\244M\255x\360\002\266q\336\231\\\\\\\\"
47
+
48
+ encoded = bytea.escape_bytea(str)
49
+ decoded = bytea.parse(encoded)
50
+
51
+ assert_equal str, decoded
52
+
53
+ # a huge test to weed out all the stragglers
54
+ 5_000.times do
55
+ str = generate_random_string
56
+
57
+ encoded = bytea.escape_bytea(str)
58
+ decoded = bytea.parse(encoded)
59
+
60
+ assert_equal str, decoded
61
+ end
62
+ end
63
+
64
+ def test_insert_retrieve
65
+ assert_nothing_raised do
66
+ str = generate_random_string
67
+ sth = @dbh.prepare('insert into bytea_test (foo) values (?)')
68
+ sth.execute(DBI::DBD::Pg::Type::ByteA.new(str))
69
+ sth.finish
70
+
71
+ sth = @dbh.prepare('select * from bytea_test')
72
+ sth.execute
73
+ assert_equal([str], sth.fetch)
74
+ sth.finish
75
+ end
76
+ end
77
+
78
+ def generate_random_string
79
+ # random string test
80
+ str = " " * LEN
81
+ for i in 0...LEN
82
+ str[i] = (rand * 256).to_i.chr
83
+ end
84
+
85
+ return str
86
+ end
87
+ end