Skip to content

Commit 9fd26be

Browse files
committed
fix: to_base64 should cast input parameter to string
1 parent ba423a0 commit 9fd26be

File tree

6 files changed

+170
-23
lines changed

6 files changed

+170
-23
lines changed

docs/en/14-reference/03-taos-sql/10-function.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,9 +1169,7 @@ TO_BASE64(expr)
11691169

11701170
**Return Type**: VARCHAR.
11711171

1172-
**Applicable Data Types**:
1173-
1174-
- `expr`: VARCHAR, NCHAR.
1172+
**Applicable Data Types**: Suitable for any type.
11751173

11761174
**Nested Subquery Support**: Applicable to both inner and outer queries.
11771175

@@ -1180,15 +1178,33 @@ TO_BASE64(expr)
11801178
**Usage Notes**:
11811179

11821180
- If `expr` is NULL, returns NULL.
1181+
- if `expr` is the empty string, it returns the empty string.
1182+
- if `expr` is a non string, it is interpreted as a string.
1183+
- This function is multibyte safe.
11831184

11841185
**Example**:
11851186

11861187
```sql
1188+
taos> select to_base64(NULL);
1189+
to_base64(null) |
1190+
==================
1191+
NULL |
1192+
11871193
taos> select to_base64("");
11881194
to_base64("") |
11891195
================
11901196
|
11911197

1198+
taos> select to_base64(14324);
1199+
to_base64(14324) |
1200+
=====================
1201+
MTQzMjQ= |
1202+
1203+
taos> select to_base64("14324");
1204+
to_base64("14324") |
1205+
=====================
1206+
MTQzMjQ= |
1207+
11921208
taos> select to_base64("Hello, world!");
11931209
to_base64("Hello, world!") |
11941210
=============================

docs/zh/14-reference/03-taos-sql/10-function.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,26 +1120,42 @@ TO_BASE64(expr)
11201120

11211121
**返回结果类型**: VARCHAR
11221122

1123-
**适用数据类型**:
1124-
1125-
- `expr`: VARCHAR, NCHAR.
1123+
**适用数据类型**: 任何类型。
11261124

11271125
**嵌套子查询支持**:适用于内层查询和外层查询。
11281126

11291127
**适用于**:表和超级表。
11301128

11311129
**使用说明**:
11321130

1133-
- 若 expr 为 NULL,返回 NULL。
1131+
-`expr` 为 NULL,返回 NULL。
1132+
- 如果 `expr` 为空字符串,则返回空字符串。
1133+
- 如果 `expr` 为非字符串,则将其解释为字符串。
1134+
- 此函数是多字节安全的。
11341135

11351136
**举例**:
11361137

11371138
```sql
1139+
taos> select to_base64(NULL);
1140+
to_base64(null) |
1141+
==================
1142+
NULL |
1143+
11381144
taos> select to_base64("");
11391145
to_base64("") |
11401146
================
11411147
|
11421148

1149+
taos> select to_base64(14324);
1150+
to_base64(14324) |
1151+
=====================
1152+
MTQzMjQ= |
1153+
1154+
taos> select to_base64("14324");
1155+
to_base64("14324") |
1156+
=====================
1157+
MTQzMjQ= |
1158+
11431159
taos> select to_base64("Hello, world!");
11441160
to_base64("Hello, world!") |
11451161
=============================

source/libs/function/src/builtins.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5462,7 +5462,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
54625462
.inputParaInfo[0][0] = {.isLastParam = true,
54635463
.startParam = 1,
54645464
.endParam = 1,
5465-
.validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE | FUNC_PARAM_SUPPORT_NCHAR_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE,
5465+
.validDataType = FUNC_PARAM_SUPPORT_ALL_TYPE,
54665466
.validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE,
54675467
.paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE,
54685468
.valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,},

source/libs/scalar/src/sclfunc.c

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,7 +1721,13 @@ static char base64Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
17211721
"abcdefghijklmnopqrstuvwxyz"
17221722
"0123456789+/";
17231723

1724-
static void base64Impl(uint8_t *base64Out, const uint8_t *inputBytes, size_t inputLen, VarDataLenT outputLen) {
1724+
uint32_t base64BufSize(size_t inputLenBytes) {
1725+
return 4 * ((inputLenBytes + 2) / 3);
1726+
}
1727+
1728+
static VarDataLenT base64Impl(uint8_t *base64Out, const uint8_t *inputBytes, size_t inputLen) {
1729+
VarDataLenT outputLen = base64BufSize(inputLen);
1730+
17251731
for (size_t i = 0, j = 0; i < inputLen;) {
17261732
unsigned int octet_a = i < inputLen ? inputBytes[i++] : 0;
17271733
unsigned int octet_b = i < inputLen ? inputBytes[i++] : 0;
@@ -1740,39 +1746,82 @@ static void base64Impl(uint8_t *base64Out, const uint8_t *inputBytes, size_t inp
17401746
}
17411747

17421748
base64Out[outputLen] = 0;
1743-
}
17441749

1745-
uint32_t base64BufSize(size_t inputLenBytes) {
1746-
return 4 * ((inputLenBytes + 2) / 3);
1750+
return outputLen;
17471751
}
17481752

1753+
#define BASE64_TRUE "MQ=="
1754+
#define BASE64_FALSE "MA=="
1755+
17491756
int32_t base64Function(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) {
17501757
int32_t code = TSDB_CODE_SUCCESS;
17511758
SColumnInfoData *pInputData = pInput->columnData;
17521759
SColumnInfoData *pOutputData = pOutput->columnData;
1753-
char *outputBuf = taosMemoryMalloc(TSDB_MAX_FIELD_LEN + VARSTR_HEADER_SIZE);
1754-
if (outputBuf == NULL) {
1760+
int16_t inputType = GET_PARAM_TYPE(&pInput[0]);
1761+
int64_t outputLen = GET_PARAM_BYTES(&pOutput[0]);
1762+
char *stringBuf = taosMemoryMalloc(TSDB_MAX_FIELD_LEN + VARSTR_HEADER_SIZE);
1763+
char *output = taosMemoryMalloc(TSDB_MAX_FIELD_LEN + VARSTR_HEADER_SIZE);
1764+
1765+
if (!stringBuf || output) {
17551766
SCL_ERR_RET(terrno);
17561767
}
1757-
1768+
1769+
/* Preparing the output buffer with VARSTR_HEADER_SIZE
1770+
non-zero char at the beginning */
1771+
for (size_t i = 0; i < VARSTR_HEADER_SIZE; i++) {
1772+
output[i] = 1;
1773+
}
1774+
char *out = output + VARSTR_HEADER_SIZE;
1775+
17581776
for (int32_t i = 0; i < pInput->numOfRows; ++i) {
17591777
if (colDataIsNull_s(pInputData, i)) {
17601778
colDataSetNULL(pOutputData, i);
17611779
continue;
17621780
}
17631781

1764-
char *input = colDataGetData(pInputData, i);
1765-
size_t inputLen = varDataLen(colDataGetData(pInputData, i));
1766-
char *out = outputBuf + VARSTR_HEADER_SIZE;
1767-
VarDataLenT outputLength = base64BufSize(inputLen);
1768-
base64Impl(out, varDataVal(input), inputLen, outputLength);
1769-
varDataSetLen(outputBuf, outputLength);
1770-
SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
1782+
char *input = colDataGetData(pInput[0].columnData, i);
1783+
size_t inputLen = varDataLen(input);
1784+
size_t outputSize = TSDB_MAX_FIELD_LEN;
1785+
1786+
if (inputType == TSDB_DATA_TYPE_BOOL) {
1787+
memcpy(out, *(int8_t *)input ? BASE64_TRUE : BASE64_FALSE, 4);
1788+
SCL_ERR_JRET(colDataSetVal(pOutputData, i, output, false));
1789+
continue;
1790+
}
1791+
1792+
if (IS_NUMERIC_TYPE(inputType)) {
1793+
if (IS_DECIMAL_TYPE(inputType)) {
1794+
outputSize = (outputLen - VARSTR_HEADER_SIZE) < TSDB_MAX_FIELD_LEN
1795+
? (outputLen - VARSTR_HEADER_SIZE + 1)
1796+
: TSDB_MAX_FIELD_LEN;
1797+
uint8_t inputPrec = GET_PARAM_PRECISON(&pInput[0]), inputScale = GET_PARAM_SCALE(&pInput[0]);
1798+
SCL_ERR_JRET(decimalToStr(input, inputType, inputPrec, inputScale, stringBuf, outputSize));
1799+
} else {
1800+
NUM_TO_STRING(inputType, input, outputSize, stringBuf);
1801+
}
1802+
outputSize = strlen(stringBuf);
1803+
} else if (inputType == TSDB_DATA_TYPE_TIMESTAMP) {
1804+
/* The format used by MySQL in the conversion from timestamp to string */
1805+
char *format = "yyyy-mm-dd hh24:mi:ss";
1806+
SArray *formats = NULL;
1807+
SCL_ERR_JRET(taosTs2Char(format, &formats, *(int64_t *)input, 0, stringBuf, outputSize, pInput->tz));
1808+
outputSize = strlen(stringBuf);
1809+
taosArrayDestroy(formats);
1810+
} else {
1811+
outputSize = inputLen;
1812+
memcpy(stringBuf, varDataVal(input), outputSize);
1813+
}
1814+
1815+
VarDataLenT outputLength = base64Impl(out, stringBuf, outputSize);
1816+
varDataSetLen(output, outputLength);
1817+
SCL_ERR_JRET(colDataSetVal(pOutputData, i, output, false));
17711818
}
17721819

17731820
pOutput->numOfRows = pInput->numOfRows;
1821+
17741822
_return:
1775-
taosMemoryFree(outputBuf);
1823+
taosMemoryFree(output);
1824+
taosMemoryFree(stringBuf);
17761825
return code;
17771826
}
17781827

tests/army/query/function/ans/base64.csv

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,58 @@ taos> select to_base64(substring('北京涛思.com', 1, 4)) == to_base64('北京
6969
===================================================================
7070
true |
7171

72+
taos> select to_base64(true)
73+
to_base64(true) |
74+
==================
75+
MQ== |
76+
77+
taos> select to_base64(true) = to_base64(1)
78+
to_base64(true) = to_base64(1) |
79+
=================================
80+
false |
81+
82+
taos> select to_base64(false)
83+
to_base64(false) |
84+
===================
85+
MA== |
86+
87+
taos> select to_base64(false) = to_base64(0)
88+
to_base64(false) = to_base64(0) |
89+
==================================
90+
false |
91+
92+
taos> select to_base64(1234)
93+
to_base64(1234) |
94+
==================
95+
MTIzNA== |
96+
97+
taos> select to_base64(1234) = to_base64("1234")
98+
to_base64(1234) = to_base64("1234") |
99+
======================================
100+
true |
101+
102+
taos> select to_base64(1234.567)
103+
to_base64(1234.567) |
104+
======================
105+
MTIzNC41Njc= |
106+
107+
taos> select to_base64(1234.567) = to_base64('1234.567')
108+
to_base64(1234.567) = to_base64('1234.567') |
109+
==============================================
110+
true |
111+
112+
taos> select to_base64(1234.567 + 0.1) = to_base64('1234.667')
113+
to_base64(1234.567 + 0.1) = to_base64('1234.667') |
114+
====================================================
115+
true |
116+
117+
taos> select to_base64(TO_TIMESTAMP("2000-01-01 00:00:00+00", "yyyy-mm-dd hh24:mi:ss")) = to_base64(TO_CHAR(TO_TIMESTAMP("2000-01-01 00:00:00+00", "yyyy-mm-dd hh24:mi:ss"), "yyyy-mm-dd hh24:mi:ss"))
118+
to_base64(to_timestamp("2000-01-01 00:00:00+00", "yyyy-mm-dd hh2 |
119+
===================================================================
120+
true |
121+
122+
taos> select to_base64(TO_TIMESTAMP("2000-01-01 00:00:00+00", "yyyy-mm-dd hh24:mi:ss")) = to_base64("2000-01-01 00:00:00")
123+
to_base64(to_timestamp("2000-01-01 00:00:00+00", "yyyy-mm-dd hh2 |
124+
===================================================================
125+
true |
126+

tests/army/query/function/in/base64.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,14 @@ select to_base64(trim(' Hello, world! ')) == to_base64('Hello, world!')
1212
select to_base64(trim(' 北京涛思 '))
1313
select to_base64(trim(' 北京涛思 ')) == to_base64('北京涛思')
1414
select to_base64(substring('北京涛思.com', 1, 4)) == to_base64('北京涛思')
15+
select to_base64(true)
16+
select to_base64(true) = to_base64(1)
17+
select to_base64(false)
18+
select to_base64(false) = to_base64(0)
19+
select to_base64(1234)
20+
select to_base64(1234) = to_base64("1234")
21+
select to_base64(1234.567)
22+
select to_base64(1234.567) = to_base64('1234.567')
23+
select to_base64(1234.567 + 0.1) = to_base64('1234.667')
24+
select to_base64(TO_TIMESTAMP("2000-01-01 00:00:00+00", "yyyy-mm-dd hh24:mi:ss")) = to_base64(TO_CHAR(TO_TIMESTAMP("2000-01-01 00:00:00+00", "yyyy-mm-dd hh24:mi:ss"), "yyyy-mm-dd hh24:mi:ss"))
25+
select to_base64(TO_TIMESTAMP("2000-01-01 00:00:00+00", "yyyy-mm-dd hh24:mi:ss")) = to_base64("2000-01-01 00:00:00")

0 commit comments

Comments
 (0)