db-postgres 0.2.2 → 0.5.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: fd023d0017d7e3a5b859c0072e9c6073b1d2f0d33a80e2602e3b10ab3fc1774a
4
- data.tar.gz: 4df334b62fb206775e8d18bc2e9431d240098b84f67a4c6c8d04e3f1ee88f24b
3
+ metadata.gz: edb8f8a5768d89eb1bd6a69b1590f11ed20e8b07570f34887b3a7ba4ebcb5c75
4
+ data.tar.gz: 3a793acd806475a5716096b2475156d733953bf3cbafec09284f808b3f70c889
5
5
  SHA512:
6
- metadata.gz: d473ba682e4fc823c5945d05d6265d5c31a11edbc4946de842ee2ab42f6867fc6c1cdd01130374f11e9605f6ab4655bb7ad7232cf3655925c9ee20cf3beb9a3c
7
- data.tar.gz: 54c94c483f379b1b1d601c2d3ce8c86477a4a7395b73b196b1a546e166413393aa4534d28f8a77a3de3179b43f386791b4798fd4fcda170adeaf8720e9da3482
6
+ metadata.gz: a55115f3c47e2b6eacf5b05799682f3e2b9b5668e289944a5c890dd644deb0a0525ea7ae8520f08a17f2df4816354d0eece6a2d47f2895789b5575b9a1d4a127
7
+ data.tar.gz: 962fdcf60e96b32221e77b690f99b47b40b09050d3c93545a3841188c423e77a94b510ffa520642b243357a0d0b77eb5ec3181d5e2c078f32e14ded354db83af
data/lib/.DS_Store ADDED
Binary file
@@ -65,20 +65,33 @@ module DB
65
65
  end
66
66
 
67
67
  def append_identifier(value, buffer = String.new)
68
- buffer << @native.escape_identifier(value)
68
+ case value
69
+ when Array
70
+ first = true
71
+ value.each do |part|
72
+ buffer << '.' unless first
73
+ first = false
74
+
75
+ buffer << @native.escape_identifier(part)
76
+ end
77
+ else
78
+ buffer << @native.escape_identifier(value)
79
+ end
69
80
 
70
81
  return buffer
71
82
  end
72
83
 
73
- def id_column(name = 'id', primary_key: true)
84
+ def key_column(name = 'id', primary: true, null: false)
74
85
  buffer = String.new
75
86
 
76
87
  append_identifier(name, buffer)
77
88
 
78
89
  buffer << " BIGSERIAL"
79
90
 
80
- if primary_key
91
+ if primary
81
92
  buffer << " PRIMARY KEY"
93
+ elsif !null
94
+ buffer << " NOT NULL"
82
95
  end
83
96
 
84
97
  return buffer
@@ -18,14 +18,38 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require 'ffi'
21
+ require 'ffi/module'
22
+ require 'ffi/module/config_tool'
22
23
 
23
24
  module DB
24
25
  module Postgres
25
26
  module Native
26
- extend FFI::Library
27
+ extend FFI::Module::Library
28
+ extend FFI::Module::Loader
29
+ extend FFI::Module::ConfigTool
27
30
 
28
- ffi_lib 'pq'
31
+ ffi_load('pq') ||
32
+ ffi_load_using_config_tool(%w{pg_config --libdir}, names: ['pq']) ||
33
+ ffi_load_failure(<<~EOF)
34
+ Unable to load libpq!
35
+
36
+ ## Ubuntu
37
+
38
+ sudo apt-get install postgresql postgresql-contrib
39
+
40
+ ## Arch Linux
41
+
42
+ sudo pacman -S postgresql
43
+
44
+ ## MacPorts
45
+
46
+ sudo port install postgresql11
47
+
48
+ ## Homebrew
49
+
50
+ brew install postgresql
51
+
52
+ EOF
29
53
  end
30
54
  end
31
55
  end
@@ -25,35 +25,35 @@ require_relative '../error'
25
25
  module DB
26
26
  module Postgres
27
27
  module Native
28
- def self.array_of_strings(values)
29
- array = FFI::MemoryPointer.new(:pointer, values.size + 1)
30
-
31
- pointers = values.map do |value|
32
- FFI::MemoryPointer.from_string(value.to_s)
28
+ class Strings
29
+ def initialize(values)
30
+ @array = FFI::MemoryPointer.new(:pointer, values.size + 1)
31
+ @pointers = values.map do |value|
32
+ FFI::MemoryPointer.from_string(value.to_s)
33
+ end
34
+ @array.write_array_of_pointer(@pointers)
33
35
  end
34
36
 
35
- array.write_array_of_pointer(pointers)
36
-
37
- return array
37
+ attr :array
38
38
  end
39
39
 
40
- attach_function :connect_start_params, :PQconnectStartParams, [:pointer, :pointer, :int], :pointer
40
+ ffi_attach_function :PQconnectStartParams, [:pointer, :pointer, :int], :pointer, as: :connect_start_params
41
41
 
42
- enum :polling_status, [
42
+ ffi_define_enumeration :polling_status, [
43
43
  :failed,
44
44
  :wait_readable,
45
45
  :wait_writable,
46
46
  :ok,
47
47
  ]
48
48
 
49
- attach_function :connect_poll, :PQconnectPoll, [:pointer], :polling_status
49
+ ffi_attach_function :PQconnectPoll, [:pointer], :polling_status, as: :connect_poll
50
50
 
51
51
  # Close the connection and release underlying resources.
52
- attach_function :finish, :PQfinish, [:pointer], :void
52
+ ffi_attach_function :PQfinish, [:pointer], :void, as: :finish
53
53
 
54
- attach_function :error_message, :PQerrorMessage, [:pointer], :string
54
+ ffi_attach_function :PQerrorMessage, [:pointer], :string, as: :error_message
55
55
 
56
- enum :status, [
56
+ ffi_define_enumeration :status, [
57
57
  # Normal mode:
58
58
  :ok,
59
59
  :bad,
@@ -70,31 +70,31 @@ module DB
70
70
  :consume, # Wait for any pending message and consume them.
71
71
  ]
72
72
 
73
- attach_function :status, :PQstatus, [:pointer], :status
73
+ ffi_attach_function :PQstatus, [:pointer], :status, as: :status
74
74
 
75
- attach_function :socket, :PQsocket, [:pointer], :int
75
+ ffi_attach_function :PQsocket, [:pointer], :int, as: :socket
76
76
 
77
- attach_function :set_nonblocking, :PQsetnonblocking, [:pointer, :int], :int
78
- attach_function :flush, :PQflush, [:pointer], :int
77
+ ffi_attach_function :PQsetnonblocking, [:pointer, :int], :int, as: :set_nonblocking
78
+ ffi_attach_function :PQflush, [:pointer], :int, as: :flush
79
79
 
80
80
  # Submits a command to the server without waiting for the result(s). 1 is returned if the command was successfully dispatched and 0 if not (in which case, use PQerrorMessage to get more information about the failure).
81
- attach_function :send_query, :PQsendQuery, [:pointer, :string], :int
81
+ ffi_attach_function :PQsendQuery, [:pointer, :string], :int, as: :send_query
82
82
 
83
83
  # int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
84
- attach_function :send_query_params, :PQsendQueryParams, [:pointer, :string, :int, :pointer, :pointer, :pointer, :pointer, :int], :int
84
+ ffi_attach_function :PQsendQueryParams, [:pointer, :string, :int, :pointer, :pointer, :pointer, :pointer, :int], :int, as: :send_query_params
85
85
 
86
- attach_function :set_single_row_mode, :PQsetSingleRowMode, [:pointer], :int
86
+ ffi_attach_function :PQsetSingleRowMode, [:pointer], :int, as: :set_single_row_mode
87
87
 
88
- attach_function :get_result, :PQgetResult, [:pointer], :pointer
88
+ ffi_attach_function :PQgetResult, [:pointer], :pointer, as: :get_result
89
89
 
90
90
  # If input is available from the server, consume it:
91
- attach_function :consume_input, :PQconsumeInput, [:pointer], :int
91
+ ffi_attach_function :PQconsumeInput, [:pointer], :int, as: :consume_input
92
92
 
93
93
  # Returns 1 if a command is busy, that is, PQgetResult would block waiting for input. A 0 return indicates that PQgetResult can be called with assurance of not blocking.
94
- attach_function :is_busy, :PQisBusy, [:pointer], :int
94
+ ffi_attach_function :PQisBusy, [:pointer], :int, as: :is_busy
95
95
 
96
- attach_function :escape_literal, :PQescapeLiteral, [:pointer, :string, :size_t], :pointer
97
- attach_function :escape_identifier, :PQescapeIdentifier, [:pointer, :string, :size_t], :pointer
96
+ ffi_attach_function :PQescapeLiteral, [:pointer, :string, :size_t], :pointer, as: :escape_literal
97
+ ffi_attach_function :PQescapeIdentifier, [:pointer, :string, :size_t], :pointer, as: :escape_identifier
98
98
 
99
99
  module IO
100
100
  def self.new(fd, mode)
@@ -104,15 +104,20 @@ module DB
104
104
 
105
105
  class Connection < FFI::Pointer
106
106
  def self.connect(wrapper: IO, types: DEFAULT_TYPES, **options)
107
- # Prefer 'database' key for 'dbname' parameter:
107
+ # Postgres expects "dbname" as the key name:
108
108
  if database = options.delete(:database)
109
109
  options[:dbname] = database
110
110
  end
111
111
 
112
- keys = Native.array_of_strings(options.keys)
113
- values = Native.array_of_strings(options.values)
112
+ # Postgres expects "user" as the key name:
113
+ if username = options.delete(:username)
114
+ options[:user] = username
115
+ end
116
+
117
+ keys = Strings.new(options.keys)
118
+ values = Strings.new(options.values)
114
119
 
115
- pointer = Native.connect_start_params(keys, values, 0)
120
+ pointer = Native.connect_start_params(keys.array, values.array, 0)
116
121
  Native.set_nonblocking(pointer, 1)
117
122
 
118
123
  io = wrapper.new(Native.socket(pointer), "r+")
@@ -23,7 +23,7 @@ require_relative '../native'
23
23
  module DB
24
24
  module Postgres
25
25
  module Native
26
- enum :query_status, [
26
+ ffi_define_enumeration :query_status, [
27
27
  :empty_query, # empty query string was executed
28
28
  :command_ok, # a query command that doesn't return anything was executed properly by the backend
29
29
  :tuples_ok, # a query command that returns tuples was executed properly by the backend, PGresult contains the result tuples
@@ -36,24 +36,26 @@ module DB
36
36
  :single_tuple, # single tuple from larger resultset
37
37
  ]
38
38
 
39
- attach_function :result_status, :PQresultStatus, [:pointer], :query_status
40
- attach_function :result_error_message, :PQresultErrorMessage, [:pointer], :string
39
+ ffi_attach_function :PQresultStatus, [:pointer], :query_status, as: :result_status
40
+ ffi_attach_function :PQresultErrorMessage, [:pointer], :string, as: :result_error_message
41
41
 
42
- attach_function :row_count, :PQntuples, [:pointer], :int
43
- attach_function :field_count, :PQnfields, [:pointer], :int
44
- attach_function :field_name, :PQfname, [:pointer, :int], :string
45
- attach_function :field_type, :PQftype, [:pointer, :int], :int
42
+ ffi_attach_function :PQntuples, [:pointer], :int, as: :row_count
43
+ ffi_attach_function :PQnfields, [:pointer], :int, as: :field_count
44
+ ffi_attach_function :PQfname, [:pointer, :int], :string, as: :field_name
45
+ ffi_attach_function :PQftype, [:pointer, :int], :int, as: :field_type
46
46
 
47
- attach_function :get_value, :PQgetvalue, [:pointer, :int, :int], :string
48
- attach_function :get_is_null, :PQgetisnull, [:pointer, :int, :int], :int
47
+ ffi_attach_function :PQgetvalue, [:pointer, :int, :int], :string, as: :get_value
48
+ ffi_attach_function :PQgetisnull, [:pointer, :int, :int], :int, as: :get_is_null
49
49
 
50
- attach_function :clear, :PQclear, [:pointer], :void
50
+ ffi_attach_function :PQclear, [:pointer], :void, as: :clear
51
51
 
52
- attach_function :put_copy_end, :PQputCopyEnd, [:pointer, :string], :int
53
- attach_function :get_copy_data, :PQgetCopyData, [:pointer, :pointer, :int], :int
54
- attach_function :free_memory, :PQfreemem, [:pointer], :void
52
+ ffi_attach_function :PQputCopyEnd, [:pointer, :string], :int, as: :put_copy_end
53
+ ffi_attach_function :PQgetCopyData, [:pointer, :pointer, :int], :int, as: :get_copy_data
54
+ ffi_attach_function :PQfreemem, [:pointer], :void, as: :free_memory
55
55
 
56
56
  class Result < FFI::Pointer
57
+ include Enumerable
58
+
57
59
  def initialize(connection, types = {}, address)
58
60
  super(address)
59
61
 
@@ -99,17 +101,8 @@ module DB
99
101
  Native.clear(self)
100
102
  end
101
103
 
102
- def to_a
103
- rows = []
104
-
105
- self.each do |row|
106
- rows << row
107
- end
108
-
109
- return rows
110
- end
111
-
112
104
  protected
105
+
113
106
  def get_value(row, field)
114
107
  if Native.get_is_null(self, row, field) == 0
115
108
  Native.get_value(self, row, field)
@@ -20,6 +20,6 @@
20
20
 
21
21
  module DB
22
22
  module Postgres
23
- VERSION = "0.2.2"
23
+ VERSION = "0.5.0"
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: db-postgres
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-07 00:00:00.000000000 Z
11
+ date: 2021-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: ffi
14
+ name: ffi-module
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: async-io
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - ">="
@@ -25,7 +39,7 @@ dependencies:
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
- name: async-io
42
+ name: async-pool
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - ">="
@@ -114,6 +128,7 @@ executables: []
114
128
  extensions: []
115
129
  extra_rdoc_files: []
116
130
  files:
131
+ - lib/.DS_Store
117
132
  - lib/db/postgres.rb
118
133
  - lib/db/postgres/adapter.rb
119
134
  - lib/db/postgres/connection.rb
@@ -143,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
158
  - !ruby/object:Gem::Version
144
159
  version: '0'
145
160
  requirements: []
146
- rubygems_version: 3.1.2
161
+ rubygems_version: 3.2.3
147
162
  signing_key:
148
163
  specification_version: 4
149
164
  summary: Ruby FFI bindings for libpq C interface.