Question

I am attempting to make my saving code more efficient through the use of re-using the prepared statement, the use of transactions, and parametrized queries. However whenever I run the save code only one record ends up in my table. I think it has to do with where the sqlite3_step is placed.

But I also want some other eyes to look over my code and let me know if I am doing things correctly; I could not find an example doing this anywhere so it is a jumble of about six forums posts and Stack Overflow topics I found on the various subjects:

//Planet Data

//Delete previous save data
dData("Generated_Planets", bErrors);

if (plData.size() > 0)
{
    sqlite3_exec(dBase, "BEGIN TRANSACTION", NULL, NULL, &error);

    sqlStr = "Insert Into Generated_Planets (ID, Name, Affiliation, Disposition, Race, Player_Owned, Is_Destroyed, EKS, Planet_Size, Current_Pop, Max_Pop) Values (?,?,?,?,?,?,?,?,?,?,?);";

    if (sqlite3_prepare_v2(dBase, sqlStr.c_str(), sqlStr.size(), &statement, 0) == SQLITE_OK)
    {
        cout << "Saving planet data";
        //Save new data
        for (i = 0; i <= plData.size(); i++)
        {
            if (i == plData.size())
            {
                finalize(statement, bErrors);
            }

            else
            {
                sqlI1 = plData.at(i).pID;
                sqlS1 = plData.at(i).pName;
                sqlS2 = plData.at(i).pAffiliation;
                sqlS3 = plData.at(i).pDispo;
                sqlS4 = plData.at(i).pRace;
                sqlI2 = plData.at(i).bIsPOwned;
                sqlI3 = plData.at(i).bIsDestroyed;
                sqlF1 = plData.at(i).pEKS;
                sqlF2 = plData.at(i).pSize;
                sqlLLI1 = plData.at(i).pCPop;
                sqlLLI2 = plData.at(i).pMPop;

                find = "'";
                temp = "\"";

                foundAt = sqlS1.find(find);

                if (foundAt != string::npos)
                {
                    sqlS1.replace(foundAt,1,temp);
                }

                //Bind parameters
                sqlite3_bind_int(statement,1,sqlI1);
                sqlite3_bind_text(statement,2,sqlS1.c_str(),sqlS1.size(),SQLITE_TRANSIENT);
                sqlite3_bind_text(statement,3,sqlS2.c_str(),sqlS2.size(),SQLITE_TRANSIENT);
                sqlite3_bind_text(statement,4,sqlS3.c_str(),sqlS3.size(),SQLITE_TRANSIENT);
                sqlite3_bind_text(statement,5,sqlS4.c_str(),sqlS4.size(),SQLITE_TRANSIENT);
                sqlite3_bind_int(statement,6,sqlI2);
                sqlite3_bind_int(statement,7,sqlI3);
                sqlite3_bind_double(statement,8,sqlF1);
                sqlite3_bind_double(statement,9,sqlF2);
                sqlite3_bind_int64(statement,10,sqlLLI1);
                sqlite3_bind_int64(statement,11,sqlLLI2);

                sqlite3_step(statement);

                cout << ".";
            }
        }
    }       

    else
    {
        *bErrors = true;
        createBInfo();      
        d.createBReport("SQL Code 2",sqlite3_errmsg(dBase),bLocale + to_string(__LINE__),bTDate,"./SC_Log.txt");    
    }

    sqlite3_exec(dBase, "END TRANSACTION", NULL, NULL, &error);

    sFlags_Temp.push_back(saveFlag());
    sFlags_Temp.at(sFlags_Temp.size()-1).sfName = "GPlanets";
    sFlags_Temp.at(sFlags_Temp.size()-1).sfValue = 1;
    cout << "Done" << endl << endl;
}
Was it helpful?

Solution

It looks like you're missing a call to sqlite3_reset after sqlite3_step and before binding the next set of parameters. And you're ignoring the return codes that would have told you about it.

See the documentation for sqlite3_step here: http://sqlite.org/c3ref/step.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top