sqlite数据库自动升级设计

1. 要求

在sqlite表结构发生变化后,现场升级数据库db文件,能够自动完成。并要求旧表中的数据不能丢失或破坏。
sqlite表结构发生变化,指的是数据库表个数发生变化,或者表中的字段(字段名字,字段类型,字段个数,字段顺序)发生变化。

2. 设计

2.1 升级条件

在现有数据库表字段与最新数据库表字段不相同的情况下,需要升级该表。
相同:指的是字段名称和顺序相同。

2.2 新旧表结构是否相同的情况

这里写图片描述
上述A~H 8种情况,可分为两类,A~D是第一类顺序相同名称不同,E~H 是第二类顺序和名称都不相同。
8种情况处理如下:
A情况:不用变动
B情况:给旧表新增列
C情况:将旧表通过swap方法升级为新表
D情况:处理同C
E情况:处理同C。E其实和A是相同的。但是因为现在软件代码中插入记录使用的是bind方法,bind方法要求插入的字段和顺序与数据库表中的字段和顺序相同。所以才不得不将E单独处理。
F情况:处理同C。F同B
G情况:处理同C。G同C
H情况:处理同C。H同D

2.3 Swap方法

1、 将被升级的旧表重命名
2、 创建新表
3、 将被升级表的数据插入到新表中
4、 删除旧表

3. 代码实现

sqlite基于3.8.4.3版本。仅给出主要数据结构设计。
主要的类设计有两个:Sqlite3 和 DB_upgrade
Sqlite3 类负责打开、关闭db文件,并将db文件中的表和字段都读取出来。
DB_upgrade 类负责对db文件升级过程的整体调度、判断和执行。它会将旧db升级为新db;如果db文件不存在则会直接创建该db。


class Sqlite3:public CppSQLite3DB
{
public:
    Sqlite3(){};
    ~Sqlite3(){};
    void Open(std::string dbname);
    void Close();

    void Load();

public:
    enum ColumnStatus
    {
        cs_equal,               //0-新旧表都有,且位置相同
        cs_not_exist_in_old,    //1-旧表有新表无
        cs_not_exist_in_new,    //2-旧表无新表有
        cs_pos_diffrent,        //3-新旧表都有,但位置不同
    };
    enum TableStatus
    {
    /*
        Table_old表字段   Table_new表字段
        x,y,z             x,y,z              A情况
        x,y               x,y,z              B情况
        x,y,w             x,y,z              C情况
        x,y,z,w           x,y,z              D情况
        x,z,y             x,y,z              E情况
        x,z,y             x,y,z,w            F情况
        x,z,w             x,y,z              G情况
        x,z,y,w           x,y,z              H情况

        对于情况A,不需要变动Table_old表。
        对于情况B,只需要给Table_old表新增列即可。
        对于情况C/D/E/F/G/H,都可采用swap方法实现升级。
        swap方法见设计文档。
    */
        ts_A,  //A情况
        ts_B,  //B情况
        ts_C,  //C情况
        ts_D,  //D情况
        ts_E,  //E情况
        ts_F,  //F情况
        ts_G,  //G情况
        ts_H,  //H情况
        ts_Q,  //一个表在新库中有但在旧库中没有,标记为本值。
        ts_default, //初始值
    };
    //sqlite_master实际存储的是每个表的信息
    struct sqlite_master
    {
        std::string type;   //有"index"/"table"两个值
        std::string name;
        std::string tbl_name;
        int         rootpage;
        std::string sql;    //对于表是建表语句
    };
    //table_info实际存储的是每个表中所有字段的信息
    struct table_info
    {
        int cid;
        std::string name;
        std::string type;
        int notnull;
        std::string dflt_value;
        int pk;

        ColumnStatus cs;
    };

    struct TableInfo
    {
        sqlite_master table;
        std::vector<table_info> columns;

        TableStatus ts;
    };

    /* m_mapMaster 
      key:tbl_name
      value:TableInfo
    */
    typedef std::map<std::string,TableInfo> T_TableInfo;
    T_TableInfo m_mapMaster;

    std::string m_dbname;
};
class DB_upgrade  
{  
public:  
    DB_upgrade();  
    ~DB_upgrade();  
    void Set(std::string dbSrc,std::string dbTmp,int tableNums,const char **tableNameArray,const char **tableSqlArray);  

    /* 构建或升级数据库表结构 */  
    void CreateOrUpgradeTable();  

private:  
    void CreateTable();  
    void UpgradeTable();  
private:  
    void CreateTmpTable();  
    void DeleteTmpTable();  

    bool CheckCaseA(Sqlite3::TableInfo &src,Sqlite3::TableInfo &tmp);  
    bool CheckCaseB(Sqlite3::TableInfo &src,Sqlite3::TableInfo &tmp);  
    void AddNewColumns(Sqlite3 &sqto,Sqlite3::TableInfo &to,Sqlite3::TableInfo &from);  
    void Swap(Sqlite3 &sqto,Sqlite3::TableInfo &to,Sqlite3 &sqfrom,Sqlite3::TableInfo &from);  
    void KeepSameColumns(std::vector<Sqlite3::table_info> &to,std::vector<Sqlite3::table_info> &from);  
private:  
    std::string m_dbTmp;  
    std::string m_dbSrc;  
    int m_tableNums;  
    char **m_tableNameArray;  
    char **m_tableSqlArray;  
};  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值