logstash-integration-jdbc 5.4.11 → 5.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7604bb8967c9d63f585d14622ab18b70bc0d9e9b34e43bca6b6c59c9d05a6b76
4
- data.tar.gz: 2e9d142376d12bbd1313142e79174d540d53e098e481330262e784c8177e4898
3
+ metadata.gz: e155ca5542f41d749481a67cf65cf28ad194f019defe6368f765cd1a0ccf3860
4
+ data.tar.gz: 81cbc828cbbdecb5d3265c07f5777f68c3103252edbc772868c1aa8f1323b566
5
5
  SHA512:
6
- metadata.gz: 165749e33fed7d98b9635f6a1d74cdb05623563a3942d34c093ef761cd8e4f4784e6eb467a699909e5420ceef8fb4779c00e1b154845838052aa278a592ddc2a
7
- data.tar.gz: b9a4e7822ea60c3dde25edd6a1a6e72837069a993046a050a05aa32e92172d4689624df12e85c31b79f62c40fd0f45f98700e07a678a7ea2656d9730f2f14a8e
6
+ metadata.gz: 0d3f9f07bd92ff1c21f417795e20edbd5f78542181a00f4bfd770dd7f9fb1066df8bbec9af242126b13148049cc70f41190b5246104a23c549af6a62338807c1
7
+ data.tar.gz: 71c92b8dba18479be7d69f64b580d2bd99902d7d330fd1633997e8134c69403f640e1ba555a1b1640d6737de8b53c68d51e4cab75b4da82eeda7fbf549f72c0c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 5.5.0
2
+ - Feat: add support for SQL `DATE` columns to jdbc static and streaming filters [#171](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/171)
3
+
1
4
  ## 5.4.11
2
5
  - Fixes an issue in which any one instance of a JDBC input plugin using `jdbc_default_timezone` changes the behaviour of plugin instances that do _not_ use `jdbc_default_timezone`, ensuring that timezone offsets remain consistent for each instance of the plugin _as configured_ [#151](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/151)
3
6
  - Fixes an exception that could occur while reloading `jdbc_static` databases when the underlying connection to the remote has been broken [#165](https://github.com/logstash-plugins/logstash-integration-jdbc/pull/165)
@@ -1,10 +1,12 @@
1
1
  # encoding: utf-8
2
2
  require_relative "lookup_result"
3
3
  require "logstash/util/loggable"
4
+ require "logstash/plugin_mixins/jdbc/value_handler"
4
5
 
5
6
  module LogStash module Filters module Jdbc
6
7
  class Lookup
7
8
  include LogStash::Util::Loggable
9
+ include LogStash::PluginMixins::Jdbc::ValueHandler
8
10
 
9
11
  class Sprintfier
10
12
  def initialize(param)
@@ -134,15 +136,13 @@ module LogStash module Filters module Jdbc
134
136
 
135
137
  def load_data_from_local(local, query, params, result)
136
138
  local.fetch(query, params).each do |row|
137
- stringified = row.inject({}){|hash,(k,v)| hash[k.to_s] = v; hash} #Stringify row keys
138
- result.push(stringified)
139
+ result.push(extract_values_from(row))
139
140
  end
140
141
  end
141
142
 
142
143
  def load_data_from_prepared(_local, _query, params, result)
143
144
  @prepared_statement.call(params).each do |row|
144
- stringified = row.inject({}){|hash,(k,v)| hash[k.to_s] = v; hash} #Stringify row keys
145
- result.push(stringified)
145
+ result.push(extract_values_from(row))
146
146
  end
147
147
  end
148
148
 
@@ -6,6 +6,7 @@ require "date"
6
6
  require_relative "value_tracking"
7
7
  require_relative "timezone_proxy"
8
8
  require_relative "statement_handler"
9
+ require_relative "value_handler"
9
10
 
10
11
  java_import java.util.concurrent.locks.ReentrantLock
11
12
 
@@ -13,6 +14,7 @@ java_import java.util.concurrent.locks.ReentrantLock
13
14
  # for potential reuse in other plugins (input/output)
14
15
  module LogStash module PluginMixins module Jdbc
15
16
  module Jdbc
17
+ include LogStash::PluginMixins::Jdbc::ValueHandler
16
18
  # This method is called when someone includes this module
17
19
  def self.included(base)
18
20
  # Add these methods to the 'base' given.
@@ -252,25 +254,6 @@ module LogStash module PluginMixins module Jdbc
252
254
  row[@tracking_column.to_sym]
253
255
  end
254
256
  end
255
-
256
- private
257
- #Stringify row keys and decorate values when necessary
258
- def extract_values_from(row)
259
- Hash[row.map { |k, v| [k.to_s, decorate_value(v)] }]
260
- end
261
-
262
- private
263
- def decorate_value(value)
264
- case value
265
- when Time
266
- # transform it to LogStash::Timestamp as required by LS
267
- LogStash::Timestamp.new(value)
268
- when Date, DateTime
269
- LogStash::Timestamp.new(value.to_time)
270
- else
271
- value
272
- end
273
- end
274
257
  end
275
258
  end end end
276
259
 
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ require "time"
3
+ require "date"
4
+
5
+ module LogStash module PluginMixins module Jdbc
6
+ # Provides functions to extract the row's values, ensuring column types
7
+ # are properly decorated to become coercible to a LogStash::Event.
8
+ module ValueHandler
9
+ # Stringify the row keys and decorate values when necessary
10
+ def extract_values_from(row)
11
+ Hash[row.map { |k, v| [k.to_s, decorate_value(v)] }]
12
+ end
13
+
14
+ # Decorate the value so it can be used as a LogStash::Event field
15
+ def decorate_value(value)
16
+ case value
17
+ when Date, DateTime
18
+ value.to_time
19
+ else
20
+ value
21
+ end
22
+ end
23
+ end
24
+ end end end
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  require "logstash/util/loggable"
3
+ require "logstash/plugin_mixins/jdbc/value_handler"
3
4
 
4
5
  module LogStash module PluginMixins module JdbcStreaming
5
6
  # so as to not clash with the class of the same name and function in the jdbc input
@@ -7,6 +8,8 @@ module LogStash module PluginMixins module JdbcStreaming
7
8
  # this duplication can be removed in a universal plugin
8
9
 
9
10
  class StatementHandler
11
+ include LogStash::PluginMixins::Jdbc::ValueHandler
12
+
10
13
  def self.build_statement_handler(plugin)
11
14
  klass = plugin.use_prepared_statements ? PreparedStatementHandler : NormalStatementHandler
12
15
  klass.new(plugin)
@@ -86,7 +89,7 @@ module LogStash module PluginMixins module JdbcStreaming
86
89
  def execute_extract_records(db, params, result)
87
90
  dataset = db[statement, params] # returns a Sequel dataset
88
91
  dataset.all do |row|
89
- result.push row.inject({}){|hash,(k,v)| hash[k.to_s] = v; hash} # Stringify row keys
92
+ result.push extract_values_from(row)
90
93
  end
91
94
  end
92
95
 
@@ -113,7 +116,7 @@ module LogStash module PluginMixins module JdbcStreaming
113
116
  def execute_extract_records(db, params, result)
114
117
  records = db.call(name, params) # returns an array of hashes
115
118
  records.each do |row|
116
- result.push row.inject({}){|hash,(k,v)| hash[k.to_s] = v; hash} #Stringify row keys
119
+ result.push extract_values_from(row)
117
120
  end
118
121
  end
119
122
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-integration-jdbc'
3
- s.version = '5.4.11'
3
+ s.version = '5.5.0'
4
4
  s.licenses = ['Apache License (2.0)']
5
5
  s.summary = "Integration with JDBC - input and filter plugins"
6
6
  s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
@@ -116,6 +116,45 @@ module LogStash module Filters
116
116
  plugin.filter(event)
117
117
  expect(event.get("server")).to eq([{"ip"=>"10.3.1.1", "name"=>"mv-server-1", "location"=>"MV-9-6-4"}])
118
118
  end
119
+
120
+ context 'and record with temporal columns' do
121
+ let(:loader_statement) { "SELECT ip, name, location, entry_date, entry_time, timestamp FROM reference_table" }
122
+ let(:local_db_objects) do
123
+ [
124
+ {
125
+ "name" => "servers",
126
+ "columns" => [
127
+ %w[ip varchar(64)],
128
+ %w[name varchar(64)],
129
+ %w[location varchar(64)],
130
+ %w[entry_date date],
131
+ %w[entry_time time],
132
+ %w[timestamp timestamp]
133
+ ]
134
+ },
135
+ ]
136
+ end
137
+
138
+ before(:each) { plugin.register }
139
+
140
+ subject { event.get("server").first }
141
+
142
+ it "maps the DATE to a Logstash Timestamp" do
143
+ plugin.filter(event)
144
+ expect(subject['entry_date']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1)))
145
+ end
146
+
147
+ it "maps the TIME field to a Logstash Timestamp" do
148
+ plugin.filter(event)
149
+ now = DateTime.now
150
+ expect(subject['entry_time']).to eq(LogStash::Timestamp.new(Time.new(now.year, now.month, now.day, 10, 5, 0)))
151
+ end
152
+
153
+ it "maps the TIMESTAMP to a Logstash Timestamp" do
154
+ plugin.filter(event)
155
+ expect(subject['timestamp']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1, 1, 2, 3)))
156
+ end
157
+ end
119
158
  end
120
159
 
121
160
  context "under normal conditions when index_columns is not specified" do
@@ -63,7 +63,32 @@ module LogStash module Filters
63
63
  end
64
64
  end
65
65
 
66
- describe "In Prepared Statement mode, found record - uses row" do
66
+ describe 'found record with temporal columns' do
67
+ let(:idx) { 200 }
68
+ let(:statement) { "SELECT entry_date, entry_time, timestamp FROM reference_table WHERE ip = :ip" }
69
+
70
+ before(:each) { plugin.register }
71
+
72
+ subject { event.get("server").first }
73
+
74
+ it "maps the DATE to a Logstash Timestamp" do
75
+ plugin.filter(event)
76
+ expect(subject['entry_date']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1)))
77
+ end
78
+
79
+ it "maps the TIME field to a Logstash Timestamp" do
80
+ plugin.filter(event)
81
+ now = DateTime.now
82
+ expect(subject['entry_time']).to eq(LogStash::Timestamp.new(Time.new(now.year, now.month, now.day, 10, 5, 0)))
83
+ end
84
+
85
+ it "maps the TIMESTAMP to a Logstash Timestamp" do
86
+ plugin.filter(event)
87
+ expect(subject['timestamp']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1, 1, 2, 3)))
88
+ end
89
+ end
90
+
91
+ context 'prepared statement mode' do
67
92
  let(:idx) { 200 }
68
93
  let(:statement) { "SELECT name, location FROM reference_table WHERE ip = ?" }
69
94
  let(:settings) do
@@ -82,10 +107,37 @@ module LogStash module Filters
82
107
  "sequel_opts" => {"pool_timeout" => 600}
83
108
  }
84
109
  end
85
- it "fills in the target" do
86
- plugin.filter(event)
87
- expect(event.get("server")).to eq([{"name" => "ldn-server-#{idx}", "location" => "LDN-#{idx}-2-3"}])
88
- expect((event.get("tags") || []) & ["lookup_failed", "default_used_instead"]).to be_empty
110
+
111
+ describe "found record - uses row" do
112
+ it "fills in the target" do
113
+ plugin.filter(event)
114
+ expect(event.get("server")).to eq([{"name" => "ldn-server-#{idx}", "location" => "LDN-#{idx}-2-3"}])
115
+ expect((event.get("tags") || []) & ["lookup_failed", "default_used_instead"]).to be_empty
116
+ end
117
+ end
118
+
119
+ describe 'found record with temporal columns' do
120
+ let(:statement) { "SELECT entry_date, entry_time, timestamp FROM reference_table WHERE ip = ?" }
121
+
122
+ before(:each) { plugin.register }
123
+
124
+ subject { event.get("server").first }
125
+
126
+ it "maps the DATE to a Logstash Timestamp" do
127
+ plugin.filter(event)
128
+ expect(subject['entry_date']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1)))
129
+ end
130
+
131
+ it "maps the TIME field to a Logstash Timestamp" do
132
+ plugin.filter(event)
133
+ now = DateTime.now
134
+ expect(subject['entry_time']).to eq(LogStash::Timestamp.new(Time.new(now.year, now.month, now.day, 10, 5, 0)))
135
+ end
136
+
137
+ it "maps the TIMESTAMP to a Logstash Timestamp" do
138
+ plugin.filter(event)
139
+ expect(subject['timestamp']).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1, 1, 2, 3)))
140
+ end
89
141
  end
90
142
  end
91
143
 
@@ -66,6 +66,29 @@ describe LogStash::Inputs::Jdbc, :integration => true do
66
66
  expect(event.get('first_name')).to eq('David')
67
67
  end
68
68
  end
69
+
70
+ context 'with temporal columns' do
71
+ let(:settings) do
72
+ super().merge("statement" => 'SELECT ENTRY_DATE, ENTRY_TIME, TIMESTAMP FROM "employee" WHERE EMP_NO = 2')
73
+ end
74
+
75
+ before(:each) { plugin.run(queue) }
76
+
77
+ subject(:event) { queue.pop }
78
+
79
+ it "maps the DATE to a Logstash Timestamp" do
80
+ expect(event.get('entry_date')).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1)))
81
+ end
82
+
83
+ it "maps the TIME field to a Logstash Timestamp" do
84
+ now = DateTime.now
85
+ expect(event.get('entry_time')).to eq(LogStash::Timestamp.new(Time.new(now.year, now.month, now.day, 10, 5, 0)))
86
+ end
87
+
88
+ it "maps the TIMESTAMP to a Logstash Timestamp" do
89
+ expect(event.get('timestamp')).to eq(LogStash::Timestamp.new(Time.new(2003, 2, 1, 1, 2, 3)))
90
+ end
91
+ end
69
92
  end
70
93
 
71
94
  context "when supplying a non-existent library" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-integration-jdbc
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.4.11
4
+ version: 5.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-23 00:00:00.000000000 Z
11
+ date: 2024-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -17,8 +17,8 @@ dependencies:
17
17
  - !ruby/object:Gem::Version
18
18
  version: '0.3'
19
19
  name: jar-dependencies
20
- type: :development
21
20
  prerelease: false
21
+ type: :development
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
@@ -34,8 +34,8 @@ dependencies:
34
34
  - !ruby/object:Gem::Version
35
35
  version: '2.99'
36
36
  name: logstash-core-plugin-api
37
- type: :runtime
38
37
  prerelease: false
38
+ type: :runtime
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - ">="
@@ -51,8 +51,8 @@ dependencies:
51
51
  - !ruby/object:Gem::Version
52
52
  version: 6.5.0
53
53
  name: logstash-core
54
- type: :runtime
55
54
  prerelease: false
55
+ type: :runtime
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
@@ -65,8 +65,8 @@ dependencies:
65
65
  - !ruby/object:Gem::Version
66
66
  version: '0'
67
67
  name: logstash-codec-plain
68
- type: :runtime
69
68
  prerelease: false
69
+ type: :runtime
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - ">="
@@ -79,8 +79,8 @@ dependencies:
79
79
  - !ruby/object:Gem::Version
80
80
  version: 5.74.0
81
81
  name: sequel
82
- type: :runtime
83
82
  prerelease: false
83
+ type: :runtime
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - ">="
@@ -93,8 +93,8 @@ dependencies:
93
93
  - !ruby/object:Gem::Version
94
94
  version: '0'
95
95
  name: lru_redux
96
- type: :runtime
97
96
  prerelease: false
97
+ type: :runtime
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - ">="
@@ -107,8 +107,8 @@ dependencies:
107
107
  - !ruby/object:Gem::Version
108
108
  version: '0'
109
109
  name: tzinfo
110
- type: :runtime
111
110
  prerelease: false
111
+ type: :runtime
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - ">="
@@ -121,8 +121,8 @@ dependencies:
121
121
  - !ruby/object:Gem::Version
122
122
  version: '0'
123
123
  name: tzinfo-data
124
- type: :runtime
125
124
  prerelease: false
125
+ type: :runtime
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - ">="
@@ -135,8 +135,8 @@ dependencies:
135
135
  - !ruby/object:Gem::Version
136
136
  version: '1.3'
137
137
  name: logstash-mixin-ecs_compatibility_support
138
- type: :runtime
139
138
  prerelease: false
139
+ type: :runtime
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
@@ -149,8 +149,8 @@ dependencies:
149
149
  - !ruby/object:Gem::Version
150
150
  version: '1.0'
151
151
  name: logstash-mixin-validator_support
152
- type: :runtime
153
152
  prerelease: false
153
+ type: :runtime
154
154
  version_requirements: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - "~>"
@@ -163,8 +163,8 @@ dependencies:
163
163
  - !ruby/object:Gem::Version
164
164
  version: '1.0'
165
165
  name: logstash-mixin-event_support
166
- type: :runtime
167
166
  prerelease: false
167
+ type: :runtime
168
168
  version_requirements: !ruby/object:Gem::Requirement
169
169
  requirements:
170
170
  - - "~>"
@@ -177,8 +177,8 @@ dependencies:
177
177
  - !ruby/object:Gem::Version
178
178
  version: '1.0'
179
179
  name: logstash-mixin-scheduler
180
- type: :runtime
181
180
  prerelease: false
181
+ type: :runtime
182
182
  version_requirements: !ruby/object:Gem::Requirement
183
183
  requirements:
184
184
  - - "~>"
@@ -191,8 +191,8 @@ dependencies:
191
191
  - !ruby/object:Gem::Version
192
192
  version: '0'
193
193
  name: childprocess
194
- type: :development
195
194
  prerelease: false
195
+ type: :development
196
196
  version_requirements: !ruby/object:Gem::Requirement
197
197
  requirements:
198
198
  - - ">="
@@ -205,8 +205,8 @@ dependencies:
205
205
  - !ruby/object:Gem::Version
206
206
  version: '2.3'
207
207
  name: logstash-devutils
208
- type: :development
209
208
  prerelease: false
209
+ type: :development
210
210
  version_requirements: !ruby/object:Gem::Requirement
211
211
  requirements:
212
212
  - - ">="
@@ -219,8 +219,8 @@ dependencies:
219
219
  - !ruby/object:Gem::Version
220
220
  version: '0'
221
221
  name: timecop
222
- type: :development
223
222
  prerelease: false
223
+ type: :development
224
224
  version_requirements: !ruby/object:Gem::Requirement
225
225
  requirements:
226
226
  - - ">="
@@ -266,6 +266,7 @@ files:
266
266
  - lib/logstash/plugin_mixins/jdbc/sequel_bootstrap.rb
267
267
  - lib/logstash/plugin_mixins/jdbc/statement_handler.rb
268
268
  - lib/logstash/plugin_mixins/jdbc/timezone_proxy.rb
269
+ - lib/logstash/plugin_mixins/jdbc/value_handler.rb
269
270
  - lib/logstash/plugin_mixins/jdbc/value_tracking.rb
270
271
  - lib/logstash/plugin_mixins/jdbc_streaming.rb
271
272
  - lib/logstash/plugin_mixins/jdbc_streaming/cache_payload.rb
@@ -323,7 +324,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
323
324
  - !ruby/object:Gem::Version
324
325
  version: '0'
325
326
  requirements: []
326
- rubygems_version: 3.3.26
327
+ rubygems_version: 3.2.33
327
328
  signing_key:
328
329
  specification_version: 4
329
330
  summary: Integration with JDBC - input and filter plugins