pg_conn 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|