diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index 4cc4e881ce..3de07f87bb 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -251,7 +251,7 @@ struct SValue { union { int64_t val; struct { - uint8_t *pData; // free or no free??? + uint8_t *pData; // TODO wjm free or no free??? uint32_t nData; }; }; diff --git a/include/libs/decimal/decimal.h b/include/libs/decimal/decimal.h index 785fe5510f..447b7be767 100644 --- a/include/libs/decimal/decimal.h +++ b/include/libs/decimal/decimal.h @@ -60,6 +60,7 @@ int32_t decimalOp(EOperatorType op, const SDataType* pLeftT, const SDataType* pR const void* pLeftData, const void* pRightData, void* pOutputData); int32_t convertToDecimal(const void* pData, const SDataType* pInputType, void* pOut, const SDataType* poutType); +// TODO wjm change rightWordNum to DecimalType?? typedef struct SDecimalOps { void (*negate)(DecimalWord* pWord); void (*abs)(DecimalWord* pWord); diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 29e95251e9..f1b894bc8d 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -161,6 +161,7 @@ int32_t taosGetErrSize(); #define TSDB_CODE_UNSUPPORT_OS TAOS_DEF_ERROR_CODE(0, 0x013A) #define TSDB_CODE_TIME_ERROR TAOS_DEF_ERROR_CODE(0, 0x013B) #define TSDB_CODE_INVALID_DISK_ID TAOS_DEF_ERROR_CODE(0, 0x013C) +#define TSDB_CODE_DECIMAL_OVERFLOW TAOS_DEF_ERROR_CODE(0, 0x013D) //client #define TSDB_CODE_TSC_INVALID_OPERATION TAOS_DEF_ERROR_CODE(0, 0x0200) diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index a9659a0dce..e6c7a9f0d7 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -751,6 +751,15 @@ int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD case TSDB_DATA_TYPE_BOOL: len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i])); + break; + case TSDB_DATA_TYPE_DECIMAL64: + case TSDB_DATA_TYPE_DECIMAL: { + // TODO wjm var header len??? + uint32_t decimalLen = strlen(row[i]); + uint32_t copyLen = TMIN(size - len - 1, decimalLen); + (void)memcpy(str + len, row[i], copyLen); + len += copyLen; + } break; default: break; } diff --git a/source/libs/decimal/src/decimal.c b/source/libs/decimal/src/decimal.c index 1198c1e33f..7323758d5b 100644 --- a/source/libs/decimal/src/decimal.c +++ b/source/libs/decimal/src/decimal.c @@ -109,26 +109,6 @@ void decimalFromTypeMod(STypeMod typeMod, uint8_t* precision, uint8_t* scale) { *scale = (uint8_t)(typeMod & 0xFF); } -int32_t decimal64FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale, - Decimal64* result) { - int32_t code = 0; - DecimalVar var = {.type = DECIMAL_64, .words = result->words}; - code = decimalVarFromStr(str, len, &var); - if (TSDB_CODE_SUCCESS != code) return code; - // TODO wjm precision check - // scale auto fit - return code; -} - -int32_t decimal128FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale, - Decimal128* result) { - int32_t code = 0; - DecimalVar var = {.type = DECIMAL_128, .words = result->words}; - code = decimalVarFromStr(str, len, &var); - if (TSDB_CODE_SUCCESS != code) return code; - return code; -} - static int32_t decimalVarFromStr(const char* str, int32_t len, DecimalVar* result) { int32_t code = 0, pos = 0; result->precision = 0; @@ -183,10 +163,12 @@ static int32_t decimalVarFromStr(const char* str, int32_t len, DecimalVar* resul } else { result->precision += places; if (afterPoint) { - result->scale++; + result->scale += places; } DecimalWord ten = 10, digit = str[pos] - '0'; - pOps->multiply(result->words, &ten, 1); + while (places-- > 0) { + pOps->multiply(result->words, &ten, 1); + } pOps->add(result->words, &digit, 1); places = 0; break; @@ -194,6 +176,7 @@ static int32_t decimalVarFromStr(const char* str, int32_t len, DecimalVar* resul } case 'e': case 'E': + // TODO wjm handle E break; default: break; @@ -212,9 +195,10 @@ int32_t decimal64ToDataVal(const Decimal64* dec, SValue* pVal) { } int32_t decimal128ToDataVal(Decimal128* dec, SValue* pVal) { - pVal->pData = taosMemCalloc(2, sizeof(DecimalWord)); - if (!pVal->pData) return terrno; - valueSetDatum(pVal, TSDB_DATA_TYPE_DECIMAL, dec->words, DECIMAL_WORD_NUM(Decimal128) * sizeof(DecimalWord)); + void* pV = taosMemCalloc(1, sizeof(Decimal128)); + if (!pV) return terrno; + memcpy(pV, dec->words, DECIMAL_WORD_NUM(Decimal128) * sizeof(DecimalWord)); + valueSetDatum(pVal, TSDB_DATA_TYPE_DECIMAL, pV, DECIMAL_WORD_NUM(Decimal128) * sizeof(DecimalWord)); return TSDB_CODE_SUCCESS; } @@ -302,6 +286,7 @@ static bool decimal128Lt(const DecimalWord* pLeft, const DecimalWord* pRight, static bool decimal128Gt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum); static bool decimal128Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum); static int32_t decimal128ToStr(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32_t bufLen); +static void decimal64ScaleTo(Decimal64* pDec, uint8_t oldScale, uint8_t newScale); SDecimalOps decimal64Ops = {decimal64Negate, decimal64Abs, decimal64Add, decimal64Subtract, decimal64Multiply, decimal64divide, decimal64Mod, decimal64Lt, @@ -341,7 +326,9 @@ bool decimal64Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t ri return *pLeft == *pRight; } int32_t decimal64ToStr(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32_t bufLen) { - return snprintf(pBuf, bufLen, "%" PRId64, *pInt); + char format[16] = "\%0"; + snprintf(format+2, 14, "%"PRIu8 PRIu64, scale); + return snprintf(pBuf, bufLen, *pInt != 0 ? format : "%"PRIu64, *pInt); } // TODO wjm handle endian problem @@ -351,46 +338,48 @@ int32_t decimal64ToStr(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32 #define DECIMAL128_SIGN(pDec) (1 | (DECIMAL128_HIGH_WORDS(pDec) >> 63)) // TODO wjm handle endian problem +#define DEFINE_DECIMAL128(lo, hi) {lo, hi} + static Decimal128 SCALE_MULTIPLIER_128[38 + 1] = { - {0, 1LL}, - {0, 10LL}, - {0, 100LL}, - {0, 1000LL}, - {0, 10000LL}, - {0, 100000LL}, - {0, 1000000LL}, - {0, 10000000LL}, - {0, 100000000LL}, - {0, 1000000000LL}, - {0, 10000000000LL}, - {0, 100000000000LL}, - {0, 1000000000000LL}, - {0, 10000000000000LL}, - {0, 100000000000000LL}, - {0, 1000000000000000LL}, - {0, 10000000000000000LL}, - {0, 100000000000000000LL}, - {0, 1000000000000000000LL}, - {0LL, 10000000000000000000ULL}, - {5LL, 7766279631452241920ULL}, - {54LL, 3875820019684212736ULL}, - {542LL, 1864712049423024128ULL}, - {5421LL, 200376420520689664ULL}, - {54210LL, 2003764205206896640ULL}, - {542101LL, 1590897978359414784ULL}, - {5421010LL, 15908979783594147840ULL}, - {54210108LL, 11515845246265065472ULL}, - {542101086LL, 4477988020393345024ULL}, - {5421010862LL, 7886392056514347008ULL}, - {54210108624LL, 5076944270305263616ULL}, - {542101086242LL, 13875954555633532928ULL}, - {5421010862427LL, 9632337040368467968ULL}, - {54210108624275LL, 4089650035136921600ULL}, - {542101086242752LL, 4003012203950112768ULL}, - {5421010862427522LL, 3136633892082024448ULL}, - {54210108624275221LL, 12919594847110692864ULL}, - {542101086242752217LL, 68739955140067328ULL}, - {5421010862427522170LL, 687399551400673280ULL}, + DEFINE_DECIMAL128( 1LL,0), + DEFINE_DECIMAL128( 10LL,0), + DEFINE_DECIMAL128( 100LL,0), + DEFINE_DECIMAL128( 1000LL,0), + DEFINE_DECIMAL128( 10000LL,0), + DEFINE_DECIMAL128( 100000LL,0), + DEFINE_DECIMAL128( 1000000LL,0), + DEFINE_DECIMAL128( 10000000LL,0), + DEFINE_DECIMAL128( 100000000LL,0), + DEFINE_DECIMAL128( 1000000000LL,0), + DEFINE_DECIMAL128( 10000000000LL,0), + DEFINE_DECIMAL128( 100000000000LL,0), + DEFINE_DECIMAL128( 1000000000000LL,0), + DEFINE_DECIMAL128( 10000000000000LL,0), + DEFINE_DECIMAL128( 100000000000000LL,0), + DEFINE_DECIMAL128( 1000000000000000LL,0), + DEFINE_DECIMAL128( 10000000000000000LL,0), + DEFINE_DECIMAL128( 100000000000000000LL,0), + DEFINE_DECIMAL128( 1000000000000000000LL,0), + DEFINE_DECIMAL128( 10000000000000000000ULL,0LL), + DEFINE_DECIMAL128( 7766279631452241920ULL,5LL), + DEFINE_DECIMAL128( 3875820019684212736ULL,54LL), + DEFINE_DECIMAL128( 1864712049423024128ULL,542LL), + DEFINE_DECIMAL128( 200376420520689664ULL,5421LL), + DEFINE_DECIMAL128( 2003764205206896640ULL,54210LL), + DEFINE_DECIMAL128( 1590897978359414784ULL,542101LL), + DEFINE_DECIMAL128( 15908979783594147840ULL,5421010LL), + DEFINE_DECIMAL128( 11515845246265065472ULL,54210108LL), + DEFINE_DECIMAL128( 4477988020393345024ULL,542101086LL), + DEFINE_DECIMAL128( 7886392056514347008ULL,5421010862LL), + DEFINE_DECIMAL128( 5076944270305263616ULL,54210108624LL), + DEFINE_DECIMAL128( 13875954555633532928ULL,542101086242LL), + DEFINE_DECIMAL128( 9632337040368467968ULL,5421010862427LL), + DEFINE_DECIMAL128( 4089650035136921600ULL,54210108624275LL), + DEFINE_DECIMAL128( 4003012203950112768ULL,542101086242752LL), + DEFINE_DECIMAL128( 3136633892082024448ULL,5421010862427522LL), + DEFINE_DECIMAL128( 12919594847110692864ULL,54210108624275221LL), + DEFINE_DECIMAL128( 68739955140067328ULL,542101086242752217LL), + DEFINE_DECIMAL128( 687399551400673280ULL,5421010862427522170LL), }; #define DECIMAL128_ONE SCALE_MULTIPLIER_128[0] @@ -510,9 +499,9 @@ static void decimal128divide(DecimalWord* pLeft, const DecimalWord* pRight, uint uInt128Divide(&a, &b); uInt128Mod(&d, &b); makeDecimal128(pLeftDec, uInt128Hi(&a), uInt128Lo(&a)); - makeDecimal128(pRemainderDec, uInt128Hi(&d), uInt128Lo(&d)); + if (pRemainder) makeDecimal128(pRemainderDec, uInt128Hi(&d), uInt128Lo(&d)); if (negate) decimal128Negate(pLeftDec->words); - if (DECIMAL128_SIGN(pLeftDec) == -1) decimal128Negate(pRemainderDec->words); + if (DECIMAL128_SIGN(pLeftDec) == -1 && pRemainder) decimal128Negate(pRemainderDec->words); } static void decimal128Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {} @@ -574,6 +563,7 @@ static int32_t decimal128ToStr(const DecimalWord* pInt, uint8_t scale, char* pBu } int32_t len = 0; for (int32_t i = digitNum - 1; i >= 0; --i) { + // TODO wjm test 0.0000000000000000000000000000000001 len += snprintf(buf + len, 64 - len, i == digitNum - 1 ? "%" PRIu64 : "%018" PRIu64, segments[i]); } int32_t wholeLen = len - scale; @@ -586,7 +576,7 @@ static int32_t decimal128ToStr(const DecimalWord* pInt, uint8_t scale, char* pBu } return 0; } - +// TODO wjm refine this interface int32_t decimalToStr(const DecimalWord* pDec, int8_t dataType, int8_t precision, int8_t scale, char* pBuf, int32_t bufLen) { pBuf[0] = '\0'; @@ -606,8 +596,8 @@ int32_t decimalToStr(const DecimalWord* pDec, int8_t dataType, int8_t precision, if (!pOps->eq(whole.words, &zero, 1)) { pos += pOps->toStr(whole.words, scale, pBuf + pos, bufLen - pos); } - pos += snprintf(pBuf + pos, bufLen - pos, "."); code = decimalGetFrac(pDec, iType, scale, frac.words); + if (frac.words[0] != 0) pos += snprintf(pBuf + pos, bufLen - pos, "."); pOps->toStr(frac.words, scale, pBuf + pos, bufLen - pos); return 0; } @@ -770,3 +760,48 @@ int32_t convertToDecimal(const void* pData, const SDataType* pInputType, void* p } return code; } + +void decimal64ScaleTo(Decimal64* pDec, uint8_t oldScale, uint8_t newScale) { + if (newScale < oldScale) { + Decimal64 divisor = SCALE_MULTIPLIER_64[oldScale - newScale]; + decimal64divide(pDec->words, divisor.words, 1, NULL); + } +} + +int32_t decimal64FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale, + Decimal64* result) { + int32_t code = 0; + DecimalVar var = {.type = DECIMAL_64, .words = result->words}; + code = decimalVarFromStr(str, len, &var); + if (TSDB_CODE_SUCCESS != code) return code; + Decimal64 max = {0}; + DECIMAL64_GET_MAX(expectPrecision - expectScale, &max); + if (decimal64Gt(result->words, max.words, 1)) { + return TSDB_CODE_DECIMAL_OVERFLOW; + } + if (var.scale > expectScale) decimal64ScaleTo(result, var.scale, expectScale); + return code; +} + +void decimal128ScaleTo(Decimal128* pDec, uint8_t oldScale, uint8_t newScale) { + if (newScale < oldScale) { + Decimal128 divisor = SCALE_MULTIPLIER_128[oldScale - newScale]; + decimal128divide(pDec->words, divisor.words, 2, NULL); + } +} + +int32_t decimal128FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale, + Decimal128* result) { + int32_t code = 0; + DecimalVar var = {.type = DECIMAL_128, .words = result->words}; + code = decimalVarFromStr(str, len, &var); + if (TSDB_CODE_SUCCESS != code) return code; + Decimal128 max = {0}; + DECIMAL128_GET_MAX(expectPrecision - expectScale, &max); + if (decimal128Gt(result->words, max.words, 2)) { + return TSDB_CODE_DECIMAL_OVERFLOW; + } + if (var.scale > expectScale) decimal128ScaleTo(result, var.scale, expectScale); + return code; +} + diff --git a/source/libs/decimal/test/CMakeLists.txt b/source/libs/decimal/test/CMakeLists.txt index 23ee480ccc..1d1c50b9e5 100644 --- a/source/libs/decimal/test/CMakeLists.txt +++ b/source/libs/decimal/test/CMakeLists.txt @@ -14,5 +14,5 @@ TARGET_INCLUDE_DIRECTORIES( TARGET_LINK_LIBRARIES( decimalTest - PUBLIC os util common gtest qcom decimal + PUBLIC gtest taos os common ) diff --git a/source/libs/decimal/test/decimalTest.cpp b/source/libs/decimal/test/decimalTest.cpp index f36bd7e2fe..4167d5329b 100644 --- a/source/libs/decimal/test/decimalTest.cpp +++ b/source/libs/decimal/test/decimalTest.cpp @@ -1,6 +1,7 @@ #include #include #include "decimal.h" +#include "tcommon.h" #include "wideInteger.h" using namespace std; @@ -103,6 +104,58 @@ TEST(decimal128, divide) { printDecimal128(&d, out_precision, out_scale); } +TEST(decimal, cpi_taos_fetch_rows) { + const char* host = "127.0.0.1"; + const char* user = "root"; + const char* passwd = "taosdata"; + const char* db = "test"; + const char* sql = "select c1, c2 from nt"; + + TAOS* pTaos = taos_connect(host, user, passwd, db, 0); + if (!pTaos) { + cout << "taos connect failed: " << host << " " << taos_errstr(NULL); + FAIL(); + } + + auto *res = taos_query(pTaos, sql); + int32_t code = taos_errno(res); + if (code != 0) { + cout << "taos_query with sql: " << sql << " failed: " << taos_errstr(res); + FAIL(); + } + + char buf[1024] = {0}; + auto *fields = taos_fetch_fields(res); + auto fieldNum = taos_field_count(res); + while (auto row = taos_fetch_row(res)) { + taos_print_row(buf, row, fields, fieldNum); + cout << buf << endl; + } + taos_free_result(res); + + res = taos_query(pTaos, sql); + code = taos_errno(res); + if (code != 0) { + cout << "taos_query with sql: " << sql << " failed: " << taos_errstr(res); + FAIL(); + } + + void* pData = NULL; + int32_t numOfRows = 0; + code = taos_fetch_raw_block(res, &numOfRows, &pData); + if (code != 0) { + cout << "taos_query with sql: " << sql << " failed: " << taos_errstr(res); + FAIL(); + } + + SSDataBlock* pBlock; + taos_free_result(res); + + + taos_close(pTaos); + taos_cleanup(); +} + int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/source/libs/parser/inc/parUtil.h b/source/libs/parser/inc/parUtil.h index 584ae16252..445883ab55 100644 --- a/source/libs/parser/inc/parUtil.h +++ b/source/libs/parser/inc/parUtil.h @@ -125,6 +125,7 @@ int32_t buildInvalidOperationMsgExt(SMsgBuf* pBuf, const char* pFormat, ...); int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr); SSchema* getTableColumnSchema(const STableMeta* pTableMeta); +SSchemaExt* getTableColumnExtSchema(const STableMeta* pTableMeta); SSchema* getTableTagSchema(const STableMeta* pTableMeta); int32_t getNumOfColumns(const STableMeta* pTableMeta); int32_t getNumOfTags(const STableMeta* pTableMeta); diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index 9382180a5a..7d086d108d 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -1571,7 +1571,7 @@ static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifyOpStm } static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema, - int16_t timePrec, SColVal* pVal) { + const SSchemaExt* pExtSchema, int16_t timePrec, SColVal* pVal) { switch (pSchema->type) { case TSDB_DATA_TYPE_BOOL: { if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) { @@ -1786,7 +1786,12 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, break; } case TSDB_DATA_TYPE_DECIMAL: { + if (!pExtSchema) { + qError("Decimal type without ext schema info, cannot parse decimal values"); + return TSDB_CODE_PAR_INTERNAL_ERROR; + } uint8_t precision = 0, scale = 0; + decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale); Decimal128 dec = {0}; int32_t code = decimal128FromStr(pToken->z, pToken->n, precision, scale, &dec); if (TSDB_CODE_SUCCESS != code) { @@ -1803,7 +1808,12 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, break; } case TSDB_DATA_TYPE_DECIMAL64: { + if (!pExtSchema) { + qError("Decimal type without ext schema info, cannot parse decimal values"); + return TSDB_CODE_PAR_INTERNAL_ERROR; + } uint8_t precision = 0, scale = 0; + decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale); Decimal64 dec = {0}; int32_t code = decimal64FromStr(pToken->z, pToken->n, precision, scale, &dec); if (TSDB_CODE_SUCCESS != code) { @@ -1827,7 +1837,7 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, } static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema, - int16_t timePrec, SColVal* pVal) { + const SSchemaExt* pExtSchema, int16_t timePrec, SColVal* pVal) { int32_t code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pSchema->type); if (TSDB_CODE_SUCCESS == code && isNullValue(pSchema->type, pToken)) { if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { @@ -1842,7 +1852,7 @@ static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, STo if (pToken->n == 0 && IS_NUMERIC_TYPE(pSchema->type)) { return buildSyntaxErrMsg(&pCxt->msg, "invalid numeric data", pToken->z); } - code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, timePrec, pVal); + code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, pExtSchema, timePrec, pVal); } return code; @@ -1942,8 +1952,9 @@ static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModif static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql, SStbRowsDataContext* pStbRowsCxt, SToken* pToken, const SBoundColInfo* pCols, - const SSchema* pSchemas, SToken* tagTokens, SSchema** tagSchemas, int* pNumOfTagTokens, - bool* bFoundTbName, bool* setCtbName, SBoundColInfo* ctbCols) { + const SSchema* pSchemas, const SSchemaExt* pExtSchemas, SToken* tagTokens, + SSchema** tagSchemas, int* pNumOfTagTokens, bool* bFoundTbName, bool* setCtbName, + SBoundColInfo* ctbCols) { int32_t code = TSDB_CODE_SUCCESS; SArray* pTagNames = pStbRowsCxt->aTagNames; SArray* pTagVals = pStbRowsCxt->aTagVals; @@ -2021,9 +2032,10 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* return buildInvalidOperationMsg(&pCxt->msg, "not support mixed bind and non-bind values"); } if (pCols->pColIndex[i] < numOfCols) { - const SSchema* pSchema = &pSchemas[pCols->pColIndex[i]]; + const SSchema* pSchema = &pSchemas[pCols->pColIndex[i]]; + const SSchemaExt* pExtSchema = pExtSchemas + pCols->pColIndex[i]; SColVal* pVal = taosArrayGet(pStbRowsCxt->aColVals, pCols->pColIndex[i]); - code = parseValueToken(pCxt, ppSql, pToken, (SSchema*)pSchema, precision, pVal); + code = parseValueToken(pCxt, ppSql, pToken, (SSchema*)pSchema, pExtSchema, precision, pVal); if (TK_NK_VARIABLE == pToken->type) { code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value"); } @@ -2071,6 +2083,7 @@ static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pS bool* setCtbName, SBoundColInfo* ctbCols) { SBoundColInfo* pCols = &pStbRowsCxt->boundColsInfo; SSchema* pSchemas = getTableColumnSchema(pStbRowsCxt->pStbMeta); + SSchemaExt* pExtSchemas = getTableColumnExtSchema(pStbRowsCxt->pStbMeta); bool bFoundTbName = false; const char* pOrigSql = *ppSql; @@ -2080,7 +2093,7 @@ static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pS SSchema* tagSchemas[TSDB_MAX_TAGS] = {0}; int numOfTagTokens = 0; - code = doGetStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pToken, pCols, pSchemas, tagTokens, tagSchemas, + code = doGetStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pToken, pCols, pSchemas, pExtSchemas, tagTokens, tagSchemas, &numOfTagTokens, &bFoundTbName, setCtbName, ctbCols); if (code != TSDB_CODE_SUCCESS) { @@ -2275,8 +2288,9 @@ static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pSt static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataCxt* pTableCxt, bool* pGotRow, SToken* pToken) { - SBoundColInfo* pCols = &pTableCxt->boundColsInfo; - SSchema* pSchemas = getTableColumnSchema(pTableCxt->pMeta); + SBoundColInfo* pCols = &pTableCxt->boundColsInfo; + SSchema* pSchemas = getTableColumnSchema(pTableCxt->pMeta); + const SSchemaExt* pExtSchemas = getTableColumnExtSchema(pTableCxt->pMeta); int32_t code = TSDB_CODE_SUCCESS; // 1. set the parsed value from sql string @@ -2289,8 +2303,9 @@ static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataC break; } - SSchema* pSchema = &pSchemas[pCols->pColIndex[i]]; - SColVal* pVal = taosArrayGet(pTableCxt->pValues, pCols->pColIndex[i]); + SSchema* pSchema = &pSchemas[pCols->pColIndex[i]]; + const SSchemaExt* pExtSchema = pExtSchemas + pCols->pColIndex[i]; + SColVal* pVal = taosArrayGet(pTableCxt->pValues, pCols->pColIndex[i]); if (pToken->type == TK_NK_QUESTION) { pCxt->isStmtBind = true; @@ -2310,7 +2325,7 @@ static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataC } if (TSDB_CODE_SUCCESS == code) { - code = parseValueToken(pCxt, pSql, pToken, pSchema, getTableInfo(pTableCxt->pMeta).precision, pVal); + code = parseValueToken(pCxt, pSql, pToken, pSchema, pExtSchema, getTableInfo(pTableCxt->pMeta).precision, pVal); } } diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index fd555c5f19..ce60513c0a 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -296,6 +296,8 @@ int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* SSchema* getTableColumnSchema(const STableMeta* pTableMeta) { return (SSchema*)pTableMeta->schema; } +SSchemaExt* getTableColumnExtSchema(const STableMeta* pTableMeta) { return pTableMeta->schemaExt; } + static SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) { SSchema* pSchema = (SSchema*)pTableMeta->schema; return &pSchema[colIndex]; diff --git a/source/util/src/terror.c b/source/util/src/terror.c index cbc7f4d1be..836323dd64 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -120,6 +120,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_OUT_OF_BUFFER, "Out of buffer") TAOS_DEFINE_ERROR(TSDB_CODE_INTERNAL_ERROR, "Internal error") TAOS_DEFINE_ERROR(TSDB_CODE_TIME_ERROR, "Internal error in time") TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_DISK_ID, "Internal error invalid disk id") +TAOS_DEFINE_ERROR(TSDB_CODE_DECIMAL_OVERFLOW, "Decimal value overflow") //client TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_OPERATION, "Invalid operation")