pg_conn 0.9.0 → 0.11.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 +17 -0
 - data/lib/pg_conn/session_methods.rb +82 -0
 - data/lib/pg_conn/version.rb +1 -1
 - data/lib/pg_conn.rb +45 -4
 - metadata +3 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 634f61e3bd96889ad4207509c73c8b3e6a78c836db9aecbfc974ec5e206c84da
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: ded665cb58df11f269d951ee0d4cf176c0b99d24c6439edba96f9cf3b03508f0
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 3ad32ff6b5f33b2ec0cd2e309e243177ba1b9b3b5d24281b8e1e2aa8c956f193df64babe15691c80f50807ff7a5dd7c58c966de872b39695354f3aefaaf89343
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 6bba6d97558b0c7750971dbc23a3d1eacf1c83072c4fcad3d327324e5547d0607b4f427810bfda3fb0e4d27b3e5f679c437fd5a57572309b9156bfc6d313daef
         
     | 
    
        data/TODO
    CHANGED
    
    | 
         @@ -1,4 +1,20 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            TODO
         
     | 
| 
      
 2 
     | 
    
         
            +
              o Create aliases
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                  tuple   ->  array
         
     | 
| 
      
 5 
     | 
    
         
            +
                  tuples      arrays
         
     | 
| 
      
 6 
     | 
    
         
            +
                  field
         
     | 
| 
      
 7 
     | 
    
         
            +
                  fields              # aka. 'column'
         
     | 
| 
      
 8 
     | 
    
         
            +
                  record      hash
         
     | 
| 
      
 9 
     | 
    
         
            +
                  records     hashes
         
     | 
| 
      
 10 
     | 
    
         
            +
                              struct  # exists
         
     | 
| 
      
 11 
     | 
    
         
            +
                              structs
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              o Make rdbms, role, schema, and session methods part of a PgModel file that
         
     | 
| 
      
 15 
     | 
    
         
            +
                monkey patch PgConn objects to include a #model method that returns the 
         
     | 
| 
      
 16 
     | 
    
         
            +
                top-level rdbms object
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
       2 
18 
     | 
    
         
             
              o #group method
         
     | 
| 
       3 
19 
     | 
    
         | 
| 
       4 
20 
     | 
    
         
             
                group(query, column: nil)
         
     | 
| 
         @@ -59,6 +75,7 @@ TODO 
     | 
|
| 
       59 
75 
     | 
    
         
             
              o Allow a :type argument to all query methods that can be used to specify the
         
     | 
| 
       60 
76 
     | 
    
         
             
                composition of anonymous record types
         
     | 
| 
       61 
77 
     | 
    
         | 
| 
      
 78 
     | 
    
         
            +
              + Quote methods (value, identier, ... -> Postgres string)
         
     | 
| 
       62 
79 
     | 
    
         | 
| 
       63 
80 
     | 
    
         
             
            REFACTOR
         
     | 
| 
       64 
81 
     | 
    
         
             
              #!/usr/bin/env ruby
         
     | 
| 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module PgConn
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Schema methods
         
     | 
| 
      
 3 
     | 
    
         
            +
              class SessionMethods
         
     | 
| 
      
 4 
     | 
    
         
            +
                attr_reader :conn
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize(conn)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @conn = conn
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                # Returns a list of users connected to the given database. If database is
         
     | 
| 
      
 11 
     | 
    
         
            +
                # nil, it returns a list of database/username tuples for all connected users
         
     | 
| 
      
 12 
     | 
    
         
            +
                def list(database)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  if database
         
     | 
| 
      
 14 
     | 
    
         
            +
                    conn.values "select usename from pg_stat_activity where datname = '#{database}'"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  else
         
     | 
| 
      
 16 
     | 
    
         
            +
                    conn.tuples %(
         
     | 
| 
      
 17 
     | 
    
         
            +
                      select datname, usename
         
     | 
| 
      
 18 
     | 
    
         
            +
                      from pg_stat_activity 
         
     | 
| 
      
 19 
     | 
    
         
            +
                      where datname is not null and usename is not null
         
     | 
| 
      
 20 
     | 
    
         
            +
                    )
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                # Terminate sessions in the database of the given users or of all users if
         
     | 
| 
      
 25 
     | 
    
         
            +
                # the users is nil. Note that 'terminate(database)' is a nop because the
         
     | 
| 
      
 26 
     | 
    
         
            +
                # absent users argument defaults to an empty list
         
     | 
| 
      
 27 
     | 
    
         
            +
                #
         
     | 
| 
      
 28 
     | 
    
         
            +
                # TODO: Make is possible to terminate a single session of a user with
         
     | 
| 
      
 29 
     | 
    
         
            +
                #       multiple sessions (is this ever relevant?)
         
     | 
| 
      
 30 
     | 
    
         
            +
                def terminate(database, *users)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  !database.nil? or raise ArgumentError
         
     | 
| 
      
 32 
     | 
    
         
            +
                  users = Array(users).flatten
         
     | 
| 
      
 33 
     | 
    
         
            +
                  case users
         
     | 
| 
      
 34 
     | 
    
         
            +
                    when []; return
         
     | 
| 
      
 35 
     | 
    
         
            +
                    when [nil]; users = list(database)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    else users = Array(users).flatten
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                  pids = self.pids(database, users)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  return if pids.empty?
         
     | 
| 
      
 40 
     | 
    
         
            +
                  pids_sql = pids.map { |pid| "(#{pid})" }.join(", ")
         
     | 
| 
      
 41 
     | 
    
         
            +
                  conn.execute "select pg_terminate_backend(pid) from ( values #{pids_sql} ) as x(pid)"
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def disable(database)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  !database.nil? or raise ArgumentError
         
     | 
| 
      
 46 
     | 
    
         
            +
                  conn.execute "alter database #{database} allow_connections = false"
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def enable(database)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  !database.nil? or raise ArgumentError
         
     | 
| 
      
 51 
     | 
    
         
            +
                  conn.execute "alter database #{database} allow_connections = true"
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                # Run block without any connected users. Existing sessions are terminated
         
     | 
| 
      
 55 
     | 
    
         
            +
                def exclusive(database, &block) 
         
     | 
| 
      
 56 
     | 
    
         
            +
                  !database.nil? or raise ArgumentError
         
     | 
| 
      
 57 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 58 
     | 
    
         
            +
                    disable(database)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    users = list(database)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    terminate(database, users)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 62 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 63 
     | 
    
         
            +
                    enable(database)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              private
         
     | 
| 
      
 68 
     | 
    
         
            +
                # Like #list but returns the PIDs of the users
         
     | 
| 
      
 69 
     | 
    
         
            +
                def pids(database, users)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  users ||= list(database)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  if !users.empty?
         
     | 
| 
      
 72 
     | 
    
         
            +
                    users_sql = "(" + users.map { |user| "'#{user}'" }.join(", ") + ")"
         
     | 
| 
      
 73 
     | 
    
         
            +
                    conn.values "select pid from pg_stat_activity where datname = '#{database}' and usename in #{users_sql}"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  else
         
     | 
| 
      
 75 
     | 
    
         
            +
                    conn.values "select pid from pg_stat_activity where datname = '#{database}'"
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
    
        data/lib/pg_conn/version.rb
    CHANGED
    
    
    
        data/lib/pg_conn.rb
    CHANGED
    
    | 
         @@ -5,6 +5,7 @@ require "pg_conn/version" 
     | 
|
| 
       5 
5 
     | 
    
         
             
            require "pg_conn/role_methods"
         
     | 
| 
       6 
6 
     | 
    
         
             
            require "pg_conn/schema_methods"
         
     | 
| 
       7 
7 
     | 
    
         
             
            require "pg_conn/rdbms_methods"
         
     | 
| 
      
 8 
     | 
    
         
            +
            require "pg_conn/session_methods"
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
10 
     | 
    
         
             
            module PgConn
         
     | 
| 
       10 
11 
     | 
    
         
             
              class Error < StandardError; end
         
     | 
| 
         @@ -59,6 +60,9 @@ module PgConn 
     | 
|
| 
       59 
60 
     | 
    
         
             
                # #exist?/#list for relations/tables/views/columns
         
     | 
| 
       60 
61 
     | 
    
         
             
                attr_reader :schema
         
     | 
| 
       61 
62 
     | 
    
         | 
| 
      
 63 
     | 
    
         
            +
                # Session manipulation methods: #list, #terminate, #disable, #enable
         
     | 
| 
      
 64 
     | 
    
         
            +
                attr_reader :session
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
       62 
66 
     | 
    
         
             
                # The transaction timestamp of the most recent SQL statement executed by
         
     | 
| 
       63 
67 
     | 
    
         
             
                # #exec or #transaction block
         
     | 
| 
       64 
68 
     | 
    
         
             
                attr_reader :timestamp
         
     | 
| 
         @@ -198,11 +202,12 @@ module PgConn 
     | 
|
| 
       198 
202 
     | 
    
         
             
                  @schema = SchemaMethods.new(self)
         
     | 
| 
       199 
203 
     | 
    
         
             
                  @role = RoleMethods.new(self)
         
     | 
| 
       200 
204 
     | 
    
         
             
                  @rdbms = RdbmsMethods.new(self)
         
     | 
| 
      
 205 
     | 
    
         
            +
                  @session = SessionMethods.new(self)
         
     | 
| 
       201 
206 
     | 
    
         
             
                  @timestamp = nil
         
     | 
| 
       202 
207 
     | 
    
         
             
                  @savepoints = nil # Stack of savepoint names. Nil if no transaction in progress
         
     | 
| 
       203 
208 
     | 
    
         
             
                end
         
     | 
| 
       204 
209 
     | 
    
         | 
| 
       205 
     | 
    
         
            -
                # Close the database connection
         
     | 
| 
      
 210 
     | 
    
         
            +
                # Close the database connection. TODO: Rename 'close'
         
     | 
| 
       206 
211 
     | 
    
         
             
                def terminate()
         
     | 
| 
       207 
212 
     | 
    
         
             
                  @pg_connection.close if @pg_connection && !@pg_connection.finished? 
         
     | 
| 
       208 
213 
     | 
    
         
             
                end
         
     | 
| 
         @@ -221,12 +226,40 @@ module PgConn 
     | 
|
| 
       221 
226 
     | 
    
         
             
                  end
         
     | 
| 
       222 
227 
     | 
    
         
             
                end
         
     | 
| 
       223 
228 
     | 
    
         | 
| 
      
 229 
     | 
    
         
            +
                # Quote value as an identifier. Value should be a non-nil string
         
     | 
| 
      
 230 
     | 
    
         
            +
                def quote_identifier(s) = @pg_connection.escape_identifier(s)
         
     | 
| 
      
 231 
     | 
    
         
            +
             
     | 
| 
      
 232 
     | 
    
         
            +
                # Quote the value as a string. Emit 'null' if value is nil
         
     | 
| 
      
 233 
     | 
    
         
            +
                #
         
     | 
| 
      
 234 
     | 
    
         
            +
                # The value can be of any type but is converted to a string using #to_s
         
     | 
| 
      
 235 
     | 
    
         
            +
                # before quoting. This works by default for the regular types Integer,
         
     | 
| 
      
 236 
     | 
    
         
            +
                # true/false, Time/Date/DateTime, and arrays. Other types may require
         
     | 
| 
      
 237 
     | 
    
         
            +
                # special handling
         
     | 
| 
      
 238 
     | 
    
         
            +
                def quote_literal(value) 
         
     | 
| 
      
 239 
     | 
    
         
            +
                  case value
         
     | 
| 
      
 240 
     | 
    
         
            +
                    when String; @pg_connection.escape_literal(value)
         
     | 
| 
      
 241 
     | 
    
         
            +
                    when Integer, Float; value.to_s
         
     | 
| 
      
 242 
     | 
    
         
            +
                    when true, false; value.to_s
         
     | 
| 
      
 243 
     | 
    
         
            +
                    when nil; 'null'
         
     | 
| 
      
 244 
     | 
    
         
            +
                    when Date, DateTime; "'#{value}'"
         
     | 
| 
      
 245 
     | 
    
         
            +
                    when Time; "'#{value.strftime("%FT%T%:z")}'"
         
     | 
| 
      
 246 
     | 
    
         
            +
                    when Array; "array[#{value.map { |elem| quote_literal(elem) }.join(', ')}]"
         
     | 
| 
      
 247 
     | 
    
         
            +
                  else
         
     | 
| 
      
 248 
     | 
    
         
            +
                    @pg_connection.escape_literal(value.to_s)
         
     | 
| 
      
 249 
     | 
    
         
            +
                  end
         
     | 
| 
      
 250 
     | 
    
         
            +
                end
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
                def quote_array(value)
         
     | 
| 
      
 253 
     | 
    
         
            +
                  
         
     | 
| 
      
 254 
     | 
    
         
            +
                end
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
       224 
256 
     | 
    
         
             
                # :call-seq:
         
     | 
| 
       225 
257 
     | 
    
         
             
                #   exist?(query)
         
     | 
| 
       226 
258 
     | 
    
         
             
                #   exist?(table, id)
         
     | 
| 
       227 
259 
     | 
    
         
             
                #   eists?(table, where_clause)
         
     | 
| 
       228 
260 
     | 
    
         
             
                #
         
     | 
| 
       229 
     | 
    
         
            -
                # Return true iff the query returns exactly one value
         
     | 
| 
      
 261 
     | 
    
         
            +
                # Return true iff the query returns exactly one value. Use '!empty?' to
         
     | 
| 
      
 262 
     | 
    
         
            +
                # check if the query returns one or more records
         
     | 
| 
       230 
263 
     | 
    
         
             
                def exist?(*args)
         
     | 
| 
       231 
264 
     | 
    
         
             
                  arg1, arg2 = *args
         
     | 
| 
       232 
265 
     | 
    
         
             
                  query = 
         
     | 
| 
         @@ -268,8 +301,9 @@ module PgConn 
     | 
|
| 
       268 
301 
     | 
    
         | 
| 
       269 
302 
     | 
    
         
             
                # Return a single value. It is an error if the query doesn't return a
         
     | 
| 
       270 
303 
     | 
    
         
             
                # single record with a single column. If :transaction is true, the query
         
     | 
| 
       271 
     | 
    
         
            -
                # will be executed in a transaction and be committed  
     | 
| 
       272 
     | 
    
         
            -
                # (the default).  
     | 
| 
      
 304 
     | 
    
         
            +
                # will be executed in a transaction and also be committed if :commit is
         
     | 
| 
      
 305 
     | 
    
         
            +
                # true (this is the default). It can be used to execute 'insert' statements
         
     | 
| 
      
 306 
     | 
    
         
            +
                # with a 'returning' clause
         
     | 
| 
       273 
307 
     | 
    
         
             
                def value(query) #, transaction: false, commit: true)
         
     | 
| 
       274 
308 
     | 
    
         
             
                  r = pg_exec(query)
         
     | 
| 
       275 
309 
     | 
    
         
             
                  check_1c(r)
         
     | 
| 
         @@ -416,6 +450,12 @@ module PgConn 
     | 
|
| 
       416 
450 
     | 
    
         
             
                  h
         
     | 
| 
       417 
451 
     | 
    
         
             
                end
         
     | 
| 
       418 
452 
     | 
    
         | 
| 
      
 453 
     | 
    
         
            +
                # TODO: #group - same as table but partitions a table on the given keys
         
     | 
| 
      
 454 
     | 
    
         
            +
                #       returning a map from key to array of records
         
     | 
| 
      
 455 
     | 
    
         
            +
             
     | 
| 
      
 456 
     | 
    
         
            +
                # TODO: An #array method that returns a map from id to tuple. Hmm... almost
         
     | 
| 
      
 457 
     | 
    
         
            +
                #       the same as #map
         
     | 
| 
      
 458 
     | 
    
         
            +
             
     | 
| 
       419 
459 
     | 
    
         
             
                # Return a hash from the record id column to an OpenStruct representation
         
     | 
| 
       420 
460 
     | 
    
         
             
                # of the record. If the :key_column option is defined it will be used
         
     | 
| 
       421 
461 
     | 
    
         
             
                # instead of id as the key. It is an error if the id field value is not
         
     | 
| 
         @@ -567,6 +607,7 @@ module PgConn 
     | 
|
| 
       567 
607 
     | 
    
         
             
                # back to the original user
         
     | 
| 
       568 
608 
     | 
    
         
             
                #
         
     | 
| 
       569 
609 
     | 
    
         
             
                # FIXME: The out-commented transaction block makes postspec fail for some reason
         
     | 
| 
      
 610 
     | 
    
         
            +
                # TODO: Rename 'sudo' because it acts just like it. 
         
     | 
| 
       570 
611 
     | 
    
         
             
                def su(username, &block)
         
     | 
| 
       571 
612 
     | 
    
         
             
                  raise Error, "Missing block in call to PgConn::Connection#su" if !block_given?
         
     | 
| 
       572 
613 
     | 
    
         
             
                  realuser = self.value "select current_user"
         
     | 
    
        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.11.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-02- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2024-02-25 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: pg
         
     | 
| 
         @@ -85,6 +85,7 @@ files: 
     | 
|
| 
       85 
85 
     | 
    
         
             
            - lib/pg_conn/rdbms_methods.rb
         
     | 
| 
       86 
86 
     | 
    
         
             
            - lib/pg_conn/role_methods.rb
         
     | 
| 
       87 
87 
     | 
    
         
             
            - lib/pg_conn/schema_methods.rb
         
     | 
| 
      
 88 
     | 
    
         
            +
            - lib/pg_conn/session_methods.rb
         
     | 
| 
       88 
89 
     | 
    
         
             
            - lib/pg_conn/version.rb
         
     | 
| 
       89 
90 
     | 
    
         
             
            - pg_conn.gemspec
         
     | 
| 
       90 
91 
     | 
    
         
             
            homepage: http://www.nowhere.com/
         
     |