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

View file

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