Skip to content

Commit 2e35b16

Browse files
authored
Merge pull request #489 from ilejn/reinstate-autogenerated-session-id
Reinstate autogenerated session
2 parents f1f2c9c + 6d864a7 commit 2e35b16

File tree

8 files changed

+43
-4
lines changed

8 files changed

+43
-4
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ The list of DSN parameters recognized by the driver is as follows:
109109
| `HugeIntAsString` | `off` | Report integer column types that may underflow or overflow 64-bit signed integer (`SQL_BIGINT`) as a `String`/`SQL_VARCHAR` |
110110
| `DriverLog` | `on` if `CMAKE_BUILD_TYPE` is `Debug`, `off` otherwise | Enable or disable the extended driver logging |
111111
| `DriverLogFile` | `\temp\clickhouse-odbc-driver.log` on Windows, `/tmp/clickhouse-odbc-driver.log` otherwise | Path to the extended driver log file (used when `DriverLog` is `on`) |
112+
| `AutoSessionId` | `off` | Auto generate session_id required to use some features of CH (e.g. TEMPORARY TABLE) |
112113

113114
### URL query string
114115

driver/config/config.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ void readDSNinfo(ConnInfo * ci, bool overwrite) {
5858
GET_CONFIG(stringmaxlength, INI_STRINGMAXLENGTH, INI_STRINGMAXLENGTH_DEFAULT);
5959
GET_CONFIG(driverlog, INI_DRIVERLOG, INI_DRIVERLOG_DEFAULT);
6060
GET_CONFIG(driverlogfile, INI_DRIVERLOGFILE, INI_DRIVERLOGFILE_DEFAULT);
61+
GET_CONFIG(auto_session_id, INI_AUTO_SESSION_ID, INI_AUTO_SESSION_ID_DEFAULT);
6162

6263
#undef GET_CONFIG
6364
}
@@ -99,6 +100,7 @@ void writeDSNinfo(const ConnInfo * ci) {
99100
WRITE_CONFIG(stringmaxlength, INI_STRINGMAXLENGTH);
100101
WRITE_CONFIG(driverlog, INI_DRIVERLOG);
101102
WRITE_CONFIG(driverlogfile, INI_DRIVERLOGFILE);
103+
WRITE_CONFIG(auto_session_id, INI_AUTO_SESSION_ID);
102104

103105
#undef WRITE_CONFIG
104106
}
@@ -342,7 +344,8 @@ key_value_map_t readDSNInfo(const std::string & dsn_utf8) {
342344
INI_DATABASE,
343345
INI_STRINGMAXLENGTH,
344346
INI_DRIVERLOG,
345-
INI_DRIVERLOGFILE
347+
INI_DRIVERLOGFILE,
348+
INI_AUTO_SESSION_ID
346349
}
347350
) {
348351
if (

driver/config/config.h

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct ConnInfo {
3232
std::string stringmaxlength;
3333
std::string driverlog;
3434
std::string driverlogfile;
35+
std::string auto_session_id;
3536
};
3637

3738
void readDSNinfo(ConnInfo * ci, bool overwrite);

driver/config/ini_defines.h

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#define INI_STRINGMAXLENGTH "StringMaxLength"
3232
#define INI_DRIVERLOG "DriverLog"
3333
#define INI_DRIVERLOGFILE "DriverLogFile"
34+
#define INI_AUTO_SESSION_ID "AutoSessionId"
3435

3536
#if defined(UNICODE)
3637
# define INI_DSN_DEFAULT DSN_DEFAULT_UNICODE
@@ -50,6 +51,7 @@
5051
#define INI_DATABASE_DEFAULT ""
5152
#define INI_HUGE_INT_AS_STRING_DEFAULT "off"
5253
#define INI_STRINGMAXLENGTH_DEFAULT "1048575"
54+
#define INI_AUTO_SESSION_ID_DEFAULT "off"
5355

5456
#ifdef NDEBUG
5557
# define INI_DRIVERLOG_DEFAULT "off"

driver/connection.cpp

+26-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <Poco/Net/HTTPClientSession.h>
99
#include <Poco/NumberParser.h> // TODO: switch to std
1010
#include <Poco/URI.h>
11+
#include <random>
1112

1213
#if !defined(WORKAROUND_DISABLE_SSL)
1314
# include <Poco/Net/AcceptCertificateHandler.h>
@@ -47,8 +48,15 @@ void SSLInit(bool ssl_strict, const std::string & privateKeyFile, const std::str
4748
}
4849
#endif
4950

51+
std::string GenerateSessionId() {
52+
std::mt19937 generator(std::random_device{}());
53+
std::uniform_int_distribution<std::uint64_t> distribution(0);
54+
return std::string("clickhouse_odbc_" + std::to_string(distribution(generator)));
55+
}
56+
5057
Connection::Connection(Environment & environment)
51-
: ChildType(environment)
58+
: ChildType(environment),
59+
session_id(GenerateSessionId())
5260
{
5361
resetConfiguration();
5462
}
@@ -84,6 +92,7 @@ Poco::URI Connection::getUri() const {
8492

8593
bool database_set = false;
8694
bool default_format_set = false;
95+
bool session_id_set = false;
8796

8897
for (const auto& parameter : uri.getQueryParameters()) {
8998
if (Poco::UTF8::icompare(parameter.first, "default_format") == 0) {
@@ -92,6 +101,9 @@ Poco::URI Connection::getUri() const {
92101
else if (Poco::UTF8::icompare(parameter.first, "database") == 0) {
93102
database_set = true;
94103
}
104+
else if (Poco::UTF8::icompare(parameter.first, "session_id") == 0 && !parameter.second.empty()) {
105+
session_id_set = true;
106+
}
95107
}
96108

97109
if (!default_format_set)
@@ -100,6 +112,12 @@ Poco::URI Connection::getUri() const {
100112
if (!database_set)
101113
uri.addQueryParameter("database", database);
102114

115+
// To use some features of CH (e.g. TEMPORARY TABLEs) we need a (named) session.
116+
if (auto_session_id && !session_id_set) {
117+
// DO not overwrite user-set session_id, just in case...
118+
uri.addQueryParameter("session_id", session_id);
119+
}
120+
103121
return uri;
104122
}
105123

@@ -379,6 +397,13 @@ void Connection::setConfiguration(const key_value_map_t & cs_fields, const key_v
379397
getDriver().setAttr(CH_SQL_ATTR_DRIVERLOG, (isYes(value) ? SQL_OPT_TRACE_ON : SQL_OPT_TRACE_OFF));
380398
}
381399
}
400+
else if (Poco::UTF8::icompare(key, INI_AUTO_SESSION_ID) == 0) {
401+
recognized_key = true;
402+
valid_value = (value.empty() || isYesOrNo(value));
403+
if (valid_value) {
404+
auto_session_id = isYes(value);
405+
}
406+
}
382407

383408
return std::make_tuple(recognized_key, valid_value);
384409
};

driver/connection.h

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class Connection
4141
std::string database;
4242
bool huge_int_as_string = false;
4343
std::int32_t stringmaxlength = 0;
44+
bool auto_session_id = false;
4445

4546
public:
4647
std::string useragent;

driver/test/misc_it.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ TEST_F(MiscellaneousTest, RowArraySizeAttribute) {
1919
rc = ODBC_CALL_ON_STMT_THROW(hstmt, SQLGetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, &size, sizeof(size), 0));
2020
ASSERT_EQ(size, 1);
2121
}
22-
22+
2323
{
2424
size = 2;
2525
rc = ODBC_CALL_ON_STMT_THROW(hstmt, SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)size, 0));
@@ -227,7 +227,11 @@ INSTANTIATE_TEST_SUITE_P(
227227

228228
std::make_tuple("AllGood_VerifyConnectionEarly_Empty", "VerifyConnectionEarly=", FailOn::Never),
229229
std::make_tuple("AllGood_VerifyConnectionEarly_On", "VerifyConnectionEarly=on", FailOn::Never),
230-
std::make_tuple("AllGood_VerifyConnectionEarly_Off", "VerifyConnectionEarly=off", FailOn::Never)
230+
std::make_tuple("AllGood_VerifyConnectionEarly_Off", "VerifyConnectionEarly=off", FailOn::Never),
231+
232+
std::make_tuple("AllGood_AutoSessionId_Empty", "AutoSessionId=", FailOn::Never),
233+
std::make_tuple("AllGood_AutoSessionId_On", "AutoSessionId=on", FailOn::Never),
234+
std::make_tuple("AllGood_AutoSessionId_Off", "AutoSessionId=off", FailOn::Never)
231235
),
232236
[] (const auto & param_info) {
233237
return std::get<0>(param_info.param);

packaging/odbc.ini.sample

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ Description = DSN (localhost) for ClickHouse ODBC Driver (ANSI)
3636
# DriverLog = yes
3737
# DriverLogFile = /tmp/chlickhouse-odbc-driver.log
3838

39+
# AutoSessionId = off
40+
3941
[ClickHouse DSN (Unicode)]
4042
Driver = ClickHouse ODBC Driver (Unicode)
4143
Description = DSN (localhost) for ClickHouse ODBC Driver (Unicode)

0 commit comments

Comments
 (0)