std::vector<Device *> ControllerDatabaseFactory::fetchDevices(
    const std::size_t id ) const {
    std::vector<Device *> devices;
    DatabaseStatement * statement;
    DatabaseResult * result;
    DatabaseResultRow * row;
    std::string query;
    std::size_t deviceId;

    query =
        "SELECT id "
        "FROM devices "
        "WHERE controller_id = ";
    query = query + std::to_string(id);
    statement = getDbConnection()->createStatement(query);
    if( statement != nullptr ) {
        result = statement->execute();
        if( result != nullptr ) {
            while( result->hasNext() ) {
                row = result->next();
                deviceId = static_cast<std::size_t>(
                        atol(row->getColumn(0).c_str()));
                devices.push_back(mDeviceContainer->get(deviceId));
                delete row;
            }
            delete result;
        }
        delete statement;
    }

    return ( devices );
}
Esempio n. 2
0
//-----------------------------------------------------------------------------
// 描述: 执行SQL (若 resultDataSet 为 NULL,则表示无数据集返回。若失败则抛出异常)
//-----------------------------------------------------------------------------
void MySqlQuery::doExecute(DbDataSet *resultDataSet)
{
    /*
    摘自MYSQL官方手册:
    Upon connection, mysql_real_connect() sets the reconnect flag (part of the
    MYSQL structure) to a value of 1 in versions of the API older than 5.0.3,
    or 0 in newer versions. A value of 1 for this flag indicates that if a
    statement cannot be performed because of a lost connection, to try reconnecting
    to the server before giving up. You can use the MYSQL_OPT_RECONNECT option
    to mysql_options() to control reconnection behavior.

    即:只要用 mysql_real_connect() 连接到数据库(而不是 mysql_connect()),那么
    在 mysql_real_query() 调用时即使连接丢失(比如TCP连接断开),该调用也会尝试
    去重新连接数据库。该特性经测试被证明属实。

    注:
    1. 对于 <= 5.0.3 的版本,MySQL默认会重连;此后的版本需调用 mysql_options()
       明确指定 MYSQL_OPT_RECONNECT 为 true,才会重连。
    2. 为了在连接丢失并重连后,能执行“数据库刚建立连接时要执行的命令”,程序明确
       指定不让 mysql_real_query() 自动重连,而是由程序显式重连。
    */

    for (int times = 0; times < 2; times++)
    {
        int r = mysql_real_query(&getConnObject(), sql_.c_str(), (int)sql_.length());

        // 如果执行SQL失败
        if (r != 0)
        {
            // 如果是首次,并且错误类型为连接丢失,则重试连接
            if (times == 0)
            {
                int errNum = mysql_errno(&getConnObject());
                if (errNum == CR_SERVER_GONE_ERROR || errNum == CR_SERVER_LOST)
                {
                    logger().writeStr(SEM_MYSQL_LOST_CONNNECTION);

                    // 强制重新连接
                    getDbConnection()->activateConnection(true);
                    continue;
                }
            }

            // 否则抛出异常
            string sql(sql_);
            if (sql.length() > 1024*2)
            {
                sql.resize(100);
                sql += "...";
            }

            string errMsg = formatString("%s; Error: %s", sql.c_str(), mysql_error(&getConnObject()));
            iseThrowDbException(errMsg.c_str());
        }
        else break;
    }
}
std::vector<ValueType *> ValueTypeDatabaseFactory::fetchAll( void ) {
    DatabaseStatement * statement;
    DatabaseResult * result;
    DatabaseResultRow * row;
    std::vector<ValueType *> types;
    std::string strId;
    long bufferId;
    std::size_t id;
    std::string identifier;
    std::string name;
    std::string description;
    std::string regex;

    statement = getDbConnection()->createStatement(
        "SELECT *"
        "FROM value_types"
    );
    if( statement != nullptr ) {
        result = statement->execute();
        if( result != nullptr ) {
            while( result->hasNext() ) {
                row = result->next();
                strId = row->getColumn(0);
                identifier = row->getColumn(1);
                regex = row->getColumn(2);
                name = row->getColumn(3);
                description = row->getColumn(4);
                bufferId = atol(strId.c_str());
                id = static_cast<std::size_t>(bufferId);
                types.push_back(
                    new ValueType(id,identifier,name,description,regex)
                );
                delete row;
            }
            delete result;
        }
        delete statement;
    }

    return ( types );
}
std::vector<Controller *> ControllerDatabaseFactory::fetchAll( void ) {
    std::vector<Controller *> controllers;
    Controller * controller;
    DatabaseStatement * statement;
    DatabaseResult * result;
    DatabaseResultRow * row;
    std::string id;
    std::string identifier;
    std::string description;
    std::string name;
    std::string securityCode;

    statement = getDbConnection()->createStatement(
        "SELECT * "
        "FROM controllers;"
    );
    if( statement != nullptr ) {
        result = statement->execute();
        if( result != nullptr ) {
            while( result->hasNext() ) {
                row = result->next();
                id = row->getColumn(0);
                identifier = row->getColumn(1);
                securityCode = row->getColumn(2);
                name = row->getColumn(3);
                description = row->getColumn(4);
                controller = allocateController(id,identifier,name,
                                                description,securityCode);
                controllers.push_back(controller);
                delete row;
            }
            delete result;
        }
        delete statement;
    }

    return ( controllers );
}