专题:一个自制代码生成器(嵌入式脚本语言)之模型开发

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


专题:一个自制代码生成器(嵌入式脚本语言)之总述-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之对象模型-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之堆栈结构和总入口-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之核心逻辑-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之辅助逻辑-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之应用实例-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之模型开发-CSDN博客(本篇)

专题:一个自制代码生成器(嵌入式脚本语言)之代码模板详解-CSDN博客


        这是对数据库操作的模型化实现,原则上与代码生成器无关,对同样的模型也可以直接写函数操作数据库,就像普通的动态方法一样。不过使用了代码生成器生成静态代码性能会比较高,也比较方便检查错误。

目录

一、回顾一下对象模型CCTObject

二、各种要素的定义

2.1 列 字段 member

2.2 索引 index

2.3 列组 group

2.4 增删改查 DML

2.5 表 table

2.6 序列 sequence

三、骨干代码

四、使用模型

五、代码模板详解


一、回顾一下对象模型CCTObject

        代码生成器接受的模型用CCTObject来定义,和一般脚本语言定义对象差不多,通过级联实现任意复杂的对象树,主要结构如下:

struct CCTObject
{enum TYPE { OBJECT, POINTER, PROPERTY, ARRAY };TYPE m_type;//根据type决定哪个成员有效CCTObject* m_Pointer;//指针string m_Property;//属性(值)map<string, CCTObject > m_Object;//对象vector<CCTObject >  m_Array;//数组
......
}

        整个模型最终生成到一个CCTObject对象里面。

二、各种要素的定义

2.1 列 字段 member

        对应数据库的列,最关键的属性是名字和类型。

	//成员变量定义struct member{//group为空则为列定义,使用下面一组成员string member_name;string member_comment;//单行string member_type;//long time double stringstring member_default;//默认值string member_show_type;//显示方式//group不为空则为列组访问,使用下面一组成员string group;//组名,string var_name;//变量名//生成数据库类型string makeDBType()const{stringstream ss;if ("string" == member_type)ss << "COLUMN_TYPE_STRING_POOL";else if ("long" == member_type)ss << "COLUMN_TYPE_LONG";else if ("time" == member_type)ss << "COLUMN_TYPE_LONG";else if ("double" == member_type)ss << "COLUMN_TYPE_DOUBLE";else ss << "错误的类型 " << member_type;return ss.str();}//生成参数类型string makeParamType()const{stringstream ss;if ("string" == member_type)ss << "char const *";else if ("long" == member_type)ss << "long const";else if ("time" == member_type)ss << "long const";else if ("double" == member_type)ss << "double const";else ss << "错误的类型 " << member_type;return ss.str();}//生成参数值string makeParamValue()const{stringstream ss;if ("string" == member_type)ss << member_name << ".c_str()";else if ("long" == member_type)ss << member_name;else if ("time" == member_type)ss << member_name;else if ("double" == member_type)ss << member_name;else ss << "错误的类型 " << member_type;return ss.str();}//生成printf类型string makePrintfType()const{stringstream ss;if ("string" == member_type)ss << "%s";else if ("long" == member_type)ss << "%ld";else if ("time" == member_type)ss << "%ld";//else if ("double" == member_type)ss << "%f";else ss << "错误的类型 " << member_type;return ss.str();}//生成HTML输出类型string makeHtmlType()const{stringstream ss;if ("string" == member_type)ss << "CHtmlDoc::CHtmlDoc_DATACLASS_LEFT";else if ("time" == member_type)ss << "CHtmlDoc::CHtmlDoc_DATACLASS_TIME";else ss << "CHtmlDoc::CHtmlDoc_DATACLASS_RIGHT";return ss.str();}//输出到CCTObjectCCTObject toCCTObject(){CCTObject O;if (0 == group.size()){O.SetObjectAddProperty("name", member_name);O.SetObjectAddProperty("GetName", member_name);O.SetObjectAddProperty("GroupIndexVar", "");O.SetObjectAddProperty("comment", member_comment);O.SetObjectAddProperty("type", ("time" == member_type ? "long" : member_type));O.SetObjectAddProperty("default", member_default);O.SetObjectAddProperty("show_type", member_show_type);O.SetObjectAddProperty("DBType", makeDBType());O.SetObjectAddProperty("ParamType", makeParamType());O.SetObjectAddProperty("ParamName", member_name);O.SetObjectAddProperty("PrintfType", makePrintfType());O.SetObjectAddProperty("ParamValue", makeParamValue());O.SetObjectAddProperty("HtmlType", makeHtmlType());}else{O.SetObjectAddProperty("name", var_name);O.SetObjectAddProperty("GetName", "\" + GetGroup" + group + "ColName(" + var_name + ") + \"");O.SetObjectAddProperty("GroupIndexVar", " " + var_name + ",");O.SetObjectAddProperty("ParamType", "long " + var_name + ", long");O.SetObjectAddProperty("ParamName", var_name);O.SetObjectAddProperty("PrintfType", "%ld");}return O;}};

         成员变量的功能是比较显而易见的,另外包含了一组把成员变量的值变成对象模型的属性的方法,最后由toCCTObject()方法变成数据模型对象。

2.2 索引 index

        索引比较简单,因为只是在创建表的时候用一下:

	//索引定义struct index{string index_name;string index_comment;bool unique{ false };string index_members;//输出到CCTObjectCCTObject toCCTObject(){CCTObject O;O.SetObjectAddProperty("name", index_name);O.SetObjectAddProperty("comment", index_comment);O.SetObjectAddProperty("unique", (unique ? "true" : "false"));O.SetObjectAddProperty("members", index_members);return O;}};

2.3 列组 group

        这个只是为了简化经常使用的一组列,并不对应数据库概念:

	//列组定义(可以用下标标识的多个列)struct group{string group_name;string group_comment;vector<member > group_members;//输出到CCTObjectCCTObject toCCTObject(){CCTObject O;O.SetObjectAddProperty("name", group_name);O.SetObjectAddProperty("comment", group_comment);for (vector<member >::iterator it = group_members.begin(); it != group_members.end(); ++it){O.SetObjectArrayPushBack("members", it->toCCTObject());}return O;}};

2.4 增删改查 DML

        所有SQL都用函数包装起来,这样客户代码不会直接使用SQL,等于所有对数据库的操作都集中在一起,以后想找出来哪些表被用到、哪些没有用到就很容易了,只要包装函数没有被调用自然就没有被用到。

	//DML定义struct dml{string dml_name;string dml_type;//select insert update deletestring dml_comment;vector<member > op_members;//操作的列bool hasWhere;//是否有where,当where_members和other_where均为空则不添加此属性vector<member > where_members;//条件列,仅支持 and =string other_where;//直接写死的条件部分//输出到CCTObjectCCTObject toCCTObject(){hasWhere = (where_members.size() != 0 || other_where.size() != 0);CCTObject O;O.SetObjectAddProperty("name", dml_name);O.SetObjectAddProperty("type", dml_type);O.SetObjectAddProperty("comment", dml_comment);for (vector<member >::iterator it = op_members.begin(); it != op_members.end(); ++it){O.SetObjectArrayPushBack("op_members", it->toCCTObject());}if (hasWhere)O.SetObjectAddProperty("hasWhere", hasWhere);for (vector<member >::iterator it = where_members.begin(); it != where_members.end(); ++it){O.SetObjectArrayPushBack("where_members", it->toCCTObject());}if(other_where.size() != 0)O.SetObjectAddProperty("other_where", other_where);return O;}};

        这个模型不允许直接传入SQL的片段,因为这样会破坏封装,实际数据库操作无法预期。

2.5 表 table

        表对象包含以上所有部分,对应一张实体表。

	class table{public:string table_name;string table_comment;vector<member > table_members;string PK_cols;//主键的列vector<index > table_indexs;//主键名称为PKvector<group > table_groups;//可以用下标访问的列组vector<dml > table_dmls;//数据操作,对应一个sqlmember * _getMember(string const & name){for (size_t i = 0; i < table_members.size(); ++i){if (name == table_members[i].member_name)return &table_members[i];}return NULL;}bool SetTable(char const * name, char const * comment){table_name = name;table_comment = comment;return true;}bool AddMember(char const * name, char const * type, char const * comment, char const * _default = "", char const * _show_type=""){member m;m.member_name = name;m.member_type = type;m.member_comment = comment;m.member_default = _default;m.member_show_type = _show_type;if ("string" == m.member_type)m.member_default = "\"" + m.member_default + "\"";else{if (0 == m.member_default.size())m.member_default = "0";}table_members.push_back(m);return true;}//设置主键bool SetPK(char const * PK){PK_cols = PK;StringTokenizer st(PK_cols, ",");for (size_t i = 0; i < st.size(); ++i){member * p = _getMember(st[i].c_str());if (NULL == p){thelog << "主键指定的列不存在 " << st[i] << ende;exit(0);}}return true;}bool AddIndex(char const * name, bool unique,char const * members, char const * comment){StringTokenizer st(members, ",");index tmp;tmp.index_name = name;tmp.unique = unique;tmp.index_comment = comment;tmp.index_members = members;//检查for (size_t i = 0; i < st.size(); ++i){member* p = _getMember(st[i].c_str());if (NULL == p){thelog << "索引指定的列不存在 " << st[i] << ende;exit(0);}}table_indexs.push_back(tmp);return true;}bool AddGroup(char const * name, char const * members, char const * comment){StringTokenizer st(members, ",");group tmp;tmp.group_name = name;tmp.group_comment = comment;for (size_t i = 0; i < st.size(); ++i){member * p = _getMember(st[i].c_str());if (NULL == p){thelog << "列组指定的列不存在 " << st[i] << ende;exit(0);}tmp.group_members.push_back(*p);}table_groups.push_back(tmp);return true;}bool AddDML(char const * name, char const * type, char const * op_members, char const * where_members, char const * comment, char const * other_where = ""){dml tmp;tmp.dml_name = name;tmp.dml_type = type;tmp.dml_comment = comment;tmp.other_where = other_where;if (0 != strlen(op_members)){StringTokenizer st(op_members, ",");for (size_t i = 0; i < st.size(); ++i){if ("*" == st[i]){//全部for (vector<member >::const_iterator it = table_members.begin(); it != table_members.end(); ++it){tmp.op_members.push_back(*it);}}else{StringTokenizer st2(st[i], ":");if (2 == st2.size()){//列组bool isGroupFound = false;for (vector<group >::const_iterator it = table_groups.begin(); it != table_groups.end(); ++it){if (it->group_name == st2[0]){isGroupFound = true;}}if (!isGroupFound){thelog << "op_members指定的列组不存在 " << st2[0] << ende;exit(0);}member tmpmember;tmpmember.group = st2[0];tmpmember.var_name = st2[1];tmp.op_members.push_back(tmpmember);}else{//简单列member * p = _getMember(st[i].c_str());if (NULL == p){thelog << "op_members指定的列不存在 " << st[i] << ende;exit(0);}tmp.op_members.push_back(*p);}}}}if (0 != strlen(where_members)){StringTokenizer st(where_members, ",");for (size_t i = 0; i < st.size(); ++i){member * p = _getMember(st[i].c_str());if (NULL == p){thelog << "where_members指定的列不存在 " << st[i] << ende;exit(0);}tmp.where_members.push_back(*p);}}table_dmls.push_back(tmp);return true;}//输出到CCTObjectCCTObject toCCTObject(){CCTObject O;O.SetObjectAddProperty("name", table_name);O.SetObjectAddProperty("comment", table_comment);O.SetObjectAddProperty("PK_cols", PK_cols);for (vector<member >::iterator it = table_members.begin(); it != table_members.end(); ++it){O.SetObjectArrayPushBack("members", it->toCCTObject());}for (vector<index >::iterator it = table_indexs.begin(); it != table_indexs.end(); ++it){O.SetObjectArrayPushBack("indexs", it->toCCTObject());}for (vector<group >::iterator it = table_groups.begin(); it != table_groups.end(); ++it){O.SetObjectArrayPushBack("groups", it->toCCTObject());}for (vector<dml >::iterator it = table_dmls.begin(); it != table_dmls.end(); ++it){O.SetObjectArrayPushBack("dmls", it->toCCTObject());}return O;}};

2.6 序列 sequence

        序列是个比较头疼的东西,因为不同数据库的支持很不一样,Oracle的序列是独立的数据库对象,Sql Server则是列可以被指定为自增列。

	class sequence{public:string sequence_name;string sequence_init;string sequence_comment;//输出到CCTObjectCCTObject toCCTObject(){CCTObject O;O.SetObjectAddProperty("name", sequence_name);O.SetObjectAddProperty("comment", sequence_comment);O.SetObjectAddProperty("init", sequence_init);return O;}};

三、骨干代码

class CCTModel_UniversalDB
{
private:vector<table > m_tables;vector<sequence > m_sequences;set<string > _table_names;//用来检查是否已经存在set<string > _sequence_names;//用来检查是否已经存在public:CCTObject toCCTObject(){CCTObject O;O.SetObjectAddProperty("name", "CodeTemplate");for (vector<table >::iterator it = m_tables.begin(); it != m_tables.end(); ++it){O.SetObjectArrayPushBack("tables", it->toCCTObject());}for (vector<sequence >::iterator it = m_sequences.begin(); it != m_sequences.end(); ++it){O.SetObjectArrayPushBack("sequences", it->toCCTObject());}return O;}sequence * AddNewSequence(char const * sequencename, char const * comment, long init){if (_sequence_names.end() != _sequence_names.find(sequencename)){thelog << sequencename << " 已经存在" << ende;return NULL;}else{_sequence_names.insert(sequencename);}m_sequences.resize(m_sequences.size() + 1);sequence * p = &m_sequences[m_sequences.size() - 1];p->sequence_name = sequencename;p->sequence_comment = comment;char buf[256];sprintf(buf, "%ld", init);p->sequence_init = buf;return p;}table * AddNewTable(char const * tablename, char const * comment){if (_table_names.end() != _table_names.find(tablename)){thelog << tablename << " 已经存在" << ende;return NULL;}else{_table_names.insert(tablename);}m_tables.resize(m_tables.size() + 1);table * p = &m_tables[m_tables.size() - 1];p->SetTable(tablename, comment);return p;}
public://_ns 名字空间,sys 总类的名称的一部分bool CreateCode(char const * _ns, char const * sys, char const * output_dir){CCTObject O;O = toCCTObject();O.SetObjectAddProperty("NAMESPACE", _ns);O.SetObjectAddProperty("SYS", sys);CCTStack S;CCodeTemplate ct;string str;//thelog << endl << O.toString(str) << endi;S.clear();if (!ct.ProcessFile("_t_UniversalDB.h.ct", (string(output_dir) + "/_cc_" + sys + ".h").c_str(), O, S))return false;vector<CCTObject > * p;if (NULL != O.FindObject("tables")){p = &O.FindObject("tables")->m_Array;for (vector<CCTObject >::iterator it = p->begin(); it != p->end(); ++it){S.clear();S.Push();S.Add("table", *it);//thelog << endl << S.toString(str) << endi;if (!ct.ProcessFile("_t_UniversalDB_table.h.ct", (string(output_dir) + "/_cc_" + sys + "_" + it->GetDefaultValue() + ".h").c_str(), O, S))return false;}}if (NULL != O.FindObject("sequences")){p = &O.FindObject("sequences")->m_Array;for (vector<CCTObject >::iterator it = p->begin(); it != p->end(); ++it){S.clear();S.Push();S.Add("sequence", *it);thelog << endl << S.toString(str) << endi;if (!ct.ProcessFile("_t_UniversalDB_sequence.h.ct", (string(output_dir) + "/_cc_" + sys + "_" + it->GetDefaultValue() + ".h").c_str(), O, S))return false;}}return true;}};

        代码很容易懂。

四、使用模型

        专题:一个自制代码生成器(嵌入式脚本语言)之应用实例-CSDN博客

五、代码模板详解

        下一篇:专题:一个自制代码生成器(嵌入式脚本语言)之代码模板详解-CSDN博客


(这里是结束但不是整个系列的结束)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/778289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FFMPEG对于处理rtp流出现马赛克问题处理

背景 本项目是基于FFMPEG 3.3版本进行的开发。 近期5G发展迅速&#xff0c;无线集群中的带宽不再是瓶颈&#xff0c;对于视频质量的要求也越来越高&#xff0c;现在使用720P、1080P、2K、4K进行视频通话成为了日常。 问题描述 本项目之前对于CIF和VGA格式的视频进行录…

Spring Boot 一些常用的高级特性

Spring Boot 提供了许多高级特性&#xff0c;这些特性旨在简化开发流程、提高开发效率、增强应用的功能和性能。下面是一些重要的高级特性&#xff1a; 1. 自动配置&#xff08;Auto-configuration&#xff09; Spring Boot 的自动配置尝试根据添加到项目中的jar依赖自动配置…

通过 key 管理状态

Vue 默认按照“就地更新”的策略来更新通过 v-for 渲染的元素列表。当数据项的顺序改变时&#xff0c;Vue 不会随之移动 DOM 元素的顺序&#xff0c;而是就地更新每个元素&#xff0c;确保它们在原本指定的索引位置上渲染。 默认模式是高效的&#xff0c;但只适用于列表渲染输…

【python 数据可视化】 WordCloud词云图

目录 词云简介 准备工作 安装方法一&#xff1a; 安装方法二&#xff1a; 生成词云步骤 数据预处理&#xff1a; 分词&#xff1a; 统计词频出现的次数&#xff1a; 去除词语&#xff1a; 生成词云&#xff1a; 显示词云&#xff1a; 保存词云&#xff1a; 完整代码 词…

AugmentedReality之路-通过蓝图启动AR相机(2)

本文实现打开AR相机和关闭AR相机功能&#xff0c;在主界面点击Start AR按钮后打开AR相机&#xff0c;在主界面点击Stop AR按钮后关闭AR相机 1、启动AR相关插件 通过Edit->Plugins启用AugmentedReality下面的所有插件 2、自定义Pawn 在Content->ARBase目录右键&…

iOS开发进阶(十一):ViewController 控制器详解

文章目录 一、前言二、UIViewController三、UINavigationController四、UITabBarController五、UIPageViewController六、拓展阅读 一、前言 iOS 界面开发最重要的首属ViewController和View&#xff0c;ViewController是View的控制器&#xff0c;也就是一般的页面&#xff0c;…

Hive详解(3)

Hive 数据类型 struct类型 struct&#xff1a;结构体&#xff0c;对应了Java中的对象&#xff0c;实际上是将数据以json形式来进行存储和处理 案例 原始数据 a tom,19,male amy,18,female b bob,18,male john,18,male c lucy,19,female lily,19,female d henry,18,male davi…

基于ssm网上服装销售系统论文

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于网上服装销售系统系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了网上服装销售系统系统&#xff0c;它彻底…

UNDERSTANDING HTML WITH LARGE LANGUAGE MODELS

UNDERSTANDING HTML WITH LARGE LANGUAGE MODELS 相关链接&#xff1a;arXiv 关键字&#xff1a;大型语言模型、HTML理解、Web自动化、自然语言处理、机器学习 摘要 大型语言模型&#xff08;LLMs&#xff09;在各种自然语言任务上表现出色。然而&#xff0c;它们在HTML理解方…

【JS笔记】JavaScript语法 《基础+重点》 知识内容,快速上手(六)

面向对象OOP 首先&#xff0c;我们要明确&#xff0c;面向对象不是语法&#xff0c;是一个思想&#xff0c;是一种 编程模式面向&#xff1a; 面&#xff08;脸&#xff09;&#xff0c;向&#xff08;朝着&#xff09;面向过程&#xff1a; 脸朝着过程 》 关注着过程的编程模…

shell脚本发布docker springboot项目示例

docker、git、Maven、jdk8安装略过。 使git pull或者git push不需要输入密码操作方法 约定&#xff1a; 路径&#xff1a;/opt/springbootdemo&#xff0c; 项目&#xff1a;springbootdemo&#xff0c; 打包&#xff1a;springbootdemo.jar&#xff0c; docker容器名字&#x…

Netty 代理TCP 转发集群方案

使用 Netty 自定义协议连接物联网设备&#xff0c;业务增大之后&#xff0c;势必需要使用集群方案。 #nginx负载均衡 Nginx 1.9 已经支持 TCP 代理和负载均衡&#xff0c;并可以通过一致性哈希算法将连接均匀的分配到所有的服务器上。 修改配置文件 http{ … } stream{ ups…

Android ImageView以及实现截图

实现效果 截图前 截图后 代码 package cn.jj.huaweiad;import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.view.ViewGro…

硬件项目中的turn-key 是啥意思?案例应用

在硬件项目中&#xff0c;turn-key是指一种工程项目模式&#xff0c;即交钥匙工程。这种模式通常由独立的第三方软件厂商直接与芯片厂商合作&#xff0c;基于芯片厂商的硬件方案和协议&#xff0c;集成成熟的上层软件和应用&#xff0c;并整套提供给电子产品生产厂商。这种模式…

LLM之RAG实战(三十五)| 使用LangChain的3种query扩展来优化RAG

RAG有时无法从矢量数据库中检索到正确的文档。比如我们问如下问题&#xff1a; 从1980年到1990年&#xff0c;国际象棋的规则是什么&#xff1f; RAG在矢量数据库中进行相似性搜索&#xff0c;来查询与国际象棋规则问题相关的相关文档。然而&#xff0c;在某些情况下&#xff0…

Ioc容器创建 和 读取组件的测试类

A接口 package com.atguigu.Ioc_03;public interface A {void dowork(); }HappyComponent.java package com.atguigu.Ioc_03;public class HappyComponent implements A {// 默认包含无参的构造方法Overridepublic void dowork() {System.out.println("我是&#xff1a;…

平台介绍-搭建赛事运营平台(3)

上文介绍了品牌隔离的基本原理&#xff0c;就是通过不同的前端和微服务来实现。但是确实很多功能是类似的&#xff0c;所以从编程角度还是有些管理手段的。 前端部分&#xff1a;前端部分没有什么特别手段&#xff0c;就是两个独立的项目工程&#xff0c;分别维护。相同的部分复…

I.MX6ULL_Linux_驱动篇(55)linux 网络驱动

网络驱动是 linux 里面驱动三巨头之一&#xff0c; linux 下的网络功能非常强大&#xff0c;嵌入式 linux 中也常常用到网络功能。前面我们已经讲过了字符设备驱动和块设备驱动&#xff0c;本章我们就来学习一下linux 里面的网络设备驱动。 嵌入式网络简介 网络硬件接口 首先…

LeetCode_Java_字符串相加(题目+思路+代码)

415.字符串相加 给定两个字符串形式的非负整数 num1 和num2 &#xff0c;计算它们的和并同样以字符串形式返回。 你不能使用任何內建的用于处理大整数的库&#xff08;比如 BigInteger&#xff09;&#xff0c; 也不能直接将输入的字符串转换为整数形式。 思路&#xff1a; 1…

如何降低 BlueNRG-LPS 的开机峰值电流

1. 前言 BlueNRG 系列存在开机瞬间会出现很大的峰值电流的现象&#xff0c;预计有 20ma 左右。针对此现象&#xff0c;经常有客户询问该峰值电流会不会导致设备工作异常&#xff1f;会不会导致电池使用寿命缩短&#xff08;考虑到一般纽扣电池能承受的峰值电流大概在 15ma 左右…