当前位置: 首页 > news >正文

sqlite - sqlite3_exec - c++回调函数的处理

文章目录

    • sqlite - sqlite3_exec - c++回调函数的处理
    • 概述
    • 笔记
    • 回调赋值实现
    • 用到的数据结构
    • 回调分发函数的实现
    • 具体的回调处理
    • sqlite3_exe执行完后, 行集的具体处理
    • END

sqlite - sqlite3_exec - c++回调函数的处理

概述

以前给客户写了个小程序, 处理sqlite执行sql时, 给定回调, 等sql执行完, 处理返回的行集.
那时候, 时间紧, 回调整的不太好, 只是能用而已.
这次给自己写账单分析程序, 关于用回调处理行集的部分, 想到了比以前好的方法.
可以只使用一个类静态回调函数(回调分发函数), 然后通过参数, 可以将具体干活的普通类成员函数, 赋值给回调参数. 程序简洁实用很多.
试过了, 好使.

笔记

demo就不单独写了, 从现有工程中, 摘取程序片段来说明.
关于回调这块, 因为有语法的细节, 即使知道这回事, 如果重新写一个新回调, 也会试错好多次.
让自己以后看, 能明白就行了.

bool COrderProcBase::db_proc_excel_to_db()
{bool b_rc = false;int ArySize = 0;CStringArray strAry;int i = 0;int id = 0;CString strOrgFile;CString strCpyEnFile;CFileOperation file_opt;CString cs_drive;CString cs_dir;CString cs_name;CString cs_ext;CString csCsvToExcel;CString csTmp;do {// 建立数据库中的表// !! 在建立表之前, 要先检查表是否存在, 如果不存在, 才去建立表// 否则在表存在的情况下, 再建立表, 就会返回错误, 错误原因是表已经存在// 检查表是否存在是一段sql, 返回的行集是2行(列名称, 列值),1列if (!is_db_tbl_exist()) // 这里要执行sql, 就会返回一个行集, 就用到了回调.{if (!db_create_tbl()){break;}}
bool COrderProcJH::is_db_tbl_exist()
{return COrderProcBase::is_db_tbl_exist(_T("TBL_FILE_JH"));
}

回调赋值实现

bool COrderProcBase::is_db_tbl_exist(TCHAR* pszTblName)
{// 表在数据中是否存在?bool b_rc = false;string str_utf8_sql;string str_sql;char* zErrMsg = NULL;	//错误信息const char* sql = NULL;int rc = 0;CString csMsg;char szBuf[4096];TAG_PARAM_CALLBACK_FOR_SQLITE3_EXEC param;do {_ASSERT(NULL != pszTblName);if (NULL == pszTblName){break;}memset(szBuf, 0, sizeof(szBuf));sprintf(szBuf, "SELECT EXISTS(SELECT name FROM sqlite_schema WHERE type='table' AND name='%s');", getLogicProxy()->my_W2A(pszTblName).c_str());str_sql = szBuf;str_utf8_sql = getLogicProxy()->UnicodeToUTF8(getLogicProxy()->my_A2W(str_sql));param.pThis = this;param.pFn = &COrderProcBase::callback_for_sqlite3_exec_proc_tbl_exist;param.row_set.clear();// 回调的赋值 为参数3, 参数4// 这样填写回调, 回调分发函数(类静态成员函数)只有一个, 不用变.// 具体的回调处理函数(类普通成员函数), 赋值在参数中. // 如果具体的回调处理函数不是这个类的this, 也可以在参数中指定. 这样就可以用任何类实例的任何普通成员函数来处理回调了, 很方便.// 这个参数中要赋值的类实例指针, 可以是一个基类的指针, 让处理回调的类都是这个基类的子类, 有基类中规定的处理回调的纯虚接口就好.rc = sqlite3_exec(get_db_handle(), str_utf8_sql.c_str(), COrderProcBase::callback_for_sqlite3_exec_dispatch, &param, &zErrMsg);if (SQLITE_OK != rc) {csMsg.Format(_T("错误 : %s"), getLogicProxy()->UTF8ToUnicode(zErrMsg).c_str());getLogicProxy()->addTips(csMsg);break;}// 等sql执行完, 只要执行的对, 就可以用另外一个函数来处理返回的结果集// 针对不同类型的sql, 实现不同的结果集处理函数b_rc = procResultSet_isTblExist(param.row_set, pszTblName);} while (false);if (NULL != zErrMsg) {sqlite3_free(zErrMsg);zErrMsg = NULL;}return b_rc;
}

用到的数据结构

// 类成员函数指针类型的定义
class COrderProcBase;
// PFN_CALLBACK_FOR_SQLITE3_EXEC是sqlite3_exec回调要求的函数样式
typedef int (COrderProcBase::* PFN_CALLBACK_FOR_SQLITE3_EXEC)(void* data, int argc, char** argv, char** azColName);
class COrderProcBase
{
public:
// ...// 这个结构在类中直接定义的typedef struct _tag_param_callback_for_sqlite3_exec{COrderProcBase* pThis; // 本类的指针, 用来从回调分发函数(类静态成员函数) 执行到类的普通成员函数PFN_CALLBACK_FOR_SQLITE3_EXEC pFn; // 本类中实际的回调处理函数指针(类的普通成员函数)C_my_row_set row_set; // 执行sql后, 返回的行集 这里是装在返回行集的类}TAG_PARAM_CALLBACK_FOR_SQLITE3_EXEC;

回调分发函数的实现

int  COrderProcBase::callback_for_sqlite3_exec_dispatch(void* data, int argc, char** argv, char** azColName)
{int i_rc = 0;TAG_PARAM_CALLBACK_FOR_SQLITE3_EXEC* param;do {if (NULL == data){break;}param = (TAG_PARAM_CALLBACK_FOR_SQLITE3_EXEC*)data;if ((NULL != param->pThis) && (NULL != param->pFn)){// 这里就可以执行sqlite3_exec指定的回调函数了(任意类, 任意类的回调实现(类的普通成员函数))// 这个回调分发函数基本不用再改.i_rc = ((param->pThis)->*(param->pFn))(data, argc, argv, azColName);}} while (false);return i_rc;
}

具体的回调处理

这个根据具体要执行的sql具体处理, 最普通的就是将行集先存起来.
等sqlite3_exec完事了, 再拿存的行集来判断结果.

以判断库中表是否存在为例
如果在回调中, 只是将行集存起来, 那么下面的回调就是一个通用的实现.

int COrderProcBase::callback_for_sqlite3_exec_proc_tbl_exist(void* data, int argc, char** argv, char** azColName)
{int i_rc = 0;TAG_PARAM_CALLBACK_FOR_SQLITE3_EXEC* param;int i = 0;do {if (NULL == data){break;}param = (TAG_PARAM_CALLBACK_FOR_SQLITE3_EXEC*)data;C_my_row row;C_my_key_val key_val;for (i = 0; i < argc; i++){key_val.m_cs_key = azColName[i];key_val.m_cs_val = argv[i];row.m_list.AddTail(key_val);}// 回调进来一次, 就是一行param->row_set.m_list.AddTail(row);} while (false);return i_rc;
}

sqlite3_exe执行完后, 行集的具体处理

以判断库中表是否存在为例
这个实现应该和每种不同的sql相关, 拿回调中存好的行集做不同的判断.

bool COrderProcBase::procResultSet_isTblExist(C_my_row_set& row_set, const TCHAR* pszTblName)
{bool b_rc = false;POSITION pos;POSITION pos1;C_my_row row;C_my_row row1;C_my_key_val key_val;TCHAR szBuf[4096];bool b_stop = false;do {if (NULL == pszTblName){break;}if (1 != row_set.m_list.GetSize()){break;}for (pos = row_set.m_list.GetHeadPosition(); (NULL != pos); row_set.m_list.GetNext(pos)){row = row_set.m_list.GetAt(pos);if (1 != row.m_list.GetSize()){break;}for (pos1 = row.m_list.GetHeadPosition(); (NULL != pos1); row.m_list.GetNext(pos1)){b_stop = true;key_val = row.m_list.GetAt(pos1);memset(szBuf, 0, sizeof(szBuf));_stprintf(szBuf, _T("EXISTS(SELECT name FROM sqlite_schema WHERE type='table' AND name='%s')"), pszTblName);if (key_val.m_cs_key != szBuf){break;}if (key_val.m_cs_val != _T("1")){break;}b_rc = true;break;}if (b_stop){break;}}} while (false);return b_rc;
}

END

相关文章:

sqlite - sqlite3_exec - c++回调函数的处理

文章目录 sqlite - sqlite3_exec - c回调函数的处理概述笔记回调赋值实现用到的数据结构回调分发函数的实现具体的回调处理sqlite3_exe执行完后, 行集的具体处理END sqlite - sqlite3_exec - c回调函数的处理 概述 以前给客户写了个小程序, 处理sqlite执行sql时, 给定回调, 等…...

docker搭建logstash和使用方法

配置logstash 查询下载镜像【固定和elasticsearch一样的版本】 [roothao ~]# docker search logstash NAME DESCRIPTION STARS OFFICIAL AUTOMATED logstash …...

Memory-augmented Deep Autoencoder for Unsupervised Anomaly Detection 论文阅读

Memorizing Normality to Detect Anomaly: Memory-augmented Deep Autoencoder for Unsupervised Anomaly Detection 摘要1.介绍2.相关工作异常检测Memory networks 3. Memory-augmented Autoencoder3.1概述3.2. Encoder and Decoder3.3. Memory Module with Attention-based S…...

Mac端 DevEco Preview 窗口无法展示,提示文件中的node.dir错误

语雀知识库地址&#xff1a;语雀HarmonyOS知识库 飞书知识库地址&#xff1a;飞书HarmonyOS知识库 DevEco版本&#xff1a;Build Version: 3.1.0.501, built on June 20, 2023 环境信息 问题描述 打开 Preview 标签窗口后&#xff0c;提示Preview failed。 Run窗口提示如下 F…...

TIMO后台管理系统 Shiro 反序列化漏洞复现

0x01 产品简介 TIMO 后台管理系统,基于SpringBoot2.0 + Spring Data Jpa + Thymeleaf + Shiro 开发的后台管理系统,采用分模块的方式便于开发和维护,支持前后台模块分别部署,目前支持的功能有:权限管理、部门管理、字典管理、日志记录、文件上传、代码生成等,为快速开发后…...

3.4_1 java自制小工具 - pdf批量转图片

相关链接 目录参考文章&#xff1a;pdf转图片(apache pdfbox)参考文章&#xff1a;GUI界面-awt参考文章&#xff1a;jar包转exe(exe4j)参考文章&#xff1a;IDEA导入GIT项目参考文章&#xff1a;IDEA中使用Gitee管理代码gitee项目链接&#xff1a;pdf_2_image网盘地址&#xf…...

vue中实现数字+英文字母组合键盘

完整代码 <template><div class"login"><div click"setFileClick">欢迎使用员工自助终端</div><el-dialog title"初始化设置文件打印消耗品配置密码" :visible.sync"dialogSetFile" width"600px&quo…...

Centos服务器上根据端口号查询jar包,根据jar包查端口号

在开发springboot服务器时&#xff0c;经常会遇到其他人部署的java服务&#xff0c;需要自己维护&#xff0c;留下的信息又非常少。经常面临找不到jar包位置&#xff0c;或者不知道占用端口&#xff0c;不知道启动命令的问题。这里记录一下常用的centos服务器上的命令&#xff…...

数据仓库与数据挖掘复习资料

一、题型与考点[第一种] 1、解释基本概念(中英互译解释简单的含义)&#xff1b; 2、简答题(每个10分有两个一定要记住)&#xff1a; ① 考时间序列Time series(第六章)的基本概念含义解释作用&#xff08;序列模式挖掘的作用&#xff09;&#xff1b; ② 考聚类(第五章)重点考…...

限流算法,基于go的gRPC 实现的

目录 一、单机限流 1、令牌桶算法 3、固定窗口限流算法 4、滑动窗口 二、集群限流 1、分布式固定窗口 &#xff08;基于redis&#xff09; 2、分布式滑动窗口 一、单机限流 1、令牌桶算法 令牌桶算法是当流量进入系统前需要获取令牌&#xff0c;没有令牌那么就要进行限…...

Shell中HTTP变量和文本处理

在Shell中&#xff0c;HTTP变量和文本处理是常见的任务之一。Shell是一个命令行解释器&#xff0c;可以用来自动化执行各种系统任务。在Shell中&#xff0c;我们可以使用各种命令和工具来处理HTTP变量和文本。 首先&#xff0c;让我们来看看如何在Shell中处理HTTP变量。HTTP变…...

java学习part39map

159-集合框架-Map不同实现类的对比与HashMap中元素的特点_哔哩哔哩_bilibili 1.Map 2.Entry 个人理解是c的pair&#xff0c;代表一个键值对。Map就是entry的叠加 3.常用方法 4.TreeMap 5.Properties...

使用sqoop操作HDFS与MySQL之间的数据互传

一&#xff0c;数据从HDFS中导出至MySQL中 1&#xff09;开启Hadoop、mysql进程 start-all.sh/etc/init.d/mysqld start/etc/init.d/mysqld status 2&#xff09;将学生数据stu_data.csv传到HDFS的/local_student目录下 在hdfs中创建目录 hdfs dfs -mkdir /local_student 上…...

Kafka使用指南

Kafka简介架构设计Kafka的架构设计关键概念Kafka的架构设计关键机制 Partition介绍Partition工作机制 应用场景ACK机制介绍ACK机制原理ACK机制对性能的影响ACK控制粒度Kafka分区数对集群性能影响调整分区优化集群性能拓展Kafka数据全局有序 Kafka简介 Kafka是由Apache软件基金…...

HarmonyOS4.0从零开始的开发教程03初识ArkTS开发语言(中)

HarmonyOS&#xff08;二&#xff09;初识ArkTS开发语言&#xff08;中&#xff09;之TypeScript入门 浅析ArkTS的起源和演进 1 引言 Mozilla创造了JS&#xff0c;Microsoft创建了TS&#xff0c;Huawei进一步推出了ArkTS。 从最初的基础的逻辑交互能力&#xff0c;到具备类…...

西工大计算机学院计算机系统基础实验一(函数编写1~10)

还是那句话&#xff0c;千万不要慌&#xff0c;千万不要着急&#xff0c;耐下性子慢慢来&#xff0c;一步一个脚印&#xff0c;把基础打的牢牢的&#xff0c;一样不比那些人差。回到实验本身&#xff0c;自从​​​​​​按照西工大计算机学院计算机系统基础实验一&#xff08;…...

VMware 虚拟机 电脑重启后 NAT 模式连不上网络问题修复

问题描述&#xff1a; 昨天 VMware 安装centos7虚拟机&#xff0c;网络模式配置的是NAT模式&#xff0c;配置好后&#xff0c;当时能连上外网&#xff0c;今天电脑重启后&#xff0c;发现连不上外网了 检查下各个配置&#xff0c;都没变动&#xff0c;突然就连不上了 网上查了…...

【桑基图】绘制桑基图

绘制桑基图 一、绘制桑基图&#xff08;1&#xff09;方法一&#xff1a;去在线网站直接绘制&#xff08;2&#xff09;方法二&#xff1a;写html之后在vscode上运行 二、遇到的问题&#xff08;1&#xff09;当导入一些excel的时候&#xff0c;无法绘制出桑基图 一、绘制桑基图…...

ACM32F403/F433 12 位多通道,支持 MPU 存储保护功能,应用于工业控制,智能家居等产品中

ACM32F403/F433 芯片的内核基于 ARMv8-M 架构&#xff0c;支持 Cortex-M33 和 Cortex-M4F 指令集。芯片内核 支持一整套DSP指令用于数字信号处理&#xff0c;支持单精度FPU处理浮点数据&#xff0c;同时还支持Memory Protection Unit &#xff08;MPU&#xff09;用于提升应用的…...

7. 从零用Rust编写正反向代理, HTTP及TCP内网穿透原理及运行篇

wmproxy wmproxy是由Rust编写&#xff0c;已实现http/https代理&#xff0c;socks5代理&#xff0c; 反向代理&#xff0c;静态文件服务器&#xff0c;内网穿透&#xff0c;配置热更新等&#xff0c; 后续将实现websocket代理等&#xff0c;同时会将实现过程分享出来&#xff…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...

面试高频问题

文章目录 &#x1f680; 消息队列核心技术揭秘&#xff1a;从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"&#xff1f;性能背后的秘密1.1 顺序写入与零拷贝&#xff1a;性能的双引擎1.2 分区并行&#xff1a;数据的"八车道高速公路"1.3 页缓存与批量处理…...

C++_哈希表

本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、基础概念 1. 哈希核心思想&#xff1a; 哈希函数的作用&#xff1a;通过此函数建立一个Key与存储位置之间的映射关系。理想目标&#xff1a;实现…...

数据库正常,但后端收不到数据原因及解决

从代码和日志来看&#xff0c;后端SQL查询确实返回了数据&#xff0c;但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离&#xff0c;并且ai辅助开发的时候&#xff0c;很容易出现前后端变量名不一致情况&#xff0c;还不报错&#xff0c;只是单…...