Class: Pgoutput::Decoder::TypeRegistry
- Inherits:
-
Object
- Object
- Pgoutput::Decoder::TypeRegistry
- Defined in:
- lib/pgoutput/decoder/type_registry.rb
Overview
Immutable PostgreSQL OID-to-decoder registry.
The registry maps PostgreSQL type OIDs to callable decoders. It is intentionally separate from pgoutput-parser so the parser remains a pure protocol layer and the decoder owns value conversion policy.
Registry instances are immutable after construction. Decoded values are passed through Ractor.make_shareable so caller-visible values can cross Ractor boundaries safely when Ruby supports the value shape.
Constant Summary collapse
- BOOL =
PostgreSQL bool OID.
16- INT8 =
PostgreSQL int8 / bigint OID.
20- INT2 =
PostgreSQL int2 / smallint OID.
21- INT4 =
PostgreSQL int4 / integer OID.
23- TEXT =
PostgreSQL text OID.
25- JSON =
PostgreSQL json OID.
114- FLOAT4 =
PostgreSQL float4 / real OID.
700- FLOAT8 =
PostgreSQL float8 / double precision OID.
701- VARCHAR =
PostgreSQL varchar OID.
1043- DATE =
PostgreSQL date OID.
1082- TIMESTAMP =
PostgreSQL timestamp without time zone OID.
1114- TIMESTAMPTZ =
PostgreSQL timestamp with time zone OID.
1184- NUMERIC =
PostgreSQL numeric OID.
1700- UUID =
PostgreSQL uuid OID.
2950- JSONB =
PostgreSQL jsonb OID.
3802
Class Method Summary collapse
-
.default ⇒ TypeRegistry
Return the process-local default immutable registry.
-
.default_decoders ⇒ Hash<Integer, Proc>
Build the default OID decoder table.
Instance Method Summary collapse
-
#decode(oid, raw, format) ⇒ Object?
Decode a raw tuple payload.
-
#initialize(decoders = self.class.default_decoders) ⇒ void
constructor
Create an immutable registry.
-
#with_decoder(oid) {|raw, format| ... } ⇒ TypeRegistry
Create a new registry with one custom decoder.
Constructor Details
#initialize(decoders = self.class.default_decoders) ⇒ void
Create an immutable registry.
96 97 98 99 |
# File 'lib/pgoutput/decoder/type_registry.rb', line 96 def initialize(decoders = self.class.default_decoders) @decoders = decoders.dup.freeze freeze end |
Class Method Details
.default ⇒ TypeRegistry
Return the process-local default immutable registry.
65 66 67 |
# File 'lib/pgoutput/decoder/type_registry.rb', line 65 def self.default @default ||= new(default_decoders) end |
.default_decoders ⇒ Hash<Integer, Proc>
Build the default OID decoder table.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/pgoutput/decoder/type_registry.rb', line 72 def self.default_decoders { BOOL => ->(raw, format) { decode_bool(raw, format) }, INT2 => ->(raw, format) { decode_int(raw, format, 2, "s>") }, INT4 => ->(raw, format) { decode_int(raw, format, 4, "l>") }, INT8 => ->(raw, format) { decode_int(raw, format, 8, "q>") }, TEXT => ->(raw, _format) { raw.dup.freeze }, VARCHAR => ->(raw, _format) { raw.dup.freeze }, FLOAT4 => ->(raw, format) { decode_float(raw, format, 4, "g") }, FLOAT8 => ->(raw, format) { decode_float(raw, format, 8, "G") }, NUMERIC => ->(raw, format) { format == :text ? BigDecimal(raw) : raw.dup.freeze }, JSON => ->(raw, format) { format == :text ? ::JSON.parse(raw) : raw.dup.freeze }, JSONB => ->(raw, format) { decode_jsonb(raw, format) }, UUID => ->(raw, format) { format == :text ? raw.dup.freeze : decode_uuid_binary(raw) }, DATE => ->(raw, format) { format == :text ? Date.iso8601(raw) : raw.dup.freeze }, TIMESTAMP => ->(raw, format) { format == :text ? Time.parse(raw) : raw.dup.freeze }, TIMESTAMPTZ => ->(raw, format) { format == :text ? Time.parse(raw) : raw.dup.freeze } }.freeze end |
Instance Method Details
#decode(oid, raw, format) ⇒ Object?
Decode a raw tuple payload.
107 108 109 110 111 112 113 |
# File 'lib/pgoutput/decoder/type_registry.rb', line 107 def decode(oid, raw, format) return nil if raw.nil? decoder = @decoders[oid] decoded = decoder ? decoder.call(raw, format) : raw.dup.freeze Ractor.make_shareable(decoded) end |
#with_decoder(oid) {|raw, format| ... } ⇒ TypeRegistry
Create a new registry with one custom decoder.
123 124 125 126 127 |
# File 'lib/pgoutput/decoder/type_registry.rb', line 123 def with_decoder(oid, &block) raise ArgumentError, "block required" unless block self.class.new(@decoders.merge(Integer(oid) => block)) end |