db-postgres 0.9.0 → 0.10.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dda5680ffcdd6de60c833681366779e9859e497ae9b367d3bcf3a84c68f15771
4
- data.tar.gz: c9d19d688ed762c97539318765b149e477d47e0cf374b774810cd0cd830336ac
3
+ metadata.gz: 260820a8ff70bad753039f66377343b0740b0925cd7f8e54b4a6b5ccc6ff01e5
4
+ data.tar.gz: 6e65a9610fd6f07c3b026852e27f7b5d03aa0a08f2a04520c493d6d2f08a56ff
5
5
  SHA512:
6
- metadata.gz: a50d56b3495fa91827ff03e1cf9da2667819f3b23e982ed2619bf5633e53222fc09218e4526c3941ee906b65976c8d1796499405a4f2b85cf3cb3ccce20de58c
7
- data.tar.gz: 68c172f739f907eca43c9270c9053ce1e0ab4d33da5c8dbcf75852e73bcb4da7d52233abcf44ef628afccfa011d2d8032391e17eec28a4a27eaacf0d59fc7c53
6
+ metadata.gz: 726edf7a8bc3bbfe27a4faa1c1450dfaadace53b90a198e92fcff8558f9ca484012fd2b0ea9272421f3ffaf4b2fcec768cf90cfcbf7abdfd0d3b72b08271e454
7
+ data.tar.gz: 4fc82ac8ffdb9908c13b2fea11b69c8a4f83a4a3c8d99eab75b92c4c043d901d025b6bcf115a7f4cf3d86bc8591a30055afc38869ceadbd7be8ed4f298505a6e
checksums.yaml.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- �_��N@Z o3����C*ɡ�e\��o�'h}��<�a�n�316P�?�E#5��>z_��"��
2
- Ĭ9o%:�Fc>�������~�%~v�H9���eE2��u��+_b��Aq��=O�������d�fۀ1��y�lA�̮�C$$�Lp���pŠu��>CZ����z���?}�b� mx��WcɄў#�Fp��_�;�^��Φ
1
+ C+gY]�e�� 8/}����1 ���L̍�t��Y��5����r���ݴ��lO =�`�R����?�wF�X.j�o]Q�1���!�-Y�5�-bR3�.z,�a � ���0b�Ȋ�:qv����/��փ;L�޾��xa+r�=
2
+ ����Q諥��������n��t����!�?tF�1����ߚl���<�&C[Q��g!##m��6��+ڵ��悀8p�#@�ƥsŊwtM)paMaR��
3
+ v�'R G����ԱKD�����[����(|�NV,OV=5�.C稦����� [c`qj%��Փk�"�fs��Pt���4d:�g3�/�XI�JbW��H���d��QMز��0V��sYj�K��ثɾ
@@ -1,19 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2024, by Samuel Williams.
4
+ # Copyright, 2018-2026, by Samuel Williams.
5
5
 
6
- require_relative 'connection'
6
+ require_relative "connection"
7
7
 
8
8
  module DB
9
9
  module Postgres
10
+ # A database adapter for connecting to PostgreSQL servers.
10
11
  class Adapter
12
+ # Initialize a new adapter with connection options.
13
+ # @parameter options [Hash] Connection options to be passed to the connection.
11
14
  def initialize(**options)
12
15
  @options = options
13
16
  end
14
17
 
18
+ # @attribute [Hash] The connection options.
15
19
  attr :options
16
20
 
21
+ # Create a new database connection.
22
+ # @returns [Connection] A new connection instance.
17
23
  def call
18
24
  Connection.new(**@options)
19
25
  end
@@ -1,22 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2024, by Samuel Williams.
4
+ # Copyright, 2018-2026, by Samuel Williams.
5
5
 
6
- require 'async/pool/resource'
7
- require 'db/features'
8
- require_relative 'native/connection'
6
+ require "async/pool/resource"
7
+ require "db/features"
8
+ require_relative "native/connection"
9
9
 
10
10
  module DB
11
11
  module Postgres
12
- # This implements the interface between the underlying
12
+ # A high-level database connection that implements the standardized connection interface.
13
+ # This class provides a bridge between the underlying native PostgreSQL interface and the DB gem's unified connection API.
13
14
  class Connection < Async::Pool::Resource
15
+ # Initialize a new database connection.
16
+ # @parameter options [Hash] Connection options passed to the native connection.
14
17
  def initialize(**options)
15
18
  @native = Native::Connection.connect(**options)
16
19
 
17
20
  super()
18
21
  end
19
22
 
23
+ # Close the database connection and release resources.
20
24
  def close
21
25
  if @native
22
26
  @native&.close
@@ -26,16 +30,26 @@ module DB
26
30
  super
27
31
  end
28
32
 
33
+ # Get the type mapping for database types.
34
+ # @returns [Hash] The type mapping configuration.
29
35
  def types
30
36
  @native.types
31
37
  end
32
38
 
39
+ # Append an escaped string value to the buffer.
40
+ # @parameter value [String] The string value to escape and append.
41
+ # @parameter buffer [String] The buffer to append to.
42
+ # @returns [String] The buffer with the escaped string appended.
33
43
  def append_string(value, buffer = String.new)
34
44
  buffer << @native.escape_literal(value)
35
45
 
36
46
  return buffer
37
47
  end
38
48
 
49
+ # Append a literal value to the buffer with appropriate formatting.
50
+ # @parameter value [Object] The value to append (supports Time, Date, Numeric, Boolean, nil, and strings).
51
+ # @parameter buffer [String] The buffer to append to.
52
+ # @returns [String] The buffer with the formatted value appended.
39
53
  def append_literal(value, buffer = String.new)
40
54
  case value
41
55
  when Time, DateTime, Date
@@ -43,11 +57,11 @@ module DB
43
57
  when Numeric
44
58
  buffer << value.to_s
45
59
  when TrueClass
46
- buffer << 'TRUE'
60
+ buffer << "TRUE"
47
61
  when FalseClass
48
- buffer << 'FALSE'
62
+ buffer << "FALSE"
49
63
  when nil
50
- buffer << 'NULL'
64
+ buffer << "NULL"
51
65
  else
52
66
  append_string(value, buffer)
53
67
  end
@@ -55,12 +69,16 @@ module DB
55
69
  return buffer
56
70
  end
57
71
 
72
+ # Append an escaped identifier to the buffer.
73
+ # @parameter value [String | Array(String)] The identifier or array of identifiers to escape.
74
+ # @parameter buffer [String] The buffer to append to.
75
+ # @returns [String] The buffer with the escaped identifier appended.
58
76
  def append_identifier(value, buffer = String.new)
59
77
  case value
60
78
  when Array
61
79
  first = true
62
80
  value.each do |part|
63
- buffer << '.' unless first
81
+ buffer << "." unless first
64
82
  first = false
65
83
 
66
84
  buffer << @native.escape_identifier(part)
@@ -72,7 +90,12 @@ module DB
72
90
  return buffer
73
91
  end
74
92
 
75
- def key_column(name = 'id', primary: true, null: false)
93
+ # Generate a key column definition for table creation.
94
+ # @parameter name [String] The column name.
95
+ # @parameter primary [Boolean] Whether this is a primary key column.
96
+ # @parameter null [Boolean] Whether this column allows null values.
97
+ # @returns [String] The column definition string.
98
+ def key_column(name = "id", primary: true, null: false)
76
99
  buffer = String.new
77
100
 
78
101
  append_identifier(name, buffer)
@@ -92,16 +115,22 @@ module DB
92
115
  return buffer
93
116
  end
94
117
 
118
+ # Get the current connection status.
119
+ # @returns [Symbol] The status symbol from the server.
95
120
  def status
96
121
  @native.status
97
122
  end
98
123
 
124
+ # Send a query to the database server.
125
+ # @parameter statement [String] The SQL statement to execute.
99
126
  def send_query(statement)
100
127
  @native.discard_results
101
128
 
102
129
  @native.send_query(statement)
103
130
  end
104
131
 
132
+ # Get the next result set from a multi-result query.
133
+ # @returns [Native::Result | Nil] The next result set, or `nil` if no more results.
105
134
  def next_result
106
135
  @native.next_result
107
136
  end
@@ -117,6 +146,7 @@ module DB
117
146
  )
118
147
 
119
148
  # Database feature detection for migration and query building.
149
+ # @returns [DB::Features] The supported database features.
120
150
  def features
121
151
  FEATURES
122
152
  end
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2024, by Samuel Williams.
4
+ # Copyright, 2020-2026, by Samuel Williams.
5
5
 
6
6
  module DB
7
7
  module Postgres
8
+ # An error raised by the PostgreSQL adapter.
8
9
  class Error < StandardError
9
10
  end
10
11
  end
@@ -1,16 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2024, by Samuel Williams.
4
+ # Copyright, 2018-2026, by Samuel Williams.
5
5
 
6
- require_relative 'result'
7
- require_relative 'field'
8
- require_relative '../error'
6
+ require_relative "result"
7
+ require_relative "field"
8
+ require_relative "../error"
9
9
 
10
10
  module DB
11
11
  module Postgres
12
12
  module Native
13
+ # Helper class for managing FFI string arrays.
13
14
  class Strings
15
+ # Initialize a string array for FFI.
16
+ # @parameter values [Array] The array of values to convert to FFI strings.
14
17
  def initialize(values)
15
18
  @array = FFI::MemoryPointer.new(:pointer, values.size + 1)
16
19
  @pointers = values.map do |value|
@@ -19,6 +22,7 @@ module DB
19
22
  @array.write_array_of_pointer(@pointers)
20
23
  end
21
24
 
25
+ # @attribute [FFI::MemoryPointer] The FFI array pointer.
22
26
  attr :array
23
27
  end
24
28
 
@@ -46,7 +50,7 @@ module DB
46
50
  # Non-blocking mode:
47
51
  :started, # Waiting for connection to be made.
48
52
  :made, # Connection OK; waiting to send.
49
- :awaiting_response, #Waiting for a response from the postmaster.
53
+ :awaiting_response, # Waiting for a response from the postmaster.
50
54
  :auth_ok, # Received authentication; waiting for backend startup.
51
55
  :setenv, # Negotiating environment.
52
56
  :ssl_startup, # Negotiating SSL.
@@ -81,7 +85,13 @@ module DB
81
85
  ffi_attach_function :PQescapeLiteral, [:pointer, :string, :size_t], :pointer, as: :escape_literal
82
86
  ffi_attach_function :PQescapeIdentifier, [:pointer, :string, :size_t], :pointer, as: :escape_identifier
83
87
 
88
+ # A native FFI connection to the PostgreSQL client library.
84
89
  class Connection < FFI::Pointer
90
+ # Establish a connection to the PostgreSQL server.
91
+ # @parameter types [Hash] Type mapping configuration.
92
+ # @parameter options [Hash] Connection options (database, username, password, host, port, etc.).
93
+ # @returns [Connection] A new connected instance.
94
+ # @raises [Error] If the connection fails.
85
95
  def self.connect(types: DEFAULT_TYPES, **options)
86
96
  # Postgres expects "dbname" as the key name:
87
97
  if database = options.delete(:database)
@@ -96,7 +106,7 @@ module DB
96
106
  keys = Strings.new(options.keys)
97
107
  values = Strings.new(options.values)
98
108
 
99
- pointer = Native.connect_start_params(keys.array, values.array, 0)
109
+ pointer = Native.connect_start_params(keys.array, values.array, 1)
100
110
  Native.set_nonblocking(pointer, 1)
101
111
 
102
112
  io = ::IO.new(Native.socket(pointer), "r+", autoclose: false)
@@ -121,6 +131,10 @@ module DB
121
131
  return self.new(pointer, io, types)
122
132
  end
123
133
 
134
+ # Initialize a native connection wrapper.
135
+ # @parameter address [FFI::Pointer] The pointer to the native connection.
136
+ # @parameter io [IO] The IO object for the socket.
137
+ # @parameter types [Hash] Type mapping configuration.
124
138
  def initialize(address, io, types)
125
139
  super(address)
126
140
 
@@ -128,6 +142,7 @@ module DB
128
142
  @types = types
129
143
  end
130
144
 
145
+ # @attribute [Hash] The type mapping configuration.
131
146
  attr :types
132
147
 
133
148
  # Return the status of the connection.
@@ -152,6 +167,9 @@ module DB
152
167
  @io.close
153
168
  end
154
169
 
170
+ # Escape a literal string value for safe inclusion in SQL queries.
171
+ # @parameter value [String] The value to escape.
172
+ # @returns [String] The escaped string with quotes.
155
173
  def escape_literal(value)
156
174
  value = value.to_s
157
175
 
@@ -164,6 +182,9 @@ module DB
164
182
  return string
165
183
  end
166
184
 
185
+ # Escape an identifier for safe inclusion in SQL queries.
186
+ # @parameter value [String] The identifier to escape.
187
+ # @returns [String] The escaped identifier with quotes.
167
188
  def escape_identifier(value)
168
189
  value = value.to_s
169
190
 
@@ -176,16 +197,23 @@ module DB
176
197
  return string
177
198
  end
178
199
 
200
+ # Enable single row mode for streaming large result sets.
179
201
  def single_row_mode!
180
202
  Native.set_single_row_mode(self)
181
203
  end
182
204
 
205
+ # Send a query to the server for execution.
206
+ # @parameter statement [String] The SQL statement to execute.
183
207
  def send_query(statement)
184
208
  check! Native.send_query(self, statement)
185
209
 
186
210
  flush
187
211
  end
188
212
 
213
+ # Get the next result set from a multi-result query.
214
+ # @parameter types [Hash] Type mapping to use for this result.
215
+ # @returns [Result | Nil] The next result set, or `nil` if no more results.
216
+ # @raises [Error] If the query resulted in an error.
189
217
  def next_result(types: @types)
190
218
  if result = self.get_result
191
219
  status = Native.result_status(result)
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2024, by Samuel Williams.
4
+ # Copyright, 2020-2026, by Samuel Williams.
5
5
 
6
- require_relative 'types'
6
+ require_relative "types"
7
7
 
8
8
  module DB
9
9
  module Postgres
10
10
  module Native
11
11
  DEFAULT_TYPES = {
12
12
  # Pseudo types:
13
- primary_key: Types::Integer.new('BIGSERIAL PRIMARY KEY'),
14
- foreign_key: Types::Integer.new('BIGINT'),
13
+ primary_key: Types::Integer.new("BIGSERIAL PRIMARY KEY"),
14
+ foreign_key: Types::Integer.new("BIGINT"),
15
15
  text: Types::Text.new("TEXT"),
16
16
  string: Types::Text.new("VARCHAR(255)"),
17
17
 
@@ -46,8 +46,8 @@ module DB
46
46
 
47
47
  114 => Types::JSON.new,
48
48
 
49
- 700 => Types::Float.new('float4'),
50
- 701 => Types::Float.new('float8'),
49
+ 700 => Types::Float.new("float4"),
50
+ 701 => Types::Float.new("float8"),
51
51
 
52
52
  1082 => Types::Date.new,
53
53
  1083 => Types::DateTime.new("TIME"),
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2024, by Samuel Williams.
4
+ # Copyright, 2018-2026, by Samuel Williams.
5
5
 
6
- require_relative '../native'
6
+ require_relative "../native"
7
7
 
8
8
  module DB
9
9
  module Postgres
@@ -38,7 +38,12 @@ module DB
38
38
  ffi_attach_function :PQgetCopyData, [:pointer, :pointer, :int], :int, as: :get_copy_data
39
39
  ffi_attach_function :PQfreemem, [:pointer], :void, as: :free_memory
40
40
 
41
+ # A result set from a database query with row iteration and type casting.
41
42
  class Result < FFI::Pointer
43
+ # Initialize a new result set wrapper.
44
+ # @parameter connection [Connection] The connection that produced this result.
45
+ # @parameter types [Hash] Type mapping for field conversion.
46
+ # @parameter address [FFI::Pointer] The pointer to the native result.
42
47
  def initialize(connection, types = {}, address)
43
48
  super(address)
44
49
 
@@ -48,22 +53,33 @@ module DB
48
53
  @casts = nil
49
54
  end
50
55
 
56
+ # Get the number of fields in this result set.
57
+ # @returns [Integer] The field count.
51
58
  def field_count
52
59
  Native.field_count(self)
53
60
  end
54
61
 
62
+ # Get the type converters for each field.
63
+ # @returns [Array] The array of type converter objects.
55
64
  def field_types
56
65
  field_count.times.collect{|i| @types[Native.field_type(self, i)]}
57
66
  end
58
67
 
68
+ # Get the field names for this result set.
69
+ # @returns [Array(String)] The array of field names.
59
70
  def field_names
60
71
  field_count.times.collect{|i| Native.field_name(self, i)}
61
72
  end
62
73
 
74
+ # Get the number of rows in this result set.
75
+ # @returns [Integer] The row count.
63
76
  def row_count
64
77
  Native.row_count(self)
65
78
  end
66
79
 
80
+ # Cast row values to appropriate Ruby types.
81
+ # @parameter row [Array] The raw row data.
82
+ # @returns [Array] The row with values cast to proper types.
67
83
  def cast!(row)
68
84
  @casts ||= self.field_types
69
85
 
@@ -76,6 +92,9 @@ module DB
76
92
  return row
77
93
  end
78
94
 
95
+ # Iterate over each row in the result set.
96
+ # @yields {|row| ...} Each row as an array.
97
+ # @parameter row [Array] The current row data.
79
98
  def each
80
99
  row_count.times do |i|
81
100
  yield cast!(get_row(i))
@@ -84,6 +103,10 @@ module DB
84
103
  Native.clear(self)
85
104
  end
86
105
 
106
+ # Map over each row in the result set.
107
+ # @yields {|row| ...} Each row as an array.
108
+ # @parameter row [Array] The current row data.
109
+ # @returns [Array] The mapped results.
87
110
  def map(&block)
88
111
  results = []
89
112
 
@@ -94,6 +117,8 @@ module DB
94
117
  return results
95
118
  end
96
119
 
120
+ # Convert the entire result set to an array.
121
+ # @returns [Array(Array)] All rows as arrays.
97
122
  def to_a
98
123
  rows = []
99
124
 
@@ -1,90 +1,137 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2024, by Samuel Williams.
4
+ # Copyright, 2020-2026, by Samuel Williams.
5
5
 
6
- require 'json'
7
- require 'bigdecimal'
6
+ require "json"
7
+ require "bigdecimal"
8
8
 
9
9
  module DB
10
10
  module Postgres
11
11
  module Native
12
+ # Provides type converters for translating between PostgreSQL types and Ruby types.
12
13
  module Types
14
+ # A text/string type converter.
13
15
  class Text
16
+ # Initialize a text type converter.
17
+ # @parameter name [String] The SQL type name.
14
18
  def initialize(name = "TEXT")
15
19
  @name = name
16
20
  end
17
21
 
22
+ # @attribute [String] The SQL type name.
18
23
  attr :name
19
24
 
25
+ # Parse a string value from the database.
26
+ # @parameter string [String | Nil] The raw string value.
27
+ # @returns [String | Nil] The string value.
20
28
  def parse(string)
21
29
  string
22
30
  end
23
31
  end
24
32
 
33
+ # An integer type converter.
25
34
  class Integer
35
+ # Initialize an integer type converter.
36
+ # @parameter name [String] The SQL type name.
26
37
  def initialize(name = "INTEGER")
27
38
  @name = name
28
39
  end
29
40
 
41
+ # @attribute [String] The SQL type name.
30
42
  attr :name
31
43
 
44
+ # Parse an integer value from the database.
45
+ # @parameter string [String | Nil] The raw string value.
46
+ # @returns [Integer | Nil] The parsed integer.
32
47
  def parse(string)
33
48
  Integer(string) if string
34
49
  end
35
50
  end
36
51
 
52
+ # A boolean type converter.
37
53
  class Boolean
54
+ # Get the SQL type name for boolean.
55
+ # @returns [String] The type name.
38
56
  def name
39
57
  "BOOLEAN"
40
58
  end
41
59
 
60
+ # Parse a boolean value from the database.
61
+ # @parameter string [String | Nil] The raw string value ('t' or 'f').
62
+ # @returns [Boolean] The parsed boolean value.
42
63
  def parse(string)
43
- string == 't'
64
+ string == "t"
44
65
  end
45
66
  end
46
67
 
68
+ # A decimal type converter.
47
69
  class Decimal
70
+ # Get the SQL type name for decimal.
71
+ # @returns [String] The type name.
48
72
  def name
49
73
  "DECIMAL"
50
74
  end
51
75
 
76
+ # Parse a decimal value from the database.
77
+ # @parameter string [String | Nil] The raw string value.
78
+ # @returns [BigDecimal | Nil] The parsed decimal.
52
79
  def parse(string)
53
80
  BigDecimal(string) if string
54
81
  end
55
82
  end
56
83
 
84
+ # A floating point type converter.
57
85
  class Float
86
+ # Initialize a float type converter.
87
+ # @parameter name [String] The SQL type name.
58
88
  def initialize(name = "FLOAT")
59
89
  @name = name
60
90
  end
61
91
 
92
+ # @attribute [String] The SQL type name.
62
93
  attr :name
63
94
 
95
+ # Parse a float value from the database.
96
+ # @parameter string [String | Nil] The raw string value.
97
+ # @returns [Float | Nil] The parsed float.
64
98
  def parse(string)
65
99
  Float(string) if string
66
100
  end
67
101
  end
68
102
 
103
+ # A symbol/enum type converter.
69
104
  class Symbol
105
+ # Get the SQL type name for enum.
106
+ # @returns [String] The type name.
70
107
  def name
71
108
  "ENUM"
72
109
  end
73
110
 
111
+ # Parse a symbol value from the database.
112
+ # @parameter string [String | Nil] The raw string value.
113
+ # @returns [Symbol | Nil] The parsed symbol.
74
114
  def parse(string)
75
115
  string&.to_sym
76
116
  end
77
117
  end
78
118
 
119
+ # A datetime/timestamp type converter.
79
120
  class DateTime
121
+ # Initialize a datetime type converter.
122
+ # @parameter name [String] The SQL type name.
80
123
  def initialize(name = "TIMESTAMP")
81
124
  @name = name
82
125
  end
83
126
 
127
+ # @attribute [String] The SQL type name.
84
128
  attr :name
85
129
 
130
+ # Parse a datetime value from the database.
131
+ # @parameter string [String | Nil] The raw string value or special values like 'infinity'.
132
+ # @returns [Time | String | Nil] The parsed datetime as a Time object, or special values as strings.
86
133
  def parse(string)
87
- if string == '-infinity' || string == 'infinity' || string.nil?
134
+ if string == "-infinity" || string == "infinity" || string.nil?
88
135
  return string
89
136
  end
90
137
 
@@ -94,7 +141,7 @@ module DB
94
141
  parts[5] = Rational(parts[5])
95
142
 
96
143
  if parts[6].nil?
97
- parts[6] = '+00'
144
+ parts[6] = "+00"
98
145
  end
99
146
 
100
147
  return Time.new(*parts)
@@ -102,11 +149,17 @@ module DB
102
149
  end
103
150
  end
104
151
 
152
+ # A date type converter.
105
153
  class Date
154
+ # Get the SQL type name for date.
155
+ # @returns [String] The type name.
106
156
  def name
107
157
  "DATE"
108
158
  end
109
159
 
160
+ # Parse a date value from the database.
161
+ # @parameter string [String | Nil] The raw string value.
162
+ # @returns [Time | Nil] The parsed date as a UTC Time object.
110
163
  def parse(string)
111
164
  if string
112
165
  parts = string.split(/[\-\s:]/)
@@ -116,11 +169,17 @@ module DB
116
169
  end
117
170
  end
118
171
 
172
+ # A JSON type converter.
119
173
  class JSON
174
+ # Get the SQL type name for JSON.
175
+ # @returns [String] The type name.
120
176
  def name
121
177
  "JSON"
122
178
  end
123
179
 
180
+ # Parse a JSON value from the database.
181
+ # @parameter string [String | Nil] The raw string value.
182
+ # @returns [Hash | Array | Nil] The parsed JSON with symbolized keys.
124
183
  def parse(string)
125
184
  ::JSON.parse(string, symbolize_names: true) if string
126
185
  end
@@ -1,20 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2024, by Samuel Williams.
4
+ # Copyright, 2018-2026, by Samuel Williams.
5
5
 
6
- require 'ffi/native'
7
- require 'ffi/native/config_tool'
6
+ require "ffi/native"
7
+ require "ffi/native/config_tool"
8
8
 
9
9
  module DB
10
10
  module Postgres
11
+ # Provides FFI bindings to the native PostgreSQL client library (libpq).
11
12
  module Native
12
13
  extend FFI::Native::Library
13
14
  extend FFI::Native::Loader
14
15
  extend FFI::Native::ConfigTool
15
16
 
16
- ffi_load('pq') ||
17
- ffi_load_using_config_tool(%w{pg_config --libdir}, names: ['pq']) ||
17
+ ffi_load("pq") ||
18
+ ffi_load_using_config_tool(%w{pg_config --libdir}, names: ["pq"]) ||
18
19
  ffi_load_failure(<<~EOF)
19
20
  Unable to load libpq!
20
21
 
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2024, by Samuel Williams.
4
+ # Copyright, 2018-2026, by Samuel Williams.
5
5
 
6
+ # @namespace
6
7
  module DB
8
+ # @namespace
7
9
  module Postgres
8
- VERSION = "0.9.0"
10
+ VERSION = "0.10.0"
9
11
  end
10
12
  end
data/lib/db/postgres.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2024, by Samuel Williams.
4
+ # Copyright, 2018-2026, by Samuel Williams.
5
5
 
6
- require_relative 'postgres/native'
7
- require_relative 'postgres/connection'
6
+ require_relative "postgres/native"
7
+ require_relative "postgres/connection"
8
8
 
9
- require_relative 'postgres/adapter'
9
+ require_relative "postgres/adapter"
10
10
 
11
- require 'db/adapters'
11
+ require "db/adapters"
12
12
  DB::Adapters.register(:postgres, DB::Postgres::Adapter)
data/license.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2018-2024, by Samuel Williams.
3
+ Copyright, 2018-2026, by Samuel Williams.
4
4
  Copyright, 2021, by Tony Schneider.
5
5
  Copyright, 2022, by Aidan Samuel.
6
6
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: db-postgres
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
124
  requirements: []
125
- rubygems_version: 3.6.9
125
+ rubygems_version: 4.0.3
126
126
  specification_version: 4
127
127
  summary: Ruby FFI bindings for libpq C interface.
128
128
  test_files: []
metadata.gz.sig CHANGED
Binary file