From e24a663cbee2c719eb3a60d447ec85fe9537904e Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Mon, 27 Mar 2023 10:04:23 +0200 Subject: [PATCH 1/2] Reduce the number of files loaded at "require 'pg'" And use autoload to load optional classes when they are used. --- lib/pg.rb | 41 +++++++++---- .../timestamp.rb} | 0 .../timestamp.rb} | 0 lib/pg/connection.rb | 7 +-- lib/pg/constants.rb | 12 ---- lib/pg/text_decoder/date.rb | 18 ++++++ lib/pg/text_decoder/json.rb | 14 +++++ .../timestamp.rb} | 19 ------ lib/pg/text_encoder.rb | 59 ------------------- lib/pg/text_encoder/date.rb | 12 ++++ lib/pg/text_encoder/inet.rb | 28 +++++++++ lib/pg/text_encoder/json.rb | 14 +++++ lib/pg/text_encoder/timestamp.rb | 24 ++++++++ spec/pg/connection_spec.rb | 1 + 14 files changed, 145 insertions(+), 104 deletions(-) rename lib/pg/{binary_decoder.rb => binary_decoder/timestamp.rb} (100%) rename lib/pg/{binary_encoder.rb => binary_encoder/timestamp.rb} (100%) delete mode 100644 lib/pg/constants.rb create mode 100644 lib/pg/text_decoder/date.rb create mode 100644 lib/pg/text_decoder/json.rb rename lib/pg/{text_decoder.rb => text_decoder/timestamp.rb} (67%) delete mode 100644 lib/pg/text_encoder.rb create mode 100644 lib/pg/text_encoder/date.rb create mode 100644 lib/pg/text_encoder/inet.rb create mode 100644 lib/pg/text_encoder/json.rb create mode 100644 lib/pg/text_encoder/timestamp.rb diff --git a/lib/pg.rb b/lib/pg.rb index 8d71f44ef..2ee2a7294 100644 --- a/lib/pg.rb +++ b/lib/pg.rb @@ -64,21 +64,42 @@ def self.connect( *args, &block ) end + module BinaryDecoder + %i[ TimestampUtc TimestampUtcToLocal TimestampLocal ].each do |klass| + autoload klass, 'pg/binary_decoder/timestamp' + end + end + module BinaryEncoder + %i[ TimestampUtc TimestampLocal ].each do |klass| + autoload klass, 'pg/binary_encoder/timestamp' + end + end + module TextDecoder + %i[ TimestampUtc TimestampUtcToLocal TimestampLocal TimestampWithoutTimeZone TimestampWithTimeZone ].each do |klass| + autoload klass, 'pg/text_decoder/timestamp' + end + autoload :Date, 'pg/text_decoder/date' + autoload :JSON, 'pg/text_decoder/json' + end + module TextEncoder + %i[ TimestampUtc TimestampWithoutTimeZone TimestampWithTimeZone ].each do |klass| + autoload klass, 'pg/text_encoder/timestamp' + end + autoload :Date, 'pg/text_encoder/date' + autoload :Inet, 'pg/text_encoder/inet' + autoload :JSON, 'pg/text_encoder/json' + end + + autoload :BasicTypeMapBasedOnResult, 'pg/basic_type_map_based_on_result' + autoload :BasicTypeMapForQueries, 'pg/basic_type_map_for_queries' + autoload :BasicTypeMapForResults, 'pg/basic_type_map_for_results' + autoload :BasicTypeRegistry, 'pg/basic_type_registry' require 'pg/exceptions' - require 'pg/constants' require 'pg/coder' - require 'pg/binary_encoder' - require 'pg/binary_decoder' - require 'pg/text_encoder' - require 'pg/text_decoder' - require 'pg/basic_type_registry' - require 'pg/basic_type_map_based_on_result' - require 'pg/basic_type_map_for_queries' - require 'pg/basic_type_map_for_results' require 'pg/type_map_by_column' require 'pg/connection' require 'pg/result' require 'pg/tuple' - require 'pg/version' + autoload :VERSION, 'pg/version' end # module PG diff --git a/lib/pg/binary_decoder.rb b/lib/pg/binary_decoder/timestamp.rb similarity index 100% rename from lib/pg/binary_decoder.rb rename to lib/pg/binary_decoder/timestamp.rb diff --git a/lib/pg/binary_encoder.rb b/lib/pg/binary_encoder/timestamp.rb similarity index 100% rename from lib/pg/binary_encoder.rb rename to lib/pg/binary_encoder/timestamp.rb diff --git a/lib/pg/connection.rb b/lib/pg/connection.rb index 832f4aaa3..4f0a2b39e 100644 --- a/lib/pg/connection.rb +++ b/lib/pg/connection.rb @@ -2,8 +2,7 @@ # frozen_string_literal: true require 'pg' unless defined?( PG ) -require 'uri' -require 'io/wait' +require 'io/wait' unless ::IO.public_instance_methods(false).include?(:wait_readable) require 'socket' # The PostgreSQL connection class. The interface for this class is based on @@ -63,8 +62,8 @@ def self.parse_connect_args( *args ) iopts = {} if args.length == 1 - case args.first - when URI, /=/, /:\/\// + case args.first.to_s + when /=/, /:\/\// # Option or URL string style conn_string = args.first.to_s iopts = PG::Connection.conninfo_parse(conn_string).each_with_object({}){|h, o| o[h[:keyword].to_sym] = h[:val] if h[:val] } diff --git a/lib/pg/constants.rb b/lib/pg/constants.rb deleted file mode 100644 index 769910b8c..000000000 --- a/lib/pg/constants.rb +++ /dev/null @@ -1,12 +0,0 @@ -# -*- ruby -*- -# frozen_string_literal: true - -require 'pg' unless defined?( PG ) - - -module PG::Constants - - # Most of these are defined in the extension. - -end # module PG::Constants - diff --git a/lib/pg/text_decoder/date.rb b/lib/pg/text_decoder/date.rb new file mode 100644 index 000000000..1a093e456 --- /dev/null +++ b/lib/pg/text_decoder/date.rb @@ -0,0 +1,18 @@ +# -*- ruby -*- +# frozen_string_literal: true + +require 'date' + +module PG + module TextDecoder + class Date < SimpleDecoder + def decode(string, tuple=nil, field=nil) + if string =~ /\A(\d{4})-(\d\d)-(\d\d)\z/ + ::Date.new $1.to_i, $2.to_i, $3.to_i + else + string + end + end + end + end +end # module PG diff --git a/lib/pg/text_decoder/json.rb b/lib/pg/text_decoder/json.rb new file mode 100644 index 000000000..9c4694671 --- /dev/null +++ b/lib/pg/text_decoder/json.rb @@ -0,0 +1,14 @@ +# -*- ruby -*- +# frozen_string_literal: true + +require 'json' + +module PG + module TextDecoder + class JSON < SimpleDecoder + def decode(string, tuple=nil, field=nil) + ::JSON.parse(string, quirks_mode: true) + end + end + end +end # module PG diff --git a/lib/pg/text_decoder.rb b/lib/pg/text_decoder/timestamp.rb similarity index 67% rename from lib/pg/text_decoder.rb rename to lib/pg/text_decoder/timestamp.rb index d0dfe17e8..668ede9ba 100644 --- a/lib/pg/text_decoder.rb +++ b/lib/pg/text_decoder/timestamp.rb @@ -1,27 +1,8 @@ # -*- ruby -*- # frozen_string_literal: true -require 'date' -require 'json' - module PG module TextDecoder - class Date < SimpleDecoder - def decode(string, tuple=nil, field=nil) - if string =~ /\A(\d{4})-(\d\d)-(\d\d)\z/ - ::Date.new $1.to_i, $2.to_i, $3.to_i - else - string - end - end - end - - class JSON < SimpleDecoder - def decode(string, tuple=nil, field=nil) - ::JSON.parse(string, quirks_mode: true) - end - end - # Convenience classes for timezone options class TimestampUtc < Timestamp def initialize(**kwargs) diff --git a/lib/pg/text_encoder.rb b/lib/pg/text_encoder.rb deleted file mode 100644 index b3fd9a032..000000000 --- a/lib/pg/text_encoder.rb +++ /dev/null @@ -1,59 +0,0 @@ -# -*- ruby -*- -# frozen_string_literal: true - -require 'json' -require 'ipaddr' - -module PG - module TextEncoder - class Date < SimpleEncoder - def encode(value) - value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d") : value - end - end - - class TimestampWithoutTimeZone < SimpleEncoder - def encode(value) - value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d %H:%M:%S.%N") : value - end - end - - class TimestampUtc < SimpleEncoder - def encode(value) - value.respond_to?(:utc) ? value.utc.strftime("%Y-%m-%d %H:%M:%S.%N") : value - end - end - - class TimestampWithTimeZone < SimpleEncoder - def encode(value) - value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d %H:%M:%S.%N %:z") : value - end - end - - class JSON < SimpleEncoder - def encode(value) - ::JSON.generate(value, quirks_mode: true) - end - end - - class Inet < SimpleEncoder - def encode(value) - case value - when IPAddr - default_prefix = (value.family == Socket::AF_INET ? 32 : 128) - s = value.to_s - if value.respond_to?(:prefix) - prefix = value.prefix - else - range = value.to_range - prefix = default_prefix - Math.log(((range.end.to_i - range.begin.to_i) + 1), 2).to_i - end - s << "/" << prefix.to_s if prefix != default_prefix - s - else - value - end - end - end - end -end # module PG diff --git a/lib/pg/text_encoder/date.rb b/lib/pg/text_encoder/date.rb new file mode 100644 index 000000000..c721b7ef3 --- /dev/null +++ b/lib/pg/text_encoder/date.rb @@ -0,0 +1,12 @@ +# -*- ruby -*- +# frozen_string_literal: true + +module PG + module TextEncoder + class Date < SimpleEncoder + def encode(value) + value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d") : value + end + end + end +end # module PG diff --git a/lib/pg/text_encoder/inet.rb b/lib/pg/text_encoder/inet.rb new file mode 100644 index 000000000..096c0f1a4 --- /dev/null +++ b/lib/pg/text_encoder/inet.rb @@ -0,0 +1,28 @@ +# -*- ruby -*- +# frozen_string_literal: true + +require 'ipaddr' + +module PG + module TextEncoder + class Inet < SimpleEncoder + def encode(value) + case value + when IPAddr + default_prefix = (value.family == Socket::AF_INET ? 32 : 128) + s = value.to_s + if value.respond_to?(:prefix) + prefix = value.prefix + else + range = value.to_range + prefix = default_prefix - Math.log(((range.end.to_i - range.begin.to_i) + 1), 2).to_i + end + s << "/" << prefix.to_s if prefix != default_prefix + s + else + value + end + end + end + end +end # module PG diff --git a/lib/pg/text_encoder/json.rb b/lib/pg/text_encoder/json.rb new file mode 100644 index 000000000..d960e3d32 --- /dev/null +++ b/lib/pg/text_encoder/json.rb @@ -0,0 +1,14 @@ +# -*- ruby -*- +# frozen_string_literal: true + +require 'json' + +module PG + module TextEncoder + class JSON < SimpleEncoder + def encode(value) + ::JSON.generate(value, quirks_mode: true) + end + end + end +end # module PG diff --git a/lib/pg/text_encoder/timestamp.rb b/lib/pg/text_encoder/timestamp.rb new file mode 100644 index 000000000..e241e59d6 --- /dev/null +++ b/lib/pg/text_encoder/timestamp.rb @@ -0,0 +1,24 @@ +# -*- ruby -*- +# frozen_string_literal: true + +module PG + module TextEncoder + class TimestampWithoutTimeZone < SimpleEncoder + def encode(value) + value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d %H:%M:%S.%N") : value + end + end + + class TimestampUtc < SimpleEncoder + def encode(value) + value.respond_to?(:utc) ? value.utc.strftime("%Y-%m-%d %H:%M:%S.%N") : value + end + end + + class TimestampWithTimeZone < SimpleEncoder + def encode(value) + value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d %H:%M:%S.%N %:z") : value + end + end + end +end # module PG diff --git a/spec/pg/connection_spec.rb b/spec/pg/connection_spec.rb index 042b1fcab..a9a5d6e67 100644 --- a/spec/pg/connection_spec.rb +++ b/spec/pg/connection_spec.rb @@ -199,6 +199,7 @@ end it "accepts an URI object" do + require "uri" string = described_class.parse_connect_args( URI.parse(uri) ) expect( string ).to be_a( String ) From 125fd17ff586d6c2e83095462ef27329ac670fb5 Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Mon, 27 Mar 2023 11:14:46 +0200 Subject: [PATCH 2/2] Load TextDecoder::Inet, TextDecoder::Numeric and TextEncoder::Numeric by autoload .. to avoid require 'ipaddr' and 'bigdecimal' if these types are'nt used. --- ext/pg_text_decoder.c | 38 +++++++++++++++++++++++++--------- ext/pg_text_encoder.c | 23 +++++++++++++------- lib/pg.rb | 3 +++ lib/pg/text_decoder/inet.rb | 9 ++++++++ lib/pg/text_decoder/numeric.rb | 9 ++++++++ lib/pg/text_encoder/numeric.rb | 9 ++++++++ 6 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 lib/pg/text_decoder/inet.rb create mode 100644 lib/pg/text_decoder/numeric.rb create mode 100644 lib/pg/text_encoder/numeric.rb diff --git a/ext/pg_text_decoder.c b/ext/pg_text_decoder.c index 120a2babe..f08ad37f4 100644 --- a/ext/pg_text_decoder.c +++ b/ext/pg_text_decoder.c @@ -43,7 +43,6 @@ #include VALUE rb_mPG_TextDecoder; -static ID s_id_decode; static ID s_id_Rational; static ID s_id_new; static ID s_id_utc; @@ -171,6 +170,19 @@ pg_text_dec_numeric(t_pg_coder *conv, const char *val, int len, int tuple, int f return rb_funcall(rb_cObject, s_id_BigDecimal, 1, rb_str_new(val, len)); } +/* called per autoload when TextDecoder::Numeric is used */ +static VALUE +init_pg_text_decoder_numeric(VALUE rb_mPG_TextDecoder) +{ + rb_require("bigdecimal"); + s_id_BigDecimal = rb_intern("BigDecimal"); + + /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Numeric", rb_cPG_SimpleDecoder ); */ + pg_define_coder( "Numeric", pg_text_dec_numeric, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder ); + + return Qnil; +} + /* * Document-class: PG::TextDecoder::Float < PG::SimpleDecoder * @@ -922,8 +934,9 @@ pg_text_dec_inet(t_pg_coder *conv, const char *val, int len, int tuple, int fiel return ip; } -void -init_pg_text_decoder(void) +/* called per autoload when TextDecoder::Inet is used */ +static VALUE +init_pg_text_decoder_inet(VALUE rb_mPG_TextDecoder) { rb_require("ipaddr"); s_IPAddr = rb_funcall(rb_cObject, rb_intern("const_get"), 1, rb_str_new2("IPAddr")); @@ -942,14 +955,21 @@ init_pg_text_decoder(void) s_vmasks6 = rb_eval_string("a = [0]*129; a[0] = 0; a[128] = 0xffffffffffffffffffffffffffffffff; 127.downto(1){|i| a[i] = a[i+1] - (1 << (127 - i))}; a.freeze"); rb_global_variable(&s_vmasks6); - s_id_decode = rb_intern("decode"); + /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Inet", rb_cPG_SimpleDecoder ); */ + pg_define_coder( "Inet", pg_text_dec_inet, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder); + + return Qnil; +} + + +void +init_pg_text_decoder(void) +{ s_id_Rational = rb_intern("Rational"); s_id_new = rb_intern("new"); s_id_utc = rb_intern("utc"); s_id_getlocal = rb_intern("getlocal"); - rb_require("bigdecimal"); - s_id_BigDecimal = rb_intern("BigDecimal"); s_nan = rb_eval_string("0.0/0.0"); rb_global_variable(&s_nan); s_pos_inf = rb_eval_string("1.0/0.0"); @@ -959,6 +979,8 @@ init_pg_text_decoder(void) /* This module encapsulates all decoder classes with text input format */ rb_mPG_TextDecoder = rb_define_module_under( rb_mPG, "TextDecoder" ); + rb_define_private_method(rb_singleton_class(rb_mPG_TextDecoder), "init_inet", init_pg_text_decoder_inet, 0); + rb_define_private_method(rb_singleton_class(rb_mPG_TextDecoder), "init_numeric", init_pg_text_decoder_numeric, 0); /* Make RDoc aware of the decoder classes... */ /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Boolean", rb_cPG_SimpleDecoder ); */ @@ -967,8 +989,6 @@ init_pg_text_decoder(void) pg_define_coder( "Integer", pg_text_dec_integer, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder ); /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Float", rb_cPG_SimpleDecoder ); */ pg_define_coder( "Float", pg_text_dec_float, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder ); - /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Numeric", rb_cPG_SimpleDecoder ); */ - pg_define_coder( "Numeric", pg_text_dec_numeric, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder ); /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "String", rb_cPG_SimpleDecoder ); */ pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder ); /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Bytea", rb_cPG_SimpleDecoder ); */ @@ -977,8 +997,6 @@ init_pg_text_decoder(void) pg_define_coder( "Identifier", pg_text_dec_identifier, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder ); /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Timestamp", rb_cPG_SimpleDecoder ); */ pg_define_coder( "Timestamp", pg_text_dec_timestamp, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder); - /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Inet", rb_cPG_SimpleDecoder ); */ - pg_define_coder( "Inet", pg_text_dec_inet, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder); /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Array", rb_cPG_CompositeDecoder ); */ pg_define_coder( "Array", pg_text_dec_array, rb_cPG_CompositeDecoder, rb_mPG_TextDecoder ); diff --git a/ext/pg_text_encoder.c b/ext/pg_text_encoder.c index 9f57094e8..d3465a8e5 100644 --- a/ext/pg_text_encoder.c +++ b/ext/pg_text_encoder.c @@ -371,6 +371,21 @@ pg_text_enc_numeric(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat } } +/* called per autoload when TextEncoder::Numeric is used */ +static VALUE +init_pg_text_encoder_numeric(VALUE rb_mPG_TextDecoder) +{ + s_str_F = rb_str_freeze(rb_str_new_cstr("F")); + rb_global_variable(&s_str_F); + rb_require("bigdecimal"); + s_cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal")); + + /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Numeric", rb_cPG_SimpleEncoder ); */ + pg_define_coder( "Numeric", pg_text_enc_numeric, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder ); + + return Qnil; +} + static const char hextab[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' @@ -784,14 +799,10 @@ init_pg_text_encoder(void) s_id_encode = rb_intern("encode"); s_id_to_i = rb_intern("to_i"); s_id_to_s = rb_intern("to_s"); - s_str_F = rb_str_freeze(rb_str_new_cstr("F")); - rb_global_variable(&s_str_F); - rb_require("bigdecimal"); - s_cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal")); - /* This module encapsulates all encoder classes with text output format */ rb_mPG_TextEncoder = rb_define_module_under( rb_mPG, "TextEncoder" ); + rb_define_private_method(rb_singleton_class(rb_mPG_TextEncoder), "init_numeric", init_pg_text_encoder_numeric, 0); /* Make RDoc aware of the encoder classes... */ /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Boolean", rb_cPG_SimpleEncoder ); */ @@ -800,8 +811,6 @@ init_pg_text_encoder(void) pg_define_coder( "Integer", pg_text_enc_integer, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder ); /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Float", rb_cPG_SimpleEncoder ); */ pg_define_coder( "Float", pg_text_enc_float, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder ); - /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Numeric", rb_cPG_SimpleEncoder ); */ - pg_define_coder( "Numeric", pg_text_enc_numeric, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder ); /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "String", rb_cPG_SimpleEncoder ); */ pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder ); /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Bytea", rb_cPG_SimpleEncoder ); */ diff --git a/lib/pg.rb b/lib/pg.rb index 2ee2a7294..a0cf87179 100644 --- a/lib/pg.rb +++ b/lib/pg.rb @@ -79,7 +79,9 @@ module TextDecoder autoload klass, 'pg/text_decoder/timestamp' end autoload :Date, 'pg/text_decoder/date' + autoload :Inet, 'pg/text_decoder/inet' autoload :JSON, 'pg/text_decoder/json' + autoload :Numeric, 'pg/text_decoder/numeric' end module TextEncoder %i[ TimestampUtc TimestampWithoutTimeZone TimestampWithTimeZone ].each do |klass| @@ -88,6 +90,7 @@ module TextEncoder autoload :Date, 'pg/text_encoder/date' autoload :Inet, 'pg/text_encoder/inet' autoload :JSON, 'pg/text_encoder/json' + autoload :Numeric, 'pg/text_encoder/numeric' end autoload :BasicTypeMapBasedOnResult, 'pg/basic_type_map_based_on_result' diff --git a/lib/pg/text_decoder/inet.rb b/lib/pg/text_decoder/inet.rb new file mode 100644 index 000000000..1f475d804 --- /dev/null +++ b/lib/pg/text_decoder/inet.rb @@ -0,0 +1,9 @@ +# -*- ruby -*- +# frozen_string_literal: true + +module PG + module TextDecoder + # Init C part of the decoder + init_inet + end +end # module PG diff --git a/lib/pg/text_decoder/numeric.rb b/lib/pg/text_decoder/numeric.rb new file mode 100644 index 000000000..84b1ac32c --- /dev/null +++ b/lib/pg/text_decoder/numeric.rb @@ -0,0 +1,9 @@ +# -*- ruby -*- +# frozen_string_literal: true + +module PG + module TextDecoder + # Init C part of the decoder + init_numeric + end +end # module PG diff --git a/lib/pg/text_encoder/numeric.rb b/lib/pg/text_encoder/numeric.rb new file mode 100644 index 000000000..f413bdd73 --- /dev/null +++ b/lib/pg/text_encoder/numeric.rb @@ -0,0 +1,9 @@ +# -*- ruby -*- +# frozen_string_literal: true + +module PG + module TextEncoder + # Init C part of the decoder + init_numeric + end +end # module PG