pg 0.18.0.pre20141117110243-x64-mingw32 → 0.18.0-x64-mingw32

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.
Binary file
Binary file
Binary file
data/lib/pg.rb CHANGED
@@ -24,7 +24,7 @@ end
24
24
  module PG
25
25
 
26
26
  # Library version
27
- VERSION = '0.18.0.pre20141117110243'
27
+ VERSION = '0.18.0'
28
28
 
29
29
  # VCS revision
30
30
  REVISION = %q$Revision$
@@ -71,11 +71,13 @@ module PG::BasicTypeRegistry
71
71
  @coders = coder_map.values
72
72
  @coders_by_name = @coders.inject({}){|h, t| h[t.name] = t; h }
73
73
  @coders_by_oid = @coders.inject({}){|h, t| h[t.oid] = t; h }
74
+ @typenames_by_oid = result.inject({}){|h, t| h[t['oid'].to_i] = t['typname']; h }
74
75
  end
75
76
 
76
77
  attr_reader :coders
77
78
  attr_reader :coders_by_oid
78
79
  attr_reader :coders_by_name
80
+ attr_reader :typenames_by_oid
79
81
 
80
82
  def coder_by_name(name)
81
83
  @coders_by_name[name]
@@ -125,7 +127,7 @@ module PG::BasicTypeRegistry
125
127
  raise(ArgumentError, "Invalid format value %p" % format) unless ValidFormats[format]
126
128
  raise(ArgumentError, "Invalid direction %p" % direction) unless ValidDirections[direction]
127
129
  end
128
-
130
+ protected :check_format_and_direction
129
131
 
130
132
  # The key of this hash maps to the `typname` column from the table.
131
133
  # encoder_map is then dynamically built with oids as the key and Type
@@ -239,6 +241,23 @@ end
239
241
  class PG::BasicTypeMapForResults < PG::TypeMapByOid
240
242
  include PG::BasicTypeRegistry
241
243
 
244
+ class WarningTypeMap < PG::TypeMapInRuby
245
+ def initialize(typenames)
246
+ @already_warned = Hash.new{|h, k| h[k] = {} }
247
+ @typenames_by_oid = typenames
248
+ end
249
+
250
+ def typecast_result_value(result, _tuple, field)
251
+ format = result.fformat(field)
252
+ oid = result.ftype(field)
253
+ unless @already_warned[format][oid]
254
+ STDERR.puts "Warning: no type cast defined for type #{@typenames_by_oid[format][oid].inspect} with oid #{oid}. Please cast this type explicitly to TEXT to be safe for future changes."
255
+ @already_warned[format][oid] = true
256
+ end
257
+ super
258
+ end
259
+ end
260
+
242
261
  def initialize(connection)
243
262
  @coder_maps = build_coder_maps(connection)
244
263
 
@@ -246,6 +265,9 @@ class PG::BasicTypeMapForResults < PG::TypeMapByOid
246
265
  @coder_maps.map{|f| f[:decoder].coders }.flatten.each do |coder|
247
266
  add_coder(coder)
248
267
  end
268
+
269
+ typenames = @coder_maps.map{|f| f[:decoder].typenames_by_oid }
270
+ self.default_type_map = WarningTypeMap.new(typenames)
249
271
  end
250
272
  end
251
273
 
@@ -259,7 +281,7 @@ end
259
281
  # the given result OIDs, but encoders. So it can be used to type cast field values based on
260
282
  # the type OID retrieved by a separate SQL query.
261
283
  #
262
- # PG::TypeMapByOid#fit_to_result(result, false) can be used to generate a result independent
284
+ # PG::TypeMapByOid#build_column_map(result) can be used to generate a result independent
263
285
  # PG::TypeMapByColumn type map, which can subsequently be used to cast query bind parameters
264
286
  # or #put_copy_data fields.
265
287
  #
@@ -268,7 +290,7 @@ end
268
290
  #
269
291
  # # Retrieve table OIDs per empty result set.
270
292
  # res = conn.exec( "SELECT * FROM copytable LIMIT 0" )
271
- # tm = basic_type_mapping.fit_to_result( res, false )
293
+ # tm = basic_type_mapping.build_column_map( res )
272
294
  # row_encoder = PG::TextEncoder::CopyRow.new type_map: tm
273
295
  #
274
296
  # conn.copy_data( "COPY copytable FROM STDIN", row_encoder ) do |res|
@@ -101,7 +101,7 @@ class PG::Connection
101
101
  #
102
102
  # Example with CSV input format:
103
103
  # conn.exec "create table my_table (a text,b text,c text,d text,e text)"
104
- # conn.copy_data "COPY my_table FROM STDOUT CSV" do
104
+ # conn.copy_data "COPY my_table FROM STDIN CSV" do
105
105
  # conn.put_copy_data "some,csv,data,to,copy\n"
106
106
  # conn.put_copy_data "more,csv,data,to,copy\n"
107
107
  # end
Binary file
@@ -195,7 +195,7 @@ describe 'Basic type mapping' do
195
195
 
196
196
  # Retrieve table OIDs per empty result.
197
197
  res = @conn.exec( "SELECT * FROM copytable LIMIT 0" )
198
- tm = basic_type_mapping.fit_to_result( res, false )
198
+ tm = basic_type_mapping.build_column_map( res )
199
199
  row_decoder = PG::TextDecoder::CopyRow.new type_map: tm
200
200
 
201
201
  rows = []
@@ -221,7 +221,7 @@ describe 'Basic type mapping' do
221
221
 
222
222
  # Retrieve table OIDs per empty result.
223
223
  res = @conn.exec( "SELECT * FROM copytable LIMIT 0" )
224
- tm = basic_type_mapping.fit_to_result( res, false )
224
+ tm = basic_type_mapping.build_column_map( res )
225
225
 
226
226
  @conn.exec_params( "INSERT INTO copytable VALUES ($1, $2, $3)", ['a', 123, [5,4,3]], 0, tm )
227
227
  @conn.exec_params( "INSERT INTO copytable VALUES ($1, $2, $3)", ['b', 234, [2,3]], 0, tm )
@@ -236,7 +236,7 @@ describe 'Basic type mapping' do
236
236
 
237
237
  # Retrieve table OIDs per empty result set.
238
238
  res = @conn.exec( "SELECT * FROM copytable LIMIT 0" )
239
- tm = basic_type_mapping.fit_to_result( res, false )
239
+ tm = basic_type_mapping.build_column_map( res )
240
240
  row_encoder = PG::TextEncoder::CopyRow.new type_map: tm
241
241
 
242
242
  @conn.copy_data( "COPY copytable FROM STDIN", row_encoder ) do |res|
@@ -133,6 +133,6 @@ describe PG::TypeMapByClass do
133
133
  tm[TrueClass] = "dummy"
134
134
  expect{
135
135
  res = @conn.exec_params( "SELECT $1", [true], 0, tm )
136
- }.to raise_error(NoMethodError, /undefined method.*call.*dummy/)
136
+ }.to raise_error(NoMethodError, /undefined method.*call/)
137
137
  end
138
138
  end
@@ -77,10 +77,7 @@ describe PG::TypeMapByOid do
77
77
 
78
78
  it "should allow building new TypeMapByColumn for a given result" do
79
79
  res = @conn.exec( "SELECT 1, 'a', 2.0::FLOAT, '2013-06-30'::DATE" )
80
- tm2 = tm.fit_to_result(res, true)
81
- expect( tm2 ).to eq( tm )
82
-
83
- tm2 = tm.fit_to_result(res, false)
80
+ tm2 = tm.build_column_map(res)
84
81
  expect( tm2 ).to be_a_kind_of(PG::TypeMapByColumn)
85
82
  expect( tm2.coders ).to eq( [textdec_int, nil, textdec_float, pass_through_type] )
86
83
  end
@@ -118,7 +115,6 @@ describe PG::TypeMapByOid do
118
115
 
119
116
  it "should build a TypeMapByColumn when assigned and the number of rows is high enough" do
120
117
  res = @conn.exec( "SELECT generate_series(1,20), 'a', 2.0::FLOAT, '2013-06-30'::DATE" )
121
- expect( tm.fit_to_result(res) ).to be_a_kind_of(PG::TypeMapByColumn)
122
118
  res.type_map = tm
123
119
  expect( res.type_map ).to be_kind_of( PG::TypeMapByColumn )
124
120
  expect( res.type_map.coders ).to eq( [textdec_int, nil, textdec_float, pass_through_type] )
@@ -126,7 +122,6 @@ describe PG::TypeMapByOid do
126
122
 
127
123
  it "should use TypeMapByOid for online lookup and the number of rows is low enough" do
128
124
  res = @conn.exec( "SELECT 1, 'a', 2.0::FLOAT, '2013-06-30'::DATE" )
129
- expect( tm.fit_to_result(res) ).to eq( tm )
130
125
  res.type_map = tm
131
126
  expect( res.type_map ).to be_kind_of( PG::TypeMapByOid )
132
127
  end
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env rspec
2
+ # encoding: utf-8
3
+
4
+ require_relative '../helpers'
5
+
6
+ require 'pg'
7
+
8
+
9
+ describe PG::TypeMapInRuby do
10
+
11
+ context "result values" do
12
+ it "should be usable non-derived" do
13
+ tm = PG::TypeMapInRuby.new
14
+ res = @conn.exec("select 5").map_types!(tm)
15
+ expect( res.getvalue(0,0) ).to eq( "5" )
16
+ end
17
+
18
+ it "should call derived result mapping methods" do
19
+ tm = Class.new(PG::TypeMapInRuby) do
20
+ attr_reader :fit_to_result_args
21
+
22
+ def fit_to_result(*args)
23
+ @fit_to_result_args = args
24
+ self
25
+ end
26
+
27
+ def typecast_result_value(*args)
28
+ [args, super]
29
+ end
30
+ end.new
31
+
32
+ res = @conn.exec("select 5,6").map_types!(tm)
33
+ expect( res.getvalue(0,1) ).to eq( [[res, 0, 1], "6"] )
34
+ expect( tm.fit_to_result_args ).to eq( [res] )
35
+ end
36
+
37
+ it "should accept only a type map object from fit_to_result" do
38
+ tm = Class.new(PG::TypeMapInRuby) do
39
+ def fit_to_result(*args)
40
+ :invalid
41
+ end
42
+ end.new
43
+
44
+ res = @conn.exec("select 5,6")
45
+ expect{ res.map_types!(tm) }.to raise_error(TypeError, /kind of PG::TypeMap/)
46
+ end
47
+ end
48
+
49
+ context "query bind params" do
50
+ it "should be usable non-derived" do
51
+ tm = PG::TypeMapInRuby.new
52
+ res = @conn.exec_params("select $1::int, $2::text", [5, 6], 0, tm)
53
+ expect( res.values ).to eq( [["5", "6"]] )
54
+ end
55
+
56
+ it "should call derived param mapping methods" do
57
+ tm = Class.new(PG::TypeMapInRuby) do
58
+ attr_reader :fit_to_query_args
59
+ attr_reader :typecast_query_param_args
60
+
61
+ def fit_to_query(params)
62
+ @fit_to_query_args = params
63
+ @typecast_query_param_args = []
64
+ self
65
+ end
66
+
67
+ def typecast_query_param(*args)
68
+ @typecast_query_param_args << [args, super]
69
+ PG::TextEncoder::Integer.new name: 'INT4', oid: 23
70
+ end
71
+ end.new
72
+
73
+ res = @conn.exec_params("select $1, $2", [5, 6], 0, tm)
74
+ expect( res.ftype(0) ).to eq( 23 )
75
+ expect( tm.fit_to_query_args ).to eq( [5, 6] )
76
+ expect( tm.typecast_query_param_args ).to eq( [[[5, 0], nil], [[6, 1], nil]] )
77
+ end
78
+ end
79
+
80
+ context "put_copy_data" do
81
+ it "should be usable non-derived" do
82
+ tm = PG::TypeMapInRuby.new
83
+ ce = PG::TextEncoder::CopyRow.new type_map: tm
84
+ res = ce.encode([5, 6])
85
+ expect( res ).to eq( "5\t6\n" )
86
+ end
87
+
88
+ it "should call derived data mapping methods" do
89
+ tm = Class.new(PG::TypeMapInRuby) do
90
+ attr_reader :fit_to_query_args
91
+ attr_reader :typecast_query_param_args
92
+
93
+ def fit_to_query(params)
94
+ @fit_to_query_args = params
95
+ @typecast_query_param_args = []
96
+ self
97
+ end
98
+
99
+ def typecast_query_param(*args)
100
+ @typecast_query_param_args << [args, super]
101
+ PG::TextEncoder::Integer.new name: 'INT4', oid: 23
102
+ end
103
+ end.new
104
+
105
+ ce = PG::TextEncoder::CopyRow.new type_map: tm
106
+ res = ce.encode([5, 6])
107
+ expect( res ).to eq( "5\t6\n" )
108
+ expect( tm.fit_to_query_args ).to eq( [5, 6] )
109
+ expect( tm.typecast_query_param_args ).to eq( [[[5, 0], nil], [[6, 1], nil]] )
110
+ end
111
+
112
+ it "shouldn't accept invalid return from typecast_query_param" do
113
+ tm = Class.new(PG::TypeMapInRuby) do
114
+ def typecast_query_param(*args)
115
+ :invalid
116
+ end
117
+ end.new
118
+
119
+ ce = PG::TextEncoder::CopyRow.new type_map: tm
120
+ expect{ ce.encode([5, 6]) }.to raise_error(TypeError, /nil or kind of PG::Coder/)
121
+ end
122
+ end
123
+
124
+ context "get_copy_data" do
125
+ it "should be usable non-derived" do
126
+ tm = PG::TypeMapInRuby.new
127
+ ce = PG::TextDecoder::CopyRow.new type_map: tm
128
+ res = ce.decode("5\t6\n")
129
+ expect( res ).to eq( ["5", "6"] )
130
+ end
131
+
132
+ it "should call derived data mapping methods" do
133
+ tm = Class.new(PG::TypeMapInRuby) do
134
+ attr_reader :fit_to_copy_get_args
135
+
136
+ def fit_to_copy_get(*args)
137
+ @fit_to_copy_get_args = args
138
+ 0
139
+ end
140
+
141
+ def typecast_copy_get(field_str, fieldno, format, enc)
142
+ [field_str, fieldno, format, enc, super]
143
+ end
144
+ end.new
145
+
146
+ ce = PG::TextDecoder::CopyRow.new type_map: tm
147
+ res = ce.decode("5\t6\n")
148
+ expect( tm.fit_to_copy_get_args ).to eq( [] )
149
+ expect( res ).to eq( [["5", 0, 0, Encoding::UTF_8, "5"], ["6", 1, 0, Encoding::UTF_8, "6"]] )
150
+ end
151
+
152
+ it "shouldn't accept invalid return from fit_to_copy_get" do
153
+ tm = Class.new(PG::TypeMapInRuby) do
154
+ def fit_to_copy_get
155
+ :invalid
156
+ end
157
+ end.new
158
+
159
+ ce = PG::TextDecoder::CopyRow.new type_map: tm
160
+ expect{ ce.decode("5\t6\n") }.to raise_error(TypeError, /kind of Integer/)
161
+ end
162
+ end
163
+
164
+ end
@@ -9,23 +9,6 @@ require 'pg'
9
9
  describe PG::TypeMap do
10
10
  let!(:tm){ PG::TypeMap.new }
11
11
 
12
- it "should respond to fit_to_query" do
13
- expect{ tm.fit_to_query( [123] ) }.to raise_error(NotImplementedError, /not suitable to map query params/)
14
- end
15
-
16
- it "should respond to fit_to_result" do
17
- res = @conn.exec( "SELECT 1" )
18
- expect{ tm.fit_to_result( res ) }.to raise_error(NotImplementedError, /not suitable to map result values/)
19
- end
20
-
21
- it "should check params type" do
22
- expect{ tm.fit_to_query( :invalid ) }.to raise_error(TypeError, /expected Array/)
23
- end
24
-
25
- it "should check result class" do
26
- expect{ tm.fit_to_result( :invalid ) }.to raise_error(TypeError, /expected kind of PG::Result/)
27
- end
28
-
29
12
  it "should raise an error when used for param type casts" do
30
13
  expect{
31
14
  @conn.exec_params( "SELECT $1", [5], 0, tm )
@@ -138,15 +138,11 @@ describe "PG::Type derivations" do
138
138
  expect( textenc_int.encode(" 123-xyz ") ).to eq( "123" )
139
139
  end
140
140
 
141
- it "should encode false and 0 to SQL FALSE value" do
142
- [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].each do |value|
143
- expect( textenc_boolean.encode(value) ).to eq( "f" )
144
- end
145
- end
146
-
147
- it "should encode true, 1 to SQL TRUE value" do
148
- [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].each do |value|
149
- expect( textenc_boolean.encode(value) ).to eq( "t" )
141
+ it "should encode boolean values" do
142
+ expect( textenc_boolean.encode(false) ).to eq( "f" )
143
+ expect( textenc_boolean.encode(true) ).to eq( "t" )
144
+ ["any", :other, "value", 0, 1, 2].each do |value|
145
+ expect( textenc_boolean.encode(value) ).to eq( value.to_s )
150
146
  end
151
147
  end
152
148
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0.pre20141117110243
4
+ version: 0.18.0
5
5
  platform: x64-mingw32
6
6
  authors:
7
7
  - Michael Granger
@@ -30,7 +30,7 @@ cert_chain:
30
30
  GrqF74zpLl7/KFdHC8VmzwZS18hvDjxeLVuVI2gIGnBInqnlqv05g/l4/1pISh5j
31
31
  dS4=
32
32
  -----END CERTIFICATE-----
33
- date: 2014-11-17 00:00:00.000000000 Z
33
+ date: 2015-01-05 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: hoe-mercurial
@@ -197,6 +197,7 @@ extra_rdoc_files:
197
197
  - ext/pg_type_map_by_column.c
198
198
  - ext/pg_type_map_by_mri_type.c
199
199
  - ext/pg_type_map_by_oid.c
200
+ - ext/pg_type_map_in_ruby.c
200
201
  - ext/util.c
201
202
  files:
202
203
  - ".gemtest"
@@ -236,6 +237,7 @@ files:
236
237
  - ext/pg_type_map_by_column.c
237
238
  - ext/pg_type_map_by_mri_type.c
238
239
  - ext/pg_type_map_by_oid.c
240
+ - ext/pg_type_map_in_ruby.c
239
241
  - ext/util.c
240
242
  - ext/util.h
241
243
  - ext/vc/pg.sln
@@ -243,6 +245,7 @@ files:
243
245
  - ext/vc/pg_19/pg_19.vcproj
244
246
  - lib/2.0/pg_ext.so
245
247
  - lib/2.1/pg_ext.so
248
+ - lib/2.2/pg_ext.so
246
249
  - lib/pg.rb
247
250
  - lib/pg/basic_type_mapping.rb
248
251
  - lib/pg/coder.rb
@@ -282,6 +285,7 @@ files:
282
285
  - spec/pg/type_map_by_column_spec.rb
283
286
  - spec/pg/type_map_by_mri_type_spec.rb
284
287
  - spec/pg/type_map_by_oid_spec.rb
288
+ - spec/pg/type_map_in_ruby_spec.rb
285
289
  - spec/pg/type_map_spec.rb
286
290
  - spec/pg/type_spec.rb
287
291
  - spec/pg_spec.rb
@@ -308,12 +312,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
308
312
  version: 1.8.7
309
313
  required_rubygems_version: !ruby/object:Gem::Requirement
310
314
  requirements:
311
- - - ">"
315
+ - - ">="
312
316
  - !ruby/object:Gem::Version
313
- version: 1.3.1
317
+ version: '0'
314
318
  requirements: []
315
319
  rubyforge_project:
316
- rubygems_version: 2.2.2
320
+ rubygems_version: 2.4.5
317
321
  signing_key:
318
322
  specification_version: 4
319
323
  summary: Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/]
metadata.gz.sig CHANGED
Binary file