fix(Data):

* make bool Session::isTransaction() return Poco::Optional
* move parsing to Statement
* SQLParser make build
* other fixes and improvemets #4230
This commit is contained in:
Alex Fabijanic 2023-11-01 00:25:21 +01:00
parent e174be8660
commit 6dad8502d3
45 changed files with 949 additions and 196 deletions

View File

@ -23,7 +23,7 @@
"${POCO_BASE}/Redis/include",
"${POCO_BASE}/MongoDB/include",
"${POCO_BASE}/ApacheConnector/include",
"/usr/include"
"${POCO_BASE}/Data/src"
]
},
"configurations": [

View File

@ -95,7 +95,11 @@
"strstream": "cpp",
"future": "cpp",
"shared_mutex": "cpp",
"stop_token": "cpp"
"stop_token": "cpp",
"codecvt": "cpp",
"numbers": "cpp",
"span": "cpp",
"semaphore": "cpp"
},
"files.exclude": {
"**/.dep": true,

View File

@ -15,8 +15,16 @@ objects = AbstractBinder AbstractBinding AbstractExtraction AbstractExtractor \
SessionPool SessionPoolContainer SQLChannel \
Statement StatementCreator StatementImpl Time Transcoder
target = PocoData
target_version = $(LIBVERSION)
target_libs = PocoFoundation
ifndef POCO_DATA_NO_SQL_PARSER
objects += SQLParser SQLParserResult \
bison_parser flex_lexer \
CreateStatement PrepareStatement SQLStatement \
Expr statements sqlhelper
target_includes = $(POCO_BASE)/Data/src
endif
target = PocoData
target_version = $(LIBVERSION)
target_libs = PocoFoundation
include $(POCO_BASE)/build/rules/lib

View File

@ -15,6 +15,10 @@ objects = Binder Extractor SessionImpl Connector \
MySQLStatementImpl ResultMetadata MySQLException \
SessionHandle StatementExecutor Utility
ifndef POCO_DATA_NO_SQL_PARSER
target_includes = $(POCO_BASE)/Data/src
endif
target = PocoDataMySQL
target_version = $(LIBVERSION)
target_libs = PocoData PocoFoundation

View File

@ -13,6 +13,10 @@ SYSLIBS += -lmysqlclient -lz -lpthread -ldl
objects = MySQLTestSuite Driver MySQLTest SQLExecutor
ifndef POCO_DATA_NO_SQL_PARSER
target_includes = $(POCO_BASE)/Data/src
endif
target = testrunner
target_version = 1
target_libs = PocoDataMySQL PocoData PocoFoundation CppUnit

View File

@ -12,6 +12,10 @@ objects = Binder ConnectionHandle Connector EnvironmentHandle \
Extractor ODBCException ODBCMetaColumn ODBCStatementImpl \
Parameter Preparator SessionImpl TypeInfo Unicode Utility
ifndef POCO_DATA_NO_SQL_PARSER
target_includes = $(POCO_BASE)/Data/src
endif
target = PocoDataODBC
target_version = $(LIBVERSION)
target_libs = PocoData PocoFoundation

View File

@ -61,8 +61,6 @@ public:
SQLRETURN rc =
#endif
SQLFreeHandle(handleType, _handle);
// N.B. Destructors should not throw, but neither do we want to
// leak resources. So, we throw here in debug mode if things go bad.
poco_assert_dbg (!Utility::isError(rc));
}
catch (...)

View File

@ -373,7 +373,7 @@ void ODBCStatementImpl::makeStep()
_extractors[currentDataSet()]->reset();
_nextResponse = SQLFetch(_stmt);
// workaround for SQL Server drivers 17, 18, ...
// stored procedure calls produce additional data,
// stored procedure calls may produce additional data,
// causing SQLFetch error 24000 (invalid cursor state);
// when it happens, SQLMoreResults() is called to
// force SQL_NO_DATA response

View File

@ -33,6 +33,10 @@ ifeq ($(POCO_CONFIG),MinGW)
objects += ODBCAccessTest
endif
ifndef POCO_DATA_NO_SQL_PARSER
target_includes = $(POCO_BASE)/Data/src
endif
target = testrunner
target_version = 1
target_libs = PocoDataODBC PocoData PocoFoundation CppUnit

View File

@ -968,9 +968,9 @@ CppUnit::Test* ODBCSQLServerTest::suite()
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSQLLogger);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testAutoCommit);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSessionTransactionNoAutoCommit);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransaction);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransactionIsolation);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSessionTransaction);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransaction);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTransactor);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testNullable);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testUnicode);

View File

@ -1230,7 +1230,7 @@ void ODBCTest::testTransactionIsolation()
recreatePersonTable();
_pSession->setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i+1));
_pExecutor->transactionIsolation(_rConnectString);
_pExecutor->transactionIsolation();
i += 2;
}
}

View File

@ -4187,7 +4187,7 @@ void SQLExecutor::autoCommit(const std::string& connect)
}
void SQLExecutor::transactionIsolation(const std::string& connect)
void SQLExecutor::transactionIsolation()
{
auto ti = session().getTransactionIsolation();
@ -4225,18 +4225,25 @@ void SQLExecutor::sessionTransaction(const std::string& connect)
std::string result;
session().setFeature("autoCommit", true);
assertTrue (session().getFeature("autoCommit"));
assertTrue (!session().isTransaction());
session().begin();
assertTrue (session().isTransaction());
assertTrue (!session().getFeature("autoCommit"));
// autocommit is invalid for session in transaction ...
// changing autocommit is invalid for session in transaction ...
try
{
session().setFeature("autoCommit", true);
fail ("must fail on autocommit setting during transaction");
}
catch(const Poco::InvalidAccessException& e) { }
// make sure nothing was changed ...
assertTrue (!session().getFeature("autoCommit"));
// but setting it to its current state is allowed (no-op)
session().setFeature("autoCommit", false);
assertTrue (!session().getFeature("autoCommit"));
session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
assertTrue (session().isTransaction());
@ -4293,6 +4300,7 @@ void SQLExecutor::sessionTransactionNoAutoCommit(const std::string& connect)
}
std::string funct = "sessionTransactionNoAutoCommit()";
std::vector<std::string> lastNames = {"LN1", "LN2"};
std::vector<std::string> firstNames = {"FN1", "FN2"};
std::vector<std::string> addresses = {"ADDR1", "ADDR2"};
@ -4311,20 +4319,24 @@ void SQLExecutor::sessionTransactionNoAutoCommit(const std::string& connect)
local << "SELECT COUNT(*) FROM Person", into(locCount), now;
assertTrue (0 == count);
assertTrue (2 == locCount);
#ifndef POCO_DATA_NO_SQL_PARSER
assertTrue (local.isTransaction());
// autocommit is invalid for session in transaction ...
try
{
local.setFeature("autoCommit", true);
fail ("must fail on autocommit setting during transaction");
fail ("must fail on autocommit setting during transaction", __LINE__);
}
catch(const Poco::InvalidAccessException& e) { }
// but setting it to its current state is allowed (no-op)
local.setFeature("autoCommit", false);
assertTrue (!session().isTransaction());
#else
session().commit();
#endif // POCO_DATA_NO_SQL_PARSER
local.commit();
assertTrue (!local.isTransaction());
@ -4341,8 +4353,12 @@ void SQLExecutor::sessionTransactionNoAutoCommit(const std::string& connect)
local << "SELECT COUNT(*) FROM Person", into(locCount), now;
assertTrue (0 == count);
assertTrue (4 == locCount);
#ifndef POCO_DATA_NO_SQL_PARSER
assertTrue (local.isTransaction());
assertTrue (!session().isTransaction());
#else
session().commit();
#endif
local.rollback();
assertTrue (!local.isTransaction());
@ -4354,7 +4370,10 @@ void SQLExecutor::sessionTransactionNoAutoCommit(const std::string& connect)
local << "SELECT COUNT(*) FROM Person", into(locCount), now;
assertTrue (2 == count);
assertTrue (2 == locCount);
#ifndef POCO_DATA_NO_SQL_PARSER
session().commit();
local.commit();
#endif
session().setFeature("autoCommit", autoCommit);
}
@ -4399,34 +4418,26 @@ void SQLExecutor::transaction(const std::string& connect)
assertTrue (trans.isActive());
assertTrue (session().isTransaction());
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
assertTrue (session().isTransaction());
assertTrue (trans.isActive());
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
session() << "SELECT COUNT(*) FROM Person", into(count), now;
assertTrue (2 == count);
assertTrue (session().isTransaction());
assertTrue (trans.isActive());
}
assertTrue (!session().isTransaction());
try { session() << "SELECT count(*) FROM Person", into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
session() << "SELECT count(*) FROM Person", into(count), now;
assertTrue (0 == count);
assertTrue (session().isTransaction());
assertTrue (!session().isTransaction());
session().commit();
{
Transaction trans(session());
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
@ -4440,20 +4451,14 @@ void SQLExecutor::transaction(const std::string& connect)
assertTrue (2 == locCount);
}
try { session() << "SELECT count(*) FROM Person", into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
session() << "SELECT count(*) FROM Person", into(count), now;
assertTrue (2 == count);
try { session() << "DELETE FROM Person", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
session() << "DELETE FROM Person", now;
Statement stmt1 = (local << "SELECT count(*) FROM Person", into(locCount), async, now);
try { session() << "SELECT count(*) FROM Person", into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
session() << "SELECT count(*) FROM Person", into(count), now;
assertTrue (0 == count);
try
{
@ -4493,9 +4498,7 @@ void SQLExecutor::transaction(const std::string& connect)
stmt2.wait();
assertTrue (0 == locCount);
try { session() << "SELECT count(*) FROM Person", into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
session() << "SELECT count(*) FROM Person", into(count), now;
assertTrue (0 == count);
trans.execute(sql);
@ -4503,9 +4506,7 @@ void SQLExecutor::transaction(const std::string& connect)
Statement stmt3 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
assertTrue (2 == locCount);
try { session() << "SELECT count(*) FROM Person", into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
session() << "SELECT count(*) FROM Person", into(count), now;
assertTrue (2 == count);
session().commit();

View File

@ -512,7 +512,7 @@ public:
void sqlLogger(const std::string& connect);
void autoCommit(const std::string& connect);
void transactionIsolation(const std::string& connect);
void transactionIsolation();
void sessionTransaction(const std::string& connect);
void sessionTransactionNoAutoCommit(const std::string& connect);

View File

@ -12,6 +12,10 @@ objects = Extractor BinaryExtractor Binder SessionImpl Connector \
PostgreSQLStatementImpl PostgreSQLException \
SessionHandle StatementExecutor PostgreSQLTypes Utility
ifndef POCO_DATA_NO_SQL_PARSER
target_includes = $(POCO_BASE)/Data/src
endif
target = PocoDataPostgreSQL
target_version = $(LIBVERSION)
target_libs = PocoData PocoFoundation

View File

@ -13,6 +13,10 @@ SYSLIBS += -lpq -lz -lpthread -ldl
objects = PostgreSQLTestSuite Driver PostgreSQLTest SQLExecutor
ifndef POCO_DATA_NO_SQL_PARSER
target_includes = $(POCO_BASE)/Data/src
endif
target = testrunner
target_version = 1
target_libs = PocoDataPostgreSQL PocoData PocoFoundation CppUnit

View File

@ -9,18 +9,20 @@ include $(POCO_BASE)/build/rules/global
COMMONFLAGS += -I$(POCO_BASE)/Data/SQLite/src
SYSFLAGS += -DSQLITE_THREADSAFE=1 -DSQLITE_DISABLE_LFS \
-DSQLITE_OMIT_UTF16 -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_COMPLETE \
-DSQLITE_OMIT_TCL_VARIABLE -DSQLITE_OMIT_DEPRECATED
-DSQLITE_OMIT_UTF16 -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_COMPLETE \
-DSQLITE_OMIT_TCL_VARIABLE -DSQLITE_OMIT_DEPRECATED
objects = Binder Extractor Notifier SessionImpl Connector \
SQLiteException SQLiteStatementImpl Utility
sqlite_objects = sqlite3
SQLiteException SQLiteStatementImpl Utility
ifdef POCO_UNBUNDLED
SYSLIBS += -lsqlite3
SYSLIBS += -lsqlite3
else
objects += $(sqlite_objects)
objects += sqlite3
endif
ifndef POCO_DATA_NO_SQL_PARSER
target_includes = $(POCO_BASE)/Data/src
endif
target = PocoDataSQLite

View File

@ -9,6 +9,10 @@ include $(POCO_BASE)/build/rules/global
objects = SQLiteTestSuite Driver \
SQLiteTest
ifndef POCO_DATA_NO_SQL_PARSER
target_includes = $(POCO_BASE)/Data/src
endif
target = testrunner
target_version = 1
target_libs = PocoDataSQLite PocoData PocoFoundation CppUnit

View File

@ -20,7 +20,7 @@
#include "Poco/Config.h"
#ifdef POCO_DATA_ENABLE_SQL_PARSER
#ifndef POCO_DATA_NO_SQL_PARSER
#include "sql-parser/src/SQLParser.h"
@ -29,13 +29,14 @@
namespace Poco {
namespace Data {
namespace Data = hsql;
namespace Parser = hsql; // namespace Poco::Data::Parser
} // namespace Poco
} } // namespace Poco::Data
#endif // POCO_DATA_ENABLE_SQL_PARSER
#endif // POCO_DATA_NO_SQL_PARSER
#endif // Data_SQLParser_INCLUDED

View File

@ -199,12 +199,9 @@ public:
template <typename T>
Statement operator << (const T& t)
/// Creates a Statement with the given data as SQLContent
/// Creates a Statement with the given string as SQLContent.
{
Statement stmt = (_statementCreator << t);
if (!_pImpl->isTransaction() && !isAutocommit())
_pImpl->begin();
return stmt;
return (_statementCreator << t);
}
SharedPtr<StatementImpl> createStatementImpl();
@ -356,7 +353,7 @@ private:
inline bool Session::isAutocommit() const
{
return hasFeature("autoCommit") && getFeature("autoCommit");
return _pImpl->isAutocommit();
}

View File

@ -146,6 +146,9 @@ public:
std::string uri() const;
/// Returns the URI for this session.
bool isAutocommit() const;
/// Returns true if autocommit is on, false otherwise.
virtual bool hasFeature(const std::string& name) const = 0;
/// Returns true if session has the named feature.
@ -238,6 +241,12 @@ inline std::string SessionImpl::uri() const
}
inline bool SessionImpl::isAutocommit() const
{
return hasFeature("autoCommit") && getFeature("autoCommit");
}
} } // namespace Poco::Data

View File

@ -24,12 +24,14 @@
#include "Poco/Data/Range.h"
#include "Poco/Data/Bulk.h"
#include "Poco/Data/Row.h"
#include "Poco/Data/SQLParser.h"
#include "Poco/Data/SimpleRowFormatter.h"
#include "Poco/SharedPtr.h"
#include "Poco/Mutex.h"
#include "Poco/ActiveMethod.h"
#include "Poco/ActiveResult.h"
#include "Poco/Format.h"
#include "Poco/Optional.h"
#include <algorithm>
@ -70,6 +72,18 @@ class Data_API Statement
/// member function.
/// If no formatter is externally supplied to the statement, the SimpleRowFormatter is lazy
/// created and used.
///
/// If compiled with SQLParser support, Statement knows the number and type of the SQL statement(s)
/// it contains, to the extent that the SQL string is a standard SQL and the staement type is supported.
/// No proprietary SQL extensions are supported.
///
/// Supported statement types are:
///
/// - SELECT
/// - INSERT
/// - UPDATE
/// - DELETE
///
{
public:
typedef void (*Manipulator)(Statement&);
@ -189,9 +203,9 @@ public:
/// Registers extraction container with the Statement.
{
if (reset) _pImpl->resetExtraction();
typename C::iterator itAE = val.begin();
typename C::iterator itAEEnd = val.end();
for (; itAE != itAEEnd; ++itAE) addExtract(*itAE);
typename C::iterator it = val.begin();
typename C::iterator end = val.end();
for (; it != end; ++it) addExtract(*it);
return *this;
}
@ -200,9 +214,9 @@ public:
/// Registers container of extraction containers with the Statement.
{
_pImpl->resetExtraction();
typename C::iterator itAEV = val.begin();
typename C::iterator itAEVEnd = val.end();
for (; itAEV != itAEVEnd; ++itAEV) addExtraction(*itAEV, false);
typename C::iterator it = val.begin();
typename C::iterator end = val.end();
for (; it != end; ++it) addExtraction(*it, false);
return *this;
}
@ -291,6 +305,53 @@ public:
const std::string& toString() const;
/// Creates a string from the accumulated SQL statement.
std::size_t statementsCount() const;
/// Returns the total number of SQL statements held in the accummulated SQL statement.
Optional<bool> parse();
/// Parses the SQL statement and returns true if successful.
///
/// Note that parsing is not guaranteed to succeed, as some backends have proprietary
/// keywords not supported by the parser. Parsing failures are silent in terms of
/// throwing exceptions or logging, but it is possible to get error information by
/// calling parseError().
const std::string& parseError();
/// Returns the SQL statement parse error message, if any.
/// For Poco::Data builds without SQLParser, it always returns empty string.
Optional<bool> isSelect() const;
/// Returns true if the statement consists only of SELECT statement(s).
/// For Poco::Data builds without SQLParser, it always returns unspecified.
Optional<bool> isInsert() const;
/// Returns true if the statement consists only of INSERT statement(s).
/// For Poco::Data builds without SQLParser, it always returns unspecified.
Optional<bool> isUpdate() const;
/// Returns true if the statement consists only of UPDATE statement(s).
/// For Poco::Data builds without SQLParser, it always returns unspecified.
Optional<bool> isDelete() const;
/// Returns true if the statement consists only of DELETE statement(s).
/// For Poco::Data builds without SQLParser, it always returns unspecified.
Optional<bool> hasSelect() const;
/// Returns true if the statement contains a SELECT statement.
/// For Poco::Data builds without SQLParser, it always returns unspecified.
Optional<bool> hasInsert() const;
/// Returns true if the statement contains an INSERT statement.
/// For Poco::Data builds without SQLParser, it always returns unspecified.
Optional<bool> hasUpdate() const;
/// Returns true if the statement contains an UPDATE statement.
/// For Poco::Data builds without SQLParser, it always returns unspecified.
Optional<bool> hasDelete() const;
/// Returns true if the statement contains a DELETE statement.
/// For Poco::Data builds without SQLParser, it always returns unspecified.
std::size_t execute(bool reset = true);
/// Executes the statement synchronously or asynchronously.
/// Stops when either a limit is hit or the whole statement was executed.
@ -298,15 +359,35 @@ public:
/// returning data) or number of rows affected (for all other statements).
/// If reset is true (default), associated storage is reset and reused.
/// Otherwise, the results from this execution step are appended.
/// Reset argument has no meaning for unlimited statements that return all rows.
/// The reset argument has no meaning for unlimited statements that return all rows.
/// If isAsync() returns true, the statement is executed asynchronously
/// and the return value from this function is zero.
/// 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.
///
/// When Poco::Data is compiled with SQL parsing support, if session is not already in
/// a transaction and not in autocommit mode, an attempt to parse the SQL is made before
/// statement execution, and if (1) successful, and (2) the statement does not consist
/// only of SELECT statements, a transaction is started.
///
/// Note that parsing is not guaranteed to succeed, as some backends have proprietary
/// keywords not supported by the parser. Parsing failures are silent in terms of
/// throwing exceptions or logging, but it is possible to get error information by calling
/// Statement::parseError().
/// When parsing does not succeed, transaction is not started, and Poco::Data::Session will
/// not reflect its state accurately. The underlying database session, however, will be in
/// transaction state. In such state, in order to complete the transaction and unlock the
/// resources, commit() or rollback() must be called on the Poco::Data::Session; this is
/// true even for a single SELECT statement in non-autocommit mode when parsing does not
/// succeed.
///
/// For Poco::Data builds without SQLParser support, the behavior is the same as
/// for unsuccesful parsing.
void executeDirect(const std::string& query);
/// Executes the query synchronously and directly.
/// If isAsync() returns true, the statement is also executed synchronously.
/// Even when isAsync() returns true, the statement is still executed synchronously.
/// For transactional behavior, see execute() documentation.
const Result& executeAsync(bool reset = true);
/// Executes the statement asynchronously.
@ -316,6 +397,7 @@ public:
/// of rows affected by the statement execution.
/// When executed on a synchronous statement, this method does not alter the
/// statement's synchronous nature.
/// For transactional behavior, see execute() documentation.
void setAsync(bool async = true);
/// Sets the asynchronous flag. If this flag is true, executeAsync() is called
@ -343,7 +425,10 @@ public:
/// and there is more work to do. When no limit is set, it will always return true after calling execute().
Statement& reset(Session& session);
/// Resets the Statement so that it can be filled with a new SQL command.
/// Resets the Statement and assigns it a new session, so that it can be filled with a new SQL query.
Statement& reset();
/// Resets the Statement so that it can be filled with a new SQL query.
bool canModifyStorage();
/// Returns true if statement is in a state that allows the internal storage to be modified.
@ -435,6 +520,33 @@ private:
return *this;
}
void formatQuery();
/// Formats the query string.
void checkBeginTransaction();
/// Checks if the transaction needs to be started
/// and starts it if not.
/// Transaction is automatically started for the first
/// statement on a non-autocommit session.
/// The best effort is made to detect if the query
/// consists of SELECT statements only, in which case
/// transaction does not need to started.
/// However, due to many SQL dialects, this logic is
/// not 100% accurate and transaction MAY be started
/// for SELECT-only queries.
#ifndef POCO_DATA_NO_SQL_PARSER
bool isType(Parser::StatementType type) const;
/// Returns true if the statement is of the argument type.
bool hasType(Parser::StatementType type) const;
/// Returns true if the statement is of the argument type.
Poco::SharedPtr<Parser::SQLParserResult> _pParseResult;
#endif // POCO_DATA_NO_SQL_PARSER
StatementImpl::Ptr _pImpl;
// asynchronous execution related members
@ -445,6 +557,7 @@ private:
std::vector<Any> _arguments;
RowFormatter::Ptr _pRowFormatter;
mutable std::string _stmtString;
std::string _parseError;
};
//
@ -456,6 +569,92 @@ inline std::size_t Statement::subTotalRowCount(int dataSet) const
}
inline const std::string& Statement::parseError()
{
return _parseError;
}
inline Optional<bool> Statement::isSelect() const
{
#ifndef POCO_DATA_NO_SQL_PARSER
return isType(Parser::StatementType::kStmtSelect);
#else
return Optional<bool>();
#endif
}
inline Optional<bool> Statement::isInsert() const
{
#ifndef POCO_DATA_NO_SQL_PARSER
return isType(Parser::StatementType::kStmtInsert);
#else
return Optional<bool>();
#endif
}
inline Optional<bool> Statement::isUpdate() const
{
#ifndef POCO_DATA_NO_SQL_PARSER
return isType(Parser::StatementType::kStmtUpdate);
#else
return Optional<bool>();
#endif
}
inline Optional<bool> Statement::isDelete() const
{
#ifndef POCO_DATA_NO_SQL_PARSER
return isType(Parser::StatementType::kStmtDelete);
#else
return Optional<bool>();
#endif
}
inline Optional<bool> Statement::hasSelect() const
{
#ifndef POCO_DATA_NO_SQL_PARSER
return hasType(Parser::StatementType::kStmtSelect);
#else
return Optional<bool>();
#endif
}
inline Optional<bool> Statement::hasInsert() const
{
#ifndef POCO_DATA_NO_SQL_PARSER
return hasType(Parser::StatementType::kStmtInsert);
#else
return Optional<bool>();
#endif
}
inline Optional<bool> Statement::hasUpdate() const
{
#ifndef POCO_DATA_NO_SQL_PARSER
return hasType(Parser::StatementType::kStmtUpdate);
#else
return Optional<bool>();
#endif
}
inline Optional<bool> Statement::hasDelete() const
{
#ifndef POCO_DATA_NO_SQL_PARSER
return hasType(Parser::StatementType::kStmtDelete);
#else
return Optional<bool>();
#endif
}
namespace Keywords {

View File

@ -68,10 +68,30 @@ public:
return stmt;
}
void reset();
/// Resets the StatementCreator.
private:
Poco::AutoPtr<SessionImpl> _ptrImpl;
};
//
// inlines
//
inline void StatementCreator::swap(StatementCreator& other) noexcept
{
using std::swap;
swap(_ptrImpl, other._ptrImpl);
}
inline void StatementCreator::reset()
{
_ptrImpl = nullptr;
}
} } // namespace Poco::Data

View File

@ -28,6 +28,10 @@
#include "Poco/SharedPtr.h"
#include <cstddef>
#if defined(POCO_COMPILER_GCC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuse-after-free"
#endif
namespace Poco {
namespace Data {
@ -5750,5 +5754,8 @@ private:
} } // namespace Poco::Data
#if defined(POCO_COMPILER_GCC)
#pragma GCC diagnostic pop
#endif
#endif // Data_TypeHandler_INCLUDED

View File

@ -60,6 +60,9 @@ Session::Session(Session&& other) noexcept:
_statementCreator(std::move(other._statementCreator)),
_wasAutoCommit(other._wasAutoCommit)
{
other._pImpl = nullptr;
other._statementCreator.reset();
other._wasAutoCommit = false;
}
Session::~Session()

View File

@ -28,6 +28,9 @@ namespace Data {
Statement::Statement(StatementImpl::Ptr pImpl):
#ifndef POCO_DATA_NO_SQL_PARSER
_pParseResult(new Parser::SQLParserResult()),
#endif
_pImpl(pImpl),
_async(false)
{
@ -43,24 +46,42 @@ Statement::Statement(Session& session):
Statement::Statement(const Statement& stmt):
#ifndef POCO_DATA_NO_SQL_PARSER
_pParseResult(stmt._pParseResult),
#endif
_pImpl(stmt._pImpl),
_async(stmt._async),
_pResult(stmt._pResult),
_pAsyncExec(stmt._pAsyncExec),
_arguments(stmt._arguments),
_pRowFormatter(stmt._pRowFormatter)
_pRowFormatter(stmt._pRowFormatter),
_stmtString(stmt._stmtString),
_parseError(stmt._parseError)
{
}
Statement::Statement(Statement&& stmt) noexcept:
#ifndef POCO_DATA_NO_SQL_PARSER
_pParseResult(std::move(stmt._pParseResult)),
#endif
_pImpl(std::move(stmt._pImpl)),
_async(std::move(stmt._async)),
_pResult(std::move(stmt._pResult)),
_pAsyncExec(std::move(stmt._pAsyncExec)),
_arguments(std::move(stmt._arguments)),
_pRowFormatter(std::move(stmt._pRowFormatter))
_pRowFormatter(std::move(stmt._pRowFormatter)),
_stmtString(std::move(stmt._stmtString)),
_parseError(std::move(stmt._parseError))
{
stmt._pImpl = nullptr;
stmt._async = false;
stmt._pResult = nullptr;
stmt._pAsyncExec = nullptr;
stmt._arguments.clear();
stmt._pRowFormatter = nullptr;
_stmtString.clear();
_parseError.clear();
}
@ -79,12 +100,25 @@ Statement& Statement::operator = (const Statement& stmt)
Statement& Statement::operator = (Statement&& stmt) noexcept
{
#ifndef POCO_DATA_NO_SQL_PARSER
_pParseResult = std::move(stmt._pParseResult);
#endif
_pImpl = std::move(stmt._pImpl);
stmt._pImpl = nullptr;
_async = std::move(stmt._async);
stmt._async = false;
_pResult = std::move(stmt._pResult);
stmt._pResult = nullptr;
_pAsyncExec = std::move(stmt._pAsyncExec);
stmt._pAsyncExec = nullptr;
_arguments = std::move(stmt._arguments);
stmt._arguments.clear();
_pRowFormatter = std::move(stmt._pRowFormatter);
stmt._pRowFormatter = nullptr;
_stmtString = std::move(stmt._stmtString);
_stmtString.clear();
_parseError = std::move(stmt._parseError);
_parseError.clear();
return *this;
}
@ -92,13 +126,17 @@ Statement& Statement::operator = (Statement&& stmt) noexcept
void Statement::swap(Statement& other) noexcept
{
using std::swap;
#ifndef POCO_DATA_NO_SQL_PARSER
swap(_pParseResult, other._pParseResult);
#endif
swap(_pImpl, other._pImpl);
swap(_async, other._async);
swap(_pAsyncExec, other._pAsyncExec);
swap(_pResult, other._pResult);
swap(_pAsyncExec, other._pAsyncExec);
_arguments.swap(other._arguments);
swap(_pRowFormatter, other._pRowFormatter);
swap(_stmtString, other._stmtString);
swap(_parseError, other._parseError);
}
@ -110,17 +148,107 @@ Statement& Statement::reset(Session& session)
}
Statement& Statement::reset()
{
Statement stmt(_pImpl->session().createStatementImpl());
swap(stmt);
return *this;
}
std::size_t Statement::statementsCount() const
{
#ifndef POCO_DATA_NO_SQL_PARSER
return _pParseResult->size();
#else
return 0u;
#endif
}
Optional<bool> Statement::parse()
{
Optional<bool> result;
#ifndef POCO_DATA_NO_SQL_PARSER
if (_stmtString.empty()) toString();
if (!_stmtString.empty())
{
_pParseResult->reset();
Parser::SQLParser::parse(_stmtString, _pParseResult.get());
result = _pParseResult->isValid();
if (!result.value())
{
Poco::format(_parseError, "%s (line %d, pos %d)",
std::string(_pParseResult->errorMsg()),
_pParseResult->errorLine(),
_pParseResult->errorColumn());
}
}
#endif
return result;
}
#ifndef POCO_DATA_NO_SQL_PARSER
bool Statement::isType(Parser::StatementType type) const
{
std::size_t sz = _pParseResult->size();
if (sz)
{
for (int i = 0; i < sz; ++i)
{
if (_pParseResult->getStatement(i)->type() != type)
return false;
}
return true;
}
return false;
}
bool Statement::hasType(Parser::StatementType type) const
{
for (int i = 0; i < _pParseResult->size(); ++i)
{
if (_pParseResult->getStatement(i)->type() == type)
return true;
}
return false;
}
#endif // POCO_DATA_NO_SQL_PARSER
void Statement::formatQuery()
{
if (_arguments.size())
{
_pImpl->formatSQL(_arguments);
_arguments.clear();
}
}
void Statement::checkBeginTransaction()
{
SessionImpl& session = _pImpl->session();
if (!session.isAutocommit() && !session.isTransaction())
{
auto result = parse();
if (result.isSpecified() && result.value() && !isSelect().value())
session.begin();
}
}
std::size_t Statement::execute(bool reset)
{
Mutex::ScopedLock lock(_mutex);
bool isDone = done();
if (initialized() || paused() || isDone)
{
if (_arguments.size())
{
_pImpl->formatSQL(_arguments);
_arguments.clear();
}
formatQuery();
checkBeginTransaction();
if (!isAsync())
{
@ -136,12 +264,15 @@ 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)
{
formatQuery();
checkBeginTransaction();
if (!isAsync())
{

View File

@ -40,6 +40,7 @@ StatementCreator::StatementCreator(const StatementCreator& other):
StatementCreator::StatementCreator(StatementCreator&& other) noexcept:
_ptrImpl(std::move(other._ptrImpl))
{
other._ptrImpl = nullptr;
}
@ -54,15 +55,10 @@ StatementCreator& StatementCreator::operator = (const StatementCreator& other)
StatementCreator& StatementCreator::operator = (StatementCreator&& other) noexcept
{
_ptrImpl = std::move(other._ptrImpl);
other._ptrImpl = nullptr;
return *this;
}
void StatementCreator::swap(StatementCreator& other) noexcept
{
using std::swap;
swap(_ptrImpl, other._ptrImpl);
}
StatementCreator::~StatementCreator()
{

View File

@ -36,7 +36,7 @@ GMAKE = make mode=$(mode)
NAME := sqlparser
PARSER_CPP = $(SRCPARSER)/bison_parser.cpp $(SRCPARSER)/flex_lexer.cpp
PARSER_H = $(SRCPARSER)/bison_parser.h $(SRCPARSER)/flex_lexer.h
LIB_CFLAGS = -std=c++17 $(OPT_FLAG)
LIB_CFLAGS = -std=c++17 -I$(SRCPARSER)/../../../ $(OPT_FLAG)
relaxed_build ?= "off"
ifeq ($(relaxed_build), on)
@ -127,7 +127,7 @@ $(BM_BUILD): $(BM_ALL) $(LIB_BUILD)
############ Test & Example ############
########################################
TEST_BUILD = $(BIN)/tests
TEST_CFLAGS = -std=c++1z -Wall -Werror -Isrc/ -Itest/ -L./ $(OPT_FLAG)
TEST_CFLAGS = -std=c++1z -Wall -Werror -I$(SRCPARSER)/../../../ -Isrc/ -Itest/ -L./ $(OPT_FLAG)
TEST_CPP = $(shell find test/ -name '*.cpp')
TEST_ALL = $(shell find test/ -name '*.cpp') $(shell find test/ -name '*.h')
EXAMPLE_SRC = $(shell find example/ -name '*.cpp') $(shell find example/ -name '*.h')

View File

@ -1,16 +1,30 @@
#include "SQLParserResult.h"
#include <algorithm>
#include <string.h>
namespace hsql {
SQLParserResult::SQLParserResult() : isValid_(false), errorMsg_(nullptr)
SQLParserResult::SQLParserResult() :
statements_(new std::vector<SQLStatement*>),
isValid_(false),
errorMsg_(nullptr),
errorLine_(-1),
errorColumn_(-1),
parameters_(new std::vector<Expr*>)
{
statements_ = new std::vector<SQLStatement*>;
parameters_ = new std::vector<Expr*>;
}
SQLParserResult::SQLParserResult(SQLStatement* stmt) : isValid_(false), errorMsg_(nullptr) { addStatement(stmt); }
SQLParserResult::SQLParserResult(SQLStatement* stmt) :
statements_(new std::vector<SQLStatement*>),
isValid_(false),
errorMsg_(nullptr),
errorLine_(-1),
errorColumn_(-1),
parameters_(new std::vector<Expr*>)
{
addStatement(stmt);
}
// Move constructor.
SQLParserResult::SQLParserResult(SQLParserResult&& moved) { *this = std::forward<SQLParserResult>(moved); }
@ -18,22 +32,29 @@ SQLParserResult::SQLParserResult(SQLParserResult&& moved) { *this = std::forward
SQLParserResult& SQLParserResult::operator=(SQLParserResult&& moved) {
isValid_ = moved.isValid_;
errorMsg_ = moved.errorMsg_;
statements_ = std::move(moved.statements_);
statements_ = moved.statements_;
parameters_ = moved.parameters_;
moved.errorMsg_ = nullptr;
moved.reset();
moved.reset(true);
return *this;
}
SQLParserResult::~SQLParserResult() { reset(); }
void SQLParserResult::addStatement(SQLStatement* stmt) { statements_->push_back(stmt); }
void SQLParserResult::addStatement(SQLStatement* stmt) {
if (!statements_) statements_ = new std::vector<SQLStatement*>;
statements_->push_back(stmt);
}
const SQLStatement* SQLParserResult::getStatement(size_t index) const { return (*statements_)[index]; }
const SQLStatement* SQLParserResult::getStatement(size_t index) const {
return statements_ ? (*statements_)[index] : nullptr;
}
SQLStatement* SQLParserResult::getMutableStatement(size_t index) { return (*statements_)[index]; }
SQLStatement* SQLParserResult::getMutableStatement(size_t index) {
return statements_ ? (*statements_)[index] : nullptr;
}
size_t SQLParserResult::size() const { return statements_->size(); }
size_t SQLParserResult::size() const { return statements_ ? statements_->size() : 0u; }
bool SQLParserResult::isValid() const { return isValid_; }
@ -46,42 +67,67 @@ int SQLParserResult::errorColumn() const { return errorColumn_; }
void SQLParserResult::setIsValid(bool isValid) { isValid_ = isValid; }
void SQLParserResult::setErrorDetails(char* errorMsg, int errorLine, int errorColumn) {
if (errorMsg_) free(errorMsg);
errorMsg_ = errorMsg;
errorLine_ = errorLine;
errorColumn_ = errorColumn;
}
const std::vector<SQLStatement*>& SQLParserResult::getStatements() const { return *statements_; }
const std::vector<SQLStatement*>& SQLParserResult::getStatements() const {
if (!statements_) statements_ = new std::vector<SQLStatement*>;
return *statements_;
}
std::vector<SQLStatement*> SQLParserResult::releaseStatements() {
std::vector<SQLStatement*> copy = *statements_;
statements_->clear();
std::vector<SQLStatement*> copy;
if (statements_)
{
copy = *statements_;
statements_->clear();
}
return copy;
}
void SQLParserResult::reset() {
for (SQLStatement* statement : *statements_) {
delete statement;
void SQLParserResult::reset(bool mv) {
if (statements_)
{
if (!mv)
{
for (SQLStatement* statement : *statements_) {
delete statement;
}
delete statements_;
}
statements_ = nullptr;
}
if (parameters_)
{
if (!mv) delete parameters_;
parameters_ = nullptr;
}
delete statements_;
delete parameters_;
isValid_ = false;
free(errorMsg_);
errorMsg_ = nullptr;
if (errorMsg_)
{
if (!mv) free(errorMsg_);
errorMsg_ = nullptr;
}
errorLine_ = -1;
errorColumn_ = -1;
}
// Does NOT take ownership.
void SQLParserResult::addParameter(Expr* parameter) {
if (!parameters_) parameters_ = new std::vector<Expr*>;
parameters_->push_back(parameter);
std::sort(parameters_->begin(), parameters_->end(), [](const Expr* a, const Expr* b) { return a->ival < b->ival; });
}
const std::vector<Expr*>& SQLParserResult::parameters() { return *parameters_; }
const std::vector<Expr*>& SQLParserResult::parameters() {
if (!parameters_) parameters_ = new std::vector<Expr*>;
return *parameters_;
}
} // namespace hsql

View File

@ -63,7 +63,7 @@ class SQLParser_API SQLParserResult {
std::vector<SQLStatement*> releaseStatements();
// Deletes all statements and other data within the result.
void reset();
void reset(bool mv = false);
// Does NOT take ownership.
void addParameter(Expr* parameter);
@ -72,7 +72,7 @@ class SQLParser_API SQLParserResult {
private:
// List of statements within the result.
std::vector<SQLStatement*>* statements_;
mutable std::vector<SQLStatement*>* statements_;
// Flag indicating the parsing was successful.
bool isValid_;

View File

@ -12,6 +12,12 @@
#else
#define SQLParser_API __declspec(dllimport)
#endif
#else
#if defined (__GNUC__) && (__GNUC__ >= 4)
#define SQLParser_API __attribute__ ((visibility ("default")))
#else
#define SQLParser_API
#endif
#endif

View File

@ -7,17 +7,22 @@
include $(POCO_BASE)/build/rules/global
ifeq ($(findstring SunOS,$(POCO_HOST_OSNAME)),SunOS)
POCO_SUN_FORTE = $(findstring SunOS-SunForte, $(POCO_CONFIG))
POCO_SUN_STUDIO = $(findstring SunOS-SunStudio, $(POCO_CONFIG))
ifneq (,$or ($(POCO_SUN_FORTE), $(POCO_SUN_STUDIO)))
CXXFLAGS += -erroff=hidevf
endif
POCO_SUN_FORTE = $(findstring SunOS-SunForte, $(POCO_CONFIG))
POCO_SUN_STUDIO = $(findstring SunOS-SunStudio, $(POCO_CONFIG))
ifneq (,$or ($(POCO_SUN_FORTE), $(POCO_SUN_STUDIO)))
CXXFLAGS += -erroff=hidevf
endif
endif
objects = DataTestSuite Driver \
DataTest SessionPoolTest \
Binder Extractor Preparator SessionImpl Connector TestStatementImpl
ifndef POCO_DATA_NO_SQL_PARSER
objects += SQLParserTest
target_includes = $(POCO_BASE)/Data/src
endif
target = testrunner
target_version = 1
target_libs = PocoData PocoFoundation CppUnit

View File

@ -1437,6 +1437,53 @@ void DataTest::testTranscode()
}
void DataTest::testSQLParse()
{
#ifndef POCO_DATA_NO_SQL_PARSER
Session sess(SessionFactory::instance().create("test", "cs"));
assertTrue (sess.getFeature("autoCommit"));
sess.setFeature("autoCommit", false);
assertTrue (!sess.getFeature("autoCommit"));
Statement stmt = (sess << "SELECT %s%c%s,%d,%u,%f,%s FROM Person WHERE Name LIKE 'Simp%%'",
"'",'a',"'",-1, 1u, 1.5, "42", now);
assertTrue ("SELECT 'a',-1,1,1.500000,42 FROM Person WHERE Name LIKE 'Simp%'" == stmt.toString());
assertTrue (stmt.isSelect().value());
assertTrue (stmt.hasSelect().value());
assertTrue (!stmt.isUpdate().value());
assertTrue (!stmt.hasUpdate().value());
assertTrue (!stmt.isInsert().value());
assertTrue (!stmt.hasInsert().value());
assertTrue (!stmt.isDelete().value());
assertTrue (!stmt.hasDelete().value());
Session sess2(SessionFactory::instance().create("test", "cs"));
stmt.reset(sess2);
stmt = (sess << "INSERT INTO Test VALUES ('1', 2, 3.5);"
"SELECT * FROM Test WHERE First = ?;"
"UPDATE Test SET value=1 WHERE First = '1';"
"DELETE FROM Test WHERE First = ?;"
"DROP TABLE table_name;"
"ALTER TABLE mytable DROP COLUMN IF EXISTS mycolumn;"
"PREPARE prep_inst FROM 'INSERT INTO test VALUES (?, ?, ?)';"
"EXECUTE prep_inst(1, 2, 3);");
stmt.execute();
assertTrue (!stmt.isSelect().value());
assertTrue (stmt.hasSelect().value());
assertTrue (!stmt.isUpdate().value());
assertTrue (stmt.hasUpdate().value());
assertTrue (!stmt.isInsert().value());
assertTrue (stmt.hasInsert().value());
assertTrue (!stmt.isDelete().value());
assertTrue (stmt.hasDelete().value());
#endif // POCO_DATA_NO_SQL_PARSER
}
void DataTest::setUp()
{
}
@ -1469,6 +1516,7 @@ CppUnit::Test* DataTest::suite()
CppUnit_addTest(pSuite, DataTest, testDateAndTime);
CppUnit_addTest(pSuite, DataTest, testExternalBindingAndExtraction);
CppUnit_addTest(pSuite, DataTest, testTranscode);
CppUnit_addTest(pSuite, DataTest, testSQLParse);
return pSuite;
}

View File

@ -45,6 +45,7 @@ public:
void testDateAndTime();
void testExternalBindingAndExtraction();
void testTranscode();
void testSQLParse();
void setUp();
void tearDown();

View File

@ -11,9 +11,9 @@
#include "DataTestSuite.h"
#include "DataTest.h"
#include "SessionPoolTest.h"
#ifdef POCO_DATA_ENABLE_SQL_PARSER
#ifndef POCO_DATA_NO_SQL_PARSER
#include "SQLParserTest.h"
#endif // POCO_DATA_ENABLE_SQL_PARSER
#endif // POCO_DATA_NO_SQL_PARSER
CppUnit::Test* DataTestSuite::suite()
@ -22,9 +22,9 @@ CppUnit::Test* DataTestSuite::suite()
pSuite->addTest(DataTest::suite());
pSuite->addTest(SessionPoolTest::suite());
#ifdef POCO_DATA_ENABLE_SQL_PARSER
#ifndef POCO_DATA_NO_SQL_PARSER
pSuite->addTest(SQLParserTest::suite());
#endif // POCO_DATA_ENABLE_SQL_PARSER
#endif // POCO_DATA_NO_SQL_PARSER
return pSuite;
}

View File

@ -11,13 +11,14 @@
#include "SQLParserTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include <sstream>
#ifdef POCO_DATA_ENABLE_SQL_PARSER
#ifndef POCO_DATA_NO_SQL_PARSER
#include "Poco/Data/SQLParser.h"
using namespace Poco::Data;
using namespace Poco::Data::Parser;
SQLParserTest::SQLParserTest(const std::string& name): CppUnit::TestCase(name)
@ -35,14 +36,25 @@ void SQLParserTest::testSQLParser()
std::string query = "INSERT INTO Test VALUES ('1', 2, 3.5);"
"SELECT * FROM Test WHERE First = ?;"
"UPDATE Test SET value=1 WHERE First = '1';"
"DELETE FROM Test WHERE First = ?;";
"DELETE FROM Test WHERE First = ?;"
"DROP TABLE table_name;"
"ALTER TABLE mytable DROP COLUMN IF EXISTS mycolumn;"
"PREPARE prep_inst FROM 'INSERT INTO test VALUES (?, ?, ?)';"
"EXECUTE prep_inst(1, 2, 3);";
SQLParserResult result;
SQLParser::parse(query, &result);
int ins = 0, sel = 0, upd = 0, del = 0;
int ins = 0, sel = 0, upd = 0, del = 0, drop = 0, alter = 0, prepare = 0, execute = 0;
if (!result.isValid())
{
std::ostringstream os;
os << "Given string is not a valid SQL query.\n";
os << result.errorMsg() << "(L" << result.errorLine() << result.errorColumn() << ")\n";
fail(os.str());
}
assertTrue(result.isValid());
assertEqual(4, result.size());
assertEqual(8, result.size());
for (auto i = 0u; i < result.size(); ++i)
{
const SQLStatement* stmt = result.getStatement(i);
@ -53,6 +65,10 @@ void SQLParserTest::testSQLParser()
case kStmtInsert: ++ins; break;
case kStmtUpdate: ++upd; break;
case kStmtDelete: ++del; break;
case kStmtDrop: ++drop; break;
case kStmtAlter: ++alter; break;
case kStmtPrepare: ++prepare; break;
case kStmtExecute: ++execute; break;
default: break;
}
}
@ -60,6 +76,13 @@ void SQLParserTest::testSQLParser()
assertEqual(1, sel);
assertEqual(1, upd);
assertEqual(1, del);
assertEqual(1, drop);
assertEqual(1, alter);
assertEqual(1, prepare);
assertEqual(1, execute);
result.reset();
SQLParser::parse(query, &result);
}
@ -83,4 +106,4 @@ CppUnit::Test* SQLParserTest::suite()
}
#endif // POCO_DATA_ENABLE_SQL_PARSER
#endif // POCO_DATA_NO_SQL_PARSER

View File

@ -15,7 +15,7 @@
#include "Poco/Config.h"
#ifdef POCO_DATA_ENABLE_SQL_PARSER
#ifndef POCO_DATA_NO_SQL_PARSER
#include "Poco/Data/Data.h"
#include "CppUnit/TestCase.h"
@ -38,7 +38,7 @@ private:
};
#endif // POCO_DATA_ENABLE_SQL_PARSER
#endif // POCO_DATA_NO_SQL_PARSER
#endif // SQLParserTest_INCLUDED

View File

@ -21,13 +21,15 @@ namespace Test {
SessionImpl::SessionImpl(const std::string& init, std::size_t timeout):
Poco::Data::AbstractSessionImpl<SessionImpl>(init, timeout),
_f(false),
_connected(true)
_connected(true),
_autoCommit(true)
{
addFeature("f1", &SessionImpl::setF, &SessionImpl::getF);
addFeature("f2", 0, &SessionImpl::getF);
addFeature("f3", &SessionImpl::setF, 0);
addFeature("throwOnHasNext", &SessionImpl::setThrowOnHasNext, &SessionImpl::getThrowOnHasNext);
addFeature("connected", &SessionImpl::setConnected, &SessionImpl::getConnected);
addFeature("autoCommit", &SessionImpl::setAutoCommit, &SessionImpl::getAutoCommit);
addProperty("p1", &SessionImpl::setP, &SessionImpl::getP);
addProperty("p2", 0, &SessionImpl::getP);
addProperty("p3", &SessionImpl::setP, &SessionImpl::getP);
@ -146,6 +148,18 @@ void SessionImpl::setConnected(const std::string&, bool value)
}
bool SessionImpl::getAutoCommit(const std::string& name) const
{
return _autoCommit;
}
void SessionImpl::setAutoCommit(const std::string&, bool value)
{
_autoCommit = value;
}
void SessionImpl::setF(const std::string&, bool value)
{
_f = value;

View File

@ -96,6 +96,10 @@ public:
/// This is normally done by implementation
/// when a database connection loss is detected.
void setAutoCommit(const std::string& name, bool value);
bool getAutoCommit(const std::string& name) const;
/// Sets/gets the autoCommit property.
void setF(const std::string& name, bool value);
bool getF(const std::string& name) const;
void setThrowOnHasNext(const std::string& name, bool value);
@ -108,6 +112,7 @@ private:
bool _throwOnHasNext = false;
Poco::Any _p;
bool _connected;
bool _autoCommit = true;
std::string _connectionString;
};

View File

@ -220,8 +220,11 @@
#define POCO_HAVE_CPP17_COMPILER (__cplusplus >= 201703L)
// Uncomment to disable usage of SQLParser
// #define POCO_DATA_NO_SQL_PARSER
// Enable usage of SQL parser in Poco::Data
#ifndef POCO_DATA_ENABLE_SQL_PARSER
#if !defined(POCO_DATA_NO_SQL_PARSER)
#ifdef POCO_HAVE_CPP17_COMPILER
#define POCO_DATA_ENABLE_SQL_PARSER
#endif

View File

@ -6,6 +6,7 @@
sinclude config.make
sinclude config.build
POCO_CONFIG_INCLUDED = 1
ifndef POCO_BASE
$(warning WARNING: POCO_BASE is not defined. Assuming current directory.)

View File

@ -45,7 +45,7 @@ SHAREDLIBLINKEXT = .so
CFLAGS = $(SANITIZEFLAGS) -std=c11
CFLAGS32 =
CFLAGS64 =
CXXFLAGS = $(SANITIZEFLAGS) -std=c++14 -Wall -Wno-sign-compare
CXXFLAGS = $(SANITIZEFLAGS) -std=c++17 -Wall -Wno-sign-compare
CXXFLAGS32 =
CXXFLAGS64 =
LINKFLAGS = $(SANITIZEFLAGS)

View File

@ -105,6 +105,85 @@ $(OBJPATH_RELEASE_SHARED)/%.o: $(GENDIR)/%.c $(DEPPATH)/%.d $(POCO_BASE)/build/c
@echo "** Compiling" $< "(release, shared)"
$(CC) $(INCLUDE) $(CFLAGS) $(RELEASEOPT_CC) $(SHAREDOPT_CC) -c $< -o $@ $(POCO_BUILD_STDERR)
ifndef POCO_DATA_NO_SQL_PARSER
# SQL parser sources
SQLDIR = src/sql-parser/src
SQLPARSERDIR = $(SQLDIR)/parser
SQLSQLDIR = $(SQLDIR)/sql
SQLUTILDIR = $(SQLDIR)/util
# SQLParser
$(OBJPATH_DEBUG_STATIC)/%.o: $(SQLDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(debug, static)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(DEBUGOPT_CXX) $(STATICOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_RELEASE_STATIC)/%.o: $(SQLDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(release, static)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(RELEASEOPT_CXX) $(STATICOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_DEBUG_SHARED)/%.o: $(SQLDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(debug, shared)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(DEBUGOPT_CXX) $(SHAREDOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_RELEASE_SHARED)/%.o: $(SQLDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(release, shared)"
@echo "** Compiling" $@ "(release, shared)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(RELEASEOPT_CXX) $(SHAREDOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
# parser
$(OBJPATH_DEBUG_STATIC)/%.o: $(SQLPARSERDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(debug, static)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(DEBUGOPT_CXX) $(STATICOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_RELEASE_STATIC)/%.o: $(SQLPARSERDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(release, static)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(RELEASEOPT_CXX) $(STATICOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_DEBUG_SHARED)/%.o: $(SQLPARSERDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(debug, shared)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(DEBUGOPT_CXX) $(SHAREDOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_RELEASE_SHARED)/%.o: $(SQLPARSERDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(release, shared)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(RELEASEOPT_CXX) $(SHAREDOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
# sql
$(OBJPATH_DEBUG_STATIC)/%.o: $(SQLSQLDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(debug, static)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(DEBUGOPT_CXX) $(STATICOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_RELEASE_STATIC)/%.o: $(SQLSQLDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(release, static)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(RELEASEOPT_CXX) $(STATICOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_DEBUG_SHARED)/%.o: $(SQLSQLDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(debug, shared)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(DEBUGOPT_CXX) $(SHAREDOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_RELEASE_SHARED)/%.o: $(SQLSQLDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(release, shared)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(RELEASEOPT_CXX) $(SHAREDOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
# util
$(OBJPATH_DEBUG_STATIC)/%.o: $(SQLUTILDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(debug, static)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(DEBUGOPT_CXX) $(STATICOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_RELEASE_STATIC)/%.o: $(SQLUTILDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(release, static)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(RELEASEOPT_CXX) $(STATICOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_DEBUG_SHARED)/%.o: $(SQLUTILDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(debug, shared)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(DEBUGOPT_CXX) $(SHAREDOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
$(OBJPATH_RELEASE_SHARED)/%.o: $(SQLUTILDIR)/%.cpp $(DEPPATH)/%.d $(POCO_BASE)/build/config/$(POCO_CONFIG)
@echo "** Compiling" $< "(release, shared)"
$(CXX) $(INCLUDE) $(CXXFLAGS) $(RELEASEOPT_CXX) $(SHAREDOPT_CXX) -c $< -o $@ $(POCO_BUILD_STDERR)
endif # !POCO_DATA_NO_SQL_PARSER
#
# Rules for creating dependency information
@ -150,4 +229,46 @@ ifneq ($(MAKECMDGOALS),distclean)
endif
endif
ifndef POCO_DATA_NO_SQL_PARSER
# Data SQL parser sources rules
$(DEPPATH)/%.d: $(SQLDIR)/%.cpp
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),distclean)
@echo "** Creating dependency info for" $^
$(MKDIR) $(DEPPATH)
$(DEP) $(SQLDIR)/$(patsubst %.d,%.cpp,$(notdir $@)) $@ $(OBJPATH_DEBUG_STATIC) $(OBJPATH_RELEASE_STATIC) $(OBJPATH_DEBUG_SHARED) $(OBJPATH_RELEASE_SHARED) $(INCLUDE) $(CXXFLAGS);
endif
endif
$(DEPPATH)/%.d: $(SQLDIR)/parser/%.cpp
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),distclean)
@echo "** Creating dependency info for" $^
$(MKDIR) $(DEPPATH)
$(DEP) $(SQLDIR)/parser/$(patsubst %.d,%.cpp,$(notdir $@)) $@ $(OBJPATH_DEBUG_STATIC) $(OBJPATH_RELEASE_STATIC) $(OBJPATH_DEBUG_SHARED) $(OBJPATH_RELEASE_SHARED) $(INCLUDE) $(CXXFLAGS)
endif
endif
$(DEPPATH)/%.d: $(SQLDIR)/sql/%.cpp
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),distclean)
@echo "** Creating dependency info for" $^
$(MKDIR) $(DEPPATH)
$(DEP) $(SQLDIR)/sql/$(patsubst %.d,%.cpp,$(notdir $@)) $@ $(OBJPATH_DEBUG_STATIC) $(OBJPATH_RELEASE_STATIC) $(OBJPATH_DEBUG_SHARED) $(OBJPATH_RELEASE_SHARED) $(INCLUDE) $(CXXFLAGS)
endif
endif
$(DEPPATH)/%.d: $(SQLDIR)/util/%.cpp
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),distclean)
@echo "** Creating dependency info for" $^
$(MKDIR) $(DEPPATH)
$(DEP) $(SQLDIR)/util/$(patsubst %.d,%.cpp,$(notdir $@)) $@ $(OBJPATH_DEBUG_STATIC) $(OBJPATH_RELEASE_STATIC) $(OBJPATH_DEBUG_SHARED) $(OBJPATH_RELEASE_SHARED) $(INCLUDE) $(CXXFLAGS)
endif
endif
endif # !POCO_DATA_NO_SQL_PARSER
depend: $(addprefix $(DEPPATH)/,$(addsuffix .d,$(objects)))

View File

@ -29,6 +29,7 @@ endif
# Include some optional make configuration
#
sinclude $(POCO_BASE)/config.build
sinclude $(POCO_BASE)/config.make
#
# Check for PROJECT_BASE

153
configure vendored
View File

@ -21,7 +21,7 @@ Options:
Use the given build configuration.
Available configurations are:
`ls -C $base/build/config/`
$(ls -C "$base"/build/config/)
--prefix=<install_prefix>
Use the given install directory for make install.
@ -78,6 +78,11 @@ Options:
Compile with -DPOCO_NO_SOO.
Disables small object optimization.
--no-sqlparser
Compile with POCO_DATA_NO_SQL_PARSER
SQLParser is not enabled by default for c++14 and below,
so this option only has meaning for c++17 and above.
--sqlite-fts=<path>
Compile with -DPOCO_DATA_SQLITE_FTS.
Compile SQLite with Full Text Search support.
@ -148,11 +153,11 @@ ENDHELP
}
# save cwd
build=`pwd`
build=$(pwd)
# get directory where we are located
cd `dirname $0`
base=`pwd`
cd $build
cd "$(dirname "$0")" || exit
base=$(pwd)
cd "$build" || exit
tests=1
samples=1
@ -166,56 +171,57 @@ odbcinclude=""
unbundled=""
static=""
shared=""
omitMinimal="Crypto NetSSL_OpenSSL Zip Data Data/SQLite Data/ODBC Data/MySQL MongoDB PDF CppParser PageCompiler"
omitTypical="Data/ODBC Data/MySQL MongoDB PDF CppParser"
nosqlparser=
omitMinimal="Crypto NetSSL_OpenSSL Zip Data Data/SQLite Data/ODBC Data/MySQL Data/PostgreSQL MongoDB Redis PDF CppParser PageCompiler"
omitTypical="Data/ODBC Data/MySQL Data/PostgreSQL MongoDB Redis PDF CppParser"
omit=$omitTypical
# parse arguments
while [ $# -ge 1 ]; do
case "$1" in
--config=*)
config="`echo ${1} | awk '{print substr($0,10)}'`" ;;
config="$(echo "${1}" | awk '{print substr($0,10)}')" ;;
--prefix=*)
prefix="`echo ${1} | awk '{print substr($0,10)}'`" ;;
prefix="$(echo "${1}" | awk '{print substr($0,10)}')" ;;
--no-prefix)
noprefix=1 ;;
--stdcxx-base=*)
stdcxx_base="`echo ${1} | awk '{print substr($0,15)}'`" ;;
stdcxx_base="$(echo "${1}" | awk '{print substr($0,15)}')" ;;
--omit=*)
omit="`echo ${1} | awk '{print substr($0,8)}' | tr ',;' ' '`" ;;
omit="$(echo "${1}" | awk '{print substr($0,8)}' | tr ',;' ' ')" ;;
--include-path=*)
includepath="`echo ${1} | awk '{print substr($0,16)}' | tr ',;' ' '`" ;;
includepath="$(echo "${1}" | awk '{print substr($0,16)}' | tr ',;' ' ')" ;;
--library-path=*)
librarypath="`echo ${1} | awk '{print substr($0,16)}' | tr ',;' ' '`" ;;
librarypath="$(echo "${1}" | awk '{print substr($0,16)}' | tr ',;' ' ')" ;;
--odbc-lib=*)
odbclib="`echo ${1} | awk '{print substr($0,12)}'`" ;;
odbclib="$(echo "${1}" | awk '{print substr($0,12)}')" ;;
--odbc-include=*)
odbcinclude="`echo ${1} | awk '{print substr($0,16)}'`" ;;
odbcinclude="$(echo "${1}" | awk '{print substr($0,16)}')" ;;
--mysql-lib=*)
mysqllib="`echo ${1} | awk '{print substr($0,13)}'`" ;;
mysqllib="$(echo "${1}" | awk '{print substr($0,13)}')" ;;
--mysql-include=*)
mysqlinclude="`echo ${1} | awk '{print substr($0,17)}'`" ;;
mysqlinclude="$(echo "${1}" | awk '{print substr($0,17)}')" ;;
--pgsql-lib=*)
pgsqllib="`echo ${1} | awk '{print substr($0,13)}'`" ;;
pgsqllib="$(echo "${1}" | awk '{print substr($0,13)}')" ;;
--pgsql-include=*)
pgsqlinclude="`echo ${1} | awk '{print substr($0,17)}'`" ;;
pgsqlinclude="$(echo "${1}" | awk '{print substr($0,17)}')" ;;
--cflags=*)
flags="$flags `echo ${1} | awk '{print substr($0,10)}'`" ;;
flags="$flags $(echo "${1}" | awk '{print substr($0,10)}')" ;;
--ldflags=*)
ldflags="$ldflags `echo ${1} | awk '{print substr($0,11)}'`" ;;
ldflags="$ldflags $(echo "${1}" | awk '{print substr($0,11)}')" ;;
--no-samples)
samples="" ;;
@ -241,11 +247,16 @@ while [ $# -ge 1 ]; do
--no-soo)
flags="$flags -DPOCO_NO_SOO" ;;
--no-sqlparser)
flags="$flags -DPOCO_DATA_NO_SQL_PARSER"
nosqlparser=1
;;
--sqlite-thread-safe=*)
flags="$flags -DSQLITE_THREADSAFE=`echo ${1} | awk '{print substr($0,22)}'`" ;;
flags="$flags -DSQLITE_THREADSAFE=$(echo "${1}" | awk '{print substr($0,22)}')" ;;
--sqlite-fts)
flags="$flags -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS" ;;
flags="$flags -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS3_PARENTHESIS" ;;
--poquito)
flags="$flags -DPOCO_NO_FILECHANNEL -DPOCO_NO_SPLITTERCHANNEL -DPOCO_NO_SYSLOGCHANNEL -DPOCO_UTIL_NO_INIFILECONFIGURATION -DPOCO_UTIL_NO_JSONCONFIGURATION -DPOCO_UTIL_NO_XMLCONFIGURATION" ;;
@ -256,7 +267,7 @@ while [ $# -ge 1 ]; do
;;
--minimal)
omit=$omitMinimal ;;
omit=$omitMinimal ;;
--typical)
omit=$omitTypical ;;
@ -286,7 +297,7 @@ done
# autodetect build environment
# ...special cases for CYGWIN or MinGW
if [ "$config" = "" ] ; then
config=`uname`
config=$(uname)
case "$config" in
CYGWIN*)
config=CYGWIN ;;
@ -299,7 +310,7 @@ if [ ! -f "$base/build/config/$config" ] ; then
echo "Unknown configuration: $config"
echo "Please use the --config option to specify another build configuration"
echo "The following configurations are available:"
ls $base/build/config
ls "$base"/build/config
exit 1
fi
@ -310,16 +321,16 @@ if [ -z "$prefix" ] ; then
fi
# check for patches
if [ -d $base/patches/$config ] ; then
if [ -d "$base"/patches/"$config" ] ; then
echo "NOTE: There are patches for your configuration available. Please apply them before compiling."
fi
# copy Makefile to build dir
if [ "$base" != "$build" ] ; then
cp $base/Makefile $build
cp "$base"/Makefile "$build"
fi
if [ -n "$static" -a -n "$shared" ] ; then
if [ -n "$static" ] && [ -n "$shared" ] ; then
linkmode=BOTH
elif [ -n "$static" ] ; then
linkmode=STATIC
@ -330,51 +341,57 @@ else
fi
# create config.make
echo '# config.make generated by configure script' >$build/config.make
echo "POCO_CONFIG = $config" >>$build/config.make
echo "POCO_BASE = $base" >>$build/config.make
echo "POCO_BUILD = $build" >>$build/config.make
echo "POCO_FLAGS = $flags" >>$build/config.make
echo "POCO_LDFLAGS = $ldflags" >>$build/config.make
echo '# config.make generated by configure script' > "$build"/config.make
{
echo "POCO_CONFIG = $config"
echo "POCO_BASE = $base"
echo "POCO_BUILD = $build"
echo "POCO_FLAGS = $flags"
echo "POCO_LDFLAGS = $ldflags"
} >> "$build"/config.make
if [ -n "$prefix" ] ; then
echo "POCO_PREFIX = $prefix" >>$build/config.make
echo "POCO_PREFIX = $prefix" >>"$build"/config.make
fi
echo "OMIT = $omit" >>$build/config.make
echo "OMIT = $omit" >>"$build"/config.make
if [ -n "$stdcxx_base" ] ; then
echo "STDCXX_BASE = $stdcxx_base" >>$build/config.make
echo "STDCXX_BASE = $stdcxx_base" >>"$build"/config.make
fi
if [ -n "$includepath" ] ; then
echo "POCO_ADD_INCLUDE = $includepath" >>$build/config.make
echo "POCO_ADD_INCLUDE = $includepath" >>"$build"/config.make
fi
if [ -n "$librarypath" ] ; then
echo "POCO_ADD_LIBRARY = $librarypath" >>$build/config.make
echo "POCO_ADD_LIBRARY = $librarypath" >>"$build"/config.make
fi
if [ -n "$odbclib" ] ; then
echo "POCO_ODBC_LIB = $odbclib" >>$build/config.make
echo "POCO_ODBC_LIB = $odbclib" >>"$build"/config.make
fi
if [ -n "$odbcinclude" ] ; then
echo "POCO_ODBC_INCLUDE = $odbcinclude" >>$build/config.make
echo "POCO_ODBC_INCLUDE = $odbcinclude" >>"$build"/config.make
fi
if [ -n "$mysqllib" ] ; then
echo "POCO_MYSQL_LIB = $mysqllib" >>$build/config.make
echo "POCO_MYSQL_LIB = $mysqllib" >>"$build"/config.make
fi
if [ -n "$mysqlinclude" ] ; then
echo "POCO_MYSQL_INCLUDE = $mysqlinclude" >>$build/config.make
echo "POCO_MYSQL_INCLUDE = $mysqlinclude" >>"$build"/config.make
fi
if [ -n "$pgsqllib" ] ; then
echo "POCO_PGSQL_LIB = $pgsqllib" >>$build/config.make
echo "POCO_PGSQL_LIB = $pgsqllib" >>"$build"/config.make
fi
if [ -n "$pgsqlinclude" ] ; then
echo "POCO_PGSQL_INCLUDE = $pgsqlinclude" >>$build/config.make
echo "POCO_PGSQL_INCLUDE = $pgsqlinclude" >>"$build"/config.make
fi
if [ -n "$unbundled" ] ; then
echo "POCO_UNBUNDLED = 1" >>$build/config.make
echo "POCO_UNBUNDLED = 1" >>"$build"/config.make
fi
if [ -n "$linkmode" ] ; then
echo "LINKMODE = $linkmode" >>$build/config.make
echo "LINKMODE = $linkmode" >>"$build"/config.make
fi
if [ -n "$nosqlparser" ] ; then
echo "POCO_DATA_NO_SQL_PARSER = $nosqlparser" >>"$build"/config.make
fi
cat <<__EOF__ >>$build/config.make
cat <<__EOF__ >>"$build"/config.make
export POCO_CONFIG
export POCO_BASE
export POCO_BUILD
@ -383,47 +400,57 @@ export POCO_LDFLAGS
__EOF__
if [ -n "$prefix" ] ; then
echo "export POCO_PREFIX" >>$build/config.make
echo "export POCO_PREFIX" >>"$build"/config.make
fi
if [ -n "$stdcxx_base" ] ; then
echo "export STDCXX_BASE" >>$build/config.make
echo "export STDCXX_BASE" >>"$build"/config.make
fi
if [ -n "$includepath" ] ; then
echo "export POCO_ADD_INCLUDE" >>$build/config.make
echo "export POCO_ADD_INCLUDE" >>"$build"/config.make
fi
if [ -n "$librarypath" ] ; then
echo "export POCO_ADD_LIBRARY" >>$build/config.make
echo "export POCO_ADD_LIBRARY" >>"$build"/config.make
fi
if [ -n "$odbclib" ] ; then
echo "export POCO_ODBC_LIB" >>$build/config.make
echo "export POCO_ODBC_LIB" >>"$build"/config.make
fi
if [ -n "$odbcinclude" ] ; then
echo "export POCO_ODBC_INCLUDE" >>$build/config.make
echo "export POCO_ODBC_INCLUDE" >>"$build"/config.make
fi
if [ -n "$mysqllib" ] ; then
echo "export POCO_MYSQL_LIB" >>$build/config.make
echo "export POCO_MYSQL_LIB" >>"$build"/config.make
fi
if [ -n "$mysqlinclude" ] ; then
echo "export POCO_MYSQL_INCLUDE" >>$build/config.make
echo "export POCO_MYSQL_INCLUDE" >>"$build"/config.make
fi
if [ -n "$pgsqllib" ] ; then
echo "export POCO_PGSQL_LIB" >>$build/config.make
echo "export POCO_PGSQL_LIB" >>"$build"/config.make
fi
if [ -n "$pgsqlinclude" ] ; then
echo "export POCO_PGSQL_INCLUDE" >>$build/config.make
echo "export POCO_PGSQL_INCLUDE" >>"$build"/config.make
fi
if [ -n "$unbundled" ] ; then
echo "export POCO_UNBUNDLED" >>$build/config.make
echo "export POCO_UNBUNDLED" >>"$build"/config.make
fi
if [ -n "$linkmode" ] ; then
echo "export LINKMODE" >>$build/config.make
echo "export LINKMODE" >>"$build"/config.make
fi
if [ -n "$nosqlparser" ] ; then
echo "export POCO_DATA_NO_SQL_PARSER" >>"$build"/config.make
fi
# create config.build
echo '# config.build generated by configure script' >$build/config.build
cat <<__EOF__ >>$build/config.build
echo '# config.build generated by configure script' >"$build"/config.build
cat <<__EOF__ >>"$build"/config.build
TESTS = $tests
SAMPLES = $samples
__EOF__
echo "Configured for $config"
echo "======================"
echo
cat "$build"/config.make
echo
cat "$build"/config.build
echo
echo "======================"

48
runLibTests.sh Executable file
View File

@ -0,0 +1,48 @@
#!/bin/bash
#
# Script to rebuild a library and dependencies
# (with or without a sanitizer) and run the tests.
# Currently works only for top-level libs
# dependent on Foundation only.
#
# Usage: ./runLibTests.sh library [address | undefined | thread ]
#
library=$1
if [ -z "${library}" ]; then
echo "Library not specified"
echo "Usage: $0 library [address | undefined | thread ]"
exit 1
fi
self="${BASH_SOURCE[0]}"
if [ -d "$self" ] ; then
basedir="$(cd "$self" || exit; pwd -P)"
else
basedir="$(cd "$(dirname "$self")" || exit; pwd -P)"
fi
# shellcheck disable=SC1091
. "$basedir"/poco_env.bash
flag=$2
make distclean -C CppUnit
make distclean -C Foundation
make distclean -C "$library"
make distclean -C "$library"/testsuite
if [ -n "${flag}" ]; then
make -s -j4 -C "$POCO_BASE"/CppUnit SANITIZEFLAGS+=-fsanitize="$flag"
make -s -j4 -C "$POCO_BASE"/Foundation SANITIZEFLAGS+=-fsanitize="$flag"
make -s -j4 -C "$POCO_BASE"/"$library" SANITIZEFLAGS+=-fsanitize="$flag"
make -s -j4 -C "$POCO_BASE"/"$library"/testsuite SANITIZEFLAGS+=-fsanitize="$flag"
else
make -s -j4 -C "$POCO_BASE"/CppUnit
make -s -j4 -C "$POCO_BASE"/Foundation
make -s -j4 -C "$POCO_BASE"/"$library"
make -s -j4 -C "$POCO_BASE"/"$library"/testsuite
fi
"$library"/testsuite/bin/"$OSNAME"/"$OSARCH"/testrunner -all
"$library"/testsuite/bin/"$OSNAME"/"$OSARCH"/testrunnerd -all