2023-07-23 10:56:41 +02:00
|
|
|
|
|
|
|
#include "filters.h"
|
|
|
|
|
|
|
|
#include "utilities/strings.h"
|
|
|
|
|
2024-01-28 17:51:30 +01:00
|
|
|
#include <QRegularExpression>
|
2023-07-23 10:56:41 +02:00
|
|
|
|
|
|
|
|
|
|
|
namespace FilterOps
|
|
|
|
{
|
|
|
|
|
2024-01-21 19:22:30 +01:00
|
|
|
std::optional<QString> parseNull( const QString& filter_str, const bool to_clean ) noexcept
|
2023-07-23 10:56:41 +02:00
|
|
|
{
|
|
|
|
std::optional<QString> result;
|
|
|
|
const QString aux{ ( to_clean )
|
|
|
|
? filter_str.simplified().toUpper()
|
|
|
|
: filter_str };
|
|
|
|
if ( !aux.isEmpty() ) { // here an empty string is considered invalid
|
2024-01-28 17:51:30 +01:00
|
|
|
if ( aux == "NULL" || aux == "NOT NULL" ) {
|
|
|
|
result.emplace( QStringLiteral(" IS %1").arg( aux ) );
|
|
|
|
} else if ( aux == "! NULL" || aux == "!NULL" ) {
|
|
|
|
result.emplace( QStringLiteral(" IS NOT NULL") );
|
2023-07-23 10:56:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-01-28 17:51:30 +01:00
|
|
|
std::optional<QString> parseNumericFilter( const QString& filter_str ) noexcept
|
2023-07-23 10:56:41 +02:00
|
|
|
{
|
|
|
|
using opt_t = std::optional<QString>;
|
2024-01-28 17:51:30 +01:00
|
|
|
|
|
|
|
// a valid string is only composed by a comparison operator followed by a number
|
|
|
|
static const QRegularExpression expected("^(=|==|!=|<|<=|>=|>)[0-9]+$");
|
|
|
|
// remove every space from the filter
|
|
|
|
static const QRegularExpression spaces(R"(\s*)");
|
|
|
|
|
2023-07-23 10:56:41 +02:00
|
|
|
if ( filter_str.isEmpty() ) {
|
|
|
|
// an empty filter is not invalid
|
2024-01-28 17:51:30 +01:00
|
|
|
return {filter_str};
|
2023-07-23 10:56:41 +02:00
|
|
|
}
|
2024-01-28 17:51:30 +01:00
|
|
|
|
2023-07-23 10:56:41 +02:00
|
|
|
// check if the filter is NULL or NOT NULL
|
2024-01-28 17:51:30 +01:00
|
|
|
if ( const opt_t aux{ parseNull( filter_str ) }; aux.has_value() ) {
|
2023-07-23 10:56:41 +02:00
|
|
|
return aux;
|
|
|
|
}
|
|
|
|
|
2024-01-28 17:51:30 +01:00
|
|
|
if ( expected.matchView( filter_str ).hasMatch() ) {
|
|
|
|
return {filter_str};
|
|
|
|
}
|
2023-07-23 10:56:41 +02:00
|
|
|
|
|
|
|
opt_t result;
|
|
|
|
// normalize the comparison operator
|
2024-01-28 17:51:30 +01:00
|
|
|
QString aux{ filter_str.toUpper().remove(spaces) };
|
|
|
|
if ( aux.isEmpty() ) {
|
|
|
|
return {aux};
|
|
|
|
|
|
|
|
} else if ( StringOps::isNumeric( aux ) ) {
|
2024-02-03 17:54:53 +01:00
|
|
|
aux.prepend( QLatin1Char('=') );
|
2024-01-28 17:51:30 +01:00
|
|
|
|
2024-02-03 17:54:53 +01:00
|
|
|
} else if ( aux.at(0) == QLatin1Char('!') && aux.at(1) != QLatin1Char('=') ) {
|
|
|
|
aux.insert(1, QLatin1Char('='));
|
2024-01-28 17:51:30 +01:00
|
|
|
|
|
|
|
} else if ( aux.startsWith(QLatin1String("EQ")) ) {
|
2024-02-03 17:54:53 +01:00
|
|
|
aux.replace(0, 2, QLatin1Char('='));
|
2024-01-28 17:51:30 +01:00
|
|
|
|
|
|
|
} else if ( aux.startsWith(QLatin1String("NE")) ) {
|
2024-02-03 17:54:53 +01:00
|
|
|
aux.replace(0, 2, QLatin1Char('=')).prepend(QLatin1Char('!'));
|
2024-01-28 17:51:30 +01:00
|
|
|
|
|
|
|
} else if ( aux.startsWith(QLatin1String("LT")) ) {
|
2024-02-03 17:54:53 +01:00
|
|
|
aux.replace(0, 2, QLatin1Char('<'));
|
2024-01-28 17:51:30 +01:00
|
|
|
|
|
|
|
} else if ( aux.startsWith(QLatin1String("LE")) ) {
|
2024-02-03 17:54:53 +01:00
|
|
|
aux.replace(0, 2, QLatin1Char('=')).prepend(QLatin1Char('<'));
|
2024-01-28 17:51:30 +01:00
|
|
|
|
|
|
|
} else if ( aux.startsWith(QLatin1String("GT")) ) {
|
2024-02-03 17:54:53 +01:00
|
|
|
aux.replace(0, 2, QLatin1Char('>'));
|
2024-01-28 17:51:30 +01:00
|
|
|
|
|
|
|
} else if ( aux.startsWith(QLatin1String("GE")) ) {
|
2024-02-03 17:54:53 +01:00
|
|
|
aux.replace(0, 2, QLatin1Char('=')).prepend(QLatin1Char('>'));
|
2023-07-23 10:56:41 +02:00
|
|
|
}
|
2024-01-28 17:51:30 +01:00
|
|
|
|
|
|
|
// final check
|
|
|
|
if ( expected.matchView( aux ).hasMatch() ) {
|
|
|
|
result.emplace( aux );
|
2023-07-23 10:56:41 +02:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-01-21 19:22:30 +01:00
|
|
|
std::optional<QString> parseTextualFilter( const QString& filter_str ) noexcept
|
2023-07-23 10:56:41 +02:00
|
|
|
{
|
|
|
|
using opt_t =std::optional<QString>;
|
2024-01-28 17:51:30 +01:00
|
|
|
|
2023-07-23 10:56:41 +02:00
|
|
|
if ( filter_str.isEmpty() ) {
|
|
|
|
// an empty filter is not invalid
|
2024-01-28 17:51:30 +01:00
|
|
|
return {filter_str};
|
2023-07-23 10:56:41 +02:00
|
|
|
}
|
2024-01-28 17:51:30 +01:00
|
|
|
|
2023-07-23 10:56:41 +02:00
|
|
|
// check if the filter is NULL or NOT NULL
|
2024-01-28 17:51:30 +01:00
|
|
|
if ( const opt_t aux{ parseNull( filter_str ) }; aux.has_value() ) {
|
2023-07-23 10:56:41 +02:00
|
|
|
return aux;
|
|
|
|
}
|
2024-01-28 17:51:30 +01:00
|
|
|
|
|
|
|
opt_t result;
|
|
|
|
QString aux{ filter_str.trimmed() };
|
|
|
|
if ( aux.isEmpty() ) {
|
|
|
|
return {aux};
|
|
|
|
|
|
|
|
} else if ( aux == "*" ) {
|
|
|
|
result.emplace(QStringLiteral(" IS NOT NULL"));
|
|
|
|
|
2023-07-23 10:56:41 +02:00
|
|
|
} else {
|
2024-02-03 17:54:53 +01:00
|
|
|
if ( aux.startsWith(QLatin1Char('!')) ) {
|
|
|
|
result.emplace( QStringLiteral(" NOT LIKE '%1'").arg( aux.removeFirst().trimmed().replace(QLatin1Char('\''),QLatin1String("''")) ) );
|
2024-01-28 17:51:30 +01:00
|
|
|
} else {
|
2024-02-03 17:54:53 +01:00
|
|
|
if ( aux.startsWith(QLatin1Char('\\')) ) {
|
2024-01-28 17:51:30 +01:00
|
|
|
aux.removeFirst();
|
|
|
|
}
|
2024-02-03 17:54:53 +01:00
|
|
|
result.emplace( QStringLiteral(" LIKE '%1'").arg( aux.replace(QLatin1Char('\''),QLatin1String("''")) ) );
|
2024-01-28 17:51:30 +01:00
|
|
|
}
|
2023-07-23 10:56:41 +02:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace FilterOps
|