db2_query 0.2.2 → 0.3.2

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +453 -110
  4. data/Rakefile +3 -2
  5. data/lib/db2_query.rb +41 -15
  6. data/lib/db2_query/base.rb +16 -5
  7. data/lib/db2_query/config.rb +20 -17
  8. data/lib/db2_query/core.rb +68 -55
  9. data/lib/db2_query/db_client.rb +56 -0
  10. data/lib/db2_query/db_connection.rb +67 -0
  11. data/lib/db2_query/db_statements.rb +87 -0
  12. data/lib/db2_query/definitions.rb +79 -0
  13. data/lib/db2_query/error.rb +81 -0
  14. data/lib/db2_query/field_type.rb +31 -0
  15. data/lib/db2_query/helper.rb +49 -0
  16. data/lib/db2_query/logger.rb +52 -0
  17. data/lib/db2_query/query.rb +117 -0
  18. data/lib/db2_query/quoting.rb +102 -0
  19. data/lib/db2_query/railtie.rb +5 -7
  20. data/lib/db2_query/result.rb +51 -31
  21. data/lib/db2_query/sql_statement.rb +34 -0
  22. data/lib/db2_query/tasks.rb +29 -0
  23. data/lib/db2_query/tasks/database.rake +2 -50
  24. data/lib/db2_query/tasks/init.rake +1 -1
  25. data/lib/db2_query/tasks/initializer.rake +2 -34
  26. data/lib/db2_query/tasks/templates/database.rb.tt +19 -0
  27. data/lib/db2_query/tasks/templates/initializer.rb.tt +8 -0
  28. data/lib/db2_query/type/binary.rb +19 -0
  29. data/lib/db2_query/type/boolean.rb +41 -0
  30. data/lib/db2_query/type/date.rb +34 -0
  31. data/lib/db2_query/type/decimal.rb +15 -0
  32. data/lib/db2_query/type/integer.rb +15 -0
  33. data/lib/db2_query/type/string.rb +30 -0
  34. data/lib/db2_query/type/text.rb +11 -0
  35. data/lib/db2_query/type/time.rb +30 -0
  36. data/lib/db2_query/type/timestamp.rb +30 -0
  37. data/lib/db2_query/type/value.rb +29 -0
  38. data/lib/db2_query/version.rb +2 -2
  39. data/lib/rails/generators/query/USAGE +15 -0
  40. data/lib/rails/generators/query/query_generator.rb +70 -0
  41. data/lib/rails/generators/query/templates/query.rb.tt +26 -0
  42. data/lib/rails/generators/query/templates/query_definitions.rb.tt +12 -0
  43. data/lib/rails/generators/query/templates/unit_test.rb.tt +9 -0
  44. metadata +62 -49
  45. data/lib/db2_query/connection.rb +0 -163
  46. data/lib/db2_query/connection_handling.rb +0 -112
  47. data/lib/db2_query/database_statements.rb +0 -93
  48. data/lib/db2_query/formatter.rb +0 -27
  49. data/lib/db2_query/odbc_connector.rb +0 -40
@@ -3,18 +3,16 @@
3
3
  require "db2_query"
4
4
  require "rails"
5
5
 
6
- module DB2Query
7
- class Railtie < Rails::Railtie
6
+ module Db2Query
7
+ class Railtie < ::Rails::Railtie
8
8
  railtie_name :db2_query
9
9
 
10
10
  rake_tasks do
11
- path = File.expand_path(__dir__)
12
- Dir.glob("#{path}/tasks/*.rake").each { |f| load f }
11
+ Dir.glob("#{Db2Query.root}/db2_query/tasks/*.rake").each { |f| load f }
13
12
  end
14
13
 
15
- initializer "db2_query.database_initialization" do
16
- DB2Query::Base.configurations = DB2Query.config
17
- DB2Query::Base.establish_connection :primary
14
+ config.app_generators do
15
+ require "#{Db2Query.root}/rails/generators/query/query_generator.rb"
18
16
  end
19
17
  end
20
18
  end
@@ -1,69 +1,89 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module DB2Query
3
+ module Db2Query
4
4
  class Result < ActiveRecord::Result
5
- attr_reader :formatters
5
+ attr_reader :definition
6
6
 
7
- def initialize(columns, rows, formatters = {}, column_types = {})
8
- @formatters = formatters
9
- super(columns, rows, column_types)
7
+ alias query definition
8
+
9
+ delegate :data_type, :validate_result_columns, to: :definition
10
+
11
+ def initialize(columns, rows, definition)
12
+ @definition = definition
13
+ validate_result_columns(columns)
14
+ super(columns, rows, {})
15
+ end
16
+
17
+ def record
18
+ records.first
10
19
  end
11
20
 
12
21
  def records
13
- @records ||= rows.map do |row|
14
- Record.new(row, columns, formatters)
15
- end
22
+ @records ||= rows.map { |row| new_record(row) }
16
23
  end
17
24
 
18
25
  def to_h
19
26
  rows.map do |row|
20
- columns.zip(row).each_with_object({}) { |cr, h| h[cr[0].to_sym] = cr[1] }
27
+ index, hash = [0, {}]
28
+ while index < columns.length
29
+ attr_name = columns[index].to_sym
30
+ hash[attr_name] = data_type(attr_name).deserialize(row[index])
31
+ index += 1
32
+ end
33
+ hash
21
34
  end
22
35
  end
23
36
 
24
37
  def inspect
25
38
  entries = records.take(11).map!(&:inspect)
26
-
27
39
  entries[10] = "..." if entries.size == 11
28
-
29
- "#<#{self.class.name} @records=[#{entries.join(', ')}]>"
40
+ "#<#{self.class.name} [#{entries.join(', ')}]>"
30
41
  end
31
42
 
32
43
  class Record
33
- attr_reader :formatters
44
+ attr_reader :definition
34
45
 
35
- def initialize(row, columns, formatters)
36
- @formatters = formatters
37
- columns.zip(row) do |col, val|
38
- column, value = format(col, val)
39
- singleton_class.class_eval { attr_accessor "#{column}" }
40
- send("#{column}=", value)
41
- end
46
+ delegate :data_type, to: :definition
47
+
48
+ def initialize(row, columns, definition)
49
+ @definition = definition
50
+ add_attributes(columns, row)
42
51
  end
43
52
 
44
53
  def inspect
45
54
  inspection = if defined?(instance_variables) && instance_variables
46
- instance_variables.reject { |var| var == :@formatters }.map do |attr|
47
- value = instance_variable_get(attr)
48
- "#{attr[1..-1]}: #{(value.kind_of? String) ? %Q{"#{value}"} : value}"
55
+ instance_variables.reject { |var| var == :@definition }.map do |attribute|
56
+ "#{attribute[1..-1]}: #{instance_variable_get(attribute)}"
49
57
  end.compact.join(", ")
50
58
  else
51
59
  "not initialized"
52
60
  end
53
-
54
61
  "#<Record #{inspection}>"
55
62
  end
56
63
 
57
64
  private
58
- def format(col, val)
59
- column = col.downcase
60
- format_name = formatters[column.to_sym]
61
- unless format_name.nil?
62
- formatter = DB2Query::Formatter.lookup(format_name)
63
- val = formatter.format(val)
65
+ def add_attributes(columns, row)
66
+ index = 0
67
+ while index < columns.length
68
+ column, value = [columns[index], row[index]]
69
+ class_eval { attr_accessor "#{column}" }
70
+ send("#{column}=", data_type(column).deserialize(value))
71
+ index += 1
64
72
  end
65
- [column, val]
66
73
  end
67
74
  end
75
+
76
+ private
77
+ def new_record(row)
78
+ Record.new(row, columns, definition)
79
+ end
80
+
81
+ def method_missing(method_name, *args, &block)
82
+ if record.respond_to?(method_name)
83
+ record.send(method_name)
84
+ else
85
+ super
86
+ end
87
+ end
68
88
  end
69
89
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Db2Query
4
+ module SqlStatement
5
+ def delete_sql?
6
+ sql.match?(/delete/i)
7
+ end
8
+
9
+ def insert_sql?
10
+ sql.match?(/insert/i)
11
+ end
12
+
13
+ def iud_sql?
14
+ sql.match?(/insert into|update|delete/i)
15
+ end
16
+
17
+ def db2_spec_sql
18
+ iud_sql? ? iud_spec_sql : sql
19
+ end
20
+
21
+ def table_name
22
+ insert_sql? ? sql.split("INTO ").last.split(" ").first : nil
23
+ end
24
+
25
+ private
26
+ def new_keys(raw_sql)
27
+ raw_sql.scan(/\$\S+/).map { |key| key.gsub!(/[$=,)]/, "").to_sym }
28
+ end
29
+
30
+ def iud_spec_sql
31
+ "SELECT * FROM #{delete_sql? ? "OLD" : "NEW"} TABLE (#{sql})"
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ module Db2Query
6
+ class Tasks < Thor::Group
7
+ include Thor::Actions
8
+
9
+ class << self
10
+ alias generate_file start
11
+ end
12
+ end
13
+
14
+ class DatabaseTask < Tasks
15
+ source_root File.expand_path("../tasks/templates", __FILE__)
16
+
17
+ def create_database_config_file
18
+ template "database.rb", File.join("config/db2query.yml")
19
+ end
20
+ end
21
+
22
+ class InitializerTask < Tasks
23
+ source_root File.expand_path("../tasks/templates", __FILE__)
24
+
25
+ def create_initializer_file
26
+ template "initializer.rb", File.join("config/initializers/db2query.rb")
27
+ end
28
+ end
29
+ end
@@ -1,58 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- DB2_QUERY_DATABASE_TEMPLATE ||= <<-EOF
4
- # frozen_string_literal: true
5
- # Database configuration example
6
- development:
7
- primary:
8
- adapter: db2_query
9
- dsn: iseries
10
- uid: <%= ENV["ISERIES_UID"] %>
11
- pwd: <%= ENV["ISERIES_PWD"] %>
12
- secondary:
13
- adapter: db2_query
14
- conn_string:
15
- driver: DB2
16
- database: ARUNIT2
17
- dbalias: ARUNIT2
18
- hostname: LOCALHOST
19
- currentschema: LIBTEST
20
- port: "0"
21
- protocol: IPC
22
- uid: <%= ENV["DB2EC_UID"] %>
23
- pwd: <%= ENV["DB2EC_PWD"] %>
24
- test:
25
- primary:
26
- adapter: db2_query
27
- dsn: iseries
28
- uid: <%= ENV["ISERIES_UID"] %>
29
- pwd: <%= ENV["ISERIES_PWD"] %>
30
- secondary:
31
- adapter: db2_query
32
- conn_string:
33
- driver: DB2
34
- database: ARUNIT2
35
- dbalias: ARUNIT2
36
- hostname: LOCALHOST
37
- currentschema: LIBTEST
38
- port: "0"
39
- protocol: IPC
40
- uid: <%= ENV["DB2EC_UID"] %>
41
- pwd: <%= ENV["DB2EC_PWD"] %>
42
- EOF
3
+ require "db2_query/tasks"
43
4
 
44
5
  namespace :db2query do
45
6
  desc "Create Database configuration file"
46
7
  task :database do
47
- database_path = "#{Rails.root}/config/db2query_database.yml"
48
- if File.exist?(database_path)
49
- raise ArgumentError, "File exists."
50
- else
51
- puts " Creating database config file ..."
52
- File.open(database_path, "w") do |file|
53
- file.puts DB2_QUERY_DATABASE_TEMPLATE
54
- end
55
- puts " File '#{database_path}' created."
56
- end
8
+ Db2Query::DatabaseTask.generate_file
57
9
  end
58
10
  end
@@ -3,7 +3,7 @@
3
3
  namespace :db2query do
4
4
  desc "Create Initializer and Database configuration file"
5
5
  task :init do
6
- Rake::Task["db2query:initializer"].invoke
7
6
  Rake::Task["db2query:database"].invoke
7
+ Rake::Task["db2query:initializer"].invoke
8
8
  end
9
9
  end
@@ -1,42 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- DB2_QUERY_INITIALIZER_TEMPLATE ||= <<-EOF
4
- # frozen_string_literal: true
5
-
6
- require "db2_query"
7
- require "db2_query/formatter"
8
-
9
- DB2Query::Base.initiation do |base|
10
- base.configurations = base.parent.config
11
- base.establish_connection ENV['RAILS_ENV'].to_sym
12
- end
13
-
14
- # Example
15
-
16
- class FirstNameFormatter < DB2Query::AbstractFormatter
17
- def format(value)
18
- "Dr." + value
19
- end
20
- end
21
-
22
- DB2Query::Formatter.registration do |format|
23
- format.register(:first_name_formatter, FirstNameFormatter)
24
- end
25
- EOF
3
+ require "db2_query/tasks"
26
4
 
27
5
  namespace :db2query do
28
6
  desc "Create Initializer file"
29
7
  task :initializer do
30
- # Create initializer file
31
- initializer_path = "#{Rails.root}/config/initializers/db2query.rb"
32
- if File.exist?(initializer_path)
33
- raise ArgumentError, "File exists."
34
- else
35
- puts " Creating initializer file ..."
36
- File.open(initializer_path, "w") do |file|
37
- file.puts DB2_QUERY_INITIALIZER_TEMPLATE
38
- end
39
- puts " File '#{initializer_path}' created."
40
- end
8
+ Db2Query::InitializerTask.generate_file
41
9
  end
42
10
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ development:
4
+ dsn: TODO
5
+ idle: 5
6
+ pool: 5
7
+ timeout: 5
8
+
9
+ test:
10
+ dsn: TODO
11
+ idle: 5
12
+ pool: 5
13
+ timeout: 5
14
+
15
+ production:
16
+ dsn: TODO
17
+ idle: 5
18
+ pool: 5
19
+ timeout: 5
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "db2_query"
4
+
5
+ Db2Query::Base.initiation do |base|
6
+ base.set_field_types
7
+ base.establish_connection
8
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Db2Query
4
+ module Type
5
+ class Binary
6
+ def type
7
+ :binary
8
+ end
9
+
10
+ def serialize(value)
11
+ value.unpack1("H*")
12
+ end
13
+
14
+ def deserialize(value)
15
+ [value].pack("H*")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Db2Query
4
+ module Type
5
+ class Boolean < Value
6
+ TRUE_VALUES = [
7
+ true, 1, "1", "t", "T",
8
+ "true", "TRUE", "on", "ON",
9
+ :"1", :t, :T, :true, :TRUE, :on, :ON
10
+ ].freeze
11
+
12
+ DEFAULT = { true: true, false: false }
13
+
14
+ def initialize(options = DEFAULT)
15
+ super(options)
16
+ end
17
+
18
+ def name
19
+ :boolean
20
+ end
21
+
22
+ def serialize(value)
23
+ case value
24
+ when *TRUE_VALUES
25
+ 1
26
+ else
27
+ 0
28
+ end
29
+ end
30
+
31
+ def deserialize(value)
32
+ case value
33
+ when 1
34
+ options[:true]
35
+ else
36
+ options[:false]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Db2Query
4
+ module Type
5
+ class Date < Value
6
+ def type
7
+ :string
8
+ end
9
+
10
+ YMD_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
11
+ DMY_DATE = /\A(\d\d)-(\d\d)-(\d{4})\z/
12
+
13
+ def serialize(value)
14
+ if value.is_a?(::String)
15
+ value = value.tr("/", "-")
16
+ case value
17
+ when YMD_DATE, DMY_DATE
18
+ quote(::Date.parse(value))
19
+ else
20
+ nil
21
+ end
22
+ elsif value.is_a?(::Date)
23
+ quote(value.strftime("%F"))
24
+ else
25
+ nil
26
+ end
27
+ end
28
+
29
+ def deserialize(value)
30
+ ::Date.parse(value.to_s)
31
+ end
32
+ end
33
+ end
34
+ end