Alpha Now
Alpha Now

Reputation: 53

Poco 1.5.2 C++ ODBC throws exceptions on insert

I have a program which reads information about 3D meshes in from a text file, stores the data as a mesh,performs some post-processing on the mesh, then collects information like volume, center of mass, etc.

The program has two threads: Main thread starts the second thread, reads the file, does the processing, then waits for the second thread. As a part of the processing, it puts information about the meshes its just read onto a queue. Second thread connects to SQL Server using Poco ODBC, puts some initial information about the file its reading into a database table, then gets information off the queue and assembles a potentially lengthy insert command. When it is done doing so, it submits the command, performs a final update command regarding the results of operations performed, then lets the main thread know it's done, and terminates the 2nd thread.

Everything works, right up until the moment it submits the large insert command. It throws an exception, and i can't figure out why.

Here i will give a simplistic outline of the code that is executing. Assume variables exist and are initialized. The poco commands i run are:

using namespace Poco;
using namespace Poco::Data::Keywords;
using namespace Poco::Data;
ODBC::Connector::registerConnector();
Session session(SessionFactory::instance().create("ODBC", "Driver={SQL Server};Server=<hostname>;Database=<DB name>;Uid=<username>;Pwd=<password>;"));

session << "INSERT INTO TableName1 (SourceFileName,UserName) VALUES (?,?)",use(_filename),use(username),now;
session << "SELECT SCOPE_IDENTITY()", into(runID),now; //This always runs and returns 0.
string queryString = "Insert into TableName2 (Field1, field2, field3, field4, ...) "+
      "VALUES (val1, val2, val3, val4, ...)"+
      ",(valA, valB, valC, valD, ...),..."

session << queryString,now; 
Statement update(session);
update << "UPDATE TableName1 SET Field2 = ?, Field3 = ?, Field4 = ? WHERE Field1 = ?", use(data2), use(data3), use(data3), use(identity);
update.execute();
ODBC::Connector::unregisterConnector();
<send signal to main thread indicating being done.>

I'm trying to figure out a few key things.

  1. How can I tell what state the Session is in?
  2. Is there a way to ask Poco what went wrong and have it print an error message?
  3. Are there any special things I need to set up to be able to specify a big insert statement all together in text like I am? I have tried it using ? placeholders, or executing individual statements, but it always gives me an exception on that part.
  4. Is there a way to have statements execute under the same connection for sure? Normally I would do my INSERT INTO TableName1(...)VALUES(...) SELECT SCOPE_IDENTITY() all as a single operation. I've tried my commands in SQL Server Management Studio and it works properly. Right now, it is always returning a 0 aka NULL, like the statements run in separate connections.

More information:

    String query = "INSERT INTO TableName1 (SourceFileName,UserName) VALUES ('"+ __file + "','" + __username + "')";
    Statement insertStmt = (session << query);
    try{insertStmt.execute(true);}
    catch(Poco::Exception exc)
    {
        cout << exc.displayText() << endl;
    }
    try{session << "SELECT SCOPE_IDENTITY() as SCOPE_IDENTITY", into(runID), now;
    cout << "Run ID: " << runID << endl;}
    catch(Poco::Exception exc)
    {
        cout << exc.displayText() << endl;
    }

I greatly appreciate your help or any suggestions on how I can improve this question.

Upvotes: 0

Views: 1365

Answers (1)

Alex
Alex

Reputation: 5330

1.: There are various query members in the Session class - isConnected(), canTransact(), isTransaction() ... (if that is what you are looking for; if not, see the next answer)


1. and 2.: Wrap your statement into try/catch block:

#include "Poco/Data/ODBC/ODBCException.h"
//...
try 
{
 session << "INSERT INTO TableName1 (SourceFileName, UserName) VALUES (?, ?) ",use(_filename),use(username),now;
}
catch(Poco::Data::ODBC::ConnectionException& ce){ std::cout << ce.toString() << std::endl; }
catch(Poco::Data::ODBC::StatementException& se){ std::cout << se.toString() << std::endl; }

3.: I don't think the problem is too large statement. There is a configurable internal setting limiting the string size to 1K, but this applies to value strings, not the whole SQL statement. If you still think that is the problem, you can increase the max field size, e.g.:

std::size_t fieldSize = 4096; //4K
session.impl()->setProperty("maxFieldSize", Poco::Any(fieldSize));

4.: Poco::Data::ODBC does not parse or analyze the SQL statement in any way; so from that standpoint, whatever works with your ODBC driver will be fine.

Upvotes: 2

Related Questions