mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-20 05:05:38 +00:00
Merge branch 'master' into try_fix_duplicating_aliases
This commit is contained in:
commit
8eb048362b
@ -10,7 +10,7 @@ HeaderFilterRegex: '^.*/(base|src|programs|utils)/.*(h|hpp)$'
|
||||
Checks: [
|
||||
'*',
|
||||
|
||||
'-abseil-*',
|
||||
'-abseil-string-find-str-contains', # disabled to avoid a misleading suggestion (obsolete absl::StrContains() instead of C++23 std::string::contains())
|
||||
|
||||
'-altera-*',
|
||||
|
||||
@ -32,8 +32,6 @@ Checks: [
|
||||
'-bugprone-crtp-constructor-accessibility',
|
||||
|
||||
'-cert-dcl16-c',
|
||||
'-cert-dcl37-c',
|
||||
'-cert-dcl51-cpp',
|
||||
'-cert-err58-cpp',
|
||||
'-cert-msc32-c',
|
||||
'-cert-msc51-cpp',
|
||||
|
@ -26,7 +26,7 @@
|
||||
* When retrieving data directly from a dictionary using Dictionary storage, dictionary table function, or direct SELECT from the dictionary itself, it is now enough to have `SELECT` permission or `dictGet` permission for the dictionary. This aligns with previous attempts to prevent ACL bypasses: https://github.com/ClickHouse/ClickHouse/pull/57362 and https://github.com/ClickHouse/ClickHouse/pull/65359. It also makes the latter one backward compatible. [#72051](https://github.com/ClickHouse/ClickHouse/pull/72051) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)).
|
||||
|
||||
#### Experimental feature
|
||||
* Implement `allowed_feature_tier` as a global switch to disable all experimental / beta features. [#71841](https://github.com/ClickHouse/ClickHouse/pull/71841) [#71145](https://github.com/ClickHouse/ClickHouse/pull/71145) ([Raúl Marín](https://github.com/Algunenano)).
|
||||
* Implement `allow_feature_tier` as a global switch to disable all experimental / beta features. [#71841](https://github.com/ClickHouse/ClickHouse/pull/71841) [#71145](https://github.com/ClickHouse/ClickHouse/pull/71145) ([Raúl Marín](https://github.com/Algunenano)).
|
||||
* Fix possible error `No such file or directory` due to unescaped special symbols in files for JSON subcolumns. [#71182](https://github.com/ClickHouse/ClickHouse/pull/71182) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Support alter from String to JSON. This PR also changes the serialization of JSON and Dynamic types to new version V2. Old version V1 can be still used by enabling setting `merge_tree_use_v1_object_and_dynamic_serialization` (can be used during upgrade to be able to rollback the version without issues). [#70442](https://github.com/ClickHouse/ClickHouse/pull/70442) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
* Implement simple CAST from Map/Tuple/Object to new JSON through serialization/deserialization from JSON string. [#71320](https://github.com/ClickHouse/ClickHouse/pull/71320) ([Pavel Kruglov](https://github.com/Avogar)).
|
||||
|
@ -14,6 +14,7 @@ The following versions of ClickHouse server are currently supported with securit
|
||||
|
||||
| Version | Supported |
|
||||
|:-|:-|
|
||||
| 24.11 | ✔️ |
|
||||
| 24.10 | ✔️ |
|
||||
| 24.9 | ✔️ |
|
||||
| 24.8 | ✔️ |
|
||||
|
@ -3,11 +3,6 @@ add_subdirectory (Data)
|
||||
add_subdirectory (Data/ODBC)
|
||||
add_subdirectory (Foundation)
|
||||
add_subdirectory (JSON)
|
||||
|
||||
if (USE_MONGODB)
|
||||
add_subdirectory(MongoDB)
|
||||
endif()
|
||||
|
||||
add_subdirectory (Net)
|
||||
add_subdirectory (NetSSL_OpenSSL)
|
||||
add_subdirectory (Redis)
|
||||
|
@ -1,16 +0,0 @@
|
||||
file (GLOB SRCS src/*.cpp)
|
||||
|
||||
add_library (_poco_mongodb ${SRCS})
|
||||
add_library (Poco::MongoDB ALIAS _poco_mongodb)
|
||||
|
||||
# TODO: remove these warning exclusions
|
||||
target_compile_options (_poco_mongodb
|
||||
PRIVATE
|
||||
-Wno-old-style-cast
|
||||
-Wno-unused-parameter
|
||||
-Wno-zero-as-null-pointer-constant
|
||||
)
|
||||
|
||||
target_include_directories (_poco_mongodb SYSTEM PUBLIC "include")
|
||||
target_link_libraries (_poco_mongodb PUBLIC Poco::Net)
|
||||
|
@ -1,142 +0,0 @@
|
||||
//
|
||||
// Array.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Array
|
||||
//
|
||||
// Definition of the Array class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_Array_INCLUDED
|
||||
#define MongoDB_Array_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Document.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API Array : public Document
|
||||
/// This class represents a BSON Array.
|
||||
{
|
||||
public:
|
||||
using Ptr = SharedPtr<Array>;
|
||||
|
||||
Array();
|
||||
/// Creates an empty Array.
|
||||
|
||||
virtual ~Array();
|
||||
/// Destroys the Array.
|
||||
|
||||
// Document template functions available for backward compatibility
|
||||
using Document::add;
|
||||
using Document::get;
|
||||
|
||||
template <typename T>
|
||||
Document & add(T value)
|
||||
/// Creates an element with the name from the current pos and value and
|
||||
/// adds it to the array document.
|
||||
///
|
||||
/// The active document is returned to allow chaining of the add methods.
|
||||
{
|
||||
return Document::add<T>(Poco::NumberFormatter::format(size()), value);
|
||||
}
|
||||
|
||||
Document & add(const char * value)
|
||||
/// Creates an element with a name from the current pos and value and
|
||||
/// adds it to the array document.
|
||||
///
|
||||
/// The active document is returned to allow chaining of the add methods.
|
||||
{
|
||||
return Document::add(Poco::NumberFormatter::format(size()), value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get(std::size_t pos) const
|
||||
/// Returns the element at the given index and tries to convert
|
||||
/// it to the template type. If the element is not found, a
|
||||
/// Poco::NotFoundException will be thrown. If the element cannot be
|
||||
/// converted a BadCastException will be thrown.
|
||||
{
|
||||
return Document::get<T>(Poco::NumberFormatter::format(pos));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get(std::size_t pos, const T & deflt) const
|
||||
/// Returns the element at the given index and tries to convert
|
||||
/// it to the template type. If the element is not found, or
|
||||
/// has the wrong type, the deflt argument will be returned.
|
||||
{
|
||||
return Document::get<T>(Poco::NumberFormatter::format(pos), deflt);
|
||||
}
|
||||
|
||||
Element::Ptr get(std::size_t pos) const;
|
||||
/// Returns the element at the given index.
|
||||
/// An empty element will be returned if the element is not found.
|
||||
|
||||
template <typename T>
|
||||
bool isType(std::size_t pos) const
|
||||
/// Returns true if the type of the element equals the TypeId of ElementTrait,
|
||||
/// otherwise false.
|
||||
{
|
||||
return Document::isType<T>(Poco::NumberFormatter::format(pos));
|
||||
}
|
||||
|
||||
std::string toString(int indent = 0) const;
|
||||
/// Returns a string representation of the Array.
|
||||
|
||||
private:
|
||||
friend void BSONReader::read<Array::Ptr>(Array::Ptr & to);
|
||||
};
|
||||
|
||||
|
||||
// BSON Embedded Array
|
||||
// spec: document
|
||||
template <>
|
||||
struct ElementTraits<Array::Ptr>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x04
|
||||
};
|
||||
|
||||
static std::string toString(const Array::Ptr & value, int indent = 0)
|
||||
{
|
||||
//TODO:
|
||||
return value.isNull() ? "null" : value->toString(indent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<Array::Ptr>(Array::Ptr & to)
|
||||
{
|
||||
to->read(_reader);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<Array::Ptr>(Array::Ptr & from)
|
||||
{
|
||||
from->write(_writer);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_Array_INCLUDED
|
@ -1,88 +0,0 @@
|
||||
//
|
||||
// BSONReader.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: BSONReader
|
||||
//
|
||||
// Definition of the BSONReader class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_BSONReader_INCLUDED
|
||||
#define MongoDB_BSONReader_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/BinaryReader.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API BSONReader
|
||||
/// Class for reading BSON using a Poco::BinaryReader
|
||||
{
|
||||
public:
|
||||
BSONReader(const Poco::BinaryReader & reader) : _reader(reader)
|
||||
/// Creates the BSONReader using the given BinaryWriter.
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~BSONReader()
|
||||
/// Destroys the BSONReader.
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read(T & t)
|
||||
/// Reads the value from the reader. The default implementation uses the >> operator to
|
||||
/// the given argument. Special types can write their own version.
|
||||
{
|
||||
_reader >> t;
|
||||
}
|
||||
|
||||
std::string readCString();
|
||||
/// Reads a cstring from the reader.
|
||||
/// A cstring is a string terminated with a 0x00.
|
||||
|
||||
private:
|
||||
Poco::BinaryReader _reader;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline std::string BSONReader::readCString()
|
||||
{
|
||||
std::string val;
|
||||
while (_reader.good())
|
||||
{
|
||||
char c;
|
||||
_reader >> c;
|
||||
if (_reader.good())
|
||||
{
|
||||
if (c == 0x00)
|
||||
return val;
|
||||
else
|
||||
val += c;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_BSONReader_INCLUDED
|
@ -1,76 +0,0 @@
|
||||
//
|
||||
// BSONWriter.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: BSONWriter
|
||||
//
|
||||
// Definition of the BSONWriter class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_BSONWriter_INCLUDED
|
||||
#define MongoDB_BSONWriter_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/BinaryWriter.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API BSONWriter
|
||||
/// Class for writing BSON using a Poco::BinaryWriter.
|
||||
{
|
||||
public:
|
||||
BSONWriter(const Poco::BinaryWriter & writer) : _writer(writer)
|
||||
/// Creates the BSONWriter.
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~BSONWriter()
|
||||
/// Destroys the BSONWriter.
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write(T & t)
|
||||
/// Writes the value to the writer. The default implementation uses
|
||||
/// the << operator. Special types can write their own version.
|
||||
{
|
||||
_writer << t;
|
||||
}
|
||||
|
||||
void writeCString(const std::string & value);
|
||||
/// Writes a cstring to the writer. A cstring is a string
|
||||
/// terminated a null character.
|
||||
|
||||
private:
|
||||
Poco::BinaryWriter _writer;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline void BSONWriter::writeCString(const std::string & value)
|
||||
{
|
||||
_writer.writeRaw(value);
|
||||
_writer << (unsigned char)0x00;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_BSONWriter_INCLUDED
|
@ -1,158 +0,0 @@
|
||||
//
|
||||
// Binary.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Binary
|
||||
//
|
||||
// Definition of the Binary class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_Binary_INCLUDED
|
||||
#define MongoDB_Binary_INCLUDED
|
||||
|
||||
|
||||
#include <sstream>
|
||||
#include "Poco/Base64Encoder.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include "Poco/MemoryStream.h"
|
||||
#include "Poco/MongoDB/Element.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/UUID.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API Binary
|
||||
/// Implements BSON Binary.
|
||||
///
|
||||
/// A Binary stores its data in a Poco::Buffer<unsigned char>.
|
||||
{
|
||||
public:
|
||||
using Ptr = SharedPtr<Binary>;
|
||||
|
||||
Binary();
|
||||
/// Creates an empty Binary with subtype 0.
|
||||
|
||||
Binary(Poco::Int32 size, unsigned char subtype);
|
||||
/// Creates a Binary with a buffer of the given size and the given subtype.
|
||||
|
||||
Binary(const UUID & uuid);
|
||||
/// Creates a Binary containing an UUID.
|
||||
|
||||
Binary(const std::string & data, unsigned char subtype = 0);
|
||||
/// Creates a Binary with the contents of the given string and the given subtype.
|
||||
|
||||
Binary(const void * data, Poco::Int32 size, unsigned char subtype = 0);
|
||||
/// Creates a Binary with the contents of the given buffer and the given subtype.
|
||||
|
||||
virtual ~Binary();
|
||||
/// Destroys the Binary.
|
||||
|
||||
Buffer<unsigned char> & buffer();
|
||||
/// Returns a reference to the internal buffer
|
||||
|
||||
unsigned char subtype() const;
|
||||
/// Returns the subtype.
|
||||
|
||||
void subtype(unsigned char type);
|
||||
/// Sets the subtype.
|
||||
|
||||
std::string toString(int indent = 0) const;
|
||||
/// Returns the contents of the Binary as Base64-encoded string.
|
||||
|
||||
std::string toRawString() const;
|
||||
/// Returns the raw content of the Binary as a string.
|
||||
|
||||
UUID uuid() const;
|
||||
/// Returns the UUID when the binary subtype is 0x04.
|
||||
/// Otherwise, throws a Poco::BadCastException.
|
||||
|
||||
private:
|
||||
Buffer<unsigned char> _buffer;
|
||||
unsigned char _subtype;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline unsigned char Binary::subtype() const
|
||||
{
|
||||
return _subtype;
|
||||
}
|
||||
|
||||
|
||||
inline void Binary::subtype(unsigned char type)
|
||||
{
|
||||
_subtype = type;
|
||||
}
|
||||
|
||||
|
||||
inline Buffer<unsigned char> & Binary::buffer()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
|
||||
inline std::string Binary::toRawString() const
|
||||
{
|
||||
return std::string(reinterpret_cast<const char *>(_buffer.begin()), _buffer.size());
|
||||
}
|
||||
|
||||
|
||||
// BSON Embedded Document
|
||||
// spec: binary
|
||||
template <>
|
||||
struct ElementTraits<Binary::Ptr>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x05
|
||||
};
|
||||
|
||||
static std::string toString(const Binary::Ptr & value, int indent = 0) { return value.isNull() ? "" : value->toString(); }
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<Binary::Ptr>(Binary::Ptr & to)
|
||||
{
|
||||
Poco::Int32 size;
|
||||
_reader >> size;
|
||||
|
||||
to->buffer().resize(size);
|
||||
|
||||
unsigned char subtype;
|
||||
_reader >> subtype;
|
||||
to->subtype(subtype);
|
||||
|
||||
_reader.readRaw((char *)to->buffer().begin(), size);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<Binary::Ptr>(Binary::Ptr & from)
|
||||
{
|
||||
_writer << (Poco::Int32)from->buffer().size();
|
||||
_writer << from->subtype();
|
||||
_writer.writeRaw((char *)from->buffer().begin(), from->buffer().size());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_Binary_INCLUDED
|
@ -1,191 +0,0 @@
|
||||
//
|
||||
// Connection.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Connection
|
||||
//
|
||||
// Definition of the Connection class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_Connection_INCLUDED
|
||||
#define MongoDB_Connection_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/OpMsgMessage.h"
|
||||
#include "Poco/MongoDB/RequestMessage.h"
|
||||
#include "Poco/MongoDB/ResponseMessage.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Net/SocketAddress.h"
|
||||
#include "Poco/Net/StreamSocket.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API Connection
|
||||
/// Represents a connection to a MongoDB server
|
||||
/// using the MongoDB wire protocol.
|
||||
///
|
||||
/// See https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/
|
||||
/// for more information on the wire protocol.
|
||||
{
|
||||
public:
|
||||
using Ptr = Poco::SharedPtr<Connection>;
|
||||
|
||||
class MongoDB_API SocketFactory
|
||||
{
|
||||
public:
|
||||
SocketFactory();
|
||||
/// Creates the SocketFactory.
|
||||
|
||||
virtual ~SocketFactory();
|
||||
/// Destroys the SocketFactory.
|
||||
|
||||
virtual Poco::Net::StreamSocket createSocket(const std::string & host, int port, Poco::Timespan connectTimeout, bool secure);
|
||||
/// Creates a Poco::Net::StreamSocket (if secure is false), or a
|
||||
/// Poco::Net::SecureStreamSocket (if secure is true) connected to the
|
||||
/// given host and port number.
|
||||
///
|
||||
/// The default implementation will throw a Poco::NotImplementedException
|
||||
/// if secure is true.
|
||||
};
|
||||
|
||||
Connection();
|
||||
/// Creates an unconnected Connection.
|
||||
///
|
||||
/// Use this when you want to connect later on.
|
||||
|
||||
Connection(const std::string & hostAndPort);
|
||||
/// Creates a Connection connected to the given MongoDB instance at host:port.
|
||||
///
|
||||
/// The host and port must be separated with a colon.
|
||||
|
||||
Connection(const std::string & uri, SocketFactory & socketFactory);
|
||||
/// Creates a Connection connected to the given MongoDB instance at the
|
||||
/// given URI.
|
||||
///
|
||||
/// See the corresponding connect() method for more information.
|
||||
|
||||
Connection(const std::string & host, int port);
|
||||
/// Creates a Connection connected to the given MongoDB instance at host and port.
|
||||
|
||||
Connection(const Poco::Net::SocketAddress & addrs);
|
||||
/// Creates a Connection connected to the given MongoDB instance at the given address.
|
||||
|
||||
Connection(const Poco::Net::StreamSocket & socket);
|
||||
/// Creates a Connection connected to the given MongoDB instance using the given socket,
|
||||
/// which must already be connected.
|
||||
|
||||
virtual ~Connection();
|
||||
/// Destroys the Connection.
|
||||
|
||||
Poco::Net::SocketAddress address() const;
|
||||
/// Returns the address of the MongoDB server.
|
||||
|
||||
const std::string & uri() const;
|
||||
/// Returns the uri on which the connection was made.
|
||||
|
||||
void connect(const std::string & hostAndPort);
|
||||
/// Connects to the given MongoDB server.
|
||||
///
|
||||
/// The host and port must be separated with a colon.
|
||||
|
||||
void connect(const std::string & uri, SocketFactory & socketFactory);
|
||||
/// Connects to the given MongoDB instance at the given URI.
|
||||
///
|
||||
/// The URI must be in standard MongoDB connection string URI format:
|
||||
///
|
||||
/// mongodb://<user>:<password>@hostname.com:<port>/database-name?options
|
||||
///
|
||||
/// The following options are supported:
|
||||
///
|
||||
/// - ssl: If ssl=true is specified, a custom SocketFactory subclass creating
|
||||
/// a SecureStreamSocket must be supplied.
|
||||
/// - connectTimeoutMS: Socket connection timeout in milliseconds.
|
||||
/// - socketTimeoutMS: Socket send/receive timeout in milliseconds.
|
||||
/// - authMechanism: Authentication mechanism. Only "SCRAM-SHA-1" (default)
|
||||
/// and "MONGODB-CR" are supported.
|
||||
///
|
||||
/// Unknown options are silently ignored.
|
||||
///
|
||||
/// Will also attempt to authenticate using the specified credentials,
|
||||
/// using Database::authenticate().
|
||||
///
|
||||
/// Throws a Poco::NoPermissionException if authentication fails.
|
||||
|
||||
void connect(const std::string & host, int port);
|
||||
/// Connects to the given MongoDB server.
|
||||
|
||||
void connect(const Poco::Net::SocketAddress & addrs);
|
||||
/// Connects to the given MongoDB server.
|
||||
|
||||
void connect(const Poco::Net::StreamSocket & socket);
|
||||
/// Connects using an already connected socket.
|
||||
|
||||
void disconnect();
|
||||
/// Disconnects from the MongoDB server.
|
||||
|
||||
void sendRequest(RequestMessage & request);
|
||||
/// Sends a request to the MongoDB server.
|
||||
///
|
||||
/// Used for one-way requests without a response.
|
||||
|
||||
void sendRequest(RequestMessage & request, ResponseMessage & response);
|
||||
/// Sends a request to the MongoDB server and receives the response.
|
||||
///
|
||||
/// Use this when a response is expected: only a "query" or "getmore"
|
||||
/// request will return a response.
|
||||
|
||||
void sendRequest(OpMsgMessage & request, OpMsgMessage & response);
|
||||
/// Sends a request to the MongoDB server and receives the response
|
||||
/// using newer wire protocol with OP_MSG.
|
||||
|
||||
void sendRequest(OpMsgMessage & request);
|
||||
/// Sends an unacknowledged request to the MongoDB server using newer
|
||||
/// wire protocol with OP_MSG.
|
||||
/// No response is sent by the server.
|
||||
|
||||
void readResponse(OpMsgMessage & response);
|
||||
/// Reads additional response data when previous message's flag moreToCome
|
||||
/// indicates that server will send more data.
|
||||
/// NOTE: See comments in OpMsgCursor code.
|
||||
|
||||
|
||||
protected:
|
||||
void connect();
|
||||
|
||||
private:
|
||||
Poco::Net::SocketAddress _address;
|
||||
Poco::Net::StreamSocket _socket;
|
||||
std::string _uri;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline Net::SocketAddress Connection::address() const
|
||||
{
|
||||
return _address;
|
||||
}
|
||||
inline const std::string & Connection::uri() const
|
||||
{
|
||||
return _uri;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_Connection_INCLUDED
|
@ -1,80 +0,0 @@
|
||||
//
|
||||
// Cursor.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Cursor
|
||||
//
|
||||
// Definition of the Cursor class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_Cursor_INCLUDED
|
||||
#define MongoDB_Cursor_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Connection.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/MongoDB/QueryRequest.h"
|
||||
#include "Poco/MongoDB/ResponseMessage.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API Cursor : public Document
|
||||
/// Cursor is an helper class for querying multiple documents.
|
||||
{
|
||||
public:
|
||||
Cursor(const std::string & dbname, const std::string & collectionName, QueryRequest::Flags flags = QueryRequest::QUERY_DEFAULT);
|
||||
/// Creates a Cursor for the given database and collection, using the specified flags.
|
||||
|
||||
Cursor(const std::string & fullCollectionName, QueryRequest::Flags flags = QueryRequest::QUERY_DEFAULT);
|
||||
/// Creates a Cursor for the given database and collection ("database.collection"), using the specified flags.
|
||||
|
||||
Cursor(const Document & aggregationResponse);
|
||||
/// Creates a Cursor for the given aggregation query response.
|
||||
|
||||
virtual ~Cursor();
|
||||
/// Destroys the Cursor.
|
||||
|
||||
ResponseMessage & next(Connection & connection);
|
||||
/// Tries to get the next documents. As long as ResponseMessage has a
|
||||
/// cursor ID next can be called to retrieve the next bunch of documents.
|
||||
///
|
||||
/// The cursor must be killed (see kill()) when not all documents are needed.
|
||||
|
||||
QueryRequest & query();
|
||||
/// Returns the associated query.
|
||||
|
||||
void kill(Connection & connection);
|
||||
/// Kills the cursor and reset it so that it can be reused.
|
||||
|
||||
private:
|
||||
QueryRequest _query;
|
||||
ResponseMessage _response;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline QueryRequest & Cursor::query()
|
||||
{
|
||||
return _query;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_Cursor_INCLUDED
|
@ -1,233 +0,0 @@
|
||||
//
|
||||
// Database.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Database
|
||||
//
|
||||
// Definition of the Database class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_Database_INCLUDED
|
||||
#define MongoDB_Database_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Connection.h"
|
||||
#include "Poco/MongoDB/DeleteRequest.h"
|
||||
#include "Poco/MongoDB/Document.h"
|
||||
#include "Poco/MongoDB/InsertRequest.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/MongoDB/QueryRequest.h"
|
||||
#include "Poco/MongoDB/UpdateRequest.h"
|
||||
|
||||
#include "Poco/MongoDB/OpMsgCursor.h"
|
||||
#include "Poco/MongoDB/OpMsgMessage.h"
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API Database
|
||||
/// Database is a helper class for creating requests. MongoDB works with
|
||||
/// collection names and uses the part before the first dot as the name of
|
||||
/// the database.
|
||||
{
|
||||
public:
|
||||
explicit Database(const std::string & name);
|
||||
/// Creates a Database for the database with the given name.
|
||||
|
||||
virtual ~Database();
|
||||
/// Destroys the Database.
|
||||
|
||||
const std::string & name() const;
|
||||
/// Database name
|
||||
|
||||
bool authenticate(
|
||||
Connection & connection,
|
||||
const std::string & username,
|
||||
const std::string & password,
|
||||
const std::string & method = AUTH_SCRAM_SHA1);
|
||||
/// Authenticates against the database using the given connection,
|
||||
/// username and password, as well as authentication method.
|
||||
///
|
||||
/// "MONGODB-CR" (default prior to MongoDB 3.0) and
|
||||
/// "SCRAM-SHA-1" (default starting in 3.0) are the only supported
|
||||
/// authentication methods.
|
||||
///
|
||||
/// Returns true if authentication was successful, otherwise false.
|
||||
///
|
||||
/// May throw a Poco::ProtocolException if authentication fails for a reason other than
|
||||
/// invalid credentials.
|
||||
|
||||
Document::Ptr queryBuildInfo(Connection & connection) const;
|
||||
/// Queries server build info (all wire protocols)
|
||||
|
||||
Document::Ptr queryServerHello(Connection & connection, bool old = false) const;
|
||||
/// Queries hello response from server (all wire protocols)
|
||||
|
||||
Int64 count(Connection & connection, const std::string & collectionName) const;
|
||||
/// Sends a count request for the given collection to MongoDB. (old wire protocol)
|
||||
///
|
||||
/// If the command fails, -1 is returned.
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> createCommand() const;
|
||||
/// Creates a QueryRequest for a command. (old wire protocol)
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> createCountRequest(const std::string & collectionName) const;
|
||||
/// Creates a QueryRequest to count the given collection.
|
||||
/// The collectionname must not contain the database name. (old wire protocol)
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::DeleteRequest> createDeleteRequest(const std::string & collectionName) const;
|
||||
/// Creates a DeleteRequest to delete documents in the given collection.
|
||||
/// The collectionname must not contain the database name. (old wire protocol)
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::InsertRequest> createInsertRequest(const std::string & collectionName) const;
|
||||
/// Creates an InsertRequest to insert new documents in the given collection.
|
||||
/// The collectionname must not contain the database name. (old wire protocol)
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> createQueryRequest(const std::string & collectionName) const;
|
||||
/// Creates a QueryRequest. (old wire protocol)
|
||||
/// The collectionname must not contain the database name.
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::UpdateRequest> createUpdateRequest(const std::string & collectionName) const;
|
||||
/// Creates an UpdateRequest. (old wire protocol)
|
||||
/// The collectionname must not contain the database name.
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::OpMsgMessage> createOpMsgMessage(const std::string & collectionName) const;
|
||||
/// Creates OpMsgMessage. (new wire protocol)
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::OpMsgMessage> createOpMsgMessage() const;
|
||||
/// Creates OpMsgMessage for database commands that do not require collection as an argument. (new wire protocol)
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::OpMsgCursor> createOpMsgCursor(const std::string & collectionName) const;
|
||||
/// Creates OpMsgCursor. (new wire protocol)
|
||||
|
||||
Poco::MongoDB::Document::Ptr ensureIndex(
|
||||
Connection & connection,
|
||||
const std::string & collection,
|
||||
const std::string & indexName,
|
||||
Poco::MongoDB::Document::Ptr keys,
|
||||
bool unique = false,
|
||||
bool background = false,
|
||||
int version = 0,
|
||||
int ttl = 0);
|
||||
/// Creates an index. The document returned is the result of a getLastError call.
|
||||
/// For more info look at the ensureIndex information on the MongoDB website. (old wire protocol)
|
||||
|
||||
Document::Ptr getLastErrorDoc(Connection & connection) const;
|
||||
/// Sends the getLastError command to the database and returns the error document.
|
||||
/// (old wire protocol)
|
||||
|
||||
std::string getLastError(Connection & connection) const;
|
||||
/// Sends the getLastError command to the database and returns the err element
|
||||
/// from the error document. When err is null, an empty string is returned.
|
||||
/// (old wire protocol)
|
||||
|
||||
static const std::string AUTH_MONGODB_CR;
|
||||
/// Default authentication mechanism prior to MongoDB 3.0.
|
||||
|
||||
static const std::string AUTH_SCRAM_SHA1;
|
||||
/// Default authentication mechanism for MongoDB 3.0.
|
||||
|
||||
enum WireVersion
|
||||
/// Wire version as reported by the command hello.
|
||||
/// See details in MongoDB github, repository specifications.
|
||||
/// @see queryServerHello
|
||||
{
|
||||
VER_26 = 1,
|
||||
VER_26_2 = 2,
|
||||
VER_30 = 3,
|
||||
VER_32 = 4,
|
||||
VER_34 = 5,
|
||||
VER_36 = 6, ///< First wire version that supports OP_MSG
|
||||
VER_40 = 7,
|
||||
VER_42 = 8,
|
||||
VER_44 = 9,
|
||||
VER_50 = 13,
|
||||
VER_51 = 14, ///< First wire version that supports only OP_MSG
|
||||
VER_52 = 15,
|
||||
VER_53 = 16,
|
||||
VER_60 = 17
|
||||
};
|
||||
|
||||
protected:
|
||||
bool authCR(Connection & connection, const std::string & username, const std::string & password);
|
||||
bool authSCRAM(Connection & connection, const std::string & username, const std::string & password);
|
||||
|
||||
private:
|
||||
std::string _dbname;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline const std::string & Database::name() const
|
||||
{
|
||||
return _dbname;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::SharedPtr<Poco::MongoDB::QueryRequest> Database::createCommand() const
|
||||
{
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> cmd = createQueryRequest("$cmd");
|
||||
cmd->setNumberToReturn(1);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::SharedPtr<Poco::MongoDB::DeleteRequest> Database::createDeleteRequest(const std::string & collectionName) const
|
||||
{
|
||||
return new Poco::MongoDB::DeleteRequest(_dbname + '.' + collectionName);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::SharedPtr<Poco::MongoDB::InsertRequest> Database::createInsertRequest(const std::string & collectionName) const
|
||||
{
|
||||
return new Poco::MongoDB::InsertRequest(_dbname + '.' + collectionName);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::SharedPtr<Poco::MongoDB::QueryRequest> Database::createQueryRequest(const std::string & collectionName) const
|
||||
{
|
||||
return new Poco::MongoDB::QueryRequest(_dbname + '.' + collectionName);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::SharedPtr<Poco::MongoDB::UpdateRequest> Database::createUpdateRequest(const std::string & collectionName) const
|
||||
{
|
||||
return new Poco::MongoDB::UpdateRequest(_dbname + '.' + collectionName);
|
||||
}
|
||||
|
||||
// -- New wire protocol commands
|
||||
|
||||
inline Poco::SharedPtr<Poco::MongoDB::OpMsgMessage> Database::createOpMsgMessage(const std::string & collectionName) const
|
||||
{
|
||||
return new Poco::MongoDB::OpMsgMessage(_dbname, collectionName);
|
||||
}
|
||||
|
||||
inline Poco::SharedPtr<Poco::MongoDB::OpMsgMessage> Database::createOpMsgMessage() const
|
||||
{
|
||||
// Collection name for database commands is not needed.
|
||||
return createOpMsgMessage("");
|
||||
}
|
||||
|
||||
inline Poco::SharedPtr<Poco::MongoDB::OpMsgCursor> Database::createOpMsgCursor(const std::string & collectionName) const
|
||||
{
|
||||
return new Poco::MongoDB::OpMsgCursor(_dbname, collectionName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_Database_INCLUDED
|
@ -1,116 +0,0 @@
|
||||
//
|
||||
// DeleteRequest.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: DeleteRequest
|
||||
//
|
||||
// Definition of the DeleteRequest class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_DeleteRequest_INCLUDED
|
||||
#define MongoDB_DeleteRequest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Document.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/MongoDB/RequestMessage.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API DeleteRequest : public RequestMessage
|
||||
/// A DeleteRequest is used to delete one or more documents from a database.
|
||||
///
|
||||
/// Specific flags for this request
|
||||
/// - DELETE_DEFAULT: default delete operation
|
||||
/// - DELETE_SINGLE_REMOVE: delete only the first document
|
||||
{
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
DELETE_DEFAULT = 0,
|
||||
/// Default
|
||||
|
||||
DELETE_SINGLE_REMOVE = 1
|
||||
/// Delete only the first document.
|
||||
};
|
||||
|
||||
DeleteRequest(const std::string & collectionName, Flags flags = DELETE_DEFAULT);
|
||||
/// Creates a DeleteRequest for the given collection using the given flags.
|
||||
///
|
||||
/// The full collection name is the concatenation of the database
|
||||
/// name with the collection name, using a "." for the concatenation. For example,
|
||||
/// for the database "foo" and the collection "bar", the full collection name is
|
||||
/// "foo.bar".
|
||||
|
||||
DeleteRequest(const std::string & collectionName, bool justOne);
|
||||
/// Creates a DeleteRequest for the given collection.
|
||||
///
|
||||
/// The full collection name is the concatenation of the database
|
||||
/// name with the collection name, using a "." for the concatenation. For example,
|
||||
/// for the database "foo" and the collection "bar", the full collection name is
|
||||
/// "foo.bar".
|
||||
///
|
||||
/// If justOne is true, only the first matching document will
|
||||
/// be removed (the same as using flag DELETE_SINGLE_REMOVE).
|
||||
|
||||
virtual ~DeleteRequest();
|
||||
/// Destructor
|
||||
|
||||
Flags flags() const;
|
||||
/// Returns the flags.
|
||||
|
||||
void flags(Flags flag);
|
||||
/// Sets the flags.
|
||||
|
||||
Document & selector();
|
||||
/// Returns the selector document.
|
||||
|
||||
protected:
|
||||
void buildRequest(BinaryWriter & writer);
|
||||
/// Writes the OP_DELETE request to the writer.
|
||||
|
||||
private:
|
||||
Flags _flags;
|
||||
std::string _fullCollectionName;
|
||||
Document _selector;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline DeleteRequest::Flags DeleteRequest::flags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
|
||||
inline void DeleteRequest::flags(DeleteRequest::Flags flags)
|
||||
{
|
||||
_flags = flags;
|
||||
}
|
||||
|
||||
|
||||
inline Document & DeleteRequest::selector()
|
||||
{
|
||||
return _selector;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_DeleteRequest_INCLUDED
|
@ -1,296 +0,0 @@
|
||||
//
|
||||
// Document.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Document
|
||||
//
|
||||
// Definition of the Document class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_Document_INCLUDED
|
||||
#define MongoDB_Document_INCLUDED
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include "Poco/BinaryReader.h"
|
||||
#include "Poco/BinaryWriter.h"
|
||||
#include "Poco/MongoDB/Element.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
class Array;
|
||||
|
||||
class ElementFindByName
|
||||
{
|
||||
public:
|
||||
ElementFindByName(const std::string & name) : _name(name) { }
|
||||
|
||||
bool operator()(const Element::Ptr & element) { return !element.isNull() && element->name() == _name; }
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
|
||||
class MongoDB_API Document
|
||||
/// Represents a MongoDB (BSON) document.
|
||||
{
|
||||
public:
|
||||
using Ptr = SharedPtr<Document>;
|
||||
using Vector = std::vector<Document::Ptr>;
|
||||
|
||||
Document();
|
||||
/// Creates an empty Document.
|
||||
|
||||
virtual ~Document();
|
||||
/// Destroys the Document.
|
||||
|
||||
Document & addElement(Element::Ptr element);
|
||||
/// Add an element to the document.
|
||||
///
|
||||
/// The active document is returned to allow chaining of the add methods.
|
||||
|
||||
template <typename T>
|
||||
Document & add(const std::string & name, T value)
|
||||
/// Creates an element with the given name and value and
|
||||
/// adds it to the document.
|
||||
///
|
||||
/// The active document is returned to allow chaining of the add methods.
|
||||
{
|
||||
return addElement(new ConcreteElement<T>(name, value));
|
||||
}
|
||||
|
||||
Document & add(const std::string & name, const char * value)
|
||||
/// Creates an element with the given name and value and
|
||||
/// adds it to the document.
|
||||
///
|
||||
/// The active document is returned to allow chaining of the add methods.
|
||||
{
|
||||
return addElement(new ConcreteElement<std::string>(name, std::string(value)));
|
||||
}
|
||||
|
||||
Document & addNewDocument(const std::string & name);
|
||||
/// Create a new document and add it to this document.
|
||||
/// Unlike the other add methods, this method returns
|
||||
/// a reference to the new document.
|
||||
|
||||
Array & addNewArray(const std::string & name);
|
||||
/// Create a new array and add it to this document.
|
||||
/// Method returns a reference to the new array.
|
||||
|
||||
void clear();
|
||||
/// Removes all elements from the document.
|
||||
|
||||
void elementNames(std::vector<std::string> & keys) const;
|
||||
/// Puts all element names into std::vector.
|
||||
|
||||
bool empty() const;
|
||||
/// Returns true if the document doesn't contain any documents.
|
||||
|
||||
bool exists(const std::string & name) const;
|
||||
/// Returns true if the document has an element with the given name.
|
||||
|
||||
template <typename T>
|
||||
T get(const std::string & name) const
|
||||
/// Returns the element with the given name and tries to convert
|
||||
/// it to the template type. When the element is not found, a
|
||||
/// NotFoundException will be thrown. When the element can't be
|
||||
/// converted a BadCastException will be thrown.
|
||||
{
|
||||
Element::Ptr element = get(name);
|
||||
if (element.isNull())
|
||||
{
|
||||
throw NotFoundException(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ElementTraits<T>::TypeId == element->type())
|
||||
{
|
||||
ConcreteElement<T> * concrete = dynamic_cast<ConcreteElement<T> *>(element.get());
|
||||
if (concrete != 0)
|
||||
{
|
||||
return concrete->value();
|
||||
}
|
||||
}
|
||||
throw BadCastException("Invalid type mismatch!");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get(const std::string & name, const T & def) const
|
||||
/// Returns the element with the given name and tries to convert
|
||||
/// it to the template type. When the element is not found, or
|
||||
/// has the wrong type, the def argument will be returned.
|
||||
{
|
||||
Element::Ptr element = get(name);
|
||||
if (element.isNull())
|
||||
{
|
||||
return def;
|
||||
}
|
||||
|
||||
if (ElementTraits<T>::TypeId == element->type())
|
||||
{
|
||||
ConcreteElement<T> * concrete = dynamic_cast<ConcreteElement<T> *>(element.get());
|
||||
if (concrete != 0)
|
||||
{
|
||||
return concrete->value();
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
Element::Ptr get(const std::string & name) const;
|
||||
/// Returns the element with the given name.
|
||||
/// An empty element will be returned when the element is not found.
|
||||
|
||||
Int64 getInteger(const std::string & name) const;
|
||||
/// Returns an integer. Useful when MongoDB returns Int32, Int64
|
||||
/// or double for a number (count for example). This method will always
|
||||
/// return an Int64. When the element is not found, a
|
||||
/// Poco::NotFoundException will be thrown.
|
||||
|
||||
bool remove(const std::string & name);
|
||||
/// Removes an element from the document.
|
||||
|
||||
template <typename T>
|
||||
bool isType(const std::string & name) const
|
||||
/// Returns true when the type of the element equals the TypeId of ElementTrait.
|
||||
{
|
||||
Element::Ptr element = get(name);
|
||||
if (element.isNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ElementTraits<T>::TypeId == element->type();
|
||||
}
|
||||
|
||||
void read(BinaryReader & reader);
|
||||
/// Reads a document from the reader
|
||||
|
||||
std::size_t size() const;
|
||||
/// Returns the number of elements in the document.
|
||||
|
||||
virtual std::string toString(int indent = 0) const;
|
||||
/// Returns a String representation of the document.
|
||||
|
||||
void write(BinaryWriter & writer);
|
||||
/// Writes a document to the reader
|
||||
|
||||
protected:
|
||||
ElementSet _elements;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline Document & Document::addElement(Element::Ptr element)
|
||||
{
|
||||
_elements.push_back(element);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline Document & Document::addNewDocument(const std::string & name)
|
||||
{
|
||||
Document::Ptr newDoc = new Document();
|
||||
add(name, newDoc);
|
||||
return *newDoc;
|
||||
}
|
||||
|
||||
|
||||
inline void Document::clear()
|
||||
{
|
||||
_elements.clear();
|
||||
}
|
||||
|
||||
|
||||
inline bool Document::empty() const
|
||||
{
|
||||
return _elements.empty();
|
||||
}
|
||||
|
||||
|
||||
inline void Document::elementNames(std::vector<std::string> & keys) const
|
||||
{
|
||||
for (ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it)
|
||||
{
|
||||
keys.push_back((*it)->name());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline bool Document::exists(const std::string & name) const
|
||||
{
|
||||
return std::find_if(_elements.begin(), _elements.end(), ElementFindByName(name)) != _elements.end();
|
||||
}
|
||||
|
||||
|
||||
inline bool Document::remove(const std::string & name)
|
||||
{
|
||||
auto it = std::find_if(_elements.begin(), _elements.end(), ElementFindByName(name));
|
||||
if (it == _elements.end())
|
||||
return false;
|
||||
|
||||
_elements.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t Document::size() const
|
||||
{
|
||||
return _elements.size();
|
||||
}
|
||||
|
||||
|
||||
// BSON Embedded Document
|
||||
// spec: document
|
||||
template <>
|
||||
struct ElementTraits<Document::Ptr>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x03
|
||||
};
|
||||
|
||||
static std::string toString(const Document::Ptr & value, int indent = 0)
|
||||
{
|
||||
return value.isNull() ? "null" : value->toString(indent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<Document::Ptr>(Document::Ptr & to)
|
||||
{
|
||||
to->read(_reader);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<Document::Ptr>(Document::Ptr & from)
|
||||
{
|
||||
from->write(_writer);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_Document_INCLUDED
|
@ -1,393 +0,0 @@
|
||||
//
|
||||
// Element.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Element
|
||||
//
|
||||
// Definition of the Element class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_Element_INCLUDED
|
||||
#define MongoDB_Element_INCLUDED
|
||||
|
||||
|
||||
#include <iomanip>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "Poco/BinaryReader.h"
|
||||
#include "Poco/BinaryWriter.h"
|
||||
#include "Poco/DateTimeFormatter.h"
|
||||
#include "Poco/MongoDB/BSONReader.h"
|
||||
#include "Poco/MongoDB/BSONWriter.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/Nullable.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/UTF8String.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API Element
|
||||
/// Represents an Element of a Document or an Array.
|
||||
{
|
||||
public:
|
||||
using Ptr = Poco::SharedPtr<Element>;
|
||||
|
||||
explicit Element(const std::string & name);
|
||||
/// Creates the Element with the given name.
|
||||
|
||||
virtual ~Element();
|
||||
/// Destructor
|
||||
|
||||
const std::string & name() const;
|
||||
/// Returns the name of the element.
|
||||
|
||||
virtual std::string toString(int indent = 0) const = 0;
|
||||
/// Returns a string representation of the element.
|
||||
|
||||
virtual int type() const = 0;
|
||||
/// Returns the MongoDB type of the element.
|
||||
|
||||
private:
|
||||
virtual void read(BinaryReader & reader) = 0;
|
||||
virtual void write(BinaryWriter & writer) = 0;
|
||||
|
||||
friend class Document;
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline const std::string & Element::name() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
|
||||
using ElementSet = std::list<Element::Ptr>;
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct ElementTraits
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
// BSON Floating point
|
||||
// spec: double
|
||||
template <>
|
||||
struct ElementTraits<double>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x01
|
||||
};
|
||||
|
||||
static std::string toString(const double & value, int indent = 0) { return Poco::NumberFormatter::format(value); }
|
||||
};
|
||||
|
||||
|
||||
// BSON UTF-8 string
|
||||
// spec: int32 (byte*) "\x00"
|
||||
// int32 is the number bytes in byte* + 1 (for trailing "\x00")
|
||||
template <>
|
||||
struct ElementTraits<std::string>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x02
|
||||
};
|
||||
|
||||
static std::string toString(const std::string & value, int indent = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << '"';
|
||||
|
||||
for (std::string::const_iterator it = value.begin(); it != value.end(); ++it)
|
||||
{
|
||||
switch (*it)
|
||||
{
|
||||
case '"':
|
||||
oss << "\\\"";
|
||||
break;
|
||||
case '\\':
|
||||
oss << "\\\\";
|
||||
break;
|
||||
case '\b':
|
||||
oss << "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
oss << "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
oss << "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
oss << "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
oss << "\\t";
|
||||
break;
|
||||
default: {
|
||||
if (*it > 0 && *it <= 0x1F)
|
||||
{
|
||||
oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << *it;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
oss << '"';
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<std::string>(std::string & to)
|
||||
{
|
||||
Poco::Int32 size;
|
||||
_reader >> size;
|
||||
_reader.readRaw(size, to);
|
||||
to.erase(to.end() - 1); // remove terminating 0
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<std::string>(std::string & from)
|
||||
{
|
||||
_writer << (Poco::Int32)(from.length() + 1);
|
||||
writeCString(from);
|
||||
}
|
||||
|
||||
|
||||
// BSON bool
|
||||
// spec: "\x00" "\x01"
|
||||
template <>
|
||||
struct ElementTraits<bool>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x08
|
||||
};
|
||||
|
||||
static std::string toString(const bool & value, int indent = 0) { return value ? "true" : "false"; }
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<bool>(bool & to)
|
||||
{
|
||||
unsigned char b;
|
||||
_reader >> b;
|
||||
to = b != 0;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<bool>(bool & from)
|
||||
{
|
||||
unsigned char b = from ? 0x01 : 0x00;
|
||||
_writer << b;
|
||||
}
|
||||
|
||||
|
||||
// BSON 32-bit integer
|
||||
// spec: int32
|
||||
template <>
|
||||
struct ElementTraits<Int32>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x10
|
||||
};
|
||||
|
||||
|
||||
static std::string toString(const Int32 & value, int indent = 0) { return Poco::NumberFormatter::format(value); }
|
||||
};
|
||||
|
||||
|
||||
// BSON UTC datetime
|
||||
// spec: int64
|
||||
template <>
|
||||
struct ElementTraits<Timestamp>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x09
|
||||
};
|
||||
|
||||
static std::string toString(const Timestamp & value, int indent = 0)
|
||||
{
|
||||
std::string result;
|
||||
result.append(1, '"');
|
||||
result.append(DateTimeFormatter::format(value, "%Y-%m-%dT%H:%M:%s%z"));
|
||||
result.append(1, '"');
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<Timestamp>(Timestamp & to)
|
||||
{
|
||||
Poco::Int64 value;
|
||||
_reader >> value;
|
||||
to = Timestamp::fromEpochTime(static_cast<std::time_t>(value / 1000));
|
||||
to += (value % 1000 * 1000);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<Timestamp>(Timestamp & from)
|
||||
{
|
||||
_writer << (from.epochMicroseconds() / 1000);
|
||||
}
|
||||
|
||||
|
||||
using NullValue = Nullable<unsigned char>;
|
||||
|
||||
|
||||
// BSON Null Value
|
||||
// spec:
|
||||
template <>
|
||||
struct ElementTraits<NullValue>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x0A
|
||||
};
|
||||
|
||||
static std::string toString(const NullValue & value, int indent = 0) { return "null"; }
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<NullValue>(NullValue & to)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<NullValue>(NullValue & from)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
struct BSONTimestamp
|
||||
{
|
||||
Poco::Timestamp ts;
|
||||
Poco::Int32 inc;
|
||||
};
|
||||
|
||||
|
||||
// BSON Timestamp
|
||||
// spec: int64
|
||||
template <>
|
||||
struct ElementTraits<BSONTimestamp>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x11
|
||||
};
|
||||
|
||||
static std::string toString(const BSONTimestamp & value, int indent = 0)
|
||||
{
|
||||
std::string result;
|
||||
result.append(1, '"');
|
||||
result.append(DateTimeFormatter::format(value.ts, "%Y-%m-%dT%H:%M:%s%z"));
|
||||
result.append(1, ' ');
|
||||
result.append(NumberFormatter::format(value.inc));
|
||||
result.append(1, '"');
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<BSONTimestamp>(BSONTimestamp & to)
|
||||
{
|
||||
Poco::Int64 value;
|
||||
_reader >> value;
|
||||
to.inc = value & 0xffffffff;
|
||||
value >>= 32;
|
||||
to.ts = Timestamp::fromEpochTime(static_cast<std::time_t>(value));
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<BSONTimestamp>(BSONTimestamp & from)
|
||||
{
|
||||
Poco::Int64 value = from.ts.epochMicroseconds() / 1000;
|
||||
value <<= 32;
|
||||
value += from.inc;
|
||||
_writer << value;
|
||||
}
|
||||
|
||||
|
||||
// BSON 64-bit integer
|
||||
// spec: int64
|
||||
template <>
|
||||
struct ElementTraits<Int64>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x12
|
||||
};
|
||||
|
||||
static std::string toString(const Int64 & value, int indent = 0) { return NumberFormatter::format(value); }
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class ConcreteElement : public Element
|
||||
{
|
||||
public:
|
||||
ConcreteElement(const std::string & name, const T & init) : Element(name), _value(init) { }
|
||||
|
||||
virtual ~ConcreteElement() { }
|
||||
|
||||
|
||||
T value() const { return _value; }
|
||||
|
||||
|
||||
std::string toString(int indent = 0) const { return ElementTraits<T>::toString(_value, indent); }
|
||||
|
||||
|
||||
int type() const { return ElementTraits<T>::TypeId; }
|
||||
|
||||
void read(BinaryReader & reader) { BSONReader(reader).read(_value); }
|
||||
|
||||
void write(BinaryWriter & writer) { BSONWriter(writer).write(_value); }
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_Element_INCLUDED
|
@ -1,92 +0,0 @@
|
||||
//
|
||||
// GetMoreRequest.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: GetMoreRequest
|
||||
//
|
||||
// Definition of the GetMoreRequest class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_GetMoreRequest_INCLUDED
|
||||
#define MongoDB_GetMoreRequest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/MongoDB/RequestMessage.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API GetMoreRequest : public RequestMessage
|
||||
/// A GetMoreRequest is used to query the database for more documents in a collection
|
||||
/// after a query request is send (OP_GETMORE).
|
||||
{
|
||||
public:
|
||||
GetMoreRequest(const std::string & collectionName, Int64 cursorID);
|
||||
/// Creates a GetMoreRequest for the give collection and cursor.
|
||||
///
|
||||
/// The full collection name is the concatenation of the database
|
||||
/// name with the collection name, using a "." for the concatenation. For example,
|
||||
/// for the database "foo" and the collection "bar", the full collection name is
|
||||
/// "foo.bar". The cursorID has been returned by the response on the query request.
|
||||
/// By default the numberToReturn is set to 100.
|
||||
|
||||
virtual ~GetMoreRequest();
|
||||
/// Destroys the GetMoreRequest.
|
||||
|
||||
Int32 getNumberToReturn() const;
|
||||
/// Returns the limit of returned documents.
|
||||
|
||||
void setNumberToReturn(Int32 n);
|
||||
/// Sets the limit of returned documents.
|
||||
|
||||
Int64 cursorID() const;
|
||||
/// Returns the cursor ID.
|
||||
|
||||
protected:
|
||||
void buildRequest(BinaryWriter & writer);
|
||||
|
||||
private:
|
||||
std::string _fullCollectionName;
|
||||
Int32 _numberToReturn;
|
||||
Int64 _cursorID;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline Int32 GetMoreRequest::getNumberToReturn() const
|
||||
{
|
||||
return _numberToReturn;
|
||||
}
|
||||
|
||||
|
||||
inline void GetMoreRequest::setNumberToReturn(Int32 n)
|
||||
{
|
||||
_numberToReturn = n;
|
||||
}
|
||||
|
||||
|
||||
inline Int64 GetMoreRequest::cursorID() const
|
||||
{
|
||||
return _cursorID;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_GetMoreRequest_INCLUDED
|
@ -1,100 +0,0 @@
|
||||
//
|
||||
// InsertRequest.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: InsertRequest
|
||||
//
|
||||
// Definition of the InsertRequest class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_InsertRequest_INCLUDED
|
||||
#define MongoDB_InsertRequest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Document.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/MongoDB/RequestMessage.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API InsertRequest : public RequestMessage
|
||||
/// A request for inserting one or more documents to the database
|
||||
/// (OP_INSERT).
|
||||
{
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
INSERT_DEFAULT = 0,
|
||||
/// If specified, perform a normal insert operation.
|
||||
|
||||
INSERT_CONTINUE_ON_ERROR = 1
|
||||
/// If set, the database will not stop processing a bulk insert if one
|
||||
/// fails (e.g. due to duplicate IDs). This makes bulk insert behave similarly
|
||||
/// to a series of single inserts, except lastError will be set if any insert
|
||||
/// fails, not just the last one. If multiple errors occur, only the most
|
||||
/// recent will be reported.
|
||||
};
|
||||
|
||||
InsertRequest(const std::string & collectionName, Flags flags = INSERT_DEFAULT);
|
||||
/// Creates an InsertRequest.
|
||||
///
|
||||
/// The full collection name is the concatenation of the database
|
||||
/// name with the collection name, using a "." for the concatenation. For example,
|
||||
/// for the database "foo" and the collection "bar", the full collection name is
|
||||
/// "foo.bar".
|
||||
|
||||
virtual ~InsertRequest();
|
||||
/// Destroys the InsertRequest.
|
||||
|
||||
Document & addNewDocument();
|
||||
/// Adds a new document for insertion. A reference to the empty document is
|
||||
/// returned. InsertRequest is the owner of the Document and will free it
|
||||
/// on destruction.
|
||||
|
||||
Document::Vector & documents();
|
||||
/// Returns the documents to insert into the database.
|
||||
|
||||
protected:
|
||||
void buildRequest(BinaryWriter & writer);
|
||||
|
||||
private:
|
||||
Int32 _flags;
|
||||
std::string _fullCollectionName;
|
||||
Document::Vector _documents;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline Document & InsertRequest::addNewDocument()
|
||||
{
|
||||
Document::Ptr doc = new Document();
|
||||
_documents.push_back(doc);
|
||||
return *doc;
|
||||
}
|
||||
|
||||
|
||||
inline Document::Vector & InsertRequest::documents()
|
||||
{
|
||||
return _documents;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_InsertRequest_INCLUDED
|
@ -1,108 +0,0 @@
|
||||
//
|
||||
// JavaScriptCode.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: JavaScriptCode
|
||||
//
|
||||
// Definition of the JavaScriptCode class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_JavaScriptCode_INCLUDED
|
||||
#define MongoDB_JavaScriptCode_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/BSONReader.h"
|
||||
#include "Poco/MongoDB/BSONWriter.h"
|
||||
#include "Poco/MongoDB/Element.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API JavaScriptCode
|
||||
/// Represents JavaScript type in BSON.
|
||||
{
|
||||
public:
|
||||
using Ptr = SharedPtr<JavaScriptCode>;
|
||||
|
||||
JavaScriptCode();
|
||||
/// Creates an empty JavaScriptCode object.
|
||||
|
||||
virtual ~JavaScriptCode();
|
||||
/// Destroys the JavaScriptCode.
|
||||
|
||||
void setCode(const std::string & code);
|
||||
/// Sets the JavaScript code.
|
||||
|
||||
std::string getCode() const;
|
||||
/// Returns the JavaScript code.
|
||||
|
||||
private:
|
||||
std::string _code;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline void JavaScriptCode::setCode(const std::string & code)
|
||||
{
|
||||
_code = code;
|
||||
}
|
||||
|
||||
|
||||
inline std::string JavaScriptCode::getCode() const
|
||||
{
|
||||
return _code;
|
||||
}
|
||||
|
||||
|
||||
// BSON JavaScript code
|
||||
// spec: string
|
||||
template <>
|
||||
struct ElementTraits<JavaScriptCode::Ptr>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x0D
|
||||
};
|
||||
|
||||
static std::string toString(const JavaScriptCode::Ptr & value, int indent = 0) { return value.isNull() ? "" : value->getCode(); }
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<JavaScriptCode::Ptr>(JavaScriptCode::Ptr & to)
|
||||
{
|
||||
std::string code;
|
||||
BSONReader(_reader).read(code);
|
||||
to = new JavaScriptCode();
|
||||
to->setCode(code);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<JavaScriptCode::Ptr>(JavaScriptCode::Ptr & from)
|
||||
{
|
||||
std::string code = from->getCode();
|
||||
BSONWriter(_writer).write(code);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_JavaScriptCode_INCLUDED
|
@ -1,65 +0,0 @@
|
||||
//
|
||||
// KillCursorsRequest.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: KillCursorsRequest
|
||||
//
|
||||
// Definition of the KillCursorsRequest class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_KillCursorsRequest_INCLUDED
|
||||
#define MongoDB_KillCursorsRequest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/MongoDB/RequestMessage.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API KillCursorsRequest : public RequestMessage
|
||||
/// Class for creating an OP_KILL_CURSORS client request. This
|
||||
/// request is used to kill cursors, which are still open,
|
||||
/// returned by query requests.
|
||||
{
|
||||
public:
|
||||
KillCursorsRequest();
|
||||
/// Creates a KillCursorsRequest.
|
||||
|
||||
virtual ~KillCursorsRequest();
|
||||
/// Destroys the KillCursorsRequest.
|
||||
|
||||
std::vector<Int64> & cursors();
|
||||
/// The internal list of cursors.
|
||||
|
||||
protected:
|
||||
void buildRequest(BinaryWriter & writer);
|
||||
std::vector<Int64> _cursors;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline std::vector<Int64> & KillCursorsRequest::cursors()
|
||||
{
|
||||
return _cursors;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_KillCursorsRequest_INCLUDED
|
@ -1,76 +0,0 @@
|
||||
//
|
||||
// Message.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Message
|
||||
//
|
||||
// Definition of the Message class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_Message_INCLUDED
|
||||
#define MongoDB_Message_INCLUDED
|
||||
|
||||
|
||||
#include <sstream>
|
||||
#include "Poco/BinaryReader.h"
|
||||
#include "Poco/BinaryWriter.h"
|
||||
#include "Poco/MongoDB/MessageHeader.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/Net/Socket.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API Message
|
||||
/// Base class for all messages send or retrieved from MongoDB server.
|
||||
{
|
||||
public:
|
||||
explicit Message(MessageHeader::OpCode opcode);
|
||||
/// Creates a Message using the given OpCode.
|
||||
|
||||
virtual ~Message();
|
||||
/// Destructor
|
||||
|
||||
MessageHeader & header();
|
||||
/// Returns the message header
|
||||
|
||||
protected:
|
||||
MessageHeader _header;
|
||||
|
||||
void messageLength(Poco::Int32 length);
|
||||
/// Sets the message length in the message header
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline MessageHeader & Message::header()
|
||||
{
|
||||
return _header;
|
||||
}
|
||||
|
||||
|
||||
inline void Message::messageLength(Poco::Int32 length)
|
||||
{
|
||||
poco_assert(length > 0);
|
||||
_header.setMessageLength(length);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_Message_INCLUDED
|
@ -1,140 +0,0 @@
|
||||
//
|
||||
// MessageHeader.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: MessageHeader
|
||||
//
|
||||
// Definition of the MessageHeader class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_MessageHeader_INCLUDED
|
||||
#define MongoDB_MessageHeader_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/MessageHeader.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class Message; // Required to disambiguate friend declaration in MessageHeader.
|
||||
|
||||
|
||||
class MongoDB_API MessageHeader
|
||||
/// Represents the message header which is always prepended to a
|
||||
/// MongoDB request or response message.
|
||||
{
|
||||
public:
|
||||
static const unsigned int MSG_HEADER_SIZE = 16;
|
||||
|
||||
enum OpCode
|
||||
{
|
||||
// Opcodes deprecated in MongoDB 5.0
|
||||
OP_REPLY = 1,
|
||||
OP_UPDATE = 2001,
|
||||
OP_INSERT = 2002,
|
||||
OP_QUERY = 2004,
|
||||
OP_GET_MORE = 2005,
|
||||
OP_DELETE = 2006,
|
||||
OP_KILL_CURSORS = 2007,
|
||||
|
||||
/// Opcodes supported in MongoDB 5.1 and later
|
||||
OP_COMPRESSED = 2012,
|
||||
OP_MSG = 2013
|
||||
};
|
||||
|
||||
explicit MessageHeader(OpCode);
|
||||
/// Creates the MessageHeader using the given OpCode.
|
||||
|
||||
virtual ~MessageHeader();
|
||||
/// Destroys the MessageHeader.
|
||||
|
||||
void read(BinaryReader & reader);
|
||||
/// Reads the header using the given BinaryReader.
|
||||
|
||||
void write(BinaryWriter & writer);
|
||||
/// Writes the header using the given BinaryWriter.
|
||||
|
||||
Int32 getMessageLength() const;
|
||||
/// Returns the message length.
|
||||
|
||||
OpCode opCode() const;
|
||||
/// Returns the OpCode.
|
||||
|
||||
Int32 getRequestID() const;
|
||||
/// Returns the request ID of the current message.
|
||||
|
||||
void setRequestID(Int32 id);
|
||||
/// Sets the request ID of the current message.
|
||||
|
||||
Int32 responseTo() const;
|
||||
/// Returns the request id from the original request.
|
||||
|
||||
private:
|
||||
void setMessageLength(Int32 length);
|
||||
/// Sets the message length.
|
||||
|
||||
Int32 _messageLength;
|
||||
Int32 _requestID;
|
||||
Int32 _responseTo;
|
||||
OpCode _opCode;
|
||||
|
||||
friend class Message;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline MessageHeader::OpCode MessageHeader::opCode() const
|
||||
{
|
||||
return _opCode;
|
||||
}
|
||||
|
||||
|
||||
inline Int32 MessageHeader::getMessageLength() const
|
||||
{
|
||||
return _messageLength;
|
||||
}
|
||||
|
||||
|
||||
inline void MessageHeader::setMessageLength(Int32 length)
|
||||
{
|
||||
poco_assert(_messageLength >= 0);
|
||||
_messageLength = MSG_HEADER_SIZE + length;
|
||||
}
|
||||
|
||||
|
||||
inline void MessageHeader::setRequestID(Int32 id)
|
||||
{
|
||||
_requestID = id;
|
||||
}
|
||||
|
||||
|
||||
inline Int32 MessageHeader::getRequestID() const
|
||||
{
|
||||
return _requestID;
|
||||
}
|
||||
|
||||
inline Int32 MessageHeader::responseTo() const
|
||||
{
|
||||
return _responseTo;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_MessageHeader_INCLUDED
|
@ -1,64 +0,0 @@
|
||||
//
|
||||
// MongoDB.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: MongoDB
|
||||
//
|
||||
// Basic definitions for the Poco MongoDB library.
|
||||
// This file must be the first file included by every other MongoDB
|
||||
// header file.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDBMongoDB_INCLUDED
|
||||
#define MongoDBMongoDB_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
|
||||
|
||||
//
|
||||
// The following block is the standard way of creating macros which make exporting
|
||||
// from a DLL simpler. All files within this DLL are compiled with the MongoDB_EXPORTS
|
||||
// symbol defined on the command line. this symbol should not be defined on any project
|
||||
// that uses this DLL. This way any other project whose source files include this file see
|
||||
// MongoDB_API functions as being imported from a DLL, whereas this DLL sees symbols
|
||||
// defined with this macro as being exported.
|
||||
//
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(POCO_DLL)
|
||||
# if defined(MongoDB_EXPORTS)
|
||||
# define MongoDB_API __declspec(dllexport)
|
||||
# else
|
||||
# define MongoDB_API __declspec(dllimport)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(MongoDB_API)
|
||||
# if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
# define MongoDB_API __attribute__((visibility("default")))
|
||||
# else
|
||||
# define MongoDB_API
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Automatically link MongoDB library.
|
||||
//
|
||||
#if defined(_MSC_VER)
|
||||
# if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(MongoDB_EXPORTS)
|
||||
# pragma comment(lib, "PocoMongoDB" POCO_LIB_SUFFIX)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif // MongoDBMongoDB_INCLUDED
|
@ -1,151 +0,0 @@
|
||||
//
|
||||
// Array.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: ObjectId
|
||||
//
|
||||
// Definition of the ObjectId class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_ObjectId_INCLUDED
|
||||
#define MongoDB_ObjectId_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Element.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API ObjectId
|
||||
/// ObjectId is a 12-byte BSON type, constructed using:
|
||||
///
|
||||
/// - a 4-byte timestamp,
|
||||
/// - a 3-byte machine identifier,
|
||||
/// - a 2-byte process id, and
|
||||
/// - a 3-byte counter, starting with a random value.
|
||||
///
|
||||
/// In MongoDB, documents stored in a collection require a unique _id field that acts
|
||||
/// as a primary key. Because ObjectIds are small, most likely unique, and fast to generate,
|
||||
/// MongoDB uses ObjectIds as the default value for the _id field if the _id field is not
|
||||
/// specified; i.e., the mongod adds the _id field and generates a unique ObjectId to assign
|
||||
/// as its value.
|
||||
{
|
||||
public:
|
||||
using Ptr = SharedPtr<ObjectId>;
|
||||
|
||||
explicit ObjectId(const std::string & id);
|
||||
/// Creates an ObjectId from a string.
|
||||
///
|
||||
/// The string must contain a hexadecimal representation
|
||||
/// of an object ID. This means a string of 24 characters.
|
||||
|
||||
ObjectId(const ObjectId & copy);
|
||||
/// Creates an ObjectId by copying another one.
|
||||
|
||||
virtual ~ObjectId();
|
||||
/// Destroys the ObjectId.
|
||||
|
||||
Timestamp timestamp() const;
|
||||
/// Returns the timestamp which is stored in the first four bytes of the id
|
||||
|
||||
std::string toString(const std::string & fmt = "%02x") const;
|
||||
/// Returns the id in string format. The fmt parameter
|
||||
/// specifies the formatting used for individual members
|
||||
/// of the ID char array.
|
||||
|
||||
private:
|
||||
ObjectId();
|
||||
|
||||
static int fromHex(char c);
|
||||
static char fromHex(const char * c);
|
||||
|
||||
unsigned char _id[12];
|
||||
|
||||
friend class BSONWriter;
|
||||
friend class BSONReader;
|
||||
friend class Document;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline Timestamp ObjectId::timestamp() const
|
||||
{
|
||||
int time;
|
||||
char * T = (char *)&time;
|
||||
T[0] = _id[3];
|
||||
T[1] = _id[2];
|
||||
T[2] = _id[1];
|
||||
T[3] = _id[0];
|
||||
return Timestamp::fromEpochTime((time_t)time);
|
||||
}
|
||||
|
||||
|
||||
inline int ObjectId::fromHex(char c)
|
||||
{
|
||||
if ('0' <= c && c <= '9')
|
||||
return c - '0';
|
||||
if ('a' <= c && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
if ('A' <= c && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
inline char ObjectId::fromHex(const char * c)
|
||||
{
|
||||
return (char)((fromHex(c[0]) << 4) | fromHex(c[1]));
|
||||
}
|
||||
|
||||
|
||||
// BSON Embedded Document
|
||||
// spec: ObjectId
|
||||
template <>
|
||||
struct ElementTraits<ObjectId::Ptr>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x07
|
||||
};
|
||||
|
||||
static std::string toString(const ObjectId::Ptr & id, int indent = 0, const std::string & fmt = "%02x")
|
||||
{
|
||||
return id->toString(fmt);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<ObjectId::Ptr>(ObjectId::Ptr & to)
|
||||
{
|
||||
_reader.readRaw((char *)to->_id, 12);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<ObjectId::Ptr>(ObjectId::Ptr & from)
|
||||
{
|
||||
_writer.writeRaw((char *)from->_id, 12);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_ObjectId_INCLUDED
|
@ -1,96 +0,0 @@
|
||||
//
|
||||
// OpMsgCursor.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: OpMsgCursor
|
||||
//
|
||||
// Definition of the OpMsgCursor class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_OpMsgCursor_INCLUDED
|
||||
#define MongoDB_OpMsgCursor_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Connection.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/MongoDB/OpMsgMessage.h"
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API OpMsgCursor : public Document
|
||||
/// OpMsgCursor is an helper class for querying multiple documents using OpMsgMessage.
|
||||
{
|
||||
public:
|
||||
OpMsgCursor(const std::string & dbname, const std::string & collectionName);
|
||||
/// Creates a OpMsgCursor for the given database and collection.
|
||||
|
||||
virtual ~OpMsgCursor();
|
||||
/// Destroys the OpMsgCursor.
|
||||
|
||||
void setEmptyFirstBatch(bool empty);
|
||||
/// Empty first batch is used to get error response faster with little server processing
|
||||
|
||||
bool emptyFirstBatch() const;
|
||||
|
||||
void setBatchSize(Int32 batchSize);
|
||||
/// Set non-default batch size
|
||||
|
||||
Int32 batchSize() const;
|
||||
/// Current batch size (zero or negative number indicates default batch size)
|
||||
|
||||
Int64 cursorID() const;
|
||||
|
||||
OpMsgMessage & next(Connection & connection);
|
||||
/// Tries to get the next documents. As long as response message has a
|
||||
/// cursor ID next can be called to retrieve the next bunch of documents.
|
||||
///
|
||||
/// The cursor must be killed (see kill()) when not all documents are needed.
|
||||
|
||||
OpMsgMessage & query();
|
||||
/// Returns the associated query.
|
||||
|
||||
void kill(Connection & connection);
|
||||
/// Kills the cursor and reset it so that it can be reused.
|
||||
|
||||
private:
|
||||
OpMsgMessage _query;
|
||||
OpMsgMessage _response;
|
||||
|
||||
bool _emptyFirstBatch{false};
|
||||
Int32 _batchSize{-1};
|
||||
/// Batch size used in the cursor. Zero or negative value means that default shall be used.
|
||||
|
||||
Int64 _cursorID{0};
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline OpMsgMessage & OpMsgCursor::query()
|
||||
{
|
||||
return _query;
|
||||
}
|
||||
|
||||
inline Int64 OpMsgCursor::cursorID() const
|
||||
{
|
||||
return _cursorID;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_OpMsgCursor_INCLUDED
|
@ -1,163 +0,0 @@
|
||||
//
|
||||
// OpMsgMessage.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: OpMsgMessage
|
||||
//
|
||||
// Definition of the OpMsgMessage class.
|
||||
//
|
||||
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_OpMsgMessage_INCLUDED
|
||||
#define MongoDB_OpMsgMessage_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Document.h"
|
||||
#include "Poco/MongoDB/Message.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API OpMsgMessage : public Message
|
||||
/// This class represents a request/response (OP_MSG) to send requests and receive responses to/from MongoDB.
|
||||
{
|
||||
public:
|
||||
// Constants for most often used MongoDB commands that can be sent using OP_MSG
|
||||
// For complete list see: https://www.mongodb.com/docs/manual/reference/command/
|
||||
|
||||
// Query and write
|
||||
static const std::string CMD_INSERT;
|
||||
static const std::string CMD_DELETE;
|
||||
static const std::string CMD_UPDATE;
|
||||
static const std::string CMD_FIND;
|
||||
static const std::string CMD_FIND_AND_MODIFY;
|
||||
static const std::string CMD_GET_MORE;
|
||||
|
||||
// Aggregation
|
||||
static const std::string CMD_AGGREGATE;
|
||||
static const std::string CMD_COUNT;
|
||||
static const std::string CMD_DISTINCT;
|
||||
static const std::string CMD_MAP_REDUCE;
|
||||
|
||||
// Replication and administration
|
||||
static const std::string CMD_HELLO;
|
||||
static const std::string CMD_REPL_SET_GET_STATUS;
|
||||
static const std::string CMD_REPL_SET_GET_CONFIG;
|
||||
|
||||
static const std::string CMD_CREATE;
|
||||
static const std::string CMD_CREATE_INDEXES;
|
||||
static const std::string CMD_DROP;
|
||||
static const std::string CMD_DROP_DATABASE;
|
||||
static const std::string CMD_KILL_CURSORS;
|
||||
static const std::string CMD_LIST_DATABASES;
|
||||
static const std::string CMD_LIST_INDEXES;
|
||||
|
||||
// Diagnostic
|
||||
static const std::string CMD_BUILD_INFO;
|
||||
static const std::string CMD_COLL_STATS;
|
||||
static const std::string CMD_DB_STATS;
|
||||
static const std::string CMD_HOST_INFO;
|
||||
|
||||
|
||||
enum Flags : UInt32
|
||||
{
|
||||
MSG_FLAGS_DEFAULT = 0,
|
||||
|
||||
MSG_CHECKSUM_PRESENT = (1 << 0),
|
||||
|
||||
MSG_MORE_TO_COME = (1 << 1),
|
||||
/// Sender will send another message and is not prepared for overlapping messages
|
||||
|
||||
MSG_EXHAUST_ALLOWED = (1 << 16)
|
||||
/// Client is prepared for multiple replies (using the moreToCome bit) to this request
|
||||
};
|
||||
|
||||
OpMsgMessage();
|
||||
/// Creates an OpMsgMessage for response.
|
||||
|
||||
OpMsgMessage(const std::string & databaseName, const std::string & collectionName, UInt32 flags = MSG_FLAGS_DEFAULT);
|
||||
/// Creates an OpMsgMessage for requests.
|
||||
|
||||
virtual ~OpMsgMessage();
|
||||
|
||||
const std::string & databaseName() const;
|
||||
|
||||
const std::string & collectionName() const;
|
||||
|
||||
void setCommandName(const std::string & command);
|
||||
/// Sets the command name and clears the command document
|
||||
|
||||
void setCursor(Poco::Int64 cursorID, Poco::Int32 batchSize = -1);
|
||||
/// Sets the command "getMore" for the cursor id with batch size (if it is not negative).
|
||||
|
||||
const std::string & commandName() const;
|
||||
/// Current command name.
|
||||
|
||||
void setAcknowledgedRequest(bool ack);
|
||||
/// Set false to create request that does not return response.
|
||||
/// It has effect only for commands that write or delete documents.
|
||||
/// Default is true (request returns acknowledge response).
|
||||
|
||||
bool acknowledgedRequest() const;
|
||||
|
||||
UInt32 flags() const;
|
||||
|
||||
Document & body();
|
||||
/// Access to body document.
|
||||
/// Additional query arguments shall be added after setting the command name.
|
||||
|
||||
const Document & body() const;
|
||||
|
||||
Document::Vector & documents();
|
||||
/// Documents prepared for request or retrieved in response.
|
||||
|
||||
const Document::Vector & documents() const;
|
||||
/// Documents prepared for request or retrieved in response.
|
||||
|
||||
bool responseOk() const;
|
||||
/// Reads "ok" status from the response message.
|
||||
|
||||
void clear();
|
||||
/// Clears the message.
|
||||
|
||||
void send(std::ostream & ostr);
|
||||
/// Writes the request to stream.
|
||||
|
||||
void read(std::istream & istr);
|
||||
/// Reads the response from the stream.
|
||||
|
||||
private:
|
||||
enum PayloadType : UInt8
|
||||
{
|
||||
PAYLOAD_TYPE_0 = 0,
|
||||
PAYLOAD_TYPE_1 = 1
|
||||
};
|
||||
|
||||
std::string _databaseName;
|
||||
std::string _collectionName;
|
||||
UInt32 _flags{MSG_FLAGS_DEFAULT};
|
||||
std::string _commandName;
|
||||
bool _acknowledged{true};
|
||||
|
||||
Document _body;
|
||||
Document::Vector _documents;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_OpMsgMessage_INCLUDED
|
@ -1,123 +0,0 @@
|
||||
//
|
||||
// PoolableConnectionFactory.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: PoolableConnectionFactory
|
||||
//
|
||||
// Definition of the PoolableConnectionFactory class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_PoolableConnectionFactory_INCLUDED
|
||||
#define MongoDB_PoolableConnectionFactory_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Connection.h"
|
||||
#include "Poco/ObjectPool.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
|
||||
|
||||
template <>
|
||||
class PoolableObjectFactory<MongoDB::Connection, MongoDB::Connection::Ptr>
|
||||
/// PoolableObjectFactory specialisation for Connection. New connections
|
||||
/// are created with the given address or URI.
|
||||
///
|
||||
/// If a Connection::SocketFactory is given, it must live for the entire
|
||||
/// lifetime of the PoolableObjectFactory.
|
||||
{
|
||||
public:
|
||||
PoolableObjectFactory(Net::SocketAddress & address) : _address(address), _pSocketFactory(0) { }
|
||||
|
||||
PoolableObjectFactory(const std::string & address) : _address(address), _pSocketFactory(0) { }
|
||||
|
||||
PoolableObjectFactory(const std::string & uri, MongoDB::Connection::SocketFactory & socketFactory)
|
||||
: _uri(uri), _pSocketFactory(&socketFactory)
|
||||
{
|
||||
}
|
||||
|
||||
MongoDB::Connection::Ptr createObject()
|
||||
{
|
||||
if (_pSocketFactory)
|
||||
return new MongoDB::Connection(_uri, *_pSocketFactory);
|
||||
else
|
||||
return new MongoDB::Connection(_address);
|
||||
}
|
||||
|
||||
bool validateObject(MongoDB::Connection::Ptr pObject) { return true; }
|
||||
|
||||
void activateObject(MongoDB::Connection::Ptr pObject) { }
|
||||
|
||||
void deactivateObject(MongoDB::Connection::Ptr pObject) { }
|
||||
|
||||
void destroyObject(MongoDB::Connection::Ptr pObject) { }
|
||||
|
||||
private:
|
||||
Net::SocketAddress _address;
|
||||
std::string _uri;
|
||||
MongoDB::Connection::SocketFactory * _pSocketFactory;
|
||||
};
|
||||
|
||||
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class PooledConnection
|
||||
/// Helper class for borrowing and returning a connection automatically from a pool.
|
||||
{
|
||||
public:
|
||||
PooledConnection(Poco::ObjectPool<Connection, Connection::Ptr> & pool) : _pool(pool) { _connection = _pool.borrowObject(); }
|
||||
|
||||
virtual ~PooledConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_connection)
|
||||
{
|
||||
_pool.returnObject(_connection);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
operator Connection::Ptr() { return _connection; }
|
||||
|
||||
#if defined(POCO_ENABLE_CPP11)
|
||||
// Disable copy to prevent unwanted release of resources: C++11 way
|
||||
PooledConnection(const PooledConnection &) = delete;
|
||||
PooledConnection & operator=(const PooledConnection &) = delete;
|
||||
|
||||
// Enable move semantics
|
||||
PooledConnection(PooledConnection && other) = default;
|
||||
PooledConnection & operator=(PooledConnection &&) = default;
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if !defined(POCO_ENABLE_CPP11)
|
||||
// Disable copy to prevent unwanted release of resources: pre C++11 way
|
||||
PooledConnection(const PooledConnection &);
|
||||
PooledConnection & operator=(const PooledConnection &);
|
||||
#endif
|
||||
|
||||
Poco::ObjectPool<Connection, Connection::Ptr> & _pool;
|
||||
Connection::Ptr _connection;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_PoolableConnectionFactory_INCLUDED
|
@ -1,190 +0,0 @@
|
||||
//
|
||||
// QueryRequest.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: QueryRequest
|
||||
//
|
||||
// Definition of the QueryRequest class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_QueryRequest_INCLUDED
|
||||
#define MongoDB_QueryRequest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Document.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/MongoDB/RequestMessage.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API QueryRequest : public RequestMessage
|
||||
/// A request to query documents in a MongoDB database
|
||||
/// using an OP_QUERY request.
|
||||
{
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
QUERY_DEFAULT = 0,
|
||||
/// Do not set any flags.
|
||||
|
||||
QUERY_TAILABLE_CURSOR = 2,
|
||||
/// Tailable means cursor is not closed when the last data is retrieved.
|
||||
/// Rather, the cursor marks the final object’s position.
|
||||
/// You can resume using the cursor later, from where it was located,
|
||||
/// if more data were received. Like any "latent cursor", the cursor may
|
||||
/// become invalid at some point (CursorNotFound) – for example if the final
|
||||
/// object it references were deleted.
|
||||
|
||||
QUERY_SLAVE_OK = 4,
|
||||
/// Allow query of replica slave. Normally these return an error except
|
||||
/// for namespace "local".
|
||||
|
||||
// QUERY_OPLOG_REPLAY = 8 (internal replication use only - drivers should not implement)
|
||||
|
||||
QUERY_NO_CURSOR_TIMEOUT = 16,
|
||||
/// The server normally times out idle cursors after an inactivity period
|
||||
/// (10 minutes) to prevent excess memory use. Set this option to prevent that.
|
||||
|
||||
QUERY_AWAIT_DATA = 32,
|
||||
/// Use with QUERY_TAILABLECURSOR. If we are at the end of the data, block for
|
||||
/// a while rather than returning no data. After a timeout period, we do
|
||||
/// return as normal.
|
||||
|
||||
QUERY_EXHAUST = 64,
|
||||
/// Stream the data down full blast in multiple "more" packages, on the
|
||||
/// assumption that the client will fully read all data queried.
|
||||
/// Faster when you are pulling a lot of data and know you want to pull
|
||||
/// it all down.
|
||||
/// Note: the client is not allowed to not read all the data unless it
|
||||
/// closes the connection.
|
||||
|
||||
QUERY_PARTIAL = 128
|
||||
/// Get partial results from a mongos if some shards are down
|
||||
/// (instead of throwing an error).
|
||||
};
|
||||
|
||||
QueryRequest(const std::string & collectionName, Flags flags = QUERY_DEFAULT);
|
||||
/// Creates a QueryRequest.
|
||||
///
|
||||
/// The full collection name is the concatenation of the database
|
||||
/// name with the collection name, using a "." for the concatenation. For example,
|
||||
/// for the database "foo" and the collection "bar", the full collection name is
|
||||
/// "foo.bar".
|
||||
|
||||
virtual ~QueryRequest();
|
||||
/// Destroys the QueryRequest.
|
||||
|
||||
Flags getFlags() const;
|
||||
/// Returns the flags.
|
||||
|
||||
void setFlags(Flags flag);
|
||||
/// Set the flags.
|
||||
|
||||
std::string fullCollectionName() const;
|
||||
/// Returns the <db>.<collection> used for this query.
|
||||
|
||||
Int32 getNumberToSkip() const;
|
||||
/// Returns the number of documents to skip.
|
||||
|
||||
void setNumberToSkip(Int32 n);
|
||||
/// Sets the number of documents to skip.
|
||||
|
||||
Int32 getNumberToReturn() const;
|
||||
/// Returns the number of documents to return.
|
||||
|
||||
void setNumberToReturn(Int32 n);
|
||||
/// Sets the number of documents to return (limit).
|
||||
|
||||
Document & selector();
|
||||
/// Returns the selector document.
|
||||
|
||||
Document & returnFieldSelector();
|
||||
/// Returns the field selector document.
|
||||
|
||||
protected:
|
||||
void buildRequest(BinaryWriter & writer);
|
||||
|
||||
private:
|
||||
Flags _flags;
|
||||
std::string _fullCollectionName;
|
||||
Int32 _numberToSkip;
|
||||
Int32 _numberToReturn;
|
||||
Document _selector;
|
||||
Document _returnFieldSelector;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline QueryRequest::Flags QueryRequest::getFlags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
|
||||
inline void QueryRequest::setFlags(QueryRequest::Flags flags)
|
||||
{
|
||||
_flags = flags;
|
||||
}
|
||||
|
||||
|
||||
inline std::string QueryRequest::fullCollectionName() const
|
||||
{
|
||||
return _fullCollectionName;
|
||||
}
|
||||
|
||||
|
||||
inline Document & QueryRequest::selector()
|
||||
{
|
||||
return _selector;
|
||||
}
|
||||
|
||||
|
||||
inline Document & QueryRequest::returnFieldSelector()
|
||||
{
|
||||
return _returnFieldSelector;
|
||||
}
|
||||
|
||||
|
||||
inline Int32 QueryRequest::getNumberToSkip() const
|
||||
{
|
||||
return _numberToSkip;
|
||||
}
|
||||
|
||||
|
||||
inline void QueryRequest::setNumberToSkip(Int32 n)
|
||||
{
|
||||
_numberToSkip = n;
|
||||
}
|
||||
|
||||
|
||||
inline Int32 QueryRequest::getNumberToReturn() const
|
||||
{
|
||||
return _numberToReturn;
|
||||
}
|
||||
|
||||
|
||||
inline void QueryRequest::setNumberToReturn(Int32 n)
|
||||
{
|
||||
_numberToReturn = n;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_QueryRequest_INCLUDED
|
@ -1,135 +0,0 @@
|
||||
//
|
||||
// RegularExpression.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: RegularExpression
|
||||
//
|
||||
// Definition of the RegularExpression class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_RegularExpression_INCLUDED
|
||||
#define MongoDB_RegularExpression_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Element.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/RegularExpression.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API RegularExpression
|
||||
/// Represents a regular expression in BSON format.
|
||||
{
|
||||
public:
|
||||
using Ptr = SharedPtr<RegularExpression>;
|
||||
|
||||
RegularExpression();
|
||||
/// Creates an empty RegularExpression.
|
||||
|
||||
RegularExpression(const std::string & pattern, const std::string & options);
|
||||
/// Creates a RegularExpression using the given pattern and options.
|
||||
|
||||
virtual ~RegularExpression();
|
||||
/// Destroys the RegularExpression.
|
||||
|
||||
SharedPtr<Poco::RegularExpression> createRE() const;
|
||||
/// Tries to create a Poco::RegularExpression from the MongoDB regular expression.
|
||||
|
||||
std::string getOptions() const;
|
||||
/// Returns the options string.
|
||||
|
||||
void setOptions(const std::string & options);
|
||||
/// Sets the options string.
|
||||
|
||||
std::string getPattern() const;
|
||||
/// Returns the pattern.
|
||||
|
||||
void setPattern(const std::string & pattern);
|
||||
/// Sets the pattern.
|
||||
|
||||
private:
|
||||
std::string _pattern;
|
||||
std::string _options;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline std::string RegularExpression::getPattern() const
|
||||
{
|
||||
return _pattern;
|
||||
}
|
||||
|
||||
|
||||
inline void RegularExpression::setPattern(const std::string & pattern)
|
||||
{
|
||||
_pattern = pattern;
|
||||
}
|
||||
|
||||
|
||||
inline std::string RegularExpression::getOptions() const
|
||||
{
|
||||
return _options;
|
||||
}
|
||||
|
||||
|
||||
inline void RegularExpression::setOptions(const std::string & options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
|
||||
// BSON Regex
|
||||
// spec: cstring cstring
|
||||
template <>
|
||||
struct ElementTraits<RegularExpression::Ptr>
|
||||
{
|
||||
enum
|
||||
{
|
||||
TypeId = 0x0B
|
||||
};
|
||||
|
||||
static std::string toString(const RegularExpression::Ptr & value, int indent = 0)
|
||||
{
|
||||
//TODO
|
||||
return "RE: not implemented yet";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONReader::read<RegularExpression::Ptr>(RegularExpression::Ptr & to)
|
||||
{
|
||||
std::string pattern = readCString();
|
||||
std::string options = readCString();
|
||||
|
||||
to = new RegularExpression(pattern, options);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline void BSONWriter::write<RegularExpression::Ptr>(RegularExpression::Ptr & from)
|
||||
{
|
||||
writeCString(from->getPattern());
|
||||
writeCString(from->getOptions());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_RegularExpression_INCLUDED
|
@ -1,61 +0,0 @@
|
||||
//
|
||||
// ReplicaSet.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: ReplicaSet
|
||||
//
|
||||
// Definition of the ReplicaSet class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_ReplicaSet_INCLUDED
|
||||
#define MongoDB_ReplicaSet_INCLUDED
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include "Poco/MongoDB/Connection.h"
|
||||
#include "Poco/Net/SocketAddress.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API ReplicaSet
|
||||
/// Class for working with a MongoDB replica set.
|
||||
{
|
||||
public:
|
||||
explicit ReplicaSet(const std::vector<Net::SocketAddress> & addresses);
|
||||
/// Creates the ReplicaSet using the given server addresses.
|
||||
|
||||
virtual ~ReplicaSet();
|
||||
/// Destroys the ReplicaSet.
|
||||
|
||||
Connection::Ptr findMaster();
|
||||
/// Tries to find the master MongoDB instance from the addresses
|
||||
/// passed to the constructor.
|
||||
///
|
||||
/// Returns the Connection to the master, or null if no master
|
||||
/// instance was found.
|
||||
|
||||
protected:
|
||||
Connection::Ptr isMaster(const Net::SocketAddress & host);
|
||||
|
||||
private:
|
||||
std::vector<Net::SocketAddress> _addresses;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_ReplicaSet_INCLUDED
|
@ -1,54 +0,0 @@
|
||||
//
|
||||
// RequestMessage.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: RequestMessage
|
||||
//
|
||||
// Definition of the RequestMessage class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_RequestMessage_INCLUDED
|
||||
#define MongoDB_RequestMessage_INCLUDED
|
||||
|
||||
|
||||
#include <ostream>
|
||||
#include "Poco/MongoDB/Message.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API RequestMessage : public Message
|
||||
/// Base class for a request sent to the MongoDB server.
|
||||
{
|
||||
public:
|
||||
explicit RequestMessage(MessageHeader::OpCode opcode);
|
||||
/// Creates a RequestMessage using the given opcode.
|
||||
|
||||
virtual ~RequestMessage();
|
||||
/// Destroys the RequestMessage.
|
||||
|
||||
void send(std::ostream & ostr);
|
||||
/// Writes the request to stream.
|
||||
|
||||
protected:
|
||||
virtual void buildRequest(BinaryWriter & ss) = 0;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_RequestMessage_INCLUDED
|
@ -1,114 +0,0 @@
|
||||
//
|
||||
// ResponseMessage.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: ResponseMessage
|
||||
//
|
||||
// Definition of the ResponseMessage class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_ResponseMessage_INCLUDED
|
||||
#define MongoDB_ResponseMessage_INCLUDED
|
||||
|
||||
|
||||
#include <cstdlib>
|
||||
#include <istream>
|
||||
#include "Poco/MongoDB/Document.h"
|
||||
#include "Poco/MongoDB/Message.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class MongoDB_API ResponseMessage : public Message
|
||||
/// This class represents a response (OP_REPLY) from MongoDB.
|
||||
{
|
||||
public:
|
||||
ResponseMessage();
|
||||
/// Creates an empty ResponseMessage.
|
||||
|
||||
ResponseMessage(const Int64 & cursorID);
|
||||
/// Creates an ResponseMessage for existing cursor ID.
|
||||
|
||||
virtual ~ResponseMessage();
|
||||
/// Destroys the ResponseMessage.
|
||||
|
||||
Int64 cursorID() const;
|
||||
/// Returns the cursor ID.
|
||||
|
||||
void clear();
|
||||
/// Clears the response.
|
||||
|
||||
std::size_t count() const;
|
||||
/// Returns the number of documents in the response.
|
||||
|
||||
Document::Vector & documents();
|
||||
/// Returns a vector containing the received documents.
|
||||
|
||||
bool empty() const;
|
||||
/// Returns true if the response does not contain any documents.
|
||||
|
||||
bool hasDocuments() const;
|
||||
/// Returns true if there is at least one document in the response.
|
||||
|
||||
void read(std::istream & istr);
|
||||
/// Reads the response from the stream.
|
||||
|
||||
private:
|
||||
Int32 _responseFlags;
|
||||
Int64 _cursorID;
|
||||
Int32 _startingFrom;
|
||||
Int32 _numberReturned;
|
||||
Document::Vector _documents;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline std::size_t ResponseMessage::count() const
|
||||
{
|
||||
return _documents.size();
|
||||
}
|
||||
|
||||
|
||||
inline bool ResponseMessage::empty() const
|
||||
{
|
||||
return _documents.size() == 0;
|
||||
}
|
||||
|
||||
|
||||
inline Int64 ResponseMessage::cursorID() const
|
||||
{
|
||||
return _cursorID;
|
||||
}
|
||||
|
||||
|
||||
inline Document::Vector & ResponseMessage::documents()
|
||||
{
|
||||
return _documents;
|
||||
}
|
||||
|
||||
|
||||
inline bool ResponseMessage::hasDocuments() const
|
||||
{
|
||||
return _documents.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_ResponseMessage_INCLUDED
|
@ -1,117 +0,0 @@
|
||||
//
|
||||
// UpdateRequest.h
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: UpdateRequest
|
||||
//
|
||||
// Definition of the UpdateRequest class.
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef MongoDB_UpdateRequest_INCLUDED
|
||||
#define MongoDB_UpdateRequest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Document.h"
|
||||
#include "Poco/MongoDB/MongoDB.h"
|
||||
#include "Poco/MongoDB/RequestMessage.h"
|
||||
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
namespace MongoDB
|
||||
{
|
||||
|
||||
|
||||
class UpdateRequest : public RequestMessage
|
||||
/// This request is used to update a document in a database
|
||||
/// using the OP_UPDATE client request.
|
||||
{
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
UPDATE_DEFAULT = 0,
|
||||
/// If set, the database will insert the supplied object into the
|
||||
/// collection if no matching document is found.
|
||||
|
||||
UPDATE_UPSERT = 1,
|
||||
/// If set, the database will update all matching objects in the collection.
|
||||
/// Otherwise only updates first matching doc.
|
||||
|
||||
UPDATE_MULTIUPDATE = 2
|
||||
/// If set to, updates multiple documents that meet the query criteria.
|
||||
/// Otherwise only updates one document.
|
||||
};
|
||||
|
||||
UpdateRequest(const std::string & collectionName, Flags flags = UPDATE_DEFAULT);
|
||||
/// Creates the UpdateRequest.
|
||||
///
|
||||
/// The full collection name is the concatenation of the database
|
||||
/// name with the collection name, using a "." for the concatenation. For example,
|
||||
/// for the database "foo" and the collection "bar", the full collection name is
|
||||
/// "foo.bar".
|
||||
|
||||
virtual ~UpdateRequest();
|
||||
/// Destroys the UpdateRequest.
|
||||
|
||||
Document & selector();
|
||||
/// Returns the selector document.
|
||||
|
||||
Document & update();
|
||||
/// Returns the document to update.
|
||||
|
||||
Flags flags() const;
|
||||
/// Returns the flags
|
||||
|
||||
void flags(Flags flags);
|
||||
/// Sets the flags
|
||||
|
||||
protected:
|
||||
void buildRequest(BinaryWriter & writer);
|
||||
|
||||
private:
|
||||
Flags _flags;
|
||||
std::string _fullCollectionName;
|
||||
Document _selector;
|
||||
Document _update;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline UpdateRequest::Flags UpdateRequest::flags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
|
||||
inline void UpdateRequest::flags(UpdateRequest::Flags flags)
|
||||
{
|
||||
_flags = flags;
|
||||
}
|
||||
|
||||
|
||||
inline Document & UpdateRequest::selector()
|
||||
{
|
||||
return _selector;
|
||||
}
|
||||
|
||||
|
||||
inline Document & UpdateRequest::update()
|
||||
{
|
||||
return _update;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // namespace Poco::MongoDB
|
||||
|
||||
|
||||
#endif // MongoDB_UpdateRequest_INCLUDED
|
@ -1,75 +0,0 @@
|
||||
//
|
||||
// Array.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Array
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Array.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
Array::Array():
|
||||
Document()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Array::~Array()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Element::Ptr Array::get(std::size_t pos) const
|
||||
{
|
||||
std::string name = Poco::NumberFormatter::format(pos);
|
||||
return Document::get(name);
|
||||
}
|
||||
|
||||
|
||||
std::string Array::toString(int indent) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << "[";
|
||||
|
||||
if (indent > 0) oss << std::endl;
|
||||
|
||||
for (ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it)
|
||||
{
|
||||
if (it != _elements.begin())
|
||||
{
|
||||
oss << ",";
|
||||
if (indent > 0) oss << std::endl;
|
||||
}
|
||||
|
||||
for (int i = 0; i < indent; ++i) oss << ' ';
|
||||
|
||||
oss << (*it)->toString(indent > 0 ? indent + 2 : 0);
|
||||
}
|
||||
|
||||
if (indent > 0)
|
||||
{
|
||||
oss << std::endl;
|
||||
if (indent >= 2) indent -= 2;
|
||||
for (int i = 0; i < indent; ++i) oss << ' ';
|
||||
}
|
||||
|
||||
oss << "]";
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
} } // Namespace Poco::Mongo
|
@ -1,89 +0,0 @@
|
||||
//
|
||||
// Binary.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Binary
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Binary.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
Binary::Binary():
|
||||
_buffer(0),
|
||||
_subtype(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Binary::Binary(Poco::Int32 size, unsigned char subtype):
|
||||
_buffer(size),
|
||||
_subtype(subtype)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Binary::Binary(const UUID& uuid):
|
||||
_buffer(128 / 8),
|
||||
_subtype(0x04)
|
||||
{
|
||||
unsigned char szUUID[16];
|
||||
uuid.copyTo((char*) szUUID);
|
||||
_buffer.assign(szUUID, 16);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Binary::Binary(const std::string& data, unsigned char subtype):
|
||||
_buffer(reinterpret_cast<const unsigned char*>(data.data()), data.size()),
|
||||
_subtype(subtype)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Binary::Binary(const void* data, Poco::Int32 size, unsigned char subtype):
|
||||
_buffer(reinterpret_cast<const unsigned char*>(data), size),
|
||||
_subtype(subtype)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Binary::~Binary()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::string Binary::toString(int indent) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
Base64Encoder encoder(oss);
|
||||
MemoryInputStream mis((const char*) _buffer.begin(), _buffer.size());
|
||||
StreamCopier::copyStream(mis, encoder);
|
||||
encoder.close();
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
UUID Binary::uuid() const
|
||||
{
|
||||
if ((_subtype == 0x04 || _subtype == 0x03) && _buffer.size() == 16)
|
||||
{
|
||||
UUID uuid;
|
||||
uuid.copyFrom((const char*) _buffer.begin());
|
||||
return uuid;
|
||||
}
|
||||
throw BadCastException("Invalid subtype: " + std::to_string(_subtype) + ", size: " + std::to_string(_buffer.size()));
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,348 +0,0 @@
|
||||
//
|
||||
// Connection.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Connection
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Net/SocketStream.h"
|
||||
#include "Poco/MongoDB/Connection.h"
|
||||
#include "Poco/MongoDB/Database.h"
|
||||
#include "Poco/URI.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/NumberParser.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
Connection::SocketFactory::SocketFactory()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Connection::SocketFactory::~SocketFactory()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Poco::Net::StreamSocket Connection::SocketFactory::createSocket(const std::string& host, int port, Poco::Timespan connectTimeout, bool secure)
|
||||
{
|
||||
if (!secure)
|
||||
{
|
||||
Poco::Net::SocketAddress addr(host, port);
|
||||
Poco::Net::StreamSocket socket;
|
||||
if (connectTimeout > 0)
|
||||
socket.connect(addr, connectTimeout);
|
||||
else
|
||||
socket.connect(addr);
|
||||
return socket;
|
||||
}
|
||||
else throw Poco::NotImplementedException("Default SocketFactory implementation does not support SecureStreamSocket");
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection():
|
||||
_address(),
|
||||
_socket()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection(const std::string& hostAndPort):
|
||||
_address(hostAndPort),
|
||||
_socket()
|
||||
{
|
||||
connect();
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection(const std::string& uri, SocketFactory& socketFactory):
|
||||
_address(),
|
||||
_socket()
|
||||
{
|
||||
connect(uri, socketFactory);
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection(const std::string& host, int port):
|
||||
_address(host, port),
|
||||
_socket()
|
||||
{
|
||||
connect();
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection(const Poco::Net::SocketAddress& addrs):
|
||||
_address(addrs),
|
||||
_socket()
|
||||
{
|
||||
connect();
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection(const Poco::Net::StreamSocket& socket):
|
||||
_address(socket.peerAddress()),
|
||||
_socket(socket)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Connection::~Connection()
|
||||
{
|
||||
try
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Connection::connect()
|
||||
{
|
||||
_socket.connect(_address);
|
||||
}
|
||||
|
||||
|
||||
void Connection::connect(const std::string& hostAndPort)
|
||||
{
|
||||
_address = Poco::Net::SocketAddress(hostAndPort);
|
||||
connect();
|
||||
}
|
||||
|
||||
|
||||
void Connection::connect(const std::string& host, int port)
|
||||
{
|
||||
_address = Poco::Net::SocketAddress(host, port);
|
||||
connect();
|
||||
}
|
||||
|
||||
|
||||
void Connection::connect(const Poco::Net::SocketAddress& addrs)
|
||||
{
|
||||
_address = addrs;
|
||||
connect();
|
||||
}
|
||||
|
||||
|
||||
void Connection::connect(const Poco::Net::StreamSocket& socket)
|
||||
{
|
||||
_address = socket.peerAddress();
|
||||
_socket = socket;
|
||||
}
|
||||
|
||||
|
||||
void Connection::connect(const std::string& uri, SocketFactory& socketFactory)
|
||||
{
|
||||
std::vector<std::string> strAddresses;
|
||||
std::string newURI;
|
||||
|
||||
if (uri.find(',') != std::string::npos)
|
||||
{
|
||||
size_t pos;
|
||||
size_t head = 0;
|
||||
if ((pos = uri.find("@")) != std::string::npos)
|
||||
{
|
||||
head = pos + 1;
|
||||
}
|
||||
else if ((pos = uri.find("://")) != std::string::npos)
|
||||
{
|
||||
head = pos + 3;
|
||||
}
|
||||
|
||||
std::string tempstr;
|
||||
std::string::const_iterator it = uri.begin();
|
||||
it += head;
|
||||
size_t tail = head;
|
||||
for (;it != uri.end() && *it != '?' && *it != '/'; ++it)
|
||||
{
|
||||
tempstr += *it;
|
||||
tail++;
|
||||
}
|
||||
|
||||
it = tempstr.begin();
|
||||
std::string token;
|
||||
for (;it != tempstr.end(); ++it)
|
||||
{
|
||||
if (*it == ',')
|
||||
{
|
||||
newURI = uri.substr(0, head) + token + uri.substr(tail, uri.length());
|
||||
strAddresses.push_back(newURI);
|
||||
token = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
token += *it;
|
||||
}
|
||||
}
|
||||
newURI = uri.substr(0, head) + token + uri.substr(tail, uri.length());
|
||||
strAddresses.push_back(newURI);
|
||||
}
|
||||
else
|
||||
{
|
||||
strAddresses.push_back(uri);
|
||||
}
|
||||
|
||||
newURI = strAddresses.front();
|
||||
Poco::URI theURI(newURI);
|
||||
if (theURI.getScheme() != "mongodb") throw Poco::UnknownURISchemeException(uri);
|
||||
|
||||
std::string userInfo = theURI.getUserInfo();
|
||||
std::string databaseName = theURI.getPath();
|
||||
if (!databaseName.empty() && databaseName[0] == '/') databaseName.erase(0, 1);
|
||||
if (databaseName.empty()) databaseName = "admin";
|
||||
|
||||
bool ssl = false;
|
||||
Poco::Timespan connectTimeout;
|
||||
Poco::Timespan socketTimeout;
|
||||
std::string authMechanism = Database::AUTH_SCRAM_SHA1;
|
||||
std::string readPreference="primary";
|
||||
|
||||
Poco::URI::QueryParameters params = theURI.getQueryParameters();
|
||||
for (Poco::URI::QueryParameters::const_iterator it = params.begin(); it != params.end(); ++it)
|
||||
{
|
||||
if (it->first == "ssl")
|
||||
{
|
||||
ssl = (it->second == "true");
|
||||
}
|
||||
else if (it->first == "connectTimeoutMS")
|
||||
{
|
||||
connectTimeout = static_cast<Poco::Timespan::TimeDiff>(1000)*Poco::NumberParser::parse(it->second);
|
||||
}
|
||||
else if (it->first == "socketTimeoutMS")
|
||||
{
|
||||
socketTimeout = static_cast<Poco::Timespan::TimeDiff>(1000)*Poco::NumberParser::parse(it->second);
|
||||
}
|
||||
else if (it->first == "authMechanism")
|
||||
{
|
||||
authMechanism = it->second;
|
||||
}
|
||||
else if (it->first == "readPreference")
|
||||
{
|
||||
readPreference= it->second;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = strAddresses.cbegin();it != strAddresses.cend(); ++it)
|
||||
{
|
||||
newURI = *it;
|
||||
theURI = Poco::URI(newURI);
|
||||
|
||||
std::string host = theURI.getHost();
|
||||
Poco::UInt16 port = theURI.getPort();
|
||||
if (port == 0) port = 27017;
|
||||
|
||||
connect(socketFactory.createSocket(host, port, connectTimeout, ssl));
|
||||
_uri = newURI;
|
||||
if (socketTimeout > 0)
|
||||
{
|
||||
_socket.setSendTimeout(socketTimeout);
|
||||
_socket.setReceiveTimeout(socketTimeout);
|
||||
}
|
||||
if (strAddresses.size() > 1)
|
||||
{
|
||||
Poco::MongoDB::QueryRequest request("admin.$cmd");
|
||||
request.setNumberToReturn(1);
|
||||
request.selector().add("isMaster", 1);
|
||||
Poco::MongoDB::ResponseMessage response;
|
||||
|
||||
sendRequest(request, response);
|
||||
_uri = newURI;
|
||||
if (!response.documents().empty())
|
||||
{
|
||||
Poco::MongoDB::Document::Ptr doc = response.documents()[0];
|
||||
if (doc->get<bool>("ismaster") && readPreference == "primary")
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (!doc->get<bool>("ismaster") && readPreference == "secondary")
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (it + 1 == strAddresses.cend())
|
||||
{
|
||||
throw Poco::URISyntaxException(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!userInfo.empty())
|
||||
{
|
||||
std::string username;
|
||||
std::string password;
|
||||
std::string::size_type pos = userInfo.find(':');
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
username.assign(userInfo, 0, pos++);
|
||||
password.assign(userInfo, pos, userInfo.size() - pos);
|
||||
}
|
||||
else username = userInfo;
|
||||
|
||||
Database database(databaseName);
|
||||
|
||||
if (!database.authenticate(*this, username, password, authMechanism))
|
||||
throw Poco::NoPermissionException(Poco::format("Access to MongoDB database %s denied for user %s", databaseName, username));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Connection::disconnect()
|
||||
{
|
||||
_socket.close();
|
||||
}
|
||||
|
||||
|
||||
void Connection::sendRequest(RequestMessage& request)
|
||||
{
|
||||
Poco::Net::SocketOutputStream sos(_socket);
|
||||
request.send(sos);
|
||||
}
|
||||
|
||||
|
||||
void Connection::sendRequest(RequestMessage& request, ResponseMessage& response)
|
||||
{
|
||||
sendRequest(request);
|
||||
|
||||
Poco::Net::SocketInputStream sis(_socket);
|
||||
response.read(sis);
|
||||
}
|
||||
|
||||
|
||||
void Connection::sendRequest(OpMsgMessage& request, OpMsgMessage& response)
|
||||
{
|
||||
Poco::Net::SocketOutputStream sos(_socket);
|
||||
request.send(sos);
|
||||
|
||||
response.clear();
|
||||
readResponse(response);
|
||||
}
|
||||
|
||||
|
||||
void Connection::sendRequest(OpMsgMessage& request)
|
||||
{
|
||||
request.setAcknowledgedRequest(false);
|
||||
Poco::Net::SocketOutputStream sos(_socket);
|
||||
request.send(sos);
|
||||
}
|
||||
|
||||
|
||||
void Connection::readResponse(OpMsgMessage& response)
|
||||
{
|
||||
Poco::Net::SocketInputStream sis(_socket);
|
||||
response.read(sis);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} } // Poco::MongoDB
|
@ -1,83 +0,0 @@
|
||||
//
|
||||
// Cursor.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Cursor
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Cursor.h"
|
||||
#include "Poco/MongoDB/GetMoreRequest.h"
|
||||
#include "Poco/MongoDB/KillCursorsRequest.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
Cursor::Cursor(const std::string& db, const std::string& collection, QueryRequest::Flags flags):
|
||||
_query(db + '.' + collection, flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Cursor::Cursor(const std::string& fullCollectionName, QueryRequest::Flags flags):
|
||||
_query(fullCollectionName, flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Cursor::Cursor(const Document& aggregationResponse) :
|
||||
_query(aggregationResponse.get<Poco::MongoDB::Document::Ptr>("cursor")->get<std::string>("ns")),
|
||||
_response(aggregationResponse.get<Poco::MongoDB::Document::Ptr>("cursor")->get<Int64>("id"))
|
||||
{
|
||||
}
|
||||
|
||||
Cursor::~Cursor()
|
||||
{
|
||||
try
|
||||
{
|
||||
poco_assert_dbg(!_response.cursorID());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ResponseMessage& Cursor::next(Connection& connection)
|
||||
{
|
||||
if (_response.cursorID() == 0)
|
||||
{
|
||||
connection.sendRequest(_query, _response);
|
||||
}
|
||||
else
|
||||
{
|
||||
Poco::MongoDB::GetMoreRequest getMore(_query.fullCollectionName(), _response.cursorID());
|
||||
getMore.setNumberToReturn(_query.getNumberToReturn());
|
||||
_response.clear();
|
||||
connection.sendRequest(getMore, _response);
|
||||
}
|
||||
return _response;
|
||||
}
|
||||
|
||||
|
||||
void Cursor::kill(Connection& connection)
|
||||
{
|
||||
if (_response.cursorID() != 0)
|
||||
{
|
||||
KillCursorsRequest killRequest;
|
||||
killRequest.cursors().push_back(_response.cursorID());
|
||||
connection.sendRequest(killRequest);
|
||||
}
|
||||
_response.clear();
|
||||
}
|
||||
|
||||
|
||||
} } // Namespace Poco::MongoDB
|
@ -1,482 +0,0 @@
|
||||
//
|
||||
// Database.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Database
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Database.h"
|
||||
#include "Poco/MongoDB/Binary.h"
|
||||
#include "Poco/MD5Engine.h"
|
||||
#include "Poco/SHA1Engine.h"
|
||||
#include "Poco/PBKDF2Engine.h"
|
||||
#include "Poco/HMACEngine.h"
|
||||
#include "Poco/Base64Decoder.h"
|
||||
#include "Poco/MemoryStream.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/RandomStream.h"
|
||||
#include "Poco/Random.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/NumberParser.h"
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
const std::string Database::AUTH_MONGODB_CR("MONGODB-CR");
|
||||
const std::string Database::AUTH_SCRAM_SHA1("SCRAM-SHA-1");
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
std::map<std::string, std::string> parseKeyValueList(const std::string& str)
|
||||
{
|
||||
std::map<std::string, std::string> kvm;
|
||||
std::string::const_iterator it = str.begin();
|
||||
std::string::const_iterator end = str.end();
|
||||
while (it != end)
|
||||
{
|
||||
std::string k;
|
||||
std::string v;
|
||||
while (it != end && *it != '=') k += *it++;
|
||||
if (it != end) ++it;
|
||||
while (it != end && *it != ',') v += *it++;
|
||||
if (it != end) ++it;
|
||||
kvm[k] = v;
|
||||
}
|
||||
return kvm;
|
||||
}
|
||||
|
||||
std::string decodeBase64(const std::string& base64)
|
||||
{
|
||||
Poco::MemoryInputStream istr(base64.data(), base64.size());
|
||||
Poco::Base64Decoder decoder(istr);
|
||||
std::string result;
|
||||
Poco::StreamCopier::copyToString(decoder, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string encodeBase64(const std::string& data)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
Poco::Base64Encoder encoder(ostr);
|
||||
encoder.rdbuf()->setLineLength(0);
|
||||
encoder << data;
|
||||
encoder.close();
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
std::string digestToBinaryString(Poco::DigestEngine& engine)
|
||||
{
|
||||
Poco::DigestEngine::Digest d = engine.digest();
|
||||
return std::string(reinterpret_cast<const char*>(&d[0]), d.size());
|
||||
}
|
||||
|
||||
std::string digestToHexString(Poco::DigestEngine& engine)
|
||||
{
|
||||
Poco::DigestEngine::Digest d = engine.digest();
|
||||
return Poco::DigestEngine::digestToHex(d);
|
||||
}
|
||||
|
||||
std::string digestToBase64(Poco::DigestEngine& engine)
|
||||
{
|
||||
return encodeBase64(digestToBinaryString(engine));
|
||||
}
|
||||
|
||||
std::string hashCredentials(const std::string& username, const std::string& password)
|
||||
{
|
||||
Poco::MD5Engine md5;
|
||||
md5.update(username);
|
||||
md5.update(std::string(":mongo:"));
|
||||
md5.update(password);
|
||||
return digestToHexString(md5);
|
||||
}
|
||||
|
||||
std::string createNonce()
|
||||
{
|
||||
Poco::MD5Engine md5;
|
||||
Poco::RandomInputStream randomStream;
|
||||
Poco::Random random;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
md5.update(randomStream.get());
|
||||
md5.update(random.nextChar());
|
||||
}
|
||||
return digestToHexString(md5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Database::Database(const std::string& db):
|
||||
_dbname(db)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Database::~Database()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool Database::authenticate(Connection& connection, const std::string& username, const std::string& password, const std::string& method)
|
||||
{
|
||||
if (username.empty()) throw Poco::InvalidArgumentException("empty username");
|
||||
if (password.empty()) throw Poco::InvalidArgumentException("empty password");
|
||||
|
||||
if (method == AUTH_MONGODB_CR)
|
||||
return authCR(connection, username, password);
|
||||
else if (method == AUTH_SCRAM_SHA1)
|
||||
return authSCRAM(connection, username, password);
|
||||
else
|
||||
throw Poco::InvalidArgumentException("authentication method", method);
|
||||
}
|
||||
|
||||
|
||||
bool Database::authCR(Connection& connection, const std::string& username, const std::string& password)
|
||||
{
|
||||
std::string nonce;
|
||||
Poco::SharedPtr<QueryRequest> pCommand = createCommand();
|
||||
pCommand->selector().add<Poco::Int32>("getnonce", 1);
|
||||
|
||||
ResponseMessage response;
|
||||
connection.sendRequest(*pCommand, response);
|
||||
if (response.documents().size() > 0)
|
||||
{
|
||||
Document::Ptr pDoc = response.documents()[0];
|
||||
if (pDoc->getInteger("ok") != 1) return false;
|
||||
nonce = pDoc->get<std::string>("nonce", "");
|
||||
if (nonce.empty()) throw Poco::ProtocolException("no nonce received");
|
||||
}
|
||||
else throw Poco::ProtocolException("empty response for getnonce");
|
||||
|
||||
std::string credsDigest = hashCredentials(username, password);
|
||||
|
||||
Poco::MD5Engine md5;
|
||||
md5.update(nonce);
|
||||
md5.update(username);
|
||||
md5.update(credsDigest);
|
||||
std::string key = digestToHexString(md5);
|
||||
|
||||
pCommand = createCommand();
|
||||
pCommand->selector()
|
||||
.add<Poco::Int32>("authenticate", 1)
|
||||
.add<std::string>("user", username)
|
||||
.add<std::string>("nonce", nonce)
|
||||
.add<std::string>("key", key);
|
||||
|
||||
connection.sendRequest(*pCommand, response);
|
||||
if (response.documents().size() > 0)
|
||||
{
|
||||
Document::Ptr pDoc = response.documents()[0];
|
||||
return pDoc->getInteger("ok") == 1;
|
||||
}
|
||||
else throw Poco::ProtocolException("empty response for authenticate");
|
||||
}
|
||||
|
||||
|
||||
bool Database::authSCRAM(Connection& connection, const std::string& username, const std::string& password)
|
||||
{
|
||||
std::string clientNonce(createNonce());
|
||||
std::string clientFirstMsg = Poco::format("n=%s,r=%s", username, clientNonce);
|
||||
|
||||
Poco::SharedPtr<QueryRequest> pCommand = createCommand();
|
||||
pCommand->selector()
|
||||
.add<Poco::Int32>("saslStart", 1)
|
||||
.add<std::string>("mechanism", AUTH_SCRAM_SHA1)
|
||||
.add<Binary::Ptr>("payload", new Binary(Poco::format("n,,%s", clientFirstMsg)));
|
||||
|
||||
ResponseMessage response;
|
||||
connection.sendRequest(*pCommand, response);
|
||||
|
||||
Int32 conversationId = 0;
|
||||
std::string serverFirstMsg;
|
||||
|
||||
if (response.documents().size() > 0)
|
||||
{
|
||||
Document::Ptr pDoc = response.documents()[0];
|
||||
if (pDoc->getInteger("ok") == 1)
|
||||
{
|
||||
Binary::Ptr pPayload = pDoc->get<Binary::Ptr>("payload");
|
||||
serverFirstMsg = pPayload->toRawString();
|
||||
conversationId = pDoc->get<Int32>("conversationId");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pDoc->exists("errmsg"))
|
||||
{
|
||||
const Poco::MongoDB::Element::Ptr value = pDoc->get("errmsg");
|
||||
auto message = static_cast<const Poco::MongoDB::ConcreteElement<std::string> &>(*value).value();
|
||||
throw Poco::RuntimeException(message);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else throw Poco::ProtocolException("empty response for saslStart");
|
||||
|
||||
std::map<std::string, std::string> kvm = parseKeyValueList(serverFirstMsg);
|
||||
const std::string serverNonce = kvm["r"];
|
||||
const std::string salt = decodeBase64(kvm["s"]);
|
||||
const unsigned iterations = Poco::NumberParser::parseUnsigned(kvm["i"]);
|
||||
const Poco::UInt32 dkLen = 20;
|
||||
|
||||
std::string hashedPassword = hashCredentials(username, password);
|
||||
|
||||
Poco::PBKDF2Engine<Poco::HMACEngine<Poco::SHA1Engine> > pbkdf2(salt, iterations, dkLen);
|
||||
pbkdf2.update(hashedPassword);
|
||||
std::string saltedPassword = digestToBinaryString(pbkdf2);
|
||||
|
||||
std::string clientFinalNoProof = Poco::format("c=biws,r=%s", serverNonce);
|
||||
std::string authMessage = Poco::format("%s,%s,%s", clientFirstMsg, serverFirstMsg, clientFinalNoProof);
|
||||
|
||||
Poco::HMACEngine<Poco::SHA1Engine> hmacKey(saltedPassword);
|
||||
hmacKey.update(std::string("Client Key"));
|
||||
std::string clientKey = digestToBinaryString(hmacKey);
|
||||
|
||||
Poco::SHA1Engine sha1;
|
||||
sha1.update(clientKey);
|
||||
std::string storedKey = digestToBinaryString(sha1);
|
||||
|
||||
Poco::HMACEngine<Poco::SHA1Engine> hmacSig(storedKey);
|
||||
hmacSig.update(authMessage);
|
||||
std::string clientSignature = digestToBinaryString(hmacSig);
|
||||
|
||||
std::string clientProof(clientKey);
|
||||
for (std::size_t i = 0; i < clientProof.size(); i++)
|
||||
{
|
||||
clientProof[i] ^= clientSignature[i];
|
||||
}
|
||||
|
||||
std::string clientFinal = Poco::format("%s,p=%s", clientFinalNoProof, encodeBase64(clientProof));
|
||||
|
||||
pCommand = createCommand();
|
||||
pCommand->selector()
|
||||
.add<Poco::Int32>("saslContinue", 1)
|
||||
.add<Poco::Int32>("conversationId", conversationId)
|
||||
.add<Binary::Ptr>("payload", new Binary(clientFinal));
|
||||
|
||||
std::string serverSecondMsg;
|
||||
connection.sendRequest(*pCommand, response);
|
||||
if (response.documents().size() > 0)
|
||||
{
|
||||
Document::Ptr pDoc = response.documents()[0];
|
||||
if (pDoc->getInteger("ok") == 1)
|
||||
{
|
||||
Binary::Ptr pPayload = pDoc->get<Binary::Ptr>("payload");
|
||||
serverSecondMsg = pPayload->toRawString();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pDoc->exists("errmsg"))
|
||||
{
|
||||
const Poco::MongoDB::Element::Ptr value = pDoc->get("errmsg");
|
||||
auto message = static_cast<const Poco::MongoDB::ConcreteElement<std::string> &>(*value).value();
|
||||
throw Poco::RuntimeException(message);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else throw Poco::ProtocolException("empty response for saslContinue");
|
||||
|
||||
Poco::HMACEngine<Poco::SHA1Engine> hmacSKey(saltedPassword);
|
||||
hmacSKey.update(std::string("Server Key"));
|
||||
std::string serverKey = digestToBinaryString(hmacSKey);
|
||||
|
||||
Poco::HMACEngine<Poco::SHA1Engine> hmacSSig(serverKey);
|
||||
hmacSSig.update(authMessage);
|
||||
std::string serverSignature = digestToBase64(hmacSSig);
|
||||
|
||||
kvm = parseKeyValueList(serverSecondMsg);
|
||||
std::string serverSignatureReceived = kvm["v"];
|
||||
|
||||
if (serverSignature != serverSignatureReceived)
|
||||
throw Poco::ProtocolException("server signature verification failed");
|
||||
|
||||
pCommand = createCommand();
|
||||
pCommand->selector()
|
||||
.add<Poco::Int32>("saslContinue", 1)
|
||||
.add<Poco::Int32>("conversationId", conversationId)
|
||||
.add<Binary::Ptr>("payload", new Binary);
|
||||
|
||||
connection.sendRequest(*pCommand, response);
|
||||
if (response.documents().size() > 0)
|
||||
{
|
||||
Document::Ptr pDoc = response.documents()[0];
|
||||
if (pDoc->getInteger("ok") == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pDoc->exists("errmsg"))
|
||||
{
|
||||
const Poco::MongoDB::Element::Ptr value = pDoc->get("errmsg");
|
||||
auto message = static_cast<const Poco::MongoDB::ConcreteElement<std::string> &>(*value).value();
|
||||
throw Poco::RuntimeException(message);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else throw Poco::ProtocolException("empty response for saslContinue");
|
||||
}
|
||||
|
||||
|
||||
Document::Ptr Database::queryBuildInfo(Connection& connection) const
|
||||
{
|
||||
// build info can be issued on "config" system database
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> request = createCommand();
|
||||
request->selector().add("buildInfo", 1);
|
||||
|
||||
Poco::MongoDB::ResponseMessage response;
|
||||
connection.sendRequest(*request, response);
|
||||
|
||||
Document::Ptr buildInfo;
|
||||
if ( response.documents().size() > 0 )
|
||||
{
|
||||
buildInfo = response.documents()[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Poco::ProtocolException("Didn't get a response from the buildinfo command");
|
||||
}
|
||||
return buildInfo;
|
||||
}
|
||||
|
||||
|
||||
Document::Ptr Database::queryServerHello(Connection& connection, bool old) const
|
||||
{
|
||||
// hello can be issued on "config" system database
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> request = createCommand();
|
||||
|
||||
// 'hello' command was previously called 'isMaster'
|
||||
std::string command_name;
|
||||
if (old)
|
||||
command_name = "isMaster";
|
||||
else
|
||||
command_name = "hello";
|
||||
|
||||
request->selector().add(command_name, 1);
|
||||
|
||||
Poco::MongoDB::ResponseMessage response;
|
||||
connection.sendRequest(*request, response);
|
||||
|
||||
Document::Ptr hello;
|
||||
if ( response.documents().size() > 0 )
|
||||
{
|
||||
hello = response.documents()[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Poco::ProtocolException("Didn't get a response from the hello command");
|
||||
}
|
||||
return hello;
|
||||
}
|
||||
|
||||
|
||||
Int64 Database::count(Connection& connection, const std::string& collectionName) const
|
||||
{
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> countRequest = createCountRequest(collectionName);
|
||||
|
||||
Poco::MongoDB::ResponseMessage response;
|
||||
connection.sendRequest(*countRequest, response);
|
||||
|
||||
if (response.documents().size() > 0)
|
||||
{
|
||||
Poco::MongoDB::Document::Ptr doc = response.documents()[0];
|
||||
return doc->getInteger("n");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Poco::MongoDB::Document::Ptr Database::ensureIndex(Connection& connection, const std::string& collection, const std::string& indexName, Poco::MongoDB::Document::Ptr keys, bool unique, bool background, int version, int ttl)
|
||||
{
|
||||
Poco::MongoDB::Document::Ptr index = new Poco::MongoDB::Document();
|
||||
index->add("ns", _dbname + "." + collection);
|
||||
index->add("name", indexName);
|
||||
index->add("key", keys);
|
||||
|
||||
if (version > 0)
|
||||
{
|
||||
index->add("version", version);
|
||||
}
|
||||
|
||||
if (unique)
|
||||
{
|
||||
index->add("unique", true);
|
||||
}
|
||||
|
||||
if (background)
|
||||
{
|
||||
index->add("background", true);
|
||||
}
|
||||
|
||||
if (ttl > 0)
|
||||
{
|
||||
index->add("expireAfterSeconds", ttl);
|
||||
}
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::InsertRequest> insertRequest = createInsertRequest("system.indexes");
|
||||
insertRequest->documents().push_back(index);
|
||||
connection.sendRequest(*insertRequest);
|
||||
|
||||
return getLastErrorDoc(connection);
|
||||
}
|
||||
|
||||
|
||||
Document::Ptr Database::getLastErrorDoc(Connection& connection) const
|
||||
{
|
||||
Document::Ptr errorDoc;
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> request = createCommand();
|
||||
request->setNumberToReturn(1);
|
||||
request->selector().add("getLastError", 1);
|
||||
|
||||
Poco::MongoDB::ResponseMessage response;
|
||||
connection.sendRequest(*request, response);
|
||||
|
||||
if (response.documents().size() > 0)
|
||||
{
|
||||
errorDoc = response.documents()[0];
|
||||
}
|
||||
|
||||
return errorDoc;
|
||||
}
|
||||
|
||||
|
||||
std::string Database::getLastError(Connection& connection) const
|
||||
{
|
||||
Document::Ptr errorDoc = getLastErrorDoc(connection);
|
||||
if (!errorDoc.isNull() && errorDoc->isType<std::string>("err"))
|
||||
{
|
||||
return errorDoc->get<std::string>("err");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> Database::createCountRequest(const std::string& collectionName) const
|
||||
{
|
||||
Poco::SharedPtr<Poco::MongoDB::QueryRequest> request = createCommand();
|
||||
request->setNumberToReturn(1);
|
||||
request->selector().add("count", collectionName);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,54 +0,0 @@
|
||||
//
|
||||
// DeleteRequest.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: DeleteRequest
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/DeleteRequest.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
DeleteRequest::DeleteRequest(const std::string& collectionName, DeleteRequest::Flags flags):
|
||||
RequestMessage(MessageHeader::OP_DELETE),
|
||||
_flags(flags),
|
||||
_fullCollectionName(collectionName),
|
||||
_selector()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DeleteRequest::DeleteRequest(const std::string& collectionName, bool justOne):
|
||||
RequestMessage(MessageHeader::OP_DELETE),
|
||||
_flags(justOne ? DELETE_SINGLE_REMOVE : DELETE_DEFAULT),
|
||||
_fullCollectionName(collectionName),
|
||||
_selector()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DeleteRequest::~DeleteRequest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void DeleteRequest::buildRequest(BinaryWriter& writer)
|
||||
{
|
||||
writer << 0; // 0 - reserved for future use
|
||||
BSONWriter(writer).writeCString(_fullCollectionName);
|
||||
writer << _flags;
|
||||
_selector.write(writer);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,227 +0,0 @@
|
||||
//
|
||||
// Document.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Document
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Document.h"
|
||||
#include "Poco/MongoDB/Binary.h"
|
||||
#include "Poco/MongoDB/ObjectId.h"
|
||||
#include "Poco/MongoDB/Array.h"
|
||||
#include "Poco/MongoDB/RegularExpression.h"
|
||||
#include "Poco/MongoDB/JavaScriptCode.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
Document::Document()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Document::~Document()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Array& Document::addNewArray(const std::string& name)
|
||||
{
|
||||
Array::Ptr newArray = new Array();
|
||||
add(name, newArray);
|
||||
return *newArray;
|
||||
}
|
||||
|
||||
|
||||
Element::Ptr Document::get(const std::string& name) const
|
||||
{
|
||||
Element::Ptr element;
|
||||
|
||||
ElementSet::const_iterator it = std::find_if(_elements.begin(), _elements.end(), ElementFindByName(name));
|
||||
if (it != _elements.end())
|
||||
{
|
||||
return *it;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
Int64 Document::getInteger(const std::string& name) const
|
||||
{
|
||||
Element::Ptr element = get(name);
|
||||
if (element.isNull()) throw Poco::NotFoundException(name);
|
||||
|
||||
if (ElementTraits<double>::TypeId == element->type())
|
||||
{
|
||||
ConcreteElement<double>* concrete = dynamic_cast<ConcreteElement<double>*>(element.get());
|
||||
if (concrete) return static_cast<Int64>(concrete->value());
|
||||
}
|
||||
else if (ElementTraits<Int32>::TypeId == element->type())
|
||||
{
|
||||
ConcreteElement<Int32>* concrete = dynamic_cast<ConcreteElement<Int32>*>(element.get());
|
||||
if (concrete) return concrete->value();
|
||||
}
|
||||
else if (ElementTraits<Int64>::TypeId == element->type())
|
||||
{
|
||||
ConcreteElement<Int64>* concrete = dynamic_cast<ConcreteElement<Int64>*>(element.get());
|
||||
if (concrete) return concrete->value();
|
||||
}
|
||||
throw Poco::BadCastException("Invalid type mismatch!");
|
||||
}
|
||||
|
||||
|
||||
void Document::read(BinaryReader& reader)
|
||||
{
|
||||
int size;
|
||||
reader >> size;
|
||||
|
||||
unsigned char type;
|
||||
reader >> type;
|
||||
|
||||
while (type != '\0')
|
||||
{
|
||||
Element::Ptr element;
|
||||
|
||||
std::string name = BSONReader(reader).readCString();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ElementTraits<double>::TypeId:
|
||||
element = new ConcreteElement<double>(name, 0);
|
||||
break;
|
||||
case ElementTraits<Int32>::TypeId:
|
||||
element = new ConcreteElement<Int32>(name, 0);
|
||||
break;
|
||||
case ElementTraits<std::string>::TypeId:
|
||||
element = new ConcreteElement<std::string>(name, "");
|
||||
break;
|
||||
case ElementTraits<Document::Ptr>::TypeId:
|
||||
element = new ConcreteElement<Document::Ptr>(name, new Document);
|
||||
break;
|
||||
case ElementTraits<Array::Ptr>::TypeId:
|
||||
element = new ConcreteElement<Array::Ptr>(name, new Array);
|
||||
break;
|
||||
case ElementTraits<Binary::Ptr>::TypeId:
|
||||
element = new ConcreteElement<Binary::Ptr>(name, new Binary);
|
||||
break;
|
||||
case ElementTraits<ObjectId::Ptr>::TypeId:
|
||||
element = new ConcreteElement<ObjectId::Ptr>(name, new ObjectId);
|
||||
break;
|
||||
case ElementTraits<bool>::TypeId:
|
||||
element = new ConcreteElement<bool>(name, false);
|
||||
break;
|
||||
case ElementTraits<Poco::Timestamp>::TypeId:
|
||||
element = new ConcreteElement<Poco::Timestamp>(name, Poco::Timestamp());
|
||||
break;
|
||||
case ElementTraits<BSONTimestamp>::TypeId:
|
||||
element = new ConcreteElement<BSONTimestamp>(name, BSONTimestamp());
|
||||
break;
|
||||
case ElementTraits<NullValue>::TypeId:
|
||||
element = new ConcreteElement<NullValue>(name, NullValue(0));
|
||||
break;
|
||||
case ElementTraits<RegularExpression::Ptr>::TypeId:
|
||||
element = new ConcreteElement<RegularExpression::Ptr>(name, new RegularExpression());
|
||||
break;
|
||||
case ElementTraits<JavaScriptCode::Ptr>::TypeId:
|
||||
element = new ConcreteElement<JavaScriptCode::Ptr>(name, new JavaScriptCode());
|
||||
break;
|
||||
case ElementTraits<Int64>::TypeId:
|
||||
element = new ConcreteElement<Int64>(name, 0);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Element " << name << " contains an unsupported type 0x" << std::hex << (int) type;
|
||||
throw Poco::NotImplementedException(ss.str());
|
||||
}
|
||||
//TODO: x0F -> JavaScript code with scope
|
||||
// xFF -> Min Key
|
||||
// x7F -> Max Key
|
||||
}
|
||||
|
||||
element->read(reader);
|
||||
_elements.push_back(element);
|
||||
|
||||
reader >> type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string Document::toString(int indent) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << '{';
|
||||
|
||||
if (indent > 0) oss << std::endl;
|
||||
|
||||
|
||||
for (ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it)
|
||||
{
|
||||
if (it != _elements.begin())
|
||||
{
|
||||
oss << ',';
|
||||
if (indent > 0) oss << std::endl;
|
||||
}
|
||||
|
||||
for (int i = 0; i < indent; ++i) oss << ' ';
|
||||
|
||||
oss << '"' << (*it)->name() << '"';
|
||||
oss << (indent > 0 ? " : " : ":");
|
||||
|
||||
oss << (*it)->toString(indent > 0 ? indent + 2 : 0);
|
||||
}
|
||||
|
||||
if (indent > 0)
|
||||
{
|
||||
oss << std::endl;
|
||||
if (indent >= 2) indent -= 2;
|
||||
|
||||
for (int i = 0; i < indent; ++i) oss << ' ';
|
||||
}
|
||||
|
||||
oss << '}';
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
void Document::write(BinaryWriter& writer)
|
||||
{
|
||||
if (_elements.empty())
|
||||
{
|
||||
writer << 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream sstream;
|
||||
Poco::BinaryWriter tempWriter(sstream, BinaryWriter::LITTLE_ENDIAN_BYTE_ORDER);
|
||||
for (ElementSet::iterator it = _elements.begin(); it != _elements.end(); ++it)
|
||||
{
|
||||
tempWriter << static_cast<unsigned char>((*it)->type());
|
||||
BSONWriter(tempWriter).writeCString((*it)->name());
|
||||
Element::Ptr element = *it;
|
||||
element->write(tempWriter);
|
||||
}
|
||||
tempWriter.flush();
|
||||
|
||||
Poco::Int32 len = static_cast<Poco::Int32>(5 + sstream.tellp()); /* 5 = sizeof(len) + 0-byte */
|
||||
writer << len;
|
||||
writer.writeRaw(sstream.str());
|
||||
}
|
||||
writer << '\0';
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,32 +0,0 @@
|
||||
//
|
||||
// Element.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Element
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Element.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
Element::Element(const std::string& name) : _name(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Element::~Element()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,46 +0,0 @@
|
||||
//
|
||||
// GetMoreRequest.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: GetMoreRequest
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/GetMoreRequest.h"
|
||||
#include "Poco/MongoDB/Element.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
GetMoreRequest::GetMoreRequest(const std::string& collectionName, Int64 cursorID):
|
||||
RequestMessage(MessageHeader::OP_GET_MORE),
|
||||
_fullCollectionName(collectionName),
|
||||
_numberToReturn(100),
|
||||
_cursorID(cursorID)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GetMoreRequest::~GetMoreRequest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GetMoreRequest::buildRequest(BinaryWriter& writer)
|
||||
{
|
||||
writer << 0; // 0 - reserved for future use
|
||||
BSONWriter(writer).writeCString(_fullCollectionName);
|
||||
writer << _numberToReturn;
|
||||
writer << _cursorID;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,49 +0,0 @@
|
||||
//
|
||||
// InsertRequest.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: InsertRequest
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/InsertRequest.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
InsertRequest::InsertRequest(const std::string& collectionName, Flags flags):
|
||||
RequestMessage(MessageHeader::OP_INSERT),
|
||||
_flags(flags),
|
||||
_fullCollectionName(collectionName)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
InsertRequest::~InsertRequest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void InsertRequest::buildRequest(BinaryWriter& writer)
|
||||
{
|
||||
poco_assert (!_documents.empty());
|
||||
|
||||
writer << _flags;
|
||||
BSONWriter bsonWriter(writer);
|
||||
bsonWriter.writeCString(_fullCollectionName);
|
||||
for (Document::Vector::iterator it = _documents.begin(); it != _documents.end(); ++it)
|
||||
{
|
||||
bsonWriter.write(*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,33 +0,0 @@
|
||||
//
|
||||
// JavaScriptCode.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: JavaScriptCode
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/JavaScriptCode.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
JavaScriptCode::JavaScriptCode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JavaScriptCode::~JavaScriptCode()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,44 +0,0 @@
|
||||
//
|
||||
// KillCursorsRequest.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: KillCursorsRequest
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/KillCursorsRequest.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
KillCursorsRequest::KillCursorsRequest():
|
||||
RequestMessage(MessageHeader::OP_KILL_CURSORS)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
KillCursorsRequest::~KillCursorsRequest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void KillCursorsRequest::buildRequest(BinaryWriter& writer)
|
||||
{
|
||||
writer << 0; // 0 - reserved for future use
|
||||
writer << static_cast<Poco::UInt64>(_cursors.size());
|
||||
for (std::vector<Int64>::iterator it = _cursors.begin(); it != _cursors.end(); ++it)
|
||||
{
|
||||
writer << *it;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,33 +0,0 @@
|
||||
//
|
||||
// Message.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: Message
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Message.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
Message::Message(MessageHeader::OpCode opcode):
|
||||
_header(opcode)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Message::~Message()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,63 +0,0 @@
|
||||
//
|
||||
// MessageHeader.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: MessageHeader
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/Message.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
MessageHeader::MessageHeader(OpCode opCode):
|
||||
_messageLength(0),
|
||||
_requestID(0),
|
||||
_responseTo(0),
|
||||
_opCode(opCode)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MessageHeader::~MessageHeader()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void MessageHeader::read(BinaryReader& reader)
|
||||
{
|
||||
reader >> _messageLength;
|
||||
reader >> _requestID;
|
||||
reader >> _responseTo;
|
||||
|
||||
Int32 opCode;
|
||||
reader >> opCode;
|
||||
_opCode = static_cast<OpCode>(opCode);
|
||||
|
||||
if (!reader.good())
|
||||
{
|
||||
throw IOException("Failed to read from socket");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MessageHeader::write(BinaryWriter& writer)
|
||||
{
|
||||
writer << _messageLength;
|
||||
writer << _requestID;
|
||||
writer << _responseTo;
|
||||
writer << static_cast<Int32>(_opCode);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,66 +0,0 @@
|
||||
//
|
||||
// ObjectId.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: ObjectId
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/ObjectId.h"
|
||||
#include "Poco/Format.h"
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
ObjectId::ObjectId()
|
||||
{
|
||||
std::memset(_id, 0, sizeof(_id));
|
||||
}
|
||||
|
||||
|
||||
ObjectId::ObjectId(const std::string& id)
|
||||
{
|
||||
poco_assert_dbg(id.size() == 24);
|
||||
|
||||
const char* p = id.c_str();
|
||||
for (std::size_t i = 0; i < 12; ++i)
|
||||
{
|
||||
_id[i] = fromHex(p);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ObjectId::ObjectId(const ObjectId& copy)
|
||||
{
|
||||
std::memcpy(_id, copy._id, sizeof(_id));
|
||||
}
|
||||
|
||||
|
||||
ObjectId::~ObjectId()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::string ObjectId::toString(const std::string& fmt) const
|
||||
{
|
||||
std::string s;
|
||||
|
||||
for (int i = 0; i < 12; ++i)
|
||||
{
|
||||
s += Poco::format(fmt, (unsigned int) _id[i]);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,187 +0,0 @@
|
||||
//
|
||||
// OpMsgCursor.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: OpMsgCursor
|
||||
//
|
||||
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/OpMsgCursor.h"
|
||||
#include "Poco/MongoDB/Array.h"
|
||||
|
||||
//
|
||||
// NOTE:
|
||||
//
|
||||
// MongoDB specification indicates that the flag MSG_EXHAUST_ALLOWED shall be
|
||||
// used in the request when the receiver is ready to receive multiple messages
|
||||
// without sending additional requests in between. Sender (MongoDB) indicates
|
||||
// that more messages follow with flag MSG_MORE_TO_COME.
|
||||
//
|
||||
// It seems that this does not work properly. MSG_MORE_TO_COME is set and reading
|
||||
// next messages sometimes works, however often the data is missing in response
|
||||
// or the message header contains wrong message length and reading blocks.
|
||||
// Opcode in the header is correct.
|
||||
//
|
||||
// Using MSG_EXHAUST_ALLOWED is therefore currently disabled.
|
||||
//
|
||||
// It seems that related JIRA ticket is:
|
||||
//
|
||||
// https://jira.mongodb.org/browse/SERVER-57297
|
||||
//
|
||||
// https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.rst
|
||||
//
|
||||
|
||||
#define MONGODB_EXHAUST_ALLOWED_WORKS false
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
[[ maybe_unused ]] static const std::string keyCursor {"cursor"};
|
||||
[[ maybe_unused ]] static const std::string keyFirstBatch {"firstBatch"};
|
||||
[[ maybe_unused ]] static const std::string keyNextBatch {"nextBatch"};
|
||||
|
||||
static Poco::Int64 cursorIdFromResponse(const MongoDB::Document& doc);
|
||||
|
||||
|
||||
OpMsgCursor::OpMsgCursor(const std::string& db, const std::string& collection):
|
||||
#if MONGODB_EXHAUST_ALLOWED_WORKS
|
||||
_query(db, collection, OpMsgMessage::MSG_EXHAUST_ALLOWED)
|
||||
#else
|
||||
_query(db, collection)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
OpMsgCursor::~OpMsgCursor()
|
||||
{
|
||||
try
|
||||
{
|
||||
poco_assert_dbg(_cursorID == 0);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OpMsgCursor::setEmptyFirstBatch(bool empty)
|
||||
{
|
||||
_emptyFirstBatch = empty;
|
||||
}
|
||||
|
||||
|
||||
bool OpMsgCursor::emptyFirstBatch() const
|
||||
{
|
||||
return _emptyFirstBatch;
|
||||
}
|
||||
|
||||
|
||||
void OpMsgCursor::setBatchSize(Int32 batchSize)
|
||||
{
|
||||
_batchSize = batchSize;
|
||||
}
|
||||
|
||||
|
||||
Int32 OpMsgCursor::batchSize() const
|
||||
{
|
||||
return _batchSize;
|
||||
}
|
||||
|
||||
|
||||
OpMsgMessage& OpMsgCursor::next(Connection& connection)
|
||||
{
|
||||
if (_cursorID == 0)
|
||||
{
|
||||
_response.clear();
|
||||
|
||||
if (_emptyFirstBatch || _batchSize > 0)
|
||||
{
|
||||
Int32 bsize = _emptyFirstBatch ? 0 : _batchSize;
|
||||
if (_query.commandName() == OpMsgMessage::CMD_FIND)
|
||||
{
|
||||
_query.body().add("batchSize", bsize);
|
||||
}
|
||||
else if (_query.commandName() == OpMsgMessage::CMD_AGGREGATE)
|
||||
{
|
||||
auto& cursorDoc = _query.body().addNewDocument("cursor");
|
||||
cursorDoc.add("batchSize", bsize);
|
||||
}
|
||||
}
|
||||
|
||||
connection.sendRequest(_query, _response);
|
||||
|
||||
const auto& rdoc = _response.body();
|
||||
_cursorID = cursorIdFromResponse(rdoc);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MONGODB_EXHAUST_ALLOWED_WORKS
|
||||
std::cout << "Response flags: " << _response.flags() << std::endl;
|
||||
if (_response.flags() & OpMsgMessage::MSG_MORE_TO_COME)
|
||||
{
|
||||
std::cout << "More to come. Reading more response: " << std::endl;
|
||||
_response.clear();
|
||||
connection.readResponse(_response);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_response.clear();
|
||||
_query.setCursor(_cursorID, _batchSize);
|
||||
connection.sendRequest(_query, _response);
|
||||
}
|
||||
}
|
||||
|
||||
const auto& rdoc = _response.body();
|
||||
_cursorID = cursorIdFromResponse(rdoc);
|
||||
|
||||
return _response;
|
||||
}
|
||||
|
||||
|
||||
void OpMsgCursor::kill(Connection& connection)
|
||||
{
|
||||
_response.clear();
|
||||
if (_cursorID != 0)
|
||||
{
|
||||
_query.setCommandName(OpMsgMessage::CMD_KILL_CURSORS);
|
||||
|
||||
MongoDB::Array::Ptr cursors = new MongoDB::Array();
|
||||
cursors->add<Poco::Int64>(_cursorID);
|
||||
_query.body().add("cursors", cursors);
|
||||
|
||||
connection.sendRequest(_query, _response);
|
||||
|
||||
const auto killed = _response.body().get<MongoDB::Array::Ptr>("cursorsKilled", nullptr);
|
||||
if (!killed || killed->size() != 1 || killed->get<Poco::Int64>(0, -1) != _cursorID)
|
||||
{
|
||||
throw Poco::ProtocolException("Cursor not killed as expected: " + std::to_string(_cursorID));
|
||||
}
|
||||
|
||||
_cursorID = 0;
|
||||
_query.clear();
|
||||
_response.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Poco::Int64 cursorIdFromResponse(const MongoDB::Document& doc)
|
||||
{
|
||||
Poco::Int64 id {0};
|
||||
auto cursorDoc = doc.get<Document::Ptr>(keyCursor, nullptr);
|
||||
if(cursorDoc)
|
||||
{
|
||||
id = cursorDoc->get<Poco::Int64>("id", 0);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
} } // Namespace Poco::MongoDB
|
@ -1,412 +0,0 @@
|
||||
//
|
||||
// OpMsgMessage.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: OpMsgMessage
|
||||
//
|
||||
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
#include "Poco/MongoDB/OpMsgMessage.h"
|
||||
#include "Poco/MongoDB/MessageHeader.h"
|
||||
#include "Poco/MongoDB/Array.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/Logger.h"
|
||||
|
||||
#define POCO_MONGODB_DUMP false
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
// Query and write
|
||||
const std::string OpMsgMessage::CMD_INSERT { "insert" };
|
||||
const std::string OpMsgMessage::CMD_DELETE { "delete" };
|
||||
const std::string OpMsgMessage::CMD_UPDATE { "update" };
|
||||
const std::string OpMsgMessage::CMD_FIND { "find" };
|
||||
const std::string OpMsgMessage::CMD_FIND_AND_MODIFY { "findAndModify" };
|
||||
const std::string OpMsgMessage::CMD_GET_MORE { "getMore" };
|
||||
|
||||
// Aggregation
|
||||
const std::string OpMsgMessage::CMD_AGGREGATE { "aggregate" };
|
||||
const std::string OpMsgMessage::CMD_COUNT { "count" };
|
||||
const std::string OpMsgMessage::CMD_DISTINCT { "distinct" };
|
||||
const std::string OpMsgMessage::CMD_MAP_REDUCE { "mapReduce" };
|
||||
|
||||
// Replication and administration
|
||||
const std::string OpMsgMessage::CMD_HELLO { "hello" };
|
||||
const std::string OpMsgMessage::CMD_REPL_SET_GET_STATUS { "replSetGetStatus" };
|
||||
const std::string OpMsgMessage::CMD_REPL_SET_GET_CONFIG { "replSetGetConfig" };
|
||||
|
||||
const std::string OpMsgMessage::CMD_CREATE { "create" };
|
||||
const std::string OpMsgMessage::CMD_CREATE_INDEXES { "createIndexes" };
|
||||
const std::string OpMsgMessage::CMD_DROP { "drop" };
|
||||
const std::string OpMsgMessage::CMD_DROP_DATABASE { "dropDatabase" };
|
||||
const std::string OpMsgMessage::CMD_KILL_CURSORS { "killCursors" };
|
||||
const std::string OpMsgMessage::CMD_LIST_DATABASES { "listDatabases" };
|
||||
const std::string OpMsgMessage::CMD_LIST_INDEXES { "listIndexes" };
|
||||
|
||||
// Diagnostic
|
||||
const std::string OpMsgMessage::CMD_BUILD_INFO { "buildInfo" };
|
||||
const std::string OpMsgMessage::CMD_COLL_STATS { "collStats" };
|
||||
const std::string OpMsgMessage::CMD_DB_STATS { "dbStats" };
|
||||
const std::string OpMsgMessage::CMD_HOST_INFO { "hostInfo" };
|
||||
|
||||
|
||||
static const std::string& commandIdentifier(const std::string& command);
|
||||
/// Commands have different names for the payload that is sent in a separate section
|
||||
|
||||
|
||||
static const std::string keyCursor {"cursor"};
|
||||
static const std::string keyFirstBatch {"firstBatch"};
|
||||
static const std::string keyNextBatch {"nextBatch"};
|
||||
|
||||
|
||||
OpMsgMessage::OpMsgMessage() :
|
||||
Message(MessageHeader::OP_MSG)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
OpMsgMessage::OpMsgMessage(const std::string& databaseName, const std::string& collectionName, UInt32 flags) :
|
||||
Message(MessageHeader::OP_MSG),
|
||||
_databaseName(databaseName),
|
||||
_collectionName(collectionName),
|
||||
_flags(flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
OpMsgMessage::~OpMsgMessage()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& OpMsgMessage::databaseName() const
|
||||
{
|
||||
return _databaseName;
|
||||
}
|
||||
|
||||
|
||||
const std::string& OpMsgMessage::collectionName() const
|
||||
{
|
||||
return _collectionName;
|
||||
}
|
||||
|
||||
|
||||
void OpMsgMessage::setCommandName(const std::string& command)
|
||||
{
|
||||
_commandName = command;
|
||||
_body.clear();
|
||||
|
||||
// IMPORTANT: Command name must be first
|
||||
if (_collectionName.empty())
|
||||
{
|
||||
// Collection is not specified. It is assumed that this particular command does
|
||||
// not need it.
|
||||
_body.add(_commandName, Int32(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
_body.add(_commandName, _collectionName);
|
||||
}
|
||||
_body.add("$db", _databaseName);
|
||||
}
|
||||
|
||||
|
||||
void OpMsgMessage::setCursor(Poco::Int64 cursorID, Poco::Int32 batchSize)
|
||||
{
|
||||
_commandName = OpMsgMessage::CMD_GET_MORE;
|
||||
_body.clear();
|
||||
|
||||
// IMPORTANT: Command name must be first
|
||||
_body.add(_commandName, cursorID);
|
||||
_body.add("$db", _databaseName);
|
||||
_body.add("collection", _collectionName);
|
||||
if (batchSize > 0)
|
||||
{
|
||||
_body.add("batchSize", batchSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::string& OpMsgMessage::commandName() const
|
||||
{
|
||||
return _commandName;
|
||||
}
|
||||
|
||||
|
||||
void OpMsgMessage::setAcknowledgedRequest(bool ack)
|
||||
{
|
||||
const auto& id = commandIdentifier(_commandName);
|
||||
if (id.empty())
|
||||
return;
|
||||
|
||||
_acknowledged = ack;
|
||||
|
||||
auto writeConcern = _body.get<Document::Ptr>("writeConcern", nullptr);
|
||||
if (writeConcern)
|
||||
writeConcern->remove("w");
|
||||
|
||||
if (ack)
|
||||
{
|
||||
_flags = _flags & (~MSG_MORE_TO_COME);
|
||||
}
|
||||
else
|
||||
{
|
||||
_flags = _flags | MSG_MORE_TO_COME;
|
||||
if (!writeConcern)
|
||||
_body.addNewDocument("writeConcern").add("w", 0);
|
||||
else
|
||||
writeConcern->add("w", 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool OpMsgMessage::acknowledgedRequest() const
|
||||
{
|
||||
return _acknowledged;
|
||||
}
|
||||
|
||||
|
||||
UInt32 OpMsgMessage::flags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
|
||||
Document& OpMsgMessage::body()
|
||||
{
|
||||
return _body;
|
||||
}
|
||||
|
||||
|
||||
const Document& OpMsgMessage::body() const
|
||||
{
|
||||
return _body;
|
||||
}
|
||||
|
||||
|
||||
Document::Vector& OpMsgMessage::documents()
|
||||
{
|
||||
return _documents;
|
||||
}
|
||||
|
||||
|
||||
const Document::Vector& OpMsgMessage::documents() const
|
||||
{
|
||||
return _documents;
|
||||
}
|
||||
|
||||
|
||||
bool OpMsgMessage::responseOk() const
|
||||
{
|
||||
Poco::Int64 ok {false};
|
||||
if (_body.exists("ok"))
|
||||
{
|
||||
ok = _body.getInteger("ok");
|
||||
}
|
||||
return (ok != 0);
|
||||
}
|
||||
|
||||
|
||||
void OpMsgMessage::clear()
|
||||
{
|
||||
_flags = MSG_FLAGS_DEFAULT;
|
||||
_commandName.clear();
|
||||
_body.clear();
|
||||
_documents.clear();
|
||||
}
|
||||
|
||||
|
||||
void OpMsgMessage::send(std::ostream& ostr)
|
||||
{
|
||||
BinaryWriter socketWriter(ostr, BinaryWriter::LITTLE_ENDIAN_BYTE_ORDER);
|
||||
|
||||
// Serialise the body
|
||||
std::stringstream ss;
|
||||
BinaryWriter writer(ss, BinaryWriter::LITTLE_ENDIAN_BYTE_ORDER);
|
||||
writer << _flags;
|
||||
|
||||
writer << PAYLOAD_TYPE_0;
|
||||
_body.write(writer);
|
||||
|
||||
if (!_documents.empty())
|
||||
{
|
||||
// Serialise attached documents
|
||||
|
||||
std::stringstream ssdoc;
|
||||
BinaryWriter wdoc(ssdoc, BinaryWriter::LITTLE_ENDIAN_BYTE_ORDER);
|
||||
for (auto& doc: _documents)
|
||||
{
|
||||
doc->write(wdoc);
|
||||
}
|
||||
wdoc.flush();
|
||||
|
||||
const std::string& identifier = commandIdentifier(_commandName);
|
||||
const Poco::Int32 size = static_cast<Poco::Int32>(sizeof(size) + identifier.size() + 1 + ssdoc.tellp());
|
||||
writer << PAYLOAD_TYPE_1;
|
||||
writer << size;
|
||||
writer.writeCString(identifier.c_str());
|
||||
StreamCopier::copyStream(ssdoc, ss);
|
||||
}
|
||||
writer.flush();
|
||||
|
||||
#if POCO_MONGODB_DUMP
|
||||
const std::string section = ss.str();
|
||||
std::string dump;
|
||||
Logger::formatDump(dump, section.data(), section.length());
|
||||
std::cout << dump << std::endl;
|
||||
#endif
|
||||
|
||||
messageLength(static_cast<Poco::Int32>(ss.tellp()));
|
||||
|
||||
_header.write(socketWriter);
|
||||
StreamCopier::copyStream(ss, ostr);
|
||||
|
||||
ostr.flush();
|
||||
}
|
||||
|
||||
|
||||
void OpMsgMessage::read(std::istream& istr)
|
||||
{
|
||||
std::string message;
|
||||
{
|
||||
BinaryReader reader(istr, BinaryReader::LITTLE_ENDIAN_BYTE_ORDER);
|
||||
_header.read(reader);
|
||||
|
||||
poco_assert_dbg(_header.opCode() == _header.OP_MSG);
|
||||
|
||||
const std::streamsize remainingSize {_header.getMessageLength() - _header.MSG_HEADER_SIZE };
|
||||
message.reserve(remainingSize);
|
||||
|
||||
#if POCO_MONGODB_DUMP
|
||||
std::cout
|
||||
<< "Message hdr: " << _header.getMessageLength() << " " << remainingSize << " "
|
||||
<< _header.opCode() << " " << _header.getRequestID() << " " << _header.responseTo()
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
reader.readRaw(remainingSize, message);
|
||||
|
||||
#if POCO_MONGODB_DUMP
|
||||
std::string dump;
|
||||
Logger::formatDump(dump, message.data(), message.length());
|
||||
std::cout << dump << std::endl;
|
||||
#endif
|
||||
}
|
||||
// Read complete message and then interpret it.
|
||||
|
||||
std::istringstream msgss(message);
|
||||
BinaryReader reader(msgss, BinaryReader::LITTLE_ENDIAN_BYTE_ORDER);
|
||||
|
||||
Poco::UInt8 payloadType {0xFF};
|
||||
|
||||
reader >> _flags;
|
||||
reader >> payloadType;
|
||||
poco_assert_dbg(payloadType == PAYLOAD_TYPE_0);
|
||||
|
||||
_body.read(reader);
|
||||
|
||||
// Read next sections from the buffer
|
||||
while (msgss.good())
|
||||
{
|
||||
// NOTE: Not tested yet with database, because it returns everything in the body.
|
||||
// Does MongoDB ever return documents as Payload type 1?
|
||||
reader >> payloadType;
|
||||
if (!msgss.good())
|
||||
{
|
||||
break;
|
||||
}
|
||||
poco_assert_dbg(payloadType == PAYLOAD_TYPE_1);
|
||||
#if POCO_MONGODB_DUMP
|
||||
std::cout << "section payload: " << payloadType << std::endl;
|
||||
#endif
|
||||
|
||||
Poco::Int32 sectionSize {0};
|
||||
reader >> sectionSize;
|
||||
poco_assert_dbg(sectionSize > 0);
|
||||
|
||||
#if POCO_MONGODB_DUMP
|
||||
std::cout << "section size: " << sectionSize << std::endl;
|
||||
#endif
|
||||
std::streamoff offset = sectionSize - sizeof(sectionSize);
|
||||
std::streampos endOfSection = msgss.tellg() + offset;
|
||||
|
||||
std::string identifier;
|
||||
reader.readCString(identifier);
|
||||
#if POCO_MONGODB_DUMP
|
||||
std::cout << "section identifier: " << identifier << std::endl;
|
||||
#endif
|
||||
|
||||
// Loop to read documents from this section.
|
||||
while (msgss.tellg() < endOfSection)
|
||||
{
|
||||
#if POCO_MONGODB_DUMP
|
||||
std::cout << "section doc: " << msgss.tellg() << " " << endOfSection << std::endl;
|
||||
#endif
|
||||
Document::Ptr doc = new Document();
|
||||
doc->read(reader);
|
||||
_documents.push_back(doc);
|
||||
if (msgss.tellg() < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract documents from the cursor batch if they are there.
|
||||
MongoDB::Array::Ptr batch;
|
||||
auto curDoc = _body.get<MongoDB::Document::Ptr>(keyCursor, nullptr);
|
||||
if (curDoc)
|
||||
{
|
||||
batch = curDoc->get<MongoDB::Array::Ptr>(keyFirstBatch, nullptr);
|
||||
if (!batch)
|
||||
{
|
||||
batch = curDoc->get<MongoDB::Array::Ptr>(keyNextBatch, nullptr);
|
||||
}
|
||||
}
|
||||
if (batch)
|
||||
{
|
||||
for(std::size_t i = 0; i < batch->size(); i++)
|
||||
{
|
||||
const auto& d = batch->get<MongoDB::Document::Ptr>(i, nullptr);
|
||||
if (d)
|
||||
{
|
||||
_documents.push_back(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const std::string& commandIdentifier(const std::string& command)
|
||||
{
|
||||
// Names of identifiers for commands that send bulk documents in the request
|
||||
// The identifier is set in the section type 1.
|
||||
static std::map<std::string, std::string> identifiers {
|
||||
{ OpMsgMessage::CMD_INSERT, "documents" },
|
||||
{ OpMsgMessage::CMD_DELETE, "deletes" },
|
||||
{ OpMsgMessage::CMD_UPDATE, "updates" },
|
||||
|
||||
// Not sure if create index can send document section
|
||||
{ OpMsgMessage::CMD_CREATE_INDEXES, "indexes" }
|
||||
};
|
||||
|
||||
const auto i = identifiers.find(command);
|
||||
if (i != identifiers.end())
|
||||
{
|
||||
return i->second;
|
||||
}
|
||||
|
||||
// This likely means that documents are incorrectly set for a command
|
||||
// that does not send list of documents in section type 1.
|
||||
static const std::string emptyIdentifier;
|
||||
return emptyIdentifier;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,54 +0,0 @@
|
||||
//
|
||||
// QueryRequest.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: QueryRequest
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/QueryRequest.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
QueryRequest::QueryRequest(const std::string& collectionName, QueryRequest::Flags flags):
|
||||
RequestMessage(MessageHeader::OP_QUERY),
|
||||
_flags(flags),
|
||||
_fullCollectionName(collectionName),
|
||||
_numberToSkip(0),
|
||||
_numberToReturn(100),
|
||||
_selector(),
|
||||
_returnFieldSelector()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QueryRequest::~QueryRequest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void QueryRequest::buildRequest(BinaryWriter& writer)
|
||||
{
|
||||
writer << _flags;
|
||||
BSONWriter(writer).writeCString(_fullCollectionName);
|
||||
writer << _numberToSkip;
|
||||
writer << _numberToReturn;
|
||||
_selector.write(writer);
|
||||
|
||||
if (!_returnFieldSelector.empty())
|
||||
{
|
||||
_returnFieldSelector.write(writer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,71 +0,0 @@
|
||||
//
|
||||
// RegularExpression.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: RegularExpression
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/RegularExpression.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
RegularExpression::RegularExpression()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RegularExpression::RegularExpression(const std::string& pattern, const std::string& options):
|
||||
_pattern(pattern),
|
||||
_options(options)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RegularExpression::~RegularExpression()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SharedPtr<Poco::RegularExpression> RegularExpression::createRE() const
|
||||
{
|
||||
int options = 0;
|
||||
for (std::string::const_iterator optIt = _options.begin(); optIt != _options.end(); ++optIt)
|
||||
{
|
||||
switch (*optIt)
|
||||
{
|
||||
case 'i': // Case Insensitive
|
||||
options |= Poco::RegularExpression::RE_CASELESS;
|
||||
break;
|
||||
case 'm': // Multiline matching
|
||||
options |= Poco::RegularExpression::RE_MULTILINE;
|
||||
break;
|
||||
case 'x': // Verbose mode
|
||||
//No equivalent in Poco
|
||||
break;
|
||||
case 'l': // \w \W Locale dependent
|
||||
//No equivalent in Poco
|
||||
break;
|
||||
case 's': // Dotall mode
|
||||
options |= Poco::RegularExpression::RE_DOTALL;
|
||||
break;
|
||||
case 'u': // \w \W Unicode
|
||||
//No equivalent in Poco
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Poco::RegularExpression(_pattern, options);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,89 +0,0 @@
|
||||
//
|
||||
// ReplicaSet.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: ReplicaSet
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/ReplicaSet.h"
|
||||
#include "Poco/MongoDB/QueryRequest.h"
|
||||
#include "Poco/MongoDB/ResponseMessage.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
ReplicaSet::ReplicaSet(const std::vector<Net::SocketAddress> &addresses):
|
||||
_addresses(addresses)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ReplicaSet::~ReplicaSet()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Connection::Ptr ReplicaSet::findMaster()
|
||||
{
|
||||
Connection::Ptr master;
|
||||
|
||||
for (std::vector<Net::SocketAddress>::iterator it = _addresses.begin(); it != _addresses.end(); ++it)
|
||||
{
|
||||
master = isMaster(*it);
|
||||
if (!master.isNull())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return master;
|
||||
}
|
||||
|
||||
|
||||
Connection::Ptr ReplicaSet::isMaster(const Net::SocketAddress& address)
|
||||
{
|
||||
Connection::Ptr conn = new Connection();
|
||||
|
||||
try
|
||||
{
|
||||
conn->connect(address);
|
||||
|
||||
QueryRequest request("admin.$cmd");
|
||||
request.setNumberToReturn(1);
|
||||
request.selector().add("isMaster", 1);
|
||||
|
||||
ResponseMessage response;
|
||||
conn->sendRequest(request, response);
|
||||
|
||||
if (response.documents().size() > 0)
|
||||
{
|
||||
Document::Ptr doc = response.documents()[0];
|
||||
if (doc->get<bool>("ismaster"))
|
||||
{
|
||||
return conn;
|
||||
}
|
||||
else if (doc->exists("primary"))
|
||||
{
|
||||
return isMaster(Net::SocketAddress(doc->get<std::string>("primary")));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
conn = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,51 +0,0 @@
|
||||
//
|
||||
// RequestMessage.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: RequestMessage
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/RequestMessage.h"
|
||||
#include "Poco/Net/SocketStream.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
RequestMessage::RequestMessage(MessageHeader::OpCode opcode):
|
||||
Message(opcode)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RequestMessage::~RequestMessage()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void RequestMessage::send(std::ostream& ostr)
|
||||
{
|
||||
std::stringstream ss;
|
||||
BinaryWriter requestWriter(ss, BinaryWriter::LITTLE_ENDIAN_BYTE_ORDER);
|
||||
buildRequest(requestWriter);
|
||||
requestWriter.flush();
|
||||
|
||||
messageLength(static_cast<Poco::Int32>(ss.tellp()));
|
||||
|
||||
BinaryWriter socketWriter(ostr, BinaryWriter::LITTLE_ENDIAN_BYTE_ORDER);
|
||||
_header.write(socketWriter);
|
||||
StreamCopier::copyStream(ss, ostr);
|
||||
ostr.flush();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,80 +0,0 @@
|
||||
//
|
||||
// ResponseMessage.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: ResponseMessage
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/ResponseMessage.h"
|
||||
#include "Poco/Net/SocketStream.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
ResponseMessage::ResponseMessage():
|
||||
Message(MessageHeader::OP_REPLY),
|
||||
_responseFlags(0),
|
||||
_cursorID(0),
|
||||
_startingFrom(0),
|
||||
_numberReturned(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ResponseMessage::ResponseMessage(const Int64& cursorID):
|
||||
Message(MessageHeader::OP_REPLY),
|
||||
_responseFlags(0),
|
||||
_cursorID(cursorID),
|
||||
_startingFrom(0),
|
||||
_numberReturned(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ResponseMessage::~ResponseMessage()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ResponseMessage::clear()
|
||||
{
|
||||
_responseFlags = 0;
|
||||
_startingFrom = 0;
|
||||
_cursorID = 0;
|
||||
_numberReturned = 0;
|
||||
_documents.clear();
|
||||
}
|
||||
|
||||
|
||||
void ResponseMessage::read(std::istream& istr)
|
||||
{
|
||||
clear();
|
||||
|
||||
BinaryReader reader(istr, BinaryReader::LITTLE_ENDIAN_BYTE_ORDER);
|
||||
|
||||
_header.read(reader);
|
||||
|
||||
reader >> _responseFlags;
|
||||
reader >> _cursorID;
|
||||
reader >> _startingFrom;
|
||||
reader >> _numberReturned;
|
||||
|
||||
for (int i = 0; i < _numberReturned; ++i)
|
||||
{
|
||||
Document::Ptr doc = new Document();
|
||||
doc->read(reader);
|
||||
_documents.push_back(doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
@ -1,47 +0,0 @@
|
||||
//
|
||||
// UpdateRequest.cpp
|
||||
//
|
||||
// Library: MongoDB
|
||||
// Package: MongoDB
|
||||
// Module: UpdateRequest
|
||||
//
|
||||
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/MongoDB/UpdateRequest.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace MongoDB {
|
||||
|
||||
|
||||
UpdateRequest::UpdateRequest(const std::string& collectionName, UpdateRequest::Flags flags):
|
||||
RequestMessage(MessageHeader::OP_UPDATE),
|
||||
_flags(flags),
|
||||
_fullCollectionName(collectionName),
|
||||
_selector(),
|
||||
_update()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
UpdateRequest::~UpdateRequest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UpdateRequest::buildRequest(BinaryWriter& writer)
|
||||
{
|
||||
writer << 0; // 0 - reserved for future use
|
||||
BSONWriter(writer).writeCString(_fullCollectionName);
|
||||
writer << _flags;
|
||||
_selector.write(writer);
|
||||
_update.write(writer);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::MongoDB
|
2
contrib/googletest
vendored
2
contrib/googletest
vendored
@ -1 +1 @@
|
||||
Subproject commit a7f443b80b105f940225332ed3c31f2790092f47
|
||||
Subproject commit 35d0c365609296fa4730d62057c487e3cfa030ff
|
@ -38,7 +38,7 @@ RUN arch=${TARGETARCH:-amd64} \
|
||||
# lts / testing / prestable / etc
|
||||
ARG REPO_CHANNEL="stable"
|
||||
ARG REPOSITORY="https://packages.clickhouse.com/tgz/${REPO_CHANNEL}"
|
||||
ARG VERSION="24.10.3.21"
|
||||
ARG VERSION="24.11.1.2557"
|
||||
ARG PACKAGES="clickhouse-keeper"
|
||||
ARG DIRECT_DOWNLOAD_URLS=""
|
||||
|
||||
|
@ -35,7 +35,7 @@ RUN arch=${TARGETARCH:-amd64} \
|
||||
# lts / testing / prestable / etc
|
||||
ARG REPO_CHANNEL="stable"
|
||||
ARG REPOSITORY="https://packages.clickhouse.com/tgz/${REPO_CHANNEL}"
|
||||
ARG VERSION="24.10.3.21"
|
||||
ARG VERSION="24.11.1.2557"
|
||||
ARG PACKAGES="clickhouse-client clickhouse-server clickhouse-common-static"
|
||||
ARG DIRECT_DOWNLOAD_URLS=""
|
||||
|
||||
|
@ -28,7 +28,7 @@ RUN sed -i "s|http://archive.ubuntu.com|${apt_archive}|g" /etc/apt/sources.list
|
||||
|
||||
ARG REPO_CHANNEL="stable"
|
||||
ARG REPOSITORY="deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb ${REPO_CHANNEL} main"
|
||||
ARG VERSION="24.10.3.21"
|
||||
ARG VERSION="24.11.1.2557"
|
||||
ARG PACKAGES="clickhouse-client clickhouse-server clickhouse-common-static"
|
||||
|
||||
#docker-official-library:off
|
||||
|
376
docs/changelogs/v24.11.1.2557-stable.md
Normal file
376
docs/changelogs/v24.11.1.2557-stable.md
Normal file
File diff suppressed because one or more lines are too long
@ -6,7 +6,7 @@ sidebar_position: 10
|
||||
|
||||
# Atomic
|
||||
|
||||
It supports non-blocking [DROP TABLE](#drop-detach-table) and [RENAME TABLE](#rename-table) queries and atomic [EXCHANGE TABLES](#exchange-tables) queries. `Atomic` database engine is used by default.
|
||||
It supports non-blocking [DROP TABLE](#drop-detach-table) and [RENAME TABLE](#rename-table) queries and atomic [EXCHANGE TABLES](#exchange-tables) queries. `Atomic` database engine is used by default. Note that on ClickHouse Cloud, the `Replicated` database engine is used by default.
|
||||
|
||||
## Creating a Database {#creating-a-database}
|
||||
|
||||
|
@ -11,11 +11,6 @@ MongoDB engine is read-only table engine which allows to read data from remote [
|
||||
Only MongoDB v3.6+ servers are supported.
|
||||
[Seed list(`mongodb+srv`)](https://www.mongodb.com/docs/manual/reference/glossary/#std-term-seed-list) is not yet supported.
|
||||
|
||||
:::note
|
||||
If you're facing troubles, please report the issue, and try to use [the legacy implementation](../../../operations/server-configuration-parameters/settings.md#use_legacy_mongodb_integration).
|
||||
Keep in mind that it is deprecated, and will be removed in next releases.
|
||||
:::
|
||||
|
||||
## Creating a Table {#creating-a-table}
|
||||
|
||||
``` sql
|
||||
|
@ -3279,15 +3279,7 @@ Default value: 100
|
||||
|
||||
Zero means unlimited
|
||||
|
||||
## use_legacy_mongodb_integration
|
||||
|
||||
Use the legacy MongoDB integration implementation. Deprecated.
|
||||
|
||||
Type: Bool
|
||||
|
||||
Default value: `true`.
|
||||
|
||||
## allowed_feature_tier
|
||||
## allow_feature_tier
|
||||
|
||||
Controls if the user can change settings related to the different feature tiers.
|
||||
0 - Changes to any setting are allowed (experimental, beta, production).
|
||||
|
@ -6,7 +6,11 @@ sidebar_position: 210
|
||||
|
||||
## varPop
|
||||
|
||||
Calculates the population variance.
|
||||
Calculates the population variance:
|
||||
|
||||
$$
|
||||
\frac{\Sigma{(x - \bar{x})^2}}{n}
|
||||
$$
|
||||
|
||||
**Syntax**
|
||||
|
||||
|
@ -17,7 +17,7 @@ To declare a column of `Dynamic` type, use the following syntax:
|
||||
Where `N` is an optional parameter between `0` and `254` indicating how many different data types can be stored as separate subcolumns inside a column with type `Dynamic` across single block of data that is stored separately (for example across single data part for MergeTree table). If this limit is exceeded, all values with new types will be stored together in a special shared data structure in binary form. Default value of `max_types` is `32`.
|
||||
|
||||
:::note
|
||||
The Dynamic data type is an experimental feature. To use it, set `allow_experimental_dynamic_type = 1`.
|
||||
The Dynamic data type is a beta feature. To use it, set `enable_dynamic_type = 1`.
|
||||
:::
|
||||
|
||||
## Creating Dynamic
|
||||
@ -54,7 +54,7 @@ SELECT 'Hello, World!'::Dynamic as d, dynamicType(d);
|
||||
Using CAST from `Variant` column:
|
||||
|
||||
```sql
|
||||
SET allow_experimental_variant_type = 1, use_variant_as_common_type = 1;
|
||||
SET enable_variant_type = 1, use_variant_as_common_type = 1;
|
||||
SELECT multiIf((number % 3) = 0, number, (number % 3) = 1, range(number + 1), NULL)::Dynamic AS d, dynamicType(d) FROM numbers(3)
|
||||
```
|
||||
|
||||
|
@ -10,8 +10,8 @@ keywords: [json, data type]
|
||||
Stores JavaScript Object Notation (JSON) documents in a single column.
|
||||
|
||||
:::note
|
||||
This feature is experimental and is not production-ready. If you need to work with JSON documents, consider using [this guide](/docs/en/integrations/data-formats/json/overview) instead.
|
||||
If you want to use JSON type, set `allow_experimental_json_type = 1`.
|
||||
This feature is beta and is not production-ready. If you need to work with JSON documents, consider using [this guide](/docs/en/integrations/data-formats/json/overview) instead.
|
||||
If you want to use JSON type, set `enable_json_type = 1`.
|
||||
:::
|
||||
|
||||
To declare a column of `JSON` type, use the following syntax:
|
||||
|
@ -18,7 +18,7 @@ because working with values of such types can lead to ambiguity. By default, cre
|
||||
:::
|
||||
|
||||
:::note
|
||||
The Variant data type is an experimental feature. To use it, set `allow_experimental_variant_type = 1`.
|
||||
The Variant data type is a beta feature. To use it, set `enable_variant_type = 1`.
|
||||
:::
|
||||
|
||||
## Creating Variant
|
||||
|
@ -8,11 +8,17 @@ sidebar_position: 9
|
||||
|
||||
Returns a value evaluated at the row that is at a specified physical offset row before the current row within the ordered frame.
|
||||
|
||||
:::warning
|
||||
`lagInFrame` behavior differs from the standard SQL `lag` window function.
|
||||
Clickhouse window function `lagInFrame` respects the window frame.
|
||||
To get behavior identical to the `lag`, use `ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING`.
|
||||
:::
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
lagInFrame(x[, offset[, default]])
|
||||
OVER ([[PARTITION BY grouping_column] [ORDER BY sorting_column]
|
||||
OVER ([[PARTITION BY grouping_column] [ORDER BY sorting_column]
|
||||
[ROWS or RANGE expression_to_bound_rows_withing_the_group]] | [window_name])
|
||||
FROM table_name
|
||||
WINDOW window_name as ([[PARTITION BY grouping_column] [ORDER BY sorting_column])
|
||||
@ -21,7 +27,7 @@ WINDOW window_name as ([[PARTITION BY grouping_column] [ORDER BY sorting_column]
|
||||
For more detail on window function syntax see: [Window Functions - Syntax](./index.md/#syntax).
|
||||
|
||||
**Parameters**
|
||||
- `x` — Column name.
|
||||
- `x` — Column name.
|
||||
- `offset` — Offset to apply. [(U)Int*](../data-types/int-uint.md). (Optional - `1` by default).
|
||||
- `default` — Value to return if calculated row exceeds the boundaries of the window frame. (Optional - default value of column type when omitted).
|
||||
|
||||
@ -59,11 +65,13 @@ INSERT INTO stock_prices FORMAT Values
|
||||
SELECT
|
||||
date,
|
||||
close,
|
||||
lagInFrame(close, 1, close) OVER (ORDER BY date ASC) AS previous_day_close,
|
||||
lagInFrame(close, 1, close) OVER (ORDER BY date ASC
|
||||
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||
) AS previous_day_close,
|
||||
COALESCE(ROUND(close - previous_day_close, 2)) AS delta,
|
||||
COALESCE(ROUND((delta / previous_day_close) * 100, 2)) AS percent_change
|
||||
FROM stock_prices
|
||||
ORDER BY date DESC;
|
||||
ORDER BY date DESC
|
||||
```
|
||||
|
||||
Result:
|
||||
@ -76,4 +84,4 @@ Result:
|
||||
4. │ 2024-06-04 │ 116.44 │ 115 │ 1.44 │ 1.25 │
|
||||
5. │ 2024-06-03 │ 115 │ 115 │ 0 │ 0 │
|
||||
└────────────┴────────┴────────────────────┴───────┴────────────────┘
|
||||
```
|
||||
```
|
||||
|
@ -8,11 +8,17 @@ sidebar_position: 10
|
||||
|
||||
Returns a value evaluated at the row that is offset rows after the current row within the ordered frame.
|
||||
|
||||
:::warning
|
||||
`leadInFrame` behavior differs from the standard SQL `lead` window function.
|
||||
Clickhouse window function `leadInFrame` respects the window frame.
|
||||
To get behavior identical to the `lead`, use `ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING`.
|
||||
:::
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
leadInFrame(x[, offset[, default]])
|
||||
OVER ([[PARTITION BY grouping_column] [ORDER BY sorting_column]
|
||||
OVER ([[PARTITION BY grouping_column] [ORDER BY sorting_column]
|
||||
[ROWS or RANGE expression_to_bound_rows_withing_the_group]] | [window_name])
|
||||
FROM table_name
|
||||
WINDOW window_name as ([[PARTITION BY grouping_column] [ORDER BY sorting_column])
|
||||
@ -36,25 +42,37 @@ This example looks at [historical data](https://www.kaggle.com/datasets/sazidthe
|
||||
Query:
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE VIEW nobel_prize_laureates AS FROM file('nobel_laureates_data.csv') SELECT *;
|
||||
CREATE OR REPLACE VIEW nobel_prize_laureates
|
||||
AS SELECT *
|
||||
FROM file('nobel_laureates_data.csv');
|
||||
```
|
||||
|
||||
```sql
|
||||
FROM nobel_prize_laureates SELECT fullName, leadInFrame(year, 1, year) OVER (PARTITION BY category ORDER BY year) AS year, category, motivation WHERE category == 'physics' ORDER BY year DESC LIMIT 9;
|
||||
SELECT
|
||||
fullName,
|
||||
leadInFrame(year, 1, year) OVER (PARTITION BY category ORDER BY year ASC
|
||||
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||
) AS year,
|
||||
category,
|
||||
motivation
|
||||
FROM nobel_prize_laureates
|
||||
WHERE category = 'physics'
|
||||
ORDER BY year DESC
|
||||
LIMIT 9
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```response
|
||||
┌─fullName─────────┬─year─┬─category─┬─motivation─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
1. │ Pierre Agostini │ 2023 │ physics │ for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter │
|
||||
2. │ Ferenc Krausz │ 2023 │ physics │ for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter │
|
||||
3. │ Anne L Huillier │ 2023 │ physics │ for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter │
|
||||
1. │ Anne L Huillier │ 2023 │ physics │ for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter │
|
||||
2. │ Pierre Agostini │ 2023 │ physics │ for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter │
|
||||
3. │ Ferenc Krausz │ 2023 │ physics │ for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter │
|
||||
4. │ Alain Aspect │ 2022 │ physics │ for experiments with entangled photons establishing the violation of Bell inequalities and pioneering quantum information science │
|
||||
5. │ Anton Zeilinger │ 2022 │ physics │ for experiments with entangled photons establishing the violation of Bell inequalities and pioneering quantum information science │
|
||||
6. │ John Clauser │ 2022 │ physics │ for experiments with entangled photons establishing the violation of Bell inequalities and pioneering quantum information science │
|
||||
7. │ Syukuro Manabe │ 2021 │ physics │ for the physical modelling of Earths climate quantifying variability and reliably predicting global warming │
|
||||
7. │ Giorgio Parisi │ 2021 │ physics │ for the discovery of the interplay of disorder and fluctuations in physical systems from atomic to planetary scales │
|
||||
8. │ Klaus Hasselmann │ 2021 │ physics │ for the physical modelling of Earths climate quantifying variability and reliably predicting global warming │
|
||||
9. │ Giorgio Parisi │ 2021 │ physics │ for the discovery of the interplay of disorder and fluctuations in physical systems from atomic to planetary scales │
|
||||
9. │ Syukuro Manabe │ 2021 │ physics │ for the physical modelling of Earths climate quantifying variability and reliably predicting global warming │
|
||||
└──────────────────┴──────┴──────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
```
|
||||
|
@ -100,7 +100,7 @@ void DiskWithPath::setPath(const String & any_path)
|
||||
String DiskWithPath::validatePathAndGetAsRelative(const String & path)
|
||||
{
|
||||
String lexically_normal_path = fs::path(path).lexically_normal();
|
||||
if (lexically_normal_path.find("..") != std::string::npos)
|
||||
if (lexically_normal_path.contains(".."))
|
||||
throw DB::Exception(DB::ErrorCodes::BAD_ARGUMENTS, "Path {} is not normalized", path);
|
||||
|
||||
/// If path is absolute we should keep it as relative inside disk, so disk will look like
|
||||
|
@ -5,6 +5,7 @@ set (CLICKHOUSE_EXTRACT_FROM_CONFIG_LINK
|
||||
boost::program_options
|
||||
clickhouse_common_config
|
||||
clickhouse_common_io
|
||||
clickhouse_common_zookeeper_base
|
||||
clickhouse_common_zookeeper
|
||||
)
|
||||
|
||||
|
@ -188,9 +188,9 @@ int mainEntryClickHouseFormat(int argc, char ** argv)
|
||||
registerInterpreters();
|
||||
registerFunctions();
|
||||
registerAggregateFunctions();
|
||||
registerTableFunctions(false);
|
||||
registerTableFunctions();
|
||||
registerDatabases();
|
||||
registerStorages(false);
|
||||
registerStorages();
|
||||
registerFormats();
|
||||
|
||||
std::unordered_set<std::string> additional_names;
|
||||
|
@ -7,6 +7,7 @@ set (CLICKHOUSE_KEEPER_LINK
|
||||
PRIVATE
|
||||
clickhouse_common_config
|
||||
clickhouse_common_io
|
||||
clickhouse_common_zookeeper_base
|
||||
clickhouse_common_zookeeper
|
||||
daemon
|
||||
clickhouse-keeper-converter-lib
|
||||
|
@ -79,7 +79,7 @@ namespace Setting
|
||||
|
||||
namespace ServerSetting
|
||||
{
|
||||
extern const ServerSettingsUInt32 allowed_feature_tier;
|
||||
extern const ServerSettingsUInt32 allow_feature_tier;
|
||||
extern const ServerSettingsDouble cache_size_to_ram_max_ratio;
|
||||
extern const ServerSettingsUInt64 compiled_expression_cache_elements_size;
|
||||
extern const ServerSettingsUInt64 compiled_expression_cache_size;
|
||||
@ -111,7 +111,9 @@ namespace ServerSetting
|
||||
extern const ServerSettingsString uncompressed_cache_policy;
|
||||
extern const ServerSettingsUInt64 uncompressed_cache_size;
|
||||
extern const ServerSettingsDouble uncompressed_cache_size_ratio;
|
||||
extern const ServerSettingsBool use_legacy_mongodb_integration;
|
||||
extern const ServerSettingsString primary_index_cache_policy;
|
||||
extern const ServerSettingsUInt64 primary_index_cache_size;
|
||||
extern const ServerSettingsDouble primary_index_cache_size_ratio;
|
||||
}
|
||||
|
||||
namespace ErrorCodes
|
||||
@ -550,10 +552,10 @@ try
|
||||
/// Don't initialize DateLUT
|
||||
registerFunctions();
|
||||
registerAggregateFunctions();
|
||||
registerTableFunctions(server_settings[ServerSetting::use_legacy_mongodb_integration]);
|
||||
registerTableFunctions();
|
||||
registerDatabases();
|
||||
registerStorages(server_settings[ServerSetting::use_legacy_mongodb_integration]);
|
||||
registerDictionaries(server_settings[ServerSetting::use_legacy_mongodb_integration]);
|
||||
registerStorages();
|
||||
registerDictionaries();
|
||||
registerDisks(/* global_skip_access_check= */ true);
|
||||
registerFormats();
|
||||
|
||||
@ -779,6 +781,16 @@ void LocalServer::processConfig()
|
||||
}
|
||||
global_context->setIndexMarkCache(index_mark_cache_policy, index_mark_cache_size, index_mark_cache_size_ratio);
|
||||
|
||||
String primary_index_cache_policy = server_settings[ServerSetting::primary_index_cache_policy];
|
||||
size_t primary_index_cache_size = server_settings[ServerSetting::primary_index_cache_size];
|
||||
double primary_index_cache_size_ratio = server_settings[ServerSetting::primary_index_cache_size_ratio];
|
||||
if (primary_index_cache_size > max_cache_size)
|
||||
{
|
||||
primary_index_cache_size = max_cache_size;
|
||||
LOG_INFO(log, "Lowered primary index cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(primary_index_cache_size));
|
||||
}
|
||||
global_context->setPrimaryIndexCache(primary_index_cache_policy, primary_index_cache_size, primary_index_cache_size_ratio);
|
||||
|
||||
size_t mmap_cache_size = server_settings[ServerSetting::mmap_cache_size];
|
||||
if (mmap_cache_size > max_cache_size)
|
||||
{
|
||||
@ -791,7 +803,7 @@ void LocalServer::processConfig()
|
||||
global_context->setQueryCache(0, 0, 0, 0);
|
||||
|
||||
/// Initialize allowed tiers
|
||||
global_context->getAccessControl().setAllowTierSettings(server_settings[ServerSetting::allowed_feature_tier]);
|
||||
global_context->getAccessControl().setAllowTierSettings(server_settings[ServerSetting::allow_feature_tier]);
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
size_t compiled_expression_cache_max_size_in_bytes = server_settings[ServerSetting::compiled_expression_cache_size];
|
||||
|
@ -8,6 +8,7 @@ set (CLICKHOUSE_SERVER_LINK
|
||||
clickhouse_aggregate_functions
|
||||
clickhouse_common_config
|
||||
clickhouse_common_io
|
||||
clickhouse_common_zookeeper_base
|
||||
clickhouse_common_zookeeper
|
||||
clickhouse_functions
|
||||
clickhouse_parsers
|
||||
|
@ -166,7 +166,7 @@ namespace MergeTreeSetting
|
||||
|
||||
namespace ServerSetting
|
||||
{
|
||||
extern const ServerSettingsUInt32 allowed_feature_tier;
|
||||
extern const ServerSettingsUInt32 allow_feature_tier;
|
||||
extern const ServerSettingsUInt32 asynchronous_heavy_metrics_update_period_s;
|
||||
extern const ServerSettingsUInt32 asynchronous_metrics_update_period_s;
|
||||
extern const ServerSettingsBool asynchronous_metrics_enable_heavy_metrics;
|
||||
@ -280,7 +280,9 @@ namespace ServerSetting
|
||||
extern const ServerSettingsString uncompressed_cache_policy;
|
||||
extern const ServerSettingsUInt64 uncompressed_cache_size;
|
||||
extern const ServerSettingsDouble uncompressed_cache_size_ratio;
|
||||
extern const ServerSettingsBool use_legacy_mongodb_integration;
|
||||
extern const ServerSettingsString primary_index_cache_policy;
|
||||
extern const ServerSettingsUInt64 primary_index_cache_size;
|
||||
extern const ServerSettingsDouble primary_index_cache_size_ratio;
|
||||
}
|
||||
|
||||
}
|
||||
@ -913,10 +915,10 @@ try
|
||||
registerInterpreters();
|
||||
registerFunctions();
|
||||
registerAggregateFunctions();
|
||||
registerTableFunctions(server_settings[ServerSetting::use_legacy_mongodb_integration]);
|
||||
registerTableFunctions();
|
||||
registerDatabases();
|
||||
registerStorages(server_settings[ServerSetting::use_legacy_mongodb_integration]);
|
||||
registerDictionaries(server_settings[ServerSetting::use_legacy_mongodb_integration]);
|
||||
registerStorages();
|
||||
registerDictionaries();
|
||||
registerDisks(/* global_skip_access_check= */ false);
|
||||
registerFormats();
|
||||
registerRemoteFileMetadatas();
|
||||
@ -1563,6 +1565,16 @@ try
|
||||
}
|
||||
global_context->setMarkCache(mark_cache_policy, mark_cache_size, mark_cache_size_ratio);
|
||||
|
||||
String primary_index_cache_policy = server_settings[ServerSetting::primary_index_cache_policy];
|
||||
size_t primary_index_cache_size = server_settings[ServerSetting::primary_index_cache_size];
|
||||
double primary_index_cache_size_ratio = server_settings[ServerSetting::primary_index_cache_size_ratio];
|
||||
if (primary_index_cache_size > max_cache_size)
|
||||
{
|
||||
primary_index_cache_size = max_cache_size;
|
||||
LOG_INFO(log, "Lowered primary index cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(primary_index_cache_size));
|
||||
}
|
||||
global_context->setPrimaryIndexCache(primary_index_cache_policy, primary_index_cache_size, primary_index_cache_size_ratio);
|
||||
|
||||
size_t page_cache_size = server_settings[ServerSetting::page_cache_size];
|
||||
if (page_cache_size != 0)
|
||||
global_context->setPageCache(
|
||||
@ -1772,7 +1784,7 @@ try
|
||||
global_context->setMaxDictionaryNumToWarn(new_server_settings[ServerSetting::max_dictionary_num_to_warn]);
|
||||
global_context->setMaxDatabaseNumToWarn(new_server_settings[ServerSetting::max_database_num_to_warn]);
|
||||
global_context->setMaxPartNumToWarn(new_server_settings[ServerSetting::max_part_num_to_warn]);
|
||||
global_context->getAccessControl().setAllowTierSettings(new_server_settings[ServerSetting::allowed_feature_tier]);
|
||||
global_context->getAccessControl().setAllowTierSettings(new_server_settings[ServerSetting::allow_feature_tier]);
|
||||
/// Only for system.server_settings
|
||||
global_context->setConfigReloaderInterval(new_server_settings[ServerSetting::config_reload_interval_ms]);
|
||||
|
||||
@ -1897,6 +1909,7 @@ try
|
||||
|
||||
global_context->updateUncompressedCacheConfiguration(*config);
|
||||
global_context->updateMarkCacheConfiguration(*config);
|
||||
global_context->updatePrimaryIndexCacheConfiguration(*config);
|
||||
global_context->updateIndexUncompressedCacheConfiguration(*config);
|
||||
global_context->updateIndexMarkCacheConfiguration(*config);
|
||||
global_context->updateMMappedFileCacheConfiguration(*config);
|
||||
|
@ -165,6 +165,8 @@ enum class AccessType : uint8_t
|
||||
M(SYSTEM_DROP_CONNECTIONS_CACHE, "SYSTEM DROP CONNECTIONS CACHE, DROP CONNECTIONS CACHE", GLOBAL, SYSTEM_DROP_CACHE) \
|
||||
M(SYSTEM_PREWARM_MARK_CACHE, "SYSTEM PREWARM MARK, PREWARM MARK CACHE, PREWARM MARKS", GLOBAL, SYSTEM_DROP_CACHE) \
|
||||
M(SYSTEM_DROP_MARK_CACHE, "SYSTEM DROP MARK, DROP MARK CACHE, DROP MARKS", GLOBAL, SYSTEM_DROP_CACHE) \
|
||||
M(SYSTEM_PREWARM_PRIMARY_INDEX_CACHE, "SYSTEM PREWARM PRIMARY INDEX, PREWARM PRIMARY INDEX CACHE, PREWARM PRIMARY INDEX", GLOBAL, SYSTEM_DROP_CACHE) \
|
||||
M(SYSTEM_DROP_PRIMARY_INDEX_CACHE, "SYSTEM DROP PRIMARY INDEX, DROP PRIMARY INDEX CACHE, DROP PRIMARY INDEX", GLOBAL, SYSTEM_DROP_CACHE) \
|
||||
M(SYSTEM_DROP_UNCOMPRESSED_CACHE, "SYSTEM DROP UNCOMPRESSED, DROP UNCOMPRESSED CACHE, DROP UNCOMPRESSED", GLOBAL, SYSTEM_DROP_CACHE) \
|
||||
M(SYSTEM_DROP_MMAP_CACHE, "SYSTEM DROP MMAP, DROP MMAP CACHE, DROP MMAP", GLOBAL, SYSTEM_DROP_CACHE) \
|
||||
M(SYSTEM_DROP_QUERY_CACHE, "SYSTEM DROP QUERY, DROP QUERY CACHE, DROP QUERY", GLOBAL, SYSTEM_DROP_CACHE) \
|
||||
|
@ -414,13 +414,13 @@ SettingsConstraints::Checker SettingsConstraints::getChecker(const Settings & cu
|
||||
if (setting_tier == SettingsTierType::EXPERIMENTAL && !allowed_experimental)
|
||||
return Checker(
|
||||
PreformattedMessage::create(
|
||||
"Cannot modify setting '{}'. Changes to EXPERIMENTAL settings are disabled in the server config ('allowed_feature_tier')",
|
||||
"Cannot modify setting '{}'. Changes to EXPERIMENTAL settings are disabled in the server config ('allow_feature_tier')",
|
||||
setting_name),
|
||||
ErrorCodes::READONLY);
|
||||
if (setting_tier == SettingsTierType::BETA && !allowed_beta)
|
||||
return Checker(
|
||||
PreformattedMessage::create(
|
||||
"Cannot modify setting '{}'. Changes to BETA settings are disabled in the server config ('allowed_feature_tier')",
|
||||
"Cannot modify setting '{}'. Changes to BETA settings are disabled in the server config ('allow_feature_tier')",
|
||||
setting_name),
|
||||
ErrorCodes::READONLY);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ using NodeToSubcolumnTransformer = std::function<void(QueryTreeNodePtr &, Functi
|
||||
|
||||
void optimizeFunctionLength(QueryTreeNodePtr & node, FunctionNode &, ColumnContext & ctx)
|
||||
{
|
||||
/// Replace `length(argument)` with `argument.size0`
|
||||
/// Replace `length(argument)` with `argument.size0`.
|
||||
/// `argument` may be Array or Map.
|
||||
|
||||
NameAndTypePair column{ctx.column.name + ".size0", std::make_shared<DataTypeUInt64>()};
|
||||
@ -56,8 +56,8 @@ void optimizeFunctionLength(QueryTreeNodePtr & node, FunctionNode &, ColumnConte
|
||||
template <bool positive>
|
||||
void optimizeFunctionEmpty(QueryTreeNodePtr &, FunctionNode & function_node, ColumnContext & ctx)
|
||||
{
|
||||
/// Replace `empty(argument)` with `equals(argument.size0, 0)` if positive
|
||||
/// Replace `notEmpty(argument)` with `notEquals(argument.size0, 0)` if not positive
|
||||
/// Replace `empty(argument)` with `equals(argument.size0, 0)` if positive.
|
||||
/// Replace `notEmpty(argument)` with `notEquals(argument.size0, 0)` if not positive.
|
||||
/// `argument` may be Array or Map.
|
||||
|
||||
NameAndTypePair column{ctx.column.name + ".size0", std::make_shared<DataTypeUInt64>()};
|
||||
@ -136,19 +136,25 @@ std::map<std::pair<TypeIndex, String>, NodeToSubcolumnTransformer> node_transfor
|
||||
},
|
||||
{
|
||||
{TypeIndex::Map, "mapKeys"},
|
||||
[](QueryTreeNodePtr & node, FunctionNode & function_node, ColumnContext & ctx)
|
||||
[](QueryTreeNodePtr & node, FunctionNode &, ColumnContext & ctx)
|
||||
{
|
||||
/// Replace `mapKeys(map_argument)` with `map_argument.keys`
|
||||
NameAndTypePair column{ctx.column.name + ".keys", function_node.getResultType()};
|
||||
const auto & data_type_map = assert_cast<const DataTypeMap &>(*ctx.column.type);
|
||||
auto key_type = std::make_shared<DataTypeArray>(data_type_map.getKeyType());
|
||||
|
||||
NameAndTypePair column{ctx.column.name + ".keys", key_type};
|
||||
node = std::make_shared<ColumnNode>(column, ctx.column_source);
|
||||
},
|
||||
},
|
||||
{
|
||||
{TypeIndex::Map, "mapValues"},
|
||||
[](QueryTreeNodePtr & node, FunctionNode & function_node, ColumnContext & ctx)
|
||||
[](QueryTreeNodePtr & node, FunctionNode &, ColumnContext & ctx)
|
||||
{
|
||||
/// Replace `mapValues(map_argument)` with `map_argument.values`
|
||||
NameAndTypePair column{ctx.column.name + ".values", function_node.getResultType()};
|
||||
const auto & data_type_map = assert_cast<const DataTypeMap &>(*ctx.column.type);
|
||||
auto value_type = std::make_shared<DataTypeArray>(data_type_map.getValueType());
|
||||
|
||||
NameAndTypePair column{ctx.column.name + ".values", value_type};
|
||||
node = std::make_shared<ColumnNode>(column, ctx.column_source);
|
||||
},
|
||||
},
|
||||
@ -439,11 +445,16 @@ public:
|
||||
if (!identifiers_to_optimize.contains(qualified_name))
|
||||
return;
|
||||
|
||||
auto result_type = function_node->getResultType();
|
||||
auto transformer_it = node_transformers.find({column.type->getTypeId(), function_node->getFunctionName()});
|
||||
|
||||
if (transformer_it != node_transformers.end())
|
||||
{
|
||||
ColumnContext ctx{std::move(column), first_argument_column_node->getColumnSource(), getContext()};
|
||||
transformer_it->second(node, *function_node, ctx);
|
||||
|
||||
if (!result_type->equals(*node->getResultType()))
|
||||
node = buildCastFunction(node, result_type, getContext());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -107,14 +107,8 @@ list (REMOVE_ITEM clickhouse_common_io_sources Common/malloc.cpp Common/new_dele
|
||||
|
||||
|
||||
add_headers_and_sources(clickhouse_compression Compression)
|
||||
add_headers_and_sources(clickhouse_compression Parsers)
|
||||
add_headers_and_sources(clickhouse_compression Core)
|
||||
#Included these specific files to avoid linking grpc
|
||||
add_glob(clickhouse_compression_headers Server/ServerType.h)
|
||||
add_glob(clickhouse_compression_sources Server/ServerType.cpp)
|
||||
add_library(clickhouse_compression ${clickhouse_compression_headers} ${clickhouse_compression_sources})
|
||||
|
||||
|
||||
add_headers_and_sources(dbms Disks/IO)
|
||||
add_headers_and_sources(dbms Disks/ObjectStorages)
|
||||
if (TARGET ch_contrib::sqlite)
|
||||
@ -222,7 +216,6 @@ add_object_library(clickhouse_access Access)
|
||||
add_object_library(clickhouse_backups Backups)
|
||||
add_object_library(clickhouse_core Core)
|
||||
add_object_library(clickhouse_core_mysql Core/MySQL)
|
||||
add_object_library(clickhouse_compression Compression)
|
||||
add_object_library(clickhouse_querypipeline QueryPipeline)
|
||||
add_object_library(clickhouse_datatypes DataTypes)
|
||||
add_object_library(clickhouse_datatypes_serializations DataTypes/Serializations)
|
||||
@ -422,6 +415,7 @@ dbms_target_link_libraries (
|
||||
boost::filesystem
|
||||
boost::program_options
|
||||
clickhouse_common_config
|
||||
clickhouse_common_zookeeper_base
|
||||
clickhouse_common_zookeeper
|
||||
clickhouse_dictionaries_embedded
|
||||
clickhouse_parsers
|
||||
@ -429,14 +423,11 @@ dbms_target_link_libraries (
|
||||
Poco::JSON
|
||||
PUBLIC
|
||||
boost::system
|
||||
clickhouse_compression
|
||||
clickhouse_common_io
|
||||
Poco::Redis
|
||||
)
|
||||
|
||||
if (USE_MONGODB)
|
||||
dbms_target_link_libraries (PUBLIC Poco::MongoDB)
|
||||
endif()
|
||||
|
||||
if (TARGET ch_contrib::mongocxx)
|
||||
dbms_target_link_libraries(
|
||||
PUBLIC
|
||||
@ -666,6 +657,7 @@ if (ENABLE_TESTS)
|
||||
clickhouse_parsers
|
||||
clickhouse_storages_system
|
||||
dbms
|
||||
clickhouse_common_zookeeper_base
|
||||
clickhouse_common_config
|
||||
clickhouse_common_zookeeper
|
||||
hilite_comparator)
|
||||
|
@ -2614,7 +2614,7 @@ bool ClientBase::addMergeTreeSettings(ASTCreateQuery & ast_create)
|
||||
|| !ast_create.storage
|
||||
|| !ast_create.storage->isExtendedStorageDefinition()
|
||||
|| !ast_create.storage->engine
|
||||
|| ast_create.storage->engine->name.find("MergeTree") == std::string::npos)
|
||||
|| !ast_create.storage->engine->name.contains("MergeTree"))
|
||||
return false;
|
||||
|
||||
auto all_changed = cmd_merge_tree_settings.changes();
|
||||
|
@ -426,29 +426,90 @@ void ColumnLowCardinality::getPermutation(IColumn::PermutationSortDirection dire
|
||||
getPermutationImpl(direction, stability, limit, nan_direction_hint, res);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/// Comparator for sorting LowCardinality column with the help of sorted dictionary.
|
||||
/// NOTE: Dictionary itself must be sorted in ASC or DESC order depending on the requested direction.
|
||||
template <typename IndexColumn, bool stable>
|
||||
struct LowCardinalityComparator
|
||||
{
|
||||
const IndexColumn & real_indexes; /// Indexes column
|
||||
const PaddedPODArray<UInt64> & position_by_index; /// Maps original dictionary index to position in sorted dictionary
|
||||
|
||||
inline bool operator () (size_t lhs, size_t rhs) const
|
||||
{
|
||||
int ret;
|
||||
|
||||
const UInt64 lhs_index = real_indexes.getUInt(lhs);
|
||||
const UInt64 rhs_index = real_indexes.getUInt(rhs);
|
||||
|
||||
if (lhs_index == rhs_index)
|
||||
ret = 0;
|
||||
else
|
||||
ret = CompareHelper<UInt64>::compare(position_by_index[lhs_index], position_by_index[rhs_index], 0);
|
||||
|
||||
if (stable && ret == 0)
|
||||
return lhs < rhs;
|
||||
|
||||
return ret < 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename IndexColumn>
|
||||
void ColumnLowCardinality::updatePermutationWithIndexType(
|
||||
IColumn::PermutationSortStability stability, size_t limit, const PaddedPODArray<UInt64> & position_by_index,
|
||||
IColumn::Permutation & res, EqualRanges & equal_ranges) const
|
||||
{
|
||||
/// Cast indexes column to the real type so that compareAt and getUInt methods can be inlined.
|
||||
const IndexColumn * real_indexes = assert_cast<const IndexColumn *>(&getIndexes());
|
||||
|
||||
auto equal_comparator = [real_indexes](size_t lhs, size_t rhs)
|
||||
{
|
||||
return real_indexes->getUInt(lhs) == real_indexes->getUInt(rhs);
|
||||
};
|
||||
|
||||
const bool stable = (stability == IColumn::PermutationSortStability::Stable);
|
||||
if (stable)
|
||||
updatePermutationImpl(limit, res, equal_ranges, LowCardinalityComparator<IndexColumn, true>{*real_indexes, position_by_index}, equal_comparator, DefaultSort(), DefaultPartialSort());
|
||||
else
|
||||
updatePermutationImpl(limit, res, equal_ranges, LowCardinalityComparator<IndexColumn, false>{*real_indexes, position_by_index}, equal_comparator, DefaultSort(), DefaultPartialSort());
|
||||
}
|
||||
|
||||
void ColumnLowCardinality::updatePermutation(IColumn::PermutationSortDirection direction, IColumn::PermutationSortStability stability,
|
||||
size_t limit, int nan_direction_hint, IColumn::Permutation & res, EqualRanges & equal_ranges) const
|
||||
{
|
||||
bool ascending = direction == IColumn::PermutationSortDirection::Ascending;
|
||||
IColumn::Permutation dict_perm;
|
||||
getDictionary().getNestedColumn()->getPermutation(direction, stability, 0, nan_direction_hint, dict_perm);
|
||||
|
||||
auto comparator = [this, ascending, stability, nan_direction_hint](size_t lhs, size_t rhs)
|
||||
/// This is a paranoid check, but in other places in code empty permutation is used to indicate that no sorting is needed.
|
||||
if (dict_perm.size() != getDictionary().size())
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR,
|
||||
"Dictionary permutation size {} is equal to dictionary size {}. It is a bug.",
|
||||
dict_perm.size(), getDictionary().size());
|
||||
PaddedPODArray<UInt64> position_by_index(dict_perm.size());
|
||||
for (size_t i = 0; i < dict_perm.size(); ++i)
|
||||
position_by_index[dict_perm[i]] = i;
|
||||
|
||||
/// Dispatch by index column type.
|
||||
switch (idx.getSizeOfIndexType())
|
||||
{
|
||||
int ret = getDictionary().compareAt(getIndexes().getUInt(lhs), getIndexes().getUInt(rhs), getDictionary(), nan_direction_hint);
|
||||
if (unlikely(stability == IColumn::PermutationSortStability::Stable && ret == 0))
|
||||
return lhs < rhs;
|
||||
|
||||
if (ascending)
|
||||
return ret < 0;
|
||||
return ret > 0;
|
||||
};
|
||||
|
||||
auto equal_comparator = [this, nan_direction_hint](size_t lhs, size_t rhs)
|
||||
{
|
||||
int ret = getDictionary().compareAt(getIndexes().getUInt(lhs), getIndexes().getUInt(rhs), getDictionary(), nan_direction_hint);
|
||||
return ret == 0;
|
||||
};
|
||||
|
||||
updatePermutationImpl(limit, res, equal_ranges, comparator, equal_comparator, DefaultSort(), DefaultPartialSort());
|
||||
case sizeof(UInt8):
|
||||
updatePermutationWithIndexType<ColumnUInt8>(stability, limit, position_by_index, res, equal_ranges);
|
||||
return;
|
||||
case sizeof(UInt16):
|
||||
updatePermutationWithIndexType<ColumnUInt16>(stability, limit, position_by_index, res, equal_ranges);
|
||||
return;
|
||||
case sizeof(UInt32):
|
||||
updatePermutationWithIndexType<ColumnUInt32>(stability, limit, position_by_index, res, equal_ranges);
|
||||
return;
|
||||
case sizeof(UInt64):
|
||||
updatePermutationWithIndexType<ColumnUInt64>(stability, limit, position_by_index, res, equal_ranges);
|
||||
return;
|
||||
default: throw Exception(ErrorCodes::LOGICAL_ERROR, "Unexpected size of index type for low cardinality column.");
|
||||
}
|
||||
}
|
||||
|
||||
void ColumnLowCardinality::getPermutationWithCollation(const Collator & collator, IColumn::PermutationSortDirection direction, IColumn::PermutationSortStability stability,
|
||||
|
@ -190,6 +190,26 @@ public:
|
||||
callback(dictionary.getColumnUniquePtr());
|
||||
}
|
||||
|
||||
void forEachSubcolumnRecursively(RecursiveColumnCallback callback) const override
|
||||
{
|
||||
/** It is important to have both const and non-const versions here.
|
||||
* The behavior of ColumnUnique::forEachSubcolumnRecursively differs between const and non-const versions.
|
||||
* The non-const version will update a field in ColumnUnique.
|
||||
* In the meantime, the default implementation IColumn::forEachSubcolumnRecursively uses const_cast,
|
||||
* so when the const version is called, the field will still be mutated.
|
||||
* This can lead to a data race if constness is expected.
|
||||
*/
|
||||
callback(*idx.getPositionsPtr());
|
||||
idx.getPositionsPtr()->forEachSubcolumnRecursively(callback);
|
||||
|
||||
/// Column doesn't own dictionary if it's shared.
|
||||
if (!dictionary.isShared())
|
||||
{
|
||||
callback(*dictionary.getColumnUniquePtr());
|
||||
dictionary.getColumnUniquePtr()->forEachSubcolumnRecursively(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void forEachSubcolumnRecursively(RecursiveMutableColumnCallback callback) override
|
||||
{
|
||||
callback(*idx.getPositionsPtr());
|
||||
@ -389,6 +409,11 @@ private:
|
||||
int compareAtImpl(size_t n, size_t m, const IColumn & rhs, int nan_direction_hint, const Collator * collator=nullptr) const;
|
||||
|
||||
void getPermutationImpl(IColumn::PermutationSortDirection direction, IColumn::PermutationSortStability stability, size_t limit, int nan_direction_hint, Permutation & res, const Collator * collator = nullptr) const;
|
||||
|
||||
template <typename IndexColumn>
|
||||
void updatePermutationWithIndexType(
|
||||
IColumn::PermutationSortStability stability, size_t limit, const PaddedPODArray<UInt64> & position_by_index,
|
||||
IColumn::Permutation & res, EqualRanges & equal_ranges) const;
|
||||
};
|
||||
|
||||
bool isColumnLowCardinalityNullable(const IColumn & column);
|
||||
|
@ -41,7 +41,7 @@ namespace
|
||||
#if defined(DEBUG_OR_SANITIZER_BUILD)
|
||||
/// Compound `ignore_keys` are not yet implemented.
|
||||
for (const auto & ignore_key : *ignore_keys)
|
||||
chassert(ignore_key.find('.') == std::string_view::npos);
|
||||
chassert(!ignore_key.contains('.'));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -11,20 +11,12 @@ set (SRCS
|
||||
add_library(clickhouse_common_config ${SRCS})
|
||||
target_link_libraries(clickhouse_common_config
|
||||
PUBLIC
|
||||
clickhouse_common_zookeeper_base
|
||||
clickhouse_common_zookeeper
|
||||
common
|
||||
Poco::XML
|
||||
)
|
||||
|
||||
add_library(clickhouse_common_config_no_zookeeper_log ${SRCS})
|
||||
target_link_libraries(clickhouse_common_config_no_zookeeper_log
|
||||
PUBLIC
|
||||
clickhouse_common_zookeeper_no_log
|
||||
common
|
||||
Poco::XML
|
||||
)
|
||||
|
||||
if (TARGET ch_contrib::yaml_cpp)
|
||||
target_link_libraries(clickhouse_common_config PRIVATE ch_contrib::yaml_cpp)
|
||||
target_link_libraries(clickhouse_common_config_no_zookeeper_log PRIVATE ch_contrib::yaml_cpp)
|
||||
endif()
|
||||
|
@ -79,6 +79,8 @@ static struct InitFiu
|
||||
REGULAR(zero_copy_lock_zk_fail_after_op) \
|
||||
REGULAR(plain_object_storage_write_fail_on_directory_create) \
|
||||
REGULAR(plain_object_storage_write_fail_on_directory_move) \
|
||||
REGULAR(zero_copy_unlock_zk_fail_before_op) \
|
||||
REGULAR(zero_copy_unlock_zk_fail_after_op) \
|
||||
|
||||
|
||||
namespace FailPoints
|
||||
|
@ -38,7 +38,7 @@ String FileRenamer::generateNewFilename(const String & filename) const
|
||||
|
||||
// Get current timestamp in microseconds
|
||||
String timestamp;
|
||||
if (rule.find("%t") != String::npos)
|
||||
if (rule.contains("%t"))
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
timestamp = std::to_string(timeInMicroseconds(now));
|
||||
|
@ -53,7 +53,7 @@ String Macros::expand(const String & s,
|
||||
/// Do not allow recursion if we expand only special macros, because it will be infinite recursion
|
||||
assert(info.level == 0 || !info.expand_special_macros_only);
|
||||
|
||||
if (s.find('{') == String::npos)
|
||||
if (!s.contains('{'))
|
||||
return s;
|
||||
|
||||
if (info.level && s.size() > 65536)
|
||||
|
@ -63,6 +63,8 @@
|
||||
M(TableFunctionExecute, "Number of table function calls.", ValueType::Number) \
|
||||
M(MarkCacheHits, "Number of times an entry has been found in the mark cache, so we didn't have to load a mark file.", ValueType::Number) \
|
||||
M(MarkCacheMisses, "Number of times an entry has not been found in the mark cache, so we had to load a mark file in memory, which is a costly operation, adding to query latency.", ValueType::Number) \
|
||||
M(PrimaryIndexCacheHits, "Number of times an entry has been found in the primary index cache, so we didn't have to load a index file.", ValueType::Number) \
|
||||
M(PrimaryIndexCacheMisses, "Number of times an entry has not been found in the primary index cache, so we had to load a index file in memory, which is a costly operation, adding to query latency.", ValueType::Number) \
|
||||
M(QueryCacheHits, "Number of times a query result has been found in the query cache (and query computation was avoided). Only updated for SELECT queries with SETTING use_query_cache = 1.", ValueType::Number) \
|
||||
M(QueryCacheMisses, "Number of times a query result has not been found in the query cache (and required query computation). Only updated for SELECT queries with SETTING use_query_cache = 1.", ValueType::Number) \
|
||||
/* Each page cache chunk access increments exactly one of the following 5 PageCacheChunk* counters. */ \
|
||||
@ -229,6 +231,9 @@
|
||||
M(BackgroundLoadingMarksTasks, "Number of background tasks for loading marks", ValueType::Number) \
|
||||
M(LoadedMarksCount, "Number of marks loaded (total across columns).", ValueType::Number) \
|
||||
M(LoadedMarksMemoryBytes, "Size of in-memory representations of loaded marks.", ValueType::Bytes) \
|
||||
M(LoadedPrimaryIndexFiles, "Number of primary index files loaded.", ValueType::Number) \
|
||||
M(LoadedPrimaryIndexRows, "Number of rows of primary key loaded.", ValueType::Number) \
|
||||
M(LoadedPrimaryIndexBytes, "Number of rows of primary key loaded.", ValueType::Bytes) \
|
||||
\
|
||||
M(Merge, "Number of launched background merges.", ValueType::Number) \
|
||||
M(MergeSourceParts, "Number of source parts scheduled for merges.", ValueType::Number) \
|
||||
|
@ -2,10 +2,20 @@ include("${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake")
|
||||
|
||||
add_headers_and_sources(clickhouse_common_zookeeper .)
|
||||
|
||||
list(APPEND clickhouse_common_zookeeper_sources ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/Coordination/KeeperFeatureFlags.cpp)
|
||||
# Needs to be built differently depending on ZOOKEEPER_LOG
|
||||
list(REMOVE_ITEM clickhouse_common_zookeeper_sources "ZooKeeperImpl.cpp")
|
||||
|
||||
|
||||
add_library(clickhouse_common_zookeeper_base ${clickhouse_common_zookeeper_headers} ${clickhouse_common_zookeeper_sources})
|
||||
target_link_libraries (clickhouse_common_zookeeper_base
|
||||
PUBLIC
|
||||
clickhouse_common_io
|
||||
clickhouse_compression
|
||||
common
|
||||
)
|
||||
|
||||
# for clickhouse server
|
||||
add_library(clickhouse_common_zookeeper ${clickhouse_common_zookeeper_headers} ${clickhouse_common_zookeeper_sources})
|
||||
add_library(clickhouse_common_zookeeper ZooKeeperImpl.cpp)
|
||||
target_compile_definitions (clickhouse_common_zookeeper PRIVATE -DZOOKEEPER_LOG)
|
||||
target_link_libraries (clickhouse_common_zookeeper
|
||||
PUBLIC
|
||||
@ -15,7 +25,7 @@ target_link_libraries (clickhouse_common_zookeeper
|
||||
)
|
||||
|
||||
# for examples -- no logging (to avoid extra dependencies)
|
||||
add_library(clickhouse_common_zookeeper_no_log ${clickhouse_common_zookeeper_headers} ${clickhouse_common_zookeeper_sources})
|
||||
add_library(clickhouse_common_zookeeper_no_log ZooKeeperImpl.cpp)
|
||||
target_link_libraries (clickhouse_common_zookeeper_no_log
|
||||
PUBLIC
|
||||
clickhouse_common_io
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <base/types.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Coordination/KeeperFeatureFlags.h>
|
||||
#include <Common/ZooKeeper/KeeperFeatureFlags.h>
|
||||
#include <Poco/Net/SocketAddress.h>
|
||||
|
||||
#include <vector>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <Coordination/KeeperFeatureFlags.h>
|
||||
#include <Common/ZooKeeper/KeeperFeatureFlags.h>
|
||||
#include <Common/ErrorCodes.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/logger_useful.h>
|
@ -11,7 +11,7 @@
|
||||
#include <Common/ZooKeeper/ZooKeeperArgs.h>
|
||||
#include <Common/ThreadPool.h>
|
||||
#include <Common/ConcurrentBoundedQueue.h>
|
||||
#include <Coordination/KeeperFeatureFlags.h>
|
||||
#include <Common/ZooKeeper/KeeperFeatureFlags.h>
|
||||
|
||||
|
||||
namespace Coordination
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "ZooKeeper.h"
|
||||
#include "Coordination/KeeperFeatureFlags.h"
|
||||
#include "Common/ZooKeeper/KeeperFeatureFlags.h"
|
||||
#include "ZooKeeperImpl.h"
|
||||
#include "KeeperException.h"
|
||||
#include "TestKeeper.h"
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <Common/ZooKeeper/ZooKeeperConstants.h>
|
||||
#include <Common/ZooKeeper/ZooKeeperArgs.h>
|
||||
#include <Common/thread_local_rng.h>
|
||||
#include <Coordination/KeeperFeatureFlags.h>
|
||||
#include <Common/ZooKeeper/KeeperFeatureFlags.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
@ -206,7 +206,7 @@ std::string ZooKeeperAuthRequest::toStringImpl(bool /*short_format*/) const
|
||||
void ZooKeeperCreateRequest::writeImpl(WriteBuffer & out) const
|
||||
{
|
||||
/// See https://github.com/ClickHouse/clickhouse-private/issues/3029
|
||||
if (path.starts_with("/clickhouse/tables/") && path.find("/parts/") != std::string::npos)
|
||||
if (path.starts_with("/clickhouse/tables/") && path.contains("/parts/"))
|
||||
{
|
||||
LOG_TRACE(getLogger(__PRETTY_FUNCTION__), "Creating part at path {}", path);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <Common/ZooKeeper/ZooKeeperArgs.h>
|
||||
#include <Common/ZooKeeper/ZooKeeper.h>
|
||||
#include <Coordination/KeeperConstants.h>
|
||||
#include <Coordination/KeeperFeatureFlags.h>
|
||||
#include <Common/ZooKeeper/KeeperFeatureFlags.h>
|
||||
|
||||
#include <IO/ReadBuffer.h>
|
||||
#include <IO/WriteBuffer.h>
|
||||
|
@ -1,15 +1,15 @@
|
||||
clickhouse_add_executable(zkutil_test_commands zkutil_test_commands.cpp)
|
||||
target_link_libraries(zkutil_test_commands PRIVATE
|
||||
clickhouse_common_zookeeper_no_log
|
||||
clickhouse_common_zookeeper_base clickhouse_common_zookeeper_no_log
|
||||
dbms)
|
||||
|
||||
clickhouse_add_executable(zkutil_test_commands_new_lib zkutil_test_commands_new_lib.cpp)
|
||||
target_link_libraries(zkutil_test_commands_new_lib PRIVATE
|
||||
clickhouse_common_zookeeper_no_log
|
||||
clickhouse_common_zookeeper_base clickhouse_common_zookeeper_no_log
|
||||
clickhouse_compression
|
||||
dbms)
|
||||
|
||||
clickhouse_add_executable(zkutil_test_async zkutil_test_async.cpp)
|
||||
target_link_libraries(zkutil_test_async PRIVATE
|
||||
clickhouse_common_zookeeper_no_log
|
||||
clickhouse_common_zookeeper_base clickhouse_common_zookeeper_no_log
|
||||
dbms)
|
||||
|
@ -143,13 +143,13 @@ try
|
||||
std::string key = line.substr(0, pos);
|
||||
std::string val = line.substr(pos + 1);
|
||||
|
||||
if (key.find("physical id") != std::string::npos)
|
||||
if (key.contains("physical id"))
|
||||
{
|
||||
cur_core_entry.first = std::stoi(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key.find("core id") != std::string::npos)
|
||||
if (key.contains("core id"))
|
||||
{
|
||||
cur_core_entry.second = std::stoi(val);
|
||||
core_entries.insert(cur_core_entry);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user