rdbi-driver-postgresql 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
File without changes
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT Licence
2
2
 
3
- Copyright (c) 2010 Pistos
3
+ Copyright (c) 2010 Pistos, Erik Hollensbe
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,9 @@
1
+ LICENSE
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/rdbi-driver-postgresql.rb
6
+ lib/rdbi/driver/postgresql.rb
7
+ rdbi-driver-postgresql.gemspec
8
+ test/helper.rb
9
+ test/test_database.rb
@@ -10,7 +10,7 @@ The PostgreSQL database driver for RDBI.
10
10
 
11
11
  == Copyright
12
12
 
13
- Copyright (c) 2010 Pistos. See LICENCE for details.
13
+ Copyright (c) 2010-2011 Pistos. See LICENCE for details.
14
14
 
15
15
  == Acknowledgements
16
16
 
data/Rakefile CHANGED
@@ -1,62 +1,46 @@
1
+ # -*- ruby -*-
2
+
1
3
  require 'rubygems'
2
- require 'rake'
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
- require 'rake/testtask'
31
- Rake::TestTask.new(:test) do |test|
32
- test.libs << 'lib' << 'test'
33
- test.pattern = 'test/**/test_*.rb'
34
- test.verbose = true
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
- begin
38
- require 'rcov/rcovtask'
39
- Rcov::RcovTask.new do |test|
40
- test.libs << 'test'
41
- test.pattern = 'test/**/test_*.rb'
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
- task :test => :check_dependencies
18
+ self.description = <<-EOF
19
+ This is the PostgreSQL driver for RDBI.
51
20
 
52
- task :default => :test
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
- require 'rdoc/task'
55
- RDoc::Task.new do |rdoc|
56
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
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
- rdoc.rdoc_dir = 'rdoc'
59
- rdoc.title = "rdbi-dbd-postgresql #{version}"
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
- @pg_conn.escape_string((named[x] || indexed[x]).to_s)
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 'BEGIN'
46
- super &block
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 'ROLLBACK'
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 'COMMIT'
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( "SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_schema = ? AND table_name = ?",
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( "SELECT table_name FROM information_schema.tables WHERE table_schema = '#{pg_schema}';" ).fetch( :all ).each do |row|
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
- if !col.nil? and @schema.columns[index2].type == 'timestamp without time zone'
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
- if !val.nil? and @schema.columns[index].type == 'timestamp without time zone'
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
- attr_threaded_accessor :stmt_name
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
- prep_finalizer { @pg_result.clear }
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
- # FIXME move to RDBI::Util or something.
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
- # FIXME move to RDBI::Util or something.
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.rdoc"
17
+ "README.txt"
18
18
  ]
19
19
  s.files = [
20
- "LICENCE",
21
20
  "LICENSE",
22
- "README.rdoc",
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",
@@ -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
- return dbh
33
+ dbh
34
34
  end
35
35
 
36
36
  def role
@@ -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.new("not connected")) do
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 * from time_test limit 1' ).fetch(1)[0][0]
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 * FROM time_test WHERE my_date IS NULL LIMIT 1' ).fetch( 1 )[0][0]
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 |c|
249
- case c.name
311
+ columns.each do |col|
312
+ case col.name
250
313
  when :foo
251
- assert_equal c.type, 'character varying'.to_sym
314
+ assert_equal col.type, 'character varying'.to_sym
252
315
  when :bar
253
- assert_equal c.type, :integer
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
- prerelease: false
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
- date: 2010-12-10 00:00:00 -05:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: test-unit
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
- requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- segments:
30
- - 0
31
- version: "0"
32
- type: :development
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: rdoc
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
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- segments:
43
- - 0
44
- version: "0"
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
- requirement: &id003 !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- segments:
56
- - 0
57
- version: "0"
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
- requirement: &id005 !ruby/object:Gem::Requirement
77
- none: false
78
- requirements:
79
- - - "="
80
- - !ruby/object:Gem::Version
81
- segments:
82
- - 0
83
- - 9
84
- - 0
85
- version: 0.9.0
86
- type: :runtime
87
- version_requirements: *id005
88
- - !ruby/object:Gem::Dependency
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
- requirement: &id006 !ruby/object:Gem::Requirement
92
- none: false
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- segments:
97
- - 0
98
- version: "0"
99
- type: :runtime
100
- version_requirements: *id006
101
- - !ruby/object:Gem::Dependency
102
- name: epoxy
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
- requirement: &id007 !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- segments:
110
- - 0
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
- extra_rdoc_files:
123
- - LICENSE
124
- - README.rdoc
125
- files:
126
- - LICENCE
111
+ extra_rdoc_files:
112
+ - Manifest.txt
113
+ - README.txt
114
+ files:
127
115
  - LICENSE
128
- - README.rdoc
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
- has_rdoc: true
137
- homepage: http://github.com/Pistos/rdbi-dbd-postgresql
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
- require_paths:
129
+ rdoc_options:
130
+ - --main
131
+ - README.txt
132
+ require_paths:
144
133
  - lib
145
- required_ruby_version: !ruby/object:Gem::Requirement
146
- none: false
147
- requirements:
148
- - - ">="
149
- - !ruby/object:Gem::Version
150
- segments:
151
- - 0
152
- version: "0"
153
- required_rubygems_version: !ruby/object:Gem::Requirement
154
- none: false
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: 1.3.7
146
+ rubygems_version: 2.0.3
165
147
  signing_key:
166
- specification_version: 3
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