mysql数据库操作通用库,通过xml解析获取建表、数据库、触发器、操作对象

介绍了一个开源项目,旨在通过XML解析简化不同数据库的操作。该项目提供了一个通用库,用于管理数据库对象,包括表、SQL语句和触发器。用户可以通过库中的方法获取数据库配置,如主机、端口、用户名、密码等,并支持数据库、表和触发器的管理。源码托管在GitHub上,鼓励感兴趣的人士查阅和反馈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

限于不同数据库操作每次都要大量的重写代码,去适用不同的数据库,最近在github上做了个开源项目,把数据库这部分操作做了一个通用库,通过xml解析来简化操作数据库编码,有兴趣的同学可以去https://github.com/shukcs/GServer看看,数据库操作在vgmysql目录下,觉得好的,请帮忙在github上点赞

数据库操作对象管理器

头文件
#include <list>
#include <string>

class ExecutItem;
class VGTable;
class VGTrigger;
class TiXmlElement;
class TiXmlNode;
class TiXmlDocument;
class MySqlStruct;

class VGDBManager
{
public:
    typedef std::list<std::string> StringList;
public:
    ~VGDBManager();

    std::string Load(const TiXmlDocument &doc, StringList &tbs);
    VGTable *GetTableByName(const std::string &name)const;
    ExecutItem *GetSqlByName(const std::string &name)const;
    VGTrigger *GetTriggerByName(const std::string &name)const;
    const char *GetMysqlHost(const std::string &db ="")const;
    int GetMysqlPort(const std::string &db="")const;
    const char *GetMysqlUser(const std::string &db="")const;
    const char *GetMysqlPswd(const std::string &db = "")const;
    const char *GetMysqlCharSet(const std::string &db = "")const;
    StringList GetDatabases()const;
    StringList GetTriggers()const;
public:
    static SHARED_SQL VGDBManager &Instance();
    static SHARED_SQL long str2int(const std::string &str, unsigned radix=10, bool *suc=NULL);
    static SHARED_SQL StringList SplitString(const std::string &str, const std::string &sp, bool bSkipEmpty = true);
    template<typename T, typename Contianer = std::list<T> >
    static bool IsContainsInList(const Contianer ls, const T &e)
    {
        for (const T &itr : ls)
        {
            if (itr == e)
                return true;
        }
        return false;
    }
private:
    VGDBManager();

    std::string parseDatabase(const TiXmlElement *e);
    StringList parseTables(const TiXmlNode *node);
    void parseSqls(const TiXmlNode *node);
    void parseTriggers(const TiXmlNode *node);
    MySqlStruct *_getDbStruct(const std::string &)const;
private:
    std::list<VGTable*>     m_tables;
    std::list<ExecutItem*>  m_sqls;
    std::list<MySqlStruct*> m_mysqls;
    std::list<VGTrigger*>   m_triggers;
};

实现

#include "VGDBManager.h"
#include "DBExecItem.h"
#include <tinyxml.h>
#include <VGTrigger.h>

static const char *sDefualtDb[5] = {
    "127.0.0.1",
    "gsuav",
    "root",
    "",
    "utf8"
};
//
//VGDBManager
//
class MySqlStruct
{
public:
    MySqlStruct() :m_port(3306) {}
    MySqlStruct(const MySqlStruct &oth) :m_port(oth.m_port)
        , m_host(oth.m_host), m_database(oth.m_host)
        , m_user(oth.m_host), m_pswd(oth.m_host)
        , m_charSet(oth.m_charSet){ }
    int                     m_port;
    std::string             m_host;
    std::string             m_database;
    std::string             m_user;
    std::string             m_pswd;
    std::string             m_charSet;
};
//
//VGDBManager
//
VGDBManager::VGDBManager()
{
}

VGDBManager::~VGDBManager()
{
    for (VGTable *itr : m_tables)
    {
        delete itr;
    }

    for (ExecutItem *itr : m_sqls)
    {
        delete itr;
    }

    for (MySqlStruct *itr : m_mysqls)
    {
        delete itr;
    }

    for (VGTrigger *itr : m_triggers)
    {
        delete itr;
    }
}

VGDBManager &VGDBManager::Instance()
{
    static VGDBManager sIns;
    return sIns;
}

long VGDBManager::str2int(const std::string &str, unsigned radix, bool *suc)
{
    unsigned count = str.length();
    bool bSuc = false;
    bool bSubMin = false;
    const char *c = str.c_str();
    long nRet = 0;
    if ((8==radix || 10==radix || 16== radix) && count >0)
    {
        unsigned i = 0;
        while (' ' == c[i] || '\t' == c[i])++i;
        if (i < count && (c[i] == '+' || c[i] == '-'))
        {
            if (c[i] == '-')
                bSubMin = true;
            ++i;
        }
        if (i < count)
            bSuc = true;
        for (; i < count; ++i)
        {
            int nTmp = c[i] - '0';
            if (nTmp > 10 && radix == 16)
                nTmp = 10 + (c[i] > 'F' ? c[i] - 'a' : c[i] - 'A');

            if (nTmp < 0 || nTmp >= int(radix))
            {
                if (' ' != c[i] && '\t' != c[i])
                    bSuc = false;
                break;
            }
            nRet = nRet * radix + (bSubMin ? -nTmp : nTmp);
        }
    }
    if (suc)
        *suc = bSuc;

    return bSuc ? nRet : 0;
}

list<string> VGDBManager::SplitString(const std::string &str, const std::string &sp, bool bSkipEmpty /*= true*/)
{
    list<string> strLsRet;
    int nSizeSp = sp.size();
    if (!nSizeSp)
        return strLsRet;

    unsigned nPos = 0;
    while (nPos < str.size())
    {
        int nTmp = str.find(sp, nPos);
        string strTmp = str.substr(nPos, nTmp < 0 ? -1 : nTmp - nPos);
        if (strTmp.size() || !bSkipEmpty)
            strLsRet.push_back(strTmp);

        if (nTmp < int(nPos))
            break;
        nPos = nTmp + nSizeSp;
    }
    return strLsRet;
}

string VGDBManager::Load(const TiXmlDocument &doc, StringList &tbs)
{
    if (const TiXmlElement *rootElement = doc.RootElement())
    {
        const TiXmlNode *node = rootElement->FirstChild("Database");
        if (!node)
            return string();

        tbs = parseTables(rootElement->FirstChild("Tables"));
        parseSqls(rootElement->FirstChild("SQLs"));
        parseTriggers(rootElement->FirstChild("Triggers"));

        return parseDatabase(node->ToElement());
    }

    return string();
}

VGTable *VGDBManager::GetTableByName(const std::string &name) const
{
    if (name.length() < 1)
        return NULL;

    for (VGTable *itr : m_tables)
    {
        if (itr->GetName() == name)
            return itr;
    }
    return NULL;
}

ExecutItem *VGDBManager::GetSqlByName(const std::string &name) const
{
    if (name.empty())
        return NULL;

    for (ExecutItem *itr : m_sqls)
    {
        if (itr->GetName() == name)
            return itr;
    }
    return NULL;
}

VGTrigger *VGDBManager::GetTriggerByName(const std::string &name) const
{
    if (name.empty())
        return NULL;

    for (VGTrigger *itr : m_triggers)
    {
        if (itr->GetName() == name)
            return itr;
    }
    return NULL;
}

const char *VGDBManager::GetMysqlHost(const std::string &db) const
{
    if (MySqlStruct *dbs = _getDbStruct(db))
        return dbs->m_host.c_str();

    return sDefualtDb[0];
}

int VGDBManager::GetMysqlPort(const std::string &db/*=""*/) const
{
    if (MySqlStruct *dbs = _getDbStruct(db))
        return dbs->m_port;

    return 3306;
}

const char *VGDBManager::GetMysqlUser(const std::string &db/*=""*/) const
{
    if (MySqlStruct *dbs = _getDbStruct(db))
        return dbs->m_user.c_str();

    return sDefualtDb[2];
}

const char *VGDBManager::GetMysqlPswd(const std::string &db/*=""*/) const
{
    if (MySqlStruct *dbs = _getDbStruct(db))
        return dbs->m_pswd.c_str();

    return sDefualtDb[3];
}

const char *VGDBManager::GetMysqlCharSet(const std::string &db) const
{
    if (MySqlStruct *dbs = _getDbStruct(db))
        return dbs->m_charSet.c_str();

     return sDefualtDb[4];;
}

list<string> VGDBManager::GetDatabases() const
{
    list<string> ret;
    for (MySqlStruct *itr : m_mysqls)
    {
        if(itr)
            ret.push_back(itr->m_database);
    }

    return ret;
}

StringList VGDBManager::GetTriggers() const
{
    StringList ret;
    for (VGTrigger *itr : m_triggers)
    {
        ret.push_back(itr->GetName());
    }

    return ret;
}

StringList VGDBManager::parseTables(const TiXmlNode *node)
{
    StringList ret;
    if (!node)
        return ret;

    const TiXmlNode *table = node ? node->FirstChild("table") : NULL;
    while (table)
    {
        if (VGTable *tb = VGTable::ParseTable(*table->ToElement()))
        {
            m_tables.push_back(tb);
            ret.push_back(tb->GetName());
        }

        table = table->NextSibling("table");
    }

    return ret;
}

void VGDBManager::parseSqls(const TiXmlNode *node)
{
    const TiXmlNode *sql = node ? node->FirstChild("SQL") : NULL;
    while (sql)
    {
        if (ExecutItem *item = ExecutItem::parse(sql->ToElement()))
        {
            if (item->GetName().length() > 0 && NULL == GetTableByName(item->GetName()))
                m_sqls.push_back(item);
            else
                delete item;
        }

        sql = sql->NextSibling("SQL");
    }
}

void VGDBManager::parseTriggers(const TiXmlNode *node)
{
    const TiXmlNode *tgNode = node ? node->FirstChild("Trigger") : NULL;
    while (tgNode)
    {
        if (VGTrigger *trg = VGTrigger::Parse(*tgNode->ToElement()))
            m_triggers.push_back(trg);

        tgNode = tgNode->NextSibling("Trigger");
    }
}

string VGDBManager::parseDatabase(const TiXmlElement *e)
{
    if (!e)
        return string();

    MySqlStruct sqlSrv;

    const char *tmp = e->Attribute("user");
    sqlSrv.m_user = tmp ? tmp : "root";

    tmp = e->Attribute("pswd");
    sqlSrv.m_pswd = tmp ? tmp : "root";

    tmp = e->Attribute("host");
    sqlSrv.m_host = tmp ? tmp : "127.0.0.1";

    tmp = e->Attribute("port");
    sqlSrv.m_port = tmp ? str2int(tmp):3306;

    tmp = e->Attribute("database");
    if (!tmp)
        return string();
    if (const char *tmpS = e->Attribute("charSet"))
        sqlSrv.m_charSet = tmpS;

    sqlSrv.m_database = tmp;
    m_mysqls.push_back(new MySqlStruct(sqlSrv));
    return sqlSrv.m_database;
}

MySqlStruct *VGDBManager::_getDbStruct(const std::string &db)const
{
    for (MySqlStruct *itr : m_mysqls)
    {
        if (itr && (db.empty() || db == itr->m_database))
            return itr;
    }
    return NULL;
}


MySql操作

头文件

#include <string>
#include <list>
#include <map>

typedef struct st_mysql MYSQL;
typedef struct st_mysql_stmt MYSQL_STMT;
typedef struct st_mysql_bind MYSQL_BIND;
typedef struct st_mysql_res MYSQL_RES;

class FiledValueItem;
class ExecutItem;
class VGTable;
class VGTrigger;

class VGMySql
{
public:
    VGMySql();
    VGMySql(const char *host, int port, const char *user, const char *pswd);
    virtual ~VGMySql();

    bool ConnectMySql(const char *host, int port, const char *user, const char *pswd);
    bool IsValid() const;

    bool Execut(ExecutItem *item);
    ExecutItem *GetResult();
    bool EnterDatabase(const std::string &db, const char *cset=NULL);
    bool ExistTable(const std::string &name);
    bool CreateTable(VGTable *tb);
    bool ExistTrigger(const std::string &name);
    bool CreateTrigger(VGTrigger *trigger);

    MYSQL_RES *Query(const std::string &sql);
protected:
    bool _canOperaterDB();
    bool _executChange(const std::string &sql, MYSQL_BIND *binds, FiledValueItem *i=NULL);
    bool _changeItem(ExecutItem *item);
    bool _selectItem(ExecutItem *item);
    std::string _getTablesString(const ExecutItem &item);
    MYSQL_STMT *_prepareMySql(const std::string &fmt, MYSQL_BIND *binds, int nRead=0);
    void _checkPrepare();
private:
    MYSQL                *m_mysql;
    std::string            m_host;
    int                    m_nPort;
    std::string            m_user;
    std::string            m_pswd;
    bool                m_bValid;
    ExecutItem          *m_execItem;
    MYSQL_BIND          *m_binds;
    MYSQL_STMT          *m_stmt;
};

MySql操作实现

#include "VGMysql.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if !defined _WIN32 && !defined _WIN64
#include <mysql/mysql.h>
#else
#include <mysql.h>
#endif
#include "DBExecItem.h"
#include "VGDBManager.h"
#include "VGTrigger.h"

using namespace std;

VGMySql::VGMySql() : m_bValid(false)
, m_binds(NULL) , m_stmt(NULL)
{
    m_mysql = mysql_init(NULL);
    if(!m_mysql)
        return;
}

VGMySql::VGMySql( const char *host, int port, const char *user, const char *pswd)
: m_bValid(false), m_binds(NULL), m_stmt(NULL)
{
    m_mysql = mysql_init(NULL);
    if(!m_mysql)
        return;

    ConnectMySql(host, port, user, pswd);
}

bool VGMySql::IsValid() const
{
    return m_mysql!=NULL && m_bValid;
}

VGMySql::~VGMySql()
{
    _checkPrepare();
    if (m_mysql)
         mysql_close(m_mysql);
}

bool VGMySql::Execut(ExecutItem *item)
{
    if (!item->IsValid())
        return false;

    switch (item->GetType())
    {
    case ExecutItem::Insert:
    case ExecutItem::Delete:
    case ExecutItem::Update:
        return _changeItem(item);
    case ExecutItem::Select:
        return _selectItem(item);
    default:
        break;
    }
    return false;
}

ExecutItem *VGMySql::GetResult()
{
    if (!m_stmt || !m_execItem || !m_binds || mysql_stmt_fetch(m_stmt))
        _checkPrepare();

    return m_execItem;
}

bool VGMySql::EnterDatabase(const std::string &db, const char *cset)
{
    bool ret = false;
    if (db.empty())
        return ret;

    char tmp[128];
    const char *set = cset ? cset : "utf8";
    sprintf(tmp, "default character set %s collate %s_general_ci", set, set);
    string sql = string("create database if not exists ") + db + " " + tmp;
    if (MYSQL_RES *res = Query(sql))
    {
        my_ulonglong nNum = mysql_num_rows(res);
        mysql_free_result(res);
        ret = nNum > 0;
    }

    if (MYSQL_RES *res = Query(string("use ") + db))
        mysql_free_result(res);

    return ret;
}

bool VGMySql::ExistTable(const std::string &name)
{
    if (!_canOperaterDB() || name.empty())
        return false;

    string sql;
    sql.resize(name.length()+20);
    sprintf(&sql.at(0), "show tables like \'%s\'", name.c_str());

    if (MYSQL_RES *res = Query(sql.c_str()))
    {
        my_ulonglong nNum = mysql_num_rows(res);
        mysql_free_result(res);
        return nNum > 0;
    }
    return false;
}

bool VGMySql::CreateTable(VGTable *tb)
{
    if (!tb || !_canOperaterDB())
        return false;

    
    if (MYSQL_RES *res = Query(tb->ToCreateSQL()))
        mysql_free_result(res);

    return ExistTable(tb->GetName());
}

bool VGMySql::ExistTrigger(const std::string &name)
{
    if (!_canOperaterDB() || name.empty())
        return false;

    static string sTrigExFmt = "SELECT TRIGGER_NAME FROM information_schema.triggers ";
    string sql= sTrigExFmt+"where TRIGGER_NAME='" + name+"'";

    if (MYSQL_RES *res = Query(sql))
    {
        my_ulonglong nNum = mysql_num_rows(res);
        mysql_free_result(res);
        return nNum > 0;
    }
    return false;
}

bool VGMySql::CreateTrigger(VGTrigger *trigger)
{
    if (!trigger || ExistTrigger(trigger->GetName()))
        return false;

    if (MYSQL_RES *res = Query(trigger->ToSqlString()))
    {
        mysql_free_result(res);
        return true;
    }
    return false;
}

bool VGMySql::_canOperaterDB()
{
    if (m_bValid && mysql_ping(m_mysql))
    {
        if (mysql_real_connect(m_mysql, m_host.c_str(), m_user.c_str(), m_pswd.c_str(), NULL, m_nPort, NULL, 0))
            return false;
    }
    return m_bValid;
}

bool VGMySql::ConnectMySql( const char *host, int port, const char *user, const char *pswd)
{
    if (!m_mysql)
        return m_bValid = false;

    if (mysql_real_connect(m_mysql, host, user, pswd, NULL, port, NULL, 0))
    {
        m_host = host ? host : string();
        m_nPort = port;
        m_user = user ? user : string();
        m_pswd = pswd ? pswd : string();
        return m_bValid = true;
    }

    fprintf(stderr, " mysql_real_connect() failed %s\n", mysql_error(m_mysql));
    string strErr = mysql_error(m_mysql);
    return m_bValid = false;
}

bool VGMySql::_executChange(const string &sql, MYSQL_BIND *binds, FiledValueItem *i)
{
    MYSQL_STMT *stmt = _prepareMySql(sql, binds);
    if (!stmt)
        return false;

    bool ret = true;
    if (mysql_stmt_affected_rows(stmt) < 1)
        ret = false;

    if(i)
    {
        uint64_t n = mysql_insert_id(m_mysql);
        i->InitBuff(sizeof(n), &n);
    }
    mysql_stmt_close(stmt);
    return ret;
}

bool VGMySql::_changeItem(ExecutItem *item)
{
    if (!item || !item->IsValid())
        return false;

    if (!_canOperaterDB())
        return false;

    MYSQL_BIND *binds  = item->GetParamBinds();
    string sql = item->GetSqlString(binds);

    bool ret = false;
    if (sql.length() > 0)
    {
        if (item->HasForeignRefTable())
        {
            if (MYSQL_RES *res = Query("SET FOREIGN_KEY_CHECKS=0"))
                mysql_free_result(res);
        }
        ret = _executChange(sql, binds, item->GetIncrement());
        if (item->HasForeignRefTable())
        {
            if (MYSQL_RES *res = Query("SET FOREIGN_KEY_CHECKS=1"))
                mysql_free_result(res);
        }
    }

    delete binds;
    return ret;
}

bool VGMySql::_selectItem(ExecutItem *item)
{
    _checkPrepare();
    int count = item ? item->CountRead() : 0;
    if (count < 1 || !item->IsValid() || item->GetType() != ExecutItem::Select)
        return false;
    if (!_canOperaterDB())
        return false;

    MYSQL_BIND *params = item->GetParamBinds();
    string sql = item->GetSqlString(params);
    MYSQL_STMT *stmt = _prepareMySql(sql, params);
    if (!stmt)
    {
        delete params;
        return false;
    }
    MYSQL_BIND *binds = item->TransformRead();
    bool ret = false;
    if (mysql_stmt_bind_result(stmt, binds))
        fprintf(stderr, "mysql_stmt_bind_result() failed! %s\n", mysql_stmt_error(stmt));
    else if (mysql_stmt_store_result(stmt))
        fprintf(stderr, " mysql_stmt_store_result() failed %s\n", mysql_stmt_error(stmt));
    else if (mysql_stmt_fetch(stmt))
        fprintf(stderr, " mysql_stmt_fetch() failed %s\n", mysql_stmt_error(stmt));
    else
        ret = true;

    delete params;
    if (!ret)
    {
        delete binds;
        if(stmt)
        {
            mysql_stmt_free_result(stmt);
            mysql_stmt_close(stmt);
        }
        return false;
    }

    m_binds = binds;
    m_stmt = stmt;
    m_execItem = item;
    return true;
}

MYSQL_STMT *VGMySql::_prepareMySql(const string &strFormat, MYSQL_BIND *binds, int nRead)
{
    MYSQL_STMT *stmt = mysql_stmt_init(m_mysql);
    if (!stmt)
    {
        fprintf(stderr, " mysql_stmt_init(), out of memory\n");
        return NULL;
    }
    bool ret = false;
    if (mysql_stmt_prepare(stmt, strFormat.c_str(), strFormat.length()))
        fprintf(stderr, "mysql_stmt_prepare() failed! %s\n", mysql_stmt_error(stmt));
    else if (binds && mysql_stmt_bind_param(stmt, binds))
        fprintf(stderr, "mysql_stmt_bind_param() failed\n");
    else
        ret = true;

    if (ret && nRead>0)
    {
        MYSQL_RES *preRes = mysql_stmt_result_metadata(stmt);
        if (!preRes || nRead != (int)mysql_num_fields(preRes))
            ret = false;
    }
    if (ret && mysql_stmt_execute(stmt))
    {
        fprintf(stderr, "mysql_stmt_execute(), %s failed\n", mysql_error(m_mysql));
        ret = false;
    }

    if (!ret)
    {
        mysql_stmt_close(stmt);
        stmt = NULL;
    }

    return stmt;
}

void VGMySql::_checkPrepare()
{
    if (m_binds)
    {
        delete m_binds;
        m_binds = NULL;
    }
    if (m_stmt)
    {
        mysql_stmt_free_result(m_stmt);
        mysql_stmt_close(m_stmt);
        m_stmt = NULL;
    }

    m_execItem = NULL;
}

std::string VGMySql::_getTablesString(const ExecutItem &item)
{
    string ret;
    for (const string &table : item.ExecutTables())
    {
        ret += " " + table;
    }
    return ret;
}

MYSQL_RES *VGMySql::Query(const std::string &sql)
{
    if (mysql_real_query(m_mysql, sql.c_str(), sql.length()))
    {
        fprintf(stderr, "mysql_real_query() failed! %s\n", mysql_error(m_mysql));
        return NULL;
    }

    return mysql_store_result(m_mysql);
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值