pg_conn 0.39.0 → 0.41.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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/TODO +1 -1
  3. data/lib/pg_conn/version.rb +1 -1
  4. data/lib/pg_conn.rb +95 -14
  5. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ace2859257bedbbdeb816bfb04d9d7e23d686942c328e0d521568b6f4fc57e90
4
- data.tar.gz: b803feaaaa619668cf00f57d2c5ffd072f04a149e144eafb061b85d4bf4cfad4
3
+ metadata.gz: 3fb72128df77cad4c2a3e5992f2d72a727af4b57fc898b8c2f7102ebd8df7ebd
4
+ data.tar.gz: ced62377173f5c33d428bec72c321a934947b5f4a24cac8467ad0c0955131a32
5
5
  SHA512:
6
- metadata.gz: b2b913861f23ed8db39f8d521571bb054c3ed9ca1526b800c5f4982f9b4a9f285cc60b17dc59194b2df7cc2147019faaef7b838a4e10d4e8659941adb6fddde9
7
- data.tar.gz: aac27bc4b8e7881ded4fdfe350a98be3de919052b9b5fcbca0d6767573dd9592d4922e3b2da968860b146d451b05bb96937e7344941d58048a104c5b8bda9081
6
+ metadata.gz: 0becdbeef4a4feb64c550e03d167143f59dda2a6eb986119eababab944cb22fefd36b13fd6fe2a4ea2866c8297bf2000f8683a3a86a47753a3cd462f214e007f
7
+ data.tar.gz: 829f2be06bfe9a278544b5c909841c418e3b248e8287dad640f43c28039f2dfc3ad028052f435c20248187774ddbbcbdd1d6df412b6b1f52fd481d5b5bfa2ce8
data/TODO CHANGED
@@ -96,7 +96,6 @@ TODO
96
96
  o Proper implementation of call of functions and procedures: Functions should
97
97
  be called through #value, #tuple etc. and procedures through #call.
98
98
  Proceduer output parameters needs handling too
99
- o Implement search_path
100
99
  o Create an abstract PgConnBase and have PgStmts (writes statements to array)
101
100
  and PgConn (sends statements to server) classes derived from it
102
101
  o fix silent
@@ -119,6 +118,7 @@ TODO
119
118
  + Quote methods (value, identier, ... -> Postgres string)
120
119
  + Have a 'with' method that combines multiple brachet-methods:
121
120
  conn.with(schema: public, transation: true) { ... }
121
+ + Implement search_path
122
122
 
123
123
 
124
124
  REFACTOR
@@ -1,3 +1,3 @@
1
1
  module PgConn
2
- VERSION = "0.39.0"
2
+ VERSION = "0.41.0"
3
3
  end
data/lib/pg_conn.rb CHANGED
@@ -209,7 +209,31 @@ module PgConn
209
209
  def debug?() !debug.nil? end
210
210
  def debug=(value) set_option(:debug, value) end
211
211
 
212
- DEFAULT_OPTIONS = { silent: false, warning: true, notice: false, info: false, debug: false }
212
+ # Log SQL or return current logger if sql is nil
213
+ def log(sql = nil)
214
+ case sql and dst = @options[:log]
215
+ when false; # do nothing
216
+ when true; $stderr.puts sql
217
+ when Proc; dst.call sql
218
+ when IO; dst.puts sql
219
+ when StringIO; dst.puts sql
220
+ when nil; return @options[:log]
221
+ else
222
+ raise "Oops"
223
+ end
224
+ sql # for convenience in #pg_exec
225
+ end
226
+
227
+ # Return true if logging is enabled
228
+ def log?() @options[:log] != false end
229
+
230
+ # Control logging of SQL commands. It can be assigned true, false, nil, an
231
+ # unary Proc object, or a IO object. True causes the message to be printed
232
+ # to standard error, false ignores it, and nil resets the state to the
233
+ # default given when the connection was initialized. Default false
234
+ def log=(value) set_option(:log, value) end
235
+
236
+ DEFAULT_OPTIONS = { silent: false, warning: true, notice: false, info: false, debug: false, log: false }
213
237
 
214
238
  # TODO: Move error message handling into the same framework as notice and
215
239
  # warning but we have a name collision just below that would need to be
@@ -465,6 +489,18 @@ module PgConn
465
489
  quote_record_impl(data, schema_name, type, array: true, **opts)
466
490
  end
467
491
 
492
+ # Return current search path. Note that a search path is part of
493
+ # the transaction
494
+ def search_path
495
+ self.value("show search_path").split(/,\s*/) - %w("$user" pg_temp)
496
+ end
497
+
498
+ # Set search path. It accepts a schema or an array of schema names
499
+ def search_path=(schemas)
500
+ schema_array = Array(schemas).flatten - %w("$user" pg_temp) + %w(pg_temp)
501
+ self.exec "set search_path to #{schema_array.join(', ')}"
502
+ end
503
+
468
504
  # :call-seq:
469
505
  # exist?(query)
470
506
  # exist?(table, id)
@@ -893,17 +929,51 @@ module PgConn
893
929
  exec %(delete from #{table} where #{constraint})
894
930
  end
895
931
 
896
- # Execute block with global options and resets afterwards. Currently only
897
- # :silent, :notice and :warning is supported. Very useful in RSpec tests
932
+ # Execute block with the given set of global or local options and reset
933
+ # them afterwards
934
+ #
935
+ # The global options :silent, :notice and :warning are supported, they're
936
+ # very useful in RSpec tests
898
937
  #
899
- # TODO: :error, :fail, :symbol, :schema, :search_path
938
+ # Local options are :search_path that runs the block with the given
939
+ # schemas, :username that runs the block as the given user, :log that controls logging,
940
+ # SQL, :commit that runs the block in a transaction if true or false; true
941
+ # commits the transaction and false rolls it back. It is not run in a
942
+ # transaction if :commit is nil
900
943
  #
901
944
  def with(**options, &block)
945
+ search_path = options.delete(:search_path)
946
+ username = options.delete(:username)
947
+ logging = options.delete(:log) || false
948
+ commit = options.delete(:commit)
949
+
950
+ saved_options = @options.dup
951
+ saved_search_path = self.search_path if search_path
952
+ saved_logger = self.log if logging
953
+
902
954
  begin
903
- saved_options = @options.dup
904
955
  set_options(options)
905
- yield
956
+ self.search_path = search_path if search_path
957
+ self.log = logging
958
+
959
+ inner = lambda {
960
+ if !commit.nil?
961
+ self.transaction(commit: commit) {
962
+ block.yield
963
+ }
964
+ else
965
+ block.yield
966
+ end
967
+ }
968
+
969
+ if username
970
+ self.su(username, &inner)
971
+ else
972
+ inner.call
973
+ end
906
974
  ensure
975
+ self.log = saved_logger if logging
976
+ self.search_path = saved_search_path if search_path
907
977
  set_options(saved_options)
908
978
  end
909
979
  end
@@ -975,16 +1045,23 @@ module PgConn
975
1045
  # Switch user to the given user and execute the statement before swithcing
976
1046
  # back to the original user
977
1047
  #
978
- # FIXME: The out-commented transaction block makes postspec fail for some reason
1048
+ # FIXME:
1049
+ # The out-commented transaction block makes postspec fail for some
1050
+ # reason. Note that user-switches lives within transactions
1051
+ #
979
1052
  # TODO: Rename 'sudo' because it acts just like it.
1053
+ #
980
1054
  def su(username, &block)
981
1055
  raise Error, "Missing block in call to PgConn::Connection#su" if !block_given?
982
1056
  realuser = self.value "select current_user"
983
1057
  result = nil
984
1058
  # transaction(commit: false) {
1059
+ begin
985
1060
  execute "set session authorization #{username}"
986
1061
  result = yield
1062
+ ensure
987
1063
  execute "set session authorization #{realuser}"
1064
+ end
988
1065
  # }
989
1066
  result
990
1067
  end
@@ -1087,7 +1164,7 @@ module PgConn
1087
1164
  # that the transaction timestamp is set to the start of the first
1088
1165
  # transaction even if transactions are nested
1089
1166
  #
1090
- # FIXME: There is some strange problem in rspec where an #insert handles
1167
+ # FIXME: There is some strange problem in rspec where #insert handles
1091
1168
  # an exception correctly while #exec, #execute, and #transaction does not
1092
1169
  def transaction(commit: true, &block)
1093
1170
  if block_given?
@@ -1271,12 +1348,16 @@ module PgConn
1271
1348
  # Assign default
1272
1349
  value = @default_options[option] if value.nil?
1273
1350
 
1351
+ # Set new value. Can be true, false, or a Proc object. The :log option
1352
+ # also allows an IO og StringIO object
1353
+ @options[option] = value
1354
+
1355
+ # Exit early if log
1356
+ return if option == :log
1357
+
1274
1358
  # Find current message level
1275
1359
  old_level = DEFAULT_PRODUCER.keys.find { |level| @producers[level] } || :error
1276
1360
 
1277
- # Set new value. Can be true, false, or a Proc object
1278
- @options[option] = value
1279
-
1280
1361
  # Set producer
1281
1362
  case option
1282
1363
  when :silent
@@ -1355,17 +1436,17 @@ module PgConn
1355
1436
  saved_silent = self.silent
1356
1437
  self.silent = silent
1357
1438
 
1358
- last_stmt = nil # To make the current SQL statement visible to the rescue clause. FIXME Not used?
1439
+ last_stmt = nil # To make the last (failed) SQL statement visible to the rescue clause. FIXME Not used?
1359
1440
  if arg.is_a?(String)
1360
1441
  return nil if arg == ""
1361
1442
  last_stmt = arg
1362
- @pg_connection.exec(last_stmt)
1443
+ @pg_connection.exec(log arg)
1363
1444
  else
1364
1445
  stmts = arg.flatten.compact
1365
1446
  return nil if stmts.empty?
1366
1447
  # stmts.unshift("set on_error_exit stop")
1367
1448
  last_stmt = stmts.last
1368
- @pg_connection.exec(stmts.join(";\n"))
1449
+ @pg_connection.exec(log stmts.join(";\n"))
1369
1450
  end
1370
1451
  rescue PG::Error => ex
1371
1452
  if @error.nil?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_conn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.39.0
4
+ version: 0.41.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen