mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-28 14:18:41 +02:00
AUP3: Use persistent prepared statements
SqliteSampleBlock now uses already prepared SQL statements for all DB usage. This means that the statements won't have to be compiled each time they are used.
This commit is contained in:
parent
73c6225906
commit
6c70cb86ee
@ -492,13 +492,35 @@ sqlite3 *ProjectFileIO::OpenDB(FilePath fileName)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mTemporary = temp;
|
||||
Prepare(GetSamples,
|
||||
"SELECT samples FROM sampleblocks WHERE blockid = ?1;");
|
||||
|
||||
SetFileName(fileName);
|
||||
Prepare(GetSummary256,
|
||||
"SELECT summary256 FROM sampleblocks WHERE blockid = ?1;");
|
||||
|
||||
Prepare(GetSummary64k,
|
||||
"SELECT summary64k FROM sampleblocks WHERE blockid = ?1;");
|
||||
|
||||
Prepare(LoadSampleBlock,
|
||||
"SELECT sampleformat, summin, summax, sumrms,"
|
||||
" length('summary256'), length('summary64k'), length('samples')"
|
||||
" FROM sampleblocks WHERE blockid = ?1;");
|
||||
|
||||
Prepare(InsertSampleBlock,
|
||||
"INSERT INTO sampleblocks (sampleformat, summin, summax, sumrms,"
|
||||
" summary256, summary64k, samples)"
|
||||
" VALUES(?1,?2,?3,?4,?5,?6,?7);");
|
||||
|
||||
Prepare(DeleteSampleBlock,
|
||||
"DELETE FROM sampleblocks WHERE blockid = ?1;");
|
||||
|
||||
// Install our checkpoint hook
|
||||
sqlite3_wal_hook(mDB, CheckpointHook, this);
|
||||
|
||||
mTemporary = temp;
|
||||
|
||||
SetFileName(fileName);
|
||||
|
||||
return mDB;
|
||||
}
|
||||
|
||||
@ -537,6 +559,13 @@ bool ProjectFileIO::CloseDB()
|
||||
}
|
||||
}
|
||||
|
||||
// We're done with the prepared statements
|
||||
for (auto stmt : mStatements)
|
||||
{
|
||||
sqlite3_finalize(stmt.second);
|
||||
}
|
||||
mStatements.clear();
|
||||
|
||||
// Close the DB
|
||||
rc = sqlite3_close(mDB);
|
||||
if (rc != SQLITE_OK)
|
||||
@ -551,25 +580,28 @@ bool ProjectFileIO::CloseDB()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProjectFileIO::DeleteDB()
|
||||
void ProjectFileIO::Prepare(enum StatementID id, const char *sql)
|
||||
{
|
||||
wxASSERT(mDB == nullptr);
|
||||
int rc;
|
||||
|
||||
if (mTemporary && !mFileName.empty())
|
||||
sqlite3_stmt *stmt = nullptr;
|
||||
|
||||
rc = sqlite3_prepare_v3(mDB, sql, -1, SQLITE_PREPARE_PERSISTENT, &stmt, 0);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
wxFileName temp(FileNames::TempDir());
|
||||
if (temp == wxPathOnly(mFileName))
|
||||
{
|
||||
if (!wxRemoveFile(mFileName))
|
||||
{
|
||||
SetError(XO("Failed to close the project file"));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
}
|
||||
|
||||
return true;
|
||||
mStatements.insert({id, stmt});
|
||||
}
|
||||
|
||||
sqlite3_stmt *ProjectFileIO::GetStatement(enum StatementID id)
|
||||
{
|
||||
auto iter = mStatements.find(id);
|
||||
|
||||
wxASSERT(iter != mStatements.end());
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
bool ProjectFileIO::TransactionStart(const wxString &name)
|
||||
@ -1036,10 +1068,10 @@ sqlite3 *ProjectFileIO::CopyTo(const FilePath &destpath,
|
||||
// Copy sample blocks from the main DB to the outbound DB
|
||||
for (auto blockid : blockids)
|
||||
{
|
||||
// BIND blockid parameter
|
||||
// Bind statement parameters
|
||||
if (sqlite3_bind_int64(stmt, 1, blockid) != SQLITE_OK)
|
||||
{
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
|
||||
}
|
||||
|
||||
// Process it
|
||||
@ -1052,7 +1084,7 @@ sqlite3 *ProjectFileIO::CopyTo(const FilePath &destpath,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// BIND blockid parameter
|
||||
// Reset statement to beginning
|
||||
if (sqlite3_reset(stmt) != SQLITE_OK)
|
||||
{
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
@ -1680,15 +1712,13 @@ bool ProjectFileIO::WriteDoc(const char *table,
|
||||
const wxMemoryBuffer &dict = autosave.GetDict();
|
||||
const wxMemoryBuffer &data = autosave.GetData();
|
||||
|
||||
// BIND SQL autosave
|
||||
// Bind statement parameters
|
||||
// Might return SQL_MISUSE which means it's our mistake that we violated
|
||||
// preconditions; should return SQL_OK which is 0
|
||||
if (
|
||||
sqlite3_bind_blob(stmt, 1, dict.GetData(), dict.GetDataLen(), SQLITE_STATIC) ||
|
||||
sqlite3_bind_blob(stmt, 2, data.GetData(), data.GetDataLen(), SQLITE_STATIC)
|
||||
)
|
||||
if (sqlite3_bind_blob(stmt, 1, dict.GetData(), dict.GetDataLen(), SQLITE_STATIC) ||
|
||||
sqlite3_bind_blob(stmt, 2, data.GetData(), data.GetDataLen(), SQLITE_STATIC))
|
||||
{
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
|
||||
}
|
||||
|
||||
rc = sqlite3_step(stmt);
|
||||
@ -1938,10 +1968,12 @@ bool ProjectFileIO::ImportProject(const FilePath &fileName)
|
||||
SampleBlockID blockid;
|
||||
attr->GetValue().ToLongLong(&blockid);
|
||||
|
||||
// BIND blockid parameter
|
||||
// Bind statement parameters
|
||||
// Might return SQL_MISUSE which means it's our mistake that we violated
|
||||
// preconditions; should return SQL_OK which is 0
|
||||
if (sqlite3_bind_int64(stmt, 1, blockid) != SQLITE_OK)
|
||||
{
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
|
||||
}
|
||||
|
||||
// Process it
|
||||
@ -2412,6 +2444,6 @@ bool AutoCommitTransaction::Rollback()
|
||||
wxASSERT(mInTrans);
|
||||
|
||||
mInTrans = !mIO.TransactionCommit(mName);
|
||||
|
||||
|
||||
return mInTrans;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ Paul Licameli split from AudacityProject.h
|
||||
|
||||
struct sqlite3;
|
||||
struct sqlite3_context;
|
||||
struct sqlite3_stmt;
|
||||
struct sqlite3_value;
|
||||
|
||||
class AudacityProject;
|
||||
@ -159,7 +160,18 @@ private:
|
||||
|
||||
sqlite3 *OpenDB(FilePath fileName = {});
|
||||
bool CloseDB();
|
||||
bool DeleteDB();
|
||||
|
||||
enum StatementID
|
||||
{
|
||||
GetSamples,
|
||||
GetSummary256,
|
||||
GetSummary64k,
|
||||
LoadSampleBlock,
|
||||
InsertSampleBlock,
|
||||
DeleteSampleBlock
|
||||
};
|
||||
void Prepare(enum StatementID id, const char *sql);
|
||||
sqlite3_stmt *GetStatement(enum StatementID id);
|
||||
|
||||
bool Query(const char *sql, const ExecCB &callback);
|
||||
|
||||
@ -233,6 +245,8 @@ private:
|
||||
std::atomic< std::uint64_t > mCheckpointWaitingPages{ 0 };
|
||||
std::atomic< std::uint64_t > mCheckpointCurrentPages{ 0 };
|
||||
|
||||
std::map<enum StatementID, sqlite3_stmt *> mStatements;
|
||||
|
||||
friend SqliteSampleBlock;
|
||||
friend AutoCommitTransaction;
|
||||
};
|
||||
|
@ -64,11 +64,11 @@ private:
|
||||
bool GetSummary(float *dest,
|
||||
size_t frameoffset,
|
||||
size_t numframes,
|
||||
const char *srccolumn,
|
||||
ProjectFileIO::StatementID id,
|
||||
size_t srcbytes);
|
||||
size_t GetBlob(void *dest,
|
||||
sampleFormat destformat,
|
||||
const char *srccolumn,
|
||||
ProjectFileIO::StatementID id,
|
||||
sampleFormat srcformat,
|
||||
size_t srcoffset,
|
||||
size_t srcbytes);
|
||||
@ -98,9 +98,6 @@ private:
|
||||
double mSumMax;
|
||||
double mSumRms;
|
||||
|
||||
const char *columns =
|
||||
"sampleformat, summin, summax, sumrms, summary256, summary64k, samples";
|
||||
|
||||
#if defined(WORDS_BIGENDIAN)
|
||||
#error All sample block data is little endian...big endian not yet supported
|
||||
#endif
|
||||
@ -291,7 +288,7 @@ size_t SqliteSampleBlock::DoGetSamples(samplePtr dest,
|
||||
{
|
||||
return GetBlob(dest,
|
||||
destformat,
|
||||
"samples",
|
||||
ProjectFileIO::GetSamples,
|
||||
mSampleFormat,
|
||||
sampleoffset * SAMPLE_SIZE(mSampleFormat),
|
||||
numsamples * SAMPLE_SIZE(mSampleFormat)) / SAMPLE_SIZE(mSampleFormat);
|
||||
@ -333,25 +330,33 @@ bool SqliteSampleBlock::GetSummary256(float *dest,
|
||||
size_t frameoffset,
|
||||
size_t numframes)
|
||||
{
|
||||
return GetSummary(dest, frameoffset, numframes, "summary256", mSummary256Bytes);
|
||||
return GetSummary(dest,
|
||||
frameoffset,
|
||||
numframes,
|
||||
ProjectFileIO::GetSummary256,
|
||||
mSummary256Bytes);
|
||||
}
|
||||
|
||||
bool SqliteSampleBlock::GetSummary64k(float *dest,
|
||||
size_t frameoffset,
|
||||
size_t numframes)
|
||||
{
|
||||
return GetSummary(dest, frameoffset, numframes, "summary64k", mSummary64kBytes);
|
||||
return GetSummary(dest,
|
||||
frameoffset,
|
||||
numframes,
|
||||
ProjectFileIO::GetSummary64k,
|
||||
mSummary256Bytes);
|
||||
}
|
||||
|
||||
bool SqliteSampleBlock::GetSummary(float *dest,
|
||||
size_t frameoffset,
|
||||
size_t numframes,
|
||||
const char *srccolumn,
|
||||
ProjectFileIO::StatementID id,
|
||||
size_t srcbytes)
|
||||
{
|
||||
return GetBlob(dest,
|
||||
floatSample,
|
||||
srccolumn,
|
||||
id,
|
||||
floatSample,
|
||||
frameoffset * 3 * SAMPLE_SIZE(floatSample),
|
||||
numframes * 3 * SAMPLE_SIZE(floatSample)) / 3 / SAMPLE_SIZE(floatSample);
|
||||
@ -398,7 +403,7 @@ MinMaxRMS SqliteSampleBlock::DoGetMinMaxRMS(size_t start, size_t len)
|
||||
|
||||
size_t copied = GetBlob(samples,
|
||||
floatSample,
|
||||
"samples",
|
||||
ProjectFileIO::GetSamples,
|
||||
mSampleFormat,
|
||||
start * SAMPLE_SIZE(mSampleFormat),
|
||||
len * SAMPLE_SIZE(mSampleFormat)) / SAMPLE_SIZE(mSampleFormat);
|
||||
@ -439,7 +444,7 @@ size_t SqliteSampleBlock::GetSpaceUsage() const
|
||||
|
||||
size_t SqliteSampleBlock::GetBlob(void *dest,
|
||||
sampleFormat destformat,
|
||||
const char *srccolumn,
|
||||
ProjectFileIO::StatementID id,
|
||||
sampleFormat srcformat,
|
||||
size_t srcoffset,
|
||||
size_t srcbytes)
|
||||
@ -456,77 +461,71 @@ size_t SqliteSampleBlock::GetBlob(void *dest,
|
||||
int rc;
|
||||
size_t minbytes = 0;
|
||||
|
||||
char sql[256];
|
||||
sqlite3_snprintf(sizeof(sql),
|
||||
sql,
|
||||
"SELECT %s FROM sampleblocks WHERE blockid = %lld;",
|
||||
srccolumn,
|
||||
mBlockID);
|
||||
// Retrieve prepared statement
|
||||
sqlite3_stmt *stmt = mIO.GetStatement(id);
|
||||
|
||||
sqlite3_stmt *stmt = nullptr;
|
||||
auto cleanup = finally([&]
|
||||
// Bind statement paraemters
|
||||
// Might return SQLITE_MISUSE which means it's our mistake that we violated
|
||||
// preconditions; should return SQL_OK which is 0
|
||||
if (sqlite3_bind_int64(stmt, 1, mBlockID))
|
||||
{
|
||||
if (stmt)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
});
|
||||
|
||||
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
wxLogDebug(wxT("SQLITE error %s"), sqlite3_errmsg(db));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc != SQLITE_ROW)
|
||||
{
|
||||
wxLogDebug(wxT("SQLITE error %s"), sqlite3_errmsg(db));
|
||||
}
|
||||
else
|
||||
{
|
||||
samplePtr src = (samplePtr) sqlite3_column_blob(stmt, 0);
|
||||
size_t blobbytes = (size_t) sqlite3_column_bytes(stmt, 0);
|
||||
|
||||
srcoffset = std::min(srcoffset, blobbytes);
|
||||
minbytes = std::min(srcbytes, blobbytes - srcoffset);
|
||||
|
||||
if (srcoffset != 0)
|
||||
{
|
||||
srcoffset += 0;
|
||||
}
|
||||
CopySamples(src + srcoffset,
|
||||
srcformat,
|
||||
(samplePtr) dest,
|
||||
destformat,
|
||||
minbytes / SAMPLE_SIZE(srcformat));
|
||||
|
||||
dest = ((samplePtr) dest) + minbytes;
|
||||
}
|
||||
wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
|
||||
}
|
||||
|
||||
if ( rc != SQLITE_ROW )
|
||||
// Execute the statement
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc != SQLITE_ROW)
|
||||
{
|
||||
wxLogDebug(wxT("SqliteSampleBlock::GetBlob - SQLITE error %s"), sqlite3_errmsg(db));
|
||||
|
||||
// Clear statement bindings and rewind statement
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
// Just showing the user a simple message, not the library error too
|
||||
// which isn't internationalized
|
||||
throw SimpleMessageBoxException{ XO("Failed to retrieve samples") };
|
||||
throw SimpleMessageBoxException{ XO("Failed to retrieve project data") };
|
||||
}
|
||||
|
||||
// Retrieve returned data
|
||||
samplePtr src = (samplePtr) sqlite3_column_blob(stmt, 0);
|
||||
size_t blobbytes = (size_t) sqlite3_column_bytes(stmt, 0);
|
||||
|
||||
srcoffset = std::min(srcoffset, blobbytes);
|
||||
minbytes = std::min(srcbytes, blobbytes - srcoffset);
|
||||
|
||||
if (srcoffset != 0)
|
||||
{
|
||||
srcoffset += 0;
|
||||
}
|
||||
|
||||
CopySamples(src + srcoffset,
|
||||
srcformat,
|
||||
(samplePtr) dest,
|
||||
destformat,
|
||||
minbytes / SAMPLE_SIZE(srcformat));
|
||||
|
||||
dest = ((samplePtr) dest) + minbytes;
|
||||
|
||||
if (srcbytes - minbytes)
|
||||
{
|
||||
memset(dest, 0, srcbytes - minbytes);
|
||||
}
|
||||
|
||||
// Clear statement bindings and rewind statement
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
return srcbytes;
|
||||
}
|
||||
|
||||
void SqliteSampleBlock::Load(SampleBlockID sbid)
|
||||
{
|
||||
auto db = mIO.DB();
|
||||
int rc;
|
||||
|
||||
wxASSERT(sbid > 0);
|
||||
|
||||
int rc;
|
||||
|
||||
mValid = false;
|
||||
mSummary256Bytes = 0;
|
||||
mSummary64kBytes = 0;
|
||||
@ -536,41 +535,33 @@ void SqliteSampleBlock::Load(SampleBlockID sbid)
|
||||
mSumMax = -FLT_MAX;
|
||||
mSumMin = 0.0;
|
||||
|
||||
char sql[256];
|
||||
sqlite3_snprintf(sizeof(sql),
|
||||
sql,
|
||||
"SELECT sampleformat, summin, summax, sumrms,"
|
||||
" length('summary256'), length('summary64k'), length('samples')"
|
||||
" FROM sampleblocks WHERE blockid = %lld;",
|
||||
sbid);
|
||||
// Retrieve prepared statement
|
||||
sqlite3_stmt *stmt = mIO.GetStatement(ProjectFileIO::LoadSampleBlock);
|
||||
|
||||
sqlite3_stmt *stmt = nullptr;
|
||||
auto cleanup = finally([&]
|
||||
// Bind statement paraemters
|
||||
// Might return SQLITE_MISUSE which means it's our mistake that we violated
|
||||
// preconditions; should return SQL_OK which is 0
|
||||
if (sqlite3_bind_int64(stmt, 1, sbid))
|
||||
{
|
||||
if (stmt)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
});
|
||||
|
||||
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
wxLogDebug(wxT("SQLITE error %s"), sqlite3_errmsg(db));
|
||||
}
|
||||
else {
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc != SQLITE_ROW)
|
||||
{
|
||||
wxLogDebug(wxT("SQLITE error %s"), sqlite3_errmsg(db));
|
||||
}
|
||||
wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
|
||||
}
|
||||
|
||||
if ( rc != SQLITE_ROW )
|
||||
// Execute the statement
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc != SQLITE_ROW)
|
||||
{
|
||||
wxLogDebug(wxT("SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
|
||||
|
||||
// Clear statement bindings and rewind statement
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
// Just showing the user a simple message, not the library error too
|
||||
// which isn't internationalized
|
||||
throw SimpleMessageBoxException{ XO("Failed to retrieve samples") };
|
||||
throw SimpleMessageBoxException{ XO("Failed to retrieve sample block") };
|
||||
}
|
||||
|
||||
// Retrieve returned data
|
||||
mBlockID = sbid;
|
||||
mSampleFormat = (sampleFormat) sqlite3_column_int(stmt, 0);
|
||||
mSumMin = sqlite3_column_double(stmt, 1);
|
||||
@ -581,6 +572,10 @@ void SqliteSampleBlock::Load(SampleBlockID sbid)
|
||||
mSampleBytes = sqlite3_column_int(stmt, 6);
|
||||
mSampleCount = mSampleBytes / SAMPLE_SIZE(mSampleFormat);
|
||||
|
||||
// Clear statement bindings and rewind statement
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
mValid = true;
|
||||
}
|
||||
|
||||
@ -589,85 +584,89 @@ void SqliteSampleBlock::Commit()
|
||||
auto db = mIO.DB();
|
||||
int rc;
|
||||
|
||||
char sql[256];
|
||||
sqlite3_snprintf(sizeof(sql),
|
||||
sql,
|
||||
"INSERT INTO sampleblocks (%s) VALUES(?,?,?,?,?,?,?);",
|
||||
columns);
|
||||
// Retrieve prepared statement
|
||||
sqlite3_stmt *stmt = mIO.GetStatement(ProjectFileIO::InsertSampleBlock);
|
||||
|
||||
sqlite3_stmt *stmt = nullptr;
|
||||
auto cleanup = finally([&]
|
||||
{
|
||||
if (stmt)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
});
|
||||
|
||||
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
wxLogDebug(wxT("SQLITE error %s"), sqlite3_errmsg(db));
|
||||
// Just showing the user a simple message, not the library error too
|
||||
// which isn't internationalized
|
||||
throw SimpleMessageBoxException{ mIO.GetLastError() };
|
||||
}
|
||||
|
||||
// BIND SQL sampleblocks
|
||||
// Might return SQL_MISUSE which means it's our mistake that we violated
|
||||
// Bind statement paraemters
|
||||
// Might return SQLITE_MISUSE which means it's our mistake that we violated
|
||||
// preconditions; should return SQL_OK which is 0
|
||||
if (
|
||||
sqlite3_bind_int(stmt, 1, mSampleFormat) ||
|
||||
sqlite3_bind_double(stmt, 2, mSumMin) ||
|
||||
sqlite3_bind_double(stmt, 3, mSumMax) ||
|
||||
sqlite3_bind_double(stmt, 4, mSumRms) ||
|
||||
sqlite3_bind_blob(stmt, 5, mSummary256.get(), mSummary256Bytes, SQLITE_STATIC) ||
|
||||
sqlite3_bind_blob(stmt, 6, mSummary64k.get(), mSummary64kBytes, SQLITE_STATIC) ||
|
||||
sqlite3_bind_blob(stmt, 7, mSamples.get(), mSampleBytes, SQLITE_STATIC)
|
||||
)
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
if (sqlite3_bind_int(stmt, 1, mSampleFormat) ||
|
||||
sqlite3_bind_double(stmt, 2, mSumMin) ||
|
||||
sqlite3_bind_double(stmt, 3, mSumMax) ||
|
||||
sqlite3_bind_double(stmt, 4, mSumRms) ||
|
||||
sqlite3_bind_blob(stmt, 5, mSummary256.get(), mSummary256Bytes, SQLITE_STATIC) ||
|
||||
sqlite3_bind_blob(stmt, 6, mSummary64k.get(), mSummary64kBytes, SQLITE_STATIC) ||
|
||||
sqlite3_bind_blob(stmt, 7, mSamples.get(), mSampleBytes, SQLITE_STATIC))
|
||||
{
|
||||
wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
|
||||
}
|
||||
|
||||
// Execute the statement
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
wxLogDebug(wxT("SQLITE error %s"), sqlite3_errmsg(db));
|
||||
wxLogDebug(wxT("SqliteSampleBlock::Commit - SQLITE error %s"), sqlite3_errmsg(db));
|
||||
|
||||
// Clear statement bindings and rewind statement
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
// Just showing the user a simple message, not the library error too
|
||||
// which isn't internationalized
|
||||
throw SimpleMessageBoxException{ mIO.GetLastError() };
|
||||
throw SimpleMessageBoxException{ XO("Failed to add sample block") };
|
||||
}
|
||||
|
||||
// Retrieve returned data
|
||||
mBlockID = sqlite3_last_insert_rowid(db);
|
||||
|
||||
// Reset local arrays
|
||||
mSamples.reset();
|
||||
mSummary256.reset();
|
||||
mSummary64k.reset();
|
||||
|
||||
// Clear statement bindings and rewind statement
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
mValid = true;
|
||||
}
|
||||
|
||||
void SqliteSampleBlock::Delete()
|
||||
{
|
||||
auto db = mIO.DB();
|
||||
int rc;
|
||||
|
||||
if (mBlockID)
|
||||
wxASSERT(mBlockID > 0);
|
||||
|
||||
// Retrieve prepared statement
|
||||
sqlite3_stmt *stmt = mIO.GetStatement(ProjectFileIO::DeleteSampleBlock);
|
||||
|
||||
// Bind statement paraemters
|
||||
// Might return SQLITE_MISUSE which means it's our mistake that we violated
|
||||
// preconditions; should return SQL_OK which is 0
|
||||
if (sqlite3_bind_int64(stmt, 1, mBlockID))
|
||||
{
|
||||
int rc;
|
||||
|
||||
char sql[256];
|
||||
sqlite3_snprintf(sizeof(sql),
|
||||
sql,
|
||||
"DELETE FROM sampleblocks WHERE blockid = %lld;",
|
||||
mBlockID);
|
||||
|
||||
rc = sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
wxLogDebug(wxT("SQLITE error %s"), sqlite3_errmsg(db));
|
||||
// Just showing the user a simple message, not the library error too
|
||||
// which isn't internationalized
|
||||
throw SimpleMessageBoxException{ XO("Failed to purge unused samples") };
|
||||
}
|
||||
wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
|
||||
}
|
||||
|
||||
// Execute the statement
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc != SQLITE_ROW)
|
||||
{
|
||||
wxLogDebug(wxT("SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
|
||||
|
||||
// Clear statement bindings and rewind statement
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
// Just showing the user a simple message, not the library error too
|
||||
// which isn't internationalized
|
||||
throw SimpleMessageBoxException{ XO("Failed to delete sample block") };
|
||||
}
|
||||
|
||||
// Clear statement bindings and rewind statement
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
}
|
||||
|
||||
void SqliteSampleBlock::SaveXML(XMLWriter &xmlFile)
|
||||
|
Loading…
x
Reference in New Issue
Block a user