Class: GoodData::CloudResources::MysqlClient

Inherits:
CloudResourceClient show all
Defined in:
lib/gooddata/cloud_resources/mysql/mysql_client.rb

Constant Summary collapse

JDBC_MYSQL_PATTERN =
%r{jdbc:mysql:\/\/([^:^\/]+)(:([0-9]+))?(\/)?}
MYSQL_DEFAULT_PORT =
3306
JDBC_MYSQL_PROTOCOL =
'jdbc:mysql://'
VERIFY_FULL =
'&useSSL=true&verifyServerCertificate=true'
PREFER =
'&useSSL=true&requireSSL=false&verifyServerCertificate=false'
REQUIRE =
'&useSSL=true&requireSSL=true&verifyServerCertificate=false'
MYSQL_FETCH_SIZE =
1000
MONGO_BI_FETCH_SIZE =
1
MONGO_BI_TYPE =
'MongoDBConnector'

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from CloudResourceClient

descendants

Constructor Details

#initialize(options = {}) ⇒ MysqlClient

Returns a new instance of MysqlClient.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/gooddata/cloud_resources/mysql/mysql_client.rb', line 37

def initialize(options = {})
  raise("Data Source needs a client to Mysql to be able to query the storage but 'mysql_client' is empty.") unless options['mysql_client']

  if options['mysql_client']['connection'].is_a?(Hash)
    @database = options['mysql_client']['connection']['database']
    @authentication = options['mysql_client']['connection']['authentication']
    @ssl_mode = options['mysql_client']['connection']['sslMode']
    @database_type = options['mysql_client']['connection']['databaseType']
    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['mysql_client']['connection']['url'])
  else
    raise('Missing connection info for Mysql client')
  end

  Java.com.mysql.jdbc.Driver
end

Class Method Details

.accept?(type) ⇒ Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/gooddata/cloud_resources/mysql/mysql_client.rb', line 32

def accept?(type)
  type == 'mysql'
end

Instance Method Details

#add_extendedObject



116
117
118
# File 'lib/gooddata/cloud_resources/mysql/mysql_client.rb', line 116

def add_extended
  @database_type == MONGO_BI_TYPE ? '&authenticationPlugins=org.mongodb.mongosql.auth.plugin.MongoSqlAuthenticationPlugin&useLocalTransactionState=true' : ''
end

#build_url(url) ⇒ Object



91
92
93
94
95
96
97
98
99
# File 'lib/gooddata/cloud_resources/mysql/mysql_client.rb', line 91

def build_url(url)
  matches = url.scan(JDBC_MYSQL_PATTERN)
  raise 'Cannot reach the url' unless matches

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

  "#{JDBC_MYSQL_PROTOCOL}#{host}:#{port}/#{@database}?#{get_ssl_mode(@ssl_mode)}#{add_extended}&useCursorFetch=true&enabledTLSProtocols=TLSv1.2"
end

#connectObject



81
82
83
84
85
86
87
88
89
# File 'lib/gooddata/cloud_resources/mysql/mysql_client.rb', line 81

def connect
  GoodData.logger.info "Setting up connection to Mysql #{@database_type} #{@url} "

  prop = java.util.Properties.new
  prop.setProperty('user', @authentication['basic']['userName'])
  prop.setProperty('password', @authentication['basic']['password'])
  @connection = java.sql.DriverManager.getConnection(@url, prop)
  @connection.set_auto_commit(false)
end

#fetch_sizeObject



101
102
103
# File 'lib/gooddata/cloud_resources/mysql/mysql_client.rb', line 101

def fetch_size
  @database_type == MONGO_BI_TYPE ? MONGO_BI_FETCH_SIZE : MYSQL_FETCH_SIZE
end

#get_ssl_mode(ssl_mode) ⇒ Object



105
106
107
108
109
110
111
112
113
114
# File 'lib/gooddata/cloud_resources/mysql/mysql_client.rb', line 105

def get_ssl_mode(ssl_mode)
  mode = PREFER
  if ssl_mode == 'verify-full'
    mode =  VERIFY_FULL
  elsif ssl_mode == 'require'
    mode =  REQUIRE
  end

  mode
end

#realize_query(query, _params) ⇒ Object



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
# File 'lib/gooddata/cloud_resources/mysql/mysql_client.rb', line 55

def realize_query(query, _params)
  GoodData.gd_logger.info("Realize SQL query: type=mysql 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(fetch_size)
    has_result = statement.execute(query)
    if has_result
      result = statement.get_result_set
       = result.
      col_count = .column_count
      CSV.open(filename, 'wb') do |csv|
        csv << Array(1..col_count).map { |i| .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=mysql status=finished duration=#{measure.real}")
  filename
ensure
  @connection&.close
  @connection = nil
end