mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-04 13:54:25 +08:00
check complete sql
This commit is contained in:
@@ -393,7 +393,8 @@ class transaction final
|
||||
transaction(const transaction &) = delete;
|
||||
transaction &operator=(const transaction &) = delete;
|
||||
|
||||
result exec(const std::string &query);
|
||||
result exec(std::string query);
|
||||
result exec(std::string query, std::string &tail);
|
||||
|
||||
template<typename... Ts>
|
||||
cql_iterator_proxy<Ts...> stream(const std::string &sql)
|
||||
@@ -419,6 +420,9 @@ class connection final
|
||||
|
||||
friend class transaction;
|
||||
|
||||
/// \brief Return true if the string @a sql contains a complete statement.
|
||||
bool statementIsComplete(const std::string &sql) const;
|
||||
|
||||
private:
|
||||
struct connection_impl *m_impl;
|
||||
};
|
||||
|
||||
126
src/cql.cpp
126
src/cql.cpp
@@ -862,6 +862,11 @@ connection::~connection()
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
bool connection::statementIsComplete(const std::string &sql) const
|
||||
{
|
||||
return sqlite3_complete(sql.c_str()) == 1;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
transaction::transaction(connection &conn)
|
||||
@@ -927,7 +932,19 @@ void transaction::rollback()
|
||||
}
|
||||
}
|
||||
|
||||
result transaction::exec(const std::string &query)
|
||||
result transaction::exec(std::string query)
|
||||
{
|
||||
trim(query);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
auto r = exec(query, query);
|
||||
if (query.empty())
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
result transaction::exec(std::string query, std::string &tail)
|
||||
{
|
||||
category cat;
|
||||
|
||||
@@ -935,72 +952,69 @@ result transaction::exec(const std::string &query)
|
||||
|
||||
try
|
||||
{
|
||||
std::string sql = query;
|
||||
while (not sql.empty())
|
||||
const char *tail_ptr = nullptr;
|
||||
int rc = sqlite3_prepare_v2(m_conn.m_impl->m_sqlite_db, query.data(), query.length(),
|
||||
&stmt, &tail_ptr);
|
||||
|
||||
auto used = tail_ptr - query.data();
|
||||
auto sql = query.substr(0, used);
|
||||
tail = trim_copy(query.substr(used));
|
||||
|
||||
if (rc != SQLITE_OK)
|
||||
throw std::runtime_error(std::format("Error preparing statement: {}", sqlite3_errmsg(m_conn.m_impl->m_sqlite_db)));
|
||||
|
||||
category ncat((std::format("result{}", m_conn.m_impl->m_next_result_nr++)));
|
||||
std::swap(cat, ncat);
|
||||
|
||||
// for (int i = 0; i < sqlite3_column_count(stmt); ++i)
|
||||
// cat.add_item(sqlite3_column_name(stmt, i));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const char *tail = nullptr;
|
||||
int rc = sqlite3_prepare_v2(m_conn.m_impl->m_sqlite_db, sql.data(), sql.length(),
|
||||
&stmt, &tail);
|
||||
auto used = tail - sql.data();
|
||||
sql = sql.substr(used, sql.length() - used);
|
||||
trim(sql);
|
||||
|
||||
if (rc != SQLITE_OK)
|
||||
throw std::runtime_error(std::format("Error preparing statement: {}", sqlite3_errmsg(m_conn.m_impl->m_sqlite_db)));
|
||||
|
||||
category ncat((std::format("result{}", m_conn.m_impl->m_next_result_nr++)));
|
||||
std::swap(cat, ncat);
|
||||
|
||||
// for (int i = 0; i < sqlite3_column_count(stmt); ++i)
|
||||
// cat.add_item(sqlite3_column_name(stmt, i));
|
||||
|
||||
for (;;)
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc == SQLITE_ROW)
|
||||
{
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc == SQLITE_ROW)
|
||||
row_initializer data;
|
||||
|
||||
for (int i = 0; i < sqlite3_column_count(stmt); ++i)
|
||||
{
|
||||
row_initializer data;
|
||||
|
||||
for (int i = 0; i < sqlite3_column_count(stmt); ++i)
|
||||
switch (sqlite3_column_type(stmt, i))
|
||||
{
|
||||
switch (sqlite3_column_type(stmt, i))
|
||||
{
|
||||
case SQLITE_INTEGER:
|
||||
data.emplace_back(sqlite3_column_name(stmt, i), sqlite3_column_int64(stmt, i));
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
data.emplace_back(sqlite3_column_name(stmt, i), sqlite3_column_double(stmt, i));
|
||||
break;
|
||||
case SQLITE_TEXT:
|
||||
data.emplace_back(sqlite3_column_name(stmt, i), (const char *)sqlite3_column_text(stmt, i));
|
||||
break;
|
||||
case SQLITE_BLOB:
|
||||
throw std::runtime_error("Unexpected: blob in result");
|
||||
break;
|
||||
case SQLITE_NULL:
|
||||
// data.emplace_back(sqlite3_column_name(stmt, i), ".");
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER:
|
||||
data.emplace_back(sqlite3_column_name(stmt, i), sqlite3_column_int64(stmt, i));
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
data.emplace_back(sqlite3_column_name(stmt, i), sqlite3_column_double(stmt, i));
|
||||
break;
|
||||
case SQLITE_TEXT:
|
||||
data.emplace_back(sqlite3_column_name(stmt, i), (const char *)sqlite3_column_text(stmt, i));
|
||||
break;
|
||||
case SQLITE_BLOB:
|
||||
throw std::runtime_error("Unexpected: blob in result");
|
||||
break;
|
||||
case SQLITE_NULL:
|
||||
// data.emplace_back(sqlite3_column_name(stmt, i), ".");
|
||||
break;
|
||||
}
|
||||
|
||||
cat.emplace(std::move(data));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rc == SQLITE_BUSY)
|
||||
throw std::runtime_error("Oops, busy?");
|
||||
if (rc == SQLITE_DONE)
|
||||
break;
|
||||
if (rc == SQLITE_ERROR)
|
||||
throw std::runtime_error(std::format("Error in sqlite: {}", sqlite3_errmsg(m_conn.m_impl->m_sqlite_db)));
|
||||
|
||||
throw std::runtime_error("Unknown result from step");
|
||||
cat.emplace(std::move(data));
|
||||
continue;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
if (rc == SQLITE_BUSY)
|
||||
throw std::runtime_error("Oops, busy?");
|
||||
if (rc == SQLITE_DONE)
|
||||
break;
|
||||
if (rc == SQLITE_ERROR)
|
||||
throw std::runtime_error(std::format("Error in sqlite: {}", sqlite3_errmsg(m_conn.m_impl->m_sqlite_db)));
|
||||
|
||||
throw std::runtime_error("Unknown result from step");
|
||||
}
|
||||
|
||||
return result(std::move(cat), query);
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return result(std::move(cat), sql);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user