#pragma once #include "acl_cpp/acl_cpp_define.hpp" #include "acl_cpp/stdlib/string.hpp" #include namespace acl { /** * SQL 查询语句查询器,该类会自动对 sql 中的一些特殊字符进行转义,使用方式类似于 * java hibernate 的 SQL 语句构建方式 */ class ACL_CPP_API query { public: query(); ~query(); /** * 创建 sql 语句,变参方式,用法和 printf 类似 * @param sql_fmt {const char*} sql 语句,格式如: * select * from xxx where name = :name and len >= %d * 其中的 :name, 将由 set_parameter 中的值进行替换, len 为整形值 * @return {query&} */ query& create_sql(const char* sql_fmt, ...) ACL_CPP_PRINTF(2, 3);; /** * 创建 sql 语句,非变参方式 * @param sql {const char*} sql 语句,格式如: * select * from xxx where name = :name and len >= :len * 其中的 :name, :len 将由 set_parameter 中的值进行替换 * @return {query&} */ query& create(const char* sql); /** * 设置字符串类型的变量值 * @param name {const char*} 变量名 * @param value {const char*} 变量值 * @return {query&} */ query& set_parameter(const char* name, const char *value); /** * 设置字符类型的变量值 * @param name {const char*} 变量名 * @param value {char} 变量值 * @return {query&} */ query& set_parameter(const char* name, char value); /** * 设置 16 位短整类型的变量值 * @param name {const char*} 变量名 * @param value {short} 变量值 * @return {query&} */ query& set_parameter(const char* name, short value); /** * 设置 32 位短整类型的变量值 * @param name {const char*} 变量名 * @param value {int} 变量值 * @return {query&} */ query& set_parameter(const char* name, int value); /** * 设置单精度浮点类型的变量值 * @param name {const char*} 变量名 * @param value {float} 单精度浮点类型 * @param precision {int} 尾数的精度值 * @return {query&} */ query& set_parameter(const char* name, float value, int precision = 8); /** * 设置双精度浮点类型的变量值 * @param name {const char*} 变量名 * @param value {double} 双精度浮点类型 * @param precision {int} 尾数的精度值 * @return {query&} */ query& set_parameter(const char* name, double value, int precision = 8); /** * 设置 64 位短整类型的变量值 * @param name {const char*} 变量名 * @param value {long long int} 变量值 * @return {query&} */ #if defined(_WIN32) || defined(_WIN64) query& set_parameter(const char* name, __int64 value); #else query& set_parameter(const char* name, long long int value); #endif /** * 设置日期(time_t)类型的变量值 * @param name {const char*} 变量名 * @param value {time_t} 变量值 * @param fmt {const char*} 日期格式 * @return {query&} */ query& set_date(const char* name, time_t value, const char* fmt = "%Y-%m-%d %H:%M:%S"); /** * 以变参方式设置变量值 * @param name {const char*} 变量名 * @param fmt {const char*} 变参值格式 * @return {query&} */ query& set_format(const char* name, const char* fmt, ...) ACL_CPP_PRINTF(3, 4); /** * 以变参方式设置变量值 * @param name {const char*} 变量名 * @param fmt {const char*} 变参值格式 * @param ap {va_list} 变参值列表 * @return {query&} */ query& set_vformat(const char* name, const char* fmt, va_list ap); /** * 对查询 sql 语句进行转义后返回给调用者 * @return {const string&} */ const string& to_string(); /** * 清空查询器上一次的缓存数据,当该 SQL 查询器对象被多次使用时,应该提前调用 * 本函数清除之前的 SQL 查询器状态 */ void reset(); /** * 对 sql 中的一些特殊字符进行转义处理,以防止 SQL 注入问题 * @param in {const char*} 变量值 * @param len {size_t} in 数据长度 * @param out {string&} 存储转换后的结果的缓冲区,该参数输入后会先被清空 * @return {const string&} 转义处理后的结果(其实是 out 的地址引用) */ static const string& escape(const char* in, size_t len, string& out); /** * 将时间转换成 DateTime 格式的字符串(YYYY-MM-DD HH:MM:SS) * @param t {time_t} 时间截 * @param out {string&} 存储转换结果的缓冲区 * @param fmt {const char*} 日期格式,在 _WIN32 下必须保证该格式的正确性, * 否则 _WIN32 API 会产生断言,格式如:"%Y-%m-%d %H:%M:%S" * @return {const char*} 转换后缓冲区地址,若返回 NULL 则表示转换失败 */ static const char* to_date(time_t t, string& out, const char* fmt = "%Y-%m-%d %H:%M:%S"); private: typedef enum { DB_PARAM_CHAR, DB_PARAM_SHORT, DB_PARAM_INT32, DB_PARAM_INT64, DB_PARAM_FLOAT, DB_PARAM_DOUBLE, DB_PARAM_STR } db_param_type; struct query_param { char type; int dlen; int precision; union { char c; short s; int n; long long int l; double d; float f; char S[1]; } v; }; std::map params_; string* sql_buf_; string sql_; string buf_; void del_param(const string& key); bool append_key(string& buf, char* key); }; } // namespace acl