Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: PostgeSQL support in ActiveRecord #3869

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ActiveRecord/Compiler/src/CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ void CodeGenerator::writeHeaderComment(const std::string& fileName) const

void CodeGenerator::writeInclude(const std::string& nameSpace, const std::string& name) const
{
_stream << "#include \"";
_stream << "#include <";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rastocny why this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optimization of compilation process and cleanness in dependencies. <> are used for includes from external libraries and compiler shall look for included files in external includes (in MSVC Additional includes directory). "" are used for internal includes, that shall have relative path from current file. When "internally" included file is not found, a fallback to external includes is applied.

The generator generates source code files that are externally depended to PoCo libraries.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave this to @obiltschnig to decide

auto ns = splitNameSpace(nameSpace);
for (const auto& s: ns)
{
_stream << s << '/';
}
_stream << name << ".h\"\n";
_stream << name << ".h>\n";
}


Expand Down
11 changes: 8 additions & 3 deletions ActiveRecord/Compiler/src/HeaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ void HeaderGenerator::generate() const
writeHeaderComment(_class.name + ".h");
std::string guard = includeGuard(_class.nameSpace, _class.name);
stream()
<< "#pragma once\n"
<< "#ifndef " << guard << "\n"
<< "#define " << guard << "\n"
<< "\n\n";
stream() << "#include \"Poco/ActiveRecord/ActiveRecord.h\"\n";
stream() << "#include <Poco/ActiveRecord/ActiveRecord.h>\n";
if (!_class.dllExport.empty())
writeInclude(_class.nameSpace, "Config"s);
for (const auto& ref: _class.references)
{
writeInclude(_class.nameSpace, ref);
Expand Down Expand Up @@ -71,7 +74,10 @@ std::string HeaderGenerator::includeGuard(const std::string& nameSpace, const st

void HeaderGenerator::writeClass() const
{
stream() << "class " << _class.name << ": public ";
stream() << "class ";
if (!_class.dllExport.empty())
stream() << _class.dllExport << " ";
stream() << _class.name << ": public ";
if (_class.key.empty())
stream() << "Poco::ActiveRecord::KeylessActiveRecord";
else
Expand Down Expand Up @@ -235,7 +241,6 @@ void HeaderGenerator::writeVariables() const
void HeaderGenerator::writeGetter(const Property& property) const
{
stream() << "\t" << paramType(property) << " " << property.name << "() const;\n";

}


Expand Down
16 changes: 8 additions & 8 deletions ActiveRecord/Compiler/src/ImplGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,17 @@ ImplGenerator::ImplGenerator(const std::string& source, std::ostream& stream, co

void ImplGenerator::generate() const
{
if (!_class.precompiledHeader.empty())
stream() << "#include \"" << _class.precompiledHeader <<"\"\n\n";

writeHeaderComment(_class.name + ".cpp");
writeInclude(_class.nameSpace, _class.name);

if (!_class.key.empty())
{
if (keyType(_class) == "Poco::UUID")
{
stream() << "#include \"Poco/UUIDGenerator.h\"\n";
stream() << "#include <Poco/UUIDGenerator.h>\n";
}
}

Expand Down Expand Up @@ -224,7 +227,7 @@ void ImplGenerator::writeInsert() const
<< "\t\t<< \"INSERT INTO " << _class.table << " (";

bool needComma = false;
if (!_class.key.empty())
if (!_class.key.empty() && !_class.autoIncrementID)
{
stream() << keyProperty(_class).column;
needComma = true;
Expand All @@ -245,12 +248,9 @@ void ImplGenerator::writeInsert() const
<< "\t\t<< \" VALUES (";

needComma = false;
if (!_class.key.empty())
if (!_class.key.empty() && !_class.autoIncrementID)
{
if (_class.autoIncrementID)
stream() << "NULL";
else
stream() << "\" << pSPP->next() << \"";
stream() << "\" << pSPP->next() << \"";
needComma = true;
}

Expand All @@ -276,7 +276,7 @@ void ImplGenerator::writeInsert() const

if (_class.autoIncrementID)
{
stream() << "\tupdateID(context()->session());\n";
stream() << "\tupdateID(context()->session(), \"" << _class.table << "\"s, \"" << keyProperty(_class).column << "\"s); \n";
}

stream() << "}\n";
Expand Down
8 changes: 6 additions & 2 deletions ActiveRecord/Compiler/src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ void Parser::endElement(const Poco::XML::XMLString& uri, const Poco::XML::XMLStr
void Parser::handleProject(const Poco::XML::Attributes& attributes)
{
_nameSpace = attributes.getValue("namespace"s);
_dllExport = attributes.getValue("dllexport"s);
_precompiledHeader = attributes.getValue("precompiledHeader"s);
_convertCamelCase = parseBool("convertCamelCase"s, attributes.getValue("convertCamelCase"s));
}

Expand All @@ -111,6 +113,8 @@ void Parser::handleClass(const Poco::XML::Attributes& attributes)
{
_class.name = attributes.getValue("name"s);
_class.nameSpace = _nameSpace;
_class.dllExport = _dllExport;
_class.precompiledHeader = _precompiledHeader;
_class.table = attributes.getValue("table"s);
if (_class.table.empty()) _class.table = toDatabaseName(_class.name);
_class.key = attributes.getValue("key"s);
Expand Down Expand Up @@ -231,14 +235,14 @@ char Parser::parseCardinality(const std::string& cardinality) const
}


bool Parser::parseBool(const std::string& name, const std::string& value, bool deflt) const
bool Parser::parseBool(const std::string& name, const std::string& value, bool defaultValue) const
{
if (value == "true")
return true;
else if (value == "false")
return false;
else if (value.empty())
return deflt;
return defaultValue;
else throw Poco::InvalidArgumentException(Poco::format("%s: %s value must be 'true' or 'false'", name, where()));
}

Expand Down
2 changes: 2 additions & 0 deletions ActiveRecord/Compiler/src/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class Parser: protected Poco::XML::DefaultHandler
const Poco::XML::Locator* _pLocator = nullptr;
bool _convertCamelCase = false;
std::string _nameSpace;
std::string _dllExport;
std::string _precompiledHeader;
Class _class;
ClassMap _classes;
std::vector<std::string> _elemStack;
Expand Down
2 changes: 2 additions & 0 deletions ActiveRecord/Compiler/src/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ struct Class
{
std::string name;
std::string nameSpace;
std::string dllExport;
std::string precompiledHeader;
std::string table;
std::string key;
bool autoIncrementID = false;
Expand Down
12 changes: 7 additions & 5 deletions ActiveRecord/include/Poco/ActiveRecord/ActiveRecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,14 @@ class ActiveRecord: public ActiveRecordBase

ID& mutableID();

void updateID(Poco::Data::Session& session);
void updateID(Poco::Data::Session& session, const std::string &table = {}, const std::string &idColumn = {});
/// Updates the ID using lastInsertID().
/// Name of the table and the ID column is required for PostgreSQL.

static ID lastInsertID(Poco::Data::Session& session);
static ID lastInsertID(Poco::Data::Session &session, const std::string &table = {}, const std::string &idColumn = {});
/// Returns the last inserted ID from the database session.
/// Used for automatically incrementing keys.
/// Name of the table and the ID column is required for PostgreSQL.

template <typename T>
static Poco::AutoPtr<T> withContext(Poco::AutoPtr<T> pObj, Context::Ptr pContext)
Expand Down Expand Up @@ -230,14 +232,14 @@ inline std::string ActiveRecord<IDType>::toString() const


template <typename IDType>
void ActiveRecord<IDType>::updateID(Poco::Data::Session& session)
void ActiveRecord<IDType>::updateID(Poco::Data::Session& session, const std::string &table, const std::string &idColumn)
{
_id = lastInsertID(session);
_id = lastInsertID(session, table, idColumn);
}


template <typename IDType>
IDType ActiveRecord<IDType>::lastInsertID(Poco::Data::Session& session)
IDType ActiveRecord<IDType>::lastInsertID(Poco::Data::Session& session, const std::string& table, const std::string& idColumn)
{
using namespace Poco::Data::Keywords;
using namespace std::string_literals;
Expand Down
5 changes: 3 additions & 2 deletions ActiveRecord/testsuite/include/ORM/Employee.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
//


#pragma once
#ifndef ORM_Employee_INCLUDED
#define ORM_Employee_INCLUDED


#include "Poco/ActiveRecord/ActiveRecord.h"
#include "ORM/Role.h"
#include <Poco/ActiveRecord/ActiveRecord.h>
#include <ORM/Role.h>


namespace ORM {
Expand Down
3 changes: 2 additions & 1 deletion ActiveRecord/testsuite/include/ORM/Role.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
//


#pragma once
#ifndef ORM_Role_INCLUDED
#define ORM_Role_INCLUDED


#include "Poco/ActiveRecord/ActiveRecord.h"
#include <Poco/ActiveRecord/ActiveRecord.h>


namespace ORM {
Expand Down
4 changes: 2 additions & 2 deletions ActiveRecord/testsuite/src/Employee.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
//


#include "ORM/Employee.h"
#include "Poco/UUIDGenerator.h"
#include <ORM/Employee.h>
#include <Poco/UUIDGenerator.h>


using namespace std::string_literals;
Expand Down
8 changes: 4 additions & 4 deletions ActiveRecord/testsuite/src/Role.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//


#include "ORM/Role.h"
#include <ORM/Role.h>


using namespace std::string_literals;
Expand Down Expand Up @@ -52,11 +52,11 @@ void Role::insert()
Poco::ActiveRecord::StatementPlaceholderProvider::Ptr pSPP(context()->statementPlaceholderProvider());

context()->session()
<< "INSERT INTO roles (id, name, description)"
<< " VALUES (NULL, " << pSPP->next() << ", " << pSPP->next() << ")",
<< "INSERT INTO roles (name, description)"
<< " VALUES (" << pSPP->next() << ", " << pSPP->next() << ")",
use(*this),
now;
updateID(context()->session());
updateID(context()->session(), "roles"s, "id"s);
}


Expand Down
3 changes: 2 additions & 1 deletion Data/PostgreSQL/src/SessionImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//


#include "Poco/Data/PostgreSQL/Connector.h"
#include "Poco/Data/PostgreSQL/SessionImpl.h"
#include "Poco/Data/PostgreSQL/PostgreSQLException.h"
#include "Poco/Data/PostgreSQL/PostgreSQLStatementImpl.h"
Expand Down Expand Up @@ -58,7 +59,7 @@ namespace PostgreSQL {

SessionImpl::SessionImpl(const std::string& aConnectionString, std::size_t aLoginTimeout):
Poco::Data::AbstractSessionImpl<SessionImpl>(aConnectionString, aLoginTimeout),
_connectorName("postgresql")
_connectorName(Connector::KEY)
{
setFeature("sqlParse", false); // the parse currently cannot handle the PostgreSQL placeholders $1, $2, etc.
setProperty("handle", static_cast<SessionHandle*>(&_sessionHandle));
Expand Down
Loading