mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
Merge pull request #64991 from arenadata/ADQM-1893
Add functions to encode and decode base64url
This commit is contained in:
commit
06b27f0922
@ -1136,16 +1136,136 @@ SELECT tryBase58Decode('3dc8KtHrwM') as res, tryBase58Decode('invalid') as res_i
|
||||
|
||||
## base64Encode
|
||||
|
||||
Encodes a String or FixedString as base64.
|
||||
Encodes a String or FixedString as base64, according to [RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648#section-4).
|
||||
|
||||
Alias: `TO_BASE64`.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
base64Encode(plaintext)
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `plaintext` — [String](../data-types/string.md) column or constant.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- A string containing the encoded value of the argument.
|
||||
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
SELECT base64Encode('clickhouse');
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```result
|
||||
┌─base64Encode('clickhouse')─┐
|
||||
│ Y2xpY2tob3VzZQ== │
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
## base64UrlEncode
|
||||
|
||||
Encodes an URL (String or FixedString) as base64 with URL-specific modifications, according to [RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648#section-5).
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
base64UrlEncode(url)
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `url` — [String](../data-types/string.md) column or constant.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- A string containing the encoded value of the argument.
|
||||
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
SELECT base64UrlEncode('https://clickhouse.com');
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```result
|
||||
┌─base64UrlEncode('https://clickhouse.com')─┐
|
||||
│ aHR0cDovL2NsaWNraG91c2UuY29t │
|
||||
└───────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## base64Decode
|
||||
|
||||
Decodes a base64-encoded String or FixedString. Throws an exception in case of error.
|
||||
Accepts a String and decodes it from base64, according to [RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648#section-4). Throws an exception in case of an error.
|
||||
|
||||
Alias: `FROM_BASE64`.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
base64Decode(encoded)
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `encoded` — [String](../data-types/string.md) column or constant. If the string is not a valid Base64-encoded value, an exception is thrown.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- A string containing the decoded value of the argument.
|
||||
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
SELECT base64Decode('Y2xpY2tob3VzZQ==');
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```result
|
||||
┌─base64Decode('Y2xpY2tob3VzZQ==')─┐
|
||||
│ clickhouse │
|
||||
└──────────────────────────────────┘
|
||||
```
|
||||
|
||||
## base64UrlDecode
|
||||
|
||||
Accepts a base64-encoded URL and decodes it from base64 with URL-specific modifications, according to [RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648#section-5). Throws an exception in case of an error.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
base64UrlDecode(encodedUrl)
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `encodedUrl` — [String](../data-types/string.md) column or constant. If the string is not a valid Base64-encoded value with URL-specific modifications, an exception is thrown.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- A string containing the decoded value of the argument.
|
||||
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
SELECT base64UrlDecode('aHR0cDovL2NsaWNraG91c2UuY29t');
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```result
|
||||
┌─base64UrlDecode('aHR0cDovL2NsaWNraG91c2UuY29t')─┐
|
||||
│ https://clickhouse.com │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## tryBase64Decode
|
||||
|
||||
Like `base64Decode` but returns an empty string in case of error.
|
||||
@ -1156,9 +1276,13 @@ Like `base64Decode` but returns an empty string in case of error.
|
||||
tryBase64Decode(encoded)
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
**Arguments**
|
||||
|
||||
- `encoded`: [String](../data-types/string.md) column or constant. If the string is not a valid Base58-encoded value, returns an empty string in case of error.
|
||||
- `encoded`: [String](../data-types/string.md) column or constant. If the string is not a valid Base64-encoded value, returns an empty string.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- A string containing the decoded value of the argument.
|
||||
|
||||
**Examples**
|
||||
|
||||
@ -1169,9 +1293,41 @@ SELECT tryBase64Decode('RW5jb2RlZA==') as res, tryBase64Decode('invalid') as res
|
||||
```
|
||||
|
||||
```response
|
||||
┌─res─────┬─res_invalid─┐
|
||||
│ Encoded │ │
|
||||
└─────────┴─────────────┘
|
||||
┌─res────────┬─res_invalid─┐
|
||||
│ clickhouse │ │
|
||||
└────────────┴─────────────┘
|
||||
```
|
||||
|
||||
## tryBase64UrlDecode
|
||||
|
||||
Like `base64UrlDecode` but returns an empty string in case of error.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
tryBase64UrlDecode(encodedUrl)
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `encodedUrl`: [String](../data-types/string.md) column or constant. If the string is not a valid Base64-encoded value with URL-specific modifications, returns an empty string.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- A string containing the decoded value of the argument.
|
||||
|
||||
**Examples**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT tryBase64UrlDecode('aHR0cDovL2NsaWNraG91c2UuY29t') as res, tryBase64Decode('aHR0cHM6Ly9jbGlja') as res_invalid;
|
||||
```
|
||||
|
||||
```response
|
||||
┌─res────────────────────┬─res_invalid─┐
|
||||
│ https://clickhouse.com │ │
|
||||
└────────────────────────┴─────────────┘
|
||||
```
|
||||
|
||||
## endsWith {#endswith}
|
||||
|
@ -538,16 +538,28 @@ SELECT base58Decode('3dc8KtHrwM');
|
||||
|
||||
Синоним: `TO_BASE64`.
|
||||
|
||||
## base64UrlEncode(s)
|
||||
|
||||
Производит кодирование URL (String или FixedString) в base64-представление в соответствии с [RFC 4648](https://tools.ietf.org/html/rfc4648).
|
||||
|
||||
## base64Decode(s) {#base64decode}
|
||||
|
||||
Декодирует base64-представление s в исходную строку. При невозможности декодирования выбрасывает исключение
|
||||
|
||||
Синоним: `FROM_BASE64`.
|
||||
|
||||
## base64UrlDecode(s)
|
||||
|
||||
Декодирует base64-представление URL в исходную строку в соответствии с [RFC 4648](https://tools.ietf.org/html/rfc4648). При невозможности декодирования выбрасывает исключение
|
||||
|
||||
## tryBase64Decode(s) {#trybase64decode}
|
||||
|
||||
Функционал аналогичен base64Decode, но при невозможности декодирования возвращает пустую строку.
|
||||
|
||||
## tryBase64UrlDecode(s)
|
||||
|
||||
Функционал аналогичен base64UrlDecode, но при невозможности декодирования возвращает пустую строку.
|
||||
|
||||
## endsWith(s, suffix) {#endswith}
|
||||
|
||||
Возвращает 1, если строка завершается указанным суффиксом, и 0 в противном случае.
|
||||
|
@ -12,7 +12,7 @@
|
||||
# include <Common/MemorySanitizer.h>
|
||||
|
||||
# include <cstddef>
|
||||
# include <span>
|
||||
# include <string_view>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -22,36 +22,125 @@ namespace ErrorCodes
|
||||
extern const int INCORRECT_DATA;
|
||||
}
|
||||
|
||||
enum class Base64Variant : uint8_t
|
||||
{
|
||||
Normal,
|
||||
Url
|
||||
};
|
||||
|
||||
inline std::string preprocessBase64Url(std::string_view src)
|
||||
{
|
||||
std::string padded_src;
|
||||
padded_src.reserve(src.size() + 3);
|
||||
|
||||
// Do symbol substitution as described in https://datatracker.ietf.org/doc/html/rfc4648#section-5
|
||||
for (auto s : src)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case '_':
|
||||
padded_src += '/';
|
||||
break;
|
||||
case '-':
|
||||
padded_src += '+';
|
||||
break;
|
||||
default:
|
||||
padded_src += s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert padding to please aklomp library
|
||||
size_t remainder = src.size() % 4;
|
||||
switch (remainder)
|
||||
{
|
||||
case 0:
|
||||
break; // no padding needed
|
||||
case 1:
|
||||
padded_src.append("==="); // this case is impossible to occur with valid base64-URL encoded input, however, we'll insert padding anyway
|
||||
break;
|
||||
case 2:
|
||||
padded_src.append("=="); // two bytes padding
|
||||
break;
|
||||
default: // remainder == 3
|
||||
padded_src.append("="); // one byte padding
|
||||
break;
|
||||
}
|
||||
|
||||
return padded_src;
|
||||
}
|
||||
|
||||
inline size_t postprocessBase64Url(UInt8 * dst, size_t out_len)
|
||||
{
|
||||
// Do symbol substitution as described in https://datatracker.ietf.org/doc/html/rfc4648#section-5
|
||||
for (size_t i = 0; i < out_len; ++i)
|
||||
{
|
||||
switch (dst[i])
|
||||
{
|
||||
case '/':
|
||||
dst[i] = '_';
|
||||
break;
|
||||
case '+':
|
||||
dst[i] = '-';
|
||||
break;
|
||||
case '=': // stop when padding is detected
|
||||
return i;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out_len;
|
||||
}
|
||||
|
||||
template <Base64Variant variant>
|
||||
struct Base64Encode
|
||||
{
|
||||
static constexpr auto name = "base64Encode";
|
||||
static constexpr auto name = (variant == Base64Variant::Normal) ? "base64Encode" : "base64UrlEncode";
|
||||
|
||||
static size_t getBufferSize(size_t string_length, size_t string_count)
|
||||
{
|
||||
return ((string_length - string_count) / 3 + string_count) * 4 + string_count;
|
||||
}
|
||||
|
||||
static size_t perform(const std::span<const UInt8> src, UInt8 * dst)
|
||||
static size_t perform(std::string_view src, UInt8 * dst)
|
||||
{
|
||||
size_t outlen = 0;
|
||||
base64_encode(reinterpret_cast<const char *>(src.data()), src.size(), reinterpret_cast<char *>(dst), &outlen, 0);
|
||||
base64_encode(src.data(), src.size(), reinterpret_cast<char *>(dst), &outlen, 0);
|
||||
|
||||
/// Base64 library is using AVX-512 with some shuffle operations.
|
||||
/// Memory sanitizer doesn't understand if there was uninitialized memory in SIMD register but it was not used in the result of shuffle.
|
||||
__msan_unpoison(dst, outlen);
|
||||
|
||||
if constexpr (variant == Base64Variant::Url)
|
||||
outlen = postprocessBase64Url(dst, outlen);
|
||||
|
||||
return outlen;
|
||||
}
|
||||
};
|
||||
|
||||
template <Base64Variant variant>
|
||||
struct Base64Decode
|
||||
{
|
||||
static constexpr auto name = "base64Decode";
|
||||
static constexpr auto name = (variant == Base64Variant::Normal) ? "base64Decode" : "base64UrlDecode";
|
||||
|
||||
static size_t getBufferSize(size_t string_length, size_t string_count)
|
||||
{
|
||||
return ((string_length - string_count) / 4 + string_count) * 3 + string_count;
|
||||
}
|
||||
|
||||
static size_t perform(const std::span<const UInt8> src, UInt8 * dst)
|
||||
static size_t perform(std::string_view src, UInt8 * dst)
|
||||
{
|
||||
int rc;
|
||||
size_t outlen = 0;
|
||||
int rc = base64_decode(reinterpret_cast<const char *>(src.data()), src.size(), reinterpret_cast<char *>(dst), &outlen, 0);
|
||||
if constexpr (variant == Base64Variant::Url)
|
||||
{
|
||||
std::string src_padded = preprocessBase64Url(src);
|
||||
rc = base64_decode(src_padded.data(), src_padded.size(), reinterpret_cast<char *>(dst), &outlen, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = base64_decode(src.data(), src.size(), reinterpret_cast<char *>(dst), &outlen, 0);
|
||||
}
|
||||
|
||||
if (rc != 1)
|
||||
throw Exception(
|
||||
@ -64,19 +153,29 @@ struct Base64Decode
|
||||
}
|
||||
};
|
||||
|
||||
template <Base64Variant variant>
|
||||
struct TryBase64Decode
|
||||
{
|
||||
static constexpr auto name = "tryBase64Decode";
|
||||
static constexpr auto name = (variant == Base64Variant::Normal) ? "tryBase64Decode" : "tryBase64UrlDecode";
|
||||
|
||||
static size_t getBufferSize(size_t string_length, size_t string_count)
|
||||
{
|
||||
return Base64Decode::getBufferSize(string_length, string_count);
|
||||
return Base64Decode<variant>::getBufferSize(string_length, string_count);
|
||||
}
|
||||
|
||||
static size_t perform(const std::span<const UInt8> src, UInt8 * dst)
|
||||
static size_t perform(std::string_view src, UInt8 * dst)
|
||||
{
|
||||
int rc;
|
||||
size_t outlen = 0;
|
||||
int rc = base64_decode(reinterpret_cast<const char *>(src.data()), src.size(), reinterpret_cast<char *>(dst), &outlen, 0);
|
||||
if constexpr (variant == Base64Variant::Url)
|
||||
{
|
||||
std::string src_padded = preprocessBase64Url(src);
|
||||
rc = base64_decode(src_padded.data(), src_padded.size(), reinterpret_cast<char *>(dst), &outlen, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = base64_decode(src.data(), src.size(), reinterpret_cast<char *>(dst), &outlen, 0);
|
||||
}
|
||||
|
||||
if (rc != 1)
|
||||
outlen = 0;
|
||||
@ -139,7 +238,7 @@ private:
|
||||
|
||||
auto * dst = dst_chars.data();
|
||||
auto * dst_pos = dst;
|
||||
const auto * src = src_chars.data();
|
||||
const auto * src = reinterpret_cast<const char *>(src_chars.data());
|
||||
|
||||
size_t src_offset_prev = 0;
|
||||
for (size_t row = 0; row < src_row_count; ++row)
|
||||
@ -147,10 +246,6 @@ private:
|
||||
const size_t src_length = src_offsets[row] - src_offset_prev - 1;
|
||||
const size_t outlen = Func::perform({src, src_length}, dst_pos);
|
||||
|
||||
/// Base64 library is using AVX-512 with some shuffle operations.
|
||||
/// Memory sanitizer don't understand if there was uninitialized memory in SIMD register but it was not used in the result of shuffle.
|
||||
__msan_unpoison(dst_pos, outlen);
|
||||
|
||||
src += src_length + 1;
|
||||
dst_pos += outlen;
|
||||
*dst_pos = '\0';
|
||||
@ -179,16 +274,12 @@ private:
|
||||
|
||||
auto * dst = dst_chars.data();
|
||||
auto * dst_pos = dst;
|
||||
const auto * src = src_chars.data();
|
||||
const auto * src = reinterpret_cast<const char *>(src_chars.data());
|
||||
|
||||
for (size_t row = 0; row < src_row_count; ++row)
|
||||
{
|
||||
const auto outlen = Func::perform({src, src_n}, dst_pos);
|
||||
|
||||
/// Base64 library is using AVX-512 with some shuffle operations.
|
||||
/// Memory sanitizer don't understand if there was uninitialized memory in SIMD register but it was not used in the result of shuffle.
|
||||
__msan_unpoison(dst_pos, outlen);
|
||||
|
||||
src += src_n;
|
||||
dst_pos += outlen;
|
||||
*dst_pos = '\0';
|
||||
|
@ -7,7 +7,14 @@ namespace DB
|
||||
{
|
||||
REGISTER_FUNCTION(Base64Decode)
|
||||
{
|
||||
factory.registerFunction<FunctionBase64Conversion<Base64Decode>>();
|
||||
FunctionDocumentation::Description description = R"(Accepts a String and decodes it from base64, according to RFC 4648 (https://datatracker.ietf.org/doc/html/rfc4648#section-4). Throws an exception in case of an error. Alias: FROM_BASE64.)";
|
||||
FunctionDocumentation::Syntax syntax = "base64Decode(encoded)";
|
||||
FunctionDocumentation::Arguments arguments = {{"encoded", "String column or constant. If the string is not a valid Base64-encoded value, an exception is thrown."}};
|
||||
FunctionDocumentation::ReturnedValue returned_value = "A string containing the decoded value of the argument.";
|
||||
FunctionDocumentation::Examples examples = {{"Example", "SELECT base64Decode('Y2xpY2tob3VzZQ==')", "clickhouse"}};
|
||||
FunctionDocumentation::Categories categories = {"String encoding"};
|
||||
|
||||
factory.registerFunction<FunctionBase64Conversion<Base64Decode<Base64Variant::Normal>>>({description, syntax, arguments, returned_value, examples, categories});
|
||||
|
||||
/// MySQL compatibility alias.
|
||||
factory.registerAlias("FROM_BASE64", "base64Decode", FunctionFactory::CaseInsensitive);
|
||||
|
@ -7,7 +7,14 @@ namespace DB
|
||||
{
|
||||
REGISTER_FUNCTION(Base64Encode)
|
||||
{
|
||||
factory.registerFunction<FunctionBase64Conversion<Base64Encode>>();
|
||||
FunctionDocumentation::Description description = R"(Encodes a String as base64, according to RFC 4648 (https://datatracker.ietf.org/doc/html/rfc4648#section-4). Alias: TO_BASE64.)";
|
||||
FunctionDocumentation::Syntax syntax = "base64Encode(plaintext)";
|
||||
FunctionDocumentation::Arguments arguments = {{"plaintext", "String column or constant."}};
|
||||
FunctionDocumentation::ReturnedValue returned_value = "A string containing the encoded value of the argument.";
|
||||
FunctionDocumentation::Examples examples = {{"Example", "SELECT base64Encode('clickhouse')", "Y2xpY2tob3VzZQ=="}};
|
||||
FunctionDocumentation::Categories categories = {"String encoding"};
|
||||
|
||||
factory.registerFunction<FunctionBase64Conversion<Base64Encode<Base64Variant::Normal>>>({description, syntax, arguments, returned_value, examples, categories});
|
||||
|
||||
/// MySQL compatibility alias.
|
||||
factory.registerAlias("TO_BASE64", "base64Encode", FunctionFactory::CaseInsensitive);
|
||||
|
21
src/Functions/base64UrlDecode.cpp
Normal file
21
src/Functions/base64UrlDecode.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include <Functions/FunctionBase64Conversion.h>
|
||||
|
||||
#if USE_BASE64
|
||||
#include <Functions/FunctionFactory.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
REGISTER_FUNCTION(Base64UrlDecode)
|
||||
{
|
||||
FunctionDocumentation::Description description = R"(Accepts a base64-encoded URL and decodes it from base64 with URL-specific modifications, according to RFC 4648 (https://datatracker.ietf.org/doc/html/rfc4648#section-5).)";
|
||||
FunctionDocumentation::Syntax syntax = "base64UrlDecode(encodedUrl)";
|
||||
FunctionDocumentation::Arguments arguments = {{"encodedUrl", "String column or constant. If the string is not a valid Base64-encoded value, an exception is thrown."}};
|
||||
FunctionDocumentation::ReturnedValue returned_value = "A string containing the decoded value of the argument.";
|
||||
FunctionDocumentation::Examples examples = {{"Example", "SELECT base64UrlDecode('aHR0cDovL2NsaWNraG91c2UuY29t')", "https://clickhouse.com"}};
|
||||
FunctionDocumentation::Categories categories = {"String encoding"};
|
||||
|
||||
factory.registerFunction<FunctionBase64Conversion<Base64Decode<Base64Variant::Url>>>({description, syntax, arguments, returned_value, examples, categories});
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
21
src/Functions/base64UrlEncode.cpp
Normal file
21
src/Functions/base64UrlEncode.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include <Functions/FunctionBase64Conversion.h>
|
||||
|
||||
#if USE_BASE64
|
||||
#include <Functions/FunctionFactory.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
REGISTER_FUNCTION(Base64UrlEncode)
|
||||
{
|
||||
FunctionDocumentation::Description description = R"(Encodes an URL (String or FixedString) as base64 with URL-specific modifications, according to RFC 4648 (https://datatracker.ietf.org/doc/html/rfc4648#section-5).)";
|
||||
FunctionDocumentation::Syntax syntax = "base64UrlEncode(url)";
|
||||
FunctionDocumentation::Arguments arguments = {{"url", "String column or constant."}};
|
||||
FunctionDocumentation::ReturnedValue returned_value = "A string containing the encoded value of the argument.";
|
||||
FunctionDocumentation::Examples examples = {{"Example", "SELECT base64UrlEncode('https://clickhouse.com')", "aHR0cHM6Ly9jbGlja2hvdXNlLmNvbQ"}};
|
||||
FunctionDocumentation::Categories categories = {"String encoding"};
|
||||
|
||||
factory.registerFunction<FunctionBase64Conversion<Base64Encode<Base64Variant::Url>>>({description, syntax, arguments, returned_value, examples, categories});
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -7,7 +7,14 @@ namespace DB
|
||||
{
|
||||
REGISTER_FUNCTION(TryBase64Decode)
|
||||
{
|
||||
factory.registerFunction<FunctionBase64Conversion<TryBase64Decode>>();
|
||||
FunctionDocumentation::Description description = R"(Decodes a String or FixedString from base64, like base64Decode but returns an empty string in case of an error.)";
|
||||
FunctionDocumentation::Syntax syntax = "tryBase64Decode(encoded)";
|
||||
FunctionDocumentation::Arguments arguments = {{"encoded", "String column or constant. If the string is not a valid Base64-encoded value, returns an empty string."}};
|
||||
FunctionDocumentation::ReturnedValue returned_value = "A string containing the decoded value of the argument.";
|
||||
FunctionDocumentation::Examples examples = {{"valid", "SELECT tryBase64Decode('Y2xpY2tob3VzZQ==')", "clickhouse"}, {"invalid", "SELECT tryBase64Decode('invalid')", ""}};
|
||||
FunctionDocumentation::Categories categories = {"String encoding"};
|
||||
|
||||
factory.registerFunction<FunctionBase64Conversion<TryBase64Decode<Base64Variant::Normal>>>({description, syntax, arguments, returned_value, examples, categories});
|
||||
}
|
||||
}
|
||||
|
||||
|
21
src/Functions/tryBase64UrlDecode.cpp
Normal file
21
src/Functions/tryBase64UrlDecode.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include <Functions/FunctionBase64Conversion.h>
|
||||
|
||||
#if USE_BASE64
|
||||
#include <Functions/FunctionFactory.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
REGISTER_FUNCTION(TryBase64UrlDecode)
|
||||
{
|
||||
FunctionDocumentation::Description description = R"(Decodes an URL from base64, like base64UrlDecode but returns an empty string in case of an error.)";
|
||||
FunctionDocumentation::Syntax syntax = "tryBase64UrlDecode(encodedUrl)";
|
||||
FunctionDocumentation::Arguments arguments = {{"encodedUrl", "String column or constant. If the string is not a valid Base64-encoded value with URL-specific modifications, returns an empty string."}};
|
||||
FunctionDocumentation::ReturnedValue returned_value = "A string containing the decoded value of the argument.";
|
||||
FunctionDocumentation::Examples examples = {{"valid", "SELECT tryBase64UrlDecode('aHR0cHM6Ly9jbGlja2hvdXNlLmNvbQ')", "https://clickhouse.com"}, {"invalid", "SELECT tryBase64UrlDecode('aHR0cHM6Ly9jbGlja')", ""}};
|
||||
FunctionDocumentation::Categories categories = {"String encoding"};
|
||||
|
||||
factory.registerFunction<FunctionBase64Conversion<TryBase64Decode<Base64Variant::Url>>>({description, syntax, arguments, returned_value, examples, categories});
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,6 +1,5 @@
|
||||
-- Tags: no-fasttest
|
||||
|
||||
SET send_logs_level = 'fatal';
|
||||
-- no-fasttest because aklomp-base64 library is required
|
||||
|
||||
SELECT base64Encode(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
SELECT base64Decode(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
|
@ -3,7 +3,6 @@
|
||||
SELECT name FROM system.functions WHERE NOT is_aggregate AND origin = 'System' AND alias_to = '' AND length(description) < 10
|
||||
AND name NOT IN (
|
||||
'aes_decrypt_mysql', 'aes_encrypt_mysql', 'decrypt', 'encrypt',
|
||||
'base64Decode', 'base64Encode', 'tryBase64Decode',
|
||||
'convertCharset',
|
||||
'detectLanguage', 'detectLanguageMixed',
|
||||
'geoToH3',
|
||||
|
@ -0,0 +1,10 @@
|
||||
https://clickhouse.com aHR0cHM6Ly9jbGlja2hvdXNlLmNvbQ https://clickhouse.com https://clickhouse.com
|
||||
12? MTI_ 12? 12?
|
||||
https://www.google.com/search?q=clickhouse+base64+decode&sca_esv=739f8bb380e4c7ed&ei=TfRiZqCDIrmnwPAP2KLRkA8&ved=0ahUKEwjg3ZHitsmGAxW5ExAIHVhRFPIQ4dUDCBA&uact=5&oq=clickhouse+base64+decode aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9zZWFyY2g_cT1jbGlja2hvdXNlK2Jhc2U2NCtkZWNvZGUmc2NhX2Vzdj03MzlmOGJiMzgwZTRjN2VkJmVpPVRmUmlacUNESXJtbndQQVAyS0xSa0E4JnZlZD0wYWhVS0V3amczWkhpdHNtR0F4VzVFeEFJSFZoUkZQSVE0ZFVEQ0JBJnVhY3Q9NSZvcT1jbGlja2hvdXNlK2Jhc2U2NCtkZWNvZGU https://www.google.com/search?q=clickhouse+base64+decode&sca_esv=739f8bb380e4c7ed&ei=TfRiZqCDIrmnwPAP2KLRkA8&ved=0ahUKEwjg3ZHitsmGAxW5ExAIHVhRFPIQ4dUDCBA&uact=5&oq=clickhouse+base64+decode https://www.google.com/search?q=clickhouse+base64+decode&sca_esv=739f8bb380e4c7ed&ei=TfRiZqCDIrmnwPAP2KLRkA8&ved=0ahUKEwjg3ZHitsmGAxW5ExAIHVhRFPIQ4dUDCBA&uact=5&oq=clickhouse+base64+decode
|
||||
aHR0cHM6Ly9jbGlj https://clic https://clic
|
||||
aHR0cHM6Ly9jbGlja2g https://clickh https://clickh
|
||||
aHR0cHM6Ly9jbGljaw https://click https://click
|
||||
|
||||
|
||||
|
||||
https://clickhouse.com aHR0cHM6Ly9jbGlja2hvdXNlLmNvbQ https://clickhouse.com https://clickhouse.com
|
36
tests/queries/0_stateless/03167_base64_url_functions.sql
Normal file
36
tests/queries/0_stateless/03167_base64_url_functions.sql
Normal file
@ -0,0 +1,36 @@
|
||||
-- Tags: no-fasttest
|
||||
-- no-fasttest because aklomp-base64 library is required
|
||||
|
||||
-- incorrect number of arguments
|
||||
SELECT base64UrlEncode(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
SELECT base64UrlDecode(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
SELECT tryBase64UrlDecode(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
SELECT base64UrlEncode('foo', 'excess argument'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
SELECT base64UrlDecode('foo', 'excess argument'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
SELECT tryBase64UrlDecode('foo', 'excess argument'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
|
||||
-- test with valid inputs
|
||||
|
||||
SELECT 'https://clickhouse.com' AS original, base64UrlEncode(original) AS encoded, base64UrlDecode(encoded), tryBase64UrlDecode(encoded);
|
||||
SELECT '12?' AS original, base64UrlEncode(original) AS encoded, base64UrlDecode(encoded), tryBase64UrlDecode(encoded);
|
||||
SELECT 'https://www.google.com/search?q=clickhouse+base64+decode&sca_esv=739f8bb380e4c7ed&ei=TfRiZqCDIrmnwPAP2KLRkA8&ved=0ahUKEwjg3ZHitsmGAxW5ExAIHVhRFPIQ4dUDCBA&uact=5&oq=clickhouse+base64+decode' AS original, base64UrlEncode(original) AS encoded, base64UrlDecode(encoded), tryBase64UrlDecode(encoded);
|
||||
|
||||
-- encoded value has no padding
|
||||
SELECT 'aHR0cHM6Ly9jbGlj' AS encoded, base64UrlDecode(encoded), tryBase64UrlDecode(encoded);
|
||||
-- encoded value has one-byte padding
|
||||
SELECT 'aHR0cHM6Ly9jbGlja2g' AS encoded, base64UrlDecode(encoded), tryBase64UrlDecode(encoded);
|
||||
-- encoded value has two-bytes padding
|
||||
SELECT 'aHR0cHM6Ly9jbGljaw' AS encoded, base64UrlDecode(encoded), tryBase64UrlDecode(encoded);
|
||||
|
||||
-- test with invalid inputs
|
||||
|
||||
SELECT base64UrlDecode('https://clickhouse.com'); -- { serverError INCORRECT_DATA }
|
||||
SELECT tryBase64UrlDecode('https://clickhouse.com');
|
||||
SELECT base64UrlDecode('12?'); -- { serverError INCORRECT_DATA }
|
||||
SELECT tryBase64UrlDecode('12?');
|
||||
SELECT base64UrlDecode('aHR0cHM6Ly9jbGlja'); -- { serverError INCORRECT_DATA }
|
||||
SELECT tryBase64UrlDecode('aHR0cHM6Ly9jbGlja');
|
||||
|
||||
-- test FixedString argument
|
||||
|
||||
SELECT toFixedString('https://clickhouse.com', 22) AS original, base64UrlEncode(original) AS encoded, base64UrlDecode(encoded), tryBase64UrlDecode(encoded);
|
@ -1011,6 +1011,8 @@ Updatable
|
||||
Uppercased
|
||||
Uptime
|
||||
Uptrace
|
||||
UrlDecode
|
||||
UrlEncode
|
||||
UserID
|
||||
Util
|
||||
VARCHAR
|
||||
|
Loading…
Reference in New Issue
Block a user