Class: SqlBeautifier::Join

Inherits:
Base
  • Object
show all
Defined in:
lib/sql_beautifier/join.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extract_keyword(join_text) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/sql_beautifier/join.rb', line 37

def self.extract_keyword(join_text)
  trimmed = join_text.strip

  Constants::JOIN_KEYWORDS_BY_LENGTH.each do |keyword|
    next unless trimmed.downcase.start_with?(keyword)

    remaining = trimmed[keyword.length..].strip
    return [keyword, remaining]
  end

  [nil, nil]
end

.extract_trailing_sentinels(text) ⇒ Object



50
51
52
53
54
# File 'lib/sql_beautifier/join.rb', line 50

def self.extract_trailing_sentinels(text)
  text.scan(CommentParser::SENTINEL_PATTERN).map do |match|
    "#{CommentParser::SENTINEL_PREFIX}#{match[0]}#{CommentParser::SENTINEL_SUFFIX}"
  end.presence
end

.parse(join_text, table_registry:) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/sql_beautifier/join.rb', line 11

def self.parse(join_text, table_registry:)
  keyword, remaining_content = extract_keyword(join_text)
  return unless keyword && remaining_content

  remaining_content, lateral = TableReference.strip_lateral_prefix(remaining_content)

  on_keyword_position = Tokenizer.find_top_level_keyword(remaining_content, "on")

  if on_keyword_position
    table_text = remaining_content[0...on_keyword_position].strip
    condition_text = remaining_content[on_keyword_position..].delete_prefix("on").strip
    conditions = Tokenizer.split_top_level_conditions(condition_text)
  else
    table_text = remaining_content
    conditions = []
  end

  table_lookup_name = TableReference.derived_table_lookup_name_from(table_text) || Util.first_word(table_text)
  table_reference = table_registry.reference_for(table_lookup_name)
  return unless table_reference

  trailing_sentinels = extract_trailing_sentinels(table_text)

  new(keyword: keyword, lateral: lateral, table_reference: table_reference, trailing_sentinels: trailing_sentinels, conditions: conditions)
end

Instance Method Details

#render(continuation_indent:, condition_indent:) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/sql_beautifier/join.rb', line 56

def render(continuation_indent:, condition_indent:)
  rendered_table = @table_reference.render(trailing_sentinels: @trailing_sentinels)
  lateral_prefix = @lateral ? "lateral " : ""
  condition_indent_width = condition_indent.length
  lines = []

  if @conditions.any?
    first_condition = @conditions.first[1]
    formatted_first_condition = format_condition(first_condition, indent_width: condition_indent_width)
    lines << "#{continuation_indent}#{@keyword} #{lateral_prefix}#{rendered_table} on #{formatted_first_condition}"

    @conditions.drop(1).each do |conjunction, condition|
      formatted_condition = format_condition(condition, indent_width: condition_indent_width)
      lines << "#{condition_indent}#{conjunction} #{formatted_condition}"
    end
  else
    lines << "#{continuation_indent}#{@keyword} #{lateral_prefix}#{rendered_table}"
  end

  lines.join("\n")
end