Class: Pgsqlarbiter::Analyzer

Inherits:
Object
  • Object
show all
Includes:
TokenType
Defined in:
lib/pgsqlarbiter/analyzer.rb

Overview

SQL query analyzer that lexes and walks a SQL string to extract its statement type, referenced tables, and function calls. Uses a hand-written lexer and single-pass token walker rather than a full parse tree.

Constant Summary collapse

JOIN_PREFIXES =
Set["INNER", "LEFT", "RIGHT", "FULL", "CROSS", "NATURAL"].freeze
FUNCTIONS_WITH_FROM_SYNTAX =
Set["EXTRACT", "TRIM", "SUBSTRING"].freeze

Constants included from TokenType

TokenType::COMMA, TokenType::DOT, TokenType::EOF, TokenType::IDENT, TokenType::KEYWORD, TokenType::LBRACKET, TokenType::LPAREN, TokenType::NUMBER, TokenType::OP, TokenType::PARAM, TokenType::QUOTED_IDENT, TokenType::RBRACKET, TokenType::RPAREN, TokenType::SEMICOLON, TokenType::STAR, TokenType::STRING, TokenType::TYPECAST

Instance Method Summary collapse

Instance Method Details

#analyze(sql) ⇒ Analysis

Analyze a SQL query string.

The analysis proceeds in four phases:

  1. Reject multiple statements
  2. Determine the statement type
  3. Pre-collect CTE names (so they are not treated as table references)
  4. Walk all tokens to extract table and function references

Parameters:

  • sql (String) —

    the SQL query to analyze

Returns:

  • (Analysis) —

    analysis result with statement_type, tables, and functions

Raises:



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
# File 'lib/pgsqlarbiter/analyzer.rb', line 29

def analyze(sql)
  @tokens = Lexer.new.tokenize(sql)
  @pos = 0
  @paren_depth = 0
  @tables = Set.new
  @functions = Set.new
  @cte_names = Set.new
  @suppress_from_depths = []

  reject_multiple_statements!
  stmt_type = determine_statement_type!

  @pos = 0
  @paren_depth = 0
  pre_collect_cte_names!

  @pos = 0
  @paren_depth = 0
  walk!

  Analysis.new(
    statement_type: stmt_type,
    tables: @tables.to_a.sort,
    functions: @functions.to_a.sort
  )
end