ydbd-pg 0.5.1

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,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