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