diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index 8f43f61404ac750eb81f3988b056df697c6107c3..493fe49e3fe79225e85060a88c07315494961a92 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -378,10 +378,10 @@ char* cloneCurrentDBName(SSqlObj* pSql); int parseJsontoTagData(char* json, SKVRowBuilder* kvRowBuilder, char* errMsg, int16_t startColId); char* parseTagDatatoJson(void *p); -void findTagValue(void* data, char* key, int32_t keyLen, char* out, int16_t len); +void findTagValue(STable* data, char* key, int32_t keyLen, char* out, int16_t len); int8_t jsonType2DbType(double data, int jsonType); -void* getJsonTagValue(STable* pTable, char* key); +void* getJsonTagValue(STable* pTable, char* key, int32_t keyLen); #ifdef __cplusplus } diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 0ccbcefbcbfeacd9bf0fdf1f86657218faa7020a..8150c45ae77647b039b3ad60d55427388d9a3fd5 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -725,22 +725,18 @@ static void setResRawPtrImpl(SSqlRes* pRes, SInternalField* pInfo, int32_t i, bo char* p = pRes->urow[i]; for (int32_t k = 0; k < pRes->numOfRows; ++k) { char* dst = pRes->buffer[i] + k * pInfo->field.bytes; - - if (isNull(p, TSDB_DATA_TYPE_NCHAR)) { - memcpy(dst, p, varDataTLen(p)); - } else { - if (*p == SELECT_ALL_JSON_TAG){ - char* json = parseTagDatatoJson(p+1); - if(json) { - memcpy(varDataVal(dst), json, strlen(json)); - varDataSetLen(dst, strlen(json)); - tfree(json); - } - }else if (*p == SELECT_ELEMENT_JSON_TAG){ - memcpy(dst, p+1, varDataTLen(p+1)); - }else{ - tscError("construct json error"); + char* realData = p + CHAR_BYTES; + if (*p == SELECT_ALL_JSON_TAG){ + char* json = parseTagDatatoJson(realData); + if(json) { + memcpy(varDataVal(dst), json, strlen(json)); + varDataSetLen(dst, strlen(json)); + tfree(json); } + }else if (*p == SELECT_ELEMENT_JSON_TAG){ + memcpy(dst, realData, varDataTLen(realData)); + }else{ + tscError("construct json error"); } p += pInfo->field.bytes; } @@ -5178,62 +5174,42 @@ char* cloneCurrentDBName(SSqlObj* pSql) { return p; } -void findTagValue(void* data, char* key, int32_t keyLen, char* out, int16_t len){ - int16_t nCols = kvRowNCols(data); - - bool found = false; - for (int k = 1; k < nCols; ++k) { - SColIdx* pColIdx = kvRowColIdxAt(data, k); - void* result = kvRowColVal(data, pColIdx); - - if (k % 2 != 0) { // json key - if (JSON_TYPE_BINARY){ - if (keyLen != varDataLen(result)) continue; - if (memcmp(varDataVal(result), key, keyLen) != 0) continue; - } else if(JSON_TYPE_NCHAR){ - char tagJsonKey[TSDB_MAX_TAGS_LEN] = {0}; - int32_t length = taosUcs4ToMbs(varDataVal(result), varDataLen(result), tagJsonKey); - if (length == 0) { - tscError("charset:%s to %s. val:%s convert json key failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, - (char*)result); - continue; - } - if (keyLen != length) continue; - if (strncmp(key, tagJsonKey, keyLen) != 0) continue; - } - found = true; - } else { // json value - if (!found) continue; - char* realData = POINTER_SHIFT(result, CHAR_BYTES); - if (*(char*)result == cJSON_String) { - - if (JSON_TYPE_BINARY){ - assert(varDataLen(realData) <= len); - memcpy(varDataVal(out), varDataVal(realData), varDataLen(realData)); - varDataSetLen(out, varDataLen(realData)); - } else if(JSON_TYPE_NCHAR) { - char tagJsonValue[TSDB_MAX_TAGS_LEN] = {0}; - int32_t length = taosUcs4ToMbs(varDataVal(realData), - varDataLen(realData), tagJsonValue); - if (length == 0) { - tscError("charset:%s to %s. val:%s convert json value failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, - (char*)result); - } else { - assert(length <= len); - varDataSetLen(out, length); - memcpy(varDataVal(out), tagJsonValue, length); - } - } - } else if (*(char*)result == cJSON_Number) { - double jsonVd = *(double*)(realData); - sprintf(varDataVal(out), "%.9lf", jsonVd); - assert(strlen(varDataVal(out)) <= len); - varDataSetLen(out, strlen(varDataVal(out))); - } else { - tscError("unsupportted json value"); - } - break; +void findTagValue(STable* data, char* key, int32_t keyLen, char* out, int16_t len){ + void* result = getJsonTagValue(data, key, keyLen); + if (result == NULL){ // json key no result + return; + } + char* realData = POINTER_SHIFT(result, CHAR_BYTES); + + if (*(char*)result == TSDB_DATA_TYPE_BINARY){ + assert(varDataLen(realData) <= len); + memcpy(varDataVal(out), varDataVal(realData), varDataLen(realData)); + varDataSetLen(out, varDataLen(realData)); + } else if(*(char*)result == TSDB_DATA_TYPE_NCHAR) { + char tagJsonValue[TSDB_MAX_TAGS_LEN] = {0}; + int32_t length = taosUcs4ToMbs(varDataVal(realData), + varDataLen(realData), tagJsonValue); + if (length == 0) { + tscError("charset:%s to %s. val:%s convert json value failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, + (char*)result); + return; } + assert(length <= len); + varDataSetLen(out, length); + memcpy(varDataVal(out), tagJsonValue, length); + }else if (*(char*)result == TSDB_DATA_TYPE_DOUBLE) { + double jsonVd = *(double*)(realData); + sprintf(varDataVal(out), "%.9lf", jsonVd); + assert(strlen(varDataVal(out)) <= len); + varDataSetLen(out, strlen(varDataVal(out))); + }else if (*(char*)result == TSDB_DATA_TYPE_BIGINT) { + int64_t jsonVd = *(int64_t*)(realData); + sprintf(varDataVal(out), "%" PRId64, jsonVd); + assert(strlen(varDataVal(out)) <= len); + varDataSetLen(out, strlen(varDataVal(out))); + } + else { + tscError("unsupportted json value"); } } @@ -5407,17 +5383,17 @@ int8_t jsonType2DbType(double data, int jsonType){ return TSDB_DATA_TYPE_NULL; } -void* getJsonTagValue(STable* pTable, char* key){ +void* getJsonTagValue(STable* pTable, char* key, int32_t keyLen){ int32_t outLen = 0; if(JSON_TYPE_NCHAR){ char tagKey[256] = {0}; - if (!taosMbsToUcs4(key, strlen(key), tagKey, 256, &outLen)) { + if (!taosMbsToUcs4(key, keyLen, tagKey, 256, &outLen)) { tscError("json key to ucs4 error:%s|%s", strerror(errno), key); return NULL; } key = tagKey; }else{ - outLen = strlen(key); + outLen = keyLen; } if(TABLE_TYPE(pTable) == TSDB_CHILD_TABLE){ STable* superTable= pTable->pSuper; diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 5c12936fd24de8b399d33b7ac862b628b96dccc3..6f826555a898751b169109df5a3ff97753863603 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -7186,23 +7186,24 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) { if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { data = tsdbGetTableName(item->pTable); } else { - data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes); if(type == TSDB_DATA_TYPE_JSON){ if(pExprInfo[j].base.numOfParams > 0){ // tag-> operation tagJsonElementData = calloc(bytes, 1); - findTagValue(data, pExprInfo[j].base.param[0].pz, pExprInfo[j].base.param[0].nLen, tagJsonElementData, bytes); + findTagValue(item->pTable, pExprInfo[j].base.param[0].pz, pExprInfo[j].base.param[0].nLen, tagJsonElementData, bytes); *dst = SELECT_ELEMENT_JSON_TAG; // select tag->element dst++; assert(varDataTLen(tagJsonElementData) < bytes); - doSetTagValueToResultBuf(dst, tagJsonElementData, type, bytes - 1); + doSetTagValueToResultBuf(dst, tagJsonElementData, type, bytes - CHAR_BYTES); tfree(tagJsonElementData); }else{ *dst = SELECT_ALL_JSON_TAG; // select tag dst++; assert(kvRowLen(data) < bytes); - doSetTagValueToResultBuf(dst, data, type, bytes - 1); + doSetTagValueToResultBuf(dst, data, type, bytes - CHAR_BYTES); } continue; + }else{ + data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes); } } doSetTagValueToResultBuf(dst, data, type, bytes); diff --git a/src/query/src/qFilter.c b/src/query/src/qFilter.c index 44831473dab4380bbcef19b444c34d818b94536f..a8d0f7ddba5958a0569303b87ebf60d0a1efbec1 100644 --- a/src/query/src/qFilter.c +++ b/src/query/src/qFilter.c @@ -3180,7 +3180,7 @@ int filterJsonTypeConvert(SFilterInfo* info) { SSchema* schema = info->fields[FLD_TYPE_COLUMN].fields[i].desc; if(schema->type == TSDB_DATA_TYPE_JSON){ - void* data = getJsonTagValue(info->pTable, schema->name); + void* data = getJsonTagValue(info->pTable, schema->name, strlen(schema->name)); if(data == NULL) return TSDB_CODE_QRY_JSON_KEY_NOT_EXIST; int8_t type = *(char*)data; assert(type > TSDB_DATA_TYPE_NULL && type < TSDB_DATA_TYPE_JSON); diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 9cb904a9d024130e9b28c10f830293acb4316237..ce0097588c5b3f398d68b571ca5649b2c83e1801 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -4075,7 +4075,7 @@ static FORCE_INLINE int32_t tsdbGetJsonTagDataFromId(void *param, int32_t id, ch if (id == TSDB_TBNAME_COLUMN_INDEX) { *data = TABLE_NAME(pTable); } else { - void* jsonData = getJsonTagValue(pTable, name); + void* jsonData = getJsonTagValue(pTable, name, strlen(name)); if (jsonData != NULL) jsonData += CHAR_BYTES; // jump type *data = jsonData; } diff --git a/tests/pytest/stable/json_tag.py b/tests/pytest/stable/json_tag.py index 30ee9a80e6488e273857fe562904059d07b4e439..96efaaf76e6b85e8fe1c38d71a604cf513d84639 100644 --- a/tests/pytest/stable/json_tag.py +++ b/tests/pytest/stable/json_tag.py @@ -45,6 +45,11 @@ class TDTestCase: tdSql.query("select jtag from db_json_tag_test.jsons1_1") tdSql.checkRows(1) + tdSql.error("select * from db_json_tag_test.jsons1 where jtag->'location'=4") + + tdSql.error("select * from db_json_tag_test.jsons1 where jtag->'location'='beijing'") + tdSql.checkRows(1) + print("==============step3") tdLog.info("alter stable add tag") tdSql.error("ALTER STABLE db_json_tag_test.jsons1 add tag tag2 nchar(20)")