9a73b634ab
This adds an ID-less table containing one row per file, per merge request diff. It has a column for each attribute on Gitlab::Git::Diff that is serialised currently, with the advantage that we can easily query the attributes of this new table. It does not migrate existing data, so we have fallback code when the legacy st_diffs column is present instead. For a merge request diff to be valid, it should have at most one of: * Rows in this new table, with the correct merge_request_diff_id. * A non-NULL st_diffs column. It may have neither, if the diff is empty.
140 lines
3.4 KiB
Ruby
140 lines
3.4 KiB
Ruby
module Gitlab
|
|
module Database
|
|
# The max value of INTEGER type is the same between MySQL and PostgreSQL:
|
|
# https://www.postgresql.org/docs/9.2/static/datatype-numeric.html
|
|
# http://dev.mysql.com/doc/refman/5.7/en/integer-types.html
|
|
MAX_INT_VALUE = 2147483647
|
|
|
|
def self.config
|
|
ActiveRecord::Base.configurations[Rails.env]
|
|
end
|
|
|
|
def self.adapter_name
|
|
config['adapter']
|
|
end
|
|
|
|
def self.mysql?
|
|
adapter_name.casecmp('mysql2').zero?
|
|
end
|
|
|
|
def self.postgresql?
|
|
adapter_name.casecmp('postgresql').zero?
|
|
end
|
|
|
|
def self.version
|
|
database_version.match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
|
|
end
|
|
|
|
def self.nulls_last_order(field, direction = 'ASC')
|
|
order = "#{field} #{direction}"
|
|
|
|
if postgresql?
|
|
order << ' NULLS LAST'
|
|
else
|
|
# `field IS NULL` will be `0` for non-NULL columns and `1` for NULL
|
|
# columns. In the (default) ascending order, `0` comes first.
|
|
order.prepend("#{field} IS NULL, ") if direction == 'ASC'
|
|
end
|
|
|
|
order
|
|
end
|
|
|
|
def self.nulls_first_order(field, direction = 'ASC')
|
|
order = "#{field} #{direction}"
|
|
|
|
if postgresql?
|
|
order << ' NULLS FIRST'
|
|
else
|
|
# `field IS NULL` will be `0` for non-NULL columns and `1` for NULL
|
|
# columns. In the (default) ascending order, `0` comes first.
|
|
order.prepend("#{field} IS NULL, ") if direction == 'DESC'
|
|
end
|
|
|
|
order
|
|
end
|
|
|
|
def self.random
|
|
postgresql? ? "RANDOM()" : "RAND()"
|
|
end
|
|
|
|
def self.true_value
|
|
if postgresql?
|
|
"'t'"
|
|
else
|
|
1
|
|
end
|
|
end
|
|
|
|
def self.false_value
|
|
if postgresql?
|
|
"'f'"
|
|
else
|
|
0
|
|
end
|
|
end
|
|
|
|
def self.with_connection_pool(pool_size)
|
|
pool = create_connection_pool(pool_size)
|
|
|
|
begin
|
|
yield(pool)
|
|
ensure
|
|
pool.disconnect!
|
|
end
|
|
end
|
|
|
|
def self.bulk_insert(table, rows)
|
|
return if rows.empty?
|
|
|
|
keys = rows.first.keys
|
|
columns = keys.map { |key| connection.quote_column_name(key) }
|
|
|
|
tuples = rows.map do |row|
|
|
row.values_at(*keys).map { |value| connection.quote(value) }
|
|
end
|
|
|
|
connection.execute <<-EOF.strip_heredoc
|
|
INSERT INTO #{table} (#{columns.join(', ')})
|
|
VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')}
|
|
EOF
|
|
end
|
|
|
|
# pool_size - The size of the DB pool.
|
|
# host - An optional host name to use instead of the default one.
|
|
def self.create_connection_pool(pool_size, host = nil)
|
|
# See activerecord-4.2.7.1/lib/active_record/connection_adapters/connection_specification.rb
|
|
env = Rails.env
|
|
original_config = ActiveRecord::Base.configurations
|
|
|
|
env_config = original_config[env].merge('pool' => pool_size)
|
|
env_config['host'] = host if host
|
|
|
|
config = original_config.merge(env => env_config)
|
|
|
|
spec =
|
|
ActiveRecord::
|
|
ConnectionAdapters::
|
|
ConnectionSpecification::Resolver.new(config).spec(env.to_sym)
|
|
|
|
ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec)
|
|
end
|
|
|
|
def self.connection
|
|
ActiveRecord::Base.connection
|
|
end
|
|
|
|
private_class_method :connection
|
|
|
|
def self.database_version
|
|
row = connection.execute("SELECT VERSION()").first
|
|
|
|
if postgresql?
|
|
row['version']
|
|
else
|
|
row.first
|
|
end
|
|
end
|
|
|
|
private_class_method :database_version
|
|
end
|
|
end
|