Class: Arel::Enhance::ContextEnhancer::ArelTable

Inherits:
Object
  • Object
show all
Defined in:
lib/arel/enhance/context_enhancer/arel_table.rb

Class Method Summary collapse

Class Method Details

.call(node) ⇒ Object

rubocop:disable Metrics/PerceivedComplexity rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/AbcSize



8
9
10
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/arel/enhance/context_enhancer/arel_table.rb', line 8

def self.call(node)
  context = node.context.merge!(
    range_variable: false, column_reference: false, alias: false,
  )
  parent_object = node.parent.object

  # Using Arel::Table as SELECT ... FROM <table>
  if parent_object.is_a?(Arel::Nodes::JoinSource)
    context[:range_variable] = true

  # NOTE: only applies to ActiveRecord generated Arel
  # which does not use Arel::Table#alias but Arel::TableAlias instead
  # Using Arel::Table as SELECT ... FROM <table> AS alias
  elsif parent_object.is_a?(Arel::Nodes::TableAlias) &&
        node.parent.parent.object.is_a?(Arel::Nodes::JoinSource)
    context[:range_variable] = true

  elsif parent_object.is_a?(Arel::Nodes::TableAlias) &&
        node.parent.parent.parent.object.is_a?(Arel::Nodes::JoinSource)
    context[:range_variable] = true

  # Using Arel::Table as SELECT ... FROM [<table>]
  elsif parent_object.is_a?(Array) &&
        node.parent.parent.object.is_a?(Arel::Nodes::JoinSource)
    context[:range_variable] = true

  # NOTE: only applies to ActiveRecord generated Arel
  # which does not use Arel::Table#alias but Arel::TableAlias instead
  # Using Arel::Table as SELECT ... FROM [<table> AS alias]
  elsif parent_object.is_a?(Arel::Nodes::TableAlias) &&
        node.parent.parent.object.is_a?(Array) &&
        node.parent.parent.parent.object.is_a?(Arel::Nodes::JoinSource)
    context[:range_variable] = true

  elsif parent_object.is_a?(Arel::Nodes::TableAlias) &&
        node.parent.parent.object.is_a?(Arel::Attributes::Attribute)
    context[:column_reference] = true

  elsif parent_object.is_a?(Arel::Nodes::TableAlias) &&
        node.parent.parent.parent.object.is_a?(Arel::Attributes::Attribute)
    context[:column_reference] = true

  # Using Arel::Table as SELECT ... INNER JOIN <table> ON TRUE
  elsif parent_object.is_a?(Arel::Nodes::Join)
    context[:range_variable] = true

  elsif parent_object.is_a?(Arel::Nodes::TableAlias) &&
        node.parent.parent.object.is_a?(Arel::Nodes::Join)
    context[:range_variable] = true

  elsif parent_object.is_a?(Arel::Nodes::TableAlias) &&
        node.parent.parent.parent.object.is_a?(Arel::Nodes::Join)
    context[:range_variable] = true

  # Using Arel::Table as an attribute SELECT <table>.id ...
  elsif parent_object.is_a?(Arel::Attributes::Attribute)
    context[:column_reference] = true

  # Using Arel::Table in an INSERT INTO <table>
  elsif parent_object.is_a?(Arel::Nodes::InsertStatement)
    context[:range_variable] = true

  # Using Arel::Table in an UPDATE <table> ...
  elsif parent_object.is_a?(Arel::Nodes::UpdateStatement)
    context[:range_variable] = true

  # Arel::Table in UPDATE ... FROM [<table>]
  elsif parent_object.is_a?(Array) &&
        node.parent.parent.object.is_a?(Arel::Nodes::UpdateStatement)
    context[:range_variable] = true

  # Using Arel::Table in an DELETE FROM <table>
  elsif parent_object.is_a?(Arel::Nodes::DeleteStatement)
    context[:range_variable] = true

  # Arel::Table in DELETE ... USING [<table>]
  elsif parent_object.is_a?(Array) &&
        node.parent.parent.object.is_a?(Arel::Nodes::DeleteStatement)
    context[:range_variable] = true

  # Using Arel::Table as an "alias" for WITH <table> AS (SELECT 1) SELECT 1
  elsif parent_object.is_a?(Arel::Nodes::As) &&
        node.parent.parent.parent.object.is_a?(Arel::Nodes::With)
    context[:alias] = true

  # Using Arel::Table as an "alias" for WITH RECURSIVE <table> AS (SELECT 1) SELECT 1
  elsif parent_object.is_a?(Arel::Nodes::As) &&
        node.parent.parent.parent.object.is_a?(Arel::Nodes::WithRecursive)
    context[:alias] = true

  # Using Arel::Table as an "alias" for SELECT INTO <table> ...
  elsif parent_object.is_a?(Arel::Nodes::Into)
    context[:alias] = true

  else
    raise "Unknown AST location for table #{node.inspect}, #{node.root_node.to_sql}"
  end
end