Add ODBC DirectExec public API (#3502)

* ODBC sqlDirectExec

* doc

* Small fix

* Fix tabs, add missing const, fix style

* Add test case

* Small fixes

* suggested fix for async

* test for returned values
This commit is contained in:
Anton 2023-03-22 08:51:57 +03:00 committed by GitHub
parent 3838070146
commit 93d18162f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 84 additions and 1 deletions

View File

@ -88,6 +88,9 @@ protected:
AbstractBinding::BinderPtr binder();
/// Returns the concrete binder used by the statement.
void execDirectImpl(const std::string& query);
/// Execute query directly impl
std::string nativeSQL();
/// Returns the SQL string as modified by the driver.

View File

@ -228,6 +228,15 @@ void ODBCStatementImpl::bindImpl()
_pBinder->synchronize();
}
void ODBCStatementImpl::execDirectImpl(const std::string& query)
{
SQLCHAR * statementText = (SQLCHAR*) query.c_str();
SQLINTEGER textLength = query.size();
SQLRETURN rc = SQLExecDirect(_stmt,statementText,textLength);
checkError(rc, "SQLExecute()");
}
void ODBCStatementImpl::putData()
{

View File

@ -148,6 +148,25 @@ void ODBCSQLServerTest::testBareboneODBC()
executor().bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
}
void ODBCSQLServerTest::testTempTable()
{
session() << "IF(OBJECT_ID('tempdb..#test') is not null) drop table #test;", now;
std::string query("create table #test (s1 int,s2 int ,s3 int);");
Statement stmt(session());
stmt.executeDirect(query);
session() << "insert into #test select 1,2,3;", now;
typedef Poco::Tuple<int, int, int> testParam;
std::vector<testParam> testParams;
session() << ("select * from #test;"), into(testParams), now;
assertEquals(1, testParams.size());
assertEquals(1, testParams.front().get<0>());
assertEquals(2, testParams.front().get<1>());
assertEquals(3, testParams.front().get<2>());
}
void ODBCSQLServerTest::testBLOB()
{

View File

@ -40,6 +40,8 @@ public:
void testBareboneODBC();
void testTempTable();
void testBLOB();
void testNull();
void testBulk();

View File

@ -101,6 +101,7 @@ public:
virtual void testIllegalRange();
virtual void testSingleSelect();
virtual void testEmptyDB();
virtual void testTempTable();
virtual void testBLOB();
virtual void testBLOBContainer();
@ -221,8 +222,13 @@ private:
// inlines
//
inline void ODBCTest::testStoredProcedure()
inline void ODBCTest::testTempTable()
{
throw Poco::NotImplementedException("ODBCTest::testTempTable()");
}
inline void ODBCTest::testStoredProcedure()
{
throw Poco::NotImplementedException("ODBCTest::testStoredProcedure()");
}

View File

@ -304,6 +304,10 @@ public:
/// The result of execution (i.e. number of returned or affected rows) can be
/// obtained by calling wait() on the statement at a later point in time.
void executeDirect(const std::string& query);
/// Executes the query synchronously and directly.
/// If isAsync() returns true, the statement is also executed synchronously.
const Result& executeAsync(bool reset = true);
/// Executes the statement asynchronously.
/// Stops when either a limit is hit or the whole statement was executed.

View File

@ -133,6 +133,9 @@ public:
/// this execution step. When reset is false, data is appended to the
/// bound containers during multiple execute calls.
void executeDirect(const std::string& query);
/// Execute query directly.
void reset();
/// Resets the statement, so that we can reuse all bindings and re-execute again.
@ -199,6 +202,9 @@ protected:
virtual void bindImpl() = 0;
/// Binds parameters.
virtual void execDirectImpl(const std::string& query);
/// Execute query directly.
virtual AbstractExtraction::ExtractorPtr extractor() = 0;
/// Returns the concrete extractor used by the statement.

View File

@ -136,6 +136,23 @@ std::size_t Statement::execute(bool reset)
else throw InvalidAccessException("Statement still executing.");
}
void Statement::executeDirect(const std::string& query)
{
Mutex::ScopedLock lock(_mutex);
bool isDone = done();
if (initialized() || paused() || isDone)
{
if (!isAsync())
{
if (isDone) _pImpl->reset();
return _pImpl->executeDirect(query);
}
else throw InvalidAccessException("Cannot be executed async.");
}
else throw InvalidAccessException("Statement still executing.");
}
const Statement::Result& Statement::executeAsync(bool reset)
{

View File

@ -107,6 +107,18 @@ std::size_t StatementImpl::execute(const bool& reset)
return lim;
}
void StatementImpl::executeDirect(const std::string &query)
{
if (!_rSession.isConnected())
{
_state = ST_DONE;
throw NotConnectedException(_rSession.connectionString());
}
_ostr.str("");
_ostr << query;
execDirectImpl(_ostr.str());
}
void StatementImpl::assignSubTotal(bool reset)
{
@ -380,6 +392,11 @@ const MetaColumn& StatementImpl::metaColumn(const std::string& name) const
throw NotFoundException(format("Invalid column name: %s", name));
}
void StatementImpl::execDirectImpl(const std::string& query)
{
poco_assert("Not implemented");
}
std::size_t StatementImpl::activateNextDataSet()
{