pg 1.1.0.pre20180730171000 → 1.1.4
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/ChangeLog +6595 -0
- data/History.rdoc +24 -6
- data/Manifest.txt +70 -2
- data/Rakefile +2 -3
- data/Rakefile.cross +3 -3
- data/ext/errorcodes.def +4 -0
- data/ext/errorcodes.txt +2 -1
- data/ext/pg.c +9 -4
- data/ext/pg.h +18 -6
- data/ext/pg_binary_decoder.c +10 -6
- data/ext/pg_binary_encoder.c +1 -1
- data/ext/pg_connection.c +31 -29
- data/ext/pg_result.c +2 -0
- data/ext/pg_text_decoder.c +1 -1
- data/ext/pg_text_encoder.c +6 -7
- data/ext/pg_tuple.c +4 -3
- data/ext/pg_type_map.c +1 -1
- data/ext/pg_type_map_all_strings.c +1 -1
- data/ext/pg_type_map_by_class.c +1 -1
- data/ext/pg_type_map_by_column.c +1 -1
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +1 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/ext/util.c +1 -1
- data/lib/pg.rb +2 -2
- data/spec/helpers.rb +8 -8
- data/spec/pg/basic_type_mapping_spec.rb +5 -5
- data/spec/pg/connection_spec.rb +131 -17
- data/spec/pg/tuple_spec.rb +16 -2
- data/spec/pg/type_spec.rb +6 -0
- metadata +38 -79
- metadata.gz.sig +0 -0
- data/.gems +0 -6
- data/.hgignore +0 -21
- data/.hgsigs +0 -29
- data/.hgtags +0 -36
- data/.hoerc +0 -2
- data/.irbrc +0 -23
- data/.pryrc +0 -23
- data/.tm_properties +0 -21
- data/.travis.yml +0 -41
- data/Gemfile +0 -2
- data/appveyor.yml +0 -50
- data/certs/ged.pem +0 -26
- data/misc/openssl-pg-segfault.rb +0 -31
- data/misc/postgres/History.txt +0 -9
- data/misc/postgres/Manifest.txt +0 -5
- data/misc/postgres/README.txt +0 -21
- data/misc/postgres/Rakefile +0 -21
- data/misc/postgres/lib/postgres.rb +0 -16
- data/misc/ruby-pg/History.txt +0 -9
- data/misc/ruby-pg/Manifest.txt +0 -5
- data/misc/ruby-pg/README.txt +0 -21
- data/misc/ruby-pg/Rakefile +0 -21
- data/misc/ruby-pg/lib/ruby/pg.rb +0 -16
- data/pg.gemspec +0 -61
- data/sample/array_insert.rb +0 -20
- data/sample/async_api.rb +0 -106
- data/sample/async_copyto.rb +0 -39
- data/sample/async_mixed.rb +0 -56
- data/sample/check_conn.rb +0 -21
- data/sample/copydata.rb +0 -71
- data/sample/copyfrom.rb +0 -81
- data/sample/copyto.rb +0 -19
- data/sample/cursor.rb +0 -21
- data/sample/disk_usage_report.rb +0 -177
- data/sample/issue-119.rb +0 -94
- data/sample/losample.rb +0 -69
- data/sample/minimal-testcase.rb +0 -17
- data/sample/notify_wait.rb +0 -72
- data/sample/pg_statistics.rb +0 -285
- data/sample/replication_monitor.rb +0 -222
- data/sample/test_binary_values.rb +0 -33
- data/sample/wal_shipper.rb +0 -434
- data/sample/warehouse_partitions.rb +0 -311
data/ext/pg_result.c
CHANGED
@@ -419,6 +419,8 @@ static void pgresult_init_fnames(VALUE self)
|
|
419
419
|
*
|
420
420
|
* The class to represent the query result tuples (rows).
|
421
421
|
* An instance of this class is created as the result of every query.
|
422
|
+
* All result rows and columns are stored in a memory block attached to the PG::Result object.
|
423
|
+
* Whenever a value is accessed it is casted to a Ruby object by the assigned #type_map .
|
422
424
|
*
|
423
425
|
* Since pg-1.1 the amount of memory in use by a PG::Result object is estimated and passed to ruby's garbage collector.
|
424
426
|
* You can invoke the #clear method to force deallocation of memory of the instance when finished with the result for better memory performance.
|
data/ext/pg_text_decoder.c
CHANGED
data/ext/pg_text_encoder.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_text_encoder.c - PG::TextEncoder module
|
3
|
-
* $Id$
|
3
|
+
* $Id: pg_text_encoder.c,v e57f6b452eb3 2018/08/18 10:58:52 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -468,20 +468,19 @@ pg_text_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
468
468
|
static char *
|
469
469
|
quote_identifier( VALUE value, VALUE out_string, char *current_out ){
|
470
470
|
char *p_in = RSTRING_PTR(value);
|
471
|
-
char *ptr1;
|
472
471
|
size_t strlen = RSTRING_LEN(value);
|
472
|
+
char *p_inend = p_in + strlen;
|
473
473
|
char *end_capa = current_out;
|
474
474
|
|
475
475
|
PG_RB_STR_ENSURE_CAPA( out_string, strlen + 2, current_out, end_capa );
|
476
476
|
*current_out++ = '"';
|
477
|
-
for(
|
478
|
-
char c = *
|
477
|
+
for(; p_in != p_inend; p_in++) {
|
478
|
+
char c = *p_in;
|
479
479
|
if (c == '"'){
|
480
|
-
|
481
|
-
PG_RB_STR_ENSURE_CAPA( out_string, p_in - ptr1 + strlen + 1, current_out, end_capa );
|
480
|
+
PG_RB_STR_ENSURE_CAPA( out_string, p_inend - p_in + 2, current_out, end_capa );
|
482
481
|
*current_out++ = '"';
|
483
482
|
} else if (c == 0){
|
484
|
-
|
483
|
+
rb_raise(rb_eArgError, "string contains null byte");
|
485
484
|
}
|
486
485
|
*current_out++ = c;
|
487
486
|
}
|
data/ext/pg_tuple.c
CHANGED
@@ -311,9 +311,9 @@ pg_tuple_yield_key_value(VALUE key, VALUE index, VALUE _this)
|
|
311
311
|
|
312
312
|
/*
|
313
313
|
* call-seq:
|
314
|
-
* tup.each{ |value| ... }
|
314
|
+
* tup.each{ |key, value| ... }
|
315
315
|
*
|
316
|
-
* Invokes block for each field value in the tuple.
|
316
|
+
* Invokes block for each field name and value in the tuple.
|
317
317
|
*/
|
318
318
|
static VALUE
|
319
319
|
pg_tuple_each(VALUE self)
|
@@ -354,7 +354,8 @@ pg_tuple_each_value(VALUE self)
|
|
354
354
|
RETURN_SIZED_ENUMERATOR(self, 0, NULL, pg_tuple_num_fields_for_enum);
|
355
355
|
|
356
356
|
for(field_num = 0; field_num < this->num_fields; field_num++) {
|
357
|
-
|
357
|
+
VALUE value = pg_tuple_materialize_field(this, field_num);
|
358
|
+
rb_yield(value);
|
358
359
|
}
|
359
360
|
|
360
361
|
pg_tuple_detach(this);
|
data/ext/pg_type_map.c
CHANGED
data/ext/pg_type_map_by_class.c
CHANGED
data/ext/pg_type_map_by_column.c
CHANGED
data/ext/pg_type_map_by_oid.c
CHANGED
data/ext/pg_type_map_in_ruby.c
CHANGED
data/ext/util.c
CHANGED
data/lib/pg.rb
CHANGED
data/spec/helpers.rb
CHANGED
@@ -22,6 +22,7 @@ module PG::TestingHelpers
|
|
22
22
|
|
23
23
|
mod.around( :each ) do |example|
|
24
24
|
begin
|
25
|
+
@conn.set_default_encoding
|
25
26
|
@conn.exec( 'BEGIN' ) unless example.metadata[:without_transaction]
|
26
27
|
desc = example.source_location.join(':')
|
27
28
|
@conn.exec %Q{SET application_name TO '%s'} %
|
@@ -197,8 +198,8 @@ module PG::TestingHelpers
|
|
197
198
|
@test_pgdata = TEST_DIRECTORY + 'data'
|
198
199
|
@test_pgdata.mkpath
|
199
200
|
|
200
|
-
|
201
|
-
ENV['PGPORT']
|
201
|
+
ENV['PGPORT'] ||= "54321"
|
202
|
+
@port = ENV['PGPORT'].to_i
|
202
203
|
ENV['PGHOST'] = 'localhost'
|
203
204
|
@conninfo = "host=localhost port=#{@port} dbname=test"
|
204
205
|
|
@@ -318,20 +319,19 @@ module PG::TestingHelpers
|
|
318
319
|
return ConnStillUsableMatcher.new
|
319
320
|
end
|
320
321
|
|
321
|
-
def wait_for_polling_ok(conn)
|
322
|
-
|
323
|
-
status = conn.connect_poll
|
322
|
+
def wait_for_polling_ok(conn, meth = :connect_poll)
|
323
|
+
status = conn.send(meth)
|
324
324
|
|
325
325
|
while status != PG::PGRES_POLLING_OK
|
326
326
|
if status == PG::PGRES_POLLING_READING
|
327
|
-
select( [
|
327
|
+
select( [conn.socket_io], [], [], 5.0 ) or
|
328
328
|
raise "Asynchronous connection timed out!"
|
329
329
|
|
330
330
|
elsif status == PG::PGRES_POLLING_WRITING
|
331
|
-
select( [], [
|
331
|
+
select( [], [conn.socket_io], [], 5.0 ) or
|
332
332
|
raise "Asynchronous connection timed out!"
|
333
333
|
end
|
334
|
-
status = conn.
|
334
|
+
status = conn.send(meth)
|
335
335
|
end
|
336
336
|
end
|
337
337
|
|
@@ -62,7 +62,7 @@ describe 'Basic type mapping' do
|
|
62
62
|
it "should do bigdecimal param encoding" do
|
63
63
|
large = ('123456790'*10) << '.' << ('012345679')
|
64
64
|
res = @conn.exec_params( "SELECT $1::numeric,$2::numeric",
|
65
|
-
[BigDecimal
|
65
|
+
[BigDecimal('1'), BigDecimal(large)], nil, basic_type_mapping )
|
66
66
|
|
67
67
|
expect( res.values ).to eq( [
|
68
68
|
[ "1.0", large ],
|
@@ -256,10 +256,10 @@ describe 'Basic type mapping' do
|
|
256
256
|
CAST('294276-12-31 23:58:59.1231+03' AS TIMESTAMP WITH TIME ZONE),
|
257
257
|
CAST('infinity' AS TIMESTAMP WITH TIME ZONE),
|
258
258
|
CAST('-infinity' AS TIMESTAMP WITH TIME ZONE)", [], format )
|
259
|
-
expect( res.getvalue(0,0)
|
260
|
-
expect( res.getvalue(0,1)
|
261
|
-
expect( res.getvalue(0,2)
|
262
|
-
expect( res.getvalue(0,3)
|
259
|
+
expect( res.getvalue(0,0) ).to be_within(1e-3).of( Time.new(2013, 12, 31, 23, 58, 59, "+02:00").getlocal )
|
260
|
+
expect( res.getvalue(0,1) ).to be_within(1e-3).of( Time.new(1913, 12, 31, 23, 58, 59.1231, "-03:00").getlocal )
|
261
|
+
expect( res.getvalue(0,2) ).to be_within(1e-3).of( Time.new(-4713, 11, 24, 23, 58, 59.1231, "-03:00").getlocal )
|
262
|
+
expect( res.getvalue(0,3) ).to be_within(1e-3).of( Time.new(294276, 12, 31, 23, 58, 59.1231, "+03:00").getlocal )
|
263
263
|
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
264
264
|
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
265
265
|
end
|
data/spec/pg/connection_spec.rb
CHANGED
@@ -228,6 +228,37 @@ describe PG::Connection do
|
|
228
228
|
|
229
229
|
res = @conn2.query("SELECT 4")
|
230
230
|
end
|
231
|
+
|
232
|
+
it "can use conn.reset_start to restart the connection" do
|
233
|
+
ios = IO.pipe
|
234
|
+
conn = described_class.connect_start( @conninfo )
|
235
|
+
wait_for_polling_ok(conn)
|
236
|
+
|
237
|
+
# Close the two pipe file descriptors, so that the file descriptor of
|
238
|
+
# newly established connection is probably distinct from the previous one.
|
239
|
+
ios.each(&:close)
|
240
|
+
conn.reset_start
|
241
|
+
wait_for_polling_ok(conn, :reset_poll)
|
242
|
+
|
243
|
+
# The new connection should work even when the file descriptor has changed.
|
244
|
+
conn.send_query("SELECT 1")
|
245
|
+
res = wait_for_query_result(conn)
|
246
|
+
expect( res.values ).to eq([["1"]])
|
247
|
+
|
248
|
+
conn.close
|
249
|
+
end
|
250
|
+
|
251
|
+
it "should properly close a socket IO when GC'ed" do
|
252
|
+
# This results in
|
253
|
+
# Errno::ENOTSOCK: An operation was attempted on something that is not a socket.
|
254
|
+
# on Windows when rb_w32_unwrap_io_handle() isn't called in pgconn_gc_free().
|
255
|
+
5.times do
|
256
|
+
conn = described_class.connect( @conninfo )
|
257
|
+
conn.socket_io.close
|
258
|
+
end
|
259
|
+
GC.start
|
260
|
+
IO.pipe.each(&:close)
|
261
|
+
end
|
231
262
|
end
|
232
263
|
|
233
264
|
it "raises proper error when sending fails" do
|
@@ -248,7 +279,7 @@ describe PG::Connection do
|
|
248
279
|
expect( @conn.db ).to eq( "test" )
|
249
280
|
expect( @conn.user ).to be_a_kind_of( String )
|
250
281
|
expect( @conn.pass ).to eq( "" )
|
251
|
-
expect( @conn.port ).to eq(
|
282
|
+
expect( @conn.port ).to eq( @port )
|
252
283
|
expect( @conn.tty ).to eq( "" )
|
253
284
|
expect( @conn.options ).to eq( "" )
|
254
285
|
end
|
@@ -734,7 +765,7 @@ describe PG::Connection do
|
|
734
765
|
it "can return the default connection options as a Hash" do
|
735
766
|
expect( described_class.conndefaults_hash ).to be_a( Hash )
|
736
767
|
expect( described_class.conndefaults_hash ).to include( :user, :password, :dbname, :host, :port )
|
737
|
-
expect( ['5432', '54321'] ).to include( described_class.conndefaults_hash[:port] )
|
768
|
+
expect( ['5432', '54321', @port.to_s] ).to include( described_class.conndefaults_hash[:port] )
|
738
769
|
expect( @conn.conndefaults_hash ).to eq( described_class.conndefaults_hash )
|
739
770
|
end
|
740
771
|
|
@@ -914,6 +945,20 @@ describe PG::Connection do
|
|
914
945
|
expect { conn.finish }.to raise_error( PG::ConnectionBad, /connection is closed/i )
|
915
946
|
end
|
916
947
|
|
948
|
+
it "can use conn.reset to restart the connection" do
|
949
|
+
ios = IO.pipe
|
950
|
+
conn = PG.connect( @conninfo )
|
951
|
+
|
952
|
+
# Close the two pipe file descriptors, so that the file descriptor of
|
953
|
+
# newly established connection is probably distinct from the previous one.
|
954
|
+
ios.each(&:close)
|
955
|
+
conn.reset
|
956
|
+
|
957
|
+
# The new connection should work even when the file descriptor has changed.
|
958
|
+
expect( conn.exec("SELECT 1").values ).to eq([["1"]])
|
959
|
+
conn.close
|
960
|
+
end
|
961
|
+
|
917
962
|
it "closes the IO fetched from #socket_io when the connection is closed", :without_transaction, :socket_io do
|
918
963
|
conn = PG.connect( @conninfo )
|
919
964
|
io = conn.socket_io
|
@@ -939,7 +984,7 @@ describe PG::Connection do
|
|
939
984
|
end
|
940
985
|
serv.close
|
941
986
|
expect{ conn.block }.to raise_error(PG::ConnectionBad, /server closed the connection unexpectedly/)
|
942
|
-
expect{ conn.block }.to raise_error(PG::ConnectionBad, /
|
987
|
+
expect{ conn.block }.to raise_error(PG::ConnectionBad, /can't get socket descriptor/)
|
943
988
|
end
|
944
989
|
|
945
990
|
it "sets the fallback_application_name on new connections" do
|
@@ -1110,8 +1155,16 @@ describe PG::Connection do
|
|
1110
1155
|
expect( ping ).to eq( PG::PQPING_NO_RESPONSE )
|
1111
1156
|
end
|
1112
1157
|
|
1113
|
-
it "returns
|
1158
|
+
it "returns error when ping connection arguments are wrong" do
|
1114
1159
|
ping = described_class.ping('localhost', 'localhost', nil, nil, :test, nil, nil)
|
1160
|
+
expect( ping ).to_not eq( PG::PQPING_OK )
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
it "returns correct response when ping connection arguments are wrong" do
|
1164
|
+
ping = described_class.ping(
|
1165
|
+
:host => 'localhost',
|
1166
|
+
:invalid_option => 9999,
|
1167
|
+
:dbname => :test)
|
1115
1168
|
expect( ping ).to eq( PG::PQPING_NO_ATTEMPT )
|
1116
1169
|
end
|
1117
1170
|
|
@@ -1236,52 +1289,68 @@ describe PG::Connection do
|
|
1236
1289
|
expect( @conn.internal_encoding ).to eq( Encoding::ASCII_8BIT )
|
1237
1290
|
end
|
1238
1291
|
|
1292
|
+
it "the connection should use JOHAB dummy encoding when it's set to JOHAB" do
|
1293
|
+
@conn.set_client_encoding "JOHAB"
|
1294
|
+
val = @conn.exec("SELECT chr(x'3391'::int)").values[0][0]
|
1295
|
+
expect( val.encoding.name ).to eq( "JOHAB" )
|
1296
|
+
expect( val.unpack("H*")[0] ).to eq( "dc65" )
|
1297
|
+
end
|
1298
|
+
|
1299
|
+
it "can retrieve server encoding as text" do
|
1300
|
+
enc = @conn.parameter_status "server_encoding"
|
1301
|
+
expect( enc ).to eq( "UTF8" )
|
1302
|
+
end
|
1303
|
+
|
1304
|
+
it "can retrieve server encoding as ruby encoding" do
|
1305
|
+
expect( @conn.external_encoding ).to eq( Encoding::UTF_8 )
|
1306
|
+
end
|
1307
|
+
|
1239
1308
|
it "uses the client encoding for escaped string" do
|
1240
|
-
original = "Möhre to
|
1309
|
+
original = "Möhre to 'scape".encode( "utf-16be" )
|
1241
1310
|
@conn.set_client_encoding( "euc_jp" )
|
1242
1311
|
escaped = @conn.escape( original )
|
1243
1312
|
expect( escaped.encoding ).to eq( Encoding::EUC_JP )
|
1244
|
-
expect( escaped ).to eq( "Möhre to".encode(Encoding::EUC_JP) )
|
1313
|
+
expect( escaped ).to eq( "Möhre to ''scape".encode(Encoding::EUC_JP) )
|
1245
1314
|
end
|
1246
1315
|
|
1247
1316
|
it "uses the client encoding for escaped literal" do
|
1248
|
-
original = "Möhre to
|
1317
|
+
original = "Möhre to 'scape".encode( "utf-16be" )
|
1249
1318
|
@conn.set_client_encoding( "euc_jp" )
|
1250
1319
|
escaped = @conn.escape_literal( original )
|
1251
1320
|
expect( escaped.encoding ).to eq( Encoding::EUC_JP )
|
1252
|
-
expect( escaped ).to eq( "'Möhre to'".encode(Encoding::EUC_JP) )
|
1321
|
+
expect( escaped ).to eq( "'Möhre to ''scape'".encode(Encoding::EUC_JP) )
|
1253
1322
|
end
|
1254
1323
|
|
1255
1324
|
it "uses the client encoding for escaped identifier" do
|
1256
|
-
original = "Möhre to
|
1325
|
+
original = "Möhre to 'scape".encode( "utf-16le" )
|
1257
1326
|
@conn.set_client_encoding( "euc_jp" )
|
1258
1327
|
escaped = @conn.escape_identifier( original )
|
1259
1328
|
expect( escaped.encoding ).to eq( Encoding::EUC_JP )
|
1260
|
-
expect( escaped ).to eq( "\"Möhre to\"".encode(Encoding::EUC_JP) )
|
1329
|
+
expect( escaped ).to eq( "\"Möhre to 'scape\"".encode(Encoding::EUC_JP) )
|
1261
1330
|
end
|
1262
1331
|
|
1263
1332
|
it "uses the client encoding for quote_ident" do
|
1264
|
-
original = "Möhre to
|
1333
|
+
original = "Möhre to 'scape".encode( "utf-16le" )
|
1265
1334
|
@conn.set_client_encoding( "euc_jp" )
|
1266
1335
|
escaped = @conn.quote_ident( original )
|
1267
1336
|
expect( escaped.encoding ).to eq( Encoding::EUC_JP )
|
1268
|
-
expect( escaped ).to eq( "\"Möhre to\"".encode(Encoding::EUC_JP) )
|
1337
|
+
expect( escaped ).to eq( "\"Möhre to 'scape\"".encode(Encoding::EUC_JP) )
|
1269
1338
|
end
|
1270
1339
|
|
1271
1340
|
it "uses the previous string encoding for escaped string" do
|
1272
|
-
original = "Möhre to
|
1341
|
+
original = "Möhre to 'scape".encode( "iso-8859-1" )
|
1273
1342
|
@conn.set_client_encoding( "euc_jp" )
|
1274
1343
|
escaped = described_class.escape( original )
|
1275
1344
|
expect( escaped.encoding ).to eq( Encoding::ISO8859_1 )
|
1276
|
-
expect( escaped ).to eq( "Möhre to".encode(Encoding::ISO8859_1) )
|
1345
|
+
expect( escaped ).to eq( "Möhre to ''scape".encode(Encoding::ISO8859_1) )
|
1277
1346
|
end
|
1278
1347
|
|
1279
1348
|
it "uses the previous string encoding for quote_ident" do
|
1280
|
-
original = "Möhre to
|
1349
|
+
original = "Möhre to 'scape".encode( "iso-8859-1" )
|
1281
1350
|
@conn.set_client_encoding( "euc_jp" )
|
1282
1351
|
escaped = described_class.quote_ident( original )
|
1283
1352
|
expect( escaped.encoding ).to eq( Encoding::ISO8859_1 )
|
1284
|
-
expect( escaped.encode ).to eq( "\"Möhre to\"".encode(Encoding::ISO8859_1) )
|
1353
|
+
expect( escaped.encode ).to eq( "\"Möhre to 'scape\"".encode(Encoding::ISO8859_1) )
|
1285
1354
|
end
|
1286
1355
|
|
1287
1356
|
it "raises appropriate error if set_client_encoding is called with invalid arguments" do
|
@@ -1366,9 +1435,54 @@ describe PG::Connection do
|
|
1366
1435
|
end
|
1367
1436
|
end
|
1368
1437
|
|
1438
|
+
it "rejects command strings with zero bytes" do
|
1439
|
+
expect{ @conn.exec( "SELECT 1;\x00" ) }.to raise_error(ArgumentError, /null byte/)
|
1440
|
+
expect{ @conn.exec_params( "SELECT 1;\x00", [] ) }.to raise_error(ArgumentError, /null byte/)
|
1441
|
+
expect{ @conn.prepare( "abc\x00", "SELECT 1;" ) }.to raise_error(ArgumentError, /null byte/)
|
1442
|
+
expect{ @conn.prepare( "abc", "SELECT 1;\x00" ) }.to raise_error(ArgumentError, /null byte/)
|
1443
|
+
expect{ @conn.exec_prepared( "abc\x00", [] ) }.to raise_error(ArgumentError, /null byte/)
|
1444
|
+
expect{ @conn.describe_prepared( "abc\x00" ) }.to raise_error(ArgumentError, /null byte/)
|
1445
|
+
expect{ @conn.describe_portal( "abc\x00" ) }.to raise_error(ArgumentError, /null byte/)
|
1446
|
+
expect{ @conn.send_query( "SELECT 1;\x00" ) }.to raise_error(ArgumentError, /null byte/)
|
1447
|
+
expect{ @conn.send_query_params( "SELECT 1;\x00", [] ) }.to raise_error(ArgumentError, /null byte/)
|
1448
|
+
expect{ @conn.send_prepare( "abc\x00", "SELECT 1;" ) }.to raise_error(ArgumentError, /null byte/)
|
1449
|
+
expect{ @conn.send_prepare( "abc", "SELECT 1;\x00" ) }.to raise_error(ArgumentError, /null byte/)
|
1450
|
+
expect{ @conn.send_query_prepared( "abc\x00", [] ) }.to raise_error(ArgumentError, /null byte/)
|
1451
|
+
expect{ @conn.send_describe_prepared( "abc\x00" ) }.to raise_error(ArgumentError, /null byte/)
|
1452
|
+
expect{ @conn.send_describe_portal( "abc\x00" ) }.to raise_error(ArgumentError, /null byte/)
|
1453
|
+
end
|
1454
|
+
|
1455
|
+
it "rejects query params with zero bytes" do
|
1456
|
+
expect{ @conn.exec_params( "SELECT 1;\x00", ["ab\x00"] ) }.to raise_error(ArgumentError, /null byte/)
|
1457
|
+
expect{ @conn.exec_prepared( "abc\x00", ["ab\x00"] ) }.to raise_error(ArgumentError, /null byte/)
|
1458
|
+
expect{ @conn.send_query_params( "SELECT 1;\x00", ["ab\x00"] ) }.to raise_error(ArgumentError, /null byte/)
|
1459
|
+
expect{ @conn.send_query_prepared( "abc\x00", ["ab\x00"] ) }.to raise_error(ArgumentError, /null byte/)
|
1460
|
+
end
|
1461
|
+
|
1462
|
+
it "rejects string with zero bytes in escape" do
|
1463
|
+
expect{ @conn.escape( "ab\x00cd" ) }.to raise_error(ArgumentError, /null byte/)
|
1464
|
+
end
|
1465
|
+
|
1466
|
+
it "rejects string with zero bytes in escape_literal" do
|
1467
|
+
expect{ @conn.escape_literal( "ab\x00cd" ) }.to raise_error(ArgumentError, /null byte/)
|
1468
|
+
end
|
1469
|
+
|
1470
|
+
it "rejects string with zero bytes in escape_identifier" do
|
1471
|
+
expect{ @conn.escape_identifier( "ab\x00cd" ) }.to raise_error(ArgumentError, /null byte/)
|
1472
|
+
end
|
1473
|
+
|
1474
|
+
it "rejects string with zero bytes in quote_ident" do
|
1475
|
+
expect{ described_class.quote_ident( "ab\x00cd" ) }.to raise_error(ArgumentError, /null byte/)
|
1476
|
+
end
|
1477
|
+
|
1478
|
+
it "rejects Array with string with zero bytes" do
|
1479
|
+
original = ["xyz", "2\x00"]
|
1480
|
+
expect{ described_class.quote_ident( original ) }.to raise_error(ArgumentError, /null byte/)
|
1481
|
+
end
|
1482
|
+
|
1369
1483
|
it "can quote bigger strings with quote_ident" do
|
1370
1484
|
original = "'01234567\"" * 100
|
1371
|
-
escaped = described_class.quote_ident( original
|
1485
|
+
escaped = described_class.quote_ident( original )
|
1372
1486
|
expect( escaped ).to eq( "\"" + original.gsub("\"", "\"\"") + "\"" )
|
1373
1487
|
end
|
1374
1488
|
|