pg 0.18.1 → 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +42 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +117 -0
  6. data/.github/workflows/source-gem.yml +141 -0
  7. data/.gitignore +22 -0
  8. data/.hgsigs +34 -0
  9. data/.hgtags +41 -0
  10. data/.irbrc +23 -0
  11. data/.pryrc +23 -0
  12. data/.tm_properties +21 -0
  13. data/.travis.yml +49 -0
  14. data/BSDL +2 -2
  15. data/Gemfile +17 -0
  16. data/History.md +901 -0
  17. data/Manifest.txt +8 -21
  18. data/README-Windows.rdoc +17 -28
  19. data/README.ja.md +300 -0
  20. data/README.md +286 -0
  21. data/Rakefile +43 -131
  22. data/Rakefile.cross +89 -70
  23. data/certs/ged.pem +24 -0
  24. data/certs/kanis@comcard.de.pem +20 -0
  25. data/certs/larskanis-2022.pem +26 -0
  26. data/certs/larskanis-2023.pem +24 -0
  27. data/certs/larskanis-2024.pem +24 -0
  28. data/ext/errorcodes.def +113 -0
  29. data/ext/errorcodes.rb +1 -1
  30. data/ext/errorcodes.txt +36 -2
  31. data/ext/extconf.rb +128 -55
  32. data/ext/gvl_wrappers.c +8 -0
  33. data/ext/gvl_wrappers.h +44 -33
  34. data/ext/pg.c +228 -202
  35. data/ext/pg.h +108 -99
  36. data/ext/pg_binary_decoder.c +164 -16
  37. data/ext/pg_binary_encoder.c +249 -22
  38. data/ext/pg_coder.c +189 -44
  39. data/ext/pg_connection.c +1889 -1195
  40. data/ext/pg_copy_coder.c +398 -42
  41. data/ext/pg_errors.c +1 -1
  42. data/ext/pg_record_coder.c +522 -0
  43. data/ext/pg_result.c +729 -234
  44. data/ext/pg_text_decoder.c +635 -52
  45. data/ext/pg_text_encoder.c +294 -130
  46. data/ext/pg_tuple.c +572 -0
  47. data/ext/pg_type_map.c +64 -23
  48. data/ext/pg_type_map_all_strings.c +21 -7
  49. data/ext/pg_type_map_by_class.c +59 -27
  50. data/ext/pg_type_map_by_column.c +86 -43
  51. data/ext/pg_type_map_by_mri_type.c +50 -21
  52. data/ext/pg_type_map_by_oid.c +62 -29
  53. data/ext/pg_type_map_in_ruby.c +59 -28
  54. data/ext/{util.c → pg_util.c} +13 -13
  55. data/ext/{util.h → pg_util.h} +3 -3
  56. data/lib/pg/basic_type_map_based_on_result.rb +67 -0
  57. data/lib/pg/basic_type_map_for_queries.rb +202 -0
  58. data/lib/pg/basic_type_map_for_results.rb +104 -0
  59. data/lib/pg/basic_type_registry.rb +303 -0
  60. data/lib/pg/binary_decoder/date.rb +9 -0
  61. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  62. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  63. data/lib/pg/coder.rb +36 -13
  64. data/lib/pg/connection.rb +813 -74
  65. data/lib/pg/exceptions.rb +16 -2
  66. data/lib/pg/result.rb +24 -7
  67. data/lib/pg/text_decoder/date.rb +18 -0
  68. data/lib/pg/text_decoder/inet.rb +9 -0
  69. data/lib/pg/text_decoder/json.rb +14 -0
  70. data/lib/pg/text_decoder/numeric.rb +9 -0
  71. data/lib/pg/text_decoder/timestamp.rb +30 -0
  72. data/lib/pg/text_encoder/date.rb +12 -0
  73. data/lib/pg/text_encoder/inet.rb +28 -0
  74. data/lib/pg/text_encoder/json.rb +14 -0
  75. data/lib/pg/text_encoder/numeric.rb +9 -0
  76. data/lib/pg/text_encoder/timestamp.rb +24 -0
  77. data/lib/pg/tuple.rb +30 -0
  78. data/lib/pg/type_map_by_column.rb +3 -2
  79. data/lib/pg/version.rb +4 -0
  80. data/lib/pg.rb +106 -41
  81. data/misc/openssl-pg-segfault.rb +31 -0
  82. data/misc/postgres/History.txt +9 -0
  83. data/misc/postgres/Manifest.txt +5 -0
  84. data/misc/postgres/README.txt +21 -0
  85. data/misc/postgres/Rakefile +21 -0
  86. data/misc/postgres/lib/postgres.rb +16 -0
  87. data/misc/ruby-pg/History.txt +9 -0
  88. data/misc/ruby-pg/Manifest.txt +5 -0
  89. data/misc/ruby-pg/README.txt +21 -0
  90. data/misc/ruby-pg/Rakefile +21 -0
  91. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  92. data/pg.gemspec +34 -0
  93. data/rakelib/task_extension.rb +46 -0
  94. data/sample/array_insert.rb +1 -1
  95. data/sample/async_api.rb +4 -8
  96. data/sample/async_copyto.rb +1 -1
  97. data/sample/async_mixed.rb +1 -1
  98. data/sample/check_conn.rb +1 -1
  99. data/sample/copydata.rb +71 -0
  100. data/sample/copyfrom.rb +1 -1
  101. data/sample/copyto.rb +1 -1
  102. data/sample/cursor.rb +1 -1
  103. data/sample/disk_usage_report.rb +6 -15
  104. data/sample/issue-119.rb +2 -2
  105. data/sample/losample.rb +1 -1
  106. data/sample/minimal-testcase.rb +2 -2
  107. data/sample/notify_wait.rb +1 -1
  108. data/sample/pg_statistics.rb +6 -15
  109. data/sample/replication_monitor.rb +9 -18
  110. data/sample/test_binary_values.rb +1 -1
  111. data/sample/wal_shipper.rb +2 -2
  112. data/sample/warehouse_partitions.rb +8 -17
  113. data.tar.gz.sig +0 -0
  114. metadata +135 -207
  115. metadata.gz.sig +0 -0
  116. data/ChangeLog +0 -5378
  117. data/History.rdoc +0 -297
  118. data/README.ja.rdoc +0 -14
  119. data/README.rdoc +0 -161
  120. data/lib/pg/basic_type_mapping.rb +0 -399
  121. data/lib/pg/constants.rb +0 -11
  122. data/lib/pg/text_decoder.rb +0 -42
  123. data/lib/pg/text_encoder.rb +0 -27
  124. data/spec/data/expected_trace.out +0 -26
  125. data/spec/data/random_binary_data +0 -0
  126. data/spec/helpers.rb +0 -355
  127. data/spec/pg/basic_type_mapping_spec.rb +0 -251
  128. data/spec/pg/connection_spec.rb +0 -1459
  129. data/spec/pg/result_spec.rb +0 -449
  130. data/spec/pg/type_map_by_class_spec.rb +0 -138
  131. data/spec/pg/type_map_by_column_spec.rb +0 -222
  132. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  133. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  134. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  135. data/spec/pg/type_map_spec.rb +0 -22
  136. data/spec/pg/type_spec.rb +0 -665
  137. data/spec/pg_spec.rb +0 -50
@@ -1,222 +0,0 @@
1
- #!/usr/bin/env rspec
2
- # encoding: utf-8
3
-
4
- require_relative '../helpers'
5
-
6
- require 'pg'
7
-
8
-
9
- describe PG::TypeMapByColumn do
10
-
11
- let!(:textenc_int){ PG::TextEncoder::Integer.new name: 'INT4', oid: 23 }
12
- let!(:textdec_int){ PG::TextDecoder::Integer.new name: 'INT4', oid: 23 }
13
- let!(:textenc_float){ PG::TextEncoder::Float.new name: 'FLOAT4', oid: 700 }
14
- let!(:textdec_float){ PG::TextDecoder::Float.new name: 'FLOAT4', oid: 700 }
15
- let!(:textenc_string){ PG::TextEncoder::String.new name: 'TEXT', oid: 25 }
16
- let!(:textdec_string){ PG::TextDecoder::String.new name: 'TEXT', oid: 25 }
17
- let!(:textdec_bytea){ PG::TextDecoder::Bytea.new name: 'BYTEA', oid: 17 }
18
- let!(:binaryenc_bytea){ PG::BinaryEncoder::Bytea.new name: 'BYTEA', oid: 17, format: 1 }
19
- let!(:binarydec_bytea){ PG::BinaryDecoder::Bytea.new name: 'BYTEA', oid: 17, format: 1 }
20
- let!(:pass_through_type) do
21
- type = Class.new(PG::SimpleDecoder) do
22
- def decode(*v)
23
- v
24
- end
25
- end.new
26
- type.oid = 123456
27
- type.format = 1
28
- type.name = 'pass_through'
29
- type
30
- end
31
-
32
- it "should retrieve it's conversions" do
33
- cm = PG::TypeMapByColumn.new( [textdec_int, textenc_string, textdec_float, pass_through_type, nil] )
34
- expect( cm.coders ).to eq( [
35
- textdec_int,
36
- textenc_string,
37
- textdec_float,
38
- pass_through_type,
39
- nil
40
- ] )
41
- expect( cm.inspect ).to eq( "#<PG::TypeMapByColumn INT4:0 TEXT:0 FLOAT4:0 pass_through:1 nil>" )
42
- end
43
-
44
- it "should retrieve it's oids" do
45
- cm = PG::TypeMapByColumn.new( [textdec_int, textdec_string, textdec_float, pass_through_type, nil] )
46
- expect( cm.oids ).to eq( [23, 25, 700, 123456, nil] )
47
- end
48
-
49
- it "should gracefully handle not initialized state" do
50
- # PG::TypeMapByColumn is not initialized in allocate function, like other
51
- # type maps, but in #initialize. So it might be not called by derived classes.
52
-
53
- not_init = Class.new(PG::TypeMapByColumn) do
54
- def initialize
55
- # no super call
56
- end
57
- end.new
58
-
59
- expect{ @conn.exec_params( "SELECT $1", [ 0 ], 0, not_init ) }.to raise_error(NotImplementedError)
60
-
61
- res = @conn.exec( "SELECT 1" )
62
- expect{ res.type_map = not_init }.to raise_error(NotImplementedError)
63
-
64
- @conn.copy_data("COPY (SELECT 1) TO STDOUT") do
65
- decoder = PG::TextDecoder::CopyRow.new(type_map: not_init)
66
- expect{ @conn.get_copy_data(false, decoder) }.to raise_error(NotImplementedError)
67
- @conn.get_copy_data
68
- end
69
- end
70
-
71
-
72
- #
73
- # Encoding Examples
74
- #
75
-
76
- it "should encode integer params" do
77
- col_map = PG::TypeMapByColumn.new( [textenc_int]*3 )
78
- res = @conn.exec_params( "SELECT $1, $2, $3", [ 0, nil, "-999" ], 0, col_map )
79
- expect( res.values ).to eq( [
80
- [ "0", nil, "-999" ],
81
- ] )
82
- end
83
-
84
- it "should encode bytea params" do
85
- data = "'\u001F\\"
86
- col_map = PG::TypeMapByColumn.new( [binaryenc_bytea]*2 )
87
- res = @conn.exec_params( "SELECT $1, $2", [ data, nil ], 0, col_map )
88
- res.type_map = PG::TypeMapByColumn.new( [textdec_bytea]*2 )
89
- expect( res.values ).to eq( [
90
- [ data, nil ],
91
- ] )
92
- end
93
-
94
-
95
- it "should allow hash form parameters for default encoder" do
96
- col_map = PG::TypeMapByColumn.new( [nil, nil] )
97
- hash_param_bin = { value: ["00ff"].pack("H*"), type: 17, format: 1 }
98
- hash_param_nil = { value: nil, type: 17, format: 1 }
99
- res = @conn.exec_params( "SELECT $1, $2",
100
- [ hash_param_bin, hash_param_nil ], 0, col_map )
101
- expect( res.values ).to eq( [["\\x00ff", nil]] )
102
- expect( result_typenames(res) ).to eq( ['bytea', 'bytea'] )
103
- end
104
-
105
- it "should convert hash form parameters to string when using string encoders" do
106
- col_map = PG::TypeMapByColumn.new( [textenc_string, textenc_string] )
107
- hash_param_bin = { value: ["00ff"].pack("H*"), type: 17, format: 1 }
108
- hash_param_nil = { value: nil, type: 17, format: 1 }
109
- res = @conn.exec_params( "SELECT $1::text, $2::text",
110
- [ hash_param_bin, hash_param_nil ], 0, col_map )
111
- expect( res.values ).to eq( [["{:value=>\"\\x00\\xFF\", :type=>17, :format=>1}", "{:value=>nil, :type=>17, :format=>1}"]] )
112
- end
113
-
114
- it "shouldn't allow param mappings with different number of fields" do
115
- expect{
116
- @conn.exec_params( "SELECT $1", [ 123 ], 0, PG::TypeMapByColumn.new([]) )
117
- }.to raise_error(ArgumentError, /mapped columns/)
118
- end
119
-
120
- it "should verify the default type map for query params as well" do
121
- tm1 = PG::TypeMapByColumn.new([])
122
- expect{
123
- @conn.exec_params( "SELECT $1", [ 123 ], 0, PG::TypeMapByColumn.new([nil]).with_default_type_map(tm1) )
124
- }.to raise_error(ArgumentError, /mapped columns/)
125
- end
126
-
127
- it "forwards query param conversions to the #default_type_map" do
128
- tm1 = PG::TypeMapByClass.new
129
- tm1[Integer] = PG::TextEncoder::Integer.new name: 'INT2', oid: 21
130
-
131
- tm2 = PG::TypeMapByColumn.new( [textenc_int, nil, nil] ).with_default_type_map( tm1 )
132
- res = @conn.exec_params( "SELECT $1, $2, $3::TEXT", [1, 2, :abc], 0, tm2 )
133
-
134
- expect( res.ftype(0) ).to eq( 23 ) # tm2
135
- expect( res.ftype(1) ).to eq( 21 ) # tm1
136
- expect( res.getvalue(0,2) ).to eq( "abc" ) # TypeMapAllStrings
137
- end
138
-
139
- #
140
- # Decoding Examples
141
- #
142
-
143
- class Exception_in_decode < PG::SimpleDecoder
144
- def decode(res, tuple, field)
145
- raise "no type decoder defined for tuple #{tuple} field #{field}"
146
- end
147
- end
148
-
149
- it "should raise an error from decode method of type converter" do
150
- res = @conn.exec( "SELECT now()" )
151
- types = Array.new( res.nfields, Exception_in_decode.new )
152
- res.type_map = PG::TypeMapByColumn.new( types )
153
- expect{ res.values }.to raise_error(/no type decoder defined/)
154
- end
155
-
156
- it "should raise an error for invalid params" do
157
- expect{ PG::TypeMapByColumn.new( :WrongType ) }.to raise_error(TypeError, /wrong argument type/)
158
- expect{ PG::TypeMapByColumn.new( [123] ) }.to raise_error(ArgumentError, /invalid/)
159
- end
160
-
161
- it "shouldn't allow result mappings with different number of fields" do
162
- res = @conn.exec( "SELECT 1" )
163
- expect{ res.type_map = PG::TypeMapByColumn.new([]) }.to raise_error(ArgumentError, /mapped columns/)
164
- end
165
-
166
- it "should verify the default type map for result values as well" do
167
- res = @conn.exec( "SELECT 1" )
168
- tm1 = PG::TypeMapByColumn.new([])
169
- expect{
170
- res.type_map = PG::TypeMapByColumn.new([nil]).with_default_type_map(tm1)
171
- }.to raise_error(ArgumentError, /mapped columns/)
172
- end
173
-
174
- it "forwards result value conversions to a TypeMapByOid as #default_type_map" do
175
- # One run with implicit built TypeMapByColumn and another with online lookup
176
- [0, 10].each do |max_rows|
177
- tm1 = PG::TypeMapByOid.new
178
- tm1.add_coder PG::TextDecoder::Integer.new name: 'INT2', oid: 21
179
- tm1.max_rows_for_online_lookup = max_rows
180
-
181
- tm2 = PG::TypeMapByColumn.new( [textdec_int, nil, nil] ).with_default_type_map( tm1 )
182
- res = @conn.exec( "SELECT '1'::INT4, '2'::INT2, '3'::INT8" ).map_types!( tm2 )
183
-
184
- expect( res.getvalue(0,0) ).to eq( 1 ) # tm2
185
- expect( res.getvalue(0,1) ).to eq( 2 ) # tm1
186
- expect( res.getvalue(0,2) ).to eq( "3" ) # TypeMapAllStrings
187
- end
188
- end
189
-
190
- it "forwards get_copy_data conversions to another TypeMapByColumn as #default_type_map" do
191
- tm1 = PG::TypeMapByColumn.new( [textdec_int, nil, nil] )
192
- tm2 = PG::TypeMapByColumn.new( [nil, textdec_int, nil] ).with_default_type_map( tm1 )
193
- decoder = PG::TextDecoder::CopyRow.new(type_map: tm2)
194
- @conn.copy_data("COPY (SELECT 1, 2, 3) TO STDOUT", decoder) do
195
- expect( @conn.get_copy_data ).to eq( [1, 2, '3'] )
196
- @conn.get_copy_data
197
- end
198
- end
199
-
200
- it "will deny copy queries with different column count" do
201
- [[2, 2], [2, 3], [3, 2]].each do |cols1, cols2|
202
- tm1 = PG::TypeMapByColumn.new( [textdec_int, nil, nil][0, cols1] )
203
- tm2 = PG::TypeMapByColumn.new( [nil, textdec_int, nil][0, cols2] ).with_default_type_map( tm1 )
204
- decoder = PG::TextDecoder::CopyRow.new(type_map: tm2)
205
- @conn.copy_data("COPY (SELECT 1, 2, 3) TO STDOUT", decoder) do
206
- expect{ @conn.get_copy_data }.to raise_error(ArgumentError, /number of copy fields/)
207
- @conn.get_copy_data
208
- end
209
- end
210
- end
211
-
212
- #
213
- # Decoding Examples text format
214
- #
215
-
216
- it "should allow mixed type conversions" do
217
- res = @conn.exec( "SELECT 1, 'a', 2.0::FLOAT, '2013-06-30'::DATE, 3" )
218
- res.type_map = PG::TypeMapByColumn.new( [textdec_int, textdec_string, textdec_float, pass_through_type, nil] )
219
- expect( res.values ).to eq( [[1, 'a', 2.0, ['2013-06-30', 0, 3], '3' ]] )
220
- end
221
-
222
- end
@@ -1,136 +0,0 @@
1
- #!/usr/bin/env rspec
2
- # encoding: utf-8
3
-
4
- require_relative '../helpers'
5
-
6
- require 'pg'
7
-
8
-
9
- describe PG::TypeMapByMriType do
10
-
11
- let!(:textenc_int){ PG::TextEncoder::Integer.new name: 'INT4', oid: 23 }
12
- let!(:textenc_float){ PG::TextEncoder::Float.new name: 'FLOAT8', oid: 701 }
13
- let!(:textenc_string){ PG::TextEncoder::String.new name: 'TEXT', oid: 25 }
14
- let!(:binaryenc_int){ PG::BinaryEncoder::Int8.new name: 'INT8', oid: 20, format: 1 }
15
- let!(:pass_through_type) do
16
- type = Class.new(PG::SimpleEncoder) do
17
- def encode(*v)
18
- v.inspect
19
- end
20
- end.new
21
- type.oid = 25
22
- type.format = 0
23
- type.name = 'pass_through'
24
- type
25
- end
26
-
27
- let!(:tm) do
28
- tm = PG::TypeMapByMriType.new
29
- tm['T_FIXNUM'] = binaryenc_int
30
- tm['T_FLOAT'] = textenc_float
31
- tm['T_SYMBOL'] = pass_through_type
32
- tm
33
- end
34
-
35
- let!(:derived_tm) do
36
- tm = Class.new(PG::TypeMapByMriType) do
37
- def array_type_map_for(value)
38
- PG::TextEncoder::Array.new name: '_INT4', oid: 1007, elements_type: PG::TextEncoder::Integer.new
39
- end
40
- end.new
41
- tm['T_FIXNUM'] = proc{|value| textenc_int }
42
- tm['T_REGEXP'] = proc{|value| :invalid }
43
- tm['T_ARRAY'] = :array_type_map_for
44
- tm
45
- end
46
-
47
- it "should retrieve all conversions" do
48
- expect( tm.coders ).to eq( {
49
- "T_FIXNUM" => binaryenc_int,
50
- "T_FLOAT" => textenc_float,
51
- "T_SYMBOL" => pass_through_type,
52
- "T_HASH" => nil,
53
- "T_ARRAY" => nil,
54
- "T_BIGNUM" => nil,
55
- "T_CLASS" => nil,
56
- "T_COMPLEX" => nil,
57
- "T_DATA" => nil,
58
- "T_FALSE" => nil,
59
- "T_FILE" => nil,
60
- "T_MODULE" => nil,
61
- "T_OBJECT" => nil,
62
- "T_RATIONAL" => nil,
63
- "T_REGEXP" => nil,
64
- "T_STRING" => nil,
65
- "T_STRUCT" => nil,
66
- "T_TRUE" => nil,
67
- } )
68
- end
69
-
70
- it "should retrieve particular conversions" do
71
- expect( tm['T_FIXNUM'] ).to eq(binaryenc_int)
72
- expect( tm['T_FLOAT'] ).to eq(textenc_float)
73
- expect( tm['T_BIGNUM'] ).to be_nil
74
- expect( derived_tm['T_REGEXP'] ).to be_kind_of(Proc)
75
- expect( derived_tm['T_ARRAY'] ).to eq(:array_type_map_for)
76
- end
77
-
78
- it "should allow deletion of coders" do
79
- tm['T_FIXNUM'] = nil
80
- expect( tm['T_FIXNUM'] ).to be_nil
81
- end
82
-
83
- it "should check MRI type key" do
84
- expect{ tm['NO_TYPE'] }.to raise_error(ArgumentError)
85
- expect{ tm[123] }.to raise_error(TypeError)
86
- expect{ tm['NO_TYPE'] = textenc_float }.to raise_error(ArgumentError)
87
- expect{ tm[123] = textenc_float }.to raise_error(TypeError)
88
- end
89
-
90
- it "forwards query param conversions to the #default_type_map" do
91
- tm1 = PG::TypeMapByColumn.new( [textenc_int, nil, nil] )
92
-
93
- tm2 = PG::TypeMapByMriType.new
94
- tm2['T_FIXNUM'] = PG::TextEncoder::Integer.new name: 'INT2', oid: 21
95
- tm2.default_type_map = tm1
96
-
97
- res = @conn.exec_params( "SELECT $1, $2, $3::TEXT", ['1', 2, 3], 0, tm2 )
98
-
99
- expect( res.ftype(0) ).to eq( 23 ) # tm1
100
- expect( res.ftype(1) ).to eq( 21 ) # tm2
101
- expect( res.getvalue(0,2) ).to eq( "3" ) # TypeMapAllStrings
102
- end
103
-
104
- #
105
- # Decoding Examples
106
- #
107
-
108
- it "should raise an error when used for results" do
109
- res = @conn.exec_params( "SELECT 1", [], 1 )
110
- expect{ res.type_map = tm }.to raise_error(NotImplementedError, /not suitable to map result values/)
111
- end
112
-
113
- #
114
- # Encoding Examples
115
- #
116
-
117
- it "should allow mixed type conversions" do
118
- res = @conn.exec_params( "SELECT $1, $2, $3", [5, 1.23, :TestSymbol], 0, tm )
119
- expect( res.values ).to eq([['5', '1.23', '[:TestSymbol]']])
120
- expect( res.ftype(0) ).to eq(20)
121
- end
122
-
123
- it "should allow mixed type conversions with derived type map" do
124
- res = @conn.exec_params( "SELECT $1, $2", [6, [7]], 0, derived_tm )
125
- expect( res.values ).to eq([['6', '{7}']])
126
- expect( res.ftype(0) ).to eq(23)
127
- expect( res.ftype(1) ).to eq(1007)
128
- end
129
-
130
- it "should raise TypeError with derived type map" do
131
- expect{
132
- @conn.exec_params( "SELECT $1", [//], 0, derived_tm )
133
- }.to raise_error(TypeError, /argument 1/)
134
- end
135
-
136
- end
@@ -1,149 +0,0 @@
1
- #!/usr/bin/env rspec
2
- # encoding: utf-8
3
-
4
- require_relative '../helpers'
5
-
6
- require 'pg'
7
-
8
-
9
- describe PG::TypeMapByOid do
10
-
11
- let!(:textdec_int){ PG::TextDecoder::Integer.new name: 'INT4', oid: 23 }
12
- let!(:textdec_float){ PG::TextDecoder::Float.new name: 'FLOAT8', oid: 701 }
13
- let!(:textdec_string){ PG::TextDecoder::String.new name: 'TEXT', oid: 25 }
14
- let!(:textdec_bytea){ PG::TextDecoder::Bytea.new name: 'BYTEA', oid: 17 }
15
- let!(:binarydec_float){ PG::BinaryDecoder::Float.new name: 'FLOAT8', oid: 701, format: 1 }
16
- let!(:pass_through_type) do
17
- type = Class.new(PG::SimpleDecoder) do
18
- def decode(*v)
19
- v
20
- end
21
- end.new
22
- type.oid = 1082
23
- type.format = 0
24
- type.name = 'pass_through'
25
- type
26
- end
27
-
28
- let!(:tm) do
29
- tm = PG::TypeMapByOid.new
30
- tm.add_coder textdec_int
31
- tm.add_coder textdec_float
32
- tm.add_coder binarydec_float
33
- tm.add_coder pass_through_type
34
- tm
35
- end
36
-
37
- it "should retrieve it's conversions" do
38
- expect( tm.coders ).to eq( [
39
- textdec_int,
40
- textdec_float,
41
- pass_through_type,
42
- binarydec_float,
43
- ] )
44
- end
45
-
46
- it "should allow deletion of coders" do
47
- expect( tm.rm_coder 0, 701 ).to eq(textdec_float)
48
- expect( tm.rm_coder 0, 701 ).to eq(nil)
49
- expect( tm.rm_coder 1, 701 ).to eq(binarydec_float)
50
- expect( tm.coders ).to eq( [
51
- textdec_int,
52
- pass_through_type,
53
- ] )
54
- end
55
-
56
- it "should check format when deleting coders" do
57
- expect{ tm.rm_coder 2, 123 }.to raise_error(ArgumentError)
58
- expect{ tm.rm_coder -1, 123 }.to raise_error(ArgumentError)
59
- end
60
-
61
- it "should check format when adding coders" do
62
- textdec_int.format = 2
63
- expect{ tm.add_coder textdec_int }.to raise_error(ArgumentError)
64
- textdec_int.format = -1
65
- expect{ tm.add_coder textdec_int }.to raise_error(ArgumentError)
66
- end
67
-
68
- it "should check coder type when adding coders" do
69
- expect{ tm.add_coder :dummy }.to raise_error(ArgumentError)
70
- end
71
-
72
- it "should allow reading and writing max_rows_for_online_lookup" do
73
- expect( tm.max_rows_for_online_lookup ).to eq(10)
74
- tm.max_rows_for_online_lookup = 5
75
- expect( tm.max_rows_for_online_lookup ).to eq(5)
76
- end
77
-
78
- it "should allow building new TypeMapByColumn for a given result" do
79
- res = @conn.exec( "SELECT 1, 'a', 2.0::FLOAT, '2013-06-30'::DATE" )
80
- tm2 = tm.build_column_map(res)
81
- expect( tm2 ).to be_a_kind_of(PG::TypeMapByColumn)
82
- expect( tm2.coders ).to eq( [textdec_int, nil, textdec_float, pass_through_type] )
83
- end
84
-
85
- it "forwards result value conversions to another TypeMapByOid as #default_type_map" do
86
- # One run with implicit built TypeMapByColumn and another with online lookup
87
- # for each type map.
88
- [[0, 0], [0, 10], [10, 0], [10, 10]].each do |max_rows1, max_rows2|
89
- tm1 = PG::TypeMapByOid.new
90
- tm1.add_coder PG::TextDecoder::Integer.new name: 'INT2', oid: 21
91
- tm1.max_rows_for_online_lookup = max_rows1
92
-
93
- tm2 = PG::TypeMapByOid.new
94
- tm2.add_coder PG::TextDecoder::Integer.new name: 'INT4', oid: 23
95
- tm2.max_rows_for_online_lookup = max_rows2
96
- tm2.default_type_map = tm1
97
-
98
- res = @conn.exec( "SELECT '1'::INT4, '2'::INT2, '3'::INT8" ).map_types!( tm2 )
99
-
100
- expect( res.getvalue(0,0) ).to eq( 1 ) # tm2
101
- expect( res.getvalue(0,1) ).to eq( 2 ) # tm1
102
- expect( res.getvalue(0,2) ).to eq( "3" ) # TypeMapAllStrings
103
- end
104
- end
105
-
106
- #
107
- # Decoding Examples text format
108
- #
109
-
110
- it "should allow mixed type conversions in text format" do
111
- res = @conn.exec( "SELECT 1, 'a', 2.0::FLOAT, '2013-06-30'::DATE" )
112
- res.type_map = tm
113
- expect( res.values ).to eq( [[1, 'a', 2.0, ['2013-06-30', 0, 3] ]] )
114
- end
115
-
116
- it "should build a TypeMapByColumn when assigned and the number of rows is high enough" do
117
- res = @conn.exec( "SELECT generate_series(1,20), 'a', 2.0::FLOAT, '2013-06-30'::DATE" )
118
- res.type_map = tm
119
- expect( res.type_map ).to be_kind_of( PG::TypeMapByColumn )
120
- expect( res.type_map.coders ).to eq( [textdec_int, nil, textdec_float, pass_through_type] )
121
- end
122
-
123
- it "should use TypeMapByOid for online lookup and the number of rows is low enough" do
124
- res = @conn.exec( "SELECT 1, 'a', 2.0::FLOAT, '2013-06-30'::DATE" )
125
- res.type_map = tm
126
- expect( res.type_map ).to be_kind_of( PG::TypeMapByOid )
127
- end
128
-
129
- #
130
- # Decoding Examples binary format
131
- #
132
-
133
- it "should allow mixed type conversions in binary format" do
134
- res = @conn.exec_params( "SELECT 1, 2.0::FLOAT", [], 1 )
135
- res.type_map = tm
136
- expect( res.values ).to eq( [["\x00\x00\x00\x01", 2.0 ]] )
137
- end
138
-
139
- #
140
- # Encoding Examples
141
- #
142
-
143
- it "should raise an error used for query params" do
144
- expect{
145
- @conn.exec_params( "SELECT $1", [5], 0, tm )
146
- }.to raise_error(NotImplementedError, /not suitable to map query params/)
147
- end
148
-
149
- end
@@ -1,164 +0,0 @@
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
@@ -1,22 +0,0 @@
1
- #!/usr/bin/env rspec
2
- # encoding: utf-8
3
-
4
- require_relative '../helpers'
5
-
6
- require 'pg'
7
-
8
-
9
- describe PG::TypeMap do
10
- let!(:tm){ PG::TypeMap.new }
11
-
12
- it "should raise an error when used for param type casts" do
13
- expect{
14
- @conn.exec_params( "SELECT $1", [5], 0, tm )
15
- }.to raise_error(NotImplementedError, /not suitable to map query params/)
16
- end
17
-
18
- it "should raise an error when used for result type casts" do
19
- res = @conn.exec( "SELECT 1" )
20
- expect{ res.map_types!(tm) }.to raise_error(NotImplementedError, /not suitable to map result values/)
21
- end
22
- end