pg_conn 0.35.0 → 0.35.1
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 +4 -4
- data/lib/pg_conn/version.rb +1 -1
- data/lib/pg_conn.rb +183 -102
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c834402fcec956ffcb288fa201d7a6bade6b435002ae4758e1d86ea54f5a656
|
4
|
+
data.tar.gz: 20fafcbbe4c9f93ab426c6012e91f073e5224ab84d23948da894f4a64b5ef7c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1da57a0c7f8daffdaac879899d3bd7d9723a6512e038afda6996329717d9b0246f7b646161ee1f0a82e00d828a12b9328f212ef98b47132914e4c66dc9f1e888
|
7
|
+
data.tar.gz: 4fd13dd8b4130ebb417379dd3ec62a3476f7d721a7617d14ae2f5b88a0c1f13812dbd440931bc14c02c3db702f9ff181a8b4ab3116a08527293ae6b632c9cd0b
|
data/lib/pg_conn/version.rb
CHANGED
data/lib/pg_conn.rb
CHANGED
@@ -53,9 +53,9 @@ module PgConn
|
|
53
53
|
# true/false, Time/Date/DateTime, and arrays. Other types may require
|
54
54
|
# special handling
|
55
55
|
#
|
56
|
-
# Hashes are quoted as a literal JSON expression
|
57
|
-
#
|
58
|
-
# or 'jsonb'
|
56
|
+
# Hashes are quoted as a literal JSON expression converted into the given
|
57
|
+
# :json_type. If :json_type is nil, it is the application's responsibility to
|
58
|
+
# cast them to either 'json' or 'jsonb'
|
59
59
|
#
|
60
60
|
# Note that a tuple value (an array) must be quoted using #quote_tuple
|
61
61
|
# because #quote_value would quote the tuple as an array value instead of a
|
@@ -66,7 +66,7 @@ module PgConn
|
|
66
66
|
# type when the argument is an empty array. It is not needed if the array
|
67
67
|
# is guaranteed to be non-empty. Nested arrays are not supported
|
68
68
|
#
|
69
|
-
def self.quote_value(value, elem_type: nil)
|
69
|
+
def self.quote_value(value, elem_type: nil, json_type: nil)
|
70
70
|
case value
|
71
71
|
when Literal; value
|
72
72
|
when String; escape_literal(value)
|
@@ -82,32 +82,34 @@ module PgConn
|
|
82
82
|
else
|
83
83
|
"array[#{value.map { |elem| quote_value(elem) }.join(', ')}]"
|
84
84
|
end
|
85
|
-
when Hash; "'#{value.to_json}'"
|
85
|
+
when Hash; ["'#{value.to_json}'", json_type].compact.join('::')
|
86
86
|
else
|
87
87
|
escape_literal(value.to_s)
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
91
|
# Quote values and concatenate them using ',' as separator
|
92
|
-
def self.quote_values(values,
|
93
|
-
values.map { |value| quote_value(value,
|
92
|
+
def self.quote_values(values, **opts)
|
93
|
+
values.map { |value| quote_value(value, **opts) }.join(", ")
|
94
94
|
end
|
95
95
|
|
96
96
|
# Quote an array of values as a tuple. The element types should be in the
|
97
97
|
# same order as the array arguments. #quote_tuples is same as #quote_values
|
98
98
|
# except the values may have different types (this makes no difference
|
99
99
|
# except in the case when the tuple may contain empty array(s))
|
100
|
-
|
100
|
+
#
|
101
|
+
# Note that it is :elem_types (plural) and not :elem_type
|
102
|
+
def self.quote_tuple(tuple, elem_types: nil, **opts)
|
101
103
|
elem_types = Array(elem_types)
|
102
104
|
tuple.map { |value|
|
103
105
|
elem_type = value.is_a?(Array) ? elem_types&.shift : nil
|
104
|
-
quote_value(value, elem_type: elem_type)
|
106
|
+
quote_value(value, **opts, elem_type: elem_type)
|
105
107
|
}.join(", ")
|
106
108
|
end
|
107
109
|
|
108
110
|
# Quote an array of tuples
|
109
|
-
def self.quote_tuples(tuples,
|
110
|
-
tuples.map { |tuple| "(#{quote_tuple(tuple,
|
111
|
+
def self.quote_tuples(tuples, **opts)
|
112
|
+
tuples.map { |tuple| "(#{quote_tuple(tuple, **opts)})" }.join(", ")
|
111
113
|
end
|
112
114
|
|
113
115
|
# Used to mark strings as literals that should not be quoted. This is the
|
@@ -125,6 +127,9 @@ module PgConn
|
|
125
127
|
# The class of column names (Symbol or String). Default is Symbol
|
126
128
|
attr_reader :field_name_class
|
127
129
|
|
130
|
+
# Default postgres JSON type (either 'json' or 'jsonb'). Default is 'jsonb'
|
131
|
+
attr_reader :default_json_type
|
132
|
+
|
128
133
|
# Name of user
|
129
134
|
def user() @pg_connection.user end
|
130
135
|
alias_method :username, :user # Obsolete FIXME Is it?
|
@@ -155,28 +160,56 @@ module PgConn
|
|
155
160
|
# #exec or #transaction block. The timestamp includes the current time zone
|
156
161
|
attr_reader :timestamptz
|
157
162
|
|
158
|
-
# Controls error messages. It can be assigned true, false, nil
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
+
# Controls error messages. It can be assigned true, false, nil, or a Proc
|
164
|
+
# object that recieves the message. True causes the message to be printed
|
165
|
+
# to standard error, false ignores it, and nil resets the state to the
|
166
|
+
# default given when the connection was initialized. #silent? returns true
|
167
|
+
# if #silent is false or a Proc object and should be used instead #silent
|
168
|
+
# to check the state because #silent returns truish when output is
|
169
|
+
# redirected to a Proc
|
170
|
+
#
|
171
|
+
# Note that #silent=, #notice=, and warning= only controls the error
|
172
|
+
# message, the exception is passed through unaltered
|
173
|
+
#
|
163
174
|
def silent() @options[:silent] end
|
175
|
+
def silent?() @producers[:silent].nil? end # silent == false/Proc is true
|
164
176
|
def silent=(value) set_option(:silent, value) end
|
165
177
|
|
166
|
-
# Controls notices. It can be assigned true, false, nil, or a Proc object
|
167
|
-
# that recieves the message. True causes the message to be printed to
|
168
|
-
# standard output, false ignores it, and nil resets the state to the
|
169
|
-
# default given when the connection was initialized or false if absent
|
170
|
-
def notice() @options[:notice] end
|
171
|
-
def notice=(value) set_option(:notice, value) end
|
172
|
-
|
173
178
|
# Controls warnings. It can be assigned true, false, nil, or a Proc object
|
174
179
|
# that recieves the message. True causes the message to be printed to
|
175
180
|
# standard error, false ignores it, and nil resets the state to the default
|
176
|
-
# given when the connection was initialized
|
181
|
+
# given when the connection was initialized
|
177
182
|
def warning() @options[:warning] end
|
183
|
+
def warning?() !warning.nil? end
|
178
184
|
def warning=(value) set_option(:warning, value) end
|
179
185
|
|
186
|
+
# Controls notice messages. It can be assigned true, false, nil, or a Proc
|
187
|
+
# object that recieves the message. True causes the message to be printed
|
188
|
+
# to standard error, false ignores it, and nil resets the state to the
|
189
|
+
# default given when the connection was initialized. Default false
|
190
|
+
def notice() @options[:notice] end
|
191
|
+
def notice?() !notice.nil? end
|
192
|
+
def notice=(value) set_option(:notice, value) end
|
193
|
+
|
194
|
+
# Controls info messages. It can be assigned true, false, nil, or a Proc
|
195
|
+
# object that recieves the message. True causes the message to be printed
|
196
|
+
# to standard output, false ignores it, and nil resets the state to the
|
197
|
+
# default given when the connection was initialized. Default false. Note
|
198
|
+
# that #info is the only level that outputs to standard output
|
199
|
+
def info() @options[:info] end
|
200
|
+
def info?() !info.nil? end
|
201
|
+
def info=(value) set_option(:info, value) end
|
202
|
+
|
203
|
+
# Controls debug messages. It can be assigned true, false, nil, or a Proc
|
204
|
+
# object that recieves the message. True causes the message to be printed
|
205
|
+
# to standard error, false ignores it, and nil resets the state to the
|
206
|
+
# default given when the connection was initialized. Default false
|
207
|
+
def debug() @options[:debug] end
|
208
|
+
def debug?() !debug.nil? end
|
209
|
+
def debug=(value) set_option(:debug, value) end
|
210
|
+
|
211
|
+
DEFAULT_OPTIONS = { silent: false, warning: true, notice: false, info: false, debug: false }
|
212
|
+
|
180
213
|
# TODO: Move error message handling into the same framework as notice and
|
181
214
|
# warning but we have a name collision just below that would need to be
|
182
215
|
# resolved somehow
|
@@ -214,8 +247,6 @@ module PgConn
|
|
214
247
|
# if absent in the Postgres error message
|
215
248
|
def errchar = err[2]
|
216
249
|
|
217
|
-
DEFAULT_OPTIONS = { silent: false, notice: false, warning: false }
|
218
|
-
|
219
250
|
# :call-seq:
|
220
251
|
# initialize(dbname = nil, user = nil, **options)
|
221
252
|
# initialize(connection_hash, **options)
|
@@ -247,8 +278,10 @@ module PgConn
|
|
247
278
|
# Symbol (the default) or String. The :timestamp option is used
|
248
279
|
# internally to set the timestamp for transactions
|
249
280
|
#
|
250
|
-
# The :notice and :warning options sets the default output handling this
|
251
|
-
# connection (FIXME fails on copied connections)
|
281
|
+
# The :notice and :warning options sets the default output handling for this
|
282
|
+
# connection (FIXME fails on copied connections). Default is to suppress
|
283
|
+
# notices and lower - this is diffent from postgres that by default include
|
284
|
+
# notices
|
252
285
|
#
|
253
286
|
# Note that the connection hash and the connection string may support more
|
254
287
|
# parameters than documented here. Consult
|
@@ -263,7 +296,17 @@ module PgConn
|
|
263
296
|
if args.last.is_a?(Hash)
|
264
297
|
opts = args.last
|
265
298
|
@field_name_class = opts.delete(:field_name_class) || Symbol
|
266
|
-
|
299
|
+
|
300
|
+
# Extract options from arguments
|
301
|
+
options = DEFAULT_OPTIONS.to_h { |k,v|
|
302
|
+
r = if opts.key?(k)
|
303
|
+
value = opts.delete(k)
|
304
|
+
value.nil? ? v : value
|
305
|
+
else
|
306
|
+
v
|
307
|
+
end
|
308
|
+
[k, r]
|
309
|
+
}
|
267
310
|
|
268
311
|
# FIXME: Is this used?
|
269
312
|
@timestamp = opts.delete(:timestamp)
|
@@ -272,7 +315,7 @@ module PgConn
|
|
272
315
|
args.pop if opts.empty?
|
273
316
|
else
|
274
317
|
@field_name_class = Symbol
|
275
|
-
options = DEFAULT_OPTIONS
|
318
|
+
options = DEFAULT_OPTIONS.dup
|
276
319
|
end
|
277
320
|
|
278
321
|
# else # We assume that the current user is a postgres superuser
|
@@ -340,11 +383,17 @@ module PgConn
|
|
340
383
|
@pg_connection.field_name_type = @field_name_class.to_s.downcase.to_sym # Use symbol field names
|
341
384
|
end
|
342
385
|
|
343
|
-
# Set options
|
344
|
-
#
|
345
|
-
|
346
|
-
|
347
|
-
|
386
|
+
# Set options. The initial options also serves as default values and are
|
387
|
+
# themselves initialized using DEFAULT_VALUES
|
388
|
+
#
|
389
|
+
# Note that options is initialized even if there is no connection to
|
390
|
+
# avoid special casing
|
391
|
+
@default_options = options
|
392
|
+
@options = {}
|
393
|
+
@producers = {} # Map from message level to Proc or nil
|
394
|
+
set_options(@default_options) if @pg_connection
|
395
|
+
|
396
|
+
@default_json_type = :jsonb
|
348
397
|
@schema = SchemaMethods.new(self)
|
349
398
|
@role = RoleMethods.new(self)
|
350
399
|
@rdbms = RdbmsMethods.new(self)
|
@@ -385,12 +434,13 @@ module PgConn
|
|
385
434
|
def literal(arg) Literal.new(arg) end
|
386
435
|
|
387
436
|
# Connection member method variations of the PgConn quote class methods
|
437
|
+
# with at least a default value for :json_type
|
388
438
|
def quote_identifier(s) = PgConn.quote_identifier(s)
|
389
439
|
def quote_identifiers(idents) = PgConn.quote_identifiers(idents)
|
390
|
-
def quote_value(value, **opts) = PgConn.quote_value(value, **opts)
|
391
|
-
def quote_values(values, **opts) = PgConn.quote_values(values, **opts)
|
392
|
-
def quote_tuple(tuple, **opts) = PgConn.quote_tuple(tuple, **opts)
|
393
|
-
def quote_tuples(tuples, **opts) = PgConn.quote_tuples(tuples, **opts)
|
440
|
+
def quote_value(value, **opts) = PgConn.quote_value(value, json_type: self.default_json_type, **opts)
|
441
|
+
def quote_values(values, **opts) = PgConn.quote_values(values, json_type: self.default_json_type, **opts)
|
442
|
+
def quote_tuple(tuple, **opts) = PgConn.quote_tuple(tuple, json_type: self.default_json_type, **opts)
|
443
|
+
def quote_tuples(tuples, **opts) = PgConn.quote_tuples(tuples, json_type: self.default_json_type, **opts)
|
394
444
|
|
395
445
|
# Quote a record and cast it into the given type, the type can also be a
|
396
446
|
# table or view. 'data' is an array, hash, or struct representation of the
|
@@ -403,14 +453,14 @@ module PgConn
|
|
403
453
|
#
|
404
454
|
# Also note that there is not class-method variant of this method because
|
405
455
|
# it requires a connection
|
406
|
-
def quote_record(data, schema_name = nil, type,
|
407
|
-
quote_record_impl(data, schema_name, type,
|
456
|
+
def quote_record(data, schema_name = nil, type, **opts)
|
457
|
+
quote_record_impl(data, schema_name, type, array: false, **opts)
|
408
458
|
end
|
409
459
|
|
410
460
|
# Quote an array of records. The type is the record type, not the type of
|
411
461
|
# the enclosing array
|
412
|
-
def quote_records(data, schema_name = nil, type,
|
413
|
-
quote_record_impl(data, schema_name, type,
|
462
|
+
def quote_records(data, schema_name = nil, type, **opts)
|
463
|
+
quote_record_impl(data, schema_name, type, array: true, **opts)
|
414
464
|
end
|
415
465
|
|
416
466
|
# :call-seq:
|
@@ -692,11 +742,11 @@ module PgConn
|
|
692
742
|
# columns (like #tuples).
|
693
743
|
#
|
694
744
|
# The name argument can be a String or a Symbol that may contain the schema
|
695
|
-
# of the function.
|
745
|
+
# of the function. If the :proc option is true the "function" is assumed
|
696
746
|
# to be a procedure
|
697
747
|
#
|
698
|
-
def call(name, *args,
|
699
|
-
args_seq = quote_values(args,
|
748
|
+
def call(name, *args, silent: self.silent, proc: false, **opts) # :proc may interfere with hashes
|
749
|
+
args_seq = quote_values(args, **opts)
|
700
750
|
if proc
|
701
751
|
pg_exec "call #{name}(#{args_seq})", silent: silent
|
702
752
|
return nil
|
@@ -719,8 +769,8 @@ module PgConn
|
|
719
769
|
end
|
720
770
|
|
721
771
|
# Like #call with :proc set to true
|
722
|
-
def proc(name, *args, silent: self.silent)
|
723
|
-
call(name, *args, silent: silent, proc: true)
|
772
|
+
def proc(name, *args, json_type: self.default_json_type, silent: self.silent)
|
773
|
+
call(name, *args, silent: silent, proc: true, json_type: json_type)
|
724
774
|
end
|
725
775
|
|
726
776
|
# :call-seq:
|
@@ -859,7 +909,14 @@ module PgConn
|
|
859
909
|
#
|
860
910
|
# TODO: Make sure the transaction stack is emptied on postgres errors
|
861
911
|
def exec(sql, commit: true, fail: true, silent: self.silent)
|
862
|
-
transaction(commit: commit) {
|
912
|
+
transaction(commit: commit) {
|
913
|
+
begin
|
914
|
+
execute(sql, fail: fail, silent: silent)
|
915
|
+
rescue PG::Error
|
916
|
+
cancel_transaction
|
917
|
+
raise
|
918
|
+
end
|
919
|
+
}
|
863
920
|
end
|
864
921
|
|
865
922
|
# Like #exec but returns true/false depending on if the command succeeded,
|
@@ -888,7 +945,6 @@ module PgConn
|
|
888
945
|
begin
|
889
946
|
pg_exec(sql, silent: silent)&.cmd_tuples
|
890
947
|
rescue PG::Error
|
891
|
-
cancel_transaction
|
892
948
|
raise if fail
|
893
949
|
return nil
|
894
950
|
end
|
@@ -954,9 +1010,9 @@ module PgConn
|
|
954
1010
|
# file instead of being executed. Maybe remove logging (or execute always
|
955
1011
|
# and log as a side-effect)
|
956
1012
|
if @pg_connection
|
957
|
-
|
958
|
-
|
959
|
-
|
1013
|
+
@timestamp, @timestamptz = @pg_connection.exec(
|
1014
|
+
'select current_timestamp::timestamp without time zone, current_timestamp'
|
1015
|
+
).tuple_values(0)
|
960
1016
|
end
|
961
1017
|
end
|
962
1018
|
end
|
@@ -987,9 +1043,16 @@ module PgConn
|
|
987
1043
|
# progress, the method always succeeds
|
988
1044
|
def cancel_transaction
|
989
1045
|
begin
|
990
|
-
|
1046
|
+
# The transaction may be invalid to we can't use #set_option to silence
|
1047
|
+
# warnings when the transaction is rolled back. Instead we manipulate the
|
1048
|
+
# procudure method
|
1049
|
+
saved_producer = @producers[:warning]
|
1050
|
+
@producers[:warning] = nil
|
1051
|
+
pg_exec("rollback", silent: true)
|
991
1052
|
rescue PG::Error
|
992
1053
|
;
|
1054
|
+
ensure
|
1055
|
+
@producers[:warning] = saved_producer
|
993
1056
|
end
|
994
1057
|
@savepoints = nil
|
995
1058
|
true
|
@@ -1018,7 +1081,6 @@ module PgConn
|
|
1018
1081
|
return nil
|
1019
1082
|
rescue PG::Error
|
1020
1083
|
cancel_transaction
|
1021
|
-
@savepoints = nil
|
1022
1084
|
raise
|
1023
1085
|
end
|
1024
1086
|
pop_transaction(commit: commit, fail: false)
|
@@ -1102,7 +1164,10 @@ module PgConn
|
|
1102
1164
|
#
|
1103
1165
|
# Note that #quote_record_impl queries the database for information about
|
1104
1166
|
# the type. TODO Cache this information?
|
1105
|
-
def quote_record_impl(
|
1167
|
+
def quote_record_impl(
|
1168
|
+
datas, schema_name = nil, type, elem_types: nil, array: nil, **opts)
|
1169
|
+
datas = [datas] if !array
|
1170
|
+
|
1106
1171
|
pg_type = [schema_name, type].compact.join('.')
|
1107
1172
|
fields = self.values(%(
|
1108
1173
|
select attname
|
@@ -1114,8 +1179,6 @@ module PgConn
|
|
1114
1179
|
order by attnum
|
1115
1180
|
)).map(&:to_sym)
|
1116
1181
|
|
1117
|
-
datas = [datas] if !array
|
1118
|
-
|
1119
1182
|
literals = datas.map { |data|
|
1120
1183
|
values =
|
1121
1184
|
case data
|
@@ -1125,10 +1188,11 @@ module PgConn
|
|
1125
1188
|
else
|
1126
1189
|
raise Error, "Illegal value #{data.inspect}"
|
1127
1190
|
end
|
1128
|
-
"(#{quote_tuple(values, elem_types: elem_types)})::#{pg_type}"
|
1191
|
+
"(#{quote_tuple(values, elem_types: elem_types, **opts)})::#{pg_type}"
|
1129
1192
|
}
|
1130
1193
|
|
1131
1194
|
if array
|
1195
|
+
# papg_type(table, where_clause, fields...)
|
1132
1196
|
"array[#{literals.join(', ')}]::#{pg_type}[]"
|
1133
1197
|
else
|
1134
1198
|
literals.first
|
@@ -1138,7 +1202,6 @@ module PgConn
|
|
1138
1202
|
# :call-seq
|
1139
1203
|
# parse_query(query)
|
1140
1204
|
# parse_query(table, id, fields...)
|
1141
|
-
# parse_query(table, where_clause, fields...)
|
1142
1205
|
# parse_query(table, hash, fields...)
|
1143
1206
|
# parse_query(table, fields...)
|
1144
1207
|
#
|
@@ -1173,44 +1236,57 @@ module PgConn
|
|
1173
1236
|
|
1174
1237
|
STDOUT_PRODUCER = lambda { |msg| $stdout.puts msg }
|
1175
1238
|
STDERR_PRODUCER = lambda { |msg| $stderr.puts msg }
|
1239
|
+
ERROR_PRODUCER = lambda { |msg, stmt| $stderr.puts stmt, nil, msg; $stderr.flush }
|
1240
|
+
|
1241
|
+
# Map from message level to default producer. Note that we rely on the key
|
1242
|
+
# order to determine the minimum message level in #set_option below
|
1243
|
+
DEFAULT_PRODUCER = {
|
1244
|
+
debug: STDERR_PRODUCER,
|
1245
|
+
info: STDOUT_PRODUCER,
|
1246
|
+
notice: STDERR_PRODUCER,
|
1247
|
+
warning: STDERR_PRODUCER,
|
1248
|
+
error: STDERR_PRODUCER
|
1249
|
+
}
|
1176
1250
|
|
1177
1251
|
# FIXME Fails if connection is copied - requires a common options object
|
1178
1252
|
# that is shared between all connection copies
|
1179
1253
|
def set_option(option, value)
|
1254
|
+
# Assign default
|
1255
|
+
value = @default_options[option] if value.nil?
|
1256
|
+
|
1257
|
+
# Find current message level
|
1258
|
+
old_level = DEFAULT_PRODUCER.keys.find { |level| @producers[level] } || :error
|
1259
|
+
|
1260
|
+
# Set new value. Can be true, false, or a Proc object
|
1261
|
+
@options[option] = value
|
1262
|
+
|
1263
|
+
# Set producer
|
1180
1264
|
case option
|
1181
1265
|
when :silent
|
1182
|
-
@
|
1266
|
+
@producers[:silent] =
|
1183
1267
|
case value
|
1184
|
-
when true
|
1185
|
-
when
|
1268
|
+
when true; nil
|
1269
|
+
when false; ERROR_PRODUCER
|
1270
|
+
when Proc; value
|
1186
1271
|
else
|
1187
|
-
raise ArgumentError, "Illegal value #{value.inspect}"
|
1272
|
+
raise ArgumentError, "Illegal value: #{value.inspect}"
|
1188
1273
|
end
|
1189
|
-
when :notice, :warning
|
1190
|
-
@
|
1274
|
+
when :debug, :info, :notice, :warning
|
1275
|
+
@producers[option] =
|
1191
1276
|
case value
|
1192
|
-
when true; option
|
1277
|
+
when true; DEFAULT_PRODUCER[option]
|
1193
1278
|
when false; nil
|
1194
|
-
when nil; @default_options[option]
|
1195
1279
|
when Proc; value
|
1196
1280
|
else
|
1197
1281
|
raise ArgumentError, "Illegal value #{value.inspect}"
|
1198
1282
|
end
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
@pg_connection.exec "set client_min_messages to error"
|
1207
|
-
end
|
1208
|
-
elsif !notice
|
1209
|
-
if enabled
|
1210
|
-
@pg_connection.exec "set client_min_messages to notice"
|
1211
|
-
else
|
1212
|
-
@pg_connection.exec "set client_min_messages to error"
|
1213
|
-
end
|
1283
|
+
|
1284
|
+
# Find new message level
|
1285
|
+
new_level = DEFAULT_PRODUCER.keys.find { |level| @producers[level] } || :error
|
1286
|
+
|
1287
|
+
# Adjust postgres message level if changed
|
1288
|
+
if old_level != new_level
|
1289
|
+
@pg_connection.exec "set client_min_messages to #{new_level}"
|
1214
1290
|
end
|
1215
1291
|
else
|
1216
1292
|
raise ArgumentError, "Illegal option: #{option.inspect}"
|
@@ -1224,10 +1300,13 @@ module PgConn
|
|
1224
1300
|
def get_options() @options.dup end
|
1225
1301
|
|
1226
1302
|
# Called from postgres. Installed in #initialize
|
1227
|
-
def message_processor(message)
|
1303
|
+
def message_processor(message, stmt = nil)
|
1228
1304
|
case message
|
1229
|
-
when /^
|
1230
|
-
when /^
|
1305
|
+
when /^DEBUG:\s*(.*)$/; @producers[:debug]&.call($1)
|
1306
|
+
when /^INFO:\s*(.*)$/; @producers[:info]&.call($1)
|
1307
|
+
when /^NOTICE:\s*(.*)$/; @producers[:notice]&.call($1)
|
1308
|
+
when /^WARNING:\s*(.*)$/; @producers[:warning]&.call($1)
|
1309
|
+
when /^ERROR:\s*(.*)$/m; @producers[:silent]&.call($1, stmt)
|
1231
1310
|
else
|
1232
1311
|
raise "Oops"
|
1233
1312
|
end
|
@@ -1255,6 +1334,10 @@ module PgConn
|
|
1255
1334
|
def pg_exec(arg, silent: self.silent)
|
1256
1335
|
if @pg_connection
|
1257
1336
|
begin
|
1337
|
+
# Set silent state
|
1338
|
+
saved_silent = self.silent
|
1339
|
+
self.silent = silent
|
1340
|
+
|
1258
1341
|
last_stmt = nil # To make the current SQL statement visible to the rescue clause. FIXME Not used?
|
1259
1342
|
if arg.is_a?(String)
|
1260
1343
|
return nil if arg == ""
|
@@ -1272,12 +1355,11 @@ module PgConn
|
|
1272
1355
|
@error = ex
|
1273
1356
|
@err = nil
|
1274
1357
|
end
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
end
|
1358
|
+
|
1359
|
+
# Process message before resetting silent state
|
1360
|
+
message_processor(@error.message, arg)
|
1361
|
+
self.silent = saved_silent
|
1362
|
+
|
1281
1363
|
raise
|
1282
1364
|
end
|
1283
1365
|
|
@@ -1313,16 +1395,15 @@ module PgConn
|
|
1313
1395
|
def self.sql_values(values) "'" + values.join("', '") + "'" end
|
1314
1396
|
def self.sql_idents(values) '"' + values.join('", "') + '"' end
|
1315
1397
|
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
# Same as postgres PG#escape_identifier but do not need a connection
|
1320
|
-
def self.escape_identifier(s)
|
1321
|
-
!s.nil? or raise TypeError, "Identifier can't be nil"
|
1322
|
-
s.is_a?(String) or raise TypeError, "Identifier can't be a #{s.class}"
|
1323
|
-
s !~ /\A\s*\z/ or raise TypeError, "Identifier be blank"
|
1324
|
-
%("#{s.gsub('"', '""')}")
|
1325
|
-
end
|
1398
|
+
# Same as postgres PG#escape_literal but do not need a connection
|
1399
|
+
def self.escape_literal(s) = s.nil? ? 'NULL' : "'#{s.gsub("'", "''")}'"
|
1326
1400
|
|
1401
|
+
# Same as postgres PG#escape_identifier but do not need a connection
|
1402
|
+
def self.escape_identifier(s)
|
1403
|
+
!s.nil? or raise TypeError, "Identifier can't be nil"
|
1404
|
+
s.is_a?(String) or raise TypeError, "Identifier can't be a #{s.class}"
|
1405
|
+
s !~ /\A\s*\z/ or raise TypeError, "Identifier be blank"
|
1406
|
+
%("#{s.gsub('"', '""')}")
|
1407
|
+
end
|
1327
1408
|
end
|
1328
1409
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_conn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.35.
|
4
|
+
version: 0.35.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claus Rasmussen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-03-
|
11
|
+
date: 2025-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|