Class: PostgresPR::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/postgres-pr/connection.rb

Defined Under Namespace

Classes: Result

Constant Summary collapse

DEFAULT_PORT =
5432
DEFAULT_HOST =
'localhost'
DEFAULT_PATH =
'/tmp'
DEFAULT_URI =
if RUBY_PLATFORM.include?('win')
  'tcp://' + DEFAULT_HOST + ':' + DEFAULT_PORT.to_s 
else
  'unix:' + File.join(DEFAULT_PATH, '.s.PGSQL.' + DEFAULT_PORT.to_s)  
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(database, user, password = nil, uri = nil) ⇒ Connection

Returns a new instance of Connection.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/postgres-pr/connection.rb', line 21

def initialize(database, user, password=nil, uri = nil)
  uri ||= DEFAULT_URI

  @params = {}
  establish_connection(uri)

  @conn << StartupMessage.new(PROTO_VERSION, 'user' => user, 'database' => database).dump

  loop do
    msg = Message.read(@conn)

    case msg
    when AuthentificationClearTextPassword
      raise ArgumentError, "no password specified" if password.nil?
      @conn << PasswordMessage.new(password).dump

    when AuthentificationCryptPassword
      raise ArgumentError, "no password specified" if password.nil?
      @conn << PasswordMessage.new(password.crypt(msg.salt)).dump

    when AuthentificationMD5Password
      raise ArgumentError, "no password specified" if password.nil?
      require 'digest/md5'

      m = Digest::MD5.hexdigest(password + user) 
      m = Digest::MD5.hexdigest(m + msg.salt)
      m = 'md5' + m
      @conn << PasswordMessage.new(m).dump

    when AuthentificationKerberosV4, AuthentificationKerberosV5, AuthentificationSCMCredential
      raise "unsupported authentification"

    when AuthentificationOk
    when ErrorResponse
      raise msg.field_values.join("\t")
    when NoticeResponse
      @notice_processor.call(msg) if @notice_processor
    when ParameterStatus
      @params[msg.key] = msg.value
    when BackendKeyData
      # TODO
      #p msg
    when ReadyForQuery
      # TODO: use transaction status
      break
    else
      raise "unhandled message type"
    end
  end
end

Instance Attribute Details

#notice_processorObject

A block which is called with the NoticeResponse object as parameter.



19
20
21
# File 'lib/postgres-pr/connection.rb', line 19

def notice_processor
  @notice_processor
end

Instance Method Details

#closeObject



72
73
74
75
76
# File 'lib/postgres-pr/connection.rb', line 72

def close
  raise "connection already closed" if @conn.nil?
  @conn.shutdown
  @conn = nil
end

#query(sql) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/postgres-pr/connection.rb', line 85

def query(sql)
  @conn << Query.dump(sql)

  result = Result.new
  errors = []

  loop do
    msg = Message.read(@conn)
    case msg
    when DataRow
      result.rows << msg.columns
    when CommandComplete
      result.cmd_tag = msg.cmd_tag
    when ReadyForQuery
      break
    when RowDescription
      result.fields = msg.fields
    when CopyInResponse
    when CopyOutResponse
    when EmptyQueryResponse
    when ErrorResponse
      # TODO
      errors << msg
    when NoticeResponse
      @notice_processor.call(msg) if @notice_processor
    else
      # TODO
    end
  end

  raise errors.map{|e| e.field_values.join("\t") }.join("\n") unless errors.empty?

  result
end