예제 #1
0
/**
 * Execute a SQL query.
 */
const RecordSet &MySqlDataProvider::execSql(const std::string& sql,
                                            const bool refresh)
{
    if (!mIsConnected)
        throw std::runtime_error("not connected to database");

    LOG_DEBUG("MySqlDataProvider::execSql Performing SQL query: " << sql);

    // do something only if the query is different from the previous
    // or if the cache must be refreshed
    // otherwise just return the recordset from cache.
    if (refresh || (sql != mSql))
    {
        mRecordSet.clear();

        // actually execute the query.
        if (mysql_query(mDb, sql.c_str()) != 0)
            throw DbSqlQueryExecFailure(mysql_error(mDb));

        if (mysql_field_count(mDb) > 0)
        {
            MYSQL_RES* res;

            // get the result of the query.
            if (!(res = mysql_store_result(mDb)))
                throw DbSqlQueryExecFailure(mysql_error(mDb));

            // set the field names.
            unsigned nFields = mysql_num_fields(res);
            MYSQL_FIELD* fields = mysql_fetch_fields(res);
            Row fieldNames;
            for (unsigned i = 0; i < nFields; ++i)
                fieldNames.push_back(fields[i].name);

            mRecordSet.setColumnHeaders(fieldNames);

            // populate the RecordSet.
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res)))
            {
                Row r;

                for (unsigned i = 0; i < nFields; ++i)
                    r.push_back(static_cast<char *>(row[i]));

                mRecordSet.add(r);
            }

            // free memory
            mysql_free_result(res);
        }
    }

    return mRecordSet;
}
예제 #2
0
void MySqlDataProvider::rollbackTransaction()
    throw (std::runtime_error)
{
    if (!mIsConnected)
    {
        const std::string error = "Trying to rollback a transaction while not "
                                  "connected to the database!";
        LOG_ERROR(error);
        throw std::runtime_error(error);
    }

    if (!inTransaction())
    {
        const std::string error = "Trying to rollback a transaction while no "
                                  "one is open!";
        LOG_ERROR(error);
        throw std::runtime_error(error);
    }

    if (mysql_rollback(mDb) != 0)
    {
        LOG_ERROR("MySqlDataProvider::rollbackTransaction: "
                  << mysql_error(mDb));
        throw DbSqlQueryExecFailure(mysql_error(mDb));
    }

    mysql_autocommit(mDb, AUTOCOMMIT_ON);
    mInTransaction = false;
    LOG_DEBUG("SQL: transaction rolled back");
}
예제 #3
0
unsigned MySqlDataProvider::getModifiedRows() const
{
    if (!mIsConnected)
    {
        const std::string error = "Trying to getModifiedRows while not "
                                  "connected to the database!";
        LOG_ERROR(error);
        throw std::runtime_error(error);
    }

    const my_ulonglong affected = mysql_affected_rows(mDb);

    if (affected > INT_MAX)
        throw std::runtime_error(
                               "MySqlDataProvider::getLastId exceeded INT_MAX");

    if (affected == (my_ulonglong)-1)
    {
        LOG_ERROR("MySqlDataProvider::getModifiedRows: " << mysql_error(mDb));
        throw DbSqlQueryExecFailure(mysql_error(mDb));
    }

    return (unsigned) affected;
}
예제 #4
0
/**
 * Execute a SQL query.
 */
const RecordSet &SqLiteDataProvider::execSql(const std::string& sql,
                                             const bool refresh)
{
    if (!mIsConnected)
        throw std::runtime_error("not connected to database");

    LOG_DEBUG("Performing SQL query: " << sql);

    // do something only if the query is different from the previous
    // or if the cache must be refreshed
    // otherwise just return the recordset from cache.
    if (refresh || (sql != mSql))
    {
        char** result;
        int nRows;
        int nCols;
        char* errMsg;

        mRecordSet.clear();

        int errCode = sqlite3_get_table(
                          mDb,          // an open database
                          sql.c_str(),  // SQL to be executed
                          &result,      // result of the query
                          &nRows,       // number of result rows
                          &nCols,       // number of result columns
                          &errMsg       // error msg
                      );

        if (errCode != SQLITE_OK)
        {
            std::string msg(sqlite3_errmsg(mDb));

            LOG_ERROR("Error in SQL: " << sql << "\n" << msg);

            // free memory
            sqlite3_free_table(result);
            sqlite3_free(errMsg);

            throw DbSqlQueryExecFailure(msg);
        }

        // the first row of result[] contains the field names.
        Row fieldNames;
        for (int col = 0; col < nCols; ++col)
            fieldNames.push_back(result[col]);

        mRecordSet.setColumnHeaders(fieldNames);

        // populate the RecordSet
        for (int row = 0; row < nRows; ++row)
        {
            Row r;

            for (int col = 0; col < nCols; ++col)
                r.push_back(result[nCols + (row * nCols) + col]);

            mRecordSet.add(r);
        }

        // free memory
        sqlite3_free_table(result);
        sqlite3_free(errMsg);
    }

    return mRecordSet;
}
예제 #5
0
const RecordSet &MySqlDataProvider::processSql()
{
    if (!mIsConnected)
        throw std::runtime_error("not connected to database");

    // Since we'll have to return something in all cases,
    // we clear the result member first.
    mRecordSet.clear();

    if (!mBind)
    {
        LOG_ERROR("MySqlDataProvider::processSql: "
                  "No bind done before processing.");
        return mRecordSet;
    }

    if (mysql_stmt_bind_param(mStmt, mBind))
    {
        LOG_ERROR("MySqlDataProvider::processSql Bind params failed: "
                  << mysql_stmt_error(mStmt));
        return mRecordSet;
    }

    if (mysql_stmt_field_count(mStmt) > 0)
    {
        MYSQL_BIND* resultBind;
        MYSQL_RES* res;

        if (mysql_stmt_execute(mStmt))
        {
            LOG_ERROR("MySqlDataProvider::processSql Execute failed: "
                      << mysql_stmt_error(mStmt));
        }

        res = mysql_stmt_result_metadata(mStmt);

        // set the field names.
        unsigned nFields = mysql_num_fields(res);
        MYSQL_FIELD* fields = mysql_fetch_fields(res);
        Row fieldNames;

        resultBind = new MYSQL_BIND[mysql_num_fields(res)];

        unsigned i = 0;
        for (i = 0; i < mysql_num_fields(res); ++i)
        {
            resultBind[i].buffer_type = MYSQL_TYPE_STRING;
            resultBind[i].buffer = (void*) new char[255];
            resultBind[i].buffer_length = 255;
            resultBind[i].is_null = new my_bool;
            resultBind[i].length = new unsigned long;
            resultBind[i].error = new my_bool;
        }

        if (mysql_stmt_bind_result(mStmt, resultBind))
        {
            LOG_ERROR("MySqlDataProvider::processSql Bind result failed: "
                      << mysql_stmt_error(mStmt));
        }

        for (i = 0; i < nFields; ++i)
            fieldNames.push_back(fields[i].name);

        mRecordSet.setColumnHeaders(fieldNames);

        // store the result of the query.
        if (mysql_stmt_store_result(mStmt))
            throw DbSqlQueryExecFailure(mysql_stmt_error(mStmt));

        // populate the RecordSet.
        while (!mysql_stmt_fetch(mStmt))
        {
            Row r;

            for (i = 0; i < nFields; ++i)
                r.push_back(static_cast<char *>(resultBind[i].buffer));

            mRecordSet.add(r);
        }

        delete[] resultBind;
    }
    else
    {
        if (mysql_stmt_execute(mStmt))
        {
            LOG_ERROR("MySqlDataProvider::processSql Execute failed: "
                      << mysql_stmt_error(mStmt));
        }
    }

    // Free memory
    mysql_stmt_free_result(mStmt);

    return mRecordSet;
}