Class: Gitlab::Database::QueryAnalyzers::PreventSetOperatorMismatch::Columns

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/database/query_analyzers/prevent_set_operator_mismatch/columns.rb

Overview

Columns refer to table columns produced by queries and parts of queries. If we have ‘SELECT namespaces.id` then `id` is a column. But, we can also have `WHERE namespaces.id > 10` and `id` is also a column.

In static analysis of a SQL query a column source can be ambiguous. Such as in ‘SELECT id FROM users, namespaces. In such cases we assume `id` could come from either `users` or `namespaces`.

Class Method Summary collapse

Class Method Details

.types(select_stmt) ⇒ Object

Determine the type of each column in the select statement. Returns a Set object containing a Types enum. When an error is found parsing will return immediately.



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
# File 'lib/gitlab/database/query_analyzers/prevent_set_operator_mismatch/columns.rb', line 19

def types(select_stmt)
  # Forward through any errors when the column refers to a part of the SQL query that is known to include
  # errors. For example, the column may refer to a column from a CTE that was invalid.
  return Set.new([Type::INVALID]) if References.errors?(select_stmt.all_references)

  types = Set.new

  # Resolve the type of reference for each target in the select statement.
  target_list = select_stmt.node.target_list
  targets = target_list.map(&:res_target)
  targets.each do |target|
    target_type = get_target_type(target, select_stmt)

    # A NULL target is of the form:
    # SELECT NULL::namespaces FROM namespaces
    types += if Targets.null?(target)
               # Maintain any errors but otherwise ignore this target.
               target_type & [Type::INVALID]
             else
               target_type
             end
  end

  types
end