pg_conn 0.20.0 → 0.21.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 +4 -4
- data/TODO +1 -0
- data/lib/pg_conn/version.rb +1 -1
- data/lib/pg_conn.rb +51 -73
- 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: 6f293ad25581975cbd57dc5973d072043d6b5cf13093a21bd354720b39c91c12
|
4
|
+
data.tar.gz: 1ad472d136a9b626717f90058cb220eaaf4c87bced2f8802c8cab68b69bf187a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7720aef7f128e0b8e3c47fdd2acb752b1d44af9625653eae0552a2ac619e3c29ae2cad25789f0f0806fe4576104a64210cf5a5d7e7c7fa66817b8538a556bd35
|
7
|
+
data.tar.gz: 61425eaeabb6b6e0872f6ed49064f8650361ecd8be684b7db2322a6a346265e253489e49be37688c9ef74171733d2c8f19a12d38105a188ba263cf5ea48c9593
|
data/TODO
CHANGED
data/lib/pg_conn/version.rb
CHANGED
data/lib/pg_conn.rb
CHANGED
@@ -67,7 +67,7 @@ module PgConn
|
|
67
67
|
# #exec or #transaction block. The timestamp is without time zone
|
68
68
|
attr_reader :timestamp
|
69
69
|
|
70
|
-
# The transaction timestamp of the most recent SQL statement executed by
|
70
|
+
# The transaction timestamp of the most recent SQL statement executed by
|
71
71
|
# #exec or #transaction block. The timestamp includes the current time zone
|
72
72
|
attr_reader :timestamptz
|
73
73
|
|
@@ -190,7 +190,7 @@ module PgConn
|
|
190
190
|
@pg_connection.set_notice_processor { |message| ; } # Intentionally a nop
|
191
191
|
|
192
192
|
# Auto-convert to ruby types
|
193
|
-
type_map = PG::BasicTypeMapForResults.new(@pg_connection)
|
193
|
+
type_map = PG::BasicTypeMapForResults.new(@pg_connection)
|
194
194
|
|
195
195
|
# Use String as default type. Kills 'Warning: no type cast defined for
|
196
196
|
# type "uuid" with oid 2950..' warnings
|
@@ -198,7 +198,7 @@ module PgConn
|
|
198
198
|
|
199
199
|
# Timestamp decoder
|
200
200
|
type_map.add_coder PG::TextDecoder::Timestamp.new( # Timestamp without time zone
|
201
|
-
oid: 1114,
|
201
|
+
oid: 1114,
|
202
202
|
flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_UTC)
|
203
203
|
|
204
204
|
# Decode anonymous records but note that this is only useful to convert the
|
@@ -222,7 +222,7 @@ module PgConn
|
|
222
222
|
|
223
223
|
# Close the database connection. TODO: Rename 'close'
|
224
224
|
def terminate()
|
225
|
-
@pg_connection.close if @pg_connection && !@pg_connection.finished?
|
225
|
+
@pg_connection.close if @pg_connection && !@pg_connection.finished?
|
226
226
|
end
|
227
227
|
|
228
228
|
def self.new(*args, **opts, &block)
|
@@ -251,7 +251,11 @@ module PgConn
|
|
251
251
|
# before quoting. This works by default for the regular types Integer,
|
252
252
|
# true/false, Time/Date/DateTime, and arrays. Other types may require
|
253
253
|
# special handling
|
254
|
-
|
254
|
+
#
|
255
|
+
# Note that a tuple value (an array) must be quoted using #quote_tuple
|
256
|
+
# because #quote_value would quote the tuple as an array instead of a list
|
257
|
+
# of values
|
258
|
+
def quote_value(value)
|
255
259
|
case value
|
256
260
|
when String; @pg_connection.escape_literal(value)
|
257
261
|
when Integer, Float; value.to_s
|
@@ -265,33 +269,17 @@ module PgConn
|
|
265
269
|
end
|
266
270
|
end
|
267
271
|
|
268
|
-
# Quote array as a
|
269
|
-
def
|
270
|
-
|
271
|
-
# Quote array as a parenthesis-enclosed sequence of identifiers. TODO: Rename quote_identifier_tuple
|
272
|
-
def quote_identifier_list(identifiers) = "(#{quote_identifier_seq(identifiers)})"
|
273
|
-
|
274
|
-
# Quote array as a bracket-enclosed sequence of identifiers
|
275
|
-
# def quote_identifier_array(identifiers) = "(#{quote_identifier_seq(identifiers)})"
|
276
|
-
|
277
|
-
# Quote array as a curly-bracket-enclosed sequence of identifiers
|
278
|
-
# def quote_identifier_hash(identifiers) = "(#{quote_identifier_seq(identifiers)})"
|
272
|
+
# Quote an array of values as a tuple. Just an alias for #quote_values
|
273
|
+
def quote_tuple(tuple) = quote_values(tuple)
|
279
274
|
|
280
|
-
# Quote
|
281
|
-
def
|
275
|
+
# Quote identifiers and concatenate them using ',' as separator
|
276
|
+
def quote_identifiers(idents) = idents.map { |ident| quote_identifier(ident) }.join(", ")
|
282
277
|
|
283
|
-
# Quote
|
284
|
-
def
|
278
|
+
# Quote values and concatenate them using ',' as separator
|
279
|
+
def quote_values(values) = values.map { |value| quote_value(value) }.join(", ")
|
285
280
|
|
286
|
-
# Quote array
|
287
|
-
|
288
|
-
|
289
|
-
# Quote array as a curly-bracket-enclosed sequence of values
|
290
|
-
# def quote_identifier_hash(values) = "(#{quote_identifier_seq(values)})"
|
291
|
-
|
292
|
-
# Old aliases. TODO Remove
|
293
|
-
def quote_literal(value) = quote_value(value)
|
294
|
-
def quote_literal_list(values) = quote_value_list(values)
|
281
|
+
# Quote an array of tuples
|
282
|
+
def quote_tuples(tuples) = tuples.map { |tuple| "(#{quote_values(tuple)})" }.join(", ")
|
295
283
|
|
296
284
|
# :call-seq:
|
297
285
|
# exist?(query)
|
@@ -302,7 +290,7 @@ module PgConn
|
|
302
290
|
# check if the query returns one or more records
|
303
291
|
def exist?(*args)
|
304
292
|
arg1, arg2 = *args
|
305
|
-
query =
|
293
|
+
query =
|
306
294
|
case arg2
|
307
295
|
when Integer; "select from #{arg1} where id = #{arg2}"
|
308
296
|
when String; "select from #{arg1} where #{arg2}"
|
@@ -316,7 +304,7 @@ module PgConn
|
|
316
304
|
# count(table, where_clause = nil)
|
317
305
|
#
|
318
306
|
# Return true if the table or the result of the query is empty
|
319
|
-
def empty?(arg, where_clause = nil)
|
307
|
+
def empty?(arg, where_clause = nil)
|
320
308
|
if arg =~ /\s/
|
321
309
|
value "select count(*) from (#{arg} limit 1) as inner_query"
|
322
310
|
elsif where_clause
|
@@ -572,23 +560,12 @@ module PgConn
|
|
572
560
|
# columns (like #tuples)
|
573
561
|
#
|
574
562
|
def call(name, *args, proc: false) # :proc may interfere with hashes
|
575
|
-
|
576
|
-
case arg
|
577
|
-
when NilClass; "null"
|
578
|
-
when String; "'#{arg}'"
|
579
|
-
when Integer; arg
|
580
|
-
when TrueClass, FalseClass; arg
|
581
|
-
when Array; "Array['#{arg.join("', '")}']" # Quick and dirty # FIXME
|
582
|
-
when Hash; raise NotImplementedError
|
583
|
-
else
|
584
|
-
raise ArgumentError, "Unrecognized value: #{arg.inspect}"
|
585
|
-
end
|
586
|
-
}.join(", ")
|
563
|
+
args_seq = quote_values(args)
|
587
564
|
if proc
|
588
|
-
pg_exec "call #{name}(#{
|
565
|
+
pg_exec "call #{name}(#{args_seq})"
|
589
566
|
return nil
|
590
567
|
else
|
591
|
-
r = pg_exec "select * from #{name}(#{
|
568
|
+
r = pg_exec "select * from #{name}(#{args_seq})"
|
592
569
|
if r.ntuples == 0
|
593
570
|
raise Error, "No records returned"
|
594
571
|
elsif r.ntuples == 1
|
@@ -632,15 +609,14 @@ module PgConn
|
|
632
609
|
table = schema ? "#{schema}.#{table}" : table
|
633
610
|
|
634
611
|
# Find method and normalize data
|
635
|
-
if data.is_a?(Array)
|
612
|
+
if data.is_a?(Array) # Array of tuples
|
613
|
+
method = :values
|
636
614
|
if data.empty?
|
637
615
|
return []
|
638
|
-
elsif data.first.is_a?(Array)
|
639
|
-
method = :values
|
616
|
+
elsif data.first.is_a?(Array) # Tuple (array) element. Requires the 'fields' argument
|
640
617
|
fields or raise ArgumentError
|
641
618
|
tuples = data
|
642
|
-
elsif data.first.is_a?(Hash)
|
643
|
-
method = :values
|
619
|
+
elsif data.first.is_a?(Hash) # Hash element
|
644
620
|
fields ||= data.first.keys
|
645
621
|
tuples = data.map { |record| fields.map { |field| record[field] } }
|
646
622
|
else
|
@@ -654,21 +630,23 @@ module PgConn
|
|
654
630
|
raise ArgumentError
|
655
631
|
end
|
656
632
|
|
657
|
-
#
|
658
|
-
|
659
|
-
|
660
|
-
|
633
|
+
# Execute SQL statement using either :value or :values depending on data arity
|
634
|
+
self.send method, %(
|
635
|
+
insert into #{table} (#{quote_identifiers(fields)})
|
636
|
+
values #{quote_tuples(tuples)}
|
637
|
+
returning id
|
638
|
+
)
|
661
639
|
end
|
662
640
|
|
663
641
|
# Update record(s)
|
664
642
|
def update(schema = nil, table, expr, hash)
|
665
643
|
table = [schema, table].compact.join(".")
|
666
|
-
assignments = hash.map { |k,v| "#{k} = #{
|
667
|
-
constraint =
|
644
|
+
assignments = hash.map { |k,v| "#{k} = #{quote_value(v)}" }.join(", ")
|
645
|
+
constraint =
|
668
646
|
case expr
|
669
647
|
when String; expr
|
670
|
-
when Integer; "id = #{
|
671
|
-
when Array; "id in #{
|
648
|
+
when Integer; "id = #{quote_value(expr)}"
|
649
|
+
when Array; "id in (#{quote_values(expr)})"
|
672
650
|
else
|
673
651
|
raise ArgumentError
|
674
652
|
end
|
@@ -678,11 +656,11 @@ module PgConn
|
|
678
656
|
# Delete record(s)
|
679
657
|
def delete(schema = nil, table, expr)
|
680
658
|
table = [schema, table].compact.join(".")
|
681
|
-
constraint =
|
659
|
+
constraint =
|
682
660
|
case expr
|
683
661
|
when String; expr
|
684
|
-
when Integer; "id = #{
|
685
|
-
when Array; "id in #{
|
662
|
+
when Integer; "id = #{quote_value(expr)}"
|
663
|
+
when Array; "id in (#{quote_values(expr)})"
|
686
664
|
else
|
687
665
|
raise ArgumentError
|
688
666
|
end
|
@@ -697,7 +675,7 @@ module PgConn
|
|
697
675
|
# is not.
|
698
676
|
#
|
699
677
|
# #exec pass Postgres exceptions to the caller unless :fail is false in which case
|
700
|
-
# it returns nil.
|
678
|
+
# it returns nil.
|
701
679
|
#
|
702
680
|
# Note that postgres crashes the whole transaction stack if any error is
|
703
681
|
# met so if you're inside a transaction, the transaction will be in an
|
@@ -713,7 +691,7 @@ module PgConn
|
|
713
691
|
# There is not a corresponding #execute? method because any failure rolls
|
714
692
|
# back the whole transaction stack. TODO: Check which exceptions that
|
715
693
|
# should be captured
|
716
|
-
def exec?(sql, commit: true, silent: true)
|
694
|
+
def exec?(sql, commit: true, silent: true)
|
717
695
|
begin
|
718
696
|
exec(sql, commit: commit, fail: true, silent: silent)
|
719
697
|
rescue PG::Error
|
@@ -748,7 +726,7 @@ module PgConn
|
|
748
726
|
# back to the original user
|
749
727
|
#
|
750
728
|
# FIXME: The out-commented transaction block makes postspec fail for some reason
|
751
|
-
# TODO: Rename 'sudo' because it acts just like it.
|
729
|
+
# TODO: Rename 'sudo' because it acts just like it.
|
752
730
|
def su(username, &block)
|
753
731
|
raise Error, "Missing block in call to PgConn::Connection#su" if !block_given?
|
754
732
|
realuser = self.value "select current_user"
|
@@ -798,13 +776,13 @@ module PgConn
|
|
798
776
|
pg_exec("begin")
|
799
777
|
@error = @err = nil
|
800
778
|
# FIXME This special-cases the situation where commands are logged to a
|
801
|
-
# file instead of being executed. Maybe remove logging (or execute always
|
779
|
+
# file instead of being executed. Maybe remove logging (or execute always
|
802
780
|
# and log as a side-effect)
|
803
781
|
if @pg_connection
|
804
782
|
@timestamp, @timestamptz = @pg_connection.exec(
|
805
783
|
'select current_timestamp, current_timestamp::timestamp without time zone'
|
806
784
|
).tuple_values(0)
|
807
|
-
end
|
785
|
+
end
|
808
786
|
end
|
809
787
|
end
|
810
788
|
|
@@ -941,7 +919,7 @@ module PgConn
|
|
941
919
|
@error = ex
|
942
920
|
@err = nil
|
943
921
|
end
|
944
|
-
if !silent # FIXME Why do we handle this?
|
922
|
+
if !silent # FIXME Why do we handle this?
|
945
923
|
$stderr.puts arg
|
946
924
|
$stderr.puts
|
947
925
|
$stderr.puts ex.message
|
@@ -961,20 +939,20 @@ module PgConn
|
|
961
939
|
end
|
962
940
|
end
|
963
941
|
|
964
|
-
def check_1c(r)
|
942
|
+
def check_1c(r)
|
965
943
|
case r.nfields
|
966
944
|
when 0; raise Error, "No columns returned"
|
967
|
-
when 1;
|
945
|
+
when 1;
|
968
946
|
else
|
969
|
-
raise Error, "More than one column returned"
|
947
|
+
raise Error, "More than one column returned"
|
970
948
|
end
|
971
949
|
end
|
972
950
|
|
973
|
-
def check_1r(r)
|
951
|
+
def check_1r(r)
|
974
952
|
if r.ntuples == 0
|
975
953
|
raise Error, "No records returned"
|
976
|
-
elsif r.ntuples > 1
|
977
|
-
raise Error, "More than one record returned"
|
954
|
+
elsif r.ntuples > 1
|
955
|
+
raise Error, "More than one record returned"
|
978
956
|
end
|
979
957
|
end
|
980
958
|
end
|
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.
|
4
|
+
version: 0.21.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claus Rasmussen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07
|
11
|
+
date: 2024-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|