pgx 1.0.5 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pgx.rb +51 -96
  3. metadata +21 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c268162193064b348f33c12034d1de7c69c147e2ce8421b5d0d1fe9849504ce9
4
- data.tar.gz: '08cac6695d7c3920f667f2392ed1da5ff53b162e37dc24461f95fc058555366c'
3
+ metadata.gz: 6d32046f29c429a8e7c9e45ec0d603fd96a2588a18bbe14d773a355e2e37e061
4
+ data.tar.gz: 28e35690b03970729e9ea98080473f90ada24435089237775d3e3c8275515aa6
5
5
  SHA512:
6
- metadata.gz: d149f7288a4a193ec0f56ecd13eadb5ffdc6a635cb4462e451d4d4122738cdf4dfee018c04871f174dd41e4918b5e03ee4b2ca17fd336fa3236aa24a986f71dd
7
- data.tar.gz: 7ac9564501c49481f86a235aeb37be98183f664d277c3707d43f57d99f087684bdd34720deca8127f0749c90bb43c63333bcd79cb6cd0d94c4e6fd29469d59ea
6
+ metadata.gz: 9b5bc92e8d2b851dd43b668ab278d7129dac7e7dd6fa9d18800d4f644d376b345a2dae37392629cc10f0bda979adb0deaff40cfee43d920ebf17dc650725b3cc
7
+ data.tar.gz: e43a561b2ec0dc3e5202d7774a52ad145a80ae543b0d7e52fb83273eb250c1ca08040c49b42be1f94e7249fb209b97530ad25deefc9a56594a97ef7814979544
data/lib/pgx.rb CHANGED
@@ -37,15 +37,13 @@ module PGx
37
37
  )
38
38
 
39
39
  # @author Kiriakos Georgiou, http://www.mockbites.com/about
40
- # Extends the base class PG::Connection methods by adding logging and
40
+ # Extends the PG::Connection methods by adding logging and
41
41
  # retrying capabilities (synchronous methods only.)
42
42
  # The arguments and method behaviors are
43
43
  # identical, except for the 'new' method.
44
44
  # @see http://www.mockbites.com/articles/tech/pgx pgx documentation
45
45
  # @see http://deveiate.org/code/pg/PG/Connection.html Base class methods
46
- class PGx::Connection < PG::Connection
47
- alias PG_close close # PG's close(), for use when closing bad connections
48
-
46
+ class PGx::Connection
49
47
  # @param [Logger] logger: a logger object, or a lambda returning the
50
48
  # logger object. Note that a lambda returning the logger is
51
49
  # preferable because it makes logging of the log object itself
@@ -87,7 +85,7 @@ module PGx
87
85
  # )
88
86
  def initialize(*args)
89
87
  connect_args = PGx.const_get('CONNECT_ARGS')
90
- (our_args, parent_args) = extract_our_args(connect_args, args)
88
+ (our_args, pg_args) = extract_our_args(connect_args, args)
91
89
 
92
90
  log = arg_with_default(connect_args, our_args, :logger)
93
91
  @logger = [ log.is_a?(Proc) ? log.call : log ].flatten
@@ -112,47 +110,29 @@ module PGx
112
110
  @connect_proc = lambda {
113
111
  @prepared_live = {} # reset on connect
114
112
  connect_log_and_try(
115
- lambda { super(*parent_args) },
113
+ lambda { PG::Connection.new(*pg_args) },
116
114
  our_args,
117
- parent_args
115
+ pg_args
118
116
  )
119
117
  }
120
118
  connect_loop()
121
119
  end
122
120
 
121
+ def method_missing(m, *args, &block)
122
+ sql_log_and_try(lambda { @connection.send(m, *args, &block) }, m, args)
123
+ end
124
+
123
125
  # @example
124
126
  # con.transaction do
125
127
  # con.exec "create temp table mytable(x text)"
126
128
  # con.exec "insert into mytable(x) values('a')"
127
129
  # con.exec "insert into mytable(x) values('b')"
128
130
  # end
129
- def transaction(*args)
131
+ def transaction(*args, &block)
130
132
  @in_transaction_block = true
131
- sql_log_and_try(lambda { super }, __method__, args)
133
+ r = sql_log_and_try(lambda { @connection.transaction(*args, &block) }, __method__, args)
132
134
  @in_transaction_block = false
133
- end
134
-
135
- # @example
136
- # con.exec "insert into mytable(x) values('test value')"
137
- # con.exec 'insert into mytable(x) values($1)', ['test value']
138
- def exec(*args)
139
- sql_log_and_try(lambda { super }, __method__, args)
140
- end
141
-
142
- # Alias for exec
143
- def query(*args)
144
- sql_log_and_try(lambda { super }, __method__, args)
145
- end
146
-
147
- # @example
148
- # con.exec_params 'select * from mytable where x = $1 limit $2', [1, 100] do |rs|
149
- # puts rs.fields.collect { |fname| "%-15s" % [fname] }.join('')
150
- # rs.values.collect { |row|
151
- # puts row.collect { |col| "%-15s" % [col] }.join('')
152
- # }
153
- # end
154
- def exec_params(*args)
155
- sql_log_and_try(lambda { super }, __method__, args)
135
+ r
156
136
  end
157
137
 
158
138
  # @example
@@ -163,52 +143,27 @@ module PGx
163
143
  # puts row.collect { |col| "%-15s" % [col] }.join('')
164
144
  # }
165
145
  # end
166
- def prepare(*args)
146
+ def prepare(*args, &block)
167
147
  # it's possible to call prepare() on an statement that is already prepared
168
148
  # if you have a prepare() inside a transaction, and the transaction is retried
169
149
  # thus we check if it's already live
170
150
  s = args[0]
151
+ r = nil
171
152
  if @prepared_live.has_key?(s)
172
153
  log_debug %Q{prepared statement #{s} is already live, skipping re-preparing it}
173
154
  else
174
- sql_log_and_try(lambda { super }, __method__, args)
155
+ r = sql_log_and_try(lambda { @connection.prepare(*args, &block) }, __method__, args)
175
156
  @prepared_statements[s] = args[1]
176
157
  @prepared_live[s] = true
177
158
  end
159
+ r
178
160
  end
179
161
 
180
- # @example
181
- # con.prepare 'sql1', 'select * from mytable limit $1'
182
- # con.exec_prepared 'sql1', [100] do |rs|
183
- # puts rs.fields.collect { |fname| "%-15s" % [fname] }.join('')
184
- # rs.values.collect { |row|
185
- # puts row.collect { |col| "%-15s" % [col] }.join('')
186
- # }
187
- # end
188
- def exec_prepared(*args)
189
- sql_log_and_try(lambda { super }, __method__, args)
190
- end
191
-
192
- def cancel(*args)
193
- sql_log_and_try(lambda { super }, __method__, args)
194
- end
195
-
196
- def close(*args)
197
- sql_log_and_try(lambda { super }, __method__, args)
198
- end
199
-
200
- def finish(*args)
201
- sql_log_and_try(lambda { super }, __method__, args)
202
- end
203
-
204
- def reset(*args)
205
- sql_log_and_try(lambda { super }, __method__, args)
162
+ def reset(*args, &block)
163
+ r = sql_log_and_try(lambda { @connection.reset(*args, &block) }, __method__, args)
206
164
  @prepared_live = {} # reset on connect
207
165
  @connect_init.call(@connection)
208
- end
209
-
210
- def wait_for_notify(*args)
211
- sql_log_and_try(lambda { super }, __method__, args)
166
+ r
212
167
  end
213
168
 
214
169
  private
@@ -221,7 +176,7 @@ module PGx
221
176
 
222
177
  # extract our arguments defined in all_our_possible_args from args
223
178
  # returns an array containing our arguments (hash) and the aguments
224
- # for the parent method
179
+ # for the pg method
225
180
  def extract_our_args(all_our_possible_args, args)
226
181
  our_args = {}
227
182
  if args[0].is_a?(Hash)
@@ -280,45 +235,45 @@ module PGx
280
235
  end
281
236
  end
282
237
 
283
- # sanitize parent arguments, eg: blank the password so it's not in the logs
284
- def sanitize_parent_connect_args(parent_args)
285
- if parent_args.empty?
286
- return parent_args
287
- elsif parent_args.length == 1
288
- if parent_args[0].is_a?(Hash) # hash method
289
- return [ parent_args[0].merge(parent_args[0]) { |k, ov| k == :password ? '...' : ov } ]
238
+ # sanitize pg arguments, eg: blank the password so it's not in the logs
239
+ def sanitize_pg_connect_args(pg_args)
240
+ if pg_args.empty?
241
+ return pg_args
242
+ elsif pg_args.length == 1
243
+ if pg_args[0].is_a?(Hash) # hash method
244
+ return [ pg_args[0].merge(pg_args[0]) { |k, ov| k == :password ? '...' : ov } ]
290
245
  end
291
- if parent_args[0].is_a?(String) # string method
292
- return [ parent_args[0].gsub(/(password\s*=\s*)\S+/, '\1...') ]
246
+ if pg_args[0].is_a?(String) # string method
247
+ return [ pg_args[0].gsub(/(password\s*=\s*)\S+/, '\1...') ]
293
248
  end
294
249
  else # positional arguments method
295
- return [ parent_args.map.with_index { |x, i| i == 6 ? '...' : x } ]
250
+ return [ pg_args.map.with_index { |x, i| i == 6 ? '...' : x } ]
296
251
  end
297
252
  end
298
253
 
299
254
  # merge as follows:
300
255
  # hash and hash -> hash
301
256
  # hash and array -> array
302
- def merge_connect_args(our_args, parent_args)
257
+ def merge_connect_args(our_args, pg_args)
303
258
  if our_args.empty?
304
- return parent_args
305
- elsif parent_args.empty?
259
+ return pg_args
260
+ elsif pg_args.empty?
306
261
  return our_args
307
- elsif parent_args.length == 1 and parent_args[0].is_a?(Hash)
308
- return our_args.merge(parent_args[0]) # connection hash style
262
+ elsif pg_args.length == 1 and pg_args[0].is_a?(Hash)
263
+ return our_args.merge(pg_args[0]) # connection hash style
309
264
  else
310
- return [our_args].concat(parent_args)
265
+ return [our_args].concat(pg_args)
311
266
  end
312
267
  end
313
268
 
314
269
  # log and retry the connect/new method
315
- def connect_log_and_try(caller_super, our_args, parent_args)
270
+ def connect_log_and_try(pg_lambda, our_args, pg_args)
316
271
  try_count = 0
317
272
  all_args = merge_connect_args( sanitize_our_connect_args(our_args),
318
- sanitize_parent_connect_args(parent_args) )
273
+ sanitize_pg_connect_args(pg_args) )
319
274
  begin
320
275
  log_debug function_call_string('connect', all_args)
321
- @connection = caller_super.call # run the parent 'pg' function, new()
276
+ @connection = pg_lambda.call # run pg new() mathod
322
277
  log_debug 'calling connection initialization proc'
323
278
  @connect_init.call(@connection)
324
279
  rescue PG::Error => e
@@ -336,25 +291,25 @@ module PGx
336
291
  end
337
292
 
338
293
  # log and retry statement related methods
339
- def sql_log_and_try(caller_super, caller_method, args)
294
+ def sql_log_and_try(pg_lambda, method, args)
340
295
  try_count = 0
341
296
  begin # re-prepare prepared statements after a failed transaction
342
- transaction_reprepare(caller_method) # just prior to retrying the transaction
343
- log_debug function_call_string(caller_method, args)
344
- caller_super.call # run the parent 'pg' function
297
+ transaction_reprepare(method) # just prior to retrying the transaction
298
+ log_debug function_call_string(method, args)
299
+ pg_lambda.call # run the pg method
345
300
  rescue PG::Error => e
346
301
  if connected? # if we are connected, it's an SQL related error
347
- if not method_in_transaction_block(caller_method) # do not log errors and retry
302
+ if not method_in_transaction_block(method) # do not log errors and retry
348
303
  try_count = try_count + 1 # methods within a transaction
349
304
  log_error(get_error_fields(e) + "\n" + get_error_message(e)) # block because the transaction
350
- error_handlers(e, caller_method, args) # itself will log the error and
305
+ error_handlers(e, method, args) # itself will log the error and
351
306
  retry if sql_retriable?(e, try_count) # retry the transaction block
352
- elsif caller_method.to_s == 'exec_prepared' # exec_prepared failed within a transaction
307
+ elsif method.to_s == 'exec_prepared' # exec_prepared failed within a transaction
353
308
  @transaction_reprepare = args[0] # make a note to re-prepare before retrying
354
309
  end # the transaction
355
310
  else # not connected
356
311
  log_warn 'bad database connection'
357
- PG_close() # close so we don't leak connections
312
+ @connection.close # just in case so we don't leak connections
358
313
  connect_loop()
359
314
  retry
360
315
  end
@@ -363,7 +318,7 @@ module PGx
363
318
  end
364
319
 
365
320
  # special handling of certain error states (not in a transaction)
366
- def error_handlers(pgerr, caller_method, args)
321
+ def error_handlers(pgerr, method, args)
367
322
  begin
368
323
  state = pgerr.result.error_field(PG::Result::PG_DIAG_SQLSTATE)
369
324
  rescue PG::Error => e
@@ -372,12 +327,12 @@ module PGx
372
327
 
373
328
  case state
374
329
  when '26000'
375
- reprepare_statement(args[0]) if caller_method.to_s == 'exec_prepared'
330
+ reprepare_statement(args[0]) if method.to_s == 'exec_prepared'
376
331
  end # case
377
332
  end
378
333
 
379
- def transaction_reprepare(caller_method)
380
- if caller_method.to_s == 'transaction' and not @transaction_reprepare.nil?
334
+ def transaction_reprepare(method)
335
+ if method.to_s == 'transaction' and not @transaction_reprepare.nil?
381
336
  reprepare_statement(@transaction_reprepare)
382
337
  @transaction_reprepare = nil
383
338
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kiriakos Georgiou
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-18 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-04-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pg
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
13
27
  description: |2
14
28
  A pure ruby "thin" extension of pg that provides logging,
15
29
  transaction retrying, and database reconnecting functionality.
@@ -23,7 +37,7 @@ homepage: http://www.mockbites.com/articles/tech/pgx
23
37
  licenses:
24
38
  - MIT
25
39
  metadata: {}
26
- post_install_message:
40
+ post_install_message:
27
41
  rdoc_options: []
28
42
  require_paths:
29
43
  - lib
@@ -38,8 +52,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
38
52
  - !ruby/object:Gem::Version
39
53
  version: '0'
40
54
  requirements: []
41
- rubygems_version: 3.1.2
42
- signing_key:
55
+ rubygems_version: 3.3.26
56
+ signing_key:
43
57
  specification_version: 4
44
58
  summary: A thin extension of pg
45
59
  test_files: []