Skip to content

Commit 23c0569

Browse files
authored
Fix chr SparkSQL function (#278)
1 parent 70898af commit 23c0569

File tree

3 files changed

+26
-7
lines changed

3 files changed

+26
-7
lines changed

velox/docs/functions/spark/string.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Unless specified otherwise, all functions return NULL if at least one of the arg
1010

1111
.. spark:function:: chr(n) -> varchar
1212
13-
Returns the Unicode code point ``n`` as a single character string.
13+
Returns a utf8 string of single ASCII character. The ASCII character has the binary
14+
equivalent of ``n``. If ``n < 0``, the result is an empty string. If ``n >= 256``,
15+
the result is equivalent to chr(``n % 256``).
1416

1517
.. spark:function:: contains(left, right) -> boolean
1618

velox/functions/sparksql/String.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ struct AsciiFunction {
3838
}
3939
};
4040

41+
/// chr function
42+
/// chr(n) -> string
43+
/// Returns a utf8 string of single ASCII character. The ASCII character has
44+
/// the binary equivalent of n. If n < 0, the result is an empty string. If n >=
45+
/// 256, the result is equivalent to chr(n % 256).
4146
template <typename T>
4247
struct ChrFunction {
4348
VELOX_DEFINE_FUNCTION_TYPES(T);
@@ -46,8 +51,15 @@ struct ChrFunction {
4651
if (ord < 0) {
4752
result.resize(0);
4853
} else {
49-
result.resize(1);
50-
*result.data() = ord;
54+
ord = ord & 0xFF;
55+
if (ord < 0x80) {
56+
result.resize(1);
57+
result.data()[0] = ord;
58+
} else {
59+
result.resize(2);
60+
result.data()[0] = 0xC0 + (ord >> 6);
61+
result.data()[1] = 0x80 + (ord & 0x3F);
62+
}
5163
}
5264
return true;
5365
}

velox/functions/sparksql/tests/StringTest.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,16 @@ TEST_F(StringTest, Ascii) {
162162
}
163163

164164
TEST_F(StringTest, Chr) {
165-
EXPECT_EQ(chr(0), std::string("\0", 1));
166-
EXPECT_EQ(chr(32), " ");
167165
EXPECT_EQ(chr(-16), "");
168-
EXPECT_EQ(chr(256), std::string("\0", 1));
169-
EXPECT_EQ(chr(256 + 32), std::string(" ", 1));
166+
EXPECT_EQ(chr(0), std::string("\0", 1));
167+
EXPECT_EQ(chr(0x100), std::string("\0", 1));
168+
EXPECT_EQ(chr(0x1100), std::string("\0", 1));
169+
EXPECT_EQ(chr(0x20), "\x20");
170+
EXPECT_EQ(chr(0x100 + 0x20), "\x20");
171+
EXPECT_EQ(chr(0x80), "\xC2\x80");
172+
EXPECT_EQ(chr(0x100 + 0x80), "\xC2\x80");
173+
EXPECT_EQ(chr(0xFF), "\xC3\xBF");
174+
EXPECT_EQ(chr(0x100 + 0xFF), "\xC3\xBF");
170175
EXPECT_EQ(chr(std::nullopt), std::nullopt);
171176
}
172177

0 commit comments

Comments
 (0)