pg 1.5.9-x64-mingw-ucrt → 1.6.0.rc2-x64-mingw-ucrt
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/{History.md → CHANGELOG.md} +54 -0
- data/Gemfile +7 -4
- data/README-Windows.rdoc +1 -1
- data/README.ja.md +4 -4
- data/README.md +6 -5
- data/Rakefile +80 -13
- data/ext/extconf.rb +158 -14
- data/ext/gvl_wrappers.c +13 -2
- data/ext/gvl_wrappers.h +33 -0
- data/ext/pg.c +16 -5
- data/ext/pg.h +9 -9
- data/ext/pg_binary_decoder.c +150 -0
- data/ext/pg_binary_encoder.c +210 -7
- data/ext/pg_cancel_connection.c +360 -0
- data/ext/pg_coder.c +52 -5
- data/ext/pg_connection.c +368 -158
- data/ext/pg_copy_coder.c +2 -2
- data/ext/pg_record_coder.c +1 -1
- data/ext/pg_result.c +9 -11
- data/ext/pg_text_encoder.c +20 -7
- data/ext/pg_tuple.c +2 -2
- 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 +2 -1
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +3 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/lib/3.1/pg_ext.so +0 -0
- data/lib/3.2/pg_ext.so +0 -0
- data/lib/3.3/pg_ext.so +0 -0
- data/lib/3.4/pg_ext.so +0 -0
- data/lib/pg/basic_type_map_for_queries.rb +7 -3
- data/lib/pg/basic_type_registry.rb +2 -2
- data/lib/pg/cancel_connection.rb +53 -0
- data/lib/pg/coder.rb +2 -1
- data/lib/pg/connection.rb +252 -131
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +13 -8
- data/misc/yugabyte/Dockerfile +9 -0
- data/misc/yugabyte/docker-compose.yml +28 -0
- data/misc/yugabyte/pg-test.rb +45 -0
- data/pg.gemspec +5 -3
- data/ports/patches/krb5/1.21.3/0001-Allow-static-linking-krb5-library.patch +30 -0
- data/ports/patches/openssl/3.5.1/0001-aarch64-mingw.patch +21 -0
- data/ports/patches/postgresql/17.5/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
- data/ports/patches/postgresql/17.5/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +52 -0
- data/{lib/x64-mingw-ucrt → ports/x64-mingw-ucrt/lib}/libpq.dll +0 -0
- data/rakelib/pg_gem_helper.rb +64 -0
- data.tar.gz.sig +0 -0
- metadata +34 -25
- metadata.gz.sig +0 -0
- data/Manifest.txt +0 -72
- data/Rakefile.cross +0 -303
data/ext/pg_copy_coder.c
CHANGED
@@ -51,7 +51,7 @@ static const rb_data_type_t pg_copycoder_type = {
|
|
51
51
|
pg_copycoder_mark,
|
52
52
|
RUBY_TYPED_DEFAULT_FREE,
|
53
53
|
pg_copycoder_memsize,
|
54
|
-
|
54
|
+
pg_copycoder_compact,
|
55
55
|
},
|
56
56
|
&pg_coder_type,
|
57
57
|
0,
|
@@ -831,7 +831,6 @@ pg_bin_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tupl
|
|
831
831
|
|
832
832
|
for( fieldno = 0; fieldno < nfields; fieldno++){
|
833
833
|
long input_len;
|
834
|
-
VALUE field_value;
|
835
834
|
|
836
835
|
/* read field size */
|
837
836
|
if (line_end_ptr - cur_ptr < 4 ) goto length_error;
|
@@ -843,6 +842,7 @@ pg_bin_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tupl
|
|
843
842
|
/* NULL indicator */
|
844
843
|
rb_ary_push(array, Qnil);
|
845
844
|
} else {
|
845
|
+
VALUE field_value;
|
846
846
|
if (line_end_ptr - cur_ptr < input_len ) goto length_error;
|
847
847
|
|
848
848
|
/* copy input data to field_str */
|
data/ext/pg_record_coder.c
CHANGED
data/ext/pg_result.c
CHANGED
@@ -147,9 +147,7 @@ pgresult_clear( void *_this )
|
|
147
147
|
t_pg_result *this = (t_pg_result *)_this;
|
148
148
|
if( this->pgresult && !this->autoclear ){
|
149
149
|
PQclear(this->pgresult);
|
150
|
-
#ifdef HAVE_RB_GC_ADJUST_MEMORY_USAGE
|
151
150
|
rb_gc_adjust_memory_usage(-this->result_size);
|
152
|
-
#endif
|
153
151
|
}
|
154
152
|
this->result_size = 0;
|
155
153
|
this->nfields = -1;
|
@@ -180,7 +178,7 @@ static const rb_data_type_t pgresult_type = {
|
|
180
178
|
pgresult_gc_mark,
|
181
179
|
pgresult_gc_free,
|
182
180
|
pgresult_memsize,
|
183
|
-
|
181
|
+
pgresult_gc_compact,
|
184
182
|
},
|
185
183
|
0, 0,
|
186
184
|
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
@@ -253,9 +251,7 @@ pg_new_result(PGresult *result, VALUE rb_pgconn)
|
|
253
251
|
*/
|
254
252
|
this->result_size = pgresult_approx_size(result);
|
255
253
|
|
256
|
-
#ifdef HAVE_RB_GC_ADJUST_MEMORY_USAGE
|
257
254
|
rb_gc_adjust_memory_usage(this->result_size);
|
258
|
-
#endif
|
259
255
|
|
260
256
|
return self;
|
261
257
|
}
|
@@ -323,6 +319,9 @@ pg_result_check( VALUE self )
|
|
323
319
|
case PGRES_COMMAND_OK:
|
324
320
|
#ifdef HAVE_PQENTERPIPELINEMODE
|
325
321
|
case PGRES_PIPELINE_SYNC:
|
322
|
+
#endif
|
323
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
324
|
+
case PGRES_TUPLES_CHUNK:
|
326
325
|
#endif
|
327
326
|
return self;
|
328
327
|
case PGRES_BAD_RESPONSE:
|
@@ -549,6 +548,7 @@ static void pgresult_init_fnames(VALUE self)
|
|
549
548
|
* * +PGRES_FATAL_ERROR+
|
550
549
|
* * +PGRES_COPY_BOTH+
|
551
550
|
* * +PGRES_SINGLE_TUPLE+
|
551
|
+
* * +PGRES_TUPLES_CHUNK+
|
552
552
|
* * +PGRES_PIPELINE_SYNC+
|
553
553
|
* * +PGRES_PIPELINE_ABORTED+
|
554
554
|
*
|
@@ -613,14 +613,12 @@ pgresult_error_message(VALUE self)
|
|
613
613
|
return ret;
|
614
614
|
}
|
615
615
|
|
616
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
617
616
|
/*
|
618
617
|
* call-seq:
|
619
618
|
* res.verbose_error_message( verbosity, show_context ) -> String
|
620
619
|
*
|
621
620
|
* Returns a reformatted version of the error message associated with a PGresult object.
|
622
621
|
*
|
623
|
-
* Available since PostgreSQL-9.6
|
624
622
|
*/
|
625
623
|
static VALUE
|
626
624
|
pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
@@ -639,7 +637,6 @@ pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
|
639
637
|
|
640
638
|
return ret;
|
641
639
|
}
|
642
|
-
#endif
|
643
640
|
|
644
641
|
/*
|
645
642
|
* call-seq:
|
@@ -1528,6 +1525,9 @@ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* da
|
|
1528
1525
|
return self;
|
1529
1526
|
rb_raise( rb_eInvalidResultStatus, "PG::Result is not in single row mode");
|
1530
1527
|
case PGRES_SINGLE_TUPLE:
|
1528
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
1529
|
+
case PGRES_TUPLES_CHUNK:
|
1530
|
+
#endif
|
1531
1531
|
break;
|
1532
1532
|
default:
|
1533
1533
|
pg_result_check( self );
|
@@ -1572,7 +1572,7 @@ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* da
|
|
1572
1572
|
* wrapping each row into a dedicated result object, it delivers data in nearly
|
1573
1573
|
* the same speed as with ordinary results.
|
1574
1574
|
*
|
1575
|
-
* The base result must be in status PGRES_SINGLE_TUPLE.
|
1575
|
+
* The base result must be in status PGRES_SINGLE_TUPLE or PGRES_TUPLES_CHUNK.
|
1576
1576
|
* It iterates over all tuples until the status changes to PGRES_TUPLES_OK.
|
1577
1577
|
* A PG::Error is raised for any errors from the server.
|
1578
1578
|
*
|
@@ -1707,10 +1707,8 @@ init_pg_result(void)
|
|
1707
1707
|
rb_define_singleton_method(rb_cPGresult, "res_status", pgresult_s_res_status, 1);
|
1708
1708
|
rb_define_method(rb_cPGresult, "error_message", pgresult_error_message, 0);
|
1709
1709
|
rb_define_alias( rb_cPGresult, "result_error_message", "error_message");
|
1710
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
1711
1710
|
rb_define_method(rb_cPGresult, "verbose_error_message", pgresult_verbose_error_message, 2);
|
1712
1711
|
rb_define_alias( rb_cPGresult, "result_verbose_error_message", "verbose_error_message");
|
1713
|
-
#endif
|
1714
1712
|
rb_define_method(rb_cPGresult, "error_field", pgresult_error_field, 1);
|
1715
1713
|
rb_define_alias( rb_cPGresult, "result_error_field", "error_field" );
|
1716
1714
|
rb_define_method(rb_cPGresult, "clear", pg_result_clear, 0);
|
data/ext/pg_text_encoder.c
CHANGED
@@ -231,7 +231,7 @@ pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
|
|
231
231
|
*
|
232
232
|
*/
|
233
233
|
static int
|
234
|
-
pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *
|
234
|
+
pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate1, int enc_idx)
|
235
235
|
{
|
236
236
|
if(out){
|
237
237
|
double dvalue = NUM2DBL(value);
|
@@ -239,7 +239,6 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
239
239
|
int neg = 0;
|
240
240
|
int exp2i, exp10i, i;
|
241
241
|
unsigned long long ll, remainder, oldval;
|
242
|
-
VALUE intermediate;
|
243
242
|
|
244
243
|
/* Cast to the same strings as value.to_s . */
|
245
244
|
if( isinf(dvalue) ){
|
@@ -283,6 +282,7 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
283
282
|
|
284
283
|
if( exp10i <= -5 || exp10i >= 15 ) {
|
285
284
|
/* Write the float in exponent format (1.23e45) */
|
285
|
+
VALUE intermediate;
|
286
286
|
|
287
287
|
/* write fraction digits from right to left */
|
288
288
|
for( i = MAX_DOUBLE_DIGITS; i > 1; i--){
|
@@ -537,7 +537,7 @@ quote_string(t_pg_coder *this, VALUE value, VALUE string, char *current_out, int
|
|
537
537
|
}
|
538
538
|
|
539
539
|
static char *
|
540
|
-
write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE string, int quote, int enc_idx)
|
540
|
+
write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE string, int quote, int enc_idx, int dimension)
|
541
541
|
{
|
542
542
|
int i;
|
543
543
|
|
@@ -545,6 +545,10 @@ write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE st
|
|
545
545
|
current_out = pg_rb_str_ensure_capa( string, 2, current_out, NULL );
|
546
546
|
*current_out++ = '{';
|
547
547
|
|
548
|
+
if( RARRAY_LEN(value) == 0 && this->dimensions >= 0 && dimension != this->dimensions ){
|
549
|
+
rb_raise(rb_eArgError, "less array dimensions to encode (%d) than expected (%d)", dimension, this->dimensions);
|
550
|
+
}
|
551
|
+
|
548
552
|
for( i=0; i<RARRAY_LEN(value); i++){
|
549
553
|
VALUE entry = rb_ary_entry(value, i);
|
550
554
|
|
@@ -554,17 +558,26 @@ write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE st
|
|
554
558
|
}
|
555
559
|
|
556
560
|
switch(TYPE(entry)){
|
557
|
-
case T_ARRAY:
|
558
|
-
current_out = write_array(this, entry, current_out, string, quote, enc_idx);
|
559
|
-
break;
|
560
561
|
case T_NIL:
|
562
|
+
if( this->dimensions >= 0 && dimension != this->dimensions ){
|
563
|
+
rb_raise(rb_eArgError, "less array dimensions to encode (%d) than expected (%d)", dimension, this->dimensions);
|
564
|
+
}
|
561
565
|
current_out = pg_rb_str_ensure_capa( string, 4, current_out, NULL );
|
562
566
|
*current_out++ = 'N';
|
563
567
|
*current_out++ = 'U';
|
564
568
|
*current_out++ = 'L';
|
565
569
|
*current_out++ = 'L';
|
566
570
|
break;
|
571
|
+
case T_ARRAY:
|
572
|
+
if( this->dimensions < 0 || dimension < this->dimensions ){
|
573
|
+
current_out = write_array(this, entry, current_out, string, quote, enc_idx, dimension+1);
|
574
|
+
break;
|
575
|
+
}
|
576
|
+
/* Number of dimensions reached -> handle array as normal value */
|
567
577
|
default:
|
578
|
+
if( this->dimensions >= 0 && dimension != this->dimensions ){
|
579
|
+
rb_raise(rb_eArgError, "less array dimensions to encode (%d) than expected (%d)", dimension, this->dimensions);
|
580
|
+
}
|
568
581
|
current_out = quote_string( this->elem, entry, string, current_out, quote, quote_array_buffer, this, enc_idx );
|
569
582
|
}
|
570
583
|
}
|
@@ -596,7 +609,7 @@ pg_text_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
596
609
|
VALUE out_str = rb_str_new(NULL, 0);
|
597
610
|
PG_ENCODING_SET_NOCHECK(out_str, enc_idx);
|
598
611
|
|
599
|
-
end_ptr = write_array(this, value, RSTRING_PTR(out_str), out_str, this->needs_quotation, enc_idx);
|
612
|
+
end_ptr = write_array(this, value, RSTRING_PTR(out_str), out_str, this->needs_quotation, enc_idx, 1);
|
600
613
|
|
601
614
|
rb_str_set_len( out_str, end_ptr - RSTRING_PTR(out_str) );
|
602
615
|
*intermediate = out_str;
|
data/ext/pg_tuple.c
CHANGED
@@ -125,7 +125,7 @@ static const rb_data_type_t pg_tuple_type = {
|
|
125
125
|
pg_tuple_gc_mark,
|
126
126
|
pg_tuple_gc_free,
|
127
127
|
pg_tuple_memsize,
|
128
|
-
|
128
|
+
pg_tuple_gc_compact,
|
129
129
|
},
|
130
130
|
0, 0,
|
131
131
|
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
@@ -135,7 +135,7 @@ static const rb_data_type_t pg_tuple_type = {
|
|
135
135
|
* Document-method: allocate
|
136
136
|
*
|
137
137
|
* call-seq:
|
138
|
-
* PG::
|
138
|
+
* PG::Tuple.allocate -> obj
|
139
139
|
*/
|
140
140
|
static VALUE
|
141
141
|
pg_tuple_s_allocate( VALUE klass )
|
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
@@ -54,6 +54,7 @@ pg_tmbc_fit_to_query( VALUE self, VALUE params )
|
|
54
54
|
t_tmbc *this = RTYPEDDATA_DATA( self );
|
55
55
|
t_typemap *default_tm;
|
56
56
|
|
57
|
+
Check_Type(params, T_ARRAY);
|
57
58
|
nfields = (int)RARRAY_LEN( params );
|
58
59
|
if ( this->nfields != nfields ) {
|
59
60
|
rb_raise( rb_eArgError, "number of result fields (%d) does not match number of mapped columns (%d)",
|
@@ -228,7 +229,7 @@ static const rb_data_type_t pg_tmbc_type = {
|
|
228
229
|
pg_tmbc_mark,
|
229
230
|
pg_tmbc_free,
|
230
231
|
pg_tmbc_memsize,
|
231
|
-
|
232
|
+
pg_tmbc_compact,
|
232
233
|
},
|
233
234
|
&pg_typemap_type,
|
234
235
|
0,
|
data/ext/pg_type_map_by_oid.c
CHANGED
@@ -190,7 +190,7 @@ static const rb_data_type_t pg_tmbo_type = {
|
|
190
190
|
pg_tmbo_mark,
|
191
191
|
RUBY_TYPED_DEFAULT_FREE,
|
192
192
|
pg_tmbo_memsize,
|
193
|
-
|
193
|
+
pg_tmbo_compact,
|
194
194
|
},
|
195
195
|
&pg_typemap_type,
|
196
196
|
0,
|
@@ -315,6 +315,8 @@ pg_tmbo_coders( VALUE self )
|
|
315
315
|
* The type map will do Hash lookups for each result value, if the number of rows
|
316
316
|
* is below or equal +number+.
|
317
317
|
*
|
318
|
+
* Default is 10.
|
319
|
+
*
|
318
320
|
*/
|
319
321
|
static VALUE
|
320
322
|
pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
|
data/ext/pg_type_map_in_ruby.c
CHANGED
data/lib/3.1/pg_ext.so
CHANGED
Binary file
|
data/lib/3.2/pg_ext.so
CHANGED
Binary file
|
data/lib/3.3/pg_ext.so
CHANGED
Binary file
|
data/lib/3.4/pg_ext.so
ADDED
Binary file
|
@@ -53,14 +53,18 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
|
|
53
53
|
@coder_maps = build_coder_maps(connection_or_coder_maps, registry: registry)
|
54
54
|
@array_encoders_by_klass = array_encoders_by_klass
|
55
55
|
@encode_array_as = :array
|
56
|
-
@if_undefined = if_undefined ||
|
56
|
+
@if_undefined = if_undefined || UndefinedDefault
|
57
57
|
init_encoders
|
58
58
|
end
|
59
59
|
|
60
|
-
|
61
|
-
|
60
|
+
class UndefinedDefault
|
61
|
+
def self.call(oid_name, format)
|
62
|
+
raise UndefinedEncoder, "no encoder defined for type #{oid_name.inspect} format #{format}"
|
63
|
+
end
|
62
64
|
end
|
63
65
|
|
66
|
+
private_constant :UndefinedDefault
|
67
|
+
|
64
68
|
# Change the mechanism that is used to encode ruby array values
|
65
69
|
#
|
66
70
|
# Possible values:
|
@@ -127,8 +127,8 @@ class PG::BasicTypeRegistry
|
|
127
127
|
@maps = [
|
128
128
|
[0, :encoder, PG::TextEncoder::Array],
|
129
129
|
[0, :decoder, PG::TextDecoder::Array],
|
130
|
-
[1, :encoder,
|
131
|
-
[1, :decoder,
|
130
|
+
[1, :encoder, PG::BinaryEncoder::Array],
|
131
|
+
[1, :decoder, PG::BinaryDecoder::Array],
|
132
132
|
].inject([]) do |h, (format, direction, arraycoder)|
|
133
133
|
coders = registry.coders_for(format, direction) || {}
|
134
134
|
h[format] ||= {}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pg' unless defined?( PG )
|
5
|
+
|
6
|
+
if defined?(PG::CancelConnection)
|
7
|
+
class PG::CancelConnection
|
8
|
+
include PG::Connection::Pollable
|
9
|
+
|
10
|
+
alias c_initialize initialize
|
11
|
+
|
12
|
+
def initialize(conn)
|
13
|
+
c_initialize(conn)
|
14
|
+
|
15
|
+
# A cancel connection is always to one destination server only.
|
16
|
+
# Prepare conninfo_hash with just enough information to allow a shared polling_loop.
|
17
|
+
@host = conn.host
|
18
|
+
@hostaddr = conn.hostaddr
|
19
|
+
@port = conn.port
|
20
|
+
|
21
|
+
@conninfo_hash = {
|
22
|
+
host: @host,
|
23
|
+
hostaddr: @hostaddr,
|
24
|
+
port: @port.to_s,
|
25
|
+
connect_timeout: conn.conninfo_hash[:connect_timeout],
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
# call-seq:
|
30
|
+
# conn.cancel
|
31
|
+
#
|
32
|
+
# Requests that the server abandons processing of the current command in a blocking manner.
|
33
|
+
#
|
34
|
+
# If the cancel request wasn't successfully dispatched an error message is raised.
|
35
|
+
#
|
36
|
+
# Successful dispatch of the cancellation is no guarantee that the request will have any effect, however.
|
37
|
+
# If the cancellation is effective, the command being canceled will terminate early and raises an error.
|
38
|
+
# If the cancellation fails (say, because the server was already done processing the command), then there will be no visible result at all.
|
39
|
+
#
|
40
|
+
def cancel
|
41
|
+
start
|
42
|
+
polling_loop(:poll)
|
43
|
+
end
|
44
|
+
alias async_cancel cancel
|
45
|
+
|
46
|
+
# These private methods are there to allow a shared polling_loop.
|
47
|
+
private
|
48
|
+
attr_reader :host
|
49
|
+
attr_reader :hostaddr
|
50
|
+
attr_reader :port
|
51
|
+
attr_reader :conninfo_hash
|
52
|
+
end
|
53
|
+
end
|
data/lib/pg/coder.rb
CHANGED
@@ -76,12 +76,13 @@ module PG
|
|
76
76
|
elements_type: elements_type,
|
77
77
|
needs_quotation: needs_quotation?,
|
78
78
|
delimiter: delimiter,
|
79
|
+
dimensions: dimensions,
|
79
80
|
}
|
80
81
|
end
|
81
82
|
|
82
83
|
def inspect
|
83
84
|
str = super
|
84
|
-
str[-1,0] = " elements_type=#{elements_type.inspect} #{needs_quotation? ? 'needs' : 'no'} quotation"
|
85
|
+
str[-1,0] = " elements_type=#{elements_type.inspect} #{needs_quotation? ? 'needs' : 'no'} quotation#{dimensions && " #{dimensions} dimensions"}"
|
85
86
|
str
|
86
87
|
end
|
87
88
|
end
|