Class: Dbviewer::Query::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/dbviewer/query/parser.rb

Overview

Parser handles parsing SQL queries and extracting useful information

Class Method Summary collapse

Class Method Details

.extract_tables(sql) ⇒ Object

Extract table names from an SQL query string



6
7
8
9
10
11
12
13
14
# File 'lib/dbviewer/query/parser.rb', line 6

def self.extract_tables(sql)
  return [] if sql.nil?

  # Convert to lowercase for case-insensitive matching
  sql = sql.downcase

  # Extract table names after FROM or JOIN
  sql.scan(/(?:from|join)\s+[`"']?(\w+)[`"']?/).flatten.uniq
end

.format_binds(binds) ⇒ Object

Format bind parameters for storage



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/dbviewer/query/parser.rb', line 27

def self.format_binds(binds)
  return [] unless binds.respond_to?(:map)

  binds.map do |bind|
    if bind.respond_to?(:value)
      bind.value
    elsif bind.is_a?(Array) && bind.size == 2
      bind.last
    else
      bind.to_s
    end
  end
rescue
  []
end

.normalize(sql) ⇒ Object

Normalize a SQL query to find similar patterns Replaces specific values with placeholders



18
19
20
21
22
23
24
# File 'lib/dbviewer/query/parser.rb', line 18

def self.normalize(sql)
  return "" if sql.nil?

  sql.gsub(/\b\d+\b/, "N")
     .gsub(/'[^']*'/, "'X'")
     .gsub(/"[^"]*"/, '"X"')
end

.should_skip_internal_query?(event) ⇒ Boolean

Determine if an internal query should be skipped Internal queries are those that are part of the Dbviewer module itself and do not represent user-generated SQL queries. This helps avoid logging internal operations that are not relevant to users.

Parameters:

  • event (ActiveSupport::Notifications::Event)

    The notification event

Returns:

  • (Boolean)

    True if the query should be skipped



63
64
65
66
67
68
69
70
71
# File 'lib/dbviewer/query/parser.rb', line 63

def self.should_skip_internal_query?(event)
  event.payload[:name]&.include?("Dbviewer::") ||
  # SQLite specific check for size queries
  event.payload[:sql].include?("PRAGMA") ||
  # PostgreSQL specific check for size queries
  event.payload[:sql].include?("pg_database_size(current_database())") ||
  # MySQL specific check for size queries
  event.payload[:sql].include?("SUM(data_length + index_length) AS size FROM information_schema.TABLES")
end

.should_skip_query?(event) ⇒ Boolean

Determine if a query should be skipped based on content Rails and ActiveRecord often run internal queries that are not useful for logging

Parameters:

  • event (ActiveSupport::Notifications::Event)

    The notification event

Returns:

  • (Boolean)

    True if the query should be skipped



47
48
49
50
51
52
53
54
55
# File 'lib/dbviewer/query/parser.rb', line 47

def self.should_skip_query?(event)
  event.payload[:name] == "SCHEMA" ||
  event.payload[:sql].include?("SHOW TABLES") ||
  event.payload[:sql].include?("sqlite_master") ||
  event.payload[:sql].include?("information_schema") ||
  event.payload[:sql].include?("schema_migrations") ||
  event.payload[:sql].include?("ar_internal_metadata") ||
  event.payload[:sql].include?("pg_catalog")
end