From e491a8908c4d7ed99076eea5f67d7f257427e4d0 Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Tue, 20 Oct 2020 15:00:12 +0800 Subject: [PATCH 1/2] fix TD-1471 --- src/client/src/tscSql.c | 7 +- .../python/linux/python2/taos/cursor.py | 6 +- .../python/linux/python3/taos/cursor.py | 6 +- .../python/windows/python2/taos/cursor.py | 3 + .../python/windows/python3/taos/cursor.py | 3 + tests/pytest/fulltest.sh | 1 + tests/pytest/query/bug1471.py | 73 +++++++++++++++++++ 7 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 tests/pytest/query/bug1471.py diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index be91255b9c..02a2c1e052 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -479,8 +479,11 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) { SSqlCmd *pCmd = &pSql->cmd; SSqlRes *pRes = &pSql->res; - if (pRes->qhandle == 0 || - pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED || + if (pRes->qhandle == 0) { + pRes->code = TSDB_CODE_TSC_INVALID_QHANDLE; + return NULL; + } + if (pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED || pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pCmd->command == TSDB_SQL_INSERT) { return NULL; diff --git a/src/connector/python/linux/python2/taos/cursor.py b/src/connector/python/linux/python2/taos/cursor.py index 8c268d8afb..37c02d330e 100644 --- a/src/connector/python/linux/python2/taos/cursor.py +++ b/src/connector/python/linux/python2/taos/cursor.py @@ -192,8 +192,10 @@ class TDengineCursor(object): buffer = [[] for i in range(len(self._fields))] self._rowcount = 0 while True: - block, num_of_fields = CTaosInterface.fetchBlock( - self._result, self._fields) + block, num_of_fields = CTaosInterface.fetchBlock(self._result, self._fields) + errno = CTaosInterface.libtaos.taos_errno(self._result) + if errno != 0: + raise ProgrammingError(CTaosInterface.errStr(self._result), errno) if num_of_fields == 0: break self._rowcount += num_of_fields diff --git a/src/connector/python/linux/python3/taos/cursor.py b/src/connector/python/linux/python3/taos/cursor.py index 3f0f315d33..ec7a85ee1a 100644 --- a/src/connector/python/linux/python3/taos/cursor.py +++ b/src/connector/python/linux/python3/taos/cursor.py @@ -207,8 +207,10 @@ class TDengineCursor(object): buffer = [[] for i in range(len(self._fields))] self._rowcount = 0 while True: - block, num_of_fields = CTaosInterface.fetchBlock( - self._result, self._fields) + block, num_of_fields = CTaosInterface.fetchBlock(self._result, self._fields) + errno = CTaosInterface.libtaos.taos_errno(self._result) + if errno != 0: + raise ProgrammingError(CTaosInterface.errStr(self._result), errno) if num_of_fields == 0: break self._rowcount += num_of_fields diff --git a/src/connector/python/windows/python2/taos/cursor.py b/src/connector/python/windows/python2/taos/cursor.py index 7eee3bfc8f..8714fe77cb 100644 --- a/src/connector/python/windows/python2/taos/cursor.py +++ b/src/connector/python/windows/python2/taos/cursor.py @@ -142,6 +142,9 @@ class TDengineCursor(object): self._rowcount = 0 while True: block, num_of_fields = CTaosInterface.fetchBlock(self._result, self._fields) + errno = CTaosInterface.libtaos.taos_errno(self._result) + if errno != 0: + raise ProgrammingError(CTaosInterface.errStr(self._result), errno) if num_of_fields == 0: break self._rowcount += num_of_fields for i in range(len(self._fields)): diff --git a/src/connector/python/windows/python3/taos/cursor.py b/src/connector/python/windows/python3/taos/cursor.py index 5f5aa4e1d7..c2c442b06e 100644 --- a/src/connector/python/windows/python3/taos/cursor.py +++ b/src/connector/python/windows/python3/taos/cursor.py @@ -142,6 +142,9 @@ class TDengineCursor(object): self._rowcount = 0 while True: block, num_of_fields = CTaosInterface.fetchBlock(self._result, self._fields) + errno = CTaosInterface.libtaos.taos_errno(self._result) + if errno != 0: + raise ProgrammingError(CTaosInterface.errStr(self._result), errno) if num_of_fields == 0: break self._rowcount += num_of_fields for i in range(len(self._fields)): diff --git a/tests/pytest/fulltest.sh b/tests/pytest/fulltest.sh index fd973b8b76..4b27c42d38 100755 --- a/tests/pytest/fulltest.sh +++ b/tests/pytest/fulltest.sh @@ -149,6 +149,7 @@ python3 ./test.py -f query/queryNullValueTest.py python3 ./test.py -f query/queryInsertValue.py python3 ./test.py -f query/queryConnection.py python3 ./test.py -f query/natualInterval.py +python3 ./test.py -f query/bug1471.py #stream python3 ./test.py -f stream/metric_1.py diff --git a/tests/pytest/query/bug1471.py b/tests/pytest/query/bug1471.py new file mode 100644 index 0000000000..f1cb0bdcdf --- /dev/null +++ b/tests/pytest/query/bug1471.py @@ -0,0 +1,73 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import taos +from util.log import * +from util.cases import * +from util.sql import * +import time +import threading + + +class myThread(threading.Thread): + def __init__(self, conn): + threading.Thread.__init__(self) + self.event = threading.Event() + self.conn = taos.connect(conn._host, port=conn._port, config=conn._config) + + def run(self): + cur = self.conn.cursor() + self.event.wait() + cur.execute("drop database db") + cur.close() + self.conn.close() + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + + def run(self): + for i in range(50): + print("round", i) + thread = myThread(tdSql.cursor._connection) + thread.start() + + tdSql.execute('reset query cache') + tdSql.execute('drop database if exists db') + tdSql.execute('create database db') + tdSql.execute('use db') + tdSql.execute("create table car (ts timestamp, s int)") + tdSql.execute("insert into car values('2020-10-19 17:00:00', 123)") + + thread.event.set() + try: + tdSql.query("select s from car where ts = '2020-10-19 17:00:00'") + except Exception as e: + pass + else: + tdSql.checkData(0, 0, 123) + + thread.join() + time.sleep(0.2) + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) From 820bf89a2e9eaf2f5cdc088fe3a9c683b322d071 Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Wed, 21 Oct 2020 10:42:09 +0800 Subject: [PATCH 2/2] TD-1471: use new error code when qhandle is null --- src/client/src/tscSql.c | 7 ++----- src/query/src/qExecutor.c | 3 +++ src/vnode/src/vnodeRead.c | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index 02a2c1e052..be91255b9c 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -479,11 +479,8 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) { SSqlCmd *pCmd = &pSql->cmd; SSqlRes *pRes = &pSql->res; - if (pRes->qhandle == 0) { - pRes->code = TSDB_CODE_TSC_INVALID_QHANDLE; - return NULL; - } - if (pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED || + if (pRes->qhandle == 0 || + pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED || pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pCmd->command == TSDB_SQL_INSERT) { return NULL; diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index f742616b05..869e2dd7ed 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -7101,6 +7101,7 @@ void qCleanupQueryMgmt(void* pQMgmt) { void** qRegisterQInfo(void* pMgmt, uint64_t qInfo) { if (pMgmt == NULL) { + terrno = TSDB_CODE_VND_INVALID_VGROUP_ID; return NULL; } @@ -7109,6 +7110,7 @@ void** qRegisterQInfo(void* pMgmt, uint64_t qInfo) { SQueryMgmt *pQueryMgmt = pMgmt; if (pQueryMgmt->qinfoPool == NULL) { qError("QInfo:%p failed to add qhandle into qMgmt, since qMgmt is closed", (void *)qInfo); + terrno = TSDB_CODE_VND_INVALID_VGROUP_ID; return NULL; } @@ -7116,6 +7118,7 @@ void** qRegisterQInfo(void* pMgmt, uint64_t qInfo) { if (pQueryMgmt->closed) { // pthread_mutex_unlock(&pQueryMgmt->lock); qError("QInfo:%p failed to add qhandle into cache, since qMgmt is colsing", (void *)qInfo); + terrno = TSDB_CODE_VND_INVALID_VGROUP_ID; return NULL; } else { TSDB_CACHE_PTR_TYPE handleVal = (TSDB_CACHE_PTR_TYPE) qInfo; diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index baaeae2a81..969a29359f 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -166,10 +166,12 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (code == TSDB_CODE_SUCCESS) { handle = qRegisterQInfo(pVnode->qMgmt, (uint64_t)pQInfo); if (handle == NULL) { // failed to register qhandle, todo add error test case + pRsp->code = terrno; + terrno = 0; vError("vgId:%d QInfo:%p register qhandle failed, return to app, code:%s", pVnode->vgId, (void *)pQInfo, tstrerror(pRsp->code)); - pRsp->code = TSDB_CODE_QRY_INVALID_QHANDLE; qDestroyQueryInfo(pQInfo); // destroy it directly + return pRsp->code; } else { assert(*handle == pQInfo); pRsp->qhandle = htobe64((uint64_t)pQInfo);