disabled exception during overriding settings with same value in readonly mode [#CLICKHOUSE-3041]

This commit is contained in:
Nikolai Kochetov 2017-07-06 17:42:31 +03:00 committed by alexey-milovidov
parent 63119eda7d
commit 25ac546e78
6 changed files with 64 additions and 10 deletions

View File

@ -121,7 +121,7 @@ static BlockOutputStreamPtr getOutputImpl(const String & name, WriteBuffer & buf
const Block & sample, const Context & context)
{
const Settings & settings = context.getSettingsRef();
FormatSettingsJSON json_settings(settings.output_format_json_quote_64bit_integers, true);
FormatSettingsJSON json_settings(settings.output_format_json_quote_64bit_integers, settings.output_format_json_quote_denormals);
if (name == "Native")
return std::make_shared<NativeBlockOutputStream>(buf);

View File

@ -65,7 +65,6 @@ void DataTypeNumberBase<T>::deserializeTextQuoted(IColumn & column, ReadBuffer &
template <typename T>
void DataTypeNumberBase<T>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettingsJSON & settings) const
{
writeCString(settings.output_format_json_quote_denormals ? "1" : "0", ostr);
auto x = static_cast<const ColumnVector<T> &>(column).getData()[row_num];
bool is_finite = isFinite(x);

View File

@ -171,6 +171,19 @@ struct Limits
#undef TRY_SET
}
bool tryGet(const String & name, String & value) const
{
#define TRY_GET(TYPE, NAME, DEFAULT) \
else if (name == #NAME) { value = NAME.toString(); return true; }
if (false) {}
APPLY_FOR_LIMITS(TRY_GET)
return false;
#undef TRY_GET
}
private:
friend struct Settings;

View File

@ -69,6 +69,37 @@ void Settings::set(const String & name, const String & value)
#undef TRY_SET
}
String Settings::get(const String & name) const
{
#define GET(TYPE, NAME, DEFAULT) \
else if (name == #NAME) return NAME.toString();
if (false) {}
APPLY_FOR_SETTINGS(GET)
else
{
String value;
if (!limits.tryGet(name, value))
throw Exception("Unknown setting " + name, ErrorCodes::UNKNOWN_SETTING);
return value;
}
#undef GET
}
bool Settings::tryGet(const String & name, String & value) const
{
#define TRY_GET(TYPE, NAME, DEFAULT) \
else if (name == #NAME) { value = NAME.toString(); return true; }
if (false) {}
APPLY_FOR_SETTINGS(TRY_GET)
else
return limits.tryGet(name, value);
#undef TRY_GET
}
/** Set the settings from the profile (in the server configuration, many settings can be listed in one profile).
* The profile can also be set using the `set` functions, like the `profile` setting.
*/

View File

@ -233,6 +233,9 @@ struct Settings
/** Controls quoting of 64-bit integers in JSON output format. */ \
M(SettingBool, output_format_json_quote_64bit_integers, true) \
\
/** Enables "+nan", "-nan", "+inf", "-inf" outputs in JSON output format. */ \
M(SettingBool, output_format_json_quote_denormals, false) \
\
/** Rows limit for Pretty formats. */ \
M(SettingUInt64, output_format_pretty_max_rows, 10000) \
\
@ -302,6 +305,11 @@ struct Settings
/// Set setting by name. Read value in text form from string (for example, from configuration file or from URL parameter).
void set(const String & name, const String & value);
/// Get setting by name. Converts value to String.
String get(const String & name) const;
bool tryGet(const String & name, String & value) const;
/** Set multiple settings from "profile" (in server configuration file (users.xml), profiles contain groups of multiple settings).
* The profile can also be set using the `set` functions, like the profile setting.
*/

View File

@ -429,6 +429,8 @@ void HTTPHandler::processQuery(
"session_id", "session_timeout", "session_check"
};
const Settings & settings = context.getSettingsRef();
for (auto it = params.begin(); it != params.end(); ++it)
{
if (it->first == "database")
@ -445,19 +447,20 @@ void HTTPHandler::processQuery(
else
{
/// All other query parameters are treated as settings.
String value;
if (!settings.tryGet(it->first, value) || it->second != value)
{
if (readonly_before_query == 1)
throw Exception("Cannot override setting (" + it->first + ") in readonly mode", ErrorCodes::READONLY);
if (readonly_before_query == 1)
throw Exception("Cannot override setting (" + it->first + ") in readonly mode", ErrorCodes::READONLY);
if (readonly_before_query && it->first == "readonly")
throw Exception("Setting 'readonly' cannot be overrided in readonly mode", ErrorCodes::READONLY);
if (readonly_before_query && it->first == "readonly")
throw Exception("Setting 'readonly' cannot be overrided in readonly mode", ErrorCodes::READONLY);
context.setSetting(it->first, it->second);
context.setSetting(it->first, it->second);
}
}
}
const Settings & settings = context.getSettingsRef();
/// HTTP response compression is turned on only if the client signalled that they support it
/// (using Accept-Encoding header) and 'enable_http_compression' setting is turned on.
used_output.out->setCompression(client_supports_http_compression && settings.enable_http_compression);