pg 0.18.0.pre20141017160319 → 0.18.0.pre20141117110243
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gemtest +0 -0
- data/ChangeLog +213 -15
- data/History.rdoc +15 -0
- data/Manifest.txt +2 -0
- data/README.rdoc +1 -1
- data/Rakefile +0 -17
- data/ext/extconf.rb +2 -0
- data/ext/pg.c +67 -1
- data/ext/pg.h +50 -13
- data/ext/pg_binary_decoder.c +4 -4
- data/ext/pg_binary_encoder.c +1 -1
- data/ext/pg_coder.c +6 -0
- data/ext/pg_connection.c +50 -55
- data/ext/pg_copy_coder.c +13 -29
- data/ext/pg_errors.c +6 -0
- data/ext/pg_result.c +273 -77
- data/ext/pg_text_decoder.c +1 -1
- data/ext/pg_text_encoder.c +44 -1
- data/ext/pg_type_map.c +85 -14
- data/ext/pg_type_map_all_strings.c +16 -13
- data/ext/pg_type_map_by_class.c +239 -0
- data/ext/pg_type_map_by_column.c +81 -23
- data/ext/pg_type_map_by_mri_type.c +42 -24
- data/ext/pg_type_map_by_oid.c +52 -20
- data/ext/util.c +1 -1
- data/lib/pg.rb +3 -3
- data/lib/pg/basic_type_mapping.rb +13 -13
- data/lib/pg/coder.rb +9 -0
- data/sample/disk_usage_report.rb +1 -1
- data/sample/pg_statistics.rb +1 -1
- data/sample/replication_monitor.rb +1 -1
- data/spec/helpers.rb +5 -3
- data/spec/pg/basic_type_mapping_spec.rb +1 -1
- data/spec/pg/connection_spec.rb +16 -5
- data/spec/pg/result_spec.rb +77 -3
- data/spec/pg/type_map_by_class_spec.rb +138 -0
- data/spec/pg/type_map_by_column_spec.rb +87 -0
- data/spec/pg/type_map_by_mri_type_spec.rb +14 -0
- data/spec/pg/type_map_by_oid_spec.rb +21 -0
- data/spec/pg/type_spec.rb +27 -7
- data/spec/pg_spec.rb +14 -0
- metadata +24 -21
- metadata.gz.sig +0 -0
data/ext/util.c
CHANGED
data/lib/pg.rb
CHANGED
@@ -10,7 +10,7 @@ rescue LoadError
|
|
10
10
|
|
11
11
|
# Set the PATH environment variable, so that libpq.dll can be found.
|
12
12
|
old_path = ENV['PATH']
|
13
|
-
ENV['PATH'] = "#{
|
13
|
+
ENV['PATH'] = "#{File.expand_path("../#{RUBY_PLATFORM}", __FILE__)};#{old_path}"
|
14
14
|
require "#{major_minor}/pg_ext"
|
15
15
|
ENV['PATH'] = old_path
|
16
16
|
else
|
@@ -24,10 +24,10 @@ end
|
|
24
24
|
module PG
|
25
25
|
|
26
26
|
# Library version
|
27
|
-
VERSION = '0.18.0'
|
27
|
+
VERSION = '0.18.0.pre20141117110243'
|
28
28
|
|
29
29
|
# VCS revision
|
30
|
-
REVISION = %q$Revision
|
30
|
+
REVISION = %q$Revision$
|
31
31
|
|
32
32
|
class NotAllCopyDataRetrieved < PG::Error
|
33
33
|
end
|
@@ -304,7 +304,7 @@ end
|
|
304
304
|
# # Execute a query. The Integer param value is typecasted internally by PG::BinaryEncoder::Int8.
|
305
305
|
# # The format of the parameter is set to 1 (binary) and the OID of this parameter is set to 20 (int8).
|
306
306
|
# res = conn.exec_params( "SELECT $1", [5] )
|
307
|
-
class PG::BasicTypeMapForQueries < PG::
|
307
|
+
class PG::BasicTypeMapForQueries < PG::TypeMapByClass
|
308
308
|
include PG::BasicTypeRegistry
|
309
309
|
|
310
310
|
def initialize(connection)
|
@@ -323,7 +323,7 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByMriType
|
|
323
323
|
end
|
324
324
|
|
325
325
|
def populate_encoder_list
|
326
|
-
DEFAULT_TYPE_MAP.each do |
|
326
|
+
DEFAULT_TYPE_MAP.each do |klass, selector|
|
327
327
|
if Array === selector
|
328
328
|
format, name, oid_name = selector
|
329
329
|
coder = coder_by_name(format, :encoder, name).dup
|
@@ -332,9 +332,9 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByMriType
|
|
332
332
|
else
|
333
333
|
coder.oid = 0
|
334
334
|
end
|
335
|
-
self[
|
335
|
+
self[klass] = coder
|
336
336
|
else
|
337
|
-
self[
|
337
|
+
self[klass] = selector
|
338
338
|
end
|
339
339
|
end
|
340
340
|
end
|
@@ -351,25 +351,25 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByMriType
|
|
351
351
|
while elem.kind_of?(Array)
|
352
352
|
elem = elem.first
|
353
353
|
end
|
354
|
-
@array_encoders_by_klass[elem.class] ||
|
354
|
+
@array_encoders_by_klass[elem.class] ||
|
355
|
+
elem.class.ancestors.lazy.map{|ancestor| @array_encoders_by_klass[ancestor] }.find{|a| a } ||
|
356
|
+
@anyarray_encoder
|
355
357
|
end
|
356
358
|
|
357
359
|
DEFAULT_TYPE_MAP = {
|
358
|
-
|
359
|
-
|
360
|
+
TrueClass => [1, 'bool', 'bool'],
|
361
|
+
FalseClass => [1, 'bool', 'bool'],
|
360
362
|
# We use text format and no type OID for numbers, because setting the OID can lead
|
361
363
|
# to unnecessary type conversions on server side.
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
'T_ARRAY'.freeze => :get_array_type,
|
364
|
+
Integer => [0, 'int8'],
|
365
|
+
Float => [0, 'float8'],
|
366
|
+
Array => :get_array_type,
|
366
367
|
}
|
367
368
|
|
368
369
|
DEFAULT_ARRAY_TYPE_MAP = {
|
369
370
|
TrueClass => [0, '_bool'],
|
370
371
|
FalseClass => [0, '_bool'],
|
371
|
-
|
372
|
-
Bignum => [0, '_int8'],
|
372
|
+
Integer => [0, '_int8'],
|
373
373
|
String => [0, '_text'],
|
374
374
|
Float => [0, '_float8'],
|
375
375
|
}
|
data/lib/pg/coder.rb
CHANGED
@@ -3,6 +3,15 @@
|
|
3
3
|
module PG
|
4
4
|
|
5
5
|
class Coder
|
6
|
+
|
7
|
+
module BinaryFormatting
|
8
|
+
Params = { format: 1 }
|
9
|
+
def initialize( params={} )
|
10
|
+
super(params.merge(Params))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
6
15
|
# Create a new coder object based on the attribute Hash.
|
7
16
|
def initialize(params={})
|
8
17
|
params.each do |key, val|
|
data/sample/disk_usage_report.rb
CHANGED
data/sample/pg_statistics.rb
CHANGED
@@ -36,7 +36,7 @@ end
|
|
36
36
|
###
|
37
37
|
class PGMonitor
|
38
38
|
|
39
|
-
VERSION = %q$Id
|
39
|
+
VERSION = %q$Id$
|
40
40
|
|
41
41
|
# When to consider a slave as 'behind', measured in WAL segments.
|
42
42
|
# The default WAL segment size is 16, so we'll alert after
|
data/spec/helpers.rb
CHANGED
@@ -343,11 +343,13 @@ RSpec.configure do |config|
|
|
343
343
|
PG::Connection.instance_methods.map( &:to_sym ).include?( :escape_literal )
|
344
344
|
|
345
345
|
if !PG.respond_to?( :library_version )
|
346
|
-
config.filter_run_excluding( :postgresql_91, :postgresql_92, :postgresql_93 )
|
346
|
+
config.filter_run_excluding( :postgresql_91, :postgresql_92, :postgresql_93, :postgresql_94 )
|
347
347
|
elsif PG.library_version < 90200
|
348
|
-
config.filter_run_excluding( :postgresql_92, :postgresql_93 )
|
348
|
+
config.filter_run_excluding( :postgresql_92, :postgresql_93, :postgresql_94 )
|
349
349
|
elsif PG.library_version < 90300
|
350
|
-
config.filter_run_excluding( :postgresql_93 )
|
350
|
+
config.filter_run_excluding( :postgresql_93, :postgresql_94 )
|
351
|
+
elsif PG.library_version < 90400
|
352
|
+
config.filter_run_excluding( :postgresql_94 )
|
351
353
|
end
|
352
354
|
end
|
353
355
|
|
data/spec/pg/connection_spec.rb
CHANGED
@@ -157,6 +157,17 @@ describe PG::Connection do
|
|
157
157
|
expect( res[0]['n'] ).to eq( '1' )
|
158
158
|
end
|
159
159
|
|
160
|
+
it "can retrieve it's connection parameters for the established connection" do
|
161
|
+
expect( @conn.db ).to eq( "test" )
|
162
|
+
expect( @conn.user ).to be_a_kind_of( String )
|
163
|
+
expect( @conn.pass ).to eq( "" )
|
164
|
+
expect( @conn.host ).to eq( "localhost" )
|
165
|
+
# TODO: Not sure why libpq returns a NULL ptr instead of "127.0.0.1"
|
166
|
+
expect( @conn.hostaddr ).to eq( nil ) if @conn.server_version >= 9_04_00
|
167
|
+
expect( @conn.port ).to eq( 54321 )
|
168
|
+
expect( @conn.tty ).to eq( "" )
|
169
|
+
expect( @conn.options ).to eq( "" )
|
170
|
+
end
|
160
171
|
|
161
172
|
EXPECTED_TRACE_OUTPUT = %{
|
162
173
|
To backend> Msg Q
|
@@ -1293,8 +1304,8 @@ describe PG::Connection do
|
|
1293
1304
|
end
|
1294
1305
|
|
1295
1306
|
it "should return nil if no type mapping is set" do
|
1296
|
-
expect( @conn.type_map_for_queries ).to
|
1297
|
-
expect( @conn.type_map_for_results ).to
|
1307
|
+
expect( @conn.type_map_for_queries ).to be_kind_of(PG::TypeMapAllStrings)
|
1308
|
+
expect( @conn.type_map_for_results ).to be_kind_of(PG::TypeMapAllStrings)
|
1298
1309
|
end
|
1299
1310
|
|
1300
1311
|
it "shouldn't type map params unless requested" do
|
@@ -1331,8 +1342,8 @@ describe PG::Connection do
|
|
1331
1342
|
context "with default query type map" do
|
1332
1343
|
before :each do
|
1333
1344
|
@conn2 = described_class.new(@conninfo)
|
1334
|
-
tm = PG::
|
1335
|
-
tm[
|
1345
|
+
tm = PG::TypeMapByClass.new
|
1346
|
+
tm[Integer] = PG::TextEncoder::Integer.new oid: 20
|
1336
1347
|
@conn2.type_map_for_queries = tm
|
1337
1348
|
|
1338
1349
|
row_encoder = PG::TextEncoder::CopyRow.new type_map: tm
|
@@ -1349,7 +1360,7 @@ describe PG::Connection do
|
|
1349
1360
|
end
|
1350
1361
|
|
1351
1362
|
it "should return the current type mapping" do
|
1352
|
-
expect( @conn2.type_map_for_queries ).to be_kind_of(PG::
|
1363
|
+
expect( @conn2.type_map_for_queries ).to be_kind_of(PG::TypeMapByClass)
|
1353
1364
|
end
|
1354
1365
|
|
1355
1366
|
it "should work with arbitrary number of params in conjunction with type casting" do
|
data/spec/pg/result_spec.rb
CHANGED
@@ -21,6 +21,80 @@ describe PG::Result do
|
|
21
21
|
expect( list ).to eq [['1', '2']]
|
22
22
|
end
|
23
23
|
|
24
|
+
it "yields a row as an Enumerator" do
|
25
|
+
res = @conn.exec("SELECT 1 AS a, 2 AS b")
|
26
|
+
e = res.each_row
|
27
|
+
expect( e ).to be_a_kind_of(Enumerator)
|
28
|
+
pending "Rubinius doesn't define RETURN_SIZED_ENUMERATOR()" if RUBY_ENGINE=='rbx'
|
29
|
+
expect( e.size ).to eq( 1 )
|
30
|
+
expect( e.to_a ).to eq [['1', '2']]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "yields a row as an Enumerator of hashs" do
|
34
|
+
res = @conn.exec("SELECT 1 AS a, 2 AS b")
|
35
|
+
e = res.each
|
36
|
+
expect( e ).to be_a_kind_of(Enumerator)
|
37
|
+
pending "Rubinius doesn't define RETURN_SIZED_ENUMERATOR()" if RUBY_ENGINE=='rbx'
|
38
|
+
expect( e.size ).to eq( 1 )
|
39
|
+
expect( e.to_a ).to eq [{'a'=>'1', 'b'=>'2'}]
|
40
|
+
end
|
41
|
+
|
42
|
+
context "result streaming", :postgresql_92 do
|
43
|
+
it "can iterate over all tuples in single row mode" do
|
44
|
+
@conn.send_query( "SELECT generate_series(2,4) AS a; SELECT 1 AS b, generate_series(5,6) AS c" )
|
45
|
+
@conn.set_single_row_mode
|
46
|
+
expect(
|
47
|
+
@conn.get_result.stream_each.to_a
|
48
|
+
).to eq(
|
49
|
+
[{'a'=>"2"}, {'a'=>"3"}, {'a'=>"4"}]
|
50
|
+
)
|
51
|
+
expect(
|
52
|
+
@conn.get_result.enum_for(:stream_each).to_a
|
53
|
+
).to eq(
|
54
|
+
[{'b'=>"1", 'c'=>"5"}, {'b'=>"1", 'c'=>"6"}]
|
55
|
+
)
|
56
|
+
expect( @conn.get_result ).to be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "can iterate over all rows in single row mode" do
|
60
|
+
@conn.send_query( "SELECT generate_series(2,4) AS a; SELECT 1 AS b, generate_series(5,6) AS c" )
|
61
|
+
@conn.set_single_row_mode
|
62
|
+
expect(
|
63
|
+
@conn.get_result.enum_for(:stream_each_row).to_a
|
64
|
+
).to eq(
|
65
|
+
[["2"], ["3"], ["4"]]
|
66
|
+
)
|
67
|
+
expect(
|
68
|
+
@conn.get_result.stream_each_row.to_a
|
69
|
+
).to eq(
|
70
|
+
[["1", "5"], ["1", "6"]]
|
71
|
+
)
|
72
|
+
expect( @conn.get_result ).to be_nil
|
73
|
+
end
|
74
|
+
|
75
|
+
it "complains when not in single row mode" do
|
76
|
+
@conn.send_query( "SELECT generate_series(2,4)" )
|
77
|
+
expect{
|
78
|
+
@conn.get_result.stream_each_row.to_a
|
79
|
+
}.to raise_error(PG::InvalidResultStatus, /not in single row mode/)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "complains when intersected with get_result" do
|
83
|
+
@conn.send_query( "SELECT 1" )
|
84
|
+
@conn.set_single_row_mode
|
85
|
+
expect{
|
86
|
+
@conn.get_result.stream_each_row.each{ @conn.get_result }
|
87
|
+
}.to raise_error(PG::NoResultError, /no result received/)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "raises server errors" do
|
91
|
+
@conn.send_query( "SELECT 0/0" )
|
92
|
+
expect{
|
93
|
+
@conn.get_result.stream_each_row.to_a
|
94
|
+
}.to raise_error(PG::DivisionByZero)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
24
98
|
it "inserts nil AS NULL and return NULL as nil" do
|
25
99
|
res = @conn.exec("SELECT $1::int AS n", [nil])
|
26
100
|
expect( res[0]['n'] ).to be_nil()
|
@@ -335,14 +409,14 @@ describe PG::Result do
|
|
335
409
|
|
336
410
|
it "should allow reading, assigning and diabling type conversions" do
|
337
411
|
res = @conn.exec( "SELECT 123" )
|
338
|
-
expect( res.type_map ).to
|
412
|
+
expect( res.type_map ).to be_kind_of(PG::TypeMapAllStrings)
|
339
413
|
res.type_map = PG::TypeMapByColumn.new [textdec_int]
|
340
414
|
expect( res.type_map ).to be_an_instance_of(PG::TypeMapByColumn)
|
341
415
|
expect( res.type_map.coders ).to eq( [textdec_int] )
|
342
416
|
res.type_map = PG::TypeMapByColumn.new [textdec_float]
|
343
417
|
expect( res.type_map.coders ).to eq( [textdec_float] )
|
344
|
-
res.type_map =
|
345
|
-
expect( res.type_map ).to
|
418
|
+
res.type_map = PG::TypeMapAllStrings.new
|
419
|
+
expect( res.type_map ).to be_kind_of(PG::TypeMapAllStrings)
|
346
420
|
end
|
347
421
|
|
348
422
|
it "should be applied to all value retrieving methods" do
|
@@ -0,0 +1,138 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require_relative '../helpers'
|
5
|
+
|
6
|
+
require 'pg'
|
7
|
+
|
8
|
+
|
9
|
+
describe PG::TypeMapByClass 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::TypeMapByClass.new
|
29
|
+
tm[Integer] = binaryenc_int
|
30
|
+
tm[Float] = textenc_float
|
31
|
+
tm[Symbol] = pass_through_type
|
32
|
+
tm
|
33
|
+
end
|
34
|
+
|
35
|
+
let!(:raise_class) do
|
36
|
+
Class.new
|
37
|
+
end
|
38
|
+
|
39
|
+
let!(:derived_tm) do
|
40
|
+
tm = Class.new(PG::TypeMapByClass) do
|
41
|
+
def array_type_map_for(value)
|
42
|
+
PG::TextEncoder::Array.new name: '_INT4', oid: 1007, elements_type: PG::TextEncoder::Integer.new
|
43
|
+
end
|
44
|
+
end.new
|
45
|
+
tm[Integer] = proc{|value| textenc_int }
|
46
|
+
tm[raise_class] = proc{|value| /invalid/ }
|
47
|
+
tm[Array] = :array_type_map_for
|
48
|
+
tm
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should retrieve all conversions" do
|
52
|
+
expect( tm.coders ).to eq( {
|
53
|
+
Integer => binaryenc_int,
|
54
|
+
Float => textenc_float,
|
55
|
+
Symbol => pass_through_type,
|
56
|
+
} )
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should retrieve particular conversions" do
|
60
|
+
expect( tm[Integer] ).to eq(binaryenc_int)
|
61
|
+
expect( tm[Float] ).to eq(textenc_float)
|
62
|
+
expect( tm[Bignum] ).to be_nil
|
63
|
+
expect( derived_tm[raise_class] ).to be_kind_of(Proc)
|
64
|
+
expect( derived_tm[Array] ).to eq(:array_type_map_for)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should allow deletion of coders" do
|
68
|
+
tm[Integer] = nil
|
69
|
+
expect( tm[Integer] ).to be_nil
|
70
|
+
expect( tm.coders ).to eq( {
|
71
|
+
Float => textenc_float,
|
72
|
+
Symbol => pass_through_type,
|
73
|
+
} )
|
74
|
+
end
|
75
|
+
|
76
|
+
it "forwards query param conversions to the #default_type_map" do
|
77
|
+
tm1 = PG::TypeMapByColumn.new( [textenc_int, nil, nil] )
|
78
|
+
|
79
|
+
tm2 = PG::TypeMapByClass.new
|
80
|
+
tm2[Integer] = PG::TextEncoder::Integer.new name: 'INT2', oid: 21
|
81
|
+
tm2.default_type_map = tm1
|
82
|
+
|
83
|
+
res = @conn.exec_params( "SELECT $1, $2, $3::TEXT", ['1', 2, 3], 0, tm2 )
|
84
|
+
|
85
|
+
expect( res.ftype(0) ).to eq( 23 ) # tm1
|
86
|
+
expect( res.ftype(1) ).to eq( 21 ) # tm2
|
87
|
+
expect( res.getvalue(0,2) ).to eq( "3" ) # TypeMapAllStrings
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Decoding Examples
|
92
|
+
#
|
93
|
+
|
94
|
+
it "should raise an error when used for results" do
|
95
|
+
res = @conn.exec_params( "SELECT 1", [], 1 )
|
96
|
+
expect{ res.type_map = tm }.to raise_error(NotImplementedError, /not suitable to map result values/)
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# Encoding Examples
|
101
|
+
#
|
102
|
+
|
103
|
+
it "should allow mixed type conversions" do
|
104
|
+
res = @conn.exec_params( "SELECT $1, $2, $3", [5, 1.23, :TestSymbol], 0, tm )
|
105
|
+
expect( res.values ).to eq([['5', '1.23', '[:TestSymbol]']])
|
106
|
+
expect( res.ftype(0) ).to eq(20)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should expire the cache after changes to the coders" do
|
110
|
+
res = @conn.exec_params( "SELECT $1", [5], 0, tm )
|
111
|
+
expect( res.ftype(0) ).to eq(20)
|
112
|
+
|
113
|
+
tm[Integer] = textenc_int
|
114
|
+
|
115
|
+
res = @conn.exec_params( "SELECT $1", [5], 0, tm )
|
116
|
+
expect( res.ftype(0) ).to eq(23)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should allow mixed type conversions with derived type map" do
|
120
|
+
res = @conn.exec_params( "SELECT $1, $2", [6, [7]], 0, derived_tm )
|
121
|
+
expect( res.values ).to eq([['6', '{7}']])
|
122
|
+
expect( res.ftype(0) ).to eq(23)
|
123
|
+
expect( res.ftype(1) ).to eq(1007)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should raise TypeError with derived type map" do
|
127
|
+
expect{
|
128
|
+
@conn.exec_params( "SELECT $1", [raise_class.new], 0, derived_tm )
|
129
|
+
}.to raise_error(TypeError, /invalid type Regexp/)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should raise error on invalid coder object" do
|
133
|
+
tm[TrueClass] = "dummy"
|
134
|
+
expect{
|
135
|
+
res = @conn.exec_params( "SELECT $1", [true], 0, tm )
|
136
|
+
}.to raise_error(NoMethodError, /undefined method.*call.*dummy/)
|
137
|
+
end
|
138
|
+
end
|