Feature PosgreSQL copy in (#2529)

* Added unit-test for testing support COPY FROM feature of PostgreSQL

Test try execute simple usage of COPY FROM with batch of data such as std::vector<int>

* Made main logic of feature COPY IN for SQL/PostgreSQL

* Added bulk binding for general types.
* Added support of bulk bindings for user types. For supporting this feature user needs implement
yet another TypeHandler<> for std::vector<T> which contains pointer to SQL::PostgreSQL::Binder in
params instead of SQL::Binder.
* Added yet another test-case for testing usage COPY IN with user types.

Other functionality need implement by developing COPY OUT feature.

* Check with a large number of objects

* Added tests for complex inserting thru std::list<> and std::deque<> by COPY IN mode

* Made feature COPY IN for batches of data like std::list<> and std::deque<>

* Changed spaces to tabs and was a little refactoring

* Fix new line in for-loops
This commit is contained in:
Aleksmia
2018-11-27 17:20:29 +03:00
committed by Aleksandar Fabijanic
parent 070685e38c
commit e60ece37d4
11 changed files with 743 additions and 127 deletions

View File

@@ -219,6 +219,17 @@ void StatementExecutor::bindParams(const InputParameterVector& anInputParameterV
}
void StatementExecutor::bindBulkParams(const InputParameterVector& inputBulkParamVec)
{
if (! _sessionHandle.isConnected()) throw NotConnectedException();
if (_state < STMT_COMPILED) throw StatementException("Statement is not compiled yet");
// Just record the input vector for later execution
_inputBulkParameterVector = inputBulkParamVec;
}
void StatementExecutor::execute()
{
if (! _sessionHandle.isConnected()) throw NotConnectedException();
@@ -276,8 +287,30 @@ void StatementExecutor::execute()
// Don't setup to auto clear the result (ptrPGResult). It is required to retrieve the results later.
if (!ptrPGResult || (PQresultStatus(ptrPGResult) != PGRES_COMMAND_OK &&
PQresultStatus(ptrPGResult) != PGRES_TUPLES_OK))
if (!ptrPGResult || (PQresultStatus(ptrPGResult) == PGRES_COPY_IN))
{
InputParameterVector::const_iterator cItr = _inputBulkParameterVector.begin();
InputParameterVector::const_iterator cItrEnd = _inputBulkParameterVector.end();
for (; cItr != cItrEnd; ++cItr)
{
const char *bulkBuffer = static_cast<const char*>(cItr->pInternalRepresentation());
if (PQputCopyData(_sessionHandle, bulkBuffer, strlen(bulkBuffer)) != 1)
{
ptrPGResult = PQgetResult(_sessionHandle);
}
}
if (PQputCopyEnd(_sessionHandle, nullptr) != 1)
{
ptrPGResult = PQgetResult(_sessionHandle);
}
}
if (!ptrPGResult || (PQresultStatus(ptrPGResult) != PGRES_COMMAND_OK &&
PQresultStatus(ptrPGResult) != PGRES_TUPLES_OK &&
PQresultStatus(ptrPGResult) != PGRES_COPY_IN))
{
PQResultClear resultClearer(ptrPGResult);