This file is indexed.

/usr/lib/ruby/vendor_ruby/database_cleaner/active_record/truncation.rb is in ruby-database-cleaner 1.5.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
require 'active_record/base'

require 'active_record/connection_adapters/abstract_adapter'

#Load available connection adapters
%w(
  abstract_mysql_adapter postgresql_adapter sqlite3_adapter mysql_adapter mysql2_adapter
).each do |known_adapter|
  begin
    require "active_record/connection_adapters/#{known_adapter}"
  rescue LoadError
  end
end

require "database_cleaner/generic/truncation"
require 'database_cleaner/active_record/base'

module DatabaseCleaner
  module ConnectionAdapters

    module AbstractAdapter
      # used to be called views but that can clash with gems like schema_plus
      # this gem is not meant to be exposing such an extra interface any way
      def database_cleaner_view_cache
        @views ||= select_values("select table_name from information_schema.views where table_schema = '#{current_database}'") rescue []
      end

      def database_cleaner_table_cache
        # the adapters don't do caching (#130) but we make the assumption that the list stays the same in tests
        @database_cleaner_tables ||= tables
      end

      def truncate_table(table_name)
        raise NotImplementedError
      end

      def truncate_tables(tables)
        tables.each do |table_name|
          self.truncate_table(table_name)
        end
      end
    end

    module AbstractMysqlAdapter
      def truncate_table(table_name)
        execute("TRUNCATE TABLE #{quote_table_name(table_name)};")
      end

      def truncate_tables(tables)
        tables.each { |t| truncate_table(t) }
      end

      def pre_count_truncate_tables(tables, options = {:reset_ids => true})
        filter = options[:reset_ids] ? method(:has_been_used?) : method(:has_rows?)
        truncate_tables(tables.select(&filter))
      end

      private

      def row_count(table)
        # Patch for MysqlAdapter with ActiveRecord 3.2.7 later
        # select_value("SELECT 1") #=> "1"
        select_value("SELECT EXISTS (SELECT 1 FROM #{quote_table_name(table)} LIMIT 1)").to_i
      end

      # Returns a boolean indicating if the given table has an auto-inc number higher than 0.
      # Note, this is different than an empty table since an table may populated, the index increased,
      # but then the table is cleaned.  In other words, this function tells us if the given table
      # was ever inserted into.
      def has_been_used?(table)
        if has_rows?(table)
          true
        else
          # Patch for MysqlAdapter with ActiveRecord 3.2.7 later
          # select_value("SELECT 1") #=> "1"
          select_value(<<-SQL).to_i > 1 # returns nil if not present
          SELECT Auto_increment
          FROM information_schema.tables
          WHERE table_name='#{table}';
          SQL
        end
      end

      def has_rows?(table)
        row_count(table) > 0
      end
    end

    module IBM_DBAdapter
      def truncate_table(table_name)
        execute("TRUNCATE #{quote_table_name(table_name)} IMMEDIATE")
      end
    end

    module SQLiteAdapter
      def delete_table(table_name)
        execute("DELETE FROM #{quote_table_name(table_name)};")
        if uses_sequence
          execute("DELETE FROM sqlite_sequence where name = '#{table_name}';")
        end
      end
      alias truncate_table delete_table

      def truncate_tables(tables)
        tables.each { |t| truncate_table(t) }
      end

      private

      # Returns a boolean indicating if the SQLite database is using the sqlite_sequence table.
      def uses_sequence
        select_value("SELECT name FROM sqlite_master WHERE type='table' AND name='sqlite_sequence';")
      end
    end

    module TruncateOrDelete
      def truncate_table(table_name)
        begin
          execute("TRUNCATE TABLE #{quote_table_name(table_name)};")
        rescue ::ActiveRecord::StatementInvalid
          execute("DELETE FROM #{quote_table_name(table_name)};")
        end
      end
    end

    module OracleAdapter
      def truncate_table(table_name)
        execute("TRUNCATE TABLE #{quote_table_name(table_name)}")
      end
    end

    module PostgreSQLAdapter
      def db_version
        @db_version ||= postgresql_version
      end

      def cascade
        @cascade ||= db_version >=  80200 ? 'CASCADE' : ''
      end

      def restart_identity
        @restart_identity ||= db_version >=  80400 ? 'RESTART IDENTITY' : ''
      end

      def truncate_table(table_name)
        truncate_tables([table_name])
      end

      def truncate_tables(table_names)
        return if table_names.nil? || table_names.empty?
        execute("TRUNCATE TABLE #{table_names.map{|name| quote_table_name(name)}.join(', ')} #{restart_identity} #{cascade};")
      end

      def pre_count_truncate_tables(tables, options = {:reset_ids => true})
        filter = options[:reset_ids] ? method(:has_been_used?) : method(:has_rows?)
        truncate_tables(tables.select(&filter))
      end

      def database_cleaner_table_cache
        # AR returns a list of tables without schema but then returns a
        # migrations table with the schema. There are other problems, too,
        # with using the base list. If a table exists in multiple schemas
        # within the search path, truncation without the schema name could
        # result in confusing, if not unexpected results.
        @database_cleaner_tables ||= tables_with_schema
      end

      private

      # Returns a boolean indicating if the given table has an auto-inc number higher than 0.
      # Note, this is different than an empty table since an table may populated, the index increased,
      # but then the table is cleaned.  In other words, this function tells us if the given table
      # was ever inserted into.
      def has_been_used?(table)
        return has_rows?(table) unless has_sequence?(table)

        cur_val = select_value("SELECT currval('#{table}_id_seq');").to_i rescue 0
        cur_val > 0
      end

      def has_sequence?(table)
        select_value("SELECT true FROM pg_class WHERE relname = '#{table}_id_seq';")
      end

      def has_rows?(table)
        select_value("SELECT true FROM #{table} LIMIT 1;")
      end

      def tables_with_schema
        rows = select_rows <<-_SQL
          SELECT schemaname || '.' || tablename
          FROM pg_tables
          WHERE
            tablename !~ '_prt_' AND
            tablename <> '#{::ActiveRecord::Migrator.schema_migrations_table_name}' AND
            schemaname = ANY (current_schemas(false))
        _SQL
        rows.collect { |result| result.first }
      end
    end
  end
end

module ActiveRecord
  module ConnectionAdapters
    #Apply adapter decoraters where applicable (adapter should be loaded)
    AbstractAdapter.class_eval { include DatabaseCleaner::ConnectionAdapters::AbstractAdapter }

    if defined?(JdbcAdapter)
      if defined?(OracleJdbcConnection)
        JdbcAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::OracleAdapter }
      else
        JdbcAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::TruncateOrDelete }
      end
    end
    AbstractMysqlAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::AbstractMysqlAdapter } if defined?(AbstractMysqlAdapter)
    Mysql2Adapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::AbstractMysqlAdapter } if defined?(Mysql2Adapter)
    MysqlAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::AbstractMysqlAdapter } if defined?(MysqlAdapter)
    SQLiteAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::SQLiteAdapter } if defined?(SQLiteAdapter)
    SQLite3Adapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::SQLiteAdapter } if defined?(SQLite3Adapter)
    PostgreSQLAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::PostgreSQLAdapter } if defined?(PostgreSQLAdapter)
    IBM_DBAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::IBM_DBAdapter } if defined?(IBM_DBAdapter)
    SQLServerAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::TruncateOrDelete } if defined?(SQLServerAdapter)
    OracleEnhancedAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::OracleAdapter } if defined?(OracleEnhancedAdapter)
  end
end

module DatabaseCleaner::ActiveRecord
  class Truncation
    include ::DatabaseCleaner::ActiveRecord::Base
    include ::DatabaseCleaner::Generic::Truncation

    def clean
      connection = connection_class.connection
      connection.disable_referential_integrity do
        if pre_count? && connection.respond_to?(:pre_count_truncate_tables)
          connection.pre_count_truncate_tables(tables_to_truncate(connection), {:reset_ids => reset_ids?})
        else
          connection.truncate_tables(tables_to_truncate(connection))
        end
      end
    end

    private

    def tables_to_truncate(connection)
      tables_in_db = cache_tables? ? connection.database_cleaner_table_cache : connection.tables
      to_reject = (@tables_to_exclude + connection.database_cleaner_view_cache)
      (@only || tables_in_db).reject do |table|
        if ( m = table.match(/([^.]+)$/) )
          to_reject.include?(m[1])
        else
          false
        end
      end
    end

    # overwritten
    def migration_storage_names
      [::ActiveRecord::Migrator.schema_migrations_table_name]
    end

    def cache_tables?
      !!@cache_tables
    end

    def pre_count?
      @pre_count == true
    end

    def reset_ids?
      @reset_ids != false
    end
  end
end