You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中用sqlite3_create_function_v2定义REGEXP函数如何返回结果?

解决SQLite自定义REGEXP函数返回结果的问题

完整的REGEXP函数实现

你需要借助SQLite提供的sqlite3_result_*系列函数向SQL返回结果。对于REGEXP这类布尔判断场景,匹配成功返回1,失败返回0;若正则表达式编译出错,要通过错误函数告知SQLite。修改后的函数实现如下:

sqlite3_create_function_v2(db, "REGEXP", 2, SQLITE_UTF8, nil,
    { context, argc, arguments in
        guard argc == 2 else {
            sqlite3_result_error(context, "REGEXP requires 2 arguments", -1)
            return
        }
        
        // 提取正则模式与待匹配文本
        guard let patternCStr = sqlite3_value_text(arguments[0]),
              let textCStr = sqlite3_value_text(arguments[1]) else {
            sqlite3_result_error(context, "Invalid argument type", -1)
            return
        }
        let pattern = String(cString: patternCStr)
        let text = String(cString: textCStr)
        
        // 编译正则并处理匹配结果
        do {
            let reg = try NSRegularExpression(pattern: pattern, options: [])
            let range = NSRange(location: 0, length: text.utf16.count)
            let hasMatch = reg.firstMatch(in: text, options: [], range: range) != nil
            // 向SQLite返回布尔结果:1=匹配,0=不匹配
            sqlite3_result_int(context, hasMatch ? 1 : 0)
        } catch {
            let errorMsg = "Invalid regex pattern: \(error.localizedDescription)"
            sqlite3_result_error(context, errorMsg, -1)
        }
    }, nil, nil, nil)

核心细节说明

  • 结果返回:通过sqlite3_result_int返回整数,SQLite会自动将1/0解析为布尔值,用于WHERE子句的条件判断。
  • 错误处理:正则编译失败时,用sqlite3_result_error返回具体错误信息,SQL查询过程中会捕获到该错误。
  • 参数校验:增加基础的参数数量、非空校验,避免空指针或参数异常导致崩溃。

优化查询代码(规避SQL注入风险)

你当前用字符串插值拼接正则模式存在安全隐患,建议改用参数绑定方式:

let sql = "SELECT * FROM Books WHERE bookID = 1 AND REGEXP(?, text);"
var statement: OpaquePointer?

if sqlite3_prepare_v2(db, sql, -1, &statement, nil) == SQLITE_OK {
    // 绑定正则模式参数
    sqlite3_bind_text(statement, 1, pattern, -1, SQLITE_TRANSIENT)
    
    while sqlite3_step(statement) == SQLITE_ROW {
        if let unsafeText = sqlite3_column_text(statement, 3) {
            let text = String(cString: unsafeText)
            print(text)
        }
    }
    sqlite3_finalize(statement) // 务必释放statement,避免内存泄漏
} else {
    let errorMessage = String(cString: sqlite3_errmsg(db))
    print("Query preparation failed: \(errorMessage)")
}

额外注意

  • SQLITE_TRANSIENT参数告知SQLite自行管理绑定字符串的内存,无需手动释放。
  • 每次执行完查询后,必须调用sqlite3_finalize释放statement资源。

内容的提问来源于stack exchange,提问作者Almudhafar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 21:58:23