class GoodData::CloudResources::PostgresClient

Constants

JDBC_POSTGRES_PATTERN
JDBC_POSTGRES_PROTOCOL
POSTGRES_DEFAULT_PORT
POSTGRES_FETCH_SIZE
POSTGRES_SET_SCHEMA_COMMAND
PREFER
REQUIRE
SSL_JAVA_FACTORY
VERIFY_FULL

Public Class Methods

accept?(type) click to toggle source
# File lib/gooddata/cloud_resources/postgresql/postgresql_client.rb, line 32
def accept?(type)
  type == 'postgresql'
end
new(options = {}) click to toggle source
# File lib/gooddata/cloud_resources/postgresql/postgresql_client.rb, line 37
def initialize(options = {})
  raise("Data Source needs a client to Postgres to be able to query the storage but 'postgresql_client' is empty.") unless options['postgresql_client']

  if options['postgresql_client']['connection'].is_a?(Hash)
    @database = options['postgresql_client']['connection']['database']
    @schema = options['postgresql_client']['connection']['schema'] || 'public'
    @authentication = options['postgresql_client']['connection']['authentication']
    @ssl_mode = options['postgresql_client']['connection']['sslMode']
    raise "SSL Mode should be prefer, require and verify-full" unless @ssl_mode == 'prefer' || @ssl_mode == 'require' || @ssl_mode == 'verify-full'

    @url = build_url(options['postgresql_client']['connection']['url'])
  else
    raise('Missing connection info for Postgres client')
  end

  Java.org.postgresql.Driver
end

Public Instance Methods

build_url(url) click to toggle source
# File lib/gooddata/cloud_resources/postgresql/postgresql_client.rb, line 95
def build_url(url)
  matches = url.scan(JDBC_POSTGRES_PATTERN)
  raise 'Cannot reach the url' unless matches

  host = matches[0][0]
  port = matches[0][2]&.to_i || POSTGRES_DEFAULT_PORT

  "#{JDBC_POSTGRES_PROTOCOL}#{host}:#{port}/#{@database}?sslmode=#{@ssl_mode}#{VERIFY_FULL == @ssl_mode ? SSL_JAVA_FACTORY : ''}"
end
connect() click to toggle source
# File lib/gooddata/cloud_resources/postgresql/postgresql_client.rb, line 81
def connect
  GoodData.logger.info "Setting up connection to Postgresql #{@url}"

  prop = java.util.Properties.new
  prop.setProperty('user', @authentication['basic']['userName'])
  prop.setProperty('password', @authentication['basic']['password'])
  prop.setProperty('schema', @schema)

  @connection = java.sql.DriverManager.getConnection(@url, prop)
  statement = @connection.create_statement
  statement.execute("#{POSTGRES_SET_SCHEMA_COMMAND} #{@schema}")
  @connection.set_auto_commit(false)
end
realize_query(query, _params) click to toggle source
# File lib/gooddata/cloud_resources/postgresql/postgresql_client.rb, line 55
def realize_query(query, _params)
  GoodData.gd_logger.info("Realize SQL query: type=postgresql status=started")

  connect
  filename = "#{SecureRandom.urlsafe_base64(6)}_#{Time.now.to_i}.csv"
  measure = Benchmark.measure do
    statement = @connection.create_statement
    statement.set_fetch_size(POSTGRES_FETCH_SIZE)
    has_result = statement.execute(query)
    if has_result
      result = statement.get_result_set
      metadata = result.get_meta_data
      col_count = metadata.column_count
      CSV.open(filename, 'wb') do |csv|
        csv << Array(1..col_count).map { |i| metadata.get_column_name(i) } # build the header
        csv << Array(1..col_count).map { |i| result.get_string(i)&.to_s } while result.next
      end
    end
  end
  GoodData.gd_logger.info("Realize SQL query: type=postgresql status=finished duration=#{measure.real}")
  filename
ensure
  @connection&.close
  @connection = nil
end