Class: Blazer::DataSource

Inherits:
Object
  • Object
show all
Defined in:
lib/blazer/data_source.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, settings) ⇒ DataSource

Returns a new instance of DataSource.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/blazer/data_source.rb', line 7

def initialize(id, settings)
  @id = id
  @settings = settings

  unless settings["url"] || Rails.env.development?
    raise Blazer::Error, "Empty url"
  end

  @connection_model =
    Class.new(Blazer::Connection) do
      def self.name
        "Blazer::Connection::#{object_id}"
      end
      establish_connection(settings["url"]) if settings["url"]
    end
end

Instance Attribute Details

#connection_modelObject (readonly)

Returns the value of attribute connection_model.



5
6
7
# File 'lib/blazer/data_source.rb', line 5

def connection_model
  @connection_model
end

#idObject (readonly)

Returns the value of attribute id.



5
6
7
# File 'lib/blazer/data_source.rb', line 5

def id
  @id
end

#settingsObject (readonly)

Returns the value of attribute settings.



5
6
7
# File 'lib/blazer/data_source.rb', line 5

def settings
  @settings
end

Instance Method Details

#cacheObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/blazer/data_source.rb', line 48

def cache
  @cache ||= begin
    if settings["cache"].is_a?(Hash)
      settings["cache"]
    elsif settings["cache"]
      {
        "mode" => "all",
        "expires_in" => settings["cache"]
      }
    else
      {
        "mode" => "off"
      }
    end
  end
end

#cache_expires_inObject



69
70
71
# File 'lib/blazer/data_source.rb', line 69

def cache_expires_in
  (cache["expires_in"] || 60).to_f
end

#cache_key(key) ⇒ Object



183
184
185
# File 'lib/blazer/data_source.rb', line 183

def cache_key(key)
  (["blazer", "v4"] + key).join("/")
end

#cache_modeObject



65
66
67
# File 'lib/blazer/data_source.rb', line 65

def cache_mode
  cache["mode"]
end

#cache_slow_thresholdObject



73
74
75
# File 'lib/blazer/data_source.rb', line 73

def cache_slow_threshold
  (cache["slow_threshold"] || 15).to_f
end

#clear_cache(statement) ⇒ Object



179
180
181
# File 'lib/blazer/data_source.rb', line 179

def clear_cache(statement)
  Blazer.cache.delete(statement_cache_key(statement))
end

#cost(statement) ⇒ Object



85
86
87
88
89
# File 'lib/blazer/data_source.rb', line 85

def cost(statement)
  result = explain(statement)
  match = /cost=\d+\.\d+..(\d+\.\d+) /.match(result)
  match[1] if match
end

#delete_results(run_id) ⇒ Object



147
148
149
# File 'lib/blazer/data_source.rb', line 147

def delete_results(run_id)
  Blazer.cache.delete(run_cache_key(run_id))
end

#explain(statement) ⇒ Object



91
92
93
94
95
96
97
# File 'lib/blazer/data_source.rb', line 91

def explain(statement)
  if postgresql? || redshift?
    connection_model.connection.select_all("EXPLAIN #{statement}").rows.first.first
  end
rescue
  nil
end

#linked_columnsObject



28
29
30
# File 'lib/blazer/data_source.rb', line 28

def linked_columns
  settings["linked_columns"] || {}
end

#local_time_suffixObject



77
78
79
# File 'lib/blazer/data_source.rb', line 77

def local_time_suffix
  @local_time_suffix ||= Array(settings["local_time_suffix"])
end

#mysql?Boolean

Returns:

  • (Boolean)


213
214
215
# File 'lib/blazer/data_source.rb', line 213

def mysql?
  ["MySQL", "Mysql2", "Mysql2Spatial"].include?(adapter_name)
end

#nameObject



24
25
26
# File 'lib/blazer/data_source.rb', line 24

def name
  settings["name"] || @id
end

#postgresql?Boolean

Returns:

  • (Boolean)


205
206
207
# File 'lib/blazer/data_source.rb', line 205

def postgresql?
  ["PostgreSQL", "PostGIS"].include?(adapter_name)
end

#read_cache(cache_key) ⇒ Object



136
137
138
139
140
141
# File 'lib/blazer/data_source.rb', line 136

def read_cache(cache_key)
  value = Blazer.cache.read(cache_key)
  if value
    Blazer::Result.new(self, *Marshal.load(value), nil)
  end
end

#reconnectObject



217
218
219
# File 'lib/blazer/data_source.rb', line 217

def reconnect
  connection_model.establish_connection(settings["url"])
end

#redshift?Boolean

Returns:

  • (Boolean)


209
210
211
# File 'lib/blazer/data_source.rb', line 209

def redshift?
  ["Redshift"].include?(adapter_name)
end

#run_cache_key(run_id) ⇒ Object



191
192
193
# File 'lib/blazer/data_source.rb', line 191

def run_cache_key(run_id)
  cache_key(["run", run_id])
end

#run_main_statement(statement, options = {}) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/blazer/data_source.rb', line 99

def run_main_statement(statement, options = {})
  query = options[:query]
  Blazer.transform_statement.call(self, statement) if Blazer.transform_statement

  # audit
  if Blazer.audit
    audit = Blazer::Audit.new(statement: statement)
    audit.query = query
    audit.data_source = id
    audit.user = options[:user]
    audit.save!
  end

  start_time = Time.now
  result = run_statement(statement, options)
  duration = Time.now - start_time

  if Blazer.audit
    audit.duration = duration if audit.respond_to?(:duration=)
    audit.error = result.error if audit.respond_to?(:error=)
    audit.timed_out = result.timed_out? if audit.respond_to?(:timed_out=)
    audit.cached = result.cached? if audit.respond_to?(:cached=)
    if !result.cached? && duration >= 10
      audit.cost = cost(statement) if audit.respond_to?(:cost=)
    end
    audit.save! if audit.changed?
  end

  if query && !result.timed_out?
    query.checks.each do |check|
      check.update_state(result)
    end
  end

  result
end

#run_results(run_id) ⇒ Object



143
144
145
# File 'lib/blazer/data_source.rb', line 143

def run_results(run_id)
  read_cache(run_cache_key(run_id))
end

#run_statement(statement, options = {}) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/blazer/data_source.rb', line 151

def run_statement(statement, options = {})
  run_id = options[:run_id]
  result = nil
  if cache_mode != "off" && !options[:refresh_cache]
    result = read_cache(statement_cache_key(statement))
  end

  unless result
    comment = "blazer"
    if options[:user].respond_to?(:id)
      comment << ",user_id:#{options[:user].id}"
    end
    if options[:user].respond_to?(Blazer.user_name)
      # only include letters, numbers, and spaces to prevent injection
      comment << ",user_name:#{options[:user].send(Blazer.user_name).to_s.gsub(/[^a-zA-Z0-9 ]/, "")}"
    end
    if options[:query].respond_to?(:id)
      comment << ",query_id:#{options[:query].id}"
    end
    if options[:check]
      comment << ",check_id:#{options[:check].id},check_emails:#{options[:check].emails}"
    end
    result = run_statement_helper(statement, comment, options[:run_id])
  end

  result
end

#schemasObject



195
196
197
198
# File 'lib/blazer/data_source.rb', line 195

def schemas
  default_schema = (postgresql? || redshift?) ? "public" : connection_model.connection_config[:database]
  settings["schemas"] || [connection_model.connection_config[:schema] || default_schema]
end

#smart_columnsObject



32
33
34
# File 'lib/blazer/data_source.rb', line 32

def smart_columns
  settings["smart_columns"] || {}
end

#smart_variablesObject



36
37
38
# File 'lib/blazer/data_source.rb', line 36

def smart_variables
  settings["smart_variables"] || {}
end

#statement_cache_key(statement) ⇒ Object



187
188
189
# File 'lib/blazer/data_source.rb', line 187

def statement_cache_key(statement)
  cache_key(["statement", id, Digest::MD5.hexdigest(statement)])
end

#tablesObject



200
201
202
203
# File 'lib/blazer/data_source.rb', line 200

def tables
  result = run_statement(connection_model.send(:sanitize_sql_array, ["SELECT table_name FROM information_schema.tables WHERE table_schema IN (?) ORDER BY table_name", schemas]))
  result.rows.map(&:first)
end

#timeoutObject



44
45
46
# File 'lib/blazer/data_source.rb', line 44

def timeout
  settings["timeout"]
end

#use_transaction?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/blazer/data_source.rb', line 81

def use_transaction?
  settings.key?("use_transaction") ? settings["use_transaction"] : true
end

#variable_defaultsObject



40
41
42
# File 'lib/blazer/data_source.rb', line 40

def variable_defaults
  settings["variable_defaults"] || {}
end