logstash-filter-jdbc_static 1.0.7 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/docs/index.asciidoc +24 -10
- data/lib/logstash/filters/jdbc/lookup.rb +73 -13
- data/lib/logstash/filters/jdbc/lookup_processor.rb +10 -0
- data/lib/logstash/filters/jdbc/read_write_database.rb +7 -0
- data/lib/logstash/filters/jdbc_static.rb +7 -2
- data/logstash-filter-jdbc_static.gemspec +1 -1
- data/spec/filters/integration/jdbc_static_spec.rb +34 -0
- data/spec/filters/jdbc/lookup_spec.rb +124 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d482ab05b8b7e9904183077976c33624b4cdd396d5701cd4db5d501772e7f33
|
4
|
+
data.tar.gz: f0168f06b31172b98c843e788ffbba5d97f9904726244c293de280f63effa56b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 723f1e3cd20a3cbe703bd9894f8036237ce22f39702cd6e4a750c9d5c289fad9c8249243ae51f13b4cc1400ae0171dea534c791e60f2694bd917b2e69f48220a
|
7
|
+
data.tar.gz: 4c7a55addf3ed97394ec533e0c86707b7151aee333ced400d5e546ac5482ef6e8e68bcfc658a04a6faf021e0a64249db801d5b351677505cf118b52822888ced
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
## 1.1.0
|
2
|
+
- Added prepared statement support in local lookups [#53](https://github.com/logstash-plugins/logstash-filter-jdbc_static/pull/53)
|
3
|
+
|
1
4
|
## 1.0.7
|
2
5
|
- Fixed issue with driver verification using Java 11 [#51](https://github.com/logstash-plugins/logstash-filter-jdbc_static/pull/51)
|
3
6
|
|
data/docs/index.asciidoc
CHANGED
@@ -101,21 +101,21 @@ filter {
|
|
101
101
|
local_lookups => [ <3>
|
102
102
|
{
|
103
103
|
id => "local-servers"
|
104
|
-
query => "
|
104
|
+
query => "SELECT descr as description FROM servers WHERE ip = :ip"
|
105
105
|
parameters => {ip => "[from_ip]"}
|
106
106
|
target => "server"
|
107
107
|
},
|
108
108
|
{
|
109
109
|
id => "local-users"
|
110
|
-
query => "
|
111
|
-
|
112
|
-
target => "user" <
|
110
|
+
query => "SELECT firstname, lastname FROM users WHERE userid = ? AND country = ?"
|
111
|
+
prepared_parameters => ["[loggedin_userid]", "[user_nation]"] <4>
|
112
|
+
target => "user" <5>
|
113
113
|
}
|
114
114
|
]
|
115
115
|
# using add_field here to add & rename values to the event root
|
116
|
-
add_field => { server_name => "%{[server][0][description]}" }
|
117
|
-
add_field => { user_firstname => "%{[user][0][firstname]}" }
|
118
|
-
add_field => { user_lastname => "%{[user][0][lastname]}" }
|
116
|
+
add_field => { server_name => "%{[server][0][description]}" } <6>
|
117
|
+
add_field => { user_firstname => "%{[user][0][firstname]}" }
|
118
|
+
add_field => { user_lastname => "%{[user][0][lastname]}" }
|
119
119
|
remove_field => ["server", "user"]
|
120
120
|
staging_directory => "/tmp/logstash/jdbc_static/import_data"
|
121
121
|
loader_schedule => "* */2 * * *" # run loaders every 2 hours
|
@@ -134,9 +134,11 @@ structure. The column names and types should match the external database.
|
|
134
134
|
The order of table definitions is significant and should match that of the loader queries.
|
135
135
|
See <<plugins-{type}s-{plugin}-object_order>>.
|
136
136
|
<3> Performs lookup queries on the local database to enrich the events.
|
137
|
-
<4>
|
137
|
+
<4> Local lookup queries can also use prepared statements where the parameters
|
138
|
+
follow the positional ordering.
|
139
|
+
<5> Specifies the event field that will store the looked-up data. If the lookup
|
138
140
|
returns multiple columns, the data is stored as a JSON object within the field.
|
139
|
-
<
|
141
|
+
<6> Takes data from the JSON object and stores it in top-level event fields for
|
140
142
|
easier analysis in Kibana.
|
141
143
|
|
142
144
|
Here's a full example:
|
@@ -546,7 +548,9 @@ default id is used instead.
|
|
546
548
|
query::
|
547
549
|
A SQL SELECT statement that is executed to achieve the lookup. To use
|
548
550
|
parameters, use named parameter syntax, for example
|
549
|
-
`"SELECT * FROM MYTABLE WHERE ID = :id"`.
|
551
|
+
`"SELECT * FROM MYTABLE WHERE ID = :id"`. Alternatively, the `?` sign
|
552
|
+
can be used as a prepared statement parameter, in which case
|
553
|
+
the `prepared_parameters` array is used to populate the values
|
550
554
|
|
551
555
|
parameters::
|
552
556
|
A key/value Hash or dictionary. The key (LHS) is the text that is
|
@@ -563,6 +567,16 @@ an id and a location, and you have a table of sensors that have a
|
|
563
567
|
column of `id-loc_id`. In this case your parameter hash would look
|
564
568
|
like this: `parameters => { "p1" => "%{[id]}-%{[loc_id]}" }`.
|
565
569
|
|
570
|
+
prepared_parameters::
|
571
|
+
An Array, where the position is related to the position of the `?` in
|
572
|
+
the query syntax. The values of array follow the same semantic of `parameters`.
|
573
|
+
If `prepared_parameters` is valorized the filter is forced to use JDBC's
|
574
|
+
prepared statement to query the local database.
|
575
|
+
Prepared statements provides two benefits: one on the performance side, because
|
576
|
+
avoid the DBMS to parse and compile the SQL expression for every call;
|
577
|
+
the other benefit is on the security side, using prepared statements
|
578
|
+
avoid SQL-injection attacks based on query string concatenation.
|
579
|
+
|
566
580
|
target::
|
567
581
|
An optional name for the field that will receive the looked-up data.
|
568
582
|
If you omit this setting then the `id` setting (or the default id) is
|
@@ -63,6 +63,8 @@ module LogStash module Filters module Jdbc
|
|
63
63
|
@valid = false
|
64
64
|
@option_errors = []
|
65
65
|
@default_result = nil
|
66
|
+
@prepared_statement = nil
|
67
|
+
@symbol_parameters = nil
|
66
68
|
parse_options
|
67
69
|
end
|
68
70
|
|
@@ -79,8 +81,11 @@ module LogStash module Filters module Jdbc
|
|
79
81
|
end
|
80
82
|
|
81
83
|
def enhance(local, event)
|
82
|
-
|
83
|
-
|
84
|
+
if @prepared_statement
|
85
|
+
result = call_prepared(local, event)
|
86
|
+
else
|
87
|
+
result = fetch(local, event) # should return a LookupResult
|
88
|
+
end
|
84
89
|
if result.failed? || result.parameters_invalid?
|
85
90
|
tag_failure(event)
|
86
91
|
end
|
@@ -98,6 +103,17 @@ module LogStash module Filters module Jdbc
|
|
98
103
|
end
|
99
104
|
end
|
100
105
|
|
106
|
+
def use_prepared_statement?
|
107
|
+
@prepared_parameters && !@prepared_parameters.empty?
|
108
|
+
end
|
109
|
+
|
110
|
+
def prepare(local)
|
111
|
+
hash = {}
|
112
|
+
@prepared_parameters.each_with_index { |v, i| hash[:"$p#{i}"] = v }
|
113
|
+
@prepared_param_placeholder_map = hash
|
114
|
+
@prepared_statement = local.prepare(query, hash.keys)
|
115
|
+
end
|
116
|
+
|
101
117
|
private
|
102
118
|
|
103
119
|
def tag_failure(event)
|
@@ -139,6 +155,33 @@ module LogStash module Filters module Jdbc
|
|
139
155
|
result
|
140
156
|
end
|
141
157
|
|
158
|
+
def call_prepared(local, event)
|
159
|
+
result = LookupResult.new()
|
160
|
+
if @parameters_specified
|
161
|
+
params = prepare_parameters_from_event(event, result)
|
162
|
+
if result.parameters_invalid?
|
163
|
+
logger.warn? && logger.warn("Parameter field not found in event", :lookup_id => @id, :invalid_parameters => result.invalid_parameters)
|
164
|
+
return result
|
165
|
+
end
|
166
|
+
else
|
167
|
+
params = {}
|
168
|
+
end
|
169
|
+
begin
|
170
|
+
logger.debug? && logger.debug("Executing Jdbc query", :lookup_id => @id, :statement => query, :parameters => params)
|
171
|
+
@prepared_statement.call(params).each do |row|
|
172
|
+
stringified = row.inject({}){|hash,(k,v)| hash[k.to_s] = v; hash} #Stringify row keys
|
173
|
+
result.push(stringified)
|
174
|
+
end
|
175
|
+
rescue ::Sequel::Error => e
|
176
|
+
# all sequel errors are a subclass of this, let all other standard or runtime errors bubble up
|
177
|
+
result.failed!
|
178
|
+
logger.warn? && logger.warn("Exception when executing Jdbc query", :lookup_id => @id, :exception => e.message, :backtrace => e.backtrace.take(8))
|
179
|
+
end
|
180
|
+
# if either of: no records or a Sequel exception occurs the payload is
|
181
|
+
# empty and the default can be substituted later.
|
182
|
+
result
|
183
|
+
end
|
184
|
+
|
142
185
|
def process_event(event, result)
|
143
186
|
# use deep clone here so other filter function don't taint the payload by reference
|
144
187
|
event.set(@target, ::LogStash::Util.deep_clone(result.payload))
|
@@ -162,17 +205,34 @@ module LogStash module Filters module Jdbc
|
|
162
205
|
@option_errors << "The options for '#{@id}' must include a 'query' string"
|
163
206
|
end
|
164
207
|
|
165
|
-
@parameters
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
208
|
+
if @options["parameters"] && @options["prepared_parameters"]
|
209
|
+
@option_errors << "Can't specify 'parameters' and 'prepared_parameters' in the same lookup"
|
210
|
+
else
|
211
|
+
@parameters = @options["parameters"]
|
212
|
+
@prepared_parameters = @options["prepared_parameters"]
|
213
|
+
@parameters_specified = false
|
214
|
+
if @parameters
|
215
|
+
if !@parameters.is_a?(Hash)
|
216
|
+
@option_errors << "The 'parameters' option for '#{@id}' must be a Hash"
|
217
|
+
else
|
218
|
+
# this is done once per lookup at start, i.e. Sprintfier.new et.al is done once.
|
219
|
+
@symbol_parameters = @parameters.inject({}) {|hash,(k,v)| hash[k.to_sym] = sprintf_or_get(v) ; hash }
|
220
|
+
# the user might specify an empty hash parameters => {}
|
221
|
+
# maybe due to an unparameterised query
|
222
|
+
@parameters_specified = !@symbol_parameters.empty?
|
223
|
+
end
|
224
|
+
elsif @prepared_parameters
|
225
|
+
if !@prepared_parameters.is_a?(Array)
|
226
|
+
@option_errors << "The 'prepared_parameters' option for '#{@id}' must be an Array"
|
227
|
+
elsif @query.count("?") != @prepared_parameters.size
|
228
|
+
@option_errors << "The 'prepared_parameters' option for '#{@id}' doesn't match count with query's placeholder"
|
229
|
+
else
|
230
|
+
#prepare the map @symbol_parameters :n => sprintf_or_get
|
231
|
+
hash = {}
|
232
|
+
@prepared_parameters.each_with_index {|v,i| hash[:"p#{i}"] = sprintf_or_get(v)}
|
233
|
+
@symbol_parameters = hash
|
234
|
+
@parameters_specified = !@prepared_parameters.empty?
|
235
|
+
end
|
176
236
|
end
|
177
237
|
end
|
178
238
|
|
@@ -38,6 +38,8 @@ module LogStash module Filters module Jdbc
|
|
38
38
|
"lookup_jdbc_driver_class",
|
39
39
|
"lookup_jdbc_driver_library").compact)
|
40
40
|
@local.connect(CONNECTION_ERROR_MSG)
|
41
|
+
|
42
|
+
create_prepared_statements_for_lookups
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
@@ -60,6 +62,14 @@ module LogStash module Filters module Jdbc
|
|
60
62
|
|
61
63
|
private
|
62
64
|
|
65
|
+
def create_prepared_statements_for_lookups()
|
66
|
+
@lookups.each do |lookup|
|
67
|
+
if lookup.use_prepared_statement?
|
68
|
+
lookup.prepare(@local)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
63
73
|
def validate_lookups(lookups_errors = [])
|
64
74
|
ids = Hash.new(0)
|
65
75
|
errors = []
|
@@ -27,6 +27,13 @@ module LogStash module Filters module Jdbc
|
|
27
27
|
@rwlock.readLock().unlock()
|
28
28
|
end
|
29
29
|
|
30
|
+
def prepare(statement, parameters)
|
31
|
+
@rwlock.readLock().lock()
|
32
|
+
@db[statement, parameters].prepare(:select, @id)
|
33
|
+
ensure
|
34
|
+
@rwlock.readLock().unlock()
|
35
|
+
end
|
36
|
+
|
30
37
|
def build_db_object(db_object)
|
31
38
|
begin
|
32
39
|
@rwlock.writeLock().lock()
|
@@ -60,14 +60,19 @@ module LogStash module Filters class JdbcStatic < LogStash::Filters::Base
|
|
60
60
|
# For example:
|
61
61
|
# local_lookups => [
|
62
62
|
# {
|
63
|
-
# "query" => "
|
63
|
+
# "query" => "SELECT * FROM country WHERE code = :code",
|
64
64
|
# "parameters" => {"code" => "country_code"}
|
65
65
|
# "target" => "country_details"
|
66
66
|
# },
|
67
67
|
# {
|
68
|
-
# "query" => "
|
68
|
+
# "query" => "SELECT ip, name FROM servers WHERE ip LIKE :ip",
|
69
69
|
# "parameters" => {"ip" => "%{[response][ip]}%"}
|
70
70
|
# "target" => "servers"
|
71
|
+
# },
|
72
|
+
# {
|
73
|
+
# "query" => "SELECT ip, name FROM servers WHERE ip = ?",
|
74
|
+
# "prepared_parameters" => ["from_ip"]
|
75
|
+
# "target" => "servers"
|
71
76
|
# }
|
72
77
|
# ]
|
73
78
|
config :local_lookups, :required => true, :validate => [LogStash::Filters::Jdbc::LookupProcessor]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-filter-jdbc_static'
|
3
|
-
s.version = '1.0
|
3
|
+
s.version = '1.1.0'
|
4
4
|
s.licenses = ['Apache-2.0']
|
5
5
|
s.summary = "This filter executes a SQL query to fetch a SQL query result, store it locally then use a second SQL query to update an event."
|
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"
|
@@ -83,6 +83,40 @@ module LogStash module Filters
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
+
context "under normal conditions with prepared statement" do
|
87
|
+
let(:lookup_statement) { "SELECT * FROM servers WHERE ip LIKE ?" }
|
88
|
+
let(:settings) do
|
89
|
+
{
|
90
|
+
"jdbc_user" => ENV['USER'],
|
91
|
+
"jdbc_driver_class" => "org.postgresql.Driver",
|
92
|
+
"jdbc_driver_library" => "/usr/share/logstash/postgresql.jar",
|
93
|
+
"staging_directory" => temp_import_path_plugin,
|
94
|
+
"jdbc_connection_string" => jdbc_connection_string,
|
95
|
+
"loaders" => [
|
96
|
+
{
|
97
|
+
"id" =>"servers",
|
98
|
+
"query" => loader_statement,
|
99
|
+
"local_table" => "servers"
|
100
|
+
}
|
101
|
+
],
|
102
|
+
"local_db_objects" => local_db_objects,
|
103
|
+
"local_lookups" => [
|
104
|
+
{
|
105
|
+
"query" => lookup_statement,
|
106
|
+
"prepared_parameters" => [parameters_rhs],
|
107
|
+
"target" => "server"
|
108
|
+
}
|
109
|
+
]
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
it "enhances an event" do
|
114
|
+
plugin.register
|
115
|
+
plugin.filter(event)
|
116
|
+
expect(event.get("server")).to eq([{"ip"=>"10.3.1.1", "name"=>"mv-server-1", "location"=>"MV-9-6-4"}])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
86
120
|
context "under normal conditions when index_columns is not specified" do
|
87
121
|
let(:local_db_objects) do
|
88
122
|
[
|
@@ -44,6 +44,27 @@ module LogStash module Filters module Jdbc
|
|
44
44
|
result = described_class.find_validation_errors([lookup_hash])
|
45
45
|
expect(result).to eq("The 'parameters' option for 'lookup-1' must be a Hash")
|
46
46
|
end
|
47
|
+
|
48
|
+
it "parameters and prepared_parameters are defined at same time" do
|
49
|
+
lookup_hash = {
|
50
|
+
"query" => "SELECT * FROM table WHERE ip=?",
|
51
|
+
"parameters" => {"ip" => "%%{[ip]}"},
|
52
|
+
"prepared_parameters" => ["%%{[ip]}"],
|
53
|
+
"target" => "server"
|
54
|
+
}
|
55
|
+
result = described_class.find_validation_errors([lookup_hash])
|
56
|
+
expect(result).to eq("Can't specify 'parameters' and 'prepared_parameters' in the same lookup")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "prepared_parameters count doesn't match the number of '?' in the query" do
|
60
|
+
lookup_hash = {
|
61
|
+
"query" => "SELECT * FROM table WHERE ip=? AND host=?",
|
62
|
+
"prepared_parameters" => ["%%{[ip]}"],
|
63
|
+
"target" => "server"
|
64
|
+
}
|
65
|
+
result = described_class.find_validation_errors([lookup_hash])
|
66
|
+
expect(result).to eq("The 'prepared_parameters' option for 'lookup-1' doesn't match count with query's placeholder")
|
67
|
+
end
|
47
68
|
end
|
48
69
|
|
49
70
|
context "when supplied with a valid arg" do
|
@@ -124,6 +145,109 @@ module LogStash module Filters module Jdbc
|
|
124
145
|
expect(event.get("server")).to eq(records)
|
125
146
|
end
|
126
147
|
end
|
148
|
+
|
149
|
+
describe "lookup operations with prepared statement" do
|
150
|
+
let(:local_db) { double("local_db") }
|
151
|
+
let(:lookup_hash) do
|
152
|
+
{
|
153
|
+
"query" => "select * from servers WHERE ip LIKE ?",
|
154
|
+
"prepared_parameters" => ["%%{[ip]}"],
|
155
|
+
"target" => "server",
|
156
|
+
"tag_on_failure" => ["_jdbcstaticfailure_server"]
|
157
|
+
}
|
158
|
+
end
|
159
|
+
let(:event) { LogStash::Event.new()}
|
160
|
+
let(:records) { [{"name" => "ldn-1-23", "rack" => "2:1:6"}] }
|
161
|
+
let(:prepared_statement) { double("prepared_statement")}
|
162
|
+
|
163
|
+
subject(:lookup) { described_class.new(lookup_hash, {}, "lookup-1") }
|
164
|
+
|
165
|
+
before(:each) do
|
166
|
+
allow(local_db).to receive(:prepare).once.and_return(prepared_statement)
|
167
|
+
allow(prepared_statement).to receive(:call).once.and_return(records)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should be valid" do
|
171
|
+
expect(subject.valid?).to be_truthy
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should have no formatted_errors" do
|
175
|
+
expect(subject.formatted_errors).to eq("")
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should enhance an event" do
|
179
|
+
event.set("ip", "20.20")
|
180
|
+
subject.prepare(local_db)
|
181
|
+
subject.enhance(local_db, event)
|
182
|
+
expect(event.get("tags")).to be_nil
|
183
|
+
expect(event.get("server")).to eq(records)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe "lookup operations with prepared statement multiple parameters" do
|
188
|
+
let(:local_db) { double("local_db") }
|
189
|
+
let(:lookup_hash) do
|
190
|
+
{
|
191
|
+
"query" => "select * from servers WHERE ip LIKE ? AND os LIKE ?",
|
192
|
+
"prepared_parameters" => ["%%{[ip]}", "os"],
|
193
|
+
"target" => "server",
|
194
|
+
"tag_on_failure" => ["_jdbcstaticfailure_server"]
|
195
|
+
}
|
196
|
+
end
|
197
|
+
let(:event) { LogStash::Event.new()}
|
198
|
+
let(:records) { [{"name" => "ldn-1-23", "rack" => "2:1:6"}] }
|
199
|
+
let(:prepared_statement) { double("prepared_statement")}
|
200
|
+
|
201
|
+
subject(:lookup) { described_class.new(lookup_hash, {}, "lookup-1") }
|
202
|
+
|
203
|
+
before(:each) do
|
204
|
+
allow(local_db).to receive(:prepare).once.and_return(prepared_statement)
|
205
|
+
allow(prepared_statement).to receive(:call).once.and_return(records)
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should be valid" do
|
209
|
+
expect(subject.valid?).to be_truthy
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should have no formatted_errors" do
|
213
|
+
expect(subject.formatted_errors).to eq("")
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should enhance an event" do
|
217
|
+
event.set("ip", "20.20")
|
218
|
+
event.set("os", "MacOS")
|
219
|
+
subject.prepare(local_db)
|
220
|
+
subject.enhance(local_db, event)
|
221
|
+
expect(event.get("tags")).to be_nil
|
222
|
+
expect(event.get("server")).to eq(records)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "lookup operations with badly configured prepared statement" do
|
227
|
+
let(:local_db) { double("local_db") }
|
228
|
+
let(:lookup_hash) do
|
229
|
+
{
|
230
|
+
"query" => "select * from servers WHERE ip LIKE ? AND os LIKE ?",
|
231
|
+
"prepared_parameters" => ["%%{[ip]}"],
|
232
|
+
"target" => "server",
|
233
|
+
"tag_on_failure" => ["_jdbcstaticfailure_server"]
|
234
|
+
}
|
235
|
+
end
|
236
|
+
let(:event) { LogStash::Event.new()}
|
237
|
+
let(:records) { [{"name" => "ldn-1-23", "rack" => "2:1:6"}] }
|
238
|
+
let(:prepared_statement) { double("prepared_statement")}
|
239
|
+
|
240
|
+
subject(:lookup) { described_class.new(lookup_hash, {}, "lookup-1") }
|
241
|
+
|
242
|
+
before(:each) do
|
243
|
+
allow(local_db).to receive(:prepare).once.and_return(prepared_statement)
|
244
|
+
allow(prepared_statement).to receive(:call).once.and_return(records)
|
245
|
+
end
|
246
|
+
|
247
|
+
it "must not be valid" do
|
248
|
+
expect(subject.valid?).to be_falsey
|
249
|
+
end
|
250
|
+
end
|
127
251
|
end
|
128
252
|
end end end
|
129
253
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-filter-jdbc_static
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|