It is shown in this answer in response to its question how string replacement in Python works.
I believe it works like
string toSql(string table, string field, string value)
{
string out;
return out = "INSERT INTO %s (%s) VALUES (%s)" % (table,field,value);
}
Is there a similar way of doing this in C++ without file i/o?
I am trying to use this to form a query for a SQLite database.
I am avoiding using external libraries. ex Boost
Also, the inputs are supplied from the program, not the user. So i do not believe i would run into injection vulnerabilities
In the interest of answering the asked question, the idiomatic C++ way to do this is with std::ostringstream
. Note that this stream class is backed by memory, not a file on disk.
(There is also the snprintf()
option, which looks closer to Python string formatting but has a C-style interface and shouldn't be used from modern C++ without a good reason. If you are writing C++ then write C++, not C.)
std::string toSql(
std::string const & table,
std::string const & field,
std::string const & value
) {
std::ostringstream s;
s << "INSERT INTO " << table
<< " (" << field << ") VALUES (" << value << ")";
return s.str();
}
However, beware that this can open your program to SQL injection attacks if any of the arguments are unsanitized user input. You should instead use a prepared statement ( sqlite3_prepare()
followed by sqlite3_bind_...()
) to bind value
into the statement -- but you will still have to build the string from the table
and field
arguments since database object names can't be bound this way.
You can use prepared statements "the C++ way" like this (C++11 or better required for std::unique_ptr
):
#include <memory>
#include <string>
#include <sqlite3.h>
// Deleter functor to properly sqlite3_finalize() statements when we
// are done with them.
struct sqlite3_stmt_deleter
{
void operator()(sqlite3_stmt * p) const {
sqlite3_finalize(p);
}
};
// Type alias for a std::unique_ptr that uses the above functor to
// clean up statements.
using sqlite3_prepared_stmt = std::unique_ptr<sqlite3_stmt, sqlite3_stmt_deleter>;
sqlite3_prepared_stmt prepare(sqlite3 * db, std::string const & sql)
{
sqlite3_stmt * stmt = nullptr;
// Note that we don't allow the caller to see any error information. A
// proper wrapper will want to throw if the return isn't SQLITE3_OK.
sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr);
return sqlite3_prepared_stmt(stmt);
}
void example() {
auto insert_stmt = prepare(
your_db,
"INSERT INTO foo (bar) VALUES (?)");
std::string value{"baz"};
// Bind value to the ? in the prepared statement
sqlite3_bind_text(insert_stmt.get(), 1, value.c_str(), -1, SQLITE_TRANSIENT);
// Execute statement.
sqlite3_step(insert_stmt.get());
// Reset statement so it can be used again with bind/step.
sqlite3_reset(insert_stmt.get());
// std::unique_ptr destructor will call sqlite3_finalize() for us.
}
Using this code, you can store a sqlite3_prepared_stmt
somewhere and reuse it.
Take a look at the printf family of functions.
string toSql( string table, string field, string value )
{
char buffer[ 100 ];
size_t length = sprintf( buffer, "INSERT INTO %s (%s) VALUES (%s)", table.data( ), field.data( ), value.data( ) );
if ( lenght < 0 )
{
//increase buffer size and try again.
}
printf("SQL Query = '%s'\n", buffer );
return buffer
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.