This file is indexed.

/usr/lib/ruby/vendor_ruby/sequel/adapters/amalgalite.rb is in ruby-sequel 4.1.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
require 'amalgalite'
Sequel.require 'adapters/shared/sqlite'

module Sequel
  # Top level module for holding all Amalgalite-related modules and classes
  # for Sequel.
  module Amalgalite
    # Type conversion map class for Sequel's use of Amalgamite
    class SequelTypeMap < ::Amalgalite::TypeMaps::DefaultMap
      methods_handling_sql_types.delete('string')
      methods_handling_sql_types.merge!(
        'datetime' => %w'datetime timestamp',
        'time' => %w'time',
        'float' => ['float', 'double', 'real', 'double precision'],
        'decimal' => %w'numeric decimal money'
      )

      # Store the related database object, in order to be able to correctly
      # handle the database timezone.
      def initialize(db)
        @db = db
      end
      
      # Return blobs as instances of Sequel::SQL::Blob instead of
      # Amalgamite::Blob
      def blob(s)
        SQL::Blob.new(s)
      end
      
      # Return numeric/decimal types as instances of BigDecimal
      # instead of Float
      def decimal(s)
        BigDecimal.new(s)
      end
      
      # Return datetime types as instances of Sequel.datetime_class
      def datetime(s)
        @db.to_application_timestamp(s)
      end

      def time(s)
        Sequel.string_to_time(s)
      end
      
      # Don't raise an error if the value is a string and the declared
      # type doesn't match a known type, just return the value.
      def result_value_of(declared_type, value)
        if value.is_a?(::Amalgalite::Blob)
          SQL::Blob.new(value.to_s)
        elsif value.is_a?(String) && declared_type
          (meth = self.class.sql_to_method(declared_type.downcase)) ? send(meth, value) : value
        else
          super
        end
      end
    end
    
    # Database class for SQLite databases used with Sequel and the
    # amalgalite driver.
    class Database < Sequel::Database
      include ::Sequel::SQLite::DatabaseMethods
      
      set_adapter_scheme :amalgalite
      
      # Mimic the file:// uri, by having 2 preceding slashes specify a relative
      # path, and 3 preceding slashes specify an absolute path.
      def self.uri_to_options(uri) # :nodoc:
        { :database => (uri.host.nil? && uri.path == '/') ? nil : "#{uri.host}#{uri.path}" }
      end
      private_class_method :uri_to_options
      
      # Connect to the database.  Since SQLite is a file based database,
      # the only options available are :database (to specify the database
      # name), and :timeout, to specify how long to wait for the database to
      # be available if it is locked, given in milliseconds (default is 5000).
      def connect(server)
        opts = server_opts(server)
        opts[:database] = ':memory:' if blank_object?(opts[:database])
        db = ::Amalgalite::Database.new(opts[:database])
        db.busy_handler(::Amalgalite::BusyTimeout.new(opts.fetch(:timeout, 5000)/50, 50))
        db.type_map = SequelTypeMap.new(self)
        connection_pragmas.each{|s| log_yield(s){db.execute_batch(s)}}
        db
      end
      
      # Amalgalite is just the SQLite database without a separate SQLite installation.
      def database_type
        :sqlite
      end

      # Run the given SQL with the given arguments. Returns nil.
      def execute_ddl(sql, opts=OPTS)
        _execute(sql, opts){|conn| log_yield(sql){conn.execute_batch(sql)}}
        nil
      end
      
      # Run the given SQL with the given arguments and return the number of changed rows.
      def execute_dui(sql, opts=OPTS)
        _execute(sql, opts){|conn| log_yield(sql){conn.execute_batch(sql)}; conn.row_changes}
      end
      
      # Run the given SQL with the given arguments and return the last inserted row id.
      def execute_insert(sql, opts=OPTS)
        _execute(sql, opts){|conn| log_yield(sql){conn.execute_batch(sql)}; conn.last_insert_rowid}
      end
      
      # Run the given SQL with the given arguments and yield each row.
      def execute(sql, opts=OPTS)
        _execute(sql, opts) do |conn|
          begin
            yield(stmt = log_yield(sql){conn.prepare(sql)})
          ensure
            stmt.close if stmt
          end
        end
      end
      
      # Run the given SQL with the given arguments and return the first value of the first row.
      def single_value(sql, opts=OPTS)
        _execute(sql, opts){|conn| log_yield(sql){conn.first_value_from(sql)}}
      end
      
      private
      
      # Yield an available connection.  Rescue
      # any Amalgalite::Errors and turn them into DatabaseErrors.
      def _execute(sql, opts)
        begin
          synchronize(opts[:server]){|conn| yield conn}
        rescue ::Amalgalite::Error, ::Amalgalite::SQLite3::Error => e
          raise_error(e)
        end
      end
      
      # The Amagalite adapter does not need the pool to convert exceptions.
      # Also, force the max connections to 1 if a memory database is being
      # used, as otherwise each connection gets a separate database.
      def connection_pool_default_options
        o = super.dup
        # Default to only a single connection if a memory database is used,
        # because otherwise each connection will get a separate database
        o[:max_connections] = 1 if @opts[:database] == ':memory:' || blank_object?(@opts[:database])
        o
      end
      
      # Both main error classes that Amalgalite raises
      def database_error_classes
        [::Amalgalite::Error, ::Amalgalite::SQLite3::Error]
      end
    end
    
    # Dataset class for SQLite datasets that use the amalgalite driver.
    class Dataset < Sequel::Dataset
      include ::Sequel::SQLite::DatasetMethods

      Database::DatasetClass = self
      
      # Yield a hash for each row in the dataset.
      def fetch_rows(sql)
        execute(sql) do |stmt|
          @columns = cols = stmt.result_fields.map{|c| output_identifier(c)}
          col_count = cols.size
          stmt.each do |result|
            row = {}
            col_count.times{|i| row[cols[i]] = result[i]}
            yield row
          end
        end
      end

      private
      
      # Quote the string using the adapter instance method.
      def literal_string_append(sql, v)
        db.synchronize(@opts[:server]){|c| sql << c.quote(v)}
      end
    end
  end
end