Refactor SQL query generators.

Accept other column names than newsgroup.

Signed-off-by: Thomas Hochstein <thh@thh.name>
This commit is contained in:
Thomas Hochstein 2025-05-11 00:29:52 +02:00
parent 713db80545
commit 867498fdc8
2 changed files with 49 additions and 46 deletions

View file

@ -110,7 +110,7 @@ my ($CaptionPeriod,$SQLWherePeriod) = &GetTimePeriod($OptMonth);
# with placeholders as well as a list of newsgroup to bind to them
my ($SQLWhereNewsgroups,@SQLBindNewsgroups);
if ($OptNewsgroups) {
($SQLWhereNewsgroups,@SQLBindNewsgroups) = &SQLGroupList($OptNewsgroups);
($SQLWhereNewsgroups,@SQLBindNewsgroups) = &SQLGroupList($OptNewsgroups,'newsgroup');
# bail out if --newsgroups is invalid
&Bleat(2,"--newsgroups option has an invalid format!")
if !$SQLWhereNewsgroups;
@ -143,7 +143,7 @@ $OptGroupBy = 'newsgroup' if (!$OptGroupBy and $OptMonth and $OptMonth =~ /:/
and $OptNewsgroups and $OptNewsgroups !~ /[:*%]/);
# parse $OptGroupBy to $GroupBy, create ORDER BY clause $SQLOrderClause
# if $OptGroupBy is still not set, SQLSortOrder() will default to 'month'
my ($GroupBy,$SQLOrderClause) = SQLSortOrder($OptGroupBy, $OptOrderBy);
my ($GroupBy,$SQLOrderClause) = SQLSortOrder($OptGroupBy, $OptOrderBy, 'newsgroup');
# $GroupBy will contain 'month' or 'newsgroup' (parsed result of $OptGroupBy)
# set it to 'month' or 'key' for OutputData()
$GroupBy = ($GroupBy eq 'month') ? 'month' : 'key';

View file

@ -579,21 +579,22 @@ sub SQLSortOrder {
### IN : $GroupBy: primary sort by 'month' (default) or 'newsgroups'
### $OrderBy: secondary sort by month/newsgroups (default)
### or number of 'postings'
### $Type : newsgroup, host, client
### OUT: a SQL ORDER BY clause
my ($GroupBy,$OrderBy) = @_;
my ($GroupBy,$OrderBy,$Type) = @_;
my ($GroupSort,$OrderSort) = ('','');
# $GroupBy (primary sorting)
if (!$GroupBy) {
$GroupBy = 'month';
} else {
($GroupBy, $GroupSort) = SQLParseOrder($GroupBy);
if ($GroupBy =~ /group/i) {
$GroupBy = 'newsgroup';
if ($GroupBy =~ /name/i) {
$GroupBy = $Type;
} else {
$GroupBy = 'month';
}
}
my $Secondary = ($GroupBy eq 'month') ? 'newsgroup' : 'month';
my $Secondary = ($GroupBy eq 'month') ? $Type : 'month';
# $OrderBy (secondary sorting)
if (!$OrderBy) {
$OrderBy = $Secondary;
@ -629,44 +630,45 @@ sub SQLParseOrder {
################################################################################
sub SQLGroupList {
################################################################################
### explode list of newsgroups separated by : (with wildcards)
### explode list of names separated by : (with wildcards)
### to a SQL 'WHERE' expression
### IN : $Newsgroups: list of newsgroups (group.one.*:group.two:group.three.*)
### IN : $Names: list of names, e.g. newsgroups (group.one.*:group.two:group.three.*)
### $Type : newsgroup, host, client
### OUT: SQL code to become part of a 'WHERE' clause,
### list of newsgroups for SQL bindings
my ($Newsgroups) = @_;
### list of names for SQL bindings
my ($Names,$Type) = @_;
# substitute '*' wildcard with SQL wildcard character '%'
$Newsgroups =~ s/\*/%/g;
return (undef,undef) if !CheckValidNewsgroups($Newsgroups);
# just one newsgroup?
return (SQLGroupWildcard($Newsgroups),$Newsgroups) if $Newsgroups !~ /:/;
my ($SQL,@WildcardGroups,@NoWildcardGroups);
# list of newsgroups separated by ':'
my @GroupList = split /:/, $Newsgroups;
foreach (@GroupList) {
$Names =~ s/\*/%/g;
return (undef,undef) if !CheckValidNames($Names);
# just one name/newsgroup?
return (SQLGroupWildcard($Names,$Type),$Names) if $Names !~ /:/;
my ($SQL,@WildcardNames,@NoWildcardNames);
# list of names/newsgroups separated by ':'
my @NameList = split /:/, $Names;
foreach (@NameList) {
if ($_ !~ /%/) {
# add to list of newsgroup names WITHOUT wildcard
push (@NoWildcardGroups,$_);
# add to list of names/newsgroup names WITHOUT wildcard
push (@NoWildcardNames,$_);
} else {
# add to list of newsgroup names WITH wildcard
push (@WildcardGroups,$_);
# add to list of names WITH wildcard
push (@WildcardNames,$_);
# add wildcard to SQL clause
# 'OR' if SQL clause is not empty
$SQL .= ' OR ' if $SQL;
$SQL .= 'newsgroup LIKE ?'
$SQL .= "$Type LIKE ?"
}
};
if (scalar(@NoWildcardGroups)) {
if (scalar(@NoWildcardNames)) {
# add 'OR' if SQL clause is not empty
$SQL .= ' OR ' if $SQL;
if (scalar(@NoWildcardGroups) < 2) {
# special case: just one newsgroup without wildcard
$SQL .= 'newsgroup = ?';
if (scalar(@NoWildcardNames) < 2) {
# special case: just one name without wildcard
$SQL .= "$Type = ?";
} else {
# create list of newsgroups to include: 'newsgroup IN (...)'
$SQL .= 'newsgroup IN (';
# create list of names to include: e.g. 'newsgroup IN (...)'
$SQL .= "$Type IN (";
my $SQLin;
foreach (@NoWildcardGroups) {
foreach (@NoWildcardNames) {
$SQLin .= ',' if $SQLin;
$SQLin .= '?';
}
@ -674,27 +676,28 @@ sub SQLGroupList {
$SQL .= $SQLin .= ')';
}
}
# add brackets '()' to SQL clause as needed (more than one wildcard group)
if (scalar(@WildcardGroups)) {
# add brackets '()' to SQL clause as needed (more than one wildcard name)
if (scalar(@WildcardNames)) {
$SQL = '(' . $SQL .')';
}
# rebuild @GroupList in (now) correct order
@GroupList = (@WildcardGroups,@NoWildcardGroups);
return ($SQL,@GroupList);
# rebuild @NameList in (now) correct order
@NameList = (@WildcardNames,@NoWildcardNames);
return ($SQL,@NameList);
};
################################################################################
sub SQLGroupWildcard {
################################################################################
### build a valid SQL 'WHERE' expression with or without wildcards
### IN : $Newsgroup: newsgroup expression, probably with wildcard
### (group.name or group.name.%)
### IN : $Name: expression, probably with wildcard
### (group.name or group.name.%)
### $Type: newsgroup, host, client
### OUT: SQL code to become part of a 'WHERE' clause
my ($Newsgroup) = @_;
if ($Newsgroup !~ /%/) {
return 'newsgroup = ?';
my ($Name,$Type) = @_;
if ($Name !~ /%/) {
return "$Type = ?";
} else {
return 'newsgroup LIKE ?';
return "$Type LIKE ?";
}
};
@ -796,14 +799,14 @@ sub SQLBuildClause {
#####--------------------------- Verifications ----------------------------#####
################################################################################
sub CheckValidNewsgroups {
sub CheckValidNames {
################################################################################
### syntax check of newgroup list
### IN : $Newsgroups: list of newsgroups (group.one.*:group.two:group.three.*)
### syntax check of a list
### IN : $Names: list of names, e.g. newsgroups (group.one.*:group.two:group.three.*)
### OUT: boolean
my ($Newsgroups) = @_;
my ($Names) = @_;
my $InvalidCharRegExp = ',; ';
return ($Newsgroups =~ /[$InvalidCharRegExp]/) ? 0 : 1;
return ($Names =~ /[$InvalidCharRegExp]/) ? 0 : 1;
};