db2_query 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Db2Query
4
- module ConnectionHandling
5
- extend ActiveSupport::Concern
6
-
7
- DEFAULT_DB = "primary"
8
-
9
- included do |base|
10
- def base.inherited(child)
11
- child.connection = @connection
12
- end
13
-
14
- base.extend ClassMethods
15
- base.connection = nil
16
- end
17
-
18
- module ClassMethods
19
- attr_reader :connection
20
-
21
- def connection=(connection)
22
- @connection = connection
23
- update_descendants_connection unless self.descendants.empty?
24
- end
25
-
26
- def update_descendants_connection
27
- self.descendants.each { |child| child.connection = @connection }
28
- end
29
-
30
- def establish_connection(db_name = nil)
31
- clear_connection unless self.connection.nil?
32
- db_name = db_name.nil? ? DEFAULT_DB : db_name.to_s
33
-
34
- self.load_database_configurations if self.configurations.nil?
35
-
36
- if self.configurations[db_name].nil?
37
- raise Error, "Database (:#{db_name}) not found at database configurations."
38
- end
39
-
40
- conn_type, conn_config = extract_configuration(db_name)
41
-
42
- connector = ODBCConnector.new(conn_type, conn_config)
43
- self.connection = Connection.new(connector, db_name)
44
- end
45
-
46
- def current_database
47
- @connection.db_name
48
- end
49
-
50
- def clear_connection
51
- @connection.disconnect!
52
- @connection = nil
53
- end
54
- end
55
- end
56
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Db2Query
4
- module DatabaseConfigurations
5
- extend ActiveSupport::Concern
6
-
7
- DEFAULT_ENV = -> { (Rails.env if defined?(Rails.env)) || ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence }
8
-
9
- included do |base|
10
- @@configurations = Hash.new
11
-
12
- base.extend ClassMethods
13
- end
14
-
15
- module ClassMethods
16
- def configurations
17
- @@configurations
18
- end
19
-
20
- def load_database_configurations(path = nil)
21
- file_path = path.nil? ? Path.database_config_file : path
22
-
23
- if File.exist?(file_path)
24
- file = File.read(file_path)
25
- @@configurations = YAML.load(ERB.new(file).result)[DEFAULT_ENV.call]
26
- else
27
- raise Error, "Could not load db2query database configuration. No such file - #{file_path}"
28
- end
29
- end
30
-
31
- def configurations_databases
32
- self.load_database_configurations if self.configurations.nil?
33
- @@configurations.keys
34
- end
35
-
36
- private
37
- def extract_configuration(db_name)
38
- configs = @@configurations[db_name.to_s]
39
- conn_config = configs.nil? ? configs : configs.transform_keys(&:to_sym)
40
- conn_type = (conn_config.keys & ODBCConnector::CONNECTION_TYPES).first
41
-
42
- if conn_type.nil?
43
- raise Error, "No data source name (:dsn) or connection string (:conn_str) provided."
44
- end
45
-
46
- [conn_type, conn_config]
47
- end
48
- end
49
- end
50
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Db2Query
4
- module DatabaseStatements
5
- def query_value(sql) # :nodoc:
6
- single_value_from_rows(query(sql))
7
- end
8
-
9
- def query(sql)
10
- exec_query(sql).last
11
- end
12
-
13
- def query_values(sql)
14
- query(sql).map(&:first)
15
- end
16
-
17
- def current_database
18
- db_name.to_s
19
- end
20
-
21
- def current_schema
22
- query_value("select current_schema from sysibm.sysdummy1").strip
23
- end
24
- alias library current_schema
25
-
26
- private
27
- def single_value_from_rows(rows)
28
- row = rows.first
29
- row && row.first
30
- end
31
- end
32
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Db2Query
4
- class LogSubscriber < ActiveSupport::LogSubscriber
5
- # Embed in a String to clear all previous ANSI sequences.
6
- CLEAR = "\e[0m"
7
- BOLD = "\e[1m"
8
-
9
- # Colors
10
- BLACK = "\e[30m"
11
- RED = "\e[31m"
12
- GREEN = "\e[32m"
13
- YELLOW = "\e[33m"
14
- BLUE = "\e[34m"
15
- MAGENTA = "\e[35m"
16
- CYAN = "\e[36m"
17
- WHITE = "\e[37m"
18
-
19
- def sql(event)
20
- class_load_duration = color("#{event.payload[:name]} Load (#{event.duration.round(2)}ms)", :cyan, true)
21
- sql_statement = color("#{event.payload[:sql]}", :blue, true)
22
- message = " #{class_load_duration} #{sql_statement}"
23
-
24
- if event.payload[:binds].size > 0
25
- binds = color("#{event.payload[:binds]}", :white)
26
- message = "#{message} [#{binds}]"
27
- end
28
-
29
- puts message
30
- end
31
-
32
- def schema_task(event)
33
- puts color(" Done (#{(event.duration).round(2)}ms)", :green, true)
34
- end
35
-
36
- def schema_task_perform(event)
37
- task_name = color(":#{event.payload[:task_name]}", :white, true)
38
- schema = color("#{event.payload[:schema]}", :white, true)
39
- puts "- Performing #{task_name} in #{schema} ..."
40
- end
41
-
42
- private
43
- def color(text, color, bold = false) # :doc:
44
- return text unless colorize_logging
45
- color = self.class.const_get(color.upcase) if color.is_a?(Symbol)
46
- bold = bold ? BOLD : ""
47
- "#{bold}#{color}#{text}#{CLEAR}"
48
- end
49
- end
50
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Db2Query
4
- class ODBCConnector
5
- attr_reader :connector, :conn_type, :conn_config
6
-
7
- CONNECTION_TYPES = %i[dsn conn_string].freeze
8
-
9
- def initialize(type, config)
10
- @conn_type, @conn_config = type, config.transform_keys(&:to_sym)
11
- @connector = Db2Query.const_get("#{conn_type.to_s.camelize}Connector").new
12
- end
13
-
14
- def connect
15
- connector.connect(conn_config)
16
- end
17
- end
18
-
19
- class DsnConnector
20
- def connect(config)
21
- ::ODBC.connect(config[:dsn], config[:uid], config[:pwd])
22
- rescue ::ODBC::Error => e
23
- raise Error, "Unable to activate ODBC DSN connection #{e}"
24
- end
25
- end
26
-
27
- class ConnStringConnector
28
- def connect(config)
29
- driver = ::ODBC::Driver.new.tap do |d|
30
- d.attrs = config[:conn_string].transform_keys(&:to_s)
31
- d.name = "odbc"
32
- end
33
- ::ODBC::Database.new.drvconnect(driver)
34
- rescue ::ODBC::Error => e
35
- raise Error, "Unable to activate ODBC Conn String connection #{e}"
36
- end
37
- end
38
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Db2Query
4
- module Path
5
- def self.database_config_file
6
- @@database_config_file ||= nil
7
- end
8
-
9
- def self.database_config_file=(file_path)
10
- @@database_config_file ||= file_path
11
- end
12
-
13
- def self.database_config_file_exists?
14
- File.exist?(self.database_config_file)
15
- end
16
- end
17
- end
@@ -1,113 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Db2Query
4
- class Schema
5
- include SQLValidator
6
-
7
- attr_accessor :config, :current_schema
8
-
9
- def initialize
10
- @config = Config.new
11
- end
12
-
13
- def connection
14
- Base.connection
15
- end
16
-
17
- def schema
18
- config.schema
19
- end
20
-
21
- def sql_files_dir(path)
22
- config.sql_files_dir = path
23
- end
24
-
25
- def is_valid_schema?
26
- connection.current_schema == config.schema
27
- end
28
-
29
- def perform_tasks(&block)
30
- raise Error, "#{config.main_library} is not connection's current schema" unless is_valid_schema?
31
-
32
- if Base.connection.nil? && config.init_connection
33
- Base.establish_connection
34
- end
35
-
36
- puts "\n# Perform Schema Tasks: \n\n"
37
-
38
- instance_eval(&block)
39
-
40
- puts "\n"
41
- end
42
-
43
- def sql(sql_statement)
44
- raise Error, "Task only for SQL execute commands." if query_command?(sql_statement)
45
- sql_statement
46
- end
47
-
48
- def file(file_name)
49
- sql(File.read("#{config.sql_files_dir}/#{file_name}"))
50
- end
51
-
52
- def task(task_name, sql = nil, *args)
53
- Task.new(schema, task_name).perform do
54
- if block_given?
55
- yield(sql)
56
- else
57
- execute(sql, *args)
58
- end
59
- end
60
- end
61
-
62
- def execute(sql, *args)
63
- connection.execute(sql, *args)
64
- rescue ::ODBC::Error => e
65
- raise Error, "Unable to execute SQL - #{e}"
66
- end
67
-
68
- def tables_in_schema
69
- connection.query_values <<-SQL
70
- SELECT table_name FROM SYSIBM.SQLTABLES
71
- WHERE table_schem='#{schema}' AND table_type='TABLE'
72
- SQL
73
- end
74
-
75
- def self.initiation(&block)
76
- new.initiation(&block)
77
- end
78
-
79
- def initiation(&block)
80
- instance_eval(&block)
81
- end
82
-
83
- class Task
84
- attr_reader :instrumenter, :schema, :task_name, :start_time, :finish_time
85
-
86
- def initialize(schema, task_name)
87
- @schema = schema
88
- @task_name = task_name
89
- @instrumenter = ActiveSupport::Notifications.instrumenter
90
- end
91
-
92
- def perform
93
- instrumenter.instrument("schema_task_perform.db2_query", payload)
94
- instrumenter.start("schema_task.db2_query", payload)
95
- yield
96
- instrumenter.finish("schema_task.db2_query", payload)
97
- end
98
-
99
- private
100
- def payload
101
- { task_name: task_name, schema: schema }
102
- end
103
- end
104
-
105
- class Config
106
- attr_accessor :initial_tasks, :init_connection, :schema, :sql_files_dir
107
-
108
- def initialize
109
- @init_connection = false
110
- end
111
- end
112
- end
113
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Db2Query
4
- module SQLValidator
5
- DEFAULT_TASK_COMMANDS = [:create, :drop, :delete, :insert, :set, :update]
6
- COMMENT_REGEX = %r{/\*(?:[^\*]|\*[^/])*\*/}m
7
-
8
- def task_command?(sql_statement)
9
- sql_statement.match?(task_commands_regexp)
10
- end
11
-
12
- def query_command?(sql_statement)
13
- sql_statement.match?(/select/i)
14
- end
15
-
16
- def is_query?(sql_statement)
17
- query_command?(sql_statement) && !task_command?(sql_statement)
18
- end
19
-
20
- private
21
- def task_commands_regexp
22
- parts = DEFAULT_TASK_COMMANDS.map { |part| /#{part}/i }
23
- /\A(?:[\(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/i
24
- end
25
- end
26
- end
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- DB2_QUERY_DATABASE_TEMPLATE ||= <<-EOF
4
- # frozen_string_literal: true
5
-
6
- # Database configuration example
7
- development:
8
- primary:
9
- conn_string:
10
- driver: DB2
11
- database: SAMPLE
12
- dbalias: SAMPLE
13
- hostname: LOCALHOST
14
- currentschema: LIBTEST
15
- port: "0"
16
- protocol: IPC
17
- uid: <%= ENV["DB2EC_UID"] %>
18
- pwd: <%= ENV["DB2EC_PWD"] %>
19
- secondary:
20
- dsn: SAMPLE
21
- uid: <%= ENV["DB2EC_UID"] %>
22
- pwd: <%= ENV["DB2EC_PWD"] %>
23
-
24
- test:
25
- primary:
26
- conn_string:
27
- driver: DB2
28
- database: SAMPLE
29
- dbalias: SAMPLE
30
- hostname: LOCALHOST
31
- currentschema: LIBTEST
32
- port: "0"
33
- protocol: IPC
34
- uid: <%= ENV["DB2EC_UID"] %>
35
- pwd: <%= ENV["DB2EC_PWD"] %>
36
- secondary:
37
- dsn: SAMPLE
38
- uid: <%= ENV["DB2EC_UID"] %>
39
- pwd: <%= ENV["DB2EC_PWD"] %>
40
- EOF
41
-
42
- namespace :db2query do
43
- desc "Create Database configuration file"
44
- task :database do
45
- database_path = "#{Rails.root}/config/db2query_database.yml"
46
- if File.exist?(database_path)
47
- raise ArgumentError, "File exists."
48
- else
49
- puts " Creating database config file ..."
50
- File.open(database_path, "w") do |file|
51
- file.puts DB2_QUERY_DATABASE_TEMPLATE
52
- end
53
- puts " File '#{database_path}' created."
54
- end
55
- end
56
- end