Method: PgQuery::ParserResult#truncate

Defined in:
lib/pg_query/truncate.rb

#truncate(max_length) ⇒ Object

Truncates the query string to be below the specified length, first trying to omit less important parts of the query, and only then cutting off the end.



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
# File 'lib/pg_query/truncate.rb', line 8

def truncate(max_length) # rubocop:disable Metrics/CyclomaticComplexity
  output = deparse

  # Early exit if we're already below the max length
  return output if output.size <= max_length

  truncations = find_possible_truncations

  # Truncate the deepest possible truncation that is the longest first
  truncations.sort_by! { |t| [-t.location.size, -t.length] }

  tree = dup_tree
  truncations.each do |truncation|
    next if truncation.length < 3

    find_tree_location(tree, truncation.location) do |node, _k|
      dummy_column_ref = PgQuery::Node.new(column_ref: PgQuery::ColumnRef.new(fields: [PgQuery::Node.new(string: PgQuery::String.new(sval: ''))]))
      case truncation.node_type
      when :target_list
        res_target_name = '' if node.is_a?(PgQuery::UpdateStmt) || node.is_a?(PgQuery::OnConflictClause)
        node.target_list.replace(
          [
            PgQuery::Node.new(res_target: PgQuery::ResTarget.new(name: res_target_name, val: dummy_column_ref))
          ]
        )
      when :where_clause
        node.where_clause = dummy_column_ref
      when :values_lists
        node.values_lists.replace(
          [
            PgQuery::Node.new(list: PgQuery::List.new(items: [dummy_column_ref]))
          ]
        )
      when :ctequery
        node.ctequery = PgQuery::Node.new(select_stmt: PgQuery::SelectStmt.new(where_clause: dummy_column_ref, op: :SETOP_NONE))
      when :cols
        node.cols.replace([PgQuery::Node.from(PgQuery::ResTarget.new(name: ''))]) if node.is_a?(PgQuery::InsertStmt)
      else
        raise ArgumentError, format('Unexpected truncation node type: %s', truncation.node_type)
      end
    end

    output = PgQuery.deparse(tree).gsub('SELECT WHERE "…"', '...').gsub('"…"', '...')
    return output if output.size <= max_length
  end

  # We couldn't do a proper smart truncation, so we need a hard cut-off
  output[0..max_length - 4] + '...'
end