diff --git a/lib_acl_cpp/changes.txt b/lib_acl_cpp/changes.txt index f2bde1899..6fa8263ab 100644 --- a/lib_acl_cpp/changes.txt +++ b/lib_acl_cpp/changes.txt @@ -1,5 +1,9 @@ 修改历史列表: +570) 2019.5.27 +570.1) feature: db_handle/db_mysql/db_pgsql 支持获取字段值的长度 +-- by 孙良灿(1142263518) + 569) 2019.5.18 569.1) compile: 增加宏编译选项 ACL_CLIENT_ONLY,当将 acl 库用于客户端模式时可以有效地 减少编译库的大小 diff --git a/lib_acl_cpp/include/acl_cpp/db/db_handle.hpp b/lib_acl_cpp/include/acl_cpp/db/db_handle.hpp index 1b8cce28b..2e20dd3d0 100644 --- a/lib_acl_cpp/include/acl_cpp/db/db_handle.hpp +++ b/lib_acl_cpp/include/acl_cpp/db/db_handle.hpp @@ -139,11 +139,25 @@ public: */ const char* field_string(const char* name) const; + /** + * 从查询结果的记录行中取得对应下标的字符串类型的字段值长度 + * @param ifield {size_t} 下标值 + * @return {size_t} + */ + size_t field_length(size_t ifield) const; + /** + * 从查询结果的记录行中取得字段名的字符串类型的字段值长度 + * @param name {const char*} 下标值 + * @return {size_t} + */ + size_t field_length(const char* name) const; + /** * 向记录行添加一个字段值,添加字段值的顺序应该与字段名的顺序一致 * @param value {const char*} 该行记录的某个字段值 + * @param len {size_t} value 数据长度 */ - void push_back(const char* value); + void push_back(const char* value, size_t len); /** * 行记录中字段值的个数 @@ -162,6 +176,9 @@ private: // 数据结果行的字段集合 std::vector values_; + + // 数据结果行字段长度集合 + std::vector lengths_; }; /** diff --git a/lib_acl_cpp/src/db/db_handle.cpp b/lib_acl_cpp/src/db/db_handle.cpp index 78e111891..fab3ee3d1 100644 --- a/lib_acl_cpp/src/db/db_handle.cpp +++ b/lib_acl_cpp/src/db/db_handle.cpp @@ -158,9 +158,46 @@ const char* db_row::field_string(const char* name) const return ptr; } -void db_row::push_back(const char* value) +size_t db_row::field_length(size_t ifield) const +{ + if (ifield >= lengths_.size()) { + logger_error("ifield(%d) invalid, lengths_.size: %d", + (int) ifield, (int) lengths_.size()); + return NULL; + } + + return lengths_[ifield]; +} + +size_t db_row::field_length(const char* name) const +{ + size_t i, n = names_.size(); + + // 必须保证表中字段名的个数与行记录的值的个数相等 + if (lengths_.size() != n) { + logger_error("invalid result, names=%d, lengths_=%d", + (int) n, (int) lengths_.size()); + return NULL; + } + + // 通过扫描字段名找出字段值的下标位置 + for (i = 0; i < n; i++) { + if (strcasecmp(name, names_[i]) == 0) + break; + } + if (i == n) { + logger_error("cloumn not exist, name: %s", name); + return NULL; + } + + // 直接返回相应下标的字段值 + return lengths_[i]; +} + +void db_row::push_back(const char* value, size_t len) { values_.push_back(value); + lengths_.push_back(len); } size_t db_row::length(void) const diff --git a/lib_acl_cpp/src/db/db_mysql.cpp b/lib_acl_cpp/src/db/db_mysql.cpp index 1f6f87dd0..56f68440f 100644 --- a/lib_acl_cpp/src/db/db_mysql.cpp +++ b/lib_acl_cpp/src/db/db_mysql.cpp @@ -41,6 +41,7 @@ typedef const char* (STDCALL *mysql_error_fn)(MYSQL*); typedef int (STDCALL *mysql_query_fn)(MYSQL*, const char*); typedef unsigned int (STDCALL *mysql_num_fields_fn)(MYSQL_RES*); typedef MYSQL_FIELD* (STDCALL *mysql_fetch_fields_fn)(MYSQL_RES*); +typedef unsigned long* (STDCALL *mysql_fetch_lengths_fn)(MYSQL_RES*); typedef MYSQL_ROW (STDCALL *mysql_fetch_row_fn)(MYSQL_RES*); typedef MYSQL_RES* (STDCALL *mysql_store_result_fn)(MYSQL*); typedef my_ulonglong (STDCALL *mysql_num_rows_fn)(MYSQL_RES*); @@ -65,6 +66,7 @@ static mysql_error_fn __mysql_error = NULL; static mysql_query_fn __mysql_query = NULL; static mysql_num_fields_fn __mysql_num_fields = NULL; static mysql_fetch_fields_fn __mysql_fetch_fields = NULL; +static mysql_fetch_lengths_fn __mysql_fetch_lengths = NULL; static mysql_fetch_row_fn __mysql_fetch_row = NULL; static mysql_store_result_fn __mysql_store_result = NULL; static mysql_num_rows_fn __mysql_num_rows = NULL; @@ -207,6 +209,12 @@ static void __mysql_dll_load(void) logger_fatal("load mysql_fetch_fields from %s error: %s", path, acl_dlerror()); + __mysql_fetch_lengths = (mysql_fetch_lengths_fn) + acl_dlsym(__mysql_dll, "mysql_fetch_lengths"); + if (__mysql_fetch_lengths == NULL) + logger_fatal("load mysql_fetch_lengths from %s error: %s", + path, acl_dlerror()); + __mysql_fetch_row = (mysql_fetch_row_fn) acl_dlsym(__mysql_dll, "mysql_fetch_row"); if (__mysql_fetch_row == NULL) @@ -291,6 +299,7 @@ static void __mysql_dll_load(void) # define __mysql_query mysql_query # define __mysql_num_fields mysql_num_fields # define __mysql_fetch_fields mysql_fetch_fields +# define __mysql_fetch_lengths mysql_fetch_lengths # define __mysql_fetch_row mysql_fetch_row # define __mysql_store_result mysql_store_result # define __mysql_num_rows mysql_num_rows @@ -339,9 +348,12 @@ static void mysql_rows_save(MYSQL_RES* my_res, db_rows& result) MYSQL_ROW my_row = __mysql_fetch_row(my_res); if (my_row == NULL) break; + unsigned long *my_lengths = __mysql_fetch_lengths(my_res); + if (my_lengths == NULL) + break; db_row* row = NEW db_row(result.names_); for (int j = 0; j < ncolumn; j++) - row->push_back(my_row[j]); + row->push_back(my_row[j], (size_t) my_lengths[j]); result.rows_.push_back(row); } diff --git a/lib_acl_cpp/src/db/db_pgsql.cpp b/lib_acl_cpp/src/db/db_pgsql.cpp index 158412ab5..002feabe8 100644 --- a/lib_acl_cpp/src/db/db_pgsql.cpp +++ b/lib_acl_cpp/src/db/db_pgsql.cpp @@ -36,6 +36,7 @@ typedef int (*PQnfields_fn)(const PGresult *res); typedef char *(*PQfname_fn)(const PGresult *res, int field_num); typedef int (*PQntuples_fn)(const PGresult *res); typedef char *(*PQgetvalue_fn)(const PGresult *res, int tup_num, int field_num); +typedef int (*PQgetlength_fn)(const PGresult *res, int tup_num, int field_num); typedef char *(*PQcmdTuples_fn)(PGresult *res); static PQconnectdb_fn __dbconnect = NULL; @@ -49,6 +50,7 @@ static PQnfields_fn __dbnfields = NULL; static PQfname_fn __dbfname = NULL; static PQntuples_fn __dbntuples = NULL; static PQgetvalue_fn __dbget_value = NULL; +static PQgetlength_fn __dbget_length = NULL; static PQcmdTuples_fn __dbcmd_tuples = NULL; static acl_pthread_once_t __pgsql_once = ACL_PTHREAD_ONCE_INIT; @@ -152,6 +154,11 @@ static void __pgsql_dll_load(void) logger_fatal("load PQgetvalue from %s error %s", path, acl_dlerror()); + __dbget_length = (PQgetlength_fn) acl_dlsym(__pgsql_dll, "PQgetlength"); + if (__dbget_length == NULL) + logger_fatal("load PQgetlength from %s error %s", + path, acl_dlerror()); + __dbcmd_tuples = (PQcmdTuples_fn) acl_dlsym(__pgsql_dll, "PQcmdTuples"); if (__dbcmd_tuples == NULL) logger_fatal("load PQcmdTuples from %s error %s", @@ -173,6 +180,7 @@ static void __pgsql_dll_load(void) # define __dbfname PQfname # define __dbntuples PQntuples # define __dbget_value PQgetvalue +# define __dbget_length PQgetlength # define __dbcmd_tuples PQcmdTuples # endif @@ -209,7 +217,11 @@ static void pgsql_rows_save(PGresult* res, db_rows& result) { db_row* row = NEW db_row(result.names_); for (int j = 0; j < ncolumn; j++) - row->push_back(__dbget_value(res, i, j)); + { + char* value = __dbget_value(res, i, j); + int len = __dbget_length(res, i, j); + row->push_back(value, (size_t) len); + } result.rows_.push_back(row); } diff --git a/lib_acl_cpp/src/db/db_sqlite.cpp b/lib_acl_cpp/src/db/db_sqlite.cpp index 2f8f5ad85..f1e6c3b98 100644 --- a/lib_acl_cpp/src/db/db_sqlite.cpp +++ b/lib_acl_cpp/src/db/db_sqlite.cpp @@ -290,7 +290,9 @@ static void sqlite_rows_save(char** results, int nrow, for (int i = 0; i < nrow; i++) { db_row* row = NEW db_row(result.names_); for (int j = 0; j < ncolumn; j++) { - row->push_back(results[n++]); + const char* value = results[n++]; + size_t len = strlen(value); + row->push_back(value, len); } result.rows_.push_back(row); } diff --git a/lib_acl_cpp/src/db/sqlite_cursor.cpp b/lib_acl_cpp/src/db/sqlite_cursor.cpp index dca95c8e3..ee9e5b514 100644 --- a/lib_acl_cpp/src/db/sqlite_cursor.cpp +++ b/lib_acl_cpp/src/db/sqlite_cursor.cpp @@ -50,19 +50,19 @@ void sqlite_cursor::add_column_value(long long n) { char* buf = (char*) dbuf_->dbuf_alloc(INT4_STR_SIZE + 1); safe_snprintf(buf, INT4_STR_SIZE + 1, "%lld", n); - row_->push_back(buf); + row_->push_back(buf, strlen(buf)); } void sqlite_cursor::add_column_value(double n) { char* buf = (char*) dbuf_->dbuf_alloc(INT4_STR_SIZE + 1); safe_snprintf(buf, INT4_STR_SIZE + 1, "%.4f", n); - row_->push_back(buf); + row_->push_back(buf, strlen(buf)); } void sqlite_cursor::add_column_value(const char* s) { - row_->push_back(s); + row_->push_back(s, strlen(s)); } } // namespace acl