decimal testing

This commit is contained in:
wangjiaming0909 2025-02-13 09:55:46 +08:00
parent 51fe4bd0c3
commit cdc6d6eaf4
9 changed files with 251 additions and 105 deletions

View File

@ -3440,6 +3440,8 @@ typedef struct {
int8_t source; // TD_REQ_FROM_TAOX-taosX or TD_REQ_FROM_APP-taosClient int8_t source; // TD_REQ_FROM_TAOX-taosX or TD_REQ_FROM_APP-taosClient
uint32_t compress; // TSDB_ALTER_TABLE_UPDATE_COLUMN_COMPRESS uint32_t compress; // TSDB_ALTER_TABLE_UPDATE_COLUMN_COMPRESS
SArray* pMultiTag; // TSDB_ALTER_TABLE_ADD_MULTI_TAGS SArray* pMultiTag; // TSDB_ALTER_TABLE_ADD_MULTI_TAGS
// for Add column
STypeMod typeMod;
} SVAlterTbReq; } SVAlterTbReq;
int32_t tEncodeSVAlterTbReq(SEncoder* pEncoder, const SVAlterTbReq* pReq); int32_t tEncodeSVAlterTbReq(SEncoder* pEncoder, const SVAlterTbReq* pReq);

View File

@ -10965,6 +10965,7 @@ int32_t tEncodeSVAlterTbReq(SEncoder *pEncoder, const SVAlterTbReq *pReq) {
TAOS_CHECK_EXIT(tEncodeI8(pEncoder, pReq->type)); TAOS_CHECK_EXIT(tEncodeI8(pEncoder, pReq->type));
TAOS_CHECK_EXIT(tEncodeI8(pEncoder, pReq->flags)); TAOS_CHECK_EXIT(tEncodeI8(pEncoder, pReq->flags));
TAOS_CHECK_EXIT(tEncodeI32v(pEncoder, pReq->bytes)); TAOS_CHECK_EXIT(tEncodeI32v(pEncoder, pReq->bytes));
TAOS_CHECK_EXIT(tEncodeI32(pEncoder, pReq->typeMod));
break; break;
case TSDB_ALTER_TABLE_DROP_COLUMN: case TSDB_ALTER_TABLE_DROP_COLUMN:
TAOS_CHECK_EXIT(tEncodeCStr(pEncoder, pReq->colName)); TAOS_CHECK_EXIT(tEncodeCStr(pEncoder, pReq->colName));
@ -11021,6 +11022,7 @@ int32_t tEncodeSVAlterTbReq(SEncoder *pEncoder, const SVAlterTbReq *pReq) {
TAOS_CHECK_EXIT(tEncodeI8(pEncoder, pReq->flags)); TAOS_CHECK_EXIT(tEncodeI8(pEncoder, pReq->flags));
TAOS_CHECK_EXIT(tEncodeI32v(pEncoder, pReq->bytes)); TAOS_CHECK_EXIT(tEncodeI32v(pEncoder, pReq->bytes));
TAOS_CHECK_EXIT(tEncodeU32(pEncoder, pReq->compress)); TAOS_CHECK_EXIT(tEncodeU32(pEncoder, pReq->compress));
TAOS_CHECK_EXIT(tEncodeI32(pEncoder, pReq->typeMod));
break; break;
default: default:
break; break;
@ -11046,6 +11048,9 @@ static int32_t tDecodeSVAlterTbReqCommon(SDecoder *pDecoder, SVAlterTbReq *pReq)
TAOS_CHECK_EXIT(tDecodeI8(pDecoder, &pReq->type)); TAOS_CHECK_EXIT(tDecodeI8(pDecoder, &pReq->type));
TAOS_CHECK_EXIT(tDecodeI8(pDecoder, &pReq->flags)); TAOS_CHECK_EXIT(tDecodeI8(pDecoder, &pReq->flags));
TAOS_CHECK_EXIT(tDecodeI32v(pDecoder, &pReq->bytes)); TAOS_CHECK_EXIT(tDecodeI32v(pDecoder, &pReq->bytes));
if (!tDecodeIsEnd(pDecoder)) {
TAOS_CHECK_EXIT(tDecodeI32(pDecoder, &pReq->typeMod));
}
break; break;
case TSDB_ALTER_TABLE_DROP_COLUMN: case TSDB_ALTER_TABLE_DROP_COLUMN:
TAOS_CHECK_EXIT(tDecodeCStr(pDecoder, &pReq->colName)); TAOS_CHECK_EXIT(tDecodeCStr(pDecoder, &pReq->colName));
@ -11109,6 +11114,9 @@ static int32_t tDecodeSVAlterTbReqCommon(SDecoder *pDecoder, SVAlterTbReq *pReq)
TAOS_CHECK_EXIT(tDecodeI8(pDecoder, &pReq->flags)); TAOS_CHECK_EXIT(tDecodeI8(pDecoder, &pReq->flags));
TAOS_CHECK_EXIT(tDecodeI32v(pDecoder, &pReq->bytes)); TAOS_CHECK_EXIT(tDecodeI32v(pDecoder, &pReq->bytes));
TAOS_CHECK_EXIT(tDecodeU32(pDecoder, &pReq->compress)); TAOS_CHECK_EXIT(tDecodeU32(pDecoder, &pReq->compress));
if (!tDecodeIsEnd(pDecoder)) {
TAOS_CHECK_EXIT(tDecodeI32(pDecoder, &pReq->typeMod));
}
default: default:
break; break;
} }

View File

@ -428,6 +428,15 @@ int32_t metaCloneEntry(const SMetaEntry *pEntry, SMetaEntry **ppEntry) {
metaCloneEntryFree(ppEntry); metaCloneEntryFree(ppEntry);
return code; return code;
} }
if (pEntry->pExtSchemas && pEntry->colCmpr.nCols > 0) {
(*ppEntry)->pExtSchemas = taosMemoryCalloc(pEntry->colCmpr.nCols, sizeof(SExtSchema));
if (!(*ppEntry)->pExtSchemas) {
code = terrno;
metaCloneEntryFree(ppEntry);
return code;
}
memcpy((*ppEntry)->pExtSchemas, pEntry->pExtSchemas, sizeof(SExtSchema) * pEntry->colCmpr.nCols);
}
return code; return code;
} }

View File

@ -69,6 +69,36 @@ int32_t updataTableColCmpr(SColCmprWrapper *pWp, SSchema *pSchema, int8_t add, u
return 0; return 0;
} }
int32_t addTableExtSchema(SMetaEntry *pEntry, const SSchema *pColumn, int32_t newColNum, SExtSchema *pExtSchema) {
// no need to add ext schema when no column needs ext schemas
if (!HAS_TYPE_MOD(pColumn) && !pEntry->pExtSchemas) return 0;
if (!pEntry->pExtSchemas) {
// add a column which needs ext schema
// set all extschemas to zero for all columns alrady existed
pEntry->pExtSchemas = (SExtSchema *)taosMemoryCalloc(newColNum, sizeof(SExtSchema));
} else {
// already has columns with ext schema
pEntry->pExtSchemas = (SExtSchema *)taosMemoryRealloc(pEntry->pExtSchemas, sizeof(SExtSchema) * newColNum);
}
if (!pEntry->pExtSchemas) return terrno;
pEntry->pExtSchemas[newColNum - 1] = *pExtSchema;
return 0;
}
int32_t dropTableExtSchema(SMetaEntry *pEntry, int32_t dropColId, int32_t newColNum) {
// no ext schema, no need to drop
if (!pEntry->pExtSchemas) return 0;
if (dropColId == newColNum) {
// drop the last column
pEntry->pExtSchemas[dropColId - 1] = (SExtSchema){0};
} else {
// drop a column in the middle
memmove(pEntry->pExtSchemas + dropColId, pEntry->pExtSchemas + dropColId + 1,
(newColNum - dropColId) * sizeof(SExtSchema));
}
return 0;
}
int metaUpdateMetaRsp(tb_uid_t uid, char *tbName, SSchemaWrapper *pSchema, STableMetaRsp *pMetaRsp) { int metaUpdateMetaRsp(tb_uid_t uid, char *tbName, SSchemaWrapper *pSchema, STableMetaRsp *pMetaRsp) {
pMetaRsp->pSchemas = taosMemoryMalloc(pSchema->nCols * sizeof(SSchema)); pMetaRsp->pSchemas = taosMemoryMalloc(pSchema->nCols * sizeof(SSchema));
if (NULL == pMetaRsp->pSchemas) { if (NULL == pMetaRsp->pSchemas) {

View File

@ -21,6 +21,8 @@ extern int32_t metaFetchEntryByUid(SMeta *pMeta, int64_t uid, SMetaEntry **ppEnt
extern int32_t metaFetchEntryByName(SMeta *pMeta, const char *name, SMetaEntry **ppEntry); extern int32_t metaFetchEntryByName(SMeta *pMeta, const char *name, SMetaEntry **ppEntry);
extern void metaFetchEntryFree(SMetaEntry **ppEntry); extern void metaFetchEntryFree(SMetaEntry **ppEntry);
extern int32_t updataTableColCmpr(SColCmprWrapper *pWp, SSchema *pSchema, int8_t add, uint32_t compress); extern int32_t updataTableColCmpr(SColCmprWrapper *pWp, SSchema *pSchema, int8_t add, uint32_t compress);
extern int32_t addTableExtSchema(SMetaEntry* pEntry, const SSchema* pColumn, int32_t newColNum, SExtSchema* pExtSchema);
extern int32_t dropTableExtSchema(SMetaEntry* pEntry, int32_t dropColId, int32_t newColNum);
static int32_t metaCheckCreateSuperTableReq(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) { static int32_t metaCheckCreateSuperTableReq(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
int32_t vgId = TD_VID(pMeta->pVnode); int32_t vgId = TD_VID(pMeta->pVnode);
@ -625,6 +627,7 @@ int32_t metaAddTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, ST
int32_t rowSize = 0; int32_t rowSize = 0;
SSchemaWrapper *pSchema = &pEntry->ntbEntry.schemaRow; SSchemaWrapper *pSchema = &pEntry->ntbEntry.schemaRow;
SSchema *pColumn; SSchema *pColumn;
SExtSchema extSchema = {0};
pEntry->version = version; pEntry->version = version;
for (int32_t i = 0; i < pSchema->nCols; i++) { for (int32_t i = 0; i < pSchema->nCols; i++) {
pColumn = &pSchema->pSchema[i]; pColumn = &pSchema->pSchema[i];
@ -659,6 +662,7 @@ int32_t metaAddTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, ST
pColumn->type = pReq->type; pColumn->type = pReq->type;
pColumn->flags = pReq->flags; pColumn->flags = pReq->flags;
pColumn->colId = pEntry->ntbEntry.ncid++; pColumn->colId = pEntry->ntbEntry.ncid++;
extSchema.typeMod = pReq->typeMod;
tstrncpy(pColumn->name, pReq->colName, TSDB_COL_NAME_LEN); tstrncpy(pColumn->name, pReq->colName, TSDB_COL_NAME_LEN);
uint32_t compress; uint32_t compress;
if (TSDB_ALTER_TABLE_ADD_COLUMN == pReq->action) { if (TSDB_ALTER_TABLE_ADD_COLUMN == pReq->action) {
@ -673,6 +677,14 @@ int32_t metaAddTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, ST
metaFetchEntryFree(&pEntry); metaFetchEntryFree(&pEntry);
TAOS_RETURN(code); TAOS_RETURN(code);
} }
code = addTableExtSchema(pEntry, pColumn, pSchema->nCols, &extSchema);
// TODO wjm update extSchema, client set typeMod in add request.
if (code) {
metaError("vgId:%d, %s failed to add ext schema at %s:%d since %s, version:%" PRId64, TD_VID(pMeta->pVnode),
__func__, __FILE__, __LINE__, tstrerror(code), version);
metaFetchEntryFree(&pEntry);
TAOS_RETURN(code);
}
// do handle entry // do handle entry
code = metaHandleEntry2(pMeta, pEntry); code = metaHandleEntry2(pMeta, pEntry);
@ -783,6 +795,15 @@ int32_t metaDropTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, S
TAOS_RETURN(TSDB_CODE_VND_INVALID_TABLE_ACTION); TAOS_RETURN(TSDB_CODE_VND_INVALID_TABLE_ACTION);
} }
// update column extschema
code = dropTableExtSchema(pEntry, iColumn, pSchema->nCols);
if (code) {
metaError("vgId:%d, %s failed to remove extschema at %s:%d since %s, version:%" PRId64, TD_VID(pMeta->pVnode),
__func__, __FILE__, __LINE__, tstrerror(code), version);
metaFetchEntryFree(&pEntry);
TAOS_RETURN(code);
}
// do handle entry // do handle entry
code = metaHandleEntry2(pMeta, pEntry); code = metaHandleEntry2(pMeta, pEntry);
if (code) { if (code) {

View File

@ -166,7 +166,15 @@ static int32_t setDescResultIntoDataBlock(bool sysInfoUser, SSDataBlock* pBlock,
STR_TO_VARSTR(buf, pMeta->schema[i].name); STR_TO_VARSTR(buf, pMeta->schema[i].name);
COL_DATA_SET_VAL_AND_CHECK(pCol1, pBlock->info.rows, buf, false); COL_DATA_SET_VAL_AND_CHECK(pCol1, pBlock->info.rows, buf, false);
STR_TO_VARSTR(buf, tDataTypes[pMeta->schema[i].type].name); if (IS_DECIMAL_TYPE(pMeta->schema[i].type) && withExtSchema(pMeta->tableType)) {
uint8_t prec = 0, scale = 0;
decimalFromTypeMod(pMeta->schemaExt[i].typeMod, &prec, &scale);
size_t len = snprintf(buf + VARSTR_HEADER_SIZE, DESCRIBE_RESULT_FIELD_LEN - VARSTR_HEADER_SIZE, "%s(%hhu, %hhu)",
tDataTypes[pMeta->schema[i].type].name, prec, scale);
varDataSetLen(buf, len);
} else {
STR_TO_VARSTR(buf, tDataTypes[pMeta->schema[i].type].name);
}
COL_DATA_SET_VAL_AND_CHECK(pCol2, pBlock->info.rows, buf, false); COL_DATA_SET_VAL_AND_CHECK(pCol2, pBlock->info.rows, buf, false);
int32_t bytes = getSchemaBytes(pMeta->schema + i); int32_t bytes = getSchemaBytes(pMeta->schema + i);
COL_DATA_SET_VAL_AND_CHECK(pCol3, pBlock->info.rows, (const char*)&bytes, false); COL_DATA_SET_VAL_AND_CHECK(pCol3, pBlock->info.rows, (const char*)&bytes, false);

View File

@ -609,94 +609,6 @@ TEST(decimal128, divide) {
ASSERT_TRUE(1); ASSERT_TRUE(1);
} }
TEST(decimal, api_taos_fetch_rows) {
const char* host = "127.0.0.1";
const char* user = "root";
const char* passwd = "taosdata";
const char* db = "test_api";
const char* create_tb = "create table if not exists test_api.nt(ts timestamp, c1 decimal(10, 2), c2 decimal(38, 10))";
const char* sql = "select c1, c2 from test_api.nt";
const char* sql_insert = "insert into test_api.nt values(now, 123456.123, 98472981092.1209111)";
TAOS* pTaos = taos_connect(host, user, passwd, NULL, 0);
if (!pTaos) {
cout << "taos connect failed: " << host << " " << taos_errstr(NULL);
FAIL();
}
auto* res = taos_query(pTaos, (std::string("create database if not exists ") + db).c_str());
taos_free_result(res);
res = taos_query(pTaos, create_tb);
taos_free_result(res);
res = taos_query(pTaos, sql_insert);
taos_free_result(res);
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);
taos_free_result(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();
}
if (numOfRows > 0) {
int32_t version = *(int32_t*)pData;
ASSERT_EQ(version, BLOCK_VERSION_1);
int32_t rows = *(int32_t*)((char*)pData + 4 + 4);
int32_t colNum = *(int32_t*)((char*)pData + 4 + 4 + 4);
int32_t bytes_skip = 4 + 4 + 4 + 4 + 4 + 8;
char* p = (char*)pData + bytes_skip;
// col1
int8_t t = *(int8_t*)p;
int32_t type_mod = *(int32_t*)(p + 1);
ASSERT_EQ(t, TSDB_DATA_TYPE_DECIMAL64);
auto check_type_mod = [](char* pStart, uint8_t prec, uint8_t scale, int32_t bytes) {
ASSERT_EQ(*pStart, bytes);
ASSERT_EQ(*(pStart + 2), prec);
ASSERT_EQ(*(pStart + 3), scale);
};
check_type_mod(p + 1, 10, 2, 8);
// col2
p += 5;
t = *(int8_t*)p;
type_mod = *(int32_t*)(p + 1);
check_type_mod(p + 1, 38, 10, 16);
p = p + 5 + BitmapLen(numOfRows) + colNum * 4;
int64_t row1Val = *(int64_t*)p;
ASSERT_EQ(row1Val, 12345612);
}
taos_free_result(res);
taos_close(pTaos);
taos_cleanup();
}
TEST(decimal, conversion) { TEST(decimal, conversion) {
// convert uint8 to decimal // convert uint8 to decimal
char buf[64] = {0}; char buf[64] = {0};
@ -1249,6 +1161,126 @@ TEST(decimal_all, ret_type_for_non_decimal_types) {
} }
} }
class DecimalTest : public ::testing::Test {
TAOS* get_connection() {
auto conn = taos_connect(host, user, passwd, db, 0);
if (!conn) {
cout << "taos connect failed: " << host << " " << taos_errstr(NULL);
}
return conn;
}
TAOS* default_conn_ = NULL;
static constexpr const char* host = "127.0.0.1";
static constexpr const char* user = "root";
static constexpr const char* passwd = "taosdata";
static constexpr const char* db = "test_api";
public:
void SetUp() override {
default_conn_ = get_connection();
if (!default_conn_) {
FAIL();
}
}
void TearDown() override {
if (default_conn_) {
taos_close(default_conn_);
}
}
};
TEST_F(DecimalTest, insert) {
}
TEST_F(DecimalTest, api_taos_fetch_rows) {
const char* host = "127.0.0.1";
const char* user = "root";
const char* passwd = "taosdata";
const char* db = "test_api";
const char* create_tb = "create table if not exists test_api.nt(ts timestamp, c1 decimal(10, 2), c2 decimal(38, 10))";
const char* sql = "select c1, c2 from test_api.nt";
const char* sql_insert = "insert into test_api.nt values(now, 123456.123, 98472981092.1209111)";
TAOS* pTaos = taos_connect(host, user, passwd, NULL, 0);
if (!pTaos) {
cout << "taos connect failed: " << host << " " << taos_errstr(NULL);
FAIL();
}
auto* res = taos_query(pTaos, (std::string("create database if not exists ") + db).c_str());
taos_free_result(res);
res = taos_query(pTaos, create_tb);
taos_free_result(res);
res = taos_query(pTaos, sql_insert);
taos_free_result(res);
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);
taos_free_result(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();
}
if (numOfRows > 0) {
int32_t version = *(int32_t*)pData;
ASSERT_EQ(version, BLOCK_VERSION_1);
int32_t rows = *(int32_t*)((char*)pData + 4 + 4);
int32_t colNum = *(int32_t*)((char*)pData + 4 + 4 + 4);
int32_t bytes_skip = 4 + 4 + 4 + 4 + 4 + 8;
char* p = (char*)pData + bytes_skip;
// col1
int8_t t = *(int8_t*)p;
int32_t type_mod = *(int32_t*)(p + 1);
ASSERT_EQ(t, TSDB_DATA_TYPE_DECIMAL64);
auto check_type_mod = [](char* pStart, uint8_t prec, uint8_t scale, int32_t bytes) {
ASSERT_EQ(*pStart, bytes);
ASSERT_EQ(*(pStart + 2), prec);
ASSERT_EQ(*(pStart + 3), scale);
};
check_type_mod(p + 1, 10, 2, 8);
// col2
p += 5;
t = *(int8_t*)p;
type_mod = *(int32_t*)(p + 1);
check_type_mod(p + 1, 38, 10, 16);
p = p + 5 + BitmapLen(numOfRows) + colNum * 4;
int64_t row1Val = *(int64_t*)p;
ASSERT_EQ(row1Val, 12345612);
}
taos_free_result(res);
taos_close(pTaos);
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();

View File

@ -9460,7 +9460,11 @@ static int32_t checkTableTagsSchema(STranslateContext* pCxt, SHashObj* pHash, SN
} else { } else {
break; break;
} }
// TODO wjm can't create tag with decimal type if (TSDB_CODE_SUCCESS == code) {
if (IS_DECIMAL_TYPE(pTag->dataType.type)) {
code = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, "Decimal type is not allowed for tag");
}
}
} }
if (TSDB_CODE_SUCCESS == code && tagsSize > TSDB_MAX_TAGS_LEN) { if (TSDB_CODE_SUCCESS == code && tagsSize > TSDB_MAX_TAGS_LEN) {
@ -16675,6 +16679,12 @@ static int32_t buildAddColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, S
int8_t code = setColCompressByOption(pReq->type, columnEncodeVal(pStmt->pColOptions->encode), int8_t code = setColCompressByOption(pReq->type, columnEncodeVal(pStmt->pColOptions->encode),
columnCompressVal(pStmt->pColOptions->compress), columnCompressVal(pStmt->pColOptions->compress),
columnLevelVal(pStmt->pColOptions->compressLevel), true, &pReq->compress); columnLevelVal(pStmt->pColOptions->compressLevel), true, &pReq->compress);
if (code != TSDB_CODE_SUCCESS) return code;
}
pReq->typeMod = 0;
if (IS_DECIMAL_TYPE(pStmt->dataType.type)) {
pReq->typeMod = decimalCalcTypeMod(pStmt->dataType.precision, pStmt->dataType.scale);
pReq->flags |= COL_HAS_TYPE_MOD;
} }
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;

View File

@ -2,6 +2,7 @@ from random import randrange
import time import time
import threading import threading
import secrets import secrets
from tag_lite import column
from util.log import * from util.log import *
from util.sql import * from util.sql import *
from util.cases import * from util.cases import *
@ -47,8 +48,13 @@ class DecimalType:
if digits == '': if digits == '':
digits = '0' digits = '0'
return digits return digits
@staticmethod
def default_compression() -> str:
return "zstd"
@staticmethod
def default_encode() -> str:
return "disabled"
class TypeEnum: class TypeEnum:
BOOL = 1 BOOL = 1
TINYINT = 2 TINYINT = 2
@ -244,13 +250,13 @@ class TableInserter:
sql += ", " sql += ", "
local_flush_database = i % 5000 == 0; local_flush_database = i % 5000 == 0;
if len(sql) > 1000: if len(sql) > 1000:
tdLog.debug(f"insert into with sql{sql}") #tdLog.debug(f"insert into with sql{sql}")
if flush_database and local_flush_database: if flush_database and local_flush_database:
self.conn.execute(f"flush database {self.dbName}", queryTimes=1) self.conn.execute(f"flush database {self.dbName}", queryTimes=1)
self.conn.execute(sql, queryTimes=1) self.conn.execute(sql, queryTimes=1)
sql = pre_insert sql = pre_insert
if len(sql) > len(pre_insert): if len(sql) > len(pre_insert):
tdLog.debug(f"insert into with sql{sql}") #tdLog.debug(f"insert into with sql{sql}")
if flush_database: if flush_database:
self.conn.execute(f"flush database {self.dbName}", queryTimes=1) self.conn.execute(f"flush database {self.dbName}", queryTimes=1)
self.conn.execute(sql, queryTimes=1) self.conn.execute(sql, queryTimes=1)
@ -392,11 +398,13 @@ class TDTestCase:
results = tdSql.queryResult results = tdSql.queryResult
for i, column_type in enumerate(column_types): for i, column_type in enumerate(column_types):
if column_type.type == TypeEnum.DECIMAL: if column_type.type == TypeEnum.DECIMAL:
if results[i+1][1] != "DECIMAL": if results[i+1][1] != column_type.__str__():
tdLog.info(str(results)) tdLog.info(str(results))
tdLog.exit(f"check desc failed for table: {tbname} column {results[i+1][0]} type is {results[i+1][1]}, expect DECIMAL") tdLog.exit(f"check desc failed for table: {tbname} column {results[i+1][0]} type is {results[i+1][1]}, expect DECIMAL")
## add decimal type bytes check if results[i+1][4] != DecimalType.default_encode():
## add compression/encode check tdLog.exit(f"check desc failed for table: {tbname} column {results[i+1][0]} encode is {results[i+1][5]}, expect {DecimalType.default_encode()}")
if results[i+1][5] != DecimalType.default_compression():
tdLog.exit(f"check desc failed for table: {tbname} column {results[i+1][0]} compression is {results[i+1][4]}, expect {DecimalType.default_compression()}")
def check_show_create_table(self, tbname: str, column_types: List[DataType], tag_types: List[DataType] = []): def check_show_create_table(self, tbname: str, column_types: List[DataType], tag_types: List[DataType] = []):
sql = f"show create table {self.db_name}.{tbname}" sql = f"show create table {self.db_name}.{tbname}"
@ -445,16 +453,34 @@ class TDTestCase:
DecimalColumnTableCreater(tdSql, self.db_name, self.stable_name, self.columns).create_child_table(self.c_table_prefix, self.c_table_num, self.tags, tag_values) DecimalColumnTableCreater(tdSql, self.db_name, self.stable_name, self.columns).create_child_table(self.c_table_prefix, self.c_table_num, self.tags, tag_values)
self.check_desc("t1", self.columns, self.tags) self.check_desc("t1", self.columns, self.tags)
return
## invalid precision/scale ## invalid precision/scale
invalid_precision_scale = ["decimal(-1, 2)", "decimal(39, 2)", "decimal(10, -1)", "decimal(10, 39)", "decimal(10, 2.5)", "decimal(10.5, 2)", "decimal(10.5, 2.5)", "decimal(0, 2)", "decimal(0)", "decimal", "decimal()"] syntax_error = -2147473920
invalid_column = -2147473918
invalid_precision_scale = [("decimal(-1, 2)", syntax_error), ("decimal(39, 2)", invalid_column), ("decimal(10, -1)", syntax_error),
("decimal(10, 39)", invalid_column), ("decimal(10, 2.5)", syntax_error), ("decimal(10.5, 2)", syntax_error),
("decimal(10.5, 2.5)", syntax_error), ("decimal(0, 2)", invalid_column), ("decimal(0)", invalid_column),
("decimal", syntax_error), ("decimal()", syntax_error)]
for i in invalid_precision_scale: for i in invalid_precision_scale:
sql = f"create table {self.db_name}.invalid_decimal_precision_scale (ts timestamp, c1 {i})" sql = f"create table {self.db_name}.invalid_decimal_precision_scale (ts timestamp, c1 {i[0]})"
tdSql.error(sql, -1) tdSql.error(sql, i[1])
## can't create decimal tag ## can't create decimal tag
sql = 'create stable %s.invalid_decimal_tag (ts timestamp) tags (t1 decimal(10, 2))' % (self.db_name)
tdSql.error(sql, invalid_column)
## alter table add column
sql = f'alter table {self.db_name}.{self.norm_table_name} add column c99 decimal(37, 19)'
self.columns.append(DataType(TypeEnum.DECIMAL, type_mod=DataType.get_decimal_type_mod(DecimalType(37, 19))))
tdSql.execute(sql, queryTimes=1)
self.check_desc(self.norm_table_name, self.columns)
## alter table add column with compression
## Test metaentry compatibility problem for decimal type:w
## How to test it?
## Create table with no decimal type, the metaentries should not have extschma, and add decimal column, the metaentries should have extschema for all columns.
## After drop this decimal column, the metaentries should not have extschema for all columns.
## Test for normal table and super table
## alter table
## drop index from stb ## drop index from stb
### These ops will override the previous stbobjs and meta entries, so test it ### These ops will override the previous stbobjs and meta entries, so test it
@ -466,7 +492,7 @@ class TDTestCase:
pass pass
#TableInserter(tdSql, self.db_name, f"{self.c_table_prefix}{i}", self.columns, self.tags).insert(1, 1537146000000, 500) #TableInserter(tdSql, self.db_name, f"{self.c_table_prefix}{i}", self.columns, self.tags).insert(1, 1537146000000, 500)
TableInserter(tdSql, self.db_name, self.norm_table_name, self.columns).insert(100000, 1537146000000, 500, flush_database=True) TableInserter(tdSql, self.db_name, self.norm_table_name, self.columns).insert(10000, 1537146000000, 500, flush_database=True)
## insert null/None for decimal type ## insert null/None for decimal type
@ -483,7 +509,8 @@ class TDTestCase:
DataType(TypeEnum.VARCHAR, 255), DataType(TypeEnum.VARCHAR, 255),
] ]
DecimalColumnTableCreater(tdSql, self.db_name, "tt", columns, []).create() DecimalColumnTableCreater(tdSql, self.db_name, "tt", columns, []).create()
TableInserter(tdSql, self.db_name, 'tt', columns).insert(100000, 1537146000000, 500, flush_database=True) TableInserter(tdSql, self.db_name, 'tt', columns).insert(10000, 1537146000000, 500, flush_database=True)
## TODO wjm test non support decimal version upgrade to decimal support version, and add decimal column
def test_decimal_ddl(self): def test_decimal_ddl(self):
tdSql.execute("create database test", queryTimes=1) tdSql.execute("create database test", queryTimes=1)
@ -493,7 +520,6 @@ class TDTestCase:
self.test_decimal_ddl() self.test_decimal_ddl()
self.no_decimal_table_test() self.no_decimal_table_test()
self.test_insert_decimal_values() self.test_insert_decimal_values()
time.sleep(9999999)
def stop(self): def stop(self):
tdSql.close() tdSql.close()