Ich weiß, es ist wahrscheinlich ein sehr dummer Fehler, aber ich sitze seit Stunden buchstäblich stundenlang auf ein paar Zeilen Code, laufe durch Dokumentationen, und ich bin immer noch ahnungslos, warum das passiert :Letztes Argument überschreibt frühere Argumente in SQLite-Bindung
Ich schreibe eine Convenience Wrapper-Klasse für die SQLite C-API in C++ 11. Wenn die Verbindung zu einer Datenbank hergestellt ist, erstellt die Funktion sql
eine Anweisung, bindet gegebenenfalls Argumente an sie und führt sie anschließend aus. Vorbereiten und Ausführen funktioniert gut, das Binden eines Arguments funktioniert gut, aber wenn ich mehr als ein Argument binden möchte, werden alle Werte immer auf das letzte Argument in der Liste gesetzt.
Die sql
Funktion sieht wie folgt aus:
template <typename... Args>
bool sql(const std::string &query, const Args &... args)
{
sql_statement call;
if(sqlite3_prepare_v2(database_, query.data(), -1, &call.statement, nullptr)
!= SQLITE_OK)
{
return false;
}
if(!bind(call.statement, 1, args...)) {
return false;
}
return sqlite3_step(call.statement) == SQLITE_DONE;
}
sql_statement
ist ein Wrapper-Struktur für sqlite3_stmt
die nichts tut, aber die Aussage freizugeben, wenn es außerhalb des Gültigkeitsbereichs ausgeführt wird. database_
ist das Handle der Arbeitsdatenbank. Ich bin mir aber nicht sicher, ob diese Funktion überhaupt etwas mit dem Problem zu tun hat. Was ich als Störenfried eher im Sinn habe, ist die bind
Funktion, die innerhalb der sql
Funktion aufgerufen wird. Hier ist es:
template <typename T, typename... Args>
bool bind(sqlite3_stmt *statement, int current, const T &first, const Args &... args)
{
std::stringstream ss;
ss << first;
if(sqlite3_bind_text(statement, current,
ss.str().data(), ss.str().length(), SQLITE_STATIC) != SQLITE_OK)
{
return false;
}
return bind(statement, current+1, args...);
}
bool bind(sqlite3_stmt *, int) { return true; }
Beachten Sie, dass es keinen Fehler gibt, die Funktion gibt True zurück. Ich habe das mit verschiedenen Eingaben getestet; betrachten Sie dieses Beispiel:
if(!db.sql("INSERT INTO test (name, age) VALUES (?, ?);", "nijansen", 23)) {
std::cerr << db.error() << std::endl;
return 1;
}
Wenn ich den Funktionsaufruf von bind
debuggen, die Rekursion wie erwartet funktioniert, so dass es die Funktion die Werte [1] nijansen
und [2] 23
gibt. The documentation of the SQLite C API sagt "Der am weitesten links liegende SQL-Parameter hat einen Index von 1", also sollte das nicht das Problem sein. In der Datenbank ist das Ergebnis der Abfrage: id: 1, name: 23, age: 23
. Ich würde mich sehr über einen zweiten Blick auf dieses Thema freuen.