2018-09-27 15:23:42 +00:00
# include "IdentifierQuoteHandler.h"
2020-05-08 14:11:19 +00:00
# if USE_ODBC
2021-03-22 11:40:29 +00:00
# include <DataTypes/DataTypeFactory.h>
# include <Server/HTTP/HTMLForm.h>
# include <Server/HTTP/WriteBufferFromHTTPServerResponse.h>
2022-08-10 07:39:32 +00:00
# include <IO/ReadHelpers.h>
2021-03-22 11:40:29 +00:00
# include <IO/WriteHelpers.h>
# include <Poco/Net/HTTPServerRequest.h>
# include <Poco/Net/HTTPServerResponse.h>
2022-08-08 14:40:19 +00:00
# include <Common/BridgeProtocolVersion.h>
2022-04-27 15:05:45 +00:00
# include <Common/logger_useful.h>
2024-07-11 12:00:05 +00:00
# include <Core/Settings.h>
2021-03-22 11:40:29 +00:00
# include "getIdentifierQuote.h"
# include "validateODBCConnectionString.h"
2022-06-01 09:00:39 +00:00
# include "ODBCPooledConnectionFactory.h"
2021-03-31 12:41:12 +00:00
2018-09-27 15:23:42 +00:00
namespace DB
{
2024-09-18 12:20:53 +00:00
namespace Setting
{
extern const SettingsUInt64 odbc_bridge_connection_pool_size ;
}
2024-01-03 16:47:15 +00:00
void IdentifierQuoteHandler : : handleRequest ( HTTPServerRequest & request , HTTPServerResponse & response , const ProfileEvents : : Event & /*write_event*/ )
2018-09-27 15:23:42 +00:00
{
2021-06-16 14:33:14 +00:00
HTMLForm params ( getContext ( ) - > getSettingsRef ( ) , request , request . getStream ( ) ) ;
2020-05-23 22:24:01 +00:00
LOG_TRACE ( log , " Request URI: {} " , request . getURI ( ) ) ;
2018-09-27 15:23:42 +00:00
2018-10-10 08:38:54 +00:00
auto process_error = [ & response , this ] ( const std : : string & message )
{
2018-09-27 15:23:42 +00:00
response . setStatusAndReason ( Poco : : Net : : HTTPResponse : : HTTP_INTERNAL_SERVER_ERROR ) ;
if ( ! response . sent ( ) )
2024-01-03 16:47:15 +00:00
response . send ( ) - > writeln ( message ) ;
Use fmt::runtime() for LOG_* for non constexpr
Here is oneliner:
$ gg 'LOG_\(DEBUG\|TRACE\|INFO\|TEST\|WARNING\|ERROR\|FATAL\)([^,]*, [a-zA-Z]' -- :*.cpp :*.h | cut -d: -f1 | sort -u | xargs -r sed -E -i 's#(LOG_[A-Z]*)\(([^,]*), ([A-Za-z][^,)]*)#\1(\2, fmt::runtime(\3)#'
Note, that I tried to do this with coccinelle (tool for semantic
patchin), but it cannot parse C++:
$ cat fmt.cocci
@@
expression log;
expression var;
@@
-LOG_DEBUG(log, var)
+LOG_DEBUG(log, fmt::runtime(var))
I've also tried to use some macros/templates magic to do this implicitly
in logger_useful.h, but I failed to do so, and apparently it is not
possible for now.
Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
v2: manual fixes
Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
2022-02-01 09:10:27 +00:00
LOG_WARNING ( log , fmt : : runtime ( message ) ) ;
2018-09-27 15:23:42 +00:00
} ;
2022-08-10 07:39:32 +00:00
size_t version ;
2022-08-08 14:40:19 +00:00
if ( ! params . has ( " version " ) )
2022-08-10 07:39:32 +00:00
version = 0 ; /// assumed version for too old servers which do not send a version
2022-08-08 14:40:19 +00:00
else
{
String version_str = params . get ( " version " ) ;
2022-08-10 07:39:32 +00:00
if ( ! tryParse ( version , version_str ) )
2022-08-08 14:40:19 +00:00
{
process_error ( " Unable to parse 'version' string in request URL: ' " + version_str + " ' Check if the server and library-bridge have the same version. " ) ;
return ;
}
2022-08-10 07:39:32 +00:00
}
if ( version ! = XDBC_BRIDGE_PROTOCOL_VERSION )
{
/// backwards compatibility is considered unnecessary for now, just let the user know that the server and the bridge must be upgraded together
process_error ( " Server and library-bridge have different versions: ' " + std : : to_string ( version ) + " ' vs. ' " + std : : to_string ( LIBRARY_BRIDGE_PROTOCOL_VERSION ) + " ' " ) ;
return ;
2022-08-08 14:40:19 +00:00
}
2018-09-28 02:46:33 +00:00
if ( ! params . has ( " connection_string " ) )
2018-09-27 15:23:42 +00:00
{
process_error ( " No 'connection_string' in request URL " ) ;
return ;
}
2023-01-19 00:36:25 +00:00
bool use_connection_pooling = params . getParsed < bool > ( " use_connection_pooling " , true ) ;
2018-09-27 15:23:42 +00:00
try
{
std : : string connection_string = params . get ( " connection_string " ) ;
2021-04-06 18:59:34 +00:00
2023-01-19 00:36:25 +00:00
nanodbc : : ConnectionHolderPtr connection ;
if ( use_connection_pooling )
connection = ODBCPooledConnectionFactory : : instance ( ) . get (
2024-09-18 12:20:53 +00:00
validateODBCConnectionString ( connection_string ) , getContext ( ) - > getSettingsRef ( ) [ Setting : : odbc_bridge_connection_pool_size ] ) ;
2023-01-19 00:36:25 +00:00
else
connection = std : : make_shared < nanodbc : : ConnectionHolder > ( validateODBCConnectionString ( connection_string ) ) ;
2021-04-06 18:59:34 +00:00
2021-06-07 18:09:16 +00:00
auto identifier = getIdentifierQuote ( std : : move ( connection ) ) ;
2018-09-27 15:23:42 +00:00
2024-03-22 20:07:12 +00:00
WriteBufferFromHTTPServerResponse out ( response , request . getMethod ( ) = = Poco : : Net : : HTTPRequest : : HTTP_HEAD ) ;
2024-09-26 08:27:37 +00:00
writeStringBinary ( identifier , out ) ;
out . finalize ( ) ;
2018-09-27 15:23:42 +00:00
}
catch ( . . . )
{
process_error ( " Error getting identifier quote style from ODBC ' " + getCurrentExceptionMessage ( false ) + " ' " ) ;
tryLogCurrentException ( log ) ;
}
}
2020-05-08 14:11:19 +00:00
2018-09-27 15:23:42 +00:00
}
2020-05-08 14:11:19 +00:00
2018-10-10 08:38:54 +00:00
# endif