提交 fa83c300 编写于 作者: W wenzhouwww

Merge branch 'develop' into test/case_runCI_query

...@@ -1350,18 +1350,18 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ...@@ -1350,18 +1350,18 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
```mysql ```mysql
SELECT LAST_ROW(field_name) FROM { tb_name | stb_name }; SELECT LAST_ROW(field_name) FROM { tb_name | stb_name };
``` ```
功能说明:返回表/超级表的最后一条记录。 功能说明:返回表/超级表的最后一条记录。
返回结果数据类型:同应用的字段。 返回结果数据类型:同应用的字段。
应用字段:所有字段。 应用字段:所有字段。
适用于:**表、超级表**。 适用于:**表、超级表**。
限制:LAST_ROW() 不能与 INTERVAL 一起使用。 限制:LAST_ROW() 不能与 INTERVAL 一起使用。
说明:在用于超级表时,时间戳完全一样且同为最大的数据行可能有多个,那么会从中随机返回一条,而并不保证多次运行所挑选的数据行必然一致。<br/> 说明:在用于超级表时,时间戳完全一样且同为最大的数据行可能有多个,那么会从中随机返回一条,而并不保证多次运行所挑选的数据行必然一致。<br/>
<br/>示例: <br/>示例:
```mysql ```mysql
taos> SELECT LAST_ROW(current) FROM meters; taos> SELECT LAST_ROW(current) FROM meters;
...@@ -1383,51 +1383,51 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ...@@ -1383,51 +1383,51 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
SELECT INTERP(field_name) FROM { tb_name | stb_name } [WHERE where_condition] [ RANGE(timestamp1,timestamp2) ] [EVERY(interval)] [FILL ({ VALUE | PREV | NULL | LINEAR | NEXT})]; SELECT INTERP(field_name) FROM { tb_name | stb_name } [WHERE where_condition] [ RANGE(timestamp1,timestamp2) ] [EVERY(interval)] [FILL ({ VALUE | PREV | NULL | LINEAR | NEXT})];
``` ```
功能说明:返回表/超级表的指定时间截面指定列的记录值(插值)。 功能说明:返回表/超级表的指定时间截面指定列的记录值(插值)。
返回结果数据类型:同字段类型。 返回结果数据类型:同字段类型。
应用字段:数值型字段。 应用字段:数值型字段。
适用于:**表、超级表、嵌套查询**。 适用于:**表、超级表、嵌套查询**。
说明: 说明:
1)INTERP用于在指定时间断面获取指定列的记录值,如果该时间断面不存在符合条件的行数据,那么会根据 FILL 参数的设定进行插值。 1)INTERP用于在指定时间断面获取指定列的记录值,如果该时间断面不存在符合条件的行数据,那么会根据 FILL 参数的设定进行插值。
2)INTERP的输入数据为指定列的数据,可以通过条件语句(where子句)来对原始列数据进行过滤,如果没有指定过滤条件则输入为全部数据。 2)INTERP的输入数据为指定列的数据,可以通过条件语句(where子句)来对原始列数据进行过滤,如果没有指定过滤条件则输入为全部数据。
3)INTERP的输出时间范围根据RANGE(timestamp1,timestamp2)字段来指定,需满足timestamp1<=timestamp2。其中timestamp1(必选值)为输出时间范围的起始值,即如果timestamp1时刻符合插值条件则timestamp1为输出的第一条记录,timestamp2(必选值)为输出时间范围的结束值,即输出的最后一条记录的timestamp不能大于timestamp2。如果没有指定RANGE,那么满足过滤条件的输入数据中第一条记录的timestamp即为timestamp1,最后一条记录的timestamp即为timestamp2,同样也满足timestamp1 <= timestamp2。 3)INTERP的输出时间范围根据RANGE(timestamp1,timestamp2)字段来指定,需满足timestamp1<=timestamp2。其中timestamp1(必选值)为输出时间范围的起始值,即如果timestamp1时刻符合插值条件则timestamp1为输出的第一条记录,timestamp2(必选值)为输出时间范围的结束值,即输出的最后一条记录的timestamp不能大于timestamp2。如果没有指定RANGE,那么满足过滤条件的输入数据中第一条记录的timestamp即为timestamp1,最后一条记录的timestamp即为timestamp2,同样也满足timestamp1 <= timestamp2。
4)INTERP根据EVERY字段来确定输出时间范围内的结果条数,即从timestamp1开始每隔固定长度的时间(EVERY值)进行插值。如果没有指定EVERY,则默认窗口大小为无穷大,即从timestamp1开始只有一个窗口。 4)INTERP根据EVERY字段来确定输出时间范围内的结果条数,即从timestamp1开始每隔固定长度的时间(EVERY值)进行插值。如果没有指定EVERY,则默认窗口大小为无穷大,即从timestamp1开始只有一个窗口。
5)INTERP根据FILL字段来决定在每个符合输出条件的时刻如何进行插值,如果没有FILL字段则默认不插值,即输出为原始记录值或不输出(原始记录不存在)。 5)INTERP根据FILL字段来决定在每个符合输出条件的时刻如何进行插值,如果没有FILL字段则默认不插值,即输出为原始记录值或不输出(原始记录不存在)。
6)INTERP只能在一个时间序列内进行插值,因此当作用于超级表时必须跟group by tbname一起使用,当作用嵌套查询外层时内层子查询不能含GROUP BY信息。 6)INTERP只能在一个时间序列内进行插值,因此当作用于超级表时必须跟group by tbname一起使用,当作用嵌套查询外层时内层子查询不能含GROUP BY信息。
7)INTERP的插值结果不受ORDER BY timestamp的影响,ORDER BY timestamp只影响输出结果的排序。 7)INTERP的插值结果不受ORDER BY timestamp的影响,ORDER BY timestamp只影响输出结果的排序。
SQL示例: SQL示例:
1) 单点线性插值 1) 单点线性插值
```mysql ```mysql
taos> SELECT INTERP(*) FROM t1 RANGE('2017-7-14 18:40:00','2017-7-14 18:40:00') FILL(LINEAR); taos> SELECT INTERP(*) FROM t1 RANGE('2017-7-14 18:40:00','2017-7-14 18:40:00') FILL(LINEAR);
``` ```
2) 在2017-07-14 18:00:00到2017-07-14 19:00:00间每隔5秒钟进行取值(不插值) 2) 在2017-07-14 18:00:00到2017-07-14 19:00:00间每隔5秒钟进行取值(不插值)
```mysql ```mysql
taos> SELECT INTERP(*) FROM t1 RANGE('2017-7-14 18:00:00','2017-7-14 19:00:00') EVERY(5s); taos> SELECT INTERP(*) FROM t1 RANGE('2017-7-14 18:00:00','2017-7-14 19:00:00') EVERY(5s);
``` ```
3) 在2017-07-14 18:00:00到2017-07-14 19:00:00间每隔5秒钟进行线性插值 3) 在2017-07-14 18:00:00到2017-07-14 19:00:00间每隔5秒钟进行线性插值
```mysql ```mysql
taos> SELECT INTERP(*) FROM t1 RANGE('2017-7-14 18:00:00','2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR); taos> SELECT INTERP(*) FROM t1 RANGE('2017-7-14 18:00:00','2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR);
``` ```
4.在所有时间范围内每隔5秒钟进行向后插值 4.在所有时间范围内每隔5秒钟进行向后插值
```mysql ```mysql
taos> SELECT INTERP(*) FROM t1 EVERY(5s) FILL(NEXT); taos> SELECT INTERP(*) FROM t1 EVERY(5s) FILL(NEXT);
``` ```
5.根据2017-07-14 17:00:00到2017-07-14 20:00:00间的数据进行从2017-07-14 18:00:00到2017-07-14 19:00:00间每隔5秒钟进行线性插值 5.根据2017-07-14 17:00:00到2017-07-14 20:00:00间的数据进行从2017-07-14 18:00:00到2017-07-14 19:00:00间每隔5秒钟进行线性插值
```mysql ```mysql
taos> SELECT INTERP(*) FROM t1 where ts >= '2017-07-14 17:00:00' and ts <= '2017-07-14 20:00:00' RANGE('2017-7-14 18:00:00','2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR); taos> SELECT INTERP(*) FROM t1 where ts >= '2017-07-14 17:00:00' and ts <= '2017-07-14 20:00:00' RANGE('2017-7-14 18:00:00','2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR);
``` ```
- **INTERP [2.3.1之前的版本]** - **INTERP [2.3.1之前的版本]**
...@@ -1436,15 +1436,15 @@ SQL示例: ...@@ -1436,15 +1436,15 @@ SQL示例:
SELECT INTERP(field_name) FROM { tb_name | stb_name } WHERE ts='timestamp' [FILL ({ VALUE | PREV | NULL | LINEAR | NEXT})]; SELECT INTERP(field_name) FROM { tb_name | stb_name } WHERE ts='timestamp' [FILL ({ VALUE | PREV | NULL | LINEAR | NEXT})];
``` ```
功能说明:返回表/超级表的指定时间截面、指定字段的记录。 功能说明:返回表/超级表的指定时间截面、指定字段的记录。
返回结果数据类型:同字段类型。 返回结果数据类型:同字段类型。
应用字段:数值型字段。 应用字段:数值型字段。
适用于:**表、超级表**。 适用于:**表、超级表**。
说明:(从 2.0.15.0 版本开始新增此函数) <br/>1)INTERP 必须指定时间断面,如果该时间断面不存在直接对应的数据,那么会根据 FILL 参数的设定进行插值。此外,条件语句里面可附带筛选条件,例如标签、tbname。<br/>2)INTERP 查询要求查询的时间区间必须位于数据集合(表)的所有记录的时间范围之内。如果给定的时间戳位于时间范围之外,即使有插值指令,仍然不返回结果。<br/>3)单个 INTERP 函数查询只能够针对一个时间点进行查询,如果需要返回等时间间隔的断面数据,可以通过 INTERP 配合 EVERY 的方式来进行查询处理(而不是使用 INTERVAL),其含义是每隔固定长度的时间进行插值。<br/> 说明:(从 2.0.15.0 版本开始新增此函数) <br/>1)INTERP 必须指定时间断面,如果该时间断面不存在直接对应的数据,那么会根据 FILL 参数的设定进行插值。此外,条件语句里面可附带筛选条件,例如标签、tbname。<br/>2)INTERP 查询要求查询的时间区间必须位于数据集合(表)的所有记录的时间范围之内。如果给定的时间戳位于时间范围之外,即使有插值指令,仍然不返回结果。<br/>3)单个 INTERP 函数查询只能够针对一个时间点进行查询,如果需要返回等时间间隔的断面数据,可以通过 INTERP 配合 EVERY 的方式来进行查询处理(而不是使用 INTERVAL),其含义是每隔固定长度的时间进行插值。<br/>
示例: 示例:
```mysql ```mysql
...@@ -1455,7 +1455,7 @@ SQL示例: ...@@ -1455,7 +1455,7 @@ SQL示例:
Query OK, 1 row(s) in set (0.002652s) Query OK, 1 row(s) in set (0.002652s)
``` ```
如果给定的时间戳无对应的数据,在不指定插值生成策略的情况下,不会返回结果,如果指定了插值策略,会根据插值策略返回结果。 如果给定的时间戳无对应的数据,在不指定插值生成策略的情况下,不会返回结果,如果指定了插值策略,会根据插值策略返回结果。
```mysql ```mysql
taos> SELECT INTERP(*) FROM meters WHERE tbname IN ('d636') AND ts='2017-7-14 18:40:00.005'; taos> SELECT INTERP(*) FROM meters WHERE tbname IN ('d636') AND ts='2017-7-14 18:40:00.005';
...@@ -1468,7 +1468,7 @@ SQL示例: ...@@ -1468,7 +1468,7 @@ SQL示例:
Query OK, 1 row(s) in set (0.003056s) Query OK, 1 row(s) in set (0.003056s)
``` ```
如下所示代码表示在时间区间 `['2017-7-14 18:40:00', '2017-7-14 18:40:00.014']` 中每隔 5 毫秒 进行一次断面计算。 如下所示代码表示在时间区间 `['2017-7-14 18:40:00', '2017-7-14 18:40:00.014']` 中每隔 5 毫秒 进行一次断面计算。
```mysql ```mysql
taos> SELECT INTERP(current) FROM d636 WHERE ts>='2017-7-14 18:40:00' AND ts<='2017-7-14 18:40:00.014' EVERY(5a); taos> SELECT INTERP(current) FROM d636 WHERE ts>='2017-7-14 18:40:00' AND ts<='2017-7-14 18:40:00.014' EVERY(5a);
...@@ -1577,8 +1577,6 @@ SQL示例: ...@@ -1577,8 +1577,6 @@ SQL示例:
支持 +、-、*、/ 运算,如 ceil(col1) + ceil(col2)。 支持 +、-、*、/ 运算,如 ceil(col1) + ceil(col2)。
只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。
该函数可以应用在普通表和超级表上。 该函数可以应用在普通表和超级表上。
支持版本:指定计算算法的功能从 2.2.0.x 版本开始,2.2.0.0 之前的版本不支持指定使用算法的功能。
- **FLOOR** - **FLOOR**
```mysql ```mysql
......
...@@ -170,6 +170,16 @@ void tscAddIntoStreamList(SSqlStream *pStream) { ...@@ -170,6 +170,16 @@ void tscAddIntoStreamList(SSqlStream *pStream) {
STscObj * pObj = pStream->pSql->pTscObj; STscObj * pObj = pStream->pSql->pTscObj;
pthread_mutex_lock(&pObj->mutex); pthread_mutex_lock(&pObj->mutex);
//check if newly added stream node is present
//in the streamList to prevent loop in the list
SSqlStream *iter = pObj->streamList;
while (iter) {
if (pStream == iter) {
pthread_mutex_unlock(&pObj->mutex);
return;
}
iter = iter->next;
}
pStream->next = pObj->streamList; pStream->next = pObj->streamList;
if (pObj->streamList) pObj->streamList->prev = pStream; if (pObj->streamList) pObj->streamList->prev = pStream;
......
...@@ -1479,6 +1479,18 @@ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQue ...@@ -1479,6 +1479,18 @@ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQue
break; break;
} }
} }
// set input data order to param[1]
if(pex->base.functionId == TSDB_FUNC_FIRST || pex->base.functionId == TSDB_FUNC_FIRST_DST ||
pex->base.functionId == TSDB_FUNC_LAST || pex->base.functionId == TSDB_FUNC_LAST_DST) {
// set input order
SQueryInfo* pInputQI = pSqlObjList[0]->cmd.pQueryInfo;
if(pInputQI) {
pex->base.numOfParams = 3;
pex->base.param[2].nType = TSDB_DATA_TYPE_INT;
pex->base.param[2].i64 = pInputQI->order.order;
}
}
} }
tscDebug("0x%"PRIx64" create QInfo 0x%"PRIx64" to execute the main query while all nest queries are ready", pSql->self, pSql->self); tscDebug("0x%"PRIx64" create QInfo 0x%"PRIx64" to execute the main query while all nest queries are ready", pSql->self, pSql->self);
...@@ -4303,6 +4315,11 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) { ...@@ -4303,6 +4315,11 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) {
// create sub query to handle the sub query. // create sub query to handle the sub query.
SQueryInfo* pq = tscGetQueryInfo(&psub->cmd); SQueryInfo* pq = tscGetQueryInfo(&psub->cmd);
STableMetaInfo* pSubMeta = tscGetMetaInfo(pq, 0);
if (UTIL_TABLE_IS_SUPER_TABLE(pSubMeta) &&
pq->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT) {
psub->cmd.command = TSDB_SQL_RETRIEVE_EMPTY_RESULT;
}
executeQuery(psub, pq); executeQuery(psub, pq);
} }
......
...@@ -131,7 +131,7 @@ static void *shellCheckThreadFp(void *arg) { ...@@ -131,7 +131,7 @@ static void *shellCheckThreadFp(void *arg) {
char *tbname = tbNames[t]; char *tbname = tbNames[t];
if (tbname == NULL) break; if (tbname == NULL) break;
snprintf(sql, SHELL_SQL_LEN, "select last_row(_c0) from %s;", tbname); snprintf(sql, SHELL_SQL_LEN, "select count(*) from %s;", tbname);
TAOS_RES *pSql = taos_query(pThread->taos, sql); TAOS_RES *pSql = taos_query(pThread->taos, sql);
int32_t code = taos_errno(pSql); int32_t code = taos_errno(pSql);
......
...@@ -43,7 +43,7 @@ void mnodeCheckUnCreatedVgroup(SDnodeObj *pDnode, SVnodeLoad *pVloads, int32_ ...@@ -43,7 +43,7 @@ void mnodeCheckUnCreatedVgroup(SDnodeObj *pDnode, SVnodeLoad *pVloads, int32_
int32_t mnodeCreateVgroup(struct SMnodeMsg *pMsg); int32_t mnodeCreateVgroup(struct SMnodeMsg *pMsg);
void mnodeDropVgroup(SVgObj *pVgroup, void *ahandle); void mnodeDropVgroup(SVgObj *pVgroup, void *ahandle);
void mnodeAlterVgroup(SVgObj *pVgroup, void *ahandle); void mnodeAlterVgroup(SVgObj *pVgroup, void *ahandle);
int32_t mnodeGetAvailableVgroup(struct SMnodeMsg *pMsg, SVgObj **pVgroup, int32_t *sid); int32_t mnodeGetAvailableVgroup(struct SMnodeMsg *pMsg, SVgObj **pVgroup, int32_t *sid, int32_t vgId);
int32_t mnodeAddTableIntoVgroup(SVgObj *pVgroup, SCTableObj *pTable, bool needCheck); int32_t mnodeAddTableIntoVgroup(SVgObj *pVgroup, SCTableObj *pTable, bool needCheck);
void mnodeRemoveTableFromVgroup(SVgObj *pVgroup, SCTableObj *pTable); void mnodeRemoveTableFromVgroup(SVgObj *pVgroup, SCTableObj *pTable);
......
...@@ -48,6 +48,12 @@ ...@@ -48,6 +48,12 @@
#define CREATE_CTABLE_RETRY_TIMES 10 #define CREATE_CTABLE_RETRY_TIMES 10
#define CREATE_CTABLE_RETRY_SEC 14 #define CREATE_CTABLE_RETRY_SEC 14
// informal
#define META_SYNC_TABLE_NAME "_taos_meta_sync_table_name_taos_"
#define META_SYNC_TABLE_NAME_LEN 32
static int32_t tsMetaSyncOption = 0;
// informal
int64_t tsCTableRid = -1; int64_t tsCTableRid = -1;
static void * tsChildTableSdb; static void * tsChildTableSdb;
int64_t tsSTableRid = -1; int64_t tsSTableRid = -1;
...@@ -1726,6 +1732,9 @@ int32_t mnodeRetrieveShowSuperTables(SShowObj *pShow, char *data, int32_t rows, ...@@ -1726,6 +1732,9 @@ int32_t mnodeRetrieveShowSuperTables(SShowObj *pShow, char *data, int32_t rows,
cols++; cols++;
numOfRows++; numOfRows++;
mDebug("stable: %s, uid: %" PRIu64, prefix, pTable->uid);
mnodeDecTableRef(pTable); mnodeDecTableRef(pTable);
} }
...@@ -2227,9 +2236,19 @@ static int32_t mnodeProcessCreateChildTableMsg(SMnodeMsg *pMsg) { ...@@ -2227,9 +2236,19 @@ static int32_t mnodeProcessCreateChildTableMsg(SMnodeMsg *pMsg) {
if (pMsg->pTable == NULL) { if (pMsg->pTable == NULL) {
SVgObj *pVgroup = NULL; SVgObj *pVgroup = NULL;
int32_t tid = 0; int32_t tid = 0;
code = mnodeGetAvailableVgroup(pMsg, &pVgroup, &tid); int32_t vgId = 0;
if (tsMetaSyncOption) {
char *pTbName = strchr(pCreate->tableName, '.');
if (pTbName && (pTbName = strchr(pTbName + 1, '.'))) {
if (0 == strncmp(META_SYNC_TABLE_NAME, ++pTbName, META_SYNC_TABLE_NAME_LEN)) {
vgId = atoi(pTbName + META_SYNC_TABLE_NAME_LEN);
}
}
}
code = mnodeGetAvailableVgroup(pMsg, &pVgroup, &tid, vgId);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
mDebug("msg:%p, app:%p table:%s, failed to get available vgroup, reason:%s", pMsg, pMsg->rpcMsg.ahandle, mError("msg:%p, app:%p table:%s, failed to get available vgroup, reason:%s", pMsg, pMsg->rpcMsg.ahandle,
pCreate->tableName, tstrerror(code)); pCreate->tableName, tstrerror(code));
return code; return code;
} }
......
...@@ -428,10 +428,47 @@ static int32_t mnodeAllocVgroupIdPool(SVgObj *pInputVgroup) { ...@@ -428,10 +428,47 @@ static int32_t mnodeAllocVgroupIdPool(SVgObj *pInputVgroup) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
int32_t mnodeGetAvailableVgroup(SMnodeMsg *pMsg, SVgObj **ppVgroup, int32_t *pSid) { int32_t mnodeGetAvailableVgroup(SMnodeMsg *pMsg, SVgObj **ppVgroup, int32_t *pSid, int32_t vgId) {
SDbObj *pDb = pMsg->pDb; SDbObj *pDb = pMsg->pDb;
pthread_mutex_lock(&pDb->mutex); pthread_mutex_lock(&pDb->mutex);
if (vgId > 0) {
for (int32_t v = 0; v < pDb->numOfVgroups; ++v) {
SVgObj *pVgroup = pDb->vgList[v];
if (pVgroup == NULL) {
mError("db:%s, vgroup: %d is null", pDb->name, v);
pthread_mutex_unlock(&pDb->mutex);
return TSDB_CODE_MND_APP_ERROR;
}
if (pVgroup->vgId != (uint32_t)vgId) { // find the target vgId
continue;
}
int32_t sid = taosAllocateId(pVgroup->idPool);
if (sid <= 0) {
int curMaxId = taosIdPoolMaxSize(pVgroup->idPool);
if ((taosUpdateIdPool(pVgroup->idPool, curMaxId + 1) < 0) || ((sid = taosAllocateId(pVgroup->idPool)) <= 0)) {
mError("msg:%p, app:%p db:%s, no enough sid in vgId:%d", pMsg, pMsg->rpcMsg.ahandle, pDb->name,
pVgroup->vgId);
pthread_mutex_unlock(&pDb->mutex);
return TSDB_CODE_MND_APP_ERROR;
}
}
mDebug("vgId:%d, alloc tid:%d", pVgroup->vgId, sid);
*pSid = sid;
*ppVgroup = pVgroup;
pDb->vgListIndex = v;
pthread_mutex_unlock(&pDb->mutex);
return TSDB_CODE_SUCCESS;
}
pthread_mutex_unlock(&pDb->mutex);
mError("db:%s, vgroup: %d not exist", pDb->name, vgId);
return TSDB_CODE_MND_APP_ERROR;
}
for (int32_t v = 0; v < pDb->numOfVgroups; ++v) { for (int32_t v = 0; v < pDb->numOfVgroups; ++v) {
int vgIndex = (v + pDb->vgListIndex) % pDb->numOfVgroups; int vgIndex = (v + pDb->vgListIndex) % pDb->numOfVgroups;
SVgObj *pVgroup = pDb->vgList[vgIndex]; SVgObj *pVgroup = pDb->vgList[vgIndex];
......
...@@ -458,14 +458,18 @@ static void monBuildMonitorSql(char *sql, int32_t cmd) { ...@@ -458,14 +458,18 @@ static void monBuildMonitorSql(char *sql, int32_t cmd) {
", expire_time int, timeseries_used int, timeseries_total int)", ", expire_time int, timeseries_used int, timeseries_total int)",
tsMonitorDbName); tsMonitorDbName);
} else if (cmd == MON_CMD_CREATE_MT_RESTFUL) { } else if (cmd == MON_CMD_CREATE_MT_RESTFUL) {
int usedLen = 0, len = 0;
int pos = snprintf(sql, SQL_LENGTH, int pos = snprintf(sql, SQL_LENGTH,
"create table if not exists %s.restful_info(ts timestamp", tsMonitorDbName); "create table if not exists %s.restful_info(ts timestamp", tsMonitorDbName);
usedLen += pos;
for (int i = 0; i < tListLen(monHttpStatusTable); ++i) { for (int i = 0; i < tListLen(monHttpStatusTable); ++i) {
pos += snprintf(sql + pos, SQL_LENGTH, ", `%s(%d)` int", len = snprintf(sql + pos, SQL_LENGTH - usedLen, ", %s_%d int",
monHttpStatusTable[i].name, monHttpStatusTable[i].name,
monHttpStatusTable[i].code); monHttpStatusTable[i].code);
usedLen += len;
pos += len;
} }
snprintf(sql + pos, SQL_LENGTH, snprintf(sql + pos, SQL_LENGTH - usedLen,
") tags (dnode_id int, dnode_ep binary(%d))", ") tags (dnode_id int, dnode_ep binary(%d))",
TSDB_EP_LEN); TSDB_EP_LEN);
} else if (cmd == MON_CMD_CREATE_TB_RESTFUL) { } else if (cmd == MON_CMD_CREATE_TB_RESTFUL) {
......
Subproject commit fd84b35d3a30c9bcf3939d565f717b7f98ff9eb7 Subproject commit 47fb0b3e627ddadf1ca983c1d75b9a4e44cd98fd
...@@ -1620,33 +1620,65 @@ static bool first_last_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* ...@@ -1620,33 +1620,65 @@ static bool first_last_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo*
// todo opt for null block // todo opt for null block
static void first_function(SQLFunctionCtx *pCtx) { static void first_function(SQLFunctionCtx *pCtx) {
if (pCtx->order == TSDB_ORDER_DESC) { SResultRowCellInfo* pResInfo = GET_RES_INFO(pCtx);
return;
}
int32_t notNullElems = 0; int32_t notNullElems = 0;
int32_t step = 1;
// handle the null value int32_t i = 0;
for (int32_t i = 0; i < pCtx->size; ++i) { bool inputAsc = true;
char *data = GET_INPUT_DATA(pCtx, i);
if (pCtx->hasNull && isNull(data, pCtx->inputType)) { // input data come from sub query, input data order equal to sub query order
continue; if(pCtx->numOfParams == 3) {
} if(pCtx->param[2].nType == TSDB_DATA_TYPE_INT && pCtx->param[2].i64 == TSDB_ORDER_DESC) {
step = -1;
memcpy(pCtx->pOutput, data, pCtx->inputBytes); i = pCtx->size - 1;
if (pCtx->ptsList != NULL) { inputAsc = false;
TSKEY k = GET_TS_DATA(pCtx, i); }
DO_UPDATE_TAG_COLUMNS(pCtx, k); } else if (pCtx->order == TSDB_ORDER_DESC) {
return ;
}
if(pCtx->order == TSDB_ORDER_ASC && inputAsc) {
for (int32_t m = 0; m < pCtx->size; ++m, i+=step) {
char *data = GET_INPUT_DATA(pCtx, i);
if (pCtx->hasNull && isNull(data, pCtx->inputType)) {
continue;
}
memcpy(pCtx->pOutput, data, pCtx->inputBytes);
if (pCtx->ptsList != NULL) {
TSKEY k = GET_TS_DATA(pCtx, i);
DO_UPDATE_TAG_COLUMNS(pCtx, k);
}
SResultRowCellInfo *pInfo = GET_RES_INFO(pCtx);
pInfo->hasResult = DATA_SET_FLAG;
pInfo->complete = true;
notNullElems++;
break;
} }
} else { // desc order
for (int32_t m = 0; m < pCtx->size; ++m, i+=step) {
char *data = GET_INPUT_DATA(pCtx, i);
if (pCtx->hasNull && isNull(data, pCtx->inputType) && (!pCtx->requireNull)) {
continue;
}
SResultRowCellInfo *pInfo = GET_RES_INFO(pCtx); TSKEY ts = pCtx->ptsList ? GET_TS_DATA(pCtx, i) : 0;
pInfo->hasResult = DATA_SET_FLAG;
pInfo->complete = true; char* buf = GET_ROWCELL_INTERBUF(pResInfo);
if (pResInfo->hasResult != DATA_SET_FLAG || (*(TSKEY*)buf) > ts) {
notNullElems++; pResInfo->hasResult = DATA_SET_FLAG;
break; memcpy(pCtx->pOutput, data, pCtx->inputBytes);
*(TSKEY*)buf = ts;
DO_UPDATE_TAG_COLUMNS(pCtx, ts);
}
notNullElems++;
break;
}
} }
SET_VAL(pCtx, notNullElems, 1); SET_VAL(pCtx, notNullElems, 1);
} }
...@@ -1730,16 +1762,23 @@ static void first_dist_func_merge(SQLFunctionCtx *pCtx) { ...@@ -1730,16 +1762,23 @@ static void first_dist_func_merge(SQLFunctionCtx *pCtx) {
* least one data in this block that is not null.(TODO opt for this case) * least one data in this block that is not null.(TODO opt for this case)
*/ */
static void last_function(SQLFunctionCtx *pCtx) { static void last_function(SQLFunctionCtx *pCtx) {
if (pCtx->order != pCtx->param[0].i64) { SResultRowCellInfo* pResInfo = GET_RES_INFO(pCtx);
int32_t notNullElems = 0;
int32_t step = -1;
int32_t i = pCtx->size - 1;
// input data come from sub query, input data order equal to sub query order
if(pCtx->numOfParams == 3) {
if(pCtx->param[2].nType == TSDB_DATA_TYPE_INT && pCtx->param[2].i64 == TSDB_ORDER_DESC) {
step = 1;
i = 0;
}
} else if (pCtx->order != pCtx->param[0].i64) {
return; return;
} }
SResultRowCellInfo* pResInfo = GET_RES_INFO(pCtx);
int32_t notNullElems = 0;
if (pCtx->order == TSDB_ORDER_DESC) { if (pCtx->order == TSDB_ORDER_DESC) {
for (int32_t m = pCtx->size - 1; m >= 0; --m, i += step) {
for (int32_t i = pCtx->size - 1; i >= 0; --i) {
char *data = GET_INPUT_DATA(pCtx, i); char *data = GET_INPUT_DATA(pCtx, i);
if (pCtx->hasNull && isNull(data, pCtx->inputType) && (!pCtx->requireNull)) { if (pCtx->hasNull && isNull(data, pCtx->inputType) && (!pCtx->requireNull)) {
continue; continue;
...@@ -1756,7 +1795,7 @@ static void last_function(SQLFunctionCtx *pCtx) { ...@@ -1756,7 +1795,7 @@ static void last_function(SQLFunctionCtx *pCtx) {
break; break;
} }
} else { // ascending order } else { // ascending order
for (int32_t i = pCtx->size - 1; i >= 0; --i) { for (int32_t m = pCtx->size - 1; m >= 0; --m, i += step) {
char *data = GET_INPUT_DATA(pCtx, i); char *data = GET_INPUT_DATA(pCtx, i);
if (pCtx->hasNull && isNull(data, pCtx->inputType) && (!pCtx->requireNull)) { if (pCtx->hasNull && isNull(data, pCtx->inputType) && (!pCtx->requireNull)) {
continue; continue;
......
...@@ -5612,6 +5612,18 @@ static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) { ...@@ -5612,6 +5612,18 @@ static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
return pTableScanInfo->order; return pTableScanInfo->order;
} }
// check all SQLFunctionCtx is completed
static bool allCtxCompleted(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx) {
// only one false, return false
for(int32_t i = 0; i < pOperator->numOfOutput; i++) {
if(pCtx[i].resultInfo == NULL)
return false;
if(!pCtx[i].resultInfo->complete)
return false;
}
return true;
}
// this is a blocking operator // this is a blocking operator
static SSDataBlock* doAggregate(void* param, bool* newgroup) { static SSDataBlock* doAggregate(void* param, bool* newgroup) {
SOperatorInfo* pOperator = (SOperatorInfo*) param; SOperatorInfo* pOperator = (SOperatorInfo*) param;
...@@ -5650,6 +5662,9 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) { ...@@ -5650,6 +5662,9 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) {
// the pDataBlock are always the same one, no need to call this again // the pDataBlock are always the same one, no need to call this again
setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order); setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock); doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
// if all pCtx is completed, then query should be over
if(allCtxCompleted(pOperator, pInfo->pCtx))
break;
} }
doSetOperatorCompleted(pOperator); doSetOperatorCompleted(pOperator);
......
###################################################################
# Copyright (c) 2021 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
from util.log import *
from util.cases import *
from util.sql import *
class TDTestCase:
def caseDescription(self):
'''
case1<shenglian zhou>: [TS-2016]fix select * from (select * from empty_stable)
'''
return
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
self._conn = conn
def run(self):
print("running {}".format(__file__))
tdSql.execute("drop database if exists td12229")
tdSql.execute("create database if not exists td12229")
tdSql.execute('use td12229')
tdSql.execute('create stable st(ts timestamp , value int ) tags (ind int)')
tdSql.execute('insert into tb1 using st tags(1) values(now ,1)')
tdSql.execute('insert into tb1 using st tags(1) values(now+1s ,2)')
tdSql.execute('insert into tb1 using st tags(1) values(now+2s ,3)')
tdSql.execute('create stable ste(ts timestamp , value int ) tags (ind int)')
tdSql.query('select * from st')
tdSql.checkRows(3)
tdSql.query('select * from (select * from ste)')
tdSql.checkRows(0)
tdSql.query('select * from st union all select * from ste')
tdSql.checkRows(3)
tdSql.query('select * from ste union all select * from st')
tdSql.checkRows(3)
tdSql.query('select elapsed(ts) from ste group by tbname union all select elapsed(ts) from st group by tbname;')
tdSql.checkRows(1)
tdSql.query('select elapsed(ts) from st group by tbname union all select elapsed(ts) from ste group by tbname;')
tdSql.checkRows(1)
tdSql.execute('drop database td12229')
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())
python3 ./test.py -f 2-query/ts_hidden_column.py python3 ./test.py -f 2-query/ts_hidden_column.py
python3 ./test.py -f 2-query/union-order.py python3 ./test.py -f 2-query/union-order.py
python3 ./test.py -f 2-query/session_two_stage.py python3 ./test.py -f 2-query/session_two_stage.py
python3 ./test.py -f 2-query/ts_2016.py
...@@ -229,7 +229,8 @@ python3 test.py -f tools/taosdemoAllTest/taosdemoTestInsertAllType.py ...@@ -229,7 +229,8 @@ python3 test.py -f tools/taosdemoAllTest/taosdemoTestInsertAllType.py
python3 test.py -f tools/taosdemoAllTest/taosdemoTestInsertShell.py python3 test.py -f tools/taosdemoAllTest/taosdemoTestInsertShell.py
#query #query
python3 test.py -f query/distinctOneColTb.py python3 ./test.py -f query/queryBase.py
python3 ./test.py -f query/distinctOneColTb.py
python3 ./test.py -f query/filter.py python3 ./test.py -f query/filter.py
python3 ./test.py -f query/filterCombo.py python3 ./test.py -f query/filterCombo.py
python3 ./test.py -f query/queryNormal.py python3 ./test.py -f query/queryNormal.py
......
###################################################################
# 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 -*-
#
# query base function test case
#
import sys
from numpy.lib.function_base import insert
import taos
from util.log import *
from util.cases import *
from util.sql import *
import numpy as np
# constant define
WAITS = 5 # wait seconds
class TDTestCase:
#
# --------------- main frame -------------------
#
def caseDescription(self):
'''
Query moudle base api or keyword test case:
case1: api first() last()
case2: none
'''
return
# init
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor())
tdSql.prepare()
self.create_tables();
self.ts = 1500000000000
# run case
def run(self):
# insert data
self.insert_data("t1", self.ts, 1*10000, 30000, 0);
self.insert_data("t2", self.ts, 2*10000, 30000, 100000);
self.insert_data("t3", self.ts, 3*10000, 30000, 200000);
# test base case
self.case_first()
tdLog.debug(" QUERYBASE first() api ............ [OK]")
# test advance case
self.case_last()
tdLog.debug(" QUERYBASE last() api ............ [OK]")
# stop
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
#
# --------------- case -------------------
#
# create table
def create_tables(self):
# super table
tdSql.execute("create table st(ts timestamp, i1 int) tags(area int)");
# child table
tdSql.execute("create table t1 using st tags(1)");
tdSql.execute("create table t2 using st tags(2)");
tdSql.execute("create table t3 using st tags(3)");
return
# insert data1
def insert_data(self, tbname, ts_start, count, batch_num, base):
pre_insert = "insert into %s values"%tbname
sql = pre_insert
tdLog.debug("doing insert table %s rows=%d ..."%(tbname, count))
for i in range(count):
sql += " (%d,%d)"%(ts_start + i*1000, base + i)
if i >0 and i%batch_num == 0:
tdSql.execute(sql)
sql = pre_insert
# end sql
if sql != pre_insert:
tdSql.execute(sql)
tdLog.debug("INSERT TABLE DATA ............ [OK]")
return
# first case base
def case_first(self):
#
# last base function
#
# base t1 table
sql = "select first(*) from t1 where ts>='2017-07-14 12:40:00' order by ts asc;"
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 7200)
sql = "select first(*) from t1 where ts>='2017-07-14 12:40:00' order by ts desc;" # desc
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 7200)
# super table st
sql = "select first(*) from st where ts>='2017-07-14 11:40:00' and ts<='2017-07-14 12:40:00' and tbname in('t1') order by ts;"
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 3600)
sql = "select first(*) from st where ts>='2017-07-14 11:40:00' and ts<='2017-07-14 12:40:00' and tbname in('t1') order by ts desc;" # desc
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 3600)
# sub query
sql = "select first(*) from ( select sum(i1) from st where ts>='2017-07-14 11:40:00' and ts<'2017-07-14 12:40:00' interval(10m) order by ts asc );"
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 187019100)
sql = "select first(*) from ( select sum(i1) from st where ts>='2017-07-14 11:40:00' and ts<'2017-07-14 12:40:00' interval(10m) order by ts desc );" # desc
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 187019100)
return
# last case
def case_last(self):
#
# last base test
#
# base t1 table
sql = "select last(*) from t1 where ts<='2017-07-14 12:40:00' order by ts asc;"
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 7200)
sql = "select last(*) from t1 where ts<='2017-07-14 12:40:00' order by ts desc;" # desc
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 7200)
# super table st
sql = "select last(*) from st where ts>='2017-07-14 11:40:00' and ts<='2017-07-14 12:40:00' and tbname in('t1') order by ts;"
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 7200)
sql = "select last(*) from st where ts>='2017-07-14 11:40:00' and ts<='2017-07-14 12:40:00' and tbname in('t1') order by ts desc;" # desc
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 7200)
# sub query
sql = "select last(*) from ( select sum(i1) from st where ts>='2017-07-14 11:40:00' and ts<'2017-07-14 12:40:00' interval(10m) order by ts asc );"
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 192419100)
sql = "select last(*) from ( select sum(i1) from st where ts>='2017-07-14 11:40:00' and ts<'2017-07-14 12:40:00' interval(10m) order by ts desc );" # desc
tdSql.waitedQuery(sql, 1, WAITS)
tdSql.checkData(0, 1, 192419100)
#
# add case with filename
#
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())
\ No newline at end of file
...@@ -26,6 +26,8 @@ class TDTestCase: ...@@ -26,6 +26,8 @@ class TDTestCase:
''' '''
tdCom.cleanTb() tdCom.cleanTb()
table_name = tdCom.getLongName(8, "letters_mixed") table_name = tdCom.getLongName(8, "letters_mixed")
while table_name.islower():
table_name = tdCom.getLongName(8, "letters_mixed")
table_name_sub = f'{table_name}_sub' table_name_sub = f'{table_name}_sub'
tb_name_lower = table_name_sub.lower() tb_name_lower = table_name_sub.lower()
tb_name_upper = table_name_sub.upper() tb_name_upper = table_name_sub.upper()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册