Class: DbGui::Model::Db

Inherits:
Struct
  • Object
show all
Defined in:
app/db_gui/model/db.rb

Constant Summary collapse

COUNT_RETRIES =
ENV.fetch('DB_COMMAND_COUNT_RETRIES', 7)
REGEX_ROW_COUNT =
/^\((\d+) row/
ERROR_PREFIX =
'ERROR:'
NEW_LINE =
OS.windows? ? "\r\n" : "\n"
DB_COMMAND_TIMEOUT_DEFAULT =
300
NAME_NEW =
'(New Config)'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeDb

Returns a new instance of Db.



24
25
26
27
28
29
30
31
32
# File 'app/db_gui/model/db.rb', line 24

def initialize
  load_db_commands
  reset
  to_h.keys.each do |attribute|
    Glimmer::DataBinding::Observer.proc do |value|
      notify_observers(:saveable)
    end.observe(self, attribute)
  end
end

Instance Attribute Details

#connectedObject Also known as: connected?

Returns the value of attribute connected.



17
18
19
# File 'app/db_gui/model/db.rb', line 17

def connected
  @connected
end

#db_commandObject

Returns the value of attribute db_command.



21
22
23
# File 'app/db_gui/model/db.rb', line 21

def db_command
  @db_command
end

#db_command_resultObject

Returns the value of attribute db_command_result.



19
20
21
# File 'app/db_gui/model/db.rb', line 19

def db_command_result
  @db_command_result
end

#db_command_result_selectionObject

Returns the value of attribute db_command_result_selection.



22
23
24
# File 'app/db_gui/model/db.rb', line 22

def db_command_result_selection
  @db_command_result_selection
end

#db_command_timeoutObject

Returns the value of attribute db_command_timeout

Returns:

  • (Object)

    the current value of db_command_timeout



7
8
9
# File 'app/db_gui/model/db.rb', line 7

def db_command_timeout
  @db_command_timeout
end

#db_commandsObject

Returns the value of attribute db_commands.



20
21
22
# File 'app/db_gui/model/db.rb', line 20

def db_commands
  @db_commands
end

#dbnameObject

Returns the value of attribute dbname

Returns:

  • (Object)

    the current value of dbname



7
8
9
# File 'app/db_gui/model/db.rb', line 7

def dbname
  @dbname
end

#deleteableObject

Returns the value of attribute deleteable.



15
16
17
# File 'app/db_gui/model/db.rb', line 15

def deleteable
  @deleteable
end

#hostObject

Returns the value of attribute host

Returns:

  • (Object)

    the current value of host



7
8
9
# File 'app/db_gui/model/db.rb', line 7

def host
  @host
end

#nameObject

Returns the value of attribute name

Returns:

  • (Object)

    the current value of name



7
8
9
# File 'app/db_gui/model/db.rb', line 7

def name
  @name
end

#passwordObject

Returns the value of attribute password

Returns:

  • (Object)

    the current value of password



7
8
9
# File 'app/db_gui/model/db.rb', line 7

def password
  @password
end

#portObject

Returns the value of attribute port

Returns:

  • (Object)

    the current value of port



7
8
9
# File 'app/db_gui/model/db.rb', line 7

def port
  @port
end

#usernameObject

Returns the value of attribute username

Returns:

  • (Object)

    the current value of username



7
8
9
# File 'app/db_gui/model/db.rb', line 7

def username
  @username
end

Instance Method Details

#clear_db_commandsObject



117
118
119
120
121
# File 'app/db_gui/model/db.rb', line 117

def clear_db_commands
  self.db_commands = ['']
  self.db_command = ''
  save_db_commands(add_current: false)
end

#connectObject



75
76
77
78
# File 'app/db_gui/model/db.rb', line 75

def connect
  io
  self.connected = true
end

#copy_selected_rowObject



162
163
164
165
# File 'app/db_gui/model/db.rb', line 162

def copy_selected_row
  return if db_command_result_rows.empty?
  Clipboard.copy(formatted_selected_row_string)
end

#copy_selected_row_with_headersObject



167
168
169
170
# File 'app/db_gui/model/db.rb', line 167

def copy_selected_row_with_headers
  return if db_command_result_rows.empty?
  Clipboard.copy(formatted_selected_row_string(include_headers: true))
end

#copy_tableObject



147
148
149
150
# File 'app/db_gui/model/db.rb', line 147

def copy_table
  return if db_command_result_rows.empty?
  Clipboard.copy(formatted_table_string)
end

#copy_table_with_headersObject



152
153
154
155
# File 'app/db_gui/model/db.rb', line 152

def copy_table_with_headers
  return if db_command_result_rows.empty?
  Clipboard.copy(formatted_table_string(include_headers: true))
end

#copy_table_with_query_and_headersObject



157
158
159
160
# File 'app/db_gui/model/db.rb', line 157

def copy_table_with_query_and_headers
  return if db_command_result_rows.empty?
  Clipboard.copy(formatted_table_string(include_query: true, include_headers: true))
end

#db_command_result_countObject



131
132
133
# File 'app/db_gui/model/db.rb', line 131

def db_command_result_count
  db_command_result_count_headers_rows[0]
end

#db_command_result_error?Boolean

Returns:

  • (Boolean)


143
144
145
# File 'app/db_gui/model/db.rb', line 143

def db_command_result_error?
  db_command_result.to_s.strip.start_with?(ERROR_PREFIX)
end

#db_command_result_headersObject



135
136
137
# File 'app/db_gui/model/db.rb', line 135

def db_command_result_headers
  db_command_result_count_headers_rows[1]
end

#db_command_result_rowsObject



139
140
141
# File 'app/db_gui/model/db.rb', line 139

def db_command_result_rows
  db_command_result_count_headers_rows[2]
end

#deleteable?Object

Returns the value of attribute deleteable.



16
17
18
# File 'app/db_gui/model/db.rb', line 16

def deleteable
  @deleteable
end

#disconnectObject



80
81
82
83
84
# File 'app/db_gui/model/db.rb', line 80

def disconnect
  io.close
  @io = nil
  self.connected = false
end

#formatted_selected_row_string(include_headers: false) ⇒ Object



186
187
188
189
190
191
# File 'app/db_gui/model/db.rb', line 186

def formatted_selected_row_string(include_headers: false)
  selected_row = db_command_result_rows[db_command_result_selection]
  selected_row.join(' | ')
  rows = [selected_row]
  formatted_table_string(rows, include_headers:)
end

#formatted_table_string(rows = nil, include_query: false, include_headers: false) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'app/db_gui/model/db.rb', line 172

def formatted_table_string(rows = nil, include_query: false, include_headers: false)
  rows ||= db_command_result_rows
  rows = rows.dup
  rows.prepend(db_command_result_headers) if include_headers
  column_max_lengths = row_column_max_lengths(rows)
  formatted_string = rows.map do |row|
    row.each_with_index.map do |data, column_index|
      data.ljust(column_max_lengths[column_index])
    end.join(" | ")
  end.join(NEW_LINE)
  formatted_string.prepend("#{db_command}\n\n") if include_query
  formatted_string
end

#ioObject



86
87
88
89
# File 'app/db_gui/model/db.rb', line 86

def io
  db_connection_command = "PGPASSWORD=\"#{password}\" psql --host=#{host} --port=#{port} --username=#{username} --dbname=#{dbname}"
  @io ||= IO.popen(db_connection_command, 'r+', err: [:child, :out])
end

#new?Boolean

Returns:

  • (Boolean)


55
56
57
# File 'app/db_gui/model/db.rb', line 55

def new?
  name === Db::NAME_NEW
end

#remove_db_commandObject



123
124
125
126
127
128
129
# File 'app/db_gui/model/db.rb', line 123

def remove_db_command
  current_db_command = db_command
  self.db_commands = self.db_commands - [current_db_command.to_s.strip]
  self.db_command = ''
  self.db_command = self.db_commands.last || ''
  save_db_commands(add_current: false)
end

#resetObject



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/db_gui/model/db.rb', line 34

def reset
  self.name = Db::NAME_NEW
  self.host = nil
  self.port ||= 5432 # PostgreSQL default port
  self.dbname = nil
  self.username = nil
  self.password = nil
  self.db_command_result = ''
  self.db_command_timeout ||= ENV.fetch('DB_COMMAND_TIMEOUT_IN_MILLISECONDS', DB_COMMAND_TIMEOUT_DEFAULT).to_i
  self.db_command_result_selection = 0
  self.db_commands ||= ['']
  self.db_command ||= ''
end

#run_db_commandObject



111
112
113
114
115
# File 'app/db_gui/model/db.rb', line 111

def run_db_command
  reset_db_command_timeout
  run_io_command(db_command)
  save_db_commands
end

#run_io_command(command) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'app/db_gui/model/db.rb', line 91

def run_io_command(command)
  command = command.strip
  command = "#{command};" unless command.end_with?(';')
  @io_command_try ||= 0
  @io_command_try += 1
  io.puts(command)
  read_io_into_db_command_result
  @io_command_try = nil
rescue Timeout::Error, Errno::EPIPE => e
  puts e.message
  @io = nil
  if @io_command_try > COUNT_RETRIES
    @io_command_try = nil
  else
    self.db_command_timeout *= 2
    puts "Retrying DB Command...  {try: #{@io_command_try + 1}, db_command_timeout: #{db_command_timeout}}"
    run_io_command(command) unless db_command_result_error?
  end
end

#saveableObject



59
60
61
# File 'app/db_gui/model/db.rb', line 59

def saveable
  !new?
end

#toggle_connectionObject



67
68
69
70
71
72
73
# File 'app/db_gui/model/db.rb', line 67

def toggle_connection
  if connected?
    disconnect
  else
    connect
  end
end