From a9787ea446b8229025054b55cb4686599a794a87 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 1 Jun 2022 12:16:06 +0800 Subject: [PATCH 1/5] enh(query): to_iso8601 add customized timzone format TD-16152 --- source/libs/function/src/builtins.c | 61 ++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index add94cb83c..52880dc5ee 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -921,16 +921,75 @@ static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { return TSDB_CODE_SUCCESS; } +/* Following are valid iso-8601 timezone format: + * z/Z + * ±hh:mm + * ±hhmm + * ±hh + * + */ + +static bool validateTimezoneFormat(const SValueNode* pVal) { + if (TSDB_DATA_TYPE_BINARY != pVal->node.resType.type) { + return false; + } + + char *tz = pVal->datum.p; + int32_t len = (int32_t)strlen(tz); + + if (len == 0) { + return false; + } else if (len == 1 && (tz[0] == 'z' || tz[0] == 'Z')) { + return true; + } else if ((tz[0] == '+' || tz[0] == '-')) { + switch (len) { + case 3: + case 5: + case 6: { + for (int32_t i = 1; i < len; ++i) { + if (len == 6 && i == 3 && tz[i] != ':') { + return false; + } + if (!isdigit(tz[i])) { + return false; + } + } + } + default: { + return false; + } + } + } else { + return false; + } + + return true; +} + static int32_t translateToIso8601(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { - if (1 != LIST_LENGTH(pFunc->pParameterList)) { + int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); + if (1 != numOfParams && 2 != numOfParams) { return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); } + //param0 uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; if (!IS_INTEGER_TYPE(paraType) && TSDB_DATA_TYPE_TIMESTAMP != paraType) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } + //param1 + if (numOfParams == 2) { + SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1); + + if (!validateTimezoneFormat(pValue)) { + return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, + "Invalid timzone format"); + } + } else { //add default client timezone + } + + //set result type pFunc->node.resType = (SDataType){.bytes = 64, .type = TSDB_DATA_TYPE_BINARY}; return TSDB_CODE_SUCCESS; } From 3d6147fd9cc329b0be63ffe006e59b82fb5226ba Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 1 Jun 2022 14:58:10 +0800 Subject: [PATCH 2/5] fix(query): fix to_iso8601 timezone param check --- source/libs/function/src/builtins.c | 31 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 52880dc5ee..9b481857ba 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -921,11 +921,11 @@ static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { return TSDB_CODE_SUCCESS; } -/* Following are valid iso-8601 timezone format: - * z/Z - * ±hh:mm - * ±hhmm - * ±hh +/* Following are valid ISO-8601 timezone format: + * 1 z/Z + * 2 ±hh:mm + * 3 ±hhmm + * 4 ±hh * */ @@ -934,8 +934,8 @@ static bool validateTimezoneFormat(const SValueNode* pVal) { return false; } - char *tz = pVal->datum.p; - int32_t len = (int32_t)strlen(tz); + char *tz = varDataVal(pVal->datum.p); + int32_t len = varDataLen(pVal->datum.p); if (len == 0) { return false; @@ -944,16 +944,27 @@ static bool validateTimezoneFormat(const SValueNode* pVal) { } else if ((tz[0] == '+' || tz[0] == '-')) { switch (len) { case 3: - case 5: + case 5: { + for (int32_t i = 1; i < len; ++i) { + if (!isdigit(tz[i])) { + return false; + } + } + break; + } case 6: { for (int32_t i = 1; i < len; ++i) { - if (len == 6 && i == 3 && tz[i] != ':') { - return false; + if (i == 3) { + if (tz[i] != ':') { + return false; + } + continue; } if (!isdigit(tz[i])) { return false; } } + break; } default: { return false; From 7d3ef94fd851760ddb3b7260228d002e79a598f3 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 1 Jun 2022 16:09:23 +0800 Subject: [PATCH 3/5] enh(query): to_iso8601 add server side handling of timezone param TD-16152 --- source/libs/scalar/src/sclfunc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index 6ee5f038d6..3241ab961e 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -849,6 +849,13 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { int32_t type = GET_PARAM_TYPE(pInput); + char* tz; + int32_t tzLen; + if (inputNum == 2) { + tz = varDataVal(pInput[1].columnData->pData); + tzLen = varDataLen(pInput[1].columnData->pData); + } + for (int32_t i = 0; i < pInput[0].numOfRows; ++i) { if (colDataIsNull_s(pInput[0].columnData, i)) { colDataAppendNULL(pOutput->columnData, i); @@ -880,9 +887,13 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam * } struct tm *tmInfo = taosLocalTime((const time_t *)&timeVal, NULL); - strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", tmInfo); + strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", tmInfo); int32_t len = (int32_t)strlen(buf); + //add timezone string + snprintf(buf + len, tzLen + 1, "%s", tz); + len += tzLen; + if (hasFraction) { int32_t fracLen = (int32_t)strlen(fraction) + 1; char *tzInfo = strchr(buf, '+'); From a00ea8e48d342317f1d90c239ab554821728198d Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 1 Jun 2022 10:27:11 +0000 Subject: [PATCH 4/5] enh(query): to_iso8601 param handing --- source/libs/function/src/builtins.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 9b481857ba..6165a16711 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -977,6 +977,27 @@ static bool validateTimezoneFormat(const SValueNode* pVal) { return true; } +void static addTimezoneParam(SNodeList* pList) { + char buf[6] = {0}; + time_t t = taosTime(NULL); + struct tm *tmInfo = taosLocalTime(&t, NULL); + strftime(buf, sizeof(buf), "%z", tmInfo); + int32_t len = (int32_t)strlen(buf); + + SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); + pVal->literal = strndup(buf, len); + pVal->isDuration =false; + pVal->translate = true; + pVal->node.resType.type = TSDB_DATA_TYPE_BINARY; + pVal->node.resType.bytes = len + VARSTR_HEADER_SIZE; + pVal->node.resType.precision = TSDB_TIME_PRECISION_MILLI; + pVal->datum.p = taosMemoryCalloc(1, len + VARSTR_HEADER_SIZE +1); + varDataSetLen(pVal->datum.p, len); + strncpy(varDataVal(pVal->datum.p), pVal->literal, len); + + nodesListAppend(pList, pVal); +} + static int32_t translateToIso8601(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); if (1 != numOfParams && 2 != numOfParams) { @@ -998,6 +1019,7 @@ static int32_t translateToIso8601(SFunctionNode* pFunc, char* pErrBuf, int32_t l "Invalid timzone format"); } } else { //add default client timezone + addTimezoneParam(pFunc->pParameterList); } //set result type From e04c09d4abe619507f06b35a01f2fc23cd089de1 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 1 Jun 2022 10:27:11 +0000 Subject: [PATCH 5/5] enh(query): to_iso8601 param handing --- source/libs/scalar/src/sclfunc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index 3241ab961e..291fbad480 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -851,10 +851,8 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam * char* tz; int32_t tzLen; - if (inputNum == 2) { - tz = varDataVal(pInput[1].columnData->pData); - tzLen = varDataLen(pInput[1].columnData->pData); - } + tz = varDataVal(pInput[1].columnData->pData); + tzLen = varDataLen(pInput[1].columnData->pData); for (int32_t i = 0; i < pInput[0].numOfRows; ++i) { if (colDataIsNull_s(pInput[0].columnData, i)) {