我在nfsen的Events插件中有一个子程序,它应该解析一个请求并根据它生成一个sql查询。这是生成WHERE
子句的子:
sub _get_where_clause ($) {
my $opts = shift;
my $condition = "";
my %importance = (
'Source'=>'1',
'Destination'=>'2',
'botnet_id'=>'3',
'Reporter'=>'4'
);
my $paramid = '5';
my @qparams;
my $true_condition = "";
my $null_condition = "";
my $true_condition_end = "";
_DEBUG("_get_where_clause start...");
while (my ($name, $oper) = each(%$opts)) {
_DEBUG("_get_where_clause. name: ".$name." oper: ".$oper);
if (_is_fixed_field($name)) {
_DEBUG("XXX fixed!");
if (ref $oper ne 'ARRAY') {
_DEBUG("XXX not an array!");
$oper=[$oper];
}
foreach my $op (@$oper) {
next if ($op !~ m/^\s*\[(\w+)\](.*)/);
_DEBUG("XXX ".$op."got matched as: ".$1);
my $op = $1;
next if (!_contains($op, \@select_oper));
my $value = $2;
_DEBUG("XXX second match: ".$2);
my $clause;
if ($op eq "null") {
$clause="$name IS NULL";
} else {
$value="\"$value\"" if ($fixed_fields{$name} eq "String");
$clause = "$name".$select_conv{$op}."$value";
}
_DEBUG("XXX clause so far: ".$clause);
$condition .= (($condition eq "")?" WHERE ":" AND ").$clause;
_DEBUG("XXX condition so far :".$condition);
}
} else {
_DEBUG("XXX Not fixed!");
if (ref $oper ne 'ARRAY') {
$oper=[$oper];
}
foreach my $op (@$oper) {
next if ($op !~ m/^\s*\[(\w+)\](.*)/);
_DEBUG("XXX ".$op."got matched as: ".$1);
my $op = $1;
next if (!_contains($op, \@select_oper));
my $value = $2;
if ($op eq "null") {
_DEBUG("XXX equals null!");
$null_condition .=
((!$null_condition)?((!$condition)?" WHERE":" AND")." event_id NOT IN ( SELECT event_id FROM attributes WHERE ":" OR "
)."Name=\"$name\"";
_DEBUG("XXX null condition: ".$null_condition);
} else {
if ($op eq "eq") {
$value="\"$value\"";
}
# insert query params to temp array
_DEBUG("importance of ".$name.": ".$importance{$name});
if($importance{$name} gt 0) {
my $i = $importance{$name};
$qparams[$i] = "Name=\"$name\" AND Value".$select_conv{$op}.$value;
_DEBUG("added qparam with importance");
} else {
$qparams[$paramid] = "Name=\"$name\" AND Value".$select_conv{$op}.$value;
_DEBUG("added qparam without importance. nr: ".$paramid);
$paramid++;
}
}
}
}
}
问题出现在这里:
$null_condition .=
((!$null_condition)?((!$condition)?" WHERE":" AND")." event_id NOT IN ( SELECT event_id FROM attributes WHERE ":" OR "
)."Name=\"$name\"";
即使此时$condition
显然不为空(从日志中可以看出),代码仍会附加WHERE
而不是AND
,从而导致包含两个WHERE
的语句} s,然后产生MySQL语法错误。
日志:
Aug 12 18:05:15 nfsen[4391]: Events: _get_where_clause. name: Notified oper: ARRAY(0x22fb778)
Aug 12 18:05:15 nfsen[4391]: Events: XXX Not fixed!
Aug 12 18:05:15 nfsen[4391]: Events: XXX [null]got matched as: null
Aug 12 18:05:15 nfsen[4391]: Events: XXX equals null!
Aug 12 18:05:15 nfsen[4391]: Events: XXX null condition: WHERE event_id NOT IN ( SELECT event_id FROM attributes WHERE Name="Notified"
Aug 12 18:05:15 nfsen[4391]: Events: XXX [set]1439388000got matched as: set
Aug 12 18:05:15 nfsen[4391]: Events: _get_where_clause. name: Type oper: [eq]botlist1
Aug 12 18:05:15 nfsen[4391]: Events: XXX fixed!
Aug 12 18:05:15 nfsen[4391]: Events: XXX not an array!
Aug 12 18:05:15 nfsen[4391]: Events: XXX [eq]botlist1got matched as: eq
Aug 12 18:05:15 nfsen[4391]: Events: XXX second match: botlist1
Aug 12 18:05:15 nfsen[4391]: Events: XXX clause so far: Type="botlist1"
Aug 12 18:05:15 nfsen[4391]: Events: XXX condition so far : WHERE Type="botlist1"
Aug 12 18:05:15 nfsen[4391]: Events: _get_where_clause. name: Level oper: [eq]alarm
Aug 12 18:05:15 nfsen[4391]: Events: XXX fixed!
Aug 12 18:05:15 nfsen[4391]: Events: XXX not an array!
Aug 12 18:05:15 nfsen[4391]: Events: XXX [eq]alarmgot matched as: eq
Aug 12 18:05:15 nfsen[4391]: Events: XXX second match: alarm
Aug 12 18:05:15 nfsen[4391]: Events: XXX clause so far: Level="alarm"
Aug 12 18:05:15 nfsen[4391]: Events: XXX condition so far : WHERE Type="botlist1" AND Level="alarm"
//note two WHEREs on the next line
Aug 12 18:05:15 nfsen[4391]: Events: return: FROM events WHERE Type="botlist1" AND Level="alarm" WHERE event_id NOT IN ( SELECT event_id FROM attributes WHERE Name="Notified")
Aug 12 18:05:15 nfsen[4391]: Events: SELECT event_id FROM events WHERE Type="botlist1" AND Level="alarm" WHERE event_id NOT IN ( SELECT event_id FROM attributes WHERE Name="Notified")
Aug 12 18:05:15 nfsen[4391]: Events: SQL ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE event_id NOT IN ( SELECT event_id FROM attributes WHERE Name="Not' at line 1
Aug 12 18:05:15 nfsen[4391]: Cmd Decode: quit
Aug 12 18:05:15 nfsen[4021]: Run plugins done.
解析器中是否存在错误,如何解决?