rdbi-driver-postgresql 0.9.1 → 0.9.2
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.
- checksums.yaml +7 -0
- data/.gemtest +0 -0
- data/LICENSE +1 -1
- data/Manifest.txt +9 -0
- data/{README.rdoc → README.txt} +1 -1
- data/Rakefile +38 -54
- data/lib/rdbi/driver/postgresql.rb +92 -38
- data/rdbi-driver-postgresql.gemspec +2 -4
- data/test/helper.rb +5 -5
- data/test/test_database.rb +88 -14
- metadata +119 -138
- data/LICENCE +0 -21
- data/VERSION +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c6929b7b46d9fa0ff8b4e34555728cd5395160d6
|
4
|
+
data.tar.gz: 6cfe5835b695e61bace5272dc48eea1faab306a2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fa2836418a5713bc58e644a7ebd932102bebc0af42a7b400041ca9e35e9b990d617af222b72e897b1160f76bf9e3a8aa544021070e8176d9386e4eb8782ffce1
|
7
|
+
data.tar.gz: 87485476570b677feed8b38440d593b9d599f2c8ecb06dc177f203b04bb488fcd77bc819a30a9f316750a37d0a901961dd89d9e91976c672926f5e547c2a53da
|
data/.gemtest
ADDED
File without changes
|
data/LICENSE
CHANGED
data/Manifest.txt
ADDED
data/{README.rdoc → README.txt}
RENAMED
data/Rakefile
CHANGED
@@ -1,62 +1,46 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
|
-
require '
|
3
|
-
|
4
|
-
begin
|
5
|
-
require 'jeweler'
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "rdbi-driver-postgresql"
|
8
|
-
gem.summary = %Q{PostgreSQL driver for RDBI}
|
9
|
-
gem.description = %Q{PostgreSQL driver for RDBI}
|
10
|
-
gem.email = "rdbi@pistos.oib.com"
|
11
|
-
gem.homepage = "http://github.com/Pistos/rdbi-dbd-postgresql"
|
12
|
-
gem.authors = [ "Pistos", "Erik Hollensbe" ]
|
13
|
-
|
14
|
-
gem.add_development_dependency 'test-unit'
|
15
|
-
gem.add_development_dependency 'rdoc'
|
16
|
-
gem.add_development_dependency 'rdbi-dbrc'
|
17
|
-
|
18
|
-
gem.add_dependency 'rdbi'
|
19
|
-
gem.add_dependency 'pg', '= 0.9.0'
|
20
|
-
gem.add_dependency 'methlab'
|
21
|
-
gem.add_dependency 'epoxy', '>= 0.3.1'
|
22
|
-
|
23
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
24
|
-
end
|
25
|
-
Jeweler::GemcutterTasks.new
|
26
|
-
rescue LoadError
|
27
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
28
|
-
end
|
4
|
+
require 'hoe'
|
29
5
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
6
|
+
Hoe.plugins.delete :rubyforge
|
7
|
+
Hoe.plugin :git
|
8
|
+
Hoe.plugin :rcov
|
9
|
+
Hoe.plugin :roodi
|
10
|
+
Hoe.plugin :reek
|
36
11
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
test.verbose = true
|
43
|
-
end
|
44
|
-
rescue LoadError
|
45
|
-
task :rcov do
|
46
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
47
|
-
end
|
48
|
-
end
|
12
|
+
spec = Hoe.spec 'rdbi-driver-postgresql' do
|
13
|
+
developer 'Pistos', 'pistos@purepistos.net'
|
14
|
+
developer 'Erik Hollensbe', 'erik@hollensbe.org'
|
15
|
+
|
16
|
+
self.rubyforge_name = nil
|
49
17
|
|
50
|
-
|
18
|
+
self.description = <<-EOF
|
19
|
+
This is the PostgreSQL driver for RDBI.
|
51
20
|
|
52
|
-
|
21
|
+
RDBI is a database interface built out of small parts. A micro framework for
|
22
|
+
databases, RDBI works with and extends libraries like 'typelib' and 'epoxy'
|
23
|
+
to provide type conversion and binding facilities. Via a driver/adapter
|
24
|
+
system it provides database access. RDBI itself provides pooling and other
|
25
|
+
enhanced database features.
|
26
|
+
EOF
|
53
27
|
|
54
|
-
|
55
|
-
|
56
|
-
|
28
|
+
self.summary = 'PostgreSQL driver for RDBI';
|
29
|
+
self.url = %w[http://github.com/rdbi/rdbi-driver-postgresql]
|
30
|
+
|
31
|
+
require_ruby_version ">= 1.8.7"
|
32
|
+
|
33
|
+
extra_dev_deps << ['hoe-roodi']
|
34
|
+
extra_dev_deps << ['hoe-reek']
|
35
|
+
extra_dev_deps << ['minitest']
|
36
|
+
|
37
|
+
extra_deps << ['rdbi']
|
38
|
+
extra_deps << ['pg', '>= 0.10.0']
|
39
|
+
|
40
|
+
desc "install a gem without sudo"
|
41
|
+
end
|
57
42
|
|
58
|
-
|
59
|
-
|
60
|
-
rdoc.rdoc_files.include('README*')
|
61
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
43
|
+
task :install => [:gem] do
|
44
|
+
sh "gem install pkg/#{spec.name}-#{spec.version}.gem"
|
62
45
|
end
|
46
|
+
# vim: syntax=ruby
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'rdbi'
|
2
2
|
require 'epoxy'
|
3
|
-
require 'methlab'
|
4
3
|
require 'pg'
|
5
4
|
|
6
5
|
class RDBI::Driver::PostgreSQL < RDBI::Driver
|
6
|
+
VERSION = "0.9.2"
|
7
|
+
|
7
8
|
def initialize( *args )
|
8
9
|
super( Database, *args )
|
9
10
|
end
|
@@ -11,8 +12,6 @@ end
|
|
11
12
|
|
12
13
|
class RDBI::Driver::PostgreSQL < RDBI::Driver
|
13
14
|
class Database < RDBI::Database
|
14
|
-
extend MethLab
|
15
|
-
|
16
15
|
attr_accessor :pg_conn
|
17
16
|
|
18
17
|
def initialize( *args )
|
@@ -29,35 +28,35 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
29
28
|
)
|
30
29
|
|
31
30
|
@preprocess_quoter = proc do |x, named, indexed|
|
32
|
-
|
31
|
+
quote(named[x] || indexed[x])
|
33
32
|
end
|
34
33
|
end
|
35
34
|
|
36
35
|
def disconnect
|
37
|
-
@pg_conn.close
|
38
36
|
super
|
37
|
+
@pg_conn.close
|
39
38
|
end
|
40
39
|
|
41
40
|
def transaction( &block )
|
42
41
|
if in_transaction?
|
43
42
|
raise RDBI::TransactionError.new( "Already in transaction (not supported by PostgreSQL)" )
|
44
43
|
end
|
45
|
-
execute
|
46
|
-
super
|
44
|
+
execute('BEGIN').finish
|
45
|
+
super(&block)
|
47
46
|
end
|
48
47
|
|
49
48
|
def rollback
|
50
49
|
if ! in_transaction?
|
51
50
|
raise RDBI::TransactionError.new( "Cannot rollback when not in a transaction" )
|
52
51
|
end
|
53
|
-
execute
|
52
|
+
execute('ROLLBACK').finish
|
54
53
|
super
|
55
54
|
end
|
56
55
|
def commit
|
57
56
|
if ! in_transaction?
|
58
57
|
raise RDBI::TransactionError.new( "Cannot commit when not in a transaction" )
|
59
58
|
end
|
60
|
-
execute
|
59
|
+
execute('COMMIT').finish
|
61
60
|
super
|
62
61
|
end
|
63
62
|
|
@@ -83,9 +82,20 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
83
82
|
sch.type = :table
|
84
83
|
when 'VIEW'
|
85
84
|
sch.type = :view
|
85
|
+
else
|
86
|
+
sch.type = :table
|
86
87
|
end
|
87
88
|
|
88
|
-
execute(
|
89
|
+
execute( %q[
|
90
|
+
SELECT c.column_name, c.data_type, c.is_nullable, tc.constraint_type
|
91
|
+
FROM information_schema.columns c
|
92
|
+
LEFT JOIN information_schema.key_column_usage kcu
|
93
|
+
ON kcu.column_name = c.column_name
|
94
|
+
AND kcu.table_name = c.table_name
|
95
|
+
LEFT JOIN information_schema.table_constraints tc
|
96
|
+
ON tc.constraint_name = kcu.constraint_name
|
97
|
+
WHERE c.table_schema = ? and c.table_name = ?
|
98
|
+
],
|
89
99
|
pg_schema,
|
90
100
|
table_name
|
91
101
|
).fetch( :all ).each do |row|
|
@@ -95,6 +105,7 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
95
105
|
# TODO: ensure this ruby_type is solid, especially re: dates and times
|
96
106
|
col.ruby_type = row[1].to_sym
|
97
107
|
col.nullable = row[2] == "YES"
|
108
|
+
col.primary_key = row[3] == "PRIMARY KEY"
|
98
109
|
sch.columns << col
|
99
110
|
end
|
100
111
|
|
@@ -103,7 +114,11 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
103
114
|
|
104
115
|
def schema( pg_schema = 'public' )
|
105
116
|
schemata = []
|
106
|
-
execute(
|
117
|
+
execute(%Q[
|
118
|
+
SELECT table_name
|
119
|
+
FROM information_schema.tables
|
120
|
+
WHERE table_schema = '#{pg_schema}'
|
121
|
+
]).fetch( :all ).each do |row|
|
107
122
|
schemata << table_schema( row[0], pg_schema )
|
108
123
|
end
|
109
124
|
schemata
|
@@ -127,6 +142,21 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
127
142
|
raise RDBI::DisconnectedError, "disconnected during ping"
|
128
143
|
end
|
129
144
|
end
|
145
|
+
|
146
|
+
def quote(item)
|
147
|
+
case item
|
148
|
+
when Numeric
|
149
|
+
item.to_s
|
150
|
+
when TrueClass
|
151
|
+
'true'
|
152
|
+
when FalseClass
|
153
|
+
'false'
|
154
|
+
when NilClass
|
155
|
+
'NULL'
|
156
|
+
else
|
157
|
+
"E'#{@pg_conn.escape_string(item.to_s)}'"
|
158
|
+
end
|
159
|
+
end
|
130
160
|
end
|
131
161
|
|
132
162
|
class Cursor < RDBI::Cursor
|
@@ -178,7 +208,7 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
178
208
|
def [](index)
|
179
209
|
fix_dates(@handle[index].values)
|
180
210
|
end
|
181
|
-
|
211
|
+
|
182
212
|
def last_row?
|
183
213
|
@index == result_count
|
184
214
|
end
|
@@ -209,18 +239,21 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
209
239
|
ary << row
|
210
240
|
end
|
211
241
|
# XXX end stupid rectifier.
|
212
|
-
|
242
|
+
|
213
243
|
return ary
|
214
244
|
end
|
215
245
|
|
216
246
|
def fix_dates(values)
|
217
247
|
index = 0
|
218
248
|
|
249
|
+
columns = @schema.columns
|
250
|
+
|
219
251
|
values.collect! do |val|
|
220
252
|
if val.kind_of?(Array)
|
221
253
|
index2 = 0
|
222
254
|
val.collect! do |col|
|
223
|
-
|
255
|
+
ctype = columns[index2].type
|
256
|
+
if !col.nil? && ctype.start_with?('timestamp') && ctype =~ /timestamp(?:\(\d\d?\))? without time zone/
|
224
257
|
col << @stub_datetime
|
225
258
|
end
|
226
259
|
|
@@ -228,7 +261,8 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
228
261
|
col
|
229
262
|
end
|
230
263
|
else
|
231
|
-
|
264
|
+
ctype = columns[index].type
|
265
|
+
if !val.nil? && ctype.start_with?('timestamp') && ctype =~ /timestamp(?:\(\d\d?\))? without time zone/
|
232
266
|
val << @stub_datetime
|
233
267
|
end
|
234
268
|
end
|
@@ -242,24 +276,24 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
242
276
|
end
|
243
277
|
|
244
278
|
class Statement < RDBI::Statement
|
245
|
-
extend MethLab
|
246
|
-
|
247
279
|
attr_accessor :pg_result
|
248
|
-
|
280
|
+
attr_accessor :stmt_name
|
249
281
|
|
250
282
|
def initialize( query, dbh )
|
251
283
|
super( query, dbh )
|
252
|
-
@stmt_name = Time.now.to_f.to_s
|
284
|
+
@stmt_name = ('stmt_' + Time.now.to_f.to_s).tr('.', '_')
|
253
285
|
|
254
286
|
ep = Epoxy.new( query )
|
255
287
|
@index_map = ep.indexed_binds
|
256
288
|
query = ep.quote(Hash[@index_map.compact.zip([])]) do |x|
|
257
289
|
case x
|
258
290
|
when Integer
|
259
|
-
"$#{x+1}"
|
291
|
+
"$#{x+1}"
|
260
292
|
when Symbol
|
261
293
|
num = @index_map.index(x)
|
262
294
|
"$#{num+1}"
|
295
|
+
else
|
296
|
+
x
|
263
297
|
end
|
264
298
|
end
|
265
299
|
|
@@ -272,18 +306,45 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
272
306
|
@output_type_map = RDBI::Type.create_type_hash( RDBI::Type::Out )
|
273
307
|
@output_type_map[ :bigint ] = RDBI::Type.filterlist( RDBI::Type::Filters::STR_TO_INT )
|
274
308
|
|
275
|
-
|
309
|
+
# PostgreSQL returns timestamps with and without subseconds.
|
310
|
+
# RDBI by default doesn't handle timestamps with subseconds,
|
311
|
+
# so here we account for that in our PostgreSQL driver
|
312
|
+
check = proc do |obj|
|
313
|
+
begin
|
314
|
+
if obj.include?('.')
|
315
|
+
format = "%Y-%m-%d %H:%M:%S.%N %z"
|
316
|
+
converted_and_back = DateTime.strptime(obj, format).strftime(format)
|
317
|
+
# Strip trailing zeros in subseconds
|
318
|
+
converted_and_back.gsub(/\.(\d+?)0* /, ".\\1 ") == obj.gsub(/\.(\d+?)0* /, ".\\1 ")
|
319
|
+
else
|
320
|
+
format = "%Y-%m-%d %H:%M:%S %z"
|
321
|
+
DateTime.strptime(obj, format).strftime(format) == obj
|
322
|
+
end
|
323
|
+
rescue ArgumentError => e
|
324
|
+
if e.message == 'invalid date'
|
325
|
+
false
|
326
|
+
else
|
327
|
+
raise e
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
convert = proc do |obj|
|
332
|
+
if obj.include?('.')
|
333
|
+
DateTime.strptime(obj, "%Y-%m-%d %H:%M:%S.%N %z")
|
334
|
+
else
|
335
|
+
DateTime.strptime(obj, "%Y-%m-%d %H:%M:%S %z")
|
336
|
+
end
|
337
|
+
end
|
338
|
+
@output_type_map[ :timestamp ] = RDBI::Type.filterlist( TypeLib::Filter.new(check, convert) )
|
339
|
+
|
340
|
+
@finish_block = Proc.new {
|
341
|
+
@dbh.pg_conn.exec("DEALLOCATE #{@stmt_name}")
|
342
|
+
@pg_result.clear
|
343
|
+
}
|
276
344
|
end
|
277
345
|
|
278
346
|
def new_modification(*binds)
|
279
|
-
|
280
|
-
hashes, binds = binds.partition { |x| x.kind_of?(Hash) }
|
281
|
-
hash = hashes.inject({}) { |x, y| x.merge(y) }
|
282
|
-
hash.keys.each do |key|
|
283
|
-
if index = @index_map.index(key)
|
284
|
-
binds.insert(index, hash[key])
|
285
|
-
end
|
286
|
-
end
|
347
|
+
binds = RDBI::Util.index_binds(binds, @index_map)
|
287
348
|
|
288
349
|
pg_result = @dbh.pg_conn.exec_prepared( @stmt_name, binds )
|
289
350
|
return pg_result.cmd_tuples
|
@@ -291,18 +352,11 @@ class RDBI::Driver::PostgreSQL < RDBI::Driver
|
|
291
352
|
|
292
353
|
# Returns an Array of things used to fill out the parameters to RDBI::Result.new
|
293
354
|
def new_execution( *binds )
|
294
|
-
|
295
|
-
hashes, binds = binds.partition { |x| x.kind_of?(Hash) }
|
296
|
-
hash = hashes.inject({}, :merge)
|
297
|
-
hash.each do |key, value|
|
298
|
-
if index = @index_map.index(key)
|
299
|
-
binds.insert(index, value)
|
300
|
-
end
|
301
|
-
end
|
355
|
+
binds = RDBI::Util.index_binds(binds, @index_map)
|
302
356
|
|
303
357
|
pg_result = @dbh.pg_conn.exec_prepared( @stmt_name, binds )
|
304
358
|
|
305
|
-
columns = []
|
359
|
+
columns = []
|
306
360
|
column_query = (0...pg_result.num_fields).map do |x|
|
307
361
|
"format_type(#{ pg_result.ftype(x) }, #{ pg_result.fmod(x) }) as col#{x}"
|
308
362
|
end.join(", ")
|
@@ -14,14 +14,12 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.email = %q{rdbi@pistos.oib.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
"README.
|
17
|
+
"README.txt"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
|
-
"LICENCE",
|
21
20
|
"LICENSE",
|
22
|
-
"README.
|
21
|
+
"README.txt",
|
23
22
|
"Rakefile",
|
24
|
-
"VERSION",
|
25
23
|
"lib/rdbi-driver-postgresql.rb",
|
26
24
|
"lib/rdbi/driver/postgresql.rb",
|
27
25
|
"rdbi-driver-postgresql.gemspec",
|
data/test/helper.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
gem 'test-unit'
|
3
2
|
require 'test/unit'
|
4
3
|
require 'fileutils'
|
5
|
-
gem 'pg', '= 0.9.0'
|
6
|
-
gem 'rdbi-dbrc'
|
7
4
|
require 'rdbi-dbrc'
|
8
5
|
require 'rdbi/driver/postgresql'
|
9
6
|
|
10
7
|
class Test::Unit::TestCase
|
11
8
|
|
12
9
|
SQL = [
|
10
|
+
'set client_min_messages = warning',
|
13
11
|
'DROP TABLE IF EXISTS foo',
|
14
12
|
'DROP TABLE IF EXISTS bar',
|
15
13
|
'DROP TABLE IF EXISTS time_test',
|
14
|
+
'DROP TABLE IF EXISTS time_test2',
|
16
15
|
'DROP TABLE IF EXISTS ordinals',
|
17
16
|
'create table foo (bar integer)',
|
18
17
|
'create table bar (foo varchar, bar integer)',
|
19
|
-
'create table time_test (my_date timestamp)',
|
18
|
+
'create table time_test (id SERIAL PRIMARY KEY, my_date timestamp)',
|
19
|
+
'create table time_test2 (id SERIAL PRIMARY KEY, ts TIMESTAMP(0) WITHOUT TIME ZONE)',
|
20
20
|
'CREATE TABLE ordinals ( id SERIAL PRIMARY KEY, cardinal INTEGER, s VARCHAR )',
|
21
21
|
"INSERT INTO ordinals ( cardinal, s ) VALUES ( 1, 'first' )",
|
22
22
|
"INSERT INTO ordinals ( cardinal, s ) VALUES ( 2, 'second' )",
|
@@ -30,7 +30,7 @@ class Test::Unit::TestCase
|
|
30
30
|
def init_database
|
31
31
|
dbh = new_database
|
32
32
|
SQL.each { |query| dbh.execute_modification(query) }
|
33
|
-
|
33
|
+
dbh
|
34
34
|
end
|
35
35
|
|
36
36
|
def role
|
data/test/test_database.rb
CHANGED
@@ -28,7 +28,7 @@ class TestDatabase < Test::Unit::TestCase
|
|
28
28
|
assert_kind_of(Numeric, RDBI.ping(driver, my_role))
|
29
29
|
dbh.disconnect
|
30
30
|
|
31
|
-
assert_raises(RDBI::DisconnectedError
|
31
|
+
assert_raises(RDBI::DisconnectedError) do
|
32
32
|
dbh.ping
|
33
33
|
end
|
34
34
|
|
@@ -182,7 +182,7 @@ class TestDatabase < Test::Unit::TestCase
|
|
182
182
|
|
183
183
|
dt = DateTime.now
|
184
184
|
dbh.execute_modification( 'insert into time_test (my_date) values (?)', dt )
|
185
|
-
dt2 = dbh.execute( 'select
|
185
|
+
dt2 = dbh.execute( 'select my_date from time_test limit 1' ).fetch(1)[0][0]
|
186
186
|
|
187
187
|
assert_kind_of( DateTime, dt2 )
|
188
188
|
assert_equal( dt2.to_s, dt.to_s )
|
@@ -190,9 +190,67 @@ class TestDatabase < Test::Unit::TestCase
|
|
190
190
|
dbh.execute 'INSERT INTO time_test ( my_date ) VALUES ( NULL )'
|
191
191
|
dt3 = "not nil"
|
192
192
|
assert_nothing_raised do
|
193
|
-
dt3 = dbh.execute( 'SELECT
|
193
|
+
dt3 = dbh.execute( 'SELECT my_date FROM time_test WHERE my_date IS NULL LIMIT 1' ).fetch( 1 )[0][0]
|
194
194
|
end
|
195
195
|
assert_nil dt3
|
196
|
+
|
197
|
+
dbh.execute_modification "INSERT INTO time_test ( my_date ) VALUES ( CAST( '2011-08-30 06:57:38.1375-04' AS TIMESTAMP(0) WITH TIME ZONE ) )"
|
198
|
+
dt = dbh.execute( 'SELECT my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][0]
|
199
|
+
assert_kind_of DateTime, dt
|
200
|
+
|
201
|
+
dbh.execute_modification "INSERT INTO time_test ( my_date ) VALUES ( CAST( '2011-08-30 06:57:38.1375-04' AS TIMESTAMP(1) WITH TIME ZONE ) )"
|
202
|
+
dt = dbh.execute( 'SELECT my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][0]
|
203
|
+
assert_kind_of DateTime, dt
|
204
|
+
|
205
|
+
dbh.execute_modification "INSERT INTO time_test ( my_date ) VALUES ( CAST( '2011-08-30 06:57:38.1375-04' AS TIMESTAMP WITH TIME ZONE ) )"
|
206
|
+
dt = dbh.execute( 'SELECT my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][0]
|
207
|
+
assert_kind_of DateTime, dt
|
208
|
+
|
209
|
+
dbh.execute_modification "INSERT INTO time_test ( my_date ) VALUES ( '2011-08-30 11:32:36.802597'::TIMESTAMP )"
|
210
|
+
dt = dbh.execute( 'SELECT my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][0]
|
211
|
+
assert_kind_of DateTime, dt
|
212
|
+
|
213
|
+
dbh.execute_modification "INSERT INTO time_test ( my_date ) VALUES ( CAST( '2011-08-30 06:57:38.1375' AS TIMESTAMP ) )"
|
214
|
+
dt = dbh.execute( 'SELECT my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][0]
|
215
|
+
assert_kind_of DateTime, dt
|
216
|
+
|
217
|
+
dbh.execute_modification "INSERT INTO time_test ( my_date ) VALUES ( CAST( '2011-08-30 06:57:38' AS TIMESTAMP ) )"
|
218
|
+
dt = dbh.execute( 'SELECT my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][0]
|
219
|
+
assert_kind_of DateTime, dt
|
220
|
+
|
221
|
+
dbh.execute_modification 'INSERT INTO time_test ( my_date ) VALUES ( CURRENT_TIMESTAMP(0) )'
|
222
|
+
dt = dbh.execute( 'SELECT my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][0]
|
223
|
+
assert_kind_of DateTime, dt
|
224
|
+
|
225
|
+
dbh.execute_modification 'INSERT INTO time_test ( my_date ) VALUES ( CURRENT_TIMESTAMP(2) )'
|
226
|
+
dt = dbh.execute( 'SELECT id, my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][1]
|
227
|
+
assert_kind_of DateTime, dt
|
228
|
+
|
229
|
+
dbh.execute_modification 'INSERT INTO time_test ( my_date ) VALUES ( CURRENT_TIMESTAMP )'
|
230
|
+
dt = dbh.execute( 'SELECT my_date, id FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][0]
|
231
|
+
assert_kind_of DateTime, dt
|
232
|
+
|
233
|
+
dbh.execute_modification 'INSERT INTO time_test ( my_date ) VALUES ( NOW() )'
|
234
|
+
dt = dbh.execute( 'SELECT id, my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 1' ).fetch(1)[0][1]
|
235
|
+
assert_kind_of DateTime, dt
|
236
|
+
|
237
|
+
dbh.execute_modification 'INSERT INTO time_test2 ( ts ) VALUES ( CURRENT_TIMESTAMP(0) )'
|
238
|
+
ts = dbh.execute( 'SELECT id, ts FROM time_test2 ORDER BY id DESC LIMIT 1' ).fetch(1)[0][1]
|
239
|
+
assert_kind_of DateTime, ts
|
240
|
+
|
241
|
+
rows = [ 'not empty' ]
|
242
|
+
assert_nothing_raised do
|
243
|
+
rows = dbh.execute( 'SELECT id, ts FROM time_test2 WHERE id = -1' ).fetch(1)
|
244
|
+
end
|
245
|
+
assert_empty rows
|
246
|
+
|
247
|
+
dbh.execute_modification "INSERT INTO time_test ( my_date ) VALUES ( CAST( '2011-08-30 06:57:38.1375' AS TIMESTAMP ) )"
|
248
|
+
dbh.execute_modification "INSERT INTO time_test ( my_date ) VALUES ( CAST( '2011-08-30 06:50:00' AS TIMESTAMP ) )"
|
249
|
+
rows = dbh.execute( 'SELECT my_date FROM time_test WHERE my_date IS NOT NULL ORDER BY id DESC LIMIT 2' ).fetch(2)
|
250
|
+
rows.each do |row|
|
251
|
+
assert_kind_of DateTime, row[0]
|
252
|
+
end
|
253
|
+
|
196
254
|
end
|
197
255
|
|
198
256
|
def test_09_basic_schema
|
@@ -200,11 +258,12 @@ class TestDatabase < Test::Unit::TestCase
|
|
200
258
|
assert_respond_to( dbh, :schema )
|
201
259
|
schema = dbh.schema.sort_by { |x| x.tables[0].to_s }
|
202
260
|
|
203
|
-
tables = [ :bar, :foo, :ordinals, :time_test ]
|
261
|
+
tables = [ :bar, :foo, :ordinals, :time_test, :time_test2 ]
|
204
262
|
columns = {
|
205
263
|
:bar => { :foo => 'character varying'.to_sym, :bar => :integer },
|
206
264
|
:foo => { :bar => :integer },
|
207
|
-
:time_test => { :my_date => 'timestamp without time zone'.to_sym },
|
265
|
+
:time_test => { :id => :integer, :my_date => 'timestamp without time zone'.to_sym },
|
266
|
+
:time_test2 => { :id => :integer, :ts => 'timestamp without time zone'.to_sym },
|
208
267
|
:ordinals => {
|
209
268
|
:id => :integer,
|
210
269
|
:cardinal => :integer,
|
@@ -235,6 +294,10 @@ class TestDatabase < Test::Unit::TestCase
|
|
235
294
|
self.dbh = init_database
|
236
295
|
assert_respond_to( dbh, :table_schema )
|
237
296
|
|
297
|
+
assert(dbh.table_schema('ordinals').columns.find {|x| x.name == :id }.primary_key)
|
298
|
+
assert(!dbh.table_schema('ordinals').columns.find {|x| x.name == :cardinal }.primary_key)
|
299
|
+
assert(!dbh.table_schema('ordinals').columns.find {|x| x.name == :s }.primary_key)
|
300
|
+
|
238
301
|
schema = dbh.table_schema( :foo )
|
239
302
|
columns = schema.columns
|
240
303
|
assert_equal columns.size, 1
|
@@ -245,12 +308,12 @@ class TestDatabase < Test::Unit::TestCase
|
|
245
308
|
schema = dbh.table_schema( :bar )
|
246
309
|
columns = schema.columns
|
247
310
|
assert_equal columns.size, 2
|
248
|
-
columns.each do |
|
249
|
-
case
|
311
|
+
columns.each do |col|
|
312
|
+
case col.name
|
250
313
|
when :foo
|
251
|
-
assert_equal
|
314
|
+
assert_equal col.type, 'character varying'.to_sym
|
252
315
|
when :bar
|
253
|
-
assert_equal
|
316
|
+
assert_equal col.type, :integer
|
254
317
|
end
|
255
318
|
end
|
256
319
|
|
@@ -263,11 +326,11 @@ class TestDatabase < Test::Unit::TestCase
|
|
263
326
|
res = dbh.execute("select id, cardinal, s from ordinals where id = ?id", { :id => 1 })
|
264
327
|
assert(res)
|
265
328
|
assert_equal([[1, 1, 'first']], res.fetch(:all))
|
266
|
-
|
329
|
+
|
267
330
|
res = dbh.execute("select id, cardinal, s from ordinals where id = ?id and cardinal = ?", { :id => 1 }, 1)
|
268
331
|
assert(res)
|
269
332
|
assert_equal([[1, 1, 'first']], res.fetch(:all))
|
270
|
-
|
333
|
+
|
271
334
|
res = dbh.execute("select id, cardinal, s from ordinals where id = ?id and cardinal = ?", 1, { :id => 1 })
|
272
335
|
assert(res)
|
273
336
|
assert_equal([[1, 1, 'first']], res.fetch(:all))
|
@@ -289,9 +352,9 @@ class TestDatabase < Test::Unit::TestCase
|
|
289
352
|
assert_equal(results[2].id, 3)
|
290
353
|
assert_equal(results[2].cardinal, 3)
|
291
354
|
assert_equal(results[2].s, 'third')
|
292
|
-
|
355
|
+
|
293
356
|
results = dbh.execute("select * from ordinals order by id").as(:Struct).fetch(:all)
|
294
|
-
|
357
|
+
|
295
358
|
assert(results)
|
296
359
|
assert_kind_of(Array, results)
|
297
360
|
assert_equal(results[0].id, 1)
|
@@ -303,7 +366,7 @@ class TestDatabase < Test::Unit::TestCase
|
|
303
366
|
assert_equal(results[2].id, 3)
|
304
367
|
assert_equal(results[2].cardinal, 3)
|
305
368
|
assert_equal(results[2].s, 'third')
|
306
|
-
|
369
|
+
|
307
370
|
result = dbh.execute("select * from ordinals order by id").as(:Struct).fetch(:first)
|
308
371
|
assert(result)
|
309
372
|
assert_kind_of(Struct, result)
|
@@ -311,4 +374,15 @@ class TestDatabase < Test::Unit::TestCase
|
|
311
374
|
assert_equal(result.cardinal, 1)
|
312
375
|
assert_equal(result.s, 'first')
|
313
376
|
end
|
377
|
+
|
378
|
+
def test_13_quote
|
379
|
+
self.dbh = init_database
|
380
|
+
|
381
|
+
assert_equal(%q[1], dbh.quote(1))
|
382
|
+
assert_equal(%q[false], dbh.quote(false))
|
383
|
+
assert_equal(%q[true], dbh.quote(true))
|
384
|
+
assert_equal(%q[NULL], dbh.quote(nil))
|
385
|
+
assert_equal(%q[E'shit'], dbh.quote('shit'))
|
386
|
+
assert_equal(%q[E'shit''t'], dbh.quote('shit\'t'))
|
387
|
+
end
|
314
388
|
end
|
metadata
CHANGED
@@ -1,170 +1,151 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdbi-driver-postgresql
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
segments:
|
6
|
-
- 0
|
7
|
-
- 9
|
8
|
-
- 1
|
9
|
-
version: 0.9.1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.2
|
10
5
|
platform: ruby
|
11
|
-
authors:
|
6
|
+
authors:
|
12
7
|
- Pistos
|
13
8
|
- Erik Hollensbe
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
12
|
+
date: 2013-06-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rdbi
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
23
22
|
prerelease: false
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
- !ruby/object:Gem::
|
35
|
-
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: pg
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.10.0
|
35
|
+
type: :runtime
|
36
36
|
prerelease: false
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.10.0
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: hoe-roodi
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
45
49
|
type: :development
|
46
|
-
version_requirements: *id002
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: rdbi-dbrc
|
49
50
|
prerelease: false
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: hoe-reek
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
58
63
|
type: :development
|
59
|
-
version_requirements: *id003
|
60
|
-
- !ruby/object:Gem::Dependency
|
61
|
-
name: rdbi
|
62
|
-
prerelease: false
|
63
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
64
|
-
none: false
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
segments:
|
69
|
-
- 0
|
70
|
-
version: "0"
|
71
|
-
type: :runtime
|
72
|
-
version_requirements: *id004
|
73
|
-
- !ruby/object:Gem::Dependency
|
74
|
-
name: pg
|
75
64
|
prerelease: false
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
name: methlab
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: minitest
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
90
78
|
prerelease: false
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
- !ruby/object:Gem::
|
102
|
-
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: hoe
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ~>
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '2.12'
|
91
|
+
type: :development
|
103
92
|
prerelease: false
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
- 3
|
112
|
-
- 1
|
113
|
-
version: 0.3.1
|
114
|
-
type: :runtime
|
115
|
-
version_requirements: *id007
|
116
|
-
description: PostgreSQL driver for RDBI
|
117
|
-
email: rdbi@pistos.oib.com
|
118
|
-
executables: []
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ~>
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '2.12'
|
98
|
+
description: |2
|
99
|
+
This is the PostgreSQL driver for RDBI.
|
119
100
|
|
101
|
+
RDBI is a database interface built out of small parts. A micro framework for
|
102
|
+
databases, RDBI works with and extends libraries like 'typelib' and 'epoxy'
|
103
|
+
to provide type conversion and binding facilities. Via a driver/adapter
|
104
|
+
system it provides database access. RDBI itself provides pooling and other
|
105
|
+
enhanced database features.
|
106
|
+
email:
|
107
|
+
- pistos@purepistos.net
|
108
|
+
- erik@hollensbe.org
|
109
|
+
executables: []
|
120
110
|
extensions: []
|
121
|
-
|
122
|
-
|
123
|
-
-
|
124
|
-
|
125
|
-
files:
|
126
|
-
- LICENCE
|
111
|
+
extra_rdoc_files:
|
112
|
+
- Manifest.txt
|
113
|
+
- README.txt
|
114
|
+
files:
|
127
115
|
- LICENSE
|
128
|
-
-
|
116
|
+
- Manifest.txt
|
117
|
+
- README.txt
|
129
118
|
- Rakefile
|
130
|
-
- VERSION
|
131
119
|
- lib/rdbi-driver-postgresql.rb
|
132
120
|
- lib/rdbi/driver/postgresql.rb
|
133
121
|
- rdbi-driver-postgresql.gemspec
|
134
122
|
- test/helper.rb
|
135
123
|
- test/test_database.rb
|
136
|
-
|
137
|
-
homepage: http://github.com/
|
124
|
+
- .gemtest
|
125
|
+
homepage: http://github.com/rdbi/rdbi-driver-postgresql
|
138
126
|
licenses: []
|
139
|
-
|
127
|
+
metadata: {}
|
140
128
|
post_install_message:
|
141
|
-
rdoc_options:
|
142
|
-
|
143
|
-
|
129
|
+
rdoc_options:
|
130
|
+
- --main
|
131
|
+
- README.txt
|
132
|
+
require_paths:
|
144
133
|
- lib
|
145
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
requirements:
|
156
|
-
- - ">="
|
157
|
-
- !ruby/object:Gem::Version
|
158
|
-
segments:
|
159
|
-
- 0
|
160
|
-
version: "0"
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.8.7
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - '>='
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
161
144
|
requirements: []
|
162
|
-
|
163
145
|
rubyforge_project:
|
164
|
-
rubygems_version:
|
146
|
+
rubygems_version: 2.0.3
|
165
147
|
signing_key:
|
166
|
-
specification_version:
|
148
|
+
specification_version: 4
|
167
149
|
summary: PostgreSQL driver for RDBI
|
168
|
-
test_files:
|
169
|
-
- test/helper.rb
|
150
|
+
test_files:
|
170
151
|
- test/test_database.rb
|
data/LICENCE
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
The MIT Licence
|
2
|
-
|
3
|
-
Copyright (c) 2010 Pistos
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.9.1
|