У меня есть программа, которая считывает информацию о трехмерных сетках из текстового файла, сохраняет данные в виде сетки, выполняет некоторую пост-обработку на сетке, затем собирает информацию, такую как объем, центр масс и т.д.
Программа имеет два потока: основной поток запускает второй поток, считывает файл, выполняет обработку, а затем ждет второй поток. Как часть обработки, он помещает информацию о сетках, которые он просто считывает в очередь. Второй поток подключается к SQL Server с помощью Poco ODBC, помещает некоторую начальную информацию о файле, его чтение в таблицу базы данных, затем получает информацию из очереди и собирает потенциально длинную команду вставки. Когда это будет сделано, он отправит команду, выполнит окончательную команду обновления, касающуюся результатов выполненных операций, а затем сообщит основному потоку и завершает второй поток.
Все работает, вплоть до момента подачи большой команды вставки. Он выдает исключение, и я не могу понять, почему.
Здесь я дам упрощенную схему выполняемого кода. Предположим, что существуют и инициализируются переменные. Команды poco, которые я запускаю:
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.>
Я пытаюсь понять несколько ключевых моментов.
Больше информации:
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;
}
Я высоко ценю вашу помощь или любые предложения о том, как я могу улучшить этот вопрос.
1. В классе Session есть различные члены запроса - isConnected(), canTransact(), isTransaction()... (если это то, что вы ищете, а если нет, см. Следующий ответ)
1. и 2.: Заверните свое выражение в блок try/catch:
#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.: Я не думаю, что проблема слишком велика. Существует настраиваемая внутренняя настройка, ограничивающая размер строки до 1K, но это относится к строкам значений, а не ко всей инструкции SQL. Если вы все еще считаете, что это проблема, вы можете увеличить размер максимального поля, например:
std::size_t fieldSize = 4096; //4K
session.impl()->setProperty("maxFieldSize", Poco::Any(fieldSize));
4.: Poco :: Data :: ODBC не анализирует и не анализирует инструкцию SQL; поэтому с этой точки зрения все, что работает с вашим драйвером ODBC, будет в порядке.