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

Sign up to get free protection for your applications and to get access to all the features.
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