未验证 提交 85710a29 编写于 作者: D dapan1121 提交者: GitHub

Merge pull request #19464 from taosdata/fix/TS-2405-2.4

fix: null check for timestamp
......@@ -895,7 +895,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);
}
......
......@@ -74,6 +74,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) {
......@@ -114,7 +117,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) {
......@@ -378,9 +381,9 @@ 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;
}
......@@ -396,6 +399,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;
......
......@@ -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;
}
......
......@@ -618,6 +618,7 @@
5,,system-test,python3 ./test.py -f 2-query/TD-11945_crash.py
5,,system-test,python3 ./test.py -f 2-query/TD-11256.py
5,,system-test,python3 test.py -f 1-insert/TD-11970.py
5,,system-test,python3 test.py -f 1-insert/stmt_error.py
5,,pytest,python3 test.py -f user/user_create.py
5,,pytest,python3 test.py -f tools/taosdemoTestWithJson.py
5,,pytest,python3 test.py -f tools/taosdemoTestSampleData.py
......
......@@ -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
......
# encoding:UTF-8
from taos import *
from ctypes import *
from datetime import datetime
import taos
import taos
import time
from util.log import *
from util.cases import *
from util.sql import *
from util.dnodes import *
class TDTestCase:
def __init__(self):
self.err_case = 0
self.curret_case = 0
def caseDescription(self):
'''
case1 <wenzhouwww>: [TD-11899] : this is an test case for check stmt error use .
'''
return
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
def conn(self):
# type: () -> taos.TaosConnection
return connect()
def test_stmt_insert(self,conn):
# type: (TaosConnection) -> None
dbname = "pytest_taos_stmt"
try:
conn.execute("drop database if exists %s" % dbname)
conn.execute("create database if not exists %s" % dbname)
conn.select_db(dbname)
conn.execute(
"create table if not exists log(ts timestamp, bo bool, nil tinyint, ti tinyint, si smallint, ii int,\
bi bigint, tu tinyint unsigned, su smallint unsigned, iu int unsigned, bu bigint unsigned, \
ff float, dd double, bb binary(100), nn nchar(100), tt timestamp)",
)
conn.load_table_info("log")
stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
params = new_bind_params(16)
params[0].timestamp(1626861392589, PrecisionEnum.Milliseconds)
params[1].bool(True)
params[2].tinyint(None)
params[3].tinyint(2)
params[4].smallint(3)
params[5].int(4)
params[6].bigint(5)
params[7].tinyint_unsigned(6)
params[8].smallint_unsigned(7)
params[9].int_unsigned(8)
params[10].bigint_unsigned(9)
params[11].float(10.1)
params[12].double(10.11)
params[13].binary("hello")
params[14].nchar("stmt")
params[15].timestamp(1626861392589, PrecisionEnum.Milliseconds)
stmt.bind_param(params)
stmt.execute()
result = stmt.use_result()
assert result.affected_rows == 1
result.close()
stmt.close()
stmt = conn.statement("select * from log")
stmt.execute()
result = stmt.use_result()
row = result.next()
print(row)
assert row[2] == None
for i in range(3, 11):
assert row[i] == i - 1
#float == may not work as expected
# assert row[10] == c_float(10.1)
assert row[12] == 10.11
assert row[13] == "hello"
assert row[14] == "stmt"
conn.execute("drop database if exists %s" % dbname)
conn.close()
except Exception as err:
conn.execute("drop database if exists %s" % dbname)
conn.close()
raise err
def test_stmt_insert_error(self,conn):
# type: (TaosConnection) -> None
dbname = "pytest_taos_stmt_error"
try:
conn.execute("drop database if exists %s" % dbname)
conn.execute("create database if not exists %s" % dbname)
conn.select_db(dbname)
conn.execute(
"create table if not exists log(ts timestamp, bo bool, nil tinyint, ti tinyint, si smallint, ii int,\
bi bigint, tu tinyint unsigned, su smallint unsigned, iu int unsigned, bu bigint unsigned, \
ff float, dd double, bb binary(100), nn nchar(100), tt timestamp , error_data int )",
)
conn.load_table_info("log")
stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1000)")
params = new_bind_params(16)
params[0].timestamp(1626861392589, PrecisionEnum.Milliseconds)
params[1].bool(True)
params[2].tinyint(None)
params[3].tinyint(2)
params[4].smallint(3)
params[5].int(4)
params[6].bigint(5)
params[7].tinyint_unsigned(6)
params[8].smallint_unsigned(7)
params[9].int_unsigned(8)
params[10].bigint_unsigned(9)
params[11].float(10.1)
params[12].double(10.11)
params[13].binary("hello")
params[14].nchar("stmt")
params[15].timestamp(1626861392589, PrecisionEnum.Milliseconds)
stmt.bind_param(params)
stmt.execute()
result = stmt.use_result()
assert result.affected_rows == 1
result.close()
stmt.close()
stmt = conn.statement("select * from log")
stmt.execute()
result = stmt.use_result()
row = result.next()
print(row)
assert row[2] == None
for i in range(3, 11):
assert row[i] == i - 1
#float == may not work as expected
# assert row[10] == c_float(10.1)
assert row[12] == 10.11
assert row[13] == "hello"
assert row[14] == "stmt"
conn.execute("drop database if exists %s" % dbname)
conn.close()
except Exception as err:
conn.execute("drop database if exists %s" % dbname)
conn.close()
raise err
def run(self):
self.test_stmt_insert(self.conn())
try:
self.test_stmt_insert_error(self.conn())
except Exception as error :
if str(error)=='[0x0200]: invalid operation: only ? allowed in values':
tdLog.info('=========stmt error occured for bind part colum ==============')
else:
tdLog.exit("expect error not occured")
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())
python3 test.py -f 1-insert/TD-11970.py
\ No newline at end of file
python3 test.py -f 1-insert/TD-11970.py
python3 test.py -f 1-insert/stmt_error.py
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册