c++ - 使用 C++ 或 Qt 将 SQL LIKE 表达式转换为正则表达式

标签 c++ sql qt

我有这样的查询:

SELECT a, b, c
FROM T
WHERE ( a LIKE 'f%' OR b LIKE 'f%' OR c LIKE 'f%' ) 

当然,原始查询更复杂,过滤器更复杂。

我需要确定在哪个字段中匹配 a、b 或 c
基于此,我使用 Qt a 可以将结果与正则表达式进行比较。

但是如何将 LIKE 中的表达式转换为正则表达式。

this文章提供了部分解决方案。但可能存在更全面的例子?

PS:(回答评论中的问题)。

  • 我处理不同的 DBMS(PostgreSQL、SQL Server、MySQL),并不是所有的数据库都内置正则表达式支持
  • 我想找到像这样的匹配:

    const QString valueA( GetValueFromQuery() );
    if( valueA.contains( QRegExp( _CONVERTED_EXPRESSION_ )) {}

  • 在链接的帖子中描述了一个手工制作的解决方案。我想找到其他行之有效的解决方案。

最佳答案

虽然我仍然更喜欢将 LIKE 部分的结果添加到结果集中的解决方案,但这可能会满足您的需求。

此代码仍可能包含错误且未优化:

#include <algorithm>
#include <string>
#include <map>
#include <iostream>
#include <sstream>

std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value)
{
    std::string::size_type pos = 0;
    while ((pos = str.find(old_value, pos)) != std::string::npos)
    {
        str.replace(pos, old_value.size(), new_value);
        pos += new_value.size() - old_value.size() + 1;
    }
    return str;
}

std::map<std::string, std::string> extractCharacterRanges(std::string& str)
{
    std::map<std::string, std::string> ranges;

    int rangeID = 0;
    std::string::size_type startPos = 0;
    std::string::size_type endPos = 0;

    while ((startPos = str.find("[", startPos)) != std::string::npos && (endPos = str.find("]", startPos + 1)) != std::string::npos)
    {
        std::stringstream ss;
        ss << "[[" << rangeID << "]]";
        std::string chars = str.substr(startPos + 1, endPos - startPos - 1);
        str.replace(startPos, chars.size() + 2, ss.str());
        rangeID++;
        startPos += ss.str().size();

        replace_all(chars, "[", "\\[");
        replace_all(chars, "]", "\\]");
        ranges[ss.str()] = "[" + chars + "]";
    }

    int open = 0;
    std::string::size_type searchPos = 0;
    startPos = 0; endPos = 0;
    do
    {
        startPos = str.find("[", searchPos);
        endPos = str.find("]", searchPos);

        if (startPos == std::string::npos && endPos == std::string::npos)
            break;

        if (startPos < endPos || endPos == std::string::npos)
        {
            open++;
            searchPos = startPos + 1;
        }
        else
        {
            if (open <= 0)
            {
                str.replace(endPos, 1, "\\]");
                searchPos = endPos + 2;
            }
            else
            {
                open--;
                searchPos = endPos + 1;
            }
        }
    } while (searchPos < str.size());
    return ranges;
}


std::string sqllike_to_regex(std::string sqllike)
{
    replace_all(sqllike, ".", "\\.");
    replace_all(sqllike, "^", "\\^");
    replace_all(sqllike, "$", "\\$");
    replace_all(sqllike, "+", "\\+");
    replace_all(sqllike, "?", "\\?");
    replace_all(sqllike, "(", "\\(");
    replace_all(sqllike, ")", "\\)");
    replace_all(sqllike, "{", "\\{");
    replace_all(sqllike, "}", "\\}");
    replace_all(sqllike, "\\", "\\\\");
    replace_all(sqllike, "|", "\\|");
    replace_all(sqllike, ".", "\\.");
    replace_all(sqllike, "*", "\\*");
    std::map<std::string, std::string> ranges = extractCharacterRanges(sqllike); //Escapes [ and ] where necessary
    replace_all(sqllike, "%", ".*");
    replace_all(sqllike, "_", ".");
    for (auto& range : ranges)
    {
        replace_all(sqllike, range.first, range.second);
    }
    return "^" + sqllike + "$";
}


int main() {
    std::cout << sqllike_to_regex("f%") << std::endl;//^f.*$
    std::cout << sqllike_to_regex("[A-Z]%") << std::endl;//^[A-Z].*$
    std::cout << sqllike_to_regex("[[A-Z][asd]]") << std::endl;//^[\[A - Z][asd]\]$
    std::cout << sqllike_to_regex("a]a") << std::endl;//^a\]a$
    std::cout << sqllike_to_regex("[%] [[] ] % [_] _") << std::endl;//^[%] [\[] \] .* [_] .$
    return 0;
}

关于c++ - 使用 C++ 或 Qt 将 SQL LIKE 表达式转换为正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34897842/

相关文章:

python - 从 Linux 中的 acpi 事件执行 PyQt 应用程序

c++ - GCC 对 lambda 中的静态变量做了什么?

c++ - 使用 sscanf 读取数字怎么会崩溃?

c++ - 2个操作数的产品类型

mysql - 触发错误1064

MySQL:MySQL 表中的两个不同值被视为相同(不能设置唯一键)

sql - SQL脚本中的Week()函数

c++ - Qt 4.6 + MinGW : suppress warnings for generated code

c++ - 如何将 Qt 库添加到 visual studio

qt - 由于 poppler,无法在 Windows 上安装 pdftotext