diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index 3598d8f81fa2269d916f1953258cbe9373713165..c4d095dc67d1e01cebb56bbe38f3ff3f7a979221 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -907,7 +907,7 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok } else { int64_t tmpVal; if (tsParseTime(pToken, &tmpVal, str, msg, timePrec) != TSDB_CODE_SUCCESS) { - return tscInvalidOperationMsg(msg, "invalid timestamp", pToken->z); + return TSDB_CODE_TSC_INVALID_OPERATION; } tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset); } diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c index 750d670d1be0f00d011f05e8ff960ef875d85519..6bf0b07328622e621287ad2a426aa53a2a1fb3fd 100644 --- a/src/client/src/tscParseInsert.c +++ b/src/client/src/tscParseInsert.c @@ -78,6 +78,9 @@ int tsParseTime(SStrToken *pToken, int64_t *pTime, char **next, char *err, int16 // do nothing } else if (pToken->type == TK_INTEGER) { useconds = taosStr2int64(pToken->z); + if (errno == ERANGE) { + return tscInvalidOperationMsg(err, "timestamp is out of range", pToken->z); + } } else { // strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm); if (taosParseTime(pToken->z, pTime, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) { @@ -118,7 +121,7 @@ int tsParseTime(SStrToken *pToken, int64_t *pTime, char **next, char *err, int16 char unit = 0; if (parseAbsoluteDuration(valueToken.z, valueToken.n, &interval, &unit, timePrec) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; + return tscInvalidOperationMsg(err, "invalid timestamp", pToken->z); } if (sToken.type == TK_PLUS) { @@ -382,7 +385,7 @@ int32_t tsParseOneColumn(SSchema *pSchema, SStrToken *pToken, char *payload, cha } else { int64_t temp; if (tsParseTime(pToken, &temp, str, msg, timePrec) != TSDB_CODE_SUCCESS) { - return tscInvalidOperationMsg(msg, "invalid timestamp", pToken->z); + return TSDB_CODE_TSC_INVALID_OPERATION; } *((int64_t *)payload) = temp; @@ -400,6 +403,9 @@ int32_t tsParseOneColumn(SSchema *pSchema, SStrToken *pToken, char *payload, cha * Do not employ sort operation is not involved if server time is used. */ int32_t tsCheckTimestamp(STableDataBlocks *pDataBlocks, const char *start) { + if (isNull(start, TSDB_DATA_TYPE_TIMESTAMP)) { + return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; + } // once the data block is disordered, we do NOT keep previous timestamp any more if (!pDataBlocks->ordered) { return TSDB_CODE_SUCCESS; diff --git a/src/client/src/tscPrepare.c b/src/client/src/tscPrepare.c index c2de205767fb7b42d437fab7d2d940f676a1ffd9..c86a920029ab4fdd763ddc1e9bb366298b80dedc 100644 --- a/src/client/src/tscPrepare.c +++ b/src/client/src/tscPrepare.c @@ -905,6 +905,12 @@ static int doBindBatchParam(STableDataBlocks* pBlock, SParamInfo* param, TAOS_MU if (pBind->is_null != NULL && pBind->is_null[i]) { setNull(data + param->offset, param->type, param->bytes); + if (param->offset == 0) { + if (tsCheckTimestamp(pBlock, data) != TSDB_CODE_SUCCESS) { + tscError("invalid timestamp"); + return TSDB_CODE_TSC_INVALID_VALUE; + } + } continue; } diff --git a/tests/script/general/insert/basic.sim b/tests/script/general/insert/basic.sim index 88eb30a1ad819a26cdc9d61cb692fde9f1446cd7..e14de01df39c0934d123ce4b1256d7d2877996dd 100644 --- a/tests/script/general/insert/basic.sim +++ b/tests/script/general/insert/basic.sim @@ -39,6 +39,9 @@ while $x < 5 $x = $x + 1 endw +print =============== step 3 (TS-2405 NULL timestamp) +sql_error insert into $tb values (9223372036854775808 , 100) + sql select * from $tb print $rows points data are retrieved diff --git a/tests/system-test/1-insert/stmt_error.py b/tests/system-test/1-insert/stmt_error.py index cefc99f2295f2faf94766db9e345582b7ac1f555..9a269d8023cb458385a52509317bde28da8c7e1c 100644 --- a/tests/system-test/1-insert/stmt_error.py +++ b/tests/system-test/1-insert/stmt_error.py @@ -164,6 +164,48 @@ class TDTestCase: conn.execute("drop database if exists %s" % dbname) conn.close() raise err + + def test_stmt_insert_error_null_timestamp(self,conn): + + dbname = "pytest_taos_stmt_error_null_ts" + try: + conn.execute("drop database if exists %s" % dbname) + conn.execute("create database if not exists %s" % dbname) + conn.execute("alter database %s keep 36500" % dbname) + conn.select_db(dbname) + + conn.execute("create stable STB(ts timestamp, n int) tags(b int)") + + stmt = conn.statement("insert into ? using STB tags(?) values(?, ?)") + params = new_bind_params(1) + params[0].int(4); + stmt.set_tbname_tags("ct", params); + + multi_params = new_multi_binds(2); + multi_params[0].timestamp([9223372036854775808]) + multi_params[1].int([123]) + stmt.bind_param_batch(multi_params) + + stmt.execute() + result = stmt.use_result() + + result.close() + stmt.close() + + stmt = conn.statement("select * from STB") + stmt.execute() + result = stmt.use_result() + print(result.affected_rows) + row = result.next() + print(row) + + result.close() + stmt.close() + conn.close() + + except Exception as err: + conn.close() + raise err def run(self): @@ -173,9 +215,18 @@ class TDTestCase: except Exception as error : if str(error)=='[0x0200]: invalid operation: only ? allowed in values': - tdLog.info('=========stmt error occured for bind part colum ==============') + tdLog.info('=========stmt error occured for bind part column ==============') else: tdLog.exit("expect error not occured") + + try: + self.test_stmt_insert_error_null_timestamp(self.conn()) + tdLog.exit("expect error not occured - 1") + except Exception as error : + if str(error)=='[0x0200]: invalid operation: bind column type mismatch or invalid': + tdLog.info('=========stmt error occured for bind part column(NULL Timestamp) ==============') + else: + tdLog.exit("expect error not occured - 2") def stop(self): tdSql.close()